diff options
| author | Mingming Liu <mingmingl@google.com> | 2025-09-10 15:25:31 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-09-10 15:25:31 -0700 |
| commit | 1417dafa1db9cb1b2b09438aa9f53ea5ab6e36e2 (patch) | |
| tree | 57f4b1f313c8cf74eed8819870f39c36ea263c68 /llvm/lib/DebugInfo | |
| parent | 898b813bc8a6d0276bf0f4769f5f2f64b34e632d (diff) | |
| parent | b8cefcb601ddaa18482555c4ff363c01a270c2fe (diff) | |
Merge branch 'main' into users/mingmingl-llvm/samplefdo-profile-formatusers/mingmingl-llvm/samplefdo-profile-format
Diffstat (limited to 'llvm/lib/DebugInfo')
| -rw-r--r-- | llvm/lib/DebugInfo/DWARF/DWARFExpressionPrinter.cpp | 163 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/GSYM/GsymContext.cpp | 1 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/LogicalView/Readers/LVBinaryReader.cpp | 15 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp | 10 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/PDB/Native/InputFile.cpp | 5 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/PDB/Native/PublicsStream.cpp | 50 | ||||
| -rw-r--r-- | llvm/lib/DebugInfo/PDB/PDBSymbolTypeBuiltin.cpp | 6 |
7 files changed, 180 insertions, 70 deletions
diff --git a/llvm/lib/DebugInfo/DWARF/DWARFExpressionPrinter.cpp b/llvm/lib/DebugInfo/DWARF/DWARFExpressionPrinter.cpp index ebcd4dda5048..078ebf4e7c03 100644 --- a/llvm/lib/DebugInfo/DWARF/DWARFExpressionPrinter.cpp +++ b/llvm/lib/DebugInfo/DWARF/DWARFExpressionPrinter.cpp @@ -48,13 +48,52 @@ static bool printOp(const DWARFExpression::Operation *Op, raw_ostream &OS, DIDumpOptions DumpOpts, const DWARFExpression *Expr, DWARFUnit *U) { if (Op->isError()) { - OS << "<decoding error>"; + if (!DumpOpts.PrintRegisterOnly) + OS << "<decoding error>"; return false; } - StringRef Name = OperationEncodingString(Op->getCode()); - assert(!Name.empty() && "DW_OP has no name!"); - OS << Name; + // In "register-only" mode, still show simple constant-valued locations. + // This lets clients print annotations like "i = 0" when the location is + // a constant (e.g. DW_OP_constu/consts ... DW_OP_stack_value). + // We continue to suppress all other non-register ops in this mode. + if (DumpOpts.PrintRegisterOnly) { + // First, try pretty-printing registers (existing behavior below also does + // this, but we need to short-circuit here to avoid printing opcode names). + if ((Op->getCode() >= DW_OP_breg0 && Op->getCode() <= DW_OP_breg31) || + (Op->getCode() >= DW_OP_reg0 && Op->getCode() <= DW_OP_reg31) || + Op->getCode() == DW_OP_bregx || Op->getCode() == DW_OP_regx || + Op->getCode() == DW_OP_regval_type) { + if (prettyPrintRegisterOp(U, OS, DumpOpts, Op->getCode(), + Op->getRawOperands())) + return true; + // If we couldn't pretty-print, fall through and suppress. + } + + // Show constants (decimal), suppress everything else. + if (Op->getCode() == DW_OP_constu) { + OS << (uint64_t)Op->getRawOperand(0); + return true; + } + if (Op->getCode() == DW_OP_consts) { + OS << (int64_t)Op->getRawOperand(0); + return true; + } + if (Op->getCode() >= DW_OP_lit0 && Op->getCode() <= DW_OP_lit31) { + OS << (unsigned)(Op->getCode() - DW_OP_lit0); + return true; + } + if (Op->getCode() == DW_OP_stack_value) + return true; // metadata; don't print a token + + return true; // suppress other opcodes silently in register-only mode + } + + if (!DumpOpts.PrintRegisterOnly) { + StringRef Name = OperationEncodingString(Op->getCode()); + assert(!Name.empty() && "DW_OP has no name!"); + OS << Name; + } if ((Op->getCode() >= DW_OP_breg0 && Op->getCode() <= DW_OP_breg31) || (Op->getCode() >= DW_OP_reg0 && Op->getCode() <= DW_OP_reg31) || @@ -64,48 +103,51 @@ static bool printOp(const DWARFExpression::Operation *Op, raw_ostream &OS, Op->getRawOperands())) return true; - for (unsigned Operand = 0; Operand < Op->getDescription().Op.size(); - ++Operand) { - unsigned Size = Op->getDescription().Op[Operand]; - unsigned Signed = Size & DWARFExpression::Operation::SignBit; - - if (Size == DWARFExpression::Operation::SizeSubOpLEB) { - StringRef SubName = - SubOperationEncodingString(Op->getCode(), Op->getRawOperand(Operand)); - assert(!SubName.empty() && "DW_OP SubOp has no name!"); - OS << " " << SubName; - } else if (Size == DWARFExpression::Operation::BaseTypeRef && U) { - // For DW_OP_convert the operand may be 0 to indicate that conversion to - // the generic type should be done. The same holds for DW_OP_reinterpret, - // which is currently not supported. - if (Op->getCode() == DW_OP_convert && Op->getRawOperand(Operand) == 0) - OS << " 0x0"; - else - prettyPrintBaseTypeRef(U, OS, DumpOpts, Op->getRawOperands(), Operand); - } else if (Size == DWARFExpression::Operation::WasmLocationArg) { - assert(Operand == 1); - switch (Op->getRawOperand(0)) { - case 0: - case 1: - case 2: - case 3: // global as uint32 - case 4: - OS << format(" 0x%" PRIx64, Op->getRawOperand(Operand)); - break; - default: - assert(false); + if (!DumpOpts.PrintRegisterOnly) { + for (unsigned Operand = 0; Operand < Op->getDescription().Op.size(); + ++Operand) { + unsigned Size = Op->getDescription().Op[Operand]; + unsigned Signed = Size & DWARFExpression::Operation::SignBit; + + if (Size == DWARFExpression::Operation::SizeSubOpLEB) { + StringRef SubName = SubOperationEncodingString( + Op->getCode(), Op->getRawOperand(Operand)); + assert(!SubName.empty() && "DW_OP SubOp has no name!"); + OS << " " << SubName; + } else if (Size == DWARFExpression::Operation::BaseTypeRef && U) { + // For DW_OP_convert the operand may be 0 to indicate that conversion to + // the generic type should be done. The same holds for + // DW_OP_reinterpret, which is currently not supported. + if (Op->getCode() == DW_OP_convert && Op->getRawOperand(Operand) == 0) + OS << " 0x0"; + else + prettyPrintBaseTypeRef(U, OS, DumpOpts, Op->getRawOperands(), + Operand); + } else if (Size == DWARFExpression::Operation::WasmLocationArg) { + assert(Operand == 1); + switch (Op->getRawOperand(0)) { + case 0: + case 1: + case 2: + case 3: // global as uint32 + case 4: + OS << format(" 0x%" PRIx64, Op->getRawOperand(Operand)); + break; + default: + assert(false); + } + } else if (Size == DWARFExpression::Operation::SizeBlock) { + uint64_t Offset = Op->getRawOperand(Operand); + for (unsigned i = 0; i < Op->getRawOperand(Operand - 1); ++i) + OS << format(" 0x%02x", + static_cast<uint8_t>(Expr->getData()[Offset++])); + } else { + if (Signed) + OS << format(" %+" PRId64, (int64_t)Op->getRawOperand(Operand)); + else if (Op->getCode() != DW_OP_entry_value && + Op->getCode() != DW_OP_GNU_entry_value) + OS << format(" 0x%" PRIx64, Op->getRawOperand(Operand)); } - } else if (Size == DWARFExpression::Operation::SizeBlock) { - uint64_t Offset = Op->getRawOperand(Operand); - for (unsigned i = 0; i < Op->getRawOperand(Operand - 1); ++i) - OS << format(" 0x%02x", - static_cast<uint8_t>(Expr->getData()[Offset++])); - } else { - if (Signed) - OS << format(" %+" PRId64, (int64_t)Op->getRawOperand(Operand)); - else if (Op->getCode() != DW_OP_entry_value && - Op->getCode() != DW_OP_GNU_entry_value) - OS << format(" 0x%" PRIx64, Op->getRawOperand(Operand)); } } return true; @@ -120,29 +162,30 @@ void printDwarfExpression(const DWARFExpression *E, raw_ostream &OS, for (auto &Op : *E) { DumpOpts.IsEH = IsEH; - if (!printOp(&Op, OS, DumpOpts, E, U)) { + if (!printOp(&Op, OS, DumpOpts, E, U) && !DumpOpts.PrintRegisterOnly) { uint64_t FailOffset = Op.getEndOffset(); while (FailOffset < E->getData().size()) OS << format(" %02x", static_cast<uint8_t>(E->getData()[FailOffset++])); return; } + if (!DumpOpts.PrintRegisterOnly) { + if (Op.getCode() == DW_OP_entry_value || + Op.getCode() == DW_OP_GNU_entry_value) { + OS << "("; + EntryValExprSize = Op.getRawOperand(0); + EntryValStartOffset = Op.getEndOffset(); + continue; + } - if (Op.getCode() == DW_OP_entry_value || - Op.getCode() == DW_OP_GNU_entry_value) { - OS << "("; - EntryValExprSize = Op.getRawOperand(0); - EntryValStartOffset = Op.getEndOffset(); - continue; - } + if (EntryValExprSize) { + EntryValExprSize -= Op.getEndOffset() - EntryValStartOffset; + if (EntryValExprSize == 0) + OS << ")"; + } - if (EntryValExprSize) { - EntryValExprSize -= Op.getEndOffset() - EntryValStartOffset; - if (EntryValExprSize == 0) - OS << ")"; + if (Op.getEndOffset() < E->getData().size()) + OS << ", "; } - - if (Op.getEndOffset() < E->getData().size()) - OS << ", "; } } diff --git a/llvm/lib/DebugInfo/GSYM/GsymContext.cpp b/llvm/lib/DebugInfo/GSYM/GsymContext.cpp index 18be6d098546..62b4caa327d8 100644 --- a/llvm/lib/DebugInfo/GSYM/GsymContext.cpp +++ b/llvm/lib/DebugInfo/GSYM/GsymContext.cpp @@ -14,6 +14,7 @@ using namespace llvm; using namespace llvm::gsym; +GsymContext::~GsymContext() = default; GsymContext::GsymContext(std::unique_ptr<GsymReader> Reader) : DIContext(CK_GSYM), Reader(std::move(Reader)) {} diff --git a/llvm/lib/DebugInfo/LogicalView/Readers/LVBinaryReader.cpp b/llvm/lib/DebugInfo/LogicalView/Readers/LVBinaryReader.cpp index 0df9137a3bd3..0d0383158dd4 100644 --- a/llvm/lib/DebugInfo/LogicalView/Readers/LVBinaryReader.cpp +++ b/llvm/lib/DebugInfo/LogicalView/Readers/LVBinaryReader.cpp @@ -274,9 +274,10 @@ void LVBinaryReader::mapVirtualAddress(const object::COFFObjectFile &COFFObj) { }); } -Error LVBinaryReader::loadGenericTargetInfo(StringRef TheTriple, +Error LVBinaryReader::loadGenericTargetInfo(StringRef TripleName, StringRef TheFeatures, StringRef TheCPU) { + Triple TheTriple(TripleName); std::string TargetLookupError; const Target *TheTarget = TargetRegistry::lookupTarget(TheTriple, TargetLookupError); @@ -287,7 +288,7 @@ Error LVBinaryReader::loadGenericTargetInfo(StringRef TheTriple, MCRegisterInfo *RegisterInfo = TheTarget->createMCRegInfo(TheTriple); if (!RegisterInfo) return createStringError(errc::invalid_argument, - "no register info for target " + TheTriple); + "no register info for target " + TripleName); MRI.reset(RegisterInfo); // Assembler properties and features. @@ -295,7 +296,7 @@ Error LVBinaryReader::loadGenericTargetInfo(StringRef TheTriple, MCAsmInfo *AsmInfo(TheTarget->createMCAsmInfo(*MRI, TheTriple, MCOptions)); if (!AsmInfo) return createStringError(errc::invalid_argument, - "no assembly info for target " + TheTriple); + "no assembly info for target " + TripleName); MAI.reset(AsmInfo); // Target subtargets. @@ -303,14 +304,14 @@ Error LVBinaryReader::loadGenericTargetInfo(StringRef TheTriple, TheTarget->createMCSubtargetInfo(TheTriple, TheCPU, TheFeatures)); if (!SubtargetInfo) return createStringError(errc::invalid_argument, - "no subtarget info for target " + TheTriple); + "no subtarget info for target " + TripleName); STI.reset(SubtargetInfo); // Instructions Info. MCInstrInfo *InstructionInfo(TheTarget->createMCInstrInfo()); if (!InstructionInfo) return createStringError(errc::invalid_argument, - "no instruction info for target " + TheTriple); + "no instruction info for target " + TripleName); MII.reset(InstructionInfo); MC = std::make_unique<MCContext>(Triple(TheTriple), MAI.get(), MRI.get(), @@ -320,7 +321,7 @@ Error LVBinaryReader::loadGenericTargetInfo(StringRef TheTriple, MCDisassembler *DisAsm(TheTarget->createMCDisassembler(*STI, *MC)); if (!DisAsm) return createStringError(errc::invalid_argument, - "no disassembler for target " + TheTriple); + "no disassembler for target " + TripleName); MD.reset(DisAsm); MCInstPrinter *InstructionPrinter(TheTarget->createMCInstPrinter( @@ -328,7 +329,7 @@ Error LVBinaryReader::loadGenericTargetInfo(StringRef TheTriple, if (!InstructionPrinter) return createStringError(errc::invalid_argument, "no target assembly language printer for target " + - TheTriple); + TripleName); MIP.reset(InstructionPrinter); InstructionPrinter->setPrintImmHex(true); diff --git a/llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp b/llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp index 62134dfdadf4..3ba506171814 100644 --- a/llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp +++ b/llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp @@ -274,7 +274,7 @@ void LVDWARFReader::processOneAttribute(const DWARFDie &Die, for (DWARFAddressRange &Range : Ranges) { // This seems to be a tombstone for empty ranges. if ((Range.LowPC == Range.HighPC) || - (Range.LowPC = getTombstoneAddress())) + (Range.LowPC == getTombstoneAddress())) continue; // Store the real upper limit for the address range. if (UpdateHighAddress && Range.HighPC > 0) @@ -461,13 +461,17 @@ LVScope *LVDWARFReader::processOneDie(const DWARFDie &InputDIE, LVScope *Parent, if (!CurrentRanges.empty()) { for (LVAddressRange &Range : CurrentRanges) addSectionRange(SectionIndex, CurrentScope, Range.first, - Range.second); + Range.second > Range.first + ? Range.second - 1 // Make hi-pc exclusive + : Range.second); CurrentRanges.clear(); } // If the scope is the CU, do not update the ranges set. if (FoundLowPC && FoundHighPC && !IsCompileUnit) { addSectionRange(SectionIndex, CurrentScope, CurrentLowPC, - CurrentHighPC); + CurrentHighPC > CurrentLowPC + ? CurrentHighPC - 1 // Make hi-pc exclusive + : CurrentHighPC); } } } diff --git a/llvm/lib/DebugInfo/PDB/Native/InputFile.cpp b/llvm/lib/DebugInfo/PDB/Native/InputFile.cpp index 328d0f5ab060..49be0edc33a1 100644 --- a/llvm/lib/DebugInfo/PDB/Native/InputFile.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/InputFile.cpp @@ -586,3 +586,8 @@ bool llvm::pdb::shouldDumpSymbolGroup(uint32_t Idx, const SymbolGroup &Group, // Otherwise, only dump if this is the same module specified. return (Filters.DumpModi == Idx); } +llvm::pdb::InputFile::InputFile(PDBFile *Pdb) { PdbOrObj = Pdb; } + +llvm::pdb::InputFile::InputFile(object::COFFObjectFile *Obj) { PdbOrObj = Obj; } + +llvm::pdb::InputFile::InputFile(MemoryBuffer *Buffer) { PdbOrObj = Buffer; } diff --git a/llvm/lib/DebugInfo/PDB/Native/PublicsStream.cpp b/llvm/lib/DebugInfo/PDB/Native/PublicsStream.cpp index c350e0e0b3e1..0453eea26605 100644 --- a/llvm/lib/DebugInfo/PDB/Native/PublicsStream.cpp +++ b/llvm/lib/DebugInfo/PDB/Native/PublicsStream.cpp @@ -22,9 +22,12 @@ //===----------------------------------------------------------------------===// #include "llvm/DebugInfo/PDB/Native/PublicsStream.h" +#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h" +#include "llvm/DebugInfo/CodeView/SymbolRecord.h" #include "llvm/DebugInfo/MSF/MappedBlockStream.h" #include "llvm/DebugInfo/PDB/Native/RawError.h" #include "llvm/DebugInfo/PDB/Native/RawTypes.h" +#include "llvm/DebugInfo/PDB/Native/SymbolStream.h" #include "llvm/Support/BinaryStreamReader.h" #include "llvm/Support/Error.h" #include <cstdint> @@ -96,3 +99,50 @@ Error PublicsStream::reload() { "Corrupted publics stream."); return Error::success(); } + +// This is a reimplementation of NearestSym: +// https://github.com/microsoft/microsoft-pdb/blob/805655a28bd8198004be2ac27e6e0290121a5e89/PDB/dbi/gsi.cpp#L1492-L1581 +std::optional<std::pair<codeview::PublicSym32, size_t>> +PublicsStream::findByAddress(const SymbolStream &Symbols, uint16_t Segment, + uint32_t Offset) const { + // The address map is sorted by address, so we can use lower_bound to find the + // position. Each element is an offset into the symbols for a public symbol. + auto It = llvm::lower_bound( + AddressMap, std::tuple(Segment, Offset), + [&](support::ulittle32_t Cur, auto Addr) { + auto Sym = Symbols.readRecord(Cur.value()); + if (Sym.kind() != codeview::S_PUB32) + return false; // stop here, this is most likely corrupted debug info + + auto Psym = + codeview::SymbolDeserializer::deserializeAs<codeview::PublicSym32>( + Sym); + if (!Psym) { + consumeError(Psym.takeError()); + return false; + } + + return std::tie(Psym->Segment, Psym->Offset) < Addr; + }); + + if (It == AddressMap.end()) + return std::nullopt; + + auto Sym = Symbols.readRecord(It->value()); + if (Sym.kind() != codeview::S_PUB32) + return std::nullopt; // this is most likely corrupted debug info + + auto MaybePsym = + codeview::SymbolDeserializer::deserializeAs<codeview::PublicSym32>(Sym); + if (!MaybePsym) { + consumeError(MaybePsym.takeError()); + return std::nullopt; + } + codeview::PublicSym32 Psym = std::move(*MaybePsym); + + if (std::tuple(Segment, Offset) != std::tuple(Psym.Segment, Psym.Offset)) + return std::nullopt; + + std::ptrdiff_t IterOffset = It - AddressMap.begin(); + return std::pair{Psym, static_cast<size_t>(IterOffset)}; +} diff --git a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeBuiltin.cpp b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeBuiltin.cpp index eca2a09c1f77..7c8ef18f126d 100644 --- a/llvm/lib/DebugInfo/PDB/PDBSymbolTypeBuiltin.cpp +++ b/llvm/lib/DebugInfo/PDB/PDBSymbolTypeBuiltin.cpp @@ -10,6 +10,12 @@ #include "llvm/DebugInfo/PDB/PDBSymDumper.h" +namespace llvm { +namespace pdb { +PDBSymbolTypeBuiltin::~PDBSymbolTypeBuiltin() = default; +} // namespace pdb +} // namespace llvm + using namespace llvm; using namespace llvm::pdb; |
