2
0

oglx.pas 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. {
  2. Copyright (c) 2002 by Daniel Mantione, Peter Vreman
  3. Contains the binary reader and writer for the linear executable
  4. format used by OS/2
  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 oglx;
  22. {$i fpcdefs.inc}
  23. interface
  24. uses
  25. { common }
  26. cclasses,
  27. { target }
  28. systems,
  29. { assembler }
  30. cpubase,aasmbase,assemble,link,
  31. { output }
  32. ogbase,ogmap,ogcoff;
  33. { An LX executable is called a module; it can be either an executable
  34. or a DLL.
  35. A module consists of objects. In other executable formats, these
  36. are usually called sections.
  37. Objects consist of pages.
  38. The objects are numbered, numbers do not have any special meaning. The
  39. pages of the object are loaded into memory with the access rights specified
  40. the object table entry. (DM)}
  41. { For the operating system the object numbers have no special meaning.
  42. However, for Free Pascal generated executables, I define: (DM)}
  43. const code_object = 0;
  44. data_object = 1;
  45. bss_object = 2;
  46. stack_object = 3;
  47. heap_object = 4;
  48. type Tlxheader = packed record
  49. magic:word; {'LX'}
  50. byteorder:byte; {0 = little 1 = big endian.}
  51. wordorder:byte; {0 = little 1 = big endian.}
  52. format_level:cardinal; {Nothing else than LX level
  53. 0 has ever been defined.}
  54. cpu_type:word; {1 = 286, 2 = 386, 3 = 486,
  55. 4 = pentium.}
  56. os_type:word; {1 = OS/2, 2 = Windows,
  57. 3 = Siemens MS-Dos 4.0,
  58. 4 = Windows 386.}
  59. module_version:cardinal; {Version of executable,
  60. defined by user.}
  61. module_flags:cardinal; {Flags.}
  62. module_page_count:cardinal; {Amount of pages in module.}
  63. eip_object,eip:cardinal; {Initial EIP, object nr and
  64. offset within object.}
  65. esp_object,esp:cardinal; {Initial ESP, object nr and
  66. offset within object.}
  67. page_size,page_shift:cardinal; {Page size, in bytes and
  68. 1 << pageshift.}
  69. fixup_sect_size:cardinal;
  70. fixup_sect_checksum:cardinal;
  71. loader_sect_size:cardinal;
  72. loader_sect_chksum:cardinal;
  73. object_table_offset:cardinal; {Location of object table.}
  74. object_count:cardinal; {Amount of objects in module.}
  75. object_pagetable_ofs:cardinal; {Location of object page
  76. table.}
  77. object_iterpages_ofs:cardinal;
  78. resource_table_ofs:cardinal; {Location of resource table.}
  79. resource_count:cardinal; {Amount of resources in
  80. resource table.}
  81. resid_name_tbl_ofs:cardinal;
  82. entry_table_offset:cardinal;
  83. module_dir_offset:cardinal;
  84. module_dir_count:cardinal;
  85. fixup_pagetab_ofs:cardinal;
  86. fixup_recrab_ofs:cardinal;
  87. import_modtab_ofs:cardinal;
  88. import_modtab_count:cardinal;
  89. data_pages_offset:cardinal;
  90. preload_page_count:cardinal;
  91. nonresid_table_ofs:cardinal;
  92. nonresid_table_len:cardinal;
  93. nonresid_tbl_chksum:cardinal;
  94. auto_ds_object_no:cardinal; {Not used by OS/2.}
  95. debug_info_offset:cardinal;
  96. inst_preload_count:cardinal;
  97. inst_demand_count:cardinal;
  98. heapsize:cardinal; {Only used for 16-bit programs.}
  99. end;
  100. Tlxobject_flags = (ofreadable,ofwriteable,ofexecutable,ofresource,
  101. ofdiscardable,ofshared,ofpreload,ofinvalid,
  102. ofzerofilled);
  103. Tlxobject_flag_set = set of Tlxobject_flags;
  104. Tlxobject_table_entry = packed record
  105. virtual_size:cardinal;
  106. reloc_base_addr:cardinal;
  107. object_flags:Tlxobject_flag_set;
  108. page_table_index:cardinal;
  109. page_count:cardinal;
  110. reserved:cardinal;
  111. end;
  112. Tlxexeoutput = class(texeoutput)
  113. private
  114. { FCoffsyms,
  115. FCoffStrs : tdynamicarray;
  116. win32 : boolean;}
  117. nsects,
  118. nsyms,
  119. sympos : longint;
  120. procedure write_symbol(const name:string;strpos,value,section,typ,aux:longint);
  121. procedure write_symbols;
  122. protected
  123. function writedata:boolean;override;
  124. public
  125. constructor createos2;
  126. function newobjectinput:tobjectinput;override;
  127. procedure CalculateMemoryMap;override;
  128. procedure GenerateExecutable(const fn:string);override;
  129. end;
  130. Tlxlinker = class(tinternallinker)
  131. constructor create;override;
  132. end;
  133. implementation
  134. uses
  135. strings,
  136. cutils,verbose,
  137. globtype,globals,fmodule,
  138. owar;
  139. {****************************************************************************
  140. tcoffexeoutput
  141. ****************************************************************************}
  142. constructor Tlxexeoutput.createos2;
  143. begin
  144. inherited create;
  145. end;
  146. function Tlxexeoutput.newobjectinput:tobjectinput;
  147. begin
  148. result:=tcoffobjectinput.createdjgpp;
  149. end;
  150. procedure Tlxexeoutput.write_symbol(const name:string;strpos,value,section,typ,aux:longint);
  151. { var
  152. sym : coffsymbol;}
  153. begin
  154. { FillChar(sym,sizeof(sym),0);
  155. if strpos=-1 then
  156. move(name[1],sym.name,length(name))
  157. else
  158. sym.strpos:=strpos;
  159. sym.value:=value;
  160. sym.section:=section;
  161. sym.typ:=typ;
  162. sym.aux:=aux;
  163. FWriter.write(sym,sizeof(sym));}
  164. end;
  165. procedure Tlxexeoutput.write_symbols;
  166. { var
  167. filename : string[18];
  168. sec : TSection;
  169. namestr : string[8];
  170. nameidx,
  171. value,
  172. sectionval,
  173. i : longint;
  174. globalval : byte;
  175. secrec : coffsectionrec;
  176. objdata : TObjData;
  177. p : tasmsymbol;
  178. s : string;}
  179. begin
  180. (* objdata:=TObjData(objdatalist.first);
  181. while assigned(objdata) do
  182. begin
  183. with tcoffObjData(objdata) do
  184. begin
  185. { The symbols used }
  186. p:=Tasmsymbol(symbols.First);
  187. while assigned(p) do
  188. begin
  189. if p.section=sec_common then
  190. sectionval:=sections[sec_bss].secsymidx
  191. else
  192. sectionval:=sections[p.section].secsymidx;
  193. if p.currbind=AB_LOCAL then
  194. globalval:=3
  195. else
  196. globalval:=2;
  197. { if local of global then set the section value to the address
  198. of the symbol }
  199. if p.currbind in [AB_LOCAL,AB_GLOBAL] then
  200. value:=p.address
  201. else
  202. value:=p.size;
  203. { symbolname }
  204. s:=p.name;
  205. if length(s)>8 then
  206. begin
  207. nameidx:=FCoffStrs.size+4;
  208. FCoffStrs.writestr(s);
  209. FCoffStrs.writestr(#0);
  210. end
  211. else
  212. begin
  213. nameidx:=-1;
  214. namestr:=s;
  215. end;
  216. write_symbol(namestr,nameidx,value,sectionval,globalval,0);
  217. p:=tasmsymbol(p.indexnext);
  218. end;
  219. end;
  220. objdata:=TObjData(objdata.next);
  221. end;*)
  222. end;
  223. procedure Tlxexeoutput.CalculateMemoryMap;
  224. { var
  225. objdata : TObjData;
  226. secsymidx,
  227. mempos,
  228. datapos : longint;
  229. sec : TSection;
  230. sym : tasmsymbol;
  231. s : TObjSection;}
  232. begin
  233. (* { retrieve amount of sections }
  234. nsects:=0;
  235. secsymidx:=0;
  236. for sec:=low(TSection) to high(TSection) do
  237. begin
  238. if sections[sec].available then
  239. begin
  240. inc(nsects);
  241. inc(secsymidx);
  242. sections[sec].secsymidx:=secsymidx;
  243. end;
  244. end;
  245. { calculate start positions after the headers }
  246. datapos:=sizeof(coffheader)+sizeof(coffoptheader)+sizeof(coffsechdr)*nsects;
  247. mempos:=sizeof(coffheader)+sizeof(coffoptheader)+sizeof(coffsechdr)*nsects;
  248. if not win32 then
  249. inc(mempos,sizeof(go32v2stub)+$1000);
  250. { add sections }
  251. MapObjData(datapos,mempos);
  252. { end symbol }
  253. AddGlobalSym('_etext',sections[sec_code].mempos+sections[sec_code].memsize);
  254. AddGlobalSym('_edata',sections[sec_data].mempos+sections[sec_data].memsize);
  255. AddGlobalSym('end',mempos);
  256. { symbols }
  257. nsyms:=0;
  258. sympos:=0;
  259. if not(cs_link_strip in current_settings.globalswitches) then
  260. begin
  261. sympos:=datapos;
  262. objdata:=TObjData(objdatalist.first);
  263. while assigned(objdata) do
  264. begin
  265. inc(nsyms,objdata.symbols.count);
  266. objdata:=TObjData(objdata.next);
  267. end;
  268. end;*)
  269. end;
  270. function gen_section_header(sec:Tsection;obj:cardinal):Tlxobject_table_entry;
  271. virtual_size:cardinal;
  272. reloc_base_addr:cardinal;
  273. object_flags:Tlxobject_flag_set;
  274. page_table_index:cardinal;
  275. page_count:cardinal;
  276. reserved:cardinal;
  277. begin
  278. gen_section_header.virtual_size:=sections[sec.memsize];
  279. end;
  280. function Tlxexeoutput.writedata:boolean;
  281. var header:Tlxheader;
  282. hsym:Tasmsymbol;
  283. code_object_header,data_object_header,bss_object_header,stack_object_header,
  284. heap_object_header:Tlxobject_table_entry;
  285. begin
  286. result:=false;
  287. fillchar(header,sizeof(header),0);
  288. header.magic:=$584c; {'LX'}
  289. header.cpu_type:=2; {Intel 386}
  290. header.os_type:=1; {OS/2}
  291. {Set the initial EIP.}
  292. header.eip_object:=code_object;
  293. hsym:=tasmsymbol(globalsyms.Find('start'));
  294. if not assigned(hsym) then
  295. begin
  296. comment(V_Error,'Entrypoint "start" not defined');
  297. exit;
  298. end;
  299. header.eip:=hsym.address-sections[sec_code].mempos;
  300. {Set the initial ESP.}
  301. header.esp_object:=stack_object;
  302. header.esp:=stacksize;
  303. Fwriter.write(header,sizeof(header));
  304. for sec:=low(Tsection) to high(Tsection) do
  305. if sections[sec].available then
  306. if not(sec in [sec_code,sec_data,sec_bss,sec_stab,sec_stabstr]) then
  307. begin
  308. result:=false;
  309. exit;
  310. end;
  311. code_object_header:=gen_section_header(sec_code,code_object);
  312. data_object_header:=gen_section_header(sec_data,data_object);
  313. bss_object_header:=gen_section_header(sec_bss,bss_object);
  314. result:=true;
  315. end;
  316. procedure Tlxexeoutput.GenerateExecutable(const fn:string);
  317. begin
  318. { AddGlobalSym('_etext',0);
  319. AddGlobalSym('_edata',0);
  320. AddGlobalSym('end',0);
  321. if not CalculateSymbols then
  322. exit;
  323. CalculateMemoryMap;
  324. FixupSymbols;
  325. FixupRelocations;
  326. writeexefile(fn);}
  327. end;
  328. {****************************************************************************
  329. TCoffLinker
  330. ****************************************************************************}
  331. constructor Tlxlinker.Create;
  332. begin
  333. inherited Create;
  334. CArObjectReader:=TArObjectReader;
  335. exeoutput:=Tlxexeoutput.createos2;
  336. end;
  337. {*****************************************************************************
  338. Initialize
  339. *****************************************************************************}
  340. begin
  341. { RegisterAssembler(as_i386_coff_info,TCoffAssembler);
  342. RegisterAssembler(as_i386_pecoff_info,TPECoffAssembler);
  343. RegisterAssembler(as_i386_pecoffwdosx_info,TPECoffAssembler);
  344. RegisterLinker(ld_i386_coff,Tlxlinker);}
  345. end.