ogelf.pas 31 KB

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