mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-29 15:00:27 +02:00
* changed the Mach-O object writer to use symbols instead of section numbers
in the relocations (change the relocations to use "external reference" in Mach-O terminology), because initially section number-based relocations were not supported for AArch64 and later they were added but behave slightly differently from those on other platforms (or there's a bug in (some?) linker versions with them) (mantis #27531) o also add a dummy text section, since the assemblers also always do that o only use references to global symbols in the relocations, because when using local symbols in assembler code then for most architectures these must then be translated to section references (like the old code did), while for others they should remain symbols. For global symbols, the behaviour is the same everywhere git-svn-id: trunk@29999 -
This commit is contained in:
parent
5302024e25
commit
6149d37e2a
@ -183,6 +183,8 @@ const
|
|||||||
N_SECT = $e; // defined in section number n_sect
|
N_SECT = $e; // defined in section number n_sect
|
||||||
N_PBUD = $c; // prebound undefined (defined in a dylib)
|
N_PBUD = $c; // prebound undefined (defined in a dylib)
|
||||||
N_INDR = $a; // indirect
|
N_INDR = $a; // indirect
|
||||||
|
|
||||||
|
NO_SECT = $0; // symbol is not in any section
|
||||||
|
|
||||||
//Relocations: masks for flag
|
//Relocations: masks for flag
|
||||||
R_SYMBOLNUM_BE = $FFFFFF00;
|
R_SYMBOLNUM_BE = $FFFFFF00;
|
||||||
|
@ -17,10 +17,11 @@ type
|
|||||||
_TMachOSymbolTable_ = class(TMachOSymbolTable)
|
_TMachOSymbolTable_ = class(TMachOSymbolTable)
|
||||||
protected
|
protected
|
||||||
function AddSymbol(aName : string; sect : byte; addr : longword;
|
function AddSymbol(aName : string; sect : byte; addr : longword;
|
||||||
glob : boolean) : integer; override;
|
glob, undef : boolean) : integer; override;
|
||||||
protected
|
protected
|
||||||
public
|
public
|
||||||
procedure WriteToStream(aStream : TStream); override;
|
procedure WriteToStream(aStream : TStream); override;
|
||||||
|
procedure SetSymbolOffset(symbolnum : integer; offset: longword); override;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
_TMachOSubWriter_ = class(TAbstractMachOSubWriter)
|
_TMachOSubWriter_ = class(TAbstractMachOSubWriter)
|
||||||
@ -43,13 +44,17 @@ type
|
|||||||
{ _TMachOSymbolTable_ }
|
{ _TMachOSymbolTable_ }
|
||||||
|
|
||||||
function _TMachOSymbolTable_.AddSymbol(aName: string; sect: byte; addr: longword;
|
function _TMachOSymbolTable_.AddSymbol(aName: string; sect: byte; addr: longword;
|
||||||
glob: boolean): integer;
|
glob, undef: boolean): integer;
|
||||||
var p : _PNlist_;
|
var p : _PNlist_;
|
||||||
begin
|
begin
|
||||||
p:=GetMem(sizeof(_TNlist_));
|
p:=GetMem(sizeof(_TNlist_));
|
||||||
p^.strx:=fStringTable.Add(aName);
|
p^.strx:=fStringTable.Add(aName);
|
||||||
p^._type:=N_SECT;
|
if not undef then
|
||||||
if glob then p^._type:=p^._type or N_EXT;
|
p^._type:=N_SECT
|
||||||
|
else
|
||||||
|
p^._type:=N_UNDF;
|
||||||
|
if glob then
|
||||||
|
p^._type:=p^._type or N_EXT;
|
||||||
p^.desc:=0;
|
p^.desc:=0;
|
||||||
p^.sect:=sect;
|
p^.sect:=sect;
|
||||||
p^.value:=addr;
|
p^.value:=addr;
|
||||||
@ -60,10 +65,20 @@ end;
|
|||||||
procedure _TMachOSymbolTable_.WriteToStream(aStream: TStream);
|
procedure _TMachOSymbolTable_.WriteToStream(aStream: TStream);
|
||||||
var nlist : _TNlist_;
|
var nlist : _TNlist_;
|
||||||
i : integer;
|
i : integer;
|
||||||
|
sawglobal: boolean;
|
||||||
begin
|
begin
|
||||||
|
{ first write local symbols, then global ones, as ilocalsym is hardcoded to
|
||||||
|
be index 0. Can't reorder here because we may already have used symbol
|
||||||
|
numbers to generate relocations -> give an error if a global symbol
|
||||||
|
comes before any local symbols }
|
||||||
|
sawglobal:=false;
|
||||||
for i:=0 to fList.Count-1 do
|
for i:=0 to fList.Count-1 do
|
||||||
begin
|
begin
|
||||||
nlist:=_PNlist_(fList[i])^;
|
nlist:=_PNlist_(fList[i])^;
|
||||||
|
if (nlist._type and N_EXT)<>0 then
|
||||||
|
sawglobal:=true
|
||||||
|
else if sawglobal then
|
||||||
|
raise EMachOResourceWriterSymbolTableWrongOrderException.Create('');
|
||||||
if fOppositeEndianess then
|
if fOppositeEndianess then
|
||||||
begin
|
begin
|
||||||
nlist.strx:=SwapEndian(nlist.strx);
|
nlist.strx:=SwapEndian(nlist.strx);
|
||||||
@ -74,6 +89,14 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure _TMachOSymbolTable_.SetSymbolOffset(symbolnum: integer; offset: longword);
|
||||||
|
var
|
||||||
|
p : _PNlist_;
|
||||||
|
begin
|
||||||
|
p:=_PNlist_(flist[symbolnum]);
|
||||||
|
p^.value:=offset;
|
||||||
|
end;
|
||||||
|
|
||||||
{ _TMachOSubWriter_ }
|
{ _TMachOSubWriter_ }
|
||||||
|
|
||||||
procedure _TMachOSubWriter_.SwapSection(var aSection: _TSection_);
|
procedure _TMachOSubWriter_.SwapSection(var aSection: _TSection_);
|
||||||
@ -108,8 +131,13 @@ begin
|
|||||||
hdr.count:=aResources.Count;
|
hdr.count:=aResources.Count;
|
||||||
hdr.usedhandles:=0;
|
hdr.usedhandles:=0;
|
||||||
hdr.handles:=0;
|
hdr.handles:=0;
|
||||||
fRelocations.Add(0,1);
|
{ the first pointer (rootptr at offset 0) goes to the root node, which comes
|
||||||
fRelocations.Add(sizeof(hdr.rootptr)+sizeof(hdr.count)+sizeof(hdr.usedhandles),2);
|
right after the header (the addend has been set to sizeof(hdr) -> add the
|
||||||
|
address of the fpc.resources section to it via a relocations}
|
||||||
|
fRelocations.Add(0,ffpcresourcessym);
|
||||||
|
{ the last pointer (handles at offset sizeof(fields before it)) goes to the
|
||||||
|
fpc.reshandles section }
|
||||||
|
fRelocations.Add(sizeof(hdr.rootptr)+sizeof(hdr.count)+sizeof(hdr.usedhandles),ffpcreshandlessym);
|
||||||
if fOppositeEndianess then
|
if fOppositeEndianess then
|
||||||
begin
|
begin
|
||||||
hdr.rootptr:=SwapEndian(hdr.rootptr);
|
hdr.rootptr:=SwapEndian(hdr.rootptr);
|
||||||
@ -123,6 +151,7 @@ end;
|
|||||||
|
|
||||||
procedure _TMachOSubWriter_.WriteNodeInfos(aStream: TStream);
|
procedure _TMachOSubWriter_.WriteNodeInfos(aStream: TStream);
|
||||||
begin
|
begin
|
||||||
|
{ offset inside the object }
|
||||||
fCurOfs:=sizeof(_TResHdr_);
|
fCurOfs:=sizeof(_TResHdr_);
|
||||||
WriteNodeInfo(aStream,fRoot);
|
WriteNodeInfo(aStream,fRoot);
|
||||||
WriteSubNodes(aStream,fRoot);
|
WriteSubNodes(aStream,fRoot);
|
||||||
@ -137,7 +166,7 @@ begin
|
|||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
infonode.nameid:=fResStrTable.StartOfs+aNode.NameRVA;
|
infonode.nameid:=fResStrTable.StartOfs+aNode.NameRVA;
|
||||||
fRelocations.Add(fCurOfs,1);
|
fRelocations.Add(fCurOfs,ffpcresourcessym);
|
||||||
end;
|
end;
|
||||||
infonode.ncount:=aNode.NamedCount;
|
infonode.ncount:=aNode.NamedCount;
|
||||||
if aNode.IsLeaf then
|
if aNode.IsLeaf then
|
||||||
@ -153,7 +182,7 @@ begin
|
|||||||
end;
|
end;
|
||||||
fRelocations.Add(
|
fRelocations.Add(
|
||||||
fCurOfs+sizeof(infonode.nameid)+sizeof(infonode.ncount)+
|
fCurOfs+sizeof(infonode.nameid)+sizeof(infonode.ncount)+
|
||||||
sizeof(infonode.idcountsize),1);
|
sizeof(infonode.idcountsize),ffpcresourcessym);
|
||||||
if fOppositeEndianess then
|
if fOppositeEndianess then
|
||||||
begin
|
begin
|
||||||
infonode.nameid:=SwapEndian(infonode.nameid);
|
infonode.nameid:=SwapEndian(infonode.nameid);
|
||||||
@ -170,7 +199,7 @@ var buf : pbyte;
|
|||||||
begin
|
begin
|
||||||
fHeader.sizeofcmds:=
|
fHeader.sizeofcmds:=
|
||||||
//segment+res section+bss section
|
//segment+res section+bss section
|
||||||
sizeof(_TSegmentCommand_)+sizeof(_TSection_)*2+
|
sizeof(_TSegmentCommand_)+sizeof(_TSection_)*3+
|
||||||
//symbol table and dynamic symbol table commands
|
//symbol table and dynamic symbol table commands
|
||||||
sizeof(TSymtabCommand)+sizeof(TDySymtabCommand)+
|
sizeof(TSymtabCommand)+sizeof(TDySymtabCommand)+
|
||||||
//common header of the three commands
|
//common header of the three commands
|
||||||
@ -189,21 +218,35 @@ var ldcommand : TLoadCommand;
|
|||||||
segcommand : _TSegmentCommand_;
|
segcommand : _TSegmentCommand_;
|
||||||
symcommand : TSymtabCommand;
|
symcommand : TSymtabCommand;
|
||||||
dysymcommand : TDySymtabCommand;
|
dysymcommand : TDySymtabCommand;
|
||||||
ressection,bsssection : _TSection_;
|
ressection,bsssection,textsection : _TSection_;
|
||||||
begin
|
begin
|
||||||
ldcommand.cmd:=fSegType;
|
ldcommand.cmd:=fSegType;
|
||||||
ldcommand.cmdsize:=sizeof(TLoadCommand)+sizeof(segcommand)+sizeof(ressection)*2;
|
ldcommand.cmdsize:=sizeof(TLoadCommand)+sizeof(segcommand)+sizeof(ressection)*3;
|
||||||
|
|
||||||
FillByte(segcommand.name[0],16,0);
|
FillByte(segcommand.name[0],16,0);
|
||||||
segcommand.vmaddr:=0;
|
segcommand.vmaddr:=0;
|
||||||
segcommand.vmsize:=fDataCurOfs+sizeof(_ptrtype_)*aResources.Count;
|
segcommand.vmsize:=fDataCurOfs+sizeof(_ptrtype_)*aResources.Count;
|
||||||
segcommand.fileoff:=fSectionStart;
|
segcommand.fileoff:=fSectionStart;
|
||||||
segcommand.filesize:=fDataCurOfs;
|
segcommand.filesize:=fDataCurOfs;
|
||||||
segcommand.maxprot:=VM_PROT_READ or VM_PROT_WRITE;
|
segcommand.maxprot:=VM_PROT_READ or VM_PROT_WRITE or VM_PROT_EXECUTE;
|
||||||
segcommand.initprot:=VM_PROT_READ or VM_PROT_WRITE;
|
segcommand.initprot:=VM_PROT_READ or VM_PROT_WRITE or VM_PROT_EXECUTE;
|
||||||
segcommand.nsects:=2;
|
segcommand.nsects:=3;
|
||||||
segcommand.flags:=0;
|
segcommand.flags:=0;
|
||||||
|
|
||||||
|
fillbyte(textsection,sizeof(textsection),0);
|
||||||
|
textsection.sectname:='__text';
|
||||||
|
textsection.segname:='__TEXT';
|
||||||
|
textsection.addr:=0;
|
||||||
|
textsection.size:=0;
|
||||||
|
textsection.offset:=segcommand.fileoff;
|
||||||
|
textsection.align:=0;
|
||||||
|
textsection.reloff:=0;
|
||||||
|
textsection.nreloc:=0;
|
||||||
|
textsection.flags:=S_ATTR_PURE_INSTRUCTIONS;
|
||||||
|
textsection.reserved1:=0;
|
||||||
|
textsection.reserved2:=0;
|
||||||
|
|
||||||
|
fillbyte(ressection,sizeof(ressection),0);
|
||||||
ressection.sectname:=RsrcSectName;
|
ressection.sectname:=RsrcSectName;
|
||||||
ressection.segname:=DataSegName;
|
ressection.segname:=DataSegName;
|
||||||
ressection.addr:=0;
|
ressection.addr:=0;
|
||||||
@ -216,6 +259,7 @@ begin
|
|||||||
ressection.reserved1:=0;
|
ressection.reserved1:=0;
|
||||||
ressection.reserved2:=0;
|
ressection.reserved2:=0;
|
||||||
|
|
||||||
|
fillbyte(bsssection,sizeof(bsssection),0);
|
||||||
bsssection.sectname:=HandlesSectName;
|
bsssection.sectname:=HandlesSectName;
|
||||||
bsssection.segname:=DataSegName;
|
bsssection.segname:=DataSegName;
|
||||||
bsssection.addr:=fDataCurOfs;
|
bsssection.addr:=fDataCurOfs;
|
||||||
@ -242,12 +286,14 @@ begin
|
|||||||
segcommand.nsects:=SwapEndian(segcommand.nsects);
|
segcommand.nsects:=SwapEndian(segcommand.nsects);
|
||||||
segcommand.flags:=SwapEndian(segcommand.flags);
|
segcommand.flags:=SwapEndian(segcommand.flags);
|
||||||
|
|
||||||
|
SwapSection(textsection);
|
||||||
SwapSection(ressection);
|
SwapSection(ressection);
|
||||||
SwapSection(bsssection);
|
SwapSection(bsssection);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
aStream.WriteBuffer(ldcommand,sizeof(ldcommand));
|
aStream.WriteBuffer(ldcommand,sizeof(ldcommand));
|
||||||
aStream.WriteBuffer(segcommand,sizeof(segcommand));
|
aStream.WriteBuffer(segcommand,sizeof(segcommand));
|
||||||
|
aStream.WriteBuffer(textsection,sizeof(textsection));
|
||||||
aStream.WriteBuffer(ressection,sizeof(ressection));
|
aStream.WriteBuffer(ressection,sizeof(ressection));
|
||||||
aStream.WriteBuffer(bsssection,sizeof(bsssection));
|
aStream.WriteBuffer(bsssection,sizeof(bsssection));
|
||||||
|
|
||||||
|
@ -25,6 +25,7 @@ uses
|
|||||||
type
|
type
|
||||||
EMachOResourceWriterException = class(EResourceWriterException);
|
EMachOResourceWriterException = class(EResourceWriterException);
|
||||||
EMachOResourceWriterUnknownBitSizeException = class(EMachOResourceWriterException);
|
EMachOResourceWriterUnknownBitSizeException = class(EMachOResourceWriterException);
|
||||||
|
EMachOResourceWriterSymbolTableWrongOrderException = class(EMachOResourceWriterException);
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
||||||
@ -86,7 +87,7 @@ type
|
|||||||
public
|
public
|
||||||
constructor Create(aMachineType : TMachOMachineType; aOppositeEndianess : boolean);
|
constructor Create(aMachineType : TMachOMachineType; aOppositeEndianess : boolean);
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
procedure Add(addr : longword; sectnum : longword);
|
procedure Add(addr: longword; symnum: longword);
|
||||||
procedure Clear;
|
procedure Clear;
|
||||||
procedure WriteToStream(aStream : TStream);
|
procedure WriteToStream(aStream : TStream);
|
||||||
property Count : integer read GetCount;
|
property Count : integer read GetCount;
|
||||||
@ -105,15 +106,17 @@ type
|
|||||||
fOppositeEndianess : boolean;
|
fOppositeEndianess : boolean;
|
||||||
function GetCount : integer;
|
function GetCount : integer;
|
||||||
function AddSymbol(aName : string; sect : byte; addr : longword;
|
function AddSymbol(aName : string; sect : byte; addr : longword;
|
||||||
glob : boolean) : integer; virtual; abstract;
|
glob, undef : boolean) : integer; virtual; abstract;
|
||||||
protected
|
protected
|
||||||
public
|
public
|
||||||
constructor Create(aStringTable : TObjectStringTable);
|
constructor Create(aStringTable : TObjectStringTable);
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
function AddLocal(aName : string; sect : byte; addr : longword) : integer;
|
function AddLocal(const aName : string; sect : byte; addr : longword) : integer;
|
||||||
function AddGlobal(aName : string; sect : byte; addr : longword) : integer;
|
function AddGlobal(const aName : string; sect : byte; addr : longword) : integer;
|
||||||
|
function AddExternal(const aName : string) : integer;
|
||||||
procedure Clear;
|
procedure Clear;
|
||||||
procedure WriteToStream(aStream : TStream); virtual; abstract;
|
procedure WriteToStream(aStream : TStream); virtual; abstract;
|
||||||
|
procedure SetSymbolOffset(symbolnum : integer; offset: longword); virtual; abstract;
|
||||||
property Count : integer read GetCount;
|
property Count : integer read GetCount;
|
||||||
property LocalCount : integer read fLocalCount;
|
property LocalCount : integer read fLocalCount;
|
||||||
property GlobalCount : integer read fGlobalCount;
|
property GlobalCount : integer read fGlobalCount;
|
||||||
@ -141,6 +144,8 @@ type
|
|||||||
fCurOfs : longword;
|
fCurOfs : longword;
|
||||||
fDataCurOfs : longword;
|
fDataCurOfs : longword;
|
||||||
fSectionStart : longword;
|
fSectionStart : longword;
|
||||||
|
ffpcresourcessym,
|
||||||
|
ffpcreshandlessym : integer;
|
||||||
|
|
||||||
function NextAligned(aBound, aValue : longword) : longword;
|
function NextAligned(aBound, aValue : longword) : longword;
|
||||||
procedure Align(aBound : integer; aStream : TStream);
|
procedure Align(aBound : integer; aStream : TStream);
|
||||||
@ -241,17 +246,23 @@ begin
|
|||||||
fList.Free;
|
fList.Free;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TMachOSymbolTable.AddLocal(aName: string; sect: byte; addr: longword
|
function TMachOSymbolTable.AddLocal(const aName: string; sect: byte; addr: longword
|
||||||
): integer;
|
): integer;
|
||||||
begin
|
begin
|
||||||
Result:=AddSymbol(aName,sect,addr,false);
|
Result:=AddSymbol(aName,sect,addr,false,false);
|
||||||
inc(fLocalCount);
|
inc(fLocalCount);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function TMachOSymbolTable.AddGlobal(aName: string; sect: byte; addr: longword
|
function TMachOSymbolTable.AddGlobal(const aName: string; sect: byte; addr: longword
|
||||||
): integer;
|
): integer;
|
||||||
begin
|
begin
|
||||||
Result:=AddSymbol(aName,sect,addr,true);
|
Result:=AddSymbol(aName,sect,addr,true,false);
|
||||||
|
inc(fGlobalCount);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TMachOSymbolTable.AddExternal(const aName: string): integer;
|
||||||
|
begin
|
||||||
|
Result:=AddSymbol(aName,NO_SECT,0,false,true);
|
||||||
inc(fGlobalCount);
|
inc(fGlobalCount);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -317,7 +328,7 @@ begin
|
|||||||
fList.Free;
|
fList.Free;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TMachORelocations.Add(addr: longword; sectnum: longword);
|
procedure TMachORelocations.Add(addr: longword; symnum: longword);
|
||||||
var p : PRelocationInfo;
|
var p : PRelocationInfo;
|
||||||
begin
|
begin
|
||||||
p:=GetMem(sizeof(TRelocationInfo));
|
p:=GetMem(sizeof(TRelocationInfo));
|
||||||
@ -325,15 +336,19 @@ begin
|
|||||||
//bit fields make things difficult...
|
//bit fields make things difficult...
|
||||||
if fEndianess=MACH_BIG_ENDIAN then
|
if fEndianess=MACH_BIG_ENDIAN then
|
||||||
begin
|
begin
|
||||||
p^.flags:=sectnum shl 8;
|
p^.flags:=symnum shl 8;
|
||||||
p^.flags:=p^.flags or (fRelocSize shl 5); //length
|
p^.flags:=p^.flags or (fRelocSize shl 5); //length
|
||||||
p^.flags:=p^.flags or fRelocType;
|
p^.flags:=p^.flags or fRelocType;
|
||||||
|
{ reference via symbol }
|
||||||
|
p^.flags:=p^.flags or R_EXTERN_BE;
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
p^.flags:=sectnum and R_SYMBOLNUM_LE;
|
p^.flags:=symnum and R_SYMBOLNUM_LE;
|
||||||
p^.flags:=p^.flags or (fRelocSize shl 25); //length
|
p^.flags:=p^.flags or (fRelocSize shl 25); //length
|
||||||
p^.flags:=p^.flags or (fRelocType shl 28);
|
p^.flags:=p^.flags or (fRelocType shl 28);
|
||||||
|
{ reference via symbol }
|
||||||
|
p^.flags:=p^.flags or R_EXTERN_LE;
|
||||||
end;
|
end;
|
||||||
fList.Add(p);
|
fList.Add(p);
|
||||||
end;
|
end;
|
||||||
@ -556,15 +571,33 @@ begin
|
|||||||
AllocateSpaceForLoadCommands(aStream);
|
AllocateSpaceForLoadCommands(aStream);
|
||||||
fSectionStart:=aStream.Position;
|
fSectionStart:=aStream.Position;
|
||||||
fRoot:=TRootResTreeNode(fParent.GetTree(aResources));
|
fRoot:=TRootResTreeNode(fParent.GetTree(aResources));
|
||||||
|
{ on AArch64, if you want to refer to a section from another one, you
|
||||||
|
have to do it via an explicit symbol reference.
|
||||||
|
|
||||||
|
}
|
||||||
|
{ dummy text section symbol }
|
||||||
|
fSymbolTable.AddLocal('ltmp0',1,0);
|
||||||
|
{ dummy fpc.resources symbol }
|
||||||
|
fSymbolTable.AddLocal('ltmp1',2,0);
|
||||||
|
{ the offset needs to be the offset in the file, *not* relative to the start
|
||||||
|
of the section. We don't know here yet how large the fpcresources section
|
||||||
|
will be -> fix up later }
|
||||||
|
ffpcreshandlessym:=fSymbolTable.AddGlobal('__fpc_reshandles_internal',3,0);
|
||||||
|
{ don't add this before any local symbols, as local symbols must be written
|
||||||
|
first. We can't reorder while writing the symbol table, because we already
|
||||||
|
need the symbol numbers above }
|
||||||
|
ffpcresourcessym:=fSymbolTable.AddGlobal('FPC_RESSYMBOL',2,0);
|
||||||
|
|
||||||
PrescanResourceTree;
|
PrescanResourceTree;
|
||||||
WriteResHeader(aStream,aResources);
|
WriteResHeader(aStream,aResources);
|
||||||
WriteNodeInfos(aStream);
|
WriteNodeInfos(aStream);
|
||||||
WriteResStringTable(aStream);
|
WriteResStringTable(aStream);
|
||||||
WriteRawData(aStream);
|
WriteRawData(aStream);
|
||||||
// fSymbolTable.AddGlobal('FPCRES_SECTION',1,0);
|
|
||||||
fSymbolTable.AddGlobal('FPC_RESSYMBOL',1,0);
|
|
||||||
fRelocations.StartOfs:=aStream.Position;
|
fRelocations.StartOfs:=aStream.Position;
|
||||||
WriteRelocations(aStream);
|
WriteRelocations(aStream);
|
||||||
|
|
||||||
|
{ fix up offset of fpcreshandles symbol }
|
||||||
|
fSymbolTable.SetSymbolOffset(ffpcreshandlessym,fDataCurOfs);
|
||||||
fSymbolTable.StartOfs:=aStream.Position;
|
fSymbolTable.StartOfs:=aStream.Position;
|
||||||
WriteSymbolTable(aStream);
|
WriteSymbolTable(aStream);
|
||||||
fMachOStringTable.StartOfs:=aStream.Position;
|
fMachOStringTable.StartOfs:=aStream.Position;
|
||||||
|
Loading…
Reference in New Issue
Block a user