ogcoff.pas 38 KB

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