Kaynağa Gözat

+ 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 yıl önce
ebeveyn
işleme
277200e7ae
1 değiştirilmiş dosya ile 47 ekleme ve 12 silme
  1. 47 12
      compiler/ogelf.pas

+ 47 - 12
compiler/ogelf.pas

@@ -118,6 +118,7 @@ interface
          shentsize: longword;
          shoffset: aword;
          shstrndx: longword;
+         symtabndx: longword;
          shstrtab: PChar;
          strtab: PChar;
          shstrtablen: longword;
@@ -216,7 +217,9 @@ interface
          pltrelocsec,
          ipltrelocsec,
          dynrelocsec: TElfObjSection;
+         dynreloclist: TFPObjectList;
          tlsseg: TElfSegment;
+         relative_reloc_count: longint;
          procedure WriteDynRelocEntry(dataofs:aword;typ:byte;symidx:aword;addend:aword);
          procedure WriteFirstPLTEntry;virtual;abstract;
          procedure WritePLTEntry(exesym:TExeSymbol);virtual;
@@ -315,6 +318,7 @@ implementation
 {$endif x86_64}
 
       SHN_UNDEF     = 0;
+      SHN_LORESERVE = $FF00;
       SHN_ABS       = $fff1;
       SHN_COMMON    = $fff2;
 
@@ -1568,16 +1572,8 @@ implementation
               Continue
             else if sym.st_shndx=SHN_COMMON then
               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
               case (sym.st_info shr 4) of
                 STB_LOCAL:
@@ -1593,6 +1589,19 @@ implementation
                 InternalError(2012060207);
               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
               STT_NOTYPE:
                 typ:=AT_NONE;
@@ -1802,7 +1811,7 @@ implementation
 
     function TElfObjInput.ReadObjData(AReader:TObjectreader;objdata:TObjData):boolean;
       var
-        i,j,symtabndx,strndx,dynndx,
+        i,j,strndx,dynndx,
         versymndx,verdefndx,verneedndx: longint;
         objsec: TElfObjSection;
         shdrs: array of TElfsechdr;
@@ -1854,7 +1863,7 @@ implementation
           Note that is is legal to have no symtable.
           For DSO, locate .dynsym instead, this one is near the beginning, but
           overall number of sections won't be big. }
-        symtabndx:=-1;
+        symtabndx:=0;
         for i:=nsects-1 downto 1 do
           begin
             if (shdrs[i].sh_type<>symsectypes[dynobj]) then
@@ -1880,6 +1889,9 @@ implementation
             break;
           end;
 
+        if symtabndx=0 then
+          InternalError(2012110706);
+
         if dynobj then
           begin
             { Locate .dynamic and version sections. Expect a single one of a kind. }
@@ -2031,6 +2043,7 @@ implementation
         neededlist.Free;
         segmentlist.Free;
         dynsymlist.Free;
+        dynreloclist.Free;
         if assigned(dynsymnames) then
           FreeMem(dynsymnames);
         inherited Destroy;
@@ -2629,8 +2642,25 @@ implementation
         i,j: longint;
         exesec: TExeSection;
         seg: TElfSegment;
+        objreloc: TObjRelocation;
       begin
         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 }
         if assigned(gotobjsec) and (gotsize<>gotobjsec.size) then
           InternalError(2012092501);
@@ -2743,6 +2773,8 @@ implementation
 
         dynrelocsec:=TElfObjSection.create_reloc(internalObjData,'.dyn',true);
         dynrelocsec.SecOptions:=[oso_keep];
+
+        dynreloclist:=TFPObjectList.Create(true);
       end;
 
 
@@ -2902,6 +2934,7 @@ implementation
       pltreltags: array[boolean] of longword=(DT_REL,DT_RELA);
       relsztags:  array[boolean] of longword=(DT_RELSZ,DT_RELASZ);
       relenttags: array[boolean] of longword=(DT_RELENT,DT_RELAENT);
+      relcnttags: array[boolean] of longword=(DT_RELCOUNT,DT_RELACOUNT);
 
     procedure TElfExeOutput.FinishDynamicTags;
       begin
@@ -2924,6 +2957,8 @@ implementation
             writeDynTag(relsztags[relocs_use_addend],dynrelocsec.Size);
             writeDynTag(relenttags[relocs_use_addend],dynrelocsec.shentsize);
           end;
+        if (relative_reloc_count>0) then
+          writeDynTag(relcnttags[relocs_use_addend],relative_reloc_count);
         writeDynTag(DT_NULL,0);
       end;