og386elf.pas 31 KB

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