summaryrefslogtreecommitdiff
path: root/llvm/lib/DebugInfo
diff options
context:
space:
mode:
authorMingming Liu <mingmingl@google.com>2025-09-10 15:25:31 -0700
committerGitHub <noreply@github.com>2025-09-10 15:25:31 -0700
commit1417dafa1db9cb1b2b09438aa9f53ea5ab6e36e2 (patch)
tree57f4b1f313c8cf74eed8819870f39c36ea263c68 /llvm/lib/DebugInfo
parent898b813bc8a6d0276bf0f4769f5f2f64b34e632d (diff)
parentb8cefcb601ddaa18482555c4ff363c01a270c2fe (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.cpp163
-rw-r--r--llvm/lib/DebugInfo/GSYM/GsymContext.cpp1
-rw-r--r--llvm/lib/DebugInfo/LogicalView/Readers/LVBinaryReader.cpp15
-rw-r--r--llvm/lib/DebugInfo/LogicalView/Readers/LVDWARFReader.cpp10
-rw-r--r--llvm/lib/DebugInfo/PDB/Native/InputFile.cpp5
-rw-r--r--llvm/lib/DebugInfo/PDB/Native/PublicsStream.cpp50
-rw-r--r--llvm/lib/DebugInfo/PDB/PDBSymbolTypeBuiltin.cpp6
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;