ogelf.pas 31 KB

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