[llvm] [llvm-objdump] Add preliminary support for decoding binary files (PR #115667)

Michael Clark via llvm-commits llvm-commits at lists.llvm.org
Tue Nov 12 13:59:09 PST 2024


https://github.com/michaeljclark updated https://github.com/llvm/llvm-project/pull/115667

>From 9022bc925f57d7d52c901fe65eea4d6beace48f2 Mon Sep 17 00:00:00 2001
From: Michael Clark <michaeljclark at mac.com>
Date: Sun, 10 Nov 2024 17:13:19 +1300
Subject: [PATCH] [llvm-objdump] Add preliminary support for decoding binary
 files

$ echo '49 0f c7 0f'  | xxd -r -p - > test.bin
$ llvm-objdump -d --binary -Mintel --triple x86_64 test.bin

test.bin:    file format binary

Disassembly of section :

0000000000000000 <.data>:
       0: 49 0f c7 0f         cmpxchg16b	xmmword ptr [r15]

Signed-off-by: Michael Clark <michaeljclark at mac.com>
---
 llvm/include/llvm/Object/Binary.h           |   7 +-
 llvm/include/llvm/Object/BinaryObjectFile.h | 130 +++++++++++
 llvm/include/llvm/Object/ObjectFile.h       |   4 +
 llvm/lib/Object/Binary.cpp                  |  16 +-
 llvm/lib/Object/BinaryObjectFile.cpp        | 242 ++++++++++++++++++++
 llvm/lib/Object/CMakeLists.txt              |   1 +
 llvm/tools/llvm-objdump/BinaryDump.cpp      |  42 ++++
 llvm/tools/llvm-objdump/BinaryDump.h        |  30 +++
 llvm/tools/llvm-objdump/CMakeLists.txt      |   1 +
 llvm/tools/llvm-objdump/ObjdumpOpts.td      |   4 +
 llvm/tools/llvm-objdump/llvm-objdump.cpp    |  14 +-
 llvm/tools/llvm-objdump/llvm-objdump.h      |   2 +
 12 files changed, 486 insertions(+), 7 deletions(-)
 create mode 100644 llvm/include/llvm/Object/BinaryObjectFile.h
 create mode 100644 llvm/lib/Object/BinaryObjectFile.cpp
 create mode 100644 llvm/tools/llvm-objdump/BinaryDump.cpp
 create mode 100644 llvm/tools/llvm-objdump/BinaryDump.h

diff --git a/llvm/include/llvm/Object/Binary.h b/llvm/include/llvm/Object/Binary.h
index ce870e25acafe0..112c3ef66c7363 100644
--- a/llvm/include/llvm/Object/Binary.h
+++ b/llvm/include/llvm/Object/Binary.h
@@ -71,6 +71,7 @@ class Binary {
 
     ID_GOFF,
     ID_Wasm,
+    ID_Binary,
 
     ID_EndObjects
   };
@@ -191,7 +192,8 @@ DEFINE_ISA_CONVERSION_FUNCTIONS(Binary, LLVMBinaryRef)
 /// @param Source The data to create the Binary from.
 Expected<std::unique_ptr<Binary>> createBinary(MemoryBufferRef Source,
                                                LLVMContext *Context = nullptr,
-                                               bool InitContent = true);
+                                               bool InitContent = true,
+                                               bool RawBinary = false);
 
 template <typename T> class OwningBinary {
   std::unique_ptr<T> Bin;
@@ -243,7 +245,8 @@ template <typename T> const T* OwningBinary<T>::getBinary() const {
 
 Expected<OwningBinary<Binary>> createBinary(StringRef Path,
                                             LLVMContext *Context = nullptr,
-                                            bool InitContent = true);
+                                            bool InitContent = true,
+                                            bool RawBinary = false);
 
 } // end namespace object
 
