514 lines · c
1/* <sys/sdt.h> - Systemtap static probe definition macros.2 3 This file is dedicated to the public domain, pursuant to CC04 (https://creativecommons.org/publicdomain/zero/1.0/)5*/6 7#ifndef _SYS_SDT_H8#define _SYS_SDT_H 19 10/*11 This file defines a family of macros12 13 STAP_PROBEn(op1, ..., opn)14 15 that emit a nop into the instruction stream, and some data into an auxiliary16 note section. The data in the note section describes the operands, in terms17 of size and location. Each location is encoded as assembler operand string.18 Consumer tools such as gdb or systemtap insert breakpoints on top of19 the nop, and decode the location operand-strings, like an assembler,20 to find the values being passed.21 22 The operand strings are selected by the compiler for each operand.23 They are constrained by gcc inline-assembler codes. The default is:24 25 #define STAP_SDT_ARG_CONSTRAINT nor26 27 This is a good default if the operands tend to be integral and28 moderate in number (smaller than number of registers). In other29 cases, the compiler may report "'asm' requires impossible reload" or30 similar. In this case, consider simplifying the macro call (fewer31 and simpler operands), reduce optimization, or override the default32 constraints string via:33 34 #define STAP_SDT_ARG_CONSTRAINT g35 #include <sys/sdt.h>36 37 See also:38 https://sourceware.org/systemtap/wiki/UserSpaceProbeImplementation39 https://gcc.gnu.org/onlinedocs/gcc/Constraints.html40 */41 42 43 44#ifdef __ASSEMBLER__45# define _SDT_PROBE(provider, name, n, arglist) \46 _SDT_ASM_BODY(provider, name, _SDT_ASM_SUBSTR_1, (_SDT_DEPAREN_##n arglist)) \47 _SDT_ASM_BASE48# define _SDT_ASM_1(x) x;49# define _SDT_ASM_2(a, b) a,b;50# define _SDT_ASM_3(a, b, c) a,b,c;51# define _SDT_ASM_5(a, b, c, d, e) a,b,c,d,e;52# define _SDT_ASM_STRING_1(x) .asciz #x;53# define _SDT_ASM_SUBSTR_1(x) .ascii #x;54# define _SDT_DEPAREN_0() /* empty */55# define _SDT_DEPAREN_1(a) a56# define _SDT_DEPAREN_2(a,b) a b57# define _SDT_DEPAREN_3(a,b,c) a b c58# define _SDT_DEPAREN_4(a,b,c,d) a b c d59# define _SDT_DEPAREN_5(a,b,c,d,e) a b c d e60# define _SDT_DEPAREN_6(a,b,c,d,e,f) a b c d e f61# define _SDT_DEPAREN_7(a,b,c,d,e,f,g) a b c d e f g62# define _SDT_DEPAREN_8(a,b,c,d,e,f,g,h) a b c d e f g h63# define _SDT_DEPAREN_9(a,b,c,d,e,f,g,h,i) a b c d e f g h i64# define _SDT_DEPAREN_10(a,b,c,d,e,f,g,h,i,j) a b c d e f g h i j65# define _SDT_DEPAREN_11(a,b,c,d,e,f,g,h,i,j,k) a b c d e f g h i j k66# define _SDT_DEPAREN_12(a,b,c,d,e,f,g,h,i,j,k,l) a b c d e f g h i j k l67#else68#if defined _SDT_HAS_SEMAPHORES69#define _SDT_NOTE_SEMAPHORE_USE(provider, name) \70 __asm__ __volatile__ ("" :: "m" (provider##_##name##_semaphore));71#else72#define _SDT_NOTE_SEMAPHORE_USE(provider, name)73#endif74 75# define _SDT_PROBE(provider, name, n, arglist) \76 do { \77 _SDT_NOTE_SEMAPHORE_USE(provider, name); \78 __asm__ __volatile__ (_SDT_ASM_BODY(provider, name, _SDT_ASM_ARGS, (n)) \79 :: _SDT_ASM_OPERANDS_##n arglist); \80 __asm__ __volatile__ (_SDT_ASM_BASE); \81 } while (0)82# define _SDT_S(x) #x83# define _SDT_ASM_1(x) _SDT_S(x) "\n"84# define _SDT_ASM_2(a, b) _SDT_S(a) "," _SDT_S(b) "\n"85# define _SDT_ASM_3(a, b, c) _SDT_S(a) "," _SDT_S(b) "," \86 _SDT_S(c) "\n"87# define _SDT_ASM_5(a, b, c, d, e) _SDT_S(a) "," _SDT_S(b) "," \88 _SDT_S(c) "," _SDT_S(d) "," \89 _SDT_S(e) "\n"90# define _SDT_ASM_ARGS(n) _SDT_ASM_TEMPLATE_##n91# define _SDT_ASM_STRING_1(x) _SDT_ASM_1(.asciz #x)92# define _SDT_ASM_SUBSTR_1(x) _SDT_ASM_1(.ascii #x)93 94# define _SDT_ARGFMT(no) _SDT_ASM_1(_SDT_SIGN %n[_SDT_S##no]) \95 _SDT_ASM_1(_SDT_SIZE %n[_SDT_S##no]) \96 _SDT_ASM_1(_SDT_TYPE %n[_SDT_S##no]) \97 _SDT_ASM_SUBSTR(_SDT_ARGTMPL(_SDT_A##no))98 99 100# ifndef STAP_SDT_ARG_CONSTRAINT101# if defined __powerpc__102# define STAP_SDT_ARG_CONSTRAINT nZr103# elif defined __arm__104# define STAP_SDT_ARG_CONSTRAINT g105# else106# define STAP_SDT_ARG_CONSTRAINT nor107# endif108# endif109 110# define _SDT_STRINGIFY(x) #x111# define _SDT_ARG_CONSTRAINT_STRING(x) _SDT_STRINGIFY(x)112/* _SDT_S encodes the size and type as 0xSSTT which is decoded by the assembler113 macros _SDT_SIZE and _SDT_TYPE */114# define _SDT_ARG(n, x) \115 [_SDT_S##n] "n" ((_SDT_ARGSIGNED (x) ? (int)-1 : 1) * (-(((int) _SDT_ARGSIZE (x)) << 8) + (-(0x7f & __builtin_classify_type (x))))), \116 [_SDT_A##n] _SDT_ARG_CONSTRAINT_STRING (STAP_SDT_ARG_CONSTRAINT) (_SDT_ARGVAL (x))117#endif118#define _SDT_ASM_STRING(x) _SDT_ASM_STRING_1(x)119#define _SDT_ASM_SUBSTR(x) _SDT_ASM_SUBSTR_1(x)120 121#define _SDT_ARGARRAY(x) (__builtin_classify_type (x) == 14 \122 || __builtin_classify_type (x) == 5)123 124#ifdef __cplusplus125# define _SDT_ARGSIGNED(x) (!_SDT_ARGARRAY (x) \126 && __sdt_type<__typeof (x)>::__sdt_signed)127# define _SDT_ARGSIZE(x) (_SDT_ARGARRAY (x) \128 ? sizeof (void *) : sizeof (x))129# define _SDT_ARGVAL(x) (x)130 131# include <cstddef>132 133template<typename __sdt_T>134struct __sdt_type135{136 static const bool __sdt_signed = false;137};138 139#define __SDT_ALWAYS_SIGNED(T) \140template<> struct __sdt_type<T> { static const bool __sdt_signed = true; };141#define __SDT_COND_SIGNED(T,CT) \142template<> struct __sdt_type<T> { static const bool __sdt_signed = ((CT)(-1) < 1); };143__SDT_ALWAYS_SIGNED(signed char)144__SDT_ALWAYS_SIGNED(short)145__SDT_ALWAYS_SIGNED(int)146__SDT_ALWAYS_SIGNED(long)147__SDT_ALWAYS_SIGNED(long long)148__SDT_ALWAYS_SIGNED(volatile signed char)149__SDT_ALWAYS_SIGNED(volatile short)150__SDT_ALWAYS_SIGNED(volatile int)151__SDT_ALWAYS_SIGNED(volatile long)152__SDT_ALWAYS_SIGNED(volatile long long)153__SDT_ALWAYS_SIGNED(const signed char)154__SDT_ALWAYS_SIGNED(const short)155__SDT_ALWAYS_SIGNED(const int)156__SDT_ALWAYS_SIGNED(const long)157__SDT_ALWAYS_SIGNED(const long long)158__SDT_ALWAYS_SIGNED(const volatile signed char)159__SDT_ALWAYS_SIGNED(const volatile short)160__SDT_ALWAYS_SIGNED(const volatile int)161__SDT_ALWAYS_SIGNED(const volatile long)162__SDT_ALWAYS_SIGNED(const volatile long long)163__SDT_COND_SIGNED(char, char)164__SDT_COND_SIGNED(wchar_t, wchar_t)165__SDT_COND_SIGNED(volatile char, char)166__SDT_COND_SIGNED(volatile wchar_t, wchar_t)167__SDT_COND_SIGNED(const char, char)168__SDT_COND_SIGNED(const wchar_t, wchar_t)169__SDT_COND_SIGNED(const volatile char, char)170__SDT_COND_SIGNED(const volatile wchar_t, wchar_t)171#if defined (__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4))172/* __SDT_COND_SIGNED(char16_t) */173/* __SDT_COND_SIGNED(char32_t) */174#endif175 176template<typename __sdt_E>177struct __sdt_type<__sdt_E[]> : public __sdt_type<__sdt_E *> {};178 179template<typename __sdt_E, size_t __sdt_N>180struct __sdt_type<__sdt_E[__sdt_N]> : public __sdt_type<__sdt_E *> {};181 182#elif !defined(__ASSEMBLER__)183__extension__ extern unsigned long long __sdt_unsp;184# define _SDT_ARGINTTYPE(x) \185 __typeof (__builtin_choose_expr (((__builtin_classify_type (x) \186 + 3) & -4) == 4, (x), 0U))187# define _SDT_ARGSIGNED(x) \188 (!__extension__ \189 (__builtin_constant_p ((((unsigned long long) \190 (_SDT_ARGINTTYPE (x)) __sdt_unsp) \191 & ((unsigned long long)1 << (sizeof (unsigned long long) \192 * __CHAR_BIT__ - 1))) == 0) \193 || (_SDT_ARGINTTYPE (x)) -1 > (_SDT_ARGINTTYPE (x)) 0))194# define _SDT_ARGSIZE(x) \195 (_SDT_ARGARRAY (x) ? sizeof (void *) : sizeof (x))196# define _SDT_ARGVAL(x) (x)197#endif198 199#if defined __powerpc__ || defined __powerpc64__200# define _SDT_ARGTMPL(id) %I[id]%[id]201#elif defined __i386__202# define _SDT_ARGTMPL(id) %k[id] /* gcc.gnu.org/PR80115 sourceware.org/PR24541 */203#else204# define _SDT_ARGTMPL(id) %[id]205#endif206 207/* NB: gdb PR24541 highlighted an unspecified corner of the sdt.h208 operand note format.209 210 The named register may be a longer or shorter (!) alias for the211 storage where the value in question is found. For example, on212 i386, 64-bit value may be put in register pairs, and the register213 name stored would identify just one of them. Previously, gcc was214 asked to emit the %w[id] (16-bit alias of some registers holding215 operands), even when a wider 32-bit value was used.216 217 Bottom line: the byte-width given before the @ sign governs. If218 there is a mismatch between that width and that of the named219 register, then a sys/sdt.h note consumer may need to employ220 architecture-specific heuristics to figure out where the compiler221 has actually put the complete value.222*/223 224#ifdef __LP64__225# define _SDT_ASM_ADDR .8byte226#else227# define _SDT_ASM_ADDR .4byte228#endif229 230/* The ia64 and s390 nop instructions take an argument. */231#if defined(__ia64__) || defined(__s390__) || defined(__s390x__)232#define _SDT_NOP nop 0233#else234#define _SDT_NOP nop235#endif236 237#define _SDT_NOTE_NAME "stapsdt"238#define _SDT_NOTE_TYPE 3239 240/* If the assembler supports the necessary feature, then we can play241 nice with code in COMDAT sections, which comes up in C++ code.242 Without that assembler support, some combinations of probe placements243 in certain kinds of C++ code may produce link-time errors. */244#include "sdt-config.h"245#if _SDT_ASM_SECTION_AUTOGROUP_SUPPORT246# define _SDT_ASM_AUTOGROUP "?"247#else248# define _SDT_ASM_AUTOGROUP ""249#endif250 251#define _SDT_DEF_MACROS \252 _SDT_ASM_1(.altmacro) \253 _SDT_ASM_1(.macro _SDT_SIGN x) \254 _SDT_ASM_3(.pushsection .note.stapsdt,"","note") \255 _SDT_ASM_1(.iflt \\x) \256 _SDT_ASM_1(.ascii "-") \257 _SDT_ASM_1(.endif) \258 _SDT_ASM_1(.popsection) \259 _SDT_ASM_1(.endm) \260 _SDT_ASM_1(.macro _SDT_SIZE_ x) \261 _SDT_ASM_3(.pushsection .note.stapsdt,"","note") \262 _SDT_ASM_1(.ascii "\x") \263 _SDT_ASM_1(.popsection) \264 _SDT_ASM_1(.endm) \265 _SDT_ASM_1(.macro _SDT_SIZE x) \266 _SDT_ASM_1(_SDT_SIZE_ %%((-(-\\x*((-\\x>0)-(-\\x<0))))>>8)) \267 _SDT_ASM_1(.endm) \268 _SDT_ASM_1(.macro _SDT_TYPE_ x) \269 _SDT_ASM_3(.pushsection .note.stapsdt,"","note") \270 _SDT_ASM_2(.ifc 8,\\x) \271 _SDT_ASM_1(.ascii "f") \272 _SDT_ASM_1(.endif) \273 _SDT_ASM_1(.ascii "@") \274 _SDT_ASM_1(.popsection) \275 _SDT_ASM_1(.endm) \276 _SDT_ASM_1(.macro _SDT_TYPE x) \277 _SDT_ASM_1(_SDT_TYPE_ %%((\\x)&(0xff))) \278 _SDT_ASM_1(.endm)279 280#define _SDT_UNDEF_MACROS \281 _SDT_ASM_1(.purgem _SDT_SIGN) \282 _SDT_ASM_1(.purgem _SDT_SIZE_) \283 _SDT_ASM_1(.purgem _SDT_SIZE) \284 _SDT_ASM_1(.purgem _SDT_TYPE_) \285 _SDT_ASM_1(.purgem _SDT_TYPE)286 287#define _SDT_ASM_BODY(provider, name, pack_args, args, ...) \288 _SDT_DEF_MACROS \289 _SDT_ASM_1(990: _SDT_NOP) \290 _SDT_ASM_3( .pushsection .note.stapsdt,_SDT_ASM_AUTOGROUP,"note") \291 _SDT_ASM_1( .balign 4) \292 _SDT_ASM_3( .4byte 992f-991f, 994f-993f, _SDT_NOTE_TYPE) \293 _SDT_ASM_1(991: .asciz _SDT_NOTE_NAME) \294 _SDT_ASM_1(992: .balign 4) \295 _SDT_ASM_1(993: _SDT_ASM_ADDR 990b) \296 _SDT_ASM_1( _SDT_ASM_ADDR _.stapsdt.base) \297 _SDT_SEMAPHORE(provider,name) \298 _SDT_ASM_STRING(provider) \299 _SDT_ASM_STRING(name) \300 pack_args args \301 _SDT_ASM_SUBSTR(\x00) \302 _SDT_UNDEF_MACROS \303 _SDT_ASM_1(994: .balign 4) \304 _SDT_ASM_1( .popsection)305 306#define _SDT_ASM_BASE \307 _SDT_ASM_1(.ifndef _.stapsdt.base) \308 _SDT_ASM_5( .pushsection .stapsdt.base,"aG","progbits", \309 .stapsdt.base,comdat) \310 _SDT_ASM_1( .weak _.stapsdt.base) \311 _SDT_ASM_1( .hidden _.stapsdt.base) \312 _SDT_ASM_1( _.stapsdt.base: .space 1) \313 _SDT_ASM_2( .size _.stapsdt.base, 1) \314 _SDT_ASM_1( .popsection) \315 _SDT_ASM_1(.endif)316 317#if defined _SDT_HAS_SEMAPHORES318#define _SDT_SEMAPHORE(p,n) \319 _SDT_ASM_1( _SDT_ASM_ADDR p##_##n##_semaphore)320#else321#define _SDT_SEMAPHORE(p,n) _SDT_ASM_1( _SDT_ASM_ADDR 0)322#endif323 324#define _SDT_ASM_BLANK _SDT_ASM_SUBSTR(\x20)325#define _SDT_ASM_TEMPLATE_0 /* no arguments */326#define _SDT_ASM_TEMPLATE_1 _SDT_ARGFMT(1)327#define _SDT_ASM_TEMPLATE_2 _SDT_ASM_TEMPLATE_1 _SDT_ASM_BLANK _SDT_ARGFMT(2)328#define _SDT_ASM_TEMPLATE_3 _SDT_ASM_TEMPLATE_2 _SDT_ASM_BLANK _SDT_ARGFMT(3)329#define _SDT_ASM_TEMPLATE_4 _SDT_ASM_TEMPLATE_3 _SDT_ASM_BLANK _SDT_ARGFMT(4)330#define _SDT_ASM_TEMPLATE_5 _SDT_ASM_TEMPLATE_4 _SDT_ASM_BLANK _SDT_ARGFMT(5)331#define _SDT_ASM_TEMPLATE_6 _SDT_ASM_TEMPLATE_5 _SDT_ASM_BLANK _SDT_ARGFMT(6)332#define _SDT_ASM_TEMPLATE_7 _SDT_ASM_TEMPLATE_6 _SDT_ASM_BLANK _SDT_ARGFMT(7)333#define _SDT_ASM_TEMPLATE_8 _SDT_ASM_TEMPLATE_7 _SDT_ASM_BLANK _SDT_ARGFMT(8)334#define _SDT_ASM_TEMPLATE_9 _SDT_ASM_TEMPLATE_8 _SDT_ASM_BLANK _SDT_ARGFMT(9)335#define _SDT_ASM_TEMPLATE_10 _SDT_ASM_TEMPLATE_9 _SDT_ASM_BLANK _SDT_ARGFMT(10)336#define _SDT_ASM_TEMPLATE_11 _SDT_ASM_TEMPLATE_10 _SDT_ASM_BLANK _SDT_ARGFMT(11)337#define _SDT_ASM_TEMPLATE_12 _SDT_ASM_TEMPLATE_11 _SDT_ASM_BLANK _SDT_ARGFMT(12)338#define _SDT_ASM_OPERANDS_0() [__sdt_dummy] "g" (0)339#define _SDT_ASM_OPERANDS_1(arg1) _SDT_ARG(1, arg1)340#define _SDT_ASM_OPERANDS_2(arg1, arg2) \341 _SDT_ASM_OPERANDS_1(arg1), _SDT_ARG(2, arg2)342#define _SDT_ASM_OPERANDS_3(arg1, arg2, arg3) \343 _SDT_ASM_OPERANDS_2(arg1, arg2), _SDT_ARG(3, arg3)344#define _SDT_ASM_OPERANDS_4(arg1, arg2, arg3, arg4) \345 _SDT_ASM_OPERANDS_3(arg1, arg2, arg3), _SDT_ARG(4, arg4)346#define _SDT_ASM_OPERANDS_5(arg1, arg2, arg3, arg4, arg5) \347 _SDT_ASM_OPERANDS_4(arg1, arg2, arg3, arg4), _SDT_ARG(5, arg5)348#define _SDT_ASM_OPERANDS_6(arg1, arg2, arg3, arg4, arg5, arg6) \349 _SDT_ASM_OPERANDS_5(arg1, arg2, arg3, arg4, arg5), _SDT_ARG(6, arg6)350#define _SDT_ASM_OPERANDS_7(arg1, arg2, arg3, arg4, arg5, arg6, arg7) \351 _SDT_ASM_OPERANDS_6(arg1, arg2, arg3, arg4, arg5, arg6), _SDT_ARG(7, arg7)352#define _SDT_ASM_OPERANDS_8(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) \353 _SDT_ASM_OPERANDS_7(arg1, arg2, arg3, arg4, arg5, arg6, arg7), \354 _SDT_ARG(8, arg8)355#define _SDT_ASM_OPERANDS_9(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9) \356 _SDT_ASM_OPERANDS_8(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8), \357 _SDT_ARG(9, arg9)358#define _SDT_ASM_OPERANDS_10(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10) \359 _SDT_ASM_OPERANDS_9(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9), \360 _SDT_ARG(10, arg10)361#define _SDT_ASM_OPERANDS_11(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11) \362 _SDT_ASM_OPERANDS_10(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10), \363 _SDT_ARG(11, arg11)364#define _SDT_ASM_OPERANDS_12(arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12) \365 _SDT_ASM_OPERANDS_11(arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11), \366 _SDT_ARG(12, arg12)367 368/* These macros can be used in C, C++, or assembly code.369 In assembly code the arguments should use normal assembly operand syntax. */370 371#define STAP_PROBE(provider, name) \372 _SDT_PROBE(provider, name, 0, ())373#define STAP_PROBE1(provider, name, arg1) \374 _SDT_PROBE(provider, name, 1, (arg1))375#define STAP_PROBE2(provider, name, arg1, arg2) \376 _SDT_PROBE(provider, name, 2, (arg1, arg2))377#define STAP_PROBE3(provider, name, arg1, arg2, arg3) \378 _SDT_PROBE(provider, name, 3, (arg1, arg2, arg3))379#define STAP_PROBE4(provider, name, arg1, arg2, arg3, arg4) \380 _SDT_PROBE(provider, name, 4, (arg1, arg2, arg3, arg4))381#define STAP_PROBE5(provider, name, arg1, arg2, arg3, arg4, arg5) \382 _SDT_PROBE(provider, name, 5, (arg1, arg2, arg3, arg4, arg5))383#define STAP_PROBE6(provider, name, arg1, arg2, arg3, arg4, arg5, arg6) \384 _SDT_PROBE(provider, name, 6, (arg1, arg2, arg3, arg4, arg5, arg6))385#define STAP_PROBE7(provider, name, arg1, arg2, arg3, arg4, arg5, arg6, arg7) \386 _SDT_PROBE(provider, name, 7, (arg1, arg2, arg3, arg4, arg5, arg6, arg7))387#define STAP_PROBE8(provider,name,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8) \388 _SDT_PROBE(provider, name, 8, (arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8))389#define STAP_PROBE9(provider,name,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9)\390 _SDT_PROBE(provider, name, 9, (arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9))391#define STAP_PROBE10(provider,name,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10) \392 _SDT_PROBE(provider, name, 10, \393 (arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10))394#define STAP_PROBE11(provider,name,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11) \395 _SDT_PROBE(provider, name, 11, \396 (arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11))397#define STAP_PROBE12(provider,name,arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12) \398 _SDT_PROBE(provider, name, 12, \399 (arg1,arg2,arg3,arg4,arg5,arg6,arg7,arg8,arg9,arg10,arg11,arg12))400 401/* This STAP_PROBEV macro can be used in variadic scenarios, where the402 number of probe arguments is not known until compile time. Since403 variadic macro support may vary with compiler options, you must404 pre-#define SDT_USE_VARIADIC to enable this type of probe.405 406 The trick to count __VA_ARGS__ was inspired by this post by407 Laurent Deniau <laurent.deniau@cern.ch>:408 http://groups.google.com/group/comp.std.c/msg/346fc464319b1ee5409 410 Note that our _SDT_NARG is called with an extra 0 arg that's not411 counted, so we don't have to worry about the behavior of macros412 called without any arguments. */413 414#define _SDT_NARG(...) __SDT_NARG(__VA_ARGS__, 12,11,10,9,8,7,6,5,4,3,2,1,0)415#define __SDT_NARG(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12, N, ...) N416#ifdef SDT_USE_VARIADIC417#define _SDT_PROBE_N(provider, name, N, ...) \418 _SDT_PROBE(provider, name, N, (__VA_ARGS__))419#define STAP_PROBEV(provider, name, ...) \420 _SDT_PROBE_N(provider, name, _SDT_NARG(0, ##__VA_ARGS__), ##__VA_ARGS__)421#endif422 423/* These macros are for use in asm statements. You must compile424 with -std=gnu99 or -std=c99 to use the STAP_PROBE_ASM macro.425 426 The STAP_PROBE_ASM macro generates a quoted string to be used in the427 template portion of the asm statement, concatenated with strings that428 contain the actual assembly code around the probe site.429 430 For example:431 432 asm ("before\n"433 STAP_PROBE_ASM(provider, fooprobe, %eax 4(%esi))434 "after");435 436 emits the assembly code for "before\nafter", with a probe in between.437 The probe arguments are the %eax register, and the value of the memory438 word located 4 bytes past the address in the %esi register. Note that439 because this is a simple asm, not a GNU C extended asm statement, these440 % characters do not need to be doubled to generate literal %reg names.441 442 In a GNU C extended asm statement, the probe arguments can be specified443 using the macro STAP_PROBE_ASM_TEMPLATE(n) for n arguments. The paired444 macro STAP_PROBE_ASM_OPERANDS gives the C values of these probe arguments,445 and appears in the input operand list of the asm statement. For example:446 447 asm ("someinsn %0,%1\n" // %0 is output operand, %1 is input operand448 STAP_PROBE_ASM(provider, fooprobe, STAP_PROBE_ASM_TEMPLATE(3))449 "otherinsn %[namedarg]"450 : "r" (outvar)451 : "g" (some_value), [namedarg] "i" (1234),452 STAP_PROBE_ASM_OPERANDS(3, some_value, some_ptr->field, 1234));453 454 This is just like writing:455 456 STAP_PROBE3(provider, fooprobe, some_value, some_ptr->field, 1234));457 458 but the probe site is right between "someinsn" and "otherinsn".459 460 The probe arguments in STAP_PROBE_ASM can be given as assembly461 operands instead, even inside a GNU C extended asm statement.462 Note that these can use operand templates like %0 or %[name],463 and likewise they must write %%reg for a literal operand of %reg. */464 465#define _SDT_ASM_BODY_1(p,n,...) _SDT_ASM_BODY(p,n,_SDT_ASM_SUBSTR,(__VA_ARGS__))466#define _SDT_ASM_BODY_2(p,n,...) _SDT_ASM_BODY(p,n,/*_SDT_ASM_STRING */,__VA_ARGS__)467#define _SDT_ASM_BODY_N2(p,n,no,...) _SDT_ASM_BODY_ ## no(p,n,__VA_ARGS__)468#define _SDT_ASM_BODY_N1(p,n,no,...) _SDT_ASM_BODY_N2(p,n,no,__VA_ARGS__)469#define _SDT_ASM_BODY_N(p,n,...) _SDT_ASM_BODY_N1(p,n,_SDT_NARG(0, __VA_ARGS__),__VA_ARGS__)470 471#if __STDC_VERSION__ >= 199901L472# define STAP_PROBE_ASM(provider, name, ...) \473 _SDT_ASM_BODY_N(provider, name, __VA_ARGS__) \474 _SDT_ASM_BASE475# define STAP_PROBE_ASM_OPERANDS(n, ...) _SDT_ASM_OPERANDS_##n(__VA_ARGS__)476#else477# define STAP_PROBE_ASM(provider, name, args) \478 _SDT_ASM_BODY(provider, name, /* _SDT_ASM_STRING */, (args)) \479 _SDT_ASM_BASE480#endif481#define STAP_PROBE_ASM_TEMPLATE(n) _SDT_ASM_TEMPLATE_##n,"use _SDT_ASM_TEMPLATE_"482 483 484/* DTrace compatible macro names. */485#define DTRACE_PROBE(provider,probe) \486 STAP_PROBE(provider,probe)487#define DTRACE_PROBE1(provider,probe,parm1) \488 STAP_PROBE1(provider,probe,parm1)489#define DTRACE_PROBE2(provider,probe,parm1,parm2) \490 STAP_PROBE2(provider,probe,parm1,parm2)491#define DTRACE_PROBE3(provider,probe,parm1,parm2,parm3) \492 STAP_PROBE3(provider,probe,parm1,parm2,parm3)493#define DTRACE_PROBE4(provider,probe,parm1,parm2,parm3,parm4) \494 STAP_PROBE4(provider,probe,parm1,parm2,parm3,parm4)495#define DTRACE_PROBE5(provider,probe,parm1,parm2,parm3,parm4,parm5) \496 STAP_PROBE5(provider,probe,parm1,parm2,parm3,parm4,parm5)497#define DTRACE_PROBE6(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6) \498 STAP_PROBE6(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6)499#define DTRACE_PROBE7(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7) \500 STAP_PROBE7(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7)501#define DTRACE_PROBE8(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8) \502 STAP_PROBE8(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8)503#define DTRACE_PROBE9(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9) \504 STAP_PROBE9(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9)505#define DTRACE_PROBE10(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9,parm10) \506 STAP_PROBE10(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9,parm10)507#define DTRACE_PROBE11(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9,parm10,parm11) \508 STAP_PROBE11(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9,parm10,parm11)509#define DTRACE_PROBE12(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9,parm10,parm11,parm12) \510 STAP_PROBE12(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9,parm10,parm11,parm12)511 512 513#endif /* sys/sdt.h */514