From be88cd47b26c14d7b3e4f8d373b13a6b46fcdcea Mon Sep 17 00:00:00 2001 From: peter Date: Sun, 2 Apr 2006 00:11:17 +0000 Subject: [PATCH] Merged revisions 3090-3113 via svnmerge from svn+ssh://peter@www.freepascal.org/FPC/svn/fpc/branches/linker/compiler r3090 | peter | 2006-03-30 15:10:15 +0100 (Thu, 30 Mar 2006) | 2 lines * infrastructure for .vtable directives r3094 | peter | 2006-03-31 10:01:48 +0100 (Fri, 31 Mar 2006) | 2 lines * vtable directive fixes r3113 | peter | 2006-04-01 22:49:57 +0100 (Sat, 01 Apr 2006) | 2 lines * Smart VTable linking using Symbols git-svn-id: trunk@3115 - --- compiler/aasmdata.pas | 1 + compiler/assemble.pas | 4 +- compiler/ncgcal.pas | 12 +- compiler/nobj.pas | 31 +-- compiler/ogbase.pas | 435 ++++++++++++++++++++++++++++++++++-------- compiler/ogcoff.pas | 174 +++++++++-------- compiler/ogelf.pas | 288 ++++++++++++++-------------- 7 files changed, 634 insertions(+), 311 deletions(-) diff --git a/compiler/aasmdata.pas b/compiler/aasmdata.pas index 2b2a03d8c3..82b846e495 100644 --- a/compiler/aasmdata.pas +++ b/compiler/aasmdata.pas @@ -122,6 +122,7 @@ interface public name, realname : string[80]; + NextVTEntryNr : longint; { Assembler lists } AsmLists : array[TAsmListType] of TAsmList; CurrAsmList : TAsmList; diff --git a/compiler/assemble.pas b/compiler/assemble.pas index be673be4b1..adcc4ba9fa 100644 --- a/compiler/assemble.pas +++ b/compiler/assemble.pas @@ -1013,8 +1013,6 @@ Implementation if assigned(Tai_stab(hp).str) then convertstab(Tai_stab(hp).str); end; - ait_function_name, - ait_force_line : ; ait_symbol : ObjData.SymbolDefine(Tai_symbol(hp).sym); ait_symbol_end : @@ -1051,7 +1049,9 @@ Implementation {$ifdef x86} co : comp; {$endif x86} + hs : string; objsym, + objsymparent, objsymend : TObjSymbol; leblen : byte; lebbuf : array[0..63] of byte; diff --git a/compiler/ncgcal.pas b/compiler/ncgcal.pas index 4cc1d27880..ca5cf62ae6 100644 --- a/compiler/ncgcal.pas +++ b/compiler/ncgcal.pas @@ -819,6 +819,7 @@ implementation regs_to_save_mm : Tcpuregisterset; href : treference; pop_size : longint; + vmtoffset : aint; pvreg, vmtreg : tregister; oldaktcallnode : tcallnode; @@ -903,9 +904,16 @@ implementation not(is_cppclass(tprocdef(procdefinition)._class)) then cg.g_maybe_testvmt(current_asmdata.CurrAsmList,vmtreg,tprocdef(procdefinition)._class); + { Call through VMT, generate a VTREF symbol to notify the linker } + vmtoffset:=tprocdef(procdefinition)._class.vmtmethodoffset(tprocdef(procdefinition).extnumber); + if not is_interface(tprocdef(procdefinition)._class) then + begin + inc(current_asmdata.NextVTEntryNr); + current_asmdata.CurrAsmList.Concat(tai_symbol.CreateName('VTREF'+tostr(current_asmdata.NextVTEntryNr)+'_'+tprocdef(procdefinition)._class.vmt_mangledname+'$$'+tostr(vmtoffset div sizeof(aint)),AT_FUNCTION,0)); + end; + pvreg:=cg.getintregister(current_asmdata.CurrAsmList,OS_ADDR); - reference_reset_base(href,vmtreg, - tprocdef(procdefinition)._class.vmtmethodoffset(tprocdef(procdefinition).extnumber)); + reference_reset_base(href,vmtreg,vmtoffset); cg.a_load_ref_reg(current_asmdata.CurrAsmList,OS_ADDR,OS_ADDR,href,pvreg); { Load parameters that are in temporary registers in the diff --git a/compiler/nobj.pas b/compiler/nobj.pas index b82ef8f368..5289976d45 100644 --- a/compiler/nobj.pas +++ b/compiler/nobj.pas @@ -1209,6 +1209,8 @@ implementation vmtentry : pvmtentry; procdefcoll : pprocdefcoll; i : longint; + procname, + hs : string; begin { walk trough all numbers for virtual methods and search } { the method } @@ -1224,18 +1226,17 @@ implementation begin { writes the addresses to the VMT } { but only this which are declared as virtual } - if procdefcoll^.data.extnumber=i then + if (procdefcoll^.data.extnumber=i) and + (po_virtualmethod in procdefcoll^.data.procoptions) then begin - if (po_virtualmethod in procdefcoll^.data.procoptions) then - begin - { if a method is abstract, then is also the } - { class abstract and it's not allow to } - { generates an instance } - if (po_abstractmethod in procdefcoll^.data.procoptions) then - List.concat(Tai_const.Createname('FPC_ABSTRACTERROR',0)) - else - List.concat(Tai_const.createname(procdefcoll^.data.mangledname,0)); - end; + if (po_abstractmethod in procdefcoll^.data.procoptions) then + procname:='FPC_ABSTRACTERROR' + else + procname:=procdefcoll^.data.mangledname; + List.concat(Tai_const.createname(procname,0)); + hs:='VTENTRY'+'_'+_class.vmt_mangledname+'$$'+tostr(_class.vmtmethodoffset(i) div sizeof(aint)); + current_asmdata.asmlists[al_globals].concat(tai_symbol.CreateName(hs,AT_DATA,0)); + break; end; procdefcoll:=procdefcoll^.next; end; @@ -1255,6 +1256,7 @@ implementation dmtlabel : tasmlabel; {$endif WITHDMT} interfacetable : tasmlabel; + hs : string; begin {$ifdef WITHDMT} dmtlabel:=gendmt; @@ -1356,6 +1358,13 @@ implementation current_asmdata.asmlists[al_globals].concat(Tai_const.create(aitconst_ptr,0)); { write the size of the VMT } current_asmdata.asmlists[al_globals].concat(Tai_symbol_end.Createname(_class.vmt_mangledname)); + { write vtinherit symbol to notify the linker of the class inheritance tree } + hs:='VTINHERIT'+'_'+_class.vmt_mangledname+'$$'; + if assigned(_class.childof) then + hs:=hs+_class.childof.vmt_mangledname + else + hs:=hs+_class.vmt_mangledname; + current_asmdata.asmlists[al_globals].concat(tai_symbol.CreateName(hs,AT_DATA,0)); end; diff --git a/compiler/ogbase.pas b/compiler/ogbase.pas index 20dffa973a..b81551af50 100644 --- a/compiler/ogbase.pas +++ b/compiler/ogbase.pas @@ -42,12 +42,28 @@ interface TExeSection = class; TExeSymbol = class; - TObjRelocationType = (Reloc_ABSOLUTE,Reloc_RELATIVE,Reloc_RVA + TObjRelocationType = ( + { Relocation to absolute address } + RELOC_ABSOLUTE, {$ifdef x86_64} - ,Reloc_ABSOLUTE32 + { 32bit Relocation to absolute address } + RELOC_ABSOLUTE32, {$endif x86_64} + { Relative relocation } + RELOC_RELATIVE, + { PECoff (Windows) RVA relocation } + RELOC_RVA, + { Generate a 0 value at the place of the relocation, + this is used to remove unused vtable entries } + RELOC_ZERO ); +{$ifdef i386} + const + RELOC_ABSOLUTE32 = RELOC_ABSOLUTE; +{$endif i386} + + type TObjSectionOption = ( { Has Data available in the file } oso_Data, @@ -100,7 +116,7 @@ interface end; PObjStabEntry=^TObjStabEntry; - TObjRelocation = class(TLinkedListItem) + TObjRelocation = class DataOffset, orgsize : aint; { original size of the symbol to Relocate, required for COFF } symbol : TObjSymbol; @@ -125,14 +141,14 @@ interface DataPos, MemPos : aint; DataAlignBytes : shortint; - { Relocation } - Relocations : TLinkedList; - { Symbols this section references and defines } - ObjSymbolRefs : TFPObjectList; - ObjSymbolDefines : TFPObjectList; + { Relocations (=references) to other sections } + ObjRelocations : TFPObjectList; + { Symbols this defines } + ObjSymbolDefines : TFPObjectList; { executable linking } ExeSection : TExeSection; Used : boolean; + VTRefList : TFPObjectList; constructor create(const Aname:string;Aalign:shortint;Aoptions:TObjSectionOptions);virtual; destructor destroy;override; function write(const d;l:aint):aint; @@ -144,7 +160,6 @@ interface procedure addsymReloc(ofs:aint;p:TObjSymbol;Reloctype:TObjRelocationType); procedure addsectionReloc(ofs:aint;aobjsec:TObjSection;Reloctype:TObjRelocationType); procedure AddSymbolDefine(p:TObjSymbol); - procedure AddSymbolRef(p:TObjSymbol); procedure FixupRelocs;virtual; procedure ReleaseData; function FullName:string; @@ -253,9 +268,36 @@ interface end; TObjInputClass=class of TObjInput; + TVTableEntry=record + ObjRelocation : TObjRelocation; + orgreloctype : TObjRelocationType; + Enabled, + Used : Boolean; + end; + PVTableEntry=^TVTableEntry; + + TExeVTable = class + private + procedure CheckIdx(VTableIdx:longint); + public + ExeSymbol : TExeSymbol; + EntryCnt : Longint; + EntryArray : PVTableEntry; + Consolidated : Boolean; + ChildList : TFPObjectList; + constructor Create(AExeSymbol:TExeSymbol); + destructor Destroy;override; + procedure AddChild(vt:TExeVTable); + procedure AddEntry(VTableIdx:Longint); + procedure SetVTableSize(ASize:longint); + function VTableRef(VTableIdx:Longint):TObjRelocation; + end; + TExeSymbol = class(TNamedIndexItem) ObjSymbol : TObjSymbol; ExeSection : TExeSection; + { Used for vmt references optimization } + VTable : TExeVTable; constructor create(sym:TObjSymbol); end; @@ -293,6 +335,7 @@ interface FExternalObjSymbols, FCommonObjSymbols : TFPObjectList; FEntryName : string; + FExeVTableList : TFPObjectList; { Objects } FObjDataList : TFPObjectList; { Position calculation } @@ -331,6 +374,7 @@ interface procedure CalcPos_Header;virtual; procedure CalcPos_Start;virtual; procedure CalcPos_Symbols;virtual; + procedure BuildVTableTree(VTInheritList,VTEntryList:TFPObjectList); procedure ResolveSymbols; procedure PrintMemoryMap; procedure FixupSymbols; @@ -348,6 +392,7 @@ interface property UnresolvedExeSymbols:TFPObjectList read FUnresolvedExeSymbols; property ExternalObjSymbols:TFPObjectList read FExternalObjSymbols; property CommonObjSymbols:TFPObjectList read FCommonObjSymbols; + property ExeVTableList:TFPObjectList read FExeVTableList; property EntryName:string read FEntryName write FEntryName; property ImageBase:aint read FImageBase write FImageBase; property CurrExeSec:TExeSection read FCurrExeSec; @@ -356,11 +401,6 @@ interface end; TExeOutputClass=class of TExeOutput; -{$ifdef i386} - const - Reloc_ABSOLUTE32 = Reloc_ABSOLUTE; -{$endif i386} - var exeoutput : TExeOutput; @@ -481,10 +521,10 @@ implementation secoptions:=Aoptions; secalign:=Aalign; secsymidx:=0; - { Relocation } - Relocations:=TLinkedList.Create; - ObjSymbolRefs:=TFPObjectList.Create(false); + { relocation } + ObjRelocations:=TFPObjectList.Create(false); ObjSymbolDefines:=TFPObjectList.Create(false); + VTRefList:=TFPObjectList.Create(false); end; @@ -492,9 +532,9 @@ implementation begin if assigned(Data) then Data.Free; - Relocations.free; - ObjSymbolRefs.Free; + ObjRelocations.Free; ObjSymbolDefines.Free; + VTRefList.Free; inherited destroy; end; @@ -576,13 +616,13 @@ implementation procedure TObjSection.addsymReloc(ofs:aint;p:TObjSymbol;Reloctype:TObjRelocationType); begin - Relocations.concat(TObjRelocation.CreateSymbol(ofs,p,Reloctype)); + ObjRelocations.Add(TObjRelocation.CreateSymbol(ofs,p,reloctype)); end; procedure TObjSection.addsectionReloc(ofs:aint;aobjsec:TObjSection;Reloctype:TObjRelocationType); begin - Relocations.concat(TObjRelocation.CreateSection(ofs,aobjsec,Reloctype)); + ObjRelocations.Add(TObjRelocation.CreateSection(ofs,aobjsec,reloctype)); end; @@ -594,14 +634,6 @@ implementation end; - procedure TObjSection.AddSymbolRef(p:TObjSymbol); - begin - { Register all references, also the local references between the - ObjSections in an ObjData } - ObjSymbolRefs.Add(p); - end; - - procedure TObjSection.FixupRelocs; begin end; @@ -614,10 +646,8 @@ implementation FData.free; FData:=nil; end; - Relocations.free; - Relocations:=nil; - ObjSymbolRefs.Free; - ObjSymbolRefs:=nil; + ObjRelocations.free; + ObjRelocations:=nil; ObjSymbolDefines.Free; ObjSymbolDefines:=nil; end; @@ -846,11 +876,7 @@ implementation FCachedAsmSymbolList.add(asmsym); end else - begin - result:=TObjSymbol(asmsym.cachedObjSymbol); - { Register also in TObjSection } - CurrObjSec.AddSymbolRef(result); - end; + result:=TObjSymbol(asmsym.cachedObjSymbol); end else result:=nil; @@ -862,8 +888,6 @@ implementation if not assigned(CurrObjSec) then internalerror(200603052); result:=CreateSymbol(aname); - { Register also in TObjSection } - CurrObjSec.AddSymbolRef(result); end; @@ -1057,6 +1081,99 @@ implementation end; +{**************************************************************************** + TExeVTable +****************************************************************************} + + constructor TExeVTable.Create(AExeSymbol:TExeSymbol); + begin + ExeSymbol:=AExeSymbol; + if not assigned(ExeSymbol.ObjSymbol) then + internalerror(200604012); + ChildList:=TFPObjectList.Create(false); + end; + + + destructor TExeVTable.Destroy; + begin + ChildList.Free; + if assigned(EntryArray) then + Freemem(EntryArray); + end; + + + procedure TExeVTable.CheckIdx(VTableIdx:longint); + var + OldEntryCnt : longint; + begin + if VTableIdx>=EntryCnt then + begin + OldEntryCnt:=EntryCnt; + EntryCnt:=VTableIdx+1; + ReAllocMem(EntryArray,EntryCnt*sizeof(TVTableEntry)); + FillChar(EntryArray[OldEntryCnt],(EntryCnt-OldEntryCnt)*sizeof(TVTableEntry),0); + end; + end; + + + procedure TExeVTable.AddChild(vt:TExeVTable); + begin + ChildList.Add(vt); +writeln(ExeSymbol.Name,'-',vt.ExeSymbol.Name); + end; + + + procedure TExeVTable.AddEntry(VTableIdx:Longint); + var + i : longint; + objreloc : TObjRelocation; + vtblentryoffset : aint; + begin + CheckIdx(VTableIdx); + vtblentryoffset:=ExeSymbol.ObjSymbol.Offset+VTableIdx*sizeof(aint); + { Find and disable relocation } + for i:=0 to ExeSymbol.ObjSymbol.ObjSection.ObjRelocations.Count-1 do + begin + objreloc:=TObjRelocation(ExeSymbol.ObjSymbol.ObjSection.ObjRelocations[i]); + if objreloc.dataoffset=vtblentryoffset then + begin + EntryArray[VTableIdx].ObjRelocation:=objreloc; + EntryArray[VTableIdx].OrgRelocType:=objreloc.typ; + objreloc.typ:=RELOC_ZERO; + break; + end; + end; + if not assigned(EntryArray[VTableIdx].ObjRelocation) then + internalerror(200604011); + end; + + + procedure TExeVTable.SetVTableSize(ASize:longint); + begin + if EntryCnt<>0 then + internalerror(200603313); + EntryCnt:=ASize div sizeof(aint); + EntryArray:=AllocMem(EntryCnt*sizeof(TVTableEntry)); + end; + + + function TExeVTable.VTableRef(VTableIdx:Longint):TObjRelocation; + begin + result:=nil; + CheckIdx(VTableIdx); + if EntryArray[VTableIdx].Used then + exit; +writeln(ExeSymbol.Name,'(',VTableIdx,')'); + { Restore relocation if available } + if assigned(EntryArray[VTableIdx].ObjRelocation) then + begin + EntryArray[VTableIdx].ObjRelocation.typ:=EntryArray[VTableIdx].OrgRelocType; + result:=EntryArray[VTableIdx].ObjRelocation; + end; + EntryArray[VTableIdx].Used:=true; + end; + + {**************************************************************************** TExeSymbol ****************************************************************************} @@ -1128,6 +1245,7 @@ implementation FUnresolvedExeSymbols:=TFPObjectList.Create(false); FExternalObjSymbols:=TFPObjectList.Create(false); FCommonObjSymbols:=TFPObjectList.Create(false); + FExeVTableList:=TFPObjectList.Create(false); FEntryName:='start'; { sections } FExeSectionDict:=TDictionary.create; @@ -1148,6 +1266,7 @@ implementation UnresolvedExeSymbols.free; ExternalObjSymbols.free; CommonObjSymbols.free; + ExeVTableList.free; FExeSectionDict.free; FExeSectionList.free; ObjDatalist.free; @@ -1383,6 +1502,68 @@ implementation end; + procedure TExeOutput.BuildVTableTree(VTInheritList,VTEntryList:TFPObjectList); + var + hs : string; + code : integer; + i,k, + vtableidx : longint; + vtableexesym, + childexesym, + parentexesym : TExeSymbol; + objsym : TObjSymbol; + begin + { Build inheritance tree from VTINHERIT } + for i:=0 to VTInheritList.Count-1 do + begin + objsym:=TObjSymbol(VTInheritList[i]); + hs:=objsym.name; + { VTINHERIT_$$ } + Delete(hs,1,Pos('_',hs)); + k:=Pos('$$',hs); + if k=0 then + internalerror(200603311); + childexesym:=texesymbol(FExeSymbolDict.search(Copy(hs,1,k-1))); + parentexesym:=texesymbol(FExeSymbolDict.search(Copy(hs,k+2,length(hs)-k-1))); + if not assigned(childexesym) or + not assigned(parentexesym)then + internalerror(200603312); + if not assigned(childexesym.vtable) then + begin + childexesym.vtable:=TExeVTable.Create(childexesym); + ExeVTableList.Add(childexesym.vtable); + end; + if not assigned(parentexesym.vtable) then + begin + parentexesym.vtable:=TExeVTable.Create(parentexesym); + ExeVTableList.Add(parentexesym.vtable); + end; + childexesym.vtable.SetVTableSize(childexesym.ObjSymbol.Size); + if parentexesym<>childexesym then + parentexesym.vtable.AddChild(childexesym.vtable); + end; + + { Find VTable entries from VTENTRY } + for i:=0 to VTEntryList.Count-1 do + begin + objsym:=TObjSymbol(VTEntryList[i]); + hs:=objsym.name; + { VTENTRY_$$ } + Delete(hs,1,Pos('_',hs)); + k:=Pos('$$',hs); + if k=0 then + internalerror(200603319); + vtableexesym:=texesymbol(FExeSymbolDict.search(Copy(hs,1,k-1))); + val(Copy(hs,k+2,length(hs)-k-1),vtableidx,code); + if (code<>0) then + internalerror(200603318); + if not assigned(vtableexesym) then + internalerror(2006033110); + vtableexesym.vtable.AddEntry(vtableidx); + end; + end; + + procedure TExeOutput.ResolveSymbols; var ObjData : TObjData; @@ -1391,7 +1572,13 @@ implementation commonsym : TObjSymbol; firstcommon : boolean; i,j : longint; + hs : string; + VTEntryList, + VTInheritList : TFPObjectList; begin + VTEntryList:=TFPObjectList.Create(false); + VTInheritList:=TFPObjectList.Create(false); + { The symbol calculation is done in 3 steps: 1. register globals @@ -1409,9 +1596,27 @@ implementation for j:=0 to ObjData.ObjSymbolList.Count-1 do begin objsym:=TObjSymbol(ObjData.ObjSymbolList[j]); - { Skip local symbols } + { From the local symbols we are only interressed in the + VTENTRY and VTINHERIT symbols } if objsym.bind=AB_LOCAL then - continue; + begin + hs:=objsym.name; + if (hs[1]='V') then + begin + if Copy(hs,1,5)='VTREF' then + begin + if not assigned(objsym.ObjSection.VTRefList) then + objsym.ObjSection.VTRefList:=TFPObjectList.Create(false); + objsym.ObjSection.VTRefList.Add(objsym); + end + else if Copy(hs,1,7)='VTENTRY' then + VTEntryList.Add(objsym) + else if Copy(hs,1,9)='VTINHERIT' then + VTInheritList.Add(objsym); + end; + continue; + end; + { Search for existing exesymbol } exesym:=texesymbol(FExeSymbolDict.search(objsym.name)); if not assigned(exesym) then begin @@ -1490,6 +1695,11 @@ implementation end else Comment(V_Error,'Entrypoint '+EntryName+' not defined'); + + { Generate VTable tree } + BuildVTableTree(VTInheritList,VTEntryList); + VTInheritList.Free; + VTEntryList.Free; end; @@ -1588,13 +1798,14 @@ implementation mergedstabsec, mergedstabstrsec : TObjSection; hstabreloc, - currstabReloc : TObjRelocation; + currstabreloc : TObjRelocation; + currstabrelocidx, i,j, mergestabcnt, stabcnt : longint; skipstab : boolean; hstab : TObjStabEntry; - stabRelocofs : longint; + stabrelocofs : longint; buf : array[0..1023] of byte; bufend, bufsize : longint; @@ -1628,7 +1839,7 @@ implementation begin stabcnt:=currstabsec.Data.size div sizeof(TObjStabEntry); currstabsec.Data.seek(0); - currstabReloc:=TObjRelocation(currstabsec.Relocations.first); + currstabrelocidx:=0; for j:=0 to stabcnt-1 do begin hstabreloc:=nil; @@ -1640,15 +1851,22 @@ implementation if not skipstab then begin { Find corresponding Relocation } - while assigned(currstabReloc) and - (currstabReloc.Dataoffset=j*sizeof(TObjStabEntry)+stabrelocofs) then + break; + inc(currstabrelocidx); + end; + if assigned(currstabreloc) and + (currstabreloc.dataoffset=j*sizeof(TObjStabEntry)+stabrelocofs) then begin hstabReloc:=currstabReloc; - currstabReloc:=TObjRelocation(currstabReloc.next); + inc(currstabrelocidx); end; + { Check if the stab is refering to a removed section } if assigned(hstabreloc) then begin @@ -1686,8 +1904,8 @@ implementation if assigned(hstabreloc) then begin hstabreloc.Dataoffset:=mergestabcnt*sizeof(TObjStabEntry)+stabRelocofs; - currstabsec.Relocations.remove(hstabreloc); - mergedstabsec.Relocations.concat(hstabreloc); + currstabsec.ObjRelocations[currstabrelocidx-1]:=nil; + mergedstabsec.ObjRelocations.Add(hstabreloc); end; { Write updated stab } mergedstabsec.write(hstab,sizeof(hstab)); @@ -1765,13 +1983,70 @@ implementation end; end; + procedure DoReloc(objreloc:TObjRelocation); + var + objsym : TObjSymbol; + refobjsec : TObjSection; + begin + { Disabled Relocation to 0 } + if objreloc.typ=RELOC_ZERO then + exit; + if assigned(objreloc.symbol) then + begin + objsym:=objreloc.symbol; + if objsym.bind<>AB_LOCAL then + begin + if not(assigned(objsym.exesymbol) and + assigned(objsym.exesymbol.objsymbol)) then + internalerror(200603063); + objsym:=objsym.exesymbol.objsymbol; + end; + if not assigned(objsym.objsection) then + internalerror(200603062); + refobjsec:=objsym.objsection; + end + else + if assigned(objreloc.objsection) then + refobjsec:=objreloc.objsection + else + internalerror(200603316); + if assigned(exemap) then + exemap.Add(' References '+refobjsec.fullname); + AddToObjSectionWorkList(refobjsec); + end; + + procedure DoVTableRef(vtable:TExeVTable;VTableIdx:longint); + var + i : longint; + objreloc : TObjRelocation; + begin + objreloc:=vtable.VTableRef(VTableIdx); + if assigned(objreloc) then + begin + { Process the relocation now if the ObjSection is + already processed and marked as used. Otherwise we leave it + unprocessed. It'll then be resolved when the ObjSection is + changed to Used } + if vtable.ExeSymbol.ObjSymbol.ObjSection.Used then + DoReloc(objreloc); + end; + { This recursive walking is done here instead of + in TExeVTable.VTableRef because we can now process + all needed relocations } + for i:=0 to vtable.ChildList.Count-1 do + DoVTableRef(TExeVTable(vtable.ChildList[i]),VTableIdx); + end; + var - i,j : longint; - exesec : TExeSection; - ObjData : TObjData; - refobjsec, - objsec : TObjSection; - objsym : TObjSymbol; + hs : string; + i,j,k : longint; + exesec : TExeSection; + objdata : TObjData; + objsec : TObjSection; + objsym : TObjSymbol; + code : integer; + vtableidx : longint; + vtableexesym : TExeSymbol; begin ObjSectionWorkList:=TFPObjectList.Create(false); @@ -1802,27 +2077,31 @@ implementation begin objsec:=TObjSection(ObjSectionWorkList.Last); if assigned(exemap) then - exemap.Add('Keeping '+objsec.FullName+' '+ToStr(objsec.ObjSymbolRefs.Count)+' references'); + exemap.Add('Keeping '+objsec.FullName+' '+ToStr(objsec.ObjRelocations.Count)+' references'); ObjSectionWorkList.Delete(ObjSectionWorkList.Count-1); - for i:=0 to objsec.ObjSymbolRefs.count-1 do + + { Process Relocations } + for i:=0 to objsec.ObjRelocations.count-1 do + DoReloc(TObjRelocation(objsec.ObjRelocations[i])); + + { Process Virtual Entry calls } + for i:=0 to objsec.VTRefList.count-1 do begin - objsym:=TObjSymbol(objsec.ObjSymbolRefs[i]); - if objsym.bind=AB_LOCAL then - begin - if not assigned(objsym.objsection) then - internalerror(200603062); - refobjsec:=objsym.objsection - end - else - begin - if not(assigned(objsym.exesymbol) and - assigned(objsym.exesymbol.objsymbol)) then - internalerror(200603063); - refobjsec:=objsym.exesymbol.objsymbol.objsection; - end; - if assigned(exemap) then - exemap.Add(' References '+refobjsec.fullname); - AddToObjSectionWorkList(refobjsec); + objsym:=TObjSymbol(objsec.VTRefList[i]); + hs:=objsym.name; + Delete(hs,1,Pos('_',hs)); + k:=Pos('$$',hs); + if k=0 then + internalerror(200603314); + vtableexesym:=texesymbol(FExeSymbolDict.search(Copy(hs,1,k-1))); + val(Copy(hs,k+2,length(hs)-k-1),vtableidx,code); + if (code<>0) then + internalerror(200603317); + if not assigned(vtableexesym) then + internalerror(200603315); + if not assigned(vtableexesym.vtable) then + internalerror(200603316); + DoVTableRef(vtableexesym.vtable,vtableidx); end; end; ObjSectionWorkList.Free; diff --git a/compiler/ogcoff.pas b/compiler/ogcoff.pas index a8105c6f4e..07f5d89a53 100644 --- a/compiler/ogcoff.pas +++ b/compiler/ogcoff.pas @@ -327,6 +327,7 @@ implementation PE_DATADIR_IMPORTADDRESSTABLE = 12; PE_DATADIR_DELAYIMPORT = 13; +{$ifdef x86_64} IMAGE_REL_AMD64_ABSOLUTE = $0000; { Reference is absolute, no relocation is necessary } IMAGE_REL_AMD64_ADDR64 = $0001; { 64-bit address (VA). } IMAGE_REL_AMD64_ADDR32 = $0002; { 32-bit address (VA). } @@ -344,8 +345,13 @@ implementation IMAGE_REL_AMD64_SREL32 = $000E; { 32 bit signed span-dependent value emitted into object } IMAGE_REL_AMD64_PAIR = $000F; IMAGE_REL_AMD64_SSPAN32 = $0010; { 32 bit signed span-dependent value applied at link time } +{$endif x86_64} - type + R_DIR32 = 6; + R_IMAGEBASE = 7; + R_PCRLONG = 20; + + type { Structures which are written directly to the output file } coffheader=packed record mach : word; @@ -723,35 +729,42 @@ const win32stub : array[0..131] of byte=( procedure TCoffObjSection.addsymsizereloc(ofs:aint;p:TObjSymbol;symsize:aint;reloctype:TObjRelocationType); begin - relocations.concat(TObjRelocation.createsymbolsize(ofs,p,symsize,reloctype)); + ObjRelocations.Add(TObjRelocation.createsymbolsize(ofs,p,symsize,reloctype)); end; procedure TCoffObjSection.fixuprelocs; var - r : TObjRelocation; + i : longint; + objreloc : TObjRelocation; address, relocval : aint; relocsec : TObjSection; begin - r:=TObjRelocation(relocations.first); - if assigned(r) and - (not assigned(data)) then + if (ObjRelocations.Count>0) and + not assigned(data) then internalerror(200205183); - while assigned(r) do + for i:=0 to ObjRelocations.Count-1 do begin - data.Seek(r.dataoffset); - data.Read(address,4); - if assigned(r.symbol) then + objreloc:=TObjRelocation(ObjRelocations[i]); + if objreloc.typ=RELOC_ZERO then begin - relocsec:=r.symbol.objsection; - relocval:=r.symbol.address; + data.Seek(objreloc.dataoffset); + data.Write(0,4); + continue; + end; + data.Seek(objreloc.dataoffset); + data.Read(address,4); + if assigned(objreloc.symbol) then + begin + relocsec:=objreloc.symbol.objsection; + relocval:=objreloc.symbol.address; end else - if assigned(r.objsection) then + if assigned(objreloc.objsection) then begin - relocsec:=r.objsection; - relocval:=r.objsection.mempos + relocsec:=objreloc.objsection; + relocval:=objreloc.objsection.mempos end else internalerror(200205183); @@ -759,12 +772,12 @@ const win32stub : array[0..131] of byte=( if not relocsec.used and not(oso_debug in secoptions) then internalerror(200603061); - case r.typ of + case objreloc.typ of RELOC_RELATIVE : begin address:=address-mempos+relocval; if TCoffObjData(objdata).win32 then - dec(address,r.dataoffset+4); + dec(address,objreloc.dataoffset+4); end; RELOC_RVA : begin @@ -779,7 +792,7 @@ const win32stub : array[0..131] of byte=( RELOC_ABSOLUTE : begin if oso_common in relocsec.secoptions then - dec(address,r.orgsize) + dec(address,objreloc.orgsize) else begin { fixup address when the symbol was known in defined object } @@ -792,10 +805,8 @@ const win32stub : array[0..131] of byte=( else internalerror(200604014); end; - data.Seek(r.dataoffset); + data.Seek(objreloc.dataoffset); data.Write(address,4); - { goto next reloc } - r:=TObjRelocation(r.next); end; end; @@ -1099,7 +1110,7 @@ const win32stub : array[0..131] of byte=( { AUX } fillchar(secrec,sizeof(secrec),0); secrec.len:=Size; - secrec.nrelocs:=relocations.count; + secrec.nrelocs:=ObjRelocations.count; inc(symidx); FCoffSyms.write(secrec,sizeof(secrec)); end; @@ -1108,60 +1119,60 @@ const win32stub : array[0..131] of byte=( procedure TCoffObjOutput.section_write_relocs(p:TObject;arg:pointer); var + i : longint; rel : coffreloc; - r : TObjRelocation; + objreloc : TObjRelocation; begin - r:=TObjRelocation(TObjSection(p).relocations.first); - while assigned(r) do - begin - rel.address:=r.dataoffset; - if assigned(r.symbol) then - begin - if (r.symbol.bind=AB_LOCAL) then - rel.sym:=r.symbol.objsection.secsymidx - else - begin - if r.symbol.symidx=-1 then - internalerror(200602233); - rel.sym:=r.symbol.symidx; - end; - end - else - begin - if r.objsection<>nil then - rel.sym:=r.objsection.secsymidx - else - rel.sym:=0; - end; + for i:=0 to TObjSection(p).ObjRelocations.Count-1 do + begin + objreloc:=TObjRelocation(TObjSection(p).ObjRelocations[i]); + rel.address:=objreloc.dataoffset; + if assigned(objreloc.symbol) then + begin + if (objreloc.symbol.bind=AB_LOCAL) then + rel.sym:=objreloc.symbol.objsection.secsymidx + else + begin + if objreloc.symbol.symidx=-1 then + internalerror(200602233); + rel.sym:=objreloc.symbol.symidx; + end; + end + else + begin + if objreloc.objsection<>nil then + rel.sym:=objreloc.objsection.secsymidx + else + rel.sym:=0; + end; + case objreloc.typ of +{$ifdef arm} + RELOC_ABSOLUTE : + ; +{$endif arm} {$ifdef i386} - case r.typ of - RELOC_RELATIVE : - rel.reloctype:=$14; - RELOC_ABSOLUTE : - rel.reloctype:=$6; - RELOC_RVA : - rel.reloctype:=$7; - else - internalerror(200604011); - end; + RELOC_RELATIVE : + rel.reloctype:=R_PCRLONG; + RELOC_ABSOLUTE : + rel.reloctype:=R_DIR32; + RELOC_RVA : + rel.reloctype:=R_IMAGEBASE; {$endif i386} {$ifdef x86_64} - case r.typ of - RELOC_RELATIVE : - rel.reloctype:=IMAGE_REL_AMD64_REL32; - RELOC_ABSOLUTE32 : - rel.reloctype:=IMAGE_REL_AMD64_ADDR32; - RELOC_ABSOLUTE : - rel.reloctype:=IMAGE_REL_AMD64_ADDR64; - RELOC_RVA : - rel.reloctype:=IMAGE_REL_AMD64_ADDR32NB; - else - internalerror(200604012); - end; + RELOC_RELATIVE : + rel.reloctype:=IMAGE_REL_AMD64_REL32; + RELOC_ABSOLUTE32 : + rel.reloctype:=IMAGE_REL_AMD64_ADDR32; + RELOC_ABSOLUTE : + rel.reloctype:=IMAGE_REL_AMD64_ADDR64; + RELOC_RVA : + rel.reloctype:=IMAGE_REL_AMD64_ADDR32NB; {$endif x86_64} - FWriter.write(rel,sizeof(rel)); - r:=TObjRelocation(r.next); - end; + else + internalerror(200603311); + end; + FWriter.write(rel,sizeof(rel)); + end; end; @@ -1226,7 +1237,7 @@ const win32stub : array[0..131] of byte=( procedure TCoffObjOutput.section_set_reloc_datapos(p:TObject;arg:pointer); begin TCoffObjSection(p).coffrelocpos:=paint(arg)^; - inc(paint(arg)^,sizeof(coffreloc)*TObjSection(p).relocations.count); + inc(paint(arg)^,sizeof(coffreloc)*TObjSection(p).ObjRelocations.count); end; @@ -1262,7 +1273,7 @@ const win32stub : array[0..131] of byte=( if (Size>0) and (oso_data in secoptions) then sechdr.datapos:=datapos; - sechdr.nrelocs:=relocations.count; + sechdr.nrelocs:=ObjRelocations.count; sechdr.relocpos:=coffrelocpos; if win32 then sechdr.flags:=peencodesechdrflags(secoptions,secalign) @@ -1432,10 +1443,17 @@ const win32stub : array[0..131] of byte=( begin FReader.read(rel,sizeof(rel)); case rel.reloctype of +{$ifdef arm} + R_IMAGEBASE : + ; +{$endif arm} {$ifdef i386} - $14 : rel_type:=RELOC_RELATIVE; - $06 : rel_type:=RELOC_ABSOLUTE; - $07 : rel_type:=RELOC_RVA; + R_PCRLONG : + rel_type:=RELOC_RELATIVE; + R_DIR32 : + rel_type:=RELOC_ABSOLUTE; + R_IMAGEBASE : + rel_type:=RELOC_RVA; {$endif i386} {$ifdef x86_64} IMAGE_REL_AMD64_REL32: @@ -1456,11 +1474,7 @@ const win32stub : array[0..131] of byte=( p:=FSymTbl^[rel.sym].sym; if assigned(p) then - begin - s.addsymsizereloc(rel.address-s.mempos,p,FSymTbl^[rel.sym].orgsize,rel_type); - { Register symbol reference in TObjSection } - s.AddSymbolRef(p); - end + s.addsymsizereloc(rel.address-s.mempos,p,FSymTbl^[rel.sym].orgsize,rel_type) else begin InputError('Failed reading coff file, can''t resolve symbol of relocation'); diff --git a/compiler/ogelf.pas b/compiler/ogelf.pas index ac846f1684..70838c5591 100644 --- a/compiler/ogelf.pas +++ b/compiler/ogelf.pas @@ -63,7 +63,6 @@ interface goTSect, plTSect, symsect : TElfObjSection; - syms : Tdynamicarray; constructor create(const n:string);override; destructor destroy;override; function sectionname(atype:TAsmSectiontype;const aname:string):string;override; @@ -114,19 +113,26 @@ implementation symbolresize = 200*18; const + { Relocation types } +{$ifdef i386} R_386_32 = 1; { ordinary absolute relocation } R_386_PC32 = 2; { PC-relative relocation } R_386_GOT32 = 3; { an offset into GOT } R_386_PLT32 = 4; { a PC-relative offset into PLT } R_386_GOTOFF = 9; { an offset from GOT base } R_386_GOTPC = 10; { a PC-relative offset _to_ GOT } - + R_386_GNU_VTINHERIT = 250; + R_386_GNU_VTENTRY = 251; +{$endif i386} +{$ifdef sparc} R_SPARC_32 = 3; R_SPARC_WDISP30 = 7; R_SPARC_HI22 = 9; R_SPARC_LO10 = 12; - - { AMD64 relocations } + R_SPARC_GNU_VTINHERIT = 250; + R_SPARC_GNU_VTENTRY = 251; +{$endif sparc} +{$ifdef x86_64} R_X86_64_NONE = 0; { Direct 64 bit } R_X86_64_64 = 1; @@ -174,7 +180,11 @@ implementation R_X86_64_GOTTPOFF = 22; { Offset in initial TLS block } R_X86_64_TPOFF32 = 23; - R_X86_64_NUM = 24; + { GNU extension to record C++ vtable hierarchy } + R_X86_64_GNU_VTINHERIT = 24; + { GNU extension to record C++ vtable member usage } + R_X86_64_GNU_VTENTRY = 25; +{$endif x86_64} SHN_UNDEF = 0; SHN_ABS = $fff1; @@ -554,8 +564,6 @@ implementation begin inherited create(n); CObjSection:=TElfObjSection; - { reset } - Syms:=TDynamicArray.Create(symbolresize); { default sections } symtabsect:=TElfObjSection.create_ext('.symtab',SHT_SYMTAB,0,0,0,4,sizeof(telfsymbol)); strtabsect:=TElfObjSection.create_ext('.strtab',SHT_STRTAB,0,0,0,1,0); @@ -577,7 +585,6 @@ implementation destructor TElfObjData.destroy; begin - Syms.Free; symtabsect.free; strtabsect.free; shstrtabsect.free; @@ -696,12 +703,14 @@ implementation procedure TElfObjectOutput.createrelocsection(s:TElfObjSection); var + i : longint; {$ifdef ver2_0_0} relnative, {$endif ver2_0_0} rel : telfreloc; - r : TObjRelocation; - relsym,reltyp : longint; + objreloc : TObjRelocation; + relsym, + reltyp : longint; begin with elf32data do begin @@ -721,85 +730,71 @@ implementation s.relocsect:=TElfObjSection.create_ext('.rela'+s.name,SHT_RELA,0,symtabsect.secshidx,s.secshidx,4,sizeof(TElfReloc)); {$endif i386} { add the relocations } - r:=TObjRelocation(s.relocations.first); - while assigned(r) do - begin - rel.address:=r.dataoffset; - if assigned(r.symbol) then - begin - if (r.symbol.bind=AB_LOCAL) then - relsym:=r.symbol.objsection.secsymidx - else - begin - if r.symbol.symidx=-1 then - internalerror(200603012); - relsym:=r.symbol.symidx; - end; - end - else - if r.objsection<>nil then - relsym:=r.objsection.secsymidx + for i:=0 to s.Objrelocations.count-1 do + begin + objreloc:=TObjRelocation(s.Objrelocations[i]); + fillchar(rel,sizeof(rel),0); + rel.address:=objreloc.dataoffset; + if assigned(objreloc.symbol) then + begin + if (objreloc.symbol.bind=AB_LOCAL) then + relsym:=objreloc.symbol.objsection.secsymidx + else + begin + if objreloc.symbol.symidx=-1 then + internalerror(200603012); + relsym:=objreloc.symbol.symidx; + end; + end else - relsym:=SHN_UNDEF; + begin + if objreloc.objsection<>nil then + relsym:=objreloc.objsection.secsymidx + else + relsym:=SHN_UNDEF; + end; - { when things settle down, we can create processor specific - derived classes - } + { when things settle down, we can create processor specific + derived classes } + case objreloc.typ of {$ifdef i386} - case r.typ of - RELOC_RELATIVE : - reltyp:=R_386_PC32; - RELOC_ABSOLUTE : - reltyp:=R_386_32; - end; + RELOC_RELATIVE : + reltyp:=R_386_PC32; + RELOC_ABSOLUTE : + reltyp:=R_386_32; {$endif i386} {$ifdef sparc} - case r.typ of -{ RELOC_RELATIVE : - reltyp:=R_386_PC32; -} - RELOC_ABSOLUTE : - reltyp:=R_SPARC_32; - else - internalerror(200410201); - end; + RELOC_ABSOLUTE : + reltyp:=R_SPARC_32; {$endif sparc} {$ifdef x86_64} - case r.typ of - RELOC_RELATIVE : - begin - reltyp:=R_X86_64_PC32; - { length of the relocated location is handled here } - rel.addend:=qword(-4); - end; - RELOC_ABSOLUTE : - begin - reltyp:=R_X86_64_64; - rel.addend:=0; - end; - RELOC_ABSOLUTE32 : - begin - reltyp:=R_X86_64_32S; - rel.addend:=0; - end; - else - internalerror(200602261); - end; + RELOC_RELATIVE : + begin + reltyp:=R_X86_64_PC32; + { length of the relocated location is handled here } + rel.addend:=qword(-4); + end; + RELOC_ABSOLUTE : + reltyp:=R_X86_64_64; + RELOC_ABSOLUTE32 : + reltyp:=R_X86_64_32S; {$endif x86_64} + else + internalerror(200602261); + end; {$ifdef cpu64bit} - rel.info:=(qword(relsym) shl 32) or reltyp; + rel.info:=(qword(relsym) shl 32) or reltyp; {$else cpu64bit} - rel.info:=(relsym shl 8) or reltyp; + rel.info:=(relsym shl 8) or reltyp; {$endif cpu64bit} - { write reloc } + { write reloc } {$ifdef ver2_0_0} - relnative:=MaybeSwapElfReloc(rel); - s.relocsect.write(relnative,sizeof(rel)); + relnative:=MaybeSwapElfReloc(rel); + s.relocsect.write(relnative,sizeof(rel)); {$else} - s.relocsect.write(MaybeSwapElfReloc(rel),sizeof(rel)); + s.relocsect.write(MaybeSwapElfReloc(rel),sizeof(rel)); {$endif ver2_0_0} - r:=TObjRelocation(r.next); - end; + end; end; end; @@ -834,11 +829,74 @@ implementation procedure TElfObjectOutput.createsymtab; - var + + procedure WriteSym(objsym:TObjSymbol); + var {$ifdef ver2_0_0} - elfsymnative, + elfsymnative, {$endif} - elfsym : telfsymbol; + elfsym : telfsymbol; + begin + with elf32data do + begin + fillchar(elfsym,sizeof(elfsym),0); + { symbolname, write the #0 separate to overcome 255+1 char not possible } + elfsym.st_name:=strtabsect.Size; + strtabsect.writestr(objsym.name); + strtabsect.writestr(#0); + elfsym.st_size:=objsym.size; + case objsym.bind of + AB_LOCAL : + begin + elfsym.st_value:=objsym.address; + elfsym.st_info:=STB_LOCAL shl 4; + inc(localsyms); + end; + AB_COMMON : + begin + elfsym.st_value:=$10; + elfsym.st_info:=STB_GLOBAL shl 4; + end; + AB_EXTERNAL : + elfsym.st_info:=STB_GLOBAL shl 4; + AB_GLOBAL : + begin + elfsym.st_value:=objsym.address; + elfsym.st_info:=STB_GLOBAL shl 4; + end; + end; + if (objsym.bind<>AB_EXTERNAL) {and + not(assigned(objsym.objsection) and + not(oso_data in objsym.objsection.secoptions))} then + begin + case objsym.typ of + AT_FUNCTION : + elfsym.st_info:=elfsym.st_info or STT_FUNC; + AT_DATA : + elfsym.st_info:=elfsym.st_info or STT_OBJECT; + end; + end; + if objsym.bind=AB_COMMON then + elfsym.st_shndx:=SHN_COMMON + else + begin + if assigned(objsym.objsection) then + elfsym.st_shndx:=TElfObjSection(objsym.objsection).secshidx + else + elfsym.st_shndx:=SHN_UNDEF; + end; + objsym.symidx:=symidx; + inc(symidx); +{$ifdef ver2_0_0} + elfsymnative:=MaybeSwapElfSymbol(elfsym); + symtabsect.write(elfsymnative,sizeof(elfsym)); +{$else} + symtabsect.write(MaybeSwapElfSymbol(elfsym),sizeof(elfsym)); +{$endif ver2_0_0} + end; + end; + + var i : longint; objsym : TObjSymbol; begin @@ -852,67 +910,21 @@ implementation write_internal_symbol(1,STT_FILE,SHN_ABS); { section } ObjSectionList.ForEachCall(@section_write_symbol,nil); - { ObjSymbols } + { First the Local Symbols, this is required by ELF. The localsyms + count stored in shinfo is used to skip the local symbols + when traversing the symtab } for i:=0 to ObjSymbolList.Count-1 do begin objsym:=TObjSymbol(ObjSymbolList[i]); - if objsym.bind<>AB_LOCAL then - begin - fillchar(elfsym,sizeof(elfsym),0); - { symbolname, write the #0 separate to overcome 255+1 char not possible } - elfsym.st_name:=strtabsect.Size; - strtabsect.writestr(objsym.name); - strtabsect.writestr(#0); - elfsym.st_size:=objsym.size; - case objsym.bind of - AB_LOCAL : - begin - elfsym.st_value:=objsym.address; - elfsym.st_info:=STB_LOCAL shl 4; - inc(localsyms); - end; - AB_COMMON : - begin - elfsym.st_value:=$10; - elfsym.st_info:=STB_GLOBAL shl 4; - end; - AB_EXTERNAL : - elfsym.st_info:=STB_GLOBAL shl 4; - AB_GLOBAL : - begin - elfsym.st_value:=objsym.address; - elfsym.st_info:=STB_GLOBAL shl 4; - end; - end; - if (objsym.bind<>AB_EXTERNAL) and - not(assigned(objsym.objsection) and - not(oso_data in objsym.objsection.secoptions)) then - begin - case objsym.typ of - AT_FUNCTION : - elfsym.st_info:=elfsym.st_info or STT_FUNC; - AT_DATA : - elfsym.st_info:=elfsym.st_info or STT_OBJECT; - end; - end; - if objsym.bind=AB_COMMON then - elfsym.st_shndx:=SHN_COMMON - else - begin - if assigned(objsym.objsection) then - elfsym.st_shndx:=TElfObjSection(objsym.objsection).secshidx - else - elfsym.st_shndx:=SHN_UNDEF; - end; - objsym.symidx:=symidx; - inc(symidx); -{$ifdef ver2_0_0} - elfsymnative:=MaybeSwapElfSymbol(elfsym); - symtabsect.write(elfsymnative,sizeof(elfsym)); -{$else} - symtabsect.write(MaybeSwapElfSymbol(elfsym),sizeof(elfsym)); -{$endif ver2_0_0} - end; + if (objsym.bind=AB_LOCAL) and (objsym.typ<>AT_LABEL) then + WriteSym(objsym); + end; + { Global Symbols } + for i:=0 to ObjSymbolList.Count-1 do + begin + objsym:=TObjSymbol(ObjSymbolList[i]); + if (objsym.bind<>AB_LOCAL) then + WriteSym(objsym); end; { update the .symtab section header } symtabsect.shlink:=strtabsect.secshidx; @@ -982,14 +994,14 @@ implementation begin TElfObjSection(p).secshidx:=pword(arg)^; inc(pword(arg)^); - if TElfObjSection(p).relocations.count>0 then + if TElfObjSection(p).ObjRelocations.count>0 then inc(pword(arg)^); end; procedure TElfObjectOutput.section_create_relocsec(p:TObject;arg:pointer); begin - if (TElfObjSection(p).relocations.count>0) then + if (TElfObjSection(p).ObjRelocations.count>0) then createrelocsection(TElfObjSection(p)); end;