diff --git a/llvm/include/llvm/Object/BinaryObjectFile.h b/llvm/include/llvm/Object/BinaryObjectFile.h
new file mode 100644
index 00000000000000..622c7fa4fbc63c
--- /dev/null
+++ b/llvm/include/llvm/Object/BinaryObjectFile.h
@@ -0,0 +1,130 @@
+//===- BinaryObjectFile.h - Binary object file implementation ---*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// This file declares the BinaryObjectFile class.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_OBJECT_RAWOBJECTFILE_H
+#define LLVM_OBJECT_RAWOBJECTFILE_H
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Object/Binary.h"
+#include "llvm/Object/Error.h"
+#include "llvm/Object/ObjectFile.h"
+#include "llvm/Object/SymbolicFile.h"
+#include "llvm/Support/Casting.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/MemoryBufferRef.h"
+#include "llvm/Support/ScopedPrinter.h"
+#include "llvm/TargetParser/SubtargetFeature.h"
+#include "llvm/TargetParser/Triple.h"
+#include <cassert>
+#include <cstdint>
+
+namespace llvm {
+
+template <typename T> class SmallVectorImpl;
+
+namespace object {
+
+struct BinarySymbol {
+  uint32_t Flags = 0;
+  uint64_t Value = 0;
+  StringRef Name;
+};
+
+struct BinaryRelocation {
+  uint64_t Offset = 0;
+  uint64_t Symbol = 0;
+  uint64_t Type = 0;
+};
+
+struct BinarySection {
+  uint64_t Offset = 0;
+  uint64_t Index = 0;
+  uint64_t Address = 0;
+  uint64_t Size = 0;
+  StringRef Name;
+  std::vector<BinaryRelocation> Relocations;
+};
+
+class BinaryObjectFile : public ObjectFile {
+private:
+  std::vector<BinarySymbol> Symbols;
+  std::vector<BinarySection> Sections;
+
+public:
+  BinaryObjectFile(MemoryBufferRef Source);
+
+  bool is64Bit() const override;
+
+  basic_symbol_iterator symbol_begin() const override;
+  basic_symbol_iterator symbol_end() const override;
+  section_iterator section_begin() const override;
+  section_iterator section_end() const override;
+
+  const BinarySymbol &getBinarySymbol(const DataRefImpl &Symb) const;
+  const BinarySymbol &getBinarySymbol(const SymbolRef &Symb) const;
+
+  void moveSymbolNext(DataRefImpl &Symb) const override;
+  Expected<StringRef> getSymbolName(DataRefImpl Symb) const override;
+  Expected<uint32_t> getSymbolFlags(DataRefImpl Symb) const override;
+  Expected<uint64_t> getSymbolAddress(DataRefImpl Symb) const override;
+  uint64_t getSymbolValueImpl(DataRefImpl Symb) const override;
+  uint64_t getCommonSymbolSizeImpl(DataRefImpl Symb) const override;
+  Expected<SymbolRef::Type> getSymbolType(DataRefImpl Symb) const override;
+  Expected<section_iterator> getSymbolSection(DataRefImpl Symb) const override;
+
+  const BinarySection &getBinarySection(const DataRefImpl Ref) const;
+  const BinarySection &getBinarySection(const SectionRef &Section) const;
+
+  void moveSectionNext(DataRefImpl &Sec) const override;
+  Expected<StringRef> getSectionName(DataRefImpl Sec) const override;
+  uint64_t getSectionAddress(DataRefImpl Sec) const override;
+  uint64_t getSectionIndex(DataRefImpl Sec) const override;
+  uint64_t getSectionSize(DataRefImpl Sec) const override;
+  Expected<ArrayRef<uint8_t>>
+  getSectionContents(DataRefImpl Sec) const override;
+  uint64_t getSectionAlignment(DataRefImpl Sec) const override;
+  bool isSectionCompressed(DataRefImpl Sec) const override;
+  bool isSectionText(DataRefImpl Sec) const override;
+  bool isSectionData(DataRefImpl Sec) const override;
+  bool isSectionBSS(DataRefImpl Sec) const override;
+  bool isSectionVirtual(DataRefImpl Sec) const override;
+
+  relocation_iterator section_rel_begin(DataRefImpl Sec) const override;
+  relocation_iterator section_rel_end(DataRefImpl Sec) const override;
+
+  const BinaryRelocation &getBinaryRelocation(const RelocationRef &Ref) const;
+  const BinaryRelocation &getBinaryRelocation(DataRefImpl Ref) const;
+
+  // Overrides from RelocationRef.
+  void moveRelocationNext(DataRefImpl &Rel) const override;
+  uint64_t getRelocationOffset(DataRefImpl Rel) const override;
+  symbol_iterator getRelocationSymbol(DataRefImpl Rel) const override;
+  uint64_t getRelocationType(DataRefImpl Rel) const override;
+  void getRelocationTypeName(DataRefImpl Rel,
+                             SmallVectorImpl<char> &Result) const override;
+
+  uint8_t getBytesInAddress() const override;
+  StringRef getFileFormatName() const override;
+  Triple::ArchType getArch() const override;
+  Expected<SubtargetFeatures> getFeatures() const override;
+  std::optional<StringRef> tryGetCPUName() const override;
+  bool isRelocatableObject() const override;
+};
+
+} // end namespace object
+} // end namespace llvm
+
+#endif // LLVM_OBJECT_RAWOBJECTFILE_H
diff --git a/llvm/include/llvm/Object/ObjectFile.h b/llvm/include/llvm/Object/ObjectFile.h
index f49763e31a9c76..886cd9be2b018d 100644
--- a/llvm/include/llvm/Object/ObjectFile.h
+++ b/llvm/include/llvm/Object/ObjectFile.h
@@ -43,6 +43,7 @@ class SectionRef;
 class SymbolRef;
 class symbol_iterator;
 class WasmObjectFile;
