Skip to content

[Cherry-pick] Upstream patches related to DWARF5 and debug_names #8088

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
71 changes: 29 additions & 42 deletions lldb/source/Interpreter/OptionArgParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,6 @@ lldb::addr_t OptionArgParser::ToAddress(const ExecutionContext *exe_ctx,
std::optional<lldb::addr_t>
OptionArgParser::DoToAddress(const ExecutionContext *exe_ctx, llvm::StringRef s,
Status *error_ptr) {
bool error_set = false;
if (s.empty()) {
if (error_ptr)
error_ptr->SetErrorStringWithFormat("invalid address expression \"%s\"",
Expand Down Expand Up @@ -223,52 +222,40 @@ OptionArgParser::DoToAddress(const ExecutionContext *exe_ctx, llvm::StringRef s,
if (error_ptr)
error_ptr->Clear();
return addr;
} else {
if (error_ptr) {
error_set = true;
error_ptr->SetErrorStringWithFormat(
"address expression \"%s\" resulted in a value whose type "
"can't be converted to an address: %s",
s.str().c_str(), valobj_sp->GetTypeName().GetCString());
}
}
if (error_ptr)
error_ptr->SetErrorStringWithFormat(
"address expression \"%s\" resulted in a value whose type "
"can't be converted to an address: %s",
s.str().c_str(), valobj_sp->GetTypeName().GetCString());
return {};
}

} else {
// Since the compiler can't handle things like "main + 12" we should try to
// do this for now. The compiler doesn't like adding offsets to function
// pointer types.
static RegularExpression g_symbol_plus_offset_regex(
"^(.*)([-\\+])[[:space:]]*(0x[0-9A-Fa-f]+|[0-9]+)[[:space:]]*$");

llvm::SmallVector<llvm::StringRef, 4> matches;
if (g_symbol_plus_offset_regex.Execute(sref, &matches)) {
uint64_t offset = 0;
std::string name = matches[1].str();
std::string sign = matches[2].str();
std::string str_offset = matches[3].str();
if (!llvm::StringRef(str_offset).getAsInteger(0, offset)) {
Status error;
addr = ToAddress(exe_ctx, name.c_str(), LLDB_INVALID_ADDRESS, &error);
if (addr != LLDB_INVALID_ADDRESS) {
if (sign[0] == '+')
return addr + offset;
else
return addr - offset;
}
// Since the compiler can't handle things like "main + 12" we should try to
// do this for now. The compiler doesn't like adding offsets to function
// pointer types.
static RegularExpression g_symbol_plus_offset_regex(
"^(.*)([-\\+])[[:space:]]*(0x[0-9A-Fa-f]+|[0-9]+)[[:space:]]*$");

llvm::SmallVector<llvm::StringRef, 4> matches;
if (g_symbol_plus_offset_regex.Execute(sref, &matches)) {
uint64_t offset = 0;
llvm::StringRef name = matches[1];
llvm::StringRef sign = matches[2];
llvm::StringRef str_offset = matches[3];
if (!str_offset.getAsInteger(0, offset)) {
Status error;
addr = ToAddress(exe_ctx, name, LLDB_INVALID_ADDRESS, &error);
if (addr != LLDB_INVALID_ADDRESS) {
if (sign[0] == '+')
return addr + offset;
return addr - offset;
}
}

if (error_ptr) {
error_set = true;
error_ptr->SetErrorStringWithFormat(
"address expression \"%s\" evaluation failed", s.str().c_str());
}
}

if (error_ptr) {
if (!error_set)
error_ptr->SetErrorStringWithFormat("invalid address expression \"%s\"",
s.str().c_str());
}
if (error_ptr)
error_ptr->SetErrorStringWithFormat(
"address expression \"%s\" evaluation failed", s.str().c_str());
return {};
}
141 changes: 9 additions & 132 deletions lldb/source/Plugins/SymbolFile/DWARF/DWARFDebugInfoEntry.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,16 +50,12 @@ bool DWARFDebugInfoEntry::Extract(const DWARFDataExtractor &data,
lldbassert(abbr_idx <= UINT16_MAX);
m_abbr_idx = abbr_idx;

// assert (fixed_form_sizes); // For best performance this should be
// specified!

if (m_abbr_idx == 0) {
m_tag = llvm::dwarf::DW_TAG_null;
m_has_children = false;
return true; // NULL debug tag entry
}

lldb::offset_t offset = *offset_ptr;
const auto *abbrevDecl = GetAbbreviationDeclarationPtr(cu);
if (abbrevDecl == nullptr) {
cu->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError(
Expand All @@ -74,137 +70,18 @@ bool DWARFDebugInfoEntry::Extract(const DWARFDataExtractor &data,
m_tag = abbrevDecl->getTag();
m_has_children = abbrevDecl->hasChildren();
// Skip all data in the .debug_info or .debug_types for the attributes
dw_form_t form;
for (const auto &attribute : abbrevDecl->attributes()) {
form = attribute.Form;
std::optional<uint8_t> fixed_skip_size =
DWARFFormValue::GetFixedSize(form, cu);
if (fixed_skip_size)
offset += *fixed_skip_size;
else {
bool form_is_indirect = false;
do {
form_is_indirect = false;
uint32_t form_size = 0;
switch (form) {
// Blocks if inlined data that have a length field and the data bytes
// inlined in the .debug_info/.debug_types
case DW_FORM_exprloc:
case DW_FORM_block:
form_size = data.GetULEB128(&offset);
break;
case DW_FORM_block1:
form_size = data.GetU8_unchecked(&offset);
break;
case DW_FORM_block2:
form_size = data.GetU16_unchecked(&offset);
break;
case DW_FORM_block4:
form_size = data.GetU32_unchecked(&offset);
break;

// Inlined NULL terminated C-strings
case DW_FORM_string:
data.GetCStr(&offset);
break;

// Compile unit address sized values
case DW_FORM_addr:
form_size = cu->GetAddressByteSize();
break;
case DW_FORM_ref_addr:
if (cu->GetVersion() <= 2)
form_size = cu->GetAddressByteSize();
else
form_size = 4;
break;
if (DWARFFormValue::SkipValue(attribute.Form, data, offset_ptr, cu))
continue;

// 0 sized form
case DW_FORM_flag_present:
form_size = 0;
break;

// 1 byte values
case DW_FORM_addrx1:
case DW_FORM_data1:
case DW_FORM_flag:
case DW_FORM_ref1:
case DW_FORM_strx1:
form_size = 1;
break;

// 2 byte values
case DW_FORM_addrx2:
case DW_FORM_data2:
case DW_FORM_ref2:
case DW_FORM_strx2:
form_size = 2;
break;

// 3 byte values
case DW_FORM_addrx3:
case DW_FORM_strx3:
form_size = 3;
break;

// 4 byte values
case DW_FORM_addrx4:
case DW_FORM_data4:
case DW_FORM_ref4:
case DW_FORM_strx4:
form_size = 4;
break;

// 8 byte values
case DW_FORM_data8:
case DW_FORM_ref8:
case DW_FORM_ref_sig8:
form_size = 8;
break;

// signed or unsigned LEB 128 values
case DW_FORM_addrx:
case DW_FORM_loclistx:
case DW_FORM_rnglistx:
case DW_FORM_sdata:
case DW_FORM_udata:
case DW_FORM_ref_udata:
case DW_FORM_GNU_addr_index:
case DW_FORM_GNU_str_index:
case DW_FORM_strx:
data.Skip_LEB128(&offset);
break;

case DW_FORM_indirect:
form_is_indirect = true;
form = static_cast<dw_form_t>(data.GetULEB128(&offset));
break;

case DW_FORM_strp:
case DW_FORM_line_strp:
case DW_FORM_sec_offset:
data.GetU32(&offset);
break;

case DW_FORM_implicit_const:
form_size = 0;
break;

default:
cu->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError(
"[{0:x16}]: Unsupported DW_FORM_{1:x}, please file a bug "
"and "
"attach the file at the start of this error message",
(uint64_t)m_offset, (unsigned)form);
*offset_ptr = m_offset;
return false;
}
offset += form_size;

} while (form_is_indirect);
}
cu->GetSymbolFileDWARF().GetObjectFile()->GetModule()->ReportError(
"[{0:x16}]: Unsupported DW_FORM_{1:x}, please file a bug "
"and "
"attach the file at the start of this error message",
(uint64_t)m_offset, (unsigned)attribute.Form);
*offset_ptr = m_offset;
return false;
}
*offset_ptr = offset;
return true;
}

Expand Down
41 changes: 21 additions & 20 deletions lldb/source/Plugins/SymbolFile/DWARF/DWARFDeclContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,27 @@
//===----------------------------------------------------------------------===//

#include "DWARFDeclContext.h"
#include "llvm/Support/raw_ostream.h"

using namespace lldb_private::dwarf;
using namespace lldb_private::plugin::dwarf;

/// Returns the name of `entry` if it has one, or the appropriate "anonymous
/// {namespace, class, struct, union}".
static const char *GetName(DWARFDeclContext::Entry entry) {
if (entry.name != nullptr)
return entry.name;
if (entry.tag == DW_TAG_namespace)
return "(anonymous namespace)";
if (entry.tag == DW_TAG_class_type)
return "(anonymous class)";
if (entry.tag == DW_TAG_structure_type)
return "(anonymous struct)";
if (entry.tag == DW_TAG_union_type)
return "(anonymous union)";
return "(anonymous)";
}

const char *DWARFDeclContext::GetQualifiedName() const {
if (m_qualified_name.empty()) {
// The declaration context array for a class named "foo" in namespace
Expand All @@ -26,26 +43,10 @@ const char *DWARFDeclContext::GetQualifiedName() const {
m_qualified_name.append(m_entries[0].name);
}
} else {
collection::const_reverse_iterator pos;
collection::const_reverse_iterator begin = m_entries.rbegin();
collection::const_reverse_iterator end = m_entries.rend();
for (pos = begin; pos != end; ++pos) {
if (pos != begin)
m_qualified_name.append("::");
if (pos->name == nullptr) {
if (pos->tag == DW_TAG_namespace)
m_qualified_name.append("(anonymous namespace)");
else if (pos->tag == DW_TAG_class_type)
m_qualified_name.append("(anonymous class)");
else if (pos->tag == DW_TAG_structure_type)
m_qualified_name.append("(anonymous struct)");
else if (pos->tag == DW_TAG_union_type)
m_qualified_name.append("(anonymous union)");
else
m_qualified_name.append("(anonymous)");
} else
m_qualified_name.append(pos->name);
}
llvm::raw_string_ostream string_stream(m_qualified_name);
llvm::interleave(
llvm::reverse(m_entries), string_stream,
[&](auto entry) { string_stream << GetName(entry); }, "::");
}
}
}
Expand Down
Loading