[Lldb-commits] [lldb] 6e56c49 - Decr pc when looking for DWARF loc list entry mid-stack
Jason Molenda via lldb-commits
lldb-commits at lists.llvm.org
Fri Apr 29 14:39:08 PDT 2022
Author: Jason Molenda
Date: 2022-04-29T14:34:06-07:00
New Revision: 6e56c4961a106b8fde69ffcf9f803fe0890722fa
URL: https://github.com/llvm/llvm-project/commit/6e56c4961a106b8fde69ffcf9f803fe0890722fa
DIFF: https://github.com/llvm/llvm-project/commit/6e56c4961a106b8fde69ffcf9f803fe0890722fa.diff
LOG: Decr pc when looking for DWARF loc list entry mid-stack
When looking for a variable location in a DWARF location list,
we search the list of ranges to find one that includes the pc.
With a function mid-stack, the "pc" is the return pc instead of
the call instruction, and in optimized code this can be another
function or a different basic block (with different variable
locations). Back up the "pc" value mid-stack to find the correct
location list entry.
Differential Revision: https://reviews.llvm.org/D124597
rdar://63903416
Added:
lldb/test/API/functionalities/location-list-lookup/Makefile
lldb/test/API/functionalities/location-list-lookup/TestLocationListLookup.py
lldb/test/API/functionalities/location-list-lookup/main.c
Modified:
lldb/source/Expression/DWARFExpression.cpp
Removed:
################################################################################
diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp
index 717cbe76450eb..1f11907dc64c4 100644
--- a/lldb/source/Expression/DWARFExpression.cpp
+++ b/lldb/source/Expression/DWARFExpression.cpp
@@ -858,29 +858,28 @@ bool DWARFExpression::Evaluate(ExecutionContext *exe_ctx,
ModuleSP module_sp = m_module_wp.lock();
if (IsLocationList()) {
- addr_t pc;
+ Address pc;
StackFrame *frame = nullptr;
- if (reg_ctx)
- pc = reg_ctx->GetPC();
- else {
+ if (!reg_ctx || !reg_ctx->GetPCForSymbolication(pc)) {
frame = exe_ctx->GetFramePtr();
if (!frame)
return false;
RegisterContextSP reg_ctx_sp = frame->GetRegisterContext();
if (!reg_ctx_sp)
return false;
- pc = reg_ctx_sp->GetPC();
+ reg_ctx_sp->GetPCForSymbolication(pc);
}
if (func_load_addr != LLDB_INVALID_ADDRESS) {
- if (pc == LLDB_INVALID_ADDRESS) {
+ if (!pc.IsValid()) {
if (error_ptr)
error_ptr->SetErrorString("Invalid PC in frame.");
return false;
}
- if (llvm::Optional<DataExtractor> expr =
- GetLocationExpression(func_load_addr, pc)) {
+ Target *target = exe_ctx->GetTargetPtr();
+ if (llvm::Optional<DataExtractor> expr = GetLocationExpression(
+ func_load_addr, pc.GetLoadAddress(target))) {
return DWARFExpression::Evaluate(
exe_ctx, reg_ctx, module_sp, *expr, m_dwarf_cu, m_reg_kind,
initial_value_ptr, object_address_ptr, result, error_ptr);
@@ -2862,7 +2861,7 @@ bool DWARFExpression::MatchesOperand(StackFrame &frame,
if (load_function_start == LLDB_INVALID_ADDRESS)
return false;
- addr_t pc = frame.GetFrameCodeAddress().GetLoadAddress(
+ addr_t pc = frame.GetFrameCodeAddressForSymbolication().GetLoadAddress(
frame.CalculateTarget().get());
if (llvm::Optional<DataExtractor> expr =
diff --git a/lldb/test/API/functionalities/location-list-lookup/Makefile b/lldb/test/API/functionalities/location-list-lookup/Makefile
new file mode 100644
index 0000000000000..78b0b11cb7484
--- /dev/null
+++ b/lldb/test/API/functionalities/location-list-lookup/Makefile
@@ -0,0 +1,3 @@
+C_SOURCES := main.c
+CFLAGS_EXTRAS := -O1
+include Makefile.rules
diff --git a/lldb/test/API/functionalities/location-list-lookup/TestLocationListLookup.py b/lldb/test/API/functionalities/location-list-lookup/TestLocationListLookup.py
new file mode 100644
index 0000000000000..2121610899b3e
--- /dev/null
+++ b/lldb/test/API/functionalities/location-list-lookup/TestLocationListLookup.py
@@ -0,0 +1,40 @@
+"""Test that lldb picks the correct DWARF location list entry with a return-pc out of bounds."""
+
+import lldb
+from lldbsuite.test.decorators import *
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test import lldbutil
+
+
+class LocationListLookupTestCase(TestBase):
+
+ mydir = TestBase.compute_mydir(__file__)
+
+ def setUp(self):
+ # Call super's setUp().
+ TestBase.setUp(self)
+
+ def test_loclist(self):
+ self.build()
+ exe = self.getBuildArtifact("a.out")
+
+ # Create a target by the debugger.
+ target = self.dbg.CreateTarget(exe)
+ self.assertTrue(target, VALID_TARGET)
+ self.dbg.SetAsync(False)
+
+ li = lldb.SBLaunchInfo(["a.out"])
+ error = lldb.SBError()
+ process = target.Launch(li, error)
+ self.assertTrue(process.IsValid())
+ self.assertTrue(process.is_stopped)
+
+ # Find `main` on the stack, then
+ # find `argv` local variable, then
+ # check that we can read the c-string in argv[0]
+ for f in process.GetSelectedThread().frames:
+ if f.GetDisplayFunctionName() == "main":
+ argv = f.GetValueForVariablePath("argv").GetChildAtIndex(0)
+ strm = lldb.SBStream()
+ argv.GetDescription(strm)
+ self.assertNotEqual(strm.GetData().find('a.out'), -1)
diff --git a/lldb/test/API/functionalities/location-list-lookup/main.c b/lldb/test/API/functionalities/location-list-lookup/main.c
new file mode 100644
index 0000000000000..852772ee52ca2
--- /dev/null
+++ b/lldb/test/API/functionalities/location-list-lookup/main.c
@@ -0,0 +1,23 @@
+#include <stdio.h>
+#include <stdlib.h>
+
+// The goal with this test is:
+// 1. Have main() followed by foo()
+// 2. Have the no-return call to abort() in main be the last instruction
+// 3. Have the next instruction be the start of foo()
+// 4. The debug info for argv uses a location list.
+// clang at -O1 on x86_64 or arm64 has debuginfo like
+// DW_AT_location (0x00000049:
+// [0x0000000100003f15, 0x0000000100003f25): DW_OP_reg4 RSI
+// [0x0000000100003f25, 0x0000000100003f5b): DW_OP_reg15 R15)
+
+void foo(int);
+int main(int argc, char **argv) {
+ char *file = argv[0];
+ char f0 = file[0];
+ printf("%c\n", f0);
+ foo(f0);
+ printf("%s %d\n", argv[0], argc);
+ abort(); /// argv is still be accessible here
+}
+void foo(int in) { printf("%d\n", in); }
More information about the lldb-commits
mailing list