ogelf.pas 29 KB

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