[llvm] Add Offoading to llvm-readobj and llvm-objcopy (PR #141978)

David Salinas via llvm-commits llvm-commits at lists.llvm.org
Thu May 29 09:47:22 PDT 2025


https://github.com/david-salinas created https://github.com/llvm/llvm-project/pull/141978

  Utilize new extensions to LLVM Offloading API to
  handle offloading fatbin Bundles.

Change-Id: Ib24a722be16f499ffb56bf46e4b82e90d8775040

>From cfe5c3725e709f8f80115c6998ad1b324436aca9 Mon Sep 17 00:00:00 2001
From: David <dsalinas at amd.com>
Date: Wed, 28 Aug 2024 04:16:30 +0100
Subject: [PATCH] Add Offoading to llvm-readobj and llvm-objcopy

  Utilize new extensions to LLVM Offloading API to
  handle offloading fatbin Bundles.

Change-Id: Ib24a722be16f499ffb56bf46e4b82e90d8775040
---
 llvm/docs/CommandGuide/llvm-objcopy.rst       |   6 +
 llvm/docs/CommandGuide/llvm-readobj.rst       |   4 +
 llvm/include/llvm/ObjCopy/CommonConfig.h      |   2 +
 llvm/include/llvm/Object/OffloadBundle.h      |   2 +-
 llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp           |  21 +++
 .../llvm-objcopy/ELF/dump-offload-bundle.test |  60 +++++++
 .../ELF/AMDGPU/dump-offload-bundle.test       |  41 +++++
 llvm/tools/llvm-objcopy/ObjcopyOptions.cpp    | 131 +++++++++------
 llvm/tools/llvm-objcopy/ObjcopyOptions.h      |   5 +
 llvm/tools/llvm-objcopy/ObjcopyOpts.td        |   3 +
 llvm/tools/llvm-objcopy/llvm-objcopy.cpp      | 151 +++++++++---------
 llvm/tools/llvm-readobj/ObjDumper.cpp         |  26 +++
 llvm/tools/llvm-readobj/ObjDumper.h           |   2 +
 llvm/tools/llvm-readobj/Opts.td               |   3 +
 llvm/tools/llvm-readobj/llvm-readobj.cpp      |   5 +
 15 files changed, 333 insertions(+), 129 deletions(-)
 create mode 100644 llvm/test/tools/llvm-objcopy/ELF/dump-offload-bundle.test
 create mode 100644 llvm/test/tools/llvm-readobj/ELF/AMDGPU/dump-offload-bundle.test

diff --git a/llvm/docs/CommandGuide/llvm-objcopy.rst b/llvm/docs/CommandGuide/llvm-objcopy.rst
index 35d907fbe44d4..1c703f631ba0d 100644
--- a/llvm/docs/CommandGuide/llvm-objcopy.rst
+++ b/llvm/docs/CommandGuide/llvm-objcopy.rst
@@ -74,6 +74,12 @@ multiple file formats.
  For MachO objects, ``<section>`` must be formatted as
  ``<segment name>,<section name>``.
 
+.. option:: --dump-offload-bundle=<URI>
+
+ Dump the HIP Offload Bundle entry specified by the URI syntax given, into a 
+ code object file.
+
+
 .. option:: --enable-deterministic-archives, -D
 
  Enable deterministic mode when copying archives, i.e. use 0 for archive member
diff --git a/llvm/docs/CommandGuide/llvm-readobj.rst b/llvm/docs/CommandGuide/llvm-readobj.rst
index 8bd29eafbbfcf..faaddb4699f7d 100644
--- a/llvm/docs/CommandGuide/llvm-readobj.rst
+++ b/llvm/docs/CommandGuide/llvm-readobj.rst
@@ -104,6 +104,10 @@ file formats.
  Do not demangle symbol names in the output. This option is only for ELF and
  XCOFF file formats. The option is enabled by default.
 
+.. option:: --offloading
+
+ Display list of HIP Offload bundles using URI syntax.
+
 .. option:: --relocations, --relocs, -r
 
  Display the relocation entries in the file.
diff --git a/llvm/include/llvm/ObjCopy/CommonConfig.h b/llvm/include/llvm/ObjCopy/CommonConfig.h
index aea9cd6f9a9c7..61acf26c1fd9c 100644
--- a/llvm/include/llvm/ObjCopy/CommonConfig.h
+++ b/llvm/include/llvm/ObjCopy/CommonConfig.h
@@ -276,6 +276,8 @@ struct CommonConfig {
   bool StripUnneeded = false;
   bool Weaken = false;
   bool DecompressDebugSections = false;
+  bool DumpOffloadBundle = false;
+  bool NeedPositional = true;
 
   DebugCompressionType CompressionType = DebugCompressionType::None;
 
diff --git a/llvm/include/llvm/Object/OffloadBundle.h b/llvm/include/llvm/Object/OffloadBundle.h
index 207b4b9d713c5..ca25d4f9a42a7 100644
--- a/llvm/include/llvm/Object/OffloadBundle.h
+++ b/llvm/include/llvm/Object/OffloadBundle.h
@@ -160,7 +160,7 @@ struct OffloadBundleURI {
     OffsetStr.getAsInteger(10, O);
     Str = Str.drop_front(OffsetStr.size());
 
-    if (Str.consume_front("&size="))
+    if (!Str.consume_front("&size="))
       return createStringError(object_error::parse_failed,
                                "Reading 'size' in URI");
 
diff --git a/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp b/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
index f810bbf639300..bcd52e728f696 100644
--- a/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
+++ b/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
@@ -210,6 +210,27 @@ static Error dumpSectionToFile(StringRef SecName, StringRef Filename,
                          "section '%s' not found", SecName.str().c_str());
 }
 
+static Error dumpRawDataURIToFile(StringRef Filename, int64_t Offset,
+                                  int64_t Size, ObjectFile &Obj) {
+  StringRef OutputFileName(Obj.getFileName().str() + "-offset" +
+                           itostr(Offset) + "-size" + itostr(Size) + ".co");
+
+  Expected<std::unique_ptr<FileOutputBuffer>> BufferOrErr =
+      FileOutputBuffer::create(OutputFileName, Size);
+
+  if (!BufferOrErr)
+    return BufferOrErr.takeError();
+
+  MemoryBufferRef Input = Obj.getMemoryBufferRef();
+  std::unique_ptr<FileOutputBuffer> Buf = std::move(*BufferOrErr);
+  std::copy(Input.getBufferStart(), Input.getBufferStart() + Size,
+            Buf->getBufferStart());
+  if (Error E = Buf->commit())
+    return E;
+
+  return Error::success();
+}
+
 Error Object::compressOrDecompressSections(const CommonConfig &Config) {
   // Build a list of sections we are going to replace.
   // We can't call `addSection` while iterating over sections,
diff --git a/llvm/test/tools/llvm-objcopy/ELF/dump-offload-bundle.test b/llvm/test/tools/llvm-objcopy/ELF/dump-offload-bundle.test
new file mode 100644
index 0000000000000..1d45632e18af1
--- /dev/null
+++ b/llvm/test/tools/llvm-objcopy/ELF/dump-offload-bundle.test
@@ -0,0 +1,60 @@
+## Test that --offloading with a fatbin works correctly
+# REQUIRES: target={{x86_64-.*-linux.*}}
+# REQUIRES: amdgpu-registered-target
+
+# RUN: yaml2obj %s -o %t.elf
+# RUN: llvm-objcopy --dump-offload-bundle=file://%t.elf#offset=8192\&size=4048.co
+# RUN: llvm-objdump -d %t.elf-offset8192-size4048.co | FileCheck %s
+
+# CHECK:        s_load_dword s7, s[4:5], 0x24                              // 000000001900: C00201C2 00000024
+# CHECK-NEXT:        s_load_dwordx4 s[0:3], s[4:5], 0x0                         // 000000001908: C00A0002 00000000
+# CHECK-NEXT:        v_mov_b32_e32 v1, 0                                        // 000000001910: 7E020280
+# CHECK-NEXT:        s_waitcnt lgkmcnt(0)                                       // 000000001914: BF8CC07F
+# CHECK-NEXT:        s_and_b32 s4, s7, 0xffff                                   // 000000001918: 8604FF07 0000FFFF
+# CHECK-NEXT:        s_mul_i32 s6, s6, s4                                       // 000000001920: 92060406
+# CHECK-NEXT:        v_add_u32_e32 v0, s6, v0                                   // 000000001924: 68000006
+# CHECK-NEXT:        v_lshlrev_b64 v[0:1], 2, v[0:1]                            // 000000001928: D28F0000 00020082
+# CHECK-NEXT:        v_mov_b32_e32 v3, s3                                       // 000000001930: 7E060203
+# CHECK-NEXT:        v_add_co_u32_e32 v2, vcc, s2, v0                           // 000000001934: 32040002
+# CHECK-NEXT:        v_addc_co_u32_e32 v3, vcc, v3, v1, vcc                     // 000000001938: 38060303
+# CHECK-NEXT:        global_load_dword v2, v[2:3], off                          // 00000000193C: DC508000 027F0002
+# CHECK-NEXT:        v_mov_b32_e32 v3, s1                                       // 000000001944: 7E060201
+# CHECK-NEXT:        v_add_co_u32_e32 v0, vcc, s0, v0                           // 000000001948: 32000000
+# CHECK-NEXT:        v_addc_co_u32_e32 v1, vcc, v3, v1, vcc                     // 00000000194C: 38020303
+# CHECK-NEXT:        global_load_dword v3, v[0:1], off                          // 000000001950: DC508000 037F0000
+# CHECK-NEXT:        s_waitcnt vmcnt(0)                                         // 000000001958: BF8C0F70
+# CHECK-NEXT:        v_add_u32_e32 v2, v3, v2                                   // 00000000195C: 68040503
+# CHECK-NEXT:        global_store_dword v[0:1], v2, off                         // 000000001960: DC708000 007F0200
+# CHECK-NEXT:        s_endpgm                                                   // 000000001968: BF810000
+
+--- !ELF
+FileHeader:
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  Type:            ET_EXEC
+  Machine:         EM_X86_64
+  Entry:           0x2041B0
+ProgramHeaders:
+  - Type:            PT_PHDR
+    Flags:           [ PF_R ]
+    VAddr:           0x200040
+    Align:           0x8
+    Offset:          0x40
+  - Type:            PT_GNU_STACK
+    Flags:           [ PF_W, PF_R ]
+    Align:           0x0
+    Offset:          0x0
+Sections:
+  - Name:            .hip_fatbin
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC ]
+    Address:         0x201000
+    AddressAlign:    0x1000
+    Content:         5F5F434C414E475F4F46464C4F41445F42554E444C455F5F0200000000000000001000000000000000000000000000001B00000000000000686F73742D7838365F36342D756E6B6E6F776E2D6C696E75782D2D0010000000000000D00F0000000000001F0000000000000068697076342D616D6467636E2D616D642D616D646873612D2D676678393038000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007F454C460201014003000000000000000300E0000100000000000000000000004000000000000000100C0000000000003005000040003800090040000F000D000600000004000000400000000000000040000000000000004000000000000000F801000000000000F80100000000000008000000000000000100000004000000000000000000000000000000000000000000000000000000C008000000000000C008000000000000001000000000000001000000050000000009000000000000001900000000000000190000000000006C000000000000006C00000000000000001000000000000001000000060000007009000000000000702900000000000070290000000000007000000000000000900600000000000000100000000000000100000006000000E009000000000000E039000000000000E039000000000000000000000000000001000000000000000010000000000000020000000600000070090000000000007029000000000000702900000000000070000000000000007000000000000000080000000000000052E574640400000070090000000000007029000000000000702900000000000070000000000000009006000000000000010000000000000051E57464060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000004000000380200000000000038020000000000003802000000000000340500000000000034050000000000000400000000000000070000001D05000020000000414D44475055000083AE616D646873612E6B65726E656C7391DE0012AB2E616770725F636F756E7400A52E61726773DC001085AE2E616464726573735F7370616365A6676C6F62616CA52E6E616D65AA415F642E636F65726365A72E6F666673657400A52E73697A6508AB2E76616C75655F6B696E64AD676C6F62616C5F62756666657285AE2E616464726573735F7370616365A6676C6F62616CA52E6E616D65AA425F642E636F65726365A72E6F666673657408A52E73697A6508AB2E76616C75655F6B696E64AD676C6F62616C5F62756666657284A52E6E616D65A14EA72E6F666673657410A52E73697A6508AB2E76616C75655F6B696E64A862795F76616C756583A72E6F666673657418A52E73697A6504AB2E76616C75655F6B696E64B468696464656E5F626C6F636B5F636F756E745F7883A72E6F66667365741CA52E73697A6504AB2E76616C75655F6B696E64B468696464656E5F626C6F636B5F636F756E745F7983A72E6F666673657420A52E73697A6504AB2E76616C75655F6B696E64B468696464656E5F626C6F636B5F636F756E745F7A83A72E6F666673657424A52E73697A6502AB2E76616C75655F6B696E64B368696464656E5F67726F75705F73697A655F7883A72E6F666673657426A52E73697A6502AB2E76616C75655F6B696E64B368696464656E5F67726F75705F73697A655F7983A72E6F666673657428A52E73697A6502AB2E76616C75655F6B696E64B368696464656E5F67726F75705F73697A655F7A83A72E6F66667365742AA52E73697A6502AB2E76616C75655F6B696E64B268696464656E5F72656D61696E6465725F7883A72E6F66667365742CA52E73697A6502AB2E76616C75655F6B696E64B268696464656E5F72656D61696E6465725F7983A72E6F66667365742EA52E73697A6502AB2E76616C75655F6B696E64B268696464656E5F72656D61696E6465725F7A83A72E6F666673657440A52E73697A6508AB2E76616C75655F6B696E64B668696464656E5F676C6F62616C5F6F66667365745F7883A72E6F666673657448A52E73697A6508AB2E76616C75655F6B696E64B668696464656E5F676C6F62616C5F6F66667365745F7983A72E6F666673657450A52E73697A6508AB2E76616C75655F6B696E64B668696464656E5F676C6F62616C5F6F66667365745F7A83A72E6F666673657458A52E73697A6502AB2E76616C75655F6B696E64B068696464656E5F677269645F64696D73B92E67726F75705F7365676D656E745F66697865645F73697A6500B62E6B65726E6172675F7365676D656E745F616C69676E08B52E6B65726E6172675F7365676D656E745F73697A65CD0118A92E6C616E6775616765A84F70656E434C2043B12E6C616E67756167655F76657273696F6E920200B82E6D61785F666C61745F776F726B67726F75705F73697A65CD0400A52E6E616D65B25F5A3973696D706C65416464506A504B6A6DBB2E707269766174655F7365676D656E745F66697865645F73697A6500AB2E736770725F636F756E740CB12E736770725F7370696C6C5F636F756E7400A72E73796D626F6CB55F5A3973696D706C65416464506A504B6A6D2E6B64B82E756E69666F726D5F776F726B5F67726F75705F73697A6501B32E757365735F64796E616D69635F737461636BC2AB2E766770725F636F756E7404B12E766770725F7370696C6C5F636F756E7400AF2E7761766566726F6E745F73697A6540AD616D646873612E746172676574B9616D6467636E2D616D642D616D646873612D2D676678393038AE616D646873612E76657273696F6E92010200000000000000000000000000000000000000000000000000000000000000010000001203070000190000000000006C000000000000001400000011030600800800000000000040000000000000002A00000011000A00E03900000000000001000000000000000100000001000000010000001A000000000008400000D20001000000360A4A7A5238A4D3F113F4DD04000000040000000200000001000000000000000300000000000000000000000000000000000000005F5A3973696D706C65416464506A504B6A6D005F5A3973696D706C65416464506A504B6A6D2E6B64005F5F6869705F637569645F623730363264386333326134613933330000000000000000000000000000000000000000000000000000000000000000000000180100000000000080100000000000000000000000000000000000000000000000000000000000004000AF008C000000090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C20102C02400000002000AC0000000008002027E7FC08CBF07FF0486FFFF0000060406920600006800008FD2820002000302067E0200043203030638008050DC02007F020102067E0000003203030238008050DC00007F03700F8CBF03050468008070DC00027F00000081BF00000000060000000000000070070000000000000B000000000000001800000000000000050000000000000020080000000000000A000000000000004600000000000000F5FEFF6F00000000D0070000000000000400000000000000F807000000000000000000000000000000000000000000004C696E6B65723A20414D44204C4C442031392E302E3000414D4420636C616E672076657273696F6E2031392E302E306769742028202032343231322063393630313665636534313337356462646438663037356266333762643666633333323230376233290000414D4420636C616E672076657273696F6E2031382E302E3067697420287373683A2F2F6765727269746769742F6C696768746E696E672F65632F6C6C766D2D70726F6A65637420616D642D6D61696E6C696E652D6F70656E20323431373620663935303039613166393032313232343865313036333964653837653635636163616338643961372900000000000000000000000000000000000000000000000000460000000002080070290000000000000000000000000000010000001203070000190000000000006C000000000000001400000011030600800800000000000040000000000000002A00000011000A00E0390000000000000100000000000000002E6E6F7465002E64796E73796D002E676E752E68617368002E68617368002E64796E737472002E726F64617461002E74657874002E64796E616D6963002E72656C726F5F70616464696E67002E627373002E636F6D6D656E74002E73796D746162002E7368737472746162002E73747274616200005F5A3973696D706C65416464506A504B6A6D005F5A3973696D706C65416464506A504B6A6D2E6B64005F5F6869705F637569645F62373036326438633332613461393333005F44594E414D494300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000070000000200000000000000380200000000000038020000000000003405000000000000000000000000000004000000000000000000000000000000070000000B00000002000000000000007007000000000000700700000000000060000000000000000500000001000000080000000000000018000000000000000F000000F6FFFF6F0200000000000000D007000000000000D007000000000000280000000000000002000000000000000800000000000000000000000000000019000000050000000200000000000000F807000000000000F80700000000000028000000000000000200000000000000040000000000000004000000000000001F000000030000000200000000000000200800000000000020080000000000004600000000000000000000000000000001000000000000000000000000000000270000000100000002000000000000008008000000000000800800000000000040000000000000000000000000000000400000000000000000000000000000002F000000010000000600000000000000001900000000000000090000000000006C00000000000000000000000000000000010000000000000000000000000000350000000600000003000000000000007029000000000000700900000000000070000000000000000500000000000000080000000000000010000000000000003E000000080000000300000000000000E029000000000000E00900000000000020060000000000000000000000000000010000000000000000000000000000004D000000080000000300000000000000E039000000000000E0090000000000000100000000000000000000000000000001000000000000000000000000000000520000000100000030000000000000000000000000000000E009000000000000F0000000000000000000000000000000010000000000000001000000000000005B0000000200000000000000000000000000000000000000D00A00000000000078000000000000000E0000000200000008000000000000001800000000000000630000000300000000000000000000000000000000000000480B00000000000075000000000000000000000000000000010000000000000000000000000000006D0000000300000000000000000000000000000000000000BD0B0000000000004F00000000000000000000000000000001000000000000000000000000000000
+  - Name:            .hipFatBinSegment
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC ]
+    Address:         0x202FD0
+    AddressAlign:    0x8
+    Content:         '465049480100000000102000000000000000000000000000'
+...
diff --git a/llvm/test/tools/llvm-readobj/ELF/AMDGPU/dump-offload-bundle.test b/llvm/test/tools/llvm-readobj/ELF/AMDGPU/dump-offload-bundle.test
new file mode 100644
index 0000000000000..9659e0e25a8f5
--- /dev/null
+++ b/llvm/test/tools/llvm-readobj/ELF/AMDGPU/dump-offload-bundle.test
@@ -0,0 +1,41 @@
+## Test that --offloading with a fatbin works correctly
+# REQUIRES: target={{x86_64-.*-linux.*}}
+# REQUIRES: amdgpu-registered-target
+
+# RUN: yaml2obj %s -o %t.elf
+# RUN: llvm-readobj --offloading %t.elf > %t.out | FileCheck %s --input-file=%t.out -DFILE_NAME=%t.elf
+
+# CHECK:        host-x86_64-unknown-linux--     file://[[FILE_NAME]]#offset=8192&size=0
+# CHECK-NEXT:   hipv4-amdgcn-amd-amdhsa--gfx908 file://[[FILE_NAME]]#offset=8192&size=4048
+
+--- !ELF
+FileHeader:
+  Class:           ELFCLASS64
+  Data:            ELFDATA2LSB
+  Type:            ET_EXEC
+  Machine:         EM_X86_64
+  Entry:           0x2041B0
+ProgramHeaders:
+  - Type:            PT_PHDR
+    Flags:           [ PF_R ]
+    VAddr:           0x200040
+    Align:           0x8
+    Offset:          0x40
+  - Type:            PT_GNU_STACK
+    Flags:           [ PF_W, PF_R ]
+    Align:           0x0
+    Offset:          0x0
+Sections:
+  - Name:            .hip_fatbin
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC ]
+    Address:         0x201000
+    AddressAlign:    0x1000
+    Content:         5F5F434C414E475F4F46464C4F41445F42554E444C455F5F0200000000000000001000000000000000000000000000001B00000000000000686F73742D7838365F36342D756E6B6E6F776E2D6C696E75782D2D0010000000000000D00F0000000000001F0000000000000068697076342D616D6467636E2D616D642D616D646873612D2D676678393038000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000007F454C460201014003000000000000000300E0000100000000000000000000004000000000000000100C0000000000003005000040003800090040000F000D000600000004000000400000000000000040000000000000004000000000000000F801000000000000F80100000000000008000000000000000100000004000000000000000000000000000000000000000000000000000000C008000000000000C008000000000000001000000000000001000000050000000009000000000000001900000000000000190000000000006C000000000000006C00000000000000001000000000000001000000060000007009000000000000702900000000000070290000000000007000000000000000900600000000000000100000000000000100000006000000E009000000000000E039000000000000E039000000000000000000000000000001000000000000000010000000000000020000000600000070090000000000007029000000000000702900000000000070000000000000007000000000000000080000000000000052E574640400000070090000000000007029000000000000702900000000000070000000000000009006000000000000010000000000000051E57464060000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000400000004000000380200000000000038020000000000003802000000000000340500000000000034050000000000000400000000000000070000001D05000020000000414D44475055000083AE616D646873612E6B65726E656C7391DE0012AB2E616770725F636F756E7400A52E61726773DC001085AE2E616464726573735F7370616365A6676C6F62616CA52E6E616D65AA415F642E636F65726365A72E6F666673657400A52E73697A6508AB2E76616C75655F6B696E64AD676C6F62616C5F62756666657285AE2E616464726573735F7370616365A6676C6F62616CA52E6E616D65AA425F642E636F65726365A72E6F666673657408A52E73697A6508AB2E76616C75655F6B696E64AD676C6F62616C5F62756666657284A52E6E616D65A14EA72E6F666673657410A52E73697A6508AB2E76616C75655F6B696E64A862795F76616C756583A72E6F666673657418A52E73697A6504AB2E76616C75655F6B696E64B468696464656E5F626C6F636B5F636F756E745F7883A72E6F66667365741CA52E73697A6504AB2E76616C75655F6B696E64B468696464656E5F626C6F636B5F636F756E745F7983A72E6F666673657420A52E73697A6504AB2E76616C75655F6B696E64B468696464656E5F626C6F636B5F636F756E745F7A83A72E6F666673657424A52E73697A6502AB2E76616C75655F6B696E64B368696464656E5F67726F75705F73697A655F7883A72E6F666673657426A52E73697A6502AB2E76616C75655F6B696E64B368696464656E5F67726F75705F73697A655F7983A72E6F666673657428A52E73697A6502AB2E76616C75655F6B696E64B368696464656E5F67726F75705F73697A655F7A83A72E6F66667365742AA52E73697A6502AB2E76616C75655F6B696E64B268696464656E5F72656D61696E6465725F7883A72E6F66667365742CA52E73697A6502AB2E76616C75655F6B696E64B268696464656E5F72656D61696E6465725F7983A72E6F66667365742EA52E73697A6502AB2E76616C75655F6B696E64B268696464656E5F72656D61696E6465725F7A83A72E6F666673657440A52E73697A6508AB2E76616C75655F6B696E64B668696464656E5F676C6F62616C5F6F66667365745F7883A72E6F666673657448A52E73697A6508AB2E76616C75655F6B696E64B668696464656E5F676C6F62616C5F6F66667365745F7983A72E6F666673657450A52E73697A6508AB2E76616C75655F6B696E64B668696464656E5F676C6F62616C5F6F66667365745F7A83A72E6F666673657458A52E73697A6502AB2E76616C75655F6B696E64B068696464656E5F677269645F64696D73B92E67726F75705F7365676D656E745F66697865645F73697A6500B62E6B65726E6172675F7365676D656E745F616C69676E08B52E6B65726E6172675F7365676D656E745F73697A65CD0118A92E6C616E6775616765A84F70656E434C2043B12E6C616E67756167655F76657273696F6E920200B82E6D61785F666C61745F776F726B67726F75705F73697A65CD0400A52E6E616D65B25F5A3973696D706C65416464506A504B6A6DBB2E707269766174655F7365676D656E745F66697865645F73697A6500AB2E736770725F636F756E740CB12E736770725F7370696C6C5F636F756E7400A72E73796D626F6CB55F5A3973696D706C65416464506A504B6A6D2E6B64B82E756E69666F726D5F776F726B5F67726F75705F73697A6501B32E757365735F64796E616D69635F737461636BC2AB2E766770725F636F756E7404B12E766770725F7370696C6C5F636F756E7400AF2E7761766566726F6E745F73697A6540AD616D646873612E746172676574B9616D6467636E2D616D642D616D646873612D2D676678393038AE616D646873612E76657273696F6E92010200000000000000000000000000000000000000000000000000000000000000010000001203070000190000000000006C000000000000001400000011030600800800000000000040000000000000002A00000011000A00E03900000000000001000000000000000100000001000000010000001A000000000008400000D20001000000360A4A7A5238A4D3F113F4DD04000000040000000200000001000000000000000300000000000000000000000000000000000000005F5A3973696D706C65416464506A504B6A6D005F5A3973696D706C65416464506A504B6A6D2E6B64005F5F6869705F637569645F623730363264386333326134613933330000000000000000000000000000000000000000000000000000000000000000000000180100000000000080100000000000000000000000000000000000000000000000000000000000004000AF008C000000090000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000C20102C02400000002000AC0000000008002027E7FC08CBF07FF0486FFFF0000060406920600006800008FD2820002000302067E0200043203030638008050DC02007F020102067E0000003203030238008050DC00007F03700F8CBF03050468008070DC00027F00000081BF00000000060000000000000070070000000000000B000000000000001800000000000000050000000000000020080000000000000A000000000000004600000000000000F5FEFF6F00000000D0070000000000000400000000000000F807000000000000000000000000000000000000000000004C696E6B65723A20414D44204C4C442031392E302E3000414D4420636C616E672076657273696F6E2031392E302E306769742028202032343231322063393630313665636534313337356462646438663037356266333762643666633333323230376233290000414D4420636C616E672076657273696F6E2031382E302E3067697420287373683A2F2F6765727269746769742F6C696768746E696E672F65632F6C6C766D2D70726F6A65637420616D642D6D61696E6C696E652D6F70656E20323431373620663935303039613166393032313232343865313036333964653837653635636163616338643961372900000000000000000000000000000000000000000000000000460000000002080070290000000000000000000000000000010000001203070000190000000000006C000000000000001400000011030600800800000000000040000000000000002A00000011000A00E0390000000000000100000000000000002E6E6F7465002E64796E73796D002E676E752E68617368002E68617368002E64796E737472002E726F64617461002E74657874002E64796E616D6963002E72656C726F5F70616464696E67002E627373002E636F6D6D656E74002E73796D746162002E7368737472746162002E73747274616200005F5A3973696D706C65416464506A504B6A6D005F5A3973696D706C65416464506A504B6A6D2E6B64005F5F6869705F637569645F62373036326438633332613461393333005F44594E414D494300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000070000000200000000000000380200000000000038020000000000003405000000000000000000000000000004000000000000000000000000000000070000000B00000002000000000000007007000000000000700700000000000060000000000000000500000001000000080000000000000018000000000000000F000000F6FFFF6F0200000000000000D007000000000000D007000000000000280000000000000002000000000000000800000000000000000000000000000019000000050000000200000000000000F807000000000000F80700000000000028000000000000000200000000000000040000000000000004000000000000001F000000030000000200000000000000200800000000000020080000000000004600000000000000000000000000000001000000000000000000000000000000270000000100000002000000000000008008000000000000800800000000000040000000000000000000000000000000400000000000000000000000000000002F000000010000000600000000000000001900000000000000090000000000006C00000000000000000000000000000000010000000000000000000000000000350000000600000003000000000000007029000000000000700900000000000070000000000000000500000000000000080000000000000010000000000000003E000000080000000300000000000000E029000000000000E00900000000000020060000000000000000000000000000010000000000000000000000000000004D000000080000000300000000000000E039000000000000E0090000000000000100000000000000000000000000000001000000000000000000000000000000520000000100000030000000000000000000000000000000E009000000000000F0000000000000000000000000000000010000000000000001000000000000005B0000000200000000000000000000000000000000000000D00A00000000000078000000000000000E0000000200000008000000000000001800000000000000630000000300000000000000000000000000000000000000480B00000000000075000000000000000000000000000000010000000000000000000000000000006D0000000300000000000000000000000000000000000000BD0B0000000000004F00000000000000000000000000000001000000000000000000000000000000
+  - Name:            .hipFatBinSegment
+    Type:            SHT_PROGBITS
+    Flags:           [ SHF_ALLOC ]
+    Address:         0x202FD0
+    AddressAlign:    0x8
+    Content:         '465049480100000000102000000000000000000000000000'
+...
diff --git a/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp b/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
index 0d209590655ef..d1700487f162f 100644
--- a/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
+++ b/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
@@ -16,6 +16,8 @@
 #include "llvm/ObjCopy/ConfigManager.h"
 #include "llvm/ObjCopy/MachO/MachOConfig.h"
 #include "llvm/Object/Binary.h"
