ogelf.pas 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885
  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. var
  274. s : string;
  275. begin
  276. inherited create(n);
  277. CAsmSection:=TElf32Section;
  278. { reset }
  279. Syms:=TDynamicArray.Create(symbolresize);
  280. { default sections }
  281. symtabsect:=telf32section.create_ext('.symtab',sec_custom,2,0,0,0,4,16);
  282. strtabsect:=telf32section.create_ext('.strtab',sec_custom,3,0,0,0,1,0);
  283. shstrtabsect:=telf32section.create_ext('.shstrtab',sec_custom,3,0,0,0,1,0);
  284. { insert the empty and filename as first in strtab }
  285. strtabsect.writestr(#0);
  286. strtabsect.writestr(SplitFileName(current_module.mainsource^)+#0);
  287. { we need at least the following sections }
  288. createsection(sec_code,'',0,[]);
  289. createsection(sec_data,'',0,[]);
  290. createsection(sec_bss,'',0,[]);
  291. {$ifdef segment_threadvars}
  292. createsection(sec_threadvar,'',0,[]);
  293. {$endif}
  294. { create stabs sections if debugging }
  295. if (cs_debuginfo in aktmoduleswitches) then
  296. begin
  297. stabssec:=createsection(sec_stab,'',0,[]);
  298. stabstrsec:=createsection(sec_stabstr,'',0,[]);
  299. end;
  300. end;
  301. destructor telf32objectdata.destroy;
  302. begin
  303. Syms.Free;
  304. symtabsect.free;
  305. strtabsect.free;
  306. shstrtabsect.free;
  307. inherited destroy;
  308. end;
  309. function telf32objectdata.sectionname(atype:tasmsectiontype;const aname:string):string;
  310. const
  311. secnames : array[tasmsectiontype] of string[12] = ('',
  312. {$ifdef userodata}
  313. '.text','.data','.rodata','.bss','.threadvar',
  314. {$else userodata}
  315. '.text','.data','.data','.bss','.threadvar',
  316. {$endif userodata}
  317. 'common',
  318. '.note',
  319. '.text', { darwin stubs }
  320. '.stab','.stabstr',
  321. '.idata$2','.idata$4','.idata$5','.idata$6','.idata$7','.edata',
  322. '.eh_frame',
  323. '.debug_frame',
  324. 'fpc.resptrs'
  325. );
  326. begin
  327. if use_smartlink_section and
  328. (aname<>'') then
  329. result:=secnames[atype]+'.'+aname
  330. else
  331. result:=secnames[atype];
  332. end;
  333. procedure telf32objectdata.writesymbol(p:tasmsymbol);
  334. begin
  335. if currsec=nil then
  336. internalerror(200403291);
  337. { already written ? }
  338. if p.indexnr<>-1 then
  339. exit;
  340. { calculate symbol index }
  341. if (p.currbind<>AB_LOCAL) then
  342. begin
  343. { insert the symbol in the local index, the indexarray
  344. will take care of the numbering }
  345. symbols.insert(p);
  346. end
  347. else
  348. p.indexnr:=-2; { local }
  349. end;
  350. procedure telf32objectdata.writereloc(data,len:aint;p:tasmsymbol;relative:TAsmRelocationType);
  351. var
  352. symaddr : longint;
  353. begin
  354. if currsec=nil then
  355. internalerror(200403292);
  356. {$ifdef userodata}
  357. if currsec.sectype in [sec_rodata,sec_bss,sec_threadvar] then
  358. internalerror(200408252);
  359. {$endif userodata}
  360. if assigned(p) then
  361. begin
  362. { real address of the symbol }
  363. symaddr:=p.address;
  364. { Local symbols can be resolved already or need a section reloc }
  365. if (p.currbind=AB_LOCAL) then
  366. begin
  367. { For a relative relocation in the same section the
  368. value can be calculated }
  369. if (p.section=currsec) and
  370. (relative=RELOC_RELATIVE) then
  371. inc(data,symaddr-len-currsec.datasize)
  372. else
  373. begin
  374. currsec.addsectionreloc(currsec.datasize,p.section,relative);
  375. inc(data,symaddr);
  376. end;
  377. end
  378. else
  379. begin
  380. writesymbol(p);
  381. currsec.addsymreloc(currsec.datasize,p,relative);
  382. if relative=RELOC_RELATIVE then
  383. dec(data,len);
  384. end;
  385. end;
  386. currsec.write(data,len);
  387. end;
  388. procedure telf32objectdata.writestab(offset:aint;ps:tasmsymbol;nidx,nother,line:longint;p:pchar);
  389. var
  390. stab : telf32stab;
  391. begin
  392. fillchar(stab,sizeof(telf32stab),0);
  393. if assigned(p) and (p[0]<>#0) then
  394. begin
  395. stab.strpos:=stabstrsec.datasize;
  396. stabstrsec.write(p^,strlen(p)+1);
  397. end;
  398. stab.ntype:=nidx;
  399. stab.ndesc:=line;
  400. stab.nother:=nother;
  401. stab.nvalue:=offset;
  402. stabssec.write(stab,sizeof(stab));
  403. if assigned(ps) then
  404. stabssec.addsymreloc(stabssec.datasize-4,ps,RELOC_ABSOLUTE);
  405. end;
  406. procedure telf32objectdata.beforealloc;
  407. begin
  408. { create stabs sections if debugging }
  409. if (cs_debuginfo in aktmoduleswitches) then
  410. begin
  411. StabsSec.Alloc(sizeof(telf32stab));
  412. StabStrSec.Alloc(length(SplitFileName(current_module.mainsource^))+2);
  413. end;
  414. end;
  415. procedure telf32objectdata.beforewrite;
  416. var
  417. s : string;
  418. begin
  419. { create stabs sections if debugging }
  420. if (cs_debuginfo in aktmoduleswitches) then
  421. begin
  422. writestab(0,nil,0,0,0,nil);
  423. { write zero pchar and name together (PM) }
  424. s:=#0+SplitFileName(current_module.mainsource^)+#0;
  425. stabstrsec.write(s[1],length(s));
  426. end;
  427. end;
  428. {****************************************************************************
  429. telf32objectoutput
  430. ****************************************************************************}
  431. function telf32objectoutput.newobjectdata(const n:string):TAsmObjectData;
  432. begin
  433. result:=telf32objectdata.create(n);
  434. end;
  435. procedure telf32objectoutput.createrelocsection(s:telf32section);
  436. var
  437. rel : telf32reloc;
  438. r : tasmrelocation;
  439. relsym,reltyp : longint;
  440. begin
  441. with elf32data do
  442. begin
  443. {$ifdef userodata}
  444. { rodata can't have relocations }
  445. if s.sectype=sec_rodata then
  446. begin
  447. if assigned(s.relocations.first) then
  448. internalerror(200408251);
  449. exit;
  450. end;
  451. {$endif userodata}
  452. { create the reloc section }
  453. s.relocsect:=telf32section.create_ext('.rel'+s.name,sec_custom,9,0,symtabsect.secshidx,s.secshidx,4,8);
  454. { add the relocations }
  455. r:=TasmRelocation(s.relocations.first);
  456. while assigned(r) do
  457. begin
  458. rel.address:=r.address;
  459. if assigned(r.symbol) then
  460. begin
  461. if (r.symbol.currbind=AB_LOCAL) then
  462. relsym:=r.symbol.section.secsymidx
  463. else
  464. begin
  465. if r.symbol.indexnr=-1 then
  466. internalerror(4321);
  467. { indexnr starts with 1, ELF starts with 0 }
  468. relsym:=r.symbol.indexnr+initsym-1;
  469. end;
  470. end
  471. else
  472. if r.section<>nil then
  473. relsym:=r.section.secsymidx
  474. else
  475. relsym:=SHN_UNDEF;
  476. case r.typ of
  477. RELOC_RELATIVE :
  478. reltyp:=R_386_PC32;
  479. RELOC_ABSOLUTE :
  480. reltyp:=R_386_32;
  481. end;
  482. rel.info:=(relsym shl 8) or reltyp;
  483. { write reloc }
  484. s.relocsect.write(rel,sizeof(rel));
  485. r:=TAsmRelocation(r.next);
  486. end;
  487. end;
  488. end;
  489. procedure telf32objectoutput.section_write_symbol(p:tnamedindexitem;arg:pointer);
  490. var
  491. elfsym : telf32symbol;
  492. begin
  493. fillchar(elfsym,sizeof(elfsym),0);
  494. elfsym.st_name:=telf32section(p).shstridx;
  495. elfsym.st_info:=STT_SECTION;
  496. elfsym.st_shndx:=telf32section(p).secshidx;
  497. elf32data.symtabsect.write(elfsym,sizeof(elfsym));
  498. { increase locals count }
  499. inc(plongint(arg)^);
  500. end;
  501. procedure telf32objectoutput.createsymtab;
  502. var
  503. elfsym : telf32symbol;
  504. locals : longint;
  505. sym : tasmsymbol;
  506. begin
  507. with elf32data do
  508. begin
  509. locals:=2;
  510. { empty entry }
  511. fillchar(elfsym,sizeof(elfsym),0);
  512. symtabsect.write(elfsym,sizeof(elfsym));
  513. { filename entry }
  514. elfsym.st_name:=1;
  515. elfsym.st_info:=STT_FILE;
  516. elfsym.st_shndx:=SHN_ABS;
  517. symtabsect.write(elfsym,sizeof(elfsym));
  518. { section }
  519. sects.foreach(@section_write_symbol,@locals);
  520. { symbols }
  521. sym:=Tasmsymbol(symbols.First);
  522. while assigned(sym) do
  523. begin
  524. fillchar(elfsym,sizeof(elfsym),0);
  525. { symbolname, write the #0 separate to overcome 255+1 char not possible }
  526. elfsym.st_name:=strtabsect.datasize;
  527. strtabsect.writestr(sym.name);
  528. strtabsect.writestr(#0);
  529. case sym.currbind of
  530. AB_LOCAL,
  531. AB_GLOBAL :
  532. elfsym.st_value:=sym.address;
  533. AB_COMMON :
  534. elfsym.st_value:=$10;
  535. end;
  536. elfsym.st_size:=sym.size;
  537. case sym.currbind of
  538. AB_LOCAL :
  539. begin
  540. elfsym.st_info:=STB_LOCAL shl 4;
  541. inc(locals);
  542. end;
  543. AB_COMMON,
  544. AB_EXTERNAL,
  545. AB_GLOBAL :
  546. elfsym.st_info:=STB_GLOBAL shl 4;
  547. end;
  548. if (sym.currbind<>AB_EXTERNAL) and
  549. not(assigned(sym.section) and
  550. (sym.section.sectype=sec_bss)) then
  551. begin
  552. case sym.typ of
  553. AT_FUNCTION :
  554. elfsym.st_info:=elfsym.st_info or STT_FUNC;
  555. AT_DATA :
  556. elfsym.st_info:=elfsym.st_info or STT_OBJECT;
  557. end;
  558. end;
  559. if sym.currbind=AB_COMMON then
  560. elfsym.st_shndx:=SHN_COMMON
  561. else
  562. if assigned(sym.section) then
  563. elfsym.st_shndx:=telf32section(sym.section).secshidx
  564. else
  565. elfsym.st_shndx:=SHN_UNDEF;
  566. symtabsect.write(elfsym,sizeof(elfsym));
  567. sym:=tasmsymbol(sym.indexnext);
  568. end;
  569. { update the .symtab section header }
  570. symtabsect.shlink:=strtabsect.secshidx;
  571. symtabsect.shinfo:=locals;
  572. end;
  573. end;
  574. procedure telf32objectoutput.section_write_sh_string(p:tnamedindexitem;arg:pointer);
  575. begin
  576. telf32section(p).shstridx:=elf32data.shstrtabsect.writestr(tasmsection(p).name+#0);
  577. if assigned(telf32section(p).relocsect) then
  578. telf32section(p).relocsect.shstridx:=elf32data.shstrtabsect.writestr(telf32section(p).relocsect.name+#0);
  579. end;
  580. procedure telf32objectoutput.createshstrtab;
  581. begin
  582. with elf32data do
  583. begin
  584. with shstrtabsect do
  585. begin
  586. writestr(#0);
  587. symtabsect.shstridx:=writestr('.symtab'#0);
  588. strtabsect.shstridx:=writestr('.strtab'#0);
  589. shstrtabsect.shstridx:=writestr('.shstrtab'#0);
  590. sects.foreach(@section_write_sh_string,nil);
  591. end;
  592. end;
  593. end;
  594. procedure telf32objectoutput.writesectionheader(s:telf32section);
  595. var
  596. sechdr : telf32sechdr;
  597. begin
  598. fillchar(sechdr,sizeof(sechdr),0);
  599. sechdr.sh_name:=s.shstridx;
  600. sechdr.sh_type:=s.shtype;
  601. sechdr.sh_flags:=s.shflags;
  602. sechdr.sh_offset:=s.datapos;
  603. sechdr.sh_size:=s.datasize;
  604. sechdr.sh_link:=s.shlink;
  605. sechdr.sh_info:=s.shinfo;
  606. sechdr.sh_addralign:=s.addralign;
  607. sechdr.sh_entsize:=s.entsize;
  608. writer.write(sechdr,sizeof(sechdr));
  609. end;
  610. procedure telf32objectoutput.writesectiondata(s:telf32section);
  611. var
  612. hp : pdynamicblock;
  613. begin
  614. FWriter.writezeros(s.dataalignbytes);
  615. s.alignsection;
  616. hp:=s.data.firstblock;
  617. while assigned(hp) do
  618. begin
  619. FWriter.write(hp^.data,hp^.used);
  620. hp:=hp^.next;
  621. end;
  622. end;
  623. procedure telf32objectoutput.section_number_symbol(p:tnamedindexitem;arg:pointer);
  624. begin
  625. tasmsection(p).secsymidx:=plongint(arg)^;
  626. inc(plongint(arg)^);
  627. end;
  628. procedure telf32objectoutput.section_count_sects(p:tnamedindexitem;arg:pointer);
  629. begin
  630. telf32section(p).secshidx:=plongint(arg)^;
  631. inc(plongint(arg)^);
  632. if telf32section(p).relocations.count>0 then
  633. inc(plongint(arg)^);
  634. end;
  635. procedure telf32objectoutput.section_create_relocsec(p:tnamedindexitem;arg:pointer);
  636. begin
  637. if (telf32section(p).relocations.count>0) then
  638. createrelocsection(telf32section(p));
  639. end;
  640. procedure telf32objectoutput.section_set_datapos(p:tnamedindexitem;arg:pointer);
  641. begin
  642. if (aso_alloconly in tasmsection(p).secoptions) then
  643. tasmsection(p).datapos:=paint(arg)^
  644. else
  645. tasmsection(p).setdatapos(paint(arg)^);
  646. end;
  647. procedure telf32objectoutput.section_relocsec_set_datapos(p:tnamedindexitem;arg:pointer);
  648. begin
  649. if assigned(telf32section(p).relocsect) then
  650. telf32section(p).relocsect.setdatapos(paint(arg)^);
  651. end;
  652. procedure telf32objectoutput.section_write_data(p:tnamedindexitem;arg:pointer);
  653. begin
  654. if (aso_alloconly in tasmsection(p).secoptions) then
  655. exit;
  656. if tasmsection(p).data=nil then
  657. internalerror(200403073);
  658. writesectiondata(telf32section(p));
  659. end;
  660. procedure telf32objectoutput.section_write_sechdr(p:tnamedindexitem;arg:pointer);
  661. begin
  662. writesectionheader(telf32section(p));
  663. if assigned(telf32section(p).relocsect) then
  664. writesectionheader(telf32section(p).relocsect);
  665. end;
  666. procedure telf32objectoutput.section_write_relocsec(p:tnamedindexitem;arg:pointer);
  667. begin
  668. if assigned(telf32section(p).relocsect) then
  669. writesectiondata(telf32section(p).relocsect);
  670. end;
  671. function telf32objectoutput.writedata(data:TAsmObjectData):boolean;
  672. var
  673. header : telf32header;
  674. datapos : aint;
  675. shoffset,
  676. nsects : longint;
  677. hstab : telf32stab;
  678. empty : array[0..63] of byte;
  679. begin
  680. result:=false;
  681. elf32data:=telf32objectdata(data);
  682. with elf32data do
  683. begin
  684. { calc amount of sections we have }
  685. initsym:=2;
  686. nsects:=1;
  687. fillchar(empty,sizeof(empty),0);
  688. { each section requires a symbol for relocation }
  689. sects.foreach(@section_number_symbol,@initsym);
  690. { also create the index in the section header table }
  691. sects.foreach(@section_count_sects,@nsects);
  692. { add default sections follows }
  693. shstrtabsect.secshidx:=nsects;
  694. inc(nsects);
  695. symtabsect.secshidx:=nsects;
  696. inc(nsects);
  697. strtabsect.secshidx:=nsects;
  698. inc(nsects);
  699. { For the stab section we need an HdrSym which can now be
  700. calculated more easily }
  701. if assigned(stabssec) then
  702. begin
  703. hstab.strpos:=1;
  704. hstab.ntype:=0;
  705. hstab.nother:=0;
  706. hstab.ndesc:=(stabssec.datasize div sizeof(telf32stab))-1{+1 according to gas output PM};
  707. hstab.nvalue:=stabstrsec.datasize;
  708. stabssec.Data.seek(0);
  709. stabssec.Data.write(hstab,sizeof(hstab));
  710. end;
  711. { Create the relocation sections }
  712. sects.foreach(@section_create_relocsec,nil);
  713. { create .symtab and .strtab }
  714. createsymtab;
  715. { create .shstrtab }
  716. createshstrtab;
  717. { Calculate the filepositions }
  718. datapos:=$40; { elfheader + alignment }
  719. { sections first }
  720. sects.foreach(@section_set_datapos,@datapos);
  721. { shstrtab }
  722. shstrtabsect.setdatapos(datapos);
  723. { section headers }
  724. shoffset:=datapos;
  725. inc(datapos,nsects*sizeof(telf32sechdr));
  726. { symtab }
  727. symtabsect.setdatapos(datapos);
  728. { strtab }
  729. strtabsect.setdatapos(datapos);
  730. { .rel sections }
  731. sects.foreach(@section_relocsec_set_datapos,@datapos);
  732. { Write ELF Header }
  733. fillchar(header,sizeof(header),0);
  734. header.magic0123:=$464c457f; { = #127'ELF' }
  735. header.file_class:=1;
  736. header.data_encoding:=1;
  737. header.file_version:=1;
  738. header.e_type:=1;
  739. header.e_machine:=3;
  740. header.e_version:=1;
  741. header.e_shoff:=shoffset;
  742. header.e_shstrndx:=shstrtabsect.secshidx;
  743. header.e_shnum:=nsects;
  744. header.e_ehsize:=sizeof(telf32header);
  745. header.e_shentsize:=sizeof(telf32sechdr);
  746. writer.write(header,sizeof(header));
  747. writer.write(empty,$40-sizeof(header)); { align }
  748. { Sections }
  749. sects.foreach(@section_write_data,nil);
  750. { .shstrtab }
  751. writesectiondata(shstrtabsect);
  752. { section headers, start with an empty header for sh_undef }
  753. writer.write(empty,sizeof(telf32sechdr));
  754. sects.foreach(@section_write_sechdr,nil);
  755. writesectionheader(shstrtabsect);
  756. writesectionheader(symtabsect);
  757. writesectionheader(strtabsect);
  758. { .symtab }
  759. writesectiondata(symtabsect);
  760. { .strtab }
  761. writesectiondata(strtabsect);
  762. { .rel sections }
  763. sects.foreach(@section_write_relocsec,nil);
  764. end;
  765. result:=true;
  766. end;
  767. {****************************************************************************
  768. TELFAssembler
  769. ****************************************************************************}
  770. constructor TELF32Assembler.Create(smart:boolean);
  771. begin
  772. inherited Create(smart);
  773. objectoutput:=telf32objectoutput.create(smart);
  774. end;
  775. {*****************************************************************************
  776. Initialize
  777. *****************************************************************************}
  778. const
  779. as_i386_elf32_info : tasminfo =
  780. (
  781. id : as_i386_elf32;
  782. idtxt : 'ELF';
  783. asmbin : '';
  784. asmcmd : '';
  785. supported_target : system_any; //target_i386_linux;
  786. flags : [af_outputbinary,af_smartlink_sections];
  787. labelprefix : '.L';
  788. comment : '';
  789. );
  790. initialization
  791. RegisterAssembler(as_i386_elf32_info,TElf32Assembler);
  792. end.