ogelf.pas 27 KB

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