ogelf.pas 30 KB

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