ogcoff.pas 39 KB

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