ogelf.pas 30 KB

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