displaying symtables kinda works
authorEli Bendersky <eliben@gmail.com>
Fri, 16 Sep 2011 11:52:54 +0000 (14:52 +0300)
committerEli Bendersky <eliben@gmail.com>
Fri, 16 Sep 2011 11:52:54 +0000 (14:52 +0300)
elftools/elf/descriptions.py
elftools/elf/enums.py
elftools/elf/structs.py
scripts/readelf.py [changed mode: 0644->0755]

index 688ee61c35288bac6270061c4360ce772a3145a8..23e789df577a610cb53e1b17551ea977f33f1040 100644 (file)
@@ -56,6 +56,18 @@ def describe_sh_flags(x):
         s += _DESCR_SH_FLAGS[flag] if (x & flag) else ''
     return s
 
+def describe_symbol_type(x):
+    return _DESCR_ST_INFO_TYPE.get(x, _unknown())
+
+def describe_symbol_bind(x):
+    return _DESCR_ST_INFO_BIND.get(x, _unknown())
+
+def describe_symbol_visibility(x):
+    return _DESCR_ST_VISIBILITY.get(x, _unknown())
+
+def describe_symbol_shndx(x):
+    return _DESCR_ST_SHNDX.get(x, '%3s' % x)
+
 
 #-------------------------------------------------------------------------------
 def _unknown():
@@ -178,3 +190,36 @@ _DESCR_SH_FLAGS = {
     SH_FLAGS.SHF_EXCLUDE: 'E',
 }
 
+_DESCR_ST_INFO_TYPE = dict(
+    STT_NOTYPE='NOTYPE',
+    STT_OBJECT='OBJECT',
+    STT_FUNC='FUNC',
+    STT_SECTION='SECTION',
+    STT_FILE='FILE',
+    STT_COMMON='COMMON',
+    STT_TLS='TLS',
+    STT_NUM='NUM',
+    STT_RELC='RELC',
+    STT_SRELC='SRELC',
+)
+
+_DESCR_ST_INFO_BIND = dict(
+    STB_LOCAL='LOCAL',
+    STB_GLOBAL='GLOBAL',
+    STB_WEAK='WEAK',
+)
+
+_DESCR_ST_VISIBILITY = dict(
+    STV_DEFAULT='DEFAULT',
+    STV_INTERNAL='INTERNAL',
+    STV_HIDDEN='HIDDEN',
+    STD_PROTECTED='PROTECTED',
+)
+
+_DESCR_ST_SHNDX = dict(
+    SHN_UNDEF='UND',
+    SHN_ABS='ABS',
+    SHN_COMMON='COM',
+)
+
+
index dadf5d4a5792fb598b6f5509743330f1377b0b90..49ee9cd6189d17e83cb02abe0401911e62305903 100644 (file)
@@ -6,6 +6,8 @@
 # Eli Bendersky (eliben@gmail.com)
 # This code is in the public domain
 #-------------------------------------------------------------------------------
+from ..construct import Pass
+
 
 # e_ident[EI_CLASS] in the ELF header
 ENUM_EI_CLASS = dict(
@@ -152,8 +154,27 @@ ENUM_ST_INFO_TYPE = dict(
     STT_COMMON=5,
     STT_TLS=6,
     STT_NUM=7,
+    STT_RELC=8,
+    STT_SRELC=9,
     STT_LOOS=10,
     STT_HIOS=12,
     STT_LOPROC=13,
     STT_HIPROC=15,
 )
+
+# visibility from st_other
+ENUM_ST_VISIBILITY = dict(
+    STV_DEFAULT=0,
+    STV_INTERNAL=1,
+    STV_HIDDEN=2,
+    STV_PROTECTED=3,
+)
+
+# st_shndx
+ENUM_ST_SHNDX = dict(
+    SHN_UNDEF=0,
+    SHN_ABS=0xfff1,
+    SHN_COMMON=0xfff2,
+    _default_=Pass,
+)
+
index 58088202d69bd3ccc3eee96ae4558a9f789d9a07..ae084d28ddf7f76e93fedc777a6b072b8171fe34 100644 (file)
@@ -132,26 +132,31 @@ class ELFStructs(object):
         )
     
     def _create_sym(self):
-        # Note that st_info is hierarchical. To access the type, use
+        # st_info is hierarchical. To access the type, use
         # container['st_info']['type']
         st_info_struct = BitStruct('st_info',
             Enum(BitField('bind', 4), **ENUM_ST_INFO_BIND),
             Enum(BitField('type', 4), **ENUM_ST_INFO_TYPE))
