og386elf.pas 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083
  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. if assigned(relocsect) then
  296. dispose(relocsect,done);
  297. end;
  298. function telf32section.write(var d;l:longint):longint;
  299. begin
  300. write:=datalen;
  301. if not assigned(Data) then
  302. Internalerror(3334441);
  303. Data^.write(d,l);
  304. inc(datalen,l);
  305. end;
  306. function telf32section.writestr(const s:string):longint;
  307. begin
  308. writestr:=datalen;
  309. if not assigned(Data) then
  310. Internalerror(3334441);
  311. Data^.write(s[1],length(s));
  312. inc(datalen,length(s));
  313. end;
  314. procedure telf32section.writealign(l:longint);
  315. var
  316. i : longint;
  317. empty : array[0..63] of char;
  318. begin
  319. { no alignment needed for 0 or 1 }
  320. if l<=1 then
  321. exit;
  322. i:=datalen mod l;
  323. if i>0 then
  324. begin
  325. if assigned(data) then
  326. begin
  327. fillchar(empty,sizeof(empty),0);
  328. data^.write(empty,l-i);
  329. end;
  330. inc(datalen,l-i);
  331. end;
  332. end;
  333. function telf32section.aligneddatalen:longint;
  334. begin
  335. aligneddatalen:=align(datalen,addralign);
  336. end;
  337. procedure telf32section.alignsection;
  338. begin
  339. writealign(addralign);
  340. end;
  341. procedure telf32section.alloc(l:longint);
  342. begin
  343. if assigned(Data) then
  344. Internalerror(3334442);
  345. inc(datalen,l);
  346. end;
  347. procedure telf32section.addsymreloc(ofs:longint;p:pasmsymbol;relative:relative_type);
  348. var
  349. r : PReloc;
  350. begin
  351. new(r);
  352. reloctail^:=r;
  353. reloctail:=@r^.next;
  354. r^.next:=nil;
  355. r^.address:=ofs;
  356. r^.symbol:=p;
  357. r^.section:=sec_none;
  358. r^.typ:=relative;
  359. inc(nrelocs);
  360. end;
  361. procedure telf32section.addsectionreloc(ofs:longint;sec:tsection;relative:relative_type);
  362. var
  363. r : PReloc;
  364. begin
  365. new(r);
  366. reloctail^:=r;
  367. reloctail:=@r^.next;
  368. r^.next:=nil;
  369. r^.address:=ofs;
  370. r^.symbol:=nil;
  371. r^.section:=sec;
  372. r^.typ:=relative;
  373. inc(nrelocs);
  374. end;
  375. {****************************************************************************
  376. TElf32Output
  377. ****************************************************************************}
  378. constructor telf32output.init(smart:boolean);
  379. begin
  380. inherited init(smart);
  381. end;
  382. destructor telf32output.done;
  383. begin
  384. inherited done;
  385. end;
  386. procedure telf32output.initwriting(Aplace:tcutplace);
  387. var
  388. s : string;
  389. begin
  390. inherited initwriting(Aplace);
  391. { reset }
  392. initsym:=0;
  393. new(syms,init(symbolresize));
  394. FillChar(Sects,sizeof(Sects),0);
  395. { default sections }
  396. new(symtabsect,initname('.symtab',2,0,0,0,4,16));
  397. new(strtabsect,initname('.strtab',3,0,0,0,1,0));
  398. new(shstrtabsect,initname('.shstrtab',3,0,0,0,1,0));
  399. { insert the empty and filename as first in strtab }
  400. strtabsect^.writestr(#0);
  401. strtabsect^.writestr(SplitFileName(current_module^.mainsource^)+#0);
  402. { we need at least the following sections }
  403. createsection(sec_code);
  404. createsection(sec_data);
  405. createsection(sec_bss);
  406. { create stabs sections if debugging }
  407. if (cs_debuginfo in aktmoduleswitches) then
  408. begin
  409. createsection(sec_stab);
  410. createsection(sec_stabstr);
  411. writestabs(sec_none,0,nil,0,0,0,false);
  412. { write zero pchar and name together (PM) }
  413. s:=#0+SplitFileName(current_module^.mainsource^)+#0;
  414. sects[sec_stabstr]^.write(s[1],length(s));
  415. end;
  416. end;
  417. procedure telf32output.donewriting;
  418. var
  419. sec : tsection;
  420. begin
  421. writetodisk;
  422. { free memory }
  423. dispose(syms,done);
  424. dispose(symtabsect,done);
  425. dispose(strtabsect,done);
  426. dispose(shstrtabsect,done);
  427. for sec:=low(tsection) to high(tsection) do
  428. if assigned(sects[sec]) then
  429. dispose(sects[sec],done);
  430. inherited donewriting;
  431. end;
  432. function telf32output.sectionsize(s:tsection):longint;
  433. begin
  434. if assigned(sects[s]) then
  435. sectionsize:=sects[s]^.datalen
  436. else
  437. sectionsize:=0;
  438. end;
  439. procedure telf32output.createsection(sec:tsection);
  440. begin
  441. sects[sec]:=new(pelf32Section,init(Sec));
  442. end;
  443. procedure telf32output.writesymbol(p:pasmsymbol);
  444. var
  445. sym : tsymbol;
  446. begin
  447. { already written ? }
  448. if p^.idx<>-1 then
  449. exit;
  450. { be sure that the section will exists }
  451. if (p^.section<>sec_none) and not(assigned(sects[p^.section])) then
  452. createsection(p^.section);
  453. FillChar(sym,sizeof(sym),0);
  454. sym.size:=p^.size;
  455. sym.bind:=p^.bind;
  456. sym.typ:=p^.typ;
  457. { if local of global then set the section value to the address
  458. of the symbol }
  459. case sym.bind of
  460. AB_LOCAL,
  461. AB_GLOBAL :
  462. begin
  463. sym.section:=p^.section;
  464. sym.value:=p^.address;
  465. end;
  466. AB_COMMON :
  467. begin
  468. sym.value:=$10;
  469. end;
  470. end;
  471. { update the asmsymbol index }
  472. p^.idx:=syms^.size div sizeof(tsymbol);
  473. { store the symbol, but not the local ones (PM) }
  474. if (sym.bind<>AB_LOCAL) then
  475. begin
  476. { symbolname, write the #0 separate to overcome 255+1 char not possible }
  477. sym.name:=strtabsect^.writestr(p^.name);
  478. strtabsect^.writestr(#0);
  479. { symbol }
  480. syms^.write(sym,sizeof(tsymbol));
  481. end;
  482. { make the exported syms known to the objectwriter
  483. (needed for .a generation) }
  484. if (sym.bind in [AB_GLOBAL,AB_COMMON]) then
  485. writer^.writesym(p^.name);
  486. end;
  487. procedure telf32output.writebytes(var data;len:longint);
  488. begin
  489. if not assigned(sects[currsec]) then
  490. createsection(currsec);
  491. sects[currsec]^.write(data,len);
  492. end;
  493. procedure telf32output.writealloc(len:longint);
  494. begin
  495. if not assigned(sects[currsec]) then
  496. createsection(currsec);
  497. sects[currsec]^.alloc(len);
  498. end;
  499. procedure telf32output.writealign(len:longint);
  500. var
  501. modulo : longint;
  502. begin
  503. if not assigned(sects[currsec]) then
  504. createsection(currsec);
  505. modulo:=sects[currsec]^.datalen mod len;
  506. if modulo > 0 then
  507. sects[currsec]^.alloc(len-modulo);
  508. end;
  509. procedure telf32output.writereloc(data,len:longint;p:pasmsymbol;relative:relative_type);
  510. var
  511. symaddr : longint;
  512. begin
  513. if not assigned(sects[currsec]) then
  514. createsection(currsec);
  515. if assigned(p) then
  516. begin
  517. { real address of the symbol }
  518. symaddr:=p^.address;
  519. { no symbol relocation need inside a section }
  520. if p^.section=currsec then
  521. begin
  522. case relative of
  523. relative_false :
  524. begin
  525. sects[currsec]^.addsectionreloc(sects[currsec]^.datalen,currsec,relative_false);
  526. inc(data,symaddr);
  527. end;
  528. relative_true :
  529. begin
  530. inc(data,symaddr-len-sects[currsec]^.datalen);
  531. end;
  532. relative_rva :
  533. internalerror(3219583);
  534. end;
  535. end
  536. else
  537. begin
  538. writesymbol(p);
  539. if (p^.section<>sec_none) and (relative<>relative_true) then
  540. begin
  541. sects[currsec]^.addsectionreloc(sects[currsec]^.datalen,p^.section,relative);
  542. inc(data,symaddr);
  543. end
  544. else
  545. sects[currsec]^.addsymreloc(sects[currsec]^.datalen,p,relative);
  546. if relative=relative_true then
  547. begin
  548. if p^.bind=AB_EXTERNAL then
  549. dec(data,len)
  550. else
  551. dec(data,len+sects[currsec]^.datalen);
  552. end;
  553. end;
  554. end;
  555. sects[currsec]^.write(data,len);
  556. end;
  557. procedure telf32output.writestabs(section:tsection;offset:longint;p:pchar;nidx,nother,line:longint;reloc : boolean);
  558. var
  559. stab : telf32stab;
  560. s : tsection;
  561. begin
  562. s:=section;
  563. if reloc then
  564. begin
  565. if (offset=-1) then
  566. begin
  567. if s=sec_none then
  568. offset:=0
  569. else
  570. offset:=sects[s]^.datalen;
  571. end;
  572. end;
  573. fillchar(stab,sizeof(telf32stab),0);
  574. if assigned(p) and (p[0]<>#0) then
  575. begin
  576. stab.strpos:=sects[sec_stabstr]^.datalen;
  577. sects[sec_stabstr]^.write(p^,strlen(p)+1);
  578. end;
  579. stab.ntype:=nidx;
  580. stab.ndesc:=line;
  581. stab.nother:=nother;
  582. stab.nvalue:=offset;
  583. sects[sec_stab]^.write(stab,sizeof(stab));
  584. { when the offset is not 0 then write a relocation, take also the
  585. hdrstab into account with the offset }
  586. if reloc then
  587. sects[sec_stab]^.addsectionreloc(sects[sec_stab]^.datalen-4,s,relative_false);
  588. end;
  589. procedure telf32output.writesymstabs(section:tsection;offset:longint;p:pchar;ps:pasmsymbol;
  590. nidx,nother,line:longint;reloc:boolean);
  591. var
  592. stab : telf32stab;
  593. s : tsection;
  594. begin
  595. s:=section;
  596. if reloc then
  597. begin
  598. if (offset=-1) then
  599. begin
  600. if s=sec_none then
  601. offset:=0
  602. else
  603. offset:=sects[s]^.datalen;
  604. end;
  605. end;
  606. fillchar(stab,sizeof(telf32stab),0);
  607. if assigned(p) and (p[0]<>#0) then
  608. begin
  609. stab.strpos:=sects[sec_stabstr]^.datalen;
  610. sects[sec_stabstr]^.write(p^,strlen(p)+1);
  611. end;
  612. stab.ntype:=nidx;
  613. stab.ndesc:=line;
  614. stab.nother:=nother;
  615. stab.nvalue:=offset;
  616. sects[sec_stab]^.write(stab,sizeof(stab));
  617. { when the offset is not 0 then write a relocation, take also the
  618. hdrstab into account with the offset }
  619. if reloc then
  620. sects[sec_stab]^.addsymreloc(sects[sec_stab]^.datalen-4,ps,relative_false);
  621. end;
  622. procedure telf32output.setsectionsizes(var s:tsecsize);
  623. var
  624. align : longint;
  625. sec : tsection;
  626. begin
  627. { multiply stab with real size }
  628. s[sec_stab]:=s[sec_stab]*sizeof(telf32stab);
  629. { if debug then also count header stab }
  630. if (cs_debuginfo in aktmoduleswitches) then
  631. begin
  632. inc(s[sec_stab],sizeof(telf32stab));
  633. inc(s[sec_stabstr],length(SplitFileName(current_module^.mainsource^))+2);
  634. end;
  635. { fix all section }
  636. for sec:=low(tsection) to high(tsection) do
  637. begin
  638. if (s[sec]>0) and (not assigned(sects[sec])) then
  639. createsection(sec);
  640. if assigned(sects[sec]) then
  641. begin
  642. sects[sec]^.size:=s[sec];
  643. { calculate the alignment }
  644. align:=sects[sec]^.addralign;
  645. sects[sec]^.fillsize:=align-(sects[sec]^.size and (align-1));
  646. if sects[sec]^.fillsize=align then
  647. sects[sec]^.fillsize:=0;
  648. end;
  649. end;
  650. end;
  651. {***********************************************
  652. Writing to disk
  653. ***********************************************}
  654. procedure telf32output.createrelocsection(s:pelf32section);
  655. var
  656. rel : telf32reloc;
  657. hr,r : preloc;
  658. relsym,reltyp : longint;
  659. begin
  660. { create the reloc section }
  661. new(s^.relocsect,initname('.rel'+s^.name,9,0,symtabsect^.secshidx,s^.secshidx,4,8));
  662. { add the relocations }
  663. r:=s^.relochead;
  664. while assigned(r) do
  665. begin
  666. rel.address:=r^.address;
  667. if assigned(r^.symbol) then
  668. begin
  669. if (r^.symbol^.bind=AB_LOCAL) then
  670. relsym:=sects[r^.symbol^.section]^.secsymidx
  671. else
  672. begin
  673. if r^.symbol^.idx=-1 then
  674. internalerror(4321);
  675. relsym:=(r^.symbol^.idx+initsym);
  676. end;
  677. end
  678. else
  679. if r^.section<>sec_none then
  680. relsym:=sects[r^.section]^.secsymidx
  681. else
  682. relsym:=SHN_UNDEF;
  683. case r^.typ of
  684. relative_true :
  685. reltyp:=R_386_PC32;
  686. relative_false :
  687. reltyp:=R_386_32;
  688. end;
  689. rel.info:=(relsym shl 8) or reltyp;
  690. { write reloc }
  691. s^.relocsect^.write(rel,sizeof(rel));
  692. { goto next and dispose this reloc }
  693. hr:=r;
  694. r:=r^.next;
  695. dispose(hr);
  696. end;
  697. end;
  698. procedure telf32output.createsymtab;
  699. var
  700. elfsym : telf32symbol;
  701. sym : tsymbol;
  702. sec : tsection;
  703. locals,
  704. i : longint;
  705. begin
  706. locals:=2;
  707. { empty entry }
  708. fillchar(elfsym,sizeof(elfsym),0);
  709. symtabsect^.write(elfsym,sizeof(elfsym));
  710. { filename entry }
  711. elfsym.st_name:=1;
  712. elfsym.st_info:=STT_FILE;
  713. elfsym.st_shndx:=SHN_ABS;
  714. symtabsect^.write(elfsym,sizeof(elfsym));
  715. { section }
  716. for sec:=low(tsection) to high(tsection) do
  717. if assigned(sects[sec]) then
  718. begin
  719. fillchar(elfsym,sizeof(elfsym),0);
  720. elfsym.st_name:=sects[sec]^.shstridx;
  721. elfsym.st_info:=STT_SECTION;
  722. elfsym.st_shndx:=sects[sec]^.secshidx;
  723. symtabsect^.write(elfsym,sizeof(elfsym));
  724. inc(locals);
  725. end;
  726. { symbols }
  727. syms^.seek(0);
  728. for i:=1 to (syms^.size div sizeof(TSymbol)) do
  729. begin
  730. syms^.read(sym,sizeof(TSymbol));
  731. fillchar(elfsym,sizeof(elfsym),0);
  732. elfsym.st_name:=sym.name;
  733. elfsym.st_value:=sym.value;
  734. elfsym.st_size:=sym.size;
  735. case sym.bind of
  736. AB_LOCAL :
  737. begin
  738. elfsym.st_info:=STB_LOCAL shl 4;
  739. inc(locals);
  740. end;
  741. AB_COMMON,
  742. AB_EXTERNAL,
  743. AB_GLOBAL :
  744. elfsym.st_info:=STB_GLOBAL shl 4;
  745. end;
  746. if sym.bind<>AB_EXTERNAL then
  747. begin
  748. case sym.typ of
  749. AT_FUNCTION :
  750. elfsym.st_info:=elfsym.st_info or STT_FUNC;
  751. AT_DATA :
  752. elfsym.st_info:=elfsym.st_info or STT_OBJECT;
  753. end;
  754. end;
  755. if sym.bind=AB_COMMON then
  756. elfsym.st_shndx:=SHN_COMMON
  757. else
  758. if assigned(sects[sym.section]) then
  759. elfsym.st_shndx:=sects[sym.section]^.secshidx
  760. else
  761. elfsym.st_shndx:=SHN_UNDEF;
  762. symtabsect^.write(elfsym,sizeof(elfsym));
  763. end;
  764. { update the .symtab section header }
  765. symtabsect^.shlink:=strtabsect^.secshidx;
  766. symtabsect^.shinfo:=locals;
  767. end;
  768. procedure telf32output.createshstrtab;
  769. var
  770. sec : tsection;
  771. begin
  772. with shstrtabsect^ do
  773. begin
  774. writestr(#0);
  775. symtabsect^.shstridx:=writestr('.symtab'#0);
  776. strtabsect^.shstridx:=writestr('.strtab'#0);
  777. shstrtabsect^.shstridx:=writestr('.shstrtab'#0);
  778. for sec:=low(tsection) to high(tsection) do
  779. if assigned(sects[sec]) then
  780. begin
  781. sects[sec]^.shstridx:=writestr(sects[sec]^.name+#0);
  782. if assigned(sects[sec]^.relocsect) then
  783. sects[sec]^.relocsect^.shstridx:=writestr(sects[sec]^.relocsect^.name+#0);
  784. end;
  785. end;
  786. end;
  787. procedure telf32output.writesectionheader(s:pelf32section);
  788. var
  789. sechdr : telf32sechdr;
  790. begin
  791. fillchar(sechdr,sizeof(sechdr),0);
  792. sechdr.sh_name:=s^.shstridx;
  793. sechdr.sh_type:=s^.shtype;
  794. sechdr.sh_flags:=s^.shflags;
  795. sechdr.sh_offset:=s^.datapos;
  796. sechdr.sh_size:=s^.datalen;
  797. sechdr.sh_link:=s^.shlink;
  798. sechdr.sh_info:=s^.shinfo;
  799. sechdr.sh_addralign:=s^.addralign;
  800. sechdr.sh_entsize:=s^.entsize;
  801. writer^.write(sechdr,sizeof(sechdr));
  802. end;
  803. procedure telf32output.writetodisk;
  804. var
  805. header : telf32header;
  806. datapos,
  807. shoffset,
  808. nsects : longint;
  809. hstab : telf32stab;
  810. sec : tsection;
  811. empty : array[0..63] of byte;
  812. hp : pdynamicblock;
  813. begin
  814. { calc amount of sections we have and align sections at 4 bytes }
  815. fillchar(empty,sizeof(empty),0);
  816. nsects:=1;
  817. initsym:=2;
  818. for sec:=low(tsection) to high(tsection) do
  819. if assigned(sects[sec]) then
  820. begin
  821. { each section requires a symbol for relocation }
  822. sects[sec]^.secsymidx:=initsym;
  823. inc(initsym);
  824. { also create the index in the section header table }
  825. sects[sec]^.secshidx:=nsects;
  826. inc(nsects);
  827. if assigned(sects[sec]^.relochead) then
  828. inc(nsects);
  829. end;
  830. { add default sections follows }
  831. shstrtabsect^.secshidx:=nsects;
  832. inc(nsects);
  833. symtabsect^.secshidx:=nsects;
  834. inc(nsects);
  835. strtabsect^.secshidx:=nsects;
  836. inc(nsects);
  837. { Create the relocation sections }
  838. for sec:=low(tsection) to high(tsection) do
  839. if assigned(sects[sec]) and
  840. (sects[sec]^.nrelocs>0) then
  841. createrelocsection(sects[sec]);
  842. { create .symtab }
  843. createsymtab;
  844. { create .shstrtab }
  845. createshstrtab;
  846. { Calculate the filepositions }
  847. datapos:=$40; { elfheader + alignment }
  848. { sections first }
  849. for sec:=low(tsection) to high(tsection) do
  850. if assigned(sects[sec]) then
  851. begin
  852. sects[sec]^.datapos:=datapos;
  853. if assigned(sects[sec]^.data) then
  854. inc(datapos,sects[sec]^.aligneddatalen);
  855. end;
  856. { shstrtab }
  857. shstrtabsect^.datapos:=datapos;
  858. inc(datapos,shstrtabsect^.aligneddatalen);
  859. { section headers }
  860. shoffset:=datapos;
  861. inc(datapos,nsects*sizeof(telf32sechdr));
  862. { symtab }
  863. symtabsect^.datapos:=datapos;
  864. inc(datapos,symtabsect^.aligneddatalen);
  865. { strtab }
  866. strtabsect^.datapos:=datapos;
  867. inc(datapos,align(strtabsect^.datalen,4));
  868. { .rel sections }
  869. for sec:=low(tsection) to high(tsection) do
  870. if assigned(sects[sec]) and
  871. assigned(sects[sec]^.relocsect) then
  872. begin
  873. sects[sec]^.relocsect^.datapos:=datapos;
  874. inc(datapos,sects[sec]^.relocsect^.aligneddatalen);
  875. end;
  876. { Write ELF Header }
  877. fillchar(header,sizeof(header),0);
  878. header.magic0123:=$464c457f; { = #127'ELF' }
  879. header.file_class:=1;
  880. header.data_encoding:=1;
  881. header.file_version:=1;
  882. header.e_type:=1;
  883. header.e_machine:=3;
  884. header.e_version:=1;
  885. header.e_shoff:=shoffset;
  886. header.e_shstrndx:=shstrtabsect^.secshidx;
  887. header.e_shnum:=nsects;
  888. header.e_ehsize:=sizeof(telf32header);
  889. header.e_shentsize:=sizeof(telf32sechdr);
  890. writer^.write(header,sizeof(header));
  891. writer^.write(empty,$40-sizeof(header)); { align }
  892. { Sections }
  893. for sec:=low(tsection) to high(tsection) do
  894. if assigned(sects[sec]) and
  895. assigned(sects[sec]^.data) then
  896. begin
  897. { For the stab section we need an HdrSym which can now be
  898. calculated more easily }
  899. if sec=sec_stab then
  900. begin
  901. hstab.strpos:=1;
  902. hstab.ntype:=0;
  903. hstab.nother:=0;
  904. hstab.ndesc:=(sects[sec_stab]^.datalen div sizeof(telf32stab))-1{+1 according to gas output PM};
  905. hstab.nvalue:=sects[sec_stabstr]^.datalen;
  906. sects[sec_stab]^.data^.seek(0);
  907. sects[sec_stab]^.data^.write(hstab,sizeof(hstab));
  908. end;
  909. sects[sec]^.alignsection;
  910. hp:=sects[sec]^.data^.firstblock;
  911. while assigned(hp) do
  912. begin
  913. writer^.write(hp^.data,hp^.used);
  914. hp:=hp^.next;
  915. end;
  916. end;
  917. { .shstrtab }
  918. shstrtabsect^.alignsection;
  919. hp:=shstrtabsect^.data^.firstblock;
  920. while assigned(hp) do
  921. begin
  922. writer^.write(hp^.data,hp^.used);
  923. hp:=hp^.next;
  924. end;
  925. { section headers, start with an empty header for sh_undef }
  926. writer^.write(empty,sizeof(telf32sechdr));
  927. for sec:=low(tsection) to high(tsection) do
  928. if assigned(sects[sec]) then
  929. begin
  930. writesectionheader(sects[sec]);
  931. if assigned(sects[sec]^.relocsect) then
  932. writesectionheader(sects[sec]^.relocsect);
  933. end;
  934. writesectionheader(shstrtabsect);
  935. writesectionheader(symtabsect);
  936. writesectionheader(strtabsect);
  937. { .symtab }
  938. symtabsect^.alignsection;
  939. hp:=symtabsect^.data^.firstblock;
  940. while assigned(hp) do
  941. begin
  942. writer^.write(hp^.data,hp^.used);
  943. hp:=hp^.next;
  944. end;
  945. { .strtab }
  946. strtabsect^.writealign(4);
  947. hp:=strtabsect^.data^.firstblock;
  948. while assigned(hp) do
  949. begin
  950. writer^.write(hp^.data,hp^.used);
  951. hp:=hp^.next;
  952. end;
  953. { .rel sections }
  954. for sec:=low(tsection) to high(tsection) do
  955. if assigned(sects[sec]) and
  956. assigned(sects[sec]^.relocsect) then
  957. begin
  958. sects[sec]^.relocsect^.alignsection;
  959. hp:=sects[sec]^.relocsect^.data^.firstblock;
  960. while assigned(hp) do
  961. begin
  962. writer^.write(hp^.data,hp^.used);
  963. hp:=hp^.next;
  964. end;
  965. end;
  966. end;
  967. end.
  968. {
  969. $Log$
  970. Revision 1.8 2000-10-14 21:52:55 peter
  971. * fixed memory leaks
  972. Revision 1.7 2000/09/24 15:06:20 peter
  973. * use defines.inc
  974. Revision 1.6 2000/08/27 16:11:51 peter
  975. * moved some util functions from globals,cobjects to cutils
  976. * splitted files into finput,fmodule
  977. Revision 1.5 2000/08/19 18:44:27 peter
  978. * new tdynamicarray implementation using blocks instead of
  979. reallocmem (merged)
  980. Revision 1.4 2000/08/12 19:14:58 peter
  981. * ELF writer works now also with -g
  982. * ELF writer is default again for linux
  983. Revision 1.3 2000/07/13 12:08:26 michael
  984. + patched to 1.1.0 with former 1.09patch from peter
  985. Revision 1.2 2000/07/13 11:32:43 michael
  986. + removed logs
  987. }