ogelf.pas 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899
  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,
  27. { target }
  28. systems,
  29. { assembler }
  30. cpubase,aasmbase,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 createsec(sec:TSection);
  46. constructor createname(const Aname:string;Atype,Aflags,Alink,Ainfo,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. procedure createsection(sec:TSection);override;
  63. procedure seTSectionsizes(var s:TAsmSectionSizes);override;
  64. procedure writereloc(data,len:longint;p:tasmsymbol;relative:TAsmRelocationType);override;
  65. procedure writesymbol(p:tasmsymbol);override;
  66. procedure writestabs(section:TSection;offset:longint;p:pchar;nidx,nother,line:longint;reloc:boolean);override;
  67. procedure writesymstabs(section:TSection;offset:longint;p:pchar;ps:tasmsymbol;
  68. nidx,nother,line:longint;reloc:boolean);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. protected
  79. function writedata(data:TAsmObjectData):boolean;override;
  80. public
  81. function newobjectdata(const n:string):TAsmObjectData;override;
  82. end;
  83. telf32assembler = class(tinternalassembler)
  84. constructor create(smart:boolean);override;
  85. end;
  86. implementation
  87. uses
  88. {$ifdef delphi}
  89. sysutils,
  90. {$else}
  91. strings,
  92. {$endif}
  93. verbose,
  94. globtype,cutils,globals,fmodule;
  95. const
  96. symbolresize = 200*18;
  97. const
  98. R_386_32 = 1; { ordinary absolute relocation }
  99. R_386_PC32 = 2; { PC-relative relocation }
  100. R_386_GOT32 = 3; { an offset into GOT }
  101. R_386_PLT32 = 4; { a PC-relative offset into PLT }
  102. R_386_GOTOFF = 9; { an offset from GOT base }
  103. R_386_GOTPC = 10; { a PC-relative offset _to_ GOT }
  104. SHN_UNDEF = 0;
  105. SHN_ABS = $fff1;
  106. SHN_COMMON = $fff2;
  107. SHT_NULL = 0;
  108. SHT_PROGBITS = 1;
  109. SHT_SYMTAB = 2;
  110. SHT_STRTAB = 3;
  111. SHT_RELA = 4;
  112. SHT_HASH = 5;
  113. SHT_DYNAMIC = 6;
  114. SHT_NOTE = 7;
  115. SHT_NOBITS = 8;
  116. SHT_REL = 9;
  117. SHT_SHLIB = 10;
  118. SHT_DYNSYM = 11;
  119. SHF_WRITE = 1;
  120. SHF_ALLOC = 2;
  121. SHF_EXECINSTR = 4;
  122. STB_LOCAL = 0;
  123. STB_GLOBAL = 1;
  124. STB_WEAK = 2;
  125. STT_NOTYPE = 0;
  126. STT_OBJECT = 1;
  127. STT_FUNC = 2;
  128. STT_SECTION = 3;
  129. STT_FILE = 4;
  130. type
  131. { Structures which are written directly to the output file }
  132. telf32header=packed record
  133. magic0123 : longint;
  134. file_class : byte;
  135. data_encoding : byte;
  136. file_version : byte;
  137. padding : array[$07..$0f] of byte;
  138. e_type : word;
  139. e_machine : word;
  140. e_version : longint;
  141. e_entry : longint; { entrypoint }
  142. e_phoff : longint; { program header offset }
  143. e_shoff : longint; { sections header offset }
  144. e_flags : longint;
  145. e_ehsize : word; { elf header size in bytes }
  146. e_phentsize : word; { size of an entry in the program header array }
  147. e_phnum : word; { 0..e_phnum-1 of entrys }
  148. e_shentsize : word; { size of an entry in sections header array }
  149. e_shnum : word; { 0..e_shnum-1 of entrys }
  150. e_shstrndx : word; { index of string section header }
  151. end;
  152. telf32sechdr=packed record
  153. sh_name : longint;
  154. sh_type : longint;
  155. sh_flags : longint;
  156. sh_addr : longint;
  157. sh_offset : longint;
  158. sh_size : longint;
  159. sh_link : longint;
  160. sh_info : longint;
  161. sh_addralign : longint;
  162. sh_entsize : longint;
  163. end;
  164. telf32reloc=packed record
  165. address : longint;
  166. info : longint; { bit 0-7: type, 8-31: symbol }
  167. end;
  168. telf32symbol=packed record
  169. st_name : longint;
  170. st_value : longint;
  171. st_size : longint;
  172. st_info : byte; { bit 0-3: type, 4-7: bind }
  173. st_other : byte;
  174. st_shndx : word;
  175. end;
  176. telf32stab=packed record
  177. strpos : longint;
  178. ntype : byte;
  179. nother : byte;
  180. ndesc : word;
  181. nvalue : longint;
  182. end;
  183. {****************************************************************************
  184. TSection
  185. ****************************************************************************}
  186. constructor telf32section.createsec(sec:TSection);
  187. var
  188. Aflags,Atype,Aalign,Aentsize : longint;
  189. begin
  190. Aflags:=0;
  191. Atype:=0;
  192. Aalign:=0;
  193. Aentsize:=0;
  194. case sec of
  195. sec_code :
  196. begin
  197. Aflags:=SHF_ALLOC or SHF_EXECINSTR;
  198. AType:=SHT_PROGBITS;
  199. AAlign:=16;
  200. end;
  201. sec_data :
  202. begin
  203. Aflags:=SHF_ALLOC or SHF_WRITE;
  204. AType:=SHT_PROGBITS;
  205. AAlign:=4;
  206. end;
  207. sec_bss :
  208. begin
  209. Aflags:=SHF_ALLOC or SHF_WRITE;
  210. AType:=SHT_NOBITS;
  211. AAlign:=4;
  212. end;
  213. sec_stab :
  214. begin
  215. AType:=SHT_PROGBITS;
  216. AAlign:=4;
  217. Aentsize:=sizeof(telf32stab);
  218. end;
  219. sec_stabstr :
  220. begin
  221. AType:=SHT_STRTAB;
  222. AAlign:=1;
  223. end;
  224. end;
  225. createname(target_asm.secnames[sec],Atype,Aflags,0,0,Aalign,Aentsize);
  226. end;
  227. constructor telf32section.createname(const Aname:string;Atype,Aflags,Alink,Ainfo,Aalign,Aentsize:longint);
  228. begin
  229. inherited create(Aname,Aalign,(AType=SHT_NOBITS));
  230. secshidx:=0;
  231. shstridx:=0;
  232. shtype:=AType;
  233. shflags:=AFlags;
  234. shlink:=Alink;
  235. shinfo:=Ainfo;
  236. entsize:=Aentsize;
  237. relocsect:=nil;
  238. end;
  239. destructor telf32section.destroy;
  240. begin
  241. if assigned(relocsect) then
  242. relocsect.free;
  243. inherited destroy;
  244. end;
  245. {****************************************************************************
  246. telf32objectdata
  247. ****************************************************************************}
  248. constructor telf32objectdata.create(const n:string);
  249. var
  250. s : string;
  251. begin
  252. inherited create(n);
  253. { reset }
  254. Syms:=TDynamicArray.Create(symbolresize);
  255. { default sections }
  256. symtabsect:=telf32section.createname('.symtab',2,0,0,0,4,16);
  257. strtabsect:=telf32section.createname('.strtab',3,0,0,0,1,0);
  258. shstrtabsect:=telf32section.createname('.shstrtab',3,0,0,0,1,0);
  259. { insert the empty and filename as first in strtab }
  260. strtabsect.writestr(#0);
  261. strtabsect.writestr(SplitFileName(current_module.mainsource^)+#0);
  262. { we need at least the following sections }
  263. createsection(sec_code);
  264. createsection(sec_data);
  265. createsection(sec_bss);
  266. { create stabs sections if debugging }
  267. if (cs_debuginfo in aktmoduleswitches) then
  268. begin
  269. createsection(sec_stab);
  270. createsection(sec_stabstr);
  271. writestabs(sec_none,0,nil,0,0,0,false);
  272. { write zero pchar and name together (PM) }
  273. s:=#0+SplitFileName(current_module.mainsource^)+#0;
  274. sects[sec_stabstr].write(s[1],length(s));
  275. end;
  276. end;
  277. destructor telf32objectdata.destroy;
  278. begin
  279. Syms.Free;
  280. symtabsect.free;
  281. strtabsect.free;
  282. shstrtabsect.free;
  283. inherited destroy;
  284. end;
  285. procedure telf32objectdata.createsection(sec:TSection);
  286. begin
  287. sects[sec]:=telf32Section.createsec(Sec);
  288. end;
  289. procedure telf32objectdata.writesymbol(p:tasmsymbol);
  290. begin
  291. { already written ? }
  292. if p.indexnr<>-1 then
  293. exit;
  294. { be sure that the section will exists }
  295. if (p.section<>sec_none) and not(assigned(sects[p.section])) then
  296. createsection(p.section);
  297. { calculate symbol index }
  298. if (p.currbind<>AB_LOCAL) then
  299. begin
  300. { insert the symbol in the local index, the indexarray
  301. will take care of the numbering }
  302. symbols.insert(p);
  303. end
  304. else
  305. p.indexnr:=-2; { local }
  306. end;
  307. procedure telf32objectdata.writereloc(data,len:longint;p:tasmsymbol;relative:TAsmRelocationType);
  308. var
  309. symaddr : longint;
  310. begin
  311. if not assigned(sects[currsec]) then
  312. createsection(currsec);
  313. if assigned(p) then
  314. begin
  315. { real address of the symbol }
  316. symaddr:=p.address;
  317. { no symbol relocation need inside a section }
  318. if p.section=currsec then
  319. begin
  320. case relative of
  321. RELOC_ABSOLUTE :
  322. begin
  323. sects[currsec].addsectionreloc(sects[currsec].datasize,currsec,RELOC_ABSOLUTE);
  324. inc(data,symaddr);
  325. end;
  326. RELOC_RELATIVE :
  327. begin
  328. inc(data,symaddr-len-sects[currsec].datasize);
  329. end;
  330. RELOC_RVA :
  331. internalerror(3219583);
  332. end;
  333. end
  334. else
  335. begin
  336. writesymbol(p);
  337. if (p.section<>sec_none) and (relative<>RELOC_RELATIVE) then
  338. begin
  339. sects[currsec].addsectionreloc(sects[currsec].datasize,p.section,relative);
  340. inc(data,symaddr);
  341. end
  342. else
  343. sects[currsec].addsymreloc(sects[currsec].datasize,p,relative);
  344. if relative=RELOC_RELATIVE then
  345. begin
  346. if p.currbind=AB_EXTERNAL then
  347. dec(data,len)
  348. else
  349. dec(data,len+sects[currsec].datasize);
  350. end;
  351. end;
  352. end;
  353. sects[currsec].write(data,len);
  354. end;
  355. procedure telf32objectdata.writestabs(section:TSection;offset:longint;p:pchar;nidx,nother,line:longint;reloc : boolean);
  356. var
  357. stab : telf32stab;
  358. begin
  359. if reloc then
  360. begin
  361. if (offset=-1) then
  362. begin
  363. if section=sec_none then
  364. offset:=0
  365. else
  366. offset:=sects[section].datasize;
  367. end;
  368. end;
  369. fillchar(stab,sizeof(telf32stab),0);
  370. if assigned(p) and (p[0]<>#0) then
  371. begin
  372. stab.strpos:=sects[sec_stabstr].datasize;
  373. sects[sec_stabstr].write(p^,strlen(p)+1);
  374. end;
  375. stab.ntype:=nidx;
  376. stab.ndesc:=line;
  377. stab.nother:=nother;
  378. stab.nvalue:=offset;
  379. sects[sec_stab].write(stab,sizeof(stab));
  380. { when the offset is not 0 then write a relocation, take also the
  381. hdrstab into account with the offset }
  382. if reloc then
  383. sects[sec_stab].addsectionreloc(sects[sec_stab].datasize-4,section,RELOC_ABSOLUTE);
  384. end;
  385. procedure telf32objectdata.writesymstabs(section:TSection;offset:longint;p:pchar;ps:tasmsymbol;
  386. nidx,nother,line:longint;reloc:boolean);
  387. var
  388. stab : telf32stab;
  389. begin
  390. fillchar(stab,sizeof(telf32stab),0);
  391. if assigned(p) and (p[0]<>#0) then
  392. begin
  393. stab.strpos:=sects[sec_stabstr].datasize;
  394. sects[sec_stabstr].write(p^,strlen(p)+1);
  395. end;
  396. stab.ntype:=nidx;
  397. stab.ndesc:=line;
  398. stab.nother:=nother;
  399. stab.nvalue:=0;
  400. sects[sec_stab].write(stab,sizeof(stab));
  401. { when the offset is not 0 then write a relocation, take also the
  402. hdrstab into account with the offset }
  403. if reloc then
  404. sects[sec_stab].addsymreloc(sects[sec_stab].datasize-4,ps,RELOC_ABSOLUTE);
  405. end;
  406. procedure telf32objectdata.seTSectionsizes(var s:TAsmSectionSizes);
  407. begin
  408. end;
  409. {****************************************************************************
  410. telf32objectoutput
  411. ****************************************************************************}
  412. function telf32objectoutput.newobjectdata(const n:string):TAsmObjectData;
  413. begin
  414. result:=telf32objectdata.create(n);
  415. end;
  416. procedure telf32objectoutput.createrelocsection(s:telf32section);
  417. var
  418. rel : telf32reloc;
  419. r : tasmrelocation;
  420. relsym,reltyp : longint;
  421. begin
  422. with elf32data do
  423. begin
  424. { create the reloc section }
  425. s.relocsect:=telf32section.createname('.rel'+s.name,9,0,symtabsect.secshidx,s.secshidx,4,8);
  426. { add the relocations }
  427. r:=TasmRelocation(s.relocations.first);
  428. while assigned(r) do
  429. begin
  430. rel.address:=r.address;
  431. if assigned(r.symbol) then
  432. begin
  433. if (r.symbol.currbind=AB_LOCAL) then
  434. relsym:=sects[r.symbol.section].secsymidx
  435. else
  436. begin
  437. if r.symbol.indexnr=-1 then
  438. internalerror(4321);
  439. { indexnr starts with 1, ELF starts with 0 }
  440. relsym:=r.symbol.indexnr+initsym-1;
  441. end;
  442. end
  443. else
  444. if r.section<>sec_none then
  445. relsym:=sects[r.section].secsymidx
  446. else
  447. relsym:=SHN_UNDEF;
  448. case r.typ of
  449. RELOC_RELATIVE :
  450. reltyp:=R_386_PC32;
  451. RELOC_ABSOLUTE :
  452. reltyp:=R_386_32;
  453. end;
  454. rel.info:=(relsym shl 8) or reltyp;
  455. { write reloc }
  456. s.relocsect.write(rel,sizeof(rel));
  457. r:=TAsmRelocation(r.next);
  458. end;
  459. end;
  460. end;
  461. procedure telf32objectoutput.createsymtab;
  462. var
  463. elfsym : telf32symbol;
  464. sec : TSection;
  465. locals,
  466. i : longint;
  467. sym : tasmsymbol;
  468. begin
  469. with elf32data do
  470. begin
  471. locals:=2;
  472. { empty entry }
  473. fillchar(elfsym,sizeof(elfsym),0);
  474. symtabsect.write(elfsym,sizeof(elfsym));
  475. { filename entry }
  476. elfsym.st_name:=1;
  477. elfsym.st_info:=STT_FILE;
  478. elfsym.st_shndx:=SHN_ABS;
  479. symtabsect.write(elfsym,sizeof(elfsym));
  480. { section }
  481. for sec:=low(TSection) to high(TSection) do
  482. if assigned(sects[sec]) then
  483. begin
  484. fillchar(elfsym,sizeof(elfsym),0);
  485. elfsym.st_name:=telf32section(sects[sec]).shstridx;
  486. elfsym.st_info:=STT_SECTION;
  487. elfsym.st_shndx:=telf32section(sects[sec]).secshidx;
  488. symtabsect.write(elfsym,sizeof(elfsym));
  489. inc(locals);
  490. end;
  491. { symbols }
  492. sym:=Tasmsymbol(symbols.First);
  493. while assigned(sym) do
  494. begin
  495. fillchar(elfsym,sizeof(elfsym),0);
  496. { symbolname, write the #0 separate to overcome 255+1 char not possible }
  497. elfsym.st_name:=strtabsect.datasize;
  498. strtabsect.writestr(sym.name);
  499. strtabsect.writestr(#0);
  500. case sym.currbind of
  501. AB_LOCAL,
  502. AB_GLOBAL :
  503. elfsym.st_value:=sym.address;
  504. AB_COMMON :
  505. elfsym.st_value:=$10;
  506. end;
  507. elfsym.st_size:=sym.size;
  508. case sym.currbind of
  509. AB_LOCAL :
  510. begin
  511. elfsym.st_info:=STB_LOCAL shl 4;
  512. inc(locals);
  513. end;
  514. AB_COMMON,
  515. AB_EXTERNAL,
  516. AB_GLOBAL :
  517. elfsym.st_info:=STB_GLOBAL shl 4;
  518. end;
  519. if sym.currbind<>AB_EXTERNAL then
  520. begin
  521. case sym.typ of
  522. AT_FUNCTION :
  523. elfsym.st_info:=elfsym.st_info or STT_FUNC;
  524. AT_DATA :
  525. elfsym.st_info:=elfsym.st_info or STT_OBJECT;
  526. end;
  527. end;
  528. if sym.currbind=AB_COMMON then
  529. elfsym.st_shndx:=SHN_COMMON
  530. else
  531. if assigned(sects[sym.section]) then
  532. elfsym.st_shndx:=telf32section(sects[sym.section]).secshidx
  533. else
  534. elfsym.st_shndx:=SHN_UNDEF;
  535. symtabsect.write(elfsym,sizeof(elfsym));
  536. sym:=tasmsymbol(sym.indexnext);
  537. end;
  538. { update the .symtab section header }
  539. symtabsect.shlink:=strtabsect.secshidx;
  540. symtabsect.shinfo:=locals;
  541. end;
  542. end;
  543. procedure telf32objectoutput.createshstrtab;
  544. var
  545. sec : TSection;
  546. begin
  547. with elf32data do
  548. begin
  549. with shstrtabsect do
  550. begin
  551. writestr(#0);
  552. symtabsect.shstridx:=writestr('.symtab'#0);
  553. strtabsect.shstridx:=writestr('.strtab'#0);
  554. shstrtabsect.shstridx:=writestr('.shstrtab'#0);
  555. for sec:=low(TSection) to high(TSection) do
  556. if assigned(sects[sec]) then
  557. begin
  558. telf32section(sects[sec]).shstridx:=writestr(sects[sec].name+#0);
  559. if assigned(telf32section(sects[sec]).relocsect) then
  560. telf32section(sects[sec]).relocsect.shstridx:=writestr(telf32section(sects[sec]).relocsect.name+#0);
  561. end;
  562. end;
  563. end;
  564. end;
  565. procedure telf32objectoutput.writesectionheader(s:telf32section);
  566. var
  567. sechdr : telf32sechdr;
  568. begin
  569. fillchar(sechdr,sizeof(sechdr),0);
  570. sechdr.sh_name:=s.shstridx;
  571. sechdr.sh_type:=s.shtype;
  572. sechdr.sh_flags:=s.shflags;
  573. sechdr.sh_offset:=s.datapos;
  574. sechdr.sh_size:=s.datasize;
  575. sechdr.sh_link:=s.shlink;
  576. sechdr.sh_info:=s.shinfo;
  577. sechdr.sh_addralign:=s.addralign;
  578. sechdr.sh_entsize:=s.entsize;
  579. writer.write(sechdr,sizeof(sechdr));
  580. end;
  581. function telf32objectoutput.writedata(data:TAsmObjectData):boolean;
  582. var
  583. header : telf32header;
  584. datapos,
  585. shoffset,
  586. nsects : longint;
  587. hstab : telf32stab;
  588. sec : TSection;
  589. empty : array[0..63] of byte;
  590. hp : pdynamicblock;
  591. begin
  592. result:=false;
  593. elf32data:=telf32objectdata(data);
  594. with elf32data do
  595. begin
  596. { calc amount of sections we have }
  597. fillchar(empty,sizeof(empty),0);
  598. nsects:=1;
  599. initsym:=2;
  600. for sec:=low(TSection) to high(TSection) do
  601. if assigned(sects[sec]) then
  602. begin
  603. { each section requires a symbol for relocation }
  604. sects[sec].secsymidx:=initsym;
  605. inc(initsym);
  606. { also create the index in the section header table }
  607. telf32section(sects[sec]).secshidx:=nsects;
  608. inc(nsects);
  609. if sects[sec].relocations.count>0 then
  610. inc(nsects);
  611. end;
  612. { add default sections follows }
  613. shstrtabsect.secshidx:=nsects;
  614. inc(nsects);
  615. symtabsect.secshidx:=nsects;
  616. inc(nsects);
  617. strtabsect.secshidx:=nsects;
  618. inc(nsects);
  619. { For the stab section we need an HdrSym which can now be
  620. calculated more easily }
  621. if assigned(sects[sec_stab]) then
  622. begin
  623. hstab.strpos:=1;
  624. hstab.ntype:=0;
  625. hstab.nother:=0;
  626. hstab.ndesc:=(sects[sec_stab].datasize div sizeof(telf32stab))-1{+1 according to gas output PM};
  627. hstab.nvalue:=sects[sec_stabstr].datasize;
  628. sects[sec_stab].Data.seek(0);
  629. sects[sec_stab].Data.write(hstab,sizeof(hstab));
  630. end;
  631. { Create the relocation sections }
  632. for sec:=low(TSection) to high(TSection) do
  633. if assigned(sects[sec]) and
  634. (sects[sec].relocations.count>0) then
  635. createrelocsection(telf32section(sects[sec]));
  636. { create .symtab and .strtab }
  637. createsymtab;
  638. { create .shstrtab }
  639. createshstrtab;
  640. { Calculate the filepositions }
  641. datapos:=$40; { elfheader + alignment }
  642. { sections first }
  643. for sec:=low(TSection) to high(TSection) do
  644. if assigned(sects[sec]) then
  645. begin
  646. sects[sec].datapos:=datapos;
  647. if assigned(sects[sec].data) then
  648. inc(datapos,sects[sec].aligneddatasize);
  649. end;
  650. { shstrtab }
  651. shstrtabsect.datapos:=datapos;
  652. inc(datapos,shstrtabsect.aligneddatasize);
  653. { section headers }
  654. shoffset:=datapos;
  655. inc(datapos,nsects*sizeof(telf32sechdr));
  656. { symtab }
  657. symtabsect.datapos:=datapos;
  658. inc(datapos,symtabsect.aligneddatasize);
  659. { strtab }
  660. strtabsect.datapos:=datapos;
  661. inc(datapos,align(strtabsect.datasize,4));
  662. { .rel sections }
  663. for sec:=low(TSection) to high(TSection) do
  664. if assigned(sects[sec]) and
  665. assigned(telf32section(sects[sec]).relocsect) then
  666. begin
  667. telf32section(sects[sec]).relocsect.datapos:=datapos;
  668. inc(datapos,telf32section(sects[sec]).relocsect.aligneddatasize);
  669. end;
  670. { Write ELF Header }
  671. fillchar(header,sizeof(header),0);
  672. header.magic0123:=$464c457f; { = #127'ELF' }
  673. header.file_class:=1;
  674. header.data_encoding:=1;
  675. header.file_version:=1;
  676. header.e_type:=1;
  677. header.e_machine:=3;
  678. header.e_version:=1;
  679. header.e_shoff:=shoffset;
  680. header.e_shstrndx:=shstrtabsect.secshidx;
  681. header.e_shnum:=nsects;
  682. header.e_ehsize:=sizeof(telf32header);
  683. header.e_shentsize:=sizeof(telf32sechdr);
  684. writer.write(header,sizeof(header));
  685. writer.write(empty,$40-sizeof(header)); { align }
  686. { Sections }
  687. for sec:=low(TSection) to high(TSection) do
  688. if assigned(sects[sec]) and
  689. assigned(sects[sec].data) then
  690. begin
  691. sects[sec].alignsection;
  692. hp:=sects[sec].Data.firstblock;
  693. while assigned(hp) do
  694. begin
  695. writer.write(hp^.data,hp^.used);
  696. hp:=hp^.next;
  697. end;
  698. end;
  699. { .shstrtab }
  700. shstrtabsect.alignsection;
  701. hp:=shstrtabsect.Data.firstblock;
  702. while assigned(hp) do
  703. begin
  704. writer.write(hp^.data,hp^.used);
  705. hp:=hp^.next;
  706. end;
  707. { section headers, start with an empty header for sh_undef }
  708. writer.write(empty,sizeof(telf32sechdr));
  709. for sec:=low(TSection) to high(TSection) do
  710. if assigned(sects[sec]) then
  711. begin
  712. writesectionheader(telf32section(sects[sec]));
  713. if assigned(telf32section(sects[sec]).relocsect) then
  714. writesectionheader(telf32section(sects[sec]).relocsect);
  715. end;
  716. writesectionheader(shstrtabsect);
  717. writesectionheader(symtabsect);
  718. writesectionheader(strtabsect);
  719. { .symtab }
  720. symtabsect.alignsection;
  721. hp:=symtabsect.Data.firstblock;
  722. while assigned(hp) do
  723. begin
  724. writer.write(hp^.data,hp^.used);
  725. hp:=hp^.next;
  726. end;
  727. { .strtab }
  728. strtabsect.writealign(4);
  729. hp:=strtabsect.Data.firstblock;
  730. while assigned(hp) do
  731. begin
  732. writer.write(hp^.data,hp^.used);
  733. hp:=hp^.next;
  734. end;
  735. { .rel sections }
  736. for sec:=low(TSection) to high(TSection) do
  737. if assigned(sects[sec]) and
  738. assigned(telf32section(sects[sec]).relocsect) then
  739. begin
  740. telf32section(sects[sec]).relocsect.alignsection;
  741. hp:=telf32section(sects[sec]).relocsect.Data.firstblock;
  742. while assigned(hp) do
  743. begin
  744. writer.write(hp^.data,hp^.used);
  745. hp:=hp^.next;
  746. end;
  747. end;
  748. end;
  749. result:=true;
  750. end;
  751. {****************************************************************************
  752. TELFAssembler
  753. ****************************************************************************}
  754. constructor TELF32Assembler.Create(smart:boolean);
  755. begin
  756. inherited Create(smart);
  757. objectoutput:=telf32objectoutput.create(smart);
  758. end;
  759. {*****************************************************************************
  760. Initialize
  761. *****************************************************************************}
  762. const
  763. as_i386_elf32_info : tasminfo =
  764. (
  765. id : as_i386_elf32;
  766. idtxt : 'ELF';
  767. asmbin : '';
  768. asmcmd : '';
  769. supported_target : system_any; //target_i386_linux;
  770. outputbinary : true;
  771. allowdirect : false;
  772. needar : false;
  773. labelprefix_only_inside_procedure: false;
  774. labelprefix : '.L';
  775. comment : '';
  776. secnames : ('',
  777. '.text','.data','.bss',
  778. '.idata$2','.idata$4','.idata$5','.idata$6','.idata$7','.edata',
  779. '.stab','.stabstr','')
  780. );
  781. initialization
  782. RegisterAssembler(as_i386_elf32_info,TElf32Assembler);
  783. end.
  784. {
  785. $Log$
  786. Revision 1.18 2002-08-12 15:08:39 carl
  787. + stab register indexes for powerpc (moved from gdb to cpubase)
  788. + tprocessor enumeration moved to cpuinfo
  789. + linker in target_info is now a class
  790. * many many updates for m68k (will soon start to compile)
  791. - removed some ifdef or correct them for correct cpu
  792. Revision 1.17 2002/07/26 21:15:39 florian
  793. * rewrote the system handling
  794. Revision 1.16 2002/07/01 18:46:24 peter
  795. * internal linker
  796. * reorganized aasm layer
  797. Revision 1.15 2002/05/18 13:34:10 peter
  798. * readded missing revisions
  799. Revision 1.14 2002/05/16 19:46:39 carl
  800. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  801. + try to fix temp allocation (still in ifdef)
  802. + generic constructor calls
  803. + start of tassembler / tmodulebase class cleanup
  804. Revision 1.12 2002/05/12 16:53:08 peter
  805. * moved entry and exitcode to ncgutil and cgobj
  806. * foreach gets extra argument for passing local data to the
  807. iterator function
  808. * -CR checks also class typecasts at runtime by changing them
  809. into as
  810. * fixed compiler to cycle with the -CR option
  811. * fixed stabs with elf writer, finally the global variables can
  812. be watched
  813. * removed a lot of routines from cga unit and replaced them by
  814. calls to cgobj
  815. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  816. u32bit then the other is typecasted also to u32bit without giving
  817. a rangecheck warning/error.
  818. * fixed pascal calling method with reversing also the high tree in
  819. the parast, detected by tcalcst3 test
  820. Revision 1.11 2002/04/04 19:05:58 peter
  821. * removed unused units
  822. * use tlocation.size in cg.a_*loc*() routines
  823. }