You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
182 lines
5.4 KiB
182 lines
5.4 KiB
4 months ago
|
//===-- PDBLocationToDWARFExpression.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 "PDBLocationToDWARFExpression.h"
|
||
|
|
||
|
#include "lldb/Core/Section.h"
|
||
|
#include "lldb/Core/StreamBuffer.h"
|
||
|
#include "lldb/Core/dwarf.h"
|
||
|
#include "lldb/Expression/DWARFExpression.h"
|
||
|
#include "lldb/Symbol/Variable.h"
|
||
|
#include "lldb/Utility/DataBufferHeap.h"
|
||
|
|
||
|
#include "llvm/DebugInfo/CodeView/CodeView.h"
|
||
|
#include "llvm/DebugInfo/PDB/IPDBSession.h"
|
||
|
#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
|
||
|
|
||
|
#include "Plugins/SymbolFile/NativePDB/CodeViewRegisterMapping.h"
|
||
|
#include "Plugins/SymbolFile/NativePDB/PdbFPOProgramToDWARFExpression.h"
|
||
|
|
||
|
using namespace lldb;
|
||
|
using namespace lldb_private;
|
||
|
using namespace lldb_private::npdb;
|
||
|
using namespace llvm::pdb;
|
||
|
|
||
|
static std::unique_ptr<IPDBFrameData>
|
||
|
GetCorrespondingFrameData(const IPDBSession &session,
|
||
|
const Variable::RangeList &ranges) {
|
||
|
auto enumFrameData = session.getFrameData();
|
||
|
if (!enumFrameData)
|
||
|
return nullptr;
|
||
|
|
||
|
std::unique_ptr<IPDBFrameData> found;
|
||
|
while (auto fd = enumFrameData->getNext()) {
|
||
|
Range<lldb::addr_t, lldb::addr_t> fdRange(fd->getVirtualAddress(),
|
||
|
fd->getLengthBlock());
|
||
|
|
||
|
for (size_t i = 0; i < ranges.GetSize(); i++) {
|
||
|
auto range = ranges.GetEntryAtIndex(i);
|
||
|
if (!range)
|
||
|
continue;
|
||
|
|
||
|
if (!range->DoesIntersect(fdRange))
|
||
|
continue;
|
||
|
|
||
|
found = std::move(fd);
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return found;
|
||
|
}
|
||
|
|
||
|
static bool EmitVFrameEvaluationDWARFExpression(
|
||
|
llvm::StringRef program, llvm::Triple::ArchType arch_type, Stream &stream) {
|
||
|
// VFrame value always stored in $TO pseudo-register
|
||
|
return TranslateFPOProgramToDWARFExpression(program, "$T0", arch_type,
|
||
|
stream);
|
||
|
}
|
||
|
|
||
|
DWARFExpression ConvertPDBLocationToDWARFExpression(
|
||
|
ModuleSP module, const PDBSymbolData &symbol,
|
||
|
const Variable::RangeList &ranges, bool &is_constant) {
|
||
|
is_constant = true;
|
||
|
|
||
|
if (!module)
|
||
|
return DWARFExpression();
|
||
|
|
||
|
const ArchSpec &architecture = module->GetArchitecture();
|
||
|
llvm::Triple::ArchType arch_type = architecture.GetMachine();
|
||
|
ByteOrder byte_order = architecture.GetByteOrder();
|
||
|
uint32_t address_size = architecture.GetAddressByteSize();
|
||
|
uint32_t byte_size = architecture.GetDataByteSize();
|
||
|
if (byte_order == eByteOrderInvalid || address_size == 0)
|
||
|
return DWARFExpression();
|
||
|
|
||
|
RegisterKind register_kind = eRegisterKindDWARF;
|
||
|
StreamBuffer<32> stream(Stream::eBinary, address_size, byte_order);
|
||
|
switch (symbol.getLocationType()) {
|
||
|
case PDB_LocType::Static:
|
||
|
case PDB_LocType::TLS: {
|
||
|
stream.PutHex8(DW_OP_addr);
|
||
|
|
||
|
SectionList *section_list = module->GetSectionList();
|
||
|
if (!section_list)
|
||
|
return DWARFExpression();
|
||
|
|
||
|
uint32_t section_id = symbol.getAddressSection();
|
||
|
|
||
|
auto section = section_list->FindSectionByID(section_id);
|
||
|
if (!section)
|
||
|
return DWARFExpression();
|
||
|
|
||
|
uint32_t offset = symbol.getAddressOffset();
|
||
|
stream.PutMaxHex64(section->GetFileAddress() + offset, address_size,
|
||
|
byte_order);
|
||
|
|
||
|
is_constant = false;
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
case PDB_LocType::RegRel: {
|
||
|
uint32_t reg_num;
|
||
|
auto reg_id = symbol.getRegisterId();
|
||
|
if (reg_id == llvm::codeview::RegisterId::VFRAME) {
|
||
|
if (auto fd = GetCorrespondingFrameData(symbol.getSession(), ranges)) {
|
||
|
if (EmitVFrameEvaluationDWARFExpression(fd->getProgram(), arch_type,
|
||
|
stream)) {
|
||
|
int32_t offset = symbol.getOffset();
|
||
|
stream.PutHex8(DW_OP_consts);
|
||
|
stream.PutSLEB128(offset);
|
||
|
stream.PutHex8(DW_OP_plus);
|
||
|
|
||
|
register_kind = eRegisterKindLLDB;
|
||
|
|
||
|
is_constant = false;
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
register_kind = eRegisterKindGeneric;
|
||
|
reg_num = LLDB_REGNUM_GENERIC_FP;
|
||
|
} else {
|
||
|
register_kind = eRegisterKindLLDB;
|
||
|
reg_num = GetLLDBRegisterNumber(arch_type, reg_id);
|
||
|
if (reg_num == LLDB_INVALID_REGNUM)
|
||
|
return DWARFExpression();
|
||
|
}
|
||
|
|
||
|
if (reg_num > 31) {
|
||
|
stream.PutHex8(DW_OP_bregx);
|
||
|
stream.PutULEB128(reg_num);
|
||
|
} else
|
||
|
stream.PutHex8(DW_OP_breg0 + reg_num);
|
||
|
|
||
|
int32_t offset = symbol.getOffset();
|
||
|
stream.PutSLEB128(offset);
|
||
|
|
||
|
is_constant = false;
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
case PDB_LocType::Enregistered: {
|
||
|
register_kind = eRegisterKindLLDB;
|
||
|
uint32_t reg_num = GetLLDBRegisterNumber(arch_type, symbol.getRegisterId());
|
||
|
if (reg_num == LLDB_INVALID_REGNUM)
|
||
|
return DWARFExpression();
|
||
|
|
||
|
if (reg_num > 31) {
|
||
|
stream.PutHex8(DW_OP_regx);
|
||
|
stream.PutULEB128(reg_num);
|
||
|
} else
|
||
|
stream.PutHex8(DW_OP_reg0 + reg_num);
|
||
|
|
||
|
is_constant = false;
|
||
|
|
||
|
break;
|
||
|
}
|
||
|
case PDB_LocType::Constant: {
|
||
|
Variant value = symbol.getValue();
|
||
|
stream.PutRawBytes(&value.Value, sizeof(value.Value),
|
||
|
endian::InlHostByteOrder());
|
||
|
break;
|
||
|
}
|
||
|
default:
|
||
|
return DWARFExpression();
|
||
|
}
|
||
|
|
||
|
DataBufferSP buffer =
|
||
|
std::make_shared<DataBufferHeap>(stream.GetData(), stream.GetSize());
|
||
|
DataExtractor extractor(buffer, byte_order, address_size, byte_size);
|
||
|
DWARFExpression result(module, extractor, nullptr);
|
||
|
result.SetRegisterKind(register_kind);
|
||
|
|
||
|
return result;
|
||
|
}
|