[binutils-gdb] [gdb/contrib] Fix KeyError in dwarf-to-dwarf-assembler.py

Tom de Vries via Gdb-cvs <[email protected]> Wed, 10 Jun 2026 07:54:30 +0000 (GMT)
Newsgroups gmane.comp.gdb.cvs
Message-ID <[email protected]>
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=04e04460078274b4011b5cb892e162ff61083fcb

commit 04e04460078274b4011b5cb892e162ff61083fcb
Author: Tom de Vries <[email protected]>
Date:   Wed Jun 10 09:54:22 2026 +0200

    [gdb/contrib] Fix KeyError in dwarf-to-dwarf-assembler.py
    
    Executable outputs/gdb.threads/stepi-over-clone/stepi-over-clone contains the
    following DWARF (using readelf -w):
    ...
        <31c5>   DW_AT_const_value : 8 byte block: ff ff ff ff ff ff ff ff
    ...
    or more explicit using llvm-dwarfdump -v:
    ...
                    DW_AT_const_value [DW_FORM_block1] \
                      (<0x08> ff ff ff ff ff ff ff ff )
    ...
    
    Before commit 18ad8c1a54d ("Emit DWARF expressions from
    dwarf-to-dwarf-assembler.py"), the dwarf-to-dwarf-assembler.py script
    generated:
    ...
    DW_AT_const_value { MANUAL: Fill expr list } SPECIAL_expr
    ...
    for this.
    
    But since the commit, we run into a KeyError.
    
    The problem is that we're trying to interpret some random data as a DWARF
    expression.
    
    Fix this by special-casing DW_AT_const_value, and generating instead:
    ...
    DW_AT_const_value "\xff\xff\xff\xff\xff\xff\xff\xff" DW_FORM_block1
    ...
    which mimics the style I found in gdb.dwarf2/info-locals-optimized-out.exp:
    ...
                    DW_TAG_variable {
                        DW_AT_name const_bytes
                        DW_AT_type :$int_type_label
                        DW_AT_const_value "\x01\x01\x01\x01" DW_FORM_block1
                    }
    ...
    
    Likewise for DW_AT_discr_list.
    
    Another case for which the KeyError triggers, is DWARF from
    outputs/gdb.ada/array_of_variant/p-minimal:
    ...
     <2><14a4>: Abbrev Number: 20 (DW_TAG_structure_type)
        <14a5>   DW_AT_name        : p__payload_t
        <14a9>   DW_AT_byte_size   : 18 byte block: \
                                     fd 63 14 0 0 97 94 1 99 45 0 0 0 23 7 9 fc 1a \
                                     (DW_OP_GNU_variable_value: <0x1463>; \
                                      DW_OP_push_object_address; \
                                      DW_OP_deref_size: 1; \
                                      DW_OP_call4: <0x1421>; \
                                      DW_OP_plus_uconst: 7; \
                                      DW_OP_const1s: -4; DW_OP_and)
    ...
    because the pyelftools version that I'm using doesn't support
    DW_OP_GNU_variable_value yet (supported starting v0.33).
    
    Fix this by catching the KeyError, and falling back to the string case:
    ...
      DW_AT_byte_size \
      "\xfd\x63\x14\x00\x00\x97\x94\x01\x99\x45\x00\x00\x00\x23\x07\x09\xfc\x1a" \
      DW_FORM_exprloc # Failed to print op as DWARF expression: 0xfd
    ...

Diff:
---
 gdb/contrib/dwarf-to-dwarf-assembler.py | 20 +++++++++++++++++---
 1 file changed, 17 insertions(+), 3 deletions(-)

diff --git a/gdb/contrib/dwarf-to-dwarf-assembler.py b/gdb/contrib/dwarf-to-dwarf-assembler.py
index 314a9e9587b..fa32bc4bbab 100755
--- a/gdb/contrib/dwarf-to-dwarf-assembler.py
+++ b/gdb/contrib/dwarf-to-dwarf-assembler.py
@@ -226,9 +226,23 @@ class DWARFAttribute:
         elif self.name == "DW_AT_encoding" and isinstance(self.value, int):
             s += "@" + ATE_NAME[self.value]
         elif self.form in EXPR_ATTRIBUTE_FORMS:
-            # This returns a complete description that is already
-            # indented.
-            return self._format_expr_value(s, indent_count)
+            postfix = ""
+            if self.name not in ["DW_AT_const_value", "DW_AT_discr_list"]:
+                # Try to print as a DWARF expression.
+                try:
+                    # This returns a complete description that is already
+                    # indented.
+                    return self._format_expr_value(s, indent_count)
+                except KeyError as e:
+                    # Fall through to basic printing.
+                    postfix = " # Failed to print op as DWARF expression: " + hex(
+                        int(str(e))
+                    )
+            # Print the data as a string in "\x01\x02\x03\x04" format.
+            result = ""
+            for op in self.value:
+                result += f"\\x{op:02x}"
+            return indent(s, indent_count) + '"' + result + '" ' + self.form + postfix
         else:
             s += self._format_value(offset_die_lookup)