og386cff.pas 31 KB

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