Commit f405f9de authored by Teng Qin's avatar Teng Qin Committed by Facebook Github Bot

Add USDT header file to folly

Summary:
Derived from `sdt.h` in [[ https://sourceware.org/systemtap/ | SystemTap ]]
Performed changes and clean-ups including:
- Get rid of the `sdt-config.h`.
- Get rid of "Running in Assembler" code.
- Replace the `DTRACE_PROBE_1, ... DTRACE_PROBE_N` Macro family with a single Macro using the "count Macro arguments" trick
- Get rid of argument signed-ness calculation. A **lot** of painful code were there only for this, and it has no real usage except for displaying purposes.
- Re-structure the helper methods (Macros) so that the logic of the code is a bit more readable.
- Add some comments so that it would be easier for users and future developers to understand what this header file is actually doing.
- Update license banner.

Reviewed By: meyering

Differential Revision: D3792966

fbshipit-source-id: 564a1011f7946d30be78191f334e072d94fa264e
parent 215636b2
# folly/tracing: Utility for User-level Statically Defined Tracing
----------------------------------------------------------
## StaticTracepoint
The `StaticTracepoint.h` header file defines the Macro
```
FOLLY_SDT(provider, name, arg1, arg2, ...)
```
Invoking the Macro will add a Static Tracepoint at the calling location. Using a
tracing toolkit ([BCC](https://github.com/iovisor/bcc) is an excellent example),
a probe can be attached to the Tracepoint, consume the provided arguments and
perform other tracing / profiling works.
The Tracepoint defined using `StaticTracepoint.h` is also compatible with any
toolkit designed for consuming [SystemTap](https://sourceware.org/systemtap/)
Tracepoints.
Internally, the Macro emits a `nop` operation at the calling location, along
with an Assembler Instruction with empty template and empty output Operands,
and the provided arguments and their sizes as input Operands.
The Macro then append to the ELF `.note` section, with information including
the provider and name of the Tracepoint, address of the `nop` operation, and
size and location (register name or memory location) of the provided arguments.
This way, the tracing toolkits would be able to parse the information, attach
the probes to the correct address, and consume arguments.
The default constraint for the arguments in the Assembler Instruction as
operands is `"nor"`. It means the argument could be an immediate integer
operand, a register operand or an offsettable memory operand. This is a good
default since tracing arguments tend to be integral, and the number of arguments
is likely to be less than the number of registers.
Otherwise, you may see compiler report errors like
```
'asm' requires impossible reload
```
You may want to simplify the Tracepoint (fewer and simpler arguments) in
such case. You may also choose to override the constraint
```
#define FOLLY_SDT_ARG_CONSTRAINT "g"
```
which means the arguments can be any memory or register operands.
/*
* Copyright 2016 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
// Default constraint for the probe arguments as operands.
#ifndef FOLLY_SDT_ARG_CONSTRAINT
#define FOLLY_SDT_ARG_CONSTRAINT "nor"
#endif
// Instruction to emit for the probe.
#define FOLLY_SDT_NOP nop
// Note section properties.
#define FOLLY_SDT_NOTE_NAME "stapsdt"
#define FOLLY_SDT_NOTE_TYPE 3
// Size of address depending on platform.
#ifdef __LP64__
#define FOLLY_SDT_ASM_ADDR .8byte
#else
#define FOLLY_SDT_ASM_ADDR .4byte
#endif
// Assembler helper Macros.
#define FOLLY_SDT_S(x) #x
#define FOLLY_SDT_ASM_1(x) FOLLY_SDT_S(x) "\n"
#define FOLLY_SDT_ASM_2(a, b) FOLLY_SDT_S(a) "," FOLLY_SDT_S(b) "\n"
#define FOLLY_SDT_ASM_3(a, b, c) FOLLY_SDT_S(a) "," FOLLY_SDT_S(b) "," \
FOLLY_SDT_S(c) "\n"
#define FOLLY_SDT_ASM_STRING(x) FOLLY_SDT_ASM_1(.asciz FOLLY_SDT_S(x))
// Helper to determine the size of an argument.
#define FOLLY_SDT_ISARRAY(x) (__builtin_classify_type(x) == 14)
#define FOLLY_SDT_ARGSIZE(x) (FOLLY_SDT_ISARRAY(x) ? sizeof(void*) : sizeof(x))
// Format of each probe arguments as operand.
// Size of the arugment tagged with FOLLY_SDT_Sn, with "n" constraint.
// Value of the argument tagged with FOLLY_SDT_An, with configured constraint.
#define FOLLY_SDT_ARG(n, x) \
[FOLLY_SDT_S##n] "n" ((size_t)FOLLY_SDT_ARGSIZE(x)), \
[FOLLY_SDT_A##n] FOLLY_SDT_ARG_CONSTRAINT (x)
// Templates to append arguments as operands.
#define FOLLY_SDT_OPERANDS_0() [__sdt_dummy] "g" (0)
#define FOLLY_SDT_OPERANDS_1(_1) FOLLY_SDT_ARG(1, _1)
#define FOLLY_SDT_OPERANDS_2(_1, _2) \
FOLLY_SDT_OPERANDS_1(_1), FOLLY_SDT_ARG(2, _2)
#define FOLLY_SDT_OPERANDS_3(_1, _2, _3) \
FOLLY_SDT_OPERANDS_2(_1, _2), FOLLY_SDT_ARG(3, _3)
#define FOLLY_SDT_OPERANDS_4(_1, _2, _3, _4) \
FOLLY_SDT_OPERANDS_3(_1, _2, _3), FOLLY_SDT_ARG(4, _4)
#define FOLLY_SDT_OPERANDS_5(_1, _2, _3, _4, _5) \
FOLLY_SDT_OPERANDS_4(_1, _2, _3, _4), FOLLY_SDT_ARG(5, _5)
#define FOLLY_SDT_OPERANDS_6(_1, _2, _3, _4, _5, _6) \
FOLLY_SDT_OPERANDS_5(_1, _2, _3, _4, _5), FOLLY_SDT_ARG(6, _6)
#define FOLLY_SDT_OPERANDS_7(_1, _2, _3, _4, _5, _6, _7) \
FOLLY_SDT_OPERANDS_6(_1, _2, _3, _4, _5, _6), FOLLY_SDT_ARG(7, _7)
#define FOLLY_SDT_OPERANDS_8(_1, _2, _3, _4, _5, _6, _7, _8) \
FOLLY_SDT_OPERANDS_7(_1, _2, _3, _4, _5, _6, _7), FOLLY_SDT_ARG(8, _8)
// Templates to reference the arguments from operands in note section.
#define FOLLY_SDT_ARGFMT(no) %n[FOLLY_SDT_S##no]@%[FOLLY_SDT_A##no]
#define FOLLY_SDT_ARG_TEMPLATE_0 /*No arguments*/
#define FOLLY_SDT_ARG_TEMPLATE_1 FOLLY_SDT_ARGFMT(1)
#define FOLLY_SDT_ARG_TEMPLATE_2 FOLLY_SDT_ARG_TEMPLATE_1 FOLLY_SDT_ARGFMT(2)
#define FOLLY_SDT_ARG_TEMPLATE_3 FOLLY_SDT_ARG_TEMPLATE_2 FOLLY_SDT_ARGFMT(3)
#define FOLLY_SDT_ARG_TEMPLATE_4 FOLLY_SDT_ARG_TEMPLATE_3 FOLLY_SDT_ARGFMT(4)
#define FOLLY_SDT_ARG_TEMPLATE_5 FOLLY_SDT_ARG_TEMPLATE_4 FOLLY_SDT_ARGFMT(5)
#define FOLLY_SDT_ARG_TEMPLATE_6 FOLLY_SDT_ARG_TEMPLATE_5 FOLLY_SDT_ARGFMT(6)
#define FOLLY_SDT_ARG_TEMPLATE_7 FOLLY_SDT_ARG_TEMPLATE_6 FOLLY_SDT_ARGFMT(7)
#define FOLLY_SDT_ARG_TEMPLATE_8 FOLLY_SDT_ARG_TEMPLATE_7 FOLLY_SDT_ARGFMT(8)
// Structure of note section for the probe.
#define FOLLY_SDT_NOTE_CONTENT(provider, name, arg_template) \
FOLLY_SDT_ASM_1(990: FOLLY_SDT_NOP) \
FOLLY_SDT_ASM_3( .pushsection .note.stapsdt,"","note") \
FOLLY_SDT_ASM_1( .balign 4) \
FOLLY_SDT_ASM_3( .4byte 992f-991f, 994f-993f, FOLLY_SDT_NOTE_TYPE) \
FOLLY_SDT_ASM_1(991: .asciz FOLLY_SDT_NOTE_NAME) \
FOLLY_SDT_ASM_1(992: .balign 4) \
FOLLY_SDT_ASM_1(993: FOLLY_SDT_ASM_ADDR 990b) \
FOLLY_SDT_ASM_1( FOLLY_SDT_ASM_ADDR 0) /*Reserved for Semaphore address*/\
FOLLY_SDT_ASM_1( FOLLY_SDT_ASM_ADDR 0) /*Reserved for Semaphore name*/ \
FOLLY_SDT_ASM_STRING(provider) \
FOLLY_SDT_ASM_STRING(name) \
FOLLY_SDT_ASM_STRING(arg_template) \
FOLLY_SDT_ASM_1(994: .balign 4) \
FOLLY_SDT_ASM_1( .popsection)
// Main probe Macro.
#define FOLLY_SDT_PROBE(provider, name, n, arglist) \
__asm__ __volatile__ ( \
FOLLY_SDT_NOTE_CONTENT(provider, name, FOLLY_SDT_ARG_TEMPLATE_##n) \
:: FOLLY_SDT_OPERANDS_##n arglist \
) \
// Helper Macros to handle variadic arguments.
#define FOLLY_SDT_NARG_(_0, _1, _2, _3, _4, _5, _6, _7, _8, N, ...) N
#define FOLLY_SDT_NARG(...) \
FOLLY_SDT_NARG_(__VA_ARGS__, 8, 7, 6, 5, 4, 3, 2, 1, 0)
#define FOLLY_SDT_PROBE_N(provider, name, N, ...) \
FOLLY_SDT_PROBE(provider, name, N, (__VA_ARGS__))
/*
* Copyright 2016 Facebook, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#pragma once
#if defined(__ELF__) && (defined(__x86_64__) || defined(__i386__))
#include <folly/tracing/StaticTracepoint-ELFx86.h>
#define FOLLY_SDT(provider, name, ...) \
FOLLY_SDT_PROBE_N( \
provider, name, FOLLY_SDT_NARG(0, ##__VA_ARGS__), ##__VA_ARGS__)
#else
#define FOLLY_SDT(provider, name, ...) do {} while(0)
#endif
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment