[lld-macho] Support reading of universal binaries

Differential Revision: https://reviews.llvm.org/D77006
This commit is contained in:
Jez Ng 2020-04-29 15:42:36 -07:00 committed by Shoaib Meenai
parent 89285a1a97
commit 918948db4d
5 changed files with 78 additions and 3 deletions

View File

@ -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 different 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;
}

View File

@ -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()

16
lld/test/MachO/fat-arch.s Normal file
View File

@ -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

View File

@ -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:

View File

@ -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: