Browse Source

* Reworked writing ELF symbols into a separate class, TElfSymtab, which is also suitable for creating symbol tables in executable and dynamic ELF files.
* Do not write ELF symbols for internal sections (symbol/string table, relocation sections and alike).

git-svn-id: trunk@21592 -

sergei 13 years ago
parent
commit
85f6062e05
1 changed files with 129 additions and 100 deletions
  1. 129 100
      compiler/ogelf.pas

+ 129 - 100
compiler/ogelf.pas

@@ -50,6 +50,18 @@ interface
           constructor create_ext(aobjdata:TObjData;const Aname:string;Ashtype,Ashflags,Ashlink,Ashinfo:longint;Aalign:shortint;Aentsize:longint);
           constructor create_ext(aobjdata:TObjData;const Aname:string;Ashtype,Ashflags,Ashlink,Ashinfo:longint;Aalign:shortint;Aentsize:longint);
        end;
        end;
 
 
+       TElfSymtabKind = (esk_obj,esk_exe,esk_dyn);
+
+       TElfSymtab = class(TElfObjSection)
+       public
+         kind: TElfSymtabKind;
+         fstrsec: TObjSection;
+         symidx: longint;
+         constructor create(aObjData:TObjData;aKind:TElfSymtabKind);reintroduce;
+         procedure writeSymbol(objsym:TObjSymbol);
+         procedure writeInternalSymbol(astridx:longint;ainfo:byte;ashndx:word);
+       end;
+
        TElfObjData = class(TObjData)
        TElfObjData = class(TObjData)
        public
        public
          constructor create(const n:string);override;
          constructor create(const n:string);override;
@@ -60,21 +72,12 @@ interface
 
 
        TElfObjectOutput = class(tObjOutput)
        TElfObjectOutput = class(tObjOutput)
        private
        private
-         symtabsect,
-         strtabsect,
+         symtabsect: TElfSymtab;
          shstrtabsect: TElfObjSection;
          shstrtabsect: TElfObjSection;
-         {gotpcsect,
-         gotoffsect,
-         goTSect,
-         plTSect,
-         symsect   : TElfObjSection;}
-         symidx,
-         localsyms : longint;
          procedure createrelocsection(s:TElfObjSection;data:TObjData);
          procedure createrelocsection(s:TElfObjSection;data:TObjData);
          procedure createshstrtab(data:TObjData);
          procedure createshstrtab(data:TObjData);
          procedure createsymtab(data: TObjData);
          procedure createsymtab(data: TObjData);
          procedure writesectionheader(s:TElfObjSection);
          procedure writesectionheader(s:TElfObjSection);
-         procedure write_internal_symbol(astridx:longint;ainfo:byte;ashndx:word);
          procedure section_write_symbol(p:TObject;arg:pointer);
          procedure section_write_symbol(p:TObject;arg:pointer);
          procedure section_write_sh_string(p:TObject;arg:pointer);
          procedure section_write_sh_string(p:TObject;arg:pointer);
          procedure section_count_sections(p:TObject;arg:pointer);
          procedure section_count_sections(p:TObject;arg:pointer);
@@ -928,6 +931,108 @@ implementation
       end;
       end;
 
 
 
 
