ogelf.pas 30 KB

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