+        # st_other is hierarchical. To access the visibility,
+        # use container['st_other']['visibility']
+        st_other_struct = BitStruct('st_other',
+            Padding(5),
+            Enum(BitField('visibility', 3), **ENUM_ST_VISIBILITY))
         if self.elfclass == 32:
             self.Elf_Sym = Struct('Elf_Sym',
                 self.Elf_word('st_name'),
                 self.Elf_addr('st_value'),
                 self.Elf_word('st_size'),
                 st_info_struct,
-                self.Elf_byte('st_other'),
-                self.Elf_half('st_shndx'),
+                st_other_struct,
+                Enum(self.Elf_half('st_shndx'), **ENUM_ST_SHNDX),
             )
         else:
             self.Elf_Sym = Struct('Elf_Sym',
                 self.Elf_word('st_name'),
                 st_info_struct,
-                self.Elf_byte('st_other'),
-                self.Elf_half('st_shndx'),
+                st_other_struct,
+                Enum(self.Elf_half('st_shndx'), **ENUM_ST_SHNDX),
                 self.Elf_addr('st_value'),
                 self.Elf_xword('st_size'),
             )
old mode 100644 (file)
new mode 100755 (executable)
index ede8738..34b4b93
@@ -1,3 +1,4 @@
+#!/usr/bin/env python
 #-------------------------------------------------------------------------------
 # readelf.py
 #
@@ -20,11 +21,14 @@ except ImportError:
 from elftools.common.exceptions import ELFError
 from elftools.elf.elffile import ELFFile
 from elftools.elf.segments import InterpSegment
+from elftools.elf.sections import SymbolTableSection
 from elftools.elf.descriptions import (
     describe_ei_class, describe_ei_data, describe_ei_version,
     describe_ei_osabi, describe_e_type, describe_e_machine,
     describe_e_version_numeric, describe_p_type, describe_p_flags,
     describe_sh_type, describe_sh_flags,
+    describe_symbol_type, describe_symbol_bind, describe_symbol_visibility,
+    describe_symbol_shndx,
     )
 
 
@@ -218,6 +222,37 @@ class ReadElf(object):
         self._emitline('  I (info), L (link order), G (group), x (unknown)')
         self._emitline('  O (extra OS processing required) o (OS specific), p (processor specific)')
 
+    def display_symbol_tables(self):
+        """ Display the symbol tables contained in the file
+        """
+        for section in self.elffile.iter_sections():
+            if not isinstance(section, SymbolTableSection):
+                continue
+
+            if section['sh_entsize'] == 0:
+                self._emitline("\nSymbol table '%s' has a sh_entsize of zero!" % (
+                    section.name))
+                continue
+
+            self._emitline("\nSymbol table '%s' contains %s entries:" % (
+                section.name, section.num_symbols()))
+
+            if self.elffile.elfclass == 32:
+                self._emitline('   Num:    Value  Size Type    Bind   Vis      Ndx Name')
+            else: # 64
+                self._emitline('   Num:    Value          Size Type    Bind   Vis      Ndx Name')
+
+            for nsym, symbol in enumerate(section.iter_symbols()):
+                self._emitline('%6d: %s %5d %-7s %-6s %-7s %4s %s' % (
+                    nsym,
+                    self._format_hex(symbol['st_value'], fullhex=True, lead0x=False),
+                    symbol['st_size'],
+                    describe_symbol_type(symbol['st_info']['type']),
+                    describe_symbol_bind(symbol['st_info']['bind']),
+                    describe_symbol_visibility(symbol['st_other']['visibility']),
+                    describe_symbol_shndx(symbol['st_shndx']),
+                    symbol.name))
+        
     def _format_hex(self, addr, fieldsize=None, fullhex=False, lead0x=True):
         """ Format an address into a hexadecimal string.
 
@@ -261,10 +296,10 @@ def main():
     with open(args[0], 'rb') as file:
         try:
             readelf = ReadElf(file, sys.stdout)
-            readelf.display_file_header()
-            print '----'
+            #readelf.display_file_header()
             #readelf.display_program_headers()
-            readelf.display_section_headers()
+            #readelf.display_section_headers()
+            readelf.display_symbol_tables()
         except ELFError as ex:
             sys.stderr.write('ELF read error: %s\n' % ex)
             sys.exit(1)