//===- SymbolRecordMapping.cpp -----------------------------------*- C++-*-===//
//
// 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 "llvm/DebugInfo/CodeView/SymbolRecordMapping.h"
using namespace llvm;
using namespace llvm::codeview;
#define error(X) \
if (auto EC = X) \
return EC;
namespace {
struct MapGap {
Error operator()(CodeViewRecordIO &IO, LocalVariableAddrGap &Gap) const {
error(IO.mapInteger(Gap.GapStartOffset));
error(IO.mapInteger(Gap.Range));
return Error::success();
}
};
}
static Error mapLocalVariableAddrRange(CodeViewRecordIO &IO,
LocalVariableAddrRange &Range) {
error(IO.mapInteger(Range.OffsetStart));
error(IO.mapInteger(Range.ISectStart));
error(IO.mapInteger(Range.Range));
return Error::success();
}
Error SymbolRecordMapping::visitSymbolBegin(CVSymbol &Record) {
error(IO.beginRecord(MaxRecordLength - sizeof(RecordPrefix)));
return Error::success();
}
Error SymbolRecordMapping::visitSymbolEnd(CVSymbol &Record) {
error(IO.padToAlignment(alignOf(Container)));
error(IO.endRecord());
return Error::success();
}
Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, BlockSym &Block) {
error(IO.mapInteger(Block.Parent));
error(IO.mapInteger(Block.End));
error(IO.mapInteger(Block.CodeSize));
error(IO.mapInteger(Block.CodeOffset));
error(IO.mapInteger(Block.Segment));
error(IO.mapStringZ(Block.Name));
return Error::success();
}
Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, Thunk32Sym &Thunk) {
error(IO.mapInteger(Thunk.Parent));
error(IO.mapInteger(Thunk.End));
error(IO.mapInteger(Thunk.Next));
error(IO.mapInteger(Thunk.Offset));
error(IO.mapInteger(Thunk.Segment));
error(IO.mapInteger(Thunk.Length));
error(IO.mapEnum(Thunk.Thunk));
error(IO.mapStringZ(Thunk.Name));
error(IO.mapByteVectorTail(Thunk.VariantData));
return Error::success();
}
Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
TrampolineSym &Tramp) {
error(IO.mapEnum(Tramp.Type));
error(IO.mapInteger(Tramp.Size));
error(IO.mapInteger(Tramp.ThunkOffset));
error(IO.mapInteger(Tramp.TargetOffset));
error(IO.mapInteger(Tramp.ThunkSection));
error(IO.mapInteger(Tramp.TargetSection));
return Error::success();
}
Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
SectionSym &Section) {
uint8_t Padding = 0;
error(IO.mapInteger(Section.SectionNumber));
error(IO.mapInteger(Section.Alignment));
error(IO.mapInteger(Padding));
error(IO.mapInteger(Section.Rva));
error(IO.mapInteger(Section.Length));
error(IO.mapInteger(Section.Characteristics));
error(IO.mapStringZ(Section.Name));
return Error::success();
}
Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
CoffGroupSym &CoffGroup) {
error(IO.mapInteger(CoffGroup.Size));
error(IO.mapInteger(CoffGroup.Characteristics));
error(IO.mapInteger(CoffGroup.Offset));
error(IO.mapInteger(CoffGroup.Segment));
error(IO.mapStringZ(CoffGroup.Name));
return Error::success();
}
Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
BPRelativeSym &BPRel) {
error(IO.mapInteger(BPRel.Offset));
error(IO.mapInteger(BPRel.Type));
error(IO.mapStringZ(BPRel.Name));
return Error::success();
}
Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
BuildInfoSym &BuildInfo) {
error(IO.mapInteger(BuildInfo.BuildId));
return Error::success();
}
Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
CallSiteInfoSym &CallSiteInfo) {
uint16_t Padding = 0;
error(IO.mapInteger(CallSiteInfo.CodeOffset));
error(IO.mapInteger(CallSiteInfo.Segment));
error(IO.mapInteger(Padding));
error(IO.mapInteger(CallSiteInfo.Type));
return Error::success();
}
Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
EnvBlockSym &EnvBlock) {
uint8_t Reserved = 0;
error(IO.mapInteger(Reserved));
error(IO.mapStringZVectorZ(EnvBlock.Fields));
return Error::success();
}
Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
FileStaticSym &FileStatic) {
error(IO.mapInteger(FileStatic.Index));
error(IO.mapInteger(FileStatic.ModFilenameOffset));
error(IO.mapEnum(FileStatic.Flags));
error(IO.mapStringZ(FileStatic.Name));
return Error::success();
}
Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, ExportSym &Export) {
error(IO.mapInteger(Export.Ordinal));
error(IO.mapEnum(Export.Flags));
error(IO.mapStringZ(Export.Name));
return Error::success();
}
Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
Compile2Sym &Compile2) {
error(IO.mapEnum(Compile2.Flags));
error(IO.mapEnum(Compile2.Machine));
error(IO.mapInteger(Compile2.VersionFrontendMajor));
error(IO.mapInteger(Compile2.VersionFrontendMinor));
error(IO.mapInteger(Compile2.VersionFrontendBuild));
error(IO.mapInteger(Compile2.VersionBackendMajor));
error(IO.mapInteger(Compile2.VersionBackendMinor));
error(IO.mapInteger(Compile2.VersionBackendBuild));
error(IO.mapStringZ(Compile2.Version));
error(IO.mapStringZVectorZ(Compile2.ExtraStrings));
return Error::success();
}
Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
Compile3Sym &Compile3) {
error(IO.mapEnum(Compile3.Flags));
error(IO.mapEnum(Compile3.Machine));
error(IO.mapInteger(Compile3.VersionFrontendMajor));
error(IO.mapInteger(Compile3.VersionFrontendMinor));
error(IO.mapInteger(Compile3.VersionFrontendBuild));
error(IO.mapInteger(Compile3.VersionFrontendQFE));
error(IO.mapInteger(Compile3.VersionBackendMajor));
error(IO.mapInteger(Compile3.VersionBackendMinor));
error(IO.mapInteger(Compile3.VersionBackendBuild));
error(IO.mapInteger(Compile3.VersionBackendQFE));
error(IO.mapStringZ(Compile3.Version));
return Error::success();
}
Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
ConstantSym &Constant) {
error(IO.mapInteger(Constant.Type));
error(IO.mapEncodedInteger(Constant.Value));
error(IO.mapStringZ(Constant.Name));
return Error::success();
}
Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, DataSym &Data) {
error(IO.mapInteger(Data.Type));
error(IO.mapInteger(Data.DataOffset));
error(IO.mapInteger(Data.Segment));
error(IO.mapStringZ(Data.Name));
return Error::success();
}
Error SymbolRecordMapping::visitKnownRecord(
CVSymbol &CVR, DefRangeFramePointerRelSym &DefRangeFramePointerRel) {
error(IO.mapObject(DefRangeFramePointerRel.Hdr.Offset));
error(mapLocalVariableAddrRange(IO, DefRangeFramePointerRel.Range));
error(IO.mapVectorTail(DefRangeFramePointerRel.Gaps, MapGap()));
return Error::success();
}
Error SymbolRecordMapping::visitKnownRecord(
CVSymbol &CVR,
DefRangeFramePointerRelFullScopeSym &DefRangeFramePointerRelFullScope) {
error(IO.mapInteger(DefRangeFramePointerRelFullScope.Offset));
return Error::success();
}
Error SymbolRecordMapping::visitKnownRecord(
CVSymbol &CVR, DefRangeRegisterRelSym &DefRangeRegisterRel) {
error(IO.mapObject(DefRangeRegisterRel.Hdr.Register));
error(IO.mapObject(DefRangeRegisterRel.Hdr.Flags));
error(IO.mapObject(DefRangeRegisterRel.Hdr.BasePointerOffset));
error(mapLocalVariableAddrRange(IO, DefRangeRegisterRel.Range));
error(IO.mapVectorTail(DefRangeRegisterRel.Gaps, MapGap()));
return Error::success();
}
Error SymbolRecordMapping::visitKnownRecord(
CVSymbol &CVR, DefRangeRegisterSym &DefRangeRegister) {
error(IO.mapObject(DefRangeRegister.Hdr.Register));
error(IO.mapObject(DefRangeRegister.Hdr.MayHaveNoName));
error(mapLocalVariableAddrRange(IO, DefRangeRegister.Range));
error(IO.mapVectorTail(DefRangeRegister.Gaps, MapGap()));
return Error::success();
}
Error SymbolRecordMapping::visitKnownRecord(
CVSymbol &CVR, DefRangeSubfieldRegisterSym &DefRangeSubfieldRegister) {
error(IO.mapObject(DefRangeSubfieldRegister.Hdr.Register));
error(IO.mapObject(DefRangeSubfieldRegister.Hdr.MayHaveNoName));
error(IO.mapObject(DefRangeSubfieldRegister.Hdr.OffsetInParent));
error(mapLocalVariableAddrRange(IO, DefRangeSubfieldRegister.Range));
error(IO.mapVectorTail(DefRangeSubfieldRegister.Gaps, MapGap()));
return Error::success();
}
Error SymbolRecordMapping::visitKnownRecord(
CVSymbol &CVR, DefRangeSubfieldSym &DefRangeSubfield) {
error(IO.mapInteger(DefRangeSubfield.Program));
error(IO.mapInteger(DefRangeSubfield.OffsetInParent));
error(mapLocalVariableAddrRange(IO, DefRangeSubfield.Range));
error(IO.mapVectorTail(DefRangeSubfield.Gaps, MapGap()));
return Error::success();
}
Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
DefRangeSym &DefRange) {
error(IO.mapInteger(DefRange.Program));
error(mapLocalVariableAddrRange(IO, DefRange.Range));
error(IO.mapVectorTail(DefRange.Gaps, MapGap()));
return Error::success();
}
Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
FrameCookieSym &FrameCookie) {
error(IO.mapInteger(FrameCookie.CodeOffset));
error(IO.mapInteger(FrameCookie.Register));
error(IO.mapEnum(FrameCookie.CookieKind));
error(IO.mapInteger(FrameCookie.Flags));
return Error::success();
}
Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
FrameProcSym &FrameProc) {
error(IO.mapInteger(FrameProc.TotalFrameBytes));
error(IO.mapInteger(FrameProc.PaddingFrameBytes));
error(IO.mapInteger(FrameProc.OffsetToPadding));
error(IO.mapInteger(FrameProc.BytesOfCalleeSavedRegisters));
error(IO.mapInteger(FrameProc.OffsetOfExceptionHandler));
error(IO.mapInteger(FrameProc.SectionIdOfExceptionHandler));
error(IO.mapEnum(FrameProc.Flags));
return Error::success();
}
Error SymbolRecordMapping::visitKnownRecord(
CVSymbol &CVR, HeapAllocationSiteSym &HeapAllocSite) {
error(IO.mapInteger(HeapAllocSite.CodeOffset));
error(IO.mapInteger(HeapAllocSite.Segment));
error(IO.mapInteger(HeapAllocSite.CallInstructionSize));
error(IO.mapInteger(HeapAllocSite.Type));
return Error::success();
}
Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
InlineSiteSym &InlineSite) {
error(IO.mapInteger(InlineSite.Parent));
error(IO.mapInteger(InlineSite.End));
error(IO.mapInteger(InlineSite.Inlinee));
error(IO.mapByteVectorTail(InlineSite.AnnotationData));
return Error::success();
}
Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
RegisterSym &Register) {
error(IO.mapInteger(Register.Index));
error(IO.mapEnum(Register.Register));
error(IO.mapStringZ(Register.Name));
return Error::success();
}
Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
PublicSym32 &Public) {
error(IO.mapEnum(Public.Flags));
error(IO.mapInteger(Public.Offset));
error(IO.mapInteger(Public.Segment));
error(IO.mapStringZ(Public.Name));
return Error::success();
}
Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
ProcRefSym &ProcRef) {
error(IO.mapInteger(ProcRef.SumName));
error(IO.mapInteger(ProcRef.SymOffset));
error(IO.mapInteger(ProcRef.Module));
error(IO.mapStringZ(ProcRef.Name));
return Error::success();
}
Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, LabelSym &Label) {
error(IO.mapInteger(Label.CodeOffset));
error(IO.mapInteger(Label.Segment));
error(IO.mapEnum(Label.Flags));
error(IO.mapStringZ(Label.Name));
return Error::success();
}
Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, LocalSym &Local) {
error(IO.mapInteger(Local.Type));
error(IO.mapEnum(Local.Flags));
error(IO.mapStringZ(Local.Name));
return Error::success();
}
Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
ObjNameSym &ObjName) {
error(IO.mapInteger(ObjName.Signature));
error(IO.mapStringZ(ObjName.Name));
return Error::success();
}
Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, ProcSym &Proc) {
error(IO.mapInteger(Proc.Parent));
error(IO.mapInteger(Proc.End));
error(IO.mapInteger(Proc.Next));
error(IO.mapInteger(Proc.CodeSize));
error(IO.mapInteger(Proc.DbgStart));
error(IO.mapInteger(Proc.DbgEnd));
error(IO.mapInteger(Proc.FunctionType));
error(IO.mapInteger(Proc.CodeOffset));
error(IO.mapInteger(Proc.Segment));
error(IO.mapEnum(Proc.Flags));
error(IO.mapStringZ(Proc.Name));
return Error::success();
}
Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
ScopeEndSym &ScopeEnd) {
return Error::success();
}
Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, CallerSym &Caller) {
error(IO.mapVectorN<uint32_t>(
Caller.Indices,
[](CodeViewRecordIO &IO, TypeIndex &N) { return IO.mapInteger(N); }));
return Error::success();
}
Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
RegRelativeSym &RegRel) {
error(IO.mapInteger(RegRel.Offset));
error(IO.mapInteger(RegRel.Type));
error(IO.mapEnum(RegRel.Register));
error(IO.mapStringZ(RegRel.Name));
return Error::success();
}
Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
ThreadLocalDataSym &Data) {
error(IO.mapInteger(Data.Type));
error(IO.mapInteger(Data.DataOffset));
error(IO.mapInteger(Data.Segment));
error(IO.mapStringZ(Data.Name));
return Error::success();
}
Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR, UDTSym &UDT) {
error(IO.mapInteger(UDT.Type));
error(IO.mapStringZ(UDT.Name));
return Error::success();
}
Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
UsingNamespaceSym &UN) {
error(IO.mapStringZ(UN.Name));
return Error::success();
}
Error SymbolRecordMapping::visitKnownRecord(CVSymbol &CVR,
AnnotationSym &Annot) {
error(IO.mapInteger(Annot.CodeOffset));
error(IO.mapInteger(Annot.Segment));
error(IO.mapVectorN<uint16_t>(
Annot.Strings,
[](CodeViewRecordIO &IO, StringRef &S) { return IO.mapStringZ(S); }));
return Error::success();
}
RegisterId codeview::decodeFramePtrReg(EncodedFramePtrReg EncodedReg,
CPUType CPU) {
assert(unsigned(EncodedReg) < 4);
switch (CPU) {
// FIXME: Add ARM and AArch64 variants here.
default:
break;
case CPUType::Intel8080:
case CPUType::Intel8086:
case CPUType::Intel80286:
case CPUType::Intel80386:
case CPUType::Intel80486:
case CPUType::Pentium:
case CPUType::PentiumPro:
case CPUType::Pentium3:
switch (EncodedReg) {
case EncodedFramePtrReg::None: return RegisterId::NONE;
case EncodedFramePtrReg::StackPtr: return RegisterId::VFRAME;
case EncodedFramePtrReg::FramePtr: return RegisterId::EBP;
case EncodedFramePtrReg::BasePtr: return RegisterId::EBX;
}
llvm_unreachable("bad encoding");
case CPUType::X64:
switch (EncodedReg) {
case EncodedFramePtrReg::None: return RegisterId::NONE;
case EncodedFramePtrReg::StackPtr: return RegisterId::RSP;
case EncodedFramePtrReg::FramePtr: return RegisterId::RBP;
case EncodedFramePtrReg::BasePtr: return RegisterId::R13;
}
llvm_unreachable("bad encoding");
}
return RegisterId::NONE;
}
EncodedFramePtrReg codeview::encodeFramePtrReg(RegisterId Reg, CPUType CPU) {
switch (CPU) {
// FIXME: Add ARM and AArch64 variants here.
default:
break;
case CPUType::Intel8080:
case CPUType::Intel8086:
case CPUType::Intel80286:
case CPUType::Intel80386:
case CPUType::Intel80486:
case CPUType::Pentium:
case CPUType::PentiumPro:
case CPUType::Pentium3:
switch (Reg) {
case RegisterId::VFRAME:
return EncodedFramePtrReg::StackPtr;
case RegisterId::EBP:
return EncodedFramePtrReg::FramePtr;
case RegisterId::EBX:
return EncodedFramePtrReg::BasePtr;
default:
break;
}
break;
case CPUType::X64:
switch (Reg) {
case RegisterId::RSP:
return EncodedFramePtrReg::StackPtr;
case RegisterId::RBP:
return EncodedFramePtrReg::FramePtr;
case RegisterId::R13:
return EncodedFramePtrReg::BasePtr;
default:
break;
}
break;
}
return EncodedFramePtrReg::None;
}