[PDB] Merge in types and items from type servers (/Zi)

Summary:
Object files compiled with /Zi emit type information into a type server
PDB. The .debug$S section will contain a single TypeServer2Record with
the absolute path and GUID of the type server. LLD needs to load the
type server PDB and merge all types and items it finds in it into the
destination PDB.

Depends on D35495

Reviewers: ruiu, inglorion

Subscribers: zturner, llvm-commits

Differential Revision: https://reviews.llvm.org/D35504

llvm-svn: 308235
This commit is contained in:
Reid Kleckner 2017-07-18 00:21:25 +00:00
parent 67653ee086
commit 651db91c2d
7 changed files with 830 additions and 28 deletions

View File

@ -14,27 +14,29 @@
#include "SymbolTable.h"
#include "Symbols.h"
#include "llvm/DebugInfo/CodeView/CVDebugRecord.h"
#include "llvm/DebugInfo/CodeView/CVTypeVisitor.h"
#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h"
#include "llvm/DebugInfo/CodeView/DebugSubsectionVisitor.h"
#include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h"
#include "llvm/DebugInfo/CodeView/SymbolSerializer.h"
#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
#include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h"
#include "llvm/DebugInfo/CodeView/TypeIndexDiscovery.h"
#include "llvm/DebugInfo/CodeView/TypeStreamMerger.h"
#include "llvm/DebugInfo/CodeView/TypeTableBuilder.h"
#include "llvm/DebugInfo/MSF/MSFBuilder.h"
#include "llvm/DebugInfo/MSF/MSFCommon.h"
#include "llvm/DebugInfo/PDB/GenericError.h"
#include "llvm/DebugInfo/PDB/Native/DbiModuleDescriptorBuilder.h"
#include "llvm/DebugInfo/PDB/Native/DbiStream.h"
#include "llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h"
#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
#include "llvm/DebugInfo/PDB/Native/InfoStreamBuilder.h"
#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
#include "llvm/DebugInfo/PDB/Native/PDBFileBuilder.h"
#include "llvm/DebugInfo/PDB/Native/PDBStringTableBuilder.h"
#include "llvm/DebugInfo/PDB/Native/TpiStream.h"
#include "llvm/DebugInfo/PDB/Native/TpiStreamBuilder.h"
#include "llvm/DebugInfo/PDB/PDB.h"
#include "llvm/Object/COFF.h"
#include "llvm/Support/BinaryByteStream.h"
#include "llvm/Support/Endian.h"
@ -53,6 +55,14 @@ using llvm::object::coff_section;
static ExitOnError ExitOnErr;
namespace {
/// Map from type index and item index in a type server PDB to the
/// corresponding index in the destination PDB.
struct CVIndexMap {
SmallVector<TypeIndex, 0> TPIMap;
SmallVector<TypeIndex, 0> IPIMap;
bool IsTypeServerMap = false;
};
class PDBLinker {
public:
PDBLinker(SymbolTable *Symtab)
@ -68,10 +78,21 @@ public:
/// Link CodeView from a single object file into the PDB.
void addObjectFile(ObjectFile *File);
/// Merge the type information from the .debug$T section in the given object
/// file. Produce a mapping from object file type indices to type or
/// item indices in the final PDB.
void mergeDebugT(ObjectFile *File, SmallVectorImpl<TypeIndex> &TypeIndexMap);
/// Produce a mapping from the type and item indices used in the object
/// file to those in the destination PDB.
///
/// If the object file uses a type server PDB (compiled with /Zi), merge TPI
/// and IPI from the type server PDB and return a map for it. Each unique type
/// server PDB is merged at most once, so this may return an existing index
/// mapping.
///
/// If the object does not use a type server PDB (compiled with /Z7), we merge
/// all the type and item records from the .debug$S stream and fill in the
/// caller-provided ObjectIndexMap.
const CVIndexMap &mergeDebugT(ObjectFile *File, CVIndexMap &ObjectIndexMap);
const CVIndexMap &maybeMergeTypeServerPDB(ObjectFile *File,
TypeServer2Record &TS);
/// Add the section map and section contributions to the PDB.
void addSections(ArrayRef<uint8_t> SectionTable);
@ -99,6 +120,9 @@ private:
llvm::SmallString<128> NativePath;
std::vector<pdb::SecMapEntry> SectionMap;
/// Type index mappings of type server PDBs that we've loaded so far.
std::map<GUID, CVIndexMap> TypeServerIndexMappings;
};
}
@ -146,25 +170,114 @@ static void addTypeInfo(pdb::TpiStreamBuilder &TpiBuilder,
});
}
void PDBLinker::mergeDebugT(ObjectFile *File,
SmallVectorImpl<TypeIndex> &TypeIndexMap) {
static Optional<TypeServer2Record>
maybeReadTypeServerRecord(CVTypeArray &Types) {
auto I = Types.begin();
if (I == Types.end())
return None;
const CVType &Type = *I;
if (Type.kind() != LF_TYPESERVER2)
return None;
TypeServer2Record TS;
if (auto EC = TypeDeserializer::deserializeAs(const_cast<CVType &>(Type), TS))
fatal(EC, "error reading type server record");
return std::move(TS);
}
const CVIndexMap &PDBLinker::mergeDebugT(ObjectFile *File,
CVIndexMap &ObjectIndexMap) {
ArrayRef<uint8_t> Data = getDebugSection(File, ".debug$T");
if (Data.empty())
return;
// Look for type server PDBs next to the input file. If this file has a parent
// archive, look next to the archive path.
StringRef LocalPath =
!File->ParentName.empty() ? File->ParentName : File->getName();
(void)LocalPath; // FIXME: Implement type server handling here.
return ObjectIndexMap;
BinaryByteStream Stream(Data, support::little);
CVTypeArray Types;
BinaryStreamReader Reader(Stream);
if (auto EC = Reader.readArray(Types, Reader.getLength()))
fatal(EC, "Reader::readArray failed");
if (auto Err = mergeTypeAndIdRecords(IDTable, TypeTable, TypeIndexMap, Types))
fatal(Err, "codeview::mergeTypeStreams failed");
// Look through type servers. If we've already seen this type server, don't
// merge any type information.
if (Optional<TypeServer2Record> TS = maybeReadTypeServerRecord(Types))
return maybeMergeTypeServerPDB(File, *TS);
// This is a /Z7 object. Fill in the temporary, caller-provided
// ObjectIndexMap.
if (auto Err = mergeTypeAndIdRecords(IDTable, TypeTable,
ObjectIndexMap.TPIMap, Types))
fatal(Err, "codeview::mergeTypeAndIdRecords failed");
return ObjectIndexMap;
}
static Expected<std::unique_ptr<pdb::NativeSession>>
tryToLoadPDB(const GUID &GuidFromObj, StringRef TSPath) {
std::unique_ptr<pdb::IPDBSession> ThisSession;
if (auto EC =
pdb::loadDataForPDB(pdb::PDB_ReaderType::Native, TSPath, ThisSession))
return std::move(EC);
std::unique_ptr<pdb::NativeSession> NS(
static_cast<pdb::NativeSession *>(ThisSession.release()));
pdb::PDBFile &File = NS->getPDBFile();
auto ExpectedInfo = File.getPDBInfoStream();
// All PDB Files should have an Info stream.
if (!ExpectedInfo)
return ExpectedInfo.takeError();
// Just because a file with a matching name was found and it was an actual
// PDB file doesn't mean it matches. For it to match the InfoStream's GUID
// must match the GUID specified in the TypeServer2 record.
if (ExpectedInfo->getGuid() != GuidFromObj)
return make_error<pdb::GenericError>(
pdb::generic_error_code::type_server_not_found, TSPath);
return std::move(NS);
}
const CVIndexMap &PDBLinker::maybeMergeTypeServerPDB(ObjectFile *File,
TypeServer2Record &TS) {
// First, check if we already loaded a PDB with this GUID. Return the type
// index mapping if we have it.
auto Insertion = TypeServerIndexMappings.insert({TS.getGuid(), CVIndexMap()});
CVIndexMap &IndexMap = Insertion.first->second;
if (!Insertion.second)
return IndexMap;
// Mark this map as a type server map.
IndexMap.IsTypeServerMap = true;
// Check for a PDB at:
// 1. The given file path
// 2. Next to the object file or archive file
auto ExpectedSession = tryToLoadPDB(TS.getGuid(), TS.getName());
if (!ExpectedSession) {
consumeError(ExpectedSession.takeError());
StringRef LocalPath =
!File->ParentName.empty() ? File->ParentName : File->getName();
SmallString<128> Path = sys::path::parent_path(LocalPath);
sys::path::append(Path, sys::path::filename(TS.getName()));
ExpectedSession = tryToLoadPDB(TS.getGuid(), Path);
}
if (auto E = ExpectedSession.takeError())
fatal(E, "Type server PDB was not found");
// Merge TPI first, because the IPI stream will reference type indices.
auto ExpectedTpi = (*ExpectedSession)->getPDBFile().getPDBTpiStream();
if (auto E = ExpectedTpi.takeError())
fatal(E, "Type server does not have TPI stream");
if (auto Err = mergeTypeRecords(TypeTable, IndexMap.TPIMap,
ExpectedTpi->typeArray()))
fatal(Err, "codeview::mergeTypeRecords failed");
// Merge IPI.
auto ExpectedIpi = (*ExpectedSession)->getPDBFile().getPDBIpiStream();
if (auto E = ExpectedIpi.takeError())
fatal(E, "Type server does not have TPI stream");
if (auto Err = mergeIdRecords(IDTable, IndexMap.TPIMap, IndexMap.IPIMap,
ExpectedIpi->typeArray()))
fatal(Err, "codeview::mergeIdRecords failed");
return IndexMap;
}
static bool remapTypeIndex(TypeIndex &TI, ArrayRef<TypeIndex> TypeIndexMap) {
@ -178,16 +291,22 @@ static bool remapTypeIndex(TypeIndex &TI, ArrayRef<TypeIndex> TypeIndexMap) {
static void remapTypesInSymbolRecord(ObjectFile *File,
MutableArrayRef<uint8_t> Contents,
ArrayRef<TypeIndex> TypeIndexMap,
const CVIndexMap &IndexMap,
ArrayRef<TiReference> TypeRefs) {
for (const TiReference &Ref : TypeRefs) {
unsigned ByteSize = Ref.Count * sizeof(TypeIndex);
if (Contents.size() < Ref.Offset + ByteSize)
fatal("symbol record too short");
// This can be an item index or a type index. Choose the appropriate map.
ArrayRef<TypeIndex> TypeOrItemMap = IndexMap.TPIMap;
if (Ref.Kind == TiRefKind::IndexRef && IndexMap.IsTypeServerMap)
TypeOrItemMap = IndexMap.IPIMap;
MutableArrayRef<TypeIndex> TIs(
reinterpret_cast<TypeIndex *>(Contents.data() + Ref.Offset), Ref.Count);
for (TypeIndex &TI : TIs) {
if (!remapTypeIndex(TI, TypeIndexMap)) {
if (!remapTypeIndex(TI, TypeOrItemMap)) {
TI = TypeIndex(SimpleTypeKind::NotTranslated);
log("ignoring symbol record in " + File->getName() +
" with bad type index 0x" + utohexstr(TI.getIndex()));
@ -292,7 +411,7 @@ static void scopeStackClose(SmallVectorImpl<SymbolScope> &Stack,
}
static void mergeSymbolRecords(BumpPtrAllocator &Alloc, ObjectFile *File,
ArrayRef<TypeIndex> TypeIndexMap,
const CVIndexMap &IndexMap,
BinaryStreamRef SymData) {
// FIXME: Improve error recovery by warning and skipping records when
// possible.
@ -315,7 +434,7 @@ static void mergeSymbolRecords(BumpPtrAllocator &Alloc, ObjectFile *File,
// Re-map all the type index references.
MutableArrayRef<uint8_t> Contents =
NewData.drop_front(sizeof(RecordPrefix));
remapTypesInSymbolRecord(File, Contents, TypeIndexMap, TypeRefs);
remapTypesInSymbolRecord(File, Contents, IndexMap, TypeRefs);
// Fill in "Parent" and "End" fields by maintaining a stack of scopes.
CVSymbol NewSym(Sym.kind(), NewData);
@ -358,8 +477,8 @@ void PDBLinker::addObjectFile(ObjectFile *File) {
// type information, file checksums, and the string table. Add type info to
// the PDB first, so that we can get the map from object file type and item
// indices to PDB type and item indices.
SmallVector<TypeIndex, 128> TypeIndexMap;
mergeDebugT(File, TypeIndexMap);
CVIndexMap ObjectIndexMap;
const CVIndexMap &IndexMap = mergeDebugT(File, ObjectIndexMap);
// Now do all live .debug$S sections.
for (SectionChunk *DebugChunk : File->getDebugChunks()) {
@ -391,7 +510,7 @@ void PDBLinker::addObjectFile(ObjectFile *File) {
File->ModuleDBI->addDebugSubsection(SS);
break;
case DebugSubsectionKind::Symbols:
mergeSymbolRecords(Alloc, File, TypeIndexMap, SS.getRecordData());
mergeSymbolRecords(Alloc, File, IndexMap, SS.getRecordData());
break;
default:
// FIXME: Process the rest of the subsections.

View File

@ -0,0 +1,255 @@
--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_AMD64
Characteristics: [ ]
sections:
- Name: .drectve
Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ]
Alignment: 1
SectionData: 2020202F44454641554C544C49423A224C4942434D5422202F44454641554C544C49423A224F4C444E414D45532220
- Name: '.debug$S'
Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ]
Alignment: 1
Subsections:
- !Symbols
Records:
- Kind: S_OBJNAME
ObjNameSym:
Signature: 0
ObjectName: 'C:\src\llvm-project\build\a.obj'
- Kind: S_COMPILE3
Compile3Sym:
Flags: [ SecurityChecks, HotPatch ]
Machine: X64
FrontendMajor: 19
FrontendMinor: 0
FrontendBuild: 24215
FrontendQFE: 1
BackendMajor: 19
BackendMinor: 0
BackendBuild: 24215
BackendQFE: 1
Version: 'Microsoft (R) Optimizing Compiler'
- !Symbols
Records:
- Kind: S_GPROC32_ID
ProcSym:
CodeSize: 27
DbgStart: 4
DbgEnd: 22
FunctionType: 4098
Flags: [ ]
DisplayName: main
- Kind: S_FRAMEPROC
FrameProcSym:
TotalFrameBytes: 56
PaddingFrameBytes: 0
OffsetToPadding: 0
BytesOfCalleeSavedRegisters: 0
OffsetOfExceptionHandler: 0
SectionIdOfExceptionHandler: 0
Flags: [ AsynchronousExceptionHandling, OptimizedForSpeed ]
- Kind: S_REGREL32
RegRelativeSym:
Offset: 32
Type: 4102
Register: RSP
VarName: f
- Kind: S_PROC_ID_END
ScopeEndSym:
- !Lines
CodeSize: 27
Flags: [ ]
RelocOffset: 0
RelocSegment: 0
Blocks:
- FileName: 'c:\src\llvm-project\build\a.c'
Lines:
- Offset: 0
LineStart: 3
IsStatement: true
EndDelta: 0
- Offset: 4
LineStart: 4
IsStatement: true
EndDelta: 0
- Offset: 12
LineStart: 5
IsStatement: true
EndDelta: 0
- Offset: 22
LineStart: 6
IsStatement: true
EndDelta: 0
Columns:
- !Symbols
Records:
- Kind: S_UDT
UDTSym:
Type: 4102
UDTName: Foo
- !FileChecksums
Checksums:
- FileName: 'c:\src\llvm-project\build\a.c'
Kind: MD5
Checksum: BF69E7E933074E1B7ED1FE8FB395965B
- !StringTable
Strings:
- 'c:\src\llvm-project\build\a.c'
- !Symbols
Records:
- Kind: S_BUILDINFO
BuildInfoSym:
BuildId: 4107
Relocations:
- VirtualAddress: 152
SymbolName: main
Type: IMAGE_REL_AMD64_SECREL
- VirtualAddress: 156
SymbolName: main
Type: IMAGE_REL_AMD64_SECTION
- VirtualAddress: 224
SymbolName: main
Type: IMAGE_REL_AMD64_SECREL
- VirtualAddress: 228
SymbolName: main
Type: IMAGE_REL_AMD64_SECTION
- Name: '.debug$T'
Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ]
Alignment: 1
Types:
- Kind: LF_TYPESERVER2
TypeServer2:
Guid: '{41414141-4141-4141-4141-414141414141}'
Age: 1
Name: 'C:\src\llvm-project\build\ts.pdb'
- Name: '.text$mn'
Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
Alignment: 16
SectionData: 4883EC38C74424202A000000488D4C2420E8000000004883C438C3
Relocations:
- VirtualAddress: 18
SymbolName: g
Type: IMAGE_REL_AMD64_REL32
- Name: .xdata
Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
Alignment: 4
SectionData: '0104010004620000'
- Name: .pdata
Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
Alignment: 4
SectionData: 000000001B00000000000000
Relocations:
- VirtualAddress: 0
SymbolName: '$LN3'
Type: IMAGE_REL_AMD64_ADDR32NB
- VirtualAddress: 4
SymbolName: '$LN3'
Type: IMAGE_REL_AMD64_ADDR32NB
- VirtualAddress: 8
SymbolName: '$unwind$main'
Type: IMAGE_REL_AMD64_ADDR32NB
symbols:
- Name: .drectve
Value: 0
SectionNumber: 1
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_STATIC
SectionDefinition:
Length: 47
NumberOfRelocations: 0
NumberOfLinenumbers: 0
CheckSum: 0
Number: 0
- Name: '.debug$S'
Value: 0
SectionNumber: 2
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_STATIC
SectionDefinition:
Length: 388
NumberOfRelocations: 4
NumberOfLinenumbers: 0
CheckSum: 0
Number: 0
- Name: '.debug$T'
Value: 0
SectionNumber: 3
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_STATIC
SectionDefinition:
Length: 64
NumberOfRelocations: 0
NumberOfLinenumbers: 0
CheckSum: 0
Number: 0
- Name: '.text$mn'
Value: 0
SectionNumber: 4
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_STATIC
SectionDefinition:
Length: 27
NumberOfRelocations: 1
NumberOfLinenumbers: 0
CheckSum: 1939996292
Number: 0
- Name: g
Value: 0
SectionNumber: 0
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_FUNCTION
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- Name: main
Value: 0
SectionNumber: 4
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_FUNCTION
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- Name: '$LN3'
Value: 0
SectionNumber: 4
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_LABEL
- Name: .xdata
Value: 0
SectionNumber: 5
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_STATIC
SectionDefinition:
Length: 8
NumberOfRelocations: 0
NumberOfLinenumbers: 0
CheckSum: 931692337
Number: 0
- Name: '$unwind$main'
Value: 0
SectionNumber: 5
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_STATIC
- Name: .pdata
Value: 0
SectionNumber: 6
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_STATIC
SectionDefinition:
Length: 12
NumberOfRelocations: 3
NumberOfLinenumbers: 0
CheckSum: 567356797
Number: 0
- Name: '$pdata$main'
Value: 0
SectionNumber: 6
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_STATIC
...

View File

@ -0,0 +1,173 @@
--- !COFF
header:
Machine: IMAGE_FILE_MACHINE_AMD64
Characteristics: [ ]
sections:
- Name: .drectve
Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ]
Alignment: 1
SectionData: 2020202F44454641554C544C49423A224C4942434D5422202F44454641554C544C49423A224F4C444E414D45532220
- Name: '.debug$S'
Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ]
Alignment: 1
Subsections:
- !Symbols
Records:
- Kind: S_OBJNAME
ObjNameSym:
Signature: 0
ObjectName: 'C:\src\llvm-project\build\b.obj'
- Kind: S_COMPILE3
Compile3Sym:
Flags: [ SecurityChecks, HotPatch ]
Machine: X64
FrontendMajor: 19
FrontendMinor: 0
FrontendBuild: 24215
FrontendQFE: 1
BackendMajor: 19
BackendMinor: 0
BackendBuild: 24215
BackendQFE: 1
Version: 'Microsoft (R) Optimizing Compiler'
- !Symbols
Records:
- Kind: S_GPROC32_ID
ProcSym:
CodeSize: 13
DbgStart: 5
DbgEnd: 12
FunctionType: 4099
Flags: [ ]
DisplayName: g
- Kind: S_FRAMEPROC
FrameProcSym:
TotalFrameBytes: 0
PaddingFrameBytes: 0
OffsetToPadding: 0
BytesOfCalleeSavedRegisters: 0
OffsetOfExceptionHandler: 0
SectionIdOfExceptionHandler: 0
Flags: [ AsynchronousExceptionHandling, OptimizedForSpeed ]
- Kind: S_REGREL32
RegRelativeSym:
Offset: 8
Type: 4097
Register: RSP
VarName: p
- Kind: S_PROC_ID_END
ScopeEndSym:
- !Lines
CodeSize: 13
Flags: [ ]
RelocOffset: 0
RelocSegment: 0
Blocks:
- FileName: 'c:\src\llvm-project\build\b.c'
Lines:
- Offset: 0
LineStart: 2
IsStatement: true
EndDelta: 0
Columns:
- !Symbols
Records:
- Kind: S_UDT
UDTSym:
Type: 4102
UDTName: Foo
- !FileChecksums
Checksums:
- FileName: 'c:\src\llvm-project\build\b.c'
Kind: MD5
Checksum: DDF8FD35CD67990C5D4147516BE10D0C
- !StringTable
Strings:
- 'c:\src\llvm-project\build\b.c'
- !Symbols
Records:
- Kind: S_BUILDINFO
BuildInfoSym:
BuildId: 4111
Relocations:
- VirtualAddress: 152
SymbolName: g
Type: IMAGE_REL_AMD64_SECREL
- VirtualAddress: 156
SymbolName: g
Type: IMAGE_REL_AMD64_SECTION
- VirtualAddress: 220
SymbolName: g
Type: IMAGE_REL_AMD64_SECREL
- VirtualAddress: 224
SymbolName: g
Type: IMAGE_REL_AMD64_SECTION
- Name: '.debug$T'
Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ]
Alignment: 1
Types:
- Kind: LF_TYPESERVER2
TypeServer2:
Guid: '{41414141-4141-4141-4141-414141414141}'
Age: 1
Name: 'C:\src\llvm-project\build\ts.pdb'
- Name: '.text$mn'
Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
Alignment: 16
SectionData: 48894C2408488B4424088B00C3
symbols:
- Name: .drectve
Value: 0
SectionNumber: 1
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_STATIC
SectionDefinition:
Length: 47
NumberOfRelocations: 0
NumberOfLinenumbers: 0
CheckSum: 0
Number: 0
- Name: '.debug$S'
Value: 0
SectionNumber: 2
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_STATIC
SectionDefinition:
Length: 360
NumberOfRelocations: 4
NumberOfLinenumbers: 0
CheckSum: 0
Number: 0
- Name: '.debug$T'
Value: 0
SectionNumber: 3
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_STATIC
SectionDefinition:
Length: 64
NumberOfRelocations: 0
NumberOfLinenumbers: 0
CheckSum: 0
Number: 0
- Name: '.text$mn'
Value: 0
SectionNumber: 4
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_NULL
StorageClass: IMAGE_SYM_CLASS_STATIC
SectionDefinition:
Length: 13
NumberOfRelocations: 0
NumberOfLinenumbers: 0
CheckSum: 3246683207
Number: 0
- Name: g
Value: 0
SectionNumber: 4
SimpleType: IMAGE_SYM_TYPE_NULL
ComplexType: IMAGE_SYM_DTYPE_FUNCTION
StorageClass: IMAGE_SYM_CLASS_EXTERNAL
...

View File

@ -0,0 +1,147 @@
---
MSF:
SuperBlock:
BlockSize: 4096
FreeBlockMap: 1
NumBlocks: 19
NumDirectoryBytes: 64
Unknown1: 0
BlockMapAddr: 17
NumDirectoryBlocks: 1
DirectoryBlocks: [ 16 ]
NumStreams: 0
FileSize: 77824
PdbStream:
Age: 1
Guid: '{41414141-4141-4141-4141-414141414141}'
Signature: 1500053944
Features: [ VC140 ]
Version: VC70
TpiStream:
Version: VC80
Records:
- Kind: LF_STRUCTURE
Class:
MemberCount: 0
Options: [ None, ForwardReference, HasUniqueName ]
FieldList: 0
Name: Foo
UniqueName: '.?AUFoo@@'
DerivationList: 0
VTableShape: 0
Size: 0
- Kind: LF_POINTER
Pointer:
ReferentType: 4096
Attrs: 65548
- Kind: LF_ARGLIST
ArgList:
ArgIndices: [ 4097 ]
- Kind: LF_PROCEDURE
Procedure:
ReturnType: 116
CallConv: NearC
Options: [ None ]
ParameterCount: 1
ArgumentList: 4098
- Kind: LF_POINTER
Pointer:
ReferentType: 4099
Attrs: 65548
- Kind: LF_FIELDLIST
FieldList:
- Kind: LF_MEMBER
DataMember:
Attrs: 3
Type: 116
FieldOffset: 0
Name: x
- Kind: LF_STRUCTURE
Class:
MemberCount: 1
Options: [ None, HasUniqueName ]
FieldList: 4101
Name: Foo
UniqueName: '.?AUFoo@@'
DerivationList: 0
VTableShape: 0
Size: 4
- Kind: LF_ARGLIST
ArgList:
ArgIndices: [ 0 ]
- Kind: LF_PROCEDURE
Procedure:
ReturnType: 116
CallConv: NearC
Options: [ None ]
ParameterCount: 0
ArgumentList: 4103
IpiStream:
Version: VC80
Records:
- Kind: LF_STRING_ID
StringId:
Id: 0
String: 'c:\src\llvm-project\build\a.c'
- Kind: LF_UDT_SRC_LINE
UdtSourceLine:
UDT: 4102
SourceFile: 4096
LineNumber: 1
- Kind: LF_FUNC_ID
FuncId:
ParentScope: 0
FunctionType: 4104
Name: main
- Kind: LF_FUNC_ID
FuncId:
ParentScope: 0
FunctionType: 4099
Name: g
- Kind: LF_STRING_ID
StringId:
Id: 0
String: 'C:\src\llvm-project\build'
- Kind: LF_STRING_ID
StringId:
Id: 0
String: 'C:\PROGRA~2\MICROS~1.0\VC\Bin\amd64\cl.exe'
- Kind: LF_STRING_ID
StringId:
Id: 0
String: '-c -Zi -MT -IC:\PROGRA~2\MICROS~1.0\VC\include -IC:\PROGRA~2\MICROS~1.0\VC\atlmfc\include -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\ucrt -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\shared -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\um'
- Kind: LF_SUBSTR_LIST
StringList:
StringIndices: [ 4102 ]
- Kind: LF_STRING_ID
StringId:
Id: 4103
String: ' -IC:\PROGRA~2\WI3CF2~1\10\include\10.0.14393.0\winrt -TC -X'
- Kind: LF_STRING_ID
StringId:
Id: 0
String: a.c
- Kind: LF_STRING_ID
StringId:
Id: 0
String: 'C:\src\llvm-project\build\ts.pdb'
- Kind: LF_BUILDINFO
BuildInfo:
ArgIndices: [ 4100, 4101, 4105, 4106, 4104 ]
- Kind: LF_STRING_ID
StringId:
Id: 0
String: 'c:\src\llvm-project\build\b.c'
- Kind: LF_UDT_SRC_LINE
UdtSourceLine:
UDT: 4102
SourceFile: 4108
LineNumber: 1
- Kind: LF_STRING_ID
StringId:
Id: 0
String: b.c
- Kind: LF_BUILDINFO
BuildInfo:
ArgIndices: [ 4100, 4101, 4110, 4106, 4104 ]
...

View File

@ -1,16 +1,13 @@
# This is an object compiled with /Zi (see the LF_TYPESERVER2 record) without an
# adjacent type server PDB. Test that LLD fails gracefully on it.
# FIXME: Type server handling was removed from LLVM.
# XFAIL: *
# FIXME: Ideally we'd do what MSVC does, which is to warn and drop all debug
# info in the object with the missing PDB.
# RUN: yaml2obj %s -o %t.obj
# RUN: not lld-link %t.obj -out:%t.exe -debug -pdb:%t.pdb -nodefaultlib -entry:main 2>&1 | FileCheck %s
# CHECK: error: {{.*}} Type server PDB was not found
# CHECK: error: Type server PDB was not found
--- !COFF
header:

View File

@ -0,0 +1,91 @@
Replicate this scenario:
$ cat a.c
struct Foo { int x; };
int g(struct Foo *p);
int main() {
struct Foo f = {42};
return g(&f);
}
$ cat b.c
struct Foo { int x; };
int g(struct Foo *p) { return p->x; }
$ cl -c a.c b.c -Zi -Fdts.pdb
$ lld-link a.obj b.obj -debug -entry:main -nodefaultlib -out:t.exe
RUN: rm -rf %t && mkdir -p %t && cd %t
RUN: yaml2obj %S/Inputs/pdb-type-server-simple-a.yaml -o a.obj
RUN: yaml2obj %S/Inputs/pdb-type-server-simple-b.yaml -o b.obj
RUN: llvm-pdbutil yaml2pdb %S/Inputs/pdb-type-server-simple-ts.yaml -pdb ts.pdb
RUN: lld-link a.obj b.obj -entry:main -debug -out:t.exe -pdb:t.pdb -nodefaultlib
RUN: llvm-pdbutil dump -symbols -types -ids %t/t.pdb | FileCheck %s
CHECK-LABEL: Types (TPI Stream)
CHECK: ============================================================
CHECK: [[FOO_DECL:[^ ]*]] | LF_STRUCTURE [size = 36] `Foo`
CHECK: [[FOO_PTR:[^ ]*]] | LF_POINTER [size = 12]
CHECK-NEXT: referent = [[FOO_DECL]]
CHECK: [[G_ARGS:[^ ]*]] | LF_ARGLIST [size = 12]
CHECK-NEXT: [[FOO_PTR]]: `Foo*`
CHECK: [[G_PROTO:[^ ]*]] | LF_PROCEDURE [size = 16]
CHECK-NEXT: return type = 0x0074 (int), # args = 1, param list = [[G_ARGS]]
CHECK-NEXT: calling conv = cdecl, options = None
CHECK: [[FOO_COMPLETE:[^ ]*]] | LF_STRUCTURE [size = 36] `Foo`
CHECK-NEXT: unique name: `.?AUFoo@@`
CHECK-NEXT: vtable: <no type>, base list: <no type>, field list: 0x{{.*}}
CHECK: options: has unique name
CHECK: [[MAIN_PROTO:[^ ]*]] | LF_PROCEDURE [size = 16]
CHECK: return type = 0x0074 (int), # args = 0, param list = 0x{{.*}}
CHECK: calling conv = cdecl, options = None
CHECK-LABEL: Types (IPI Stream)
CHECK: ============================================================
CHECK: [[MAIN_ID:[^ ]*]] | LF_FUNC_ID [size = 20]
CHECK: name = main, type = [[MAIN_PROTO]], parent scope = <no type>
CHECK: [[G_ID:[^ ]*]] | LF_FUNC_ID [size = 16]
CHECK: name = g, type = [[G_PROTO]], parent scope = <no type>
CHECK: [[A_BUILD:[^ ]*]] | LF_BUILDINFO [size = 28]
CHECK: {{.*}}: `a.c`
CHECK: [[B_BUILD:[^ ]*]] | LF_BUILDINFO [size = 28]
CHECK: {{.*}}: `b.c`
CHECK-LABEL: Symbols
CHECK: ============================================================
CHECK-LABEL: Mod 0000 | `{{.*}}a.obj`:
CHECK: 4 | S_OBJNAME [size = 40] sig=0, `C:\src\llvm-project\build\a.obj`
CHECK: 104 | S_GPROC32_ID [size = 44] `main`
CHECK: parent = 0, end = 196, addr = 0002:0000, code size = 27
CHECK: type = {{.*}}, debug start = 4, debug end = 22, flags = none
CHECK: 200 | S_UDT [size = 12] `Foo`
CHECK: original type = [[FOO_COMPLETE]]
CHECK: 212 | S_BUILDINFO [size = 8] BuildId = `[[A_BUILD]]`
CHECK-LABEL: Mod 0001 | `{{.*}}b.obj`:
CHECK: 4 | S_OBJNAME [size = 40] sig=0, `C:\src\llvm-project\build\b.obj`
CHECK: 44 | S_COMPILE3 [size = 60]
CHECK: machine = intel x86-x64, Ver = Microsoft (R) Optimizing Compiler, language = c
CHECK: frontend = 19.0.24215.1, backend = 19.0.24215.1
CHECK: flags = security checks | hot patchable
CHECK: 104 | S_GPROC32_ID [size = 44] `g`
CHECK: parent = 0, end = 196, addr = 0002:0032, code size = 13
CHECK: type = {{.*}}, debug start = 5, debug end = 12, flags = none
CHECK: 148 | S_FRAMEPROC [size = 32]
CHECK: size = 0, padding size = 0, offset to padding = 0
CHECK: bytes of callee saved registers = 0, exception handler addr = 0000:0000
CHECK: flags = has async eh | opt speed
CHECK: 180 | S_REGREL32 [size = 16] `p`
CHECK: type = [[FOO_PTR]] (Foo*), register = rsp, offset = 8
CHECK: 196 | S_END [size = 4]
CHECK: 200 | S_UDT [size = 12] `Foo`
CHECK: original type = [[FOO_COMPLETE]]
CHECK: 212 | S_BUILDINFO [size = 8] BuildId = `[[B_BUILD]]`
CHECK-LABEL: Mod 0002 | `* Linker *`:

View File

@ -27,6 +27,26 @@ inline bool operator==(const GUID &LHS, const GUID &RHS) {
return 0 == ::memcmp(LHS.Guid, RHS.Guid, sizeof(LHS.Guid));
}
inline bool operator<(const GUID &LHS, const GUID &RHS) {
return ::memcmp(LHS.Guid, RHS.Guid, sizeof(LHS.Guid)) < 0;
}
inline bool operator<=(const GUID &LHS, const GUID &RHS) {
return ::memcmp(LHS.Guid, RHS.Guid, sizeof(LHS.Guid)) <= 0;
}
inline bool operator>(const GUID &LHS, const GUID &RHS) {
return !(LHS <= RHS);
}
inline bool operator>=(const GUID &LHS, const GUID &RHS) {
return !(LHS < RHS);
}
inline bool operator!=(const GUID &LHS, const GUID &RHS) {
return !(LHS == RHS);
}
raw_ostream &operator<<(raw_ostream &OS, const GUID &Guid);
} // namespace codeview