Index: lld/trunk/COFF/PDB.cpp =================================================================== --- lld/trunk/COFF/PDB.cpp +++ lld/trunk/COFF/PDB.cpp @@ -165,7 +165,7 @@ /// List of TypeServer PDBs which cannot be loaded. /// Cached to prevent repeated load attempts. - std::set MissingTypeServerPDBs; + std::map MissingTypeServerPDBs; }; } @@ -326,21 +326,21 @@ // 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::generic_error_code::type_server_not_found, TSPath); + return make_error( + pdb::pdb_error_code::signature_out_of_date); return std::move(NS); } Expected PDBLinker::maybeMergeTypeServerPDB(ObjFile *File, TypeServer2Record &TS) { - const GUID& TSId = TS.getGuid(); + const GUID &TSId = TS.getGuid(); StringRef TSPath = TS.getName(); // First, check if the PDB has previously failed to load. - if (MissingTypeServerPDBs.count(TSId)) - return make_error( - pdb::generic_error_code::type_server_not_found, TSPath); + auto PrevErr = MissingTypeServerPDBs.find(TSId); + if (PrevErr != MissingTypeServerPDBs.end()) + return createFileError(TSPath, std::move(make_error(PrevErr->second, inconvertibleErrorCode()))); // Second, check if we already loaded a PDB with this GUID. Return the type // index mapping if we have it. @@ -355,20 +355,37 @@ // Check for a PDB at: // 1. The given file path // 2. Next to the object file or archive file - auto ExpectedSession = tryToLoadPDB(TSId, TSPath); - 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(TSPath, sys::path::Style::windows)); - ExpectedSession = tryToLoadPDB(TSId, Path); - } + auto ExpectedSession = handleExpected( + tryToLoadPDB(TSId, TSPath), + [&]() { + StringRef LocalPath = + !File->ParentName.empty() ? File->ParentName : File->getName(); + SmallString<128> Path = sys::path::parent_path(LocalPath); + sys::path::append( + Path, sys::path::filename(TSPath, sys::path::Style::windows)); + return tryToLoadPDB(TSId, Path); + }, + [&](std::unique_ptr EC) -> Error { + auto SysErr = EC->convertToErrorCode(); + // Only re-try loading if the previous error was "No such file or + // directory" + if (SysErr.category() == std::generic_category() && + SysErr.value() == ENOENT) + return Error::success(); + return Error(std::move(EC)); + }); + if (auto E = ExpectedSession.takeError()) { TypeServerIndexMappings.erase(TSId); - MissingTypeServerPDBs.emplace(TSId); - return std::move(E); + + // Flatten the error to a string, for later display, if the error occurs + // again on the same PDB. + std::string ErrMsg; + raw_string_ostream S(ErrMsg); + S << E; + auto It = MissingTypeServerPDBs.emplace(TSId, S.str()); + + return createFileError(TSPath, std::move(E)); } pdb::NativeSession *Session = ExpectedSession->get(); @@ -837,8 +854,9 @@ // If the .debug$T sections fail to merge, assume there is no debug info. if (!IndexMapResult) { - warn("Type server PDB for " + Name + " is invalid, ignoring debug info. " + - toString(IndexMapResult.takeError())); + auto FileName = sys::path::filename(Path); + warn("Cannot use debug info for '" + FileName + "'\n" + + " failed to load referenced file " + StringRef(toString(IndexMapResult.takeError())) + "."); return; } @@ -1037,6 +1055,22 @@ } } +static std::string quote(ArrayRef Args) { + std::string ArgStr; + ArgStr.reserve(256); + for (StringRef Arg : Args) { + if (!ArgStr.empty()) + ArgStr.push_back(' '); + bool HasWS = Arg.find(' ') != StringRef::npos; + if (HasWS) + ArgStr.push_back('"'); + ArgStr.append(Arg); + if (HasWS) + ArgStr.push_back('"'); + } + return ArgStr; +} + static void addCommonLinkerModuleSymbols(StringRef Path, pdb::DbiModuleDescriptorBuilder &Mod, BumpPtrAllocator &Allocator) { @@ -1072,7 +1106,8 @@ CS.setLanguage(SourceLanguage::Link); ArrayRef Args = makeArrayRef(Config->Argv).drop_front(); - std::string ArgStr = llvm::join(Args, " "); + // Mimic MSVC which surrounds arguments containing whitespace with quotes. + std::string ArgStr = quote(Args); EBS.Fields.push_back("cwd"); SmallString<64> cwd; sys::fs::current_path(cwd); Index: lld/trunk/Common/ErrorHandler.cpp =================================================================== --- lld/trunk/Common/ErrorHandler.cpp +++ lld/trunk/Common/ErrorHandler.cpp @@ -47,7 +47,7 @@ } void lld::exitLld(int Val) { - // Delete the output buffer so that any tempory file is deleted. + // Delete the output buffer so that any temporary file is deleted. errorHandler().OutputBuffer.reset(); // Dealloc/destroy ManagedStatic variables before calling Index: lld/trunk/test/COFF/Inputs/bad-block-size.pdb =================================================================== --- lld/trunk/test/COFF/Inputs/bad-block-size.pdb +++ lld/trunk/test/COFF/Inputs/bad-block-size.pdb @@ -0,0 +1,2 @@ +Microsoft C/C++ MSF 7.00 +DS \ No newline at end of file Index: lld/trunk/test/COFF/Inputs/pdb-type-server-missing-2.yaml =================================================================== --- lld/trunk/test/COFF/Inputs/pdb-type-server-missing-2.yaml +++ lld/trunk/test/COFF/Inputs/pdb-type-server-missing-2.yaml @@ -0,0 +1,32 @@ +--- !COFF +header: + Machine: IMAGE_FILE_MACHINE_AMD64 + Characteristics: [ ] +sections: + - 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: '{01DF191B-22BF-6B42-96CE-5258B8329FE5}' + Age: 18 + Name: 'C:\src\llvm-project\build\definitely_not_found_for_sure.pdb' + - Name: '.text$mn' + Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] + Alignment: 16 + SectionData: 33C0C3 +symbols: + - Name: '.debug$T' + Value: 0 + SectionNumber: 2 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 564 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 0 + Number: 0 +... Index: lld/trunk/test/COFF/Inputs/pdb-type-server-valid-signature.yaml =================================================================== --- lld/trunk/test/COFF/Inputs/pdb-type-server-valid-signature.yaml +++ lld/trunk/test/COFF/Inputs/pdb-type-server-valid-signature.yaml @@ -0,0 +1,121 @@ +--- !COFF +header: + Machine: IMAGE_FILE_MACHINE_AMD64 + Characteristics: [ ] +sections: + - Name: '.debug$S' + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] + Alignment: 1 + Subsections: + - !Symbols + Records: + - Kind: S_GPROC32_ID + ProcSym: + CodeSize: 3 + DbgStart: 0 + DbgEnd: 2 + FunctionType: 4199 + Flags: [ ] + DisplayName: main + - Kind: S_FRAMEPROC + FrameProcSym: + TotalFrameBytes: 0 + PaddingFrameBytes: 0 + OffsetToPadding: 0 + BytesOfCalleeSavedRegisters: 0 + OffsetOfExceptionHandler: 0 + SectionIdOfExceptionHandler: 0 + Flags: [ AsynchronousExceptionHandling, OptimizedForSpeed ] + - Kind: S_PROC_ID_END + ScopeEndSym: + - !Lines + CodeSize: 3 + Flags: [ ] + RelocOffset: 0 + RelocSegment: 0 + Blocks: + - FileName: 'c:\src\llvm-project\build\t.c' + Lines: + - Offset: 0 + LineStart: 1 + IsStatement: true + EndDelta: 0 + Columns: + - !FileChecksums + Checksums: + - FileName: 'c:\src\llvm-project\build\t.c' + Kind: MD5 + Checksum: 270A878DCC1B845655B162F56C4F5020 + - !StringTable + Strings: + - 'c:\src\llvm-project\build\t.c' + Relocations: + - VirtualAddress: 44 + SymbolName: main + Type: IMAGE_REL_AMD64_SECREL + - VirtualAddress: 48 + SymbolName: main + Type: IMAGE_REL_AMD64_SECTION + - VirtualAddress: 100 + SymbolName: main + Type: IMAGE_REL_AMD64_SECREL + - VirtualAddress: 104 + 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: '{8DABD2A0-28FF-CB43-9BAF-175B77B76414}' + Age: 18 + Name: 'pdb-diff-cl.pdb' + - Name: '.text$mn' + Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] + Alignment: 16 + SectionData: 33C0C3 +symbols: + - Name: '.debug$S' + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 328 + NumberOfRelocations: 4 + NumberOfLinenumbers: 0 + CheckSum: 0 + Number: 0 + - Name: '.debug$T' + Value: 0 + SectionNumber: 2 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 564 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 0 + Number: 0 + - Name: '.text$mn' + Value: 0 + SectionNumber: 3 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 3 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 4021952397 + Number: 0 + - Name: main + Value: 0 + SectionNumber: 3 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_FUNCTION + StorageClass: IMAGE_SYM_CLASS_EXTERNAL +... Index: lld/trunk/test/COFF/pdb-linker-module.test =================================================================== --- lld/trunk/test/COFF/pdb-linker-module.test +++ lld/trunk/test/COFF/pdb-linker-module.test @@ -1,5 +1,5 @@ RUN: echo "/nodefaultlib" > %t.rsp -RUN: lld-link /debug /pdb:%t.pdb @%t.rsp /entry:main %S/Inputs/pdb-diff.obj +RUN: lld-link /debug /pdb:%t.pdb /nodefaultlib /entry:main /manifestuac:"level='asInvoker' uiAccess='false'" %S/Inputs/pdb-diff.obj RUN: llvm-pdbutil dump -modules %t.pdb | FileCheck --check-prefix=MODS %s RUN: llvm-pdbutil dump -symbols %t.pdb | FileCheck --check-prefix=SYMS %s @@ -22,4 +22,4 @@ SYMS-NEXT: - pdb SYMS-NEXT: - {{.*}}pdb-linker-module{{.*}}pdb SYMS-NEXT: - cmd -SYMS-NEXT: - /debug /pdb:{{.*}}pdb-linker-module{{.*}}pdb /nodefaultlib /entry:main {{.*}}pdb-diff.obj +SYMS-NEXT: - /debug /pdb:{{.*}}pdb-linker-module{{.*}}pdb /nodefaultlib /entry:main "/manifestuac:level='asInvoker' uiAccess='false'" {{.*}}pdb-diff.obj Index: lld/trunk/test/COFF/pdb-type-server-invalid-signature.yaml =================================================================== --- lld/trunk/test/COFF/pdb-type-server-invalid-signature.yaml +++ lld/trunk/test/COFF/pdb-type-server-invalid-signature.yaml @@ -0,0 +1,140 @@ + +# RUN: cd %S/Inputs +# RUN: yaml2obj %s -o %t.obj +# RUN: lld-link %t.obj -out:%t.exe -debug -pdb:%t.pdb -nodefaultlib -entry:main 2>&1 | FileCheck %s +# RUN: cd %S + +# CHECK: warning: Cannot use debug info for {{.*}}.obj +# CHECK-NEXT: The signature does not match; the file(s) might be out of date + +# Also test a valid match + +# RUN: cd %S/Inputs +# RUN: yaml2obj %S/Inputs/pdb-type-server-valid-signature.yaml -o %t2.obj +# RUN: lld-link %t2.obj -out:%t2.exe -debug -pdb:%t2.pdb -nodefaultlib -entry:main 2>&1 | FileCheck %s -check-prefix=VALID-SIGNATURE -allow-empty +# RUN: cd %S + +# VALID-SIGNATURE-NOT: warning: Cannot use debug info for {{.*}}.obj +# VALID-SIGNATURE-NOT: The signature does not match; the file(s) might be out of date + +--- !COFF +header: + Machine: IMAGE_FILE_MACHINE_AMD64 + Characteristics: [ ] +sections: + - Name: '.debug$S' + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] + Alignment: 1 + Subsections: + - !Symbols + Records: + - Kind: S_GPROC32_ID + ProcSym: + CodeSize: 3 + DbgStart: 0 + DbgEnd: 2 + FunctionType: 4199 + Flags: [ ] + DisplayName: main + - Kind: S_FRAMEPROC + FrameProcSym: + TotalFrameBytes: 0 + PaddingFrameBytes: 0 + OffsetToPadding: 0 + BytesOfCalleeSavedRegisters: 0 + OffsetOfExceptionHandler: 0 + SectionIdOfExceptionHandler: 0 + Flags: [ AsynchronousExceptionHandling, OptimizedForSpeed ] + - Kind: S_PROC_ID_END + ScopeEndSym: + - !Lines + CodeSize: 3 + Flags: [ ] + RelocOffset: 0 + RelocSegment: 0 + Blocks: + - FileName: 'c:\src\llvm-project\build\t.c' + Lines: + - Offset: 0 + LineStart: 1 + IsStatement: true + EndDelta: 0 + Columns: + - !FileChecksums + Checksums: + - FileName: 'c:\src\llvm-project\build\t.c' + Kind: MD5 + Checksum: 270A878DCC1B845655B162F56C4F5020 + - !StringTable + Strings: + - 'c:\src\llvm-project\build\t.c' + Relocations: + - VirtualAddress: 44 + SymbolName: main + Type: IMAGE_REL_AMD64_SECREL + - VirtualAddress: 48 + SymbolName: main + Type: IMAGE_REL_AMD64_SECTION + - VirtualAddress: 100 + SymbolName: main + Type: IMAGE_REL_AMD64_SECREL + - VirtualAddress: 104 + 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: '{01DF191B-22BF-6B42-96CE-5258B8329FE5}' + Age: 18 + Name: 'pdb-diff-cl.pdb' + - Name: '.text$mn' + Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] + Alignment: 16 + SectionData: 33C0C3 +symbols: + - Name: '.debug$S' + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 328 + NumberOfRelocations: 4 + NumberOfLinenumbers: 0 + CheckSum: 0 + Number: 0 + - Name: '.debug$T' + Value: 0 + SectionNumber: 2 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 564 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 0 + Number: 0 + - Name: '.text$mn' + Value: 0 + SectionNumber: 3 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 3 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 4021952397 + Number: 0 + - Name: main + Value: 0 + SectionNumber: 3 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_FUNCTION + StorageClass: IMAGE_SYM_CLASS_EXTERNAL +... Index: lld/trunk/test/COFF/pdb-type-server-missing.yaml =================================================================== --- lld/trunk/test/COFF/pdb-type-server-missing.yaml +++ lld/trunk/test/COFF/pdb-type-server-missing.yaml @@ -1,10 +1,15 @@ # 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. -# RUN: yaml2obj %s -o %t.obj -# RUN: lld-link %t.obj -out:%t.exe -debug -pdb:%t.pdb -nodefaultlib -entry:main 2>&1 | FileCheck %s +# RUN: yaml2obj %s -o %t1.obj +# RUN: yaml2obj %p/Inputs/pdb-type-server-missing-2.yaml -o %t2.obj +# RUN: lld-link %t1.obj %t2.obj -out:%t.exe -debug -pdb:%t.pdb -nodefaultlib -entry:main 2>&1 | FileCheck %s -# CHECK: warning: Type server PDB for {{.*}}.obj is invalid, ignoring debug info. +# CHECK: warning: Cannot use debug info for {{.*}}.obj +# CHECK-NEXT: {{N|n}}o such file or directory + +# CHECK: warning: Cannot use debug info for {{.*}}.obj +# CHECK-NEXT: {{N|n}}o such file or directory --- !COFF header: Index: lld/trunk/test/COFF/pdb-type-server-native-errors.yaml =================================================================== --- lld/trunk/test/COFF/pdb-type-server-native-errors.yaml +++ lld/trunk/test/COFF/pdb-type-server-native-errors.yaml @@ -0,0 +1,130 @@ + +# RUN: cd %S/Inputs +# RUN: yaml2obj %s -o %t.obj +# RUN: lld-link %t.obj -out:%t.exe -debug -pdb:%t.pdb -nodefaultlib -entry:main 2>&1 | FileCheck %s +# RUN: cd %S + +# CHECK: warning: Cannot use debug info for {{.*}}.obj +# CHECK-NEXT: The PDB file is corrupt. MSF superblock is missing + +--- !COFF +header: + Machine: IMAGE_FILE_MACHINE_AMD64 + Characteristics: [ ] +sections: + - Name: '.debug$S' + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] + Alignment: 1 + Subsections: + - !Symbols + Records: + - Kind: S_GPROC32_ID + ProcSym: + CodeSize: 3 + DbgStart: 0 + DbgEnd: 2 + FunctionType: 4199 + Flags: [ ] + DisplayName: main + - Kind: S_FRAMEPROC + FrameProcSym: + TotalFrameBytes: 0 + PaddingFrameBytes: 0 + OffsetToPadding: 0 + BytesOfCalleeSavedRegisters: 0 + OffsetOfExceptionHandler: 0 + SectionIdOfExceptionHandler: 0 + Flags: [ AsynchronousExceptionHandling, OptimizedForSpeed ] + - Kind: S_PROC_ID_END + ScopeEndSym: + - !Lines + CodeSize: 3 + Flags: [ ] + RelocOffset: 0 + RelocSegment: 0 + Blocks: + - FileName: 'c:\src\llvm-project\build\t.c' + Lines: + - Offset: 0 + LineStart: 1 + IsStatement: true + EndDelta: 0 + Columns: + - !FileChecksums + Checksums: + - FileName: 'c:\src\llvm-project\build\t.c' + Kind: MD5 + Checksum: 270A878DCC1B845655B162F56C4F5020 + - !StringTable + Strings: + - 'c:\src\llvm-project\build\t.c' + Relocations: + - VirtualAddress: 44 + SymbolName: main + Type: IMAGE_REL_AMD64_SECREL + - VirtualAddress: 48 + SymbolName: main + Type: IMAGE_REL_AMD64_SECTION + - VirtualAddress: 100 + SymbolName: main + Type: IMAGE_REL_AMD64_SECREL + - VirtualAddress: 104 + 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: '{01DF191B-22BF-6B42-96CE-5258B8329FE5}' + Age: 18 + Name: 'bad-block-size.pdb' + - Name: '.text$mn' + Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] + Alignment: 16 + SectionData: 33C0C3 +symbols: + - Name: '.debug$S' + Value: 0 + SectionNumber: 1 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 328 + NumberOfRelocations: 4 + NumberOfLinenumbers: 0 + CheckSum: 0 + Number: 0 + - Name: '.debug$T' + Value: 0 + SectionNumber: 2 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 564 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 0 + Number: 0 + - Name: '.text$mn' + Value: 0 + SectionNumber: 3 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_NULL + StorageClass: IMAGE_SYM_CLASS_STATIC + SectionDefinition: + Length: 3 + NumberOfRelocations: 0 + NumberOfLinenumbers: 0 + CheckSum: 4021952397 + Number: 0 + - Name: main + Value: 0 + SectionNumber: 3 + SimpleType: IMAGE_SYM_TYPE_NULL + ComplexType: IMAGE_SYM_DTYPE_FUNCTION + StorageClass: IMAGE_SYM_CLASS_EXTERNAL +... Index: llvm/trunk/include/llvm/DebugInfo/CodeView/CodeViewError.h =================================================================== --- llvm/trunk/include/llvm/DebugInfo/CodeView/CodeViewError.h +++ llvm/trunk/include/llvm/DebugInfo/CodeView/CodeViewError.h @@ -25,22 +25,18 @@ unknown_member_record, }; +class CodeViewErrorCategory : public std::error_category { +public: + const char *name() const noexcept override; + std::string message(int Condition) const override; +}; + /// Base class for errors originating when parsing raw PDB files -class CodeViewError : public ErrorInfo { +class CodeViewError : public DebugErrorInfo { public: - static char ID; - CodeViewError(cv_error_code C); - CodeViewError(const std::string &Context); - CodeViewError(cv_error_code C, const std::string &Context); - - void log(raw_ostream &OS) const override; - const std::string &getErrorMessage() const; - std::error_code convertToErrorCode() const override; - -private: - std::string ErrMsg; - cv_error_code Code; + using DebugErrorInfo::DebugErrorInfo; }; -} -} + +} // namespace codeview +} // namespace llvm #endif Index: llvm/trunk/include/llvm/DebugInfo/MSF/MSFError.h =================================================================== --- llvm/trunk/include/llvm/DebugInfo/MSF/MSFError.h +++ llvm/trunk/include/llvm/DebugInfo/MSF/MSFError.h @@ -25,21 +25,16 @@ block_in_use }; +class MSFErrorCategory : public std::error_category { +public: + const char *name() const noexcept override; + std::string message(int Condition) const override; +}; + /// Base class for errors originating when parsing raw PDB files -class MSFError : public ErrorInfo { +class MSFError : public DebugErrorInfo { public: - static char ID; - MSFError(msf_error_code C); - MSFError(const std::string &Context); - MSFError(msf_error_code C, const std::string &Context); - - void log(raw_ostream &OS) const override; - const std::string &getErrorMessage() const; - std::error_code convertToErrorCode() const override; - -private: - std::string ErrMsg; - msf_error_code Code; + using DebugErrorInfo::DebugErrorInfo; }; } // namespace msf } // namespace llvm Index: llvm/trunk/include/llvm/DebugInfo/PDB/DIA/DIAError.h =================================================================== --- llvm/trunk/include/llvm/DebugInfo/PDB/DIA/DIAError.h +++ llvm/trunk/include/llvm/DebugInfo/PDB/DIA/DIAError.h @@ -24,22 +24,17 @@ debug_info_mismatch, }; -/// Base class for errors originating in DIA SDK, e.g. COM calls -class DIAError : public ErrorInfo { +class DIAErrorCategory : public std::error_category { public: - static char ID; - DIAError(dia_error_code C); - DIAError(StringRef Context); - DIAError(dia_error_code C, StringRef Context); - - void log(raw_ostream &OS) const override; - StringRef getErrorMessage() const; - std::error_code convertToErrorCode() const override; + const char *name() const noexcept override; + std::string message(int Condition) const override; +}; -private: - std::string ErrMsg; - dia_error_code Code; +/// Base class for errors originating in DIA SDK, e.g. COM calls +class DIAError : public DebugErrorInfo { +public: + using DebugErrorInfo::DebugErrorInfo; }; -} -} +} // namespace pdb +} // namespace llvm #endif Index: llvm/trunk/include/llvm/DebugInfo/PDB/GenericError.h =================================================================== --- llvm/trunk/include/llvm/DebugInfo/PDB/GenericError.h +++ llvm/trunk/include/llvm/DebugInfo/PDB/GenericError.h @@ -16,29 +16,25 @@ namespace llvm { namespace pdb { -enum class generic_error_code { - invalid_path = 1, +enum class pdb_error_code { + invalid_utf8_path = 1, dia_sdk_not_present, - type_server_not_found, + dia_failed_loading, + signature_out_of_date, unspecified, }; +class PDBErrorCategory : public std::error_category { +public: + const char *name() const noexcept override; + std::string message(int Condition) const override; +}; + /// Base class for errors originating when parsing raw PDB files -class GenericError : public ErrorInfo { +class PDBError : public DebugErrorInfo { public: - static char ID; - GenericError(generic_error_code C); - GenericError(StringRef Context); - GenericError(generic_error_code C, StringRef Context); - - void log(raw_ostream &OS) const override; - StringRef getErrorMessage() const; - std::error_code convertToErrorCode() const override; - -private: - std::string ErrMsg; - generic_error_code Code; + using DebugErrorInfo::DebugErrorInfo; }; -} -} +} // namespace pdb +} // namespace llvm #endif Index: llvm/trunk/include/llvm/DebugInfo/PDB/Native/RawError.h =================================================================== --- llvm/trunk/include/llvm/DebugInfo/PDB/Native/RawError.h +++ llvm/trunk/include/llvm/DebugInfo/PDB/Native/RawError.h @@ -32,22 +32,17 @@ invalid_tpi_hash, }; +class RawErrorCategory : public std::error_category { +public: + const char *name() const noexcept override; + std::string message(int Condition) const override; +}; + /// Base class for errors originating when parsing raw PDB files -class RawError : public ErrorInfo { +class RawError : public DebugErrorInfo { public: - static char ID; - RawError(raw_error_code C); - RawError(const std::string &Context); - RawError(raw_error_code C, const std::string &Context); - - void log(raw_ostream &OS) const override; - const std::string &getErrorMessage() const; - std::error_code convertToErrorCode() const override; - -private: - std::string ErrMsg; - raw_error_code Code; + using DebugErrorInfo::DebugErrorInfo; }; -} -} +} // namespace pdb +} // namespace llvm #endif Index: llvm/trunk/include/llvm/Support/Error.h =================================================================== --- llvm/trunk/include/llvm/Support/Error.h +++ llvm/trunk/include/llvm/Support/Error.h @@ -26,6 +26,7 @@ #include "llvm/Support/ErrorOr.h" #include "llvm/Support/Format.h" #include "llvm/Support/raw_ostream.h" +#include "llvm/Support/ManagedStatic.h" #include #include #include @@ -155,9 +156,10 @@ /// they're moved-assigned or constructed from Success values that have already /// been checked. This enforces checking through all levels of the call stack. class LLVM_NODISCARD Error { - // ErrorList needs to be able to yank ErrorInfoBase pointers out of this - // class to add to the error list. + // Both ErrorList and FileError needs to be able to yank ErrorInfoBase + // pointers out of this class to add to the error list. friend class ErrorList; + friend class FileError; // handleErrors needs to be able to set the Checked flag. template @@ -924,7 +926,7 @@ /// foo(Aggressive), /// []() { return foo(Conservative); }, /// [](AggressiveStrategyError&) { -/// // Implicitly conusme this - we'll recover by using a conservative +/// // Implicitly consume this - we'll recover by using a conservative /// // strategy. /// }); /// @@ -1134,6 +1136,103 @@ Error createStringError(std::error_code EC, char const *Msg); +/// This class wraps a filename and another Error. +/// +/// In some cases, an error needs to live along a 'source' name, in order to +/// show more detailed information to the user. +class FileError final : public ErrorInfo { + + friend Error createFileError(std::string, Error); + +public: + void log(raw_ostream &OS) const override { + OS << "'" << FileName << "': "; + Err->log(OS); + } + + std::error_code convertToErrorCode() const override; + + // Used by ErrorInfo::classID. + static char ID; + +private: + FileError(std::string F, std::unique_ptr Payload) { + FileName = F; + Err = std::move(Payload); + } + + static Error build(std::string F, Error E) { + return Error(std::unique_ptr( + new FileError(F, E.takePayload()))); + } + + std::string FileName; + std::unique_ptr Err; +}; + +/// Concatenate a source file path and/or name with an Error. The resulting +/// Error is unchecked. +inline Error createFileError(std::string F, Error E) { + return FileError::build(F, std::move(E)); +} + +/// This class provides the combined features of ECError and StringError, while +/// allowing for sub typing. +/// +/// DebugErrorInfo<> is useful when an Error sub type is required, for later +/// inspection, along with an std::error_code and an optional String, such as: +/// +/// @code{.cpp} +/// Expected foo() { +/// return llvm::make_error(pdb_error_code::dia_failed_loading, +/// "Additional information"); +/// } +/// @endcode +/// +/// When implementing the class, the following shall be provided: +/// - a custom enumeration, starting at 1, where a 'unspecified' +/// element should be present +/// - a custom std::error_category with a fully defined singleton object. +/// - an Error subtype of DebugErrorInfo<> +/// +template +class DebugErrorInfo : public ErrorInfo { +public: + DebugErrorInfo(EC C) : DebugErrorInfo(C, "") {} + DebugErrorInfo(Twine Context) + : DebugErrorInfo(EC::unspecified, Context.str()) {} + DebugErrorInfo(EC C, StringRef Context) : Code(C) { + if (Code == EC::unspecified) + ErrMsg += Context; + else { + ErrMsg += convertToErrorCode().message(); + if (!Context.empty()) + ErrMsg += (" " + Context).str(); + } + } + + void log(raw_ostream &OS) const override { OS << ErrMsg; } + StringRef getErrorMessage() const { return ErrMsg; } + EC getError() const { return Code; } + + static ManagedStatic Category; + + std::error_code convertToErrorCode() const override { + return std::error_code(static_cast(Code), *Category); + } + + // Used by ErrorInfo::classID. + static char ID; + +protected: + std::string ErrMsg; + EC Code; +}; + +#define DEFINE_DEBUGERRORINFO(C, EC, Cat) \ + template <> char DebugErrorInfo::ID; \ + template <> ManagedStatic DebugErrorInfo::Category; + /// Helper for check-and-exit error handling. /// /// For tool use only. NOT FOR USE IN LIBRARY CODE. Index: llvm/trunk/lib/DebugInfo/CodeView/CodeViewError.cpp =================================================================== --- llvm/trunk/lib/DebugInfo/CodeView/CodeViewError.cpp +++ llvm/trunk/lib/DebugInfo/CodeView/CodeViewError.cpp @@ -14,58 +14,30 @@ using namespace llvm; using namespace llvm::codeview; -namespace { // FIXME: This class is only here to support the transition to llvm::Error. It // will be removed once this transition is complete. Clients should prefer to // deal with the Error value directly, rather than converting to error_code. -class CodeViewErrorCategory : public std::error_category { -public: - const char *name() const noexcept override { return "llvm.codeview"; } +const char *llvm::codeview::CodeViewErrorCategory::name() const noexcept { + return "llvm.codeview"; +} - std::string message(int Condition) const override { - switch (static_cast(Condition)) { - case cv_error_code::unspecified: - return "An unknown error has occurred."; - case cv_error_code::insufficient_buffer: - return "The buffer is not large enough to read the requested number of " - "bytes."; - case cv_error_code::corrupt_record: - return "The CodeView record is corrupted."; - case cv_error_code::no_records: - return "There are no records"; - case cv_error_code::operation_unsupported: - return "The requested operation is not supported."; - case cv_error_code::unknown_member_record: - return "The member record is of an unknown type."; - } - llvm_unreachable("Unrecognized cv_error_code"); +std::string llvm::codeview::CodeViewErrorCategory::message(int Condition) const { + switch (static_cast(Condition)) { + case cv_error_code::unspecified: + return "An unknown error has occurred."; + case cv_error_code::insufficient_buffer: + return "The buffer is not large enough to read the requested number of " + "bytes."; + case cv_error_code::corrupt_record: + return "The CodeView record is corrupted."; + case cv_error_code::no_records: + return "There are no records."; + case cv_error_code::operation_unsupported: + return "The requested operation is not supported."; + case cv_error_code::unknown_member_record: + return "The member record is of an unknown type."; } -}; -} // end anonymous namespace - -static ManagedStatic Category; - -char CodeViewError::ID = 0; - -CodeViewError::CodeViewError(cv_error_code C) : CodeViewError(C, "") {} - -CodeViewError::CodeViewError(const std::string &Context) - : CodeViewError(cv_error_code::unspecified, Context) {} - -CodeViewError::CodeViewError(cv_error_code C, const std::string &Context) - : Code(C) { - ErrMsg = "CodeView Error: "; - std::error_code EC = convertToErrorCode(); - if (Code != cv_error_code::unspecified) - ErrMsg += EC.message() + " "; - if (!Context.empty()) - ErrMsg += Context; + llvm_unreachable("Unrecognized cv_error_code"); } -void CodeViewError::log(raw_ostream &OS) const { OS << ErrMsg << "\n"; } - -const std::string &CodeViewError::getErrorMessage() const { return ErrMsg; } - -std::error_code CodeViewError::convertToErrorCode() const { - return std::error_code(static_cast(Code), *Category); -} +DEFINE_DEBUGERRORINFO(CodeViewError, cv_error_code, CodeViewErrorCategory) Index: llvm/trunk/lib/DebugInfo/CodeView/TypeStreamMerger.cpp =================================================================== --- llvm/trunk/lib/DebugInfo/CodeView/TypeStreamMerger.cpp +++ llvm/trunk/lib/DebugInfo/CodeView/TypeStreamMerger.cpp @@ -326,7 +326,7 @@ "second pass found more bad indices"); if (!LastError && NumBadIndices == BadIndicesRemaining) { return llvm::make_error( - cv_error_code::corrupt_record, "input type graph contains cycles"); + cv_error_code::corrupt_record, "Input type graph contains cycles"); } } Index: llvm/trunk/lib/DebugInfo/MSF/MSFError.cpp =================================================================== --- llvm/trunk/lib/DebugInfo/MSF/MSFError.cpp +++ llvm/trunk/lib/DebugInfo/MSF/MSFError.cpp @@ -14,57 +14,30 @@ using namespace llvm; using namespace llvm::msf; -namespace { // FIXME: This class is only here to support the transition to llvm::Error. It // will be removed once this transition is complete. Clients should prefer to // deal with the Error value directly, rather than converting to error_code. -class MSFErrorCategory : public std::error_category { -public: - const char *name() const noexcept override { return "llvm.msf"; } +const char *llvm::msf::MSFErrorCategory::name() const noexcept { + return "llvm.msf"; +} - std::string message(int Condition) const override { - switch (static_cast(Condition)) { - case msf_error_code::unspecified: - return "An unknown error has occurred."; - case msf_error_code::insufficient_buffer: - return "The buffer is not large enough to read the requested number of " - "bytes."; - case msf_error_code::not_writable: - return "The specified stream is not writable."; - case msf_error_code::no_stream: - return "The specified stream does not exist."; - case msf_error_code::invalid_format: - return "The data is in an unexpected format."; - case msf_error_code::block_in_use: - return "The block is already in use."; - } - llvm_unreachable("Unrecognized msf_error_code"); +std::string llvm::msf::MSFErrorCategory::message(int Condition) const { + switch (static_cast(Condition)) { + case msf_error_code::unspecified: + return "An unknown error has occurred."; + case msf_error_code::insufficient_buffer: + return "The buffer is not large enough to read the requested number of " + "bytes."; + case msf_error_code::not_writable: + return "The specified stream is not writable."; + case msf_error_code::no_stream: + return "The specified stream does not exist."; + case msf_error_code::invalid_format: + return "The data is in an unexpected format."; + case msf_error_code::block_in_use: + return "The block is already in use."; } -}; -} // end anonymous namespace - -static ManagedStatic Category; - -char MSFError::ID = 0; - -MSFError::MSFError(msf_error_code C) : MSFError(C, "") {} - -MSFError::MSFError(const std::string &Context) - : MSFError(msf_error_code::unspecified, Context) {} - -MSFError::MSFError(msf_error_code C, const std::string &Context) : Code(C) { - ErrMsg = "MSF Error: "; - std::error_code EC = convertToErrorCode(); - if (Code != msf_error_code::unspecified) - ErrMsg += EC.message() + " "; - if (!Context.empty()) - ErrMsg += Context; + llvm_unreachable("Unrecognized msf_error_code"); } -void MSFError::log(raw_ostream &OS) const { OS << ErrMsg << "\n"; } - -const std::string &MSFError::getErrorMessage() const { return ErrMsg; } - -std::error_code MSFError::convertToErrorCode() const { - return std::error_code(static_cast(Code), *Category); -} +DEFINE_DEBUGERRORINFO(MSFError, msf_error_code, MSFErrorCategory) Index: llvm/trunk/lib/DebugInfo/PDB/DIA/DIAError.cpp =================================================================== --- llvm/trunk/lib/DebugInfo/PDB/DIA/DIAError.cpp +++ llvm/trunk/lib/DebugInfo/PDB/DIA/DIAError.cpp @@ -8,51 +8,27 @@ // FIXME: This class is only here to support the transition to llvm::Error. It // will be removed once this transition is complete. Clients should prefer to // deal with the Error value directly, rather than converting to error_code. -class DIAErrorCategory : public std::error_category { -public: - const char *name() const noexcept override { return "llvm.pdb.dia"; } +const char *llvm::pdb::DIAErrorCategory::name() const noexcept { + return "llvm.pdb.dia"; +} - std::string message(int Condition) const override { - switch (static_cast(Condition)) { - case dia_error_code::could_not_create_impl: - return "Failed to connect to DIA at runtime. Verify that Visual Studio " - "is properly installed, or that msdiaXX.dll is in your PATH."; - case dia_error_code::invalid_file_format: - return "Unable to load PDB. The file has an unrecognized format."; - case dia_error_code::invalid_parameter: - return "The parameter is incorrect."; - case dia_error_code::already_loaded: - return "Unable to load the PDB or EXE, because it is already loaded."; - case dia_error_code::debug_info_mismatch: - return "The PDB file and the EXE file do not match."; - case dia_error_code::unspecified: - return "An unknown error has occurred."; - } - llvm_unreachable("Unrecognized DIAErrorCode"); +std::string llvm::pdb::DIAErrorCategory::message(int Condition) const { + switch (static_cast(Condition)) { + case dia_error_code::could_not_create_impl: + return "Failed to connect to DIA at runtime. Verify that Visual Studio " + "is properly installed, or that msdiaXX.dll is in your PATH."; + case dia_error_code::invalid_file_format: + return "Unable to load PDB. The file has an unrecognized format."; + case dia_error_code::invalid_parameter: + return "The parameter is incorrect."; + case dia_error_code::already_loaded: + return "Unable to load the PDB or EXE, because it is already loaded."; + case dia_error_code::debug_info_mismatch: + return "The PDB file and the EXE file do not match."; + case dia_error_code::unspecified: + return "An unknown error has occurred."; } -}; - -static ManagedStatic Category; - -char DIAError::ID = 0; - -DIAError::DIAError(dia_error_code C) : DIAError(C, "") {} - -DIAError::DIAError(StringRef Context) - : DIAError(dia_error_code::unspecified, Context) {} - -DIAError::DIAError(dia_error_code C, StringRef Context) : Code(C) { - ErrMsg = "DIA Error: "; - std::error_code EC = convertToErrorCode(); - ErrMsg += EC.message() + " "; - if (!Context.empty()) - ErrMsg += Context; + llvm_unreachable("Unrecognized DIAErrorCode"); } -void DIAError::log(raw_ostream &OS) const { OS << ErrMsg << "\n"; } - -StringRef DIAError::getErrorMessage() const { return ErrMsg; } - -std::error_code DIAError::convertToErrorCode() const { - return std::error_code(static_cast(Code), *Category); -} +DEFINE_DEBUGERRORINFO(DIAError, dia_error_code, DIAErrorCategory) Index: llvm/trunk/lib/DebugInfo/PDB/DIA/DIASession.cpp =================================================================== --- llvm/trunk/lib/DebugInfo/PDB/DIA/DIASession.cpp +++ llvm/trunk/lib/DebugInfo/PDB/DIA/DIASession.cpp @@ -42,7 +42,7 @@ switch (Result) { case E_PDB_NOT_FOUND: - return make_error(generic_error_code::invalid_path, Context); + return errorCodeToError(std::error_code(ENOENT, std::generic_category())); case E_PDB_FORMAT: return make_error(dia_error_code::invalid_file_format, Context); case E_INVALIDARG: @@ -71,8 +71,7 @@ // If the CoCreateInstance call above failed, msdia*.dll is not registered. // Try loading the DLL corresponding to the #included DIA SDK. #if !defined(_MSC_VER) - return llvm::make_error( - "DIA is only supported when using MSVC."); + return llvm::make_error(pdb_error_code::dia_failed_loading); #else const wchar_t *msdia_dll = nullptr; #if _MSC_VER >= 1900 && _MSC_VER < 2000 @@ -104,7 +103,7 @@ llvm::SmallVector Path16; if (!llvm::convertUTF8ToUTF16String(Path, Path16)) - return make_error(generic_error_code::invalid_path); + return make_error(pdb_error_code::invalid_utf8_path, Path); const wchar_t *Path16Str = reinterpret_cast(Path16.data()); HRESULT HR; @@ -130,7 +129,7 @@ llvm::SmallVector Path16; if (!llvm::convertUTF8ToUTF16String(Path, Path16)) - return make_error(generic_error_code::invalid_path, Path); + return make_error(pdb_error_code::invalid_utf8_path, Path); const wchar_t *Path16Str = reinterpret_cast(Path16.data()); HRESULT HR; Index: llvm/trunk/lib/DebugInfo/PDB/GenericError.cpp =================================================================== --- llvm/trunk/lib/DebugInfo/PDB/GenericError.cpp +++ llvm/trunk/lib/DebugInfo/PDB/GenericError.cpp @@ -14,55 +14,29 @@ using namespace llvm; using namespace llvm::pdb; -namespace { // FIXME: This class is only here to support the transition to llvm::Error. It // will be removed once this transition is complete. Clients should prefer to // deal with the Error value directly, rather than converting to error_code. -class GenericErrorCategory : public std::error_category { -public: - const char *name() const noexcept override { return "llvm.pdb"; } +const char *llvm::pdb::PDBErrorCategory::name() const noexcept { + return "llvm.pdb"; +} - std::string message(int Condition) const override { - switch (static_cast(Condition)) { - case generic_error_code::unspecified: - return "An unknown error has occurred."; - case generic_error_code::type_server_not_found: - return "Type server PDB was not found."; - case generic_error_code::dia_sdk_not_present: - return "LLVM was not compiled with support for DIA. This usually means " - "that you are not using MSVC, or your Visual Studio " - "installation " - "is corrupt."; - case generic_error_code::invalid_path: - return "Unable to load PDB. Make sure the file exists and is readable."; - } - llvm_unreachable("Unrecognized generic_error_code"); +std::string llvm::pdb::PDBErrorCategory::message(int Condition) const { + switch (static_cast(Condition)) { + case pdb_error_code::unspecified: + return "An unknown error has occurred."; + case pdb_error_code::dia_sdk_not_present: + return "LLVM was not compiled with support for DIA. This usually means " + "that you are not using MSVC, or your Visual Studio " + "installation is corrupt."; + case pdb_error_code::dia_failed_loading: + return "DIA is only supported when using MSVC."; + case pdb_error_code::invalid_utf8_path: + return "The PDB file path is an invalid UTF8 sequence."; + case pdb_error_code::signature_out_of_date: + return "The signature does not match; the file(s) might be out of date"; } -}; -} // end anonymous namespace - -static ManagedStatic Category; - -char GenericError::ID = 0; - -GenericError::GenericError(generic_error_code C) : GenericError(C, "") {} - -GenericError::GenericError(StringRef Context) - : GenericError(generic_error_code::unspecified, Context) {} - -GenericError::GenericError(generic_error_code C, StringRef Context) : Code(C) { - ErrMsg = "PDB Error: "; - std::error_code EC = convertToErrorCode(); - if (Code != generic_error_code::unspecified) - ErrMsg += EC.message() + " "; - if (!Context.empty()) - ErrMsg += Context; + llvm_unreachable("Unrecognized generic_error_code"); } -void GenericError::log(raw_ostream &OS) const { OS << ErrMsg << "\n"; } - -StringRef GenericError::getErrorMessage() const { return ErrMsg; } - -std::error_code GenericError::convertToErrorCode() const { - return std::error_code(static_cast(Code), *Category); -} +DEFINE_DEBUGERRORINFO(PDBError, pdb_error_code, PDBErrorCategory) Index: llvm/trunk/lib/DebugInfo/PDB/Native/NativeSession.cpp =================================================================== --- llvm/trunk/lib/DebugInfo/PDB/Native/NativeSession.cpp +++ llvm/trunk/lib/DebugInfo/PDB/Native/NativeSession.cpp @@ -11,7 +11,6 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/DebugInfo/CodeView/TypeIndex.h" -#include "llvm/DebugInfo/PDB/GenericError.h" #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" #include "llvm/DebugInfo/PDB/IPDBSourceFile.h" #include "llvm/DebugInfo/PDB/Native/NativeBuiltinSymbol.h" Index: llvm/trunk/lib/DebugInfo/PDB/Native/PDBFile.cpp =================================================================== --- llvm/trunk/lib/DebugInfo/PDB/Native/PDBFile.cpp +++ llvm/trunk/lib/DebugInfo/PDB/Native/PDBFile.cpp @@ -125,7 +125,7 @@ if (auto EC = Reader.readObject(SB)) { consumeError(std::move(EC)); return make_error(raw_error_code::corrupt_file, - "Does not contain superblock"); + "MSF superblock is missing"); } if (auto EC = msf::validateSuperBlock(*SB)) Index: llvm/trunk/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp =================================================================== --- llvm/trunk/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp +++ llvm/trunk/lib/DebugInfo/PDB/Native/PDBFileBuilder.cpp @@ -12,7 +12,6 @@ #include "llvm/ADT/BitVector.h" #include "llvm/DebugInfo/MSF/MSFBuilder.h" -#include "llvm/DebugInfo/PDB/GenericError.h" #include "llvm/DebugInfo/PDB/Native/DbiStream.h" #include "llvm/DebugInfo/PDB/Native/DbiStreamBuilder.h" #include "llvm/DebugInfo/PDB/Native/GSIStreamBuilder.h" Index: llvm/trunk/lib/DebugInfo/PDB/Native/RawError.cpp =================================================================== --- llvm/trunk/lib/DebugInfo/PDB/Native/RawError.cpp +++ llvm/trunk/lib/DebugInfo/PDB/Native/RawError.cpp @@ -5,71 +5,44 @@ using namespace llvm; using namespace llvm::pdb; -namespace { // FIXME: This class is only here to support the transition to llvm::Error. It // will be removed once this transition is complete. Clients should prefer to // deal with the Error value directly, rather than converting to error_code. -class RawErrorCategory : public std::error_category { -public: - const char *name() const noexcept override { return "llvm.pdb.raw"; } +const char *llvm::pdb::RawErrorCategory::name() const noexcept { + return "llvm.pdb.raw"; +} - std::string message(int Condition) const override { - switch (static_cast(Condition)) { - case raw_error_code::unspecified: - return "An unknown error has occurred."; - case raw_error_code::feature_unsupported: - return "The feature is unsupported by the implementation."; - case raw_error_code::invalid_format: - return "The record is in an unexpected format."; - case raw_error_code::corrupt_file: - return "The PDB file is corrupt."; - case raw_error_code::insufficient_buffer: - return "The buffer is not large enough to read the requested number of " - "bytes."; - case raw_error_code::no_stream: - return "The specified stream could not be loaded."; - case raw_error_code::index_out_of_bounds: - return "The specified item does not exist in the array."; - case raw_error_code::invalid_block_address: - return "The specified block address is not valid."; - case raw_error_code::duplicate_entry: - return "The entry already exists."; - case raw_error_code::no_entry: - return "The entry does not exist."; - case raw_error_code::not_writable: - return "The PDB does not support writing."; - case raw_error_code::stream_too_long: - return "The stream was longer than expected."; - case raw_error_code::invalid_tpi_hash: - return "The Type record has an invalid hash value."; - } - llvm_unreachable("Unrecognized raw_error_code"); +std::string llvm::pdb::RawErrorCategory::message(int Condition) const { + switch (static_cast(Condition)) { + case raw_error_code::unspecified: + return "An unknown error has occurred."; + case raw_error_code::feature_unsupported: + return "The feature is unsupported by the implementation."; + case raw_error_code::invalid_format: + return "The record is in an unexpected format."; + case raw_error_code::corrupt_file: + return "The PDB file is corrupt."; + case raw_error_code::insufficient_buffer: + return "The buffer is not large enough to read the requested number of " + "bytes."; + case raw_error_code::no_stream: + return "The specified stream could not be loaded."; + case raw_error_code::index_out_of_bounds: + return "The specified item does not exist in the array."; + case raw_error_code::invalid_block_address: + return "The specified block address is not valid."; + case raw_error_code::duplicate_entry: + return "The entry already exists."; + case raw_error_code::no_entry: + return "The entry does not exist."; + case raw_error_code::not_writable: + return "The PDB does not support writing."; + case raw_error_code::stream_too_long: + return "The stream was longer than expected."; + case raw_error_code::invalid_tpi_hash: + return "The Type record has an invalid hash value."; } -}; -} // end anonymous namespace - -static ManagedStatic Category; - -char RawError::ID = 0; - -RawError::RawError(raw_error_code C) : RawError(C, "") {} - -RawError::RawError(const std::string &Context) - : RawError(raw_error_code::unspecified, Context) {} - -RawError::RawError(raw_error_code C, const std::string &Context) : Code(C) { - ErrMsg = "Native PDB Error: "; - std::error_code EC = convertToErrorCode(); - if (Code != raw_error_code::unspecified) - ErrMsg += EC.message() + " "; - if (!Context.empty()) - ErrMsg += Context; + llvm_unreachable("Unrecognized raw_error_code"); } -void RawError::log(raw_ostream &OS) const { OS << ErrMsg << "\n"; } - -const std::string &RawError::getErrorMessage() const { return ErrMsg; } - -std::error_code RawError::convertToErrorCode() const { - return std::error_code(static_cast(Code), *Category); -} +DEFINE_DEBUGERRORINFO(RawError, raw_error_code, RawErrorCategory) Index: llvm/trunk/lib/DebugInfo/PDB/PDB.cpp =================================================================== --- llvm/trunk/lib/DebugInfo/PDB/PDB.cpp +++ llvm/trunk/lib/DebugInfo/PDB/PDB.cpp @@ -29,7 +29,7 @@ MemoryBuffer::getFileOrSTDIN(Path, /*FileSize=*/-1, /*RequiresNullTerminator=*/false); if (!ErrorOrBuffer) - return make_error(generic_error_code::invalid_path, Path); + return errorCodeToError(ErrorOrBuffer.getError()); return NativeSession::createFromPdb(std::move(*ErrorOrBuffer), Session); } @@ -37,7 +37,7 @@ #if LLVM_ENABLE_DIA_SDK return DIASession::createFromPdb(Path, Session); #else - return make_error("DIA is not installed on the system"); + return make_error(pdb_error_code::dia_sdk_not_present); #endif } @@ -50,6 +50,6 @@ #if LLVM_ENABLE_DIA_SDK return DIASession::createFromExe(Path, Session); #else - return make_error("DIA is not installed on the system"); + return make_error(pdb_error_code::dia_sdk_not_present); #endif } Index: llvm/trunk/lib/DebugInfo/Symbolize/Symbolize.cpp =================================================================== --- llvm/trunk/lib/DebugInfo/Symbolize/Symbolize.cpp +++ llvm/trunk/lib/DebugInfo/Symbolize/Symbolize.cpp @@ -410,7 +410,8 @@ Objects.first->getFileName(), Session)) { Modules.insert( std::make_pair(ModuleName, std::unique_ptr())); - return std::move(Err); + // Return along the PDB filename to provide more context + return createFileError(PDBFileName, std::move(Err)); } Context.reset(new PDBContext(*CoffObject, std::move(Session))); } Index: llvm/trunk/lib/Support/BinaryStreamError.cpp =================================================================== --- llvm/trunk/lib/Support/BinaryStreamError.cpp +++ llvm/trunk/lib/Support/BinaryStreamError.cpp @@ -47,7 +47,7 @@ } } -void BinaryStreamError::log(raw_ostream &OS) const { OS << ErrMsg << "\n"; } +void BinaryStreamError::log(raw_ostream &OS) const { OS << ErrMsg; } StringRef BinaryStreamError::getErrorMessage() const { return ErrMsg; } Index: llvm/trunk/lib/Support/Error.cpp =================================================================== --- llvm/trunk/lib/Support/Error.cpp +++ llvm/trunk/lib/Support/Error.cpp @@ -53,6 +53,7 @@ char ErrorList::ID = 0; char ECError::ID = 0; char StringError::ID = 0; +char FileError::ID = 0; void logAllUnhandledErrors(Error E, raw_ostream &OS, Twine ErrorBanner) { if (!E) @@ -75,6 +76,10 @@ *ErrorErrorCat); } +std::error_code FileError::convertToErrorCode() const { + return inconvertibleErrorCode(); +} + Error errorCodeToError(std::error_code EC) { if (!EC) return Error::success(); Index: llvm/trunk/test/DebugInfo/PDB/pdb-invalid-type.test =================================================================== --- llvm/trunk/test/DebugInfo/PDB/pdb-invalid-type.test +++ llvm/trunk/test/DebugInfo/PDB/pdb-invalid-type.test @@ -2,7 +2,7 @@ # RUN: llvm-pdbutil yaml2pdb -pdb=%t2.pdb %s # RUN: not llvm-pdbutil merge -pdb=%t.pdb %t1.pdb %t2.pdb 2>&1 | FileCheck %s -# CHECK: CodeView Error: The CodeView record is corrupted. +# CHECK: The CodeView record is corrupted --- TpiStream: Index: llvm/trunk/test/DebugInfo/PDB/pdbdump-headers.test =================================================================== --- llvm/trunk/test/DebugInfo/PDB/pdbdump-headers.test +++ llvm/trunk/test/DebugInfo/PDB/pdbdump-headers.test @@ -1167,4 +1167,4 @@ BIG-NEXT: Mod 0046 | `api-ms-win-crt-heap-l1-1-0.dll`: BIG-NEXT: Mod 0047 | `* Linker *`: -BAD-BLOCK-SIZE: Native PDB Error: The PDB file is corrupt. Does not contain superblock +BAD-BLOCK-SIZE: The PDB file is corrupt. MSF superblock is missing Index: llvm/trunk/test/tools/llvm-readobj/codeview-merging-cycle.test =================================================================== --- llvm/trunk/test/tools/llvm-readobj/codeview-merging-cycle.test +++ llvm/trunk/test/tools/llvm-readobj/codeview-merging-cycle.test @@ -1,6 +1,6 @@ ; RUN: not llvm-readobj -codeview-merged-types %S/Inputs/codeview-cycle.obj 2>&1 | FileCheck %s -; CHECK: Error{{.*}} input type graph contains cycles +; CHECK: Error{{.*}} Input type graph contains cycles ; To reproduce codeview-cycle.obj: ; $ cat codeview-cycle.asm Index: llvm/trunk/test/tools/llvm-symbolizer/pdb/missing_pdb.test =================================================================== --- llvm/trunk/test/tools/llvm-symbolizer/pdb/missing_pdb.test +++ llvm/trunk/test/tools/llvm-symbolizer/pdb/missing_pdb.test @@ -8,7 +8,7 @@ llvm-symbolizer should print one error and two unknown line info records. -ERROR: LLVMSymbolizer: error reading file: PDB Error: Unable to load PDB. Make sure the file exists and is readable. +ERROR: LLVMSymbolizer: error reading file: {{.*}}: {{N|n}}o such file or directory ERROR-NOT: error reading file CHECK: ?? Index: llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.cpp =================================================================== --- llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.cpp +++ llvm/trunk/tools/llvm-pdbutil/llvm-pdbutil.cpp @@ -46,7 +46,6 @@ #include "llvm/DebugInfo/CodeView/StringsAndChecksums.h" #include "llvm/DebugInfo/CodeView/TypeStreamMerger.h" #include "llvm/DebugInfo/MSF/MSFBuilder.h" -#include "llvm/DebugInfo/PDB/GenericError.h" #include "llvm/DebugInfo/PDB/IPDBEnumChildren.h" #include "llvm/DebugInfo/PDB/IPDBInjectedSource.h" #include "llvm/DebugInfo/PDB/IPDBRawSymbol.h" @@ -681,7 +680,7 @@ /*RequiresNullTerminator=*/false); if (ErrorOrBuffer.getError()) { - ExitOnErr(make_error(generic_error_code::invalid_path, Path)); + ExitOnErr(createFileError(Path, errorCodeToError(ErrorOrBuffer.getError()))); } std::unique_ptr &Buffer = ErrorOrBuffer.get(); Index: llvm/trunk/tools/obj2yaml/Error.cpp =================================================================== --- llvm/trunk/tools/obj2yaml/Error.cpp +++ llvm/trunk/tools/obj2yaml/Error.cpp @@ -53,7 +53,7 @@ char Obj2YamlError::ID = 0; -void Obj2YamlError::log(raw_ostream &OS) const { OS << ErrMsg << "\n"; } +void Obj2YamlError::log(raw_ostream &OS) const { OS << ErrMsg; } std::error_code Obj2YamlError::convertToErrorCode() const { return std::error_code(static_cast(Code), obj2yaml_category());