og386cff.pas 32 KB

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