ogelf.pas 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924
  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,
  27. { target }
  28. systems,
  29. { assembler }
  30. cpubase,aasm,assemble,
  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:tasmsymbol;relative:relative_type);override;
  65. procedure writesymbol(p:tasmsymbol);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:tasmsymbol;
  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. telf32assembler = class(tinternalassembler)
  83. constructor create(smart:boolean);override;
  84. end;
  85. implementation
  86. uses
  87. {$ifdef delphi}
  88. sysutils,
  89. {$else}
  90. strings,
  91. {$endif}
  92. verbose,
  93. globtype,cutils,globals,fmodule;
  94. const
  95. symbolresize = 200*18;
  96. DataResize = 8192;
  97. const
  98. R_386_32 = 1; { ordinary absolute relocation }
  99. R_386_PC32 = 2; { PC-relative relocation }
  100. R_386_GOT32 = 3; { an offset into GOT }
  101. R_386_PLT32 = 4; { a PC-relative offset into PLT }
  102. R_386_GOTOFF = 9; { an offset from GOT base }
  103. R_386_GOTPC = 10; { a PC-relative offset _to_ GOT }
  104. SHN_UNDEF = 0;
  105. SHN_ABS = $fff1;
  106. SHN_COMMON = $fff2;
  107. SHT_NULL = 0;
  108. SHT_PROGBITS = 1;
  109. SHT_SYMTAB = 2;
  110. SHT_STRTAB = 3;
  111. SHT_RELA = 4;
  112. SHT_HASH = 5;
  113. SHT_DYNAMIC = 6;
  114. SHT_NOTE = 7;
  115. SHT_NOBITS = 8;
  116. SHT_REL = 9;
  117. SHT_SHLIB = 10;
  118. SHT_DYNSYM = 11;
  119. SHF_WRITE = 1;
  120. SHF_ALLOC = 2;
  121. SHF_EXECINSTR = 4;
  122. STB_LOCAL = 0;
  123. STB_GLOBAL = 1;
  124. STB_WEAK = 2;
  125. STT_NOTYPE = 0;
  126. STT_OBJECT = 1;
  127. STT_FUNC = 2;
  128. STT_SECTION = 3;
  129. STT_FILE = 4;
  130. type
  131. { Structures which are written directly to the output file }
  132. telf32header=packed record
  133. magic0123 : longint;
  134. file_class : byte;
  135. data_encoding : byte;
  136. file_version : byte;
  137. padding : array[$07..$0f] of byte;
  138. e_type : word;
  139. e_machine : word;
  140. e_version : longint;
  141. e_entry : longint; { entrypoint }
  142. e_phoff : longint; { program header offset }
  143. e_shoff : longint; { sections header offset }
  144. e_flags : longint;
  145. e_ehsize : word; { elf header size in bytes }
  146. e_phentsize : word; { size of an entry in the program header array }
  147. e_phnum : word; { 0..e_phnum-1 of entrys }
  148. e_shentsize : word; { size of an entry in sections header array }
  149. e_shnum : word; { 0..e_shnum-1 of entrys }
  150. e_shstrndx : word; { index of string section header }
  151. end;
  152. telf32sechdr=packed record
  153. sh_name : longint;
  154. sh_type : longint;
  155. sh_flags : longint;
  156. sh_addr : longint;
  157. sh_offset : longint;
  158. sh_size : longint;
  159. sh_link : longint;
  160. sh_info : longint;
  161. sh_addralign : longint;
  162. sh_entsize : longint;
  163. end;
  164. pelf32reloc=^telf32reloc;
  165. telf32reloc=packed record
  166. address : longint;
  167. info : longint; { bit 0-7: type, 8-31: symbol }
  168. end;
  169. pelf32symbol=^telf32symbol;
  170. telf32symbol=packed record
  171. st_name : longint;
  172. st_value : longint;
  173. st_size : longint;
  174. st_info : byte; { bit 0-3: type, 4-7: bind }
  175. st_other : byte;
  176. st_shndx : word;
  177. end;
  178. pelf32stab=^telf32stab;
  179. telf32stab=packed record
  180. strpos : longint;
  181. ntype : byte;
  182. nother : byte;
  183. ndesc : word;
  184. nvalue : longint;
  185. end;
  186. {****************************************************************************
  187. TSection
  188. ****************************************************************************}
  189. constructor telf32section.createsec(sec:TSection);
  190. var
  191. Aflags,Atype,Aalign,Aentsize : longint;
  192. begin
  193. Aflags:=0;
  194. Atype:=0;
  195. Aalign:=0;
  196. Aentsize:=0;
  197. case sec of
  198. sec_code :
  199. begin
  200. Aflags:=SHF_ALLOC or SHF_EXECINSTR;
  201. AType:=SHT_PROGBITS;
  202. AAlign:=16;
  203. end;
  204. sec_data :
  205. begin
  206. Aflags:=SHF_ALLOC or SHF_WRITE;
  207. AType:=SHT_PROGBITS;
  208. AAlign:=4;
  209. end;
  210. sec_bss :
  211. begin
  212. Aflags:=SHF_ALLOC or SHF_WRITE;
  213. AType:=SHT_NOBITS;
  214. AAlign:=4;
  215. end;
  216. sec_stab :
  217. begin
  218. AType:=SHT_PROGBITS;
  219. AAlign:=4;
  220. Aentsize:=sizeof(telf32stab);
  221. end;
  222. sec_stabstr :
  223. begin
  224. AType:=SHT_STRTAB;
  225. AAlign:=1;
  226. end;
  227. end;
  228. createname(target_asm.secnames[sec],Atype,Aflags,0,0,Aalign,Aentsize);
  229. end;
  230. constructor telf32section.createname(const Aname:string;Atype,Aflags,Alink,Ainfo,Aalign,Aentsize:longint);
  231. begin
  232. inherited create(Aname,Aalign,(AType=SHT_NOBITS));
  233. secshidx:=0;
  234. shstridx:=0;
  235. shtype:=AType;
  236. shflags:=AFlags;
  237. shlink:=Alink;
  238. shinfo:=Ainfo;
  239. entsize:=Aentsize;
  240. relocsect:=nil;
  241. end;
  242. destructor telf32section.destroy;
  243. begin
  244. if assigned(relocsect) then
  245. relocsect.free;
  246. inherited destroy;
  247. end;
  248. {****************************************************************************
  249. TElf32Data
  250. ****************************************************************************}
  251. constructor telf32data.create;
  252. var
  253. s : string;
  254. begin
  255. inherited create;
  256. { reset }
  257. Syms:=TDynamicArray.Create(symbolresize);
  258. { default sections }
  259. symtabsect:=telf32section.createname('.symtab',2,0,0,0,4,16);
  260. strtabsect:=telf32section.createname('.strtab',3,0,0,0,1,0);
  261. shstrtabsect:=telf32section.createname('.shstrtab',3,0,0,0,1,0);
  262. { insert the empty and filename as first in strtab }
  263. strtabsect.writestr(#0);
  264. strtabsect.writestr(SplitFileName(current_module.mainsource^)+#0);
  265. { we need at least the following sections }
  266. createsection(sec_code);
  267. createsection(sec_data);
  268. createsection(sec_bss);
  269. { create stabs sections if debugging }
  270. if (cs_debuginfo in aktmoduleswitches) then
  271. begin
  272. createsection(sec_stab);
  273. createsection(sec_stabstr);
  274. writestabs(sec_none,0,nil,0,0,0,false);
  275. { write zero pchar and name together (PM) }
  276. s:=#0+SplitFileName(current_module.mainsource^)+#0;
  277. sects[sec_stabstr].write(s[1],length(s));
  278. end;
  279. end;
  280. destructor telf32data.destroy;
  281. begin
  282. Syms.Free;
  283. symtabsect.free;
  284. strtabsect.free;
  285. shstrtabsect.free;
  286. inherited destroy;
  287. end;
  288. procedure telf32data.createsection(sec:tsection);
  289. begin
  290. sects[sec]:=telf32Section.createsec(Sec);
  291. end;
  292. procedure telf32data.writesymbol(p:tasmsymbol);
  293. var
  294. sym : toutputsymbol;
  295. begin
  296. { already written ? }
  297. if p.idx<>-1 then
  298. exit;
  299. { be sure that the section will exists }
  300. if (p.section<>sec_none) and not(assigned(sects[p.section])) then
  301. createsection(p.section);
  302. FillChar(sym,sizeof(sym),0);
  303. sym.size:=p.size;
  304. sym.bind:=p.bind;
  305. sym.typ:=p.typ;
  306. { if local of global then set the section value to the address
  307. of the symbol }
  308. case sym.bind of
  309. AB_LOCAL,
  310. AB_GLOBAL :
  311. begin
  312. sym.section:=p.section;
  313. sym.value:=p.address;
  314. end;
  315. AB_COMMON :
  316. begin
  317. sym.value:=$10;
  318. end;
  319. end;
  320. { store the symbol, but not the local ones }
  321. if (sym.bind<>AB_LOCAL) then
  322. begin
  323. { symbolname, write the #0 separate to overcome 255+1 char not possible }
  324. sym.nameidx:=strtabsect.datasize;
  325. strtabsect.writestr(p.name);
  326. strtabsect.writestr(#0);
  327. { update the asmsymbol index }
  328. p.idx:=syms.size div sizeof(toutputsymbol);
  329. { symbol }
  330. Syms.write(sym,sizeof(toutputsymbol));
  331. end
  332. else
  333. begin
  334. p.idx:=-2; { local }
  335. end;
  336. end;
  337. procedure telf32data.writereloc(data,len:longint;p:tasmsymbol;relative:relative_type);
  338. var
  339. symaddr : longint;
  340. begin
  341. if not assigned(sects[currsec]) then
  342. createsection(currsec);
  343. if assigned(p) then
  344. begin
  345. { real address of the symbol }
  346. symaddr:=p.address;
  347. { no symbol relocation need inside a section }
  348. if p.section=currsec then
  349. begin
  350. case relative of
  351. relative_false :
  352. begin
  353. sects[currsec].addsectionreloc(sects[currsec].datasize,currsec,relative_false);
  354. inc(data,symaddr);
  355. end;
  356. relative_true :
  357. begin
  358. inc(data,symaddr-len-sects[currsec].datasize);
  359. end;
  360. relative_rva :
  361. internalerror(3219583);
  362. end;
  363. end
  364. else
  365. begin
  366. writesymbol(p);
  367. if (p.section<>sec_none) and (relative<>relative_true) then
  368. begin
  369. sects[currsec].addsectionreloc(sects[currsec].datasize,p.section,relative);
  370. inc(data,symaddr);
  371. end
  372. else
  373. sects[currsec].addsymreloc(sects[currsec].datasize,p,relative);
  374. if relative=relative_true then
  375. begin
  376. if p.bind=AB_EXTERNAL then
  377. dec(data,len)
  378. else
  379. dec(data,len+sects[currsec].datasize);
  380. end;
  381. end;
  382. end;
  383. sects[currsec].write(data,len);
  384. end;
  385. procedure telf32data.writestabs(section:tsection;offset:longint;p:pchar;nidx,nother,line:longint;reloc : boolean);
  386. var
  387. stab : telf32stab;
  388. s : tsection;
  389. begin
  390. s:=section;
  391. if reloc then
  392. begin
  393. if (offset=-1) then
  394. begin
  395. if s=sec_none then
  396. offset:=0
  397. else
  398. offset:=sects[s].datasize;
  399. end;
  400. end;
  401. fillchar(stab,sizeof(telf32stab),0);
  402. if assigned(p) and (p[0]<>#0) then
  403. begin
  404. stab.strpos:=sects[sec_stabstr].datasize;
  405. sects[sec_stabstr].write(p^,strlen(p)+1);
  406. end;
  407. stab.ntype:=nidx;
  408. stab.ndesc:=line;
  409. stab.nother:=nother;
  410. stab.nvalue:=offset;
  411. sects[sec_stab].write(stab,sizeof(stab));
  412. { when the offset is not 0 then write a relocation, take also the
  413. hdrstab into account with the offset }
  414. if reloc then
  415. sects[sec_stab].addsectionreloc(sects[sec_stab].datasize-4,s,relative_false);
  416. end;
  417. procedure telf32data.writesymstabs(section:tsection;offset:longint;p:pchar;ps:tasmsymbol;
  418. nidx,nother,line:longint;reloc:boolean);
  419. var
  420. stab : telf32stab;
  421. begin
  422. if reloc then
  423. begin
  424. if (offset=-1) then
  425. begin
  426. if section=sec_none then
  427. offset:=0
  428. else
  429. offset:=sects[section].datasize;
  430. end;
  431. end;
  432. fillchar(stab,sizeof(telf32stab),0);
  433. if assigned(p) and (p[0]<>#0) then
  434. begin
  435. stab.strpos:=sects[sec_stabstr].datasize;
  436. sects[sec_stabstr].write(p^,strlen(p)+1);
  437. end;
  438. stab.ntype:=nidx;
  439. stab.ndesc:=line;
  440. stab.nother:=nother;
  441. stab.nvalue:=offset;
  442. sects[sec_stab].write(stab,sizeof(stab));
  443. { when the offset is not 0 then write a relocation, take also the
  444. hdrstab into account with the offset }
  445. if reloc then
  446. sects[sec_stab].addsymreloc(sects[sec_stab].datasize-4,ps,relative_false);
  447. end;
  448. procedure telf32data.setsectionsizes(var s:tsecsize);
  449. begin
  450. end;
  451. {****************************************************************************
  452. telf32objectoutput
  453. ****************************************************************************}
  454. function telf32objectoutput.initwriting(const fn:string):boolean;
  455. begin
  456. result:=inherited initwriting(fn);
  457. if result then
  458. begin
  459. initsym:=0;
  460. Fdata:=telf32data.create;
  461. end;
  462. end;
  463. procedure telf32objectoutput.createrelocsection(s:telf32section);
  464. var
  465. rel : telf32reloc;
  466. hr,r : poutputreloc;
  467. relsym,reltyp : longint;
  468. begin
  469. with telf32data(data) do
  470. begin
  471. { create the reloc section }
  472. s.relocsect:=telf32section.createname('.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. end;
  510. procedure telf32objectoutput.createsymtab;
  511. var
  512. elfsym : telf32symbol;
  513. sym : toutputsymbol;
  514. sec : tsection;
  515. locals,
  516. i : longint;
  517. begin
  518. with telf32data(data) do
  519. begin
  520. locals:=2;
  521. { empty entry }
  522. fillchar(elfsym,sizeof(elfsym),0);
  523. symtabsect.write(elfsym,sizeof(elfsym));
  524. { filename entry }
  525. elfsym.st_name:=1;
  526. elfsym.st_info:=STT_FILE;
  527. elfsym.st_shndx:=SHN_ABS;
  528. symtabsect.write(elfsym,sizeof(elfsym));
  529. { section }
  530. for sec:=low(tsection) to high(tsection) do
  531. if assigned(sects[sec]) then
  532. begin
  533. fillchar(elfsym,sizeof(elfsym),0);
  534. elfsym.st_name:=telf32section(sects[sec]).shstridx;
  535. elfsym.st_info:=STT_SECTION;
  536. elfsym.st_shndx:=telf32section(sects[sec]).secshidx;
  537. symtabsect.write(elfsym,sizeof(elfsym));
  538. inc(locals);
  539. end;
  540. { symbols }
  541. Syms.seek(0);
  542. for i:=1 to (Syms.size div sizeof(toutputsymbol)) do
  543. begin
  544. Syms.read(sym,sizeof(toutputsymbol));
  545. fillchar(elfsym,sizeof(elfsym),0);
  546. elfsym.st_name:=sym.nameidx;
  547. elfsym.st_value:=sym.value;
  548. elfsym.st_size:=sym.size;
  549. case sym.bind of
  550. AB_LOCAL :
  551. begin
  552. elfsym.st_info:=STB_LOCAL shl 4;
  553. inc(locals);
  554. end;
  555. AB_COMMON,
  556. AB_EXTERNAL,
  557. AB_GLOBAL :
  558. elfsym.st_info:=STB_GLOBAL shl 4;
  559. end;
  560. if sym.bind<>AB_EXTERNAL then
  561. begin
  562. case sym.typ of
  563. AT_FUNCTION :
  564. elfsym.st_info:=elfsym.st_info or STT_FUNC;
  565. AT_DATA :
  566. elfsym.st_info:=elfsym.st_info or STT_OBJECT;
  567. end;
  568. end;
  569. if sym.bind=AB_COMMON then
  570. elfsym.st_shndx:=SHN_COMMON
  571. else
  572. if assigned(sects[sym.section]) then
  573. elfsym.st_shndx:=telf32section(sects[sym.section]).secshidx
  574. else
  575. elfsym.st_shndx:=SHN_UNDEF;
  576. symtabsect.write(elfsym,sizeof(elfsym));
  577. end;
  578. { update the .symtab section header }
  579. symtabsect.shlink:=strtabsect.secshidx;
  580. symtabsect.shinfo:=locals;
  581. end;
  582. end;
  583. procedure telf32objectoutput.createshstrtab;
  584. var
  585. sec : tsection;
  586. begin
  587. with telf32data(data) do
  588. begin
  589. with shstrtabsect do
  590. begin
  591. writestr(#0);
  592. symtabsect.shstridx:=writestr('.symtab'#0);
  593. strtabsect.shstridx:=writestr('.strtab'#0);
  594. shstrtabsect.shstridx:=writestr('.shstrtab'#0);
  595. for sec:=low(tsection) to high(tsection) do
  596. if assigned(sects[sec]) then
  597. begin
  598. telf32section(sects[sec]).shstridx:=writestr(sects[sec].name+#0);
  599. if assigned(telf32section(sects[sec]).relocsect) then
  600. telf32section(sects[sec]).relocsect.shstridx:=writestr(telf32section(sects[sec]).relocsect.name+#0);
  601. end;
  602. end;
  603. end;
  604. end;
  605. procedure telf32objectoutput.writesectionheader(s:telf32section);
  606. var
  607. sechdr : telf32sechdr;
  608. begin
  609. fillchar(sechdr,sizeof(sechdr),0);
  610. sechdr.sh_name:=s.shstridx;
  611. sechdr.sh_type:=s.shtype;
  612. sechdr.sh_flags:=s.shflags;
  613. sechdr.sh_offset:=s.datapos;
  614. sechdr.sh_size:=s.datasize;
  615. sechdr.sh_link:=s.shlink;
  616. sechdr.sh_info:=s.shinfo;
  617. sechdr.sh_addralign:=s.addralign;
  618. sechdr.sh_entsize:=s.entsize;
  619. writer.write(sechdr,sizeof(sechdr));
  620. end;
  621. procedure telf32objectoutput.writetodisk;
  622. var
  623. header : telf32header;
  624. datapos,
  625. shoffset,
  626. nsects : longint;
  627. hstab : telf32stab;
  628. sec : tsection;
  629. empty : array[0..63] of byte;
  630. hp : pdynamicblock;
  631. begin
  632. with telf32data(data) do
  633. begin
  634. { calc amount of sections we have }
  635. fillchar(empty,sizeof(empty),0);
  636. nsects:=1;
  637. initsym:=2;
  638. for sec:=low(tsection) to high(tsection) do
  639. if assigned(sects[sec]) then
  640. begin
  641. { each section requires a symbol for relocation }
  642. sects[sec].secsymidx:=initsym;
  643. inc(initsym);
  644. { also create the index in the section header table }
  645. telf32section(sects[sec]).secshidx:=nsects;
  646. inc(nsects);
  647. if assigned(sects[sec].relochead) then
  648. inc(nsects);
  649. end;
  650. { add default sections follows }
  651. shstrtabsect.secshidx:=nsects;
  652. inc(nsects);
  653. symtabsect.secshidx:=nsects;
  654. inc(nsects);
  655. strtabsect.secshidx:=nsects;
  656. inc(nsects);
  657. { For the stab section we need an HdrSym which can now be
  658. calculated more easily }
  659. if assigned(sects[sec_stab]) then
  660. begin
  661. hstab.strpos:=1;
  662. hstab.ntype:=0;
  663. hstab.nother:=0;
  664. hstab.ndesc:=(sects[sec_stab].datasize div sizeof(telf32stab))-1{+1 according to gas output PM};
  665. hstab.nvalue:=sects[sec_stabstr].datasize;
  666. sects[sec_stab].Data.seek(0);
  667. sects[sec_stab].Data.write(hstab,sizeof(hstab));
  668. end;
  669. { Create the relocation sections }
  670. for sec:=low(tsection) to high(tsection) do
  671. if assigned(sects[sec]) and
  672. (sects[sec].nrelocs>0) then
  673. createrelocsection(telf32section(sects[sec]));
  674. { create .symtab }
  675. createsymtab;
  676. { create .shstrtab }
  677. createshstrtab;
  678. { Calculate the filepositions }
  679. datapos:=$40; { elfheader + alignment }
  680. { sections first }
  681. for sec:=low(tsection) to high(tsection) do
  682. if assigned(sects[sec]) then
  683. begin
  684. sects[sec].datapos:=datapos;
  685. if assigned(sects[sec].data) then
  686. inc(datapos,sects[sec].aligneddatasize);
  687. end;
  688. { shstrtab }
  689. shstrtabsect.datapos:=datapos;
  690. inc(datapos,shstrtabsect.aligneddatasize);
  691. { section headers }
  692. shoffset:=datapos;
  693. inc(datapos,nsects*sizeof(telf32sechdr));
  694. { symtab }
  695. symtabsect.datapos:=datapos;
  696. inc(datapos,symtabsect.aligneddatasize);
  697. { strtab }
  698. strtabsect.datapos:=datapos;
  699. inc(datapos,align(strtabsect.datasize,4));
  700. { .rel sections }
  701. for sec:=low(tsection) to high(tsection) do
  702. if assigned(sects[sec]) and
  703. assigned(telf32section(sects[sec]).relocsect) then
  704. begin
  705. telf32section(sects[sec]).relocsect.datapos:=datapos;
  706. inc(datapos,telf32section(sects[sec]).relocsect.aligneddatasize);
  707. end;
  708. { Write ELF Header }
  709. fillchar(header,sizeof(header),0);
  710. header.magic0123:=$464c457f; { = #127'ELF' }
  711. header.file_class:=1;
  712. header.data_encoding:=1;
  713. header.file_version:=1;
  714. header.e_type:=1;
  715. header.e_machine:=3;
  716. header.e_version:=1;
  717. header.e_shoff:=shoffset;
  718. header.e_shstrndx:=shstrtabsect.secshidx;
  719. header.e_shnum:=nsects;
  720. header.e_ehsize:=sizeof(telf32header);
  721. header.e_shentsize:=sizeof(telf32sechdr);
  722. writer.write(header,sizeof(header));
  723. writer.write(empty,$40-sizeof(header)); { align }
  724. { Sections }
  725. for sec:=low(tsection) to high(tsection) do
  726. if assigned(sects[sec]) and
  727. assigned(sects[sec].data) then
  728. begin
  729. sects[sec].alignsection;
  730. hp:=sects[sec].Data.firstblock;
  731. while assigned(hp) do
  732. begin
  733. writer.write(hp^.data,hp^.used);
  734. hp:=hp^.next;
  735. end;
  736. end;
  737. { .shstrtab }
  738. shstrtabsect.alignsection;
  739. hp:=shstrtabsect.Data.firstblock;
  740. while assigned(hp) do
  741. begin
  742. writer.write(hp^.data,hp^.used);
  743. hp:=hp^.next;
  744. end;
  745. { section headers, start with an empty header for sh_undef }
  746. writer.write(empty,sizeof(telf32sechdr));
  747. for sec:=low(tsection) to high(tsection) do
  748. if assigned(sects[sec]) then
  749. begin
  750. writesectionheader(telf32section(sects[sec]));
  751. if assigned(telf32section(sects[sec]).relocsect) then
  752. writesectionheader(telf32section(sects[sec]).relocsect);
  753. end;
  754. writesectionheader(shstrtabsect);
  755. writesectionheader(symtabsect);
  756. writesectionheader(strtabsect);
  757. { .symtab }
  758. symtabsect.alignsection;
  759. hp:=symtabsect.Data.firstblock;
  760. while assigned(hp) do
  761. begin
  762. writer.write(hp^.data,hp^.used);
  763. hp:=hp^.next;
  764. end;
  765. { .strtab }
  766. strtabsect.writealign(4);
  767. hp:=strtabsect.Data.firstblock;
  768. while assigned(hp) do
  769. begin
  770. writer.write(hp^.data,hp^.used);
  771. hp:=hp^.next;
  772. end;
  773. { .rel sections }
  774. for sec:=low(tsection) to high(tsection) do
  775. if assigned(sects[sec]) and
  776. assigned(telf32section(sects[sec]).relocsect) then
  777. begin
  778. telf32section(sects[sec]).relocsect.alignsection;
  779. hp:=telf32section(sects[sec]).relocsect.Data.firstblock;
  780. while assigned(hp) do
  781. begin
  782. writer.write(hp^.data,hp^.used);
  783. hp:=hp^.next;
  784. end;
  785. end;
  786. end;
  787. end;
  788. {****************************************************************************
  789. TELFAssembler
  790. ****************************************************************************}
  791. constructor TELF32Assembler.Create(smart:boolean);
  792. begin
  793. inherited Create(smart);
  794. objectoutput:=telf32objectoutput.create(smart);
  795. end;
  796. {*****************************************************************************
  797. Initialize
  798. *****************************************************************************}
  799. const
  800. as_i386_elf32_info : tasminfo =
  801. (
  802. id : as_i386_elf32;
  803. idtxt : 'ELF';
  804. asmbin : '';
  805. asmcmd : '';
  806. supported_target : target_any; //target_i386_linux;
  807. outputbinary : true;
  808. allowdirect : false;
  809. externals : true;
  810. needar : false;
  811. labelprefix : '.L';
  812. comment : '';
  813. secnames : ('',
  814. '.text','.data','.bss',
  815. '.idata$2','.idata$4','.idata$5','.idata$6','.idata$7','.edata',
  816. '.stab','.stabstr')
  817. );
  818. initialization
  819. RegisterAssembler(as_i386_elf32_info,TElf32Assembler);
  820. end.
  821. {
  822. $Log$
  823. Revision 1.9 2001-05-04 19:50:58 peter
  824. * finally added the missing outputbinary field that was missing
  825. Revision 1.8 2001/04/18 22:01:54 peter
  826. * registration of targets and assemblers
  827. Revision 1.7 2001/04/13 01:22:10 peter
  828. * symtable change to classes
  829. * range check generation and errors fixed, make cycle DEBUG=1 works
  830. * memory leaks fixed
  831. Revision 1.6 2001/03/05 21:40:39 peter
  832. * more things for tcoffobjectinput
  833. Revision 1.5 2000/12/25 00:07:26 peter
  834. + new tlinkedlist class (merge of old tstringqueue,tcontainer and
  835. tlinkedlist objects)
  836. Revision 1.4 2000/12/24 12:25:32 peter
  837. + cstreams unit
  838. * dynamicarray object to class
  839. Revision 1.3 2000/12/23 19:59:35 peter
  840. * object to class for ow/og objects
  841. * split objectdata from objectoutput
  842. Revision 1.2 2000/11/12 22:45:14 peter
  843. * moved setting of stab hdrsym
  844. Revision 1.1 2000/11/12 22:20:37 peter
  845. * create generic toutputsection for binary writers
  846. }