Browse Source

Merged revisions 3090-3113 via svnmerge from
svn+ssh://[email protected]/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 -

peter 19 năm trước cách đây
mục cha
commit
be88cd47b2
7 tập tin đã thay đổi với 633 bổ sung310 xóa
  1. 1 0
      compiler/aasmdata.pas
  2. 2 2
      compiler/assemble.pas
  3. 10 2
      compiler/ncgcal.pas
  4. 20 11
      compiler/nobj.pas
  5. 357 78
      compiler/ogbase.pas
  6. 93 79
      compiler/ogcoff.pas
  7. 150 138
      compiler/ogelf.pas

+ 1 - 0
compiler/aasmdata.pas

@@ -122,6 +122,7 @@ interface
       public
         name,
         realname      : string[80];
+        NextVTEntryNr : longint;
         { Assembler lists }
         AsmLists      : array[TAsmListType] of TAsmList;
         CurrAsmList   : TAsmList;

+ 2 - 2
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;

+ 10 - 2
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

+ 20 - 11
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;
 
 

+ 357 - 78
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_<ChildVMTName>$$<ParentVMTName> }
+            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_<VTableName>$$<Index> }
+            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) do
-                          currstabReloc:=TObjRelocation(currstabReloc.next);
-                        if assigned(currstabReloc) and
-                           (currstabReloc.Dataoffset=j*sizeof(TObjStabEntry)+stabRelocofs) then
+                        currstabreloc:=nil;
+                        while (currstabrelocidx<currstabsec.ObjRelocations.Count) do
+                          begin
+                            currstabreloc:=TObjRelocation(currstabsec.ObjRelocations[currstabrelocidx]);
+                            if 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;

+ 93 - 79
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}
+
+       R_DIR32 = 6;
+       R_IMAGEBASE = 7;
+       R_PCRLONG = 20;
 
-       type
+    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);
+            objreloc:=TObjRelocation(ObjRelocations[i]);
+            if objreloc.typ=RELOC_ZERO then
+              begin
+                data.Seek(objreloc.dataoffset);
+                data.Write(0,4);
+                continue;
+              end;
+            data.Seek(objreloc.dataoffset);
             data.Read(address,4);
-            if assigned(r.symbol) then
+            if assigned(objreloc.symbol) then
               begin
-                relocsec:=r.symbol.objsection;
-                relocval:=r.symbol.address;
+                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');

+ 150 - 138
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;