og386elf.pas 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Peter Vreman
  4. Contains the binary elf 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 og386elf;
  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,og386,cpubase,aasm;
  58. type
  59. preloc = ^treloc;
  60. treloc = packed record
  61. next : preloc;
  62. address : longint;
  63. symbol : pasmsymbol;
  64. section : tsection; { only used if symbol=nil }
  65. relative : relative_type;
  66. end;
  67. psymbol = ^tsymbol;
  68. tsymbol = packed record
  69. name : string[8];
  70. strpos : longint;
  71. section : longint;
  72. value : longint;
  73. typ : TAsmsymtype;
  74. end;
  75. pcoffsection = ^tcoffsection;
  76. tcoffsection = object
  77. index : tsection;
  78. data : PDynamicArray;
  79. len,
  80. pos,
  81. datapos,
  82. relocpos,
  83. nrelocs,
  84. flags : longint;
  85. relochead : PReloc;
  86. reloctail : ^PReloc;
  87. constructor init(sec:TSection;Aflags:longint);
  88. destructor done;
  89. procedure write(var d;l:longint);
  90. procedure alloc(l:longint);
  91. procedure addsymreloc(ofs:longint;p:pasmsymbol;relative:relative_type);
  92. procedure addsectionreloc(ofs:longint;sec:tsection);
  93. end;
  94. pgenericcoffoutput = ^tgenericcoffoutput;
  95. tgenericcoffoutput = object(tobjectoutput)
  96. win32 : boolean;
  97. sects : array[TSection] of PCoffSection;
  98. strs,
  99. syms : Pdynamicarray;
  100. initsym : longint;
  101. constructor init;
  102. destructor done;virtual;
  103. procedure initwriting;virtual;
  104. procedure donewriting;virtual;
  105. procedure writebytes(var data;len:longint);virtual;
  106. procedure writealloc(len:longint);virtual;
  107. procedure writereloc(data,len:longint;p:pasmsymbol;relative:relative_type);virtual;
  108. procedure writesymbol(p:pasmsymbol);virtual;
  109. procedure writestabs(section:tsection;offset:longint;p:pchar;nidx,nother,line:longint;reloc:boolean);virtual;
  110. function text_flags : longint;virtual;
  111. function data_flags : longint;virtual;
  112. function bss_flags : longint;virtual;
  113. function info_flags : longint;virtual;
  114. private
  115. procedure createsection(sec:tsection);
  116. procedure write_relocs(s:pcoffsection);
  117. procedure write_symbol(const name:string;strpos,value,section,typ,aux:longint);
  118. procedure write_symbols;
  119. procedure writetodisk;
  120. end;
  121. pdjgppcoffoutput = ^tdjgppcoffoutput;
  122. tdjgppcoffoutput = object(tgenericcoffoutput)
  123. constructor init;
  124. function text_flags : longint;virtual;
  125. function data_flags : longint;virtual;
  126. function bss_flags : longint;virtual;
  127. function info_flags : longint;virtual;
  128. end;
  129. pwin32coffoutput = ^twin32coffoutput;
  130. twin32coffoutput = object(tgenericcoffoutput)
  131. constructor init;
  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. implementation
  138. uses
  139. strings,verbose,
  140. globtype,globals,files;
  141. type
  142. { Structures which are written directly to the output file }
  143. coffheader=packed record
  144. mach : word;
  145. nsects : word;
  146. time : longint;
  147. sympos : longint;
  148. syms : longint;
  149. opthdr : word;
  150. flag : word;
  151. end;
  152. coffsechdr=packed record
  153. name : array[0..7] of char;
  154. vsize : longint;
  155. rvaofs : longint;
  156. datalen : longint;
  157. datapos : longint;
  158. relocpos : longint;
  159. lineno1 : longint;
  160. nrelocs : word;
  161. lineno2 : word;
  162. flags : longint;
  163. end;
  164. coffsectionrec=packed record
  165. len : longint;
  166. nrelocs : word;
  167. empty : array[0..11] of char;
  168. end;
  169. coffreloc=packed record
  170. address : longint;
  171. sym : longint;
  172. relative : word;
  173. end;
  174. coffsymbol=packed record
  175. name : array[0..3] of char; { real is [0..7], which overlaps the strpos ! }
  176. strpos : longint;
  177. value : longint;
  178. section : integer;
  179. empty : integer;
  180. typ : byte;
  181. aux : byte;
  182. end;
  183. pcoffstab=^coffstab;
  184. coffstab=packed record
  185. strpos : longint;
  186. ntype : byte;
  187. nother : byte;
  188. ndesc : word;
  189. nvalue : longint;
  190. end;
  191. const
  192. sec_2_str : array[tsection] of string[8]=('',
  193. '.text','.data','.bss',
  194. '.stab','.stabstr',
  195. '.idata$2','.idata$4','.idata$5','.idata$6','.idata$7','.edata',
  196. ''
  197. );
  198. {****************************************************************************
  199. TSection
  200. ****************************************************************************}
  201. constructor tcoffsection.init(sec:TSection;Aflags:longint);
  202. begin
  203. index:=sec;
  204. flags:=AFlags;
  205. relocHead:=nil;
  206. relocTail:=@relocHead;
  207. Len:=0;
  208. NRelocs:=0;
  209. if sec=sec_bss then
  210. data:=nil
  211. else
  212. new(Data,Init(1,8192));
  213. end;
  214. destructor tcoffsection.done;
  215. begin
  216. if assigned(Data) then
  217. dispose(Data,done);
  218. end;
  219. procedure tcoffsection.write(var d;l:longint);
  220. begin
  221. if not assigned(Data) then
  222. Internalerror(3334441);
  223. Data^.write(d,l);
  224. inc(len,l);
  225. end;
  226. procedure tcoffsection.alloc(l:longint);
  227. begin
  228. if assigned(Data) then
  229. Internalerror(3334442);
  230. inc(len,l);
  231. end;
  232. procedure tcoffsection.addsymreloc(ofs:longint;p:pasmsymbol;relative:relative_type);
  233. var
  234. r : PReloc;
  235. begin
  236. new(r);
  237. reloctail^:=r;
  238. reloctail:=@r^.next;
  239. r^.next:=nil;
  240. r^.address:=ofs;
  241. r^.symbol:=p;
  242. r^.section:=sec_none;
  243. r^.relative:=relative;
  244. inc(nrelocs);
  245. end;
  246. procedure tcoffsection.addsectionreloc(ofs:longint;sec:tsection);
  247. var
  248. r : PReloc;
  249. begin
  250. new(r);
  251. reloctail^:=r;
  252. reloctail:=@r^.next;
  253. r^.next:=nil;
  254. r^.address:=ofs;
  255. r^.symbol:=nil;
  256. r^.section:=sec;
  257. r^.relative:=relative_false;
  258. inc(nrelocs);
  259. end;
  260. {****************************************************************************
  261. Genericcoffoutput
  262. ****************************************************************************}
  263. const
  264. {$ifdef TP}
  265. symbolresize = 50;
  266. strsresize = 200;
  267. {$else}
  268. symbolresize = 200;
  269. strsresize = 8192;
  270. {$endif}
  271. constructor tgenericcoffoutput.init;
  272. begin
  273. inherited init;
  274. end;
  275. destructor tgenericcoffoutput.done;
  276. begin
  277. inherited done;
  278. end;
  279. procedure tgenericcoffoutput.initwriting;
  280. var
  281. s : string;
  282. begin
  283. inherited initwriting;
  284. { reset }
  285. initsym:=0;
  286. new(syms,init(sizeof(TSymbol),symbolresize));
  287. new(strs,init(1,strsresize));
  288. FillChar(Sects,sizeof(Sects),0);
  289. { we need at least the following 3 sections }
  290. createsection(sec_code);
  291. createsection(sec_data);
  292. createsection(sec_bss);
  293. if (cs_debuginfo in aktmoduleswitches) then
  294. begin
  295. createsection(sec_stab);
  296. createsection(sec_stabstr);
  297. writestabs(sec_none,0,nil,0,0,0,false);
  298. { write zero pchar and name together (PM) }
  299. s:=#0+SplitFileName(current_module^.mainsource^)+#0;
  300. sects[sec_stabstr]^.write(s[1],length(s));
  301. end;
  302. end;
  303. procedure tgenericcoffoutput.donewriting;
  304. var
  305. sec : tsection;
  306. begin
  307. writetodisk;
  308. dispose(syms,done);
  309. dispose(strs,done);
  310. for sec:=low(tsection) to high(tsection) do
  311. if assigned(sects[sec]) then
  312. dispose(sects[sec],done);
  313. inherited donewriting;
  314. end;
  315. function tgenericcoffoutput.text_flags : longint;
  316. begin
  317. text_flags:=0;
  318. end;
  319. function tgenericcoffoutput.data_flags : longint;
  320. begin
  321. data_flags:=0;
  322. end;
  323. function tgenericcoffoutput.bss_flags : longint;
  324. begin
  325. bss_flags:=0;
  326. end;
  327. function tgenericcoffoutput.info_flags : longint;
  328. begin
  329. info_flags:=0;
  330. end;
  331. procedure tgenericcoffoutput.createsection(sec:TSection);
  332. var
  333. Aflags : longint;
  334. begin
  335. Aflags:=0;
  336. case sec of
  337. sec_code :
  338. Aflags:=text_flags;
  339. sec_data :
  340. Aflags:=data_flags;
  341. sec_bss :
  342. Aflags:=bss_flags;
  343. { sec_info :
  344. Aflags:=info_flags; }
  345. else
  346. Aflags:=0;
  347. end;
  348. sects[sec]:=new(PcoffSection,init(Sec,Aflags));
  349. end;
  350. procedure tgenericcoffoutput.writesymbol(p:pasmsymbol);
  351. var
  352. pos : longint;
  353. sym : tsymbol;
  354. c : char;
  355. s : string;
  356. begin
  357. { already written ? }
  358. if p^.idx<>-1 then
  359. exit;
  360. { be sure that the section will exists }
  361. if (p^.section<>sec_none) and not(assigned(sects[p^.section])) then
  362. createsection(p^.section);
  363. { symbolname }
  364. pos:=strs^.usedsize+4;
  365. c:=#0;
  366. s:=p^.name;
  367. if length(s)>8 then
  368. begin
  369. s:=s+#0;
  370. strs^.write(s[1],length(s));
  371. end
  372. else
  373. pos:=-1;
  374. FillChar(sym,sizeof(sym),0);
  375. sym.strpos:=pos;
  376. if pos=-1 then
  377. sym.name:=s;
  378. sym.value:=p^.size;
  379. sym.typ:=p^.typ;
  380. { if local of global then set the section value to the address
  381. of the symbol }
  382. if p^.typ in [AS_LOCAL,AS_GLOBAL] then
  383. begin
  384. sym.section:=ord(p^.section);
  385. sym.value:=p^.address;
  386. end;
  387. { update the asmsymbol index }
  388. p^.idx:=syms^.count;
  389. { store the symbol, but not the local ones (PM) }
  390. if (p^.typ<>AS_LOCAL) or ((copy(s,1,2)<>'.L') and
  391. ((copy(s,1,1)<>'L') or not win32)) then
  392. syms^.write(sym,1);
  393. { make the exported syms known to the objectwriter
  394. (needed for .a generation) }
  395. if (p^.typ=AS_GLOBAL) or
  396. ((p^.typ=AS_EXTERNAL) and (sym.value=p^.size) and (sym.value>0)) then
  397. writer^.writesym(p^.name);
  398. end;
  399. procedure tgenericcoffoutput.writebytes(var data;len:longint);
  400. begin
  401. if not assigned(sects[currsec]) then
  402. createsection(currsec);
  403. sects[currsec]^.write(data,len);
  404. end;
  405. procedure tgenericcoffoutput.writealloc(len:longint);
  406. begin
  407. if not assigned(sects[currsec]) then
  408. createsection(currsec);
  409. sects[currsec]^.alloc(len);
  410. end;
  411. procedure tgenericcoffoutput.writereloc(data,len:longint;p:pasmsymbol;relative:relative_type);
  412. begin
  413. if not assigned(sects[currsec]) then
  414. createsection(currsec);
  415. if assigned(p) then
  416. begin
  417. { no symbol relocation need inside a section }
  418. if p^.section=currsec then
  419. begin
  420. if relative=relative_false then
  421. begin
  422. sects[currsec]^.addsectionreloc(sects[currsec]^.len,currsec);
  423. inc(data,p^.address);
  424. end
  425. else if relative=relative_true then
  426. begin
  427. inc(data,p^.address-len-sects[currsec]^.len);
  428. end
  429. else if relative=relative_rva then
  430. begin
  431. { don't know if this can happens !! }
  432. { does this work ?? }
  433. sects[currsec]^.addsectionreloc(sects[currsec]^.len,currsec);
  434. inc(data,p^.address);
  435. end;
  436. end
  437. else
  438. begin
  439. writesymbol(p);
  440. if (p^.section<>sec_none) and (relative=relative_false) then
  441. begin
  442. sects[currsec]^.addsectionreloc(sects[currsec]^.len,p^.section);
  443. end
  444. else
  445. sects[currsec]^.addsymreloc(sects[currsec]^.len,p,relative);
  446. if not win32 then {seems wrong to me (PM) }
  447. begin
  448. {if p^.section<>sec_none then
  449. this is the cause of the strange
  450. feature see Note (5) before
  451. address contains the size for
  452. global vars switched to common }
  453. inc(data,p^.address);
  454. end
  455. else
  456. if (relative<>relative_true) and (p^.section<>sec_none) then
  457. inc(data,p^.address);
  458. if relative=relative_true then
  459. begin
  460. if win32 then
  461. {inc(data,4-len)}
  462. dec(data,len-4{+p^.address})
  463. else
  464. dec(data,len+sects[currsec]^.len);
  465. end;
  466. end;
  467. end;
  468. sects[currsec]^.write(data,len);
  469. end;
  470. procedure tgenericcoffoutput.writestabs(section:tsection;offset:longint;p:pchar;nidx,nother,line:longint;reloc : boolean);
  471. var
  472. stab : coffstab;
  473. s : tsection;
  474. begin
  475. if section=sec_none then
  476. s:=currsec
  477. else
  478. s:=section;
  479. { local var can be at offset -1 !! PM }
  480. if (offset=-1) and reloc then
  481. begin
  482. if s=sec_none then
  483. offset:=0
  484. else
  485. offset:=sects[s]^.len;
  486. end;
  487. fillchar(stab,sizeof(coffstab),0);
  488. if assigned(p) and (p[0]<>#0) then
  489. begin
  490. stab.strpos:=sects[sec_stabstr]^.len;
  491. sects[sec_stabstr]^.write(p^,strlen(p)+1);
  492. end;
  493. stab.ntype:=nidx;
  494. stab.ndesc:=line;
  495. stab.nother:=nother;
  496. stab.nvalue:=offset;
  497. sects[sec_stab]^.write(stab,sizeof(stab));
  498. { when the offset is not 0 then write a relocation, take also the
  499. hdrstab into account with the offset }
  500. if reloc then
  501. sects[sec_stab]^.addsectionreloc(sects[sec_stab]^.len-4,s);
  502. end;
  503. procedure tgenericcoffoutput.write_relocs(s:pcoffsection);
  504. var
  505. rel : coffreloc;
  506. hr,r : preloc;
  507. begin
  508. r:=s^.relochead;
  509. while assigned(r) do
  510. begin
  511. rel.address:=r^.address;
  512. if assigned(r^.symbol) then
  513. begin
  514. if (r^.symbol^.typ=AS_LOCAL) then
  515. rel.sym:=2*ord(r^.symbol^.section)
  516. else
  517. rel.sym:=r^.symbol^.idx+initsym;
  518. end
  519. else
  520. rel.sym:=2*ord(r^.section);
  521. case r^.relative of
  522. relative_true : rel.relative:=$14;
  523. relative_false : rel.relative:=$6;
  524. relative_rva : rel.relative:=$7;
  525. end;
  526. writer^.write(rel,sizeof(rel));
  527. { goto next and dispose this reloc }
  528. hr:=r;
  529. r:=r^.next;
  530. dispose(hr);
  531. end;
  532. end;
  533. procedure tgenericcoffoutput.write_symbol(const name:string;strpos,value,section,typ,aux:longint);
  534. var
  535. sym : coffsymbol;
  536. begin
  537. FillChar(sym,sizeof(sym),0);
  538. if strpos=-1 then
  539. move(name[1],sym.name,length(name))
  540. else
  541. sym.strpos:=strpos;
  542. sym.value:=value;
  543. sym.section:=section;
  544. sym.typ:=typ;
  545. sym.aux:=aux;
  546. writer^.write(sym,sizeof(sym));
  547. end;
  548. procedure tgenericcoffoutput.write_symbols;
  549. var
  550. filename : string[18];
  551. sec : tsection;
  552. i : longint;
  553. globalval : byte;
  554. secrec : coffsectionrec;
  555. sym : tsymbol;
  556. begin
  557. { The `.file' record, and the file name auxiliary record. }
  558. write_symbol ('.file', -1, 0, -2, $67, 1);
  559. fillchar(filename,sizeof(filename),0);
  560. filename:=SplitFileName(current_module^.mainsource^);
  561. writer^.write(filename[1],sizeof(filename)-1);
  562. { The section records, with their auxiliaries }
  563. i:=0;
  564. for sec:=low(tsection) to high(tsection) do
  565. if assigned(sects[sec]) then
  566. begin
  567. inc(i);
  568. write_symbol(sec_2_str[sec],-1,{sects[sec]^.pos}0,i,3,1);
  569. fillchar(secrec,sizeof(secrec),0);
  570. secrec.len:=sects[sec]^.len;
  571. secrec.nrelocs:=sects[sec]^.nrelocs;
  572. writer^.write(secrec,sizeof(secrec));
  573. end;
  574. { The real symbols. }
  575. syms^.seek(0);
  576. for i:=1 to syms^.count do
  577. begin
  578. syms^.read(sym,1);
  579. if sym.typ=AS_LOCAL then
  580. globalval:=3
  581. else
  582. globalval:=2;
  583. write_symbol(sym.name,sym.strpos,sym.value,sym.section,globalval,0);
  584. end;
  585. end;
  586. procedure tgenericcoffoutput.writetodisk;
  587. var
  588. datapos,
  589. nsects,pos,sympos,i,fillsize : longint;
  590. sec : tsection;
  591. header : coffheader;
  592. sechdr : coffsechdr;
  593. empty : array[0..15] of byte;
  594. begin
  595. { calc amount of sections we have and align sections at 4 bytes }
  596. fillchar(empty,sizeof(empty),0);
  597. nsects:=0;
  598. for sec:=low(tsection) to high(tsection) do
  599. { .stabstr section length must be without alignment !! }
  600. if assigned(sects[sec]) then
  601. begin
  602. { fill with zero }
  603. fillsize:=4-(sects[sec]^.len and 3);
  604. if fillsize<>4 then
  605. begin
  606. if assigned(sects[sec]^.data) then
  607. sects[sec]^.write(empty,fillsize)
  608. else
  609. sects[sec]^.alloc(fillsize);
  610. { .stabstr section length must be without alignment !! }
  611. if (sec=sec_stabstr) then
  612. dec(sects[sec]^.len,fillsize);
  613. end;
  614. inc(nsects);
  615. end;
  616. { Calculate the filepositions }
  617. datapos:=sizeof(coffheader)+sizeof(coffsechdr)*nsects;
  618. pos:=0;
  619. initsym:=2; { 2 for the file }
  620. { sections first }
  621. for sec:=low(tsection) to high(tsection) do
  622. if assigned(sects[sec]) then
  623. begin
  624. sects[sec]^.pos:=pos;
  625. sects[sec]^.datapos:=datapos;
  626. inc(pos,sects[sec]^.len);
  627. if assigned(sects[sec]^.data) then
  628. inc(datapos,sects[sec]^.len);
  629. { align after stabstr section !! }
  630. if (sec=sec_stabstr) and ((sects[sec]^.len and 3)<>0) then
  631. inc(datapos,4-(sects[sec]^.len and 3));
  632. inc(initsym,2); { 2 for each section }
  633. end;
  634. { relocs }
  635. for sec:=low(tsection) to high(tsection) do
  636. if assigned(sects[sec]) then
  637. begin
  638. sects[sec]^.relocpos:=datapos;
  639. inc(datapos,10*sects[sec]^.nrelocs);
  640. end;
  641. { symbols }
  642. sympos:=datapos;
  643. { COFF header }
  644. fillchar(header,sizeof(coffheader),0);
  645. header.mach:=$14c;
  646. header.nsects:=nsects;
  647. header.sympos:=sympos;
  648. header.syms:=syms^.count+initsym;
  649. if not win32 then
  650. header.flag:=$104;
  651. writer^.write(header,sizeof(header));
  652. { Section headers }
  653. for sec:=low(tsection) to high(tsection) do
  654. if assigned(sects[sec]) then
  655. begin
  656. fillchar(sechdr,sizeof(sechdr),0);
  657. move(sec_2_str[sec][1],sechdr.name,length(sec_2_str[sec]));
  658. if not win32 then
  659. sechdr.vsize:=sects[sec]^.pos
  660. else if sec=sec_bss then
  661. sechdr.vsize:=sects[sec]^.len;
  662. sechdr.datalen:=sects[sec]^.len;
  663. { apparently win32 asw leaves section at datapos zero }
  664. { this was an error by me (PM) }
  665. if (sects[sec]^.len>0) and assigned(sects[sec]^.data) then
  666. sechdr.datapos:=sects[sec]^.datapos;
  667. sechdr.relocpos:=sects[sec]^.relocpos;
  668. sechdr.nrelocs:=sects[sec]^.nrelocs;
  669. sechdr.flags:=sects[sec]^.flags;
  670. writer^.write(sechdr,sizeof(sechdr));
  671. end;
  672. { Sections }
  673. for sec:=low(tsection) to high(tsection) do
  674. if assigned(sects[sec]) and
  675. assigned(sects[sec]^.data) then
  676. begin
  677. { For the stab section we need an HdrSym which can now be
  678. calculated more easily }
  679. if sec=sec_stab then
  680. begin
  681. pcoffstab(sects[sec_stab]^.data^.data)^.nvalue:=sects[sec_stabstr]^.len;
  682. pcoffstab(sects[sec_stab]^.data^.data)^.strpos:=1;
  683. pcoffstab(sects[sec_stab]^.data^.data)^.ndesc:=
  684. (sects[sec_stab]^.len div sizeof(coffstab))-1{+1 according to gas output PM};
  685. end;
  686. writer^.write(sects[sec]^.data^.data^,sects[sec]^.data^.usedsize);
  687. end;
  688. { Relocs }
  689. for sec:=low(tsection) to high(tsection) do
  690. if assigned(sects[sec]) then
  691. write_relocs(sects[sec]);
  692. { Symbols }
  693. write_symbols;
  694. { Strings }
  695. i:=strs^.usedsize+4;
  696. writer^.write(i,4);
  697. writer^.write(strs^.data^,strs^.usedsize);
  698. end;
  699. {****************************************************************************
  700. DJGppcoffoutput
  701. ****************************************************************************}
  702. constructor tdjgppcoffoutput.init;
  703. begin
  704. inherited init;
  705. win32:=false;
  706. end;
  707. function tdjgppcoffoutput.text_flags : longint;
  708. begin
  709. text_flags:=$20;
  710. end;
  711. function tdjgppcoffoutput.data_flags : longint;
  712. begin
  713. data_flags:=$40;
  714. end;
  715. function tdjgppcoffoutput.bss_flags : longint;
  716. begin
  717. bss_flags:=$80;
  718. end;
  719. function tdjgppcoffoutput.info_flags : longint;
  720. begin
  721. writeln('djgpp coff doesn''t support info sections');
  722. info_flags:=$40;
  723. end;
  724. {****************************************************************************
  725. Win32coffoutput
  726. ****************************************************************************}
  727. constructor twin32coffoutput.init;
  728. begin
  729. inherited init;
  730. win32:=true;
  731. end;
  732. function twin32coffoutput.text_flags : longint;
  733. begin
  734. text_flags:={ $60500020}$60300020{changed to get same as asw.exe (PM)};
  735. end;
  736. function twin32coffoutput.data_flags : longint;
  737. begin
  738. data_flags:=$c0300040;
  739. end;
  740. function twin32coffoutput.bss_flags : longint;
  741. begin
  742. bss_flags:=$c0300080;
  743. end;
  744. function twin32coffoutput.info_flags : longint;
  745. begin
  746. info_flags:=$100a00;
  747. end;
  748. end.
  749. {
  750. $Log$
  751. Revision 1.4 2000-02-09 13:22:54 peter
  752. * log truncated
  753. Revision 1.3 2000/01/07 01:14:27 peter
  754. * updated copyright to 2000
  755. Revision 1.2 1999/08/04 00:23:07 florian
  756. * renamed i386asm and i386base to cpuasm and cpubase
  757. }