ogelf.pas 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Peter Vreman
  4. Contains the binary elf writer
  5. * This code was inspired by the NASM sources
  6. The Netwide Assembler is copyright (C) 1996 Simon Tatham and
  7. Julian Hall. All rights reserved.
  8. This program is free software; you can redistribute it and/or modify
  9. it under the terms of the GNU General Public License as published by
  10. the Free Software Foundation; either version 2 of the License, or
  11. (at your option) any later version.
  12. This program is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. GNU General Public License for more details.
  16. You should have received a copy of the GNU General Public License
  17. along with this program; if not, write to the Free Software
  18. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19. ****************************************************************************
  20. }
  21. unit ogelf;
  22. {$i defines.inc}
  23. interface
  24. uses
  25. { common }
  26. cclasses,cobjects,
  27. { target }
  28. systems,
  29. { assembler }
  30. cpubase,aasm,
  31. { output }
  32. ogbase;
  33. type
  34. telf32section = class(tobjectsection)
  35. public
  36. secshidx : longint; { index for the section in symtab }
  37. shstridx,
  38. shtype,
  39. shflags,
  40. shlink,
  41. shinfo,
  42. entsize : longint;
  43. { relocation }
  44. relocsect : telf32Section;
  45. constructor createsec(sec:TSection);
  46. constructor createname(const Aname:string;Atype,Aflags,Alink,Ainfo,Aalign,Aentsize:longint);
  47. destructor destroy;override;
  48. end;
  49. telf32data = class(tobjectdata)
  50. public
  51. symtabsect,
  52. strtabsect,
  53. shstrtabsect,
  54. gotpcsect,
  55. gotoffsect,
  56. gotsect,
  57. pltsect,
  58. symsect : telf32Section;
  59. syms : Tdynamicarray;
  60. constructor create;
  61. destructor destroy;override;
  62. procedure createsection(sec:tsection);override;
  63. procedure setsectionsizes(var s:tsecsize);override;
  64. procedure writereloc(data,len:longint;p:pasmsymbol;relative:relative_type);override;
  65. procedure writesymbol(p:pasmsymbol);override;
  66. procedure writestabs(section:tsection;offset:longint;p:pchar;nidx,nother,line:longint;reloc:boolean);override;
  67. procedure writesymstabs(section:tsection;offset:longint;p:pchar;ps:pasmsymbol;
  68. nidx,nother,line:longint;reloc:boolean);override;
  69. end;
  70. telf32output = class(tobjectoutput)
  71. private
  72. initsym : longint;
  73. procedure createrelocsection(s:telf32section);
  74. procedure createshstrtab;
  75. procedure createsymtab;
  76. procedure writesectionheader(s:telf32section);
  77. protected
  78. procedure writetodisk;override;
  79. public
  80. function initwriting(Aplace:tcutplace):tobjectdata;override;
  81. end;
  82. implementation
  83. uses
  84. {$ifdef delphi}
  85. sysutils,
  86. {$else}
  87. strings,
  88. {$endif}
  89. verbose,
  90. globtype,cutils,globals,fmodule;
  91. const
  92. symbolresize = 200*18;
  93. DataResize = 8192;
  94. const
  95. R_386_32 = 1; { ordinary absolute relocation }
  96. R_386_PC32 = 2; { PC-relative relocation }
  97. R_386_GOT32 = 3; { an offset into GOT }
  98. R_386_PLT32 = 4; { a PC-relative offset into PLT }
  99. R_386_GOTOFF = 9; { an offset from GOT base }
  100. R_386_GOTPC = 10; { a PC-relative offset _to_ GOT }
  101. SHN_UNDEF = 0;
  102. SHN_ABS = $fff1;
  103. SHN_COMMON = $fff2;
  104. SHT_NULL = 0;
  105. SHT_PROGBITS = 1;
  106. SHT_SYMTAB = 2;
  107. SHT_STRTAB = 3;
  108. SHT_RELA = 4;
  109. SHT_HASH = 5;
  110. SHT_DYNAMIC = 6;
  111. SHT_NOTE = 7;
  112. SHT_NOBITS = 8;
  113. SHT_REL = 9;
  114. SHT_SHLIB = 10;
  115. SHT_DYNSYM = 11;
  116. SHF_WRITE = 1;
  117. SHF_ALLOC = 2;
  118. SHF_EXECINSTR = 4;
  119. STB_LOCAL = 0;
  120. STB_GLOBAL = 1;
  121. STB_WEAK = 2;
  122. STT_NOTYPE = 0;
  123. STT_OBJECT = 1;
  124. STT_FUNC = 2;
  125. STT_SECTION = 3;
  126. STT_FILE = 4;
  127. type
  128. { Structures which are written directly to the output file }
  129. telf32header=packed record
  130. magic0123 : longint;
  131. file_class : byte;
  132. data_encoding : byte;
  133. file_version : byte;
  134. padding : array[$07..$0f] of byte;
  135. e_type : word;
  136. e_machine : word;
  137. e_version : longint;
  138. e_entry : longint; { entrypoint }
  139. e_phoff : longint; { program header offset }
  140. e_shoff : longint; { sections header offset }
  141. e_flags : longint;
  142. e_ehsize : word; { elf header size in bytes }
  143. e_phentsize : word; { size of an entry in the program header array }
  144. e_phnum : word; { 0..e_phnum-1 of entrys }
  145. e_shentsize : word; { size of an entry in sections header array }
  146. e_shnum : word; { 0..e_shnum-1 of entrys }
  147. e_shstrndx : word; { index of string section header }
  148. end;
  149. telf32sechdr=packed record
  150. sh_name : longint;
  151. sh_type : longint;
  152. sh_flags : longint;
  153. sh_addr : longint;
  154. sh_offset : longint;
  155. sh_size : longint;
  156. sh_link : longint;
  157. sh_info : longint;
  158. sh_addralign : longint;
  159. sh_entsize : longint;
  160. end;
  161. pelf32reloc=^telf32reloc;
  162. telf32reloc=packed record
  163. address : longint;
  164. info : longint; { bit 0-7: type, 8-31: symbol }
  165. end;
  166. pelf32symbol=^telf32symbol;
  167. telf32symbol=packed record
  168. st_name : longint;
  169. st_value : longint;
  170. st_size : longint;
  171. st_info : byte; { bit 0-3: type, 4-7: bind }
  172. st_other : byte;
  173. st_shndx : word;
  174. end;
  175. pelf32stab=^telf32stab;
  176. telf32stab=packed record
  177. strpos : longint;
  178. ntype : byte;
  179. nother : byte;
  180. ndesc : word;
  181. nvalue : longint;
  182. end;
  183. {****************************************************************************
  184. TSection
  185. ****************************************************************************}
  186. constructor telf32section.createsec(sec:TSection);
  187. var
  188. Aflags,Atype,Aalign,Aentsize : longint;
  189. begin
  190. Aflags:=0;
  191. Atype:=0;
  192. Aalign:=0;
  193. Aentsize:=0;
  194. case sec of
  195. sec_code :
  196. begin
  197. Aflags:=SHF_ALLOC or SHF_EXECINSTR;
  198. AType:=SHT_PROGBITS;
  199. AAlign:=16;
  200. end;
  201. sec_data :
  202. begin
  203. Aflags:=SHF_ALLOC or SHF_WRITE;
  204. AType:=SHT_PROGBITS;
  205. AAlign:=4;
  206. end;
  207. sec_bss :
  208. begin
  209. Aflags:=SHF_ALLOC or SHF_WRITE;
  210. AType:=SHT_NOBITS;
  211. AAlign:=4;
  212. end;
  213. sec_stab :
  214. begin
  215. AType:=SHT_PROGBITS;
  216. AAlign:=4;
  217. Aentsize:=sizeof(telf32stab);
  218. end;
  219. sec_stabstr :
  220. begin
  221. AType:=SHT_STRTAB;
  222. AAlign:=1;
  223. end;
  224. end;
  225. createname(target_asm.secnames[sec],Atype,Aflags,0,0,Aalign,Aentsize);
  226. end;
  227. constructor telf32section.createname(const Aname:string;Atype,Aflags,Alink,Ainfo,Aalign,Aentsize:longint);
  228. begin
  229. inherited create(Aname,Aalign,(AType=SHT_NOBITS));
  230. secshidx:=0;
  231. shstridx:=0;
  232. shtype:=AType;
  233. shflags:=AFlags;
  234. shlink:=Alink;
  235. shinfo:=Ainfo;
  236. entsize:=Aentsize;
  237. relocsect:=nil;
  238. end;
  239. destructor telf32section.destroy;
  240. begin
  241. if assigned(relocsect) then
  242. relocsect.free;
  243. inherited destroy;
  244. end;
  245. {****************************************************************************
  246. TElf32Data
  247. ****************************************************************************}
  248. constructor telf32data.create;
  249. var
  250. s : string;
  251. begin
  252. inherited create;
  253. { reset }
  254. Syms:=TDynamicArray.Create(symbolresize);
  255. { default sections }
  256. symtabsect:=telf32section.createname('.symtab',2,0,0,0,4,16);
  257. strtabsect:=telf32section.createname('.strtab',3,0,0,0,1,0);
  258. shstrtabsect:=telf32section.createname('.shstrtab',3,0,0,0,1,0);
  259. { insert the empty and filename as first in strtab }
  260. strtabsect.writestr(#0);
  261. strtabsect.writestr(SplitFileName(current_module.mainsource^)+#0);
  262. { we need at least the following sections }
  263. createsection(sec_code);
  264. createsection(sec_data);
  265. createsection(sec_bss);
  266. { create stabs sections if debugging }
  267. if (cs_debuginfo in aktmoduleswitches) then
  268. begin
  269. createsection(sec_stab);
  270. createsection(sec_stabstr);
  271. writestabs(sec_none,0,nil,0,0,0,false);
  272. { write zero pchar and name together (PM) }
  273. s:=#0+SplitFileName(current_module.mainsource^)+#0;
  274. sects[sec_stabstr].write(s[1],length(s));
  275. end;
  276. end;
  277. destructor telf32data.destroy;
  278. begin
  279. Syms.Free;
  280. symtabsect.free;
  281. strtabsect.free;
  282. shstrtabsect.free;
  283. inherited destroy;
  284. end;
  285. procedure telf32data.createsection(sec:tsection);
  286. begin
  287. sects[sec]:=telf32Section.createsec(Sec);
  288. end;
  289. procedure telf32data.writesymbol(p:pasmsymbol);
  290. var
  291. sym : toutputsymbol;
  292. begin
  293. { already written ? }
  294. if p^.idx<>-1 then
  295. exit;
  296. { be sure that the section will exists }
  297. if (p^.section<>sec_none) and not(assigned(sects[p^.section])) then
  298. createsection(p^.section);
  299. FillChar(sym,sizeof(sym),0);
  300. sym.size:=p^.size;
  301. sym.bind:=p^.bind;
  302. sym.typ:=p^.typ;
  303. { if local of global then set the section value to the address
  304. of the symbol }
  305. case sym.bind of
  306. AB_LOCAL,
  307. AB_GLOBAL :
  308. begin
  309. sym.section:=p^.section;
  310. sym.value:=p^.address;
  311. end;
  312. AB_COMMON :
  313. begin
  314. sym.value:=$10;
  315. end;
  316. end;
  317. { store the symbol, but not the local ones }
  318. if (sym.bind<>AB_LOCAL) then
  319. begin
  320. { symbolname, write the #0 separate to overcome 255+1 char not possible }
  321. sym.nameidx:=strtabsect.datasize;
  322. strtabsect.writestr(p^.name);
  323. strtabsect.writestr(#0);
  324. { update the asmsymbol index }
  325. p^.idx:=syms.size div sizeof(toutputsymbol);
  326. { symbol }
  327. Syms.write(sym,sizeof(toutputsymbol));
  328. end
  329. else
  330. begin
  331. p^.idx:=-2; { local }
  332. end;
  333. end;
  334. procedure telf32data.writereloc(data,len:longint;p:pasmsymbol;relative:relative_type);
  335. var
  336. symaddr : longint;
  337. begin
  338. if not assigned(sects[currsec]) then
  339. createsection(currsec);
  340. if assigned(p) then
  341. begin
  342. { real address of the symbol }
  343. symaddr:=p^.address;
  344. { no symbol relocation need inside a section }
  345. if p^.section=currsec then
  346. begin
  347. case relative of
  348. relative_false :
  349. begin
  350. sects[currsec].addsectionreloc(sects[currsec].datasize,currsec,relative_false);
  351. inc(data,symaddr);
  352. end;
  353. relative_true :
  354. begin
  355. inc(data,symaddr-len-sects[currsec].datasize);
  356. end;
  357. relative_rva :
  358. internalerror(3219583);
  359. end;
  360. end
  361. else
  362. begin
  363. writesymbol(p);
  364. if (p^.section<>sec_none) and (relative<>relative_true) then
  365. begin
  366. sects[currsec].addsectionreloc(sects[currsec].datasize,p^.section,relative);
  367. inc(data,symaddr);
  368. end
  369. else
  370. sects[currsec].addsymreloc(sects[currsec].datasize,p,relative);
  371. if relative=relative_true then
  372. begin
  373. if p^.bind=AB_EXTERNAL then
  374. dec(data,len)
  375. else
  376. dec(data,len+sects[currsec].datasize);
  377. end;
  378. end;
  379. end;
  380. sects[currsec].write(data,len);
  381. end;
  382. procedure telf32data.writestabs(section:tsection;offset:longint;p:pchar;nidx,nother,line:longint;reloc : boolean);
  383. var
  384. stab : telf32stab;
  385. s : tsection;
  386. begin
  387. s:=section;
  388. if reloc then
  389. begin
  390. if (offset=-1) then
  391. begin
  392. if s=sec_none then
  393. offset:=0
  394. else
  395. offset:=sects[s].datasize;
  396. end;
  397. end;
  398. fillchar(stab,sizeof(telf32stab),0);
  399. if assigned(p) and (p[0]<>#0) then
  400. begin
  401. stab.strpos:=sects[sec_stabstr].datasize;
  402. sects[sec_stabstr].write(p^,strlen(p)+1);
  403. end;
  404. stab.ntype:=nidx;
  405. stab.ndesc:=line;
  406. stab.nother:=nother;
  407. stab.nvalue:=offset;
  408. sects[sec_stab].write(stab,sizeof(stab));
  409. { when the offset is not 0 then write a relocation, take also the
  410. hdrstab into account with the offset }
  411. if reloc then
  412. sects[sec_stab].addsectionreloc(sects[sec_stab].datasize-4,s,relative_false);
  413. end;
  414. procedure telf32data.writesymstabs(section:tsection;offset:longint;p:pchar;ps:pasmsymbol;
  415. nidx,nother,line:longint;reloc:boolean);
  416. var
  417. stab : telf32stab;
  418. begin
  419. if reloc then
  420. begin
  421. if (offset=-1) then
  422. begin
  423. if section=sec_none then
  424. offset:=0
  425. else
  426. offset:=sects[section].datasize;
  427. end;
  428. end;
  429. fillchar(stab,sizeof(telf32stab),0);
  430. if assigned(p) and (p[0]<>#0) then
  431. begin
  432. stab.strpos:=sects[sec_stabstr].datasize;
  433. sects[sec_stabstr].write(p^,strlen(p)+1);
  434. end;
  435. stab.ntype:=nidx;
  436. stab.ndesc:=line;
  437. stab.nother:=nother;
  438. stab.nvalue:=offset;
  439. sects[sec_stab].write(stab,sizeof(stab));
  440. { when the offset is not 0 then write a relocation, take also the
  441. hdrstab into account with the offset }
  442. if reloc then
  443. sects[sec_stab].addsymreloc(sects[sec_stab].datasize-4,ps,relative_false);
  444. end;
  445. procedure telf32data.setsectionsizes(var s:tsecsize);
  446. begin
  447. end;
  448. {****************************************************************************
  449. TElf32Output
  450. ****************************************************************************}
  451. function telf32output.initwriting(Aplace:tcutplace):tobjectdata;
  452. begin
  453. inherited initwriting(Aplace);
  454. initsym:=0;
  455. data:=telf32data.create;
  456. initwriting:=data;
  457. end;
  458. procedure telf32output.createrelocsection(s:telf32section);
  459. var
  460. rel : telf32reloc;
  461. hr,r : poutputreloc;
  462. relsym,reltyp : longint;
  463. begin
  464. with telf32data(data) do
  465. begin
  466. { create the reloc section }
  467. s.relocsect:=telf32section.createname('.rel'+s.name,9,0,symtabsect.secshidx,s.secshidx,4,8);
  468. { add the relocations }
  469. r:=s.relochead;
  470. while assigned(r) do
  471. begin
  472. rel.address:=r^.address;
  473. if assigned(r^.symbol) then
  474. begin
  475. if (r^.symbol^.bind=AB_LOCAL) then
  476. relsym:=sects[r^.symbol^.section].secsymidx
  477. else
  478. begin
  479. if r^.symbol^.idx=-1 then
  480. internalerror(4321);
  481. relsym:=(r^.symbol^.idx+initsym);
  482. end;
  483. end
  484. else
  485. if r^.section<>sec_none then
  486. relsym:=sects[r^.section].secsymidx
  487. else
  488. relsym:=SHN_UNDEF;
  489. case r^.typ of
  490. relative_true :
  491. reltyp:=R_386_PC32;
  492. relative_false :
  493. reltyp:=R_386_32;
  494. end;
  495. rel.info:=(relsym shl 8) or reltyp;
  496. { write reloc }
  497. s.relocsect.write(rel,sizeof(rel));
  498. { goto next and dispose this reloc }
  499. hr:=r;
  500. r:=r^.next;
  501. dispose(hr);
  502. end;
  503. end;
  504. end;
  505. procedure telf32output.createsymtab;
  506. var
  507. elfsym : telf32symbol;
  508. sym : toutputsymbol;
  509. sec : tsection;
  510. locals,
  511. i : longint;
  512. begin
  513. with telf32data(data) do
  514. begin
  515. locals:=2;
  516. { empty entry }
  517. fillchar(elfsym,sizeof(elfsym),0);
  518. symtabsect.write(elfsym,sizeof(elfsym));
  519. { filename entry }
  520. elfsym.st_name:=1;
  521. elfsym.st_info:=STT_FILE;
  522. elfsym.st_shndx:=SHN_ABS;
  523. symtabsect.write(elfsym,sizeof(elfsym));
  524. { section }
  525. for sec:=low(tsection) to high(tsection) do
  526. if assigned(sects[sec]) then
  527. begin
  528. fillchar(elfsym,sizeof(elfsym),0);
  529. elfsym.st_name:=telf32section(sects[sec]).shstridx;
  530. elfsym.st_info:=STT_SECTION;
  531. elfsym.st_shndx:=telf32section(sects[sec]).secshidx;
  532. symtabsect.write(elfsym,sizeof(elfsym));
  533. inc(locals);
  534. end;
  535. { symbols }
  536. Syms.seek(0);
  537. for i:=1 to (Syms.size div sizeof(toutputsymbol)) do
  538. begin
  539. Syms.read(sym,sizeof(toutputsymbol));
  540. fillchar(elfsym,sizeof(elfsym),0);
  541. elfsym.st_name:=sym.nameidx;
  542. elfsym.st_value:=sym.value;
  543. elfsym.st_size:=sym.size;
  544. case sym.bind of
  545. AB_LOCAL :
  546. begin
  547. elfsym.st_info:=STB_LOCAL shl 4;
  548. inc(locals);
  549. end;
  550. AB_COMMON,
  551. AB_EXTERNAL,
  552. AB_GLOBAL :
  553. elfsym.st_info:=STB_GLOBAL shl 4;
  554. end;
  555. if sym.bind<>AB_EXTERNAL then
  556. begin
  557. case sym.typ of
  558. AT_FUNCTION :
  559. elfsym.st_info:=elfsym.st_info or STT_FUNC;
  560. AT_DATA :
  561. elfsym.st_info:=elfsym.st_info or STT_OBJECT;
  562. end;
  563. end;
  564. if sym.bind=AB_COMMON then
  565. elfsym.st_shndx:=SHN_COMMON
  566. else
  567. if assigned(sects[sym.section]) then
  568. elfsym.st_shndx:=telf32section(sects[sym.section]).secshidx
  569. else
  570. elfsym.st_shndx:=SHN_UNDEF;
  571. symtabsect.write(elfsym,sizeof(elfsym));
  572. end;
  573. { update the .symtab section header }
  574. symtabsect.shlink:=strtabsect.secshidx;
  575. symtabsect.shinfo:=locals;
  576. end;
  577. end;
  578. procedure telf32output.createshstrtab;
  579. var
  580. sec : tsection;
  581. begin
  582. with telf32data(data) do
  583. begin
  584. with shstrtabsect do
  585. begin
  586. writestr(#0);
  587. symtabsect.shstridx:=writestr('.symtab'#0);
  588. strtabsect.shstridx:=writestr('.strtab'#0);
  589. shstrtabsect.shstridx:=writestr('.shstrtab'#0);
  590. for sec:=low(tsection) to high(tsection) do
  591. if assigned(sects[sec]) then
  592. begin
  593. telf32section(sects[sec]).shstridx:=writestr(sects[sec].name+#0);
  594. if assigned(telf32section(sects[sec]).relocsect) then
  595. telf32section(sects[sec]).relocsect.shstridx:=writestr(telf32section(sects[sec]).relocsect.name+#0);
  596. end;
  597. end;
  598. end;
  599. end;
  600. procedure telf32output.writesectionheader(s:telf32section);
  601. var
  602. sechdr : telf32sechdr;
  603. begin
  604. fillchar(sechdr,sizeof(sechdr),0);
  605. sechdr.sh_name:=s.shstridx;
  606. sechdr.sh_type:=s.shtype;
  607. sechdr.sh_flags:=s.shflags;
  608. sechdr.sh_offset:=s.datapos;
  609. sechdr.sh_size:=s.datasize;
  610. sechdr.sh_link:=s.shlink;
  611. sechdr.sh_info:=s.shinfo;
  612. sechdr.sh_addralign:=s.addralign;
  613. sechdr.sh_entsize:=s.entsize;
  614. writer.write(sechdr,sizeof(sechdr));
  615. end;
  616. procedure telf32output.writetodisk;
  617. var
  618. header : telf32header;
  619. datapos,
  620. shoffset,
  621. nsects : longint;
  622. hstab : telf32stab;
  623. sec : tsection;
  624. empty : array[0..63] of byte;
  625. hp : pdynamicblock;
  626. begin
  627. with telf32data(data) do
  628. begin
  629. { calc amount of sections we have }
  630. fillchar(empty,sizeof(empty),0);
  631. nsects:=1;
  632. initsym:=2;
  633. for sec:=low(tsection) to high(tsection) do
  634. if assigned(sects[sec]) then
  635. begin
  636. { each section requires a symbol for relocation }
  637. sects[sec].secsymidx:=initsym;
  638. inc(initsym);
  639. { also create the index in the section header table }
  640. telf32section(sects[sec]).secshidx:=nsects;
  641. inc(nsects);
  642. if assigned(sects[sec].relochead) then
  643. inc(nsects);
  644. end;
  645. { add default sections follows }
  646. shstrtabsect.secshidx:=nsects;
  647. inc(nsects);
  648. symtabsect.secshidx:=nsects;
  649. inc(nsects);
  650. strtabsect.secshidx:=nsects;
  651. inc(nsects);
  652. { For the stab section we need an HdrSym which can now be
  653. calculated more easily }
  654. if assigned(sects[sec_stab]) then
  655. begin
  656. hstab.strpos:=1;
  657. hstab.ntype:=0;
  658. hstab.nother:=0;
  659. hstab.ndesc:=(sects[sec_stab].datasize div sizeof(telf32stab))-1{+1 according to gas output PM};
  660. hstab.nvalue:=sects[sec_stabstr].datasize;
  661. sects[sec_stab].Data.seek(0);
  662. sects[sec_stab].Data.write(hstab,sizeof(hstab));
  663. end;
  664. { Create the relocation sections }
  665. for sec:=low(tsection) to high(tsection) do
  666. if assigned(sects[sec]) and
  667. (sects[sec].nrelocs>0) then
  668. createrelocsection(telf32section(sects[sec]));
  669. { create .symtab }
  670. createsymtab;
  671. { create .shstrtab }
  672. createshstrtab;
  673. { Calculate the filepositions }
  674. datapos:=$40; { elfheader + alignment }
  675. { sections first }
  676. for sec:=low(tsection) to high(tsection) do
  677. if assigned(sects[sec]) then
  678. begin
  679. sects[sec].datapos:=datapos;
  680. if assigned(sects[sec].data) then
  681. inc(datapos,sects[sec].aligneddatasize);
  682. end;
  683. { shstrtab }
  684. shstrtabsect.datapos:=datapos;
  685. inc(datapos,shstrtabsect.aligneddatasize);
  686. { section headers }
  687. shoffset:=datapos;
  688. inc(datapos,nsects*sizeof(telf32sechdr));
  689. { symtab }
  690. symtabsect.datapos:=datapos;
  691. inc(datapos,symtabsect.aligneddatasize);
  692. { strtab }
  693. strtabsect.datapos:=datapos;
  694. inc(datapos,align(strtabsect.datasize,4));
  695. { .rel sections }
  696. for sec:=low(tsection) to high(tsection) do
  697. if assigned(sects[sec]) and
  698. assigned(telf32section(sects[sec]).relocsect) then
  699. begin
  700. telf32section(sects[sec]).relocsect.datapos:=datapos;
  701. inc(datapos,telf32section(sects[sec]).relocsect.aligneddatasize);
  702. end;
  703. { Write ELF Header }
  704. fillchar(header,sizeof(header),0);
  705. header.magic0123:=$464c457f; { = #127'ELF' }
  706. header.file_class:=1;
  707. header.data_encoding:=1;
  708. header.file_version:=1;
  709. header.e_type:=1;
  710. header.e_machine:=3;
  711. header.e_version:=1;
  712. header.e_shoff:=shoffset;
  713. header.e_shstrndx:=shstrtabsect.secshidx;
  714. header.e_shnum:=nsects;
  715. header.e_ehsize:=sizeof(telf32header);
  716. header.e_shentsize:=sizeof(telf32sechdr);
  717. writer.write(header,sizeof(header));
  718. writer.write(empty,$40-sizeof(header)); { align }
  719. { Sections }
  720. for sec:=low(tsection) to high(tsection) do
  721. if assigned(sects[sec]) and
  722. assigned(sects[sec].data) then
  723. begin
  724. sects[sec].alignsection;
  725. hp:=sects[sec].Data.firstblock;
  726. while assigned(hp) do
  727. begin
  728. writer.write(hp^.data,hp^.used);
  729. hp:=hp^.next;
  730. end;
  731. end;
  732. { .shstrtab }
  733. shstrtabsect.alignsection;
  734. hp:=shstrtabsect.Data.firstblock;
  735. while assigned(hp) do
  736. begin
  737. writer.write(hp^.data,hp^.used);
  738. hp:=hp^.next;
  739. end;
  740. { section headers, start with an empty header for sh_undef }
  741. writer.write(empty,sizeof(telf32sechdr));
  742. for sec:=low(tsection) to high(tsection) do
  743. if assigned(sects[sec]) then
  744. begin
  745. writesectionheader(telf32section(sects[sec]));
  746. if assigned(telf32section(sects[sec]).relocsect) then
  747. writesectionheader(telf32section(sects[sec]).relocsect);
  748. end;
  749. writesectionheader(shstrtabsect);
  750. writesectionheader(symtabsect);
  751. writesectionheader(strtabsect);
  752. { .symtab }
  753. symtabsect.alignsection;
  754. hp:=symtabsect.Data.firstblock;
  755. while assigned(hp) do
  756. begin
  757. writer.write(hp^.data,hp^.used);
  758. hp:=hp^.next;
  759. end;
  760. { .strtab }
  761. strtabsect.writealign(4);
  762. hp:=strtabsect.Data.firstblock;
  763. while assigned(hp) do
  764. begin
  765. writer.write(hp^.data,hp^.used);
  766. hp:=hp^.next;
  767. end;
  768. { .rel sections }
  769. for sec:=low(tsection) to high(tsection) do
  770. if assigned(sects[sec]) and
  771. assigned(telf32section(sects[sec]).relocsect) then
  772. begin
  773. telf32section(sects[sec]).relocsect.alignsection;
  774. hp:=telf32section(sects[sec]).relocsect.Data.firstblock;
  775. while assigned(hp) do
  776. begin
  777. writer.write(hp^.data,hp^.used);
  778. hp:=hp^.next;
  779. end;
  780. end;
  781. end;
  782. end;
  783. end.
  784. {
  785. $Log$
  786. Revision 1.5 2000-12-25 00:07:26 peter
  787. + new tlinkedlist class (merge of old tstringqueue,tcontainer and
  788. tlinkedlist objects)
  789. Revision 1.4 2000/12/24 12:25:32 peter
  790. + cstreams unit
  791. * dynamicarray object to class
  792. Revision 1.3 2000/12/23 19:59:35 peter
  793. * object to class for ow/og objects
  794. * split objectdata from objectoutput
  795. Revision 1.2 2000/11/12 22:45:14 peter
  796. * moved setting of stab hdrsym
  797. Revision 1.1 2000/11/12 22:20:37 peter
  798. * create generic toutputsection for binary writers
  799. }