ogcoff.pas 35 KB

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