+ OS/2 lx format support: Copied ogcoff and started to modify it

This commit is contained in:
daniel 2002-07-08 19:22:22 +00:00
parent 5346e509fe
commit d8acdf44fa

407
compiler/oglx.pas Normal file
View File

@ -0,0 +1,407 @@
{
$Id$
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;
type Tlxheader = packed record
magic:word; {'LX'}
byteorder:byte; {0 = little 1 = big endian}
wordorder:byte;
cpu_type:word;
os_type:word;
module_version:cardinal;
module_flags:cardinal;
module_page_count:cardinal;
eip_object,eip:cardinal;
esp_object,esp:cardinal;
page_size,page_shift:cardinal;
fixup_sect_size:cardinal;
fixup_sect_checksum:cardinal;
loader_sect_size:cardinal;
loader_sect_chksum:cardinal;
object_table_offset:cardinal;
object_count:cardinal;
object_pagetable_ofs:cardinal;
object_iterpages_ofs:cardinal;
resource_table_ofs:cardinal;
resource_count: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
{$ifdef delphi}
sysutils,
{$else}
strings,
{$endif}
cutils,verbose,
globtype,globals,fmodule;
{****************************************************************************
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 : TAsmObjectData;
p : tasmsymbol;
s : string;}
begin
(* objdata:=TAsmObjectData(objdatalist.first);
while assigned(objdata) do
begin
with tcoffobjectdata(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:=TAsmObjectData(objdata.next);
end;*)
end;
procedure Tlxexeoutput.CalculateMemoryMap;
{ var
objdata : TAsmObjectData;
secsymidx,
mempos,
datapos : longint;
sec : TSection;
sym : tasmsymbol;
s : TAsmSection;}
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 }
MapObjectdata(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 aktglobalswitches) then
begin
sympos:=datapos;
objdata:=TAsmObjectData(objdatalist.first);
while assigned(objdata) do
begin
inc(nsyms,objdata.symbols.count);
objdata:=TAsmObjectData(objdata.next);
end;
end;*)
end;
function Tlxexeoutput.writedata:boolean;
{ var
datapos,
secsymidx,
i : longint;
hstab : coffstab;
gotreloc : boolean;
sec : TSection;
header : coffheader;
optheader : coffoptheader;
sechdr : coffsechdr;
empty : array[0..15] of byte;
hp : pdynamicblock;
objdata : TAsmObjectData;
hsym : tasmsymbol;}
begin
(* result:=false;
FCoffSyms:=TDynamicArray.Create(symbolresize);
FCoffStrs:=TDynamicArray.Create(strsresize);
{ Stub }
if not win32 then
FWriter.write(go32v2stub,sizeof(go32v2stub));
{ COFF header }
fillchar(header,sizeof(header),0);
header.mach:=$14c;
header.nsects:=nsects;
header.sympos:=sympos;
header.syms:=nsyms;
header.opthdr:=sizeof(coffoptheader);
header.flag:=COFF_FLAG_AR32WR or COFF_FLAG_EXE or COFF_FLAG_NORELOCS or COFF_FLAG_NOLINES;
FWriter.write(header,sizeof(header));
{ Optional COFF Header }
fillchar(optheader,sizeof(optheader),0);
optheader.magic:=$10b;
optheader.tsize:=sections[sec_code].memsize;
optheader.dsize:=sections[sec_data].memsize;
optheader.bsize:=sections[sec_bss].memsize;
hsym:=tasmsymbol(globalsyms.search('start'));
if not assigned(hsym) then
begin
Comment(V_Error,'Entrypoint "start" not defined');
exit;
end;
optheader.entry:=hsym.address;
optheader.text_start:=sections[sec_code].mempos;
optheader.data_start:=sections[sec_data].mempos;
FWriter.write(optheader,sizeof(optheader));
{ Section headers }
for sec:=low(TSection) to high(TSection) do
if sections[sec].available then
begin
fillchar(sechdr,sizeof(sechdr),0);
move(target_asm.secnames[sec][1],sechdr.name,length(target_asm.secnames[sec]));
if not win32 then
begin
sechdr.rvaofs:=sections[sec].mempos;
sechdr.vsize:=sections[sec].mempos;
end
else
begin
if sec=sec_bss then
sechdr.vsize:=sections[sec].memsize;
end;
if sec=sec_bss then
sechdr.datasize:=sections[sec].memsize
else
begin
sechdr.datasize:=sections[sec].datasize;
sechdr.datapos:=sections[sec].datapos;
end;
sechdr.nrelocs:=0;
sechdr.relocpos:=0;
sechdr.flags:=sections[sec].flags;
FWriter.write(sechdr,sizeof(sechdr));
end;
{ Sections }
for sec:=low(TSection) to high(TSection) do
if sections[sec].available then
begin
{ update objectfiles }
objdata:=TAsmObjectData(objdatalist.first);
while assigned(objdata) do
begin
if assigned(objdata.sects[sec]) and
assigned(objdata.sects[sec].data) then
begin
WriteZeros(objdata.sects[sec].dataalignbytes);
hp:=objdata.sects[sec].data.firstblock;
while assigned(hp) do
begin
FWriter.write(hp^.data,hp^.used);
hp:=hp^.next;
end;
end;
objdata:=TAsmObjectData(objdata.next);
end;
end;
{ Optional symbols }
if not(cs_link_strip in aktglobalswitches) then
begin
{ Symbols }
write_symbols;
{ Strings }
i:=FCoffStrs.size+4;
FWriter.write(i,4);
hp:=FCoffStrs.firstblock;
while assigned(hp) do
begin
FWriter.write(hp^.data,hp^.used);
hp:=hp^.next;
end;
end;
{ Release }
FCoffStrs.Free;
FCoffSyms.Free;
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;
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.
{
$Log$
Revision 1.1 2002-07-08 19:22:22 daniel
+ OS/2 lx format support: Copied ogcoff and started to modify it
}