[Lldb-commits] [lldb] [lldb] Add DWARFExpressionEntry and GetExpressionEntryAtAddress() to … (PR #144238)
via lldb-commits
lldb-commits at lists.llvm.org
Sat Jun 14 14:46:26 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-lldb
Author: Abdullah Mohammad Amin (UltimateForce21)
<details>
<summary>Changes</summary>
This patch introduces a new struct and helper API in `DWARFExpressionList` to expose
variable location metadata (base address, end address, and DWARFExpression pointer) for
a given PC address. It will be used in later patches to annotate disassembly instructions
with source-level variable locations.
## New struct
```
/// Represents one entry in a DWARFExpressionList, with its range and expr.
struct DWARFExpressionEntry {
lldb::addr_t base; // file‐address start of this location range
lldb::addr_t end; // file‐address end of this range (exclusive)
const DWARFExpression *expr; // the DWARF expression for this range
};
```
## New API
```
/// Retrieve the DWARFExpressionEntry covering a particular instruction.
///
/// \param func_load_addr
/// The load address of the start of the function containing this location list;
/// used to translate between file offsets and load addresses. If this is
/// LLDB_INVALID_ADDRESS, the stored CU base (m_func_file_addr) is used.
///
/// \param load_addr
/// The load address of the *current* PC (i.e., the instruction for which
/// we want its variable‐location entry). We first convert this back into
/// the function’s file‐address space to find the correct DWARF range.
///
/// \returns
/// On success, an entry whose `[base,end)` covers this PC; else an Error.
llvm::Expected<DWARFExpressionEntry>
GetExpressionEntryAtAddress(lldb::addr_t func_load_addr,
lldb::addr_t load_addr) const;
```
## Rationale
LLDB already provides:
```
const DWARFExpression *
GetExpressionAtAddress(lldb::addr_t func_load_addr,
lldb::addr_t load_addr) const;
```
However, this only returns the DWARF expression itself, without the file‐address start (base) and end (end) of the location range. Those bounds are crucial for:
1) Detecting range beginnings: render a var = <location> annotation exactly when a variable’s live‐range starts.
2) Detecting range continuation: optionally display a “|” on subsequent instructions in the same range.
3) Detecting state changes: know when a variable moves (e.g. from one register to another), becomes a constant, or goes out of scope.
These primitives form the foundation for the Rich Disassembler feature proposed for GSoC 25.
---
Full diff: https://github.com/llvm/llvm-project/pull/144238.diff
2 Files Affected:
- (modified) lldb/include/lldb/Expression/DWARFExpressionList.h (+12)
- (modified) lldb/source/Expression/DWARFExpressionList.cpp (+21)
``````````diff
diff --git a/lldb/include/lldb/Expression/DWARFExpressionList.h b/lldb/include/lldb/Expression/DWARFExpressionList.h
index d8f8ec247ed56..a329b37393018 100644
--- a/lldb/include/lldb/Expression/DWARFExpressionList.h
+++ b/lldb/include/lldb/Expression/DWARFExpressionList.h
@@ -59,6 +59,18 @@ class DWARFExpressionList {
lldb::addr_t GetFuncFileAddress() { return m_func_file_addr; }
+ /// Represents an entry in the DWARFExpressionList with all needed metadata
+ struct DWARFExpressionEntry {
+ lldb::addr_t base;
+ lldb::addr_t end;
+ const DWARFExpression *expr;
+ };
+
+ /// Returns the entry (base, end, data) for a given PC address
+ llvm::Expected<DWARFExpressionEntry>
+ GetExpressionEntryAtAddress(lldb::addr_t func_load_addr,
+ lldb::addr_t load_addr) const;
+
const DWARFExpression *GetExpressionAtAddress(lldb::addr_t func_load_addr,
lldb::addr_t load_addr) const;
diff --git a/lldb/source/Expression/DWARFExpressionList.cpp b/lldb/source/Expression/DWARFExpressionList.cpp
index 04592a1eb7ff4..b55bc7120c4af 100644
--- a/lldb/source/Expression/DWARFExpressionList.cpp
+++ b/lldb/source/Expression/DWARFExpressionList.cpp
@@ -53,6 +53,27 @@ bool DWARFExpressionList::ContainsAddress(lldb::addr_t func_load_addr,
return GetExpressionAtAddress(func_load_addr, addr) != nullptr;
}
+llvm::Expected<DWARFExpressionList::DWARFExpressionEntry>
+DWARFExpressionList::GetExpressionEntryAtAddress(lldb::addr_t func_load_addr,
+ lldb::addr_t load_addr) const {
+ if (const DWARFExpression *expr = GetAlwaysValidExpr()) {
+ return DWARFExpressionEntry{0, LLDB_INVALID_ADDRESS, expr};
+ }
+
+ if (func_load_addr == LLDB_INVALID_ADDRESS)
+ func_load_addr = m_func_file_addr;
+
+ addr_t addr = load_addr - func_load_addr + m_func_file_addr;
+ uint32_t index = m_exprs.FindEntryIndexThatContains(addr);
+ if (index == UINT32_MAX) {
+ return llvm::createStringError(llvm::inconvertibleErrorCode(),
+ "No DWARF expression found for address 0x%llx", addr);
+ }
+
+ const Entry &entry = *m_exprs.GetEntryAtIndex(index);
+ return DWARFExpressionEntry{entry.base, entry.GetRangeEnd(), &entry.data};
+}
+
const DWARFExpression *
DWARFExpressionList::GetExpressionAtAddress(lldb::addr_t func_load_addr,
lldb::addr_t load_addr) const {
``````````
</details>
https://github.com/llvm/llvm-project/pull/144238
More information about the lldb-commits
mailing list