Emit DWARF expressions from dwarf-to-dwarf-assembler.py

Message ID 20260522171856.3378166-1-tromey@adacore.com
State New
Headers
Series Emit DWARF expressions from dwarf-to-dwarf-assembler.py |

Checks

Context Check Description
linaro-tcwg-bot/tcwg_gdb_build--master-aarch64 success Build passed
linaro-tcwg-bot/tcwg_gdb_build--master-arm success Build passed
linaro-tcwg-bot/tcwg_gdb_check--master-aarch64 success Test passed
linaro-tcwg-bot/tcwg_gdb_check--master-arm success Test passed

Commit Message

Tom Tromey May 22, 2026, 5:18 p.m. UTC
  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.
---
 gdb/contrib/dwarf-to-dwarf-assembler.py | 25 ++++++++++++++++++-------
 1 file changed, 18 insertions(+), 7 deletions(-)


base-commit: 1678d7d3d2e4cf83cda5a96334a0326573ad0f7c
  

Comments

Tom Tromey June 5, 2026, 9:11 p.m. UTC | #1
>>>>> "Tom" == Tom Tromey <tromey@adacore.com> writes:

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

I'm going to check this in.

Tom
  

Patch

diff --git a/gdb/contrib/dwarf-to-dwarf-assembler.py b/gdb/contrib/dwarf-to-dwarf-assembler.py
index 4832c6c8cb1..5f990f79569 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: