Do not crash if CIE doesn't define CFA (#177)
authoremersion <contact@emersion.fr>
Sat, 20 Jan 2018 17:18:09 +0000 (18:18 +0100)
committerEli Bendersky <eliben@users.noreply.github.com>
Sat, 20 Jan 2018 17:18:09 +0000 (09:18 -0800)
elftools/dwarf/callframe.py
scripts/readelf.py
test/testfiles_for_readelf/empty-cie.o.elf [new file with mode: 0755]

index 127e2d875801a60fe8fa05b20c45401b530b3852..e64c745cae6ff09ed50a149d955d723980d0968b 100644 (file)
@@ -475,8 +475,11 @@ class CFIEntry(object):
             # line that serves as the base (first) line in the FDE's table.
             cie = self.cie
             cie_decoded_table = cie.get_decoded()
-            last_line_in_CIE = copy.copy(cie_decoded_table.table[-1])
-            cur_line = copy.copy(last_line_in_CIE)
+            if len(cie_decoded_table.table) > 0:
+                last_line_in_CIE = copy.copy(cie_decoded_table.table[-1])
+                cur_line = copy.copy(last_line_in_CIE)
+            else:
+                cur_line = dict(cfa=None)
             cur_line['pc'] = self['initial_location']
             reg_order = copy.copy(cie_decoded_table.reg_order)
 
@@ -569,8 +572,10 @@ class CFIEntry(object):
                 cur_line = line_stack.pop()
 
         # The current line is appended to the table after all instructions
-        # have ended, in any case (even if there were no instructions).
-        table.append(cur_line)
+        # have ended, if there were instructions.
+        if cur_line['cfa'] is not None or len(cur_line) > 2:
+            table.append(cur_line)
+
         return DecodedCallFrameTable(table=table, reg_order=reg_order)
 
 
@@ -669,7 +674,3 @@ _OPCODE_NAME_MAP = {}
 for name in list(iterkeys(globals())):
     if name.startswith('DW_CFA'):
         _OPCODE_NAME_MAP[globals()[name]] = name
-
-
-
-
index 397dfbdf0cb47b11a0999c4d1b6a9355a9d88bb1..4fec084fd94fd0cb1534e6ce71c5f716503a7de9 100755 (executable)
@@ -1171,13 +1171,17 @@ class ReadElf(object):
                 self._emitline('\n%08x ZERO terminator' % entry.offset)
                 continue
 
+            # Decode the table.
+            decoded_table = entry.get_decoded()
+            if len(decoded_table.table) == 0:
+                continue
 
             # Print the heading row for the decoded table
             self._emit('   LOC')
             self._emit('  ' if entry.structs.address_size == 4 else '          ')
             self._emit(' CFA      ')
 
-            # Decode the table and look at the registers it describes.
+            # Look at the registers the decoded table describes.
             # We build reg_order here to match readelf's order. In particular,
             # registers are sorted by their number, and the register matching
             # ra_regnum is always listed last with a special heading.
@@ -1201,7 +1205,12 @@ class ReadElf(object):
             for line in decoded_table.table:
                 self._emit(self._format_hex(
                     line['pc'], fullhex=True, lead0x=False))
-                self._emit(' %-9s' % describe_CFI_CFA_rule(line['cfa']))
+
+                if line['cfa'] is not None:
+                    s = describe_CFI_CFA_rule(line['cfa'])
+                else:
+                    s = 'u'
+                self._emit(' %-9s' % s)
 
                 for regnum in reg_order:
                     if regnum in line:
diff --git a/test/testfiles_for_readelf/empty-cie.o.elf b/test/testfiles_for_readelf/empty-cie.o.elf
new file mode 100755 (executable)
index 0000000..9780273
Binary files /dev/null and b/test/testfiles_for_readelf/empty-cie.o.elf differ