llvm.org GIT mirror llvm / a64c974
[xray] Add XRay support for Mach-O in CodeGen Currently, XRay only supports emitting the XRay table (xray_instr_map) on ELF binaries. Let's add Mach-O support. Differential Revision: https://reviews.llvm.org/D26983 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@287734 91177308-0d34-0410-b5e6-96231b3b80d8 Kuba Mracek 3 years ago
8 changed file(s) with 124 addition(s) and 92 deletion(s). Raw diff Collapse all Expand all
3838 #include "llvm/MC/MCSymbol.h"
3939 #include "llvm/MC/MCSymbolELF.h"
4040 #include "llvm/MC/MCSectionELF.h"
41 #include "llvm/MC/MCSectionMachO.h"
4142 #include "llvm/Support/Debug.h"
4243 #include "llvm/Support/TargetRegistry.h"
4344 #include "llvm/Support/raw_ostream.h"
154155 // code duplication as it is now for x86_64, ARM32 and AArch64.
155156 if (Sleds.empty())
156157 return;
158
159 auto PrevSection = OutStreamer->getCurrentSectionOnly();
160 auto Fn = MF->getFunction();
161 MCSection *Section;
162
157163 if (STI->isTargetELF()) {
158 auto PrevSection = OutStreamer->getCurrentSectionOnly();
159 auto Fn = MF->getFunction();
160 MCSection *Section;
161164 if (Fn->hasComdat())
162165 Section = OutContext.getELFSection("xray_instr_map", ELF::SHT_PROGBITS,
163166 ELF::SHF_ALLOC | ELF::SHF_GROUP, 0,
165168 else
166169 Section = OutContext.getELFSection("xray_instr_map", ELF::SHT_PROGBITS,
167170 ELF::SHF_ALLOC);
168
169 // Before we switch over, we force a reference to a label inside the
170 // xray_instr_map section. Since EmitXRayTable() is always called just
171 // before the function's end, we assume that this is happening after the
172 // last return instruction.
173 //
174 // We then align the reference to 16 byte boundaries, which we determined
175 // experimentally to be beneficial to avoid causing decoder stalls.
176 MCSymbol *Tmp = OutContext.createTempSymbol("xray_synthetic_", true);
177 OutStreamer->EmitCodeAlignment(16);
178 OutStreamer->EmitSymbolValue(Tmp, 8, false);
179 OutStreamer->SwitchSection(Section);
180 OutStreamer->EmitLabel(Tmp);
181 for (const auto &Sled : Sleds) {
182 OutStreamer->EmitSymbolValue(Sled.Sled, 8);
183 OutStreamer->EmitSymbolValue(CurrentFnSym, 8);
184 auto Kind = static_cast(Sled.Kind);
185 OutStreamer->EmitBytes(
186 StringRef(reinterpret_cast(&Kind), 1));
187 OutStreamer->EmitBytes(
188 StringRef(reinterpret_cast(&Sled.AlwaysInstrument), 1));
189 OutStreamer->EmitZeros(14);
190 }
191 OutStreamer->SwitchSection(PrevSection);
192 }
171 } else if (STI->isTargetMachO()) {
172 Section = OutContext.getMachOSection("__DATA", "xray_instr_map", 0,
173 SectionKind::getReadOnlyWithRel());
174 } else {
175 llvm_unreachable("Unsupported target");
176 }
177
178 // Before we switch over, we force a reference to a label inside the
179 // xray_instr_map section. Since EmitXRayTable() is always called just
180 // before the function's end, we assume that this is happening after the
181 // last return instruction.
182 //
183 // We then align the reference to 16 byte boundaries, which we determined
184 // experimentally to be beneficial to avoid causing decoder stalls.
185 MCSymbol *Tmp = OutContext.createTempSymbol("xray_synthetic_", true);
186 OutStreamer->EmitCodeAlignment(16);
187 OutStreamer->EmitSymbolValue(Tmp, 8, false);
188 OutStreamer->SwitchSection(Section);
189 OutStreamer->EmitLabel(Tmp);
190 for (const auto &Sled : Sleds) {
191 OutStreamer->EmitSymbolValue(Sled.Sled, 8);
192 OutStreamer->EmitSymbolValue(CurrentFnSym, 8);
193 auto Kind = static_cast(Sled.Kind);
194 OutStreamer->EmitBytes(
195 StringRef(reinterpret_cast(&Kind), 1));
196 OutStreamer->EmitBytes(
197 StringRef(reinterpret_cast(&Sled.AlwaysInstrument), 1));
198 OutStreamer->EmitZeros(14);
199 }
200 OutStreamer->SwitchSection(PrevSection);
201
193202 Sleds.clear();
194203 }
195204
2323 #include "llvm/MC/MCContext.h"
2424 #include "llvm/MC/MCSymbolELF.h"
2525 #include "llvm/MC/MCSectionELF.h"
26 #include "llvm/MC/MCSectionMachO.h"
2627 #include "llvm/MC/MCInstBuilder.h"
2728 #include "llvm/MC/MCStreamer.h"
2829 using namespace llvm;
227228 {
228229 if (Sleds.empty())
229230 return;
231
232 MCSection *Section = nullptr;
230233 if (Subtarget->isTargetELF()) {
231 auto *Section = OutContext.getELFSection(
232 "xray_instr_map", ELF::SHT_PROGBITS,
233 ELF::SHF_ALLOC | ELF::SHF_GROUP | ELF::SHF_MERGE, 0,
234 CurrentFnSym->getName());
235 auto PrevSection = OutStreamer->getCurrentSectionOnly();
236 OutStreamer->SwitchSection(Section);
237 for (const auto &Sled : Sleds) {
238 OutStreamer->EmitSymbolValue(Sled.Sled, 4);
239 OutStreamer->EmitSymbolValue(CurrentFnSym, 4);
240 auto Kind = static_cast(Sled.Kind);
241 OutStreamer->EmitBytes(
242 StringRef(reinterpret_cast(&Kind), 1));
243 OutStreamer->EmitBytes(
244 StringRef(reinterpret_cast(&Sled.AlwaysInstrument), 1));
245 OutStreamer->EmitZeros(6);
246 }
247 OutStreamer->SwitchSection(PrevSection);
248 }
234 Section = OutContext.getELFSection("xray_instr_map", ELF::SHT_PROGBITS,
235 ELF::SHF_ALLOC | ELF::SHF_GROUP |
236 ELF::SHF_MERGE,
237 0, CurrentFnSym->getName());
238 } else if (Subtarget->isTargetMachO()) {
239 Section = OutContext.getMachOSection("__DATA", "xray_instr_map", 0,
240 SectionKind::getReadOnlyWithRel());
241 } else {
242 llvm_unreachable("Unsupported target");
243 }
244
245 auto PrevSection = OutStreamer->getCurrentSectionOnly();
246 OutStreamer->SwitchSection(Section);
247 for (const auto &Sled : Sleds) {
248 OutStreamer->EmitSymbolValue(Sled.Sled, 4);
249 OutStreamer->EmitSymbolValue(CurrentFnSym, 4);
250 auto Kind = static_cast(Sled.Kind);
251 OutStreamer->EmitBytes(
252 StringRef(reinterpret_cast(&Kind), 1));
253 OutStreamer->EmitBytes(
254 StringRef(reinterpret_cast(&Sled.AlwaysInstrument), 1));
255 OutStreamer->EmitZeros(6);
256 }
257 OutStreamer->SwitchSection(PrevSection);
258
249259 Sleds.clear();
250260 }
4040 #include "llvm/MC/MCSymbol.h"
4141 #include "llvm/MC/MCSymbolELF.h"
4242 #include "llvm/MC/MCSectionELF.h"
43 #include "llvm/MC/MCSectionMachO.h"
4344 #include "llvm/Support/TargetRegistry.h"
4445 #include "llvm/Support/ELF.h"
4546 #include "llvm/Target/TargetLoweringObjectFile.h"
11151116 void X86AsmPrinter::EmitXRayTable() {
11161117 if (Sleds.empty())
11171118 return;
1119
1120 auto PrevSection = OutStreamer->getCurrentSectionOnly();
1121 auto Fn = MF->getFunction();
1122 MCSection *Section = nullptr;
11181123 if (Subtarget->isTargetELF()) {
1119 auto PrevSection = OutStreamer->getCurrentSectionOnly();
1120 auto Fn = MF->getFunction();
1121 MCSection *Section = nullptr;
11221124 if (Fn->hasComdat()) {
11231125 Section = OutContext.getELFSection("xray_instr_map", ELF::SHT_PROGBITS,
11241126 ELF::SHF_ALLOC | ELF::SHF_GROUP, 0,
11271129 Section = OutContext.getELFSection("xray_instr_map", ELF::SHT_PROGBITS,
11281130 ELF::SHF_ALLOC);
11291131 }
1130
1131 // Before we switch over, we force a reference to a label inside the
1132 // xray_instr_map section. Since EmitXRayTable() is always called just
1133 // before the function's end, we assume that this is happening after the
1134 // last return instruction.
1135 //
1136 // We then align the reference to 16 byte boundaries, which we determined
1137 // experimentally to be beneficial to avoid causing decoder stalls.
1138 MCSymbol *Tmp = OutContext.createTempSymbol("xray_synthetic_", true);
1139 OutStreamer->EmitCodeAlignment(16);
1140 OutStreamer->EmitSymbolValue(Tmp, 8, false);
1141 OutStreamer->SwitchSection(Section);
1142 OutStreamer->EmitLabel(Tmp);
1143 for (const auto &Sled : Sleds) {
1144 OutStreamer->EmitSymbolValue(Sled.Sled, 8);
1145 OutStreamer->EmitSymbolValue(CurrentFnSym, 8);
1146 auto Kind = static_cast(Sled.Kind);
1147 OutStreamer->EmitBytes(
1148 StringRef(reinterpret_cast(&Kind), 1));
1149 OutStreamer->EmitBytes(
1150 StringRef(reinterpret_cast(&Sled.AlwaysInstrument), 1));
1151 OutStreamer->EmitZeros(14);
1152 }
1153 OutStreamer->SwitchSection(PrevSection);
1154 }
1132 } else if (Subtarget->isTargetMachO()) {
1133 Section = OutContext.getMachOSection("__DATA", "xray_instr_map", 0,
1134 SectionKind::getReadOnlyWithRel());
1135 } else {
1136 llvm_unreachable("Unsupported target");
1137 }
1138
1139 // Before we switch over, we force a reference to a label inside the
1140 // xray_instr_map section. Since EmitXRayTable() is always called just
1141 // before the function's end, we assume that this is happening after the
1142 // last return instruction.
1143 //
1144 // We then align the reference to 16 byte boundaries, which we determined
1145 // experimentally to be beneficial to avoid causing decoder stalls.
1146 MCSymbol *Tmp = OutContext.createTempSymbol("xray_synthetic_", true);
1147 OutStreamer->EmitCodeAlignment(16);
1148 OutStreamer->EmitSymbolValue(Tmp, 8, false);
1149 OutStreamer->SwitchSection(Section);
1150 OutStreamer->EmitLabel(Tmp);
1151 for (const auto &Sled : Sleds) {
1152 OutStreamer->EmitSymbolValue(Sled.Sled, 8);
1153 OutStreamer->EmitSymbolValue(CurrentFnSym, 8);
1154 auto Kind = static_cast(Sled.Kind);
1155 OutStreamer->EmitBytes(
1156 StringRef(reinterpret_cast(&Kind), 1));
1157 OutStreamer->EmitBytes(
1158 StringRef(reinterpret_cast(&Sled.AlwaysInstrument), 1));
1159 OutStreamer->EmitZeros(14);
1160 }
1161 OutStreamer->SwitchSection(PrevSection);
1162
11551163 Sleds.clear();
11561164 }
11571165
0 ; RUN: llc -filetype=asm -o - -mtriple=armv6-unknown-linux-gnu < %s | FileCheck %s
1 ; RUN: llc -filetype=asm -o - -mtriple=armv6-apple-ios6.0.0 < %s | FileCheck %s
12
23 define i32 @foo() nounwind noinline uwtable "function-instrument"="xray-always" {
34 ; CHECK-LABEL: Lxray_sled_0:
0 ; RUN: llc -filetype=asm -o - -mtriple=armv7-unknown-linux-gnu < %s | FileCheck %s
1 ; RUN: llc -filetype=asm -o - -mtriple=armv7-apple-ios6.0.0 < %s | FileCheck %s
12
23 define i32 @foo() nounwind noinline uwtable "function-instrument"="xray-always" {
34 ; CHECK-LABEL: Lxray_sled_0:
0 ; RUN: llc -filetype=asm -o - -mtriple=armv7-unknown-linux-gnu < %s | FileCheck %s
1 ; RUN: llc -filetype=asm -o - -mtriple=armv7-apple-ios6.0.0 < %s | FileCheck %s
12
23 define i32 @callee() nounwind noinline uwtable "function-instrument"="xray-always" {
34 ; CHECK: .p2align 2
4748 ; CHECK-NEXT: nop
4849 ; CHECK-LABEL: Ltmp3:
4950 %retval = tail call i32 @callee()
50 ; CHECK: b callee
51 ; CHECK: b {{.*}}callee
5152 ret i32 %retval
5253 }
0 ; RUN: llc -filetype=asm -o - -mtriple=x86_64-unknown-linux-gnu < %s | FileCheck %s
1 ; RUN: llc -filetype=asm -o - -mtriple=x86_64-darwin-unknown < %s | FileCheck %s
12
23 define i32 @foo() nounwind noinline uwtable "function-instrument"="xray-always" {
34 ; CHECK: .p2align 1, 0x90
1213 ; CHECK-NEXT: nopw %cs:512(%rax,%rax)
1314 }
1415 ; CHECK: .p2align 4, 0x90
15 ; CHECK-NEXT: .quad .Lxray_synthetic_0
16 ; CHECK-NEXT: .section xray_instr_map,{{.*}}
16 ; CHECK-NEXT: .quad {{.*}}xray_synthetic_0
17 ; CHECK-NEXT: .section {{.*}}xray_instr_map
1718 ; CHECK-LABEL: Lxray_synthetic_0:
18 ; CHECK: .quad .Lxray_sled_0
19 ; CHECK: .quad .Lxray_sled_1
19 ; CHECK: .quad {{.*}}xray_sled_0
20 ; CHECK: .quad {{.*}}xray_sled_1
2021
2122 ; We test multiple returns in a single function to make sure we're getting all
2223 ; of them with XRay instrumentation.
4344 ; CHECK-NEXT: nopw %cs:512(%rax,%rax)
4445 }
4546 ; CHECK: .p2align 4, 0x90
46 ; CHECK-NEXT: .quad .Lxray_synthetic_1
47 ; CHECK-NEXT: .section xray_instr_map,{{.*}}
47 ; CHECK-NEXT: .quad {{.*}}xray_synthetic_1
48 ; CHECK-NEXT: .section {{.*}}xray_instr_map
4849 ; CHECK-LABEL: Lxray_synthetic_1:
49 ; CHECK: .quad .Lxray_sled_2
50 ; CHECK: .quad .Lxray_sled_3
51 ; CHECK: .quad .Lxray_sled_4
50 ; CHECK: .quad {{.*}}xray_sled_2
51 ; CHECK: .quad {{.*}}xray_sled_3
52 ; CHECK: .quad {{.*}}xray_sled_4
0 ; RUN: llc -filetype=asm -o - -mtriple=x86_64-unknown-linux-gnu < %s | FileCheck %s
1 ; RUN: llc -filetype=asm -o - -mtriple=x86_64-darwin-unknown < %s | FileCheck %s
12
23 define i32 @callee() nounwind noinline uwtable "function-instrument"="xray-always" {
34 ; CHECK: .p2align 1, 0x90
1213 ; CHECK-NEXT: nopw %cs:512(%rax,%rax)
1314 }
1415 ; CHECK: .p2align 4, 0x90
15 ; CHECK-NEXT: .quad .Lxray_synthetic_0
16 ; CHECK-NEXT: .section xray_instr_map,{{.*}}
16 ; CHECK-NEXT: .quad {{.*}}xray_synthetic_0
17 ; CHECK-NEXT: .section {{.*}}xray_instr_map
1718 ; CHECK-LABEL: Lxray_synthetic_0:
18 ; CHECK: .quad .Lxray_sled_0
19 ; CHECK: .quad .Lxray_sled_1
19 ; CHECK: .quad {{.*}}xray_sled_0
20 ; CHECK: .quad {{.*}}xray_sled_1
2021
2122 define i32 @caller() nounwind noinline uwtable "function-instrument"="xray-always" {
2223 ; CHECK: .p2align 1, 0x90
3031 ; CHECK-NEXT: nopw 512(%rax,%rax)
3132 ; CHECK-LABEL: Ltmp2:
3233 %retval = tail call i32 @callee()
33 ; CHECK: jmp callee # TAILCALL
34 ; CHECK: jmp {{.*}}callee {{.*}}# TAILCALL
3435 ret i32 %retval
3536 }
3637 ; CHECK: .p2align 4, 0x90
37 ; CHECK-NEXT: .quad .Lxray_synthetic_1
38 ; CHECK-NEXT: .quad {{.*}}xray_synthetic_1
3839 ; CHECK-LABEL: Lxray_synthetic_1:
39 ; CHECK: .quad .Lxray_sled_2
40 ; CHECK: .quad .Lxray_sled_3
40 ; CHECK: .quad {{.*}}xray_sled_2
41 ; CHECK: .quad {{.*}}xray_sled_3