ogelf.pas 29 KB

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