og386cff.pas 32 KB

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