2
0

oglx.pas 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  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. {****************************************************************************
  139. tcoffexeoutput
  140. ****************************************************************************}
  141. constructor Tlxexeoutput.createos2;
  142. begin
  143. inherited create;
  144. end;
  145. function Tlxexeoutput.newobjectinput:tobjectinput;
  146. begin
  147. result:=tcoffobjectinput.createdjgpp;
  148. end;
  149. procedure Tlxexeoutput.write_symbol(const name:string;strpos,value,section,typ,aux:longint);
  150. { var
  151. sym : coffsymbol;}
  152. begin
  153. { FillChar(sym,sizeof(sym),0);
  154. if strpos=-1 then
  155. move(name[1],sym.name,length(name))
  156. else
  157. sym.strpos:=strpos;
  158. sym.value:=value;
  159. sym.section:=section;
  160. sym.typ:=typ;
  161. sym.aux:=aux;
  162. FWriter.write(sym,sizeof(sym));}
  163. end;
  164. procedure Tlxexeoutput.write_symbols;
  165. { var
  166. filename : string[18];
  167. sec : TSection;
  168. namestr : string[8];
  169. nameidx,
  170. value,
  171. sectionval,
  172. i : longint;
  173. globalval : byte;
  174. secrec : coffsectionrec;
  175. objdata : TObjData;
  176. p : tasmsymbol;
  177. s : string;}
  178. begin
  179. (* objdata:=TObjData(objdatalist.first);
  180. while assigned(objdata) do
  181. begin
  182. with tcoffObjData(objdata) do
  183. begin
  184. { The symbols used }
  185. p:=Tasmsymbol(symbols.First);
  186. while assigned(p) do
  187. begin
  188. if p.section=sec_common then
  189. sectionval:=sections[sec_bss].secsymidx
  190. else
  191. sectionval:=sections[p.section].secsymidx;
  192. if p.currbind=AB_LOCAL then
  193. globalval:=3
  194. else
  195. globalval:=2;
  196. { if local of global then set the section value to the address
  197. of the symbol }
  198. if p.currbind in [AB_LOCAL,AB_GLOBAL] then
  199. value:=p.address
  200. else
  201. value:=p.size;
  202. { symbolname }
  203. s:=p.name;
  204. if length(s)>8 then
  205. begin
  206. nameidx:=FCoffStrs.size+4;
  207. FCoffStrs.writestr(s);
  208. FCoffStrs.writestr(#0);
  209. end
  210. else
  211. begin
  212. nameidx:=-1;
  213. namestr:=s;
  214. end;
  215. write_symbol(namestr,nameidx,value,sectionval,globalval,0);
  216. p:=tasmsymbol(p.indexnext);
  217. end;
  218. end;
  219. objdata:=TObjData(objdata.next);
  220. end;*)
  221. end;
  222. procedure Tlxexeoutput.CalculateMemoryMap;
  223. { var
  224. objdata : TObjData;
  225. secsymidx,
  226. mempos,
  227. datapos : longint;
  228. sec : TSection;
  229. sym : tasmsymbol;
  230. s : TObjSection;}
  231. begin
  232. (* { retrieve amount of sections }
  233. nsects:=0;
  234. secsymidx:=0;
  235. for sec:=low(TSection) to high(TSection) do
  236. begin
  237. if sections[sec].available then
  238. begin
  239. inc(nsects);
  240. inc(secsymidx);
  241. sections[sec].secsymidx:=secsymidx;
  242. end;
  243. end;
  244. { calculate start positions after the headers }
  245. datapos:=sizeof(coffheader)+sizeof(coffoptheader)+sizeof(coffsechdr)*nsects;
  246. mempos:=sizeof(coffheader)+sizeof(coffoptheader)+sizeof(coffsechdr)*nsects;
  247. if not win32 then
  248. inc(mempos,sizeof(go32v2stub)+$1000);
  249. { add sections }
  250. MapObjData(datapos,mempos);
  251. { end symbol }
  252. AddGlobalSym('_etext',sections[sec_code].mempos+sections[sec_code].memsize);
  253. AddGlobalSym('_edata',sections[sec_data].mempos+sections[sec_data].memsize);
  254. AddGlobalSym('end',mempos);
  255. { symbols }
  256. nsyms:=0;
  257. sympos:=0;
  258. if not(cs_link_strip in current_settings.globalswitches) then
  259. begin
  260. sympos:=datapos;
  261. objdata:=TObjData(objdatalist.first);
  262. while assigned(objdata) do
  263. begin
  264. inc(nsyms,objdata.symbols.count);
  265. objdata:=TObjData(objdata.next);
  266. end;
  267. end;*)
  268. end;
  269. function gen_section_header(sec:Tsection;obj:cardinal):Tlxobject_table_entry;
  270. virtual_size:cardinal;
  271. reloc_base_addr:cardinal;
  272. object_flags:Tlxobject_flag_set;
  273. page_table_index:cardinal;
  274. page_count:cardinal;
  275. reserved:cardinal;
  276. begin
  277. gen_section_header.virtual_size:=sections[sec.memsize];
  278. end;
  279. function Tlxexeoutput.writedata:boolean;
  280. var header:Tlxheader;
  281. hsym:Tasmsymbol;
  282. code_object_header,data_object_header,bss_object_header,stack_object_header,
  283. heap_object_header:Tlxobject_table_entry;
  284. begin
  285. result:=false;
  286. fillchar(header,sizeof(header),0);
  287. header.magic:=$584c; {'LX'}
  288. header.cpu_type:=2; {Intel 386}
  289. header.os_type:=1; {OS/2}
  290. {Set the initial EIP.}
  291. header.eip_object:=code_object;
  292. hsym:=tasmsymbol(globalsyms.Find('start'));
  293. if not assigned(hsym) then
  294. begin
  295. comment(V_Error,'Entrypoint "start" not defined');
  296. exit;
  297. end;
  298. header.eip:=hsym.address-sections[sec_code].mempos;
  299. {Set the initial ESP.}
  300. header.esp_object:=stack_object;
  301. header.esp:=stacksize;
  302. Fwriter.write(header,sizeof(header));
  303. for sec:=low(Tsection) to high(Tsection) do
  304. if sections[sec].available then
  305. if not(sec in [sec_code,sec_data,sec_bss,sec_stab,sec_stabstr]) then
  306. begin
  307. result:=false;
  308. exit;
  309. end;
  310. code_object_header:=gen_section_header(sec_code,code_object);
  311. data_object_header:=gen_section_header(sec_data,data_object);
  312. bss_object_header:=gen_section_header(sec_bss,bss_object);
  313. result:=true;
  314. end;
  315. procedure Tlxexeoutput.GenerateExecutable(const fn:string);
  316. begin
  317. { AddGlobalSym('_etext',0);
  318. AddGlobalSym('_edata',0);
  319. AddGlobalSym('end',0);
  320. if not CalculateSymbols then
  321. exit;
  322. CalculateMemoryMap;
  323. FixupSymbols;
  324. FixupRelocations;
  325. writeexefile(fn);}
  326. end;
  327. {****************************************************************************
  328. TCoffLinker
  329. ****************************************************************************}
  330. constructor Tlxlinker.Create;
  331. begin
  332. inherited Create;
  333. exeoutput:=Tlxexeoutput.createos2;
  334. end;
  335. {*****************************************************************************
  336. Initialize
  337. *****************************************************************************}
  338. begin
  339. { RegisterAssembler(as_i386_coff_info,TCoffAssembler);
  340. RegisterAssembler(as_i386_pecoff_info,TPECoffAssembler);
  341. RegisterAssembler(as_i386_pecoffwdosx_info,TPECoffAssembler);
  342. RegisterLinker(ld_i386_coff,Tlxlinker);}
  343. end.