Add VC Debug support for linking pdb files - #3
Merged
Conversation
MSVC 6.0's /Zi writes each TU's types into an external PDB 2.0 type
server (*.o.pdb), referenced from .debug$T by an old LF_TYPESERVER/
LF_TYPESERVER_ST record. PDB 2.0 is a different, older MSF container
than PDB 7.0 ("DS"), so PDBFile/NativeSession can't open it, and its
named type records use old "_ST" (Pascal-name) leaf kinds lld doesn't
recognize -- so --debug PDBs for VC6-era objects previously got no
struct/class/enum type info, only function names from COFF symbols.
Adds a small from-scratch PDB 2.0 MSF + TPI-stream reader
(Pdb2TypeServer.h/.cpp) that extracts the TPI stream and rewrites
_ST leaf kinds to their modern equivalents in place (Pascal-length-
prefixed names to null-terminated; same byte length, no reindexing).
Intra-object TypeIndex references are already 0x1000-based per
record position, matching what TypeIndex::toArrayIndex() expects, so
no remapping is needed there.
Wires this into InputFiles.cpp's LF_TYPESERVER/_ST handling as a
plain generic TpiSource, bypassing TypeServerSource/NativeSession
entirely for the old format. Every failure path (sidecar not found,
unreadable, wrong format) falls back to an empty TpiSource rather
than leaving debugTypesObj null, since PDB.cpp's writeSymbolRecord
dereferences it unconditionally for any object with .debug$S symbol
records.
Chunks.cpp: accept CV_SIGNATURE_C11 for .debug$T specifically, so the
old-format LF_TYPESERVER record isn't rejected before it can be read
(.debug$S stays rejected -- VC6's C11 symbol subsection format isn't
handled here).
PDB.cpp: guard against empty-chunk output sections in
addLinkerModuleSectionSymbol (unrelated crash hit along the way).
llvm-pdbutil: fix a pre-existing build break (TpiStream::getHashValues
was renamed to getHashValuesV80) hit while verifying the output PDB.
Verified against a real BW1 game binary rebuild: --debug link
completes cleanly and the output PDB contains real type names
(enum and struct) round-tripped from VC6 object files.
MSVC 6.0 /Zi writes each .debug$S section using the old CodeView C11 signature: a flat, unwrapped sequence of symbol records (no subsection framing, unlike modern C13), using old "_ST" (Pascal-name) kinds for the handful of record types that carry a name. lld previously rejected these sections outright (unrecognized magic), so --debug PDBs had no local/global variable names, enum constants, or UDT references -- only function names from COFF publics and (as of the previous commit) types from the per-object PDB 2.0 .debug$T type servers. Adds Pdb2Symbols.h/.cpp, converting the old symbol kinds actually emitted by real compiled objects in this project (surveyed across all of them): S_OBJNAME_ST, S_CONSTANT_ST, S_UDT_ST, S_LDATA32_ST, S_GDATA32_ST, S_REGISTER_ST, S_BPREL32_ST, S_LABEL32_ST, S_LPROC32_ST, S_GPROC32_ST -> their modern equivalents, and S_COMPILE (which predates the "_ST" family and has no modern equivalent in LLVM at all) -> S_SKIP. Objects with more than one function have additional .debug$S sections -- one per function -- that carry no magic at all, starting directly with S_GPROC32_ST/S_LPROC32_ST; those are handled too. Conversion happens once per chunk at object-load time (InputFiles.cpp) and is strictly in-place: same total size, same byte offsets, magic present or absent exactly as given. This section's own COFF relocations point at byte offsets within these records (e.g. S_GDATA32_ST's DataOffset/Segment fields), so nothing may shift them -- not even by stripping a magic prefix from the stored copy, which is why the override still carries whatever magic (or lack thereof) the original had; callers check isOldCodeViewSymbols/ isBareOldCodeViewSymbols to decide how to treat it instead. SectionChunk has a static_assert on its size (there can be very many instances), so the override lives in a small DenseMap on ObjFile instead of a new SectionChunk field -- ObjFile instances are much rarer. Verified against a real BW1 game binary rebuild: the output PDB now contains real global/local variable names, enum constants, and compiler-generated labels (e.g. "MPFEConnectionStatus::IsInternetLobby", "$L17277") round-tripped from VC6 object files, with zero errors or warnings.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.