+ 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:
svenbarth 2017-02-03 22:36:58 +00:00
parent addb92e62b
commit 95bea696ca

View File

@ -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