og386cff.pas 33 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060
  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 : TAsmsymtype;
  75. end;
  76. pcoffsection = ^tcoffsection;
  77. tcoffsection = object
  78. index : tsection;
  79. secidx : longint;
  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. procedure setsectionsizes(var s:tsecsize);virtual;
  111. procedure writebytes(var data;len:longint);virtual;
  112. procedure writealloc(len:longint);virtual;
  113. procedure writealign(len:longint);virtual;
  114. procedure writereloc(data,len:longint;p:pasmsymbol;relative:relative_type);virtual;
  115. procedure writesymbol(p:pasmsymbol);virtual;
  116. procedure writestabs(section:tsection;offset:longint;p:pchar;nidx,nother,line:longint;reloc:boolean);virtual;
  117. procedure writesymstabs(section:tsection;offset:longint;p:pchar;ps:pasmsymbol;
  118. nidx,nother,line:longint;reloc:boolean);virtual;
  119. function text_flags : longint;virtual;
  120. function data_flags : longint;virtual;
  121. function bss_flags : longint;virtual;
  122. function idata_flags : longint;virtual;
  123. function edata_flags : longint;virtual;
  124. private
  125. procedure createsection(sec:tsection);
  126. procedure write_relocs(s:pcoffsection);
  127. procedure write_symbol(const name:string;strpos,value,section,typ,aux:longint);
  128. procedure write_symbols;
  129. procedure writetodisk;
  130. end;
  131. pdjgppcoffoutput = ^tdjgppcoffoutput;
  132. tdjgppcoffoutput = object(tgenericcoffoutput)
  133. constructor init(smart:boolean);
  134. function text_flags : longint;virtual;
  135. function data_flags : longint;virtual;
  136. function bss_flags : longint;virtual;
  137. end;
  138. pwin32coffoutput = ^twin32coffoutput;
  139. twin32coffoutput = object(tgenericcoffoutput)
  140. constructor init(smart:boolean);
  141. function text_flags : longint;virtual;
  142. function data_flags : longint;virtual;
  143. function bss_flags : longint;virtual;
  144. function idata_flags : longint;virtual;
  145. function edata_flags : longint;virtual;
  146. end;
  147. implementation
  148. uses
  149. strings,verbose,
  150. globtype,globals,files;
  151. type
  152. { Structures which are written directly to the output file }
  153. coffheader=packed record
  154. mach : word;
  155. nsects : word;
  156. time : longint;
  157. sympos : longint;
  158. syms : longint;
  159. opthdr : word;
  160. flag : word;
  161. end;
  162. coffsechdr=packed record
  163. name : array[0..7] of char;
  164. vsize : longint;
  165. rvaofs : longint;
  166. datalen : longint;
  167. datapos : longint;
  168. relocpos : longint;
  169. lineno1 : longint;
  170. nrelocs : word;
  171. lineno2 : word;
  172. flags : longint;
  173. end;
  174. coffsectionrec=packed record
  175. len : longint;
  176. nrelocs : word;
  177. empty : array[0..11] of char;
  178. end;
  179. coffreloc=packed record
  180. address : longint;
  181. sym : longint;
  182. relative : word;
  183. end;
  184. coffsymbol=packed record
  185. name : array[0..3] of char; { real is [0..7], which overlaps the strpos ! }
  186. strpos : longint;
  187. value : longint;
  188. section : integer;
  189. empty : integer;
  190. typ : byte;
  191. aux : byte;
  192. end;
  193. pcoffstab=^coffstab;
  194. coffstab=packed record
  195. strpos : longint;
  196. ntype : byte;
  197. nother : byte;
  198. ndesc : word;
  199. nvalue : longint;
  200. end;
  201. {****************************************************************************
  202. TSection
  203. ****************************************************************************}
  204. constructor tcoffsection.init(sec:TSection;Aflags:longint);
  205. begin
  206. index:=sec;
  207. secidx:=0;
  208. flags:=AFlags;
  209. { alignment after section }
  210. case sec of
  211. sec_code,
  212. sec_data,
  213. sec_bss :
  214. align:=4;
  215. else
  216. align:=1;
  217. end;
  218. { filled after pass 1 }
  219. size:=0;
  220. fillsize:=0;
  221. mempos:=0;
  222. { pass 2 data }
  223. relocHead:=nil;
  224. relocTail:=@relocHead;
  225. Len:=0;
  226. NRelocs:=0;
  227. if sec=sec_bss then
  228. data:=nil
  229. else
  230. new(Data,Init(1,8192));
  231. end;
  232. destructor tcoffsection.done;
  233. begin
  234. if assigned(Data) then
  235. dispose(Data,done);
  236. end;
  237. procedure tcoffsection.write(var d;l:longint);
  238. begin
  239. if not assigned(Data) then
  240. Internalerror(3334441);
  241. Data^.write(d,l);
  242. inc(len,l);
  243. end;
  244. procedure tcoffsection.alloc(l:longint);
  245. begin
  246. if assigned(Data) then
  247. Internalerror(3334442);
  248. inc(len,l);
  249. end;
  250. procedure tcoffsection.addsymreloc(ofs:longint;p:pasmsymbol;relative:relative_type);
  251. var
  252. r : PReloc;
  253. begin
  254. new(r);
  255. reloctail^:=r;
  256. reloctail:=@r^.next;
  257. r^.next:=nil;
  258. r^.address:=ofs+mempos;
  259. r^.symbol:=p;
  260. r^.section:=sec_none;
  261. r^.relative:=relative;
  262. inc(nrelocs);
  263. end;
  264. procedure tcoffsection.addsectionreloc(ofs:longint;sec:tsection;relative:relative_type);
  265. var
  266. r : PReloc;
  267. begin
  268. new(r);
  269. reloctail^:=r;
  270. reloctail:=@r^.next;
  271. r^.next:=nil;
  272. r^.address:=ofs+mempos;
  273. r^.symbol:=nil;
  274. r^.section:=sec;
  275. r^.relative:=relative;
  276. inc(nrelocs);
  277. end;
  278. {****************************************************************************
  279. Genericcoffoutput
  280. ****************************************************************************}
  281. const
  282. {$ifdef TP}
  283. symbolresize = 50;
  284. strsresize = 200;
  285. {$else}
  286. symbolresize = 200;
  287. strsresize = 8192;
  288. {$endif}
  289. constructor tgenericcoffoutput.init(smart:boolean);
  290. begin
  291. inherited init(smart);
  292. end;
  293. destructor tgenericcoffoutput.done;
  294. begin
  295. inherited done;
  296. end;
  297. procedure tgenericcoffoutput.initwriting(Aplace:tcutplace);
  298. var
  299. s : string;
  300. begin
  301. inherited initwriting(Aplace);
  302. { reset }
  303. initsym:=0;
  304. new(syms,init(sizeof(TSymbol),symbolresize));
  305. new(strs,init(1,strsresize));
  306. FillChar(Sects,sizeof(Sects),0);
  307. { we need at least the following 3 sections }
  308. createsection(sec_code);
  309. createsection(sec_data);
  310. createsection(sec_bss);
  311. if (cs_gdb_lineinfo in aktglobalswitches) or
  312. (cs_debuginfo in aktmoduleswitches) then
  313. begin
  314. createsection(sec_stab);
  315. createsection(sec_stabstr);
  316. writestabs(sec_none,0,nil,0,0,0,false);
  317. { write zero pchar and name together (PM) }
  318. s:=#0+SplitFileName(current_module^.mainsource^)+#0;
  319. sects[sec_stabstr]^.write(s[1],length(s));
  320. end;
  321. end;
  322. procedure tgenericcoffoutput.donewriting;
  323. var
  324. sec : tsection;
  325. begin
  326. { Only write the .o if there are no errors }
  327. if errorcount=0 then
  328. writetodisk;
  329. dispose(syms,done);
  330. dispose(strs,done);
  331. for sec:=low(tsection) to high(tsection) do
  332. if assigned(sects[sec]) then
  333. dispose(sects[sec],done);
  334. inherited donewriting;
  335. end;
  336. function tgenericcoffoutput.text_flags : longint;
  337. begin
  338. text_flags:=0;
  339. end;
  340. function tgenericcoffoutput.data_flags : longint;
  341. begin
  342. data_flags:=0;
  343. end;
  344. function tgenericcoffoutput.bss_flags : longint;
  345. begin
  346. bss_flags:=0;
  347. end;
  348. function tgenericcoffoutput.edata_flags : longint;
  349. begin
  350. edata_flags:=0;
  351. end;
  352. function tgenericcoffoutput.idata_flags : longint;
  353. begin
  354. idata_flags:=0;
  355. end;
  356. procedure tgenericcoffoutput.createsection(sec:TSection);
  357. var
  358. Aflags : longint;
  359. begin
  360. Aflags:=0;
  361. case sec of
  362. sec_code :
  363. Aflags:=text_flags;
  364. sec_data :
  365. Aflags:=data_flags;
  366. sec_bss :
  367. Aflags:=bss_flags;
  368. sec_idata2,
  369. sec_idata4,
  370. sec_idata5,
  371. sec_idata6,
  372. sec_idata7 :
  373. Aflags:=idata_flags;
  374. sec_edata :
  375. Aflags:=edata_flags;
  376. else
  377. Aflags:=0;
  378. end;
  379. sects[sec]:=new(PcoffSection,init(Sec,Aflags));
  380. end;
  381. procedure tgenericcoffoutput.writesymbol(p:pasmsymbol);
  382. var
  383. pos : longint;
  384. sym : tsymbol;
  385. s : string;
  386. begin
  387. { already written ? }
  388. if p^.idx<>-1 then
  389. exit;
  390. { be sure that the section will exists }
  391. if (p^.section<>sec_none) and not(assigned(sects[p^.section])) then
  392. createsection(p^.section);
  393. { symbolname }
  394. pos:=strs^.usedsize+4;
  395. s:=p^.name;
  396. if length(s)>8 then
  397. begin
  398. if length(s)<255 then
  399. s:=s+#0;
  400. strs^.write(s[1],length(s));
  401. { if the length is 255 we need to addd the terminal #0
  402. separately bug report from Florian 20/6/2000 }
  403. if length(s)=255 then
  404. begin
  405. s:=#0;
  406. strs^.write(s[1],length(s));
  407. end;
  408. end
  409. else
  410. pos:=-1;
  411. FillChar(sym,sizeof(sym),0);
  412. sym.strpos:=pos;
  413. if pos=-1 then
  414. sym.name:=s;
  415. sym.value:=p^.size;
  416. sym.typ:=p^.typ;
  417. { if local of global then set the section value to the address
  418. of the symbol }
  419. if p^.typ in [AS_LOCAL,AS_GLOBAL] then
  420. begin
  421. sym.section:=p^.section;
  422. sym.value:=p^.address+sects[p^.section]^.mempos;
  423. end;
  424. { update the asmsymbol index }
  425. p^.idx:=syms^.count;
  426. { store the symbol, but not the local ones (PM) }
  427. if (p^.typ<>AS_LOCAL) or ((copy(s,1,2)<>'.L') and
  428. ((copy(s,1,1)<>'L') or not win32)) then
  429. syms^.write(sym,1);
  430. { make the exported syms known to the objectwriter
  431. (needed for .a generation) }
  432. if (p^.typ=AS_GLOBAL) or
  433. ((p^.typ=AS_EXTERNAL) and (sym.value=p^.size) and (sym.value>0)) then
  434. writer^.writesym(p^.name);
  435. end;
  436. procedure tgenericcoffoutput.writebytes(var data;len:longint);
  437. begin
  438. if not assigned(sects[currsec]) then
  439. createsection(currsec);
  440. sects[currsec]^.write(data,len);
  441. end;
  442. procedure tgenericcoffoutput.writealloc(len:longint);
  443. begin
  444. if not assigned(sects[currsec]) then
  445. createsection(currsec);
  446. sects[currsec]^.alloc(len);
  447. end;
  448. procedure tgenericcoffoutput.writealign(len:longint);
  449. var modulo : longint;
  450. begin
  451. if not assigned(sects[currsec]) then
  452. createsection(currsec);
  453. modulo:=sects[currsec]^.len mod len;
  454. if modulo > 0 then
  455. sects[currsec]^.alloc(len-modulo);
  456. end;
  457. procedure tgenericcoffoutput.writereloc(data,len:longint;p:pasmsymbol;relative:relative_type);
  458. var
  459. symaddr : longint;
  460. begin
  461. if not assigned(sects[currsec]) then
  462. createsection(currsec);
  463. if assigned(p) then
  464. begin
  465. { real address of the symbol }
  466. symaddr:=p^.address;
  467. if p^.section<>sec_none then
  468. inc(symaddr,sects[p^.section]^.mempos);
  469. { no symbol relocation need inside a section }
  470. if p^.section=currsec then
  471. begin
  472. case relative of
  473. relative_false :
  474. begin
  475. sects[currsec]^.addsectionreloc(sects[currsec]^.len,currsec,relative_false);
  476. inc(data,symaddr);
  477. end;
  478. relative_true :
  479. begin
  480. inc(data,symaddr-len-sects[currsec]^.len);
  481. end;
  482. relative_rva :
  483. begin
  484. { don't know if this can happens !! }
  485. { does this work ?? }
  486. sects[currsec]^.addsectionreloc(sects[currsec]^.len,currsec,relative_rva);
  487. inc(data,symaddr);
  488. end;
  489. end;
  490. end
  491. else
  492. begin
  493. writesymbol(p);
  494. if (p^.section<>sec_none) and (relative<>relative_true) then
  495. sects[currsec]^.addsectionreloc(sects[currsec]^.len,p^.section,relative)
  496. else
  497. sects[currsec]^.addsymreloc(sects[currsec]^.len,p,relative);
  498. if not win32 then {seems wrong to me (PM) }
  499. inc(data,symaddr)
  500. else
  501. if (relative<>relative_true) and (p^.section<>sec_none) then
  502. inc(data,symaddr);
  503. if relative=relative_true then
  504. begin
  505. if win32 then
  506. dec(data,len-4)
  507. else
  508. dec(data,len+sects[currsec]^.len);
  509. end;
  510. end;
  511. end;
  512. sects[currsec]^.write(data,len);
  513. end;
  514. procedure tgenericcoffoutput.writestabs(section:tsection;offset:longint;p:pchar;nidx,nother,line:longint;reloc : boolean);
  515. var
  516. stab : coffstab;
  517. s : tsection;
  518. begin
  519. { This is wrong because
  520. sec_none is used only for external bss
  521. if section=sec_none then
  522. s:=currsec
  523. else }
  524. s:=section;
  525. { local var can be at offset -1 !! PM }
  526. if reloc then
  527. begin
  528. if (offset=-1) then
  529. begin
  530. if s=sec_none then
  531. offset:=0
  532. else
  533. offset:=sects[s]^.len;
  534. end;
  535. if (s<>sec_none) then
  536. inc(offset,sects[s]^.mempos);
  537. end;
  538. fillchar(stab,sizeof(coffstab),0);
  539. if assigned(p) and (p[0]<>#0) then
  540. begin
  541. stab.strpos:=sects[sec_stabstr]^.len;
  542. sects[sec_stabstr]^.write(p^,strlen(p)+1);
  543. end;
  544. stab.ntype:=nidx;
  545. stab.ndesc:=line;
  546. stab.nother:=nother;
  547. stab.nvalue:=offset;
  548. sects[sec_stab]^.write(stab,sizeof(stab));
  549. { when the offset is not 0 then write a relocation, take also the
  550. hdrstab into account with the offset }
  551. if reloc then
  552. if DLLSource and RelocSection then
  553. { avoid relocation in the .stab section
  554. because it ends up in the .reloc section instead }
  555. sects[sec_stab]^.addsectionreloc(sects[sec_stab]^.len-4,s,relative_rva)
  556. else
  557. sects[sec_stab]^.addsectionreloc(sects[sec_stab]^.len-4,s,relative_false);
  558. end;
  559. procedure tgenericcoffoutput.writesymstabs(section:tsection;offset:longint;p:pchar;ps:pasmsymbol;
  560. nidx,nother,line:longint;reloc:boolean);
  561. var
  562. stab : coffstab;
  563. s : tsection;
  564. begin
  565. { This is wrong because
  566. sec_none is used only for external bss
  567. if section=sec_none then
  568. s:=currsec
  569. else }
  570. s:=section;
  571. { do not use the size stored in offset field
  572. this is DJGPP specific ! PM }
  573. if win32 then
  574. offset:=0;
  575. { local var can be at offset -1 !! PM }
  576. if reloc then
  577. begin
  578. if (offset=-1) then
  579. begin
  580. if s=sec_none then
  581. offset:=0
  582. else
  583. offset:=sects[s]^.len;
  584. end;
  585. if (s<>sec_none) then
  586. inc(offset,sects[s]^.mempos);
  587. end;
  588. fillchar(stab,sizeof(coffstab),0);
  589. if assigned(p) and (p[0]<>#0) then
  590. begin
  591. stab.strpos:=sects[sec_stabstr]^.len;
  592. sects[sec_stabstr]^.write(p^,strlen(p)+1);
  593. end;
  594. stab.ntype:=nidx;
  595. stab.ndesc:=line;
  596. stab.nother:=nother;
  597. stab.nvalue:=offset;
  598. sects[sec_stab]^.write(stab,sizeof(stab));
  599. { when the offset is not 0 then write a relocation, take also the
  600. hdrstab into account with the offset }
  601. if reloc then
  602. if DLLSource and RelocSection then
  603. { avoid relocation in the .stab section
  604. because it ends up in the .reloc section instead }
  605. sects[sec_stab]^.addsymreloc(sects[sec_stab]^.len-4,ps,relative_rva)
  606. else
  607. sects[sec_stab]^.addsymreloc(sects[sec_stab]^.len-4,ps,relative_false);
  608. end;
  609. procedure tgenericcoffoutput.write_relocs(s:pcoffsection);
  610. var
  611. rel : coffreloc;
  612. hr,r : preloc;
  613. begin
  614. r:=s^.relochead;
  615. while assigned(r) do
  616. begin
  617. rel.address:=r^.address;
  618. if assigned(r^.symbol) then
  619. begin
  620. if (r^.symbol^.typ=AS_LOCAL) then
  621. rel.sym:=2*sects[r^.symbol^.section]^.secidx
  622. else
  623. begin
  624. if r^.symbol^.idx=-1 then
  625. internalerror(4321);
  626. rel.sym:=r^.symbol^.idx+initsym;
  627. end;
  628. end
  629. else if r^.section<>sec_none then
  630. rel.sym:=2*sects[r^.section]^.secidx
  631. else
  632. rel.sym:=0;
  633. case r^.relative of
  634. relative_true : rel.relative:=$14;
  635. relative_false : rel.relative:=$6;
  636. relative_rva : rel.relative:=$7;
  637. end;
  638. writer^.write(rel,sizeof(rel));
  639. { goto next and dispose this reloc }
  640. hr:=r;
  641. r:=r^.next;
  642. dispose(hr);
  643. end;
  644. end;
  645. procedure tgenericcoffoutput.write_symbol(const name:string;strpos,value,section,typ,aux:longint);
  646. var
  647. sym : coffsymbol;
  648. begin
  649. FillChar(sym,sizeof(sym),0);
  650. if strpos=-1 then
  651. move(name[1],sym.name,length(name))
  652. else
  653. sym.strpos:=strpos;
  654. sym.value:=value;
  655. sym.section:=section;
  656. sym.typ:=typ;
  657. sym.aux:=aux;
  658. writer^.write(sym,sizeof(sym));
  659. end;
  660. procedure tgenericcoffoutput.write_symbols;
  661. var
  662. filename : string[18];
  663. sec : tsection;
  664. sectionval,
  665. i : longint;
  666. globalval : byte;
  667. secrec : coffsectionrec;
  668. sym : tsymbol;
  669. begin
  670. { The `.file' record, and the file name auxiliary record. }
  671. write_symbol ('.file', -1, 0, -2, $67, 1);
  672. fillchar(filename,sizeof(filename),0);
  673. filename:=SplitFileName(current_module^.mainsource^);
  674. writer^.write(filename[1],sizeof(filename)-1);
  675. { The section records, with their auxiliaries, also store the
  676. symbol index }
  677. for sec:=low(tsection) to high(tsection) do
  678. if assigned(sects[sec]) then
  679. begin
  680. write_symbol(target_asm.secnames[sec],-1,sects[sec]^.mempos,sects[sec]^.secidx,3,1);
  681. fillchar(secrec,sizeof(secrec),0);
  682. secrec.len:=sects[sec]^.len;
  683. secrec.nrelocs:=sects[sec]^.nrelocs;
  684. writer^.write(secrec,sizeof(secrec));
  685. end;
  686. { The real symbols. }
  687. syms^.seek(0);
  688. for i:=1 to syms^.count do
  689. begin
  690. syms^.read(sym,1);
  691. if sym.typ=AS_LOCAL then
  692. globalval:=3
  693. else
  694. globalval:=2;
  695. if assigned(sects[sym.section]) then
  696. sectionval:=sects[sym.section]^.secidx
  697. else
  698. sectionval:=0;
  699. write_symbol(sym.name,sym.strpos,sym.value,sectionval,globalval,0);
  700. end;
  701. end;
  702. procedure tgenericcoffoutput.setsectionsizes(var s:tsecsize);
  703. var
  704. align,
  705. mempos : longint;
  706. sec : tsection;
  707. begin
  708. { multiply stab with real size }
  709. s[sec_stab]:=s[sec_stab]*sizeof(coffstab);
  710. { if debug then also count header stab }
  711. if (cs_gdb_lineinfo in aktglobalswitches) or
  712. (cs_debuginfo in aktmoduleswitches) then
  713. begin
  714. inc(s[sec_stab],sizeof(coffstab));
  715. inc(s[sec_stabstr],length(SplitFileName(current_module^.mainsource^))+2);
  716. end;
  717. { fix all section }
  718. mempos:=0;
  719. for sec:=low(tsection) to high(tsection) do
  720. begin
  721. if (s[sec]>0) and (not assigned(sects[sec])) then
  722. createsection(sec);
  723. if assigned(sects[sec]) then
  724. begin
  725. sects[sec]^.size:=s[sec];
  726. sects[sec]^.mempos:=mempos;
  727. { calculate the alignment }
  728. align:=sects[sec]^.align;
  729. sects[sec]^.fillsize:=align-(sects[sec]^.size and (align-1));
  730. if sects[sec]^.fillsize=align then
  731. sects[sec]^.fillsize:=0;
  732. { next section position, not for win32 which uses
  733. relative addresses }
  734. if not win32 then
  735. inc(mempos,sects[sec]^.size+sects[sec]^.fillsize);
  736. end;
  737. end;
  738. end;
  739. procedure tgenericcoffoutput.writetodisk;
  740. var
  741. datapos,secidx,
  742. nsects,sympos,i : longint;
  743. gotreloc : boolean;
  744. sec : tsection;
  745. header : coffheader;
  746. sechdr : coffsechdr;
  747. empty : array[0..15] of byte;
  748. begin
  749. { calc amount of sections we have and align sections at 4 bytes }
  750. fillchar(empty,sizeof(empty),0);
  751. nsects:=0;
  752. for sec:=low(tsection) to high(tsection) do
  753. if assigned(sects[sec]) then
  754. begin
  755. {$ifdef EXTDEBUG}
  756. { check if the section is still the same size }
  757. if (sects[sec]^.len<>sects[sec]^.size) then
  758. Comment(V_Warning,'Size of section changed '+
  759. tostr(sects[sec]^.size)+'->'+tostr(sects[sec]^.len)+
  760. ' ['+target_asm.secnames[sec]+']');
  761. {$endif EXTDEBUG}
  762. { fill with zero }
  763. if sects[sec]^.fillsize>0 then
  764. begin
  765. if assigned(sects[sec]^.data) then
  766. sects[sec]^.write(empty,sects[sec]^.fillsize)
  767. else
  768. sects[sec]^.alloc(sects[sec]^.fillsize);
  769. end;
  770. inc(nsects);
  771. end;
  772. { Calculate the filepositions }
  773. datapos:=sizeof(coffheader)+sizeof(coffsechdr)*nsects;
  774. initsym:=2; { 2 for the file }
  775. { sections first }
  776. secidx:=0;
  777. for sec:=low(tsection) to high(tsection) do
  778. if assigned(sects[sec]) then
  779. begin
  780. inc(secidx);
  781. sects[sec]^.secidx:=secidx;
  782. sects[sec]^.datapos:=datapos;
  783. if assigned(sects[sec]^.data) then
  784. inc(datapos,sects[sec]^.len);
  785. inc(initsym,2); { 2 for each section }
  786. end;
  787. { relocs }
  788. gotreloc:=false;
  789. for sec:=low(tsection) to high(tsection) do
  790. if assigned(sects[sec]) then
  791. begin
  792. sects[sec]^.relocpos:=datapos;
  793. inc(datapos,10*sects[sec]^.nrelocs);
  794. if (not gotreloc) and (sects[sec]^.nrelocs>0) then
  795. gotreloc:=true;
  796. end;
  797. { symbols }
  798. sympos:=datapos;
  799. { COFF header }
  800. fillchar(header,sizeof(coffheader),0);
  801. header.mach:=$14c;
  802. header.nsects:=nsects;
  803. header.sympos:=sympos;
  804. header.syms:=syms^.count+initsym;
  805. if gotreloc then
  806. header.flag:=$104
  807. else
  808. header.flag:=$105;
  809. writer^.write(header,sizeof(header));
  810. { Section headers }
  811. for sec:=low(tsection) to high(tsection) do
  812. if assigned(sects[sec]) then
  813. begin
  814. fillchar(sechdr,sizeof(sechdr),0);
  815. move(target_asm.secnames[sec][1],sechdr.name,length(target_asm.secnames[sec]));
  816. if not win32 then
  817. begin
  818. sechdr.rvaofs:=sects[sec]^.mempos;
  819. sechdr.vsize:=sects[sec]^.mempos;
  820. end
  821. else
  822. begin
  823. if sec=sec_bss then
  824. sechdr.vsize:=sects[sec]^.len;
  825. end;
  826. sechdr.datalen:=sects[sec]^.len;
  827. if (sects[sec]^.len>0) and assigned(sects[sec]^.data) then
  828. sechdr.datapos:=sects[sec]^.datapos;
  829. sechdr.relocpos:=sects[sec]^.relocpos;
  830. sechdr.nrelocs:=sects[sec]^.nrelocs;
  831. sechdr.flags:=sects[sec]^.flags;
  832. writer^.write(sechdr,sizeof(sechdr));
  833. end;
  834. { Sections }
  835. for sec:=low(tsection) to high(tsection) do
  836. if assigned(sects[sec]) and
  837. assigned(sects[sec]^.data) then
  838. begin
  839. { For the stab section we need an HdrSym which can now be
  840. calculated more easily }
  841. if sec=sec_stab then
  842. begin
  843. pcoffstab(sects[sec_stab]^.data^.data)^.nvalue:=sects[sec_stabstr]^.len;
  844. pcoffstab(sects[sec_stab]^.data^.data)^.strpos:=1;
  845. pcoffstab(sects[sec_stab]^.data^.data)^.ndesc:=
  846. (sects[sec_stab]^.len div sizeof(coffstab))-1{+1 according to gas output PM};
  847. end;
  848. writer^.write(sects[sec]^.data^.data^,sects[sec]^.data^.usedsize);
  849. end;
  850. { Relocs }
  851. for sec:=low(tsection) to high(tsection) do
  852. if assigned(sects[sec]) then
  853. write_relocs(sects[sec]);
  854. { Symbols }
  855. write_symbols;
  856. { Strings }
  857. i:=strs^.usedsize+4;
  858. writer^.write(i,4);
  859. writer^.write(strs^.data^,strs^.usedsize);
  860. end;
  861. {****************************************************************************
  862. DJGppcoffoutput
  863. ****************************************************************************}
  864. constructor tdjgppcoffoutput.init(smart:boolean);
  865. begin
  866. inherited init(smart);
  867. win32:=false;
  868. end;
  869. function tdjgppcoffoutput.text_flags : longint;
  870. begin
  871. text_flags:=$20;
  872. end;
  873. function tdjgppcoffoutput.data_flags : longint;
  874. begin
  875. data_flags:=$40;
  876. end;
  877. function tdjgppcoffoutput.bss_flags : longint;
  878. begin
  879. bss_flags:=$80;
  880. end;
  881. {****************************************************************************
  882. Win32coffoutput
  883. ****************************************************************************}
  884. constructor twin32coffoutput.init(smart:boolean);
  885. begin
  886. inherited init(smart);
  887. win32:=true;
  888. end;
  889. function twin32coffoutput.text_flags : longint;
  890. begin
  891. text_flags:=$60000020; { same as as 2.9.1 }
  892. end;
  893. function twin32coffoutput.data_flags : longint;
  894. begin
  895. data_flags:=$c0300040;
  896. end;
  897. function twin32coffoutput.bss_flags : longint;
  898. begin
  899. bss_flags:=$c0300080;
  900. end;
  901. function twin32coffoutput.edata_flags : longint;
  902. begin
  903. edata_flags:=$c0300040;
  904. end;
  905. function twin32coffoutput.idata_flags : longint;
  906. begin
  907. idata_flags:=$40000000;
  908. end;
  909. end.
  910. {
  911. $Log$
  912. Revision 1.24 2000-06-21 20:56:37 pierre
  913. * fix the problem of long mangledname in internal writer
  914. Revision 1.23 2000/04/12 12:42:29 pierre
  915. * fix the -g-l option
  916. Revision 1.22 2000/03/10 16:05:28 pierre
  917. * check that symbol is in object
  918. Revision 1.21 2000/03/10 09:15:54 pierre
  919. * rva relocation bug fixed
  920. Revision 1.20 2000/03/09 14:29:47 pierre
  921. * fix for the stab section size changes with smartlinking
  922. Revision 1.19 2000/02/09 13:22:54 peter
  923. * log truncated
  924. Revision 1.18 2000/01/12 10:38:18 peter
  925. * smartlinking fixes for binary writer
  926. * release alignreg code and moved instruction writing align to cpuasm,
  927. but it doesn't use the specified register yet
  928. Revision 1.17 2000/01/07 01:14:27 peter
  929. * updated copyright to 2000
  930. Revision 1.16 1999/12/20 22:29:26 pierre
  931. * relocation with debug info in rva (only with internal compiler)
  932. Revision 1.15 1999/11/30 10:40:43 peter
  933. + ttype, tsymlist
  934. Revision 1.14 1999/11/06 14:34:21 peter
  935. * truncated log to 20 revs
  936. Revision 1.13 1999/11/02 15:06:57 peter
  937. * import library fixes for win32
  938. * alignment works again
  939. Revision 1.12 1999/08/16 15:35:25 pierre
  940. * fix for DLL relocation problems
  941. * external bss vars had wrong stabs for pecoff
  942. + -WB11000000 to specify default image base, allows to
  943. load several DLLs with debugging info included
  944. (relocatable DLL are stripped because the relocation
  945. of the .Stab section is misplaced by ldw)
  946. Revision 1.11 1999/08/11 17:17:38 peter
  947. * fixed rva writting for section relocs
  948. * fixed section flags for edata and idata
  949. Revision 1.10 1999/08/04 00:23:05 florian
  950. * renamed i386asm and i386base to cpuasm and cpubase
  951. }