oglx.pas 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  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. { An LX executable is called a module; it can be either an executable
  35. or a DLL.
  36. A module consists of objects. In other executable formats, these
  37. are usually called sections.
  38. Objects consist of pages.
  39. The objects are numbered, numbers do not have any special meaning. The
  40. pages of the object are loaded into memory with the access rights specified
  41. the object table entry. (DM)}
  42. { For the operating system the object numbers have no special meaning.
  43. However, for Free Pascal generated executables, I define: (DM)}
  44. const code_object = 0;
  45. data_object = 1;
  46. bss_object = 2;
  47. stack_object = 3;
  48. heap_object = 4;
  49. type Tlxheader = packed record
  50. magic:word; {'LX'}
  51. byteorder:byte; {0 = little 1 = big endian.}
  52. wordorder:byte; {0 = little 1 = big endian.}
  53. format_level:cardinal; {Nothing else than LX level
  54. 0 has ever been defined.}
  55. cpu_type:word; {1 = 286, 2 = 386, 3 = 486,
  56. 4 = pentium.}
  57. os_type:word; {1 = OS/2, 2 = Windows,
  58. 3 = Siemens MS-Dos 4.0,
  59. 4 = Windows 386.}
  60. module_version:cardinal; {Version of executable,
  61. defined by user.}
  62. module_flags:cardinal; {Flags.}
  63. module_page_count:cardinal; {Amount of pages in module.}
  64. eip_object,eip:cardinal; {Initial EIP, object nr and
  65. offset within object.}
  66. esp_object,esp:cardinal; {Initial ESP, object nr and
  67. offset within object.}
  68. page_size,page_shift:cardinal; {Page size, in bytes and
  69. 1 << pageshift.}
  70. fixup_sect_size:cardinal;
  71. fixup_sect_checksum:cardinal;
  72. loader_sect_size:cardinal;
  73. loader_sect_chksum:cardinal;
  74. object_table_offset:cardinal; {Location of object table.}
  75. object_count:cardinal; {Amount of objects in module.}
  76. object_pagetable_ofs:cardinal; {Location of object page
  77. table.}
  78. object_iterpages_ofs:cardinal;
  79. resource_table_ofs:cardinal; {Location of resource table.}
  80. resource_count:cardinal; {Amount of resources in
  81. resource table.}
  82. resid_name_tbl_ofs:cardinal;
  83. entry_table_offset:cardinal;
  84. module_dir_offset:cardinal;
  85. module_dir_count:cardinal;
  86. fixup_pagetab_ofs:cardinal;
  87. fixup_recrab_ofs:cardinal;
  88. import_modtab_ofs:cardinal;
  89. import_modtab_count:cardinal;
  90. data_pages_offset:cardinal;
  91. preload_page_count:cardinal;
  92. nonresid_table_ofs:cardinal;
  93. nonresid_table_len:cardinal;
  94. nonresid_tbl_chksum:cardinal;
  95. auto_ds_object_no:cardinal; {Not used by OS/2.}
  96. debug_info_offset:cardinal;
  97. inst_preload_count:cardinal;
  98. inst_demand_count:cardinal;
  99. heapsize:cardinal; {Only used for 16-bit programs.}
  100. end;
  101. Tlxobject_flags = (ofreadable,ofwriteable,ofexecutable,ofresource,
  102. ofdiscardable,ofshared,ofpreload,ofinvalid,
  103. ofzerofilled);
  104. Tlxobject_flag_set = set of Tlxobject_flags;
  105. Tlxobject_table_entry = packed record
  106. virtual_size:cardinal;
  107. reloc_base_addr:cardinal;
  108. object_flags:Tlxobject_flag_set;
  109. page_table_index:cardinal;
  110. page_count:cardinal;
  111. reserved:cardinal;
  112. end;
  113. Tlxexeoutput = class(texeoutput)
  114. private
  115. { FCoffsyms,
  116. FCoffStrs : tdynamicarray;
  117. win32 : boolean;}
  118. nsects,
  119. nsyms,
  120. sympos : longint;
  121. procedure write_symbol(const name:string;strpos,value,section,typ,aux:longint);
  122. procedure write_symbols;
  123. protected
  124. function writedata:boolean;override;
  125. public
  126. constructor createos2;
  127. function newobjectinput:tobjectinput;override;
  128. procedure CalculateMemoryMap;override;
  129. procedure GenerateExecutable(const fn:string);override;
  130. end;
  131. Tlxlinker = class(tinternallinker)
  132. constructor create;override;
  133. end;
  134. implementation
  135. uses
  136. strings,
  137. cutils,verbose,
  138. globtype,globals,fmodule;
  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 : TAsmObjectData;
  177. p : tasmsymbol;
  178. s : string;}
  179. begin
  180. (* objdata:=TAsmObjectData(objdatalist.first);
  181. while assigned(objdata) do
  182. begin
  183. with tcoffobjectdata(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:=TAsmObjectData(objdata.next);
  221. end;*)
  222. end;
  223. procedure Tlxexeoutput.CalculateMemoryMap;
  224. { var
  225. objdata : TAsmObjectData;
  226. secsymidx,
  227. mempos,
  228. datapos : longint;
  229. sec : TSection;
  230. sym : tasmsymbol;
  231. s : TAsmSection;}
  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. MapObjectdata(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 aktglobalswitches) then
  260. begin
  261. sympos:=datapos;
  262. objdata:=TAsmObjectData(objdatalist.first);
  263. while assigned(objdata) do
  264. begin
  265. inc(nsyms,objdata.symbols.count);
  266. objdata:=TAsmObjectData(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.search('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. exeoutput:=Tlxexeoutput.createos2;
  335. end;
  336. {*****************************************************************************
  337. Initialize
  338. *****************************************************************************}
  339. begin
  340. { RegisterAssembler(as_i386_coff_info,TCoffAssembler);
  341. RegisterAssembler(as_i386_pecoff_info,TPECoffAssembler);
  342. RegisterAssembler(as_i386_pecoffwdosx_info,TPECoffAssembler);
  343. RegisterLinker(ld_i386_coff,Tlxlinker);}
  344. end.
  345. {
  346. $Log$
  347. Revision 1.7 2004-10-15 09:14:17 mazen
  348. - remove $IFDEF DELPHI and related code
  349. - remove $IFDEF FPCPROCVAR and related code
  350. Revision 1.6 2004/06/20 08:55:30 florian
  351. * logs truncated
  352. }