123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396 |
- {
- Copyright (c) 2002 by Daniel Mantione, Peter Vreman
- Contains the binary reader and writer for the linear executable
- format used by OS/2
- * This code was inspired by the NASM sources
- The Netwide Assembler is copyright (C) 1996 Simon Tatham and
- Julian Hall. All rights reserved.
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- ****************************************************************************
- }
- unit oglx;
- {$i fpcdefs.inc}
- interface
- uses
- { common }
- cclasses,
- { target }
- systems,
- { assembler }
- cpubase,aasmbase,assemble,link,
- { output }
- ogbase,ogmap,ogcoff;
- { An LX executable is called a module; it can be either an executable
- or a DLL.
- A module consists of objects. In other executable formats, these
- are usually called sections.
- Objects consist of pages.
- The objects are numbered, numbers do not have any special meaning. The
- pages of the object are loaded into memory with the access rights specified
- the object table entry. (DM)}
- { For the operating system the object numbers have no special meaning.
- However, for Free Pascal generated executables, I define: (DM)}
- const code_object = 0;
- data_object = 1;
- bss_object = 2;
- stack_object = 3;
- heap_object = 4;
- type Tlxheader = packed record
- magic:word; {'LX'}
- byteorder:byte; {0 = little 1 = big endian.}
- wordorder:byte; {0 = little 1 = big endian.}
- format_level:cardinal; {Nothing else than LX level
- 0 has ever been defined.}
- cpu_type:word; {1 = 286, 2 = 386, 3 = 486,
- 4 = pentium.}
- os_type:word; {1 = OS/2, 2 = Windows,
- 3 = Siemens MS-Dos 4.0,
- 4 = Windows 386.}
- module_version:cardinal; {Version of executable,
- defined by user.}
- module_flags:cardinal; {Flags.}
- module_page_count:cardinal; {Amount of pages in module.}
- eip_object,eip:cardinal; {Initial EIP, object nr and
- offset within object.}
- esp_object,esp:cardinal; {Initial ESP, object nr and
- offset within object.}
- page_size,page_shift:cardinal; {Page size, in bytes and
- 1 << pageshift.}
- fixup_sect_size:cardinal;
- fixup_sect_checksum:cardinal;
- loader_sect_size:cardinal;
- loader_sect_chksum:cardinal;
- object_table_offset:cardinal; {Location of object table.}
- object_count:cardinal; {Amount of objects in module.}
- object_pagetable_ofs:cardinal; {Location of object page
- table.}
- object_iterpages_ofs:cardinal;
- resource_table_ofs:cardinal; {Location of resource table.}
- resource_count:cardinal; {Amount of resources in
- resource table.}
- resid_name_tbl_ofs:cardinal;
- entry_table_offset:cardinal;
- module_dir_offset:cardinal;
- module_dir_count:cardinal;
- fixup_pagetab_ofs:cardinal;
- fixup_recrab_ofs:cardinal;
- import_modtab_ofs:cardinal;
- import_modtab_count:cardinal;
- data_pages_offset:cardinal;
- preload_page_count:cardinal;
- nonresid_table_ofs:cardinal;
- nonresid_table_len:cardinal;
- nonresid_tbl_chksum:cardinal;
- auto_ds_object_no:cardinal; {Not used by OS/2.}
- debug_info_offset:cardinal;
- inst_preload_count:cardinal;
- inst_demand_count:cardinal;
- heapsize:cardinal; {Only used for 16-bit programs.}
- end;
- Tlxobject_flags = (ofreadable,ofwriteable,ofexecutable,ofresource,
- ofdiscardable,ofshared,ofpreload,ofinvalid,
- ofzerofilled);
- Tlxobject_flag_set = set of Tlxobject_flags;
- Tlxobject_table_entry = packed record
- virtual_size:cardinal;
- reloc_base_addr:cardinal;
- object_flags:Tlxobject_flag_set;
- page_table_index:cardinal;
- page_count:cardinal;
- reserved:cardinal;
- end;
- Tlxexeoutput = class(texeoutput)
- private
- { FCoffsyms,
- FCoffStrs : tdynamicarray;
- win32 : boolean;}
- nsects,
- nsyms,
- sympos : longint;
- procedure write_symbol(const name:string;strpos,value,section,typ,aux:longint);
- procedure write_symbols;
- protected
- function writedata:boolean;override;
- public
- constructor createos2;
- function newobjectinput:tobjectinput;override;
- procedure CalculateMemoryMap;override;
- procedure GenerateExecutable(const fn:string);override;
- end;
- Tlxlinker = class(tinternallinker)
- constructor create;override;
- end;
- implementation
- uses
- strings,
- cutils,verbose,
- globtype,globals,fmodule,
- owar;
- {****************************************************************************
- tcoffexeoutput
- ****************************************************************************}
- constructor Tlxexeoutput.createos2;
- begin
- inherited create;
- end;
- function Tlxexeoutput.newobjectinput:tobjectinput;
- begin
- result:=tcoffobjectinput.createdjgpp;
- end;
- procedure Tlxexeoutput.write_symbol(const name:string;strpos,value,section,typ,aux:longint);
- { var
- sym : coffsymbol;}
- begin
- { FillChar(sym,sizeof(sym),0);
- if strpos=-1 then
- move(name[1],sym.name,length(name))
- else
- sym.strpos:=strpos;
- sym.value:=value;
- sym.section:=section;
- sym.typ:=typ;
- sym.aux:=aux;
- FWriter.write(sym,sizeof(sym));}
- end;
- procedure Tlxexeoutput.write_symbols;
- { var
- filename : string[18];
- sec : TSection;
- namestr : string[8];
- nameidx,
- value,
- sectionval,
- i : longint;
- globalval : byte;
- secrec : coffsectionrec;
- objdata : TObjData;
- p : tasmsymbol;
- s : string;}
- begin
- (* objdata:=TObjData(objdatalist.first);
- while assigned(objdata) do
- begin
- with tcoffObjData(objdata) do
- begin
- { The symbols used }
- p:=Tasmsymbol(symbols.First);
- while assigned(p) do
- begin
- if p.section=sec_common then
- sectionval:=sections[sec_bss].secsymidx
- else
- sectionval:=sections[p.section].secsymidx;
- if p.currbind=AB_LOCAL then
- globalval:=3
- else
- globalval:=2;
- { if local of global then set the section value to the address
- of the symbol }
- if p.currbind in [AB_LOCAL,AB_GLOBAL] then
- value:=p.address
- else
- value:=p.size;
- { symbolname }
- s:=p.name;
- if length(s)>8 then
- begin
- nameidx:=FCoffStrs.size+4;
- FCoffStrs.writestr(s);
- FCoffStrs.writestr(#0);
- end
- else
- begin
- nameidx:=-1;
- namestr:=s;
- end;
- write_symbol(namestr,nameidx,value,sectionval,globalval,0);
- p:=tasmsymbol(p.indexnext);
- end;
- end;
- objdata:=TObjData(objdata.next);
- end;*)
- end;
- procedure Tlxexeoutput.CalculateMemoryMap;
- { var
- objdata : TObjData;
- secsymidx,
- mempos,
- datapos : longint;
- sec : TSection;
- sym : tasmsymbol;
- s : TObjSection;}
- begin
- (* { retrieve amount of sections }
- nsects:=0;
- secsymidx:=0;
- for sec:=low(TSection) to high(TSection) do
- begin
- if sections[sec].available then
- begin
- inc(nsects);
- inc(secsymidx);
- sections[sec].secsymidx:=secsymidx;
- end;
- end;
- { calculate start positions after the headers }
- datapos:=sizeof(coffheader)+sizeof(coffoptheader)+sizeof(coffsechdr)*nsects;
- mempos:=sizeof(coffheader)+sizeof(coffoptheader)+sizeof(coffsechdr)*nsects;
- if not win32 then
- inc(mempos,sizeof(go32v2stub)+$1000);
- { add sections }
- MapObjData(datapos,mempos);
- { end symbol }
- AddGlobalSym('_etext',sections[sec_code].mempos+sections[sec_code].memsize);
- AddGlobalSym('_edata',sections[sec_data].mempos+sections[sec_data].memsize);
- AddGlobalSym('end',mempos);
- { symbols }
- nsyms:=0;
- sympos:=0;
- if not(cs_link_strip in current_settings.globalswitches) then
- begin
- sympos:=datapos;
- objdata:=TObjData(objdatalist.first);
- while assigned(objdata) do
- begin
- inc(nsyms,objdata.symbols.count);
- objdata:=TObjData(objdata.next);
- end;
- end;*)
- end;
- function gen_section_header(sec:Tsection;obj:cardinal):Tlxobject_table_entry;
- virtual_size:cardinal;
- reloc_base_addr:cardinal;
- object_flags:Tlxobject_flag_set;
- page_table_index:cardinal;
- page_count:cardinal;
- reserved:cardinal;
- begin
- gen_section_header.virtual_size:=sections[sec.memsize];
- end;
- function Tlxexeoutput.writedata:boolean;
- var header:Tlxheader;
- hsym:Tasmsymbol;
- code_object_header,data_object_header,bss_object_header,stack_object_header,
- heap_object_header:Tlxobject_table_entry;
- begin
- result:=false;
- fillchar(header,sizeof(header),0);
- header.magic:=$584c; {'LX'}
- header.cpu_type:=2; {Intel 386}
- header.os_type:=1; {OS/2}
- {Set the initial EIP.}
- header.eip_object:=code_object;
- hsym:=tasmsymbol(globalsyms.Find('start'));
- if not assigned(hsym) then
- begin
- comment(V_Error,'Entrypoint "start" not defined');
- exit;
- end;
- header.eip:=hsym.address-sections[sec_code].mempos;
- {Set the initial ESP.}
- header.esp_object:=stack_object;
- header.esp:=stacksize;
- Fwriter.write(header,sizeof(header));
- for sec:=low(Tsection) to high(Tsection) do
- if sections[sec].available then
- if not(sec in [sec_code,sec_data,sec_bss,sec_stab,sec_stabstr]) then
- begin
- result:=false;
- exit;
- end;
- code_object_header:=gen_section_header(sec_code,code_object);
- data_object_header:=gen_section_header(sec_data,data_object);
- bss_object_header:=gen_section_header(sec_bss,bss_object);
- result:=true;
- end;
- procedure Tlxexeoutput.GenerateExecutable(const fn:string);
- begin
- { AddGlobalSym('_etext',0);
- AddGlobalSym('_edata',0);
- AddGlobalSym('end',0);
- if not CalculateSymbols then
- exit;
- CalculateMemoryMap;
- FixupSymbols;
- FixupRelocations;
- writeexefile(fn);}
- end;
- {****************************************************************************
- TCoffLinker
- ****************************************************************************}
- constructor Tlxlinker.Create;
- begin
- inherited Create;
- CArObjectReader:=TArObjectReader;
- exeoutput:=Tlxexeoutput.createos2;
- end;
- {*****************************************************************************
- Initialize
- *****************************************************************************}
- begin
- { RegisterAssembler(as_i386_coff_info,TCoffAssembler);
- RegisterAssembler(as_i386_pecoff_info,TPECoffAssembler);
- RegisterAssembler(as_i386_pecoffwdosx_info,TPECoffAssembler);
- RegisterLinker(ld_i386_coff,Tlxlinker);}
- end.
|