og386cff.pas 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021
  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,i386base,aasm,
  59. og386;
  60. type
  61. preloc = ^treloc;
  62. treloc = packed record
  63. next : preloc;
  64. address : longint;
  65. symbol : pasmsymbol;
  66. section : tsection; { only used if symbol=nil }
  67. relative : relative_type;
  68. end;
  69. psymbol = ^tsymbol;
  70. tsymbol = packed record
  71. name : string[8];
  72. strpos : longint;
  73. section : tsection;
  74. value : longint;
  75. typ : TAsmsymtype;
  76. end;
  77. pcoffsection = ^tcoffsection;
  78. tcoffsection = object
  79. index : tsection;
  80. secidx : longint;
  81. data : PDynamicArray;
  82. size,
  83. fillsize,
  84. mempos,
  85. len,
  86. datapos,
  87. relocpos,
  88. nrelocs,
  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);
  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;
  107. destructor done;virtual;
  108. procedure initwriting;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 info_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;
  133. function text_flags : longint;virtual;
  134. function data_flags : longint;virtual;
  135. function bss_flags : longint;virtual;
  136. function info_flags : longint;virtual;
  137. end;
  138. pwin32coffoutput = ^twin32coffoutput;
  139. twin32coffoutput = object(tgenericcoffoutput)
  140. constructor init;
  141. function text_flags : longint;virtual;
  142. function data_flags : longint;virtual;
  143. function bss_flags : longint;virtual;
  144. function info_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);
  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_false;
  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;
  280. begin
  281. inherited init;
  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.info_flags : longint;
  338. begin
  339. info_flags:=0;
  340. end;
  341. procedure tgenericcoffoutput.createsection(sec:TSection);
  342. var
  343. Aflags : longint;
  344. begin
  345. Aflags:=0;
  346. case sec of
  347. sec_code :
  348. Aflags:=text_flags;
  349. sec_data :
  350. Aflags:=data_flags;
  351. sec_bss :
  352. Aflags:=bss_flags;
  353. else
  354. Aflags:=0;
  355. end;
  356. sects[sec]:=new(PcoffSection,init(Sec,Aflags));
  357. end;
  358. procedure tgenericcoffoutput.writesymbol(p:pasmsymbol);
  359. var
  360. pos : longint;
  361. sym : tsymbol;
  362. c : char;
  363. s : string;
  364. begin
  365. { already written ? }
  366. if p^.idx<>-1 then
  367. exit;
  368. { be sure that the section will exists }
  369. if (p^.section<>sec_none) and not(assigned(sects[p^.section])) then
  370. createsection(p^.section);
  371. { symbolname }
  372. pos:=strs^.usedsize+4;
  373. c:=#0;
  374. s:=p^.name;
  375. if length(s)>8 then
  376. begin
  377. s:=s+#0;
  378. strs^.write(s[1],length(s));
  379. end
  380. else
  381. pos:=-1;
  382. FillChar(sym,sizeof(sym),0);
  383. sym.strpos:=pos;
  384. if pos=-1 then
  385. sym.name:=s;
  386. sym.value:=p^.size;
  387. sym.typ:=p^.typ;
  388. { if local of global then set the section value to the address
  389. of the symbol }
  390. if p^.typ in [AS_LOCAL,AS_GLOBAL] then
  391. begin
  392. sym.section:=p^.section;
  393. sym.value:=p^.address+sects[p^.section]^.mempos;
  394. end;
  395. { update the asmsymbol index }
  396. p^.idx:=syms^.count;
  397. { store the symbol, but not the local ones (PM) }
  398. if (p^.typ<>AS_LOCAL) or ((copy(s,1,2)<>'.L') and
  399. ((copy(s,1,1)<>'L') or not win32)) then
  400. syms^.write(sym,1);
  401. { make the exported syms known to the objectwriter
  402. (needed for .a generation) }
  403. if (p^.typ=AS_GLOBAL) or
  404. ((p^.typ=AS_EXTERNAL) and (sym.value=p^.size) and (sym.value>0)) then
  405. writer^.writesym(p^.name);
  406. end;
  407. procedure tgenericcoffoutput.writebytes(var data;len:longint);
  408. begin
  409. if not assigned(sects[currsec]) then
  410. createsection(currsec);
  411. sects[currsec]^.write(data,len);
  412. end;
  413. procedure tgenericcoffoutput.writealloc(len:longint);
  414. begin
  415. if not assigned(sects[currsec]) then
  416. createsection(currsec);
  417. sects[currsec]^.alloc(len);
  418. end;
  419. procedure tgenericcoffoutput.writealign(len:longint);
  420. var modulo : longint;
  421. begin
  422. if not assigned(sects[currsec]) then
  423. createsection(currsec);
  424. modulo:=sects[currsec]^.len mod len;
  425. if modulo > 0 then
  426. sects[currsec]^.alloc(len-modulo);
  427. end;
  428. procedure tgenericcoffoutput.writereloc(data,len:longint;p:pasmsymbol;relative:relative_type);
  429. var
  430. symaddr : longint;
  431. begin
  432. if not assigned(sects[currsec]) then
  433. createsection(currsec);
  434. if assigned(p) then
  435. begin
  436. { real address of the symbol }
  437. symaddr:=p^.address;
  438. if p^.section<>sec_none then
  439. inc(symaddr,sects[p^.section]^.mempos);
  440. { no symbol relocation need inside a section }
  441. if p^.section=currsec then
  442. begin
  443. case relative of
  444. relative_false :
  445. begin
  446. sects[currsec]^.addsectionreloc(sects[currsec]^.len,currsec);
  447. inc(data,symaddr);
  448. end;
  449. relative_true :
  450. begin
  451. inc(data,symaddr-len-sects[currsec]^.len);
  452. end;
  453. relative_rva :
  454. begin
  455. { don't know if this can happens !! }
  456. { does this work ?? }
  457. sects[currsec]^.addsectionreloc(sects[currsec]^.len,currsec);
  458. inc(data,symaddr);
  459. end;
  460. end;
  461. end
  462. else
  463. begin
  464. writesymbol(p);
  465. if (p^.section<>sec_none) and (relative=relative_false) then
  466. sects[currsec]^.addsectionreloc(sects[currsec]^.len,p^.section)
  467. else
  468. sects[currsec]^.addsymreloc(sects[currsec]^.len,p,relative);
  469. if not win32 then {seems wrong to me (PM) }
  470. inc(data,symaddr)
  471. else
  472. if (relative<>relative_true) and (p^.section<>sec_none) then
  473. inc(data,symaddr);
  474. if relative=relative_true then
  475. begin
  476. if win32 then
  477. dec(data,len-4)
  478. else
  479. dec(data,len+sects[currsec]^.len);
  480. end;
  481. end;
  482. end;
  483. sects[currsec]^.write(data,len);
  484. end;
  485. procedure tgenericcoffoutput.writestabs(section:tsection;offset:longint;p:pchar;nidx,nother,line:longint;reloc : boolean);
  486. var
  487. stab : coffstab;
  488. s : tsection;
  489. begin
  490. { This is wrong because
  491. sec_none is used only for external bss
  492. if section=sec_none then
  493. s:=currsec
  494. else }
  495. s:=section;
  496. { local var can be at offset -1 !! PM }
  497. if reloc then
  498. begin
  499. if (offset=-1) then
  500. begin
  501. if s=sec_none then
  502. offset:=0
  503. else
  504. offset:=sects[s]^.len;
  505. end;
  506. if (s<>sec_none) then
  507. inc(offset,sects[s]^.mempos);
  508. end;
  509. fillchar(stab,sizeof(coffstab),0);
  510. if assigned(p) and (p[0]<>#0) then
  511. begin
  512. stab.strpos:=sects[sec_stabstr]^.len;
  513. sects[sec_stabstr]^.write(p^,strlen(p)+1);
  514. end;
  515. stab.ntype:=nidx;
  516. stab.ndesc:=line;
  517. stab.nother:=nother;
  518. stab.nvalue:=offset;
  519. sects[sec_stab]^.write(stab,sizeof(stab));
  520. { when the offset is not 0 then write a relocation, take also the
  521. hdrstab into account with the offset }
  522. if reloc then
  523. sects[sec_stab]^.addsectionreloc(sects[sec_stab]^.len-4,s);
  524. end;
  525. procedure tgenericcoffoutput.writesymstabs(section:tsection;offset:longint;p:pchar;ps:pasmsymbol;
  526. nidx,nother,line:longint;reloc:boolean);
  527. var
  528. stab : coffstab;
  529. s : tsection;
  530. begin
  531. { This is wrong because
  532. sec_none is used only for external bss
  533. if section=sec_none then
  534. s:=currsec
  535. else }
  536. s:=section;
  537. { local var can be at offset -1 !! PM }
  538. if reloc then
  539. begin
  540. if (offset=-1) then
  541. begin
  542. if s=sec_none then
  543. offset:=0
  544. else
  545. offset:=sects[s]^.len;
  546. end;
  547. if (s<>sec_none) then
  548. inc(offset,sects[s]^.mempos);
  549. end;
  550. fillchar(stab,sizeof(coffstab),0);
  551. if assigned(p) and (p[0]<>#0) then
  552. begin
  553. stab.strpos:=sects[sec_stabstr]^.len;
  554. sects[sec_stabstr]^.write(p^,strlen(p)+1);
  555. end;
  556. stab.ntype:=nidx;
  557. stab.ndesc:=line;
  558. stab.nother:=nother;
  559. stab.nvalue:=offset;
  560. sects[sec_stab]^.write(stab,sizeof(stab));
  561. { when the offset is not 0 then write a relocation, take also the
  562. hdrstab into account with the offset }
  563. if reloc then
  564. sects[sec_stab]^.addsymreloc(sects[sec_stab]^.len-4,ps,relative_false);
  565. end;
  566. procedure tgenericcoffoutput.write_relocs(s:pcoffsection);
  567. var
  568. rel : coffreloc;
  569. hr,r : preloc;
  570. begin
  571. r:=s^.relochead;
  572. while assigned(r) do
  573. begin
  574. rel.address:=r^.address;
  575. if assigned(r^.symbol) then
  576. begin
  577. if (r^.symbol^.typ=AS_LOCAL) then
  578. rel.sym:=2*sects[r^.symbol^.section]^.secidx
  579. else
  580. rel.sym:=r^.symbol^.idx+initsym;
  581. end
  582. else if r^.section<>sec_none then
  583. rel.sym:=2*sects[r^.section]^.secidx
  584. else
  585. rel.sym:=0;
  586. case r^.relative of
  587. relative_true : rel.relative:=$14;
  588. relative_false : rel.relative:=$6;
  589. relative_rva : rel.relative:=$7;
  590. end;
  591. writer^.write(rel,sizeof(rel));
  592. { goto next and dispose this reloc }
  593. hr:=r;
  594. r:=r^.next;
  595. dispose(hr);
  596. end;
  597. end;
  598. procedure tgenericcoffoutput.write_symbol(const name:string;strpos,value,section,typ,aux:longint);
  599. var
  600. sym : coffsymbol;
  601. begin
  602. FillChar(sym,sizeof(sym),0);
  603. if strpos=-1 then
  604. move(name[1],sym.name,length(name))
  605. else
  606. sym.strpos:=strpos;
  607. sym.value:=value;
  608. sym.section:=section;
  609. sym.typ:=typ;
  610. sym.aux:=aux;
  611. writer^.write(sym,sizeof(sym));
  612. end;
  613. procedure tgenericcoffoutput.write_symbols;
  614. var
  615. filename : string[18];
  616. sec : tsection;
  617. sectionval,
  618. i : longint;
  619. globalval : byte;
  620. secrec : coffsectionrec;
  621. sym : tsymbol;
  622. begin
  623. { The `.file' record, and the file name auxiliary record. }
  624. write_symbol ('.file', -1, 0, -2, $67, 1);
  625. fillchar(filename,sizeof(filename),0);
  626. filename:=SplitFileName(current_module^.mainsource^);
  627. writer^.write(filename[1],sizeof(filename)-1);
  628. { The section records, with their auxiliaries, also store the
  629. symbol index }
  630. for sec:=low(tsection) to high(tsection) do
  631. if assigned(sects[sec]) then
  632. begin
  633. write_symbol(target_asm.secnames[sec],-1,sects[sec]^.mempos,sects[sec]^.secidx,3,1);
  634. fillchar(secrec,sizeof(secrec),0);
  635. secrec.len:=sects[sec]^.len;
  636. secrec.nrelocs:=sects[sec]^.nrelocs;
  637. writer^.write(secrec,sizeof(secrec));
  638. end;
  639. { The real symbols. }
  640. syms^.seek(0);
  641. for i:=1 to syms^.count do
  642. begin
  643. syms^.read(sym,1);
  644. if sym.typ=AS_LOCAL then
  645. globalval:=3
  646. else
  647. globalval:=2;
  648. if assigned(sects[sym.section]) then
  649. sectionval:=sects[sym.section]^.secidx
  650. else
  651. sectionval:=0;
  652. write_symbol(sym.name,sym.strpos,sym.value,sectionval,globalval,0);
  653. end;
  654. end;
  655. procedure tgenericcoffoutput.setsectionsizes(var s:tsecsize);
  656. var
  657. align,
  658. mempos : longint;
  659. sec : tsection;
  660. begin
  661. { multiply stab with real size }
  662. s[sec_stab]:=s[sec_stab]*sizeof(coffstab);
  663. { if debug then also count header stab }
  664. if (cs_debuginfo in aktmoduleswitches) then
  665. begin
  666. inc(s[sec_stab],sizeof(coffstab));
  667. inc(s[sec_stabstr],length(SplitFileName(current_module^.mainsource^))+2);
  668. end;
  669. { fix all section }
  670. mempos:=0;
  671. for sec:=low(tsection) to high(tsection) do
  672. if s[sec]>0 then
  673. begin
  674. if not assigned(sects[sec]) then
  675. createsection(sec);
  676. sects[sec]^.size:=s[sec];
  677. sects[sec]^.mempos:=mempos;
  678. { calculate the alignment }
  679. if sects[sec]^.flags=0 then
  680. align:=1
  681. else
  682. align:=4;
  683. sects[sec]^.fillsize:=align-(sects[sec]^.size and (align-1));
  684. if sects[sec]^.fillsize=align then
  685. sects[sec]^.fillsize:=0;
  686. { next section position, not for win32 which uses
  687. relative addresses }
  688. if not win32 then
  689. inc(mempos,sects[sec]^.size+sects[sec]^.fillsize);
  690. end;
  691. end;
  692. procedure tgenericcoffoutput.writetodisk;
  693. var
  694. datapos,secidx,
  695. nsects,sympos,i : longint;
  696. sec : tsection;
  697. header : coffheader;
  698. sechdr : coffsechdr;
  699. empty : array[0..15] of byte;
  700. begin
  701. { calc amount of sections we have and align sections at 4 bytes }
  702. fillchar(empty,sizeof(empty),0);
  703. nsects:=0;
  704. for sec:=low(tsection) to high(tsection) do
  705. if assigned(sects[sec]) then
  706. begin
  707. { check if the section is still the same size }
  708. if (sects[sec]^.len<>sects[sec]^.size) then
  709. Comment(V_Warning,'Size of section changed '+tostr(sects[sec]^.size)+'->'+tostr(sects[sec]^.len)+
  710. ' ['+target_asm.secnames[sec]+']');
  711. { fill with zero }
  712. if sects[sec]^.fillsize>0 then
  713. begin
  714. if assigned(sects[sec]^.data) then
  715. sects[sec]^.write(empty,sects[sec]^.fillsize)
  716. else
  717. sects[sec]^.alloc(sects[sec]^.fillsize);
  718. end;
  719. inc(nsects);
  720. end;
  721. { Calculate the filepositions }
  722. datapos:=sizeof(coffheader)+sizeof(coffsechdr)*nsects;
  723. initsym:=2; { 2 for the file }
  724. { sections first }
  725. secidx:=0;
  726. for sec:=low(tsection) to high(tsection) do
  727. if assigned(sects[sec]) then
  728. begin
  729. inc(secidx);
  730. sects[sec]^.secidx:=secidx;
  731. sects[sec]^.datapos:=datapos;
  732. if assigned(sects[sec]^.data) then
  733. inc(datapos,sects[sec]^.len);
  734. inc(initsym,2); { 2 for each section }
  735. end;
  736. { relocs }
  737. for sec:=low(tsection) to high(tsection) do
  738. if assigned(sects[sec]) then
  739. begin
  740. sects[sec]^.relocpos:=datapos;
  741. inc(datapos,10*sects[sec]^.nrelocs);
  742. end;
  743. { symbols }
  744. sympos:=datapos;
  745. { COFF header }
  746. fillchar(header,sizeof(coffheader),0);
  747. header.mach:=$14c;
  748. header.nsects:=nsects;
  749. header.sympos:=sympos;
  750. header.syms:=syms^.count+initsym;
  751. header.flag:=$104;
  752. writer^.write(header,sizeof(header));
  753. { Section headers }
  754. for sec:=low(tsection) to high(tsection) do
  755. if assigned(sects[sec]) then
  756. begin
  757. fillchar(sechdr,sizeof(sechdr),0);
  758. move(target_asm.secnames[sec][1],sechdr.name,length(target_asm.secnames[sec]));
  759. if not win32 then
  760. begin
  761. sechdr.rvaofs:=sects[sec]^.mempos;
  762. sechdr.vsize:=sects[sec]^.mempos;
  763. end
  764. else
  765. begin
  766. if sec=sec_bss then
  767. sechdr.vsize:=sects[sec]^.len;
  768. end;
  769. sechdr.datalen:=sects[sec]^.len;
  770. if (sects[sec]^.len>0) and assigned(sects[sec]^.data) then
  771. sechdr.datapos:=sects[sec]^.datapos;
  772. sechdr.relocpos:=sects[sec]^.relocpos;
  773. sechdr.nrelocs:=sects[sec]^.nrelocs;
  774. sechdr.flags:=sects[sec]^.flags;
  775. writer^.write(sechdr,sizeof(sechdr));
  776. end;
  777. { Sections }
  778. for sec:=low(tsection) to high(tsection) do
  779. if assigned(sects[sec]) and
  780. assigned(sects[sec]^.data) then
  781. begin
  782. { For the stab section we need an HdrSym which can now be
  783. calculated more easily }
  784. if sec=sec_stab then
  785. begin
  786. pcoffstab(sects[sec_stab]^.data^.data)^.nvalue:=sects[sec_stabstr]^.len;
  787. pcoffstab(sects[sec_stab]^.data^.data)^.strpos:=1;
  788. pcoffstab(sects[sec_stab]^.data^.data)^.ndesc:=
  789. (sects[sec_stab]^.len div sizeof(coffstab))-1{+1 according to gas output PM};
  790. end;
  791. writer^.write(sects[sec]^.data^.data^,sects[sec]^.data^.usedsize);
  792. end;
  793. { Relocs }
  794. for sec:=low(tsection) to high(tsection) do
  795. if assigned(sects[sec]) then
  796. write_relocs(sects[sec]);
  797. { Symbols }
  798. write_symbols;
  799. { Strings }
  800. i:=strs^.usedsize+4;
  801. writer^.write(i,4);
  802. writer^.write(strs^.data^,strs^.usedsize);
  803. end;
  804. {****************************************************************************
  805. DJGppcoffoutput
  806. ****************************************************************************}
  807. constructor tdjgppcoffoutput.init;
  808. begin
  809. inherited init;
  810. win32:=false;
  811. end;
  812. function tdjgppcoffoutput.text_flags : longint;
  813. begin
  814. text_flags:=$20;
  815. end;
  816. function tdjgppcoffoutput.data_flags : longint;
  817. begin
  818. data_flags:=$40;
  819. end;
  820. function tdjgppcoffoutput.bss_flags : longint;
  821. begin
  822. bss_flags:=$80;
  823. end;
  824. function tdjgppcoffoutput.info_flags : longint;
  825. begin
  826. writeln('djgpp coff doesn''t support info sections');
  827. info_flags:=$40;
  828. end;
  829. {****************************************************************************
  830. Win32coffoutput
  831. ****************************************************************************}
  832. constructor twin32coffoutput.init;
  833. begin
  834. inherited init;
  835. win32:=true;
  836. end;
  837. function twin32coffoutput.text_flags : longint;
  838. begin
  839. text_flags:=$60000020; { same as as 2.9.1 }
  840. end;
  841. function twin32coffoutput.data_flags : longint;
  842. begin
  843. data_flags:=$c0300040;
  844. end;
  845. function twin32coffoutput.bss_flags : longint;
  846. begin
  847. bss_flags:=$c0300080;
  848. end;
  849. function twin32coffoutput.info_flags : longint;
  850. begin
  851. info_flags:=$100a00;
  852. end;
  853. end.
  854. {
  855. $Log$
  856. Revision 1.8 1999-06-03 16:39:09 pierre
  857. * EXTERNALBSS fixed for stabs and default again
  858. Revision 1.7 1999/05/21 13:55:03 peter
  859. * NEWLAB for label as symbol
  860. Revision 1.6 1999/05/19 11:54:19 pierre
  861. + experimental code for externalbss and stabs problem
  862. Revision 1.5 1999/05/09 11:38:05 peter
  863. * don't write .o and link if errors occure during assembling
  864. Revision 1.4 1999/05/07 00:36:57 pierre
  865. * added alignment code for .bss
  866. * stabs correct but externalbss disabled
  867. would need a special treatment in writestabs
  868. Revision 1.3 1999/05/05 17:34:31 peter
  869. * output is more like as 2.9.1
  870. * stabs really working for go32v2
  871. Revision 1.2 1999/05/02 22:36:35 peter
  872. * fixed section index when not all sections are used
  873. Revision 1.1 1999/05/01 13:24:24 peter
  874. * merged nasm compiler
  875. * old asm moved to oldasm/
  876. Revision 1.13 1999/03/18 20:30:49 peter
  877. + .a writer
  878. Revision 1.12 1999/03/12 00:20:06 pierre
  879. + win32 output working !
  880. Revision 1.11 1999/03/11 13:43:08 pierre
  881. * more fixes for win32
  882. Revision 1.10 1999/03/10 13:41:10 pierre
  883. + partial implementation for win32 !
  884. winhello works but pp still does not !
  885. Revision 1.9 1999/03/08 14:51:09 peter
  886. + smartlinking for ag386bin
  887. Revision 1.8 1999/03/05 13:09:52 peter
  888. * first things for tai_cut support for ag386bin
  889. Revision 1.7 1999/03/04 13:44:58 pierre
  890. * win32 pecoff sections datapos allways zero
  891. Revision 1.6 1999/03/03 11:41:54 pierre
  892. + stabs info corrected to give results near to GAS output
  893. * local labels (with .L are not stored in object anymore)
  894. so we get the same number of symbols as from GAS !
  895. Revision 1.5 1999/03/03 01:36:46 pierre
  896. + stabs output working (though not really tested)
  897. for a simple file the only difference to GAS output is due
  898. to the VMA of the different sections
  899. Revision 1.4 1999/03/02 02:56:27 peter
  900. + stabs support for binary writers
  901. * more fixes and missing updates from the previous commit :(
  902. Revision 1.3 1999/03/01 15:46:25 peter
  903. * ag386bin finally make cycles correct
  904. * prefixes are now also normal opcodes
  905. Revision 1.2 1999/02/25 21:03:10 peter
  906. * ag386bin updates
  907. + coff writer
  908. }