diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp --- a/lldb/source/Expression/DWARFExpression.cpp +++ b/lldb/source/Expression/DWARFExpression.cpp @@ -858,29 +858,28 @@ 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 expr = - GetLocationExpression(func_load_addr, pc)) { + Target *target = exe_ctx->GetTargetPtr(); + if (llvm::Optional 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 @@ 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 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 --- /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 --- /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 --- /dev/null +++ b/lldb/test/API/functionalities/location-list-lookup/main.c @@ -0,0 +1,23 @@ +#include +#include + +// 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); }