Index: lld/MachO/Arch/ARM.cpp =================================================================== --- lld/MachO/Arch/ARM.cpp +++ lld/MachO/Arch/ARM.cpp @@ -40,6 +40,9 @@ void relaxGotLoad(uint8_t *loc, uint8_t type) const override; const RelocAttrs &getRelocAttrs(uint8_t type) const override; uint64_t getPageSize() const override { return 4 * 1024; } + + void handleDtraceReloc(const Symbol *sym, const Reloc &r, + uint8_t *loc) const override; }; } // namespace @@ -170,3 +173,41 @@ static ARM t(cpuSubtype); return &t; } + +void ARM::handleDtraceReloc(const Symbol *sym, const Reloc &r, + uint8_t *loc) const { + switch (r.type) { + case ARM_RELOC_BR24: + if (sym->getName().startswith("___dtrace_probe")) { + if (config->outputType == MH_OBJECT) + return; + // change call site to a NOP + write32le(loc, 0xE1A00000); + } else if (sym->getName().startswith("___dtrace_isenabled")) { + if (config->outputType == MH_OBJECT) + return; + // change call site to 'eor r0, r0, r0' + write32le(loc, 0xE0200000); + } else { + error("Unrecognized dtrace symbol prefix: " + sym->getName()); + } + break; + case ARM_THUMB_RELOC_BR22: + if (sym->getName().startswith("___dtrace_probe")) { + if (config->outputType == MH_OBJECT) + return; + // change 32-bit blx call site to two thumb NOPs + write32le(loc, 0x46C046C0); + } else if (sym->getName().startswith("___dtrace_isenabled")) { + if (config->outputType == MH_OBJECT) + return; + // change 32-bit blx call site to 'nop', 'eor r0, r0' + write32le(loc, 0x46C04040); + } else { + error("Unrecognized dtrace symbol prefix: " + toString(*sym)); + } + break; + default: + llvm_unreachable("Unsupported dtrace relocation type for ARM"); + } +} Index: lld/MachO/Arch/ARM64Common.h =================================================================== --- lld/MachO/Arch/ARM64Common.h +++ lld/MachO/Arch/ARM64Common.h @@ -29,6 +29,9 @@ void relaxGotLoad(uint8_t *loc, uint8_t type) const override; uint64_t getPageSize() const override { return 16 * 1024; } + + void handleDtraceReloc(const Symbol *sym, const Reloc &r, + uint8_t *loc) const override; }; inline uint64_t bitField(uint64_t value, int right, int width, int left) { Index: lld/MachO/Arch/ARM64Common.cpp =================================================================== --- lld/MachO/Arch/ARM64Common.cpp +++ lld/MachO/Arch/ARM64Common.cpp @@ -109,3 +109,22 @@ instruction = ((instruction & 0x001fffff) | 0x91000000); write32le(loc, instruction); } + +void ARM64Common::handleDtraceReloc(const Symbol *sym, const Reloc &r, + uint8_t *loc) const { + assert(r.type == ARM64_RELOC_BRANCH26); + + if (sym->getName().startswith("___dtrace_probe")) { + if (config->outputType == MH_OBJECT) + return; + // change call site to a NOP + write32le(loc, 0xD503201F); + } else if (sym->getName().startswith("___dtrace_isenabled")) { + if (config->outputType == MH_OBJECT) + return; + // change call site to 'MOVZ X0,0' + write32le(loc, 0xD2800000); + } else { + error("Unrecognized dtrace symbol prefix: " + toString(*sym)); + } +} Index: lld/MachO/Arch/X86_64.cpp =================================================================== --- lld/MachO/Arch/X86_64.cpp +++ lld/MachO/Arch/X86_64.cpp @@ -38,6 +38,9 @@ void relaxGotLoad(uint8_t *loc, uint8_t type) const override; const RelocAttrs &getRelocAttrs(uint8_t type) const override; uint64_t getPageSize() const override { return 4 * 1024; } + + void handleDtraceReloc(const Symbol *sym, const Reloc &r, + uint8_t *loc) const override; }; } // namespace @@ -194,3 +197,30 @@ static X86_64 t; return &t; } + +void X86_64::handleDtraceReloc(const Symbol *sym, const Reloc &r, + uint8_t *loc) const { + assert(r.type == X86_64_RELOC_BRANCH); + + if (sym->getName().startswith("___dtrace_probe")) { + if (config->outputType == MH_OBJECT) + return; + // change call site to a NOP + loc[-1] = 0x90; // 1-byte nop + loc[0] = 0x0F; // 4-byte nop + loc[1] = 0x1F; + loc[2] = 0x40; + loc[3] = 0x00; + } else if (sym->getName().startswith("___dtrace_isenabled")) { + if (config->outputType == MH_OBJECT) + return; + // change call site to a clear eax + loc[-1] = 0x33; // xorl eax,eax + loc[0] = 0xC0; + loc[1] = 0x90; // 1-byte nop + loc[2] = 0x90; // 1-byte nop + loc[3] = 0x90; // 1-byte nop + } else { + error("Unrecognized dtrace symbol prefix: " + toString(*sym)); + } +} Index: lld/MachO/InputSection.cpp =================================================================== --- lld/MachO/InputSection.cpp +++ lld/MachO/InputSection.cpp @@ -141,6 +141,12 @@ if (target->hasAttr(r.type, RelocAttrBits::LOAD) && !referentSym->isInGot()) target->relaxGotLoad(loc, r.type); + // For dtrace symbols, do not handle them as normal undefined symbols + if (referentSym->getName().startswith("___dtrace_")) { + // Change dtrace call site to pre-defined instructions + target->handleDtraceReloc(referentSym, r, loc); + continue; + } referentVA = resolveSymbolVA(referentSym, r.type) + r.addend; if (isThreadLocalVariables(getFlags())) { Index: lld/MachO/SymbolTable.cpp =================================================================== --- lld/MachO/SymbolTable.cpp +++ lld/MachO/SymbolTable.cpp @@ -314,6 +314,10 @@ if (name.consume_front("segment$end$")) return handleSegmentBoundarySymbol(sym, name, Boundary::End); + // Leave dtrace symbols, since we will handle them when we do the relocation + if (name.startswith("___dtrace_")) + return; + // Handle -U. if (config->explicitDynamicLookups.count(sym.getName())) { symtab->addDynamicLookup(sym.getName()); Index: lld/MachO/Target.h =================================================================== --- lld/MachO/Target.h +++ lld/MachO/Target.h @@ -76,6 +76,14 @@ bool usesThunks() const { return thunkSize > 0; } + // For now, handleDtraceReloc only implements -no_dtrace_dof, and ensures + // that the linking would not fail even when there are user-provided dtrace + // symbols. However, unlike ld64, lld currently does not emit __dof sections. + virtual void handleDtraceReloc(const Symbol *sym, const Reloc &r, + uint8_t *loc) const { + llvm_unreachable("Unsupported architecture for dtrace symbols"); + } + uint32_t magic; llvm::MachO::CPUType cpuType; uint32_t cpuSubtype; Index: lld/test/MachO/arm-dtrace.s =================================================================== --- /dev/null +++ lld/test/MachO/arm-dtrace.s @@ -0,0 +1,61 @@ +# REQUIRES: arm +# RUN: rm -rf %t; split-file %s %t + +# RUN: llvm-mc -filetype=obj -triple=armv4t-apple-macosx12.0.0 %t/armv4t-dtrace.s -o %t/armv4t-dtrace.o +# RUN: %lld -demangle -dynamic -arch armv4t -platform_version macos 12.0.0 12.3 -o %t/armv4t-dtrace %t/armv4t-dtrace.o + +## If references of dtrace symbols are handled by lld, their relocation should be replaced with the following instructions +# RUN: llvm-objdump --macho -D %t/armv4t-dtrace | FileCheck %s --check-prefix=CHECK-armv4t + +# CHECK-armv4t: 00 00 20 e0 eor r0, r0, r0 + +# CHECK-armv4t: 00 00 a0 e1 mov r0, r0 + +# RUN: llvm-mc -filetype=obj -triple=thumbv7-apple-macosx12.0.0 %t/armv7-dtrace.s -o %t/armv7-dtrace.o +# RUN: %lld -demangle -dynamic -arch armv7 -platform_version macos 12.0.0 12.3 -o %t/armv7-dtrace %t/armv7-dtrace.o + +## If references of dtrace symbols are handled by lld, their relocation should be replaced with the following instructions +# RUN: llvm-objdump --macho -D %t/armv7-dtrace | FileCheck %s --check-prefix=CHECK-armv7 + +# CHECK-armv7: 40 40 eors r0, r0 +# CHECK-armv7-NEXT: c0 46 mov r8, r8 + +# CHECK-armv7: c0 46 mov r8, r8 +# CHECK-armv7-NEXT: c0 46 mov r8, r8 + +;--- armv4t-dtrace.s + .globl _main +_main: + bl ___dtrace_isenabled$Foo$added$v1 + beq LBB0_4 + b LBB0_1 +LBB0_1: + b LBB0_2 +LBB0_2: + .reference ___dtrace_typedefs$Foo$v2 + bl ___dtrace_probe$Foo$added$v1$696e74 + .reference ___dtrace_stability$Foo$v1$1_1_0_1_1_0_1_1_0_1_1_0_1_1_0 + b LBB0_3 +LBB0_3: + b LBB0_4 +LBB0_4: + bx lr + +.subsections_via_symbols + +;--- armv7-dtrace.s + .globl _main + .thumb_func _main +_main: + bl ___dtrace_isenabled$Foo$added$v1 + cbz r0, LBB0_4 + b LBB0_2 +LBB0_2: + .reference ___dtrace_typedefs$Foo$v2 + bl ___dtrace_probe$Foo$added$v1$696e74 + .reference ___dtrace_stability$Foo$v1$1_1_0_1_1_0_1_1_0_1_1_0_1_1_0 +@ %bb.3: + b LBB0_4 +LBB0_4: + +.subsections_via_symbols Index: lld/test/MachO/arm64-32-dtrace.s =================================================================== --- /dev/null +++ lld/test/MachO/arm64-32-dtrace.s @@ -0,0 +1,32 @@ +# REQUIRES: aarch64 +# RUN: rm -rf %t; split-file %s %t + +# RUN: llvm-mc -filetype=obj -triple=arm64_32-apple-macosx12.0.0 %t/arm64-32-dtrace.s -o %t/arm64-32-dtrace.o +# RUN: %lld -demangle -dynamic -arch arm64_32 -platform_version macos 12.0.0 12.3 -o %t/arm64-32-dtrace %t/arm64-32-dtrace.o + +## If references of dtrace symbols are handled by lld, their relocation should be replaced with the following instructions +# RUN: llvm-objdump --macho -D %t/arm64-32-dtrace | FileCheck %s --check-prefix=CHECK + +# CHECK: 00 00 80 d2 mov x0, #0 + +# CHECK: 1f 20 03 d5 nop + +#--- arm64-32-dtrace.s + .globl _main +_main: + bl ___dtrace_isenabled$Foo$added$v1 + cbz w8, LBB0_4 + b LBB0_1 +LBB0_1: + b LBB0_2 +LBB0_2: + .reference ___dtrace_typedefs$Foo$v2 + bl ___dtrace_probe$Foo$added$v1$696e74 + .reference ___dtrace_stability$Foo$v1$1_1_0_1_1_0_1_1_0_1_1_0_1_1_0 + b LBB0_3 +LBB0_3: + b LBB0_4 +LBB0_4: + ret + +.subsections_via_symbols Index: lld/test/MachO/arm64-dtrace.s =================================================================== --- /dev/null +++ lld/test/MachO/arm64-dtrace.s @@ -0,0 +1,32 @@ +# REQUIRES: aarch64 +# RUN: rm -rf %t; split-file %s %t + +# RUN: llvm-mc -filetype=obj -triple=arm64-apple-macosx12.0.0 %t/arm64-dtrace.s -o %t/arm64-dtrace.o +# RUN: %lld -demangle -dynamic -arch arm64 -platform_version macos 12.0.0 12.3 -o %t/arm64-dtrace %t/arm64-dtrace.o + +## If references of dtrace symbols are handled by lld, their relocation should be replaced with the following instructions +# RUN: llvm-objdump --macho -D %t/arm64-dtrace | FileCheck %s --check-prefix=CHECK + +# CHECK: 00 00 80 d2 mov x0, #0 + +# CHECK: 1f 20 03 d5 nop + +#--- arm64-dtrace.s + .globl _main +_main: + bl ___dtrace_isenabled$Foo$added$v1 + cbz w8, LBB0_4 + b LBB0_1 +LBB0_1: + b LBB0_2 +LBB0_2: + .reference ___dtrace_typedefs$Foo$v2 + bl ___dtrace_probe$Foo$added$v1$696e74 + .reference ___dtrace_stability$Foo$v1$1_1_0_1_1_0_1_1_0_1_1_0_1_1_0 + b LBB0_3 +LBB0_3: + b LBB0_4 +LBB0_4: + ret + +.subsections_via_symbols Index: lld/test/MachO/x86_64-dtrace.s =================================================================== --- /dev/null +++ lld/test/MachO/x86_64-dtrace.s @@ -0,0 +1,32 @@ +# REQUIRES: x86 +# RUN: rm -rf %t; split-file %s %t + +# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/x86_64-dtrace.s -o %t/x86_64-dtrace.o +# RUN: %lld -demangle -dynamic -arch x86_64 -platform_version macos 12.0.0 12.3 -o %t/x86_64-dtrace %t/x86_64-dtrace.o + +## If references of dtrace symbols are handled by lld, their relocation should be replaced with the following instructions +# RUN: llvm-objdump --macho -D %t/x86_64-dtrace | FileCheck %s --check-prefix=CHECK + +# CHECK: 33 c0 xorl %eax, %eax +# CHECK-NEXT: 90 nop +# CHECK-NEXT: 90 nop +# CHECK-NEXT: 90 nop + +# CHECK: 90 nop +# CHECK-NEXT: 0f 1f 40 00 nopl (%rax) + +#--- x86_64-dtrace.s + .globl _main +_main: + callq ___dtrace_isenabled$Foo$added$v1 + je LBB0_4 + jmp LBB0_2 +LBB0_2: + .reference ___dtrace_typedefs$Foo$v2 + callq ___dtrace_probe$Foo$added$v1$696e74 + .reference ___dtrace_stability$Foo$v1$1_1_0_1_1_0_1_1_0_1_1_0_1_1_0 + jmp LBB0_4 +LBB0_4: + retq + +.subsections_via_symbols