Browse Source

+ ELF linker: Support writing RELATIVE dynamic relocations ahead of the rest, and their number in DT_REL[A]COUNT dynamic tag (still needs changes in CPU-specific code to function properly).
* TElfObjInput.LoadSymbols: ignore STT_SECTION symbols for sections that were ignored in LoadSections().
* TElfObjInput: changed symtabndx (index of .symtab/.dynsym section) into field and its type to unsigned.

git-svn-id: trunk@22951 -

sergei 12 years ago
parent
commit
277200e7ae
1 changed files with 47 additions and 12 deletions
  1. 47 12
      compiler/ogelf.pas

+ 47 - 12
compiler/ogelf.pas

@@ -118,6 +118,7 @@ interface
          shentsize: longword;
          shentsize: longword;
          shoffset: aword;
          shoffset: aword;
          shstrndx: longword;
          shstrndx: longword;
+         symtabndx: longword;
          shstrtab: PChar;
          shstrtab: PChar;
          strtab: PChar;
          strtab: PChar;
          shstrtablen: longword;
          shstrtablen: longword;
@@ -216,7 +217,9 @@ interface
          pltrelocsec,
          pltrelocsec,
          ipltrelocsec,
          ipltrelocsec,
          dynrelocsec: TElfObjSection;
          dynrelocsec: TElfObjSection;
+         dynreloclist: TFPObjectList;
          tlsseg: TElfSegment;
          tlsseg: TElfSegment;
+         relative_reloc_count: longint;
          procedure WriteDynRelocEntry(dataofs:aword;typ:byte;symidx:aword;addend:aword);
          procedure WriteDynRelocEntry(dataofs:aword;typ:byte;symidx:aword;addend:aword);
          procedure WriteFirstPLTEntry;virtual;abstract;
          procedure WriteFirstPLTEntry;virtual;abstract;
          procedure WritePLTEntry(exesym:TExeSymbol);virtual;
          procedure WritePLTEntry(exesym:TExeSymbol);virtual;
@@ -315,6 +318,7 @@ implementation
 {$endif x86_64}
 {$endif x86_64}
 
 
       SHN_UNDEF     = 0;
       SHN_UNDEF     = 0;
+      SHN_LORESERVE = $FF00;
       SHN_ABS       = $fff1;
       SHN_ABS       = $fff1;
       SHN_COMMON    = $fff2;
       SHN_COMMON    = $fff2;
 
 
@@ -1568,16 +1572,8 @@ implementation
               Continue
               Continue
             else if sym.st_shndx=SHN_COMMON then
             else if sym.st_shndx=SHN_COMMON then
               bind:=AB_COMMON
               bind:=AB_COMMON
-            else if (sym.st_shndx>=nsects) or
-              (
-                (sym.st_shndx>0) and
-                (FSecTbl[sym.st_shndx].sec=nil) and
-                (not dynobj)
-              ) then
-              begin
-                writeln(objdata.name,' ',i);
-                InternalError(2012060206)
-              end
+            else if (sym.st_shndx>=nsects) then
+              InternalError(2012060206)
             else
             else
               case (sym.st_info shr 4) of
               case (sym.st_info shr 4) of
                 STB_LOCAL:
                 STB_LOCAL:
@@ -1593,6 +1589,19 @@ implementation
                 InternalError(2012060207);
                 InternalError(2012060207);
               end;
               end;
 
 
+            { Ignore section symbol if we didn't create the corresponding objsection
+              (examples are SHT_GROUP or .note.GNU-stack sections). }
+            if (sym.st_shndx>0) and (sym.st_shndx<SHN_LORESERVE) and
+              (FSecTbl[sym.st_shndx].sec=nil) and
+              (not dynobj) then
+              if ((sym.st_info and $0F)=STT_SECTION) then
+                Continue
+              else
+                begin
+                  writeln(objdata.name,' ',i);
+                  InternalError(2012110701)
+                end;
+
             case (sym.st_info and $0F) of
             case (sym.st_info and $0F) of
               STT_NOTYPE:
               STT_NOTYPE:
                 typ:=AT_NONE;
                 typ:=AT_NONE;
@@ -1802,7 +1811,7 @@ implementation
 
 
     function TElfObjInput.ReadObjData(AReader:TObjectreader;objdata:TObjData):boolean;
     function TElfObjInput.ReadObjData(AReader:TObjectreader;objdata:TObjData):boolean;
       var
       var
-        i,j,symtabndx,strndx,dynndx,
+        i,j,strndx,dynndx,
         versymndx,verdefndx,verneedndx: longint;
         versymndx,verdefndx,verneedndx: longint;
         objsec: TElfObjSection;
         objsec: TElfObjSection;
         shdrs: array of TElfsechdr;
         shdrs: array of TElfsechdr;
