Skip to content

Commit a3b0dde

Browse files
committed
Reland: [llvm-cov] Look up object files using debuginfod
Reviewed By: gulfem Differential Revision: https://reviews.llvm.org/D136702
1 parent 42c36da commit a3b0dde

File tree

17 files changed

+271
-60
lines changed

17 files changed

+271
-60
lines changed

compiler-rt/test/profile/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ if(APPLE)
1616
darwin_filter_host_archs(PROFILE_SUPPORTED_ARCH PROFILE_TEST_ARCH)
1717
endif()
1818

19+
pythonize_bool(LLVM_ENABLE_CURL)
20+
1921
foreach(arch ${PROFILE_TEST_ARCH})
2022
set(PROFILE_TEST_TARGET_ARCH ${arch})
2123
get_test_cc_for_arch(${arch} PROFILE_TEST_TARGET_CC PROFILE_TEST_TARGET_CFLAGS)
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
// REQUIRES: linux, curl
2+
// RUN: split-file %s %t
3+
// RUN: %clang_profgen -Wl,--build-id=0x12345678 -fcoverage-mapping -O2 -shared %t/foo.c -o %t/libfoo.so
4+
// RUN: %clang_profgen -Wl,--build-id=0xabcd1234 -fcoverage-mapping -O2 %t/main.c -L%t -lfoo -o %t.main
5+
// RUN: rm -rf %t.profdir
6+
// RUN: env LLVM_PROFILE_FILE=%t.profdir/default_%m.profraw LD_LIBRARY_PATH=%t %run %t.main
7+
// RUN: mkdir -p %t/buildid/12345678 %t/buildid/abcd1234
8+
// RUN: cp %t/libfoo.so %t/buildid/12345678/debuginfo
9+
// RUN: cp %t.main %t/buildid/abcd1234/debuginfo
10+
// RUN: llvm-profdata merge -o %t.profdata %t.profdir/default_*.profraw
11+
// RUN: env DEBUGINFOD_URLS=file://%t llvm-cov show -instr-profile %t.profdata | FileCheck %s
12+
// RUN: echo "bad" > %t/libfoo.so %t/buildid/12345678/debuginfo
13+
// RUN: echo "bad" > %t/buildid/abcd1234/debuginfo
14+
// RUN: env DEBUGINFOD_URLS=file://%t llvm-cov show -instr-profile %t.profdata -debuginfod=false %t.main | FileCheck %s --check-prefix=NODEBUGINFOD
15+
16+
// CHECK: 1| 1|void foo(void) {}
17+
// CHECK: 2| 1|void bar(void) {}
18+
// CHECK: 3| 1|int main() {
19+
20+
// NODEBUGINFOD-NOT: foo(void) {}
21+
// NODEBUGINFOD: main
22+
23+
//--- foo.c
24+
void foo(void) {}
25+
26+
//--- main.c
27+
void foo(void);
28+
void bar(void) {}
29+
int main() {
30+
foo();
31+
bar();
32+
return 0;
33+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// REQUIRES: linux
2+
// RUN: split-file %s %t
3+
// RUN: %clang_profgen -Wl,--build-id=0x12345678 -fcoverage-mapping -O2 -shared %t/foo.c -o %t/libfoo.so
4+
// RUN: %clang_profgen -Wl,--build-id=0xabcd1234 -fcoverage-mapping -O2 %t/main.c -L%t -lfoo -o %t.main
5+
// RUN: rm -rf %t.profdir
6+
// RUN: env LLVM_PROFILE_FILE=%t.profdir/default_%m.profraw LD_LIBRARY_PATH=%t %run %t.main
7+
// RUN: mkdir -p %t/.build-id/12 %t/.build-id/ab
8+
// RUN: cp %t/libfoo.so %t/.build-id/12/345678.debug
9+
// RUN: cp %t.main %t/.build-id/ab/cd1234.debug
10+
// RUN: llvm-profdata merge -o %t.profdata %t.profdir/default_*.profraw
11+
// RUN: llvm-cov show -instr-profile %t.profdata -debug-file-directory %t | FileCheck %s
12+
// RUN: echo "bad" > %t/.build-id/ab/cd1234.debug
13+
// RUN: llvm-cov show -instr-profile %t.profdata -debug-file-directory %t %t.main | FileCheck %s
14+
// RUN: not llvm-cov show -instr-profile %t.profdata -debug-file-directory %t/empty 2>&1 | FileCheck %s --check-prefix=NODATA
15+
16+
// CHECK: 1| 1|void foo(void) {}
17+
// CHECK: 2| 1|void bar(void) {}
18+
// CHECK: 3| 1|int main() {
19+
20+
// NODATA: error: Failed to load coverage: '': No coverage data found
21+
22+
//--- foo.c
23+
void foo(void) {}
24+
25+
//--- main.c
26+
void foo(void);
27+
void bar(void) {}
28+
int main() {
29+
foo();
30+
bar();
31+
return 0;
32+
}

compiler-rt/test/profile/Linux/lit.local.cfg.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,6 @@ def is_gold_linker_available():
3838

3939
if root.host_os not in ['Linux'] or not is_gold_linker_available():
4040
config.unsupported = True
41+
42+
if config.have_curl:
43+
config.available_features.add('curl')

compiler-rt/test/profile/lit.site.cfg.py.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
config.profile_lit_binary_dir = "@PROFILE_LIT_BINARY_DIR@"
55
config.target_cflags = "@PROFILE_TEST_TARGET_CFLAGS@"
66
config.target_arch = "@PROFILE_TEST_TARGET_ARCH@"
7+
config.have_curl = @LLVM_ENABLE_CURL_PYBOOL@
78

89
# Load common config for all compiler-rt lit tests.
910
lit_config.load_config(config, "@COMPILER_RT_BINARY_DIR@/test/lit.common.configured")

llvm/cmake/modules/LLVMConfig.cmake.in

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,11 @@ if(LLVM_ENABLE_LIBXML2)
8383
find_package(LibXml2)
8484
endif()
8585

86+
set(LLVM_ENABLE_CURL @LLVM_ENABLE_CURL@)
87+
if(LLVM_ENABLE_CURL)
88+
find_package(CURL)
89+
endif()
90+
8691
set(LLVM_WITH_Z3 @LLVM_WITH_Z3@)
8792

8893
set(LLVM_ENABLE_DIA_SDK @LLVM_ENABLE_DIA_SDK@)

llvm/docs/CommandGuide/llvm-cov.rst

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,17 @@ OPTIONS
349349
coverage >= high, red when coverage < low, and yellow otherwise. Both high and
350350
low should be between 0-100 and high > low.
351351

352+
.. option:: -debuginfod
353+
354+
Use debuginfod to look up coverage mapping for binary IDs present in the profile
355+
but not in any object given on the command line. Defaults to true if debuginfod
356+
is compiled in and configured via the DEBUGINFOD_URLS environment variable.
357+
358+
.. option:: -debug-file-directory=<dir>
359+
360+
Provides local directories to search for objects corresponding to binary IDs in
361+
the profile (as with debuginfod). Defaults to system build ID directories.
362+
352363
.. program:: llvm-cov report
353364

354365
.. _llvm-cov-report:
@@ -418,6 +429,18 @@ OPTIONS
418429
when binaries have been compiled with one of `-fcoverage-prefix-map`
419430
`-fcoverage-compilation-dir`, or `-ffile-compilation-dir`.
420431

432+
.. option:: -debuginfod
433+
434+
Attempt to look up coverage mapping from objects using debuginfod. This is
435+
attempted by default for binary IDs present in the profile but not provided on
436+
the command line, so long as debuginfod is compiled in and configured via
437+
DEBUGINFOD_URLS.
438+
439+
.. option:: -debug-file-directory=<dir>
440+
441+
Provides a directory to search for objects corresponding to binary IDs in the
442+
profile.
443+
421444
.. program:: llvm-cov export
422445

423446
.. _llvm-cov-export:
@@ -492,3 +515,15 @@ OPTIONS
492515
Directory used as a base for relative coverage mapping paths. Only applicable
493516
when binaries have been compiled with one of `-fcoverage-prefix-map`
494517
`-fcoverage-compilation-dir`, or `-ffile-compilation-dir`.
518+
519+
.. option:: -debuginfod
520+
521+
Attempt to look up coverage mapping from objects using debuginfod. This is
522+
attempted by default for binary IDs present in the profile but not provided on
523+
the command line, so long as debuginfod is compiled in and configured via
524+
DEBUGINFOD_URLS.
525+
526+
.. option:: -debug-file-directory=<dir>
527+
528+
Provides a directory to search for objects corresponding to binary IDs in the
529+
profile.

llvm/include/llvm/Debuginfod/Debuginfod.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,13 @@
3838

3939
namespace llvm {
4040

41+
/// Returns false if a debuginfod lookup can be determined to have no chance of
42+
/// succeeding.
43+
bool canUseDebuginfod();
44+
4145
/// Finds default array of Debuginfod server URLs by checking DEBUGINFOD_URLS
4246
/// environment variable.
43-
Expected<SmallVector<StringRef>> getDefaultDebuginfodUrls();
47+
SmallVector<StringRef> getDefaultDebuginfodUrls();
4448

4549
/// Finds a default local file caching directory for the debuginfod client,
4650
/// first checking DEBUGINFOD_CACHE_PATH.

llvm/include/llvm/ProfileData/Coverage/CoverageMapping.h

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "llvm/ADT/StringRef.h"
2222
#include "llvm/ADT/iterator.h"
2323
#include "llvm/ADT/iterator_range.h"
24+
#include "llvm/Object/BuildID.h"
2425
#include "llvm/ProfileData/InstrProf.h"
2526
#include "llvm/Support/Alignment.h"
2627
#include "llvm/Support/Compiler.h"
@@ -42,6 +43,10 @@ namespace llvm {
4243

4344
class IndexedInstrProfReader;
4445

46+
namespace object {
47+
class BuildIDFetcher;
48+
} // namespace object
49+
4550
namespace coverage {
4651

4752
class CoverageMappingReader;
@@ -579,6 +584,13 @@ class CoverageMapping {
579584
ArrayRef<std::unique_ptr<CoverageMappingReader>> CoverageReaders,
580585
IndexedInstrProfReader &ProfileReader, CoverageMapping &Coverage);
581586

587+
// Load coverage records from file.
588+
static Error
589+
loadFromFile(StringRef Filename, StringRef Arch, StringRef CompilationDir,
590+
IndexedInstrProfReader &ProfileReader, CoverageMapping &Coverage,
591+
bool &DataFound,
592+
SmallVectorImpl<object::BuildID> *FoundBinaryIDs = nullptr);
593+
582594
/// Add a function record corresponding to \p Record.
583595
Error loadFunctionRecord(const CoverageMappingRecord &Record,
584596
IndexedInstrProfReader &ProfileReader);
@@ -604,8 +616,8 @@ class CoverageMapping {
604616
/// Ignores non-instrumented object files unless all are not instrumented.
605617
static Expected<std::unique_ptr<CoverageMapping>>
606618
load(ArrayRef<StringRef> ObjectFilenames, StringRef ProfileFilename,
607-
ArrayRef<StringRef> Arches = std::nullopt,
608-
StringRef CompilationDir = "");
619+
ArrayRef<StringRef> Arches = std::nullopt, StringRef CompilationDir = "",
620+
const object::BuildIDFetcher *BIDFetcher = nullptr);
609621

610622
/// The number of functions that couldn't have their profiles mapped.
611623
///

llvm/include/llvm/ProfileData/Coverage/CoverageMappingReader.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,8 @@ class BinaryCoverageReader : public CoverageMappingReader {
205205
static Expected<std::vector<std::unique_ptr<BinaryCoverageReader>>>
206206
create(MemoryBufferRef ObjectBuffer, StringRef Arch,
207207
SmallVectorImpl<std::unique_ptr<MemoryBuffer>> &ObjectFileBuffers,
208-
StringRef CompilationDir = "");
208+
StringRef CompilationDir = "",
209+
SmallVectorImpl<object::BuildIDRef> *BinaryIDs = nullptr);
209210

210211
static Expected<std::unique_ptr<BinaryCoverageReader>>
211212
createCoverageReaderFromBuffer(StringRef Coverage,

llvm/lib/Debuginfod/Debuginfod.cpp

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,11 @@ static std::string buildIDToString(BuildIDRef ID) {
5555
return llvm::toHex(ID, /*LowerCase=*/true);
5656
}
5757

58-
Expected<SmallVector<StringRef>> getDefaultDebuginfodUrls() {
58+
bool canUseDebuginfod() {
59+
return HTTPClient::isAvailable() && !getDefaultDebuginfodUrls().empty();
60+
}
61+
62+
SmallVector<StringRef> getDefaultDebuginfodUrls() {
5963
const char *DebuginfodUrlsEnv = std::getenv("DEBUGINFOD_URLS");
6064
if (DebuginfodUrlsEnv == nullptr)
6165
return SmallVector<StringRef>();
@@ -126,13 +130,8 @@ Expected<std::string> getCachedOrDownloadArtifact(StringRef UniqueKey,
126130
return CacheDirOrErr.takeError();
127131
CacheDir = *CacheDirOrErr;
128132

129-
Expected<SmallVector<StringRef>> DebuginfodUrlsOrErr =
130-
getDefaultDebuginfodUrls();
131-
if (!DebuginfodUrlsOrErr)
132-
return DebuginfodUrlsOrErr.takeError();
133-
SmallVector<StringRef> &DebuginfodUrls = *DebuginfodUrlsOrErr;
134133
return getCachedOrDownloadArtifact(UniqueKey, UrlPath, CacheDir,
135-
DebuginfodUrls,
134+
getDefaultDebuginfodUrls(),
136135
getDefaultDebuginfodTimeout());
137136
}
138137

@@ -159,7 +158,8 @@ class StreamedHTTPResponseHandler : public HTTPResponseHandler {
159158

160159
Error StreamedHTTPResponseHandler::handleBodyChunk(StringRef BodyChunk) {
161160
if (!FileStream) {
162-
if (Client.responseCode() != 200)
161+
unsigned Code = Client.responseCode();
162+
if (Code && Code != 200)
163163
return Error::success();
164164
Expected<std::unique_ptr<CachedFileStream>> FileStreamOrError =
165165
CreateStream();
@@ -259,7 +259,8 @@ Expected<std::string> getCachedOrDownloadArtifact(
259259
if (Err)
260260
return std::move(Err);
261261

262-
if (Client.responseCode() != 200)
262+
unsigned Code = Client.responseCode();
263+
if (Code && Code != 200)
263264
continue;
264265

265266
// Return the path to the artifact on disk.

0 commit comments

Comments
 (0)