Index: compiler-rt/lib/sanitizer_common/symbolizer/scripts/build_symbolizer.sh =================================================================== --- compiler-rt/lib/sanitizer_common/symbolizer/scripts/build_symbolizer.sh +++ compiler-rt/lib/sanitizer_common/symbolizer/scripts/build_symbolizer.sh @@ -143,7 +143,7 @@ $LLVM_SRC fi cd ${LLVM_BUILD} -ninja LLVMSymbolize LLVMObject LLVMBinaryFormat LLVMDebugInfoDWARF LLVMSupport LLVMDebugInfoPDB LLVMMC LLVMDemangle LLVMTextAPI +ninja LLVMSymbolize LLVMObject LLVMBinaryFormat LLVMDebugInfoDWARF LLVMSupport LLVMDebugInfoPDB LLVMDebuginfod LLVMMC LLVMDemangle LLVMTextAPI cd ${BUILD_DIR} rm -rf ${SYMBOLIZER_BUILD} @@ -170,6 +170,7 @@ $LLVM_BUILD/lib/libLLVMDebugInfoPDB.a \ $LLVM_BUILD/lib/libLLVMDebugInfoMSF.a \ $LLVM_BUILD/lib/libLLVMDebugInfoCodeView.a \ + $LLVM_BUILD/lib/libLLVMDebuginfod.a \ $LLVM_BUILD/lib/libLLVMDemangle.a \ $LLVM_BUILD/lib/libLLVMMC.a \ $LLVM_BUILD/lib/libLLVMTextAPI.a \ Index: llvm/include/llvm/Debuginfod/HTTPClient.h =================================================================== --- llvm/include/llvm/Debuginfod/HTTPClient.h +++ llvm/include/llvm/Debuginfod/HTTPClient.h @@ -79,13 +79,14 @@ class HTTPClient { #ifdef LLVM_ENABLE_CURL void *Curl = nullptr; - static bool IsInitialized; #endif public: HTTPClient(); ~HTTPClient(); + static bool IsInitialized; + /// Returns true only if LLVM has been compiled with a working HTTPClient. static bool isAvailable(); Index: llvm/lib/DebugInfo/Symbolize/CMakeLists.txt =================================================================== --- llvm/lib/DebugInfo/Symbolize/CMakeLists.txt +++ llvm/lib/DebugInfo/Symbolize/CMakeLists.txt @@ -9,6 +9,7 @@ LINK_COMPONENTS DebugInfoDWARF DebugInfoPDB + Debuginfod Object Support Demangle Index: llvm/lib/DebugInfo/Symbolize/Symbolize.cpp =================================================================== --- llvm/lib/DebugInfo/Symbolize/Symbolize.cpp +++ llvm/lib/DebugInfo/Symbolize/Symbolize.cpp @@ -20,6 +20,7 @@ #include "llvm/DebugInfo/DWARF/DWARFContext.h" #include "llvm/DebugInfo/PDB/PDB.h" #include "llvm/DebugInfo/PDB/PDBContext.h" +#include "llvm/Debuginfod/Debuginfod.h" #include "llvm/Demangle/Demangle.h" #include "llvm/Object/COFF.h" #include "llvm/Object/MachO.h" @@ -384,7 +385,14 @@ } } } - return false; + // Try debuginfod client cache and known servers. + Expected PathOrErr = getCachedOrDownloadDebuginfo(BuildID); + if (!PathOrErr) { + consumeError(PathOrErr.takeError()); + return false; + } + Result = *PathOrErr; + return true; } } // end anonymous namespace Index: llvm/lib/Debuginfod/Debuginfod.cpp =================================================================== --- llvm/lib/Debuginfod/Debuginfod.cpp +++ llvm/lib/Debuginfod/Debuginfod.cpp @@ -139,6 +139,13 @@ return createStringError(errc::io_error, "No working HTTP client is available."); + if (!HTTPClient::IsInitialized) + return createStringError( + errc::io_error, + "A working HTTP client is available, but it is not initialized. To " + "allow Debuginfod to make HTTP requests, call HTTPClient::initialize() " + "at the beginning of main."); + HTTPClient Client; Client.setTimeout(Timeout); for (StringRef ServerUrl : DebuginfodUrls) { @@ -157,7 +164,7 @@ // file cache. Expected> FileStreamOrErr = CacheAddStream(Task); - if (FileStreamOrErr) + if (!FileStreamOrErr) return FileStreamOrErr.takeError(); std::unique_ptr &FileStream = *FileStreamOrErr; if (!Response.Body) Index: llvm/lib/Debuginfod/HTTPClient.cpp =================================================================== --- llvm/lib/Debuginfod/HTTPClient.cpp +++ llvm/lib/Debuginfod/HTTPClient.cpp @@ -72,6 +72,14 @@ return Error::success(); } +bool HTTPClient::IsInitialized = false; + +class HTTPClientCleanup { +public: + ~HTTPClientCleanup() { HTTPClient::cleanup(); } +}; +static const HTTPClientCleanup Cleanup; + Expected HTTPClient::perform(const HTTPRequest &Request) { BufferedHTTPResponseHandler Handler; if (Error Err = perform(Request, Handler)) @@ -88,8 +96,6 @@ bool HTTPClient::isAvailable() { return true; } -bool HTTPClient::IsInitialized = false; - void HTTPClient::initialize() { if (!IsInitialized) { curl_global_init(CURL_GLOBAL_ALL); Index: llvm/test/tools/llvm-symbolizer/debuginfod.test =================================================================== --- /dev/null +++ llvm/test/tools/llvm-symbolizer/debuginfod.test @@ -0,0 +1,27 @@ +# This test uses the local debuginfod cache to test the symbolizer integration +# with the debuginfod client. +RUN: rm -rf %t +RUN: mkdir %t + +# Produce a stripped copy of the input binary addr.exe +RUN: llvm-objcopy --strip-debug %p/Inputs/addr.exe %t/addr.exe + +# Symbolizing the stripped binary should fail. +RUN: env DEBUGINFOD_CACHE_PATH=%t llvm-symbolizer --print-address \ +RUN: --obj=%t/addr.exe 0x40054d | FileCheck %s --check-prefix=NOTFOUND +NOTFOUND: 0x40054d +NOTFOUND-NEXT: main +NOTFOUND-NEXT: ??:0:0 + +# Use llvm-objcopy to write the debuginfo of the addr.exe binary to an +# appropriately-named file in the llvm debuginfod cache. The filename is +# determined by the debuginfod client's caching scheme, so it is manually +# specified here as llvmcache-98...19 +RUN: llvm-objcopy --keep-section=.debug_info %p/Inputs/addr.exe \ +RUN: %t/llvmcache-9800707741016212219 + +# The symbolizer should call the debuginfod client library, which finds the +# debuginfo placed in the cache, enabling symbolization of the address. +RUN: env DEBUGINFOD_CACHE_PATH=%t llvm-symbolizer \ +RUN: --obj=%t/addr.exe 0x40054d | FileCheck %s --check-prefix=FOUND +FOUND: {{[/\]+}}tmp{{[/\]+}}x.c:14:0 Index: llvm/tools/llvm-symbolizer/CMakeLists.txt =================================================================== --- llvm/tools/llvm-symbolizer/CMakeLists.txt +++ llvm/tools/llvm-symbolizer/CMakeLists.txt @@ -10,6 +10,7 @@ set(LLVM_LINK_COMPONENTS DebugInfoDWARF DebugInfoPDB + Debuginfod Demangle Object Option Index: llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp =================================================================== --- llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp +++ llvm/tools/llvm-symbolizer/llvm-symbolizer.cpp @@ -19,6 +19,7 @@ #include "llvm/Config/config.h" #include "llvm/DebugInfo/Symbolize/DIPrinter.h" #include "llvm/DebugInfo/Symbolize/Symbolize.h" +#include "llvm/Debuginfod/HTTPClient.h" #include "llvm/Option/Arg.h" #include "llvm/Option/ArgList.h" #include "llvm/Option/Option.h" @@ -261,6 +262,8 @@ int main(int argc, char **argv) { InitLLVM X(argc, argv); + // The HTTPClient must be initialized for use by the debuginfod client. + HTTPClient::initialize(); sys::InitializeCOMRAII COM(sys::COMThreadingMode::MultiThreaded); bool IsAddr2Line = sys::path::stem(argv[0]).contains("addr2line"); Index: llvm/utils/gn/secondary/llvm/lib/DebugInfo/Symbolize/BUILD.gn =================================================================== --- llvm/utils/gn/secondary/llvm/lib/DebugInfo/Symbolize/BUILD.gn +++ llvm/utils/gn/secondary/llvm/lib/DebugInfo/Symbolize/BUILD.gn @@ -4,6 +4,7 @@ "//llvm/include/llvm/Config:config", "//llvm/lib/DebugInfo/DWARF", "//llvm/lib/DebugInfo/PDB", + "//llvm/lib/Debuginfod", "//llvm/lib/Demangle", "//llvm/lib/Object", "//llvm/lib/Support",