@@ -1854,7 +1863,7 @@ implementation
           Note that is is legal to have no symtable.
           Note that is is legal to have no symtable.
           For DSO, locate .dynsym instead, this one is near the beginning, but
           For DSO, locate .dynsym instead, this one is near the beginning, but
           overall number of sections won't be big. }
           overall number of sections won't be big. }
-        symtabndx:=-1;
+        symtabndx:=0;
         for i:=nsects-1 downto 1 do
         for i:=nsects-1 downto 1 do
           begin
           begin
             if (shdrs[i].sh_type<>symsectypes[dynobj]) then
             if (shdrs[i].sh_type<>symsectypes[dynobj]) then
@@ -1880,6 +1889,9 @@ implementation
             break;
             break;
           end;
           end;
 
 
+        if symtabndx=0 then
+          InternalError(2012110706);
+
         if dynobj then
         if dynobj then
           begin
           begin
             { Locate .dynamic and version sections. Expect a single one of a kind. }
             { Locate .dynamic and version sections. Expect a single one of a kind. }
@@ -2031,6 +2043,7 @@ implementation
         neededlist.Free;
         neededlist.Free;
         segmentlist.Free;
         segmentlist.Free;
         dynsymlist.Free;
         dynsymlist.Free;
+        dynreloclist.Free;
         if assigned(dynsymnames) then
         if assigned(dynsymnames) then
           FreeMem(dynsymnames);
           FreeMem(dynsymnames);
         inherited Destroy;
         inherited Destroy;
@@ -2629,8 +2642,25 @@ implementation
         i,j: longint;
         i,j: longint;
         exesec: TExeSection;
         exesec: TExeSection;
         seg: TElfSegment;
         seg: TElfSegment;
+        objreloc: TObjRelocation;
       begin
       begin
         gotwritten:=true;
         gotwritten:=true;
+        { If target does not support sorted relocations, it is expected to write the
+          entire .rel[a].dyn section during FixupRelocations. Otherwise, only RELATIVE ones
+          should be written, space for non-relative relocations should remain. }
+        if assigned(dynrelocsec) and (relative_reloc_count>0) then
+          begin
+            if (dynrelocsec.size+(dynreloclist.count*dynrelocsec.shentsize)<>dynrelsize) then
+              InternalError(2012110601);
+            { Write out non-RELATIVE dynamic relocations
+              TODO: additional sorting? }
+            for i:=0 to dynreloclist.count-1 do
+              begin
+                objreloc:=TObjRelocation(dynreloclist[i]);
+                WriteDynRelocEntry(objreloc.dataoffset,objreloc.ftype,objreloc.symbol.exesymbol.dynindex,0);
+              end;
+          end;
+
         { sanity checks }
         { sanity checks }
         if assigned(gotobjsec) and (gotsize<>gotobjsec.size) then
         if assigned(gotobjsec) and (gotsize<>gotobjsec.size) then
           InternalError(2012092501);
           InternalError(2012092501);
@@ -2743,6 +2773,8 @@ implementation
 
 
         dynrelocsec:=TElfObjSection.create_reloc(internalObjData,'.dyn',true);
         dynrelocsec:=TElfObjSection.create_reloc(internalObjData,'.dyn',true);
         dynrelocsec.SecOptions:=[oso_keep];
         dynrelocsec.SecOptions:=[oso_keep];
+
+        dynreloclist:=TFPObjectList.Create(true);
       end;
       end;
 
 
 
 
@@ -2902,6 +2934,7 @@ implementation
       pltreltags: array[boolean] of longword=(DT_REL,DT_RELA);
       pltreltags: array[boolean] of longword=(DT_REL,DT_RELA);
       relsztags:  array[boolean] of longword=(DT_RELSZ,DT_RELASZ);
       relsztags:  array[boolean] of longword=(DT_RELSZ,DT_RELASZ);
       relenttags: array[boolean] of longword=(DT_RELENT,DT_RELAENT);
       relenttags: array[boolean] of longword=(DT_RELENT,DT_RELAENT);
+      relcnttags: array[boolean] of longword=(DT_RELCOUNT,DT_RELACOUNT);
 
 
     procedure TElfExeOutput.FinishDynamicTags;
     procedure TElfExeOutput.FinishDynamicTags;
       begin
       begin
@@ -2924,6 +2957,8 @@ implementation
             writeDynTag(relsztags[relocs_use_addend],dynrelocsec.Size);
             writeDynTag(relsztags[relocs_use_addend],dynrelocsec.Size);
             writeDynTag(relenttags[relocs_use_addend],dynrelocsec.shentsize);
             writeDynTag(relenttags[relocs_use_addend],dynrelocsec.shentsize);
           end;
           end;
+        if (relative_reloc_count>0) then
+          writeDynTag(relcnttags[relocs_use_addend],relative_reloc_count);
         writeDynTag(DT_NULL,0);
         writeDynTag(DT_NULL,0);
       end;
       end;