+#include "llvm/Object/OffloadBinary.h"
+#include "llvm/Object/OffloadBundle.h"
 #include "llvm/Option/Arg.h"
 #include "llvm/Option/ArgList.h"
 #include "llvm/Support/CRC.h"
@@ -284,6 +286,11 @@ static Expected<uint8_t> parseVisibilityType(StringRef VisType) {
   return type;
 }
 
+static void llvm::objcopy::parseDumpOffloadBundle(StringRef URI) {
+  if (Error Err = object::extractOffloadBundleByURI(URI))
+    outs() << "Failed to extract from URI.";
+}
+
 namespace {
 struct TargetInfo {
   FileFormat Format;
@@ -727,6 +734,15 @@ objcopy::parseObjcopyOptions(ArrayRef<const char *> ArgsArr,
 
   SmallVector<const char *, 2> Positional;
 
+  ConfigManager ConfigMgr;
+  CommonConfig &Config = ConfigMgr.Common;
+  COFFConfig &COFFConfig = ConfigMgr.COFF;
+  ELFConfig &ELFConfig = ConfigMgr.ELF;
+  MachOConfig &MachOConfig = ConfigMgr.MachO;
+
+  if (InputArgs.hasArg(OBJCOPY_dump_offload_bundle))
+    Config.NeedPositional = false;
+
   for (auto *Arg : InputArgs.filtered(OBJCOPY_UNKNOWN))
     return createStringError(errc::invalid_argument, "unknown argument '%s'",
                              Arg->getAsString(InputArgs).c_str());
@@ -734,27 +750,29 @@ objcopy::parseObjcopyOptions(ArrayRef<const char *> ArgsArr,
   for (auto *Arg : InputArgs.filtered(OBJCOPY_INPUT))
     Positional.push_back(Arg->getValue());
 
-  if (Positional.empty())
+  if (Positional.empty() && Config.NeedPositional)
     return createStringError(errc::invalid_argument, "no input file specified");
 
-  if (Positional.size() > 2)
+  if (Positional.size() > 2 && Config.NeedPositional)
     return createStringError(errc::invalid_argument,
                              "too many positional arguments");
 
-  ConfigManager ConfigMgr;
-  CommonConfig &Config = ConfigMgr.Common;
-  COFFConfig &COFFConfig = ConfigMgr.COFF;
-  ELFConfig &ELFConfig = ConfigMgr.ELF;
-  MachOConfig &MachOConfig = ConfigMgr.MachO;
-  Config.InputFilename = Positional[0];
-  Config.OutputFilename = Positional[Positional.size() == 1 ? 0 : 1];
-  if (InputArgs.hasArg(OBJCOPY_target) &&
-      (InputArgs.hasArg(OBJCOPY_input_target) ||
-       InputArgs.hasArg(OBJCOPY_output_target)))
-    return createStringError(
-        errc::invalid_argument,
-        "--target cannot be used with --input-target or --output-target");
+  if (Arg *A = InputArgs.getLastArg(OBJCOPY_dump_offload_bundle)) {
+    for (StringRef URIStr : llvm::split(A->getValue(), ",")) {
+      llvm::objcopy::parseDumpOffloadBundle(URIStr);
+    }
+  }
 
+  if (Config.NeedPositional) {
+    Config.InputFilename = Positional[0];
+    Config.OutputFilename = Positional[Positional.size() == 1 ? 0 : 1];
+    if (InputArgs.hasArg(OBJCOPY_target) &&
+        (InputArgs.hasArg(OBJCOPY_input_target) ||
+         InputArgs.hasArg(OBJCOPY_output_target)))
+      return createStringError(
+          errc::invalid_argument,
+          "--target cannot be used with --input-target or --output-target");
+  }
   if (InputArgs.hasArg(OBJCOPY_regex) && InputArgs.hasArg(OBJCOPY_wildcard))
     return createStringError(errc::invalid_argument,
                              "--regex and --wildcard are incompatible");
@@ -1417,25 +1435,26 @@ objcopy::parseInstallNameToolOptions(ArrayRef<const char *> ArgsArr) {
                              Arg->getAsString(InputArgs).c_str());
   for (auto *Arg : InputArgs.filtered(INSTALL_NAME_TOOL_INPUT))
     Positional.push_back(Arg->getValue());
-  if (Positional.empty())
+  if (Positional.empty() && Config.NeedPositional)
     return createStringError(errc::invalid_argument, "no input file specified");
-  if (Positional.size() > 1)
+  if (Positional.size() > 1 && Config.NeedPositional)
     return createStringError(
         errc::invalid_argument,
         "llvm-install-name-tool expects a single input file");
-  Config.InputFilename = Positional[0];
-  Config.OutputFilename = Positional[0];
-
-  Expected<OwningBinary<Binary>> BinaryOrErr =
-      createBinary(Config.InputFilename);
-  if (!BinaryOrErr)
-    return createFileError(Config.InputFilename, BinaryOrErr.takeError());
-  auto *Binary = (*BinaryOrErr).getBinary();
-  if (!Binary->isMachO() && !Binary->isMachOUniversalBinary())
-    return createStringError(errc::invalid_argument,
-                             "input file: %s is not a Mach-O file",
-                             Config.InputFilename.str().c_str());
-
+  if (Config.NeedPositional) {
+    Config.InputFilename = Positional[0];
+    Config.OutputFilename = Positional[0];
+
+    Expected<OwningBinary<Binary>> BinaryOrErr =
+        createBinary(Config.InputFilename);
+    if (!BinaryOrErr)
+      return createFileError(Config.InputFilename, BinaryOrErr.takeError());
+    auto *Binary = (*BinaryOrErr).getBinary();
+    if (!Binary->isMachO() && !Binary->isMachOUniversalBinary())
+      return createStringError(errc::invalid_argument,
+                               "input file: %s is not a Mach-O file",
+                               Config.InputFilename.str().c_str());
+  }
   DC.CopyConfigs.push_back(std::move(ConfigMgr));
   return std::move(DC);
 }
@@ -1474,13 +1493,16 @@ objcopy::parseBitcodeStripOptions(ArrayRef<const char *> ArgsArr,
                              Arg->getAsString(InputArgs).c_str());
 
   SmallVector<StringRef, 2> Positional;
-  for (auto *Arg : InputArgs.filtered(BITCODE_STRIP_INPUT))
-    Positional.push_back(Arg->getValue());
-  if (Positional.size() > 1)
-    return createStringError(errc::invalid_argument,
-                             "llvm-bitcode-strip expects a single input file");
-  assert(!Positional.empty());
-  Config.InputFilename = Positional[0];
+  if (Config.NeedPositional) {
+    for (auto *Arg : InputArgs.filtered(BITCODE_STRIP_INPUT))
+      Positional.push_back(Arg->getValue());
+    if (Positional.size() > 1)
+      return createStringError(
+          errc::invalid_argument,
+          "llvm-bitcode-strip expects a single input file");
+    assert(!Positional.empty());
+    Config.InputFilename = Positional[0];
+  }
 
   if (!InputArgs.hasArg(BITCODE_STRIP_output)) {
     return createStringError(errc::invalid_argument,
@@ -1542,27 +1564,30 @@ objcopy::parseStripOptions(ArrayRef<const char *> RawArgsArr,
     exit(0);
   }
 
-  SmallVector<StringRef, 2> Positional;
-  for (auto *Arg : InputArgs.filtered(STRIP_UNKNOWN))
-    return createStringError(errc::invalid_argument, "unknown argument '%s'",
-                             Arg->getAsString(InputArgs).c_str());
-  for (auto *Arg : InputArgs.filtered(STRIP_INPUT))
-    Positional.push_back(Arg->getValue());
-  std::copy(DashDash, RawArgsArr.end(), std::back_inserter(Positional));
-
-  if (Positional.empty())
-    return createStringError(errc::invalid_argument, "no input file specified");
-
-  if (Positional.size() > 1 && InputArgs.hasArg(STRIP_output))
-    return createStringError(
-        errc::invalid_argument,
-        "multiple input files cannot be used in combination with -o");
-
   ConfigManager ConfigMgr;
   CommonConfig &Config = ConfigMgr.Common;
   ELFConfig &ELFConfig = ConfigMgr.ELF;
   MachOConfig &MachOConfig = ConfigMgr.MachO;
 
+  SmallVector<StringRef, 2> Positional;
+  if (Config.NeedPositional) {
+    for (auto *Arg : InputArgs.filtered(STRIP_UNKNOWN))
+      return createStringError(errc::invalid_argument, "unknown argument '%s'",
+                               Arg->getAsString(InputArgs).c_str());
+    for (auto *Arg : InputArgs.filtered(STRIP_INPUT))
+      Positional.push_back(Arg->getValue());
+    std::copy(DashDash, RawArgsArr.end(), std::back_inserter(Positional));
+
+    if (Positional.empty())
+      return createStringError(errc::invalid_argument,
+                               "no input file specified");
+
+    if (Positional.size() > 1 && InputArgs.hasArg(STRIP_output))
+      return createStringError(
+          errc::invalid_argument,
+          "multiple input files cannot be used in combination with -o");
+  }
+
   if (InputArgs.hasArg(STRIP_regex) && InputArgs.hasArg(STRIP_wildcard))
     return createStringError(errc::invalid_argument,
                              "--regex and --wildcard are incompatible");
diff --git a/llvm/tools/llvm-objcopy/ObjcopyOptions.h b/llvm/tools/llvm-objcopy/ObjcopyOptions.h
index 3b8878981da47..72b2171e0a477 100644
--- a/llvm/tools/llvm-objcopy/ObjcopyOptions.h
+++ b/llvm/tools/llvm-objcopy/ObjcopyOptions.h
@@ -51,6 +51,11 @@ parseBitcodeStripOptions(ArrayRef<const char *> ArgsArr,
 Expected<DriverConfig>
 parseStripOptions(ArrayRef<const char *> ArgsArr,
                   llvm::function_ref<Error(Error)> ErrorCallback);
+
+// parseDumpURI reads a URI as a string, and extracts the raw memory into a
+// code object file named from the URI string given
+static void parseDumpOffloadBundle(StringRef URI);
+
 } // namespace objcopy
 } // namespace llvm
 
diff --git a/llvm/tools/llvm-objcopy/ObjcopyOpts.td b/llvm/tools/llvm-objcopy/ObjcopyOpts.td
index fbc6a59d9461e..c6216a6b8a627 100644
--- a/llvm/tools/llvm-objcopy/ObjcopyOpts.td
+++ b/llvm/tools/llvm-objcopy/ObjcopyOpts.td
@@ -239,6 +239,9 @@ defm dump_section
     : Eq<"dump-section",
          "Dump contents of section named <section> into file <file>">,
       MetaVarName<"section=file">;
+
+defm dump_offload_bundle : Eq<"dump-offload-bundle", "Dump the contents specified by URI">;
+
 defm prefix_symbols
     : Eq<"prefix-symbols", "Add <prefix> to the start of every symbol name">,
       MetaVarName<"prefix">;
diff --git a/llvm/tools/llvm-objcopy/llvm-objcopy.cpp b/llvm/tools/llvm-objcopy/llvm-objcopy.cpp
index ad67b673b2cc7..dc3bb54e0f6ed 100644
--- a/llvm/tools/llvm-objcopy/llvm-objcopy.cpp
+++ b/llvm/tools/llvm-objcopy/llvm-objcopy.cpp
@@ -124,88 +124,89 @@ static Error executeObjcopyOnRawBinary(ConfigManager &ConfigMgr,
 static Error executeObjcopy(ConfigManager &ConfigMgr) {
   CommonConfig &Config = ConfigMgr.Common;
 
-  Expected<FilePermissionsApplier> PermsApplierOrErr =
-      FilePermissionsApplier::create(Config.InputFilename);
-  if (!PermsApplierOrErr)
-    return PermsApplierOrErr.takeError();
-
-  std::function<Error(raw_ostream & OutFile)> ObjcopyFunc;
-
-  OwningBinary<llvm::object::Binary> BinaryHolder;
-  std::unique_ptr<MemoryBuffer> MemoryBufferHolder;
-
-  if (Config.InputFormat == FileFormat::Binary ||
-      Config.InputFormat == FileFormat::IHex) {
-    ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
-        MemoryBuffer::getFileOrSTDIN(Config.InputFilename);
-    if (!BufOrErr)
-      return createFileError(Config.InputFilename, BufOrErr.getError());
-    MemoryBufferHolder = std::move(*BufOrErr);
-
-    if (Config.InputFormat == FileFormat::Binary)
-      ObjcopyFunc = [&](raw_ostream &OutFile) -> Error {
-        // Handle FileFormat::Binary.
-        return executeObjcopyOnRawBinary(ConfigMgr, *MemoryBufferHolder,
-                                         OutFile);
-      };
-    else
-      ObjcopyFunc = [&](raw_ostream &OutFile) -> Error {
-        // Handle FileFormat::IHex.
-        return executeObjcopyOnIHex(ConfigMgr, *MemoryBufferHolder, OutFile);
-      };
-  } else {
-    Expected<OwningBinary<llvm::object::Binary>> BinaryOrErr =
-        createBinary(Config.InputFilename);
-    if (!BinaryOrErr)
-      return createFileError(Config.InputFilename, BinaryOrErr.takeError());
-    BinaryHolder = std::move(*BinaryOrErr);
-
-    if (Archive *Ar = dyn_cast<Archive>(BinaryHolder.getBinary())) {
-      // Handle Archive.
-      if (Error E = executeObjcopyOnArchive(ConfigMgr, *Ar))
-        return E;
+  if (Config.NeedPositional) {
+    Expected<FilePermissionsApplier> PermsApplierOrErr =
+        FilePermissionsApplier::create(Config.InputFilename);
+    if (!PermsApplierOrErr)
+      return PermsApplierOrErr.takeError();
+
+    std::function<Error(raw_ostream & OutFile)> ObjcopyFunc;
+
+    OwningBinary<llvm::object::Binary> BinaryHolder;
+    std::unique_ptr<MemoryBuffer> MemoryBufferHolder;
+
+    if (Config.InputFormat == FileFormat::Binary ||
+        Config.InputFormat == FileFormat::IHex) {
+      ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
+          MemoryBuffer::getFileOrSTDIN(Config.InputFilename);
+      if (!BufOrErr)
+        return createFileError(Config.InputFilename, BufOrErr.getError());
+      MemoryBufferHolder = std::move(*BufOrErr);
+
+      if (Config.InputFormat == FileFormat::Binary)
+        ObjcopyFunc = [&](raw_ostream &OutFile) -> Error {
+          // Handle FileFormat::Binary.
+          return executeObjcopyOnRawBinary(ConfigMgr, *MemoryBufferHolder,
+                                           OutFile);
+        };
+      else
+        ObjcopyFunc = [&](raw_ostream &OutFile) -> Error {
+          // Handle FileFormat::IHex.
+          return executeObjcopyOnIHex(ConfigMgr, *MemoryBufferHolder, OutFile);
+        };
     } else {
-      // Handle llvm::object::Binary.
-      ObjcopyFunc = [&](raw_ostream &OutFile) -> Error {
-        return executeObjcopyOnBinary(ConfigMgr, *BinaryHolder.getBinary(),
-                                      OutFile);
-      };
+      Expected<OwningBinary<llvm::object::Binary>> BinaryOrErr =
+          createBinary(Config.InputFilename);
+      if (!BinaryOrErr)
+        return createFileError(Config.InputFilename, BinaryOrErr.takeError());
+      BinaryHolder = std::move(*BinaryOrErr);
+
+      if (Archive *Ar = dyn_cast<Archive>(BinaryHolder.getBinary())) {
+        // Handle Archive.
+        if (Error E = executeObjcopyOnArchive(ConfigMgr, *Ar))
+          return E;
+      } else {
+        // Handle llvm::object::Binary.
+        ObjcopyFunc = [&](raw_ostream &OutFile) -> Error {
+          return executeObjcopyOnBinary(ConfigMgr, *BinaryHolder.getBinary(),
+                                        OutFile);
+        };
+      }
     }
-  }
 
-  if (ObjcopyFunc) {
-    if (Config.SplitDWO.empty()) {
-      // Apply transformations described by Config and store result into
-      // Config.OutputFilename using specified ObjcopyFunc function.
-      if (Error E = writeToOutput(Config.OutputFilename, ObjcopyFunc))
-        return E;
-    } else {
-      Config.ExtractDWO = true;
-      Config.StripDWO = false;
-      // Copy .dwo tables from the Config.InputFilename into Config.SplitDWO
-      // file using specified ObjcopyFunc function.
-      if (Error E = writeToOutput(Config.SplitDWO, ObjcopyFunc))
-        return E;
-      Config.ExtractDWO = false;
-      Config.StripDWO = true;
-      // Apply transformations described by Config, remove .dwo tables and
-      // store result into Config.OutputFilename using specified ObjcopyFunc
-      // function.
-      if (Error E = writeToOutput(Config.OutputFilename, ObjcopyFunc))
-        return E;
+    if (ObjcopyFunc) {
+      if (Config.SplitDWO.empty()) {
+        // Apply transformations described by Config and store result into
+        // Config.OutputFilename using specified ObjcopyFunc function.
+        if (Error E = writeToOutput(Config.OutputFilename, ObjcopyFunc))
+          return E;
+      } else {
+        Config.ExtractDWO = true;
+        Config.StripDWO = false;
+        // Copy .dwo tables from the Config.InputFilename into Config.SplitDWO
+        // file using specified ObjcopyFunc function.
+        if (Error E = writeToOutput(Config.SplitDWO, ObjcopyFunc))
+          return E;
+        Config.ExtractDWO = false;
+        Config.StripDWO = true;
+        // Apply transformations described by Config, remove .dwo tables and
+        // store result into Config.OutputFilename using specified ObjcopyFunc
+        // function.
+        if (Error E = writeToOutput(Config.OutputFilename, ObjcopyFunc))
+          return E;
+      }
     }
-  }
-
-  if (Error E =
-          PermsApplierOrErr->apply(Config.OutputFilename, Config.PreserveDates))
-    return E;
 
-  if (!Config.SplitDWO.empty())
-    if (Error E =
-            PermsApplierOrErr->apply(Config.SplitDWO, Config.PreserveDates,
-                                     static_cast<sys::fs::perms>(0666)))
+    if (Error E = PermsApplierOrErr->apply(Config.OutputFilename,
+                                           Config.PreserveDates))
       return E;
 
+    if (!Config.SplitDWO.empty())
+      if (Error E =
+              PermsApplierOrErr->apply(Config.SplitDWO, Config.PreserveDates,
+                                       static_cast<sys::fs::perms>(0666)))
+        return E;
+  }
   return Error::success();
 }
 
diff --git a/llvm/tools/llvm-readobj/ObjDumper.cpp b/llvm/tools/llvm-readobj/ObjDumper.cpp
index d3c613ee823ba..290eca7506e25 100644
--- a/llvm/tools/llvm-readobj/ObjDumper.cpp
+++ b/llvm/tools/llvm-readobj/ObjDumper.cpp
@@ -16,6 +16,8 @@
 #include "llvm/Object/Archive.h"
 #include "llvm/Object/Decompressor.h"
 #include "llvm/Object/ObjectFile.h"
+#include "llvm/Object/OffloadBinary.h"
+#include "llvm/Object/OffloadBundle.h"
 #include "llvm/Support/Error.h"
 #include "llvm/Support/FormatVariadic.h"
 #include "llvm/Support/ScopedPrinter.h"
@@ -230,4 +232,28 @@ void ObjDumper::printSectionsAsHex(const object::ObjectFile &Obj,
   }
 }
 
+// TODO: add proper error handling.
+void ObjDumper::printOffloading(const object::ObjectFile &Obj) {
+  // we can use an argument to let user select which offloading section they
+  // want to print. but for now, we're hardcoding ELF and "hip_fatbin".
+  assert((Obj.isELF() || Obj.isCOFF()) && "Invalid file type");
+
+  SmallVector<llvm::object::OffloadBundleFatBin> Bundles;
+  if (Error Err = llvm::object::extractOffloadBundleFatBinary(Obj, Bundles))
+    reportWarning(createError("Cannot extract Fatbin Binary from Object."),
+                  Obj.getFileName());
+
+  // Print out all the FatBin Bundles that are contained in this buffer.
+  for (const auto &[Index, Bundle] : llvm::enumerate(Bundles)) {
+    Bundle.printEntriesAsURI();
+  }
+  /**SmallVectorImpl<llvm::object::OffloadBundleFatBin>::iterator it =
+      Bundles.begin();
+  for (uint64_t I = 0; I < Bundles.size(); I++) {
+    outs() << "Bundle " << I << "\n";
+    it->printEntriesAsURI();
+    ++it;
+  } **/
+}
+
 } // namespace llvm
diff --git a/llvm/tools/llvm-readobj/ObjDumper.h b/llvm/tools/llvm-readobj/ObjDumper.h
index cd744e3bbfb71..aaa294c3c3f25 100644
--- a/llvm/tools/llvm-readobj/ObjDumper.h
+++ b/llvm/tools/llvm-readobj/ObjDumper.h
@@ -16,6 +16,7 @@
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Object/ObjectFile.h"
+#include "llvm/Object/OffloadBinary.h"
 #include "llvm/Support/CommandLine.h"
 
 #include <unordered_set>
@@ -184,6 +185,7 @@ class ObjDumper {
   std::function<Error(const Twine &Msg)> WarningHandler;
   void reportUniqueWarning(Error Err) const;
   void reportUniqueWarning(const Twine &Msg) const;
+  void printOffloading(const object::ObjectFile &Obj);
 
 protected:
   ScopedPrinter &W;
diff --git a/llvm/tools/llvm-readobj/Opts.td b/llvm/tools/llvm-readobj/Opts.td
index 7d574d875d22e..df681555ea9e1 100644
--- a/llvm/tools/llvm-readobj/Opts.td
+++ b/llvm/tools/llvm-readobj/Opts.td
@@ -64,6 +64,9 @@ def notes : FF<"notes", "Display notes">, Group<grp_elf>;
 def program_headers : FF<"program-headers", "Display program headers">, Group<grp_elf>;
 def version_info : FF<"version-info", "Display version sections">, Group<grp_elf>;
 
+def offloading : Flag<["--"], "offloading">,
+  HelpText<"Display the content of the offloading section">;
+
 // Mach-O specific options.
 def grp_mach_o : OptionGroup<"kind">, HelpText<"OPTIONS (Mach-O specific)">;
 def macho_data_in_code : FF<"macho-data-in-code", "Display Data in Code command">, Group<grp_mach_o>;
diff --git a/llvm/tools/llvm-readobj/llvm-readobj.cpp b/llvm/tools/llvm-readobj/llvm-readobj.cpp
index 1231c02035d1f..73c0ff8d7650b 100644
--- a/llvm/tools/llvm-readobj/llvm-readobj.cpp
+++ b/llvm/tools/llvm-readobj/llvm-readobj.cpp
@@ -138,6 +138,7 @@ static bool Notes;
 static bool ProgramHeaders;
 static bool SectionGroups;
 static bool VersionInfo;
+static bool Offloading;
 
 // Mach-O specific options.
 static bool MachODataInCode;
@@ -288,6 +289,7 @@ static void parseOptions(const opt::InputArgList &Args) {
     }
   }
   opts::VersionInfo = Args.hasArg(OPT_version_info);
+  opts::Offloading = Args.hasArg(OPT_offloading);
 
   // Mach-O specific options.
   opts::MachODataInCode = Args.hasArg(OPT_macho_data_in_code);
@@ -455,6 +457,8 @@ static void dumpObject(ObjectFile &Obj, ScopedPrinter &Writer,
     Dumper->printGnuHashTable();
   if (opts::VersionInfo)
     Dumper->printVersionInfo();
+  if (opts::Offloading)
+    Dumper->printOffloading(Obj);
   if (opts::StringTable)
     Dumper->printStringTable();
   if (Obj.isELF()) {
@@ -699,6 +703,7 @@ int llvm_readobj_main(int argc, char **argv, const llvm::ToolContext &) {
     opts::DynamicTable = true;
     opts::Notes = true;
     opts::VersionInfo = true;
+    opts::Offloading = true;
     opts::UnwindInfo = true;
     opts::SectionGroups = true;
     opts::HashHistogram = true;



More information about the llvm-commits mailing list