1 | /* |
2 | * Copyright 2016-present Facebook, Inc. |
3 | * |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. |
6 | * You may obtain a copy of the License at |
7 | * |
8 | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | * |
10 | * Unless required by applicable law or agreed to in writing, software |
11 | * distributed under the License is distributed on an "AS IS" BASIS, |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | * See the License for the specific language governing permissions and |
14 | * limitations under the License. |
15 | */ |
16 | |
17 | #pragma once |
18 | |
19 | // clang-format off |
20 | #include <cstddef> |
21 | |
22 | // Default constraint for the probe arguments as operands. |
23 | #ifndef FOLLY_SDT_ARG_CONSTRAINT |
24 | #define FOLLY_SDT_ARG_CONSTRAINT "nor" |
25 | #endif |
26 | |
27 | // Instruction to emit for the probe. |
28 | #define FOLLY_SDT_NOP nop |
29 | |
30 | // Note section properties. |
31 | #define FOLLY_SDT_NOTE_NAME "stapsdt" |
32 | #define FOLLY_SDT_NOTE_TYPE 3 |
33 | |
34 | // Semaphore variables are put in this section |
35 | #define FOLLY_SDT_SEMAPHORE_SECTION ".probes" |
36 | |
37 | // Size of address depending on platform. |
38 | #ifdef __LP64__ |
39 | #define FOLLY_SDT_ASM_ADDR .8byte |
40 | #else |
41 | #define FOLLY_SDT_ASM_ADDR .4byte |
42 | #endif |
43 | |
44 | // Assembler helper Macros. |
45 | #define FOLLY_SDT_S(x) #x |
46 | #define FOLLY_SDT_ASM_1(x) FOLLY_SDT_S(x) "\n" |
47 | #define FOLLY_SDT_ASM_2(a, b) FOLLY_SDT_S(a) "," FOLLY_SDT_S(b) "\n" |
48 | #define FOLLY_SDT_ASM_3(a, b, c) FOLLY_SDT_S(a) "," FOLLY_SDT_S(b) "," \ |
49 | FOLLY_SDT_S(c) "\n" |
50 | #define FOLLY_SDT_ASM_STRING(x) FOLLY_SDT_ASM_1(.asciz FOLLY_SDT_S(x)) |
51 | |
52 | // Helper to determine the size of an argument. |
53 | #define FOLLY_SDT_IS_ARRAY_POINTER(x) ((__builtin_classify_type(x) == 14) || \ |
54 | (__builtin_classify_type(x) == 5)) |
55 | #define FOLLY_SDT_ARGSIZE(x) (FOLLY_SDT_IS_ARRAY_POINTER(x) \ |
56 | ? sizeof(void*) \ |
57 | : sizeof(x)) |
58 | |
59 | // Format of each probe arguments as operand. |
60 | // Size of the arugment tagged with FOLLY_SDT_Sn, with "n" constraint. |
61 | // Value of the argument tagged with FOLLY_SDT_An, with configured constraint. |
62 | #define FOLLY_SDT_ARG(n, x) \ |
63 | [FOLLY_SDT_S##n] "n" ((size_t)FOLLY_SDT_ARGSIZE(x)), \ |
64 | [FOLLY_SDT_A##n] FOLLY_SDT_ARG_CONSTRAINT (x) |
65 | |
66 | // Templates to append arguments as operands. |
67 | #define FOLLY_SDT_OPERANDS_0() [__sdt_dummy] "g" (0) |
68 | #define FOLLY_SDT_OPERANDS_1(_1) FOLLY_SDT_ARG(1, _1) |
69 | #define FOLLY_SDT_OPERANDS_2(_1, _2) \ |
70 | FOLLY_SDT_OPERANDS_1(_1), FOLLY_SDT_ARG(2, _2) |
71 | #define FOLLY_SDT_OPERANDS_3(_1, _2, _3) \ |
72 | FOLLY_SDT_OPERANDS_2(_1, _2), FOLLY_SDT_ARG(3, _3) |
73 | #define FOLLY_SDT_OPERANDS_4(_1, _2, _3, _4) \ |
74 | FOLLY_SDT_OPERANDS_3(_1, _2, _3), FOLLY_SDT_ARG(4, _4) |
75 | #define FOLLY_SDT_OPERANDS_5(_1, _2, _3, _4, _5) \ |
76 | FOLLY_SDT_OPERANDS_4(_1, _2, _3, _4), FOLLY_SDT_ARG(5, _5) |
77 | #define FOLLY_SDT_OPERANDS_6(_1, _2, _3, _4, _5, _6) \ |
78 | FOLLY_SDT_OPERANDS_5(_1, _2, _3, _4, _5), FOLLY_SDT_ARG(6, _6) |
79 | #define FOLLY_SDT_OPERANDS_7(_1, _2, _3, _4, _5, _6, _7) \ |
80 | FOLLY_SDT_OPERANDS_6(_1, _2, _3, _4, _5, _6), FOLLY_SDT_ARG(7, _7) |
81 | #define FOLLY_SDT_OPERANDS_8(_1, _2, _3, _4, _5, _6, _7, _8) \ |
82 | FOLLY_SDT_OPERANDS_7(_1, _2, _3, _4, _5, _6, _7), FOLLY_SDT_ARG(8, _8) |
83 | #define FOLLY_SDT_OPERANDS_9(_1, _2, _3, _4, _5, _6, _7, _8, _9) \ |
84 | FOLLY_SDT_OPERANDS_8(_1, _2, _3, _4, _5, _6, _7, _8), FOLLY_SDT_ARG(9, _9) |
85 | |
86 | // Templates to reference the arguments from operands in note section. |
87 | #define FOLLY_SDT_ARGFMT(no) %n[FOLLY_SDT_S##no]@%[FOLLY_SDT_A##no] |
88 | #define FOLLY_SDT_ARG_TEMPLATE_0 /*No arguments*/ |
89 | #define FOLLY_SDT_ARG_TEMPLATE_1 FOLLY_SDT_ARGFMT(1) |
90 | #define FOLLY_SDT_ARG_TEMPLATE_2 FOLLY_SDT_ARG_TEMPLATE_1 FOLLY_SDT_ARGFMT(2) |
91 | #define FOLLY_SDT_ARG_TEMPLATE_3 FOLLY_SDT_ARG_TEMPLATE_2 FOLLY_SDT_ARGFMT(3) |
92 | #define FOLLY_SDT_ARG_TEMPLATE_4 FOLLY_SDT_ARG_TEMPLATE_3 FOLLY_SDT_ARGFMT(4) |
93 | #define FOLLY_SDT_ARG_TEMPLATE_5 FOLLY_SDT_ARG_TEMPLATE_4 FOLLY_SDT_ARGFMT(5) |
94 | #define FOLLY_SDT_ARG_TEMPLATE_6 FOLLY_SDT_ARG_TEMPLATE_5 FOLLY_SDT_ARGFMT(6) |
95 | #define FOLLY_SDT_ARG_TEMPLATE_7 FOLLY_SDT_ARG_TEMPLATE_6 FOLLY_SDT_ARGFMT(7) |
96 | #define FOLLY_SDT_ARG_TEMPLATE_8 FOLLY_SDT_ARG_TEMPLATE_7 FOLLY_SDT_ARGFMT(8) |
97 | #define FOLLY_SDT_ARG_TEMPLATE_9 FOLLY_SDT_ARG_TEMPLATE_8 FOLLY_SDT_ARGFMT(9) |
98 | |
99 | // Semaphore define, declare and probe note format |
100 | |
101 | #define FOLLY_SDT_SEMAPHORE(provider, name) \ |
102 | folly_sdt_semaphore_##provider##_##name |
103 | |
104 | #define FOLLY_SDT_DEFINE_SEMAPHORE(provider, name) \ |
105 | extern "C" { \ |
106 | volatile unsigned short FOLLY_SDT_SEMAPHORE(provider, name) \ |
107 | __attribute__((section(FOLLY_SDT_SEMAPHORE_SECTION), used)) = 0; \ |
108 | } |
109 | |
110 | #define FOLLY_SDT_DECLARE_SEMAPHORE(provider, name) \ |
111 | extern "C" volatile unsigned short FOLLY_SDT_SEMAPHORE(provider, name) |
112 | |
113 | #define FOLLY_SDT_SEMAPHORE_NOTE_0(provider, name) \ |
114 | FOLLY_SDT_ASM_1( FOLLY_SDT_ASM_ADDR 0) /*No Semaphore*/ \ |
115 | |
116 | #define FOLLY_SDT_SEMAPHORE_NOTE_1(provider, name) \ |
117 | FOLLY_SDT_ASM_1(FOLLY_SDT_ASM_ADDR FOLLY_SDT_SEMAPHORE(provider, name)) |
118 | |
119 | // Structure of note section for the probe. |
120 | #define FOLLY_SDT_NOTE_CONTENT(provider, name, has_semaphore, arg_template) \ |
121 | FOLLY_SDT_ASM_1(990: FOLLY_SDT_NOP) \ |
122 | FOLLY_SDT_ASM_3( .pushsection .note.stapsdt,"","note") \ |
123 | FOLLY_SDT_ASM_1( .balign 4) \ |
124 | FOLLY_SDT_ASM_3( .4byte 992f-991f, 994f-993f, FOLLY_SDT_NOTE_TYPE) \ |
125 | FOLLY_SDT_ASM_1(991: .asciz FOLLY_SDT_NOTE_NAME) \ |
126 | FOLLY_SDT_ASM_1(992: .balign 4) \ |
127 | FOLLY_SDT_ASM_1(993: FOLLY_SDT_ASM_ADDR 990b) \ |
128 | FOLLY_SDT_ASM_1( FOLLY_SDT_ASM_ADDR 0) /*Reserved for Base Address*/ \ |
129 | FOLLY_SDT_SEMAPHORE_NOTE_##has_semaphore(provider, name) \ |
130 | FOLLY_SDT_ASM_STRING(provider) \ |
131 | FOLLY_SDT_ASM_STRING(name) \ |
132 | FOLLY_SDT_ASM_STRING(arg_template) \ |
133 | FOLLY_SDT_ASM_1(994: .balign 4) \ |
134 | FOLLY_SDT_ASM_1( .popsection) |
135 | |
136 | // Main probe Macro. |
137 | #define FOLLY_SDT_PROBE(provider, name, has_semaphore, n, arglist) \ |
138 | __asm__ __volatile__ ( \ |
139 | FOLLY_SDT_NOTE_CONTENT( \ |
140 | provider, name, has_semaphore, FOLLY_SDT_ARG_TEMPLATE_##n) \ |
141 | :: FOLLY_SDT_OPERANDS_##n arglist \ |
142 | ) \ |
143 | |
144 | // Helper Macros to handle variadic arguments. |
145 | #define FOLLY_SDT_NARG_(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, N, ...) N |
146 | #define FOLLY_SDT_NARG(...) \ |
147 | FOLLY_SDT_NARG_(__VA_ARGS__, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0) |
148 | #define FOLLY_SDT_PROBE_N(provider, name, has_semaphore, N, ...) \ |
149 | FOLLY_SDT_PROBE(provider, name, has_semaphore, N, (__VA_ARGS__)) |
150 | |