Implemented ELFFile.get_section_by_name and changed readelf.py to use it
authoreliben <devnull@localhost>
Mon, 19 Sep 2011 10:10:57 +0000 (13:10 +0300)
committereliben <devnull@localhost>
Mon, 19 Sep 2011 10:10:57 +0000 (13:10 +0300)
elftools/elf/elffile.py
scripts/readelf.py
z.py

index 8195c7f895026be7cfbaa4d42783280a59d168d5..8704249088f4a28cc8f49c67957c463cabb030e8 100644 (file)
@@ -46,6 +46,7 @@ class ELFFile(object):
         self.e_ident_raw = self.stream.read(16)
         
         self._file_stringtable_section = self._get_file_stringtable()
+        self._section_name_map = None
     
     def num_sections(self):
         """ Number of sections in the file
@@ -59,6 +60,20 @@ class ELFFile(object):
         section_header = self._get_section_header(n)
         return self._make_section(section_header)
     
+    def get_section_by_name(self, name):
+        """ Get a section from the file, by name. Return None if no such 
+            section exists.
+        """
+        # The first time this method is called, construct a name to number
+        # mapping
+        #
+        if self._section_name_map is None:
+            self._section_name_map = {}
+            for i, sec in enumerate(self.iter_sections()):
+                self._section_name_map[sec.name] = i
+        secnum = self._section_name_map.get(name, None)
+        return None if secnum is None else self.get_section(secnum)
+    
     def iter_sections(self):
         """ Yield all the sections in the file
         """
index 44e15db71e80fe253eb94f36bda7be35018d662f..4554ab0988300c5bf43f6dddef65d83299f381ec 100755 (executable)
@@ -270,13 +270,12 @@ class ReadElf(object):
         """ Display a hex dump of a section. section_spec is either a section
             number or a name.
         """
-        secnum = self._section_num_from_spec(section_spec)
-        if secnum is None:
+        section = self._section_from_spec(section_spec)
+        if section is None:
             self._emitline("Section '%s' does not exist in the file!" % (
                 section_spec))
             return
 
-        section = self.elffile.get_section(secnum)
         self._emitline("\nHex dump of section '%s':" % section.name)
 
         addr = section['sh_addr']
@@ -314,15 +313,13 @@ class ReadElf(object):
         """ Display a strings dump of a section. section_spec is either a
             section number or a name.
         """
-        secnum = self._section_num_from_spec(section_spec)
-        if secnum is None:
+        section = self._section_from_spec(section_spec)
+        if section is None:
             self._emitline("Section '%s' does not exist in the file!" % (
                 section_spec))
             return
 
         printables = set(string.printable)
-
-        section = self.elffile.get_section(secnum)
         self._emitline("\nString dump of section '%s':" % section.name)
 
         found = False
@@ -376,18 +373,19 @@ class ReadElf(object):
             field = '%' + '0%sx' % fieldsize
         return s + field % addr
         
-    def _section_num_from_spec(self, spec):
-        """ Translate a section "spec" (either number or name) to its number.
+    def _section_from_spec(self, spec):
+        """ Retrieve a section given a "spec" (either number or name).
             Return None if no such section exists in the file.
         """
         try:
             num = int(spec)
-            return num if num < self.elffile.num_sections() else None
+            if num < self.elffile.num_sections():
+                return self.elffile.get_section(num) 
+            else:
+                return None
         except ValueError:
             # Not a number. Must be a name then
-            for nsec, section in enumerate(self.elffile.iter_sections()):
-                if section.name == spec:
-                    return nsec
+            return self.elffile.get_section_by_name(spec)
 
     def _emit(self, s=''):
         """ Emit an object to output
diff --git a/z.py b/z.py
index bddd6e0127a303260f412e17f94bbaac63cc3f69..8ef75d212c163d3bccbd339ffaa084714b223852 100644 (file)
--- a/z.py
+++ b/z.py
@@ -16,53 +16,22 @@ stream = open('tests/testfiles/z.elf', 'rb')
 efile = ELFFile(stream)
 
 print '===> %s sections!' % efile.num_sections() 
-print '===> %s segments!' % efile.num_segments()
 
-for sec in efile.iter_sections():
-    print type(sec), sec.name
-    if isinstance(sec, SymbolTableSection):
-        print '   linked string table:', sec.stringtable.name
+print efile.get_section_by_name('.debug_info').name
 
-for seg in efile.iter_segments():
-    print type(seg), seg['p_type'], seg['p_offset']
+#~ print '===> %s segments!' % efile.num_segments()
 
 for sec in efile.iter_sections():
+    print type(sec), sec.name
     if isinstance(sec, SymbolTableSection):
-        print 'symbol table "%s ~~~"' % sec.name
-        for sym in sec.iter_symbols():
-            print '%-26s %s %s' % (sym.name, sym['st_info']['type'], sym['st_info']['bind'])
-
-
-#~ print 'num', efile.num_sections()
-#~ sec = efile.get_section(39)
-#~ print sec.header
-#~ print sec.name
-#~ print sec['sh_type']
-#~ print map(ord, sec.data())
-
-#~ print sec.stream
-#~ print map(ord, efile._stringtable)
-
-#~ print efile.header
-#~ print dir(efile)
-#~ print efile['e_type']
-
-#~ shtable_offset = efile['e_shoff']
-#~ strtable_section_offset = shtable_offset + efile['e_shstrndx'] * efile['e_shentsize']
-
-#~ # get to the section header for the sh string table
-#~ print strtable_section_offset
-#~ stream.seek(strtable_section_offset)
-#~ sheader = es.Elf_Shdr.parse_stream(stream)
-#~ print sheader
-
-#~ # yay, looks correct!!
-#~ stream.seek(sheader.sh_offset)
-#~ buf = stream.read(sheader.sh_size)
-#~ for c in buf:
-    #~ sys.stdout.write('%02X' % ord(c))
-
+        print '   linked string table:', sec.stringtable.name
 
+#~ for seg in efile.iter_segments():
+    #~ print type(seg), seg['p_type'], seg['p_offset']
 
+#~ for sec in efile.iter_sections():
+    #~ if isinstance(sec, SymbolTableSection):
+        #~ print 'symbol table "%s ~~~"' % sec.name
+        #~ for sym in sec.iter_symbols():
+            #~ print '%-26s %s %s' % (sym.name, sym['st_info']['type'], sym['st_info']['bind'])
 
-#~ print es.Elf_Ehdr