diff options
Diffstat (limited to 'lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp')
-rw-r--r-- | lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp | 258 |
1 files changed, 258 insertions, 0 deletions
diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp new file mode 100644 index 00000000000..55de9662592 --- /dev/null +++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbUtil.cpp @@ -0,0 +1,258 @@ +//===-- PdbUtil.cpp ---------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "PdbUtil.h" + +#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h" + +#include "lldb/Utility/LLDBAssert.h" + +using namespace lldb_private; +using namespace lldb_private::npdb; +using namespace llvm::codeview; +using namespace llvm::pdb; + +llvm::pdb::PDB_SymType +lldb_private::npdb::CVSymToPDBSym(llvm::codeview::SymbolKind kind) { + switch (kind) { + case S_COMPILE3: + case S_OBJNAME: + return PDB_SymType::CompilandDetails; + case S_ENVBLOCK: + return PDB_SymType::CompilandEnv; + case S_THUNK32: + case S_TRAMPOLINE: + return PDB_SymType::Thunk; + case S_COFFGROUP: + return PDB_SymType::CoffGroup; + case S_EXPORT: + return PDB_SymType::Export; + case S_LPROC32: + case S_GPROC32: + case S_LPROC32_DPC: + return PDB_SymType::Function; + case S_PUB32: + return PDB_SymType::PublicSymbol; + case S_INLINESITE: + return PDB_SymType::InlineSite; + case S_LOCAL: + case S_BPREL32: + case S_REGREL32: + case S_MANCONSTANT: + case S_CONSTANT: + case S_LDATA32: + case S_GDATA32: + case S_LMANDATA: + case S_GMANDATA: + case S_LTHREAD32: + case S_GTHREAD32: + return PDB_SymType::Data; + case S_BLOCK32: + return PDB_SymType::Block; + case S_LABEL32: + return PDB_SymType::Label; + case S_CALLSITEINFO: + return PDB_SymType::CallSite; + case S_HEAPALLOCSITE: + return PDB_SymType::HeapAllocationSite; + case S_CALLEES: + return PDB_SymType::Callee; + case S_CALLERS: + return PDB_SymType::Caller; + default: + lldbassert(false && "Invalid symbol record kind!"); + } + return PDB_SymType::None; +} + +bool lldb_private::npdb::SymbolHasAddress(const llvm::codeview::CVSymbol &sym) { + switch (sym.kind()) { + case S_GPROC32: + case S_LPROC32: + case S_GPROC32_ID: + case S_LPROC32_ID: + case S_LPROC32_DPC: + case S_LPROC32_DPC_ID: + case S_THUNK32: + case S_TRAMPOLINE: + case S_COFFGROUP: + case S_BLOCK32: + case S_LABEL32: + case S_CALLSITEINFO: + case S_HEAPALLOCSITE: + case S_LDATA32: + case S_GDATA32: + case S_LMANDATA: + case S_GMANDATA: + case S_LTHREAD32: + case S_GTHREAD32: + return true; + default: + return false; + } +} + +bool lldb_private::npdb::SymbolIsCode(const llvm::codeview::CVSymbol &sym) { + switch (sym.kind()) { + case S_GPROC32: + case S_LPROC32: + case S_GPROC32_ID: + case S_LPROC32_ID: + case S_LPROC32_DPC: + case S_LPROC32_DPC_ID: + case S_THUNK32: + case S_TRAMPOLINE: + case S_COFFGROUP: + case S_BLOCK32: + return true; + default: + return false; + } +} + +template <typename RecordT> RecordT createRecord(const CVSymbol &sym) { + RecordT record(static_cast<SymbolRecordKind>(sym.kind())); + cantFail(SymbolDeserializer::deserializeAs<RecordT>(sym, record)); + return record; +} + +template <typename RecordT> +static SegmentOffset GetSegmentAndOffset(const CVSymbol &sym) { + RecordT record = createRecord<RecordT>(sym); + return {record.Segment, record.CodeOffset}; +} + +template <> +SegmentOffset GetSegmentAndOffset<TrampolineSym>(const CVSymbol &sym) { + TrampolineSym record = createRecord<TrampolineSym>(sym); + return {record.ThunkSection, record.ThunkOffset}; +} + +template <> SegmentOffset GetSegmentAndOffset<Thunk32Sym>(const CVSymbol &sym) { + Thunk32Sym record = createRecord<Thunk32Sym>(sym); + return {record.Segment, record.Offset}; +} + +template <> +SegmentOffset GetSegmentAndOffset<CoffGroupSym>(const CVSymbol &sym) { + CoffGroupSym record = createRecord<CoffGroupSym>(sym); + return {record.Segment, record.Offset}; +} + +template <> SegmentOffset GetSegmentAndOffset<DataSym>(const CVSymbol &sym) { + DataSym record = createRecord<DataSym>(sym); + return {record.Segment, record.DataOffset}; +} + +template <> +SegmentOffset GetSegmentAndOffset<ThreadLocalDataSym>(const CVSymbol &sym) { + ThreadLocalDataSym record = createRecord<ThreadLocalDataSym>(sym); + return {record.Segment, record.DataOffset}; +} + +SegmentOffset +lldb_private::npdb::GetSegmentAndOffset(const llvm::codeview::CVSymbol &sym) { + switch (sym.kind()) { + case S_GPROC32: + case S_LPROC32: + case S_GPROC32_ID: + case S_LPROC32_ID: + case S_LPROC32_DPC: + case S_LPROC32_DPC_ID: + return ::GetSegmentAndOffset<ProcSym>(sym); + case S_THUNK32: + return ::GetSegmentAndOffset<Thunk32Sym>(sym); + break; + case S_TRAMPOLINE: + return ::GetSegmentAndOffset<TrampolineSym>(sym); + break; + case S_COFFGROUP: + return ::GetSegmentAndOffset<CoffGroupSym>(sym); + break; + case S_BLOCK32: + return ::GetSegmentAndOffset<BlockSym>(sym); + break; + case S_LABEL32: + return ::GetSegmentAndOffset<LabelSym>(sym); + break; + case S_CALLSITEINFO: + return ::GetSegmentAndOffset<CallSiteInfoSym>(sym); + break; + case S_HEAPALLOCSITE: + return ::GetSegmentAndOffset<HeapAllocationSiteSym>(sym); + break; + case S_LDATA32: + case S_GDATA32: + case S_LMANDATA: + case S_GMANDATA: + return ::GetSegmentAndOffset<DataSym>(sym); + break; + case S_LTHREAD32: + case S_GTHREAD32: + return ::GetSegmentAndOffset<ThreadLocalDataSym>(sym); + break; + default: + lldbassert(false && "Record does not have a segment/offset!"); + } + return {0, 0}; +} + +template <typename RecordT> +SegmentOffsetLength GetSegmentOffsetAndLength(const CVSymbol &sym) { + RecordT record = createRecord<RecordT>(sym); + return {record.Segment, record.CodeOffset, record.CodeSize}; +} + +template <> +SegmentOffsetLength +GetSegmentOffsetAndLength<TrampolineSym>(const CVSymbol &sym) { + TrampolineSym record = createRecord<TrampolineSym>(sym); + return {record.ThunkSection, record.ThunkOffset, record.Size}; +} + +template <> +SegmentOffsetLength GetSegmentOffsetAndLength<Thunk32Sym>(const CVSymbol &sym) { + Thunk32Sym record = createRecord<Thunk32Sym>(sym); + return SegmentOffsetLength{record.Segment, record.Offset, record.Length}; +} + +template <> +SegmentOffsetLength +GetSegmentOffsetAndLength<CoffGroupSym>(const CVSymbol &sym) { + CoffGroupSym record = createRecord<CoffGroupSym>(sym); + return SegmentOffsetLength{record.Segment, record.Offset, record.Size}; +} + +SegmentOffsetLength lldb_private::npdb::GetSegmentOffsetAndLength( + const llvm::codeview::CVSymbol &sym) { + switch (sym.kind()) { + case S_GPROC32: + case S_LPROC32: + case S_GPROC32_ID: + case S_LPROC32_ID: + case S_LPROC32_DPC: + case S_LPROC32_DPC_ID: + return ::GetSegmentOffsetAndLength<ProcSym>(sym); + case S_THUNK32: + return ::GetSegmentOffsetAndLength<Thunk32Sym>(sym); + break; + case S_TRAMPOLINE: + return ::GetSegmentOffsetAndLength<TrampolineSym>(sym); + break; + case S_COFFGROUP: + return ::GetSegmentOffsetAndLength<CoffGroupSym>(sym); + break; + case S_BLOCK32: + return ::GetSegmentOffsetAndLength<BlockSym>(sym); + break; + default: + lldbassert(false && "Record does not have a segment/offset/length triple!"); + } + return {0, 0, 0}; +} |