ogelf.pas 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901
  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 : longint;
  466. sym : tasmsymbol;
  467. begin
  468. with elf32data do
  469. begin
  470. locals:=2;
  471. { empty entry }
  472. fillchar(elfsym,sizeof(elfsym),0);
  473. symtabsect.write(elfsym,sizeof(elfsym));
  474. { filename entry }
  475. elfsym.st_name:=1;
  476. elfsym.st_info:=STT_FILE;
  477. elfsym.st_shndx:=SHN_ABS;
  478. symtabsect.write(elfsym,sizeof(elfsym));
  479. { section }
  480. for sec:=low(TSection) to high(TSection) do
  481. if assigned(sects[sec]) then
  482. begin
  483. fillchar(elfsym,sizeof(elfsym),0);
  484. elfsym.st_name:=telf32section(sects[sec]).shstridx;
  485. elfsym.st_info:=STT_SECTION;
  486. elfsym.st_shndx:=telf32section(sects[sec]).secshidx;
  487. symtabsect.write(elfsym,sizeof(elfsym));
  488. inc(locals);
  489. end;
  490. { symbols }
  491. sym:=Tasmsymbol(symbols.First);
  492. while assigned(sym) do
  493. begin
  494. fillchar(elfsym,sizeof(elfsym),0);
  495. { symbolname, write the #0 separate to overcome 255+1 char not possible }
  496. elfsym.st_name:=strtabsect.datasize;
  497. strtabsect.writestr(sym.name);
  498. strtabsect.writestr(#0);
  499. case sym.currbind of
  500. AB_LOCAL,
  501. AB_GLOBAL :
  502. elfsym.st_value:=sym.address;
  503. AB_COMMON :
  504. elfsym.st_value:=$10;
  505. end;
  506. elfsym.st_size:=sym.size;
  507. case sym.currbind of
  508. AB_LOCAL :
  509. begin
  510. elfsym.st_info:=STB_LOCAL shl 4;
  511. inc(locals);
  512. end;
  513. AB_COMMON,
  514. AB_EXTERNAL,
  515. AB_GLOBAL :
  516. elfsym.st_info:=STB_GLOBAL shl 4;
  517. end;
  518. if sym.currbind<>AB_EXTERNAL then
  519. begin
  520. case sym.typ of
  521. AT_FUNCTION :
  522. elfsym.st_info:=elfsym.st_info or STT_FUNC;
  523. AT_DATA :
  524. elfsym.st_info:=elfsym.st_info or STT_OBJECT;
  525. end;
  526. end;
  527. if sym.currbind=AB_COMMON then
  528. elfsym.st_shndx:=SHN_COMMON
  529. else
  530. if assigned(sects[sym.section]) then
  531. elfsym.st_shndx:=telf32section(sects[sym.section]).secshidx
  532. else
  533. elfsym.st_shndx:=SHN_UNDEF;
  534. symtabsect.write(elfsym,sizeof(elfsym));
  535. sym:=tasmsymbol(sym.indexnext);
  536. end;
  537. { update the .symtab section header }
  538. symtabsect.shlink:=strtabsect.secshidx;
  539. symtabsect.shinfo:=locals;
  540. end;
  541. end;
  542. procedure telf32objectoutput.createshstrtab;
  543. var
  544. sec : TSection;
  545. begin
  546. with elf32data do
  547. begin
  548. with shstrtabsect do
  549. begin
  550. writestr(#0);
  551. symtabsect.shstridx:=writestr('.symtab'#0);
  552. strtabsect.shstridx:=writestr('.strtab'#0);
  553. shstrtabsect.shstridx:=writestr('.shstrtab'#0);
  554. for sec:=low(TSection) to high(TSection) do
  555. if assigned(sects[sec]) then
  556. begin
  557. telf32section(sects[sec]).shstridx:=writestr(sects[sec].name+#0);
  558. if assigned(telf32section(sects[sec]).relocsect) then
  559. telf32section(sects[sec]).relocsect.shstridx:=writestr(telf32section(sects[sec]).relocsect.name+#0);
  560. end;
  561. end;
  562. end;
  563. end;
  564. procedure telf32objectoutput.writesectionheader(s:telf32section);
  565. var
  566. sechdr : telf32sechdr;
  567. begin
  568. fillchar(sechdr,sizeof(sechdr),0);
  569. sechdr.sh_name:=s.shstridx;
  570. sechdr.sh_type:=s.shtype;
  571. sechdr.sh_flags:=s.shflags;
  572. sechdr.sh_offset:=s.datapos;
  573. sechdr.sh_size:=s.datasize;
  574. sechdr.sh_link:=s.shlink;
  575. sechdr.sh_info:=s.shinfo;
  576. sechdr.sh_addralign:=s.addralign;
  577. sechdr.sh_entsize:=s.entsize;
  578. writer.write(sechdr,sizeof(sechdr));
  579. end;
  580. function telf32objectoutput.writedata(data:TAsmObjectData):boolean;
  581. var
  582. header : telf32header;
  583. datapos,
  584. shoffset,
  585. nsects : longint;
  586. hstab : telf32stab;
  587. sec : TSection;
  588. empty : array[0..63] of byte;
  589. hp : pdynamicblock;
  590. begin
  591. result:=false;
  592. elf32data:=telf32objectdata(data);
  593. with elf32data do
  594. begin
  595. { calc amount of sections we have }
  596. fillchar(empty,sizeof(empty),0);
  597. nsects:=1;
  598. initsym:=2;
  599. for sec:=low(TSection) to high(TSection) do
  600. if assigned(sects[sec]) then
  601. begin
  602. { each section requires a symbol for relocation }
  603. sects[sec].secsymidx:=initsym;
  604. inc(initsym);
  605. { also create the index in the section header table }
  606. telf32section(sects[sec]).secshidx:=nsects;
  607. inc(nsects);
  608. if sects[sec].relocations.count>0 then
  609. inc(nsects);
  610. end;
  611. { add default sections follows }
  612. shstrtabsect.secshidx:=nsects;
  613. inc(nsects);
  614. symtabsect.secshidx:=nsects;
  615. inc(nsects);
  616. strtabsect.secshidx:=nsects;
  617. inc(nsects);
  618. { For the stab section we need an HdrSym which can now be
  619. calculated more easily }
  620. if assigned(sects[sec_stab]) then
  621. begin
  622. hstab.strpos:=1;
  623. hstab.ntype:=0;
  624. hstab.nother:=0;
  625. hstab.ndesc:=(sects[sec_stab].datasize div sizeof(telf32stab))-1{+1 according to gas output PM};
  626. hstab.nvalue:=sects[sec_stabstr].datasize;
  627. sects[sec_stab].Data.seek(0);
  628. sects[sec_stab].Data.write(hstab,sizeof(hstab));
  629. end;
  630. { Create the relocation sections }
  631. for sec:=low(TSection) to high(TSection) do
  632. if assigned(sects[sec]) and
  633. (sects[sec].relocations.count>0) then
  634. createrelocsection(telf32section(sects[sec]));
  635. { create .symtab and .strtab }
  636. createsymtab;
  637. { create .shstrtab }
  638. createshstrtab;
  639. { Calculate the filepositions }
  640. datapos:=$40; { elfheader + alignment }
  641. { sections first }
  642. for sec:=low(TSection) to high(TSection) do
  643. if assigned(sects[sec]) then
  644. begin
  645. sects[sec].datapos:=datapos;
  646. if assigned(sects[sec].data) then
  647. inc(datapos,sects[sec].aligneddatasize);
  648. end;
  649. { shstrtab }
  650. shstrtabsect.datapos:=datapos;
  651. inc(datapos,shstrtabsect.aligneddatasize);
  652. { section headers }
  653. shoffset:=datapos;
  654. inc(datapos,nsects*sizeof(telf32sechdr));
  655. { symtab }
  656. symtabsect.datapos:=datapos;
  657. inc(datapos,symtabsect.aligneddatasize);
  658. { strtab }
  659. strtabsect.datapos:=datapos;
  660. inc(datapos,align(strtabsect.datasize,4));
  661. { .rel sections }
  662. for sec:=low(TSection) to high(TSection) do
  663. if assigned(sects[sec]) and
  664. assigned(telf32section(sects[sec]).relocsect) then
  665. begin
  666. telf32section(sects[sec]).relocsect.datapos:=datapos;
  667. inc(datapos,telf32section(sects[sec]).relocsect.aligneddatasize);
  668. end;
  669. { Write ELF Header }
  670. fillchar(header,sizeof(header),0);
  671. header.magic0123:=$464c457f; { = #127'ELF' }
  672. header.file_class:=1;
  673. header.data_encoding:=1;
  674. header.file_version:=1;
  675. header.e_type:=1;
  676. header.e_machine:=3;
  677. header.e_version:=1;
  678. header.e_shoff:=shoffset;
  679. header.e_shstrndx:=shstrtabsect.secshidx;
  680. header.e_shnum:=nsects;
  681. header.e_ehsize:=sizeof(telf32header);
  682. header.e_shentsize:=sizeof(telf32sechdr);
  683. writer.write(header,sizeof(header));
  684. writer.write(empty,$40-sizeof(header)); { align }
  685. { Sections }
  686. for sec:=low(TSection) to high(TSection) do
  687. if assigned(sects[sec]) and
  688. assigned(sects[sec].data) then
  689. begin
  690. sects[sec].alignsection;
  691. hp:=sects[sec].Data.firstblock;
  692. while assigned(hp) do
  693. begin
  694. writer.write(hp^.data,hp^.used);
  695. hp:=hp^.next;
  696. end;
  697. end;
  698. { .shstrtab }
  699. shstrtabsect.alignsection;
  700. hp:=shstrtabsect.Data.firstblock;
  701. while assigned(hp) do
  702. begin
  703. writer.write(hp^.data,hp^.used);
  704. hp:=hp^.next;
  705. end;
  706. { section headers, start with an empty header for sh_undef }
  707. writer.write(empty,sizeof(telf32sechdr));
  708. for sec:=low(TSection) to high(TSection) do
  709. if assigned(sects[sec]) then
  710. begin
  711. writesectionheader(telf32section(sects[sec]));
  712. if assigned(telf32section(sects[sec]).relocsect) then
  713. writesectionheader(telf32section(sects[sec]).relocsect);
  714. end;
  715. writesectionheader(shstrtabsect);
  716. writesectionheader(symtabsect);
  717. writesectionheader(strtabsect);
  718. { .symtab }
  719. symtabsect.alignsection;
  720. hp:=symtabsect.Data.firstblock;
  721. while assigned(hp) do
  722. begin
  723. writer.write(hp^.data,hp^.used);
  724. hp:=hp^.next;
  725. end;
  726. { .strtab }
  727. strtabsect.writealign(4);
  728. hp:=strtabsect.Data.firstblock;
  729. while assigned(hp) do
  730. begin
  731. writer.write(hp^.data,hp^.used);
  732. hp:=hp^.next;
  733. end;
  734. { .rel sections }
  735. for sec:=low(TSection) to high(TSection) do
  736. if assigned(sects[sec]) and
  737. assigned(telf32section(sects[sec]).relocsect) then
  738. begin
  739. telf32section(sects[sec]).relocsect.alignsection;
  740. hp:=telf32section(sects[sec]).relocsect.Data.firstblock;
  741. while assigned(hp) do
  742. begin
  743. writer.write(hp^.data,hp^.used);
  744. hp:=hp^.next;
  745. end;
  746. end;
  747. end;
  748. result:=true;
  749. end;
  750. {****************************************************************************
  751. TELFAssembler
  752. ****************************************************************************}
  753. constructor TELF32Assembler.Create(smart:boolean);
  754. begin
  755. inherited Create(smart);
  756. objectoutput:=telf32objectoutput.create(smart);
  757. end;
  758. {*****************************************************************************
  759. Initialize
  760. *****************************************************************************}
  761. const
  762. as_i386_elf32_info : tasminfo =
  763. (
  764. id : as_i386_elf32;
  765. idtxt : 'ELF';
  766. asmbin : '';
  767. asmcmd : '';
  768. supported_target : system_any; //target_i386_linux;
  769. outputbinary : true;
  770. allowdirect : false;
  771. needar : false;
  772. labelprefix_only_inside_procedure: false;
  773. labelprefix : '.L';
  774. comment : '';
  775. secnames : ('',
  776. '.text','.data','.bss',
  777. '.idata$2','.idata$4','.idata$5','.idata$6','.idata$7','.edata',
  778. '.stab','.stabstr','')
  779. );
  780. initialization
  781. RegisterAssembler(as_i386_elf32_info,TElf32Assembler);
  782. end.
  783. {
  784. $Log$
  785. Revision 1.19 2003-04-22 14:33:38 peter
  786. * removed some notes/hints
  787. Revision 1.18 2002/08/12 15:08:39 carl
  788. + stab register indexes for powerpc (moved from gdb to cpubase)
  789. + tprocessor enumeration moved to cpuinfo
  790. + linker in target_info is now a class
  791. * many many updates for m68k (will soon start to compile)
  792. - removed some ifdef or correct them for correct cpu
  793. Revision 1.17 2002/07/26 21:15:39 florian
  794. * rewrote the system handling
  795. Revision 1.16 2002/07/01 18:46:24 peter
  796. * internal linker
  797. * reorganized aasm layer
  798. Revision 1.15 2002/05/18 13:34:10 peter
  799. * readded missing revisions
  800. Revision 1.14 2002/05/16 19:46:39 carl
  801. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  802. + try to fix temp allocation (still in ifdef)
  803. + generic constructor calls
  804. + start of tassembler / tmodulebase class cleanup
  805. Revision 1.12 2002/05/12 16:53:08 peter
  806. * moved entry and exitcode to ncgutil and cgobj
  807. * foreach gets extra argument for passing local data to the
  808. iterator function
  809. * -CR checks also class typecasts at runtime by changing them
  810. into as
  811. * fixed compiler to cycle with the -CR option
  812. * fixed stabs with elf writer, finally the global variables can
  813. be watched
  814. * removed a lot of routines from cga unit and replaced them by
  815. calls to cgobj
  816. * u32bit-s32bit updates for and,or,xor nodes. When one element is
  817. u32bit then the other is typecasted also to u32bit without giving
  818. a rangecheck warning/error.
  819. * fixed pascal calling method with reversing also the high tree in
  820. the parast, detected by tcalcst3 test
  821. Revision 1.11 2002/04/04 19:05:58 peter
  822. * removed unused units
  823. * use tlocation.size in cg.a_*loc*() routines
  824. }