ogelf.pas 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870
  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. telf32objectoutput = 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(const fn:string):boolean;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. telf32objectoutput
  450. ****************************************************************************}
  451. function telf32objectoutput.initwriting(const fn:string):boolean;
  452. begin
  453. result:=inherited initwriting(fn);
  454. if result then
  455. begin
  456. initsym:=0;
  457. Fdata:=telf32data.create;
  458. end;
  459. end;
  460. procedure telf32objectoutput.createrelocsection(s:telf32section);
  461. var
  462. rel : telf32reloc;
  463. hr,r : poutputreloc;
  464. relsym,reltyp : longint;
  465. begin
  466. with telf32data(data) do
  467. begin
  468. { create the reloc section }
  469. s.relocsect:=telf32section.createname('.rel'+s.name,9,0,symtabsect.secshidx,s.secshidx,4,8);
  470. { add the relocations }
  471. r:=s.relochead;
  472. while assigned(r) do
  473. begin
  474. rel.address:=r^.address;
  475. if assigned(r^.symbol) then
  476. begin
  477. if (r^.symbol^.bind=AB_LOCAL) then
  478. relsym:=sects[r^.symbol^.section].secsymidx
  479. else
  480. begin
  481. if r^.symbol^.idx=-1 then
  482. internalerror(4321);
  483. relsym:=(r^.symbol^.idx+initsym);
  484. end;
  485. end
  486. else
  487. if r^.section<>sec_none then
  488. relsym:=sects[r^.section].secsymidx
  489. else
  490. relsym:=SHN_UNDEF;
  491. case r^.typ of
  492. relative_true :
  493. reltyp:=R_386_PC32;
  494. relative_false :
  495. reltyp:=R_386_32;
  496. end;
  497. rel.info:=(relsym shl 8) or reltyp;
  498. { write reloc }
  499. s.relocsect.write(rel,sizeof(rel));
  500. { goto next and dispose this reloc }
  501. hr:=r;
  502. r:=r^.next;
  503. dispose(hr);
  504. end;
  505. end;
  506. end;
  507. procedure telf32objectoutput.createsymtab;
  508. var
  509. elfsym : telf32symbol;
  510. sym : toutputsymbol;
  511. sec : tsection;
  512. locals,
  513. i : longint;
  514. begin
  515. with telf32data(data) do
  516. begin
  517. locals:=2;
  518. { empty entry }
  519. fillchar(elfsym,sizeof(elfsym),0);
  520. symtabsect.write(elfsym,sizeof(elfsym));
  521. { filename entry }
  522. elfsym.st_name:=1;
  523. elfsym.st_info:=STT_FILE;
  524. elfsym.st_shndx:=SHN_ABS;
  525. symtabsect.write(elfsym,sizeof(elfsym));
  526. { section }
  527. for sec:=low(tsection) to high(tsection) do
  528. if assigned(sects[sec]) then
  529. begin
  530. fillchar(elfsym,sizeof(elfsym),0);
  531. elfsym.st_name:=telf32section(sects[sec]).shstridx;
  532. elfsym.st_info:=STT_SECTION;
  533. elfsym.st_shndx:=telf32section(sects[sec]).secshidx;
  534. symtabsect.write(elfsym,sizeof(elfsym));
  535. inc(locals);
  536. end;
  537. { symbols }
  538. Syms.seek(0);
  539. for i:=1 to (Syms.size div sizeof(toutputsymbol)) do
  540. begin
  541. Syms.read(sym,sizeof(toutputsymbol));
  542. fillchar(elfsym,sizeof(elfsym),0);
  543. elfsym.st_name:=sym.nameidx;
  544. elfsym.st_value:=sym.value;
  545. elfsym.st_size:=sym.size;
  546. case sym.bind of
  547. AB_LOCAL :
  548. begin
  549. elfsym.st_info:=STB_LOCAL shl 4;
  550. inc(locals);
  551. end;
  552. AB_COMMON,
  553. AB_EXTERNAL,
  554. AB_GLOBAL :
  555. elfsym.st_info:=STB_GLOBAL shl 4;
  556. end;
  557. if sym.bind<>AB_EXTERNAL then
  558. begin
  559. case sym.typ of
  560. AT_FUNCTION :
  561. elfsym.st_info:=elfsym.st_info or STT_FUNC;
  562. AT_DATA :
  563. elfsym.st_info:=elfsym.st_info or STT_OBJECT;
  564. end;
  565. end;
  566. if sym.bind=AB_COMMON then
  567. elfsym.st_shndx:=SHN_COMMON
  568. else
  569. if assigned(sects[sym.section]) then
  570. elfsym.st_shndx:=telf32section(sects[sym.section]).secshidx
  571. else
  572. elfsym.st_shndx:=SHN_UNDEF;
  573. symtabsect.write(elfsym,sizeof(elfsym));
  574. end;
  575. { update the .symtab section header }
  576. symtabsect.shlink:=strtabsect.secshidx;
  577. symtabsect.shinfo:=locals;
  578. end;
  579. end;
  580. procedure telf32objectoutput.createshstrtab;
  581. var
  582. sec : tsection;
  583. begin
  584. with telf32data(data) do
  585. begin
  586. with shstrtabsect do
  587. begin
  588. writestr(#0);
  589. symtabsect.shstridx:=writestr('.symtab'#0);
  590. strtabsect.shstridx:=writestr('.strtab'#0);
  591. shstrtabsect.shstridx:=writestr('.shstrtab'#0);
  592. for sec:=low(tsection) to high(tsection) do
  593. if assigned(sects[sec]) then
  594. begin
  595. telf32section(sects[sec]).shstridx:=writestr(sects[sec].name+#0);
  596. if assigned(telf32section(sects[sec]).relocsect) then
  597. telf32section(sects[sec]).relocsect.shstridx:=writestr(telf32section(sects[sec]).relocsect.name+#0);
  598. end;
  599. end;
  600. end;
  601. end;
  602. procedure telf32objectoutput.writesectionheader(s:telf32section);
  603. var
  604. sechdr : telf32sechdr;
  605. begin
  606. fillchar(sechdr,sizeof(sechdr),0);
  607. sechdr.sh_name:=s.shstridx;
  608. sechdr.sh_type:=s.shtype;
  609. sechdr.sh_flags:=s.shflags;
  610. sechdr.sh_offset:=s.datapos;
  611. sechdr.sh_size:=s.datasize;
  612. sechdr.sh_link:=s.shlink;
  613. sechdr.sh_info:=s.shinfo;
  614. sechdr.sh_addralign:=s.addralign;
  615. sechdr.sh_entsize:=s.entsize;
  616. writer.write(sechdr,sizeof(sechdr));
  617. end;
  618. procedure telf32objectoutput.writetodisk;
  619. var
  620. header : telf32header;
  621. datapos,
  622. shoffset,
  623. nsects : longint;
  624. hstab : telf32stab;
  625. sec : tsection;
  626. empty : array[0..63] of byte;
  627. hp : pdynamicblock;
  628. begin
  629. with telf32data(data) do
  630. begin
  631. { calc amount of sections we have }
  632. fillchar(empty,sizeof(empty),0);
  633. nsects:=1;
  634. initsym:=2;
  635. for sec:=low(tsection) to high(tsection) do
  636. if assigned(sects[sec]) then
  637. begin
  638. { each section requires a symbol for relocation }
  639. sects[sec].secsymidx:=initsym;
  640. inc(initsym);
  641. { also create the index in the section header table }
  642. telf32section(sects[sec]).secshidx:=nsects;
  643. inc(nsects);
  644. if assigned(sects[sec].relochead) then
  645. inc(nsects);
  646. end;
  647. { add default sections follows }
  648. shstrtabsect.secshidx:=nsects;
  649. inc(nsects);
  650. symtabsect.secshidx:=nsects;
  651. inc(nsects);
  652. strtabsect.secshidx:=nsects;
  653. inc(nsects);
  654. { For the stab section we need an HdrSym which can now be
  655. calculated more easily }
  656. if assigned(sects[sec_stab]) then
  657. begin
  658. hstab.strpos:=1;
  659. hstab.ntype:=0;
  660. hstab.nother:=0;
  661. hstab.ndesc:=(sects[sec_stab].datasize div sizeof(telf32stab))-1{+1 according to gas output PM};
  662. hstab.nvalue:=sects[sec_stabstr].datasize;
  663. sects[sec_stab].Data.seek(0);
  664. sects[sec_stab].Data.write(hstab,sizeof(hstab));
  665. end;
  666. { Create the relocation sections }
  667. for sec:=low(tsection) to high(tsection) do
  668. if assigned(sects[sec]) and
  669. (sects[sec].nrelocs>0) then
  670. createrelocsection(telf32section(sects[sec]));
  671. { create .symtab }
  672. createsymtab;
  673. { create .shstrtab }
  674. createshstrtab;
  675. { Calculate the filepositions }
  676. datapos:=$40; { elfheader + alignment }
  677. { sections first }
  678. for sec:=low(tsection) to high(tsection) do
  679. if assigned(sects[sec]) then
  680. begin
  681. sects[sec].datapos:=datapos;
  682. if assigned(sects[sec].data) then
  683. inc(datapos,sects[sec].aligneddatasize);
  684. end;
  685. { shstrtab }
  686. shstrtabsect.datapos:=datapos;
  687. inc(datapos,shstrtabsect.aligneddatasize);
  688. { section headers }
  689. shoffset:=datapos;
  690. inc(datapos,nsects*sizeof(telf32sechdr));
  691. { symtab }
  692. symtabsect.datapos:=datapos;
  693. inc(datapos,symtabsect.aligneddatasize);
  694. { strtab }
  695. strtabsect.datapos:=datapos;
  696. inc(datapos,align(strtabsect.datasize,4));
  697. { .rel sections }
  698. for sec:=low(tsection) to high(tsection) do
  699. if assigned(sects[sec]) and
  700. assigned(telf32section(sects[sec]).relocsect) then
  701. begin
  702. telf32section(sects[sec]).relocsect.datapos:=datapos;
  703. inc(datapos,telf32section(sects[sec]).relocsect.aligneddatasize);
  704. end;
  705. { Write ELF Header }
  706. fillchar(header,sizeof(header),0);
  707. header.magic0123:=$464c457f; { = #127'ELF' }
  708. header.file_class:=1;
  709. header.data_encoding:=1;
  710. header.file_version:=1;
  711. header.e_type:=1;
  712. header.e_machine:=3;
  713. header.e_version:=1;
  714. header.e_shoff:=shoffset;
  715. header.e_shstrndx:=shstrtabsect.secshidx;
  716. header.e_shnum:=nsects;
  717. header.e_ehsize:=sizeof(telf32header);
  718. header.e_shentsize:=sizeof(telf32sechdr);
  719. writer.write(header,sizeof(header));
  720. writer.write(empty,$40-sizeof(header)); { align }
  721. { Sections }
  722. for sec:=low(tsection) to high(tsection) do
  723. if assigned(sects[sec]) and
  724. assigned(sects[sec].data) then
  725. begin
  726. sects[sec].alignsection;
  727. hp:=sects[sec].Data.firstblock;
  728. while assigned(hp) do
  729. begin
  730. writer.write(hp^.data,hp^.used);
  731. hp:=hp^.next;
  732. end;
  733. end;
  734. { .shstrtab }
  735. shstrtabsect.alignsection;
  736. hp:=shstrtabsect.Data.firstblock;
  737. while assigned(hp) do
  738. begin
  739. writer.write(hp^.data,hp^.used);
  740. hp:=hp^.next;
  741. end;
  742. { section headers, start with an empty header for sh_undef }
  743. writer.write(empty,sizeof(telf32sechdr));
  744. for sec:=low(tsection) to high(tsection) do
  745. if assigned(sects[sec]) then
  746. begin
  747. writesectionheader(telf32section(sects[sec]));
  748. if assigned(telf32section(sects[sec]).relocsect) then
  749. writesectionheader(telf32section(sects[sec]).relocsect);
  750. end;
  751. writesectionheader(shstrtabsect);
  752. writesectionheader(symtabsect);
  753. writesectionheader(strtabsect);
  754. { .symtab }
  755. symtabsect.alignsection;
  756. hp:=symtabsect.Data.firstblock;
  757. while assigned(hp) do
  758. begin
  759. writer.write(hp^.data,hp^.used);
  760. hp:=hp^.next;
  761. end;
  762. { .strtab }
  763. strtabsect.writealign(4);
  764. hp:=strtabsect.Data.firstblock;
  765. while assigned(hp) do
  766. begin
  767. writer.write(hp^.data,hp^.used);
  768. hp:=hp^.next;
  769. end;
  770. { .rel sections }
  771. for sec:=low(tsection) to high(tsection) do
  772. if assigned(sects[sec]) and
  773. assigned(telf32section(sects[sec]).relocsect) then
  774. begin
  775. telf32section(sects[sec]).relocsect.alignsection;
  776. hp:=telf32section(sects[sec]).relocsect.Data.firstblock;
  777. while assigned(hp) do
  778. begin
  779. writer.write(hp^.data,hp^.used);
  780. hp:=hp^.next;
  781. end;
  782. end;
  783. end;
  784. end;
  785. end.
  786. {
  787. $Log$
  788. Revision 1.6 2001-03-05 21:40:39 peter
  789. * more things for tcoffobjectinput
  790. Revision 1.5 2000/12/25 00:07:26 peter
  791. + new tlinkedlist class (merge of old tstringqueue,tcontainer and
  792. tlinkedlist objects)
  793. Revision 1.4 2000/12/24 12:25:32 peter
  794. + cstreams unit
  795. * dynamicarray object to class
  796. Revision 1.3 2000/12/23 19:59:35 peter
  797. * object to class for ow/og objects
  798. * split objectdata from objectoutput
  799. Revision 1.2 2000/11/12 22:45:14 peter
  800. * moved setting of stab hdrsym
  801. Revision 1.1 2000/11/12 22:20:37 peter
  802. * create generic toutputsection for binary writers
  803. }