Skip to content

Commit 2edf534

Browse files
authored
[LLDB][NFC] Added the interface DWARFExpression::Delegate to break dependencies and reduce lldb-server size (llvm#131645)
This patch addresses the issue llvm#129543. After this patch DWARFExpression does not call DWARFUnit directly and does not depend on lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp and a lot of clang code. After this patch the size of lldb-server binary (Linux Aarch64) is reduced from 47MB to 17MB.
1 parent ea68d83 commit 2edf534

File tree

8 files changed

+175
-130
lines changed

8 files changed

+175
-130
lines changed

lldb/include/lldb/Expression/DWARFExpression.h

Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
#include "lldb/Core/Address.h"
1313
#include "lldb/Core/Disassembler.h"
14+
#include "lldb/Core/dwarf.h"
1415
#include "lldb/Utility/DataExtractor.h"
1516
#include "lldb/Utility/Scalar.h"
1617
#include "lldb/Utility/Status.h"
@@ -21,12 +22,6 @@
2122

2223
namespace lldb_private {
2324

24-
namespace plugin {
25-
namespace dwarf {
26-
class DWARFUnit;
27-
} // namespace dwarf
28-
} // namespace plugin
29-
3025
/// \class DWARFExpression DWARFExpression.h
3126
/// "lldb/Expression/DWARFExpression.h" Encapsulates a DWARF location
3227
/// expression and interprets it.
@@ -40,6 +35,30 @@ class DWARFUnit;
4035
/// location expression or a location list and interprets it.
4136
class DWARFExpression {
4237
public:
38+
class Delegate {
39+
public:
40+
Delegate() = default;
41+
virtual ~Delegate() = default;
42+
43+
virtual uint16_t GetVersion() const = 0;
44+
virtual dw_addr_t GetBaseAddress() const = 0;
45+
virtual uint8_t GetAddressByteSize() const = 0;
46+
virtual llvm::Expected<std::pair<uint64_t, bool>>
47+
GetDIEBitSizeAndSign(uint64_t relative_die_offset) const = 0;
48+
virtual dw_addr_t ReadAddressFromDebugAddrSection(uint32_t index) const = 0;
49+
virtual lldb::offset_t
50+
GetVendorDWARFOpcodeSize(const DataExtractor &data,
51+
const lldb::offset_t data_offset,
52+
const uint8_t op) const = 0;
53+
virtual bool ParseVendorDWARFOpcode(uint8_t op,
54+
const DataExtractor &opcodes,
55+
lldb::offset_t &offset,
56+
std::vector<Value> &stack) const = 0;
57+
58+
Delegate(const Delegate &) = delete;
59+
Delegate &operator=(const Delegate &) = delete;
60+
};
61+
4362
DWARFExpression();
4463

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

71-
bool Update_DW_OP_addr(const plugin::dwarf::DWARFUnit *dwarf_cu,
72-
lldb::addr_t file_addr);
90+
bool Update_DW_OP_addr(const Delegate *dwarf_cu, lldb::addr_t file_addr);
7391

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

77-
bool
78-
ContainsThreadLocalStorage(const plugin::dwarf::DWARFUnit *dwarf_cu) const;
95+
bool ContainsThreadLocalStorage(const Delegate *dwarf_cu) const;
7996

8097
bool LinkThreadLocalStorage(
81-
const plugin::dwarf::DWARFUnit *dwarf_cu,
98+
const Delegate *dwarf_cu,
8299
std::function<lldb::addr_t(lldb::addr_t file_addr)> const
83100
&link_address_callback);
84101

@@ -132,13 +149,8 @@ class DWARFExpression {
132149
static llvm::Expected<Value>
133150
Evaluate(ExecutionContext *exe_ctx, RegisterContext *reg_ctx,
134151
lldb::ModuleSP module_sp, const DataExtractor &opcodes,
135-
const plugin::dwarf::DWARFUnit *dwarf_cu,
136-
const lldb::RegisterKind reg_set, const Value *initial_value_ptr,
137-
const Value *object_address_ptr);
138-
139-
static bool ParseDWARFLocationList(const plugin::dwarf::DWARFUnit *dwarf_cu,
140-
const DataExtractor &data,
141-
DWARFExpressionList *loc_list);
152+
const Delegate *dwarf_cu, const lldb::RegisterKind reg_set,
153+
const Value *initial_value_ptr, const Value *object_address_ptr);
142154

143155
bool GetExpressionData(DataExtractor &data) const {
144156
data = m_data;

lldb/source/Expression/DWARFExpression.cpp

Lines changed: 38 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515

1616
#include "lldb/Core/Module.h"
1717
#include "lldb/Core/Value.h"
18-
#include "lldb/Core/dwarf.h"
1918
#include "lldb/Utility/DataEncoder.h"
2019
#include "lldb/Utility/LLDBLog.h"
2120
#include "lldb/Utility/Log.h"
@@ -37,11 +36,8 @@
3736
#include "lldb/Target/StackID.h"
3837
#include "lldb/Target/Target.h"
3938
#include "lldb/Target/Thread.h"
40-
#include "llvm/DebugInfo/DWARF/DWARFDebugLoc.h"
4139
#include "llvm/DebugInfo/DWARF/DWARFExpression.h"
4240

43-
#include "Plugins/SymbolFile/DWARF/DWARFUnit.h"
44-
4541
using namespace lldb;
4642
using namespace lldb_private;
4743
using namespace lldb_private::dwarf;
@@ -130,10 +126,10 @@ static llvm::Error ReadRegisterValueAsScalar(RegisterContext *reg_ctx,
130126

131127
/// Return the length in bytes of the set of operands for \p op. No guarantees
132128
/// are made on the state of \p data after this call.
133-
static lldb::offset_t GetOpcodeDataSize(const DataExtractor &data,
134-
const lldb::offset_t data_offset,
135-
const LocationAtom op,
136-
const DWARFUnit *dwarf_cu) {
129+
static lldb::offset_t
130+
GetOpcodeDataSize(const DataExtractor &data, const lldb::offset_t data_offset,
131+
const LocationAtom op,
132+
const DWARFExpression::Delegate *dwarf_cu) {
137133
lldb::offset_t offset = data_offset;
138134
switch (op) {
139135
// Only used in LLVM metadata.
@@ -362,7 +358,8 @@ static lldb::offset_t GetOpcodeDataSize(const DataExtractor &data,
362358
// + LEB128
363359
{
364360
data.Skip_LEB128(&offset);
365-
return DWARFUnit::GetAddressByteSize(dwarf_cu) + offset - data_offset;
361+
return (dwarf_cu ? dwarf_cu->GetAddressByteSize() : 4) + offset -
362+
data_offset;
366363
}
367364

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

389386
if (dwarf_cu)
390-
return dwarf_cu->GetSymbolFileDWARF().GetVendorDWARFOpcodeSize(
391-
data, data_offset, op);
387+
return dwarf_cu->GetVendorDWARFOpcodeSize(data, data_offset, op);
392388

393389
return LLDB_INVALID_OFFSET;
394390
}
395391

396-
llvm::Expected<lldb::addr_t>
397-
DWARFExpression::GetLocation_DW_OP_addr(const DWARFUnit *dwarf_cu) const {
392+
static const char *DW_OP_value_to_name(uint32_t val) {
393+
static char invalid[100];
394+
llvm::StringRef llvmstr = llvm::dwarf::OperationEncodingString(val);
395+
if (llvmstr.empty()) {
396+
snprintf(invalid, sizeof(invalid), "Unknown DW_OP constant: 0x%x", val);
397+
return invalid;
398+
}
399+
return llvmstr.data();
400+
}
401+
402+
llvm::Expected<lldb::addr_t> DWARFExpression::GetLocation_DW_OP_addr(
403+
const DWARFExpression::Delegate *dwarf_cu) const {
398404
lldb::offset_t offset = 0;
399405
while (m_data.ValidOffset(offset)) {
400406
const LocationAtom op = static_cast<LocationAtom>(m_data.GetU8(&offset));
@@ -422,8 +428,8 @@ DWARFExpression::GetLocation_DW_OP_addr(const DWARFUnit *dwarf_cu) const {
422428
return LLDB_INVALID_ADDRESS;
423429
}
424430

425-
bool DWARFExpression::Update_DW_OP_addr(const DWARFUnit *dwarf_cu,
426-
lldb::addr_t file_addr) {
431+
bool DWARFExpression::Update_DW_OP_addr(
432+
const DWARFExpression::Delegate *dwarf_cu, lldb::addr_t file_addr) {
427433
lldb::offset_t offset = 0;
428434
while (m_data.ValidOffset(offset)) {
429435
const LocationAtom op = static_cast<LocationAtom>(m_data.GetU8(&offset));
@@ -481,7 +487,7 @@ bool DWARFExpression::Update_DW_OP_addr(const DWARFUnit *dwarf_cu,
481487
}
482488

483489
bool DWARFExpression::ContainsThreadLocalStorage(
484-
const DWARFUnit *dwarf_cu) const {
490+
const DWARFExpression::Delegate *dwarf_cu) const {
485491
lldb::offset_t offset = 0;
486492
while (m_data.ValidOffset(offset)) {
487493
const LocationAtom op = static_cast<LocationAtom>(m_data.GetU8(&offset));
@@ -497,7 +503,7 @@ bool DWARFExpression::ContainsThreadLocalStorage(
497503
return false;
498504
}
499505
bool DWARFExpression::LinkThreadLocalStorage(
500-
const DWARFUnit *dwarf_cu,
506+
const DWARFExpression::Delegate *dwarf_cu,
501507
std::function<lldb::addr_t(lldb::addr_t file_addr)> const
502508
&link_address_callback) {
503509
const uint32_t addr_byte_size = m_data.GetAddressByteSize();
@@ -783,9 +789,9 @@ enum LocationDescriptionKind {
783789
/* Composite*/
784790
};
785791
/// Adjust value's ValueType according to the kind of location description.
786-
void UpdateValueTypeFromLocationDescription(Log *log, const DWARFUnit *dwarf_cu,
787-
LocationDescriptionKind kind,
788-
Value *value = nullptr) {
792+
void UpdateValueTypeFromLocationDescription(
793+
Log *log, const DWARFExpression::Delegate *dwarf_cu,
794+
LocationDescriptionKind kind, Value *value = nullptr) {
789795
// Note that this function is conflating DWARF expressions with
790796
// DWARF location descriptions. Perhaps it would be better to define
791797
// a wrapper for DWARFExpression::Eval() that deals with DWARF
@@ -875,8 +881,9 @@ static Scalar DerefSizeExtractDataHelper(uint8_t *addr_bytes,
875881
llvm::Expected<Value> DWARFExpression::Evaluate(
876882
ExecutionContext *exe_ctx, RegisterContext *reg_ctx,
877883
lldb::ModuleSP module_sp, const DataExtractor &opcodes,
878-
const DWARFUnit *dwarf_cu, const lldb::RegisterKind reg_kind,
879-
const Value *initial_value_ptr, const Value *object_address_ptr) {
884+
const DWARFExpression::Delegate *dwarf_cu,
885+
const lldb::RegisterKind reg_kind, const Value *initial_value_ptr,
886+
const Value *object_address_ptr) {
880887

881888
if (opcodes.GetByteSize() == 0)
882889
return llvm::createStringError(
@@ -2150,10 +2157,10 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
21502157
// DESCRIPTION: Pop the top stack element, convert it to a
21512158
// different type, and push the result.
21522159
case DW_OP_convert: {
2153-
const uint64_t die_offset = opcodes.GetULEB128(&offset);
2160+
const uint64_t relative_die_offset = opcodes.GetULEB128(&offset);
21542161
uint64_t bit_size;
21552162
bool sign;
2156-
if (die_offset == 0) {
2163+
if (relative_die_offset == 0) {
21572164
// The generic type has the size of an address on the target
21582165
// machine and an unspecified signedness. Scalar has no
21592166
// "unspecified signedness", so we use unsigned types.
@@ -2164,35 +2171,12 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
21642171
if (!bit_size)
21652172
return llvm::createStringError("unspecified architecture");
21662173
} else {
2167-
// Retrieve the type DIE that the value is being converted to. This
2168-
// offset is compile unit relative so we need to fix it up.
2169-
const uint64_t abs_die_offset = die_offset + dwarf_cu->GetOffset();
2170-
// FIXME: the constness has annoying ripple effects.
2171-
DWARFDIE die = const_cast<DWARFUnit *>(dwarf_cu)->GetDIE(abs_die_offset);
2172-
if (!die)
2173-
return llvm::createStringError(
2174-
"cannot resolve DW_OP_convert type DIE");
2175-
uint64_t encoding =
2176-
die.GetAttributeValueAsUnsigned(DW_AT_encoding, DW_ATE_hi_user);
2177-
bit_size = die.GetAttributeValueAsUnsigned(DW_AT_byte_size, 0) * 8;
2178-
if (!bit_size)
2179-
bit_size = die.GetAttributeValueAsUnsigned(DW_AT_bit_size, 0);
2180-
if (!bit_size)
2181-
return llvm::createStringError(
2182-
"unsupported type size in DW_OP_convert");
2183-
switch (encoding) {
2184-
case DW_ATE_signed:
2185-
case DW_ATE_signed_char:
2186-
sign = true;
2187-
break;
2188-
case DW_ATE_unsigned:
2189-
case DW_ATE_unsigned_char:
2190-
sign = false;
2191-
break;
2192-
default:
2193-
return llvm::createStringError(
2194-
"unsupported encoding in DW_OP_convert");
2195-
}
2174+
auto bit_size_sign_or_err =
2175+
dwarf_cu->GetDIEBitSizeAndSign(relative_die_offset);
2176+
if (!bit_size_sign_or_err)
2177+
return bit_size_sign_or_err.takeError();
2178+
bit_size = bit_size_sign_or_err->first;
2179+
sign = bit_size_sign_or_err->second;
21962180
}
21972181
Scalar &top = stack.back().ResolveValue(exe_ctx);
21982182
top.TruncOrExtendTo(bit_size, sign);
@@ -2316,8 +2300,7 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
23162300

23172301
default:
23182302
if (dwarf_cu) {
2319-
if (dwarf_cu->GetSymbolFileDWARF().ParseVendorDWARFOpcode(
2320-
op, opcodes, offset, stack)) {
2303+
if (dwarf_cu->ParseVendorDWARFOpcode(op, opcodes, offset, stack)) {
23212304
break;
23222305
}
23232306
}
@@ -2352,43 +2335,6 @@ llvm::Expected<Value> DWARFExpression::Evaluate(
23522335
return stack.back();
23532336
}
23542337

2355-
bool DWARFExpression::ParseDWARFLocationList(
2356-
const DWARFUnit *dwarf_cu, const DataExtractor &data,
2357-
DWARFExpressionList *location_list) {
2358-
location_list->Clear();
2359-
std::unique_ptr<llvm::DWARFLocationTable> loctable_up =
2360-
dwarf_cu->GetLocationTable(data);
2361-
Log *log = GetLog(LLDBLog::Expressions);
2362-
auto lookup_addr =
2363-
[&](uint32_t index) -> std::optional<llvm::object::SectionedAddress> {
2364-
addr_t address = dwarf_cu->ReadAddressFromDebugAddrSection(index);
2365-
if (address == LLDB_INVALID_ADDRESS)
2366-
return std::nullopt;
2367-
return llvm::object::SectionedAddress{address};
2368-
};
2369-
auto process_list = [&](llvm::Expected<llvm::DWARFLocationExpression> loc) {
2370-
if (!loc) {
2371-
LLDB_LOG_ERROR(log, loc.takeError(), "{0}");
2372-
return true;
2373-
}
2374-
auto buffer_sp =
2375-
std::make_shared<DataBufferHeap>(loc->Expr.data(), loc->Expr.size());
2376-
DWARFExpression expr = DWARFExpression(DataExtractor(
2377-
buffer_sp, data.GetByteOrder(), data.GetAddressByteSize()));
2378-
location_list->AddExpression(loc->Range->LowPC, loc->Range->HighPC, expr);
2379-
return true;
2380-
};
2381-
llvm::Error error = loctable_up->visitAbsoluteLocationList(
2382-
0, llvm::object::SectionedAddress{dwarf_cu->GetBaseAddress()},
2383-
lookup_addr, process_list);
2384-
location_list->Sort();
2385-
if (error) {
2386-
LLDB_LOG_ERROR(log, std::move(error), "{0}");
2387-
return false;
2388-
}
2389-
return true;
2390-
}
2391-
23922338
bool DWARFExpression::MatchesOperand(
23932339
StackFrame &frame, const Instruction::Operand &operand) const {
23942340
using namespace OperandMatchers;

lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ bool DWARFDebugInfoEntry::GetDIENamesAndRanges(
240240
data = DataExtractor(data, offset, data.GetByteSize() - offset);
241241
if (lo_pc != LLDB_INVALID_ADDRESS) {
242242
assert(lo_pc >= cu->GetBaseAddress());
243-
DWARFExpression::ParseDWARFLocationList(cu, data, frame_base);
243+
cu->ParseDWARFLocationList(data, *frame_base);
244244
frame_base->SetFuncFileAddress(lo_pc);
245245
} else
246246
set_frame_base_loclist_addr = true;

lldb/source/Plugins/SymbolFile/DWARF/DWARFDefines.cpp

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,15 +23,5 @@ llvm::StringRef DW_TAG_value_to_name(dw_tag_t tag) {
2323
return s_unknown_tag_name;
2424
}
2525

26-
const char *DW_OP_value_to_name(uint32_t val) {
27-
static char invalid[100];
28-
llvm::StringRef llvmstr = llvm::dwarf::OperationEncodingString(val);
29-
if (llvmstr.empty()) {
30-
snprintf(invalid, sizeof(invalid), "Unknown DW_OP constant: 0x%x", val);
31-
return invalid;
32-
}
33-
return llvmstr.data();
34-
}
35-
3626
} // namespace dwarf
3727
} // namespace lldb_private::plugin

lldb/source/Plugins/SymbolFile/DWARF/DWARFDefines.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@ namespace dwarf {
1717

1818
llvm::StringRef DW_TAG_value_to_name(dw_tag_t tag);
1919

20-
const char *DW_OP_value_to_name(uint32_t val);
21-
2220
} // namespace dwarf
2321
} // namespace lldb_private::plugin
2422

0 commit comments

Comments
 (0)