ogelf.pas 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928
  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 defines.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. s : tsection;
  385. begin
  386. s:=section;
  387. if reloc then
  388. begin
  389. if (offset=-1) then
  390. begin
  391. if s=sec_none then
  392. offset:=0
  393. else
  394. offset:=sects[s].datasize;
  395. end;
  396. end;
  397. fillchar(stab,sizeof(telf32stab),0);
  398. if assigned(p) and (p[0]<>#0) then
  399. begin
  400. stab.strpos:=sects[sec_stabstr].datasize;
  401. sects[sec_stabstr].write(p^,strlen(p)+1);
  402. end;
  403. stab.ntype:=nidx;
  404. stab.ndesc:=line;
  405. stab.nother:=nother;
  406. stab.nvalue:=offset;
  407. sects[sec_stab].write(stab,sizeof(stab));
  408. { when the offset is not 0 then write a relocation, take also the
  409. hdrstab into account with the offset }
  410. if reloc then
  411. sects[sec_stab].addsectionreloc(sects[sec_stab].datasize-4,s,relative_false);
  412. end;
  413. procedure telf32data.writesymstabs(section:tsection;offset:longint;p:pchar;ps:tasmsymbol;
  414. nidx,nother,line:longint;reloc:boolean);
  415. var
  416. stab : telf32stab;
  417. begin
  418. if reloc then
  419. begin
  420. if (offset=-1) then
  421. begin
  422. if section=sec_none then
  423. offset:=0
  424. else
  425. offset:=sects[section].datasize;
  426. end;
  427. end;
  428. fillchar(stab,sizeof(telf32stab),0);
  429. if assigned(p) and (p[0]<>#0) then
  430. begin
  431. stab.strpos:=sects[sec_stabstr].datasize;
  432. sects[sec_stabstr].write(p^,strlen(p)+1);
  433. end;
  434. stab.ntype:=nidx;
  435. stab.ndesc:=line;
  436. stab.nother:=nother;
  437. stab.nvalue:=offset;
  438. sects[sec_stab].write(stab,sizeof(stab));
  439. { when the offset is not 0 then write a relocation, take also the
  440. hdrstab into account with the offset }
  441. if reloc then
  442. sects[sec_stab].addsymreloc(sects[sec_stab].datasize-4,ps,relative_false);
  443. end;
  444. procedure telf32data.setsectionsizes(var s:tsecsize);
  445. begin
  446. end;
  447. {****************************************************************************
  448. telf32objectoutput
  449. ****************************************************************************}
  450. function telf32objectoutput.initwriting(const fn:string):boolean;
  451. begin
  452. result:=inherited initwriting(fn);
  453. if result then
  454. begin
  455. initsym:=0;
  456. Fdata:=telf32data.create;
  457. end;
  458. end;
  459. procedure telf32objectoutput.createrelocsection(s:telf32section);
  460. var
  461. rel : telf32reloc;
  462. hr,r : poutputreloc;
  463. relsym,reltyp : longint;
  464. begin
  465. with telf32data(data) do
  466. begin
  467. { create the reloc section }
  468. s.relocsect:=telf32section.createname('.rel'+s.name,9,0,symtabsect.secshidx,s.secshidx,4,8);
  469. { add the relocations }
  470. r:=s.relochead;
  471. while assigned(r) do
  472. begin
  473. rel.address:=r^.address;
  474. if assigned(r^.symbol) then
  475. begin
  476. if (r^.symbol.bind=AB_LOCAL) then
  477. relsym:=sects[r^.symbol.section].secsymidx
  478. else
  479. begin
  480. if r^.symbol.idx=-1 then
  481. internalerror(4321);
  482. relsym:=(r^.symbol.idx+initsym);
  483. end;
  484. end
  485. else
  486. if r^.section<>sec_none then
  487. relsym:=sects[r^.section].secsymidx
  488. else
  489. relsym:=SHN_UNDEF;
  490. case r^.typ of
  491. relative_true :
  492. reltyp:=R_386_PC32;
  493. relative_false :
  494. reltyp:=R_386_32;
  495. end;
  496. rel.info:=(relsym shl 8) or reltyp;
  497. { write reloc }
  498. s.relocsect.write(rel,sizeof(rel));
  499. { goto next and dispose this reloc }
  500. hr:=r;
  501. r:=r^.next;
  502. dispose(hr);
  503. end;
  504. end;
  505. end;
  506. procedure telf32objectoutput.createsymtab;
  507. var
  508. elfsym : telf32symbol;
  509. sym : toutputsymbol;
  510. sec : tsection;
  511. locals,
  512. i : longint;
  513. begin
  514. with telf32data(data) do
  515. begin
  516. locals:=2;
  517. { empty entry }
  518. fillchar(elfsym,sizeof(elfsym),0);
  519. symtabsect.write(elfsym,sizeof(elfsym));
  520. { filename entry }
  521. elfsym.st_name:=1;
  522. elfsym.st_info:=STT_FILE;
  523. elfsym.st_shndx:=SHN_ABS;
  524. symtabsect.write(elfsym,sizeof(elfsym));
  525. { section }
  526. for sec:=low(tsection) to high(tsection) do
  527. if assigned(sects[sec]) then
  528. begin
  529. fillchar(elfsym,sizeof(elfsym),0);
  530. elfsym.st_name:=telf32section(sects[sec]).shstridx;
  531. elfsym.st_info:=STT_SECTION;
  532. elfsym.st_shndx:=telf32section(sects[sec]).secshidx;
  533. symtabsect.write(elfsym,sizeof(elfsym));
  534. inc(locals);
  535. end;
  536. { symbols }
  537. Syms.seek(0);
  538. for i:=1 to (Syms.size div sizeof(toutputsymbol)) do
  539. begin
  540. Syms.read(sym,sizeof(toutputsymbol));
  541. fillchar(elfsym,sizeof(elfsym),0);
  542. elfsym.st_name:=sym.nameidx;
  543. elfsym.st_value:=sym.value;
  544. elfsym.st_size:=sym.size;
  545. case sym.bind of
  546. AB_LOCAL :
  547. begin
  548. elfsym.st_info:=STB_LOCAL shl 4;
  549. inc(locals);
  550. end;
  551. AB_COMMON,
  552. AB_EXTERNAL,
  553. AB_GLOBAL :
  554. elfsym.st_info:=STB_GLOBAL shl 4;
  555. end;
  556. if sym.bind<>AB_EXTERNAL then
  557. begin
  558. case sym.typ of
  559. AT_FUNCTION :
  560. elfsym.st_info:=elfsym.st_info or STT_FUNC;
  561. AT_DATA :
  562. elfsym.st_info:=elfsym.st_info or STT_OBJECT;
  563. end;
  564. end;
  565. if sym.bind=AB_COMMON then
  566. elfsym.st_shndx:=SHN_COMMON
  567. else
  568. if assigned(sects[sym.section]) then
  569. elfsym.st_shndx:=telf32section(sects[sym.section]).secshidx
  570. else
  571. elfsym.st_shndx:=SHN_UNDEF;
  572. symtabsect.write(elfsym,sizeof(elfsym));
  573. end;
  574. { update the .symtab section header }
  575. symtabsect.shlink:=strtabsect.secshidx;
  576. symtabsect.shinfo:=locals;
  577. end;
  578. end;
  579. procedure telf32objectoutput.createshstrtab;
  580. var
  581. sec : tsection;
  582. begin
  583. with telf32data(data) do
  584. begin
  585. with shstrtabsect do
  586. begin
  587. writestr(#0);
  588. symtabsect.shstridx:=writestr('.symtab'#0);
  589. strtabsect.shstridx:=writestr('.strtab'#0);
  590. shstrtabsect.shstridx:=writestr('.shstrtab'#0);
  591. for sec:=low(tsection) to high(tsection) do
  592. if assigned(sects[sec]) then
  593. begin
  594. telf32section(sects[sec]).shstridx:=writestr(sects[sec].name+#0);
  595. if assigned(telf32section(sects[sec]).relocsect) then
  596. telf32section(sects[sec]).relocsect.shstridx:=writestr(telf32section(sects[sec]).relocsect.name+#0);
  597. end;
  598. end;
  599. end;
  600. end;
  601. procedure telf32objectoutput.writesectionheader(s:telf32section);
  602. var
  603. sechdr : telf32sechdr;
  604. begin
  605. fillchar(sechdr,sizeof(sechdr),0);
  606. sechdr.sh_name:=s.shstridx;
  607. sechdr.sh_type:=s.shtype;
  608. sechdr.sh_flags:=s.shflags;
  609. sechdr.sh_offset:=s.datapos;
  610. sechdr.sh_size:=s.datasize;
  611. sechdr.sh_link:=s.shlink;
  612. sechdr.sh_info:=s.shinfo;
  613. sechdr.sh_addralign:=s.addralign;
  614. sechdr.sh_entsize:=s.entsize;
  615. writer.write(sechdr,sizeof(sechdr));
  616. end;
  617. procedure telf32objectoutput.writetodisk;
  618. var
  619. header : telf32header;
  620. datapos,
  621. shoffset,
  622. nsects : longint;
  623. hstab : telf32stab;
  624. sec : tsection;
  625. empty : array[0..63] of byte;
  626. hp : pdynamicblock;
  627. begin
  628. with telf32data(data) do
  629. begin
  630. { calc amount of sections we have }
  631. fillchar(empty,sizeof(empty),0);
  632. nsects:=1;
  633. initsym:=2;
  634. for sec:=low(tsection) to high(tsection) do
  635. if assigned(sects[sec]) then
  636. begin
  637. { each section requires a symbol for relocation }
  638. sects[sec].secsymidx:=initsym;
  639. inc(initsym);
  640. { also create the index in the section header table }
  641. telf32section(sects[sec]).secshidx:=nsects;
  642. inc(nsects);
  643. if assigned(sects[sec].relochead) then
  644. inc(nsects);
  645. end;
  646. { add default sections follows }
  647. shstrtabsect.secshidx:=nsects;
  648. inc(nsects);
  649. symtabsect.secshidx:=nsects;
  650. inc(nsects);
  651. strtabsect.secshidx:=nsects;
  652. inc(nsects);
  653. { For the stab section we need an HdrSym which can now be
  654. calculated more easily }
  655. if assigned(sects[sec_stab]) then
  656. begin
  657. hstab.strpos:=1;
  658. hstab.ntype:=0;
  659. hstab.nother:=0;
  660. hstab.ndesc:=(sects[sec_stab].datasize div sizeof(telf32stab))-1{+1 according to gas output PM};
  661. hstab.nvalue:=sects[sec_stabstr].datasize;
  662. sects[sec_stab].Data.seek(0);
  663. sects[sec_stab].Data.write(hstab,sizeof(hstab));
  664. end;
  665. { Create the relocation sections }
  666. for sec:=low(tsection) to high(tsection) do
  667. if assigned(sects[sec]) and
  668. (sects[sec].nrelocs>0) then
  669. createrelocsection(telf32section(sects[sec]));
  670. { create .symtab }
  671. createsymtab;
  672. { create .shstrtab }
  673. createshstrtab;
  674. { Calculate the filepositions }
  675. datapos:=$40; { elfheader + alignment }
  676. { sections first }
  677. for sec:=low(tsection) to high(tsection) do
  678. if assigned(sects[sec]) then
  679. begin
  680. sects[sec].datapos:=datapos;
  681. if assigned(sects[sec].data) then
  682. inc(datapos,sects[sec].aligneddatasize);
  683. end;
  684. { shstrtab }
  685. shstrtabsect.datapos:=datapos;
  686. inc(datapos,shstrtabsect.aligneddatasize);
  687. { section headers }
  688. shoffset:=datapos;
  689. inc(datapos,nsects*sizeof(telf32sechdr));
  690. { symtab }
  691. symtabsect.datapos:=datapos;
  692. inc(datapos,symtabsect.aligneddatasize);
  693. { strtab }
  694. strtabsect.datapos:=datapos;
  695. inc(datapos,align(strtabsect.datasize,4));
  696. { .rel sections }
  697. for sec:=low(tsection) to high(tsection) do
  698. if assigned(sects[sec]) and
  699. assigned(telf32section(sects[sec]).relocsect) then
  700. begin
  701. telf32section(sects[sec]).relocsect.datapos:=datapos;
  702. inc(datapos,telf32section(sects[sec]).relocsect.aligneddatasize);
  703. end;
  704. { Write ELF Header }
  705. fillchar(header,sizeof(header),0);
  706. header.magic0123:=$464c457f; { = #127'ELF' }
  707. header.file_class:=1;
  708. header.data_encoding:=1;
  709. header.file_version:=1;
  710. header.e_type:=1;
  711. header.e_machine:=3;
  712. header.e_version:=1;
  713. header.e_shoff:=shoffset;
  714. header.e_shstrndx:=shstrtabsect.secshidx;
  715. header.e_shnum:=nsects;
  716. header.e_ehsize:=sizeof(telf32header);
  717. header.e_shentsize:=sizeof(telf32sechdr);
  718. writer.write(header,sizeof(header));
  719. writer.write(empty,$40-sizeof(header)); { align }
  720. { Sections }
  721. for sec:=low(tsection) to high(tsection) do
  722. if assigned(sects[sec]) and
  723. assigned(sects[sec].data) then
  724. begin
  725. sects[sec].alignsection;
  726. hp:=sects[sec].Data.firstblock;
  727. while assigned(hp) do
  728. begin
  729. writer.write(hp^.data,hp^.used);
  730. hp:=hp^.next;
  731. end;
  732. end;
  733. { .shstrtab }
  734. shstrtabsect.alignsection;
  735. hp:=shstrtabsect.Data.firstblock;
  736. while assigned(hp) do
  737. begin
  738. writer.write(hp^.data,hp^.used);
  739. hp:=hp^.next;
  740. end;
  741. { section headers, start with an empty header for sh_undef }
  742. writer.write(empty,sizeof(telf32sechdr));
  743. for sec:=low(tsection) to high(tsection) do
  744. if assigned(sects[sec]) then
  745. begin
  746. writesectionheader(telf32section(sects[sec]));
  747. if assigned(telf32section(sects[sec]).relocsect) then
  748. writesectionheader(telf32section(sects[sec]).relocsect);
  749. end;
  750. writesectionheader(shstrtabsect);
  751. writesectionheader(symtabsect);
  752. writesectionheader(strtabsect);
  753. { .symtab }
  754. symtabsect.alignsection;
  755. hp:=symtabsect.Data.firstblock;
  756. while assigned(hp) do
  757. begin
  758. writer.write(hp^.data,hp^.used);
  759. hp:=hp^.next;
  760. end;
  761. { .strtab }
  762. strtabsect.writealign(4);
  763. hp:=strtabsect.Data.firstblock;
  764. while assigned(hp) do
  765. begin
  766. writer.write(hp^.data,hp^.used);
  767. hp:=hp^.next;
  768. end;
  769. { .rel sections }
  770. for sec:=low(tsection) to high(tsection) do
  771. if assigned(sects[sec]) and
  772. assigned(telf32section(sects[sec]).relocsect) then
  773. begin
  774. telf32section(sects[sec]).relocsect.alignsection;
  775. hp:=telf32section(sects[sec]).relocsect.Data.firstblock;
  776. while assigned(hp) do
  777. begin
  778. writer.write(hp^.data,hp^.used);
  779. hp:=hp^.next;
  780. end;
  781. end;
  782. end;
  783. end;
  784. {****************************************************************************
  785. TELFAssembler
  786. ****************************************************************************}
  787. constructor TELF32Assembler.Create(smart:boolean);
  788. begin
  789. inherited Create(smart);
  790. objectoutput:=telf32objectoutput.create(smart);
  791. end;
  792. {*****************************************************************************
  793. Initialize
  794. *****************************************************************************}
  795. const
  796. as_i386_elf32_info : tasminfo =
  797. (
  798. id : as_i386_elf32;
  799. idtxt : 'ELF';
  800. asmbin : '';
  801. asmcmd : '';
  802. supported_target : target_any; //target_i386_linux;
  803. outputbinary : true;
  804. allowdirect : false;
  805. externals : true;
  806. needar : false;
  807. labelprefix_only_inside_procedure: false;
  808. labelprefix : '.L';
  809. comment : '';
  810. secnames : ('',
  811. '.text','.data','.bss',
  812. '.idata$2','.idata$4','.idata$5','.idata$6','.idata$7','.edata',
  813. '.stab','.stabstr')
  814. );
  815. initialization
  816. RegisterAssembler(as_i386_elf32_info,TElf32Assembler);
  817. end.
  818. {
  819. $Log$
  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. Revision 1.10 2001/05/06 17:13:23 jonas
  824. * completed incomplete typed constant records
  825. Revision 1.9 2001/05/04 19:50:58 peter
  826. * finally added the missing outputbinary field that was missing
  827. Revision 1.8 2001/04/18 22:01:54 peter
  828. * registration of targets and assemblers
  829. Revision 1.7 2001/04/13 01:22:10 peter
  830. * symtable change to classes
  831. * range check generation and errors fixed, make cycle DEBUG=1 works
  832. * memory leaks fixed
  833. Revision 1.6 2001/03/05 21:40:39 peter
  834. * more things for tcoffobjectinput
  835. Revision 1.5 2000/12/25 00:07:26 peter
  836. + new tlinkedlist class (merge of old tstringqueue,tcontainer and
  837. tlinkedlist objects)
  838. Revision 1.4 2000/12/24 12:25:32 peter
  839. + cstreams unit
  840. * dynamicarray object to class
  841. Revision 1.3 2000/12/23 19:59:35 peter
  842. * object to class for ow/og objects
  843. * split objectdata from objectoutput
  844. Revision 1.2 2000/11/12 22:45:14 peter
  845. * moved setting of stab hdrsym
  846. Revision 1.1 2000/11/12 22:20:37 peter
  847. * create generic toutputsection for binary writers
  848. }