og386cff.pas 33 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Peter Vreman and Pierre Muller
  4. Contains the 386 binary coff 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 og386cff;
  22. {
  23. Notes on COFF:
  24. (0) When I say `standard COFF' below, I mean `COFF as output and
  25. used by DJGPP'. I assume DJGPP gets it right.
  26. (1) Win32 appears to interpret the term `relative relocation'
  27. differently from standard COFF. Standard COFF understands a
  28. relative relocation to mean that during relocation you add the
  29. address of the symbol you're referencing, and subtract the base
  30. address of the section you're in. Win32 COFF, by contrast, seems
  31. to add the address of the symbol and then subtract the address
  32. of THE BYTE AFTER THE RELOCATED DWORD. Hence the two formats are
  33. subtly incompatible.
  34. (2) Win32 doesn't bother putting any flags in the header flags
  35. field (at offset 0x12 into the file).
  36. (3) Win32 uses some extra flags into the section header table:
  37. it defines flags 0x80000000 (writable), 0x40000000 (readable)
  38. and 0x20000000 (executable), and uses them in the expected
  39. combinations. It also defines 0x00100000 through 0x00700000 for
  40. section alignments of 1 through 64 bytes.
  41. (4) Both standard COFF and Win32 COFF seem to use the DWORD
  42. field directly after the section name in the section header
  43. table for something strange: they store what the address of the
  44. section start point _would_ be, if you laid all the sections end
  45. to end starting at zero. Dunno why. Microsoft's documentation
  46. lists this field as "Virtual Size of Section", which doesn't
  47. seem to fit at all. In fact, Win32 even includes non-linked
  48. sections such as .drectve in this calculation.
  49. (5) Standard COFF does something very strange to common
  50. variables: the relocation point for a common variable is as far
  51. _before_ the variable as its size stretches out _after_ it. So
  52. we must fix up common variable references. Win32 seems to be
  53. sensible on this one.
  54. }
  55. interface
  56. uses
  57. cobjects,
  58. systems,cpubase,aasm,og386;
  59. type
  60. preloc = ^treloc;
  61. treloc = packed record
  62. next : preloc;
  63. address : longint;
  64. symbol : pasmsymbol;
  65. section : tsection; { only used if symbol=nil }
  66. relative : relative_type;
  67. end;
  68. psymbol = ^tsymbol;
  69. tsymbol = packed record
  70. name : string[8];
  71. strpos : longint;
  72. section : tsection;
  73. value : longint;
  74. typ : TAsmsymbind;
  75. end;
  76. pcoffsection = ^tcoffsection;
  77. tcoffsection = object
  78. index : tsection;
  79. secsymidx : longint; { index for the section in symtab }
  80. data : PDynamicArray;
  81. size,
  82. fillsize,
  83. mempos,
  84. len,
  85. datapos,
  86. relocpos,
  87. nrelocs,
  88. align,
  89. flags : longint;
  90. relochead : PReloc;
  91. reloctail : ^PReloc;
  92. constructor init(sec:TSection;Aflags:longint);
  93. destructor done;
  94. procedure write(var d;l:longint);
  95. procedure alloc(l:longint);
  96. procedure addsymreloc(ofs:longint;p:pasmsymbol;relative:relative_type);
  97. procedure addsectionreloc(ofs:longint;sec:tsection;relative:relative_type);
  98. end;
  99. pgenericcoffoutput = ^tgenericcoffoutput;
  100. tgenericcoffoutput = object(tobjectoutput)
  101. win32 : boolean;
  102. sects : array[TSection] of PCoffSection;
  103. strs,
  104. syms : Pdynamicarray;
  105. initsym : longint;
  106. constructor init(smart:boolean);
  107. destructor done;virtual;
  108. procedure initwriting(Aplace:tcutplace);virtual;
  109. procedure donewriting;virtual;
  110. function sectionsize(s:tsection):longint;virtual;
  111. procedure setsectionsizes(var s:tsecsize);virtual;
  112. procedure writebytes(var data;len:longint);virtual;
  113. procedure writealloc(len:longint);virtual;
  114. procedure writealign(len:longint);virtual;
  115. procedure writereloc(data,len:longint;p:pasmsymbol;relative:relative_type);virtual;
  116. procedure writesymbol(p:pasmsymbol);virtual;
  117. procedure writestabs(section:tsection;offset:longint;p:pchar;nidx,nother,line:longint;reloc:boolean);virtual;
  118. procedure writesymstabs(section:tsection;offset:longint;p:pchar;ps:pasmsymbol;
  119. nidx,nother,line:longint;reloc:boolean);virtual;
  120. function text_flags : longint;virtual;
  121. function data_flags : longint;virtual;
  122. function bss_flags : longint;virtual;
  123. function idata_flags : longint;virtual;
  124. function edata_flags : longint;virtual;
  125. private
  126. procedure createsection(sec:tsection);
  127. procedure write_relocs(s:pcoffsection);
  128. procedure write_symbol(const name:string;strpos,value,section,typ,aux:longint);
  129. procedure write_symbols;
  130. procedure writetodisk;
  131. end;
  132. pdjgppcoffoutput = ^tdjgppcoffoutput;
  133. tdjgppcoffoutput = object(tgenericcoffoutput)
  134. constructor init(smart:boolean);
  135. function text_flags : longint;virtual;
  136. function data_flags : longint;virtual;
  137. function bss_flags : longint;virtual;
  138. end;
  139. pwin32coffoutput = ^twin32coffoutput;
  140. twin32coffoutput = object(tgenericcoffoutput)
  141. constructor init(smart:boolean);
  142. function text_flags : longint;virtual;
  143. function data_flags : longint;virtual;
  144. function bss_flags : longint;virtual;
  145. function idata_flags : longint;virtual;
  146. function edata_flags : longint;virtual;
  147. end;
  148. implementation
  149. uses
  150. cutils,strings,verbose,
  151. globtype,globals,fmodule;
  152. const
  153. {$ifdef TP}
  154. symbolresize = 20*18;
  155. strsresize = 256;
  156. DataResize = 1024;
  157. {$else}
  158. symbolresize = 200*18;
  159. strsresize = 8192;
  160. DataResize = 8192;
  161. {$endif}
  162. type
  163. { Structures which are written directly to the output file }
  164. coffheader=packed record
  165. mach : word;
  166. nsects : word;
  167. time : longint;
  168. sympos : longint;
  169. syms : longint;
  170. opthdr : word;
  171. flag : word;
  172. end;
  173. coffsechdr=packed record
  174. name : array[0..7] of char;
  175. vsize : longint;
  176. rvaofs : longint;
  177. datalen : longint;
  178. datapos : longint;
  179. relocpos : longint;
  180. lineno1 : longint;
  181. nrelocs : word;
  182. lineno2 : word;
  183. flags : longint;
  184. end;
  185. coffsectionrec=packed record
  186. len : longint;
  187. nrelocs : word;
  188. empty : array[0..11] of char;
  189. end;
  190. coffreloc=packed record
  191. address : longint;
  192. sym : longint;
  193. relative : word;
  194. end;
  195. coffsymbol=packed record
  196. name : array[0..3] of char; { real is [0..7], which overlaps the strpos ! }
  197. strpos : longint;
  198. value : longint;
  199. section : integer;
  200. empty : integer;
  201. typ : byte;
  202. aux : byte;
  203. end;
  204. pcoffstab=^coffstab;
  205. coffstab=packed record
  206. strpos : longint;
  207. ntype : byte;
  208. nother : byte;
  209. ndesc : word;
  210. nvalue : longint;
  211. end;
  212. {****************************************************************************
  213. TSection
  214. ****************************************************************************}
  215. constructor tcoffsection.init(sec:TSection;Aflags:longint);
  216. begin
  217. index:=sec;
  218. secsymidx:=0;
  219. flags:=AFlags;
  220. { alignment after section }
  221. case sec of
  222. sec_code,
  223. sec_data,
  224. sec_bss :
  225. align:=4;
  226. else
  227. align:=1;
  228. end;
  229. { filled after pass 1 }
  230. size:=0;
  231. fillsize:=0;
  232. mempos:=0;
  233. { pass 2 data }
  234. relocHead:=nil;
  235. relocTail:=@relocHead;
  236. Len:=0;
  237. NRelocs:=0;
  238. if sec=sec_bss then
  239. data:=nil
  240. else
  241. new(Data,Init(DataResize));
  242. end;
  243. destructor tcoffsection.done;
  244. begin
  245. if assigned(Data) then
  246. dispose(Data,done);
  247. end;
  248. procedure tcoffsection.write(var d;l:longint);
  249. begin
  250. if not assigned(Data) then
  251. Internalerror(3334441);
  252. Data^.write(d,l);
  253. inc(len,l);
  254. end;
  255. procedure tcoffsection.alloc(l:longint);
  256. begin
  257. if assigned(Data) then
  258. Internalerror(3334442);
  259. inc(len,l);
  260. end;
  261. procedure tcoffsection.addsymreloc(ofs:longint;p:pasmsymbol;relative:relative_type);
  262. var
  263. r : PReloc;
  264. begin
  265. new(r);
  266. reloctail^:=r;
  267. reloctail:=@r^.next;
  268. r^.next:=nil;
  269. r^.address:=ofs+mempos;
  270. r^.symbol:=p;
  271. r^.section:=sec_none;
  272. r^.relative:=relative;
  273. inc(nrelocs);
  274. end;
  275. procedure tcoffsection.addsectionreloc(ofs:longint;sec:tsection;relative:relative_type);
  276. var
  277. r : PReloc;
  278. begin
  279. new(r);
  280. reloctail^:=r;
  281. reloctail:=@r^.next;
  282. r^.next:=nil;
  283. r^.address:=ofs+mempos;
  284. r^.symbol:=nil;
  285. r^.section:=sec;
  286. r^.relative:=relative;
  287. inc(nrelocs);
  288. end;
  289. {****************************************************************************
  290. Genericcoffoutput
  291. ****************************************************************************}
  292. constructor tgenericcoffoutput.init(smart:boolean);
  293. begin
  294. inherited init(smart);
  295. end;
  296. destructor tgenericcoffoutput.done;
  297. begin
  298. inherited done;
  299. end;
  300. procedure tgenericcoffoutput.initwriting(Aplace:tcutplace);
  301. var
  302. s : string;
  303. begin
  304. inherited initwriting(Aplace);
  305. { reset }
  306. initsym:=0;
  307. new(syms,init(symbolresize));
  308. new(strs,init(strsresize));
  309. FillChar(Sects,sizeof(Sects),0);
  310. { we need at least the following 3 sections }
  311. createsection(sec_code);
  312. createsection(sec_data);
  313. createsection(sec_bss);
  314. if (cs_gdb_lineinfo in aktglobalswitches) or
  315. (cs_debuginfo in aktmoduleswitches) then
  316. begin
  317. createsection(sec_stab);
  318. createsection(sec_stabstr);
  319. writestabs(sec_none,0,nil,0,0,0,false);
  320. { write zero pchar and name together (PM) }
  321. s:=#0+SplitFileName(current_module^.mainsource^)+#0;
  322. sects[sec_stabstr]^.write(s[1],length(s));
  323. end;
  324. end;
  325. procedure tgenericcoffoutput.donewriting;
  326. var
  327. sec : tsection;
  328. begin
  329. { Only write the .o if there are no errors }
  330. if errorcount=0 then
  331. writetodisk;
  332. dispose(syms,done);
  333. dispose(strs,done);
  334. for sec:=low(tsection) to high(tsection) do
  335. if assigned(sects[sec]) then
  336. dispose(sects[sec],done);
  337. inherited donewriting;
  338. end;
  339. function tgenericcoffoutput.sectionsize(s:tsection):longint;
  340. begin
  341. if assigned(sects[s]) then
  342. sectionsize:=sects[s]^.len
  343. else
  344. sectionsize:=0;
  345. end;
  346. function tgenericcoffoutput.text_flags : longint;
  347. begin
  348. text_flags:=0;
  349. end;
  350. function tgenericcoffoutput.data_flags : longint;
  351. begin
  352. data_flags:=0;
  353. end;
  354. function tgenericcoffoutput.bss_flags : longint;
  355. begin
  356. bss_flags:=0;
  357. end;
  358. function tgenericcoffoutput.edata_flags : longint;
  359. begin
  360. edata_flags:=0;
  361. end;
  362. function tgenericcoffoutput.idata_flags : longint;
  363. begin
  364. idata_flags:=0;
  365. end;
  366. procedure tgenericcoffoutput.createsection(sec:TSection);
  367. var
  368. Aflags : longint;
  369. begin
  370. Aflags:=0;
  371. case sec of
  372. sec_code :
  373. Aflags:=text_flags;
  374. sec_data :
  375. Aflags:=data_flags;
  376. sec_bss :
  377. Aflags:=bss_flags;
  378. sec_idata2,
  379. sec_idata4,
  380. sec_idata5,
  381. sec_idata6,
  382. sec_idata7 :
  383. Aflags:=idata_flags;
  384. sec_edata :
  385. Aflags:=edata_flags;
  386. else
  387. Aflags:=0;
  388. end;
  389. sects[sec]:=new(PcoffSection,init(Sec,Aflags));
  390. end;
  391. procedure tgenericcoffoutput.writesymbol(p:pasmsymbol);
  392. var
  393. pos : longint;
  394. sym : tsymbol;
  395. s : string;
  396. begin
  397. { already written ? }
  398. if p^.idx<>-1 then
  399. exit;
  400. { be sure that the section will exists }
  401. if (p^.section<>sec_none) and not(assigned(sects[p^.section])) then
  402. createsection(p^.section);
  403. { symbolname }
  404. pos:=strs^.size+4;
  405. s:=p^.name;
  406. if length(s)>8 then
  407. begin
  408. if length(s)<255 then
  409. s:=s+#0;
  410. strs^.write(s[1],length(s));
  411. { if the length is 255 we need to addd the terminal #0
  412. separately bug report from Florian 20/6/2000 }
  413. if length(s)=255 then
  414. begin
  415. s:=#0;
  416. strs^.write(s[1],length(s));
  417. end;
  418. end
  419. else
  420. pos:=-1;
  421. FillChar(sym,sizeof(sym),0);
  422. sym.strpos:=pos;
  423. if pos=-1 then
  424. sym.name:=s;
  425. sym.value:=p^.size;
  426. sym.typ:=p^.bind;
  427. { coff doesn't have common, replace with external }
  428. if sym.typ=AB_COMMON then
  429. sym.typ:=AB_EXTERNAL;
  430. { if local of global then set the section value to the address
  431. of the symbol }
  432. if sym.typ in [AB_LOCAL,AB_GLOBAL] then
  433. begin
  434. sym.section:=p^.section;
  435. sym.value:=p^.address+sects[p^.section]^.mempos;
  436. end;
  437. { update the asmsymbol index }
  438. p^.idx:=syms^.size div sizeof(TSymbol);
  439. { store the symbol, but not the local ones (PM) }
  440. if (sym.typ<>AB_LOCAL) or ((copy(s,1,2)<>'.L') and
  441. ((copy(s,1,1)<>'L') or not win32)) then
  442. syms^.write(sym,sizeof(tsymbol));
  443. { make the exported syms known to the objectwriter
  444. (needed for .a generation) }
  445. if (sym.typ=AB_GLOBAL) or
  446. ((sym.typ=AB_EXTERNAL) and (sym.value=p^.size) and (sym.value>0)) then
  447. writer^.writesym(p^.name);
  448. end;
  449. procedure tgenericcoffoutput.writebytes(var data;len:longint);
  450. begin
  451. if not assigned(sects[currsec]) then
  452. createsection(currsec);
  453. sects[currsec]^.write(data,len);
  454. end;
  455. procedure tgenericcoffoutput.writealloc(len:longint);
  456. begin
  457. if not assigned(sects[currsec]) then
  458. createsection(currsec);
  459. sects[currsec]^.alloc(len);
  460. end;
  461. procedure tgenericcoffoutput.writealign(len:longint);
  462. var
  463. modulo : longint;
  464. begin
  465. if not assigned(sects[currsec]) then
  466. createsection(currsec);
  467. modulo:=sects[currsec]^.len mod len;
  468. if modulo > 0 then
  469. sects[currsec]^.alloc(len-modulo);
  470. end;
  471. procedure tgenericcoffoutput.writereloc(data,len:longint;p:pasmsymbol;relative:relative_type);
  472. var
  473. symaddr : longint;
  474. begin
  475. if not assigned(sects[currsec]) then
  476. createsection(currsec);
  477. if assigned(p) then
  478. begin
  479. { real address of the symbol }
  480. symaddr:=p^.address;
  481. if p^.section<>sec_none then
  482. inc(symaddr,sects[p^.section]^.mempos);
  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]^.len,currsec,relative_false);
  490. inc(data,symaddr);
  491. end;
  492. relative_true :
  493. begin
  494. inc(data,symaddr-len-sects[currsec]^.len);
  495. end;
  496. relative_rva :
  497. begin
  498. { don't know if this can happens !! }
  499. { does this work ?? }
  500. sects[currsec]^.addsectionreloc(sects[currsec]^.len,currsec,relative_rva);
  501. inc(data,symaddr);
  502. end;
  503. end;
  504. end
  505. else
  506. begin
  507. writesymbol(p);
  508. if (p^.section<>sec_none) and (relative<>relative_true) then
  509. sects[currsec]^.addsectionreloc(sects[currsec]^.len,p^.section,relative)
  510. else
  511. sects[currsec]^.addsymreloc(sects[currsec]^.len,p,relative);
  512. if not win32 then {seems wrong to me (PM) }
  513. inc(data,symaddr)
  514. else
  515. if (relative<>relative_true) and (p^.section<>sec_none) then
  516. inc(data,symaddr);
  517. if relative=relative_true then
  518. begin
  519. if win32 then
  520. dec(data,len-4)
  521. else
  522. dec(data,len+sects[currsec]^.len);
  523. end;
  524. end;
  525. end;
  526. sects[currsec]^.write(data,len);
  527. end;
  528. procedure tgenericcoffoutput.writestabs(section:tsection;offset:longint;p:pchar;nidx,nother,line:longint;reloc : boolean);
  529. var
  530. stab : coffstab;
  531. s : tsection;
  532. begin
  533. { This is wrong because
  534. sec_none is used only for external bss
  535. if section=sec_none then
  536. s:=currsec
  537. else }
  538. s:=section;
  539. { local var can be at offset -1 !! PM }
  540. if reloc then
  541. begin
  542. if (offset=-1) then
  543. begin
  544. if s=sec_none then
  545. offset:=0
  546. else
  547. offset:=sects[s]^.len;
  548. end;
  549. if (s<>sec_none) then
  550. inc(offset,sects[s]^.mempos);
  551. end;
  552. fillchar(stab,sizeof(coffstab),0);
  553. if assigned(p) and (p[0]<>#0) then
  554. begin
  555. stab.strpos:=sects[sec_stabstr]^.len;
  556. sects[sec_stabstr]^.write(p^,strlen(p)+1);
  557. end;
  558. stab.ntype:=nidx;
  559. stab.ndesc:=line;
  560. stab.nother:=nother;
  561. stab.nvalue:=offset;
  562. sects[sec_stab]^.write(stab,sizeof(stab));
  563. { when the offset is not 0 then write a relocation, take also the
  564. hdrstab into account with the offset }
  565. if reloc then
  566. if DLLSource and RelocSection then
  567. { avoid relocation in the .stab section
  568. because it ends up in the .reloc section instead }
  569. sects[sec_stab]^.addsectionreloc(sects[sec_stab]^.len-4,s,relative_rva)
  570. else
  571. sects[sec_stab]^.addsectionreloc(sects[sec_stab]^.len-4,s,relative_false);
  572. end;
  573. procedure tgenericcoffoutput.writesymstabs(section:tsection;offset:longint;p:pchar;ps:pasmsymbol;
  574. nidx,nother,line:longint;reloc:boolean);
  575. var
  576. stab : coffstab;
  577. s : tsection;
  578. begin
  579. { This is wrong because
  580. sec_none is used only for external bss
  581. if section=sec_none then
  582. s:=currsec
  583. else }
  584. s:=section;
  585. { do not use the size stored in offset field
  586. this is DJGPP specific ! PM }
  587. if win32 then
  588. offset:=0;
  589. { local var can be at offset -1 !! PM }
  590. if reloc then
  591. begin
  592. if (offset=-1) then
  593. begin
  594. if s=sec_none then
  595. offset:=0
  596. else
  597. offset:=sects[s]^.len;
  598. end;
  599. if (s<>sec_none) then
  600. inc(offset,sects[s]^.mempos);
  601. end;
  602. fillchar(stab,sizeof(coffstab),0);
  603. if assigned(p) and (p[0]<>#0) then
  604. begin
  605. stab.strpos:=sects[sec_stabstr]^.len;
  606. sects[sec_stabstr]^.write(p^,strlen(p)+1);
  607. end;
  608. stab.ntype:=nidx;
  609. stab.ndesc:=line;
  610. stab.nother:=nother;
  611. stab.nvalue:=offset;
  612. sects[sec_stab]^.write(stab,sizeof(stab));
  613. { when the offset is not 0 then write a relocation, take also the
  614. hdrstab into account with the offset }
  615. if reloc then
  616. if DLLSource and RelocSection then
  617. { avoid relocation in the .stab section
  618. because it ends up in the .reloc section instead }
  619. sects[sec_stab]^.addsymreloc(sects[sec_stab]^.len-4,ps,relative_rva)
  620. else
  621. sects[sec_stab]^.addsymreloc(sects[sec_stab]^.len-4,ps,relative_false);
  622. end;
  623. procedure tgenericcoffoutput.setsectionsizes(var s:tsecsize);
  624. var
  625. align,
  626. mempos : longint;
  627. sec : tsection;
  628. begin
  629. { multiply stab with real size }
  630. s[sec_stab]:=s[sec_stab]*sizeof(coffstab);
  631. { if debug then also count header stab }
  632. if (cs_debuginfo in aktmoduleswitches) then
  633. begin
  634. inc(s[sec_stab],sizeof(coffstab));
  635. inc(s[sec_stabstr],length(SplitFileName(current_module^.mainsource^))+2);
  636. end;
  637. { fix all section }
  638. mempos:=0;
  639. for sec:=low(tsection) to high(tsection) do
  640. begin
  641. if (s[sec]>0) and (not assigned(sects[sec])) then
  642. createsection(sec);
  643. if assigned(sects[sec]) then
  644. begin
  645. sects[sec]^.size:=s[sec];
  646. sects[sec]^.mempos:=mempos;
  647. { calculate the alignment }
  648. align:=sects[sec]^.align;
  649. sects[sec]^.fillsize:=align-(sects[sec]^.size and (align-1));
  650. if sects[sec]^.fillsize=align then
  651. sects[sec]^.fillsize:=0;
  652. { next section position, not for win32 which uses
  653. relative addresses }
  654. if not win32 then
  655. inc(mempos,sects[sec]^.size+sects[sec]^.fillsize);
  656. end;
  657. end;
  658. end;
  659. {***********************************************
  660. Writing to disk
  661. ***********************************************}
  662. procedure tgenericcoffoutput.write_relocs(s:pcoffsection);
  663. var
  664. rel : coffreloc;
  665. hr,r : preloc;
  666. begin
  667. r:=s^.relochead;
  668. while assigned(r) do
  669. begin
  670. rel.address:=r^.address;
  671. if assigned(r^.symbol) then
  672. begin
  673. if (r^.symbol^.bind=AB_LOCAL) then
  674. rel.sym:=2*sects[r^.symbol^.section]^.secsymidx
  675. else
  676. begin
  677. if r^.symbol^.idx=-1 then
  678. internalerror(4321);
  679. rel.sym:=r^.symbol^.idx+initsym;
  680. end;
  681. end
  682. else if r^.section<>sec_none then
  683. rel.sym:=2*sects[r^.section]^.secsymidx
  684. else
  685. rel.sym:=0;
  686. case r^.relative of
  687. relative_true : rel.relative:=$14;
  688. relative_false : rel.relative:=$6;
  689. relative_rva : rel.relative:=$7;
  690. end;
  691. writer^.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 tgenericcoffoutput.write_symbol(const name:string;strpos,value,section,typ,aux:longint);
  699. var
  700. sym : coffsymbol;
  701. begin
  702. FillChar(sym,sizeof(sym),0);
  703. if strpos=-1 then
  704. move(name[1],sym.name,length(name))
  705. else
  706. sym.strpos:=strpos;
  707. sym.value:=value;
  708. sym.section:=section;
  709. sym.typ:=typ;
  710. sym.aux:=aux;
  711. writer^.write(sym,sizeof(sym));
  712. end;
  713. procedure tgenericcoffoutput.write_symbols;
  714. var
  715. filename : string[18];
  716. sec : tsection;
  717. sectionval,
  718. i : longint;
  719. globalval : byte;
  720. secrec : coffsectionrec;
  721. sym : tsymbol;
  722. begin
  723. { The `.file' record, and the file name auxiliary record. }
  724. write_symbol ('.file', -1, 0, -2, $67, 1);
  725. fillchar(filename,sizeof(filename),0);
  726. filename:=SplitFileName(current_module^.mainsource^);
  727. writer^.write(filename[1],sizeof(filename)-1);
  728. { The section records, with their auxiliaries, also store the
  729. symbol index }
  730. for sec:=low(tsection) to high(tsection) do
  731. if assigned(sects[sec]) then
  732. begin
  733. write_symbol(target_asm.secnames[sec],-1,sects[sec]^.mempos,sects[sec]^.secsymidx,3,1);
  734. fillchar(secrec,sizeof(secrec),0);
  735. secrec.len:=sects[sec]^.len;
  736. secrec.nrelocs:=sects[sec]^.nrelocs;
  737. writer^.write(secrec,sizeof(secrec));
  738. end;
  739. { The real symbols. }
  740. syms^.seek(0);
  741. for i:=1 to syms^.size div sizeof(TSymbol) do
  742. begin
  743. syms^.read(sym,sizeof(TSymbol));
  744. if sym.typ=AB_LOCAL then
  745. globalval:=3
  746. else
  747. globalval:=2;
  748. if assigned(sects[sym.section]) then
  749. sectionval:=sects[sym.section]^.secsymidx
  750. else
  751. sectionval:=0;
  752. write_symbol(sym.name,sym.strpos,sym.value,sectionval,globalval,0);
  753. end;
  754. end;
  755. procedure tgenericcoffoutput.writetodisk;
  756. var
  757. datapos,secsymidx,
  758. nsects,sympos,i : longint;
  759. hstab : coffstab;
  760. gotreloc : boolean;
  761. sec : tsection;
  762. header : coffheader;
  763. sechdr : coffsechdr;
  764. empty : array[0..15] of byte;
  765. hp : pdynamicblock;
  766. begin
  767. { calc amount of sections we have and align sections at 4 bytes }
  768. fillchar(empty,sizeof(empty),0);
  769. nsects:=0;
  770. for sec:=low(tsection) to high(tsection) do
  771. if assigned(sects[sec]) then
  772. begin
  773. {$ifdef EXTDEBUG}
  774. { check if the section is still the same size }
  775. if (sects[sec]^.len<>sects[sec]^.size) then
  776. Comment(V_Warning,'Size of section changed '+
  777. tostr(sects[sec]^.size)+'->'+tostr(sects[sec]^.len)+
  778. ' ['+target_asm.secnames[sec]+']');
  779. {$endif EXTDEBUG}
  780. { fill with zero }
  781. if sects[sec]^.fillsize>0 then
  782. begin
  783. if assigned(sects[sec]^.data) then
  784. sects[sec]^.write(empty,sects[sec]^.fillsize)
  785. else
  786. sects[sec]^.alloc(sects[sec]^.fillsize);
  787. end;
  788. inc(nsects);
  789. end;
  790. { Calculate the filepositions }
  791. datapos:=sizeof(coffheader)+sizeof(coffsechdr)*nsects;
  792. initsym:=2; { 2 for the file }
  793. { sections first }
  794. secsymidx:=0;
  795. for sec:=low(tsection) to high(tsection) do
  796. if assigned(sects[sec]) then
  797. begin
  798. inc(secsymidx);
  799. sects[sec]^.secsymidx:=secsymidx;
  800. sects[sec]^.datapos:=datapos;
  801. if assigned(sects[sec]^.data) then
  802. inc(datapos,sects[sec]^.len);
  803. inc(initsym,2); { 2 for each section }
  804. end;
  805. { relocs }
  806. gotreloc:=false;
  807. for sec:=low(tsection) to high(tsection) do
  808. if assigned(sects[sec]) then
  809. begin
  810. sects[sec]^.relocpos:=datapos;
  811. inc(datapos,10*sects[sec]^.nrelocs);
  812. if (not gotreloc) and (sects[sec]^.nrelocs>0) then
  813. gotreloc:=true;
  814. end;
  815. { symbols }
  816. sympos:=datapos;
  817. { COFF header }
  818. fillchar(header,sizeof(coffheader),0);
  819. header.mach:=$14c;
  820. header.nsects:=nsects;
  821. header.sympos:=sympos;
  822. header.syms:=(syms^.size div sizeof(TSymbol))+initsym;
  823. if gotreloc then
  824. header.flag:=$104
  825. else
  826. header.flag:=$105;
  827. writer^.write(header,sizeof(header));
  828. { Section headers }
  829. for sec:=low(tsection) to high(tsection) do
  830. if assigned(sects[sec]) then
  831. begin
  832. fillchar(sechdr,sizeof(sechdr),0);
  833. move(target_asm.secnames[sec][1],sechdr.name,length(target_asm.secnames[sec]));
  834. if not win32 then
  835. begin
  836. sechdr.rvaofs:=sects[sec]^.mempos;
  837. sechdr.vsize:=sects[sec]^.mempos;
  838. end
  839. else
  840. begin
  841. if sec=sec_bss then
  842. sechdr.vsize:=sects[sec]^.len;
  843. end;
  844. sechdr.datalen:=sects[sec]^.len;
  845. if (sects[sec]^.len>0) and assigned(sects[sec]^.data) then
  846. sechdr.datapos:=sects[sec]^.datapos;
  847. sechdr.relocpos:=sects[sec]^.relocpos;
  848. sechdr.nrelocs:=sects[sec]^.nrelocs;
  849. sechdr.flags:=sects[sec]^.flags;
  850. writer^.write(sechdr,sizeof(sechdr));
  851. end;
  852. { Sections }
  853. for sec:=low(tsection) to high(tsection) do
  854. if assigned(sects[sec]) and
  855. assigned(sects[sec]^.data) then
  856. begin
  857. { For the stab section we need an HdrSym which can now be
  858. calculated more easily }
  859. if sec=sec_stab then
  860. begin
  861. hstab.strpos:=1;
  862. hstab.ntype:=0;
  863. hstab.nother:=0;
  864. hstab.ndesc:=(sects[sec_stab]^.len div sizeof(coffstab))-1{+1 according to gas output PM};
  865. hstab.nvalue:=sects[sec_stabstr]^.len;
  866. sects[sec_stab]^.data^.seek(0);
  867. sects[sec_stab]^.data^.write(hstab,sizeof(hstab));
  868. end;
  869. hp:=sects[sec]^.data^.firstblock;
  870. while assigned(hp) do
  871. begin
  872. writer^.write(hp^.data,hp^.used);
  873. hp:=hp^.next;
  874. end;
  875. end;
  876. { Relocs }
  877. for sec:=low(tsection) to high(tsection) do
  878. if assigned(sects[sec]) then
  879. write_relocs(sects[sec]);
  880. { Symbols }
  881. write_symbols;
  882. { Strings }
  883. i:=strs^.size+4;
  884. writer^.write(i,4);
  885. hp:=strs^.firstblock;
  886. while assigned(hp) do
  887. begin
  888. writer^.write(hp^.data,hp^.used);
  889. hp:=hp^.next;
  890. end;
  891. end;
  892. {****************************************************************************
  893. DJGppcoffoutput
  894. ****************************************************************************}
  895. constructor tdjgppcoffoutput.init(smart:boolean);
  896. begin
  897. inherited init(smart);
  898. win32:=false;
  899. end;
  900. function tdjgppcoffoutput.text_flags : longint;
  901. begin
  902. text_flags:=$20;
  903. end;
  904. function tdjgppcoffoutput.data_flags : longint;
  905. begin
  906. data_flags:=$40;
  907. end;
  908. function tdjgppcoffoutput.bss_flags : longint;
  909. begin
  910. bss_flags:=$80;
  911. end;
  912. {****************************************************************************
  913. Win32coffoutput
  914. ****************************************************************************}
  915. constructor twin32coffoutput.init(smart:boolean);
  916. begin
  917. inherited init(smart);
  918. win32:=true;
  919. end;
  920. function twin32coffoutput.text_flags : longint;
  921. begin
  922. text_flags:=$60000020; { same as as 2.9.1 }
  923. end;
  924. function twin32coffoutput.data_flags : longint;
  925. begin
  926. data_flags:=$c0300040;
  927. end;
  928. function twin32coffoutput.bss_flags : longint;
  929. begin
  930. bss_flags:=$c0300080;
  931. end;
  932. function twin32coffoutput.edata_flags : longint;
  933. begin
  934. edata_flags:=$c0300040;
  935. end;
  936. function twin32coffoutput.idata_flags : longint;
  937. begin
  938. idata_flags:=$40000000;
  939. end;
  940. end.
  941. {
  942. $Log$
  943. Revision 1.6 2000-09-19 23:09:07 pierre
  944. * problems wih extdebug cond. solved
  945. Revision 1.5 2000/08/27 16:11:51 peter
  946. * moved some util functions from globals,cobjects to cutils
  947. * splitted files into finput,fmodule
  948. Revision 1.4 2000/08/19 18:44:27 peter
  949. * new tdynamicarray implementation using blocks instead of
  950. reallocmem (merged)
  951. Revision 1.3 2000/07/13 12:08:26 michael
  952. + patched to 1.1.0 with former 1.09patch from peter
  953. Revision 1.2 2000/07/13 11:32:43 michael
  954. + removed logs
  955. }