[binutils-gdb] Emit DWARF expressions from dwarf-to-dwarf-assembler.py

Tom Tromey via Gdb-cvs <[email protected]> Fri, 5 Jun 2026 21:11:56 +0000 (GMT)
Newsgroups gmane.comp.gdb.cvs
Message-ID <[email protected]>
https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=18ad8c1a54d5d0e3fe3ff6c13f217e0dc840f991

commit 18ad8c1a54d5d0e3fe3ff6c13f217e0dc840f991
Author: Tom Tromey <[email protected]>
Date:   Fri May 22 11:17:17 2026 -0600

    Emit DWARF expressions from dwarf-to-dwarf-assembler.py
    
    This changes dwarf-to-dwarf-assembler.py to attempt to emit DWARF
    expressions.  It is not close to perfect, since it relies on the
    elftools formatting to some extent, but it does at least eliminate the
    need to do a separate "readelf" step to try to work on the expression
    by hand.

Diff:
---
 gdb/contrib/dwarf-to-dwarf-assembler.py | 25 ++++++++++++++++++-------
 1 file changed, 18 insertions(+), 7 deletions(-)

diff --git a/gdb/contrib/dwarf-to-dwarf-assembler.py b/gdb/contrib/dwarf-to-dwarf-assembler.py
index 58342274fb1..314a9e9587b 100755
--- a/gdb/contrib/dwarf-to-dwarf-assembler.py
+++ b/gdb/contrib/dwarf-to-dwarf-assembler.py
@@ -52,6 +52,7 @@ from elftools.construct.lib.container import ListContainer
 from elftools.dwarf.compileunit import CompileUnit as RawCompileUnit
 from elftools.dwarf.die import DIE as RawDIE
 from elftools.dwarf.die import AttributeValue
+from elftools.dwarf.dwarf_expr import DWARFExprParser
 from elftools.dwarf.enums import ENUM_DW_ATE, ENUM_DW_LANG
 from elftools.elf.elffile import ELFFile
 
@@ -118,19 +119,27 @@ class DWARFAttribute:
 
     def __init__(
         self,
+        cu,
         die_offset: int,
         name: str,
         value: str | bytes | int | bool,
         form=None,
     ):
+        self.cu = cu
         self.die_offset = die_offset
         self.name = name
         self.value = value
         self.form = form
 
-    def _format_expr_value(self) -> str:
-        self.form = "SPECIAL_expr"
-        return "{ MANUAL: Fill expr list }"
+    def _format_expr_value(self, intro, indent_count: int) -> str:
+        result = indent(intro, indent_count) + "{\n"
+        parser = DWARFExprParser(self.cu.structs)
+        for op in parser.parse_expr(self.value):
+            result += indent(f"{op.op_name} 0x{op.op:02x}", indent_count + 1)
+            if op.args:
+                result += f" {op.args}"
+            result += "\n"
+        return result + indent("} SPECIAL_expr", indent_count)
 
     def _needs_escaping(self, str_value: str) -> bool:
         charset = set(str_value)
@@ -151,9 +160,7 @@ class DWARFAttribute:
     def _format_value(
         self, offset_die_lookup: dict[int, "DWARFDIE"], indent_count: int = 0
     ) -> str:
-        if self.form in EXPR_ATTRIBUTE_FORMS:
-            return self._format_expr_value()
-        elif isinstance(self.value, bool):
+        if isinstance(self.value, bool):
             return str(int(self.value))
         elif isinstance(self.value, int):
             if self.form == "DW_FORM_ref4":
@@ -218,6 +225,10 @@ class DWARFAttribute:
                 s += "@" + LANG_NAME[self.value]
         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)
         else:
             s += self._format_value(offset_die_lookup)
 
@@ -491,7 +502,7 @@ class DWARFParser:
                 self.referenced_offsets.add(referenced_die.offset)
 
             processed_attrs[attr_name] = DWARFAttribute(
-                raw_die.offset, attr_name, actual_value, attr_value.form
+                die_cu, raw_die.offset, attr_name, actual_value, attr_value.form
             )
 
         if raw_die.tag == DWARFCompileUnit.compile_unit_tag: