og386cff.pas 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Peter Vreman and Pierre Muller
  4. Contains the 386 binary coff writer
  5. * This code was inspired by the NASM sources
  6. The Netwide Assembler is copyright (C) 1996 Simon Tatham and
  7. Julian Hall. All rights reserved.
  8. This program is free software; you can redistribute it and/or modify
  9. it under the terms of the GNU General Public License as published by
  10. the Free Software Foundation; either version 2 of the License, or
  11. (at your option) any later version.
  12. This program is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. GNU General Public License for more details.
  16. You should have received a copy of the GNU General Public License
  17. along with this program; if not, write to the Free Software
  18. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19. ****************************************************************************
  20. }
  21. unit og386cff;
  22. {$i defines.inc}
  23. {
  24. Notes on COFF:
  25. (0) When I say `standard COFF' below, I mean `COFF as output and
  26. used by DJGPP'. I assume DJGPP gets it right.
  27. (1) Win32 appears to interpret the term `relative relocation'
  28. differently from standard COFF. Standard COFF understands a
  29. relative relocation to mean that during relocation you add the
  30. address of the symbol you're referencing, and subtract the base
  31. address of the section you're in. Win32 COFF, by contrast, seems
  32. to add the address of the symbol and then subtract the address
  33. of THE BYTE AFTER THE RELOCATED DWORD. Hence the two formats are
  34. subtly incompatible.
  35. (2) Win32 doesn't bother putting any flags in the header flags
  36. field (at offset 0x12 into the file).
  37. (3) Win32 uses some extra flags into the section header table:
  38. it defines flags 0x80000000 (writable), 0x40000000 (readable)
  39. and 0x20000000 (executable), and uses them in the expected
  40. combinations. It also defines 0x00100000 through 0x00700000 for
  41. section alignments of 1 through 64 bytes.
  42. (4) Both standard COFF and Win32 COFF seem to use the DWORD
  43. field directly after the section name in the section header
  44. table for something strange: they store what the address of the
  45. section start point _would_ be, if you laid all the sections end
  46. to end starting at zero. Dunno why. Microsoft's documentation
  47. lists this field as "Virtual Size of Section", which doesn't
  48. seem to fit at all. In fact, Win32 even includes non-linked
  49. sections such as .drectve in this calculation.
  50. (5) Standard COFF does something very strange to common
  51. variables: the relocation point for a common variable is as far
  52. _before_ the variable as its size stretches out _after_ it. So
  53. we must fix up common variable references. Win32 seems to be
  54. sensible on this one.
  55. }
  56. interface
  57. uses
  58. cobjects,
  59. systems,cpubase,aasm,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 : TAsmsymbind;
  76. end;
  77. pcoffsection = ^tcoffsection;
  78. tcoffsection = object
  79. index : tsection;
  80. secsymidx : longint; { index for the section in symtab }
  81. data : PDynamicArray;
  82. size,
  83. fillsize,
  84. mempos,
  85. len,
  86. datapos,
  87. relocpos,
  88. nrelocs,
  89. align,
  90. flags : longint;
  91. relochead : PReloc;
  92. reloctail : ^PReloc;
  93. constructor init(sec:TSection;Aflags:longint);
  94. destructor done;
  95. procedure write(var d;l:longint);
  96. procedure alloc(l:longint);
  97. procedure addsymreloc(ofs:longint;p:pasmsymbol;relative:relative_type);
  98. procedure addsectionreloc(ofs:longint;sec:tsection;relative:relative_type);
  99. end;
  100. pgenericcoffoutput = ^tgenericcoffoutput;
  101. tgenericcoffoutput = object(tobjectoutput)
  102. win32 : boolean;
  103. sects : array[TSection] of PCoffSection;
  104. strs,
  105. syms : Pdynamicarray;
  106. initsym : longint;
  107. constructor init(smart:boolean);
  108. destructor done;virtual;
  109. procedure initwriting(Aplace:tcutplace);virtual;
  110. procedure donewriting;virtual;
  111. function sectionsize(s:tsection):longint;virtual;
  112. procedure setsectionsizes(var s:tsecsize);virtual;
  113. procedure writebytes(var data;len:longint);virtual;
  114. procedure writealloc(len:longint);virtual;
  115. procedure writealign(len:longint);virtual;
  116. procedure writereloc(data,len:longint;p:pasmsymbol;relative:relative_type);virtual;
  117. procedure writesymbol(p:pasmsymbol);virtual;
  118. procedure writestabs(section:tsection;offset:longint;p:pchar;nidx,nother,line:longint;reloc:boolean);virtual;
  119. procedure writesymstabs(section:tsection;offset:longint;p:pchar;ps:pasmsymbol;
  120. nidx,nother,line:longint;reloc:boolean);virtual;
  121. function text_flags : longint;virtual;
  122. function data_flags : longint;virtual;
  123. function bss_flags : longint;virtual;
  124. function idata_flags : longint;virtual;
  125. function edata_flags : longint;virtual;
  126. private
  127. procedure createsection(sec:tsection);
  128. procedure write_relocs(s:pcoffsection);
  129. procedure write_symbol(const name:string;strpos,value,section,typ,aux:longint);
  130. procedure write_symbols;
  131. procedure writetodisk;
  132. end;
  133. pdjgppcoffoutput = ^tdjgppcoffoutput;
  134. tdjgppcoffoutput = object(tgenericcoffoutput)
  135. constructor init(smart:boolean);
  136. function text_flags : longint;virtual;
  137. function data_flags : longint;virtual;
  138. function bss_flags : longint;virtual;
  139. end;
  140. pwin32coffoutput = ^twin32coffoutput;
  141. twin32coffoutput = object(tgenericcoffoutput)
  142. constructor init(smart:boolean);
  143. function text_flags : longint;virtual;
  144. function data_flags : longint;virtual;
  145. function bss_flags : longint;virtual;
  146. function idata_flags : longint;virtual;
  147. function edata_flags : longint;virtual;
  148. end;
  149. implementation
  150. uses
  151. {$ifdef delphi}
  152. sysutils,
  153. {$else}
  154. strings,
  155. {$endif}
  156. cutils,verbose,
  157. globtype,globals,fmodule;
  158. const
  159. symbolresize = 200*18;
  160. strsresize = 8192;
  161. DataResize = 8192;
  162. type
  163. { Structures which are written directly to the output file }
  164. coffheader=packed record
  165. mach : word;
  166. nsects : word;
  167. time : longint;
  168. sympos : longint;
  169. syms : longint;
  170. opthdr : word;
  171. flag : word;
  172. end;
  173. coffsechdr=packed record
  174. name : array[0..7] of char;
  175. vsize : longint;
  176. rvaofs : longint;
  177. datalen : longint;
  178. datapos : longint;
  179. relocpos : longint;
  180. lineno1 : longint;
  181. nrelocs : word;
  182. lineno2 : word;
  183. flags : longint;
  184. end;
  185. coffsectionrec=packed record
  186. len : longint;
  187. nrelocs : word;
  188. empty : array[0..11] of char;
  189. end;
  190. coffreloc=packed record
  191. address : longint;
  192. sym : longint;
  193. relative : word;
  194. end;
  195. coffsymbol=packed record
  196. name : array[0..3] of char; { real is [0..7], which overlaps the strpos ! }
  197. strpos : longint;
  198. value : longint;
  199. section : smallint;
  200. empty : smallint;
  201. typ : byte;
  202. aux : byte;
  203. end;
  204. pcoffstab=^coffstab;
  205. coffstab=packed record
  206. strpos : longint;
  207. ntype : byte;
  208. nother : byte;
  209. ndesc : word;
  210. nvalue : longint;
  211. end;
  212. {****************************************************************************
  213. TSection
  214. ****************************************************************************}
  215. constructor tcoffsection.init(sec:TSection;Aflags:longint);
  216. begin
  217. index:=sec;
  218. secsymidx:=0;
  219. flags:=AFlags;
  220. { alignment after section }
  221. case sec of
  222. sec_code,
  223. sec_data,
  224. sec_bss :
  225. align:=4;
  226. else
  227. align:=1;
  228. end;
  229. { filled after pass 1 }
  230. size:=0;
  231. fillsize:=0;
  232. mempos:=0;
  233. { pass 2 data }
  234. relocHead:=nil;
  235. relocTail:=@relocHead;
  236. Len:=0;
  237. NRelocs:=0;
  238. if sec=sec_bss then
  239. data:=nil
  240. else
  241. new(Data,Init(DataResize));
  242. end;
  243. destructor tcoffsection.done;
  244. begin
  245. if assigned(Data) then
  246. dispose(Data,done);
  247. end;
  248. procedure tcoffsection.write(var d;l:longint);
  249. begin
  250. if not assigned(Data) then
  251. Internalerror(3334441);
  252. Data^.write(d,l);
  253. inc(len,l);
  254. end;
  255. procedure tcoffsection.alloc(l:longint);
  256. begin
  257. if assigned(Data) then
  258. Internalerror(3334442);
  259. inc(len,l);
  260. end;
  261. procedure tcoffsection.addsymreloc(ofs:longint;p:pasmsymbol;relative:relative_type);
  262. var
  263. r : PReloc;
  264. begin
  265. new(r);
  266. reloctail^:=r;
  267. reloctail:=@r^.next;
  268. r^.next:=nil;
  269. r^.address:=ofs+mempos;
  270. r^.symbol:=p;
  271. r^.section:=sec_none;
  272. r^.relative:=relative;
  273. inc(nrelocs);
  274. end;
  275. procedure tcoffsection.addsectionreloc(ofs:longint;sec:tsection;relative:relative_type);
  276. var
  277. r : PReloc;
  278. begin
  279. new(r);
  280. reloctail^:=r;
  281. reloctail:=@r^.next;
  282. r^.next:=nil;
  283. r^.address:=ofs+mempos;
  284. r^.symbol:=nil;
  285. r^.section:=sec;
  286. r^.relative:=relative;
  287. inc(nrelocs);
  288. end;
  289. {****************************************************************************
  290. Genericcoffoutput
  291. ****************************************************************************}
  292. constructor tgenericcoffoutput.init(smart:boolean);
  293. begin
  294. inherited init(smart);
  295. end;
  296. destructor tgenericcoffoutput.done;
  297. begin
  298. inherited done;
  299. end;
  300. procedure tgenericcoffoutput.initwriting(Aplace:tcutplace);
  301. var
  302. s : string;
  303. begin
  304. inherited initwriting(Aplace);
  305. { reset }
  306. initsym:=0;
  307. new(syms,init(symbolresize));
  308. new(strs,init(strsresize));
  309. FillChar(Sects,sizeof(Sects),0);
  310. { we need at least the following 3 sections }
  311. createsection(sec_code);
  312. createsection(sec_data);
  313. createsection(sec_bss);
  314. if (cs_gdb_lineinfo in aktglobalswitches) or
  315. (cs_debuginfo in aktmoduleswitches) then
  316. begin
  317. createsection(sec_stab);
  318. createsection(sec_stabstr);
  319. writestabs(sec_none,0,nil,0,0,0,false);
  320. { write zero pchar and name together (PM) }
  321. s:=#0+SplitFileName(current_module^.mainsource^)+#0;
  322. sects[sec_stabstr]^.write(s[1],length(s));
  323. end;
  324. end;
  325. procedure tgenericcoffoutput.donewriting;
  326. var
  327. sec : tsection;
  328. begin
  329. { Only write the .o if there are no errors }
  330. if errorcount=0 then
  331. writetodisk;
  332. dispose(syms,done);
  333. dispose(strs,done);
  334. for sec:=low(tsection) to high(tsection) do
  335. if assigned(sects[sec]) then
  336. dispose(sects[sec],done);
  337. inherited donewriting;
  338. end;
  339. function tgenericcoffoutput.sectionsize(s:tsection):longint;
  340. begin
  341. if assigned(sects[s]) then
  342. sectionsize:=sects[s]^.len
  343. else
  344. sectionsize:=0;
  345. end;
  346. function tgenericcoffoutput.text_flags : longint;
  347. begin
  348. text_flags:=0;
  349. end;
  350. function tgenericcoffoutput.data_flags : longint;
  351. begin
  352. data_flags:=0;
  353. end;
  354. function tgenericcoffoutput.bss_flags : longint;
  355. begin
  356. bss_flags:=0;
  357. end;
  358. function tgenericcoffoutput.edata_flags : longint;
  359. begin
  360. edata_flags:=0;
  361. end;
  362. function tgenericcoffoutput.idata_flags : longint;
  363. begin
  364. idata_flags:=0;
  365. end;
  366. procedure tgenericcoffoutput.createsection(sec:TSection);
  367. var
  368. Aflags : longint;
  369. begin
  370. Aflags:=0;
  371. case sec of
  372. sec_code :
  373. Aflags:=text_flags;
  374. sec_data :
  375. Aflags:=data_flags;
  376. sec_bss :
  377. Aflags:=bss_flags;
  378. sec_idata2,
  379. sec_idata4,
  380. sec_idata5,
  381. sec_idata6,
  382. sec_idata7 :
  383. Aflags:=idata_flags;
  384. sec_edata :
  385. Aflags:=edata_flags;
  386. else
  387. Aflags:=0;
  388. end;
  389. sects[sec]:=new(PcoffSection,init(Sec,Aflags));
  390. end;
  391. procedure tgenericcoffoutput.writesymbol(p:pasmsymbol);
  392. var
  393. pos : longint;
  394. sym : tsymbol;
  395. s : string;
  396. begin
  397. { already written ? }
  398. if p^.idx<>-1 then
  399. exit;
  400. { be sure that the section will exists }
  401. if (p^.section<>sec_none) and not(assigned(sects[p^.section])) then
  402. createsection(p^.section);
  403. { symbolname }
  404. pos:=strs^.size+4;
  405. s:=p^.name;
  406. if length(s)>8 then
  407. begin
  408. if length(s)<255 then
  409. s:=s+#0;
  410. strs^.write(s[1],length(s));
  411. { if the length is 255 we need to addd the terminal #0
  412. separately bug report from Florian 20/6/2000 }
  413. if length(s)=255 then
  414. begin
  415. s:=#0;
  416. strs^.write(s[1],length(s));
  417. end;
  418. end
  419. else
  420. pos:=-1;
  421. FillChar(sym,sizeof(sym),0);
  422. sym.strpos:=pos;
  423. if pos=-1 then
  424. sym.name:=s;
  425. sym.value:=p^.size;
  426. sym.typ:=p^.bind;
  427. { coff doesn't have common, replace with external }
  428. if sym.typ=AB_COMMON then
  429. sym.typ:=AB_EXTERNAL;
  430. { if local of global then set the section value to the address
  431. of the symbol }
  432. if sym.typ in [AB_LOCAL,AB_GLOBAL] then
  433. begin
  434. sym.section:=p^.section;
  435. sym.value:=p^.address+sects[p^.section]^.mempos;
  436. end;
  437. { update the asmsymbol index }
  438. p^.idx:=syms^.size div sizeof(TSymbol);
  439. { store the symbol, but not the local ones (PM) }
  440. if (sym.typ<>AB_LOCAL) or ((copy(s,1,2)<>'.L') and
  441. ((copy(s,1,1)<>'L') or not win32)) then
  442. syms^.write(sym,sizeof(tsymbol));
  443. { make the exported syms known to the objectwriter
  444. (needed for .a generation) }
  445. if (sym.typ=AB_GLOBAL) or
  446. ((sym.typ=AB_EXTERNAL) and (sym.value=p^.size) and (sym.value>0)) then
  447. writer^.writesym(p^.name);
  448. end;
  449. procedure tgenericcoffoutput.writebytes(var data;len:longint);
  450. begin
  451. if not assigned(sects[currsec]) then
  452. createsection(currsec);
  453. sects[currsec]^.write(data,len);
  454. end;
  455. procedure tgenericcoffoutput.writealloc(len:longint);
  456. begin
  457. if not assigned(sects[currsec]) then
  458. createsection(currsec);
  459. sects[currsec]^.alloc(len);
  460. end;
  461. procedure tgenericcoffoutput.writealign(len:longint);
  462. var
  463. modulo : longint;
  464. begin
  465. if not assigned(sects[currsec]) then
  466. createsection(currsec);
  467. modulo:=sects[currsec]^.len mod len;
  468. if modulo > 0 then
  469. sects[currsec]^.alloc(len-modulo);
  470. end;
  471. procedure tgenericcoffoutput.writereloc(data,len:longint;p:pasmsymbol;relative:relative_type);
  472. var
  473. symaddr : longint;
  474. begin
  475. if not assigned(sects[currsec]) then
  476. createsection(currsec);
  477. if assigned(p) then
  478. begin
  479. { real address of the symbol }
  480. symaddr:=p^.address;
  481. if p^.section<>sec_none then
  482. inc(symaddr,sects[p^.section]^.mempos);
  483. { no symbol relocation need inside a section }
  484. if p^.section=currsec then
  485. begin
  486. case relative of
  487. relative_false :
  488. begin
  489. sects[currsec]^.addsectionreloc(sects[currsec]^.len,currsec,relative_false);
  490. inc(data,symaddr);
  491. end;
  492. relative_true :
  493. begin
  494. inc(data,symaddr-len-sects[currsec]^.len);
  495. end;
  496. relative_rva :
  497. begin
  498. { don't know if this can happens !! }
  499. { does this work ?? }
  500. sects[currsec]^.addsectionreloc(sects[currsec]^.len,currsec,relative_rva);
  501. inc(data,symaddr);
  502. end;
  503. end;
  504. end
  505. else
  506. begin
  507. writesymbol(p);
  508. if (p^.section<>sec_none) and (relative<>relative_true) then
  509. sects[currsec]^.addsectionreloc(sects[currsec]^.len,p^.section,relative)
  510. else
  511. sects[currsec]^.addsymreloc(sects[currsec]^.len,p,relative);
  512. if not win32 then {seems wrong to me (PM) }
  513. inc(data,symaddr)
  514. else
  515. if (relative<>relative_true) and (p^.section<>sec_none) then
  516. inc(data,symaddr);
  517. if relative=relative_true then
  518. begin
  519. if win32 then
  520. dec(data,len-4)
  521. else
  522. dec(data,len+sects[currsec]^.len);
  523. end;
  524. end;
  525. end;
  526. sects[currsec]^.write(data,len);
  527. end;
  528. procedure tgenericcoffoutput.writestabs(section:tsection;offset:longint;p:pchar;nidx,nother,line:longint;reloc : boolean);
  529. var
  530. stab : coffstab;
  531. s : tsection;
  532. begin
  533. { This is wrong because
  534. sec_none is used only for external bss
  535. if section=sec_none then
  536. s:=currsec
  537. else }
  538. s:=section;
  539. { local var can be at offset -1 !! PM }
  540. if reloc then
  541. begin
  542. if (offset=-1) then
  543. begin
  544. if s=sec_none then
  545. offset:=0
  546. else
  547. offset:=sects[s]^.len;
  548. end;
  549. if (s<>sec_none) then
  550. inc(offset,sects[s]^.mempos);
  551. end;
  552. if assigned(p) and (p[0]<>#0) then
  553. begin
  554. stab.strpos:=sects[sec_stabstr]^.len;
  555. sects[sec_stabstr]^.write(p^,strlen(p)+1);
  556. end
  557. else
  558. stab.strpos:=0;
  559. stab.ntype:=nidx;
  560. stab.ndesc:=line;
  561. stab.nother:=nother;
  562. stab.nvalue:=offset;
  563. sects[sec_stab]^.write(stab,sizeof(stab));
  564. { when the offset is not 0 then write a relocation, take also the
  565. hdrstab into account with the offset }
  566. if reloc then
  567. if DLLSource and RelocSection then
  568. { avoid relocation in the .stab section
  569. because it ends up in the .reloc section instead }
  570. sects[sec_stab]^.addsectionreloc(sects[sec_stab]^.len-4,s,relative_rva)
  571. else
  572. sects[sec_stab]^.addsectionreloc(sects[sec_stab]^.len-4,s,relative_false);
  573. end;
  574. procedure tgenericcoffoutput.writesymstabs(section:tsection;offset:longint;p:pchar;ps:pasmsymbol;
  575. nidx,nother,line:longint;reloc:boolean);
  576. var
  577. stab : coffstab;
  578. s : tsection;
  579. begin
  580. { This is wrong because
  581. sec_none is used only for external bss
  582. if section=sec_none then
  583. s:=currsec
  584. else }
  585. s:=section;
  586. { do not use the size stored in offset field
  587. this is DJGPP specific ! PM }
  588. if win32 then
  589. offset:=0;
  590. { local var can be at offset -1 !! PM }
  591. if reloc then
  592. begin
  593. if (offset=-1) then
  594. begin
  595. if s=sec_none then
  596. offset:=0
  597. else
  598. offset:=sects[s]^.len;
  599. end;
  600. if (s<>sec_none) then
  601. inc(offset,sects[s]^.mempos);
  602. end;
  603. if assigned(p) and (p[0]<>#0) then
  604. begin
  605. stab.strpos:=sects[sec_stabstr]^.len;
  606. sects[sec_stabstr]^.write(p^,strlen(p)+1);
  607. end
  608. else
  609. stab.strpos:=0;
  610. stab.ntype:=nidx;
  611. stab.ndesc:=line;
  612. stab.nother:=nother;
  613. stab.nvalue:=offset;
  614. sects[sec_stab]^.write(stab,sizeof(stab));
  615. { when the offset is not 0 then write a relocation, take also the
  616. hdrstab into account with the offset }
  617. if reloc then
  618. if DLLSource and RelocSection then
  619. { avoid relocation in the .stab section
  620. because it ends up in the .reloc section instead }
  621. sects[sec_stab]^.addsymreloc(sects[sec_stab]^.len-4,ps,relative_rva)
  622. else
  623. sects[sec_stab]^.addsymreloc(sects[sec_stab]^.len-4,ps,relative_false);
  624. end;
  625. procedure tgenericcoffoutput.setsectionsizes(var s:tsecsize);
  626. var
  627. align,
  628. mempos : longint;
  629. sec : tsection;
  630. begin
  631. { multiply stab with real size }
  632. s[sec_stab]:=s[sec_stab]*sizeof(coffstab);
  633. { if debug then also count header stab }
  634. if (cs_debuginfo in aktmoduleswitches) then
  635. begin
  636. inc(s[sec_stab],sizeof(coffstab));
  637. inc(s[sec_stabstr],length(SplitFileName(current_module^.mainsource^))+2);
  638. end;
  639. { fix all section }
  640. mempos:=0;
  641. for sec:=low(tsection) to high(tsection) do
  642. begin
  643. if (s[sec]>0) and (not assigned(sects[sec])) then
  644. createsection(sec);
  645. if assigned(sects[sec]) then
  646. begin
  647. sects[sec]^.size:=s[sec];
  648. sects[sec]^.mempos:=mempos;
  649. { calculate the alignment }
  650. align:=sects[sec]^.align;
  651. sects[sec]^.fillsize:=align-(sects[sec]^.size and (align-1));
  652. if sects[sec]^.fillsize=align then
  653. sects[sec]^.fillsize:=0;
  654. { next section position, not for win32 which uses
  655. relative addresses }
  656. if not win32 then
  657. inc(mempos,sects[sec]^.size+sects[sec]^.fillsize);
  658. end;
  659. end;
  660. end;
  661. {***********************************************
  662. Writing to disk
  663. ***********************************************}
  664. procedure tgenericcoffoutput.write_relocs(s:pcoffsection);
  665. var
  666. rel : coffreloc;
  667. hr,r : preloc;
  668. begin
  669. r:=s^.relochead;
  670. while assigned(r) do
  671. begin
  672. rel.address:=r^.address;
  673. if assigned(r^.symbol) then
  674. begin
  675. if (r^.symbol^.bind=AB_LOCAL) then
  676. rel.sym:=2*sects[r^.symbol^.section]^.secsymidx
  677. else
  678. begin
  679. if r^.symbol^.idx=-1 then
  680. internalerror(4321);
  681. rel.sym:=r^.symbol^.idx+initsym;
  682. end;
  683. end
  684. else if r^.section<>sec_none then
  685. rel.sym:=2*sects[r^.section]^.secsymidx
  686. else
  687. rel.sym:=0;
  688. case r^.relative of
  689. relative_true : rel.relative:=$14;
  690. relative_false : rel.relative:=$6;
  691. relative_rva : rel.relative:=$7;
  692. end;
  693. writer^.write(rel,sizeof(rel));
  694. { goto next and dispose this reloc }
  695. hr:=r;
  696. r:=r^.next;
  697. dispose(hr);
  698. end;
  699. end;
  700. procedure tgenericcoffoutput.write_symbol(const name:string;strpos,value,section,typ,aux:longint);
  701. var
  702. sym : coffsymbol;
  703. begin
  704. FillChar(sym,sizeof(sym),0);
  705. if strpos=-1 then
  706. move(name[1],sym.name,length(name))
  707. else
  708. sym.strpos:=strpos;
  709. sym.value:=value;
  710. sym.section:=section;
  711. sym.typ:=typ;
  712. sym.aux:=aux;
  713. writer^.write(sym,sizeof(sym));
  714. end;
  715. procedure tgenericcoffoutput.write_symbols;
  716. var
  717. filename : string[18];
  718. sec : tsection;
  719. sectionval,
  720. i : longint;
  721. globalval : byte;
  722. secrec : coffsectionrec;
  723. sym : tsymbol;
  724. begin
  725. { The `.file' record, and the file name auxiliary record. }
  726. write_symbol ('.file', -1, 0, -2, $67, 1);
  727. fillchar(filename,sizeof(filename),0);
  728. filename:=SplitFileName(current_module^.mainsource^);
  729. writer^.write(filename[1],sizeof(filename)-1);
  730. { The section records, with their auxiliaries, also store the
  731. symbol index }
  732. for sec:=low(tsection) to high(tsection) do
  733. if assigned(sects[sec]) then
  734. begin
  735. write_symbol(target_asm.secnames[sec],-1,sects[sec]^.mempos,sects[sec]^.secsymidx,3,1);
  736. fillchar(secrec,sizeof(secrec),0);
  737. secrec.len:=sects[sec]^.len;
  738. secrec.nrelocs:=sects[sec]^.nrelocs;
  739. writer^.write(secrec,sizeof(secrec));
  740. end;
  741. { The real symbols. }
  742. syms^.seek(0);
  743. for i:=1 to syms^.size div sizeof(TSymbol) do
  744. begin
  745. syms^.read(sym,sizeof(TSymbol));
  746. if sym.typ=AB_LOCAL then
  747. globalval:=3
  748. else
  749. globalval:=2;
  750. if assigned(sects[sym.section]) then
  751. sectionval:=sects[sym.section]^.secsymidx
  752. else
  753. sectionval:=0;
  754. write_symbol(sym.name,sym.strpos,sym.value,sectionval,globalval,0);
  755. end;
  756. end;
  757. procedure tgenericcoffoutput.writetodisk;
  758. var
  759. datapos,secsymidx,
  760. nsects,sympos,i : longint;
  761. hstab : coffstab;
  762. gotreloc : boolean;
  763. sec : tsection;
  764. header : coffheader;
  765. sechdr : coffsechdr;
  766. empty : array[0..15] of byte;
  767. hp : pdynamicblock;
  768. begin
  769. { calc amount of sections we have and align sections at 4 bytes }
  770. fillchar(empty,sizeof(empty),0);
  771. nsects:=0;
  772. for sec:=low(tsection) to high(tsection) do
  773. if assigned(sects[sec]) then
  774. begin
  775. {$ifdef EXTDEBUG}
  776. { check if the section is still the same size }
  777. if (sects[sec]^.len<>sects[sec]^.size) then
  778. Comment(V_Warning,'Size of section changed '+
  779. tostr(sects[sec]^.size)+'->'+tostr(sects[sec]^.len)+
  780. ' ['+target_asm.secnames[sec]+']');
  781. {$endif EXTDEBUG}
  782. { fill with zero }
  783. if sects[sec]^.fillsize>0 then
  784. begin
  785. if assigned(sects[sec]^.data) then
  786. sects[sec]^.write(empty,sects[sec]^.fillsize)
  787. else
  788. sects[sec]^.alloc(sects[sec]^.fillsize);
  789. end;
  790. inc(nsects);
  791. end;
  792. { Calculate the filepositions }
  793. datapos:=sizeof(coffheader)+sizeof(coffsechdr)*nsects;
  794. initsym:=2; { 2 for the file }
  795. { sections first }
  796. secsymidx:=0;
  797. for sec:=low(tsection) to high(tsection) do
  798. if assigned(sects[sec]) then
  799. begin
  800. inc(secsymidx);
  801. sects[sec]^.secsymidx:=secsymidx;
  802. sects[sec]^.datapos:=datapos;
  803. if assigned(sects[sec]^.data) then
  804. inc(datapos,sects[sec]^.len);
  805. inc(initsym,2); { 2 for each section }
  806. end;
  807. { relocs }
  808. gotreloc:=false;
  809. for sec:=low(tsection) to high(tsection) do
  810. if assigned(sects[sec]) then
  811. begin
  812. sects[sec]^.relocpos:=datapos;
  813. inc(datapos,10*sects[sec]^.nrelocs);
  814. if (not gotreloc) and (sects[sec]^.nrelocs>0) then
  815. gotreloc:=true;
  816. end;
  817. { symbols }
  818. sympos:=datapos;
  819. { COFF header }
  820. fillchar(header,sizeof(coffheader),0);
  821. header.mach:=$14c;
  822. header.nsects:=nsects;
  823. header.sympos:=sympos;
  824. header.syms:=(syms^.size div sizeof(TSymbol))+initsym;
  825. if gotreloc then
  826. header.flag:=$104
  827. else
  828. header.flag:=$105;
  829. writer^.write(header,sizeof(header));
  830. { Section headers }
  831. for sec:=low(tsection) to high(tsection) do
  832. if assigned(sects[sec]) then
  833. begin
  834. fillchar(sechdr,sizeof(sechdr),0);
  835. move(target_asm.secnames[sec][1],sechdr.name,length(target_asm.secnames[sec]));
  836. if not win32 then
  837. begin
  838. sechdr.rvaofs:=sects[sec]^.mempos;
  839. sechdr.vsize:=sects[sec]^.mempos;
  840. end
  841. else
  842. begin
  843. if sec=sec_bss then
  844. sechdr.vsize:=sects[sec]^.len;
  845. end;
  846. sechdr.datalen:=sects[sec]^.len;
  847. if (sects[sec]^.len>0) and assigned(sects[sec]^.data) then
  848. sechdr.datapos:=sects[sec]^.datapos;
  849. sechdr.relocpos:=sects[sec]^.relocpos;
  850. sechdr.nrelocs:=sects[sec]^.nrelocs;
  851. sechdr.flags:=sects[sec]^.flags;
  852. writer^.write(sechdr,sizeof(sechdr));
  853. end;
  854. { Sections }
  855. for sec:=low(tsection) to high(tsection) do
  856. if assigned(sects[sec]) and
  857. assigned(sects[sec]^.data) then
  858. begin
  859. { For the stab section we need an HdrSym which can now be
  860. calculated more easily }
  861. if sec=sec_stab then
  862. begin
  863. hstab.strpos:=1;
  864. hstab.ntype:=0;
  865. hstab.nother:=0;
  866. hstab.ndesc:=(sects[sec_stab]^.len div sizeof(coffstab))-1{+1 according to gas output PM};
  867. hstab.nvalue:=sects[sec_stabstr]^.len;
  868. sects[sec_stab]^.data^.seek(0);
  869. sects[sec_stab]^.data^.write(hstab,sizeof(hstab));
  870. end;
  871. hp:=sects[sec]^.data^.firstblock;
  872. while assigned(hp) do
  873. begin
  874. writer^.write(hp^.data,hp^.used);
  875. hp:=hp^.next;
  876. end;
  877. end;
  878. { Relocs }
  879. for sec:=low(tsection) to high(tsection) do
  880. if assigned(sects[sec]) then
  881. write_relocs(sects[sec]);
  882. { Symbols }
  883. write_symbols;
  884. { Strings }
  885. i:=strs^.size+4;
  886. writer^.write(i,4);
  887. hp:=strs^.firstblock;
  888. while assigned(hp) do
  889. begin
  890. writer^.write(hp^.data,hp^.used);
  891. hp:=hp^.next;
  892. end;
  893. end;
  894. {****************************************************************************
  895. DJGppcoffoutput
  896. ****************************************************************************}
  897. constructor tdjgppcoffoutput.init(smart:boolean);
  898. begin
  899. inherited init(smart);
  900. win32:=false;
  901. end;
  902. function tdjgppcoffoutput.text_flags : longint;
  903. begin
  904. text_flags:=$20;
  905. end;
  906. function tdjgppcoffoutput.data_flags : longint;
  907. begin
  908. data_flags:=$40;
  909. end;
  910. function tdjgppcoffoutput.bss_flags : longint;
  911. begin
  912. bss_flags:=$80;
  913. end;
  914. {****************************************************************************
  915. Win32coffoutput
  916. ****************************************************************************}
  917. constructor twin32coffoutput.init(smart:boolean);
  918. begin
  919. inherited init(smart);
  920. win32:=true;
  921. end;
  922. function twin32coffoutput.text_flags : longint;
  923. begin
  924. text_flags:=$60000020; { same as as 2.9.1 }
  925. end;
  926. function twin32coffoutput.data_flags : longint;
  927. begin
  928. data_flags:=$c0300040;
  929. end;
  930. function twin32coffoutput.bss_flags : longint;
  931. begin
  932. bss_flags:=$c0300080;
  933. end;
  934. function twin32coffoutput.edata_flags : longint;
  935. begin
  936. edata_flags:=$c0300040;
  937. end;
  938. function twin32coffoutput.idata_flags : longint;
  939. begin
  940. idata_flags:=$40000000;
  941. end;
  942. end.
  943. {
  944. $Log$
  945. Revision 1.8 2000-10-21 14:36:26 peter
  946. * merged pierres fixes
  947. Revision 1.7 2000/09/24 15:06:19 peter
  948. * use defines.inc
  949. Revision 1.6 2000/09/19 23:09:07 pierre
  950. * problems wih extdebug cond. solved
  951. Revision 1.5 2000/08/27 16:11:51 peter
  952. * moved some util functions from globals,cobjects to cutils
  953. * splitted files into finput,fmodule
  954. Revision 1.4 2000/08/19 18:44:27 peter
  955. * new tdynamicarray implementation using blocks instead of
  956. reallocmem (merged)
  957. Revision 1.3 2000/07/13 12:08:26 michael
  958. + patched to 1.1.0 with former 1.09patch from peter
  959. Revision 1.2 2000/07/13 11:32:43 michael
  960. + removed logs
  961. }