Skip to content

[lldb] Improve error reporting in GetLocation_DW_OP_addr #120162

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 1 commit into from
Dec 17, 2024
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
11 changes: 4 additions & 7 deletions lldb/include/lldb/Expression/DWARFExpression.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "lldb/Utility/Status.h"
#include "lldb/lldb-private.h"
#include "llvm/DebugInfo/DWARF/DWARFLocationExpression.h"
#include "llvm/Support/Error.h"
#include <functional>

namespace lldb_private {
Expand Down Expand Up @@ -61,15 +62,11 @@ class DWARFExpression {
/// The dwarf unit this expression belongs to. Only required to resolve
/// DW_OP{addrx, GNU_addr_index}.
///
/// \param[out] error
/// If the location stream contains unknown DW_OP opcodes or the
/// data is missing, \a error will be set to \b true.
///
/// \return
/// The address specified by the operation, if the operation exists, or
/// LLDB_INVALID_ADDRESS otherwise.
lldb::addr_t GetLocation_DW_OP_addr(const plugin::dwarf::DWARFUnit *dwarf_cu,
bool &error) const;
/// an llvm::Error otherwise.
llvm::Expected<lldb::addr_t>
GetLocation_DW_OP_addr(const plugin::dwarf::DWARFUnit *dwarf_cu) const;

bool Update_DW_OP_addr(const plugin::dwarf::DWARFUnit *dwarf_cu,
lldb::addr_t file_addr);
Expand Down
22 changes: 12 additions & 10 deletions lldb/source/Expression/DWARFExpression.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -343,30 +343,32 @@ static lldb::offset_t GetOpcodeDataSize(const DataExtractor &data,
}
}

lldb::addr_t DWARFExpression::GetLocation_DW_OP_addr(const DWARFUnit *dwarf_cu,
bool &error) const {
error = false;
llvm::Expected<lldb::addr_t>
DWARFExpression::GetLocation_DW_OP_addr(const DWARFUnit *dwarf_cu) const {
lldb::offset_t offset = 0;
while (m_data.ValidOffset(offset)) {
const uint8_t op = m_data.GetU8(&offset);

if (op == DW_OP_addr)
return m_data.GetAddress(&offset);

if (op == DW_OP_GNU_addr_index || op == DW_OP_addrx) {
uint64_t index = m_data.GetULEB128(&offset);
const uint64_t index = m_data.GetULEB128(&offset);
if (dwarf_cu)
return dwarf_cu->ReadAddressFromDebugAddrSection(index);
error = true;
break;
return llvm::createStringError("cannot evaluate %s without a DWARF unit",
DW_OP_value_to_name(op));
}

const lldb::offset_t op_arg_size =
GetOpcodeDataSize(m_data, offset, op, dwarf_cu);
if (op_arg_size == LLDB_INVALID_OFFSET) {
error = true;
break;
}
if (op_arg_size == LLDB_INVALID_OFFSET)
return llvm::createStringError("cannot get opcode data size for %s",
DW_OP_value_to_name(op));

offset += op_arg_size;
}

return LLDB_INVALID_ADDRESS;
}

Expand Down
28 changes: 16 additions & 12 deletions lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include "llvm/Support/Casting.h"
#include "llvm/Support/FileUtilities.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/FormatAdapters.h"
#include "llvm/Support/Threading.h"

#include "lldb/Core/Module.h"
Expand Down Expand Up @@ -1705,7 +1706,7 @@ SymbolFileDWARF *SymbolFileDWARF::GetDIERefSymbolFile(const DIERef &die_ref) {
// We have a SymbolFileDWARFDebugMap, so let it find the right file
if (SymbolFileDWARFDebugMap *debug_map = GetDebugMapSymfile())
return debug_map->GetSymbolFileByOSOIndex(*file_index);

// Handle the .dwp file case correctly
if (*file_index == DIERef::k_file_index_mask)
return GetDwpSymbolFile().get(); // DWP case
Expand Down Expand Up @@ -3539,17 +3540,20 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc,
// 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;
const DWARFExpression* location = location_list.GetAlwaysValidExpr();
if (location)
location_DW_OP_addr =
location->GetLocation_DW_OP_addr(location_form.GetUnit(), op_error);
if (op_error) {
StreamString strm;
location->DumpLocation(&strm, eDescriptionLevelFull, nullptr);
GetObjectFile()->GetModule()->ReportError(
"{0:x16}: {1} ({2}) has an invalid location: {3}", die.GetOffset(),
DW_TAG_value_to_name(die.Tag()), die.Tag(), strm.GetData());
if (const DWARFExpression *location =
location_list.GetAlwaysValidExpr()) {
if (auto maybe_location_DW_OP_addr =
location->GetLocation_DW_OP_addr(location_form.GetUnit())) {
location_DW_OP_addr = *maybe_location_DW_OP_addr;
} else {
StreamString strm;
location->DumpLocation(&strm, eDescriptionLevelFull, nullptr);
GetObjectFile()->GetModule()->ReportError(
"{0:x16}: {1} ({2}) has an invalid location: {3}: {4}",
die.GetOffset(), DW_TAG_value_to_name(die.Tag()), die.Tag(),
llvm::fmt_consume(maybe_location_DW_OP_addr.takeError()),
strm.GetData());
}
}
if (location_DW_OP_addr != LLDB_INVALID_ADDRESS)
is_static_lifetime = true;
Expand Down
Loading