Skip to content

Commit

Permalink
[llvm-objdump][Offload] Use common offload extraction method
Browse files Browse the repository at this point in the history
A previous patch introduced a common function used to extract offloading
binaries from an image. Therefore we no longer need to duplicate the
functionality in the `llvm-objdump` implementation. Functionally, this
removes the old warning behaviour when given malformed input. This has
been changed to a hard error, which is effectively the same.

This required a slight tweak in the linker wrapper to filter out the
user passing shared objects directly.

Reviewed By: tra

Differential Revision: https://reviews.llvm.org/D136796
  • Loading branch information
jhuber6 committed Nov 3, 2022
1 parent 247dede commit 3384f05
Show file tree
Hide file tree
Showing 6 changed files with 38 additions and 76 deletions.
4 changes: 4 additions & 0 deletions clang/tools/clang-linker-wrapper/ClangLinkerWrapper.cpp
Expand Up @@ -1259,6 +1259,10 @@ Expected<SmallVector<OffloadFile>> getDeviceInput(const ArgList &Args) {
if (std::error_code EC = BufferOrErr.getError())
return createFileError(Filename, EC);

if (identify_magic((*BufferOrErr)->getBuffer()) ==
file_magic::elf_shared_object)
continue;

bool IsLazy =
identify_magic((*BufferOrErr)->getBuffer()) == file_magic::archive;
if (Error Err = extractOffloadBinaries(
Expand Down
8 changes: 7 additions & 1 deletion llvm/lib/Object/OffloadBinary.cpp
Expand Up @@ -41,6 +41,10 @@ Error extractOffloadFiles(MemoryBufferRef Contents,
std::unique_ptr<MemoryBuffer> Buffer =
MemoryBuffer::getMemBuffer(Contents.getBuffer().drop_front(Offset), "",
/*RequiresNullTerminator*/ false);
if (!isAddrAligned(Align(OffloadBinary::getAlignment()),
Buffer->getBufferStart()))
Buffer = MemoryBuffer::getMemBufferCopy(Buffer->getBuffer(),
Buffer->getBufferIdentifier());
auto BinaryOrErr = OffloadBinary::create(*Buffer);
if (!BinaryOrErr)
return BinaryOrErr.takeError();
Expand Down Expand Up @@ -254,7 +258,9 @@ Error object::extractOffloadBinaries(MemoryBufferRef Buffer,
switch (Type) {
case file_magic::bitcode:
return extractFromBitcode(Buffer, Binaries);
case file_magic::elf_relocatable: {
case file_magic::elf_relocatable:
case file_magic::elf_executable:
case file_magic::elf_shared_object: {
Expected<std::unique_ptr<ObjectFile>> ObjFile =
ObjectFile::createObjectFile(Buffer, Type);
if (!ObjFile)
Expand Down
Expand Up @@ -15,4 +15,4 @@ Sections:
ShOffset: 0x99999
AddressAlign: 0x0000000000000008

# CHECK: error: '[[FILENAME]]': The end of the file was unexpectedly encountered
# CHECK: error: '[[FILENAME]]': while extracting offloading files: The end of the file was unexpectedly encountered
Expand Up @@ -3,15 +3,21 @@
# RUN: llvm-objdump --offloading %t.bin | FileCheck %s --match-full-lines --strict-whitespace --implicit-check-not={{.}}

## Check that we can dump an offloading binary inside of an ELF section.
# RUN: yaml2obj %s -o %t.elf
# RUN: llvm-objcopy --update-section .llvm.offloading=%t.bin %t.elf
# RUN: llvm-objdump --offloading %t.elf | FileCheck %s --check-prefixes=CHECK,ELF --match-full-lines --strict-whitespace --implicit-check-not={{.}}
# RUN: yaml2obj %s -o %t -DTYPE=ET_EXEC
# RUN: yaml2obj %s -o %t.so -DTYPE=ET_DYN
# RUN: yaml2obj %s -o %t.o -DTYPE=ET_REL
# RUN: llvm-objcopy --update-section .llvm.offloading=%t.bin %t
# RUN: llvm-objcopy --update-section .llvm.offloading=%t.bin %t.so
# RUN: llvm-objcopy --update-section .llvm.offloading=%t.bin %t.o
# RUN: llvm-objdump --offloading %t | FileCheck %s --check-prefixes=CHECK,ELF --match-full-lines --strict-whitespace --implicit-check-not={{.}}
# RUN: llvm-objdump --offloading %t.so | FileCheck %s --check-prefixes=CHECK,ELF --match-full-lines --strict-whitespace --implicit-check-not={{.}}
# RUN: llvm-objdump --offloading %t.o | FileCheck %s --check-prefixes=CHECK,ELF --match-full-lines --strict-whitespace --implicit-check-not={{.}}

!ELF
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
Type: ET_EXEC
Type: [[TYPE]]
Sections:
- Name: .llvm.offloading
Type: SHT_LLVM_OFFLOADING
Expand Down
21 changes: 0 additions & 21 deletions llvm/test/tools/llvm-objdump/Offloading/warning.test

This file was deleted.

65 changes: 16 additions & 49 deletions llvm/tools/llvm-objdump/OffloadDump.cpp
Expand Up @@ -10,6 +10,7 @@
/// This file implements the offloading-specific dumper for llvm-objdump.
///
//===----------------------------------------------------------------------===//

#include "OffloadDump.h"
#include "llvm-objdump.h"
#include "llvm/Object/ELFObjectFile.h"
Expand Down Expand Up @@ -46,24 +47,6 @@ static void printBinary(const OffloadBinary &OB, uint64_t Index) {
<< 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) {
if (!O.isELF()) {
Expand All @@ -72,41 +55,25 @@ void llvm::dumpOffloadBinary(const ObjectFile &O) {
return;
}

for (ELFSectionRef Sec : O.sections()) {
if (Sec.getType() != ELF::SHT_LLVM_OFFLOADING)
continue;

Expected<StringRef> Contents = Sec.getContents();
if (!Contents)
reportError(Contents.takeError(), O.getFileName());

std::unique_ptr<MemoryBuffer> Buffer =
MemoryBuffer::getMemBuffer(*Contents, O.getFileName(), false);
if (!isAddrAligned(Align(OffloadBinary::getAlignment()),
Buffer->getBufferStart()))
Buffer = MemoryBuffer::getMemBufferCopy(Buffer->getBuffer(),
Buffer->getBufferIdentifier());
auto BinaryOrErr = OffloadBinary::create(*Buffer);
if (!BinaryOrErr)
reportError(O.getFileName(), "while extracting offloading files: " +
toString(BinaryOrErr.takeError()));
OffloadBinary &Binary = **BinaryOrErr;
SmallVector<OffloadFile> Binaries;
if (Error Err = extractOffloadBinaries(O.getMemoryBufferRef(), Binaries))
reportError(O.getFileName(), "while extracting offloading files: " +
toString(std::move(Err)));

// 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 out all the binaries that are contained in this buffer.
for (uint64_t I = 0, E = Binaries.size(); I != E; ++I)
printBinary(*Binaries[I].getBinary(), I);
}

/// 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());
SmallVector<OffloadFile> Binaries;
if (Error Err = extractOffloadBinaries(OB.getMemoryBufferRef(), Binaries))
reportError(OB.getFileName(), "while extracting offloading files: " +
toString(std::move(Err)));

// Print out all the binaries that are contained in this buffer.
for (uint64_t I = 0, E = Binaries.size(); I != E; ++I)
printBinary(*Binaries[I].getBinary(), I);
}

0 comments on commit 3384f05

Please sign in to comment.