From 8ca366935b055283b571ba0893f53a7a18ac59bb Mon Sep 17 00:00:00 2001 From: Jez Ng Date: Tue, 13 Apr 2021 12:39:24 -0400 Subject: [PATCH] Revert "[lld-macho] Add support for arm64_32" and other stacked diffs This reverts commits: * 8914902b01a3f8bdea9c71a0d9d23e4ee0ae80e4 * 35a745d814e1cde3de25d0d959fddc31e1061a41 * 682d1dfe09436857aa3b64365b5cc6fcbf1f043b --- lld/MachO/Arch/ARM64.cpp | 201 +++++++++++++++++- lld/MachO/Arch/ARM64Common.cpp | 111 ---------- lld/MachO/Arch/ARM64Common.h | 141 ------------ lld/MachO/Arch/ARM64_32.cpp | 116 ---------- lld/MachO/CMakeLists.txt | 2 - lld/MachO/Driver.cpp | 2 - lld/MachO/MachOStructs.h | 7 - lld/MachO/Relocations.h | 14 -- lld/MachO/SyntheticSections.h | 2 - lld/MachO/Target.h | 1 - lld/MachO/UnwindInfoSection.cpp | 120 ++++------- lld/MachO/UnwindInfoSection.h | 54 ++++- lld/MachO/Writer.cpp | 15 +- .../Inputs/WatchOS.sdk/usr/lib/libSystem.tbd | 14 -- .../Inputs/WatchOS.sdk/usr/lib/libc++.tbd | 14 -- .../Inputs/WatchOS.sdk/usr/lib/libc++abi.tbd | 14 -- lld/test/MachO/arm64-32-reloc-got-load.s | 48 ----- lld/test/MachO/arm64-32-stubs.s | 60 ------ lld/test/MachO/compact-unwind.s | 25 +-- lld/test/MachO/header.s | 26 +-- lld/test/MachO/lit.local.cfg | 16 +- lld/test/MachO/segments.s | 40 ++-- 22 files changed, 322 insertions(+), 721 deletions(-) delete mode 100644 lld/MachO/Arch/ARM64Common.cpp delete mode 100644 lld/MachO/Arch/ARM64Common.h delete mode 100644 lld/MachO/Arch/ARM64_32.cpp delete mode 100644 lld/test/MachO/Inputs/WatchOS.sdk/usr/lib/libSystem.tbd delete mode 100644 lld/test/MachO/Inputs/WatchOS.sdk/usr/lib/libc++.tbd delete mode 100644 lld/test/MachO/Inputs/WatchOS.sdk/usr/lib/libc++abi.tbd delete mode 100644 lld/test/MachO/arm64-32-reloc-got-load.s delete mode 100644 lld/test/MachO/arm64-32-stubs.s diff --git a/lld/MachO/Arch/ARM64.cpp b/lld/MachO/Arch/ARM64.cpp index a5953637b7f7..f0d0b308c3ed 100644 --- a/lld/MachO/Arch/ARM64.cpp +++ b/lld/MachO/Arch/ARM64.cpp @@ -6,7 +6,6 @@ // //===----------------------------------------------------------------------===// -#include "Arch/ARM64Common.h" #include "InputFiles.h" #include "Symbols.h" #include "SyntheticSections.h" @@ -26,13 +25,22 @@ using namespace lld::macho; namespace { -struct ARM64 : ARM64Common { +struct ARM64 : TargetInfo { ARM64(); + + int64_t getEmbeddedAddend(MemoryBufferRef, uint64_t offset, + const relocation_info) const override; + void relocateOne(uint8_t *loc, const Reloc &, uint64_t va, + uint64_t pc) const override; + void writeStub(uint8_t *buf, const Symbol &) const override; void writeStubHelperHeader(uint8_t *buf) const override; void writeStubHelperEntry(uint8_t *buf, const DylibSymbol &, uint64_t entryAddr) const override; + + void relaxGotLoad(uint8_t *loc, uint8_t type) const override; const RelocAttrs &getRelocAttrs(uint8_t type) const override; + uint64_t getPageSize() const override { return 16 * 1024; } }; } // namespace @@ -69,6 +77,140 @@ const RelocAttrs &ARM64::getRelocAttrs(uint8_t type) const { return relocAttrsArray[type]; } +int64_t ARM64::getEmbeddedAddend(MemoryBufferRef mb, uint64_t offset, + const relocation_info rel) const { + if (rel.r_type != ARM64_RELOC_UNSIGNED && + rel.r_type != ARM64_RELOC_SUBTRACTOR) { + // All other reloc types should use the ADDEND relocation to store their + // addends. + // TODO(gkm): extract embedded addend just so we can assert that it is 0 + return 0; + } + + auto *buf = reinterpret_cast(mb.getBufferStart()); + const uint8_t *loc = buf + offset + rel.r_address; + switch (rel.r_length) { + case 2: + return static_cast(read32le(loc)); + case 3: + return read64le(loc); + default: + llvm_unreachable("invalid r_length"); + } +} + +inline uint64_t bitField(uint64_t value, int right, int width, int left) { + return ((value >> right) & ((1 << width) - 1)) << left; +} + +// 25 0 +// +-----------+---------------------------------------------------+ +// | | imm26 | +// +-----------+---------------------------------------------------+ + +inline uint64_t encodeBranch26(const Reloc &r, uint64_t base, uint64_t va) { + checkInt(r, va, 28); + // Since branch destinations are 4-byte aligned, the 2 least- + // significant bits are 0. They are right shifted off the end. + return (base | bitField(va, 2, 26, 0)); +} + +inline uint64_t encodeBranch26(SymbolDiagnostic d, uint64_t base, uint64_t va) { + checkInt(d, va, 28); + return (base | bitField(va, 2, 26, 0)); +} + +// 30 29 23 5 +// +-+---+---------+-------------------------------------+---------+ +// | |ilo| | immhi | | +// +-+---+---------+-------------------------------------+---------+ + +inline uint64_t encodePage21(const Reloc &r, uint64_t base, uint64_t va) { + checkInt(r, va, 35); + return (base | bitField(va, 12, 2, 29) | bitField(va, 14, 19, 5)); +} + +inline uint64_t encodePage21(SymbolDiagnostic d, uint64_t base, uint64_t va) { + checkInt(d, va, 35); + return (base | bitField(va, 12, 2, 29) | bitField(va, 14, 19, 5)); +} + +// 21 10 +// +-------------------+-----------------------+-------------------+ +// | | imm12 | | +// +-------------------+-----------------------+-------------------+ + +inline uint64_t encodePageOff12(uint32_t base, uint64_t va) { + int scale = 0; + if ((base & 0x3b00'0000) == 0x3900'0000) { // load/store + scale = base >> 30; + if (scale == 0 && (base & 0x0480'0000) == 0x0480'0000) // 128-bit variant + scale = 4; + } + + // TODO(gkm): extract embedded addend and warn if != 0 + // uint64_t addend = ((base & 0x003FFC00) >> 10); + return (base | bitField(va, scale, 12 - scale, 10)); +} + +inline uint64_t pageBits(uint64_t address) { + const uint64_t pageMask = ~0xfffull; + return address & pageMask; +} + +// For instruction relocations (load, store, add), the base +// instruction is pre-populated in the text section. A pre-populated +// instruction has opcode & register-operand bits set, with immediate +// operands zeroed. We read it from text, OR-in the immediate +// operands, then write-back the completed instruction. + +void ARM64::relocateOne(uint8_t *loc, const Reloc &r, uint64_t value, + uint64_t pc) const { + uint32_t base = ((r.length == 2) ? read32le(loc) : 0); + value += r.addend; + switch (r.type) { + case ARM64_RELOC_BRANCH26: + value = encodeBranch26(r, base, value - pc); + break; + case ARM64_RELOC_SUBTRACTOR: + case ARM64_RELOC_UNSIGNED: + if (r.length == 2) + checkInt(r, value, 32); + break; + case ARM64_RELOC_POINTER_TO_GOT: + if (r.pcrel) + value -= pc; + checkInt(r, value, 32); + break; + case ARM64_RELOC_PAGE21: + case ARM64_RELOC_GOT_LOAD_PAGE21: + case ARM64_RELOC_TLVP_LOAD_PAGE21: { + assert(r.pcrel); + value = encodePage21(r, base, pageBits(value) - pageBits(pc)); + break; + } + case ARM64_RELOC_PAGEOFF12: + case ARM64_RELOC_GOT_LOAD_PAGEOFF12: + case ARM64_RELOC_TLVP_LOAD_PAGEOFF12: + assert(!r.pcrel); + value = encodePageOff12(base, value); + break; + default: + llvm_unreachable("unexpected relocation type"); + } + + switch (r.length) { + case 2: + write32le(loc, value); + break; + case 3: + write64le(loc, value); + break; + default: + llvm_unreachable("invalid r_length"); + } +} + static constexpr uint32_t stubCode[] = { 0x90000010, // 00: adrp x16, __la_symbol_ptr@page 0xf9400210, // 04: ldr x16, [x16, __la_symbol_ptr@pageoff] @@ -76,7 +218,15 @@ static constexpr uint32_t stubCode[] = { }; void ARM64::writeStub(uint8_t *buf8, const Symbol &sym) const { - ::writeStub(buf8, sym); + auto *buf32 = reinterpret_cast(buf8); + uint64_t pcPageBits = + pageBits(in.stubs->addr + sym.stubsIndex * sizeof(stubCode)); + uint64_t lazyPointerVA = + in.lazyPointers->addr + sym.stubsIndex * LP64::wordSize; + buf32[0] = encodePage21({&sym, "stub"}, stubCode[0], + pageBits(lazyPointerVA) - pcPageBits); + buf32[1] = encodePageOff12(stubCode[1], lazyPointerVA); + buf32[2] = stubCode[2]; } static constexpr uint32_t stubHelperHeaderCode[] = { @@ -89,7 +239,22 @@ static constexpr uint32_t stubHelperHeaderCode[] = { }; void ARM64::writeStubHelperHeader(uint8_t *buf8) const { - ::writeStubHelperHeader(buf8); + auto *buf32 = reinterpret_cast(buf8); + auto pcPageBits = [](int i) { + return pageBits(in.stubHelper->addr + i * sizeof(uint32_t)); + }; + uint64_t loaderVA = in.imageLoaderCache->getVA(); + SymbolDiagnostic d = {nullptr, "stub header helper"}; + buf32[0] = encodePage21(d, stubHelperHeaderCode[0], + pageBits(loaderVA) - pcPageBits(0)); + buf32[1] = encodePageOff12(stubHelperHeaderCode[1], loaderVA); + buf32[2] = stubHelperHeaderCode[2]; + uint64_t binderVA = + in.got->addr + in.stubHelper->stubBinder->gotIndex * LP64::wordSize; + buf32[3] = encodePage21(d, stubHelperHeaderCode[3], + pageBits(binderVA) - pcPageBits(3)); + buf32[4] = encodePageOff12(stubHelperHeaderCode[4], binderVA); + buf32[5] = stubHelperHeaderCode[5]; } static constexpr uint32_t stubHelperEntryCode[] = { @@ -100,10 +265,34 @@ static constexpr uint32_t stubHelperEntryCode[] = { void ARM64::writeStubHelperEntry(uint8_t *buf8, const DylibSymbol &sym, uint64_t entryVA) const { - ::writeStubHelperEntry(buf8, sym, entryVA); + auto *buf32 = reinterpret_cast(buf8); + auto pcVA = [entryVA](int i) { return entryVA + i * sizeof(uint32_t); }; + uint64_t stubHelperHeaderVA = in.stubHelper->addr; + buf32[0] = stubHelperEntryCode[0]; + buf32[1] = encodeBranch26({&sym, "stub helper"}, stubHelperEntryCode[1], + stubHelperHeaderVA - pcVA(1)); + buf32[2] = sym.lazyBindOffset; } -ARM64::ARM64() : ARM64Common(LP64()) { +void ARM64::relaxGotLoad(uint8_t *loc, uint8_t type) const { + // The instruction format comments below are quoted from + // ArmĀ® Architecture Reference Manual + // Armv8, for Armv8-A architecture profile + // ARM DDI 0487G.a (ID011921) + uint32_t instruction = read32le(loc); + // C6.2.132 LDR (immediate) + // LDR , [{, #}] + if ((instruction & 0xffc00000) != 0xf9400000) + error(getRelocAttrs(type).name + " reloc requires LDR instruction"); + assert(((instruction >> 10) & 0xfff) == 0 && + "non-zero embedded LDR immediate"); + // C6.2.4 ADD (immediate) + // ADD , , #{, } + instruction = ((instruction & 0x001fffff) | 0x91000000); + write32le(loc, instruction); +} + +ARM64::ARM64() : TargetInfo(LP64()) { cpuType = CPU_TYPE_ARM64; cpuSubtype = CPU_SUBTYPE_ARM64_ALL; diff --git a/lld/MachO/Arch/ARM64Common.cpp b/lld/MachO/Arch/ARM64Common.cpp deleted file mode 100644 index 88e7286d1450..000000000000 --- a/lld/MachO/Arch/ARM64Common.cpp +++ /dev/null @@ -1,111 +0,0 @@ -//===- ARM64Common.cpp ----------------------------------------------------===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -#include "Arch/ARM64Common.h" - -#include "lld/Common/ErrorHandler.h" -#include "llvm/Support/Endian.h" - -using namespace llvm::MachO; -using namespace llvm::support::endian; -using namespace lld; -using namespace lld::macho; - -int64_t ARM64Common::getEmbeddedAddend(MemoryBufferRef mb, uint64_t offset, - const relocation_info rel) const { - if (rel.r_type != ARM64_RELOC_UNSIGNED && - rel.r_type != ARM64_RELOC_SUBTRACTOR) { - // All other reloc types should use the ADDEND relocation to store their - // addends. - // TODO(gkm): extract embedded addend just so we can assert that it is 0 - return 0; - } - - const auto *buf = reinterpret_cast(mb.getBufferStart()); - const uint8_t *loc = buf + offset + rel.r_address; - switch (rel.r_length) { - case 2: - return static_cast(read32le(loc)); - case 3: - return read64le(loc); - default: - llvm_unreachable("invalid r_length"); - } -} - -// For instruction relocations (load, store, add), the base -// instruction is pre-populated in the text section. A pre-populated -// instruction has opcode & register-operand bits set, with immediate -// operands zeroed. We read it from text, OR-in the immediate -// operands, then write-back the completed instruction. - -void ARM64Common::relocateOne(uint8_t *loc, const Reloc &r, uint64_t value, - uint64_t pc) const { - uint32_t base = ((r.length == 2) ? read32le(loc) : 0); - value += r.addend; - switch (r.type) { - case ARM64_RELOC_BRANCH26: - value = encodeBranch26(r, base, value - pc); - break; - case ARM64_RELOC_SUBTRACTOR: - case ARM64_RELOC_UNSIGNED: - if (r.length == 2) - checkInt(r, value, 32); - break; - case ARM64_RELOC_POINTER_TO_GOT: - if (r.pcrel) - value -= pc; - checkInt(r, value, 32); - break; - case ARM64_RELOC_PAGE21: - case ARM64_RELOC_GOT_LOAD_PAGE21: - case ARM64_RELOC_TLVP_LOAD_PAGE21: { - assert(r.pcrel); - value = encodePage21(r, base, pageBits(value) - pageBits(pc)); - break; - } - case ARM64_RELOC_PAGEOFF12: - case ARM64_RELOC_GOT_LOAD_PAGEOFF12: - case ARM64_RELOC_TLVP_LOAD_PAGEOFF12: - assert(!r.pcrel); - value = encodePageOff12(base, value); - break; - default: - llvm_unreachable("unexpected relocation type"); - } - - switch (r.length) { - case 2: - write32le(loc, value); - break; - case 3: - write64le(loc, value); - break; - default: - llvm_unreachable("invalid r_length"); - } -} - -void ARM64Common::relaxGotLoad(uint8_t *loc, uint8_t type) const { - // The instruction format comments below are quoted from - // ArmĀ® Architecture Reference Manual - // Armv8, for Armv8-A architecture profile - // ARM DDI 0487G.a (ID011921) - uint32_t instruction = read32le(loc); - // C6.2.132 LDR (immediate) - // This matches both the 64- and 32-bit variants: - // LDR <(X|W)t>, [{, #}] - if ((instruction & 0xbfc00000) != 0xb9400000) - error(getRelocAttrs(type).name + " reloc requires LDR instruction"); - assert(((instruction >> 10) & 0xfff) == 0 && - "non-zero embedded LDR immediate"); - // C6.2.4 ADD (immediate) - // ADD , , #{, } - instruction = ((instruction & 0x001fffff) | 0x91000000); - write32le(loc, instruction); -} diff --git a/lld/MachO/Arch/ARM64Common.h b/lld/MachO/Arch/ARM64Common.h deleted file mode 100644 index 1e858f6748c7..000000000000 --- a/lld/MachO/Arch/ARM64Common.h +++ /dev/null @@ -1,141 +0,0 @@ -//===- ARM64Common.h --------------------------------------------*- 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 LLD_MACHO_ARCH_ARM64COMMON_H -#define LLD_MACHO_ARCH_ARM64COMMON_H - -#include "InputFiles.h" -#include "Symbols.h" -#include "SyntheticSections.h" -#include "Target.h" - -#include "llvm/BinaryFormat/MachO.h" - -namespace lld { -namespace macho { - -struct ARM64Common : TargetInfo { - template ARM64Common(LP lp) : TargetInfo(lp) {} - - int64_t getEmbeddedAddend(MemoryBufferRef, uint64_t offset, - const llvm::MachO::relocation_info) const override; - void relocateOne(uint8_t *loc, const Reloc &, uint64_t va, - uint64_t pc) const override; - - void relaxGotLoad(uint8_t *loc, uint8_t type) const override; - uint64_t getPageSize() const override { return 16 * 1024; } -}; - -inline uint64_t bitField(uint64_t value, int right, int width, int left) { - return ((value >> right) & ((1 << width) - 1)) << left; -} - -// 25 0 -// +-----------+---------------------------------------------------+ -// | | imm26 | -// +-----------+---------------------------------------------------+ - -inline uint64_t encodeBranch26(const Reloc &r, uint64_t base, uint64_t va) { - checkInt(r, va, 28); - // Since branch destinations are 4-byte aligned, the 2 least- - // significant bits are 0. They are right shifted off the end. - return (base | bitField(va, 2, 26, 0)); -} - -inline uint64_t encodeBranch26(SymbolDiagnostic d, uint64_t base, uint64_t va) { - checkInt(d, va, 28); - return (base | bitField(va, 2, 26, 0)); -} - -// 30 29 23 5 -// +-+---+---------+-------------------------------------+---------+ -// | |ilo| | immhi | | -// +-+---+---------+-------------------------------------+---------+ - -inline uint64_t encodePage21(const Reloc &r, uint64_t base, uint64_t va) { - checkInt(r, va, 35); - return (base | bitField(va, 12, 2, 29) | bitField(va, 14, 19, 5)); -} - -inline uint64_t encodePage21(SymbolDiagnostic d, uint64_t base, uint64_t va) { - checkInt(d, va, 35); - return (base | bitField(va, 12, 2, 29) | bitField(va, 14, 19, 5)); -} - -// 21 10 -// +-------------------+-----------------------+-------------------+ -// | | imm12 | | -// +-------------------+-----------------------+-------------------+ - -inline uint64_t encodePageOff12(uint32_t base, uint64_t va) { - int scale = 0; - if ((base & 0x3b00'0000) == 0x3900'0000) { // load/store - scale = base >> 30; - if (scale == 0 && (base & 0x0480'0000) == 0x0480'0000) // 128-bit variant - scale = 4; - } - - // TODO(gkm): extract embedded addend and warn if != 0 - // uint64_t addend = ((base & 0x003FFC00) >> 10); - return (base | bitField(va, scale, 12 - scale, 10)); -} - -inline uint64_t pageBits(uint64_t address) { - const uint64_t pageMask = ~0xfffull; - return address & pageMask; -} - -template -inline void writeStub(uint8_t *buf8, const macho::Symbol &sym) { - auto *buf32 = reinterpret_cast(buf8); - uint64_t pcPageBits = - pageBits(in.stubs->addr + sym.stubsIndex * sizeof(stubCode)); - uint64_t lazyPointerVA = - in.lazyPointers->addr + sym.stubsIndex * LP::wordSize; - buf32[0] = encodePage21({&sym, "stub"}, stubCode[0], - pageBits(lazyPointerVA) - pcPageBits); - buf32[1] = encodePageOff12(stubCode[1], lazyPointerVA); - buf32[2] = stubCode[2]; -} - -template -inline void writeStubHelperHeader(uint8_t *buf8) { - auto *buf32 = reinterpret_cast(buf8); - auto pcPageBits = [](int i) { - return pageBits(in.stubHelper->addr + i * sizeof(uint32_t)); - }; - uint64_t loaderVA = in.imageLoaderCache->getVA(); - SymbolDiagnostic d = {nullptr, "stub header helper"}; - buf32[0] = encodePage21(d, stubHelperHeaderCode[0], - pageBits(loaderVA) - pcPageBits(0)); - buf32[1] = encodePageOff12(stubHelperHeaderCode[1], loaderVA); - buf32[2] = stubHelperHeaderCode[2]; - uint64_t binderVA = - in.got->addr + in.stubHelper->stubBinder->gotIndex * LP::wordSize; - buf32[3] = encodePage21(d, stubHelperHeaderCode[3], - pageBits(binderVA) - pcPageBits(3)); - buf32[4] = encodePageOff12(stubHelperHeaderCode[4], binderVA); - buf32[5] = stubHelperHeaderCode[5]; -} - -template -void writeStubHelperEntry(uint8_t *buf8, const DylibSymbol &sym, - uint64_t entryVA) { - auto *buf32 = reinterpret_cast(buf8); - auto pcVA = [entryVA](int i) { return entryVA + i * sizeof(uint32_t); }; - uint64_t stubHelperHeaderVA = in.stubHelper->addr; - buf32[0] = stubHelperEntryCode[0]; - buf32[1] = encodeBranch26({&sym, "stub helper"}, stubHelperEntryCode[1], - stubHelperHeaderVA - pcVA(1)); - buf32[2] = sym.lazyBindOffset; -} - -} // namespace macho -} // namespace lld - -#endif diff --git a/lld/MachO/Arch/ARM64_32.cpp b/lld/MachO/Arch/ARM64_32.cpp deleted file mode 100644 index f0d39c5b1a82..000000000000 --- a/lld/MachO/Arch/ARM64_32.cpp +++ /dev/null @@ -1,116 +0,0 @@ -//===- ARM64_32.cpp -//----------------------------------------------------------===// -// -// 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 -// -//===----------------------------------------------------------------------===// - -#include "Arch/ARM64Common.h" -#include "InputFiles.h" -#include "Symbols.h" -#include "SyntheticSections.h" -#include "Target.h" - -#include "lld/Common/ErrorHandler.h" -#include "llvm/ADT/SmallVector.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/BinaryFormat/MachO.h" -#include "llvm/Support/Endian.h" -#include "llvm/Support/MathExtras.h" - -using namespace llvm::MachO; -using namespace llvm::support::endian; -using namespace lld; -using namespace lld::macho; - -namespace { - -struct ARM64_32 : ARM64Common { - ARM64_32(); - void writeStub(uint8_t *buf, const Symbol &) const override; - void writeStubHelperHeader(uint8_t *buf) const override; - void writeStubHelperEntry(uint8_t *buf, const DylibSymbol &, - uint64_t entryAddr) const override; - const RelocAttrs &getRelocAttrs(uint8_t type) const override; -}; - -} // namespace - -// These are very similar to ARM64's relocation attributes, except that we don't -// have the BYTE8 flag set. -const RelocAttrs &ARM64_32::getRelocAttrs(uint8_t type) const { - static const std::array relocAttrsArray{{ -#define B(x) RelocAttrBits::x - {"UNSIGNED", B(UNSIGNED) | B(ABSOLUTE) | B(EXTERN) | B(LOCAL) | B(BYTE4)}, - {"SUBTRACTOR", B(SUBTRAHEND) | B(BYTE4)}, - {"BRANCH26", B(PCREL) | B(EXTERN) | B(BRANCH) | B(BYTE4)}, - {"PAGE21", B(PCREL) | B(EXTERN) | B(BYTE4)}, - {"PAGEOFF12", B(ABSOLUTE) | B(EXTERN) | B(BYTE4)}, - {"GOT_LOAD_PAGE21", B(PCREL) | B(EXTERN) | B(GOT) | B(BYTE4)}, - {"GOT_LOAD_PAGEOFF12", - B(ABSOLUTE) | B(EXTERN) | B(GOT) | B(LOAD) | B(BYTE4)}, - {"POINTER_TO_GOT", B(PCREL) | B(EXTERN) | B(GOT) | B(POINTER) | B(BYTE4)}, - {"TLVP_LOAD_PAGE21", B(PCREL) | B(EXTERN) | B(TLV) | B(BYTE4)}, - {"TLVP_LOAD_PAGEOFF12", - B(ABSOLUTE) | B(EXTERN) | B(TLV) | B(LOAD) | B(BYTE4)}, - {"ADDEND", B(ADDEND)}, -#undef B - }}; - assert(type < relocAttrsArray.size() && "invalid relocation type"); - if (type >= relocAttrsArray.size()) - return invalidRelocAttrs; - return relocAttrsArray[type]; -} - -// The stub code is fairly similar to ARM64's, except that we load pointers into -// 32-bit 'w' registers, instead of the 64-bit 'x' ones. - -static constexpr uint32_t stubCode[] = { - 0x90000010, // 00: adrp x16, __la_symbol_ptr@page - 0xb9400210, // 04: ldr w16, [x16, __la_symbol_ptr@pageoff] - 0xd61f0200, // 08: br x16 -}; - -void ARM64_32::writeStub(uint8_t *buf8, const Symbol &sym) const { - ::writeStub(buf8, sym); -} - -static constexpr uint32_t stubHelperHeaderCode[] = { - 0x90000011, // 00: adrp x17, _dyld_private@page - 0x91000231, // 04: add x17, x17, _dyld_private@pageoff - 0xa9bf47f0, // 08: stp x16/x17, [sp, #-16]! - 0x90000010, // 0c: adrp x16, dyld_stub_binder@page - 0xb9400210, // 10: ldr w16, [x16, dyld_stub_binder@pageoff] - 0xd61f0200, // 14: br x16 -}; - -void ARM64_32::writeStubHelperHeader(uint8_t *buf8) const { - ::writeStubHelperHeader(buf8); -} - -static constexpr uint32_t stubHelperEntryCode[] = { - 0x18000050, // 00: ldr w16, l0 - 0x14000000, // 04: b stubHelperHeader - 0x00000000, // 08: l0: .long 0 -}; - -void ARM64_32::writeStubHelperEntry(uint8_t *buf8, const DylibSymbol &sym, - uint64_t entryVA) const { - ::writeStubHelperEntry(buf8, sym, entryVA); -} - -ARM64_32::ARM64_32() : ARM64Common(ILP32()) { - cpuType = CPU_TYPE_ARM64_32; - cpuSubtype = CPU_SUBTYPE_ARM64_V8; - - stubSize = sizeof(stubCode); - stubHelperHeaderSize = sizeof(stubHelperHeaderCode); - stubHelperEntrySize = sizeof(stubHelperEntryCode); -} - -TargetInfo *macho::createARM64_32TargetInfo() { - static ARM64_32 t; - return &t; -} diff --git a/lld/MachO/CMakeLists.txt b/lld/MachO/CMakeLists.txt index 1cff068e8081..16b372945d07 100644 --- a/lld/MachO/CMakeLists.txt +++ b/lld/MachO/CMakeLists.txt @@ -7,8 +7,6 @@ include_directories(${LLVM_MAIN_SRC_DIR}/../libunwind/include) add_lld_library(lldMachO2 Arch/X86_64.cpp Arch/ARM64.cpp - Arch/ARM64Common.cpp - Arch/ARM64_32.cpp UnwindInfoSection.cpp Driver.cpp DriverUtils.cpp diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp index 0d4768f99964..ec20bdc92419 100644 --- a/lld/MachO/Driver.cpp +++ b/lld/MachO/Driver.cpp @@ -604,8 +604,6 @@ static TargetInfo *createTargetInfo(InputArgList &args) { return createX86_64TargetInfo(); case CPU_TYPE_ARM64: return createARM64TargetInfo(); - case CPU_TYPE_ARM64_32: - return createARM64_32TargetInfo(); default: fatal("missing or unsupported -arch " + archName); } diff --git a/lld/MachO/MachOStructs.h b/lld/MachO/MachOStructs.h index 44715bf29dac..6d9cc49a22e4 100644 --- a/lld/MachO/MachOStructs.h +++ b/lld/MachO/MachOStructs.h @@ -37,13 +37,6 @@ struct nlist { llvm::support::ulittle32_t n_value; }; -struct entry_point_command { - llvm::support::ulittle32_t cmd; - llvm::support::ulittle32_t cmdsize; - llvm::support::ulittle64_t entryoff; - llvm::support::ulittle64_t stacksize; -}; - } // namespace structs } // namespace lld diff --git a/lld/MachO/Relocations.h b/lld/MachO/Relocations.h index 91b2d00f26a1..6d31d27ec832 100644 --- a/lld/MachO/Relocations.h +++ b/lld/MachO/Relocations.h @@ -12,7 +12,6 @@ #include "llvm/ADT/BitmaskEnum.h" #include "llvm/ADT/PointerUnion.h" #include "llvm/BinaryFormat/MachO.h" -#include "llvm/Support/Endian.h" #include #include @@ -94,19 +93,6 @@ inline void checkUInt(Diagnostic d, uint64_t v, int bits) { reportRangeError(d, llvm::Twine(v), bits, 0, llvm::maxUIntN(bits)); } -inline void writeAddress(uint8_t *loc, uint64_t addr, uint8_t length) { - switch (length) { - case 2: - llvm::support::endian::write32le(loc, addr); - break; - case 3: - llvm::support::endian::write64le(loc, addr); - break; - default: - llvm_unreachable("invalid r_length"); - } -} - extern const RelocAttrs invalidRelocAttrs; } // namespace macho diff --git a/lld/MachO/SyntheticSections.h b/lld/MachO/SyntheticSections.h index 38d966e61825..eaad8aa3455f 100644 --- a/lld/MachO/SyntheticSections.h +++ b/lld/MachO/SyntheticSections.h @@ -32,7 +32,6 @@ class Defined; class DylibSymbol; class LoadCommand; class ObjFile; -class UnwindInfoSection; class SyntheticSection : public OutputSection { public: @@ -504,7 +503,6 @@ struct InStruct { StubsSection *stubs = nullptr; StubHelperSection *stubHelper = nullptr; ImageLoaderCacheSection *imageLoaderCache = nullptr; - UnwindInfoSection *unwindInfo = nullptr; }; extern InStruct in; diff --git a/lld/MachO/Target.h b/lld/MachO/Target.h index c9747e9b62f2..ac9c55659893 100644 --- a/lld/MachO/Target.h +++ b/lld/MachO/Target.h @@ -79,7 +79,6 @@ public: TargetInfo *createX86_64TargetInfo(); TargetInfo *createARM64TargetInfo(); -TargetInfo *createARM64_32TargetInfo(); struct LP64 { using mach_header = llvm::MachO::mach_header_64; diff --git a/lld/MachO/UnwindInfoSection.cpp b/lld/MachO/UnwindInfoSection.cpp index b94642404091..52abdc6b0400 100644 --- a/lld/MachO/UnwindInfoSection.cpp +++ b/lld/MachO/UnwindInfoSection.cpp @@ -91,62 +91,31 @@ using namespace lld::macho; // TODO(gkm): prune __eh_frame entries superseded by __unwind_info // TODO(gkm): how do we align the 2nd-level pages? -using EncodingMap = llvm::DenseMap; +UnwindInfoSection::UnwindInfoSection() + : SyntheticSection(segment_names::text, section_names::unwindInfo) { + align = 4; // mimic ld64 +} -template struct CompactUnwindEntry { - Ptr functionAddress; - uint32_t functionLength; - compact_unwind_encoding_t encoding; - Ptr personality; - Ptr lsda; -}; +bool UnwindInfoSection::isNeeded() const { + return (compactUnwindSection != nullptr); +} -struct SecondLevelPage { - uint32_t kind; - size_t entryIndex; - size_t entryCount; - size_t byteCount; - std::vector localEncodings; - EncodingMap localEncodingIndexes; -}; - -template class UnwindInfoSectionImpl : public UnwindInfoSection { -public: - void prepareRelocations(InputSection *) override; - void finalize() override; - void writeTo(uint8_t *buf) const override; - -private: - std::vector> commonEncodings; - EncodingMap commonEncodingIndexes; - // Indices of personality functions within the GOT. - std::vector personalities; - SmallDenseMap, Symbol *> - personalityTable; - std::vector lsdaEntries; - // Map of function offset (from the image base) to an index within the LSDA - // array. - llvm::DenseMap functionToLsdaIndex; - std::vector> cuVector; - std::vector *> cuPtrVector; - std::vector secondLevelPages; - uint64_t level2PagesOffset = 0; -}; +SmallDenseMap, Symbol *> + personalityTable; // Compact unwind relocations have different semantics, so we handle them in a // separate code path from regular relocations. First, we do not wish to add // rebase opcodes for __LD,__compact_unwind, because that section doesn't // actually end up in the final binary. Second, personality pointers always // reside in the GOT and must be treated specially. -template -void UnwindInfoSectionImpl::prepareRelocations(InputSection *isec) { +void macho::prepareCompactUnwind(InputSection *isec) { assert(isec->segname == segment_names::ld && isec->name == section_names::compactUnwind); for (Reloc &r : isec->relocs) { assert(target->hasAttr(r.type, RelocAttrBits::UNSIGNED)); - if (r.offset % sizeof(CompactUnwindEntry) != - offsetof(CompactUnwindEntry, personality)) + if (r.offset % sizeof(CompactUnwindEntry64) != + offsetof(struct CompactUnwindEntry64, personality)) continue; if (auto *s = r.referent.dyn_cast()) { @@ -203,10 +172,8 @@ static void checkTextSegment(InputSection *isec) { // before converting it to post-link form. There should only be absolute // relocations here: since we are not emitting the pre-link CU section, there // is no source address to make a relative location meaningful. -template -static void -relocateCompactUnwind(MergedOutputSection *compactUnwindSection, - std::vector> &cuVector) { +static void relocateCompactUnwind(MergedOutputSection *compactUnwindSection, + std::vector &cuVector) { for (const InputSection *isec : compactUnwindSection->inputs) { uint8_t *buf = reinterpret_cast(cuVector.data()) + isec->outSecFileOff; @@ -228,23 +195,21 @@ relocateCompactUnwind(MergedOutputSection *compactUnwindSection, checkTextSegment(referentIsec); referentVA = referentIsec->getVA() + r.addend; } - - writeAddress(buf + r.offset, referentVA, r.length); + support::endian::write64le(buf + r.offset, referentVA); } } } // There should only be a handful of unique personality pointers, so we can // encode them as 2-bit indices into a small array. -template -void encodePersonalities( - const std::vector *> &cuPtrVector, - std::vector &personalities) { - for (CompactUnwindEntry *cu : cuPtrVector) { +void encodePersonalities(const std::vector &cuPtrVector, + std::vector &personalities) { + for (CompactUnwindEntry64 *cu : cuPtrVector) { if (cu->personality == 0) continue; + uint32_t personalityOffset = cu->personality - in.header->addr; // Linear search is fast enough for a small array. - auto it = find(personalities, cu->personality); + auto it = find(personalities, personalityOffset); uint32_t personalityIndex; // 1-based index if (it != personalities.end()) { personalityIndex = std::distance(personalities.begin(), it) + 1; @@ -263,7 +228,7 @@ void encodePersonalities( // Scan the __LD,__compact_unwind entries and compute the space needs of // __TEXT,__unwind_info and __TEXT,__eh_frame -template void UnwindInfoSectionImpl::finalize() { +void UnwindInfoSection::finalize() { if (compactUnwindSection == nullptr) return; @@ -275,23 +240,21 @@ template void UnwindInfoSectionImpl::finalize() { // encoding+personality+lsda. Folding is necessary because it reduces // the number of CU entries by as much as 3 orders of magnitude! compactUnwindSection->finalize(); - assert(compactUnwindSection->getSize() % sizeof(CompactUnwindEntry) == - 0); + assert(compactUnwindSection->getSize() % sizeof(CompactUnwindEntry64) == 0); size_t cuCount = - compactUnwindSection->getSize() / sizeof(CompactUnwindEntry); + compactUnwindSection->getSize() / sizeof(CompactUnwindEntry64); cuVector.resize(cuCount); relocateCompactUnwind(compactUnwindSection, cuVector); // Rather than sort & fold the 32-byte entries directly, we create a // vector of pointers to entries and sort & fold that instead. cuPtrVector.reserve(cuCount); - for (CompactUnwindEntry &cuEntry : cuVector) + for (CompactUnwindEntry64 &cuEntry : cuVector) cuPtrVector.emplace_back(&cuEntry); - std::sort( - cuPtrVector.begin(), cuPtrVector.end(), - [](const CompactUnwindEntry *a, const CompactUnwindEntry *b) { - return a->functionAddress < b->functionAddress; - }); + std::sort(cuPtrVector.begin(), cuPtrVector.end(), + [](const CompactUnwindEntry64 *a, const CompactUnwindEntry64 *b) { + return a->functionAddress < b->functionAddress; + }); // Fold adjacent entries with matching encoding+personality+lsda // We use three iterators on the same cuPtrVector to fold in-situ: @@ -317,7 +280,7 @@ template void UnwindInfoSectionImpl::finalize() { // Count frequencies of the folded encodings EncodingMap encodingFrequencies; - for (const CompactUnwindEntry *cuPtrEntry : cuPtrVector) + for (const CompactUnwindEntry64 *cuPtrEntry : cuPtrVector) encodingFrequencies[cuPtrEntry->encoding]++; // Make a vector of encodings, sorted by descending frequency @@ -353,7 +316,7 @@ template void UnwindInfoSectionImpl::finalize() { // If more entries fit in the regular format, we use that. for (size_t i = 0; i < cuPtrVector.size();) { secondLevelPages.emplace_back(); - SecondLevelPage &page = secondLevelPages.back(); + UnwindInfoSection::SecondLevelPage &page = secondLevelPages.back(); page.entryIndex = i; uintptr_t functionAddressMax = cuPtrVector[i]->functionAddress + COMPRESSED_ENTRY_FUNC_OFFSET_MASK; @@ -363,7 +326,7 @@ template void UnwindInfoSectionImpl::finalize() { sizeof(unwind_info_compressed_second_level_page_header) / sizeof(uint32_t); while (wordsRemaining >= 1 && i < cuPtrVector.size()) { - const CompactUnwindEntry *cuPtr = cuPtrVector[i]; + const CompactUnwindEntry64 *cuPtr = cuPtrVector[i]; if (cuPtr->functionAddress >= functionAddressMax) { break; } else if (commonEncodingIndexes.count(cuPtr->encoding) || @@ -396,7 +359,7 @@ template void UnwindInfoSectionImpl::finalize() { } } - for (const CompactUnwindEntry *cu : cuPtrVector) { + for (const CompactUnwindEntry64 *cu : cuPtrVector) { uint32_t functionOffset = cu->functionAddress - in.header->addr; functionToLsdaIndex[functionOffset] = lsdaEntries.size(); if (cu->lsda != 0) @@ -419,8 +382,7 @@ template void UnwindInfoSectionImpl::finalize() { // All inputs are relocated and output addresses are known, so write! -template -void UnwindInfoSectionImpl::writeTo(uint8_t *buf) const { +void UnwindInfoSection::writeTo(uint8_t *buf) const { // section header auto *uip = reinterpret_cast(buf); uip->version = 1; @@ -441,8 +403,7 @@ void UnwindInfoSectionImpl::writeTo(uint8_t *buf) const { // Personalities for (const uint32_t &personality : personalities) - *i32p++ = - in.got->addr + (personality - 1) * target->wordSize - in.header->addr; + *i32p++ = in.got->addr + (personality - 1) * target->wordSize; // Level-1 index uint32_t lsdaOffset = @@ -461,7 +422,7 @@ void UnwindInfoSectionImpl::writeTo(uint8_t *buf) const { l2PagesOffset += SECOND_LEVEL_PAGE_BYTES; } // Level-1 sentinel - const CompactUnwindEntry &cuEnd = cuVector.back(); + const CompactUnwindEntry64 &cuEnd = cuVector.back(); iep->functionOffset = cuEnd.functionAddress + cuEnd.functionLength; iep->secondLevelPagesSectionOffset = 0; iep->lsdaIndexArraySectionOffset = @@ -494,7 +455,7 @@ void UnwindInfoSectionImpl::writeTo(uint8_t *buf) const { p2p->encodingsCount = page.localEncodings.size(); auto *ep = reinterpret_cast(&p2p[1]); for (size_t i = 0; i < page.entryCount; i++) { - const CompactUnwindEntry *cuep = cuPtrVector[page.entryIndex + i]; + const CompactUnwindEntry64 *cuep = cuPtrVector[page.entryIndex + i]; auto it = commonEncodingIndexes.find(cuep->encoding); if (it == commonEncodingIndexes.end()) it = page.localEncodingIndexes.find(cuep->encoding); @@ -513,7 +474,7 @@ void UnwindInfoSectionImpl::writeTo(uint8_t *buf) const { p2p->entryCount = page.entryCount; auto *ep = reinterpret_cast(&p2p[1]); for (size_t i = 0; i < page.entryCount; i++) { - const CompactUnwindEntry *cuep = cuPtrVector[page.entryIndex + i]; + const CompactUnwindEntry64 *cuep = cuPtrVector[page.entryIndex + i]; *ep++ = cuep->functionAddress; *ep++ = cuep->encoding; } @@ -521,10 +482,3 @@ void UnwindInfoSectionImpl::writeTo(uint8_t *buf) const { pp += SECOND_LEVEL_PAGE_WORDS; } } - -UnwindInfoSection *macho::makeUnwindInfoSection() { - if (target->wordSize == 8) - return make>(); - else - return make>(); -} diff --git a/lld/MachO/UnwindInfoSection.h b/lld/MachO/UnwindInfoSection.h index a33cd381a36e..1368625c291d 100644 --- a/lld/MachO/UnwindInfoSection.h +++ b/lld/MachO/UnwindInfoSection.h @@ -17,30 +17,66 @@ #include +// In 2020, we mostly care about 64-bit targets: x86_64 and arm64 +struct CompactUnwindEntry64 { + uint64_t functionAddress; + uint32_t functionLength; + compact_unwind_encoding_t encoding; + uint64_t personality; + uint64_t lsda; +}; + +// FIXME(gkm): someday we might care about 32-bit targets: x86 & arm +struct CompactUnwindEntry32 { + uint32_t functionAddress; + uint32_t functionLength; + compact_unwind_encoding_t encoding; + uint32_t personality; + uint32_t lsda; +}; + namespace lld { namespace macho { class UnwindInfoSection : public SyntheticSection { public: - bool isNeeded() const override { return compactUnwindSection != nullptr; } + UnwindInfoSection(); uint64_t getSize() const override { return unwindInfoSize; } - virtual void prepareRelocations(InputSection *) = 0; - + bool isNeeded() const override; + void finalize() override; + void writeTo(uint8_t *buf) const override; void setCompactUnwindSection(MergedOutputSection *cuSection) { compactUnwindSection = cuSection; } -protected: - UnwindInfoSection() - : SyntheticSection(segment_names::text, section_names::unwindInfo) { - align = 4; - } + using EncodingMap = llvm::DenseMap; + struct SecondLevelPage { + uint32_t kind; + size_t entryIndex; + size_t entryCount; + size_t byteCount; + std::vector localEncodings; + EncodingMap localEncodingIndexes; + }; + +private: + std::vector> commonEncodings; + EncodingMap commonEncodingIndexes; + // Indices of personality functions within the GOT. + std::vector personalities; + std::vector lsdaEntries; + // Map of function offset (from the image base) to an index within the LSDA + // array. + llvm::DenseMap functionToLsdaIndex; + std::vector cuVector; + std::vector cuPtrVector; + std::vector secondLevelPages; MergedOutputSection *compactUnwindSection = nullptr; + uint64_t level2PagesOffset = 0; uint64_t unwindInfoSize = 0; }; -UnwindInfoSection *makeUnwindInfoSection(); void prepareCompactUnwind(InputSection *isec); } // namespace macho diff --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp index 9afe73d872d2..8b10e176bf89 100644 --- a/lld/MachO/Writer.cpp +++ b/lld/MachO/Writer.cpp @@ -71,6 +71,7 @@ public: SymtabSection *symtabSection = nullptr; IndirectSymtabSection *indirectSymtabSection = nullptr; CodeSignatureSection *codeSignatureSection = nullptr; + UnwindInfoSection *unwindInfoSection = nullptr; FunctionStartsSection *functionStartsSection = nullptr; LCUuid *uuidCommand = nullptr; @@ -233,12 +234,10 @@ private: }; class LCMain : public LoadCommand { - uint32_t getSize() const override { - return sizeof(structs::entry_point_command); - } + uint32_t getSize() const override { return sizeof(entry_point_command); } void writeTo(uint8_t *buf) const override { - auto *c = reinterpret_cast(buf); + auto *c = reinterpret_cast(buf); c->cmd = LC_MAIN; c->cmdsize = getSize(); @@ -516,7 +515,7 @@ void Writer::scanRelocations() { TimeTraceScope timeScope("Scan relocations"); for (InputSection *isec : inputSections) { if (isec->segname == segment_names::ld) { - in.unwindInfo->prepareRelocations(isec); + prepareCompactUnwind(isec); continue; } @@ -797,6 +796,7 @@ template void Writer::createOutputSections() { TimeTraceScope timeScope("Create output sections"); // First, create hidden sections stringTableSection = make(); + unwindInfoSection = make(); // TODO(gkm): only when no -r symtabSection = makeSymtabSection(*stringTableSection); indirectSymtabSection = make(); if (config->adhocCodesign) @@ -828,9 +828,9 @@ template void Writer::createOutputSections() { for (const auto &it : mergedOutputSections) { StringRef segname = it.first.first; MergedOutputSection *osec = it.second; - if (segname == segment_names::ld) { + if (unwindInfoSection && segname == segment_names::ld) { assert(osec->name == section_names::compactUnwind); - in.unwindInfo->setCompactUnwindSection(osec); + unwindInfoSection->setCompactUnwindSection(osec); } else { getOrCreateOutputSegment(segname)->addOutputSection(osec); } @@ -991,7 +991,6 @@ template void macho::createSyntheticSections() { in.stubs = make(); in.stubHelper = make(); in.imageLoaderCache = make(); - in.unwindInfo = makeUnwindInfoSection(); } OutputSection *macho::firstTLVDataSection = nullptr; diff --git a/lld/test/MachO/Inputs/WatchOS.sdk/usr/lib/libSystem.tbd b/lld/test/MachO/Inputs/WatchOS.sdk/usr/lib/libSystem.tbd deleted file mode 100644 index b7d54aa6b556..000000000000 --- a/lld/test/MachO/Inputs/WatchOS.sdk/usr/lib/libSystem.tbd +++ /dev/null @@ -1,14 +0,0 @@ ---- !tapi-tbd -tbd-version: 4 -targets: [ armv7k-watchos, arm64_32-watchos ] -uuids: - - target: armv7k-watchos - value: 00000000-0000-0000-0000-000000000001 - - target: arm64_32-watchos - value: 00000000-0000-0000-0000-000000000002 -install-name: '/usr/lib/libSystem.dylib' -current-version: 1.0.0 -exports: - - targets: [ arm64_32-watchos, armv7k-watchos ] - symbols: [ dyld_stub_binder ] -... diff --git a/lld/test/MachO/Inputs/WatchOS.sdk/usr/lib/libc++.tbd b/lld/test/MachO/Inputs/WatchOS.sdk/usr/lib/libc++.tbd deleted file mode 100644 index 67d0f5d84165..000000000000 --- a/lld/test/MachO/Inputs/WatchOS.sdk/usr/lib/libc++.tbd +++ /dev/null @@ -1,14 +0,0 @@ ---- !tapi-tbd -tbd-version: 4 -targets: [ armv7k-watchos, arm64_32-watchos ] -uuids: - - target: armv7k-watchos - value: 00000000-0000-0000-0000-000000000001 - - target: arm64_32-watchos - value: 00000000-0000-0000-0000-000000000002 -install-name: '/usr/lib/libc++.dylib' -current-version: 1.0.0 -reexported-libraries: - - targets: [ arm64_32-watchos, armv7k-watchos ] - libraries: [ '/usr/lib/libc++abi.dylib' ] -... diff --git a/lld/test/MachO/Inputs/WatchOS.sdk/usr/lib/libc++abi.tbd b/lld/test/MachO/Inputs/WatchOS.sdk/usr/lib/libc++abi.tbd deleted file mode 100644 index 435cc82f2558..000000000000 --- a/lld/test/MachO/Inputs/WatchOS.sdk/usr/lib/libc++abi.tbd +++ /dev/null @@ -1,14 +0,0 @@ ---- !tapi-tbd -tbd-version: 4 -targets: [ armv7k-watchos, arm64_32-watchos ] -uuids: - - target: armv7k-watchos - value: 00000000-0000-0000-0000-000000000001 - - target: arm64_32-watchos - value: 00000000-0000-0000-0000-000000000002 -install-name: '/usr/lib/libc++abi.dylib' -current-version: 1.0.0 -exports: - - targets: [ arm64_32-watchos, armv7k-watchos ] - symbols: [ ___gxx_personality_v0 ] -... diff --git a/lld/test/MachO/arm64-32-reloc-got-load.s b/lld/test/MachO/arm64-32-reloc-got-load.s deleted file mode 100644 index b26aea3d4eda..000000000000 --- a/lld/test/MachO/arm64-32-reloc-got-load.s +++ /dev/null @@ -1,48 +0,0 @@ -# REQUIRES: aarch64 - -# RUN: rm -rf %t; split-file %s %t -# RUN: llvm-mc -filetype=obj -triple=arm64_32-apple-darwin %t/main.s -o %t/main.o -# RUN: llvm-mc -filetype=obj -triple=arm64_32-apple-darwin %t/foobar.s -o %t/foobar.o - -# RUN: %lld-watchos -lSystem -arch arm64_32 -o %t/static %t/main.o %t/foobar.o -# RUN: llvm-objdump --macho -d --no-show-raw-insn --syms %t/static | FileCheck %s --check-prefix=STATIC - -# RUN: %lld-watchos -lSystem -arch arm64_32 -dylib -o %t/libfoo.dylib %t/foobar.o -# RUN: %lld-watchos -lSystem -arch arm64_32 -o %t/main %t/main.o %t/libfoo.dylib -# RUN: llvm-objdump --macho -d --no-show-raw-insn --section-headers %t/main | FileCheck %s --check-prefix=DYLIB - -# STATIC-LABEL: _main: -# STATIC-NEXT: adrp x8, [[#]] ; 0x[[#%x,PAGE:]] -# STATIC-NEXT: add x8, x8, #[[#%u,FOO_OFF:]] -# STATIC-NEXT: adrp x8, [[#]] ; 0x[[#PAGE]] -# STATIC-NEXT: add x8, x8, #[[#%u,BAR_OFF:]] -# STATIC-NEXT: ret - -# STATIC-LABEL: SYMBOL TABLE: -# STATIC-DAG: {{0*}}[[#%x,PAGE+FOO_OFF]] g F __TEXT,__text _foo -# STATIC-DAG: {{0*}}[[#%x,PAGE+BAR_OFF]] g F __TEXT,__text _bar - -# DYLIB-LABEL: _main: -# DYLIB-NEXT: adrp x8, [[#]] ; 0x[[#%x,GOT:]] -# DYLIB-NEXT: ldr w8, [x8, #4] -# DYLIB-NEXT: adrp x8, [[#]] ; 0x[[#GOT]] -# DYLIB-NEXT: ldr w8, [x8] -# DYLIB-NEXT: ret -# DYLIB-NEXT: Sections: -# DYLIB-NEXT: Idx Name Size VMA Type -# DYLIB: [[#]] __got 00000008 [[#%.8x,GOT]] DATA - -#--- main.s -.globl _main, _foo, _bar -.p2align 2 -_main: - adrp x8, _foo@GOTPAGE - ldr w8, [x8, _foo@GOTPAGEOFF] - adrp x8, _bar@GOTPAGE - ldr w8, [x8, _bar@GOTPAGEOFF] - ret - -#--- foobar.s -.globl _foo, _bar -_foo: -_bar: diff --git a/lld/test/MachO/arm64-32-stubs.s b/lld/test/MachO/arm64-32-stubs.s deleted file mode 100644 index 9ea957d2ce1a..000000000000 --- a/lld/test/MachO/arm64-32-stubs.s +++ /dev/null @@ -1,60 +0,0 @@ -# REQUIRES: aarch64 - -## FIXME: This test is very similar to arm64-stubs.s, but has been split into a -## separate file because llvm-objdump doesn't correctly symbolize arm64_32. In -## particular, the "literal pool symbol address" comments are missing (PR49944). - -# RUN: rm -rf %t; split-file %s %t -# RUN: llvm-mc -filetype=obj -triple=arm64_32-apple-watchos %t/foo.s -o %t/foo.o -# RUN: llvm-mc -filetype=obj -triple=arm64_32-apple-watchos %t/bar.s -o %t/bar.o -# RUN: llvm-mc -filetype=obj -triple=arm64_32-apple-watchos %t/test.s -o %t/test.o -# RUN: %lld-watchos -dylib -install_name @executable_path/libfoo.dylib %t/foo.o -o %t/libfoo.dylib -# RUN: %lld-watchos -dylib -install_name @executable_path/libbar.dylib %t/bar.o -o %t/libbar.dylib -# RUN: %lld-watchos -lSystem %t/libfoo.dylib %t/libbar.dylib %t/test.o -o %t/test - -# RUN: llvm-objdump --macho -d --no-show-raw-insn --section="__TEXT,__stubs" --section="__TEXT,__stub_helper" %t/test | FileCheck %s - -# CHECK: _main: -# CHECK-NEXT: bl 0x[[#%x,FOO:]] ; symbol stub for: _foo -# CHECK-NEXT: bl 0x[[#%x,BAR:]] ; symbol stub for: _bar -# CHECK-NEXT: ret - -# CHECK-LABEL: Contents of (__TEXT,__stubs) section -# CHECK-NEXT: [[#BAR]]: adrp x16 -# CHECK-NEXT: ldr w16, [x16{{.*}}] -# CHECK-NEXT: br x16 -# CHECK-NEXT: [[#FOO]]: adrp x16 -# CHECK-NEXT: ldr w16, [x16{{.*}}] -# CHECK-NEXT: br x16 - -# CHECK-LABEL: Contents of (__TEXT,__stub_helper) section -# CHECK-NEXT: [[#%x,HELPER_HEADER:]]: adrp x17 -# CHECK-NEXT: add x17, x17 -# CHECK-NEXT: stp x16, x17, [sp, #-16]! -# CHECK-NEXT: adrp x16 -# CHECK-NEXT: ldr w16, [x16] -# CHECK-NEXT: br x16 -# CHECK-NEXT: ldr w16, 0x[[#%x,BAR_BIND_OFF_ADDR:]] -# CHECK-NEXT: b 0x[[#HELPER_HEADER]] -# CHECK-NEXT: [[#BAR_BIND_OFF_ADDR]]: udf #0 -# CHECK-NEXT: ldr w16, 0x[[#%x,FOO_BIND_OFF_ADDR:]] -# CHECK-NEXT: b 0x[[#HELPER_HEADER]] -# CHECK-NEXT: [[#FOO_BIND_OFF_ADDR]]: udf #11 - -#--- foo.s -.globl _foo -_foo: - -#--- bar.s -.globl _bar -_bar: - -#--- test.s -.text -.globl _main - -.p2align 2 -_main: - bl _foo - bl _bar - ret diff --git a/lld/test/MachO/compact-unwind.s b/lld/test/MachO/compact-unwind.s index 1da965f2b319..1d65d41964e0 100644 --- a/lld/test/MachO/compact-unwind.s +++ b/lld/test/MachO/compact-unwind.s @@ -3,23 +3,16 @@ # RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin19.0.0 %t/my-personality.s -o %t/x86_64-my-personality.o # RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin19.0.0 %t/main.s -o %t/x86_64-main.o # RUN: %lld -arch x86_64 -pie -lSystem -lc++ %t/x86_64-my-personality.o %t/x86_64-main.o -o %t/x86_64-personality-first -# RUN: llvm-objdump --macho --unwind-info --syms --indirect-symbols --rebase %t/x86_64-personality-first | FileCheck %s --check-prefixes=FIRST,CHECK -D#%x,BASE=0x100000000 +# RUN: llvm-objdump --macho --unwind-info --syms --indirect-symbols --rebase %t/x86_64-personality-first | FileCheck %s --check-prefixes=FIRST,CHECK # RUN: %lld -arch x86_64 -pie -lSystem -lc++ %t/x86_64-main.o %t/x86_64-my-personality.o -o %t/x86_64-personality-second -# RUN: llvm-objdump --macho --unwind-info --syms --indirect-symbols --rebase %t/x86_64-personality-second | FileCheck %s --check-prefixes=SECOND,CHECK -D#%x,BASE=0x100000000 +# RUN: llvm-objdump --macho --unwind-info --syms --indirect-symbols --rebase %t/x86_64-personality-second | FileCheck %s --check-prefixes=SECOND,CHECK # RUN: llvm-mc -filetype=obj -triple=arm64-apple-darwin19.0.0 %t/my-personality.s -o %t/arm64-my-personality.o # RUN: llvm-mc -filetype=obj -triple=arm64-apple-darwin19.0.0 %t/main.s -o %t/arm64-main.o # RUN: %lld -arch arm64 -pie -lSystem -lc++ %t/arm64-my-personality.o %t/arm64-main.o -o %t/arm64-personality-first -# RUN: llvm-objdump --macho --unwind-info --syms --indirect-symbols --rebase %t/arm64-personality-first | FileCheck %s --check-prefixes=FIRST,CHECK -D#%x,BASE=0x100000000 +# RUN: llvm-objdump --macho --unwind-info --syms --indirect-symbols --rebase %t/arm64-personality-first | FileCheck %s --check-prefixes=FIRST,CHECK # RUN: %lld -arch arm64 -pie -lSystem -lc++ %t/arm64-main.o %t/arm64-my-personality.o -o %t/arm64-personality-second -# RUN: llvm-objdump --macho --unwind-info --syms --indirect-symbols --rebase %t/arm64-personality-second | FileCheck %s --check-prefixes=SECOND,CHECK -D#%x,BASE=0x100000000 - -# RUN: llvm-mc -filetype=obj -triple=arm64_32-apple-watchos %t/my-personality.s -o %t/arm64-32-my-personality.o -# RUN: llvm-mc -filetype=obj -triple=arm64_32-apple-watchos %t/main.s -o %t/arm64-32-main.o -# RUN: %lld-watchos -pie -lSystem -lc++ %t/arm64-32-my-personality.o %t/arm64-32-main.o -o %t/arm64-32-personality-first -# RUN: llvm-objdump --macho --unwind-info --syms --indirect-symbols --rebase %t/arm64-32-personality-first | FileCheck %s --check-prefixes=FIRST,CHECK -D#%x,BASE=0x4000 -# RUN: %lld-watchos -pie -lSystem -lc++ %t/arm64-32-main.o %t/arm64-32-my-personality.o -o %t/arm64-32-personality-second -# RUN: llvm-objdump --macho --unwind-info --syms --indirect-symbols --rebase %t/arm64-32-personality-second | FileCheck %s --check-prefixes=SECOND,CHECK -D#%x,BASE=0x4000 +# RUN: llvm-objdump --macho --unwind-info --syms --indirect-symbols --rebase %t/arm64-personality-second | FileCheck %s --check-prefixes=SECOND,CHECK # FIRST: Indirect symbols for (__DATA_CONST,__got) # FIRST-NEXT: address index name @@ -39,16 +32,16 @@ # CHECK: Contents of __unwind_info section: # CHECK: Personality functions: (count = 2) -# CHECK-DAG: personality[{{[0-9]+}}]: 0x{{0*}}[[#MY_PERSONALITY-BASE]] -# CHECK-DAG: personality[{{[0-9]+}}]: 0x{{0*}}[[#GXX_PERSONALITY-BASE]] +# CHECK-DAG: personality[{{[0-9]+}}]: 0x{{0*}}[[#MY_PERSONALITY-0x100000000]] +# CHECK-DAG: personality[{{[0-9]+}}]: 0x{{0*}}[[#GXX_PERSONALITY-0x100000000]] # CHECK: LSDA descriptors: -# CHECK-DAG: function offset=0x[[#%.8x,FOO-BASE]], LSDA offset=0x[[#%.8x,EXCEPTION0-BASE]] -# CHECK-DAG: function offset=0x[[#%.8x,MAIN-BASE]], LSDA offset=0x[[#%.8x,EXCEPTION1-BASE]] +# CHECK-DAG: function offset=0x{{0*}}[[#FOO-0x100000000]], LSDA offset=0x{{0*}}[[#EXCEPTION0-0x100000000]] +# CHECK-DAG: function offset=0x{{0*}}[[#MAIN-0x100000000]], LSDA offset=0x{{0*}}[[#EXCEPTION1-0x100000000]] ## Check that we do not add rebase opcodes to the compact unwind section. # CHECK: Rebase table: # CHECK-NEXT: segment section address type -# CHECK-NEXT: __DATA_CONST __got 0x{{[0-9A-F]*}} pointer +# CHECK-NEXT: __DATA_CONST __got 0x{{[0-9a-f]*}} pointer # CHECK-NOT: __TEXT #--- my-personality.s diff --git a/lld/test/MachO/header.s b/lld/test/MachO/header.s index 77356eb813cd..17bcb0f3e039 100644 --- a/lld/test/MachO/header.s +++ b/lld/test/MachO/header.s @@ -1,27 +1,19 @@ # REQUIRES: x86, aarch64 # RUN: rm -rf %t && mkdir -p %t -# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %s -o %t/x86-64-test.o +# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %s -o %t/x86_64-test.o # RUN: llvm-mc -filetype=obj -triple=arm64-apple-darwin %s -o %t/arm64-test.o -# RUN: llvm-mc -filetype=obj -triple=arm64_32-apple-watchos %s -o %t/arm64-32-test.o -# RUN: %lld -arch x86_64 -platform_version macos 10.5.0 11.0 -o %t/x86-64-executable %t/x86-64-test.o +# RUN: %lld -arch x86_64 -platform_version macos 10.5.0 11.0 -o %t/x86-64-executable %t/x86_64-test.o # RUN: %lld -arch arm64 -o %t/arm64-executable %t/arm64-test.o -# RUN: %lld-watchos -o %t/arm64-32-executable %t/arm64-32-test.o -# RUN: %lld -arch x86_64 -dylib -o %t/x86-64-dylib %t/x86-64-test.o +# RUN: %lld -arch x86_64 -dylib -o %t/x86-64-dylib %t/x86_64-test.o # RUN: %lld -arch arm64 -dylib -o %t/arm64-dylib %t/arm64-test.o -# RUN: %lld-watchos -dylib -o %t/arm64-32-dylib %t/arm64-32-test.o -# RUN: llvm-objdump --macho --private-header %t/x86-64-executable | FileCheck %s -DCPU=X86_64 -DCAPS=LIB64 -# RUN: llvm-objdump --macho --private-header %t/arm64-executable | FileCheck %s -DCPU=ARM64 -DCAPS=0x00 -# RUN: llvm-objdump --macho --private-header %t/arm64-32-executable | FileCheck %s --check-prefix=ARM64-32 -# RUN: llvm-objdump --macho --private-header %t/x86-64-dylib | FileCheck %s -DCPU=X86_64 -DCAPS=0x00 -# RUN: llvm-objdump --macho --private-header %t/arm64-dylib | FileCheck %s -DCPU=ARM64 -DCAPS=0x00 -# RUN: llvm-objdump --macho --private-header %t/arm64-32-dylib | FileCheck %s --check-prefix=ARM64-32 +# RUN: llvm-objdump --macho --private-header %t/x86-64-executable | FileCheck %s -DCAPS=LIB64 +# RUN: llvm-objdump --macho --private-header %t/arm64-executable | FileCheck %s -DCAPS=0x00 +# RUN: llvm-objdump --macho --private-header %t/x86-64-dylib | FileCheck %s -DCAPS=0x00 +# RUN: llvm-objdump --macho --private-header %t/arm64-dylib | FileCheck %s -DCAPS=0x00 -# CHECK: magic cputype cpusubtype caps filetype {{.*}} flags -# CHECK-NEXT: MH_MAGIC_64 [[CPU]] ALL [[CAPS]] {{.*}} NOUNDEFS {{.*}} TWOLEVEL - -# ARM64-32: magic cputype cpusubtype caps filetype {{.*}} flags -# ARM64-32-NEXT: MH_MAGIC ARM64_32 V8 0x00 {{.*}} NOUNDEFS {{.*}} TWOLEVEL +# CHECK: magic cputype cpusubtype caps filetype {{.*}} flags +# CHECK-NEXT: MH_MAGIC_64 {{.*}} ALL [[CAPS]] {{.*}} NOUNDEFS {{.*}} TWOLEVEL .globl _main _main: diff --git a/lld/test/MachO/lit.local.cfg b/lld/test/MachO/lit.local.cfg index 17e63171502d..dd5d7cbc425b 100644 --- a/lld/test/MachO/lit.local.cfg +++ b/lld/test/MachO/lit.local.cfg @@ -2,20 +2,12 @@ import os -# We specify the most commonly-used archs and platform versions in our tests -# here. Tests which need different settings can just append to this, as only -# the last value will be used. +# We specify the most commonly-used arch and platform version in our tests here +# Tests which need different settings can just append to this, as only the last +# value will be used. # # Note however that this does not apply to `-syslibroot`: each instance of that -# flag will append to the set of library roots. As such, we define a separate -# alias for each platform. - -config.substitutions.append(('%lld-watchos', - 'ld64.lld -fatal_warnings -arch arm64_32 -platform_version watchos 7.0 8.0 -syslibroot ' + - os.path.join(config.test_source_root, "MachO", "Inputs", "WatchOS.sdk"))) - -# Since most of our tests are written around x86_64, we give this platform the -# shortest substitution of "%lld". +# flag will append to the set of library roots. lld = ('ld64.lld -arch x86_64 -platform_version macos 10.0 11.0 -syslibroot ' + os.path.join(config.test_source_root, "MachO", "Inputs", "MacOSX.sdk")) config.substitutions.append(('%lld', lld + ' -fatal_warnings')) diff --git a/lld/test/MachO/segments.s b/lld/test/MachO/segments.s index e63848baf3a4..f4ac4c80a176 100644 --- a/lld/test/MachO/segments.s +++ b/lld/test/MachO/segments.s @@ -1,28 +1,19 @@ -# REQUIRES: x86, aarch64 -# RUN: rm -rf %t; mkdir -p %t -# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %s -o %t/x86_64.o -# RUN: llvm-mc -filetype=obj -triple=arm64_32-apple-watchos %s -o %t/arm64-32.o -# RUN: %lld -o %t/x86_64 %t/x86_64.o -# RUN: %lld-watchos -o %t/arm64_32 %t/arm64-32.o - -# RUN: llvm-readobj --macho-segment %t/x86_64 > %t/x86_64.out -# RUN: echo "Total file size" >> %t/x86_64.out -# RUN: wc -c %t/x86_64 >> %t/x86_64.out -# RUN: FileCheck %s -DSUFFIX=_64 -DPAGEZERO_SIZE=0x100000000 -DTEXT_ADDR=0x100000000 < %t/x86_64.out - -# RUN: llvm-readobj --macho-segment %t/arm64_32 > %t/arm64-32.out -# RUN: echo "Total file size" >> %t/arm64-32.out -# RUN: wc -c %t/arm64_32 >> %t/arm64-32.out -# RUN: FileCheck %s -DSUFFIX= -DPAGEZERO_SIZE=0x1000 -DTEXT_ADDR=0x4000 < %t/arm64-32.out +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %s -o %t.o +# RUN: %lld -o %t %t.o +# RUN: llvm-readobj --macho-segment %t > %t.out +# RUN: echo "Total file size" >> %t.out +# RUN: wc -c %t >> %t.out +# RUN: FileCheck %s < %t.out ## These two segments must always be present at the start of an executable. # CHECK-NOT: Segment { # CHECK: Segment { -# CHECK-NEXT: Cmd: LC_SEGMENT[[SUFFIX]]{{$}} +# CHECK-NEXT: Cmd: LC_SEGMENT_64 # CHECK-NEXT: Name: __PAGEZERO -# CHECK-NEXT: Size: +# CHECK-NEXT: Size: 72 # CHECK-NEXT: vmaddr: 0x0 -# CHECK-NEXT: vmsize: [[PAGEZERO_SIZE]] +# CHECK-NEXT: vmsize: 0x100000000 # CHECK-NEXT: fileoff: 0 # CHECK-NEXT: filesize: 0 ## The kernel won't execute a binary with the wrong protections for __PAGEZERO. @@ -32,10 +23,10 @@ # CHECK-NEXT: flags: 0x0 # CHECK-NEXT: } # CHECK-NEXT: Segment { -# CHECK-NEXT: Cmd: LC_SEGMENT[[SUFFIX]]{{$}} +# CHECK-NEXT: Cmd: LC_SEGMENT_64 # CHECK-NEXT: Name: __TEXT -# CHECK-NEXT: Size: -# CHECK-NEXT: vmaddr: [[TEXT_ADDR]] +# CHECK-NEXT: Size: 152 +# CHECK-NEXT: vmaddr: 0x100000000 # CHECK-NEXT: vmsize: ## dyld3 assumes that the __TEXT segment starts from the file header # CHECK-NEXT: fileoff: 0 @@ -47,7 +38,7 @@ # CHECK-NEXT: } ## Check that we handle max-length names correctly. -# CHECK: Cmd: LC_SEGMENT[[SUFFIX]]{{$}} +# CHECK: Cmd: LC_SEGMENT_64 # CHECK-NEXT: Name: maxlen_16ch_name ## This segment must always be present at the end of an executable, and cover @@ -60,7 +51,7 @@ # CHECK-NEXT: filesize: [[#%u, LINKEDIT_SIZE:]] # CHECK-NEXT: maxprot: r-- # CHECK-NEXT: initprot: r-- -# CHECK-NOT: Cmd: LC_SEGMENT[[SUFFIX]]{{$}} +# CHECK-NOT: Cmd: LC_SEGMENT_64 # CHECK-LABEL: Total file size # CHECK-NEXT: [[#%u, LINKEDIT_OFF + LINKEDIT_SIZE]] @@ -68,6 +59,7 @@ .text .global _main _main: + mov $0, %rax ret .section maxlen_16ch_name,foo