In Clang/LLVM we are moving towards a new binary format to store many embedded object files to create a fatbinary. This patch adds support for dumping these embedded images in the `llvm-objdump` tool. This will allow users to query information about what is stored inside the binary. This has very similar functionality to the `cuobjdump` tool for thoe familiar with the Nvidia utilities. The proposed use is as follows: ``` $ clang input.c -fopenmp --offload-arch=sm_70 --offload-arch=sm_52 -c $ llvm-objdump -O input.o input.o: file format elf64-x86-64 OFFLOADIND IMAGE [0]: kind cubin arch sm_52 triple nvptx64-nvidia-cuda producer openmp OFFLOADIND IMAGE [1]: kind cubin arch sm_70 triple nvptx64-nvidia-cuda producer openmp ``` This will be expanded further once we start embedding more information into these offloading images. Right now we are planning on adding flags and entries for debug level, optimization, LTO usage, target features, among others. This patch only supports printing these sections, later we will want to support dumping files the user may be interested in via another flag. I am unsure if this should go here in `llvm-objdump` or `llvm-objcopy`. Reviewed By: MaskRay, tra, jhenderson, JonChesterfield Differential Revision: https://reviews.llvm.org/D126904
103 lines
3.6 KiB
C++
103 lines
3.6 KiB
C++
//===-- OffloadDump.cpp - Offloading dumper ---------------------*- C++ -*-===//
|
|
//
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
|
//
|
|
//===----------------------------------------------------------------------===//
|
|
///
|
|
/// \file
|
|
/// This file implements the offloading-specific dumper for llvm-objdump.
|
|
///
|
|
//===----------------------------------------------------------------------===//
|
|
#include "OffloadDump.h"
|
|
#include "llvm-objdump.h"
|
|
|
|
using namespace llvm;
|
|
using namespace llvm::object;
|
|
using namespace llvm::objdump;
|
|
|
|
constexpr const char OffloadSectionString[] = ".llvm.offloading";
|
|
|
|
/// Get the printable name of the image kind.
|
|
static StringRef getImageName(const OffloadBinary &OB) {
|
|
switch (OB.getImageKind()) {
|
|
case IMG_Object:
|
|
return "elf";
|
|
case IMG_Bitcode:
|
|
return "llvm ir";
|
|
case IMG_Cubin:
|
|
return "cubin";
|
|
case IMG_Fatbinary:
|
|
return "fatbinary";
|
|
case IMG_PTX:
|
|
return "ptx";
|
|
default:
|
|
return "<none>";
|
|
}
|
|
}
|
|
|
|
static void printBinary(const OffloadBinary &OB, uint64_t Index) {
|
|
outs() << "\nOFFLOADING IMAGE [" << Index << "]:\n";
|
|
outs() << left_justify("kind", 16) << getImageName(OB) << "\n";
|
|
outs() << left_justify("arch", 16) << OB.getArch() << "\n";
|
|
outs() << left_justify("triple", 16) << OB.getTriple() << "\n";
|
|
outs() << left_justify("producer", 16)
|
|
<< getOffloadKindName(OB.getOffloadKind()) << "\n";
|
|
}
|
|
|
|
static Error visitAllBinaries(const OffloadBinary &OB) {
|
|
uint64_t Offset = 0;
|
|
uint64_t Index = 0;
|
|
while (Offset < OB.getMemoryBufferRef().getBufferSize()) {
|
|
MemoryBufferRef Buffer =
|
|
MemoryBufferRef(OB.getData().drop_front(Offset), OB.getFileName());
|
|
auto BinaryOrErr = OffloadBinary::create(Buffer);
|
|
if (!BinaryOrErr)
|
|
return BinaryOrErr.takeError();
|
|
|
|
OffloadBinary &Binary = **BinaryOrErr;
|
|
printBinary(Binary, Index++);
|
|
|
|
Offset += Binary.getSize();
|
|
}
|
|
return Error::success();
|
|
}
|
|
|
|
/// Print the embedded offloading contents of an ObjectFile \p O.
|
|
void llvm::dumpOffloadBinary(const ObjectFile &O) {
|
|
for (SectionRef Sec : O.sections()) {
|
|
Expected<StringRef> Name = Sec.getName();
|
|
if (!Name || !Name->startswith(OffloadSectionString))
|
|
continue;
|
|
|
|
Expected<StringRef> Contents = Sec.getContents();
|
|
if (!Contents)
|
|
reportError(Contents.takeError(), O.getFileName());
|
|
|
|
MemoryBufferRef Buffer = MemoryBufferRef(*Contents, O.getFileName());
|
|
auto BinaryOrErr = OffloadBinary::create(Buffer);
|
|
if (!BinaryOrErr)
|
|
reportError(O.getFileName(), "while extracting offloading files: " +
|
|
toString(BinaryOrErr.takeError()));
|
|
OffloadBinary &Binary = **BinaryOrErr;
|
|
|
|
// Print out all the binaries that are contained in this buffer. If we fail
|
|
// to parse a binary before reaching the end of the buffer emit a warning.
|
|
if (Error Err = visitAllBinaries(Binary))
|
|
reportWarning("while parsing offloading files: " +
|
|
toString(std::move(Err)),
|
|
O.getFileName());
|
|
}
|
|
}
|
|
|
|
/// Print the contents of an offload binary file \p OB. This may contain
|
|
/// multiple binaries stored in the same buffer.
|
|
void llvm::dumpOffloadSections(const OffloadBinary &OB) {
|
|
// Print out all the binaries that are contained at this buffer. If we fail to
|
|
// parse a binary before reaching the end of the buffer emit a warning.
|
|
if (Error Err = visitAllBinaries(OB))
|
|
reportWarning("while parsing offloading files: " + toString(std::move(Err)),
|
|
OB.getFileName());
|
|
}
|