Przeglądaj źródła

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

+ 2 - 0
compiler/systems/t_linux.pas

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