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,51 @@ static ARM t(cpuSubtype); return &t; } + +void ARM::handleDtraceReloc(const Symbol *sym, const Reloc r, + uint8_t *loc) const { + assert(r.type == ARM_RELOC_BR24 || r.type == ARM_THUMB_RELOC_BR22); + + switch (r.type) { + case ARM_RELOC_BR24: + if (sym->getName().startswith("___dtrace_probe")) { + // ld64: fixup is kindStoreARMDtraceCallSiteNop + if (config->outputType == MH_OBJECT) { + return; + } + // change call site to a NOP + write32le(loc, 0xE1A00000); + } else if (sym->getName().startswith("___dtrace_isenabled")) { + // ld64: fixup is kindStoreARMDtraceIsEnableSiteClear + 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")) { + // ld64: fixup is kindStoreThumbDtraceCallSiteNop + 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")) { + // ld64: fixup is kindStoreThumbDtraceIsEnableSiteClear + 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: " + sym->getName()); + } + break; + default: + llvm_unreachable("Unsupported dtrace relocation type for ARM"); + } +} \ No newline at end of file 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,32 @@ 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 (!r.pcrel) + error("Not pcrel and ARM64_RELOC_BRANCH26 not supported"); + + if (r.length != 2) + error("r_length != 2 and ARM64_RELOC_BRANCH26 not supported"); + + if (sym->getName().startswith("___dtrace_probe")) { + // ld64: fixup is kindStoreARM64DtraceCallSiteNop + if (config->outputType == MH_OBJECT) { + return; + } + // change call site to a NOP + write32le(loc, 0xD503201F); + } else if (sym->getName().startswith("___dtrace_isenabled")) { + // ld64: fixup is kindStoreARM64DtraceIsEnableSiteClear + if (config->outputType == MH_OBJECT) { + return; + } + // change call site to 'MOVZ X0,0' + write32le(loc, 0xD2800000); + } else { + error("Unrecognized dtrace symbol prefix: " + sym->getName()); + } +} \ No newline at end of file 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,44 @@ 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 (!r.pcrel) + error("Not pcrel and X86_64_RELOC_BRANCH not supported"); + + if (r.length != 2) + error("r_length != 2 and X86_64_RELOC_BRANCH not supported"); + + if (sym->getName().startswith("___dtrace_probe")) { + // ld64: fixup is kindStoreX86DtraceCallSiteNop + 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; + write32le(loc - 4, (read32le(loc - 4) & 0x00ffffff) | 0x90000000); + write32le(loc, 0x00401F0F); + } else if (sym->getName().startswith("___dtrace_isenabled")) { + // ld64: fixup is kindStoreX86DtraceIsEnableSiteClear + 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 + write32le(loc - 4, (read32le(loc - 4) & 0x00ffffff) | 0x33000000); + write32le(loc, 0x909090C0); + } else { + error("Unrecognized dtrace symbol prefix: " + sym->getName()); + } +} \ No newline at end of file Index: lld/MachO/CMakeLists.txt =================================================================== --- lld/MachO/CMakeLists.txt +++ lld/MachO/CMakeLists.txt @@ -13,6 +13,7 @@ ConcatOutputSection.cpp Driver.cpp DriverUtils.cpp + Dtrace.cpp Dwarf.cpp ExportTrie.cpp ICF.cpp Index: lld/MachO/Dtrace.h =================================================================== --- /dev/null +++ lld/MachO/Dtrace.h @@ -0,0 +1,26 @@ +//===- Dtrace.h ----------------------------------------------------------===// +// +// 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 LLVM_DTRACE_H +#define LLVM_DTRACE_H + +#include "Symbols.h" +#include "Target.h" +#include "lld/Common/LLVM.h" + +namespace lld { +namespace macho { + +bool isDtraceSym(StringRef name); + +void resolveDtraceSymbol(const Symbol *sym, const Reloc r, uint8_t *loc); + +} // namespace macho +} // namespace lld + +#endif // LLVM_DTRACE_H Index: lld/MachO/Dtrace.cpp =================================================================== --- /dev/null +++ lld/MachO/Dtrace.cpp @@ -0,0 +1,40 @@ +//===- Dtrace.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 "Dtrace.h" + +using namespace lld; +using namespace lld::macho; +using namespace llvm; +using namespace llvm::MachO; + +bool lld::macho::isDtraceSym(StringRef name) { + if (name.substr(0, 10) == "___dtrace_") { + return true; + } + return false; +} + +void lld::macho::resolveDtraceSymbol(const Symbol *sym, const Reloc r, + uint8_t *loc) { + // Dtrace symbol should be undefined + assert(sym && isa(sym)); + + switch (target->cpuType) { + case CPU_TYPE_X86_64: + case CPU_TYPE_ARM: + case CPU_TYPE_ARM64: + case CPU_TYPE_ARM64_32: + target->handleDtraceReloc(sym, r, loc); + break; + default: + error("Unsupported architecture for dtrace symbols"); + break; + } +} \ No newline at end of file Index: lld/MachO/InputFiles.cpp =================================================================== --- lld/MachO/InputFiles.cpp +++ lld/MachO/InputFiles.cpp @@ -44,6 +44,7 @@ #include "InputFiles.h" #include "Config.h" #include "Driver.h" +#include "Dtrace.h" #include "Dwarf.h" #include "ExportTrie.h" #include "InputSection.h" Index: lld/MachO/InputSection.cpp =================================================================== --- lld/MachO/InputSection.cpp +++ lld/MachO/InputSection.cpp @@ -9,6 +9,7 @@ #include "InputSection.h" #include "ConcatOutputSection.h" #include "Config.h" +#include "Dtrace.h" #include "InputFiles.h" #include "OutputSegment.h" #include "Symbols.h" @@ -141,6 +142,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 (isDtraceSym(referentSym->getName())) { + // Change dtrace call site to pre-defined instructions + resolveDtraceSymbol(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 @@ -9,6 +9,7 @@ #include "SymbolTable.h" #include "ConcatOutputSection.h" #include "Config.h" +#include "Dtrace.h" #include "InputFiles.h" #include "InputSection.h" #include "Symbols.h" @@ -314,6 +315,11 @@ 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 (isDtraceSym(name)) { + 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,12 @@ bool usesThunks() const { return thunkSize > 0; } + virtual void handleDtraceReloc(const Symbol *sym, const Reloc r, + uint8_t *loc) const { + llvm_unreachable( + "Dtrace support for current architecture not implemented yet"); + } + uint32_t magic; llvm::MachO::CPUType cpuType; uint32_t cpuSubtype; Index: lld/test/MachO/arm-dtrace.ll =================================================================== --- /dev/null +++ lld/test/MachO/arm-dtrace.ll @@ -0,0 +1,113 @@ +; RUN: rm -rf %t; split-file %s %t + +; RUN: llvm-as %t/armv4t-dtrace.ll -o %t/armv4t-dtrace.ll.o +; RUN: %lld -demangle -dynamic -arch armv4t -platform_version macos 12.0.0 12.3 -o %t/armv4t-dtrace %t/armv4t-dtrace.ll.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 kindStoreARMDtraceIsEnableSiteClear +; CHECK-armv4t: 00 00 20 e0 eor r0, r0, r0 + +;; Check kindStoreARMDtraceCallSiteNop +; CHECK-armv4t: 00 00 a0 e1 mov r0, r0 + +; RUN: llvm-as %t/armv7-dtrace.ll -o %t/armv7-dtrace.ll.o +; RUN: %lld -demangle -dynamic -arch armv7 -platform_version macos 12.0.0 12.3 -o %t/armv7-dtrace %t/armv7-dtrace.ll.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 kindStoreThumbDtraceIsEnableSiteClear +; CHECK-armv7: 40 40 eors r0, r0 +; CHECK-armv7-NEXT: c0 46 mov r8, r8 + +;; Check kindStoreThumbDtraceCallSiteNop +; CHECK-armv7: c0 46 mov r8, r8 +; CHECK-armv7-NEXT: c0 46 mov r8, r8 + +;--- armv4t-dtrace.ll +source_filename = "main.cpp" +target datalayout = "e-m:o-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32" +target triple = "armv4t-apple-macosx12.0.0" + +define i32 @main() #0 { + %1 = alloca i32, align 4 + %2 = alloca i32, align 4 + %3 = alloca i32, align 4 + store i32 0, i32* %1, align 4 + %4 = call i32 @"__dtrace_isenabled$Foo$added$v1"() + store i32 %4, i32* %2, align 4 + call void asm sideeffect "", ""() #2, !srcloc !6 + %5 = load i32, i32* %2, align 4 + store i32 %5, i32* %3, align 4 + %6 = load i32, i32* %3, align 4 + %7 = icmp ne i32 %6, 0 + br i1 %7, label %8, label %11 + +8: ; preds = %0 + br label %9 + +9: ; preds = %8 + call void asm sideeffect ".reference ___dtrace_typedefs$$Foo$$v2", ""() #2, !srcloc !7 + call void @"__dtrace_probe$Foo$added$v1$696e74"(i32 0) + call void asm sideeffect ".reference ___dtrace_stability$$Foo$$v1$$1_1_0_1_1_0_1_1_0_1_1_0_1_1_0", ""() #2, !srcloc !8 + br label %10 + +10: ; preds = %9 + br label %11 + +11: ; preds = %10, %0 + ret i32 0 +} + +declare i32 @"__dtrace_isenabled$Foo$added$v1"() #1 + +declare void @"__dtrace_probe$Foo$added$v1$696e74"(i32) #1 + +!6 = !{i64 2147497205} +!7 = !{i64 2147497248} +!8 = !{i64 2147497342} + +;--- armv7-dtrace.ll +source_filename = "main.cpp" +target datalayout = "e-m:o-p:32:32-Fi8-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32" +target triple = "thumbv7-apple-macosx12.0.0" + +define i32 @main() #0 { + %1 = alloca i32, align 4 + %2 = alloca i32, align 4 + %3 = alloca i32, align 4 + store i32 0, i32* %1, align 4 + %4 = call i32 @"__dtrace_isenabled$Foo$added$v1"() + store i32 %4, i32* %2, align 4 + call void asm sideeffect "", ""() #2, !srcloc !6 + %5 = load i32, i32* %2, align 4 + store i32 %5, i32* %3, align 4 + %6 = load i32, i32* %3, align 4 + %7 = icmp ne i32 %6, 0 + br i1 %7, label %8, label %11 + +8: ; preds = %0 + br label %9 + +9: ; preds = %8 + call void asm sideeffect ".reference ___dtrace_typedefs$$Foo$$v2", ""() #2, !srcloc !7 + call void @"__dtrace_probe$Foo$added$v1$696e74"(i32 1) + call void asm sideeffect ".reference ___dtrace_stability$$Foo$$v1$$1_1_0_1_1_0_1_1_0_1_1_0_1_1_0", ""() #2, !srcloc !8 + br label %10 + +10: ; preds = %9 + br label %11 + +11: ; preds = %10, %0 + ret i32 0 +} + +declare i32 @"__dtrace_isenabled$Foo$added$v1"() #1 + +declare void @"__dtrace_probe$Foo$added$v1$696e74"(i32) #1 + +!6 = !{i64 2147497836} +!7 = !{i64 2147497879} +!8 = !{i64 2147497973} Index: lld/test/MachO/arm64-32-dtrace.ll =================================================================== --- /dev/null +++ lld/test/MachO/arm64-32-dtrace.ll @@ -0,0 +1,56 @@ +; RUN: rm -rf %t; split-file %s %t + +; RUN: llvm-as %t/arm64_32-dtrace.ll -o %t/arm64_32-dtrace.ll.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.ll.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 kindStoreARM64DtraceIsEnableSiteClear +; CHECK: 00 00 80 d2 mov x0, #0 + +;; Check kindStoreARM64DtraceCallSiteNop +; CHECK: 1f 20 03 d5 nop + +;--- arm64_32-dtrace.ll +source_filename = "main.cpp" +target datalayout = "e-m:o-p:32:32-i64:64-i128:128-n32:64-S128" +target triple = "arm64_32-apple-macosx12.0.0" + +define i32 @main() #0 { + %1 = alloca i32, align 4 + %2 = alloca i32, align 4 + %3 = alloca i32, align 4 + store i32 0, i32* %1, align 4 + %4 = call i32 @"__dtrace_isenabled$Foo$added$v1"() + store i32 %4, i32* %2, align 4 + call void asm sideeffect "", ""() #2, !srcloc !10 + %5 = load i32, i32* %2, align 4 + store i32 %5, i32* %3, align 4 + %6 = load i32, i32* %3, align 4 + %7 = icmp ne i32 %6, 0 + br i1 %7, label %8, label %11 + +8: ; preds = %0 + br label %9 + +9: ; preds = %8 + call void asm sideeffect ".reference ___dtrace_typedefs$$Foo$$v2", ""() #2, !srcloc !11 + call void @"__dtrace_probe$Foo$added$v1$696e74"(i32 0) + call void asm sideeffect ".reference ___dtrace_stability$$Foo$$v1$$1_1_0_1_1_0_1_1_0_1_1_0_1_1_0", ""() #2, !srcloc !12 + br label %10 + +10: ; preds = %9 + br label %11 + +11: ; preds = %10, %0 + ret i32 0 +} + +declare i32 @"__dtrace_isenabled$Foo$added$v1"() #1 + +declare void @"__dtrace_probe$Foo$added$v1$696e74"(i32) #1 + +!10 = !{i64 2147498363} +!11 = !{i64 2147498406} +!12 = !{i64 2147498500} Index: lld/test/MachO/arm64-dtrace.ll =================================================================== --- /dev/null +++ lld/test/MachO/arm64-dtrace.ll @@ -0,0 +1,56 @@ +; RUN: rm -rf %t; split-file %s %t + +; RUN: llvm-as %t/arm64-dtrace.ll -o %t/arm64-dtrace.ll.o +; RUN: %lld -demangle -dynamic -arch arm64 -platform_version macos 12.0.0 12.3 -o %t/arm64-dtrace %t/arm64-dtrace.ll.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 kindStoreARM64DtraceIsEnableSiteClear +; CHECK: 00 00 80 d2 mov x0, #0 + +;; Check kindStoreARM64DtraceCallSiteNop +; CHECK: 1f 20 03 d5 nop + +;--- arm64-dtrace.ll +source_filename = "main.cpp" +target datalayout = "e-m:o-i64:64-i128:128-n32:64-S128" +target triple = "arm64-apple-macosx12.0.0" + +define i32 @main() #0 { + %1 = alloca i32, align 4 + %2 = alloca i32, align 4 + %3 = alloca i32, align 4 + store i32 0, i32* %1, align 4 + %4 = call i32 @"__dtrace_isenabled$Foo$added$v1"() + store i32 %4, i32* %2, align 4 + call void asm sideeffect "", ""() #2, !srcloc !10 + %5 = load i32, i32* %2, align 4 + store i32 %5, i32* %3, align 4 + %6 = load i32, i32* %3, align 4 + %7 = icmp ne i32 %6, 0 + br i1 %7, label %8, label %11 + +8: ; preds = %0 + br label %9 + +9: ; preds = %8 + call void asm sideeffect ".reference ___dtrace_typedefs$$Foo$$v2", ""() #2, !srcloc !11 + call void @"__dtrace_probe$Foo$added$v1$696e74"(i32 0) + call void asm sideeffect ".reference ___dtrace_stability$$Foo$$v1$$1_1_0_1_1_0_1_1_0_1_1_0_1_1_0", ""() #2, !srcloc !12 + br label %10 + +10: ; preds = %9 + br label %11 + +11: ; preds = %10, %0 + ret i32 0 +} + +declare i32 @"__dtrace_isenabled$Foo$added$v1"() #1 + +declare void @"__dtrace_probe$Foo$added$v1$696e74"(i32) #1 + +!10 = !{i64 2147498685} +!11 = !{i64 2147498728} +!12 = !{i64 2147498822} Index: lld/test/MachO/x86_64-dtrace.ll =================================================================== --- /dev/null +++ lld/test/MachO/x86_64-dtrace.ll @@ -0,0 +1,60 @@ +; RUN: rm -rf %t; split-file %s %t + +; RUN: llvm-as %t/x86_64-dtrace.ll -o %t/x86_64-dtrace.ll.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.ll.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 kindStoreX86DtraceIsEnableSiteClear +; CHECK: 33 c0 xorl %eax, %eax +; CHECK: 90 nop +; CHECK: 90 nop +; CHECK: 90 nop + +;; Check kindStoreX86DtraceCallSiteNop +; CHECK: 90 nop +; CHECK: 0f 1f 40 00 nopl (%rax) + +;--- x86_64-dtrace.ll +source_filename = "main.cpp" +target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128" +target triple = "x86_64-apple-macosx12.0.0" + +define i32 @main() #0 { + %1 = alloca i32, align 4 + %2 = alloca i32, align 4 + %3 = alloca i32, align 4 + store i32 0, i32* %1, align 4 + %4 = call i32 @"__dtrace_isenabled$Foo$added$v1"() + store i32 %4, i32* %2, align 4 + call void asm sideeffect "", "~{dirflag},~{fpsr},~{flags}"() #2, !srcloc !6 + %5 = load i32, i32* %2, align 4 + store i32 %5, i32* %3, align 4 + %6 = load i32, i32* %3, align 4 + %7 = icmp ne i32 %6, 0 + br i1 %7, label %8, label %11 + +8: ; preds = %0 + br label %9 + +9: ; preds = %8 + call void asm sideeffect ".reference ___dtrace_typedefs$$Foo$$v2", "~{dirflag},~{fpsr},~{flags}"() #2, !srcloc !7 + call void @"__dtrace_probe$Foo$added$v1$696e74"(i32 0) + call void asm sideeffect ".reference ___dtrace_stability$$Foo$$v1$$1_1_0_1_1_0_1_1_0_1_1_0_1_1_0", "~{dirflag},~{fpsr},~{flags}"() #2, !srcloc !8 + br label %10 + +10: ; preds = %9 + br label %11 + +11: ; preds = %10, %0 + ret i32 0 +} + +declare i32 @"__dtrace_isenabled$Foo$added$v1"() #1 + +declare void @"__dtrace_probe$Foo$added$v1$696e74"(i32) #1 + +!6 = !{i64 2147497742} +!7 = !{i64 2147497785} +!8 = !{i64 2147497879}