Prechádzať zdrojové kódy

* ELF linker: fixed written values of STT_TLS symbols, they must be relative to PT_TLS segment address.
* Made name of dynamic interpreter variable, it is now set correctly for each target.
- Removed setting header flags for ARM. This functionality belongs to CPU-specific unit anyway, and probably must be implemented using object attributes in modern ABIs.

git-svn-id: trunk@23032 -

sergei 12 rokov pred
rodič
commit
a7e7d97da6
2 zmenil súbory, kde vykonal 24 pridanie a 31 odobranie
  1. 22 31
      compiler/ogelf.pas
  2. 2 0
      compiler/systems/t_linux.pas

+ 22 - 31
compiler/ogelf.pas

@@ -58,6 +58,7 @@ interface
          kind: TElfSymtabKind;
          fstrsec: TObjSection;
          symidx: longint;
+         tlsbase: aword;
          constructor create(aObjData:TObjData;aKind:TElfSymtabKind);reintroduce;
          procedure writeSymbol(objsym:TObjSymbol;nameidx:longword=0);
          procedure writeInternalSymbol(avalue:aword;astridx:longword;ainfo:byte;ashndx:word);
@@ -184,6 +185,7 @@ interface
          dynsymnames: Plongword;
          dynsymtable: TElfSymtab;
          interpobjsec: TObjSection;
+         FInterpreter: pshortstring;
          dynamicsec,
          hashobjsec: TElfObjSection;
          neededlist: TFPHashList;
@@ -239,6 +241,7 @@ interface
          procedure DataPos_ExeSection(const aname:string);override;
          function writeData:boolean;override;
          procedure GenerateLibraryImports(ImportLibraryList:TFPHashObjectList);override;
+         property interpreter:pshortstring read FInterpreter write FInterpreter;
        end;
 
      var
@@ -1159,10 +1162,10 @@ implementation
         else
           elfsym.st_name:=nameidx;
         elfsym.st_size:=objsym.size;
+        elfsym.st_value:=objsym.address;
         case objsym.bind of
           AB_LOCAL :
             begin
-              elfsym.st_value:=objsym.address;
               elfsym.st_info:=STB_LOCAL shl 4;
               inc(shinfo);
             end;
@@ -1175,19 +1178,13 @@ implementation
           AB_EXTERNAL :
             elfsym.st_info:=STB_GLOBAL shl 4;
           AB_WEAK_EXTERNAL :
-            begin
-              elfsym.st_info:=STB_WEAK shl 4;
-              elfsym.st_value:=objsym.address;
-            end;
+            elfsym.st_info:=STB_WEAK shl 4;
           AB_GLOBAL :
-            begin
-              elfsym.st_value:=objsym.address;
-              elfsym.st_info:=STB_GLOBAL shl 4;
-            end;
+            elfsym.st_info:=STB_GLOBAL shl 4;
+        else
+          InternalError(2012111801);
         end;
-        if (objsym.bind<>AB_EXTERNAL) {and
-           not(assigned(objsym.objsection) and
-           not(oso_data in objsym.objsection.secoptions))} then
+        if (objsym.bind<>AB_EXTERNAL) then
           begin
             case objsym.typ of
               AT_FUNCTION :
@@ -1198,6 +1195,7 @@ implementation
                 elfsym.st_info:=elfsym.st_info or STT_TLS;
               AT_GNU_IFUNC:
                 elfsym.st_info:=elfsym.st_info or STT_GNU_IFUNC;
+            { other types are implicitly mapped to STT_NOTYPE }
             end;
           end;
         if objsym.bind<>AB_COMMON then
@@ -1206,7 +1204,9 @@ implementation
               begin
                 if assigned(objsym.objsection) and assigned(objsym.objsection.ExeSection) then
                   begin
-                    if (oso_plt in objsym.objsection.SecOptions) then
+                    if (objsym.typ=AT_TLS) then
+                      elfsym.st_value:=elfsym.st_value-tlsbase
+                    else if (oso_plt in objsym.objsection.SecOptions) then
                       elfsym.st_value:=0
                     else
                       elfsym.st_shndx:=TElfExeSection(objsym.objsection.ExeSection).secshidx;
