oglx.pas 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407
  1. {
  2. $Id$
  3. Copyright (c) 2002 by Daniel Mantione, Peter Vreman
  4. Contains the binary reader and writer for the linear executable
  5. format used by OS/2
  6. * This code was inspired by the NASM sources
  7. The Netwide Assembler is copyright (C) 1996 Simon Tatham and
  8. Julian Hall. All rights reserved.
  9. This program is free software; you can redistribute it and/or modify
  10. it under the terms of the GNU General Public License as published by
  11. the Free Software Foundation; either version 2 of the License, or
  12. (at your option) any later version.
  13. This program is distributed in the hope that it will be useful,
  14. but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. GNU General Public License for more details.
  17. You should have received a copy of the GNU General Public License
  18. along with this program; if not, write to the Free Software
  19. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20. ****************************************************************************
  21. }
  22. unit oglx;
  23. {$i fpcdefs.inc}
  24. interface
  25. uses
  26. { common }
  27. cclasses,
  28. { target }
  29. systems,
  30. { assembler }
  31. cpubase,aasmbase,assemble,link,
  32. { output }
  33. ogbase,ogmap,ogcoff;
  34. type Tlxheader = packed record
  35. magic:word; {'LX'}
  36. byteorder:byte; {0 = little 1 = big endian}
  37. wordorder:byte;
  38. cpu_type:word;
  39. os_type:word;
  40. module_version:cardinal;
  41. module_flags:cardinal;
  42. module_page_count:cardinal;
  43. eip_object,eip:cardinal;
  44. esp_object,esp:cardinal;
  45. page_size,page_shift:cardinal;
  46. fixup_sect_size:cardinal;
  47. fixup_sect_checksum:cardinal;
  48. loader_sect_size:cardinal;
  49. loader_sect_chksum:cardinal;
  50. object_table_offset:cardinal;
  51. object_count:cardinal;
  52. object_pagetable_ofs:cardinal;
  53. object_iterpages_ofs:cardinal;
  54. resource_table_ofs:cardinal;
  55. resource_count:cardinal;
  56. end;
  57. Tlxexeoutput = class(texeoutput)
  58. private
  59. { FCoffsyms,
  60. FCoffStrs : tdynamicarray;
  61. win32 : boolean;}
  62. nsects,
  63. nsyms,
  64. sympos : longint;
  65. procedure write_symbol(const name:string;strpos,value,section,typ,aux:longint);
  66. procedure write_symbols;
  67. protected
  68. function writedata:boolean;override;
  69. public
  70. constructor createos2;
  71. function newobjectinput:tobjectinput;override;
  72. procedure CalculateMemoryMap;override;
  73. procedure GenerateExecutable(const fn:string);override;
  74. end;
  75. tlxlinker = class(tinternallinker)
  76. constructor create;override;
  77. end;
  78. implementation
  79. uses
  80. {$ifdef delphi}
  81. sysutils,
  82. {$else}
  83. strings,
  84. {$endif}
  85. cutils,verbose,
  86. globtype,globals,fmodule;
  87. {****************************************************************************
  88. tcoffexeoutput
  89. ****************************************************************************}
  90. constructor Tlxexeoutput.createos2;
  91. begin
  92. inherited create;
  93. end;
  94. function Tlxexeoutput.newobjectinput:tobjectinput;
  95. begin
  96. result:=tcoffobjectinput.createdjgpp;
  97. end;
  98. procedure Tlxexeoutput.write_symbol(const name:string;strpos,value,section,typ,aux:longint);
  99. { var
  100. sym : coffsymbol;}
  101. begin
  102. { FillChar(sym,sizeof(sym),0);
  103. if strpos=-1 then
  104. move(name[1],sym.name,length(name))
  105. else
  106. sym.strpos:=strpos;
  107. sym.value:=value;
  108. sym.section:=section;
  109. sym.typ:=typ;
  110. sym.aux:=aux;
  111. FWriter.write(sym,sizeof(sym));}
  112. end;
  113. procedure Tlxexeoutput.write_symbols;
  114. { var
  115. filename : string[18];
  116. sec : TSection;
  117. namestr : string[8];
  118. nameidx,
  119. value,
  120. sectionval,
  121. i : longint;
  122. globalval : byte;
  123. secrec : coffsectionrec;
  124. objdata : TAsmObjectData;
  125. p : tasmsymbol;
  126. s : string;}
  127. begin
  128. (* objdata:=TAsmObjectData(objdatalist.first);
  129. while assigned(objdata) do
  130. begin
  131. with tcoffobjectdata(objdata) do
  132. begin
  133. { The symbols used }
  134. p:=Tasmsymbol(symbols.First);
  135. while assigned(p) do
  136. begin
  137. if p.section=sec_common then
  138. sectionval:=sections[sec_bss].secsymidx
  139. else
  140. sectionval:=sections[p.section].secsymidx;
  141. if p.currbind=AB_LOCAL then
  142. globalval:=3
  143. else
  144. globalval:=2;
  145. { if local of global then set the section value to the address
  146. of the symbol }
  147. if p.currbind in [AB_LOCAL,AB_GLOBAL] then
  148. value:=p.address
  149. else
  150. value:=p.size;
  151. { symbolname }
  152. s:=p.name;
  153. if length(s)>8 then
  154. begin
  155. nameidx:=FCoffStrs.size+4;
  156. FCoffStrs.writestr(s);
  157. FCoffStrs.writestr(#0);
  158. end
  159. else
  160. begin
  161. nameidx:=-1;
  162. namestr:=s;
  163. end;
  164. write_symbol(namestr,nameidx,value,sectionval,globalval,0);
  165. p:=tasmsymbol(p.indexnext);
  166. end;
  167. end;
  168. objdata:=TAsmObjectData(objdata.next);
  169. end;*)
  170. end;
  171. procedure Tlxexeoutput.CalculateMemoryMap;
  172. { var
  173. objdata : TAsmObjectData;
  174. secsymidx,
  175. mempos,
  176. datapos : longint;
  177. sec : TSection;
  178. sym : tasmsymbol;
  179. s : TAsmSection;}
  180. begin
  181. (* { retrieve amount of sections }
  182. nsects:=0;
  183. secsymidx:=0;
  184. for sec:=low(TSection) to high(TSection) do
  185. begin
  186. if sections[sec].available then
  187. begin
  188. inc(nsects);
  189. inc(secsymidx);
  190. sections[sec].secsymidx:=secsymidx;
  191. end;
  192. end;
  193. { calculate start positions after the headers }
  194. datapos:=sizeof(coffheader)+sizeof(coffoptheader)+sizeof(coffsechdr)*nsects;
  195. mempos:=sizeof(coffheader)+sizeof(coffoptheader)+sizeof(coffsechdr)*nsects;
  196. if not win32 then
  197. inc(mempos,sizeof(go32v2stub)+$1000);
  198. { add sections }
  199. MapObjectdata(datapos,mempos);
  200. { end symbol }
  201. AddGlobalSym('_etext',sections[sec_code].mempos+sections[sec_code].memsize);
  202. AddGlobalSym('_edata',sections[sec_data].mempos+sections[sec_data].memsize);
  203. AddGlobalSym('end',mempos);
  204. { symbols }
  205. nsyms:=0;
  206. sympos:=0;
  207. if not(cs_link_strip in aktglobalswitches) then
  208. begin
  209. sympos:=datapos;
  210. objdata:=TAsmObjectData(objdatalist.first);
  211. while assigned(objdata) do
  212. begin
  213. inc(nsyms,objdata.symbols.count);
  214. objdata:=TAsmObjectData(objdata.next);
  215. end;
  216. end;*)
  217. end;
  218. function Tlxexeoutput.writedata:boolean;
  219. { var
  220. datapos,
  221. secsymidx,
  222. i : longint;
  223. hstab : coffstab;
  224. gotreloc : boolean;
  225. sec : TSection;
  226. header : coffheader;
  227. optheader : coffoptheader;
  228. sechdr : coffsechdr;
  229. empty : array[0..15] of byte;
  230. hp : pdynamicblock;
  231. objdata : TAsmObjectData;
  232. hsym : tasmsymbol;}
  233. begin
  234. (* result:=false;
  235. FCoffSyms:=TDynamicArray.Create(symbolresize);
  236. FCoffStrs:=TDynamicArray.Create(strsresize);
  237. { Stub }
  238. if not win32 then
  239. FWriter.write(go32v2stub,sizeof(go32v2stub));
  240. { COFF header }
  241. fillchar(header,sizeof(header),0);
  242. header.mach:=$14c;
  243. header.nsects:=nsects;
  244. header.sympos:=sympos;
  245. header.syms:=nsyms;
  246. header.opthdr:=sizeof(coffoptheader);
  247. header.flag:=COFF_FLAG_AR32WR or COFF_FLAG_EXE or COFF_FLAG_NORELOCS or COFF_FLAG_NOLINES;
  248. FWriter.write(header,sizeof(header));
  249. { Optional COFF Header }
  250. fillchar(optheader,sizeof(optheader),0);
  251. optheader.magic:=$10b;
  252. optheader.tsize:=sections[sec_code].memsize;
  253. optheader.dsize:=sections[sec_data].memsize;
  254. optheader.bsize:=sections[sec_bss].memsize;
  255. hsym:=tasmsymbol(globalsyms.search('start'));
  256. if not assigned(hsym) then
  257. begin
  258. Comment(V_Error,'Entrypoint "start" not defined');
  259. exit;
  260. end;
  261. optheader.entry:=hsym.address;
  262. optheader.text_start:=sections[sec_code].mempos;
  263. optheader.data_start:=sections[sec_data].mempos;
  264. FWriter.write(optheader,sizeof(optheader));
  265. { Section headers }
  266. for sec:=low(TSection) to high(TSection) do
  267. if sections[sec].available then
  268. begin
  269. fillchar(sechdr,sizeof(sechdr),0);
  270. move(target_asm.secnames[sec][1],sechdr.name,length(target_asm.secnames[sec]));
  271. if not win32 then
  272. begin
  273. sechdr.rvaofs:=sections[sec].mempos;
  274. sechdr.vsize:=sections[sec].mempos;
  275. end
  276. else
  277. begin
  278. if sec=sec_bss then
  279. sechdr.vsize:=sections[sec].memsize;
  280. end;
  281. if sec=sec_bss then
  282. sechdr.datasize:=sections[sec].memsize
  283. else
  284. begin
  285. sechdr.datasize:=sections[sec].datasize;
  286. sechdr.datapos:=sections[sec].datapos;
  287. end;
  288. sechdr.nrelocs:=0;
  289. sechdr.relocpos:=0;
  290. sechdr.flags:=sections[sec].flags;
  291. FWriter.write(sechdr,sizeof(sechdr));
  292. end;
  293. { Sections }
  294. for sec:=low(TSection) to high(TSection) do
  295. if sections[sec].available then
  296. begin
  297. { update objectfiles }
  298. objdata:=TAsmObjectData(objdatalist.first);
  299. while assigned(objdata) do
  300. begin
  301. if assigned(objdata.sects[sec]) and
  302. assigned(objdata.sects[sec].data) then
  303. begin
  304. WriteZeros(objdata.sects[sec].dataalignbytes);
  305. hp:=objdata.sects[sec].data.firstblock;
  306. while assigned(hp) do
  307. begin
  308. FWriter.write(hp^.data,hp^.used);
  309. hp:=hp^.next;
  310. end;
  311. end;
  312. objdata:=TAsmObjectData(objdata.next);
  313. end;
  314. end;
  315. { Optional symbols }
  316. if not(cs_link_strip in aktglobalswitches) then
  317. begin
  318. { Symbols }
  319. write_symbols;
  320. { Strings }
  321. i:=FCoffStrs.size+4;
  322. FWriter.write(i,4);
  323. hp:=FCoffStrs.firstblock;
  324. while assigned(hp) do
  325. begin
  326. FWriter.write(hp^.data,hp^.used);
  327. hp:=hp^.next;
  328. end;
  329. end;
  330. { Release }
  331. FCoffStrs.Free;
  332. FCoffSyms.Free;
  333. result:=true;*)
  334. end;
  335. procedure Tlxexeoutput.GenerateExecutable(const fn:string);
  336. begin
  337. { AddGlobalSym('_etext',0);
  338. AddGlobalSym('_edata',0);
  339. AddGlobalSym('end',0);
  340. if not CalculateSymbols then
  341. exit;
  342. CalculateMemoryMap;
  343. FixupSymbols;
  344. FixupRelocations;
  345. writeexefile(fn);}
  346. end;
  347. {****************************************************************************
  348. TCoffLinker
  349. ****************************************************************************}
  350. constructor Tlxlinker.Create;
  351. begin
  352. inherited Create;
  353. exeoutput:=Tlxexeoutput.createos2;
  354. end;
  355. {*****************************************************************************
  356. Initialize
  357. *****************************************************************************}
  358. begin
  359. { RegisterAssembler(as_i386_coff_info,TCoffAssembler);
  360. RegisterAssembler(as_i386_pecoff_info,TPECoffAssembler);
  361. RegisterAssembler(as_i386_pecoffwdosx_info,TPECoffAssembler);}
  362. RegisterLinker(ld_i386_coff,Tlxlinker);
  363. end.
  364. {
  365. $Log$
  366. Revision 1.1 2002-07-08 19:22:22 daniel
  367. + OS/2 lx format support: Copied ogcoff and started to modify it
  368. }