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