@@ -1302,9 +1302,7 @@ implementation
       begin
         with data do
          begin
-           { filename entry }
-           symtabsect.writeInternalSymbol(0,1,STT_FILE,SHN_ABS);
-           { section }
+           { section symbols }
            ObjSectionList.ForEachCall(@section_write_symbol,nil);
            { First the Local Symbols, this is required by ELF. The localsyms
              count stored in shinfo is used to skip the local symbols
@@ -1414,8 +1412,9 @@ implementation
            if (target_info.system in systems_linux) and
               not(cs_executable_stack in current_settings.moduleswitches) then
              TElfObjSection.create_ext(data,'.note.GNU-stack',SHT_PROGBITS,0,1,0);
-           { insert filename as first in strtab }
+           { symbol for filename }
            symtabsect.fstrsec.writestr(ExtractFileName(current_module.mainsource));
+           symtabsect.writeInternalSymbol(0,1,STT_FILE,SHN_ABS);
            { calc amount of sections we have }
            nsections:=1;
            { also create the index in the section header table }
@@ -1453,10 +1452,6 @@ implementation
            header.e_ident[EI_VERSION]:=1;
            header.e_type:=ET_REL;
            header.e_machine:=ELFMACHINE;
-{$ifdef arm}
-           if (current_settings.fputype=fpu_soft) then
-             header.e_flags:=$600;
-{$endif arm}
            header.e_version:=1;
            header.e_shoff:=shoffset;
            header.e_shstrndx:=shstrtabsect.index;
@@ -2117,6 +2112,7 @@ implementation
         dynreloclist.Free;
         if assigned(dynsymnames) then
           FreeMem(dynsymnames);
+        stringdispose(FInterpreter);
         inherited Destroy;
       end;
 
@@ -2159,10 +2155,6 @@ implementation
         else
           header.e_type:=ET_EXEC;
         header.e_machine:=ELFMACHINE;
-{$ifdef arm}
-        if (current_settings.fputype=fpu_soft) then
-          header.e_flags:=$600;
-{$endif arm}
         header.e_version:=1;
         header.e_phoff:=sizeof(TElfHeader);
         header.e_shoff:=shoffset;
@@ -2232,6 +2224,8 @@ implementation
         sec: TElfExeSection;
         exesym: TExeSymbol;
       begin
+        if assigned(tlsseg) then
+          symtab.tlsbase:=tlsseg.MemPos;
         for i:=0 to ExeSectionList.Count-1 do
           begin
             sec:=TElfExeSection(ExeSectionList[i]);
@@ -2680,6 +2674,8 @@ implementation
               begin
                 dynrelocsec.size:=0;
                 { write actual .dynsym content (needs valid symbol addresses) }
+                if assigned(tlsseg) then
+                  dynsymtable.tlsbase:=tlsseg.MemPos;
                 dynsymtable.size:=sizeof(TElfsymbol);
                 for i:=0 to dynsymlist.count-1 do
                   dynsymtable.writeSymbol(TExeSymbol(dynsymlist[i]).objsymbol,dynsymnames[i]);
@@ -2828,12 +2824,7 @@ implementation
         if not IsSharedLibrary then
           begin
             interpobjsec:=internalObjData.createsection('.interp',1,[oso_data,oso_load,oso_keep]);
-            { TODO: supply target-specific default }
-{$ifdef x86_64}
-            interpobjsec.writestr('/lib64/ld-linux-x86-64.so.2');
-{$else}
-            interpobjsec.writestr('/lib/ld-linux.so.2');
-{$endif x86_64}
+            interpobjsec.writestr(interpreter^);
           end;
 
         hashobjsec:=TElfObjSection.create_ext(internalObjData,'.hash',

+ 2 - 0
compiler/systems/t_linux.pas

@@ -1216,6 +1216,8 @@ begin
       AddSharedLibrary('c');
     end;
 
+  TElfExeOutput(exeoutput).interpreter:=stringdup(dynlinker);
+
   { add objectfiles, start with prt0 always }
   if not (target_info.system in systems_internal_sysinit) and (prtobj<>'') then
     LinkScript.Concat('READOBJECT '+ maybequoted(FindObjectFile(prtobj,'',false)));