+class BinaryObjectFile;
 
 using section_iterator = content_iterator<SectionRef>;
 
@@ -400,6 +401,9 @@ class ObjectFile : public SymbolicFile {
 
   static Expected<std::unique_ptr<WasmObjectFile>>
   createWasmObjectFile(MemoryBufferRef Object);
+
+  static Expected<std::unique_ptr<BinaryObjectFile>>
+  createBinaryObjectFile(MemoryBufferRef Object);
 };
 
 /// A filtered iterator for SectionRefs that skips sections based on some given
diff --git a/llvm/lib/Object/Binary.cpp b/llvm/lib/Object/Binary.cpp
index 2dfae8ab5d3c64..740e5169fc91ca 100644
--- a/llvm/lib/Object/Binary.cpp
+++ b/llvm/lib/Object/Binary.cpp
@@ -14,6 +14,7 @@
 #include "llvm/ADT/StringRef.h"
 #include "llvm/BinaryFormat/Magic.h"
 #include "llvm/Object/Archive.h"
+#include "llvm/Object/BinaryObjectFile.h"
 #include "llvm/Object/Error.h"
 #include "llvm/Object/MachOUniversal.h"
 #include "llvm/Object/Minidump.h"
@@ -44,9 +45,14 @@ MemoryBufferRef Binary::getMemoryBufferRef() const { return Data; }
 
 Expected<std::unique_ptr<Binary>> object::createBinary(MemoryBufferRef Buffer,
                                                        LLVMContext *Context,
-                                                       bool InitContent) {
+                                                       bool InitContent,
+                                                       bool RawBinary) {
   file_magic Type = identify_magic(Buffer.getBuffer());
 
+  if (RawBinary) {
+    return ObjectFile::createBinaryObjectFile(Buffer);
+  }
+
   switch (Type) {
   case file_magic::archive:
     return Archive::create(Buffer);
@@ -103,8 +109,10 @@ Expected<std::unique_ptr<Binary>> object::createBinary(MemoryBufferRef Buffer,
   llvm_unreachable("Unexpected Binary File Type");
 }
 
-Expected<OwningBinary<Binary>>
-object::createBinary(StringRef Path, LLVMContext *Context, bool InitContent) {
+Expected<OwningBinary<Binary>> object::createBinary(StringRef Path,
+                                                    LLVMContext *Context,
+                                                    bool InitContent,
+                                                    bool RawBinary) {
   ErrorOr<std::unique_ptr<MemoryBuffer>> FileOrErr =
       MemoryBuffer::getFileOrSTDIN(Path, /*IsText=*/false,
                                    /*RequiresNullTerminator=*/false);
@@ -113,7 +121,7 @@ object::createBinary(StringRef Path, LLVMContext *Context, bool InitContent) {
   std::unique_ptr<MemoryBuffer> &Buffer = FileOrErr.get();
 
   Expected<std::unique_ptr<Binary>> BinOrErr =
-      createBinary(Buffer->getMemBufferRef(), Context, InitContent);
+      createBinary(Buffer->getMemBufferRef(), Context, InitContent, RawBinary);
   if (!BinOrErr)
     return BinOrErr.takeError();
   std::unique_ptr<Binary> &Bin = BinOrErr.get();
diff --git a/llvm/lib/Object/BinaryObjectFile.cpp b/llvm/lib/Object/BinaryObjectFile.cpp
new file mode 100644
index 00000000000000..a3a3846fa822db
--- /dev/null
+++ b/llvm/lib/Object/BinaryObjectFile.cpp
@@ -0,0 +1,242 @@
+//===- BinaryObjectFile.cpp - Binary object file implementation -----------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+//
+// Part of the BinaryObjectFile class implementation.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Object/BinaryObjectFile.h"
+#include "llvm/MC/TargetRegistry.h"
+#include "llvm/Object/Error.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/TargetParser/SubtargetFeature.h"
+#include "llvm/TargetParser/Triple.h"
+#include <algorithm>
+#include <cstddef>
+#include <cstdint>
+#include <memory>
+#include <optional>
+#include <string>
+#include <utility>
+
+using namespace llvm;
+using namespace object;
+
+BinaryObjectFile::BinaryObjectFile(MemoryBufferRef Source)
+    : ObjectFile(ID_Binary, Source), Symbols(), Sections() {
+  Symbols.push_back(BinarySymbol{});
+  Symbols[0].Name = ".data";
+  Sections.push_back(BinarySection{});
+  Sections[0].Size = Source.getBufferSize();
+}
+
+Expected<std::unique_ptr<BinaryObjectFile>>
+ObjectFile::createBinaryObjectFile(MemoryBufferRef Obj) {
+  Error Err = Error::success();
+  auto ObjectFile = std::make_unique<BinaryObjectFile>(Obj);
+  return std::move(ObjectFile);
+}
+
+bool BinaryObjectFile::is64Bit() const { return true; }
+
+basic_symbol_iterator BinaryObjectFile::symbol_begin() const {
+  DataRefImpl Ref;
+  Ref.d.a = 1; // Arbitrary non-zero value so that Ref.p is non-null
+  Ref.d.b = 0; // Symbol index
+  return BasicSymbolRef(Ref, this);
+}
+
+basic_symbol_iterator BinaryObjectFile::symbol_end() const {
+  DataRefImpl Ref;
+  Ref.d.a = 1; // Arbitrary non-zero value so that Ref.p is non-null
+  Ref.d.b = Symbols.size(); // Symbol index
+  return BasicSymbolRef(Ref, this);
+}
+
+void BinaryObjectFile::moveSymbolNext(DataRefImpl &Symb) const { Symb.d.b++; }
+
+const BinarySymbol &
+BinaryObjectFile::getBinarySymbol(const DataRefImpl &Symb) const {
+  assert(Symb.d.b < Symbols.size());
+  return Symbols[Symb.d.b];
+}
+
+const BinarySymbol &
+BinaryObjectFile::getBinarySymbol(const SymbolRef &Symb) const {
+  return getBinarySymbol(Symb.getRawDataRefImpl());
+}
+
+const BinarySection &
+BinaryObjectFile::getBinarySection(const DataRefImpl Ref) const {
+  assert(Ref.d.a < Sections.size());
+  return Sections[Ref.d.a];
+}
+
+const BinarySection &
+BinaryObjectFile::getBinarySection(const SectionRef &Section) const {
+  return getBinarySection(Section.getRawDataRefImpl());
+}
+
+const BinaryRelocation &
+BinaryObjectFile::getBinaryRelocation(const RelocationRef &Ref) const {
+  return getBinaryRelocation(Ref.getRawDataRefImpl());
+}
+
+const BinaryRelocation &
+BinaryObjectFile::getBinaryRelocation(DataRefImpl Ref) const {
+  assert(Ref.d.a < Sections.size());
+  const BinarySection &Sec = Sections[Ref.d.a];
+  assert(Ref.d.b < Sec.Relocations.size());
+  return Sec.Relocations[Ref.d.b];
+}
+
+Expected<StringRef> BinaryObjectFile::getSymbolName(DataRefImpl Symb) const {
+  return getBinarySymbol(Symb).Name;
+}
+
+Expected<uint32_t> BinaryObjectFile::getSymbolFlags(DataRefImpl Symb) const {
+  return getBinarySymbol(Symb).Flags;
+}
+
+uint64_t BinaryObjectFile::getSymbolValueImpl(DataRefImpl Symb) const {
+  return getBinarySymbol(Symb).Value;
+}
+
+uint64_t BinaryObjectFile::getCommonSymbolSizeImpl(DataRefImpl Symb) const {
+  llvm_unreachable("not yet implemented");
+  return 0;
+}
+
+Expected<SymbolRef::Type>
+BinaryObjectFile::getSymbolType(DataRefImpl Symb) const {
+  return SymbolRef::ST_Other;
+}
+
+Expected<section_iterator>
+BinaryObjectFile::getSymbolSection(DataRefImpl Symb) const {
+  DataRefImpl Ref;
+  Ref.d.a = 0;
+  return section_iterator(SectionRef(Ref, this));
+}
+
+Expected<uint64_t> BinaryObjectFile::getSymbolAddress(DataRefImpl Sym) const {
+  return getSymbolValue(Sym);
+}
+
+section_iterator BinaryObjectFile::section_begin() const {
+  DataRefImpl Ref;
+  Ref.d.a = 0;
+  return section_iterator(SectionRef(Ref, this));
+}
+
+section_iterator BinaryObjectFile::section_end() const {
+  DataRefImpl Ref;
+  Ref.d.a = Sections.size();
+  return section_iterator(SectionRef(Ref, this));
+}
+void BinaryObjectFile::moveSectionNext(DataRefImpl &Sec) const { Sec.d.a++; }
+
+Expected<StringRef> BinaryObjectFile::getSectionName(DataRefImpl Ref) const {
+  return getBinarySection(Ref).Name;
+}
+
+uint64_t BinaryObjectFile::getSectionAddress(DataRefImpl Ref) const {
+  return getBinarySection(Ref).Address;
+}
+uint64_t BinaryObjectFile::getSectionIndex(DataRefImpl Ref) const {
+  return getBinarySection(Ref).Index;
+}
+uint64_t BinaryObjectFile::getSectionSize(DataRefImpl Ref) const {
+  return getBinarySection(Ref).Size;
+}
+
+Expected<ArrayRef<uint8_t>>
+BinaryObjectFile::getSectionContents(DataRefImpl Sec) const {
+  return ArrayRef<uint8_t>((const uint8_t *)Data.getBuffer().data(),
+                           Data.getBufferSize());
+}
+
+uint64_t BinaryObjectFile::getSectionAlignment(DataRefImpl Sec) const {
+  return 1;
+}
+
+bool BinaryObjectFile::isSectionCompressed(DataRefImpl Sec) const {
+  return false;
+}
+bool BinaryObjectFile::isSectionText(DataRefImpl Sec) const { return true; }
+bool BinaryObjectFile::isSectionData(DataRefImpl Sec) const { return false; }
+bool BinaryObjectFile::isSectionBSS(DataRefImpl Sec) const { return false; }
+bool BinaryObjectFile::isSectionVirtual(DataRefImpl Sec) const { return false; }
+
+relocation_iterator BinaryObjectFile::section_rel_begin(DataRefImpl Ref) const {
+  DataRefImpl RelocRef;
+  RelocRef.d.a = Ref.d.a;
+  RelocRef.d.b = 0;
+  return relocation_iterator(RelocationRef(RelocRef, this));
+}
+
+relocation_iterator BinaryObjectFile::section_rel_end(DataRefImpl Ref) const {
+  const BinarySection &Sec = getBinarySection(Ref);
+  DataRefImpl RelocRef;
+  RelocRef.d.a = Ref.d.a;
+  RelocRef.d.b = Sec.Relocations.size();
+  return relocation_iterator(RelocationRef(RelocRef, this));
+}
+
+void BinaryObjectFile::moveRelocationNext(DataRefImpl &Rel) const { Rel.d.b++; }
+
+uint64_t BinaryObjectFile::getRelocationOffset(DataRefImpl Ref) const {
+  const BinaryRelocation &Rel = getBinaryRelocation(Ref);
+  return Rel.Offset;
+}
+
+symbol_iterator BinaryObjectFile::getRelocationSymbol(DataRefImpl Ref) const {
+  const BinaryRelocation &Rel = getBinaryRelocation(Ref);
+  DataRefImpl Sym;
+  Sym.d.a = 1;
+  Sym.d.b = Rel.Symbol;
+  return symbol_iterator(SymbolRef(Sym, this));
+}
+
+uint64_t BinaryObjectFile::getRelocationType(DataRefImpl Ref) const {
+  const BinaryRelocation &Rel = getBinaryRelocation(Ref);
+  return Rel.Type;
+}
+
+void BinaryObjectFile::getRelocationTypeName(
+    DataRefImpl Ref, SmallVectorImpl<char> &Result) const {
+  const BinaryRelocation &Rel = getBinaryRelocation(Ref);
+  StringRef Res;
+  switch (Rel.Type) {
+  case 0:
+  default:
+    Res = "unknown";
+    break;
+  }
+  Result.append(Res.begin(), Res.end());
+}
+
+uint8_t BinaryObjectFile::getBytesInAddress() const {
+  return is64Bit() ? 8 : 4;
+}
+
+StringRef BinaryObjectFile::getFileFormatName() const { return "binary"; }
+
+Triple::ArchType BinaryObjectFile::getArch() const {
+  return Triple::UnknownArch;
+}
+
+Expected<SubtargetFeatures> BinaryObjectFile::getFeatures() const {
+  return SubtargetFeatures();
+}
+
+std::optional<StringRef> BinaryObjectFile::tryGetCPUName() const {
+  return std::nullopt;
+}
+
+bool BinaryObjectFile::isRelocatableObject() const { return false; }
diff --git a/llvm/lib/Object/CMakeLists.txt b/llvm/lib/Object/CMakeLists.txt
index bfb420e57a7f49..0b1a3d32b0ef0d 100644
--- a/llvm/lib/Object/CMakeLists.txt
+++ b/llvm/lib/Object/CMakeLists.txt
@@ -33,6 +33,7 @@ add_llvm_component_library(LLVMObject
   WindowsMachineFlag.cpp
   WindowsResource.cpp
   XCOFFObjectFile.cpp
+  BinaryObjectFile.cpp
 
   ADDITIONAL_HEADER_DIRS
   ${LLVM_MAIN_INCLUDE_DIR}/llvm/Object
diff --git a/llvm/tools/llvm-objdump/BinaryDump.cpp b/llvm/tools/llvm-objdump/BinaryDump.cpp
new file mode 100644
index 00000000000000..6c2c691ef1d74e
--- /dev/null
+++ b/llvm/tools/llvm-objdump/BinaryDump.cpp
@@ -0,0 +1,42 @@
+//===-- BinaryDump.cpp - raw-binary 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 raw binary dumper for llvm-objdump.
+///
+//===----------------------------------------------------------------------===//
+
+#include "BinaryDump.h"
+
+#include "llvm-objdump.h"
+#include "llvm/Object/BinaryObjectFile.h"
+#include "llvm/Object/ObjectFile.h"
+#include "llvm/Support/Error.h"
+
+using namespace llvm;
+using namespace llvm::object;
+
+namespace {
+class BinaryDumper : public objdump::Dumper {
+  const BinaryObjectFile &Obj;
+
+public:
+  BinaryDumper(const BinaryObjectFile &O) : Dumper(O), Obj(O) {}
+};
+} // namespace
+
+std::unique_ptr<objdump::Dumper>
+objdump::createBinaryDumper(const BinaryObjectFile &Obj) {
+  return std::make_unique<BinaryDumper>(Obj);
+}
+
+Error objdump::getBinaryRelocationValueString(const BinaryObjectFile *Obj,
+                                              const RelocationRef &RelRef,
+                                              SmallVectorImpl<char> &Result) {
+  return Error::success();
+}
diff --git a/llvm/tools/llvm-objdump/BinaryDump.h b/llvm/tools/llvm-objdump/BinaryDump.h
new file mode 100644
index 00000000000000..f8c76e11b20088
--- /dev/null
+++ b/llvm/tools/llvm-objdump/BinaryDump.h
@@ -0,0 +1,30 @@
+//===-- BinaryDump.h - raw-binary 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
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TOOLS_LLVM_OBJDUMP_BINARYDUMP_H
+#define LLVM_TOOLS_LLVM_OBJDUMP_BINARYDUMP_H
+
+#include "llvm/ADT/SmallVector.h"
+
+namespace llvm {
+class Error;
+namespace object {
+class BinaryObjectFile;
+class RelocationRef;
+} // namespace object
+
+namespace objdump {
+
+Error getBinaryRelocationValueString(const object::BinaryObjectFile *Obj,
+                                     const object::RelocationRef &RelRef,
+                                     llvm::SmallVectorImpl<char> &Result);
+
+} // namespace objdump
+} // namespace llvm
+
+#endif
diff --git a/llvm/tools/llvm-objdump/CMakeLists.txt b/llvm/tools/llvm-objdump/CMakeLists.txt
index 0306736388979b..9034b2a0bf5b63 100644
--- a/llvm/tools/llvm-objdump/CMakeLists.txt
+++ b/llvm/tools/llvm-objdump/CMakeLists.txt
@@ -30,6 +30,7 @@ add_llvm_tool(llvm-objdump
   ELFDump.cpp
   MachODump.cpp
   OffloadDump.cpp
+  BinaryDump.cpp
   WasmDump.cpp
   XCOFFDump.cpp
   DEPENDS
diff --git a/llvm/tools/llvm-objdump/ObjdumpOpts.td b/llvm/tools/llvm-objdump/ObjdumpOpts.td
index c3764c6e97534a..63d74a6f1e3d47 100644
--- a/llvm/tools/llvm-objdump/ObjdumpOpts.td
+++ b/llvm/tools/llvm-objdump/ObjdumpOpts.td
@@ -38,6 +38,10 @@ def arch_name_EQ : Joined<["--"], "arch-name=">,
 def archive_headers : Flag<["--"], "archive-headers">,
   HelpText<"Display archive header information">;
 
+def binary : Flag<["--"], "binary">,
+  HelpText<"Treat the file as binary, to be combined with --triple=">;
+def : Flag<["-"], "b">, Alias<binary>, HelpText<"Alias for --binary">;
+
 defm build_id :
   Eq<"build-id", "Build ID to look up. Once found, added as an input file">,
   MetaVarName<"<hex>">;
diff --git a/llvm/tools/llvm-objdump/llvm-objdump.cpp b/llvm/tools/llvm-objdump/llvm-objdump.cpp
index b69d14b4e7609a..037f9d3883b478 100644
--- a/llvm/tools/llvm-objdump/llvm-objdump.cpp
+++ b/llvm/tools/llvm-objdump/llvm-objdump.cpp
@@ -16,6 +16,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm-objdump.h"
+#include "BinaryDump.h"
 #include "COFFDump.h"
 #include "ELFDump.h"
 #include "MachODump.h"
@@ -51,6 +52,7 @@
 #include "llvm/MC/MCTargetOptions.h"
 #include "llvm/MC/TargetRegistry.h"
 #include "llvm/Object/Archive.h"
+#include "llvm/Object/BinaryObjectFile.h"
 #include "llvm/Object/BuildID.h"
 #include "llvm/Object/COFF.h"
 #include "llvm/Object/COFFImportFile.h"
@@ -300,6 +302,7 @@ enum class ColorOutput {
 
 static uint64_t AdjustVMA;
 static bool AllHeaders;
+static bool BinaryFile;
 static std::string ArchName;
 bool objdump::ArchiveHeaders;
 bool objdump::Demangle;
@@ -386,6 +389,8 @@ static Expected<std::unique_ptr<Dumper>> createDumper(const ObjectFile &Obj) {
     return createWasmDumper(*O);
   if (const auto *O = dyn_cast<XCOFFObjectFile>(&Obj))
     return createXCOFFDumper(*O);
+  if (const auto *O = dyn_cast<BinaryObjectFile>(&Obj))
+    return createBinaryDumper(*O);
 
   return createStringError(errc::invalid_argument,
                            "unsupported object file format");
@@ -553,6 +558,8 @@ static Error getRelocationValueString(const RelocationRef &Rel,
   if (auto *XCOFF = dyn_cast<XCOFFObjectFile>(Obj))
     return getXCOFFRelocationValueString(*XCOFF, Rel, SymbolDescription,
                                          Result);
+  if (auto *Binary = dyn_cast<BinaryObjectFile>(Obj))
+    return getBinaryRelocationValueString(Binary, Rel, Result);
   llvm_unreachable("unknown object file format");
 }
 
@@ -3392,7 +3399,8 @@ static void dumpInput(StringRef file) {
   }
 
   // Attempt to open the binary.
-  OwningBinary<Binary> OBinary = unwrapOrError(createBinary(file), file);
+  OwningBinary<Binary> OBinary =
+      unwrapOrError(createBinary(file, nullptr, true, BinaryFile), file);
   Binary &Binary = *OBinary.getBinary();
 
   if (Archive *A = dyn_cast<Archive>(&Binary))
@@ -3577,6 +3585,10 @@ static void parseObjdumpOptions(const llvm::opt::InputArgList &InputArgs) {
 
   parseMachOOptions(InputArgs);
 
+  if (InputArgs.getLastArg(OBJDUMP_binary)) {
+    BinaryFile = true;
+  }
+
   // Parse -M (--disassembler-options) and deprecated
   // --x86-asm-syntax={att,intel}.
   //
diff --git a/llvm/tools/llvm-objdump/llvm-objdump.h b/llvm/tools/llvm-objdump/llvm-objdump.h
index 7778cf6c2784eb..38c3c10c9b0c22 100644
--- a/llvm/tools/llvm-objdump/llvm-objdump.h
+++ b/llvm/tools/llvm-objdump/llvm-objdump.h
@@ -38,6 +38,7 @@ class ELFObjectFileBase;
 class MachOObjectFile;
 class WasmObjectFile;
 class XCOFFObjectFile;
+class BinaryObjectFile;
 } // namespace object
 
 namespace objdump {
@@ -104,6 +105,7 @@ std::unique_ptr<Dumper> createELFDumper(const object::ELFObjectFileBase &Obj);
 std::unique_ptr<Dumper> createMachODumper(const object::MachOObjectFile &Obj);
 std::unique_ptr<Dumper> createWasmDumper(const object::WasmObjectFile &Obj);
 std::unique_ptr<Dumper> createXCOFFDumper(const object::XCOFFObjectFile &Obj);
+std::unique_ptr<Dumper> createBinaryDumper(const object::BinaryObjectFile &Obj);
 
 // Various helper functions.
 



More information about the llvm-commits mailing list