+{****************************************************************************
+                            TElfSymtab
+****************************************************************************}
+
+    const
+      symsecnames: array[boolean] of string[8] = ('.symtab','.dynsym');
+      strsecnames: array[boolean] of string[8] = ('.strtab','.dynstr');
+      symsectypes: array[boolean] of longint   = (SHT_SYMTAB,SHT_DYNSYM);
+      symsecattrs: array[boolean] of longint   = (0,SHF_ALLOC);
+
+
+    constructor TElfSymtab.create(aObjData:TObjData;aKind:TElfSymtabKind);
+      var
+        dyn:boolean;
+      begin
+        dyn:=(aKind=esk_dyn);
+        create_ext(aObjData,symsecnames[dyn],symsectypes[dyn],symsecattrs[dyn],0,0,sizeof(pint),sizeof(TElfSymbol));
+        fstrsec:=TElfObjSection.create_ext(aObjData,strsecnames[dyn],SHT_STRTAB,symsecattrs[dyn],0,0,1,0);
+        fstrsec.writestr(#0);
+        writezeros(sizeof(TElfSymbol));
+        symidx:=1;
+        shinfo:=1;
+        kind:=aKind;
+      end;
+
+    procedure TElfSymtab.writeInternalSymbol(astridx:longint;ainfo:byte;ashndx:word);
+      var
+        elfsym:TElfSymbol;
+      begin
+        fillchar(elfsym,sizeof(elfsym),0);
+        elfsym.st_name:=astridx;
+        elfsym.st_info:=ainfo;
+        elfsym.st_shndx:=ashndx;
+        inc(symidx);
+        inc(shinfo);
+        MaybeSwapElfSymbol(elfsym);
+        write(elfsym,sizeof(elfsym));
+      end;
+
+    procedure TElfSymtab.writeSymbol(objsym:TObjSymbol);
+      var
+        elfsym:TElfSymbol;
+      begin
+        fillchar(elfsym,sizeof(elfsym),0);
+        { symbolname, write the #0 separate to overcome 255+1 char not possible }
+        elfsym.st_name:=fstrsec.writestr(objsym.name);
+        fstrsec.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(shinfo);
+            end;
+          AB_COMMON :
+            begin
+              elfsym.st_value:=$10;            { ?? should not be hardcoded }
+              elfsym.st_info:=STB_GLOBAL shl 4;
+              elfsym.st_shndx:=SHN_COMMON;
+            end;
+          AB_EXTERNAL :
+            elfsym.st_info:=STB_GLOBAL shl 4;
+          AB_WEAK_EXTERNAL :
+            elfsym.st_info:=STB_WEAK 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
+          begin
+            if kind<>esk_obj then
+              begin
+                { TODO }
+              end
+            else
+              begin
+                if assigned(objsym.objsection) then
+                  elfsym.st_shndx:=TElfObjSection(objsym.objsection).secshidx
+                else
+                  elfsym.st_shndx:=SHN_UNDEF;
+                objsym.symidx:=symidx;
+              end;
+          end;
+        inc(symidx);
+        MaybeSwapElfSymbol(elfsym);
+        write(elfsym,sizeof(TElfSymbol));
+      end;
+
 {****************************************************************************
 {****************************************************************************
                             TElfObjectOutput
                             TElfObjectOutput
 ****************************************************************************}
 ****************************************************************************}
@@ -1080,100 +1185,26 @@ implementation
       end;
       end;
 
 
 
 
-    procedure TElfObjectOutput.write_internal_symbol(astridx:longint;ainfo:byte;ashndx:word);
-      var
-        elfsym : telfsymbol;
-      begin
-        fillchar(elfsym,sizeof(elfsym),0);
-        elfsym.st_name:=astridx;
-        elfsym.st_info:=ainfo;
-        elfsym.st_shndx:=ashndx;
-        inc(symidx);
-        inc(localsyms);
-        MaybeSwapElfSymbol(elfsym);
-        symtabsect.write(elfsym,sizeof(elfsym));
-      end;
-
-
     procedure TElfObjectOutput.section_write_symbol(p:TObject;arg:pointer);
     procedure TElfObjectOutput.section_write_symbol(p:TObject;arg:pointer);
       begin
       begin
-        TObjSection(p).secsymidx:=symidx;
-        write_internal_symbol(0,STT_SECTION,TElfObjSection(p).secshidx);
+        { Must not write symbols for internal sections like .symtab }
+        { TODO: maybe use inclusive list of section types instead }
+        if (TElfObjSection(p).shtype in [SHT_SYMTAB,SHT_STRTAB,SHT_REL,SHT_RELA]) then
+          exit;
+        TObjSection(p).secsymidx:=symtabsect.symidx;
+        symtabsect.writeInternalSymbol(0,STT_SECTION,TElfObjSection(p).secshidx);
       end;
       end;
 
 
 
 
     procedure TElfObjectOutput.createsymtab(data: TObjData);
     procedure TElfObjectOutput.createsymtab(data: TObjData);
-
-        procedure WriteSym(objsym:TObjSymbol);
-        var
-          elfsym : telfsymbol;
-        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_WEAK_EXTERNAL :
-              elfsym.st_info:=STB_WEAK 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);
-          MaybeSwapElfSymbol(elfsym);
-          symtabsect.write(elfsym,sizeof(elfsym));
-        end;
-
       var
       var
         i      : longint;
         i      : longint;
         objsym : TObjSymbol;
         objsym : TObjSymbol;
       begin
       begin
         with data do
         with data do
          begin
          begin
-           symidx:=0;
-           localsyms:=0;
-           { empty entry }
-           write_internal_symbol(0,0,0);
            { filename entry }
            { filename entry }
-           write_internal_symbol(1,STT_FILE,SHN_ABS);
+           symtabsect.writeInternalSymbol(1,STT_FILE,SHN_ABS);
            { section }
            { section }
            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
@@ -1183,18 +1214,17 @@ implementation
              begin
              begin
                objsym:=TObjSymbol(ObjSymbolList[i]);
                objsym:=TObjSymbol(ObjSymbolList[i]);
                if (objsym.bind=AB_LOCAL) and (objsym.typ<>AT_LABEL) then
                if (objsym.bind=AB_LOCAL) and (objsym.typ<>AT_LABEL) then
-                 WriteSym(objsym);
+                 symtabsect.WriteSymbol(objsym);
              end;
              end;
            { Global Symbols }
            { Global Symbols }
            for i:=0 to ObjSymbolList.Count-1 do
            for i:=0 to ObjSymbolList.Count-1 do
              begin
              begin
                objsym:=TObjSymbol(ObjSymbolList[i]);
                objsym:=TObjSymbol(ObjSymbolList[i]);
                if (objsym.bind<>AB_LOCAL) then
                if (objsym.bind<>AB_LOCAL) then
-                 WriteSym(objsym);
+                 symtabsect.WriteSymbol(objsym);
              end;
              end;
            { update the .symtab section header }
            { update the .symtab section header }
-           symtabsect.shlink:=strtabsect.secshidx;
-           symtabsect.shinfo:=localsyms;
+           symtabsect.shlink:=TElfObjSection(symtabsect.fstrsec).secshidx;
          end;
          end;
       end;
       end;
 
 
@@ -1265,16 +1295,15 @@ implementation
         with data do
         with data do
          begin
          begin
            { default sections }
            { default sections }
-           symtabsect:=TElfObjSection.create_ext(data,'.symtab',SHT_SYMTAB,0,0,0,4,sizeof(telfsymbol));
-           strtabsect:=TElfObjSection.create_ext(data,'.strtab',SHT_STRTAB,0,0,0,1,0);
+           symtabsect:=TElfSymtab.create(data,esk_obj);
            shstrtabsect:=TElfObjSection.create_ext(data,'.shstrtab',SHT_STRTAB,0,0,0,1,0);
            shstrtabsect:=TElfObjSection.create_ext(data,'.shstrtab',SHT_STRTAB,0,0,0,1,0);
            { "no executable stack" marker for Linux }
            { "no executable stack" marker for Linux }
            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,0,0,1,0);
              TElfObjSection.create_ext(data,'.note.GNU-stack',SHT_PROGBITS,0,0,0,1,0);
-           { insert the empty and filename as first in strtab }
-           strtabsect.writestr(#0);
-           strtabsect.writestr(ExtractFileName(current_module.mainsource)+#0);
+           { insert filename as first in strtab }
+           symtabsect.fstrsec.writestr(ExtractFileName(current_module.mainsource));
+           symtabsect.fstrsec.writestr(#0);
            { 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 }