[lld] 918948d - [lld-macho] Support reading of universal binaries

Shoaib Meenai via llvm-commits llvm-commits at lists.llvm.org
Wed Apr 29 15:52:34 PDT 2020


Author: Jez Ng
Date: 2020-04-29T15:44:44-07:00
New Revision: 918948db4dc8718cb7aae8765653c27cba3cfe86

URL: https://github.com/llvm/llvm-project/commit/918948db4dc8718cb7aae8765653c27cba3cfe86
DIFF: https://github.com/llvm/llvm-project/commit/918948db4dc8718cb7aae8765653c27cba3cfe86.diff

LOG: [lld-macho] Support reading of universal binaries

Differential Revision: https://reviews.llvm.org/D77006

Added: 
    lld/test/MachO/fat-arch.s
    lld/test/MachO/invalid-fat-narch.s
    lld/test/MachO/invalid-fat-offset.s

Modified: 
    lld/MachO/InputFiles.cpp
    lld/test/CMakeLists.txt

Removed: 
    


################################################################################
diff  --git a/lld/MachO/InputFiles.cpp b/lld/MachO/InputFiles.cpp
index 7794f3e893fd..1c56418bc69e 100644
--- a/lld/MachO/InputFiles.cpp
+++ b/lld/MachO/InputFiles.cpp
@@ -81,7 +81,31 @@ Optional<MemoryBufferRef> macho::readFile(StringRef path) {
   if (read32be(&hdr->magic) != MachO::FAT_MAGIC)
     return mbref;
 
-  error("TODO: Add support for universal binaries");
+  // Object files and archive files may be fat files, which contains
+  // multiple real files for 
diff erent CPU ISAs. Here, we search for a
+  // file that matches with the current link target and returns it as
+  // a MemoryBufferRef.
+  auto *arch = reinterpret_cast<const MachO::fat_arch *>(buf + sizeof(*hdr));
+
+  for (uint32_t i = 0, n = read32be(&hdr->nfat_arch); i < n; ++i) {
+    if (reinterpret_cast<const char *>(arch + i + 1) >
+        buf + mbref.getBufferSize()) {
+      error(path + ": fat_arch struct extends beyond end of file");
+      return None;
+    }
+
+    if (read32be(&arch[i].cputype) != target->cpuType ||
+        read32be(&arch[i].cpusubtype) != target->cpuSubtype)
+      continue;
+
+    uint32_t offset = read32be(&arch[i].offset);
+    uint32_t size = read32be(&arch[i].size);
+    if (offset + size > mbref.getBufferSize())
+      error(path + ": slice extends beyond end of file");
+    return MemoryBufferRef(StringRef(buf + offset, size), path.copy(bAlloc));
+  }
+
+  error("unable to find matching architecture in " + path);
   return None;
 }
 

diff  --git a/lld/test/CMakeLists.txt b/lld/test/CMakeLists.txt
index 80721384c287..150865245965 100644
--- a/lld/test/CMakeLists.txt
+++ b/lld/test/CMakeLists.txt
@@ -35,8 +35,9 @@ set(LLD_TEST_DEPS lld)
 if (NOT LLD_BUILT_STANDALONE)
   list(APPEND LLD_TEST_DEPS
     FileCheck count llc llvm-ar llvm-as llvm-bcanalyzer llvm-config llvm-cvtres
-    llvm-dis llvm-dwarfdump llvm-lib llvm-mc llvm-nm llvm-objcopy llvm-objdump
-    llvm-pdbutil llvm-readelf llvm-readobj not obj2yaml opt yaml2obj
+    llvm-dis llvm-dwarfdump llvm-lib llvm-lipo llvm-mc llvm-nm llvm-objcopy
+    llvm-objdump llvm-pdbutil llvm-readelf llvm-readobj not obj2yaml opt
+    yaml2obj
     )
 endif()
 

diff  --git a/lld/test/MachO/fat-arch.s b/lld/test/MachO/fat-arch.s
new file mode 100644
index 000000000000..7cdd800728ea
--- /dev/null
+++ b/lld/test/MachO/fat-arch.s
@@ -0,0 +1,16 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=i386-apple-darwin %s -o %t.i386.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %s -o %t.x86_64.o
+# RUN: llvm-lipo %t.i386.o %t.x86_64.o -create -o %t.fat.o
+# RUN: lld -flavor darwinnew -arch x86_64 -o /dev/null %t.fat.o
+
+# RUN: llvm-lipo %t.i386.o -create -o %t.noarch.o
+# RUN: not lld -flavor darwinnew -arch x86_64 -o /dev/null %t.noarch.o 2>&1 | \
+# RUN:    FileCheck %s -DFILE=%t.noarch.o
+# CHECK: error: unable to find matching architecture in [[FILE]]
+
+.text
+.global _main
+_main:
+  mov $0, %eax
+  ret

diff  --git a/lld/test/MachO/invalid-fat-narch.s b/lld/test/MachO/invalid-fat-narch.s
new file mode 100644
index 000000000000..265b7b8fa41c
--- /dev/null
+++ b/lld/test/MachO/invalid-fat-narch.s
@@ -0,0 +1,12 @@
+# REQUIRES: x86
+# RUN: yaml2obj %s -o %t.o
+# RUN: not lld -flavor darwinnew -arch x86_64 -o /dev/null %t.o 2>&1 | \
+# RUN:    FileCheck %s -DFILE=%t.o
+# CHECK: error: [[FILE]]: fat_arch struct extends beyond end of file
+
+!fat-mach-o
+FatHeader:
+  magic:           0xCAFEBABE
+  nfat_arch:       2
+FatArchs:
+Slices:

diff  --git a/lld/test/MachO/invalid-fat-offset.s b/lld/test/MachO/invalid-fat-offset.s
new file mode 100644
index 000000000000..fc662e3f56c7
--- /dev/null
+++ b/lld/test/MachO/invalid-fat-offset.s
@@ -0,0 +1,22 @@
+# REQUIRES: x86
+# RUN: yaml2obj %s -o %t.o
+# RUN: not lld -flavor darwinnew -arch x86_64 -o /dev/null %t.o 2>&1 | \
+# RUN:    FileCheck %s -DFILE=%t.o
+# CHECK: error: [[FILE]]: slice extends beyond end of file
+
+!fat-mach-o
+FatHeader:
+  magic:           0xCAFEBABE
+  nfat_arch:       2
+FatArchs:
+  - cputype:         0x01000007
+    cpusubtype:      0x00000003
+    offset:          0x0000000000001000
+    size:            0
+    align:           12
+  - cputype:         0x00000007
+    cpusubtype:      0x00000003
+    offset:          0x000000000000B000
+    size:            0
+    align:           12
+Slices:


        


More information about the llvm-commits mailing list