ogcoff.pas 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Peter Vreman and Pierre Muller
  4. Contains the binary coff reader and 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 ogcoff;
  22. {$i defines.inc}
  23. interface
  24. uses
  25. { common }
  26. cclasses,cobjects,
  27. { target }
  28. systems,
  29. { assembler }
  30. cpubase,aasm,
  31. { output }
  32. ogbase;
  33. type
  34. tcoffsection = class(tobjectsection)
  35. public
  36. flags : cardinal;
  37. coffrelocs,
  38. coffrelocpos : longint;
  39. constructor createsec(sec:TSection;AAlign,AFlags:cardinal);
  40. end;
  41. tcoffdata = class(tobjectdata)
  42. private
  43. Fstrs,
  44. Fsyms : Tdynamicarray;
  45. win32 : boolean;
  46. procedure reset;
  47. public
  48. constructor createdjgpp;
  49. constructor createwin32;
  50. destructor destroy;override;
  51. procedure setsectionsizes(var s:tsecsize);override;
  52. procedure createsection(sec:tsection);override;
  53. procedure writereloc(data,len:longint;p:pasmsymbol;relative:relative_type);override;
  54. procedure writesymbol(p:pasmsymbol);override;
  55. procedure writestabs(section:tsection;offset:longint;p:pchar;nidx,nother,line:longint;reloc:boolean);override;
  56. procedure writesymstabs(section:tsection;offset:longint;p:pchar;ps:pasmsymbol;nidx,nother,line:longint;reloc:boolean);override;
  57. end;
  58. tcoffobjectoutput = class(tobjectoutput)
  59. private
  60. win32 : boolean;
  61. initsym : longint;
  62. procedure write_relocs(s:tobjectsection);
  63. procedure write_symbol(const name:string;strpos,value,section,typ,aux:longint);
  64. procedure write_symbols;
  65. protected
  66. procedure writetodisk;override;
  67. public
  68. constructor createdjgpp(smart:boolean);
  69. constructor createwin32(smart:boolean);
  70. function initwriting(const fn:string):boolean;override;
  71. end;
  72. tpasmsymbolarray = array[0..high(word)] of pasmsymbol;
  73. tcoffobjectinput = class(tobjectinput)
  74. private
  75. Fidx2sec : array[0..255] of tsection;
  76. FCoffsyms : tdynamicarray;
  77. FSymTbl : ^tpasmsymbolarray;
  78. win32 : boolean;
  79. procedure read_relocs(s:tcoffsection);
  80. procedure handle_symbols;
  81. public
  82. constructor createdjgpp(const fn:string);
  83. constructor createwin32(const fn:string);
  84. function initreading:boolean;override;
  85. procedure donereading;override;
  86. procedure readfromdisk;override;
  87. end;
  88. implementation
  89. uses
  90. {$ifdef delphi}
  91. sysutils,
  92. {$else}
  93. strings,
  94. {$endif}
  95. cutils,verbose,
  96. globtype,globals,fmodule;
  97. const
  98. symbolresize = 200*sizeof(toutputsymbol);
  99. coffsymbolresize = 200*18;
  100. strsresize = 8192;
  101. DataResize = 8192;
  102. const
  103. COFF_SYM_EXTERNAL = 2;
  104. COFF_SYM_STATIC = 3;
  105. COFF_SYM_LABEL = 6;
  106. COFF_SYM_FUNCTION = 101;
  107. COFF_SYM_FILE = 103;
  108. COFF_SYM_SECTION = 104;
  109. type
  110. { Structures which are written directly to the output file }
  111. coffheader=packed record
  112. mach : word;
  113. nsects : word;
  114. time : longint;
  115. sympos : longint;
  116. syms : longint;
  117. opthdr : word;
  118. flag : word;
  119. end;
  120. coffsechdr=packed record
  121. name : array[0..7] of char;
  122. vsize : longint;
  123. rvaofs : longint;
  124. datasize : longint;
  125. datapos : longint;
  126. relocpos : longint;
  127. lineno1 : longint;
  128. nrelocs : word;
  129. lineno2 : word;
  130. flags : cardinal;
  131. end;
  132. coffsectionrec=packed record
  133. len : longint;
  134. nrelocs : word;
  135. empty : array[0..11] of char;
  136. end;
  137. coffreloc=packed record
  138. address : longint;
  139. sym : longint;
  140. relative : word;
  141. end;
  142. coffsymbol=packed record
  143. name : array[0..3] of char; { real is [0..7], which overlaps the strpos ! }
  144. strpos : longint;
  145. value : longint;
  146. section : smallint;
  147. empty : smallint;
  148. typ : byte;
  149. aux : byte;
  150. end;
  151. pcoffstab=^coffstab;
  152. coffstab=packed record
  153. strpos : longint;
  154. ntype : byte;
  155. nother : byte;
  156. ndesc : word;
  157. nvalue : longint;
  158. end;
  159. {****************************************************************************
  160. TCoffSection
  161. ****************************************************************************}
  162. constructor tcoffsection.createsec(sec:TSection;AAlign,AFlags:cardinal);
  163. begin
  164. inherited create(target_asm.secnames[sec],AAlign,(sec=sec_bss));
  165. Flags:=AFlags;
  166. end;
  167. {****************************************************************************
  168. TCoffData
  169. ****************************************************************************}
  170. constructor tcoffdata.createdjgpp;
  171. begin
  172. inherited create;
  173. win32:=false;
  174. reset;
  175. end;
  176. constructor tcoffdata.createwin32;
  177. begin
  178. inherited create;
  179. win32:=true;
  180. reset;
  181. end;
  182. destructor tcoffdata.destroy;
  183. begin
  184. FSyms.Free;
  185. FStrs.Free;
  186. inherited destroy;
  187. end;
  188. procedure tcoffdata.reset;
  189. var
  190. s : string;
  191. begin
  192. FSyms:=TDynamicArray.Create(symbolresize);
  193. FStrs:=TDynamicArray.Create(strsresize);
  194. { we need at least the following 3 sections }
  195. createsection(sec_code);
  196. createsection(sec_data);
  197. createsection(sec_bss);
  198. if (cs_gdb_lineinfo in aktglobalswitches) or
  199. (cs_debuginfo in aktmoduleswitches) then
  200. begin
  201. createsection(sec_stab);
  202. createsection(sec_stabstr);
  203. writestabs(sec_none,0,nil,0,0,0,false);
  204. { write zero pchar and name together (PM) }
  205. s:=#0+SplitFileName(current_module.mainsource^)+#0;
  206. sects[sec_stabstr].write(s[1],length(s));
  207. end;
  208. end;
  209. procedure tcoffdata.createsection(sec:TSection);
  210. var
  211. Flags,
  212. AAlign : cardinal;
  213. begin
  214. { defaults }
  215. Flags:=0;
  216. Aalign:=1;
  217. { alignment after section }
  218. case sec of
  219. sec_code :
  220. begin
  221. if win32 then
  222. Flags:=$60000020
  223. else
  224. Flags:=$20;
  225. Aalign:=4;
  226. end;
  227. sec_data :
  228. begin
  229. if win32 then
  230. Flags:=$c0300040
  231. else
  232. Flags:=$40;
  233. Aalign:=4;
  234. end;
  235. sec_bss :
  236. begin
  237. if win32 then
  238. Flags:=$c0300080
  239. else
  240. Flags:=$80;
  241. Aalign:=4;
  242. end;
  243. sec_idata2,
  244. sec_idata4,
  245. sec_idata5,
  246. sec_idata6,
  247. sec_idata7 :
  248. begin
  249. if win32 then
  250. Flags:=$40000000;
  251. end;
  252. sec_edata :
  253. begin
  254. if win32 then
  255. Flags:=$c0300040;
  256. end;
  257. end;
  258. sects[sec]:=tcoffSection.createsec(Sec,AAlign,Flags);
  259. end;
  260. procedure tcoffdata.writesymbol(p:pasmsymbol);
  261. var
  262. sym : toutputsymbol;
  263. s : string;
  264. begin
  265. { already written ? }
  266. if p^.idx<>-1 then
  267. exit;
  268. { be sure that the section will exists }
  269. if (p^.section<>sec_none) and not(assigned(sects[p^.section])) then
  270. createsection(p^.section);
  271. FillChar(sym,sizeof(sym),0);
  272. sym.value:=p^.size;
  273. sym.bind:=p^.bind;
  274. sym.typ:=AT_NONE;
  275. { if local of global then set the section value to the address
  276. of the symbol }
  277. if sym.bind in [AB_LOCAL,AB_GLOBAL] then
  278. begin
  279. sym.section:=p^.section;
  280. sym.value:=p^.address+sects[sym.section].mempos;
  281. end;
  282. { store the symbol, but not the local ones }
  283. if (sym.bind<>AB_LOCAL) then
  284. begin
  285. { symbolname }
  286. s:=p^.name;
  287. if length(s)>8 then
  288. begin
  289. sym.nameidx:=FStrs.size+4;
  290. FStrs.writestr(s);
  291. FStrs.writestr(#0);
  292. end
  293. else
  294. begin
  295. sym.nameidx:=-1;
  296. sym.namestr:=s;
  297. end;
  298. { update the asmsymbol index }
  299. p^.idx:=FSyms.size div sizeof(TOutputSymbol);
  300. { write the symbol }
  301. FSyms.write(sym,sizeof(toutputsymbol));
  302. end
  303. else
  304. begin
  305. p^.idx:=-2; { local }
  306. end;
  307. end;
  308. procedure tcoffdata.writereloc(data,len:longint;p:pasmsymbol;relative:relative_type);
  309. var
  310. curraddr,
  311. symaddr : longint;
  312. begin
  313. if not assigned(sects[currsec]) then
  314. createsection(currsec);
  315. if assigned(p) then
  316. begin
  317. { current address }
  318. curraddr:=sects[currsec].mempos+sects[currsec].datasize;
  319. { real address of the symbol }
  320. symaddr:=p^.address;
  321. if p^.section<>sec_none then
  322. inc(symaddr,sects[p^.section].mempos);
  323. { no symbol relocation need inside a section }
  324. if p^.section=currsec then
  325. begin
  326. case relative of
  327. relative_false :
  328. begin
  329. sects[currsec].addsectionreloc(curraddr,currsec,relative_false);
  330. inc(data,symaddr);
  331. end;
  332. relative_true :
  333. begin
  334. inc(data,symaddr-len-sects[currsec].datasize);
  335. end;
  336. relative_rva :
  337. begin
  338. sects[currsec].addsectionreloc(curraddr,currsec,relative_rva);
  339. inc(data,symaddr);
  340. end;
  341. end;
  342. end
  343. else
  344. begin
  345. writesymbol(p);
  346. if (p^.section<>sec_none) and (relative<>relative_true) then
  347. sects[currsec].addsectionreloc(curraddr,p^.section,relative)
  348. else
  349. sects[currsec].addsymreloc(curraddr,p,relative);
  350. if not win32 then {seems wrong to me (PM) }
  351. inc(data,symaddr)
  352. else
  353. if (relative<>relative_true) and (p^.section<>sec_none) then
  354. inc(data,symaddr);
  355. if relative=relative_true then
  356. begin
  357. if win32 then
  358. dec(data,len-4)
  359. else
  360. dec(data,len+sects[currsec].datasize);
  361. end;
  362. end;
  363. end;
  364. sects[currsec].write(data,len);
  365. end;
  366. procedure tcoffdata.writestabs(section:tsection;offset:longint;p:pchar;nidx,nother,line:longint;reloc : boolean);
  367. var
  368. stab : coffstab;
  369. s : tsection;
  370. curraddr : longint;
  371. begin
  372. s:=section;
  373. { local var can be at offset -1 !! PM }
  374. if reloc then
  375. begin
  376. if (offset=-1) then
  377. begin
  378. if s=sec_none then
  379. offset:=0
  380. else
  381. offset:=sects[s].datasize;
  382. end;
  383. if (s<>sec_none) then
  384. inc(offset,sects[s].datapos);
  385. end;
  386. if assigned(p) and (p[0]<>#0) then
  387. begin
  388. stab.strpos:=sects[sec_stabstr].datasize;
  389. sects[sec_stabstr].write(p^,strlen(p)+1);
  390. end
  391. else
  392. stab.strpos:=0;
  393. stab.ntype:=nidx;
  394. stab.ndesc:=line;
  395. stab.nother:=nother;
  396. stab.nvalue:=offset;
  397. sects[sec_stab].write(stab,sizeof(stab));
  398. { when the offset is not 0 then write a relocation, take also the
  399. hdrstab into account with the offset }
  400. if reloc then
  401. begin
  402. { current address }
  403. curraddr:=sects[sec_stab].mempos+sects[sec_stab].datasize;
  404. if DLLSource and RelocSection then
  405. { avoid relocation in the .stab section
  406. because it ends up in the .reloc section instead }
  407. sects[sec_stab].addsectionreloc(curraddr-4,s,relative_rva)
  408. else
  409. sects[sec_stab].addsectionreloc(curraddr-4,s,relative_false);
  410. end;
  411. end;
  412. procedure tcoffdata.writesymstabs(section:tsection;offset:longint;p:pchar;ps:pasmsymbol;
  413. nidx,nother,line:longint;reloc:boolean);
  414. var
  415. stab : coffstab;
  416. curraddr : longint;
  417. begin
  418. { do not use the size stored in offset field
  419. this is DJGPP specific ! PM }
  420. if win32 then
  421. offset:=0;
  422. { local var can be at offset -1 !! PM }
  423. if reloc then
  424. begin
  425. if (offset=-1) then
  426. begin
  427. if section=sec_none then
  428. offset:=0
  429. else
  430. offset:=sects[section].datasize;
  431. end;
  432. if (section<>sec_none) then
  433. inc(offset,sects[section].mempos);
  434. end;
  435. if assigned(p) and (p[0]<>#0) then
  436. begin
  437. stab.strpos:=sects[sec_stabstr].datasize;
  438. sects[sec_stabstr].write(p^,strlen(p)+1);
  439. end
  440. else
  441. stab.strpos:=0;
  442. stab.ntype:=nidx;
  443. stab.ndesc:=line;
  444. stab.nother:=nother;
  445. stab.nvalue:=offset;
  446. sects[sec_stab].write(stab,sizeof(stab));
  447. { when the offset is not 0 then write a relocation, take also the
  448. hdrstab into account with the offset }
  449. if reloc then
  450. begin
  451. { current address }
  452. curraddr:=sects[sec_stab].mempos+sects[sec_stab].datasize;
  453. if DLLSource and RelocSection then
  454. { avoid relocation in the .stab section
  455. because it ends up in the .reloc section instead }
  456. sects[sec_stab].addsymreloc(curraddr-4,ps,relative_rva)
  457. else
  458. sects[sec_stab].addsymreloc(curraddr-4,ps,relative_false);
  459. end;
  460. end;
  461. procedure tcoffdata.setsectionsizes(var s:tsecsize);
  462. var
  463. mempos : longint;
  464. sec : tsection;
  465. begin
  466. { multiply stab with real size }
  467. s[sec_stab]:=s[sec_stab]*sizeof(coffstab);
  468. { if debug then also count header stab }
  469. if (cs_debuginfo in aktmoduleswitches) then
  470. begin
  471. inc(s[sec_stab],sizeof(coffstab));
  472. inc(s[sec_stabstr],length(SplitFileName(current_module.mainsource^))+2);
  473. end;
  474. { calc mempos }
  475. mempos:=0;
  476. for sec:=low(tsection) to high(tsection) do
  477. begin
  478. if (s[sec]>0) and
  479. (not assigned(sects[sec])) then
  480. createsection(sec);
  481. if assigned(sects[sec]) then
  482. begin
  483. sects[sec].memsize:=s[sec];
  484. { memory position }
  485. if not win32 then
  486. begin
  487. sects[sec].mempos:=mempos;
  488. inc(mempos,align(sects[sec].memsize,sects[sec].addralign));
  489. end;
  490. end;
  491. end;
  492. end;
  493. {****************************************************************************
  494. tcoffobjectoutput
  495. ****************************************************************************}
  496. constructor tcoffobjectoutput.createdjgpp(smart:boolean);
  497. begin
  498. inherited create(smart);
  499. win32:=false;
  500. end;
  501. constructor tcoffobjectoutput.createwin32(smart:boolean);
  502. begin
  503. inherited create(smart);
  504. win32:=true;
  505. end;
  506. function tcoffobjectoutput.initwriting(const fn:string):boolean;
  507. begin
  508. result:=inherited initwriting(fn);
  509. if result then
  510. begin
  511. initsym:=0;
  512. if win32 then
  513. FData:=tcoffdata.createwin32
  514. else
  515. FData:=tcoffdata.createdjgpp;
  516. end;
  517. end;
  518. procedure tcoffobjectoutput.write_relocs(s:tobjectsection);
  519. var
  520. rel : coffreloc;
  521. hr,r : poutputreloc;
  522. begin
  523. r:=s.relochead;
  524. while assigned(r) do
  525. begin
  526. rel.address:=r^.address;
  527. if assigned(r^.symbol) then
  528. begin
  529. if (r^.symbol^.bind=AB_LOCAL) then
  530. rel.sym:=2*data.sects[r^.symbol^.section].secsymidx
  531. else
  532. begin
  533. if r^.symbol^.idx=-1 then
  534. internalerror(4321);
  535. rel.sym:=r^.symbol^.idx+initsym;
  536. end;
  537. end
  538. else
  539. begin
  540. if r^.section<>sec_none then
  541. rel.sym:=2*data.sects[r^.section].secsymidx
  542. else
  543. rel.sym:=0;
  544. end;
  545. case r^.typ of
  546. relative_true : rel.relative:=$14;
  547. relative_false : rel.relative:=$6;
  548. relative_rva : rel.relative:=$7;
  549. end;
  550. FWriter.write(rel,sizeof(rel));
  551. { goto next and dispose this reloc }
  552. hr:=r;
  553. r:=r^.next;
  554. dispose(hr);
  555. end;
  556. end;
  557. procedure tcoffobjectoutput.write_symbol(const name:string;strpos,value,section,typ,aux:longint);
  558. var
  559. sym : coffsymbol;
  560. begin
  561. FillChar(sym,sizeof(sym),0);
  562. if strpos=-1 then
  563. move(name[1],sym.name,length(name))
  564. else
  565. sym.strpos:=strpos;
  566. sym.value:=value;
  567. sym.section:=section;
  568. sym.typ:=typ;
  569. sym.aux:=aux;
  570. FWriter.write(sym,sizeof(sym));
  571. end;
  572. procedure tcoffobjectoutput.write_symbols;
  573. var
  574. filename : string[18];
  575. sec : tsection;
  576. sectionval,
  577. i : longint;
  578. globalval : byte;
  579. secrec : coffsectionrec;
  580. sym : toutputsymbol;
  581. begin
  582. with tcoffdata(data) do
  583. begin
  584. { The `.file' record, and the file name auxiliary record }
  585. write_symbol ('.file', -1, 0, -2, $67, 1);
  586. fillchar(filename,sizeof(filename),0);
  587. filename:=SplitFileName(current_module.mainsource^);
  588. FWriter.write(filename[1],sizeof(filename)-1);
  589. { The section records, with their auxiliaries, also store the
  590. symbol index }
  591. for sec:=low(tsection) to high(tsection) do
  592. if assigned(sects[sec]) then
  593. begin
  594. write_symbol(target_asm.secnames[sec],-1,sects[sec].mempos,sects[sec].secsymidx,3,1);
  595. fillchar(secrec,sizeof(secrec),0);
  596. secrec.len:=sects[sec].aligneddatasize;
  597. secrec.nrelocs:=sects[sec].nrelocs;
  598. FWriter.write(secrec,sizeof(secrec));
  599. end;
  600. { The real symbols }
  601. FSyms.seek(0);
  602. for i:=1 to FSyms.size div sizeof(TOutputSymbol) do
  603. begin
  604. FSyms.read(sym,sizeof(TOutputSymbol));
  605. if sym.bind=AB_LOCAL then
  606. globalval:=3
  607. else
  608. globalval:=2;
  609. if assigned(sects[sym.section]) then
  610. sectionval:=sects[sym.section].secsymidx
  611. else
  612. sectionval:=0;
  613. write_symbol(sym.namestr,sym.nameidx,sym.value,sectionval,globalval,0);
  614. end;
  615. end;
  616. end;
  617. procedure tcoffobjectoutput.writetodisk;
  618. var
  619. datapos,
  620. secsymidx,
  621. nsects,
  622. sympos,i : longint;
  623. hstab : coffstab;
  624. gotreloc : boolean;
  625. sec : tsection;
  626. header : coffheader;
  627. sechdr : coffsechdr;
  628. empty : array[0..15] of byte;
  629. hp : pdynamicblock;
  630. begin
  631. with tcoffdata(data) do
  632. begin
  633. { calc amount of sections we have }
  634. fillchar(empty,sizeof(empty),0);
  635. nsects:=0;
  636. initsym:=2; { 2 for the file }
  637. secsymidx:=0;
  638. for sec:=low(tsection) to high(tsection) do
  639. if assigned(sects[sec]) then
  640. begin
  641. inc(nsects);
  642. inc(secsymidx);
  643. sects[sec].secsymidx:=secsymidx;
  644. inc(initsym,2); { 2 for each section }
  645. end;
  646. { For the stab section we need an HdrSym which can now be
  647. calculated more easily }
  648. if assigned(sects[sec_stab]) then
  649. begin
  650. hstab.strpos:=1;
  651. hstab.ntype:=0;
  652. hstab.nother:=0;
  653. hstab.ndesc:=(sects[sec_stab].datasize div sizeof(coffstab))-1{+1 according to gas output PM};
  654. hstab.nvalue:=sects[sec_stabstr].datasize;
  655. sects[sec_stab].data.seek(0);
  656. sects[sec_stab].data.write(hstab,sizeof(hstab));
  657. end;
  658. { Calculate the filepositions }
  659. datapos:=sizeof(coffheader)+sizeof(coffsechdr)*nsects;
  660. { sections first }
  661. for sec:=low(tsection) to high(tsection) do
  662. if assigned(sects[sec]) then
  663. begin
  664. sects[sec].datapos:=datapos;
  665. if assigned(sects[sec].data) then
  666. inc(datapos,sects[sec].aligneddatasize);
  667. end;
  668. { relocs }
  669. gotreloc:=false;
  670. for sec:=low(tsection) to high(tsection) do
  671. if assigned(sects[sec]) then
  672. begin
  673. tcoffsection(sects[sec]).coffrelocpos:=datapos;
  674. inc(datapos,10*sects[sec].nrelocs);
  675. if (not gotreloc) and (sects[sec].nrelocs>0) then
  676. gotreloc:=true;
  677. end;
  678. { symbols }
  679. sympos:=datapos;
  680. { COFF header }
  681. fillchar(header,sizeof(coffheader),0);
  682. header.mach:=$14c;
  683. header.nsects:=nsects;
  684. header.sympos:=sympos;
  685. header.syms:=(FSyms.size div sizeof(TOutputSymbol))+initsym;
  686. if gotreloc then
  687. header.flag:=$104
  688. else
  689. header.flag:=$105;
  690. FWriter.write(header,sizeof(header));
  691. { Section headers }
  692. for sec:=low(tsection) to high(tsection) do
  693. if assigned(sects[sec]) then
  694. begin
  695. fillchar(sechdr,sizeof(sechdr),0);
  696. move(target_asm.secnames[sec][1],sechdr.name,length(target_asm.secnames[sec]));
  697. if not win32 then
  698. begin
  699. sechdr.rvaofs:=sects[sec].mempos;
  700. sechdr.vsize:=sects[sec].mempos;
  701. end
  702. else
  703. begin
  704. if sec=sec_bss then
  705. sechdr.vsize:=sects[sec].aligneddatasize;
  706. end;
  707. sechdr.datasize:=sects[sec].aligneddatasize;
  708. if (sects[sec].datasize>0) and assigned(sects[sec].data) then
  709. sechdr.datapos:=sects[sec].datapos;
  710. sechdr.nrelocs:=sects[sec].nrelocs;
  711. sechdr.relocpos:=TCoffSection(sects[sec]).coffrelocpos;
  712. sechdr.flags:=TCoffSection(sects[sec]).flags;
  713. FWriter.write(sechdr,sizeof(sechdr));
  714. end;
  715. { Sections }
  716. for sec:=low(tsection) to high(tsection) do
  717. if assigned(sects[sec]) and
  718. assigned(sects[sec].data) then
  719. begin
  720. sects[sec].alignsection;
  721. hp:=sects[sec].data.firstblock;
  722. while assigned(hp) do
  723. begin
  724. FWriter.write(hp^.data,hp^.used);
  725. hp:=hp^.next;
  726. end;
  727. end;
  728. { Relocs }
  729. for sec:=low(tsection) to high(tsection) do
  730. if assigned(sects[sec]) then
  731. write_relocs(sects[sec]);
  732. { Symbols }
  733. write_symbols;
  734. { Strings }
  735. i:=FStrs.size+4;
  736. FWriter.write(i,4);
  737. hp:=FStrs.firstblock;
  738. while assigned(hp) do
  739. begin
  740. FWriter.write(hp^.data,hp^.used);
  741. hp:=hp^.next;
  742. end;
  743. end;
  744. end;
  745. {****************************************************************************
  746. tcoffobjectinput
  747. ****************************************************************************}
  748. constructor tcoffobjectinput.createdjgpp(const fn:string);
  749. begin
  750. inherited create(fn);
  751. win32:=false;
  752. end;
  753. constructor tcoffobjectinput.createwin32(const fn:string);
  754. begin
  755. inherited create(fn);
  756. win32:=true;
  757. end;
  758. function tcoffobjectinput.initreading:boolean;
  759. begin
  760. result:=inherited initreading;
  761. if result then
  762. begin
  763. if win32 then
  764. FData:=tcoffdata.createwin32
  765. else
  766. FData:=tcoffdata.createdjgpp;
  767. FCoffSyms:=TDynamicArray.Create(symbolresize);
  768. end;
  769. end;
  770. procedure tcoffobjectinput.donereading;
  771. begin
  772. FCoffSyms.Free;
  773. end;
  774. procedure tcoffobjectinput.read_relocs(s:tcoffsection);
  775. var
  776. rel : coffreloc;
  777. rel_type : relative_type;
  778. i : longint;
  779. p : pasmsymbol;
  780. begin
  781. for i:=1 to s.coffrelocs do
  782. begin
  783. FReader.read(rel,sizeof(rel));
  784. case rel.relative of
  785. $14 : rel_type:=relative_true;
  786. $06 : rel_type:=relative_false;
  787. $07 : rel_type:=relative_rva;
  788. else
  789. begin
  790. Comment(V_Error,'Error reading coff file');
  791. exit;
  792. end;
  793. end;
  794. p:=FSymTbl^[rel.sym];
  795. if assigned(p) then
  796. begin
  797. s.addsymreloc(rel.address,p,rel_type);
  798. end
  799. else
  800. begin
  801. Comment(V_Error,'Error reading coff file');
  802. exit;
  803. end;
  804. end;
  805. end;
  806. procedure tcoffobjectinput.handle_symbols;
  807. var
  808. filename : string[18];
  809. sec : tsection;
  810. sectionval,
  811. i,nsyms,
  812. symidx : longint;
  813. globalval : byte;
  814. secrec : coffsectionrec;
  815. sym,
  816. sym2 : coffsymbol;
  817. strname,
  818. strname2 : string;
  819. p : pasmsymbol;
  820. auxrec : array[0..17] of byte;
  821. begin
  822. with tcoffdata(data) do
  823. begin
  824. nsyms:=FCoffSyms.Size div sizeof(CoffSymbol);
  825. { Allocate memory for symidx -> pasmsymbol table }
  826. GetMem(FSymTbl,nsyms*sizeof(pointer));
  827. FillChar(FSymTbl^,nsyms*sizeof(pointer),0);
  828. { Loop all symbols }
  829. FCoffSyms.Seek(0);
  830. symidx:=0;
  831. while (symidx<nsyms) do
  832. begin
  833. FCoffSyms.Read(sym,sizeof(sym));
  834. if plongint(@sym.name)^<>0 then
  835. begin
  836. move(sym.name,strname[1],8);
  837. strname[9]:=#0;
  838. end
  839. else
  840. begin
  841. FStrs.Seek(sym.strpos-4);
  842. FStrs.Read(strname[1],255);
  843. strname[255]:=#0;
  844. end;
  845. strname[0]:=chr(strlen(@strname[1]));
  846. if strname='' then
  847. Internalerror(341324310);
  848. case sym.typ of
  849. COFF_SYM_EXTERNAL :
  850. begin
  851. if sym.section=0 then
  852. begin
  853. p:=new(pasmsymbol,init(strname,AB_EXTERNAL,AT_FUNCTION));
  854. end
  855. else
  856. begin
  857. p:=new(pasmsymbol,init(strname,AB_GLOBAL,AT_FUNCTION));
  858. sec:=Fidx2sec[sym.section];
  859. if assigned(sects[sec]) then
  860. begin
  861. p^.section:=sec;
  862. if sym.value>=sects[sec].mempos then
  863. p^.address:=sym.value-sects[sec].mempos
  864. else
  865. internalerror(432432432);
  866. end
  867. else
  868. internalerror(34243214);
  869. end;
  870. AddSymbol(p);
  871. FSymTbl^[symidx]:=p
  872. end;
  873. COFF_SYM_STATIC :
  874. begin
  875. p:=new(pasmsymbol,init(strname,AB_LOCAL,AT_FUNCTION));
  876. sec:=Fidx2sec[sym.section];
  877. if assigned(sects[sec]) then
  878. begin
  879. p^.section:=sec;
  880. if sym.value>=sects[sec].mempos then
  881. p^.address:=sym.value-sects[sec].mempos
  882. else
  883. begin
  884. if Str2Sec(strname)<>sec then
  885. internalerror(432432432);
  886. end;
  887. end
  888. else
  889. internalerror(34243214);
  890. AddSymbol(p);
  891. FSymTbl^[symidx]:=p;
  892. end;
  893. COFF_SYM_SECTION,
  894. COFF_SYM_LABEL,
  895. COFF_SYM_FUNCTION,
  896. COFF_SYM_FILE :
  897. ;
  898. else
  899. internalerror(4342343);
  900. end;
  901. { read aux records }
  902. for i:=1 to sym.aux do
  903. begin
  904. FCoffSyms.Read(auxrec,sizeof(auxrec));
  905. inc(symidx);
  906. end;
  907. inc(symidx);
  908. end;
  909. end;
  910. end;
  911. procedure tcoffobjectinput.readfromdisk;
  912. var
  913. datapos,
  914. secsymidx,
  915. nsects,
  916. strsize,
  917. sympos,i : longint;
  918. hstab : coffstab;
  919. gotreloc : boolean;
  920. sec : tsection;
  921. header : coffheader;
  922. sechdr : coffsechdr;
  923. empty : array[0..15] of byte;
  924. hp : pdynamicblock;
  925. begin
  926. with tcoffdata(data) do
  927. begin
  928. FillChar(Fidx2sec,sizeof(Fidx2sec),0);
  929. { COFF header }
  930. if not reader.read(header,sizeof(coffheader)) then
  931. begin
  932. Comment(V_Error,'Error reading coff file');
  933. exit;
  934. end;
  935. if header.mach<>$14c then
  936. begin
  937. Comment(V_Error,'Not a coff file');
  938. exit;
  939. end;
  940. if header.nsects>255 then
  941. begin
  942. Comment(V_Error,'To many sections');
  943. exit;
  944. end;
  945. { header.mach:=$14c;
  946. header.nsects:=nsects;
  947. header.sympos:=sympos;
  948. header.syms:=(Syms.size div sizeof(TOutputSymbol))+initsym;
  949. if gotreloc then
  950. header.flag:=$104
  951. else
  952. header.flag:=$105 }
  953. { Section headers }
  954. for i:=1 to header.nsects do
  955. begin
  956. if not reader.read(sechdr,sizeof(sechdr)) then
  957. begin
  958. Comment(V_Error,'Error reading coff file');
  959. exit;
  960. end;
  961. sec:=str2sec(strpas(sechdr.name));
  962. if sec<>sec_none then
  963. begin
  964. Fidx2sec[i]:=sec;
  965. createsection(sec);
  966. if not win32 then
  967. sects[sec].mempos:=sechdr.rvaofs;
  968. tcoffsection(sects[sec]).coffrelocs:=sechdr.nrelocs;
  969. tcoffsection(sects[sec]).coffrelocpos:=sechdr.relocpos;
  970. sects[sec].datapos:=sechdr.datapos;
  971. sects[sec].datasize:=sechdr.datasize;
  972. tcoffsection(sects[sec]).flags:=sechdr.flags;
  973. end
  974. else
  975. Comment(V_Warning,'skipping unsupported section '+strpas(sechdr.name));
  976. end;
  977. { Symbols }
  978. Reader.Seek(header.sympos);
  979. if not Reader.ReadArray(FCoffSyms,header.syms*sizeof(CoffSymbol)) then
  980. begin
  981. Comment(V_Error,'Error reading coff file');
  982. exit;
  983. end;
  984. { Strings }
  985. if not Reader.Read(strsize,4) then
  986. begin
  987. Comment(V_Error,'Error reading coff file');
  988. exit;
  989. end;
  990. if strsize<4 then
  991. begin
  992. Comment(V_Error,'Error reading coff file');
  993. exit;
  994. end;
  995. if not Reader.ReadArray(FStrs,Strsize-4) then
  996. begin
  997. Comment(V_Error,'Error reading coff file');
  998. exit;
  999. end;
  1000. { Insert all symbols }
  1001. handle_symbols;
  1002. { Sections }
  1003. for sec:=low(tsection) to high(tsection) do
  1004. if assigned(sects[sec]) and
  1005. (sec<>sec_bss) then
  1006. begin
  1007. Reader.Seek(sects[sec].datapos);
  1008. if not Reader.ReadArray(sects[sec].data,sects[sec].datasize) then
  1009. begin
  1010. Comment(V_Error,'Error reading coff file');
  1011. exit;
  1012. end;
  1013. end;
  1014. { Relocs }
  1015. for sec:=low(tsection) to high(tsection) do
  1016. if assigned(sects[sec]) and
  1017. (tcoffsection(sects[sec]).coffrelocs>0) then
  1018. begin
  1019. Reader.Seek(tcoffsection(sects[sec]).coffrelocpos);
  1020. read_relocs(tcoffsection(sects[sec]));
  1021. end;
  1022. end;
  1023. end;
  1024. end.
  1025. {
  1026. $Log$
  1027. Revision 1.10 2001-03-13 18:45:07 peter
  1028. * fixed some memory leaks
  1029. Revision 1.9 2001/03/05 21:40:38 peter
  1030. * more things for tcoffobjectinput
  1031. Revision 1.8 2000/12/25 00:07:26 peter
  1032. + new tlinkedlist class (merge of old tstringqueue,tcontainer and
  1033. tlinkedlist objects)
  1034. Revision 1.7 2000/12/24 12:25:31 peter
  1035. + cstreams unit
  1036. * dynamicarray object to class
  1037. Revision 1.6 2000/12/23 19:59:35 peter
  1038. * object to class for ow/og objects
  1039. * split objectdata from objectoutput
  1040. Revision 1.5 2000/12/21 12:06:38 jonas
  1041. * changed type of all "flags" variables/parameters/fields to cardinal
  1042. and removed longint typecasts around constants
  1043. Revision 1.4 2000/12/20 15:59:04 jonas
  1044. * fixed range check errors
  1045. Revision 1.3 2000/12/18 21:56:35 peter
  1046. * fixed stab reloc writing
  1047. Revision 1.2 2000/12/07 17:19:42 jonas
  1048. * new constant handling: from now on, hex constants >$7fffffff are
  1049. parsed as unsigned constants (otherwise, $80000000 got sign extended
  1050. and became $ffffffff80000000), all constants in the longint range
  1051. become longints, all constants >$7fffffff and <=cardinal($ffffffff)
  1052. are cardinals and the rest are int64's.
  1053. * added lots of longint typecast to prevent range check errors in the
  1054. compiler and rtl
  1055. * type casts of symbolic ordinal constants are now preserved
  1056. * fixed bug where the original resulttype wasn't restored correctly
  1057. after doing a 64bit rangecheck
  1058. Revision 1.1 2000/11/12 22:20:37 peter
  1059. * create generic toutputsection for binary writers
  1060. }