ogelf.pas 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883
  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<>'') 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. stabssec.addsymreloc(stabssec.datasize-4,ps,RELOC_ABSOLUTE);
  403. end;
  404. procedure telf32objectdata.beforealloc;
  405. begin
  406. { create stabs sections if debugging }
  407. if (cs_debuginfo in aktmoduleswitches) then
  408. begin
  409. StabsSec.Alloc(sizeof(telf32stab));
  410. StabStrSec.Alloc(length(SplitFileName(current_module.mainsource^))+2);
  411. end;
  412. end;
  413. procedure telf32objectdata.beforewrite;
  414. var
  415. s : string;
  416. begin
  417. { create stabs sections if debugging }
  418. if (cs_debuginfo in aktmoduleswitches) then
  419. begin
  420. writestab(0,nil,0,0,0,nil);
  421. { write zero pchar and name together (PM) }
  422. s:=#0+SplitFileName(current_module.mainsource^)+#0;
  423. stabstrsec.write(s[1],length(s));
  424. end;
  425. end;
  426. {****************************************************************************
  427. telf32objectoutput
  428. ****************************************************************************}
  429. function telf32objectoutput.newobjectdata(const n:string):TAsmObjectData;
  430. begin
  431. result:=telf32objectdata.create(n);
  432. end;
  433. procedure telf32objectoutput.createrelocsection(s:telf32section);
  434. var
  435. rel : telf32reloc;
  436. r : tasmrelocation;
  437. relsym,reltyp : longint;
  438. begin
  439. with elf32data do
  440. begin
  441. {$ifdef userodata}
  442. { rodata can't have relocations }
  443. if s.sectype=sec_rodata then
  444. begin
  445. if assigned(s.relocations.first) then
  446. internalerror(200408251);
  447. exit;
  448. end;
  449. {$endif userodata}
  450. { create the reloc section }
  451. s.relocsect:=telf32section.create_ext('.rel'+s.name,sec_custom,9,0,symtabsect.secshidx,s.secshidx,4,8);
  452. { add the relocations }
  453. r:=TasmRelocation(s.relocations.first);
  454. while assigned(r) do
  455. begin
  456. rel.address:=r.address;
  457. if assigned(r.symbol) then
  458. begin
  459. if (r.symbol.currbind=AB_LOCAL) then
  460. relsym:=r.symbol.section.secsymidx
  461. else
  462. begin
  463. if r.symbol.indexnr=-1 then
  464. internalerror(4321);
  465. { indexnr starts with 1, ELF starts with 0 }
  466. relsym:=r.symbol.indexnr+initsym-1;
  467. end;
  468. end
  469. else
  470. if r.section<>nil then
  471. relsym:=r.section.secsymidx
  472. else
  473. relsym:=SHN_UNDEF;
  474. case r.typ of
  475. RELOC_RELATIVE :
  476. reltyp:=R_386_PC32;
  477. RELOC_ABSOLUTE :
  478. reltyp:=R_386_32;
  479. end;
  480. rel.info:=(relsym shl 8) or reltyp;
  481. { write reloc }
  482. s.relocsect.write(rel,sizeof(rel));
  483. r:=TAsmRelocation(r.next);
  484. end;
  485. end;
  486. end;
  487. procedure telf32objectoutput.section_write_symbol(p:tnamedindexitem;arg:pointer);
  488. var
  489. elfsym : telf32symbol;
  490. begin
  491. fillchar(elfsym,sizeof(elfsym),0);
  492. elfsym.st_name:=telf32section(p).shstridx;
  493. elfsym.st_info:=STT_SECTION;
  494. elfsym.st_shndx:=telf32section(p).secshidx;
  495. elf32data.symtabsect.write(elfsym,sizeof(elfsym));
  496. { increase locals count }
  497. inc(plongint(arg)^);
  498. end;
  499. procedure telf32objectoutput.createsymtab;
  500. var
  501. elfsym : telf32symbol;
  502. locals : longint;
  503. sym : tasmsymbol;
  504. begin
  505. with elf32data do
  506. begin
  507. locals:=2;
  508. { empty entry }
  509. fillchar(elfsym,sizeof(elfsym),0);
  510. symtabsect.write(elfsym,sizeof(elfsym));
  511. { filename entry }
  512. elfsym.st_name:=1;
  513. elfsym.st_info:=STT_FILE;
  514. elfsym.st_shndx:=SHN_ABS;
  515. symtabsect.write(elfsym,sizeof(elfsym));
  516. { section }
  517. sects.foreach(@section_write_symbol,@locals);
  518. { symbols }
  519. sym:=Tasmsymbol(symbols.First);
  520. while assigned(sym) do
  521. begin
  522. fillchar(elfsym,sizeof(elfsym),0);
  523. { symbolname, write the #0 separate to overcome 255+1 char not possible }
  524. elfsym.st_name:=strtabsect.datasize;
  525. strtabsect.writestr(sym.name);
  526. strtabsect.writestr(#0);
  527. case sym.currbind of
  528. AB_LOCAL,
  529. AB_GLOBAL :
  530. elfsym.st_value:=sym.address;
  531. AB_COMMON :
  532. elfsym.st_value:=$10;
  533. end;
  534. elfsym.st_size:=sym.size;
  535. case sym.currbind of
  536. AB_LOCAL :
  537. begin
  538. elfsym.st_info:=STB_LOCAL shl 4;
  539. inc(locals);
  540. end;
  541. AB_COMMON,
  542. AB_EXTERNAL,
  543. AB_GLOBAL :
  544. elfsym.st_info:=STB_GLOBAL shl 4;
  545. end;
  546. if (sym.currbind<>AB_EXTERNAL) and
  547. not(assigned(sym.section) and
  548. (sym.section.sectype=sec_bss)) then
  549. begin
  550. case sym.typ of
  551. AT_FUNCTION :
  552. elfsym.st_info:=elfsym.st_info or STT_FUNC;
  553. AT_DATA :
  554. elfsym.st_info:=elfsym.st_info or STT_OBJECT;
  555. end;
  556. end;
  557. if sym.currbind=AB_COMMON then
  558. elfsym.st_shndx:=SHN_COMMON
  559. else
  560. if assigned(sym.section) then
  561. elfsym.st_shndx:=telf32section(sym.section).secshidx
  562. else
  563. elfsym.st_shndx:=SHN_UNDEF;
  564. symtabsect.write(elfsym,sizeof(elfsym));
  565. sym:=tasmsymbol(sym.indexnext);
  566. end;
  567. { update the .symtab section header }
  568. symtabsect.shlink:=strtabsect.secshidx;
  569. symtabsect.shinfo:=locals;
  570. end;
  571. end;
  572. procedure telf32objectoutput.section_write_sh_string(p:tnamedindexitem;arg:pointer);
  573. begin
  574. telf32section(p).shstridx:=elf32data.shstrtabsect.writestr(tasmsection(p).name+#0);
  575. if assigned(telf32section(p).relocsect) then
  576. telf32section(p).relocsect.shstridx:=elf32data.shstrtabsect.writestr(telf32section(p).relocsect.name+#0);
  577. end;
  578. procedure telf32objectoutput.createshstrtab;
  579. begin
  580. with elf32data do
  581. begin
  582. with shstrtabsect do
  583. begin
  584. writestr(#0);
  585. symtabsect.shstridx:=writestr('.symtab'#0);
  586. strtabsect.shstridx:=writestr('.strtab'#0);
  587. shstrtabsect.shstridx:=writestr('.shstrtab'#0);
  588. sects.foreach(@section_write_sh_string,nil);
  589. end;
  590. end;
  591. end;
  592. procedure telf32objectoutput.writesectionheader(s:telf32section);
  593. var
  594. sechdr : telf32sechdr;
  595. begin
  596. fillchar(sechdr,sizeof(sechdr),0);
  597. sechdr.sh_name:=s.shstridx;
  598. sechdr.sh_type:=s.shtype;
  599. sechdr.sh_flags:=s.shflags;
  600. sechdr.sh_offset:=s.datapos;
  601. sechdr.sh_size:=s.datasize;
  602. sechdr.sh_link:=s.shlink;
  603. sechdr.sh_info:=s.shinfo;
  604. sechdr.sh_addralign:=s.addralign;
  605. sechdr.sh_entsize:=s.entsize;
  606. writer.write(sechdr,sizeof(sechdr));
  607. end;
  608. procedure telf32objectoutput.writesectiondata(s:telf32section);
  609. var
  610. hp : pdynamicblock;
  611. begin
  612. FWriter.writezeros(s.dataalignbytes);
  613. s.alignsection;
  614. hp:=s.data.firstblock;
  615. while assigned(hp) do
  616. begin
  617. FWriter.write(hp^.data,hp^.used);
  618. hp:=hp^.next;
  619. end;
  620. end;
  621. procedure telf32objectoutput.section_number_symbol(p:tnamedindexitem;arg:pointer);
  622. begin
  623. tasmsection(p).secsymidx:=plongint(arg)^;
  624. inc(plongint(arg)^);
  625. end;
  626. procedure telf32objectoutput.section_count_sects(p:tnamedindexitem;arg:pointer);
  627. begin
  628. telf32section(p).secshidx:=plongint(arg)^;
  629. inc(plongint(arg)^);
  630. if telf32section(p).relocations.count>0 then
  631. inc(plongint(arg)^);
  632. end;
  633. procedure telf32objectoutput.section_create_relocsec(p:tnamedindexitem;arg:pointer);
  634. begin
  635. if (telf32section(p).relocations.count>0) then
  636. createrelocsection(telf32section(p));
  637. end;
  638. procedure telf32objectoutput.section_set_datapos(p:tnamedindexitem;arg:pointer);
  639. begin
  640. if (aso_alloconly in tasmsection(p).secoptions) then
  641. tasmsection(p).datapos:=paint(arg)^
  642. else
  643. tasmsection(p).setdatapos(paint(arg)^);
  644. end;
  645. procedure telf32objectoutput.section_relocsec_set_datapos(p:tnamedindexitem;arg:pointer);
  646. begin
  647. if assigned(telf32section(p).relocsect) then
  648. telf32section(p).relocsect.setdatapos(paint(arg)^);
  649. end;
  650. procedure telf32objectoutput.section_write_data(p:tnamedindexitem;arg:pointer);
  651. begin
  652. if (aso_alloconly in tasmsection(p).secoptions) then
  653. exit;
  654. if tasmsection(p).data=nil then
  655. internalerror(200403073);
  656. writesectiondata(telf32section(p));
  657. end;
  658. procedure telf32objectoutput.section_write_sechdr(p:tnamedindexitem;arg:pointer);
  659. begin
  660. writesectionheader(telf32section(p));
  661. if assigned(telf32section(p).relocsect) then
  662. writesectionheader(telf32section(p).relocsect);
  663. end;
  664. procedure telf32objectoutput.section_write_relocsec(p:tnamedindexitem;arg:pointer);
  665. begin
  666. if assigned(telf32section(p).relocsect) then
  667. writesectiondata(telf32section(p).relocsect);
  668. end;
  669. function telf32objectoutput.writedata(data:TAsmObjectData):boolean;
  670. var
  671. header : telf32header;
  672. datapos : aint;
  673. shoffset,
  674. nsects : longint;
  675. hstab : telf32stab;
  676. empty : array[0..63] of byte;
  677. begin
  678. result:=false;
  679. elf32data:=telf32objectdata(data);
  680. with elf32data do
  681. begin
  682. { calc amount of sections we have }
  683. initsym:=2;
  684. nsects:=1;
  685. fillchar(empty,sizeof(empty),0);
  686. { each section requires a symbol for relocation }
  687. sects.foreach(@section_number_symbol,@initsym);
  688. { also create the index in the section header table }
  689. sects.foreach(@section_count_sects,@nsects);
  690. { add default sections follows }
  691. shstrtabsect.secshidx:=nsects;
  692. inc(nsects);
  693. symtabsect.secshidx:=nsects;
  694. inc(nsects);
  695. strtabsect.secshidx:=nsects;
  696. inc(nsects);
  697. { For the stab section we need an HdrSym which can now be
  698. calculated more easily }
  699. if assigned(stabssec) then
  700. begin
  701. hstab.strpos:=1;
  702. hstab.ntype:=0;
  703. hstab.nother:=0;
  704. hstab.ndesc:=(stabssec.datasize div sizeof(telf32stab))-1{+1 according to gas output PM};
  705. hstab.nvalue:=stabstrsec.datasize;
  706. stabssec.Data.seek(0);
  707. stabssec.Data.write(hstab,sizeof(hstab));
  708. end;
  709. { Create the relocation sections }
  710. sects.foreach(@section_create_relocsec,nil);
  711. { create .symtab and .strtab }
  712. createsymtab;
  713. { create .shstrtab }
  714. createshstrtab;
  715. { Calculate the filepositions }
  716. datapos:=$40; { elfheader + alignment }
  717. { sections first }
  718. sects.foreach(@section_set_datapos,@datapos);
  719. { shstrtab }
  720. shstrtabsect.setdatapos(datapos);
  721. { section headers }
  722. shoffset:=datapos;
  723. inc(datapos,nsects*sizeof(telf32sechdr));
  724. { symtab }
  725. symtabsect.setdatapos(datapos);
  726. { strtab }
  727. strtabsect.setdatapos(datapos);
  728. { .rel sections }
  729. sects.foreach(@section_relocsec_set_datapos,@datapos);
  730. { Write ELF Header }
  731. fillchar(header,sizeof(header),0);
  732. header.magic0123:=$464c457f; { = #127'ELF' }
  733. header.file_class:=1;
  734. header.data_encoding:=1;
  735. header.file_version:=1;
  736. header.e_type:=1;
  737. header.e_machine:=3;
  738. header.e_version:=1;
  739. header.e_shoff:=shoffset;
  740. header.e_shstrndx:=shstrtabsect.secshidx;
  741. header.e_shnum:=nsects;
  742. header.e_ehsize:=sizeof(telf32header);
  743. header.e_shentsize:=sizeof(telf32sechdr);
  744. writer.write(header,sizeof(header));
  745. writer.write(empty,$40-sizeof(header)); { align }
  746. { Sections }
  747. sects.foreach(@section_write_data,nil);
  748. { .shstrtab }
  749. writesectiondata(shstrtabsect);
  750. { section headers, start with an empty header for sh_undef }
  751. writer.write(empty,sizeof(telf32sechdr));
  752. sects.foreach(@section_write_sechdr,nil);
  753. writesectionheader(shstrtabsect);
  754. writesectionheader(symtabsect);
  755. writesectionheader(strtabsect);
  756. { .symtab }
  757. writesectiondata(symtabsect);
  758. { .strtab }
  759. writesectiondata(strtabsect);
  760. { .rel sections }
  761. sects.foreach(@section_write_relocsec,nil);
  762. end;
  763. result:=true;
  764. end;
  765. {****************************************************************************
  766. TELFAssembler
  767. ****************************************************************************}
  768. constructor TELF32Assembler.Create(smart:boolean);
  769. begin
  770. inherited Create(smart);
  771. objectoutput:=telf32objectoutput.create(smart);
  772. end;
  773. {*****************************************************************************
  774. Initialize
  775. *****************************************************************************}
  776. const
  777. as_i386_elf32_info : tasminfo =
  778. (
  779. id : as_i386_elf32;
  780. idtxt : 'ELF';
  781. asmbin : '';
  782. asmcmd : '';
  783. supported_target : system_any; //target_i386_linux;
  784. flags : [af_outputbinary,af_smartlink_sections];
  785. labelprefix : '.L';
  786. comment : '';
  787. );
  788. initialization
  789. RegisterAssembler(as_i386_elf32_info,TElf32Assembler);
  790. end.