og386elf.pas 32 KB

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