//===-- 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 RecordT createRecord(const CVSymbol &sym) { RecordT record(static_cast(sym.kind())); cantFail(SymbolDeserializer::deserializeAs(sym, record)); return record; } template static SegmentOffset GetSegmentAndOffset(const CVSymbol &sym) { RecordT record = createRecord(sym); return {record.Segment, record.CodeOffset}; } template <> SegmentOffset GetSegmentAndOffset(const CVSymbol &sym) { TrampolineSym record = createRecord(sym); return {record.ThunkSection, record.ThunkOffset}; } template <> SegmentOffset GetSegmentAndOffset(const CVSymbol &sym) { Thunk32Sym record = createRecord(sym); return {record.Segment, record.Offset}; } template <> SegmentOffset GetSegmentAndOffset(const CVSymbol &sym) { CoffGroupSym record = createRecord(sym); return {record.Segment, record.Offset}; } template <> SegmentOffset GetSegmentAndOffset(const CVSymbol &sym) { DataSym record = createRecord(sym); return {record.Segment, record.DataOffset}; } template <> SegmentOffset GetSegmentAndOffset(const CVSymbol &sym) { ThreadLocalDataSym record = createRecord(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(sym); case S_THUNK32: return ::GetSegmentAndOffset(sym); break; case S_TRAMPOLINE: return ::GetSegmentAndOffset(sym); break; case S_COFFGROUP: return ::GetSegmentAndOffset(sym); break; case S_BLOCK32: return ::GetSegmentAndOffset(sym); break; case S_LABEL32: return ::GetSegmentAndOffset(sym); break; case S_CALLSITEINFO: return ::GetSegmentAndOffset(sym); break; case S_HEAPALLOCSITE: return ::GetSegmentAndOffset(sym); break; case S_LDATA32: case S_GDATA32: case S_LMANDATA: case S_GMANDATA: return ::GetSegmentAndOffset(sym); break; case S_LTHREAD32: case S_GTHREAD32: return ::GetSegmentAndOffset(sym); break; default: lldbassert(false && "Record does not have a segment/offset!"); } return {0, 0}; } template SegmentOffsetLength GetSegmentOffsetAndLength(const CVSymbol &sym) { RecordT record = createRecord(sym); return {record.Segment, record.CodeOffset, record.CodeSize}; } template <> SegmentOffsetLength GetSegmentOffsetAndLength(const CVSymbol &sym) { TrampolineSym record = createRecord(sym); return {record.ThunkSection, record.ThunkOffset, record.Size}; } template <> SegmentOffsetLength GetSegmentOffsetAndLength(const CVSymbol &sym) { Thunk32Sym record = createRecord(sym); return SegmentOffsetLength{record.Segment, record.Offset, record.Length}; } template <> SegmentOffsetLength GetSegmentOffsetAndLength(const CVSymbol &sym) { CoffGroupSym record = createRecord(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(sym); case S_THUNK32: return ::GetSegmentOffsetAndLength(sym); break; case S_TRAMPOLINE: return ::GetSegmentOffsetAndLength(sym); break; case S_COFFGROUP: return ::GetSegmentOffsetAndLength(sym); break; case S_BLOCK32: return ::GetSegmentOffsetAndLength(sym); break; default: lldbassert(false && "Record does not have a segment/offset/length triple!"); } return {0, 0, 0}; }