og386elf.pas 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074
  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 og386elf;
  22. {$i defines.inc}
  23. interface
  24. uses
  25. cobjects,
  26. systems,cpubase,aasm,og386;
  27. type
  28. preloc = ^treloc;
  29. treloc = packed record
  30. next : preloc;
  31. address : longint;
  32. symbol : pasmsymbol;
  33. section : tsection; { only used if symbol=nil }
  34. typ : relative_type;
  35. end;
  36. psymbol = ^tsymbol;
  37. tsymbol = packed record
  38. name : longint;
  39. section : tsection;
  40. value : longint;
  41. bind : TAsmsymbind;
  42. typ : TAsmsymtype;
  43. size : longint;
  44. end;
  45. pelf32section = ^telf32section;
  46. telf32section = object
  47. name : string[16];
  48. secshidx,
  49. secsymidx : longint; { index for the section in symtab }
  50. shstridx,
  51. shtype,
  52. shflags,
  53. shlink,
  54. shinfo,
  55. addralign,
  56. entsize : longint;
  57. { size of the data and in the file }
  58. data : PDynamicArray;
  59. datalen,
  60. datapos : longint;
  61. { settings after setsectionsize }
  62. size : longint;
  63. fillsize : longint;
  64. { relocation }
  65. nrelocs : longint;
  66. relochead : PReloc;
  67. reloctail : ^PReloc;
  68. relocsect : PElf32Section;
  69. constructor init(sec:TSection);
  70. constructor initname(const Aname:string;Atype,Aflags,Alink,Ainfo,Aalign,Aentsize:longint);
  71. destructor done;
  72. function write(var d;l:longint):longint;
  73. function writestr(const s:string):longint;
  74. procedure writealign(l:longint);
  75. function aligneddatalen:longint;
  76. procedure alignsection;
  77. procedure alloc(l:longint);
  78. procedure addsymreloc(ofs:longint;p:pasmsymbol;relative:relative_type);
  79. procedure addsectionreloc(ofs:longint;sec:tsection;relative:relative_type);
  80. end;
  81. pelf32output = ^telf32output;
  82. telf32output = object(tobjectoutput)
  83. sects : array[TSection] of pelf32Section;
  84. symtabsect,
  85. strtabsect,
  86. shstrtabsect,
  87. gotpcsect,
  88. gotoffsect,
  89. gotsect,
  90. pltsect,
  91. symsect : pelf32Section;
  92. strs,
  93. syms : Pdynamicarray;
  94. initsym : longint;
  95. constructor init(smart:boolean);
  96. destructor done;virtual;
  97. procedure initwriting(Aplace:tcutplace);virtual;
  98. procedure donewriting;virtual;
  99. function sectionsize(s:tsection):longint;virtual;
  100. procedure setsectionsizes(var s:tsecsize);virtual;
  101. procedure writebytes(var data;len:longint);virtual;
  102. procedure writealloc(len:longint);virtual;
  103. procedure writealign(len:longint);virtual;
  104. procedure writereloc(data,len:longint;p:pasmsymbol;relative:relative_type);virtual;
  105. procedure writesymbol(p:pasmsymbol);virtual;
  106. procedure writestabs(section:tsection;offset:longint;p:pchar;nidx,nother,line:longint;reloc:boolean);virtual;
  107. procedure writesymstabs(section:tsection;offset:longint;p:pchar;ps:pasmsymbol;
  108. nidx,nother,line:longint;reloc:boolean);virtual;
  109. private
  110. procedure createsection(sec:tsection);
  111. procedure createrelocsection(s:pelf32section);
  112. procedure createshstrtab;
  113. procedure createsymtab;
  114. procedure writesectionheader(s:pelf32section);
  115. procedure writetodisk;
  116. end;
  117. implementation
  118. uses
  119. {$ifdef delphi}
  120. sysutils,
  121. {$else}
  122. strings,
  123. {$endif}
  124. verbose,
  125. globtype,cutils,globals,fmodule;
  126. const
  127. symbolresize = 200*18;
  128. strsresize = 8192;
  129. DataResize = 8192;
  130. const
  131. R_386_32 = 1; { ordinary absolute relocation }
  132. R_386_PC32 = 2; { PC-relative relocation }
  133. R_386_GOT32 = 3; { an offset into GOT }
  134. R_386_PLT32 = 4; { a PC-relative offset into PLT }
  135. R_386_GOTOFF = 9; { an offset from GOT base }
  136. R_386_GOTPC = 10; { a PC-relative offset _to_ GOT }
  137. SHN_UNDEF = 0;
  138. SHN_ABS = $fff1;
  139. SHN_COMMON = $fff2;
  140. SHT_NULL = 0;
  141. SHT_PROGBITS = 1;
  142. SHT_SYMTAB = 2;
  143. SHT_STRTAB = 3;
  144. SHT_RELA = 4;
  145. SHT_HASH = 5;
  146. SHT_DYNAMIC = 6;
  147. SHT_NOTE = 7;
  148. SHT_NOBITS = 8;
  149. SHT_REL = 9;
  150. SHT_SHLIB = 10;
  151. SHT_DYNSYM = 11;
  152. SHF_WRITE = 1;
  153. SHF_ALLOC = 2;
  154. SHF_EXECINSTR = 4;
  155. STB_LOCAL = 0;
  156. STB_GLOBAL = 1;
  157. STB_WEAK = 2;
  158. STT_NOTYPE = 0;
  159. STT_OBJECT = 1;
  160. STT_FUNC = 2;
  161. STT_SECTION = 3;
  162. STT_FILE = 4;
  163. type
  164. { Structures which are written directly to the output file }
  165. telf32header=packed record
  166. magic0123 : longint;
  167. file_class : byte;
  168. data_encoding : byte;
  169. file_version : byte;
  170. padding : array[$07..$0f] of byte;
  171. e_type : word;
  172. e_machine : word;
  173. e_version : longint;
  174. e_entry : longint; { entrypoint }
  175. e_phoff : longint; { program header offset }
  176. e_shoff : longint; { sections header offset }
  177. e_flags : longint;
  178. e_ehsize : word; { elf header size in bytes }
  179. e_phentsize : word; { size of an entry in the program header array }
  180. e_phnum : word; { 0..e_phnum-1 of entrys }
  181. e_shentsize : word; { size of an entry in sections header array }
  182. e_shnum : word; { 0..e_shnum-1 of entrys }
  183. e_shstrndx : word; { index of string section header }
  184. end;
  185. telf32sechdr=packed record
  186. sh_name : longint;
  187. sh_type : longint;
  188. sh_flags : longint;
  189. sh_addr : longint;
  190. sh_offset : longint;
  191. sh_size : longint;
  192. sh_link : longint;
  193. sh_info : longint;
  194. sh_addralign : longint;
  195. sh_entsize : longint;
  196. end;
  197. pelf32reloc=^telf32reloc;
  198. telf32reloc=packed record
  199. address : longint;
  200. info : longint; { bit 0-7: type, 8-31: symbol }
  201. end;
  202. pelf32symbol=^telf32symbol;
  203. telf32symbol=packed record
  204. st_name : longint;
  205. st_value : longint;
  206. st_size : longint;
  207. st_info : byte; { bit 0-3: type, 4-7: bind }
  208. st_other : byte;
  209. st_shndx : word;
  210. end;
  211. pelf32stab=^telf32stab;
  212. telf32stab=packed record
  213. strpos : longint;
  214. ntype : byte;
  215. nother : byte;
  216. ndesc : word;
  217. nvalue : longint;
  218. end;
  219. {****************************************************************************
  220. TSection
  221. ****************************************************************************}
  222. constructor telf32section.init(sec:TSection);
  223. var
  224. Aflags,Atype,Aalign,Aentsize : longint;
  225. begin
  226. Aflags:=0;
  227. Atype:=0;
  228. Aalign:=0;
  229. Aentsize:=0;
  230. case sec of
  231. sec_code :
  232. begin
  233. Aflags:=SHF_ALLOC or SHF_EXECINSTR;
  234. AType:=SHT_PROGBITS;
  235. AAlign:=16;
  236. end;
  237. sec_data :
  238. begin
  239. Aflags:=SHF_ALLOC or SHF_WRITE;
  240. AType:=SHT_PROGBITS;
  241. AAlign:=4;
  242. end;
  243. sec_bss :
  244. begin
  245. Aflags:=SHF_ALLOC or SHF_WRITE;
  246. AType:=SHT_NOBITS;
  247. AAlign:=4;
  248. end;
  249. sec_stab :
  250. begin
  251. AType:=SHT_PROGBITS;
  252. AAlign:=4;
  253. Aentsize:=sizeof(telf32stab);
  254. end;
  255. sec_stabstr :
  256. begin
  257. AType:=SHT_STRTAB;
  258. AAlign:=1;
  259. end;
  260. end;
  261. initname(target_asm.secnames[sec],Atype,Aflags,0,0,Aalign,Aentsize);
  262. end;
  263. constructor telf32section.initname(const Aname:string;Atype,Aflags,Alink,Ainfo,Aalign,Aentsize:longint);
  264. begin
  265. name:=Aname;
  266. secshidx:=0;
  267. secsymidx:=0;
  268. shstridx:=0;
  269. shtype:=AType;
  270. shflags:=AFlags;
  271. shlink:=Alink;
  272. shinfo:=Ainfo;
  273. addralign:=Aalign;
  274. entsize:=Aentsize;
  275. { setsectionsize data }
  276. fillsize:=0;
  277. size:=0;
  278. { data }
  279. dataLen:=0;
  280. dataPos:=0;
  281. if shtype=SHT_NOBITS then
  282. data:=nil
  283. else
  284. new(Data,Init(8192));
  285. { relocation }
  286. NRelocs:=0;
  287. relocHead:=nil;
  288. relocTail:=@relocHead;
  289. relocsect:=nil;
  290. end;
  291. destructor telf32section.done;
  292. begin
  293. if assigned(Data) then
  294. dispose(Data,done);
  295. end;
  296. function telf32section.write(var d;l:longint):longint;
  297. begin
  298. write:=datalen;
  299. if not assigned(Data) then
  300. Internalerror(3334441);
  301. Data^.write(d,l);
  302. inc(datalen,l);
  303. end;
  304. function telf32section.writestr(const s:string):longint;
  305. begin
  306. writestr:=datalen;
  307. if not assigned(Data) then
  308. Internalerror(3334441);
  309. Data^.write(s[1],length(s));
  310. inc(datalen,length(s));
  311. end;
  312. procedure telf32section.writealign(l:longint);
  313. var
  314. i : longint;
  315. empty : array[0..63] of char;
  316. begin
  317. { no alignment needed for 0 or 1 }
  318. if l<=1 then
  319. exit;
  320. i:=datalen mod l;
  321. if i>0 then
  322. begin
  323. if assigned(data) then
  324. begin
  325. fillchar(empty,sizeof(empty),0);
  326. data^.write(empty,l-i);
  327. end;
  328. inc(datalen,l-i);
  329. end;
  330. end;
  331. function telf32section.aligneddatalen:longint;
  332. begin
  333. aligneddatalen:=align(datalen,addralign);
  334. end;
  335. procedure telf32section.alignsection;
  336. begin
  337. writealign(addralign);
  338. end;
  339. procedure telf32section.alloc(l:longint);
  340. begin
  341. if assigned(Data) then
  342. Internalerror(3334442);
  343. inc(datalen,l);
  344. end;
  345. procedure telf32section.addsymreloc(ofs:longint;p:pasmsymbol;relative:relative_type);
  346. var
  347. r : PReloc;
  348. begin
  349. new(r);
  350. reloctail^:=r;
  351. reloctail:=@r^.next;
  352. r^.next:=nil;
  353. r^.address:=ofs;
  354. r^.symbol:=p;
  355. r^.section:=sec_none;
  356. r^.typ:=relative;
  357. inc(nrelocs);
  358. end;
  359. procedure telf32section.addsectionreloc(ofs:longint;sec:tsection;relative:relative_type);
  360. var
  361. r : PReloc;
  362. begin
  363. new(r);
  364. reloctail^:=r;
  365. reloctail:=@r^.next;
  366. r^.next:=nil;
  367. r^.address:=ofs;
  368. r^.symbol:=nil;
  369. r^.section:=sec;
  370. r^.typ:=relative;
  371. inc(nrelocs);
  372. end;
  373. {****************************************************************************
  374. TElf32Output
  375. ****************************************************************************}
  376. constructor telf32output.init(smart:boolean);
  377. begin
  378. inherited init(smart);
  379. end;
  380. destructor telf32output.done;
  381. begin
  382. inherited done;
  383. end;
  384. procedure telf32output.initwriting(Aplace:tcutplace);
  385. var
  386. s : string;
  387. begin
  388. inherited initwriting(Aplace);
  389. { reset }
  390. initsym:=0;
  391. new(syms,init(symbolresize));
  392. FillChar(Sects,sizeof(Sects),0);
  393. { default sections }
  394. new(symtabsect,initname('.symtab',2,0,0,0,4,16));
  395. new(strtabsect,initname('.strtab',3,0,0,0,1,0));
  396. new(shstrtabsect,initname('.shstrtab',3,0,0,0,1,0));
  397. { insert the empty and filename as first in strtab }
  398. strtabsect^.writestr(#0);
  399. strtabsect^.writestr(SplitFileName(current_module^.mainsource^)+#0);
  400. { we need at least the following sections }
  401. createsection(sec_code);
  402. createsection(sec_data);
  403. createsection(sec_bss);
  404. { create stabs sections if debugging }
  405. if (cs_debuginfo in aktmoduleswitches) then
  406. begin
  407. createsection(sec_stab);
  408. createsection(sec_stabstr);
  409. writestabs(sec_none,0,nil,0,0,0,false);
  410. { write zero pchar and name together (PM) }
  411. s:=#0+SplitFileName(current_module^.mainsource^)+#0;
  412. sects[sec_stabstr]^.write(s[1],length(s));
  413. end;
  414. end;
  415. procedure telf32output.donewriting;
  416. var
  417. sec : tsection;
  418. begin
  419. writetodisk;
  420. dispose(syms,done);
  421. for sec:=low(tsection) to high(tsection) do
  422. if assigned(sects[sec]) then
  423. dispose(sects[sec],done);
  424. inherited donewriting;
  425. end;
  426. function telf32output.sectionsize(s:tsection):longint;
  427. begin
  428. if assigned(sects[s]) then
  429. sectionsize:=sects[s]^.datalen
  430. else
  431. sectionsize:=0;
  432. end;
  433. procedure telf32output.createsection(sec:tsection);
  434. begin
  435. sects[sec]:=new(pelf32Section,init(Sec));
  436. end;
  437. procedure telf32output.writesymbol(p:pasmsymbol);
  438. var
  439. sym : tsymbol;
  440. begin
  441. { already written ? }
  442. if p^.idx<>-1 then
  443. exit;
  444. { be sure that the section will exists }
  445. if (p^.section<>sec_none) and not(assigned(sects[p^.section])) then
  446. createsection(p^.section);
  447. FillChar(sym,sizeof(sym),0);
  448. sym.size:=p^.size;
  449. sym.bind:=p^.bind;
  450. sym.typ:=p^.typ;
  451. { if local of global then set the section value to the address
  452. of the symbol }
  453. case sym.bind of
  454. AB_LOCAL,
  455. AB_GLOBAL :
  456. begin
  457. sym.section:=p^.section;
  458. sym.value:=p^.address;
  459. end;
  460. AB_COMMON :
  461. begin
  462. sym.value:=$10;
  463. end;
  464. end;
  465. { update the asmsymbol index }
  466. p^.idx:=syms^.size div sizeof(tsymbol);
  467. { store the symbol, but not the local ones (PM) }
  468. if (sym.bind<>AB_LOCAL) then
  469. begin
  470. { symbolname, write the #0 separate to overcome 255+1 char not possible }
  471. sym.name:=strtabsect^.writestr(p^.name);
  472. strtabsect^.writestr(#0);
  473. { symbol }
  474. syms^.write(sym,sizeof(tsymbol));
  475. end;
  476. { make the exported syms known to the objectwriter
  477. (needed for .a generation) }
  478. if (sym.bind in [AB_GLOBAL,AB_COMMON]) then
  479. writer^.writesym(p^.name);
  480. end;
  481. procedure telf32output.writebytes(var data;len:longint);
  482. begin
  483. if not assigned(sects[currsec]) then
  484. createsection(currsec);
  485. sects[currsec]^.write(data,len);
  486. end;
  487. procedure telf32output.writealloc(len:longint);
  488. begin
  489. if not assigned(sects[currsec]) then
  490. createsection(currsec);
  491. sects[currsec]^.alloc(len);
  492. end;
  493. procedure telf32output.writealign(len:longint);
  494. var
  495. modulo : longint;
  496. begin
  497. if not assigned(sects[currsec]) then
  498. createsection(currsec);
  499. modulo:=sects[currsec]^.datalen mod len;
  500. if modulo > 0 then
  501. sects[currsec]^.alloc(len-modulo);
  502. end;
  503. procedure telf32output.writereloc(data,len:longint;p:pasmsymbol;relative:relative_type);
  504. var
  505. symaddr : longint;
  506. begin
  507. if not assigned(sects[currsec]) then
  508. createsection(currsec);
  509. if assigned(p) then
  510. begin
  511. { real address of the symbol }
  512. symaddr:=p^.address;
  513. { no symbol relocation need inside a section }
  514. if p^.section=currsec then
  515. begin
  516. case relative of
  517. relative_false :
  518. begin
  519. sects[currsec]^.addsectionreloc(sects[currsec]^.datalen,currsec,relative_false);
  520. inc(data,symaddr);
  521. end;
  522. relative_true :
  523. begin
  524. inc(data,symaddr-len-sects[currsec]^.datalen);
  525. end;
  526. relative_rva :
  527. internalerror(3219583);
  528. end;
  529. end
  530. else
  531. begin
  532. writesymbol(p);
  533. if (p^.section<>sec_none) and (relative<>relative_true) then
  534. begin
  535. sects[currsec]^.addsectionreloc(sects[currsec]^.datalen,p^.section,relative);
  536. inc(data,symaddr);
  537. end
  538. else
  539. sects[currsec]^.addsymreloc(sects[currsec]^.datalen,p,relative);
  540. if relative=relative_true then
  541. begin
  542. if p^.bind=AB_EXTERNAL then
  543. dec(data,len)
  544. else
  545. dec(data,len+sects[currsec]^.datalen);
  546. end;
  547. end;
  548. end;
  549. sects[currsec]^.write(data,len);
  550. end;
  551. procedure telf32output.writestabs(section:tsection;offset:longint;p:pchar;nidx,nother,line:longint;reloc : boolean);
  552. var
  553. stab : telf32stab;
  554. s : tsection;
  555. begin
  556. s:=section;
  557. if reloc then
  558. begin
  559. if (offset=-1) then
  560. begin
  561. if s=sec_none then
  562. offset:=0
  563. else
  564. offset:=sects[s]^.datalen;
  565. end;
  566. end;
  567. fillchar(stab,sizeof(telf32stab),0);
  568. if assigned(p) and (p[0]<>#0) then
  569. begin
  570. stab.strpos:=sects[sec_stabstr]^.datalen;
  571. sects[sec_stabstr]^.write(p^,strlen(p)+1);
  572. end;
  573. stab.ntype:=nidx;
  574. stab.ndesc:=line;
  575. stab.nother:=nother;
  576. stab.nvalue:=offset;
  577. sects[sec_stab]^.write(stab,sizeof(stab));
  578. { when the offset is not 0 then write a relocation, take also the
  579. hdrstab into account with the offset }
  580. if reloc then
  581. sects[sec_stab]^.addsectionreloc(sects[sec_stab]^.datalen-4,s,relative_false);
  582. end;
  583. procedure telf32output.writesymstabs(section:tsection;offset:longint;p:pchar;ps:pasmsymbol;
  584. nidx,nother,line:longint;reloc:boolean);
  585. var
  586. stab : telf32stab;
  587. s : tsection;
  588. begin
  589. s:=section;
  590. if reloc then
  591. begin
  592. if (offset=-1) then
  593. begin
  594. if s=sec_none then
  595. offset:=0
  596. else
  597. offset:=sects[s]^.datalen;
  598. end;
  599. end;
  600. fillchar(stab,sizeof(telf32stab),0);
  601. if assigned(p) and (p[0]<>#0) then
  602. begin
  603. stab.strpos:=sects[sec_stabstr]^.datalen;
  604. sects[sec_stabstr]^.write(p^,strlen(p)+1);
  605. end;
  606. stab.ntype:=nidx;
  607. stab.ndesc:=line;
  608. stab.nother:=nother;
  609. stab.nvalue:=offset;
  610. sects[sec_stab]^.write(stab,sizeof(stab));
  611. { when the offset is not 0 then write a relocation, take also the
  612. hdrstab into account with the offset }
  613. if reloc then
  614. sects[sec_stab]^.addsymreloc(sects[sec_stab]^.datalen-4,ps,relative_false);
  615. end;
  616. procedure telf32output.setsectionsizes(var s:tsecsize);
  617. var
  618. align : longint;
  619. sec : tsection;
  620. begin
  621. { multiply stab with real size }
  622. s[sec_stab]:=s[sec_stab]*sizeof(telf32stab);
  623. { if debug then also count header stab }
  624. if (cs_debuginfo in aktmoduleswitches) then
  625. begin
  626. inc(s[sec_stab],sizeof(telf32stab));
  627. inc(s[sec_stabstr],length(SplitFileName(current_module^.mainsource^))+2);
  628. end;
  629. { fix all section }
  630. for sec:=low(tsection) to high(tsection) do
  631. begin
  632. if (s[sec]>0) and (not assigned(sects[sec])) then
  633. createsection(sec);
  634. if assigned(sects[sec]) then
  635. begin
  636. sects[sec]^.size:=s[sec];
  637. { calculate the alignment }
  638. align:=sects[sec]^.addralign;
  639. sects[sec]^.fillsize:=align-(sects[sec]^.size and (align-1));
  640. if sects[sec]^.fillsize=align then
  641. sects[sec]^.fillsize:=0;
  642. end;
  643. end;
  644. end;
  645. {***********************************************
  646. Writing to disk
  647. ***********************************************}
  648. procedure telf32output.createrelocsection(s:pelf32section);
  649. var
  650. rel : telf32reloc;
  651. hr,r : preloc;
  652. relsym,reltyp : longint;
  653. begin
  654. { create the reloc section }
  655. new(s^.relocsect,initname('.rel'+s^.name,9,0,symtabsect^.secshidx,s^.secshidx,4,8));
  656. { add the relocations }
  657. r:=s^.relochead;
  658. while assigned(r) do
  659. begin
  660. rel.address:=r^.address;
  661. if assigned(r^.symbol) then
  662. begin
  663. if (r^.symbol^.bind=AB_LOCAL) then
  664. relsym:=sects[r^.symbol^.section]^.secsymidx
  665. else
  666. begin
  667. if r^.symbol^.idx=-1 then
  668. internalerror(4321);
  669. relsym:=(r^.symbol^.idx+initsym);
  670. end;
  671. end
  672. else
  673. if r^.section<>sec_none then
  674. relsym:=sects[r^.section]^.secsymidx
  675. else
  676. relsym:=SHN_UNDEF;
  677. case r^.typ of
  678. relative_true :
  679. reltyp:=R_386_PC32;
  680. relative_false :
  681. reltyp:=R_386_32;
  682. end;
  683. rel.info:=(relsym shl 8) or reltyp;
  684. { write reloc }
  685. s^.relocsect^.write(rel,sizeof(rel));
  686. { goto next and dispose this reloc }
  687. hr:=r;
  688. r:=r^.next;
  689. dispose(hr);
  690. end;
  691. end;
  692. procedure telf32output.createsymtab;
  693. var
  694. elfsym : telf32symbol;
  695. sym : tsymbol;
  696. sec : tsection;
  697. locals,
  698. i : longint;
  699. begin
  700. locals:=2;
  701. { empty entry }
  702. fillchar(elfsym,sizeof(elfsym),0);
  703. symtabsect^.write(elfsym,sizeof(elfsym));
  704. { filename entry }
  705. elfsym.st_name:=1;
  706. elfsym.st_info:=STT_FILE;
  707. elfsym.st_shndx:=SHN_ABS;
  708. symtabsect^.write(elfsym,sizeof(elfsym));
  709. { section }
  710. for sec:=low(tsection) to high(tsection) do
  711. if assigned(sects[sec]) then
  712. begin
  713. fillchar(elfsym,sizeof(elfsym),0);
  714. elfsym.st_name:=sects[sec]^.shstridx;
  715. elfsym.st_info:=STT_SECTION;
  716. elfsym.st_shndx:=sects[sec]^.secshidx;
  717. symtabsect^.write(elfsym,sizeof(elfsym));
  718. inc(locals);
  719. end;
  720. { symbols }
  721. syms^.seek(0);
  722. for i:=1 to (syms^.size div sizeof(TSymbol)) do
  723. begin
  724. syms^.read(sym,sizeof(TSymbol));
  725. fillchar(elfsym,sizeof(elfsym),0);
  726. elfsym.st_name:=sym.name;
  727. elfsym.st_value:=sym.value;
  728. elfsym.st_size:=sym.size;
  729. case sym.bind of
  730. AB_LOCAL :
  731. begin
  732. elfsym.st_info:=STB_LOCAL shl 4;
  733. inc(locals);
  734. end;
  735. AB_COMMON,
  736. AB_EXTERNAL,
  737. AB_GLOBAL :
  738. elfsym.st_info:=STB_GLOBAL shl 4;
  739. end;
  740. if sym.bind<>AB_EXTERNAL then
  741. begin
  742. case sym.typ of
  743. AT_FUNCTION :
  744. elfsym.st_info:=elfsym.st_info or STT_FUNC;
  745. AT_DATA :
  746. elfsym.st_info:=elfsym.st_info or STT_OBJECT;
  747. end;
  748. end;
  749. if sym.bind=AB_COMMON then
  750. elfsym.st_shndx:=SHN_COMMON
  751. else
  752. if assigned(sects[sym.section]) then
  753. elfsym.st_shndx:=sects[sym.section]^.secshidx
  754. else
  755. elfsym.st_shndx:=SHN_UNDEF;
  756. symtabsect^.write(elfsym,sizeof(elfsym));
  757. end;
  758. { update the .symtab section header }
  759. symtabsect^.shlink:=strtabsect^.secshidx;
  760. symtabsect^.shinfo:=locals;
  761. end;
  762. procedure telf32output.createshstrtab;
  763. var
  764. sec : tsection;
  765. begin
  766. with shstrtabsect^ do
  767. begin
  768. writestr(#0);
  769. symtabsect^.shstridx:=writestr('.symtab'#0);
  770. strtabsect^.shstridx:=writestr('.strtab'#0);
  771. shstrtabsect^.shstridx:=writestr('.shstrtab'#0);
  772. for sec:=low(tsection) to high(tsection) do
  773. if assigned(sects[sec]) then
  774. begin
  775. sects[sec]^.shstridx:=writestr(sects[sec]^.name+#0);
  776. if assigned(sects[sec]^.relocsect) then
  777. sects[sec]^.relocsect^.shstridx:=writestr(sects[sec]^.relocsect^.name+#0);
  778. end;
  779. end;
  780. end;
  781. procedure telf32output.writesectionheader(s:pelf32section);
  782. var
  783. sechdr : telf32sechdr;
  784. begin
  785. fillchar(sechdr,sizeof(sechdr),0);
  786. sechdr.sh_name:=s^.shstridx;
  787. sechdr.sh_type:=s^.shtype;
  788. sechdr.sh_flags:=s^.shflags;
  789. sechdr.sh_offset:=s^.datapos;
  790. sechdr.sh_size:=s^.datalen;
  791. sechdr.sh_link:=s^.shlink;
  792. sechdr.sh_info:=s^.shinfo;
  793. sechdr.sh_addralign:=s^.addralign;
  794. sechdr.sh_entsize:=s^.entsize;
  795. writer^.write(sechdr,sizeof(sechdr));
  796. end;
  797. procedure telf32output.writetodisk;
  798. var
  799. header : telf32header;
  800. datapos,
  801. shoffset,
  802. nsects : longint;
  803. hstab : telf32stab;
  804. sec : tsection;
  805. empty : array[0..63] of byte;
  806. hp : pdynamicblock;
  807. begin
  808. { calc amount of sections we have and align sections at 4 bytes }
  809. fillchar(empty,sizeof(empty),0);
  810. nsects:=1;
  811. initsym:=2;
  812. for sec:=low(tsection) to high(tsection) do
  813. if assigned(sects[sec]) then
  814. begin
  815. { each section requires a symbol for relocation }
  816. sects[sec]^.secsymidx:=initsym;
  817. inc(initsym);
  818. { also create the index in the section header table }
  819. sects[sec]^.secshidx:=nsects;
  820. inc(nsects);
  821. if assigned(sects[sec]^.relochead) then
  822. inc(nsects);
  823. end;
  824. { add default sections follows }
  825. shstrtabsect^.secshidx:=nsects;
  826. inc(nsects);
  827. symtabsect^.secshidx:=nsects;
  828. inc(nsects);
  829. strtabsect^.secshidx:=nsects;
  830. inc(nsects);
  831. { Create the relocation sections }
  832. for sec:=low(tsection) to high(tsection) do
  833. if assigned(sects[sec]) and
  834. (sects[sec]^.nrelocs>0) then
  835. createrelocsection(sects[sec]);
  836. { create .symtab }
  837. createsymtab;
  838. { create .shstrtab }
  839. createshstrtab;
  840. { Calculate the filepositions }
  841. datapos:=$40; { elfheader + alignment }
  842. { sections first }
  843. for sec:=low(tsection) to high(tsection) do
  844. if assigned(sects[sec]) then
  845. begin
  846. sects[sec]^.datapos:=datapos;
  847. if assigned(sects[sec]^.data) then
  848. inc(datapos,sects[sec]^.aligneddatalen);
  849. end;
  850. { shstrtab }
  851. shstrtabsect^.datapos:=datapos;
  852. inc(datapos,shstrtabsect^.aligneddatalen);
  853. { section headers }
  854. shoffset:=datapos;
  855. inc(datapos,nsects*sizeof(telf32sechdr));
  856. { symtab }
  857. symtabsect^.datapos:=datapos;
  858. inc(datapos,symtabsect^.aligneddatalen);
  859. { strtab }
  860. strtabsect^.datapos:=datapos;
  861. inc(datapos,align(strtabsect^.datalen,4));
  862. { .rel sections }
  863. for sec:=low(tsection) to high(tsection) do
  864. if assigned(sects[sec]) and
  865. assigned(sects[sec]^.relocsect) then
  866. begin
  867. sects[sec]^.relocsect^.datapos:=datapos;
  868. inc(datapos,sects[sec]^.relocsect^.aligneddatalen);
  869. end;
  870. { Write ELF Header }
  871. fillchar(header,sizeof(header),0);
  872. header.magic0123:=$464c457f; { = #127'ELF' }
  873. header.file_class:=1;
  874. header.data_encoding:=1;
  875. header.file_version:=1;
  876. header.e_type:=1;
  877. header.e_machine:=3;
  878. header.e_version:=1;
  879. header.e_shoff:=shoffset;
  880. header.e_shstrndx:=shstrtabsect^.secshidx;
  881. header.e_shnum:=nsects;
  882. header.e_ehsize:=sizeof(telf32header);
  883. header.e_shentsize:=sizeof(telf32sechdr);
  884. writer^.write(header,sizeof(header));
  885. writer^.write(empty,$40-sizeof(header)); { align }
  886. { Sections }
  887. for sec:=low(tsection) to high(tsection) do
  888. if assigned(sects[sec]) and
  889. assigned(sects[sec]^.data) then
  890. begin
  891. { For the stab section we need an HdrSym which can now be
  892. calculated more easily }
  893. if sec=sec_stab then
  894. begin
  895. hstab.strpos:=1;
  896. hstab.ntype:=0;
  897. hstab.nother:=0;
  898. hstab.ndesc:=(sects[sec_stab]^.datalen div sizeof(telf32stab))-1{+1 according to gas output PM};
  899. hstab.nvalue:=sects[sec_stabstr]^.datalen;
  900. sects[sec_stab]^.data^.seek(0);
  901. sects[sec_stab]^.data^.write(hstab,sizeof(hstab));
  902. end;
  903. sects[sec]^.alignsection;
  904. hp:=sects[sec]^.data^.firstblock;
  905. while assigned(hp) do
  906. begin
  907. writer^.write(hp^.data,hp^.used);
  908. hp:=hp^.next;
  909. end;
  910. end;
  911. { .shstrtab }
  912. shstrtabsect^.alignsection;
  913. hp:=shstrtabsect^.data^.firstblock;
  914. while assigned(hp) do
  915. begin
  916. writer^.write(hp^.data,hp^.used);
  917. hp:=hp^.next;
  918. end;
  919. { section headers, start with an empty header for sh_undef }
  920. writer^.write(empty,sizeof(telf32sechdr));
  921. for sec:=low(tsection) to high(tsection) do
  922. if assigned(sects[sec]) then
  923. begin
  924. writesectionheader(sects[sec]);
  925. if assigned(sects[sec]^.relocsect) then
  926. writesectionheader(sects[sec]^.relocsect);
  927. end;
  928. writesectionheader(shstrtabsect);
  929. writesectionheader(symtabsect);
  930. writesectionheader(strtabsect);
  931. { .symtab }
  932. symtabsect^.alignsection;
  933. hp:=symtabsect^.data^.firstblock;
  934. while assigned(hp) do
  935. begin
  936. writer^.write(hp^.data,hp^.used);
  937. hp:=hp^.next;
  938. end;
  939. { .strtab }
  940. strtabsect^.writealign(4);
  941. hp:=strtabsect^.data^.firstblock;
  942. while assigned(hp) do
  943. begin
  944. writer^.write(hp^.data,hp^.used);
  945. hp:=hp^.next;
  946. end;
  947. { .rel sections }
  948. for sec:=low(tsection) to high(tsection) do
  949. if assigned(sects[sec]) and
  950. assigned(sects[sec]^.relocsect) then
  951. begin
  952. sects[sec]^.relocsect^.alignsection;
  953. hp:=sects[sec]^.relocsect^.data^.firstblock;
  954. while assigned(hp) do
  955. begin
  956. writer^.write(hp^.data,hp^.used);
  957. hp:=hp^.next;
  958. end;
  959. end;
  960. end;
  961. end.
  962. {
  963. $Log$
  964. Revision 1.7 2000-09-24 15:06:20 peter
  965. * use defines.inc
  966. Revision 1.6 2000/08/27 16:11:51 peter
  967. * moved some util functions from globals,cobjects to cutils
  968. * splitted files into finput,fmodule
  969. Revision 1.5 2000/08/19 18:44:27 peter
  970. * new tdynamicarray implementation using blocks instead of
  971. reallocmem (merged)
  972. Revision 1.4 2000/08/12 19:14:58 peter
  973. * ELF writer works now also with -g
  974. * ELF writer is default again for linux
  975. Revision 1.3 2000/07/13 12:08:26 michael
  976. + patched to 1.1.0 with former 1.09patch from peter
  977. Revision 1.2 2000/07/13 11:32:43 michael
  978. + removed logs
  979. }