zequanwu created this revision.
Herald added subscribers: hiraditya, mgorny.
Herald added a reviewer: shafik.
Herald added a project: All.
zequanwu requested review of this revision.
Herald added projects: LLDB, LLVM.
Herald added subscribers: llvm-commits, lldb-commits.
Repository:
rG LLVM Github Monorepo
https://reviews.llvm.org/D125509
Files:
lldb/include/lldb/Expression/DWARFExpression.h
lldb/include/lldb/Expression/DWARFExpressionList.h
lldb/include/lldb/Symbol/Function.h
lldb/include/lldb/Symbol/Variable.h
lldb/include/lldb/Target/StackFrame.h
lldb/include/lldb/lldb-forward.h
lldb/source/Core/ValueObjectVariable.cpp
lldb/source/Expression/CMakeLists.txt
lldb/source/Expression/DWARFExpression.cpp
lldb/source/Expression/DWARFExpressionList.cpp
lldb/source/Expression/Materializer.cpp
lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h
lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp
lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
lldb/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp
lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
lldb/source/Symbol/Function.cpp
lldb/source/Symbol/Variable.cpp
lldb/source/Target/RegisterContextUnwind.cpp
lldb/source/Target/StackFrame.cpp
lldb/test/Shell/SymbolFile/DWARF/x86/debug_loc.s
lldb/test/Shell/SymbolFile/DWARF/x86/dwp.s
llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp
llvm/utils/gn/secondary/lldb/source/Expression/BUILD.gn
Index: llvm/utils/gn/secondary/lldb/source/Expression/BUILD.gn
===================================================================
--- llvm/utils/gn/secondary/lldb/source/Expression/BUILD.gn
+++ llvm/utils/gn/secondary/lldb/source/Expression/BUILD.gn
@@ -23,6 +23,7 @@
include_dirs = [ ".." ]
sources = [
"DWARFExpression.cpp",
+ "DWARFExpressionList.cpp",
"DiagnosticManager.cpp",
"Expression.cpp",
"ExpressionVariable.cpp",
Index: llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp
===================================================================
--- llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp
+++ llvm/lib/DebugInfo/DWARF/DWARFDebugLoc.cpp
@@ -177,8 +177,8 @@
return visitLocationList(&Offset, [&](const DWARFLocationEntry &E) {
Expected<Optional<DWARFLocationExpression>> Loc = Interp.Interpret(E);
if (!Loc)
- return Callback(Loc.takeError());
- if (*Loc)
+ consumeError(Loc.takeError());
+ else if (*Loc)
return Callback(**Loc);
return true;
});
Index: lldb/test/Shell/SymbolFile/DWARF/x86/dwp.s
===================================================================
--- lldb/test/Shell/SymbolFile/DWARF/x86/dwp.s
+++ lldb/test/Shell/SymbolFile/DWARF/x86/dwp.s
@@ -19,29 +19,29 @@
# SYMBOLS-NEXT: Variable{{.*}}, name = "A", {{.*}}, location = DW_OP_GNU_addr_index 0x0
# SYMBOLS-NEXT: Function{{.*}}, demangled = F0
# SYMBOLS-NEXT: Block{{.*}}, ranges = [0x00000000-0x00000001)
-# SYMBOLS-NEXT: Variable{{.*}}, name = "x", {{.*}}, location =
-# SYMBOLS-NEXT: DW_LLE_startx_length (0x0000000000000001, 0x0000000000000001): DW_OP_reg0 RAX
+# SYMBOLS-NEXT: Variable{{.*}}, name = "x", {{.*}}, location =
+# SYMBOLS-NEXT: [0x0000000000000000, 0x0000000000000001): DW_OP_reg0 RAX
# SYMBOLS-EMPTY:
# SYMBOLS-NEXT: CompileUnit{0x00000001}, language = "<not loaded>", file = '1.c'
# SYMBOLS-NEXT: Variable{{.*}}, name = "A", {{.*}}, location = DW_OP_GNU_addr_index 0x2
# SYMBOLS-NEXT: Function{{.*}}, demangled = F1
# SYMBOLS-NEXT: Block{{.*}}, ranges = [0x00000001-0x00000002)
-# SYMBOLS-NEXT: Variable{{.*}}, name = "x", {{.*}}, location =
-# SYMBOLS-NEXT: DW_LLE_startx_length (0x0000000000000003, 0x0000000000000001): DW_OP_reg1 RDX
+# SYMBOLS-NEXT: Variable{{.*}}, name = "x", {{.*}}, location =
+# SYMBOLS-NEXT: [0x0000000000000001, 0x0000000000000002): DW_OP_reg1 RDX
# SYMBOLS-EMPTY:
# SYMBOLS-NEXT: CompileUnit{0x00000002}, language = "<not loaded>", file = '2.c'
# SYMBOLS-NEXT: Variable{{.*}}, name = "A", {{.*}}, location = DW_OP_GNU_addr_index 0x4
# SYMBOLS-NEXT: Function{{.*}}, demangled = F2
# SYMBOLS-NEXT: Block{{.*}}, ranges = [0x00000002-0x00000003)
-# SYMBOLS-NEXT: Variable{{.*}}, name = "x", {{.*}}, location =
-# SYMBOLS-NEXT: DW_LLE_startx_length (0x0000000000000005, 0x0000000000000001): DW_OP_reg2 RCX
+# SYMBOLS-NEXT: Variable{{.*}}, name = "x", {{.*}}, location =
+# SYMBOLS-NEXT: [0x0000000000000002, 0x0000000000000003): DW_OP_reg2 RCX
# SYMBOLS-EMPTY:
# SYMBOLS-NEXT: CompileUnit{0x00000003}, language = "<not loaded>", file = '3.c'
# SYMBOLS-NEXT: Variable{{.*}}, name = "A", {{.*}}, location = DW_OP_GNU_addr_index 0x6
# SYMBOLS-NEXT: Function{{.*}}, demangled = F3
# SYMBOLS-NEXT: Block{{.*}}, ranges = [0x00000003-0x00000004)
-# SYMBOLS-NEXT: Variable{{.*}}, name = "x", {{.*}}, location =
-# SYMBOLS-NEXT: DW_LLE_startx_length (0x0000000000000007, 0x0000000000000001): DW_OP_reg3 RBX
+# SYMBOLS-NEXT: Variable{{.*}}, name = "x", {{.*}}, location =
+# SYMBOLS-NEXT: [0x0000000000000003, 0x0000000000000004): DW_OP_reg3 RBX
# SYMBOLS-EMPTY:
# SYMBOLS-NEXT: CompileUnit{0x00000004}, language = "<not loaded>", file = ''
# SYMBOLS-EMPTY:
@@ -116,7 +116,7 @@
.Lloc\I:
.byte 3 # DW_LLE_startx_length
.uleb128 \I*2+1
- .long 1
+ .long 1
.short 1 # Expression size
.byte 80+\I # super-register DW_OP_reg0+\I
.byte 0 # DW_LLE_end_of_list
Index: lldb/test/Shell/SymbolFile/DWARF/x86/debug_loc.s
===================================================================
--- lldb/test/Shell/SymbolFile/DWARF/x86/debug_loc.s
+++ lldb/test/Shell/SymbolFile/DWARF/x86/debug_loc.s
@@ -40,11 +40,11 @@
# CHECK-NEXT: [0x0000000000000000, 0x0000000000000001): DW_OP_reg5 RDI
# CHECK-NEXT: [0x0000000000000001, 0x0000000000000006): DW_OP_reg0 RAX
# CHECK: Variable{{.*}}, name = "x1", {{.*}}, scope = parameter
-# CHECK: Variable{{.*}}, name = "x2", {{.*}}, scope = parameter, location = 0x00000000: error: unexpected end of data
+# CHECK: Variable{{.*}}, name = "x2", {{.*}}, scope = parameter
# CHECK: Variable{{.*}}, name = "x3", {{.*}}, scope = parameter, location =
# CHECK-NEXT: [0x0000000000000002, 0x0000000000000003): DW_OP_reg1 RDX
-# LOCLISTS: Variable{{.*}}, name = "x4", {{.*}}, scope = parameter, location =
-# LOCLISTS-NEXT: DW_LLE_startx_length (0x000000000000dead, 0x0000000000000001): DW_OP_reg2 RCX
+# LOCLISTS: Variable{{.*}}, name = "x4", {{.*}}, scope = parameter
+# LOCLISTS-EMPTY:
.ifdef LOC
.macro OFFSET_PAIR lo hi
Index: lldb/source/Target/StackFrame.cpp
===================================================================
--- lldb/source/Target/StackFrame.cpp
+++ lldb/source/Target/StackFrame.cpp
@@ -1080,15 +1080,9 @@
m_flags.Set(GOT_FRAME_BASE);
ExecutionContext exe_ctx(shared_from_this());
Value expr_value;
- addr_t loclist_base_addr = LLDB_INVALID_ADDRESS;
- if (m_sc.function->GetFrameBaseExpression().IsLocationList())
- loclist_base_addr =
- m_sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress(
- exe_ctx.GetTargetPtr());
-
if (!m_sc.function->GetFrameBaseExpression().Evaluate(
- &exe_ctx, nullptr, loclist_base_addr, nullptr, nullptr,
- expr_value, &m_frame_base_error)) {
+ &exe_ctx, nullptr, nullptr, nullptr, expr_value,
+ &m_frame_base_error)) {
// We should really have an error if evaluate returns, but in case we
// don't, lets set the error to something at least.
if (m_frame_base_error.Success())
@@ -1110,7 +1104,7 @@
return m_frame_base_error.Success();
}
-DWARFExpression *StackFrame::GetFrameBaseExpression(Status *error_ptr) {
+DWARFExpressionList *StackFrame::GetFrameBaseExpression(Status *error_ptr) {
if (!m_sc.function) {
if (error_ptr) {
error_ptr->SetErrorString("No function in symbol context.");
@@ -1194,7 +1188,7 @@
LanguageType lang_type = GetLanguage();
if (lang_type == eLanguageTypeUnknown) {
- SymbolContext sc = GetSymbolContext(eSymbolContextFunction
+ SymbolContext sc = GetSymbolContext(eSymbolContextFunction
| eSymbolContextSymbol);
if (sc.function) {
lang_type = sc.function->GetMangled().GuessLanguage();
@@ -1411,7 +1405,7 @@
Status error;
ValueObjectSP pointee = base->Dereference(error);
-
+
if (!pointee) {
return ValueObjectSP();
}
@@ -1499,7 +1493,7 @@
Instruction::Operand::BuildRegister(reg));
for (VariableSP var_sp : variables) {
- if (var_sp->LocationExpression().MatchesOperand(frame, op))
+ if (var_sp->LocationExpressionList().MatchesOperand(frame, op))
return frame.GetValueObjectForFrameVariable(var_sp, eNoDynamicValues);
}
Index: lldb/source/Target/RegisterContextUnwind.cpp
===================================================================
--- lldb/source/Target/RegisterContextUnwind.cpp
+++ lldb/source/Target/RegisterContextUnwind.cpp
@@ -11,7 +11,7 @@
#include "lldb/Core/AddressRange.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/Value.h"
-#include "lldb/Expression/DWARFExpression.h"
+#include "lldb/Expression/DWARFExpressionList.h"
#include "lldb/Symbol/ArmUnwindInfo.h"
#include "lldb/Symbol/CallFrameInfo.h"
#include "lldb/Symbol/DWARFCallFrameInfo.h"
@@ -381,7 +381,7 @@
// symbol/function information - just stick in some reasonable defaults and
// hope we can unwind past this frame. If we're above a trap handler,
// we may be at a bogus address because we jumped through a bogus function
- // pointer and trapped, so don't force the arch default unwind plan in that
+ // pointer and trapped, so don't force the arch default unwind plan in that
// case.
ModuleSP pc_module_sp(m_current_pc.GetModule());
if ((!m_current_pc.IsValid() || !pc_module_sp) &&
@@ -1286,7 +1286,7 @@
// arch default unwind plan is used as the Fast Unwind Plan, we
// need to recognize this & switch over to the Full Unwind Plan
// to see what unwind rule that (more knoweldgeable, probably)
- // UnwindPlan has. If the full UnwindPlan says the register
+ // UnwindPlan has. If the full UnwindPlan says the register
// location is Undefined, then it really is.
if (active_row->GetRegisterInfo(regnum.GetAsKind(unwindplan_registerkind),
unwindplan_regloc) &&
@@ -1335,13 +1335,13 @@
m_full_unwind_plan_sp->GetReturnAddressRegister() !=
LLDB_INVALID_REGNUM) {
// If this is a trap handler frame, we should have access to
- // the complete register context when the interrupt/async
+ // the complete register context when the interrupt/async
// signal was received, we should fetch the actual saved $pc
// value instead of the Return Address register.
// If $pc is not available, fall back to the RA reg.
UnwindPlan::Row::RegisterLocation scratch;
if (m_frame_type == eTrapHandlerFrame &&
- active_row->GetRegisterInfo
+ active_row->GetRegisterInfo
(pc_regnum.GetAsKind (unwindplan_registerkind), scratch)) {
UnwindLogMsg("Providing pc register instead of rewriting to "
"RA reg because this is a trap handler and there is "
@@ -1642,14 +1642,14 @@
process->GetByteOrder(),
process->GetAddressByteSize());
ModuleSP opcode_ctx;
- DWARFExpression dwarfexpr(opcode_ctx, dwarfdata, nullptr);
- dwarfexpr.SetRegisterKind(unwindplan_registerkind);
+ DWARFExpressionList dwarfexpr(opcode_ctx, dwarfdata, nullptr);
+ dwarfexpr.GetMutableExpressionAtAddress(0)->SetRegisterKind(
+ unwindplan_registerkind);
Value cfa_val = Scalar(m_cfa);
cfa_val.SetValueType(Value::ValueType::LoadAddress);
Value result;
Status error;
- if (dwarfexpr.Evaluate(&exe_ctx, this, 0, &cfa_val, nullptr, result,
- &error)) {
+ if (dwarfexpr.Evaluate(&exe_ctx, this, &cfa_val, nullptr, result, &error)) {
addr_t val;
val = result.GetScalar().ULongLong();
if (unwindplan_regloc.IsDWARFExpression()) {
@@ -2006,11 +2006,12 @@
process->GetByteOrder(),
process->GetAddressByteSize());
ModuleSP opcode_ctx;
- DWARFExpression dwarfexpr(opcode_ctx, dwarfdata, nullptr);
- dwarfexpr.SetRegisterKind(row_register_kind);
+ DWARFExpressionList dwarfexpr(opcode_ctx, dwarfdata, nullptr);
+ dwarfexpr.GetMutableExpressionAtAddress(0)->SetRegisterKind(
+ row_register_kind);
Value result;
Status error;
- if (dwarfexpr.Evaluate(&exe_ctx, this, 0, nullptr, nullptr, result,
+ if (dwarfexpr.Evaluate(&exe_ctx, this, nullptr, nullptr, result,
&error)) {
address = result.GetScalar().ULongLong();
if (ABISP abi_sp = m_thread.GetProcess()->GetABI())
Index: lldb/source/Symbol/Variable.cpp
===================================================================
--- lldb/source/Symbol/Variable.cpp
+++ lldb/source/Symbol/Variable.cpp
@@ -39,13 +39,13 @@
const lldb::SymbolFileTypeSP &symfile_type_sp,
ValueType scope, SymbolContextScope *context,
const RangeList &scope_range, Declaration *decl_ptr,
- const DWARFExpression &location, bool external,
+ const DWARFExpressionList &location_list, bool external,
bool artificial, bool location_is_constant_data,
bool static_member)
: UserID(uid), m_name(name), m_mangled(ConstString(mangled)),
m_symfile_type_sp(symfile_type_sp), m_scope(scope),
m_owner_scope(context), m_scope_range(scope_range),
- m_declaration(decl_ptr), m_location(location), m_external(external),
+ m_declaration(decl_ptr), m_location_list(location_list), m_external(external),
m_artificial(artificial), m_loc_is_const_data(location_is_constant_data),
m_static_member(static_member) {}
@@ -145,7 +145,7 @@
bool show_fullpaths = false;
m_declaration.Dump(s, show_fullpaths);
- if (m_location.IsValid()) {
+ if (m_location_list.IsValid()) {
s->PutCString(", location = ");
ABISP abi;
if (m_owner_scope) {
@@ -153,7 +153,7 @@
if (module_sp)
abi = ABI::FindPlugin(ProcessSP(), module_sp->GetArchitecture());
}
- m_location.GetDescription(s, lldb::eDescriptionLevelBrief, abi.get());
+ m_location_list.GetDescription(s, lldb::eDescriptionLevelBrief, abi.get());
}
if (m_external)
@@ -212,31 +212,8 @@
}
bool Variable::LocationIsValidForFrame(StackFrame *frame) {
- // Is the variable is described by a single location?
- if (!m_location.IsLocationList()) {
- // Yes it is, the location is valid.
- return true;
- }
-
- if (frame) {
- Function *function =
- frame->GetSymbolContext(eSymbolContextFunction).function;
- if (function) {
- TargetSP target_sp(frame->CalculateTarget());
-
- addr_t loclist_base_load_addr =
- function->GetAddressRange().GetBaseAddress().GetLoadAddress(
- target_sp.get());
- if (loclist_base_load_addr == LLDB_INVALID_ADDRESS)
- return false;
- // It is a location list. We just need to tell if the location list
- // contains the current address when converted to a load address
- return m_location.LocationListContainsAddress(
- loclist_base_load_addr,
- frame->GetFrameCodeAddress().GetLoadAddress(target_sp.get()));
- }
- }
- return false;
+ return m_location_list.ContainsAddress(
+ frame->GetFrameCodeAddress().GetFileAddress());
}
bool Variable::LocationIsValidForAddress(const Address &address) {
@@ -244,7 +221,7 @@
// function.
if (address.IsSectionOffset()) {
// We need to check if the address is valid for both scope range and value
- // range.
+ // range.
// Empty scope range means block range.
bool valid_in_scope_range =
GetScopeRange().IsEmpty() || GetScopeRange().FindEntryThatContains(
@@ -254,22 +231,10 @@
SymbolContext sc;
CalculateSymbolContext(&sc);
if (sc.module_sp == address.GetModule()) {
- // Is the variable is described by a single location?
- if (!m_location.IsLocationList()) {
- // Yes it is, the location is valid.
- return true;
- }
-
- if (sc.function) {
- addr_t loclist_base_file_addr =
- sc.function->GetAddressRange().GetBaseAddress().GetFileAddress();
- if (loclist_base_file_addr == LLDB_INVALID_ADDRESS)
- return false;
- // It is a location list. We just need to tell if the location list
- // contains the current address when converted to a load address
- return m_location.LocationListContainsAddress(loclist_base_file_addr,
- address.GetFileAddress());
- }
+ // Empty location list means we have missing value range info, but it's in
+ // the scope.
+ return m_location_list.GetSize() == 0 ||
+ m_location_list.ContainsAddress(address.GetFileAddress());
}
}
return false;
@@ -454,16 +419,8 @@
}
const addr_t file_addr = address.GetFileAddress();
- if (sc.function) {
- addr_t loclist_base_file_addr =
- sc.function->GetAddressRange().GetBaseAddress().GetFileAddress();
- if (loclist_base_file_addr == LLDB_INVALID_ADDRESS)
- return false;
- return m_location.DumpLocations(s, eDescriptionLevelBrief,
- loclist_base_file_addr, file_addr,
- abi.get());
- }
- return false;
+ return m_location_list.DumpLocations(s, eDescriptionLevelBrief, file_addr,
+ abi.get());
}
static void PrivateAutoComplete(
Index: lldb/source/Symbol/Function.cpp
===================================================================
--- lldb/source/Symbol/Function.cpp
+++ lldb/source/Symbol/Function.cpp
@@ -196,7 +196,6 @@
Status error;
Value callee_addr_val;
if (!call_target.Evaluate(&exe_ctx, exe_ctx.GetRegisterContext(),
- /*loclist_base_load_addr=*/LLDB_INVALID_ADDRESS,
/*initial_value_ptr=*/nullptr,
/*object_address_ptr=*/nullptr, callee_addr_val,
&error)) {
Index: lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
+++ lldb/source/Plugins/SymbolFile/PDB/SymbolFilePDB.cpp
@@ -1023,8 +1023,11 @@
auto mangled_cstr = mangled.empty() ? nullptr : mangled.c_str();
bool is_constant;
- DWARFExpression location = ConvertPDBLocationToDWARFExpression(
- GetObjectFile()->GetModule(), pdb_data, ranges, is_constant);
+ ModuleSP module_sp = GetObjectFile()->GetModule();
+ DWARFExpressionList location(module_sp,
+ ConvertPDBLocationToDWARFExpression(
+ module_sp, pdb_data, ranges, is_constant),
+ nullptr);
var_sp = std::make_shared<Variable>(
var_uid, var_name.c_str(), mangled_cstr, type_sp, scope, context_scope,
Index: lldb/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp
+++ lldb/source/Plugins/SymbolFile/PDB/PDBLocationToDWARFExpression.cpp
@@ -175,7 +175,7 @@
DataBufferSP buffer =
std::make_shared<DataBufferHeap>(stream.GetData(), stream.GetSize());
DataExtractor extractor(buffer, byte_order, address_size, byte_size);
- DWARFExpression result(module, extractor, nullptr);
+ DWARFExpression result(extractor);
result.SetRegisterKind(register_kind);
return result;
Index: lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
+++ lldb/source/Plugins/SymbolFile/NativePDB/SymbolFileNativePDB.cpp
@@ -817,8 +817,10 @@
m_ast->GetOrCreateVariableDecl(var_id);
- DWARFExpression location = MakeGlobalLocationExpression(
- section, offset, GetObjectFile()->GetModule());
+ ModuleSP module_sp = GetObjectFile()->GetModule();
+ DWARFExpressionList location(
+ module_sp, MakeGlobalLocationExpression(section, offset, module_sp),
+ nullptr);
std::string global_name("::");
global_name += name;
@@ -849,8 +851,10 @@
Declaration decl;
Variable::RangeList ranges;
ModuleSP module = GetObjectFile()->GetModule();
- DWARFExpression location = MakeConstantLocationExpression(
- constant.Type, tpi, constant.Value, module);
+ DWARFExpressionList location(module,
+ MakeConstantLocationExpression(
+ constant.Type, tpi, constant.Value, module),
+ nullptr);
bool external = false;
bool artificial = false;
@@ -1696,7 +1700,8 @@
bool static_member = false;
VariableSP var_sp = std::make_shared<Variable>(
toOpaqueUid(var_id), name.c_str(), name.c_str(), sftype, var_scope,
- &block, *var_info.ranges, &decl, *var_info.location, external,
+ &block, *var_info.ranges, &decl,
+ DWARFExpressionList(module, *var_info.location, nullptr), external,
artificial, location_is_constant_data, static_member);
if (!is_param)
Index: lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp
+++ lldb/source/Plugins/SymbolFile/NativePDB/DWARFLocationExpression.cpp
@@ -122,7 +122,7 @@
DataBufferSP buffer =
std::make_shared<DataBufferHeap>(stream.GetData(), stream.GetSize());
DataExtractor extractor(buffer, byte_order, address_size, byte_size);
- DWARFExpression result(module, extractor, nullptr);
+ DWARFExpression result(extractor);
result.SetRegisterKind(register_kind);
return result;
@@ -247,7 +247,7 @@
.take_front(size);
buffer->CopyData(bytes.data(), size);
DataExtractor extractor(buffer, lldb::eByteOrderLittle, address_size);
- DWARFExpression result(nullptr, extractor, nullptr);
+ DWARFExpression result(extractor);
return result;
}
Index: lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
+++ lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.h
@@ -21,6 +21,7 @@
#include "lldb/Core/UniqueCStringMap.h"
#include "lldb/Core/dwarf.h"
+#include "lldb/Expression/DWARFExpressionList.h"
#include "lldb/Symbol/DebugMacros.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/SymbolFile.h"
Index: lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
+++ lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
@@ -9,6 +9,7 @@
#include "SymbolFileDWARF.h"
#include "llvm/ADT/Optional.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Threading.h"
@@ -1885,11 +1886,13 @@
for (size_t g = 0; g < num_globals; ++g) {
VariableSP var_sp = globals_sp->GetVariableAtIndex(g);
if (var_sp && !var_sp->GetLocationIsConstantValueData()) {
- const DWARFExpression &location = var_sp->LocationExpression();
+ const DWARFExpressionList &location =
+ var_sp->LocationExpressionList();
Value location_result;
Status error;
- if (location.Evaluate(nullptr, LLDB_INVALID_ADDRESS, nullptr,
- nullptr, location_result, &error)) {
+ ExecutionContext exe_ctx;
+ if (location.Evaluate(&exe_ctx, nullptr, nullptr, nullptr,
+ location_result, &error)) {
if (location_result.GetValueType() ==
Value::ValueType::FileAddress) {
lldb::addr_t file_addr =
@@ -3163,7 +3166,7 @@
const char *mangled = nullptr;
Declaration decl;
DWARFFormValue type_die_form;
- DWARFExpression location;
+ DWARFExpressionList location_list(module, DWARFExpression(), die.GetCU());
bool is_external = false;
bool is_artificial = false;
DWARFFormValue const_value_form, location_form;
@@ -3229,16 +3232,15 @@
// present in the class declaration and DW_AT_location in the DIE defining
// the member.
bool location_is_const_value_data = false;
- bool has_explicit_location = false;
+ bool has_explicit_location = location_form.IsValid();
bool use_type_size_for_value = false;
if (location_form.IsValid()) {
- has_explicit_location = true;
if (DWARFFormValue::IsBlockForm(location_form.Form())) {
const DWARFDataExtractor &data = die.GetData();
uint32_t block_offset = location_form.BlockData() - data.GetDataStart();
uint32_t block_length = location_form.Unsigned();
- location = DWARFExpression(
+ location_list = DWARFExpressionList(
module, DataExtractor(data, block_offset, block_length), die.GetCU());
} else {
DataExtractor data = die.GetCU()->GetLocationData();
@@ -3247,10 +3249,8 @@
offset = die.GetCU()->GetLoclistOffset(offset).getValueOr(-1);
if (data.ValidOffset(offset)) {
data = DataExtractor(data, offset, data.GetByteSize() - offset);
- location = DWARFExpression(module, data, die.GetCU());
- assert(func_low_pc != LLDB_INVALID_ADDRESS);
- location.SetLocationListAddresses(
- location_form.GetUnit()->GetBaseAddress(), func_low_pc);
+ const DWARFUnit *dwarf_cu = location_form.GetUnit();
+ DWARFExpression::ParseDWARFLocationList(dwarf_cu, data, &location_list);
}
}
} else if (const_value_form.IsValid()) {
@@ -3263,7 +3263,7 @@
uint32_t block_offset =
const_value_form.BlockData() - debug_info_data.GetDataStart();
uint32_t block_length = const_value_form.Unsigned();
- location = DWARFExpression(
+ location_list = DWARFExpressionList(
module, DataExtractor(debug_info_data, block_offset, block_length),
die.GetCU());
} else if (DWARFFormValue::IsDataForm(const_value_form.Form())) {
@@ -3273,7 +3273,7 @@
use_type_size_for_value = true;
} else if (const char *str = const_value_form.AsCString()) {
uint32_t string_length = strlen(str) + 1;
- location = DWARFExpression(
+ location_list = DWARFExpressionList(
module,
DataExtractor(str, string_length, die.GetCU()->GetByteOrder(),
die.GetCU()->GetAddressByteSize()),
@@ -3323,16 +3323,19 @@
// with locations like: DW_OP_addr(0x1000), DW_OP_constu(2), DW_OP_plus
// so we need to look through the whole expression.
bool is_static_lifetime =
- has_explicit_mangled || (has_explicit_location && !location.IsValid());
+ has_explicit_mangled ||
+ (has_explicit_location && !location_list.IsValid());
// Check if the location has a DW_OP_addr with any address value...
lldb::addr_t location_DW_OP_addr = LLDB_INVALID_ADDRESS;
if (!location_is_const_value_data) {
bool op_error = false;
- location_DW_OP_addr = location.GetLocation_DW_OP_addr(0, op_error);
+ const DWARFExpression* location = location_list.GetExpressionAtAddress(0);
+ if (location)
+ location_DW_OP_addr = location->GetLocation_DW_OP_addr(
+ location_form.GetUnit(), 0, op_error);
if (op_error) {
StreamString strm;
- location.DumpLocationForAddress(&strm, eDescriptionLevelFull, 0, 0,
- nullptr);
+ location->DumpLocation(&strm, eDescriptionLevelFull, nullptr);
GetObjectFile()->GetModule()->ReportError(
"0x%8.8x: %s has an invalid location: %s", die.GetOffset(),
die.GetTagAsCString(), strm.GetData());
@@ -3345,7 +3348,7 @@
// Set the module of the expression to the linked module
// instead of the object file so the relocated address can be
// found there.
- location.SetModule(debug_map_symfile->GetObjectFile()->GetModule());
+ location_list.SetModule(debug_map_symfile->GetObjectFile()->GetModule());
if (is_static_lifetime) {
if (is_external)
@@ -3386,7 +3389,9 @@
const addr_t exe_file_addr =
exe_symbol->GetAddressRef().GetFileAddress();
if (exe_file_addr != LLDB_INVALID_ADDRESS) {
- if (location.Update_DW_OP_addr(exe_file_addr)) {
+ DWARFExpression *location =
+ location_list.GetMutableExpressionAtAddress(0);
+ if (location->Update_DW_OP_addr(exe_file_addr)) {
linked_oso_file_addr = true;
symbol_context_scope = exe_symbol;
}
@@ -3404,7 +3409,9 @@
debug_map_symfile->LinkOSOFileAddress(this, location_DW_OP_addr);
if (exe_file_addr != LLDB_INVALID_ADDRESS) {
// Update the file address for this variable
- location.Update_DW_OP_addr(exe_file_addr);
+ DWARFExpression *location =
+ location_list.GetMutableExpressionAtAddress(0);
+ location->Update_DW_OP_addr(exe_file_addr);
} else {
// Variable didn't make it into the final executable
return nullptr;
@@ -3419,8 +3426,8 @@
scope = eValueTypeVariableLocal;
if (debug_map_symfile) {
// We need to check for TLS addresses that we need to fixup
- if (location.ContainsThreadLocalStorage()) {
- location.LinkThreadLocalStorage(
+ if (location_list.ContainsThreadLocalStorage()) {
+ location_list.LinkThreadLocalStorage(
debug_map_symfile->GetObjectFile()->GetModule(),
[this, debug_map_symfile](
lldb::addr_t unlinked_file_addr) -> lldb::addr_t {
@@ -3463,14 +3470,17 @@
auto type_sp = std::make_shared<SymbolFileType>(
*this, GetUID(type_die_form.Reference()));
- if (use_type_size_for_value && type_sp->GetType())
- location.UpdateValue(const_value_form.Unsigned(),
- type_sp->GetType()->GetByteSize(nullptr).getValueOr(0),
- die.GetCU()->GetAddressByteSize());
+ if (use_type_size_for_value && type_sp->GetType()) {
+ DWARFExpression *location = location_list.GetMutableExpressionAtAddress(0);
+ location->UpdateValue(
+ const_value_form.Unsigned(),
+ type_sp->GetType()->GetByteSize(nullptr).getValueOr(0),
+ die.GetCU()->GetAddressByteSize());
+ }
return std::make_shared<Variable>(
die.GetID(), name, mangled, type_sp, scope, symbol_context_scope,
- scope_ranges, &decl, location, is_external, is_artificial,
+ scope_ranges, &decl, location_list, is_external, is_artificial,
location_is_const_value_data, is_static_member);
}
@@ -3755,8 +3765,8 @@
child.Tag() != DW_TAG_GNU_call_site_parameter)
continue;
- llvm::Optional<DWARFExpression> LocationInCallee;
- llvm::Optional<DWARFExpression> LocationInCaller;
+ llvm::Optional<DWARFExpressionList> LocationInCallee;
+ llvm::Optional<DWARFExpressionList> LocationInCaller;
DWARFAttributes attributes;
const size_t num_attributes = child.GetAttributes(attributes);
@@ -3764,7 +3774,7 @@
// Parse the location at index \p attr_index within this call site parameter
// DIE, or return None on failure.
auto parse_simple_location =
- [&](int attr_index) -> llvm::Optional<DWARFExpression> {
+ [&](int attr_index) -> llvm::Optional<DWARFExpressionList> {
DWARFFormValue form_value;
if (!attributes.ExtractFormValueAtIndex(attr_index, form_value))
return {};
@@ -3773,9 +3783,9 @@
auto data = child.GetData();
uint32_t block_offset = form_value.BlockData() - data.GetDataStart();
uint32_t block_length = form_value.Unsigned();
- return DWARFExpression(module,
- DataExtractor(data, block_offset, block_length),
- child.GetCU());
+ return DWARFExpressionList(
+ module, DataExtractor(data, block_offset, block_length),
+ child.GetCU());
};
for (size_t i = 0; i < num_attributes; ++i) {
@@ -3820,7 +3830,7 @@
continue;
llvm::Optional<DWARFDIE> call_origin;
- llvm::Optional<DWARFExpression> call_target;
+ llvm::Optional<DWARFExpressionList> call_target;
addr_t return_pc = LLDB_INVALID_ADDRESS;
addr_t call_inst_pc = LLDB_INVALID_ADDRESS;
addr_t low_pc = LLDB_INVALID_ADDRESS;
@@ -3881,7 +3891,7 @@
auto data = child.GetData();
uint32_t block_offset = form_value.BlockData() - data.GetDataStart();
uint32_t block_length = form_value.Unsigned();
- call_target = DWARFExpression(
+ call_target = DWARFExpressionList(
module, DataExtractor(data, block_offset, block_length),
child.GetCU());
}
Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h
+++ lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.h
@@ -104,7 +104,7 @@
DWARFUnit *cu, const char *&name, const char *&mangled,
DWARFRangeList &rangeList, int &decl_file, int &decl_line,
int &decl_column, int &call_file, int &call_line, int &call_column,
- lldb_private::DWARFExpression *frame_base = nullptr) const;
+ lldb_private::DWARFExpressionList *frame_base = nullptr) const;
const DWARFAbbreviationDeclaration *
GetAbbreviationDeclarationPtr(const DWARFUnit *cu) const;
Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
+++ lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
@@ -231,11 +231,10 @@
DWARFUnit *cu, const char *&name, const char *&mangled,
DWARFRangeList &ranges, int &decl_file, int &decl_line, int &decl_column,
int &call_file, int &call_line, int &call_column,
- DWARFExpression *frame_base) const {
+ DWARFExpressionList *frame_base) const {
dw_addr_t lo_pc = LLDB_INVALID_ADDRESS;
dw_addr_t hi_pc = LLDB_INVALID_ADDRESS;
std::vector<DWARFDIE> dies;
- bool set_frame_base_loclist_addr = false;
const auto *abbrevDecl = GetAbbreviationDeclarationPtr(cu);
@@ -345,21 +344,17 @@
uint32_t block_offset =
form_value.BlockData() - data.GetDataStart();
uint32_t block_length = form_value.Unsigned();
- *frame_base = DWARFExpression(
- module, DataExtractor(data, block_offset, block_length), cu);
+ *frame_base =
+ DWARFExpressionList(module,
+ DWARFExpression(DataExtractor(
+ data, block_offset, block_length)),
+ cu);
} else {
DataExtractor data = cu->GetLocationData();
const dw_offset_t offset = form_value.Unsigned();
if (data.ValidOffset(offset)) {
data = DataExtractor(data, offset, data.GetByteSize() - offset);
- *frame_base = DWARFExpression(module, data, cu);
- if (lo_pc != LLDB_INVALID_ADDRESS) {
- assert(lo_pc >= cu->GetBaseAddress());
- frame_base->SetLocationListAddresses(cu->GetBaseAddress(),
- lo_pc);
- } else {
- set_frame_base_loclist_addr = true;
- }
+ DWARFExpression::ParseDWARFLocationList(cu, data, frame_base);
}
}
}
@@ -381,12 +376,6 @@
}
}
- if (set_frame_base_loclist_addr) {
- dw_addr_t lowest_range_pc = ranges.GetMinRangeBase(0);
- assert(lowest_range_pc >= cu->GetBaseAddress());
- frame_base->SetLocationListAddresses(cu->GetBaseAddress(), lowest_range_pc);
- }
-
if (ranges.IsEmpty() || name == nullptr || mangled == nullptr) {
for (const DWARFDIE &die : dies) {
if (die) {
Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
+++ lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.h
@@ -85,11 +85,12 @@
DWARFDIE
GetAttributeValueAsReferenceDIE(const dw_attr_t attr) const;
- bool GetDIENamesAndRanges(const char *&name, const char *&mangled,
- DWARFRangeList &ranges, int &decl_file,
- int &decl_line, int &decl_column, int &call_file,
- int &call_line, int &call_column,
- lldb_private::DWARFExpression *frame_base) const;
+ bool
+ GetDIENamesAndRanges(const char *&name, const char *&mangled,
+ DWARFRangeList &ranges, int &decl_file, int &decl_line,
+ int &decl_column, int &call_file, int &call_line,
+ int &call_column,
+ lldb_private::DWARFExpressionList *frame_base) const;
/// The range of all the children of this DIE.
llvm::iterator_range<child_iterator> children() const;
Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
+++ lldb/source/Plugins/SymbolFile/DWARF/DWARFDIE.cpp
@@ -441,7 +441,7 @@
const char *&name, const char *&mangled, DWARFRangeList &ranges,
int &decl_file, int &decl_line, int &decl_column, int &call_file,
int &call_line, int &call_column,
- lldb_private::DWARFExpression *frame_base) const {
+ lldb_private::DWARFExpressionList *frame_base) const {
if (IsValid()) {
return m_die->GetDIENamesAndRanges(
GetCU(), name, mangled, ranges, decl_file, decl_line, decl_column,
Index: lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
===================================================================
--- lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
+++ lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
@@ -2305,7 +2305,7 @@
int call_file = 0;
int call_line = 0;
int call_column = 0;
- DWARFExpression frame_base;
+ DWARFExpressionList frame_base;
const dw_tag_t tag = die.Tag();
Index: lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
===================================================================
--- lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
+++ lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp
@@ -1485,15 +1485,14 @@
return false;
}
- DWARFExpression &var_location_expr = var->LocationExpression();
+ DWARFExpressionList &var_location_list = var->LocationExpressionList();
Target *target = m_parser_vars->m_exe_ctx.GetTargetPtr();
Status err;
if (var->GetLocationIsConstantValueData()) {
DataExtractor const_value_extractor;
-
- if (var_location_expr.GetExpressionData(const_value_extractor)) {
+ if (var_location_list.GetExpressionData(const_value_extractor)) {
var_location = Value(const_value_extractor.GetDataStart(),
const_value_extractor.GetByteSize());
var_location.SetValueType(Value::ValueType::HostAddress);
Index: lldb/source/Expression/Materializer.cpp
===================================================================
--- lldb/source/Expression/Materializer.cpp
+++ lldb/source/Expression/Materializer.cpp
@@ -518,7 +518,7 @@
if (data.GetByteSize() < m_variable_sp->GetType()->GetByteSize(scope)) {
if (data.GetByteSize() == 0 &&
- !m_variable_sp->LocationExpression().IsValid()) {
+ !m_variable_sp->LocationExpressionList().IsValid()) {
err.SetErrorStringWithFormat("the variable '%s' has no location, "
"it may have been optimized out",
m_variable_sp->GetName().AsCString());
Index: lldb/source/Expression/DWARFExpressionList.cpp
===================================================================
--- /dev/null
+++ lldb/source/Expression/DWARFExpressionList.cpp
@@ -0,0 +1,220 @@
+//===-- DWARFExpressionList.cpp -------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Expression/DWARFExpressionList.h"
+#include "Plugins/SymbolFile/DWARF/DWARFUnit.h"
+#include "lldb/Symbol/Function.h"
+#include "lldb/Target/RegisterContext.h"
+#include "lldb/Target/StackFrame.h"
+#include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
+#include "llvm/DebugInfo/DWARF/DWARFFormValue.h"
+
+using namespace lldb;
+using namespace lldb_private;
+
+bool DWARFExpressionList::AddExpression(addr_t base, addr_t end,
+ DWARFExpression expr) {
+ if (base >= end)
+ return false;
+ m_exprs.Append({base, end - base, expr});
+ return true;
+}
+
+bool DWARFExpressionList::GetExpressionData(DataExtractor &data) const {
+ if (m_exprs.GetSize() != 1)
+ return false;
+ return m_exprs.Back()->data.GetExpressionData(data);
+}
+
+bool DWARFExpressionList::ContainsAddress(lldb::addr_t file_addr) const {
+ return m_exprs.FindEntryThatContains(file_addr) != nullptr;
+}
+
+const DWARFExpression *
+DWARFExpressionList::GetExpressionAtAddress(lldb::addr_t file_addr) const {
+ uint32_t index = m_exprs.FindEntryIndexThatContains(file_addr);
+ if (index == UINT32_MAX)
+ return nullptr;
+ return &m_exprs.GetEntryAtIndex(index)->data;
+}
+
+DWARFExpression *
+DWARFExpressionList::GetMutableExpressionAtAddress(lldb::addr_t file_addr) {
+ uint32_t index = m_exprs.FindEntryIndexThatContains(file_addr);
+ if (index == UINT32_MAX)
+ return nullptr;
+ return &m_exprs.GetMutableEntryAtIndex(index)->data;
+}
+
+bool DWARFExpressionList::ContainsThreadLocalStorage() const {
+ // We are assuming for now that any thread local variable will not have a
+ // location list. This has been true for all thread local variables we have
+ // seen so far produced by any compiler.
+ if (m_exprs.GetSize() != 1)
+ return false;
+
+ const DWARFExpression &expr = m_exprs.GetEntryRef(0).data;
+ return expr.ContainsThreadLocalStorage();
+}
+
+bool DWARFExpressionList::LinkThreadLocalStorage(
+ lldb::ModuleSP new_module_sp,
+ std::function<lldb::addr_t(lldb::addr_t file_addr)> const
+ &link_address_callback) {
+ // We are assuming for now that any thread local variable will not have a
+ // location list. This has been true for all thread local variables we have
+ // seen so far produced by any compiler.
+ if (m_exprs.GetSize() != 1)
+ return false;
+
+ DWARFExpression &expr = m_exprs.GetEntryRef(0).data;
+ // If we linked the TLS address correctly, update the module so that when the
+ // expression is evaluated it can resolve the file address to a load address
+ // and read the TLS data
+ if (expr.LinkThreadLocalStorage(link_address_callback))
+ m_module_wp = new_module_sp;
+ return true;
+}
+
+bool DWARFExpressionList::MatchesOperand(StackFrame &frame,
+ const Instruction::Operand &operand) {
+ RegisterContextSP reg_ctx_sp = frame.GetRegisterContext();
+ if (!reg_ctx_sp) {
+ return false;
+ }
+ DWARFExpression *expr = nullptr;
+ if (m_exprs.GetSize() == 1)
+ expr = &m_exprs.GetMutableEntryAtIndex(0)->data;
+ else {
+ SymbolContext sc = frame.GetSymbolContext(eSymbolContextFunction);
+ if (!sc.function)
+ return false;
+
+ addr_t load_function_start =
+ sc.function->GetAddressRange().GetBaseAddress().GetFileAddress();
+ if (load_function_start == LLDB_INVALID_ADDRESS)
+ return false;
+
+ addr_t pc = frame.GetFrameCodeAddressForSymbolication().GetFileAddress();
+ expr = GetMutableExpressionAtAddress(pc);
+ }
+ if (!expr)
+ return false;
+ return expr->MatchesOperand(frame, operand);
+}
+
+void DWARFExpressionList::ForAllLocations(
+ const std::function<bool(const Entry *)> &fn) const {
+ for (size_t i = 0; i < m_exprs.GetSize(); ++i) {
+ if (!fn(m_exprs.GetEntryAtIndex(i)))
+ break;
+ }
+}
+
+bool DWARFExpressionList::DumpLocations(Stream *s, lldb::DescriptionLevel level,
+ lldb::addr_t file_addr,
+ ABI *abi) const {
+ llvm::raw_ostream &os = s->AsRawOstream();
+ llvm::ListSeparator separator;
+ ForAllLocations([&](const Entry *entry) {
+ if (file_addr != LLDB_INVALID_ADDRESS &&
+ (file_addr < entry->GetRangeBase() ||
+ file_addr >= entry->GetRangeEnd()))
+ return true;
+ const auto &expr = entry->data;
+ DataExtractor data;
+ expr.GetExpressionData(data);
+ uint32_t addr_size = data.GetAddressByteSize();
+ if (entry->GetRangeEnd() == LLDB_INVALID_ADDRESS) {
+ expr.DumpLocation(s, level, abi);
+ return false;
+ }
+
+ os << separator;
+ os << "[";
+ os << llvm::format_hex(entry->GetRangeBase(), 2 + 2 * addr_size);
+ os << ", ";
+ os << llvm::format_hex(entry->GetRangeEnd(), 2 + 2 * addr_size);
+ os << ") -> ";
+ expr.DumpLocation(s, level, abi);
+ if (file_addr != LLDB_INVALID_ADDRESS)
+ return false;
+ return true;
+ });
+ return true;
+}
+
+void DWARFExpressionList::GetDescription(Stream *s,
+ lldb::DescriptionLevel level,
+ ABI *abi) const {
+ llvm::raw_ostream &os = s->AsRawOstream();
+ if (m_exprs.GetSize() == 1 &&
+ m_exprs.Back()->GetRangeEnd() == LLDB_INVALID_ADDRESS) {
+ m_exprs.Back()->data.DumpLocation(s, level, abi);
+ return;
+ }
+ os << llvm::format("0x%8.8" PRIx64 ": ", 0);
+ ForAllLocations([&](const Entry *entry) {
+ const auto &expr = entry->data;
+ DataExtractor data;
+ expr.GetExpressionData(data);
+ uint32_t addr_size = data.GetAddressByteSize();
+ os << "\n";
+ os.indent(s->GetIndentLevel() + 2);
+ os << "[";
+ llvm::DWARFFormValue::dumpAddress(os, addr_size, entry->GetRangeBase());
+ os << ", ";
+ llvm::DWARFFormValue::dumpAddress(os, addr_size, entry->GetRangeEnd());
+ os << "): ";
+ expr.DumpLocation(s, level, abi);
+ return true;
+ });
+}
+
+bool DWARFExpressionList::Evaluate(ExecutionContext *exe_ctx,
+ RegisterContext *reg_ctx,
+ const Value *initial_value_ptr,
+ const Value *object_address_ptr,
+ Value &result, Status *error_ptr) const {
+ ModuleSP module_sp = m_module_wp.lock();
+ DataExtractor data;
+ RegisterKind reg_kind;
+ DWARFExpression expr;
+ if (m_exprs.GetSize() == 1) {
+ expr = m_exprs.Back()->data;
+ } else {
+ Address pc;
+ StackFrame *frame = nullptr;
+ if (!reg_ctx || !reg_ctx->GetPCForSymbolication(pc)) {
+ if (exe_ctx)
+ frame = exe_ctx->GetFramePtr();
+ if (!frame)
+ return false;
+ RegisterContextSP reg_ctx_sp = frame->GetRegisterContext();
+ if (!reg_ctx_sp)
+ return false;
+ reg_ctx_sp->GetPCForSymbolication(pc);
+ }
+
+ if (!pc.IsValid()) {
+ if (error_ptr)
+ error_ptr->SetErrorString("Invalid PC in frame.");
+ return false;
+ }
+ addr_t addr = pc.GetFileAddress();
+ const auto *entry = m_exprs.FindEntryThatContains(addr);
+ if (!entry)
+ return false;
+ expr = entry->data;
+ }
+ expr.GetExpressionData(data);
+ reg_kind = expr.GetRegisterKind();
+ return DWARFExpression::Evaluate(exe_ctx, reg_ctx, module_sp, data,
+ m_dwarf_cu, reg_kind, initial_value_ptr,
+ object_address_ptr, result, error_ptr);
+}
Index: lldb/source/Expression/DWARFExpression.cpp
===================================================================
--- lldb/source/Expression/DWARFExpression.cpp
+++ lldb/source/Expression/DWARFExpression.cpp
@@ -59,15 +59,9 @@
}
// DWARFExpression constructor
-DWARFExpression::DWARFExpression() : m_module_wp(), m_data() {}
-
-DWARFExpression::DWARFExpression(lldb::ModuleSP module_sp,
- const DataExtractor &data,
- const DWARFUnit *dwarf_cu)
- : m_module_wp(), m_data(data), m_dwarf_cu(dwarf_cu) {
- if (module_sp)
- m_module_wp = module_sp;
-}
+DWARFExpression::DWARFExpression() : m_data() {}
+
+DWARFExpression::DWARFExpression(const DataExtractor &data) : m_data(data) {}
// Destructor
DWARFExpression::~DWARFExpression() = default;
@@ -86,71 +80,19 @@
m_data.SetAddressByteSize(addr_byte_size);
}
-void DWARFExpression::DumpLocation(Stream *s, const DataExtractor &data,
- lldb::DescriptionLevel level,
+void DWARFExpression::DumpLocation(Stream *s, lldb::DescriptionLevel level,
ABI *abi) const {
- llvm::DWARFExpression(data.GetAsLLVM(), data.GetAddressByteSize())
+ llvm::DWARFExpression(m_data.GetAsLLVM(), m_data.GetAddressByteSize())
.print(s->AsRawOstream(), llvm::DIDumpOptions(),
abi ? &abi->GetMCRegisterInfo() : nullptr, nullptr);
}
-void DWARFExpression::SetLocationListAddresses(addr_t cu_file_addr,
- addr_t func_file_addr) {
- m_loclist_addresses = LoclistAddresses{cu_file_addr, func_file_addr};
-}
-
-int DWARFExpression::GetRegisterKind() { return m_reg_kind; }
+RegisterKind DWARFExpression::GetRegisterKind() const { return m_reg_kind; }
void DWARFExpression::SetRegisterKind(RegisterKind reg_kind) {
m_reg_kind = reg_kind;
}
-bool DWARFExpression::IsLocationList() const {
- return bool(m_loclist_addresses);
-}
-
-namespace {
-/// Implement enough of the DWARFObject interface in order to be able to call
-/// DWARFLocationTable::dumpLocationList. We don't have access to a real
-/// DWARFObject here because DWARFExpression is used in non-DWARF scenarios too.
-class DummyDWARFObject final: public llvm::DWARFObject {
-public:
- DummyDWARFObject(bool IsLittleEndian) : IsLittleEndian(IsLittleEndian) {}
-
- bool isLittleEndian() const override { return IsLittleEndian; }
-
- llvm::Optional<llvm::RelocAddrEntry> find(const llvm::DWARFSection &Sec,
- uint64_t Pos) const override {
- return llvm::None;
- }
-private:
- bool IsLittleEndian;
-};
-}
-
-void DWARFExpression::GetDescription(Stream *s, lldb::DescriptionLevel level,
- ABI *abi) const {
- if (IsLocationList()) {
- // We have a location list
- lldb::offset_t offset = 0;
- std::unique_ptr<llvm::DWARFLocationTable> loctable_up =
- m_dwarf_cu->GetLocationTable(m_data);
-
- llvm::MCRegisterInfo *MRI = abi ? &abi->GetMCRegisterInfo() : nullptr;
- llvm::DIDumpOptions DumpOpts;
- DumpOpts.RecoverableErrorHandler = [&](llvm::Error E) {
- s->AsRawOstream() << "error: " << toString(std::move(E));
- };
- loctable_up->dumpLocationList(
- &offset, s->AsRawOstream(),
- llvm::object::SectionedAddress{m_loclist_addresses->cu_file_addr}, MRI,
- DummyDWARFObject(m_data.GetByteOrder() == eByteOrderLittle), nullptr,
- DumpOpts, s->GetIndentLevel() + 2);
- } else {
- // We have a normal location that contains DW_OP location opcodes
- DumpLocation(s, m_data, level, abi);
- }
-}
static bool ReadRegisterValueAsScalar(RegisterContext *reg_ctx,
lldb::RegisterKind reg_kind,
@@ -409,11 +351,10 @@
return LLDB_INVALID_OFFSET;
}
-lldb::addr_t DWARFExpression::GetLocation_DW_OP_addr(uint32_t op_addr_idx,
+lldb::addr_t DWARFExpression::GetLocation_DW_OP_addr(const DWARFUnit *dwarf_cu,
+ uint32_t op_addr_idx,
bool &error) const {
error = false;
- if (IsLocationList())
- return LLDB_INVALID_ADDRESS;
lldb::offset_t offset = 0;
uint32_t curr_op_addr_idx = 0;
while (m_data.ValidOffset(offset)) {
@@ -423,19 +364,18 @@
const lldb::addr_t op_file_addr = m_data.GetAddress(&offset);
if (curr_op_addr_idx == op_addr_idx)
return op_file_addr;
- else
- ++curr_op_addr_idx;
+ ++curr_op_addr_idx;
} else if (op == DW_OP_GNU_addr_index || op == DW_OP_addrx) {
uint64_t index = m_data.GetULEB128(&offset);
if (curr_op_addr_idx == op_addr_idx) {
- if (!m_dwarf_cu) {
+ if (!dwarf_cu) {
error = true;
break;
}
- return ReadAddressFromDebugAddrSection(m_dwarf_cu, index);
- } else
- ++curr_op_addr_idx;
+ return ReadAddressFromDebugAddrSection(dwarf_cu, index);
+ }
+ ++curr_op_addr_idx;
} else {
const offset_t op_arg_size = GetOpcodeDataSize(m_data, offset, op);
if (op_arg_size == LLDB_INVALID_OFFSET) {
@@ -449,8 +389,6 @@
}
bool DWARFExpression::Update_DW_OP_addr(lldb::addr_t file_addr) {
- if (IsLocationList())
- return false;
lldb::offset_t offset = 0;
while (m_data.ValidOffset(offset)) {
const uint8_t op = m_data.GetU8(&offset);
@@ -487,11 +425,6 @@
}
bool DWARFExpression::ContainsThreadLocalStorage() const {
- // We are assuming for now that any thread local variable will not have a
- // location list. This has been true for all thread local variables we have
- // seen so far produced by any compiler.
- if (IsLocationList())
- return false;
lldb::offset_t offset = 0;
while (m_data.ValidOffset(offset)) {
const uint8_t op = m_data.GetU8(&offset);
@@ -501,27 +434,18 @@
const offset_t op_arg_size = GetOpcodeDataSize(m_data, offset, op);
if (op_arg_size == LLDB_INVALID_OFFSET)
return false;
- else
- offset += op_arg_size;
+ offset += op_arg_size;
}
return false;
}
bool DWARFExpression::LinkThreadLocalStorage(
- lldb::ModuleSP new_module_sp,
std::function<lldb::addr_t(lldb::addr_t file_addr)> const
&link_address_callback) {
- // We are assuming for now that any thread local variable will not have a
- // location list. This has been true for all thread local variables we have
- // seen so far produced by any compiler.
- if (IsLocationList())
- return false;
-
const uint32_t addr_byte_size = m_data.GetAddressByteSize();
// We have to make a copy of the data as we don't know if this data is from a
// read only memory mapped buffer, so we duplicate all of the data first,
// then modify it, and if all goes well, we then replace the data for this
// expression.
-
// Make en encoder that contains a copy of the location expression data so we
// can write the address into the buffer using the correct byte order.
DataEncoder encoder(m_data.GetDataStart(), m_data.GetByteSize(),
@@ -593,42 +517,10 @@
}
}
- // If we linked the TLS address correctly, update the module so that when the
- // expression is evaluated it can resolve the file address to a load address
- // and read the
- // TLS data
- m_module_wp = new_module_sp;
m_data.SetData(encoder.GetDataBuffer());
return true;
}
-bool DWARFExpression::LocationListContainsAddress(addr_t func_load_addr,
- lldb::addr_t addr) const {
- if (func_load_addr == LLDB_INVALID_ADDRESS || addr == LLDB_INVALID_ADDRESS)
- return false;
-
- if (!IsLocationList())
- return false;
-
- return GetLocationExpression(func_load_addr, addr) != llvm::None;
-}
-
-bool DWARFExpression::DumpLocationForAddress(Stream *s,
- lldb::DescriptionLevel level,
- addr_t func_load_addr,
- addr_t address, ABI *abi) {
- if (!IsLocationList()) {
- DumpLocation(s, m_data, level, abi);
- return true;
- }
- if (llvm::Optional<DataExtractor> expr =
- GetLocationExpression(func_load_addr, address)) {
- DumpLocation(s, *expr, level, abi);
- return true;
- }
- return false;
-}
-
static bool Evaluate_DW_OP_entry_value(std::vector<Value> &stack,
ExecutionContext *exe_ctx,
RegisterContext *reg_ctx,
@@ -794,7 +686,8 @@
const CallSiteParameter *matched_param = nullptr;
for (const CallSiteParameter ¶m : call_edge->GetCallSiteParameters()) {
DataExtractor param_subexpr_extractor;
- if (!param.LocationInCallee.GetExpressionData(param_subexpr_extractor))
+ if (!param.LocationInCallee.GetExpressionAtAddress(0)->GetExpressionData(
+ param_subexpr_extractor))
continue;
lldb::offset_t param_subexpr_offset = 0;
const void *param_subexpr_data =
@@ -824,10 +717,9 @@
// TODO: Add support for DW_OP_push_object_address within a DW_OP_entry_value
// subexpresion whenever llvm does.
Value result;
- const DWARFExpression ¶m_expr = matched_param->LocationInCaller;
+ const DWARFExpressionList ¶m_expr = matched_param->LocationInCaller;
if (!param_expr.Evaluate(&parent_exe_ctx,
parent_frame->GetRegisterContext().get(),
- /*loclist_base_load_addr=*/LLDB_INVALID_ADDRESS,
/*initial_value_ptr=*/nullptr,
/*object_address_ptr=*/nullptr, result, error_ptr)) {
LLDB_LOG(log,
@@ -839,63 +731,6 @@
return true;
}
-bool DWARFExpression::Evaluate(ExecutionContextScope *exe_scope,
- lldb::addr_t loclist_base_load_addr,
- const Value *initial_value_ptr,
- const Value *object_address_ptr, Value &result,
- Status *error_ptr) const {
- ExecutionContext exe_ctx(exe_scope);
- return Evaluate(&exe_ctx, nullptr, loclist_base_load_addr, initial_value_ptr,
- object_address_ptr, result, error_ptr);
-}
-
-bool DWARFExpression::Evaluate(ExecutionContext *exe_ctx,
- RegisterContext *reg_ctx,
- lldb::addr_t func_load_addr,
- const Value *initial_value_ptr,
- const Value *object_address_ptr, Value &result,
- Status *error_ptr) const {
- ModuleSP module_sp = m_module_wp.lock();
-
- if (IsLocationList()) {
- Address pc;
- StackFrame *frame = nullptr;
- 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;
- reg_ctx_sp->GetPCForSymbolication(pc);
- }
-
- if (func_load_addr != LLDB_INVALID_ADDRESS) {
- if (!pc.IsValid()) {
- if (error_ptr)
- error_ptr->SetErrorString("Invalid PC in frame.");
- return false;
- }
-
- 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);
- }
- }
- if (error_ptr)
- error_ptr->SetErrorString("variable not available");
- return false;
- }
-
- // Not a location list, just a single expression.
- return DWARFExpression::Evaluate(exe_ctx, reg_ctx, module_sp, m_data,
- m_dwarf_cu, m_reg_kind, initial_value_ptr,
- object_address_ptr, result, error_ptr);
-}
-
namespace {
/// The location description kinds described by the DWARF v5
/// specification. Composite locations are handled out-of-band and
@@ -2743,82 +2578,33 @@
return true; // Return true on success
}
-static DataExtractor ToDataExtractor(const llvm::DWARFLocationExpression &loc,
- ByteOrder byte_order, uint32_t addr_size) {
- auto buffer_sp =
- std::make_shared<DataBufferHeap>(loc.Expr.data(), loc.Expr.size());
- return DataExtractor(buffer_sp, byte_order, addr_size);
-}
-
-bool DWARFExpression::DumpLocations(Stream *s, lldb::DescriptionLevel level,
- addr_t load_function_start, addr_t addr,
- ABI *abi) {
- if (!IsLocationList()) {
- DumpLocation(s, m_data, level, abi);
- return true;
- }
- bool dump_all = addr == LLDB_INVALID_ADDRESS;
- llvm::ListSeparator separator;
- auto callback = [&](llvm::DWARFLocationExpression loc) -> bool {
- if (loc.Range &&
- (dump_all || (loc.Range->LowPC <= addr && addr < loc.Range->HighPC))) {
- uint32_t addr_size = m_data.GetAddressByteSize();
- DataExtractor data = ToDataExtractor(loc, m_data.GetByteOrder(),
- m_data.GetAddressByteSize());
- s->AsRawOstream() << separator;
- s->PutCString("[");
- s->AsRawOstream() << llvm::format_hex(loc.Range->LowPC,
- 2 + 2 * addr_size);
- s->PutCString(", ");
- s->AsRawOstream() << llvm::format_hex(loc.Range->HighPC,
- 2 + 2 * addr_size);
- s->PutCString(") -> ");
- DumpLocation(s, data, level, abi);
- return dump_all;
- }
- return true;
- };
- if (!GetLocationExpressions(load_function_start, callback))
- return false;
- return true;
-}
-
-bool DWARFExpression::GetLocationExpressions(
- addr_t load_function_start,
- llvm::function_ref<bool(llvm::DWARFLocationExpression)> callback) const {
- if (load_function_start == LLDB_INVALID_ADDRESS)
- return false;
-
- Log *log = GetLog(LLDBLog::Expressions);
-
+bool DWARFExpression::ParseDWARFLocationList(
+ const DWARFUnit *dwarf_cu, const DataExtractor &data,
+ DWARFExpressionList *location_list) {
+ location_list->Clear();
std::unique_ptr<llvm::DWARFLocationTable> loctable_up =
- m_dwarf_cu->GetLocationTable(m_data);
-
- uint64_t offset = 0;
+ dwarf_cu->GetLocationTable(data);
auto lookup_addr =
[&](uint32_t index) -> llvm::Optional<llvm::object::SectionedAddress> {
- addr_t address = ReadAddressFromDebugAddrSection(m_dwarf_cu, index);
+ addr_t address = ReadAddressFromDebugAddrSection(dwarf_cu, index);
if (address == LLDB_INVALID_ADDRESS)
return llvm::None;
return llvm::object::SectionedAddress{address};
};
auto process_list = [&](llvm::Expected<llvm::DWARFLocationExpression> loc) {
- if (!loc) {
- LLDB_LOG_ERROR(log, loc.takeError(), "{0}");
+ if (!loc)
return true;
- }
- if (loc->Range) {
- // This relocates low_pc and high_pc by adding the difference between the
- // function file address, and the actual address it is loaded in memory.
- addr_t slide = load_function_start - m_loclist_addresses->func_file_addr;
- loc->Range->LowPC += slide;
- loc->Range->HighPC += slide;
- }
- return callback(*loc);
+ auto buffer_sp =
+ std::make_shared<DataBufferHeap>(loc->Expr.data(), loc->Expr.size());
+ DWARFExpression expr = DWARFExpression(DataExtractor(
+ buffer_sp, data.GetByteOrder(), data.GetAddressByteSize()));
+ location_list->AddExpression(loc->Range->LowPC, loc->Range->HighPC, expr);
+ return true;
};
llvm::Error error = loctable_up->visitAbsoluteLocationList(
- offset, llvm::object::SectionedAddress{m_loclist_addresses->cu_file_addr},
+ 0, llvm::object::SectionedAddress{dwarf_cu->GetBaseAddress()},
lookup_addr, process_list);
+ Log *log = GetLog(LLDBLog::Expressions);
if (error) {
LLDB_LOG_ERROR(log, std::move(error), "{0}");
return false;
@@ -2826,21 +2612,6 @@
return true;
}
-llvm::Optional<DataExtractor>
-DWARFExpression::GetLocationExpression(addr_t load_function_start,
- addr_t addr) const {
- llvm::Optional<DataExtractor> data;
- auto callback = [&](llvm::DWARFLocationExpression loc) {
- if (loc.Range && loc.Range->LowPC <= addr && addr < loc.Range->HighPC) {
- data = ToDataExtractor(loc, m_data.GetByteOrder(),
- m_data.GetAddressByteSize());
- }
- return !data;
- };
- GetLocationExpressions(load_function_start, callback);
- return data;
-}
-
bool DWARFExpression::MatchesOperand(StackFrame &frame,
const Instruction::Operand &operand) {
using namespace OperandMatchers;
@@ -2850,28 +2621,7 @@
return false;
}
- DataExtractor opcodes;
- if (IsLocationList()) {
- SymbolContext sc = frame.GetSymbolContext(eSymbolContextFunction);
- if (!sc.function)
- return false;
-
- addr_t load_function_start =
- sc.function->GetAddressRange().GetBaseAddress().GetFileAddress();
- if (load_function_start == LLDB_INVALID_ADDRESS)
- return false;
-
- addr_t pc = frame.GetFrameCodeAddressForSymbolication().GetLoadAddress(
- frame.CalculateTarget().get());
-
- if (llvm::Optional<DataExtractor> expr =
- GetLocationExpression(load_function_start, pc))
- opcodes = std::move(*expr);
- else
- return false;
- } else
- opcodes = m_data;
-
+ DataExtractor opcodes(m_data);
lldb::offset_t op_offset = 0;
uint8_t opcode = opcodes.GetU8(&op_offset);
@@ -2879,7 +2629,7 @@
if (opcode == DW_OP_fbreg) {
int64_t offset = opcodes.GetSLEB128(&op_offset);
- DWARFExpression *fb_expr = frame.GetFrameBaseExpression(nullptr);
+ DWARFExpressionList *fb_expr = frame.GetFrameBaseExpression(nullptr);
if (!fb_expr) {
return false;
}
Index: lldb/source/Expression/CMakeLists.txt
===================================================================
--- lldb/source/Expression/CMakeLists.txt
+++ lldb/source/Expression/CMakeLists.txt
@@ -1,6 +1,7 @@
add_lldb_library(lldbExpression
DiagnosticManager.cpp
DWARFExpression.cpp
+ DWARFExpressionList.cpp
Expression.cpp
ExpressionVariable.cpp
FunctionCaller.cpp
Index: lldb/source/Core/ValueObjectVariable.cpp
===================================================================
--- lldb/source/Core/ValueObjectVariable.cpp
+++ lldb/source/Core/ValueObjectVariable.cpp
@@ -13,7 +13,7 @@
#include "lldb/Core/Declaration.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/Value.h"
-#include "lldb/Expression/DWARFExpression.h"
+#include "lldb/Expression/DWARFExpressionList.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/SymbolContext.h"
@@ -127,22 +127,20 @@
m_error.Clear();
Variable *variable = m_variable_sp.get();
- DWARFExpression &expr = variable->LocationExpression();
+ DWARFExpressionList &expr_list = variable->LocationExpressionList();
if (variable->GetLocationIsConstantValueData()) {
// expr doesn't contain DWARF bytes, it contains the constant variable
// value bytes themselves...
- if (expr.GetExpressionData(m_data)) {
- if (m_data.GetDataStart() && m_data.GetByteSize())
+ if (expr_list.GetExpressionData(m_data)) {
+ if (m_data.GetDataStart() && m_data.GetByteSize())
m_value.SetBytes(m_data.GetDataStart(), m_data.GetByteSize());
m_value.SetContext(Value::ContextType::Variable, variable);
- }
- else
+ } else
m_error.SetErrorString("empty constant data");
// constant bytes can't be edited - sorry
m_resolved_value.SetContext(Value::ContextType::Invalid, nullptr);
} else {
- lldb::addr_t loclist_base_load_addr = LLDB_INVALID_ADDRESS;
ExecutionContext exe_ctx(GetExecutionContextRef());
Target *target = exe_ctx.GetTargetPtr();
@@ -151,17 +149,8 @@
m_data.SetAddressByteSize(target->GetArchitecture().GetAddressByteSize());
}
- if (expr.IsLocationList()) {
- SymbolContext sc;
- variable->CalculateSymbolContext(&sc);
- if (sc.function)
- loclist_base_load_addr =
- sc.function->GetAddressRange().GetBaseAddress().GetLoadAddress(
- target);
- }
Value old_value(m_value);
- if (expr.Evaluate(&exe_ctx, nullptr, loclist_base_load_addr, nullptr,
- nullptr, m_value, &m_error)) {
+ if (expr_list.Evaluate(&exe_ctx, nullptr, nullptr, nullptr, m_value, &m_error)) {
m_resolved_value = m_value;
m_value.SetContext(Value::ContextType::Variable, variable);
@@ -246,7 +235,7 @@
m_resolved_value.SetContext(Value::ContextType::Invalid, nullptr);
}
}
-
+
return m_error.Success();
}
Index: lldb/include/lldb/lldb-forward.h
===================================================================
--- lldb/include/lldb/lldb-forward.h
+++ lldb/include/lldb/lldb-forward.h
@@ -66,6 +66,7 @@
class DWARFCallFrameInfo;
class DWARFDataExtractor;
class DWARFExpression;
+class DWARFExpressionList;
class DataBuffer;
class WritableDataBuffer;
class DataBufferHeap;
Index: lldb/include/lldb/Target/StackFrame.h
===================================================================
--- lldb/include/lldb/Target/StackFrame.h
+++ lldb/include/lldb/Target/StackFrame.h
@@ -202,7 +202,7 @@
/// frames may be unable to provide this value; they will return false.
bool GetFrameBaseValue(Scalar &value, Status *error_ptr);
- /// Get the DWARFExpression corresponding to the Canonical Frame Address.
+ /// Get the DWARFExpressionList corresponding to the Canonical Frame Address.
///
/// Often a register (bp), but sometimes a register + offset.
///
@@ -212,7 +212,7 @@
///
/// \return
/// Returns the corresponding DWARF expression, or NULL.
- DWARFExpression *GetFrameBaseExpression(Status *error_ptr);
+ DWARFExpressionList *GetFrameBaseExpression(Status *error_ptr);
/// Get the current lexical scope block for this StackFrame, if possible.
///
Index: lldb/include/lldb/Symbol/Variable.h
===================================================================
--- lldb/include/lldb/Symbol/Variable.h
+++ lldb/include/lldb/Symbol/Variable.h
@@ -11,7 +11,7 @@
#include "lldb/Core/Declaration.h"
#include "lldb/Core/Mangled.h"
-#include "lldb/Expression/DWARFExpression.h"
+#include "lldb/Expression/DWARFExpressionList.h"
#include "lldb/Utility/CompletionRequest.h"
#include "lldb/Utility/RangeMap.h"
#include "lldb/Utility/UserID.h"
@@ -32,8 +32,8 @@
Variable(lldb::user_id_t uid, const char *name, const char *mangled,
const lldb::SymbolFileTypeSP &symfile_type_sp, lldb::ValueType scope,
SymbolContextScope *owner_scope, const RangeList &scope_range,
- Declaration *decl, const DWARFExpression &location, bool external,
- bool artificial, bool location_is_constant_data,
+ Declaration *decl, const DWARFExpressionList &location,
+ bool external, bool artificial, bool location_is_constant_data,
bool static_member = false);
virtual ~Variable();
@@ -73,9 +73,11 @@
bool IsStaticMember() const { return m_static_member; }
- DWARFExpression &LocationExpression() { return m_location; }
+ DWARFExpressionList &LocationExpressionList() { return m_location_list; }
- const DWARFExpression &LocationExpression() const { return m_location; }
+ const DWARFExpressionList &LocationExpressionList() const {
+ return m_location_list;
+ }
// When given invalid address, it dumps all locations. Otherwise it only dumps
// the location that contains this address.
@@ -128,7 +130,7 @@
Declaration m_declaration;
/// The location of this variable that can be fed to
/// DWARFExpression::Evaluate().
- DWARFExpression m_location;
+ DWARFExpressionList m_location_list;
/// Visible outside the containing compile unit?
unsigned m_external : 1;
/// Non-zero if the variable is not explicitly declared in source.
Index: lldb/include/lldb/Symbol/Function.h
===================================================================
--- lldb/include/lldb/Symbol/Function.h
+++ lldb/include/lldb/Symbol/Function.h
@@ -12,7 +12,7 @@
#include "lldb/Core/AddressRange.h"
#include "lldb/Core/Declaration.h"
#include "lldb/Core/Mangled.h"
-#include "lldb/Expression/DWARFExpression.h"
+#include "lldb/Expression/DWARFExpressionList.h"
#include "lldb/Symbol/Block.h"
#include "lldb/Utility/UserID.h"
#include "llvm/ADT/ArrayRef.h"
@@ -253,8 +253,8 @@
/// Represent the locations of a parameter at a call site, both in the caller
/// and in the callee.
struct CallSiteParameter {
- DWARFExpression LocationInCallee;
- DWARFExpression LocationInCaller;
+ DWARFExpressionList LocationInCallee;
+ DWARFExpressionList LocationInCaller;
};
/// A vector of \c CallSiteParameter.
@@ -370,7 +370,7 @@
public:
/// Construct a call edge using a DWARFExpression to identify the callee, and
/// a return PC within the calling function to identify a specific call site.
- IndirectCallEdge(DWARFExpression call_target, AddrType caller_address_type,
+ IndirectCallEdge(DWARFExpressionList call_target, AddrType caller_address_type,
lldb::addr_t caller_address, bool is_tail_call,
CallSiteParameterArray &¶meters)
: CallEdge(caller_address_type, caller_address, is_tail_call,
@@ -383,7 +383,7 @@
// Used to describe an indirect call.
//
// Specifies the location of the callee address in the calling frame.
- DWARFExpression call_target;
+ DWARFExpressionList call_target;
};
/// \class Function Function.h "lldb/Symbol/Function.h"
@@ -521,13 +521,13 @@
/// \return
/// A location expression that describes the function frame
/// base.
- DWARFExpression &GetFrameBaseExpression() { return m_frame_base; }
+ DWARFExpressionList &GetFrameBaseExpression() { return m_frame_base; }
/// Get const accessor for the frame base location.
///
/// \return
/// A const compile unit object pointer.
- const DWARFExpression &GetFrameBaseExpression() const { return m_frame_base; }
+ const DWARFExpressionList &GetFrameBaseExpression() const { return m_frame_base; }
ConstString GetName() const;
@@ -659,7 +659,7 @@
/// The frame base expression for variables that are relative to the frame
/// pointer.
- DWARFExpression m_frame_base;
+ DWARFExpressionList m_frame_base;
Flags m_flags;
Index: lldb/include/lldb/Expression/DWARFExpressionList.h
===================================================================
--- /dev/null
+++ lldb/include/lldb/Expression/DWARFExpressionList.h
@@ -0,0 +1,126 @@
+//===-- DWARFExpressionList.h ---------------------------------------*- C++
+//-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDB_EXPRESSION_DWARFEXPRESSIONLIST_H
+#define LLDB_EXPRESSION_DWARFEXPRESSIONLIST_H
+
+#include "lldb/Expression/DWARFExpression.h"
+#include "lldb/Utility/RangeMap.h"
+#include "lldb/lldb-private.h"
+#include "llvm/ADT/Optional.h"
+
+class DWARFUnit;
+
+namespace lldb_private {
+
+// It's the interface to get or evaluate a DWARFExpression.
+class DWARFExpressionList {
+private:
+ // RangeDataVector requires a comparator for DWARFExpression, but it doesn't
+ // make sense to do so.
+ struct DWARFExpressionCompare {
+ public:
+ bool operator()(const DWARFExpression &lhs,
+ const DWARFExpression &rhs) const {
+ return true;
+ }
+ };
+
+ // File address range mapping to single dwarf expression.
+ RangeDataVector<lldb::addr_t, lldb::addr_t, DWARFExpression, 0,
+ DWARFExpressionCompare>
+ m_exprs;
+
+ /// Module which defined this expression.
+ lldb::ModuleWP m_module_wp;
+
+ /// The DWARF compile unit this expression belongs to. It is used to evaluate
+ /// values indexing into the .debug_addr section (e.g. DW_OP_GNU_addr_index,
+ /// DW_OP_GNU_const_index)
+ const DWARFUnit *m_dwarf_cu = nullptr;
+
+ typedef RangeDataVector<lldb::addr_t, lldb::addr_t, DWARFExpression, 0,
+ DWARFExpressionCompare>::Entry Entry;
+
+ void ForAllLocations(const std::function<bool(const Entry *)> &fn) const;
+
+public:
+ DWARFExpressionList() = default;
+
+ DWARFExpressionList(lldb::ModuleSP module_sp, const DWARFUnit *dwarf_cu)
+ : m_module_wp(), m_dwarf_cu(dwarf_cu) {
+ if (module_sp)
+ m_module_wp = module_sp;
+ }
+
+ DWARFExpressionList(lldb::ModuleSP module_sp, DWARFExpression expr,
+ const DWARFUnit *dwarf_cu)
+ : DWARFExpressionList(module_sp, dwarf_cu) {
+ AddExpression(0, LLDB_INVALID_ADDRESS, expr);
+ }
+
+ /// Return true if the location expression contains data
+ bool IsValid() const { return !m_exprs.IsEmpty(); }
+
+ void Clear() { m_exprs.Clear(); }
+
+ bool AddExpression(lldb::addr_t base, lldb::addr_t end, DWARFExpression expr);
+
+ /// Only useful when the size is equal to 1.
+ bool GetExpressionData(DataExtractor &data) const;
+
+ /// Sort m_expressions.
+ void FinishExpressions() { m_exprs.Sort(); }
+
+ const DWARFExpression *GetExpressionAtAddress(lldb::addr_t file_addr) const;
+
+ DWARFExpression *GetMutableExpressionAtAddress(lldb::addr_t file_addr);
+
+ size_t GetSize() const { return m_exprs.GetSize(); }
+
+ bool ContainsThreadLocalStorage() const;
+
+ bool LinkThreadLocalStorage(
+ lldb::ModuleSP new_module_sp,
+ std::function<lldb::addr_t(lldb::addr_t file_addr)> const
+ &link_address_callback);
+
+ bool MatchesOperand(StackFrame &frame, const Instruction::Operand &operand);
+
+ /// Dump locations that contains file_addr if it's valid. Otherwise. dump all
+ /// locations.
+ bool DumpLocations(Stream *s, lldb::DescriptionLevel level,
+ lldb::addr_t file_addr, ABI *abi) const;
+
+ /// Dump all locaitons using DWARFLocationTable::dumpLocationList format.
+ void GetDescription(Stream *s, lldb::DescriptionLevel level, ABI *abi) const;
+
+ /// Search for a load address in the location list
+ ///
+ /// \param[in] file_addr
+ /// The file address to resolve
+ ///
+ /// \return
+ /// True if IsLocationList() is true and the address was found;
+ /// false otherwise.
+ // bool
+ // LocationListContainsLoadAddress (Process* process, const Address &addr)
+ // const;
+ //
+ bool ContainsAddress(lldb::addr_t file_addr) const;
+
+ void SetModule(const lldb::ModuleSP &module) { m_module_wp = module; }
+
+ bool Evaluate(ExecutionContext *exe_ctx, RegisterContext *reg_ctx,
+ const Value *initial_value_ptr, const Value *object_address_ptr,
+ Value &result, Status *error_ptr) const;
+};
+} // namespace lldb_private
+
+#endif // LLDB_EXPRESSION_DWARFEXPRESSIONLIST_H
\ No newline at end of file
Index: lldb/include/lldb/Expression/DWARFExpression.h
===================================================================
--- lldb/include/lldb/Expression/DWARFExpression.h
+++ lldb/include/lldb/Expression/DWARFExpression.h
@@ -42,49 +42,14 @@
/// \param[in] data
/// A data extractor configured to read the DWARF location expression's
/// bytecode.
- DWARFExpression(lldb::ModuleSP module, const DataExtractor &data,
- const DWARFUnit *dwarf_cu);
+ DWARFExpression(const DataExtractor &data);
/// Destructor
virtual ~DWARFExpression();
- /// Print the description of the expression to a stream
- ///
- /// \param[in] s
- /// The stream to print to.
- ///
- /// \param[in] level
- /// The level of verbosity to use.
- ///
- /// \param[in] abi
- /// An optional ABI plug-in that can be used to resolve register
- /// names.
- void GetDescription(Stream *s, lldb::DescriptionLevel level, ABI *abi) const;
-
/// Return true if the location expression contains data
bool IsValid() const;
- /// Return true if a location list was provided
- bool IsLocationList() const;
-
- /// Search for a load address in the location list
- ///
- /// \param[in] func_load_addr
- /// The actual address of the function containing this location list.
- ///
- /// \param[in] addr
- /// The address to resolve
- ///
- /// \return
- /// True if IsLocationList() is true and the address was found;
- /// false otherwise.
- // bool
- // LocationListContainsLoadAddress (Process* process, const Address &addr)
- // const;
- //
- bool LocationListContainsAddress(lldb::addr_t func_load_addr,
- lldb::addr_t addr) const;
-
/// If a location is not a location list, return true if the location
/// contains a DW_OP_addr () opcode in the stream that matches \a file_addr.
/// If file_addr is LLDB_INVALID_ADDRESS, the this function will return true
@@ -93,6 +58,9 @@
/// static variable since there is no other indication from DWARF debug
/// info.
///
+ /// \param[in] dwarf_cu
+ /// The dwarf unit this expression belongs to.
+ ///
/// \param[in] op_addr_idx
/// The DW_OP_addr index to retrieve in case there is more than
/// one DW_OP_addr opcode in the location byte stream.
@@ -104,36 +72,22 @@
/// \return
/// LLDB_INVALID_ADDRESS if the location doesn't contain a
/// DW_OP_addr for \a op_addr_idx, otherwise a valid file address
- lldb::addr_t GetLocation_DW_OP_addr(uint32_t op_addr_idx, bool &error) const;
+ lldb::addr_t GetLocation_DW_OP_addr(const DWARFUnit *dwarf_cu,
+ uint32_t op_addr_idx, bool &error) const;
bool Update_DW_OP_addr(lldb::addr_t file_addr);
void UpdateValue(uint64_t const_value, lldb::offset_t const_value_byte_size,
uint8_t addr_byte_size);
- void SetModule(const lldb::ModuleSP &module) { m_module_wp = module; }
-
bool ContainsThreadLocalStorage() const;
bool LinkThreadLocalStorage(
- lldb::ModuleSP new_module_sp,
std::function<lldb::addr_t(lldb::addr_t file_addr)> const
&link_address_callback);
- /// Tells the expression that it refers to a location list.
- ///
- /// \param[in] cu_file_addr
- /// The base address to use for interpreting relative location list
- /// entries.
- /// \param[in] func_file_addr
- /// The file address of the function containing this location list. This
- /// address will be used to relocate the location list on the fly (in
- /// conjuction with the func_load_addr arguments).
- void SetLocationListAddresses(lldb::addr_t cu_file_addr,
- lldb::addr_t func_file_addr);
-
/// Return the call-frame-info style register kind
- int GetRegisterKind();
+ lldb::RegisterKind GetRegisterKind() const;
/// Set the call-frame-info style register kind
///
@@ -141,20 +95,6 @@
/// The register kind.
void SetRegisterKind(lldb::RegisterKind reg_kind);
- /// Wrapper for the static evaluate function that accepts an
- /// ExecutionContextScope instead of an ExecutionContext and uses member
- /// variables to populate many operands
- bool Evaluate(ExecutionContextScope *exe_scope, lldb::addr_t func_load_addr,
- const Value *initial_value_ptr, const Value *object_address_ptr,
- Value &result, Status *error_ptr) const;
-
- /// Wrapper for the static evaluate function that uses member variables to
- /// populate many operands
- bool Evaluate(ExecutionContext *exe_ctx, RegisterContext *reg_ctx,
- lldb::addr_t loclist_base_load_addr,
- const Value *initial_value_ptr, const Value *object_address_ptr,
- Value &result, Status *error_ptr) const;
-
/// Evaluate a DWARF location expression in a particular context
///
/// \param[in] exe_ctx
@@ -201,65 +141,25 @@
const Value *object_address_ptr, Value &result,
Status *error_ptr);
+ static bool ParseDWARFLocationList(const DWARFUnit *dwarf_cu,
+ const DataExtractor &data,
+ DWARFExpressionList *loc_list);
+
bool GetExpressionData(DataExtractor &data) const {
data = m_data;
return data.GetByteSize() > 0;
}
- bool DumpLocationForAddress(Stream *s, lldb::DescriptionLevel level,
- lldb::addr_t func_load_addr, lldb::addr_t address,
- ABI *abi);
-
- bool DumpLocations(Stream *s, lldb::DescriptionLevel level,
- lldb::addr_t func_load_addr, lldb::addr_t addr, ABI *abi);
-
- bool GetLocationExpressions(
- lldb::addr_t load_function_start,
- llvm::function_ref<bool(llvm::DWARFLocationExpression)> callback) const;
+ void DumpLocation(Stream *s, lldb::DescriptionLevel level, ABI *abi) const;
bool MatchesOperand(StackFrame &frame, const Instruction::Operand &op);
- llvm::Optional<DataExtractor>
- GetLocationExpression(lldb::addr_t load_function_start,
- lldb::addr_t addr) const;
-
private:
- /// Pretty-prints the location expression to a stream
- ///
- /// \param[in] s
- /// The stream to use for pretty-printing.
- ///
- /// \param[in] data
- /// The data extractor.
- ///
- /// \param[in] level
- /// The level of detail to use in pretty-printing.
- ///
- /// \param[in] abi
- /// An optional ABI plug-in that can be used to resolve register
- /// names.
- void DumpLocation(Stream *s, const DataExtractor &data,
- lldb::DescriptionLevel level, ABI *abi) const;
-
- /// Module which defined this expression.
- lldb::ModuleWP m_module_wp;
-
/// A data extractor capable of reading opcode bytes
DataExtractor m_data;
- /// The DWARF compile unit this expression belongs to. It is used to evaluate
- /// values indexing into the .debug_addr section (e.g. DW_OP_GNU_addr_index,
- /// DW_OP_GNU_const_index)
- const DWARFUnit *m_dwarf_cu = nullptr;
-
/// One of the defines that starts with LLDB_REGKIND_
lldb::RegisterKind m_reg_kind = lldb::eRegisterKindDWARF;
-
- struct LoclistAddresses {
- lldb::addr_t cu_file_addr;
- lldb::addr_t func_file_addr;
- };
- llvm::Optional<LoclistAddresses> m_loclist_addresses;
};
} // namespace lldb_private
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits