diff --git a/llvm/test/tools/llvm-objdump/debuginfod.test b/llvm/test/tools/llvm-objdump/debuginfod.test
--- a/llvm/test/tools/llvm-objdump/debuginfod.test
+++ b/llvm/test/tools/llvm-objdump/debuginfod.test
@@ -30,6 +30,11 @@
RUN: %t/stripped | \
RUN: FileCheck %s --check-prefix=FOUND
+# Use debuginfod to look up build IDs
+RUN: env DEBUGINFOD_CACHE_PATH=%t llvm-objdump -d --source \
+RUN: --build-id 1512f769114c011387393822af15dd660c080295 | \
+RUN: FileCheck %s --check-prefix=FOUND
+
# Use debuginfod to replace very-stripped binaries entirely.
RUN: llvm-strip --strip-sections %t/stripped
RUN: env DEBUGINFOD_CACHE_PATH=%t llvm-objdump -d --debuginfod \
diff --git a/llvm/tools/llvm-objdump/ObjdumpOpts.td b/llvm/tools/llvm-objdump/ObjdumpOpts.td
--- a/llvm/tools/llvm-objdump/ObjdumpOpts.td
+++ b/llvm/tools/llvm-objdump/ObjdumpOpts.td
@@ -38,6 +38,10 @@
def archive_headers : Flag<["--"], "archive-headers">,
HelpText<"Display archive header information">;
+defm build_id :
+ Eq<"build-id", "Build ID to look up. Once found, added as an input file.">,
+ MetaVarName<"
">;
+
def : Flag<["-"], "a">, Alias,
HelpText<"Alias for --archive-headers">;
diff --git a/llvm/tools/llvm-objdump/llvm-objdump.cpp b/llvm/tools/llvm-objdump/llvm-objdump.cpp
--- a/llvm/tools/llvm-objdump/llvm-objdump.cpp
+++ b/llvm/tools/llvm-objdump/llvm-objdump.cpp
@@ -2790,6 +2790,17 @@
}
}
+static object::BuildID parseBuildIDArg(const opt::Arg *A) {
+ StringRef V(A->getValue());
+ std::string Bytes;
+ if (!tryGetFromHex(V, Bytes))
+ reportCmdLineError(A->getSpelling() + ": expected a build ID, but got '" +
+ V + "'");
+ ArrayRef BuildID(reinterpret_cast(Bytes.data()),
+ Bytes.size());
+ return object::BuildID(BuildID.begin(), BuildID.end());
+}
+
static void invalidArgValue(const opt::Arg *A) {
reportCmdLineError("'" + StringRef(A->getValue()) +
"' is not a valid value for '" + A->getSpelling() + "'");
@@ -2956,6 +2967,16 @@
llvm::cl::ParseCommandLineOptions(2, Argv);
}
+ // Look up any provided build IDs, then append them to the input filenames.
+ for (const opt::Arg *A : InputArgs.filtered(OBJDUMP_build_id)) {
+ object::BuildID BuildID = parseBuildIDArg(A);
+ Optional Path = BIDFetcher->fetch(BuildID);
+ if (!Path)
+ reportCmdLineError(A->getSpelling() + ": could not find build ID '" +
+ A->getValue() + "'");
+ InputFilenames.push_back(std::move(*Path));
+ }
+
// objdump defaults to a.out if no filenames specified.
if (InputFilenames.empty())
InputFilenames.push_back("a.out");
@@ -3023,15 +3044,11 @@
return 0;
}
- if (Is("otool"))
- parseOtoolOptions(InputArgs);
- else
- parseObjdumpOptions(InputArgs);
-
// Initialize debuginfod.
const bool ShouldUseDebuginfodByDefault =
- HTTPClient::isAvailable() &&
- !ExitOnErr(getDefaultDebuginfodUrls()).empty();
+ InputArgs.hasArg(OBJDUMP_build_id) ||
+ (HTTPClient::isAvailable() &&
+ !ExitOnErr(getDefaultDebuginfodUrls()).empty());
if (InputArgs.hasFlag(OBJDUMP_debuginfod, OBJDUMP_no_debuginfod,
ShouldUseDebuginfodByDefault)) {
HTTPClient::initialize();
@@ -3040,6 +3057,11 @@
BIDFetcher = std::make_unique(DebugFileDirectories);
}
+ if (Is("otool"))
+ parseOtoolOptions(InputArgs);
+ else
+ parseObjdumpOptions(InputArgs);
+
if (StartAddress >= StopAddress)
reportCmdLineError("start address should be less than stop address");