Skip to content

[LLDB][NFC] Added the interface DWARFExpression::Delegate to break dependencies and reduce lldb-server size #131645

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Mar 24, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 31 additions & 19 deletions lldb/include/lldb/Expression/DWARFExpression.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

#include "lldb/Core/Address.h"
#include "lldb/Core/Disassembler.h"
#include "lldb/Core/dwarf.h"
#include "lldb/Utility/DataExtractor.h"
#include "lldb/Utility/Scalar.h"
#include "lldb/Utility/Status.h"
Expand All @@ -21,12 +22,6 @@

namespace lldb_private {

namespace plugin {
namespace dwarf {
class DWARFUnit;
} // namespace dwarf
} // namespace plugin

/// \class DWARFExpression DWARFExpression.h
/// "lldb/Expression/DWARFExpression.h" Encapsulates a DWARF location
/// expression and interprets it.
Expand All @@ -40,6 +35,30 @@ class DWARFUnit;
/// location expression or a location list and interprets it.
class DWARFExpression {
public:
class Delegate {
public:
Delegate() = default;
virtual ~Delegate() = default;

virtual uint16_t GetVersion() const = 0;
virtual dw_addr_t GetBaseAddress() const = 0;
virtual uint8_t GetAddressByteSize() const = 0;
virtual llvm::Expected<std::pair<uint64_t, bool>>
GetDIEBitSizeAndSign(uint64_t relative_die_offset) const = 0;
virtual dw_addr_t ReadAddressFromDebugAddrSection(uint32_t index) const = 0;
virtual lldb::offset_t
GetVendorDWARFOpcodeSize(const DataExtractor &data,
const lldb::offset_t data_offset,
const uint8_t op) const = 0;
virtual bool ParseVendorDWARFOpcode(uint8_t op,
const DataExtractor &opcodes,
lldb::offset_t &offset,
std::vector<Value> &stack) const = 0;

Delegate(const Delegate &) = delete;
Delegate &operator=(const Delegate &) = delete;
};

DWARFExpression();

/// Constructor
Expand All @@ -66,19 +85,17 @@ class DWARFExpression {
/// The address specified by the operation, if the operation exists, or
/// an llvm::Error otherwise.
llvm::Expected<lldb::addr_t>
GetLocation_DW_OP_addr(const plugin::dwarf::DWARFUnit *dwarf_cu) const;
GetLocation_DW_OP_addr(const Delegate *dwarf_cu) const;

bool Update_DW_OP_addr(const plugin::dwarf::DWARFUnit *dwarf_cu,
lldb::addr_t file_addr);
bool Update_DW_OP_addr(const Delegate *dwarf_cu, lldb::addr_t file_addr);

void UpdateValue(uint64_t const_value, lldb::offset_t const_value_byte_size,
uint8_t addr_byte_size);

bool
ContainsThreadLocalStorage(const plugin::dwarf::DWARFUnit *dwarf_cu) const;
bool ContainsThreadLocalStorage(const Delegate *dwarf_cu) const;

bool LinkThreadLocalStorage(
const plugin::dwarf::DWARFUnit *dwarf_cu,
const Delegate *dwarf_cu,
std::function<lldb::addr_t(lldb::addr_t file_addr)> const
&link_address_callback);

Expand Down Expand Up @@ -132,13 +149,8 @@ class DWARFExpression {
static llvm::Expected<Value>
Evaluate(ExecutionContext *exe_ctx, RegisterContext *reg_ctx,
lldb::ModuleSP module_sp, const DataExtractor &opcodes,
const plugin::dwarf::DWARFUnit *dwarf_cu,
const lldb::RegisterKind reg_set, const Value *initial_value_ptr,
const Value *object_address_ptr);

static bool ParseDWARFLocationList(const plugin::dwarf::DWARFUnit *dwarf_cu,
const DataExtractor &data,
DWARFExpressionList *loc_list);
const Delegate *dwarf_cu, const lldb::RegisterKind reg_set,
const Value *initial_value_ptr, const Value *object_address_ptr);

bool GetExpressionData(DataExtractor &data) const {
data = m_data;
Expand Down
130 changes: 38 additions & 92 deletions lldb/source/Expression/DWARFExpression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@

#include "lldb/Core/Module.h"
#include "lldb/Core/Value.h"
#include "lldb/Core/dwarf.h"
#include "lldb/Utility/DataEncoder.h"
#include "lldb/Utility/LLDBLog.h"
#include "lldb/Utility/Log.h"
Expand All @@ -37,11 +36,8 @@
#include "lldb/Target/StackID.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
#include "llvm/DebugInfo/DWARF/DWARFExpression.h"

#include "Plugins/SymbolFile/DWARF/DWARFUnit.h"

using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::dwarf;
Expand Down Expand Up @@ -130,10 +126,10 @@ static llvm::Error ReadRegisterValueAsScalar(RegisterContext *reg_ctx,

/// Return the length in bytes of the set of operands for \p op. No guarantees
/// are made on the state of \p data after this call.
static lldb::offset_t GetOpcodeDataSize(const DataExtractor &data,
const lldb::offset_t data_offset,
const LocationAtom op,
const DWARFUnit *dwarf_cu) {
static lldb::offset_t
GetOpcodeDataSize(const DataExtractor &data, const lldb::offset_t data_offset,
const LocationAtom op,
const DWARFExpression::Delegate *dwarf_cu) {
lldb::offset_t offset = data_offset;
switch (op) {
// Only used in LLVM metadata.
Expand Down Expand Up @@ -362,7 +358,8 @@ static lldb::offset_t GetOpcodeDataSize(const DataExtractor &data,
// + LEB128
{
data.Skip_LEB128(&offset);
return DWARFUnit::GetAddressByteSize(dwarf_cu) + offset - data_offset;
return (dwarf_cu ? dwarf_cu->GetAddressByteSize() : 4) + offset -
data_offset;
}

case DW_OP_GNU_entry_value:
Expand All @@ -387,14 +384,23 @@ static lldb::offset_t GetOpcodeDataSize(const DataExtractor &data,
}

if (dwarf_cu)
return dwarf_cu->GetSymbolFileDWARF().GetVendorDWARFOpcodeSize(
data, data_offset, op);
return dwarf_cu->GetVendorDWARFOpcodeSize(data, data_offset, op);

return LLDB_INVALID_OFFSET;
}

llvm::Expected<lldb::addr_t>
DWARFExpression::GetLocation_DW_OP_addr(const DWARFUnit *dwarf_cu) const {
static const char *DW_OP_value_to_name(uint32_t val) {
static char invalid[100];
llvm::StringRef llvmstr = llvm::dwarf::OperationEncodingString(val);
if (llvmstr.empty()) {
snprintf(invalid, sizeof(invalid), "Unknown DW_OP constant: 0x%x", val);
return invalid;
}
return llvmstr.data();
}

llvm::Expected<lldb::addr_t> DWARFExpression::GetLocation_DW_OP_addr(
const DWARFExpression::Delegate *dwarf_cu) const {
lldb::offset_t offset = 0;
while (m_data.ValidOffset(offset)) {
const LocationAtom op = static_cast<LocationAtom>(m_data.GetU8(&offset));
Expand Down Expand Up @@ -422,8 +428,8 @@ DWARFExpression::GetLocation_DW_OP_addr(const DWARFUnit *dwarf_cu) const {
return LLDB_INVALID_ADDRESS;
}

bool DWARFExpression::Update_DW_OP_addr(const DWARFUnit *dwarf_cu,
lldb::addr_t file_addr) {
bool DWARFExpression::Update_DW_OP_addr(
const DWARFExpression::Delegate *dwarf_cu, lldb::addr_t file_addr) {
lldb::offset_t offset = 0;
while (m_data.ValidOffset(offset)) {
const LocationAtom op = static_cast<LocationAtom>(m_data.GetU8(&offset));
Expand Down Expand Up @@ -481,7 +487,7 @@ bool DWARFExpression::Update_DW_OP_addr(const DWARFUnit *dwarf_cu,
}

bool DWARFExpression::ContainsThreadLocalStorage(
const DWARFUnit *dwarf_cu) const {
const DWARFExpression::Delegate *dwarf_cu) const {
lldb::offset_t offset = 0;
while (m_data.ValidOffset(offset)) {
const LocationAtom op = static_cast<LocationAtom>(m_data.GetU8(&offset));
Expand All @@ -497,7 +503,7 @@ bool DWARFExpression::ContainsThreadLocalStorage(
return false;
}
bool DWARFExpression::LinkThreadLocalStorage(
const DWARFUnit *dwarf_cu,
const DWARFExpression::Delegate *dwarf_cu,
std::function<lldb::addr_t(lldb::addr_t file_addr)> const
&link_address_callback) {
const uint32_t addr_byte_size = m_data.GetAddressByteSize();
Expand Down Expand Up @@ -783,9 +789,9 @@ enum LocationDescriptionKind {
/* Composite*/
};
/// Adjust value's ValueType according to the kind of location description.
void UpdateValueTypeFromLocationDescription(Log *log, const DWARFUnit *dwarf_cu,
LocationDescriptionKind kind,
Value *value = nullptr) {
void UpdateValueTypeFromLocationDescription(
Log *log, const DWARFExpression::Delegate *dwarf_cu,
LocationDescriptionKind kind, Value *value = nullptr) {
// Note that this function is conflating DWARF expressions with
// DWARF location descriptions. Perhaps it would be better to define
// a wrapper for DWARFExpression::Eval() that deals with DWARF
Expand Down Expand Up @@ -875,8 +881,9 @@ static Scalar DerefSizeExtractDataHelper(uint8_t *addr_bytes,
llvm::Expected<Value> DWARFExpression::Evaluate(
ExecutionContext *exe_ctx, RegisterContext *reg_ctx,
lldb::ModuleSP module_sp, const DataExtractor &opcodes,
const DWARFUnit *dwarf_cu, const lldb::RegisterKind reg_kind,
const Value *initial_value_ptr, const Value *object_address_ptr) {
const DWARFExpression::Delegate *dwarf_cu,
const lldb::RegisterKind reg_kind, const Value *initial_value_ptr,
const Value *object_address_ptr) {

if (opcodes.GetByteSize() == 0)
return llvm::createStringError(
Expand Down Expand Up @@ -2150,10 +2157,10 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
// DESCRIPTION: Pop the top stack element, convert it to a
// different type, and push the result.
case DW_OP_convert: {
const uint64_t die_offset = opcodes.GetULEB128(&offset);
const uint64_t relative_die_offset = opcodes.GetULEB128(&offset);
uint64_t bit_size;
bool sign;
if (die_offset == 0) {
if (relative_die_offset == 0) {
// The generic type has the size of an address on the target
// machine and an unspecified signedness. Scalar has no
// "unspecified signedness", so we use unsigned types.
Expand All @@ -2164,35 +2171,12 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
if (!bit_size)
return llvm::createStringError("unspecified architecture");
} else {
// Retrieve the type DIE that the value is being converted to. This
// offset is compile unit relative so we need to fix it up.
const uint64_t abs_die_offset = die_offset + dwarf_cu->GetOffset();
// FIXME: the constness has annoying ripple effects.
DWARFDIE die = const_cast<DWARFUnit *>(dwarf_cu)->GetDIE(abs_die_offset);
if (!die)
return llvm::createStringError(
"cannot resolve DW_OP_convert type DIE");
uint64_t encoding =
die.GetAttributeValueAsUnsigned(DW_AT_encoding, DW_ATE_hi_user);
bit_size = die.GetAttributeValueAsUnsigned(DW_AT_byte_size, 0) * 8;
if (!bit_size)
bit_size = die.GetAttributeValueAsUnsigned(DW_AT_bit_size, 0);
if (!bit_size)
return llvm::createStringError(
"unsupported type size in DW_OP_convert");
switch (encoding) {
case DW_ATE_signed:
case DW_ATE_signed_char:
sign = true;
break;
case DW_ATE_unsigned:
case DW_ATE_unsigned_char:
sign = false;
break;
default:
return llvm::createStringError(
"unsupported encoding in DW_OP_convert");
}
auto bit_size_sign_or_err =
dwarf_cu->GetDIEBitSizeAndSign(relative_die_offset);
if (!bit_size_sign_or_err)
return bit_size_sign_or_err.takeError();
bit_size = bit_size_sign_or_err->first;
sign = bit_size_sign_or_err->second;
}
Scalar &top = stack.back().ResolveValue(exe_ctx);
top.TruncOrExtendTo(bit_size, sign);
Expand Down Expand Up @@ -2316,8 +2300,7 @@ llvm::Expected<Value> DWARFExpression::Evaluate(

default:
if (dwarf_cu) {
if (dwarf_cu->GetSymbolFileDWARF().ParseVendorDWARFOpcode(
op, opcodes, offset, stack)) {
if (dwarf_cu->ParseVendorDWARFOpcode(op, opcodes, offset, stack)) {
break;
}
}
Expand Down Expand Up @@ -2352,43 +2335,6 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
return stack.back();
}

bool DWARFExpression::ParseDWARFLocationList(
const DWARFUnit *dwarf_cu, const DataExtractor &data,
DWARFExpressionList *location_list) {
location_list->Clear();
std::unique_ptr<llvm::DWARFLocationTable> loctable_up =
dwarf_cu->GetLocationTable(data);
Log *log = GetLog(LLDBLog::Expressions);
auto lookup_addr =
[&](uint32_t index) -> std::optional<llvm::object::SectionedAddress> {
addr_t address = dwarf_cu->ReadAddressFromDebugAddrSection(index);
if (address == LLDB_INVALID_ADDRESS)
return std::nullopt;
return llvm::object::SectionedAddress{address};
};
auto process_list = [&](llvm::Expected<llvm::DWARFLocationExpression> loc) {
if (!loc) {
LLDB_LOG_ERROR(log, loc.takeError(), "{0}");
return true;
}
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(
0, llvm::object::SectionedAddress{dwarf_cu->GetBaseAddress()},
lookup_addr, process_list);
location_list->Sort();
if (error) {
LLDB_LOG_ERROR(log, std::move(error), "{0}");
return false;
}
return true;
}

bool DWARFExpression::MatchesOperand(
StackFrame &frame, const Instruction::Operand &operand) const {
using namespace OperandMatchers;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ bool DWARFDebugInfoEntry::GetDIENamesAndRanges(
data = DataExtractor(data, offset, data.GetByteSize() - offset);
if (lo_pc != LLDB_INVALID_ADDRESS) {
assert(lo_pc >= cu->GetBaseAddress());
DWARFExpression::ParseDWARFLocationList(cu, data, frame_base);
cu->ParseDWARFLocationList(data, *frame_base);
frame_base->SetFuncFileAddress(lo_pc);
} else
set_frame_base_loclist_addr = true;
Expand Down
10 changes: 0 additions & 10 deletions lldb/source/Plugins/SymbolFile/DWARF/DWARFDefines.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,5 @@ llvm::StringRef DW_TAG_value_to_name(dw_tag_t tag) {
return s_unknown_tag_name;
}

const char *DW_OP_value_to_name(uint32_t val) {
static char invalid[100];
llvm::StringRef llvmstr = llvm::dwarf::OperationEncodingString(val);
if (llvmstr.empty()) {
snprintf(invalid, sizeof(invalid), "Unknown DW_OP constant: 0x%x", val);
return invalid;
}
return llvmstr.data();
}

} // namespace dwarf
} // namespace lldb_private::plugin
2 changes: 0 additions & 2 deletions lldb/source/Plugins/SymbolFile/DWARF/DWARFDefines.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ namespace dwarf {

llvm::StringRef DW_TAG_value_to_name(dw_tag_t tag);

const char *DW_OP_value_to_name(uint32_t val);

} // namespace dwarf
} // namespace lldb_private::plugin

Expand Down
Loading