mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-15 21:19:26 +02:00
+ add ability to read Big Obj COFF files as generated by MSVC with /bigobj and GNU AS with -mbig-obj (starting from version 2.25); this format allows 2^31 sections per COFF file instead of 2^16, thus solving the problem of compiling packages\odata\src\sharepoint.pp
Note: the field names of tcoffbigobjheader and coffbigobjsymbol are inspired from the field names of the structs declared in LLVM git-svn-id: trunk@35379 -
This commit is contained in:
parent
addb92e62b
commit
95bea696ca
@ -53,6 +53,18 @@ interface
|
||||
opthdr : word;
|
||||
flag : word;
|
||||
end;
|
||||
tcoffbigobjheader = packed record
|
||||
Sig1 : word;
|
||||
Sig2 : word;
|
||||
Version : word;
|
||||
Machine : word;
|
||||
TimeDateStame : longword;
|
||||
UUID : array[0..15] of byte;
|
||||
unused : array[0..3] of longword;
|
||||
NumberOfSections : longword;
|
||||
PointerToSymbolTable : longword;
|
||||
NumberOfSymbols : longword;
|
||||
end;
|
||||
tcoffpeoptheader = packed record
|
||||
Magic : word;
|
||||
MajorLinkerVersion : byte;
|
||||
@ -171,6 +183,7 @@ interface
|
||||
FSecCount : Longint;
|
||||
FSecTbl : ^TObjSectionArray;
|
||||
win32 : boolean;
|
||||
bigobj : boolean;
|
||||
function GetSection(secidx:longint):TObjSection;
|
||||
function Read_str(strpos:longword):string;
|
||||
procedure read_relocs(s:TCoffObjSection);
|
||||
@ -270,6 +283,8 @@ interface
|
||||
COFF_OPT_MAGIC = $20b;
|
||||
TLSDIR_SIZE = $28;
|
||||
{$endif x86_64}
|
||||
COFF_BIG_OBJ_MAGIC: array[0..15] of byte = ($C7, $A1, $BA, $D1, $EE, $BA, $A9, $4B, $AF, $20, $FA, $F6, $6A, $A4, $DC, $B8);
|
||||
COFF_BIG_OBJ_VERSION = 2;
|
||||
function ReadDLLImports(const dllname:string;readdllproc:Treaddllproc):boolean;
|
||||
|
||||
implementation
|
||||
@ -474,6 +489,10 @@ implementation
|
||||
sym : longword;
|
||||
reloctype : word;
|
||||
end;
|
||||
strtableoffset=packed record
|
||||
Zeroes : longword;
|
||||
Offset : longword;
|
||||
end;
|
||||
coffsymbol=packed record
|
||||
name : array[0..3] of char; { real is [0..7], which overlaps the strpos ! }
|
||||
strpos : longword;
|
||||
@ -483,6 +502,18 @@ implementation
|
||||
typ : byte;
|
||||
aux : byte;
|
||||
end;
|
||||
coffbigobjsymbol=packed record
|
||||
Name : record
|
||||
case boolean of
|
||||
True: (ShortName : array[0..7] of char);
|
||||
False: (Offset : strtableoffset)
|
||||
end;
|
||||
Value : longword;
|
||||
SectionNumber : longword;
|
||||
_Type : word;
|
||||
StorageClass : byte;
|
||||
NumberOfAuxSymbols : byte;
|
||||
end;
|
||||
|
||||
{ This is defined in rtl/win/sysos.inc source }
|
||||
tlsdirectory=packed record
|
||||
@ -1561,6 +1592,7 @@ const pemagic : array[0..3] of byte = (
|
||||
begin
|
||||
inherited create;
|
||||
win32:=awin32;
|
||||
bigobj:=false;
|
||||
FSymTbl:=nil;
|
||||
end;
|
||||
|
||||
@ -1696,22 +1728,31 @@ const pemagic : array[0..3] of byte = (
|
||||
symidx : aint;
|
||||
i : longint;
|
||||
sym : coffsymbol;
|
||||
bosym : coffbigobjsymbol;
|
||||
objsym : TObjSymbol;
|
||||
bind : Tasmsymbind;
|
||||
strname : string;
|
||||
auxrec : array[0..17] of byte;
|
||||
auxrec : array[0..sizeof(coffsymbol)-1] of byte;
|
||||
boauxrec : array[0..sizeof(coffbigobjsymbol)-1] of byte;
|
||||
objsec : TObjSection;
|
||||
secidx : longint;
|
||||
symvalue : longword;
|
||||
auxcount : byte;
|
||||
symcls : byte;
|
||||
|
||||
{ keeps string manipulations out of main routine }
|
||||
procedure UnsupportedSymbolType;
|
||||
begin
|
||||
Comment(V_Fatal,'Unsupported COFF symbol type '+tostr(sym.typ)+' at index '+tostr(symidx)+' while reading '+InputFileName);
|
||||
Comment(V_Fatal,'Unsupported COFF symbol type '+tostr(symcls)+' at index '+tostr(symidx)+' while reading '+InputFileName);
|
||||
end;
|
||||
|
||||
begin
|
||||
with TCoffObjData(objdata) do
|
||||
begin
|
||||
nsyms:=FCoffSyms.Size div sizeof(CoffSymbol);
|
||||
if bigobj then
|
||||
nsyms:=FCoffSyms.Size div sizeof(coffbigobjsymbol)
|
||||
else
|
||||
nsyms:=FCoffSyms.Size div sizeof(CoffSymbol);
|
||||
{ Allocate memory for symidx -> TObjSymbol table }
|
||||
FSymTbl:=AllocMem(nsyms*sizeof(TObjSymbol));
|
||||
{ Load the Symbols }
|
||||
@ -1719,28 +1760,53 @@ const pemagic : array[0..3] of byte = (
|
||||
symidx:=0;
|
||||
while (symidx<nsyms) do
|
||||
begin
|
||||
FCoffSyms.Read(sym,sizeof(sym));
|
||||
if plongint(@sym.name)^<>0 then
|
||||
if bigobj then
|
||||
begin
|
||||
move(sym.name,strname[1],8);
|
||||
strname[9]:=#0;
|
||||
strname[0]:=chr(strlen(@strname[1]));
|
||||
if strname='' then
|
||||
Internalerror(200205171);
|
||||
FCoffSyms.Read(bosym,sizeof(bosym));
|
||||
if bosym.Name.Offset.Zeroes<>0 then
|
||||
begin
|
||||
move(bosym.Name.ShortName,strname[1],8);
|
||||
strname[9]:=#0;
|
||||
strname[0]:=chr(strlen(@strname[1]));
|
||||
if strname='' then
|
||||
internalerror(2017020301);
|
||||
end
|
||||
else
|
||||
strname:=Read_str(bosym.Name.Offset.Offset);
|
||||
secidx:=longint(bosym.SectionNumber);
|
||||
symvalue:=bosym.Value;
|
||||
auxcount:=bosym.NumberOfAuxSymbols;
|
||||
symcls:=bosym.StorageClass;
|
||||
end
|
||||
else
|
||||
strname:=Read_str(sym.strpos);
|
||||
begin
|
||||
FCoffSyms.Read(sym,sizeof(sym));
|
||||
if plongint(@sym.name)^<>0 then
|
||||
begin
|
||||
move(sym.name,strname[1],8);
|
||||
strname[9]:=#0;
|
||||
strname[0]:=chr(strlen(@strname[1]));
|
||||
if strname='' then
|
||||
Internalerror(200205171);
|
||||
end
|
||||
else
|
||||
strname:=Read_str(sym.strpos);
|
||||
secidx:=sym.section;
|
||||
symvalue:=sym.value;
|
||||
auxcount:=sym.aux;
|
||||
symcls:=sym.typ;
|
||||
end;
|
||||
bind:=AB_EXTERNAL;
|
||||
size:=0;
|
||||
address:=0;
|
||||
objsym:=nil;
|
||||
objsec:=nil;
|
||||
case sym.typ of
|
||||
case symcls of
|
||||
COFF_SYM_GLOBAL :
|
||||
begin
|
||||
if sym.section=0 then
|
||||
if secidx=0 then
|
||||
begin
|
||||
if sym.value=0 then
|
||||
if symvalue=0 then
|
||||
bind:=AB_EXTERNAL
|
||||
else
|
||||
begin
|
||||
@ -1751,9 +1817,9 @@ const pemagic : array[0..3] of byte = (
|
||||
else
|
||||
begin
|
||||
bind:=AB_GLOBAL;
|
||||
objsec:=GetSection(word(sym.section));
|
||||
if sym.value>=objsec.mempos then
|
||||
address:=sym.value-objsec.mempos;
|
||||
objsec:=GetSection(secidx);
|
||||
if symvalue>=objsec.mempos then
|
||||
address:=symvalue-objsec.mempos;
|
||||
end;
|
||||
objsym:=CreateSymbol(strname);
|
||||
objsym.bind:=bind;
|
||||
@ -1766,11 +1832,11 @@ const pemagic : array[0..3] of byte = (
|
||||
COFF_SYM_LOCAL :
|
||||
begin
|
||||
{ do not add constants (section=-1) }
|
||||
if sym.section<>-1 then
|
||||
if secidx<>-1 then
|
||||
begin
|
||||
objsec:=GetSection(word(sym.section));
|
||||
if sym.value>=objsec.mempos then
|
||||
address:=sym.value-objsec.mempos;
|
||||
objsec:=GetSection(secidx);
|
||||
if symvalue>=objsec.mempos then
|
||||
address:=symvalue-objsec.mempos;
|
||||
objsym:=CreateSymbol(strname);
|
||||
objsym.bind:=AB_LOCAL;
|
||||
objsym.typ:=AT_FUNCTION;
|
||||
@ -1782,11 +1848,11 @@ const pemagic : array[0..3] of byte = (
|
||||
COFF_SYM_SECTION :
|
||||
begin
|
||||
{ GetSection checks that index is in range }
|
||||
objsec:=GetSection(word(sym.section));
|
||||
objsec:=GetSection(secidx);
|
||||
if assigned(objsec) then
|
||||
begin
|
||||
if sym.value>=objsec.mempos then
|
||||
address:=sym.value-objsec.mempos;
|
||||
if symvalue>=objsec.mempos then
|
||||
address:=symvalue-objsec.mempos;
|
||||
objsym:=CreateSymbol(strname);
|
||||
objsym.bind:=AB_LOCAL;
|
||||
objsym.typ:=AT_FUNCTION;
|
||||
@ -1803,9 +1869,12 @@ const pemagic : array[0..3] of byte = (
|
||||
end;
|
||||
FSymTbl^[symidx]:=objsym;
|
||||
{ read aux records }
|
||||
for i:=1 to sym.aux do
|
||||
for i:=1 to auxcount do
|
||||
begin
|
||||
FCoffSyms.Read(auxrec,sizeof(auxrec));
|
||||
if bigobj then
|
||||
FCoffSyms.Read(boauxrec,sizeof(boauxrec))
|
||||
else
|
||||
FCoffSyms.Read(auxrec,sizeof(auxrec));
|
||||
inc(symidx);
|
||||
end;
|
||||
inc(symidx);
|
||||
@ -1836,12 +1905,17 @@ const pemagic : array[0..3] of byte = (
|
||||
function TCoffObjInput.ReadObjData(AReader:TObjectreader;out objdata:TObjData):boolean;
|
||||
var
|
||||
secalign : shortint;
|
||||
secofs,
|
||||
strpos,
|
||||
i : longint;
|
||||
sympos,
|
||||
symcount,
|
||||
symsize,
|
||||
code : longint;
|
||||
objsec : TCoffObjSection;
|
||||
secoptions : TObjSectionOptions;
|
||||
header : tcoffheader;
|
||||
boheader : tcoffbigobjheader;
|
||||
sechdr : tcoffsechdr;
|
||||
secname : string;
|
||||
secnamebuf : array[0..15] of char;
|
||||
@ -1859,7 +1933,34 @@ const pemagic : array[0..3] of byte = (
|
||||
InputError('Can''t read COFF Header');
|
||||
exit;
|
||||
end;
|
||||
if header.mach<>COFF_MAGIC then
|
||||
if (header.mach=0) and (header.nsects=$ffff) then
|
||||
begin
|
||||
{ either a library or big obj COFF }
|
||||
AReader.seek(0);
|
||||
if not AReader.read(boheader,sizeof(boheader)) then
|
||||
begin
|
||||
InputError('Can''t read Big Obj COFF Header');
|
||||
exit;
|
||||
end;
|
||||
if CompareByte(boheader.UUID,COFF_BIG_OBJ_MAGIC,length(boheader.uuid))<>0 then
|
||||
begin
|
||||
{ ToDo: this should be treated as a library }
|
||||
InputError('Illegal Big Obj COFF Magic');
|
||||
exit;
|
||||
end;
|
||||
if boheader.Version<>COFF_BIG_OBJ_VERSION then
|
||||
begin
|
||||
InputError('Illegal Big Obj COFF Version');
|
||||
exit;
|
||||
end;
|
||||
if boheader.Machine<>COFF_MAGIC then
|
||||
begin
|
||||
InputError('Illegal COFF Machine type');
|
||||
exit;
|
||||
end;
|
||||
bigobj:=true;
|
||||
end
|
||||
else if header.mach<>COFF_MAGIC then
|
||||
begin
|
||||
InputError('Illegal COFF Magic');
|
||||
exit;
|
||||
@ -1868,8 +1969,20 @@ const pemagic : array[0..3] of byte = (
|
||||
eVCobj:=header.flag=$100;
|
||||
{$endif arm}
|
||||
{ ObjSymbols }
|
||||
AReader.Seek(header.sympos);
|
||||
if not AReader.ReadArray(FCoffSyms,header.syms*sizeof(CoffSymbol)) then
|
||||
if bigobj then
|
||||
begin
|
||||
sympos:=longint(boheader.PointerToSymbolTable);
|
||||
symcount:=longint(boheader.NumberOfSymbols);
|
||||
symsize:=sizeof(CoffBigObjSymbol);
|
||||
end
|
||||
else
|
||||
begin
|
||||
sympos:=longint(header.sympos);
|
||||
symcount:=longint(header.syms);
|
||||
symsize:=sizeof(CoffSymbol);
|
||||
end;
|
||||
AReader.Seek(sympos);
|
||||
if not AReader.ReadArray(FCoffSyms,symcount*symsize) then
|
||||
begin
|
||||
InputError('Error reading coff symbol table');
|
||||
exit;
|
||||
@ -1895,10 +2008,17 @@ const pemagic : array[0..3] of byte = (
|
||||
end;
|
||||
{ Section headers }
|
||||
{ Allocate SecIdx -> TObjSection table, secidx is 1-based }
|
||||
FSecCount:=header.nsects;
|
||||
FSecTbl:=AllocMem((header.nsects+1)*sizeof(TObjSection));
|
||||
AReader.Seek(sizeof(tcoffheader)+header.opthdr);
|
||||
for i:=1 to header.nsects do
|
||||
if bigobj then
|
||||
FSecCount:=longint(boheader.NumberOfSections)
|
||||
else
|
||||
FSecCount:=header.nsects;
|
||||
FSecTbl:=AllocMem((FSecCount+1)*sizeof(TObjSection));
|
||||
if bigobj then
|
||||
secofs:=sizeof(tcoffbigobjheader)
|
||||
else
|
||||
secofs:=sizeof(tcoffheader)+header.opthdr;
|
||||
AReader.Seek(secofs);
|
||||
for i:=1 to FSecCount do
|
||||
begin
|
||||
if not AReader.read(sechdr,sizeof(sechdr)) then
|
||||
begin
|
||||
|
Loading…
Reference in New Issue
Block a user