ogelf.pas 29 KB

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