Commit | Line | Data |
---|---|---|
e5aa0be3 | 1 | # barectf |
fffd4c7d | 2 | |
8be23338 PP |
3 | [![](https://img.shields.io/pypi/v/barectf.svg)](https://pypi.python.org/pypi/barectf) |
4 | ||
fffd4c7d | 5 | **barectf** is a command-line utility which generates pure C99 |
e5aa0be3 PP |
6 | code that is able to write native [Common Trace Format](http://diamon.org/ctf) |
7 | (CTF) binary streams. | |
fffd4c7d PP |
8 | |
9 | You will find barectf interesting if: | |
10 | ||
e5aa0be3 PP |
11 | 1. You need to trace an application. |
12 | 2. You need tracing to be efficient, yet flexible: | |
fffd4c7d | 13 | record integers of custom sizes, custom floating point numbers, |
e5aa0be3 PP |
14 | enumerations supported by a specific integer type, and |
15 | null-terminated UTF-8/ASCII strings (C strings). | |
fffd4c7d PP |
16 | 3. You need to be able to convert the recorded binary events to |
17 | human-readable text, as well as analyze them with Python scripts | |
18 | ([Babeltrace](http://www.efficios.com/babeltrace) does all that, | |
19 | given a CTF input). | |
20 | 4. You _cannot_ use [LTTng](http://lttng.org/), an efficient tracing | |
21 | framework for the Linux kernel and Linux/BSD user applications, which | |
e5aa0be3 | 22 | also outputs CTF. |
fffd4c7d PP |
23 | |
24 | The target audience of barectf is developers who need to trace bare metal | |
25 | systems (without an operating system). The code produced by barectf | |
e5aa0be3 | 26 | is pure C99 and can be lightweight enough to fit on a tiny microcontroller. |
fffd4c7d | 27 | |
e5aa0be3 | 28 | **Key features**: |
fffd4c7d | 29 | |
e5aa0be3 PP |
30 | * Single input: easy-to-write [YAML](https://en.wikipedia.org/wiki/YAML) |
31 | configuration file (documentation below) | |
32 | * 1-to-1 mapping from tracing function parameters to event fields | |
33 | * Custom and bundled _platforms_ hiding the details of opening/closing | |
34 | packets and writing them to a back-end (continuous tracing), getting | |
35 | the clock values, etc.: | |
36 | * _linux-fs_: basic Linux application tracing writing stream files to | |
37 | the file system for demonstration purposes | |
38 | * _parallella_: Adapteva Epiphany/[Parallella](http://parallella.org/) | |
39 | with host-side consumer | |
40 | * CTF metadata generated by the command-line tool (automatic trace UUID, | |
41 | stream IDs, and event IDs) | |
42 | * All basic CTF types are supported: integers, floating point numbers, | |
43 | enumerations, and null-terminated strings (C strings) | |
44 | * Binary streams produced by the generated C code and metadata file | |
45 | produced by barectf are CTF 1.8-compliant | |
46 | * Human-readable error reporting | |
fffd4c7d | 47 | |
e5aa0be3 | 48 | **Current limitations**: |
fffd4c7d | 49 | |
e5aa0be3 PP |
50 | As of this version: |
51 | ||
52 | * All the generated tracing C functions, for a given barectf | |
53 | stream-specific context, need to be called from the same thread, and cannot | |
54 | be called from an interrupt handler, unless a user-provided | |
55 | synchronization mechanism is used. | |
56 | * CTF compound types (array, sequence, structure, variant) are not supported | |
57 | yet, except at some very specific locations in the metadata. | |
de9eae2c PP |
58 | * The current generated C code is not strictly C99 compliant: |
59 | [statement expressions](https://gcc.gnu.org/onlinedocs/gcc/Statement-Exprs.html) | |
60 | and the | |
61 | [`typeof` keyword](https://gcc.gnu.org/onlinedocs/gcc/Typeof.html) | |
62 | GCC extensions are used in the generated bitfield macros. The | |
63 | generated C code is known to be compiled with no warnings using | |
64 | both GCC and Clang. | |
e5aa0be3 PP |
65 | |
66 | barectf is written in Python 3. | |
67 | ||
68 | ||
69 | ## Installing | |
70 | ||
71 | Make sure you have Python 3 and `pip` for Python 3 installed, then | |
72 | install barectf. | |
73 | ||
74 | Note that you may pass the `--user` argument to | |
75 | `pip install` to install the tool in your home directory (instead of | |
76 | installing globally). | |
77 | ||
78 | **Latest Ubuntu**: | |
fffd4c7d PP |
79 | |
80 | sudo apt-get install python3-pip | |
e5aa0be3 | 81 | sudo pip3 install barectf |
fffd4c7d | 82 | |
e5aa0be3 | 83 | **Ubuntu 12.04 and lower**: |
fffd4c7d PP |
84 | |
85 | sudo apt-get install python3-setuptools | |
86 | sudo easy_install3 pip | |
e5aa0be3 | 87 | sudo pip3 install barectf |
fffd4c7d | 88 | |
e5aa0be3 | 89 | **Debian**: |
fffd4c7d | 90 | |
e5aa0be3 | 91 | sudo apt-get install python3-pip |
fffd4c7d PP |
92 | sudo pip3 install barectf |
93 | ||
e5aa0be3 | 94 | **Fedora 20 and up**: |
fffd4c7d | 95 | |
e5aa0be3 PP |
96 | sudo yum install python3-pip |
97 | sudo pip3 install barectf | |
fffd4c7d | 98 | |
e5aa0be3 | 99 | **Arch Linux**: |
fffd4c7d | 100 | |
c119e70b | 101 | sudo pacman -S python-pip |
e5aa0be3 | 102 | sudo pip install barectf |
fffd4c7d | 103 | |
e5aa0be3 | 104 | **OS X** |
fffd4c7d | 105 | |
e5aa0be3 | 106 | With [Homebrew](http://brew.sh/): |
ca3417e6 | 107 | |
e5aa0be3 PP |
108 | brew install python3 |
109 | pip3 install barectf | |
fffd4c7d | 110 | |
fffd4c7d | 111 | |
e5aa0be3 | 112 | ## What is CTF? |
fffd4c7d | 113 | |
e5aa0be3 PP |
114 | See the [CTF in a nutshell](http://diamon.org/ctf/#ctf-in-a-nutshell) |
115 | section of CTF's website to understand the basics of this | |
116 | trace format. | |
fffd4c7d | 117 | |
e5aa0be3 PP |
118 | The most important thing to understand about CTF, for barectf use |
119 | cases, is the layout of a binary stream packet: | |
fffd4c7d | 120 | |
e5aa0be3 PP |
121 | * Packet header (defined at the trace level) |
122 | * Packet context (defined at the stream level) | |
123 | * Sequence of events (defined at the stream level): | |
124 | * Event header (defined at the stream level) | |
125 | * Stream event context (defined at the stream level) | |
126 | * Event context (defined at the event level) | |
127 | * Event payload (defined at the event level) | |
fffd4c7d | 128 | |
e5aa0be3 PP |
129 | The following diagram, stolen without remorse from CTF's website, shows |
130 | said packet layout: | |
fffd4c7d | 131 | |
e5aa0be3 | 132 | ![](http://diamon.org/ctf/img/ctf-stream-packet.png) |
fffd4c7d | 133 | |
e5aa0be3 PP |
134 | Any of those six dynamic scopes, if defined at all, has an associated |
135 | CTF type. barectf requires them to be structure types. | |
fffd4c7d | 136 | |
fffd4c7d | 137 | |
e5aa0be3 | 138 | ## Using |
fffd4c7d | 139 | |
e5aa0be3 | 140 | Using barectf involves the following steps: |
fffd4c7d | 141 | |
e5aa0be3 PP |
142 | 1. Writing the YAML configuration file defining the various header, |
143 | context, and event field types. | |
144 | 2. Running the `barectf` command-line tool with this configuration file | |
145 | to generate the CTF metadata and C files. | |
146 | 3. Using the generated C code (tracing functions), along with the C code | |
147 | provided by the appropriate barectf platform, in the source code of | |
148 | your own application. | |
149 | 4. Running your application, along with anything the barectf platform | |
150 | you chose requires, to generate the binary streams of a CTF trace. | |
fffd4c7d | 151 | |
e5aa0be3 PP |
152 | Your application, when running, will generate CTF packets. Depending |
153 | on the chosen barectf platform, those packets will be consumed and | |
154 | sequentially written at some place for later viewing/analysis. | |
fffd4c7d | 155 | |
e5aa0be3 | 156 | Here's a diagram summarizing the steps described above: |
fffd4c7d | 157 | |
e5aa0be3 | 158 | ![](http://0x3b.org/ss/cardiectasis400.png) |
fffd4c7d | 159 | |
e5aa0be3 | 160 | The following subsections explain the four steps above. |
fffd4c7d | 161 | |
e5aa0be3 PP |
162 | Also, have a look at the [`doc/examples`](doc/examples) directory, which |
163 | contains complete examples. | |
fffd4c7d | 164 | |
fffd4c7d | 165 | |
e5aa0be3 | 166 | ### Writing the YAML configuration file |
fffd4c7d | 167 | |
e5aa0be3 PP |
168 | The barectf [YAML](https://en.wikipedia.org/wiki/YAML) configuration file |
169 | is the only input the `barectf` command-line tool needs in order to generate | |
170 | the corresponding CTF metadata and C files. | |
fffd4c7d | 171 | |
e5aa0be3 | 172 | To start with a concrete configuration, here's some minimal configuration: |
fffd4c7d | 173 | |
e5aa0be3 PP |
174 | ```yaml |
175 | version: '2.0' | |
176 | metadata: | |
177 | type-aliases: | |
178 | uint16: | |
179 | class: int | |
180 | size: 16 | |
181 | trace: | |
182 | byte-order: le | |
183 | streams: | |
184 | my_stream: | |
185 | packet-context-type: | |
186 | class: struct | |
187 | fields: | |
188 | packet_size: uint16 | |
189 | content_size: uint16 | |
190 | events: | |
191 | my_event: | |
192 | payload-type: | |
193 | class: struct | |
194 | fields: | |
195 | my_field: | |
196 | class: int | |
197 | size: 8 | |
fffd4c7d | 198 | ``` |
fffd4c7d | 199 | |
e5aa0be3 PP |
200 | The `version` property must be set to the `2.0` _string_ (hence the single |
201 | quotes). As features are added to barectf and to its configuration file schema, | |
202 | this version will be bumped accordingly. | |
203 | ||
204 | The `metadata` property is where the properties and layout of the | |
205 | eventual CTF trace are defined. The accepted properties of each object | |
206 | are documented later in this document. For the moment, note simply | |
207 | that the native byte order of the trace is set to `le` (little-endian), | |
208 | and that there's one defined stream named `my_stream`, having one | |
209 | defined event named `my_event`, having a structure as its payload | |
210 | type, with a single 8-bit unsigned integer type field named `my_field`. Also, | |
211 | the stream packet context type is a structure defining the mandatory | |
212 | `packet_size` and `content_size` special fields as 16-bit unsigned integer | |
213 | types. | |
fffd4c7d | 214 | |
e5aa0be3 PP |
215 | Running `barectf` with the configuration above (as a file named `config.yaml`): |
216 | ||
217 | barectf config.yaml | |
218 | ||
219 | will produce a C file (`barectf.c`), and its header file (`barectf.h`), | |
220 | the latter declaring the following function: | |
221 | ||
222 | ```c | |
223 | void barectf_my_stream_trace_my_event( | |
224 | struct barectf_my_stream_ctx *ctx, uint8_t ep_my_field); | |
fffd4c7d | 225 | ``` |
e5aa0be3 PP |
226 | |
227 | `ctx` is the barectf context for the stream named `my_stream` (usually | |
228 | initialized and provided by the barectf platform), and `ep_my_field` is the | |
229 | value of the `my_event` event payload's `my_field` field. | |
230 | ||
231 | The following subsections define all the objects of the YAML configuration | |
232 | file. | |
233 | ||
234 | ||
235 | #### Configuration object | |
236 | ||
237 | The top-level object of the YAML configuration file. | |
238 | ||
239 | **Properties**: | |
240 | ||
241 | | Property | Type | Description | Required? | Default value | | |
242 | |---|---|---|---|---| | |
243 | | `version` | String | Must be set to `'2.0'` | Required | N/A | | |
244 | | `prefix` | String | Prefix to be used for function names, file names, etc. | Optional | `barectf_` | | |
245 | | `metadata` | [Metadata object](#metadata-object) | Trace metadata | Required | N/A | | |
246 | ||
247 | The `prefix` property must be set to a valid C identifier. It can be | |
248 | overridden by the `barectf` command-line tool's `--prefix` option. | |
249 | ||
250 | **Example**: | |
251 | ||
252 | ```yaml | |
253 | version: '2.0' | |
254 | prefix: axx_ | |
255 | metadata: | |
256 | type-aliases: | |
257 | uint16: | |
258 | class: int | |
259 | size: 16 | |
260 | trace: | |
261 | byte-order: le | |
262 | streams: | |
263 | my_stream: | |
264 | packet-context-type: | |
265 | class: struct | |
266 | fields: | |
267 | packet_size: uint16 | |
268 | content_size: uint16 | |
269 | events: | |
270 | my_event: | |
271 | payload-type: | |
272 | class: struct | |
273 | fields: | |
274 | a: | |
275 | class: int | |
276 | size: 8 | |
fffd4c7d PP |
277 | ``` |
278 | ||
fffd4c7d | 279 | |
e5aa0be3 PP |
280 | #### Metadata object |
281 | ||
282 | A metadata object defines the desired layout of the CTF trace to be | |
283 | produced by the generated C code. It is used by barectf to generate C code, | |
284 | as well as a corresponding CTF metadata file. | |
285 | ||
286 | **Properties**: | |
287 | ||
288 | | Property | Type | Description | Required? | Default value | | |
289 | |---|---|---|---|---| | |
290 | | `type-aliases` | Associative array of strings (alias names) to [type objects](#type-objects) or strings (previous alias names) | Type aliases to be used in trace, stream, and event objects | Optional | `{}` | | |
291 | | `log-levels` | Associative array of strings (log level names) to log level constant integers | Log levels to be used in event objects | Optional | `{}` | | |
292 | | `clocks` | Associative array of strings (clock names) to [clock objects](#clock-object) | Trace clocks | Optional | `{}` | | |
293 | | `env` | Associative array of strings (names) to strings or integers (values) | Trace environment variables | Optional | `{}` | | |
294 | | `trace` | [Trace object](#trace-object) | Metadata common to the whole trace | Required | N/A | | |
295 | | `streams` | Associative array of strings (stream names) to [stream objects](#stream-object) | Trace streams | Required | N/A | | |
296 | ||
297 | Each clock name of the `clocks` property must be a valid C identifier. | |
298 | ||
299 | The `streams` property must contain at least one entry. Each stream name must be | |
300 | a valid C identifier. | |
301 | ||
302 | Each environment variable name in the `env` property must be a valid | |
303 | C identifier. Those variables will be appended to some environment | |
304 | variables set by barectf itself. | |
305 | ||
306 | The order of the `type-aliases` entries is important: a type alias may only | |
307 | inherit from another type alias if the latter is defined before. | |
308 | ||
309 | **Example**: | |
310 | ||
311 | ```yaml | |
312 | type-aliases: | |
313 | uint8: | |
314 | class: integer | |
315 | size: 8 | |
316 | uint16: | |
317 | class: integer | |
318 | size: 16 | |
319 | uint32: | |
320 | class: integer | |
321 | size: 32 | |
322 | uint64: | |
323 | class: integer | |
324 | size: 64 | |
325 | clock-int: | |
326 | inherit: uint64 | |
327 | property-mappings: | |
328 | - type: clock | |
329 | name: my_clock | |
330 | property: value | |
331 | byte: uint8 | |
332 | uuid: | |
333 | class: array | |
334 | length: 16 | |
335 | element-type: byte | |
336 | log-levels: | |
337 | emerg: 0 | |
338 | alert: 1 | |
339 | critical: 2 | |
340 | error: 3 | |
341 | warning: 4 | |
342 | notice: 5 | |
343 | info: 6 | |
344 | clocks: | |
345 | my_clock: | |
346 | freq: 1000000000 | |
347 | offset: | |
348 | seconds: 1434072888 | |
349 | return-ctype: uint64_t | |
350 | env: | |
351 | my_system_version: '0.3.2-2015.03' | |
352 | bID: 15 | |
353 | trace: | |
354 | byte-order: le | |
355 | uuid: auto | |
356 | packet-header-type: | |
357 | class: struct | |
358 | min-align: 8 | |
359 | fields: | |
360 | magic: uint32 | |
361 | uuid: uuid | |
362 | stream_id: uint8 | |
363 | streams: | |
364 | my_stream: | |
365 | packet-context-type: | |
366 | class: struct | |
367 | fields: | |
368 | timestamp_begin: clock-int | |
369 | timestamp_end: clock-int | |
370 | packet_size: uint32 | |
371 | something: float | |
372 | content_size: uint32 | |
373 | events_discarded: uint32 | |
374 | event-header-type: | |
375 | class: struct | |
376 | fields: | |
377 | timestamp: clock-int | |
378 | id: uint16 | |
379 | events: | |
380 | simple_uint32: | |
381 | log-level: error | |
382 | payload-type: | |
383 | class: struct | |
384 | fields: | |
385 | value: uint32 | |
386 | simple_int16: | |
387 | payload-type: | |
388 | class: struct | |
389 | fields: | |
390 | value: | |
391 | inherit: uint16 | |
392 | signed: true | |
393 | ``` | |
fffd4c7d | 394 | |
fffd4c7d | 395 | |
e5aa0be3 | 396 | #### Clock object |
fffd4c7d | 397 | |
e5aa0be3 | 398 | A CTF clock. |
fffd4c7d | 399 | |
e5aa0be3 | 400 | **Properties**: |
fffd4c7d | 401 | |
e5aa0be3 PP |
402 | | Property | Type | Description | Required? | Default value | |
403 | |---|---|---|---|---| | |
404 | | `freq` | Integer (positive) | Frequency (Hz) | Optional | 1000000000 | | |
405 | | `description` | String | Description | Optional | No description | | |
406 | | `uuid` | String (UUID canonical format) | UUID (unique identifier of this clock) | Optional | No UUID | | |
407 | | `error-cycles` | Integer (zero or positive) | Error (uncertainty) of clock in clock cycles | Optional | 0 | | |
408 | | `offset` | [Clock offset object](#clock-offset-object) | Offset | Optional | Default clock offset object | | |
409 | | `absolute` | Boolean | Absolute clock | Optional | `false` | | |
410 | | `return-ctype` | String | Return C type of the associated clock callback | Optional | `uint32_t` | | |
411 | ||
412 | The `return-ctype` property must be set to a valid C integer type | |
413 | (or valid type definition). This is not currently validated by barectf | |
414 | itself, but the C compiler will fail to compile the generated C code | |
415 | if the clock's return type is not a valid C integer type. | |
416 | ||
417 | **Example**: | |
418 | ||
419 | ```yaml | |
420 | freq: 2450000000 | |
421 | description: CCLK/A2 (System clock, A2 clock domain) | |
422 | uuid: 184883f6-6b6e-4bfd-bcf7-1e45c055c56a | |
423 | error-cycles: 23 | |
424 | offset: | |
425 | seconds: 1434072888 | |
426 | cycles: 2003912 | |
427 | absolute: false | |
428 | return-ctype: unsigned long long | |
fffd4c7d PP |
429 | ``` |
430 | ||
fffd4c7d | 431 | |
e5aa0be3 | 432 | ##### Clock offset object |
fffd4c7d | 433 | |
e5aa0be3 | 434 | An offset in seconds and clock cycles from the Unix epoch. |
fffd4c7d | 435 | |
e5aa0be3 | 436 | **Properties**: |
fffd4c7d | 437 | |
e5aa0be3 PP |
438 | | Property | Type | Description | Required? | Default value | |
439 | |---|---|---|---|---| | |
440 | | `seconds` | Integer (zero or positive) | Seconds since the Unix epoch | Optional | 0 | | |
441 | | `cycles` | Integer (zero or positive) | Clock cycles since the Unix epoch plus the value of the `seconds` property | Optional | 0 | | |
442 | ||
443 | **Example**: | |
444 | ||
445 | ```yaml | |
446 | seconds: 1435617321 | |
447 | cycles: 194570 | |
fffd4c7d PP |
448 | ``` |
449 | ||
fffd4c7d | 450 | |
e5aa0be3 PP |
451 | #### Trace object |
452 | ||
453 | Metadata common to the whole trace. | |
454 | ||
455 | **Properties**: | |
456 | ||
457 | | Property | Type | Description | Required? | Default value | | |
458 | |---|---|---|---|---| | |
459 | | `byte-order` | String | Native byte order (`le` for little-endian or `be` for big-endian) | Required | N/A | | |
460 | | `uuid` | String (UUID canonical format or `auto`) | UUID (unique identifier of this trace); automatically generated if value is `auto` | Optional | No UUID | | |
461 | | `packet-header-type` | [Type object](#type-objects) or string (alias name) | Type of packet header (must be a [structure type object](#structure-type-object)) | Optional | No packet header | | |
462 | ||
463 | Each field of the packet header structure type (`packet-header-type` property) | |
464 | corresponds to one parameter | |
465 | of the generated packet opening function (prefixed with `tph_`), except for the | |
466 | following special fields, which are automatically written if present: | |
467 | ||
468 | * `magic` (32-bit unsigned [integer type object](#integer-type-object)): | |
469 | packet magic number | |
470 | * `uuid` ([array type object](#array-type-object) of 8-bit unsigned | |
471 | [integer type objects](#integer-type-object), of length 16): | |
472 | trace UUID (`uuid` property of trace object must be set) | |
473 | * `stream_id` (unsigned [integer type object](#integer-type-object)): | |
474 | stream ID | |
475 | ||
476 | As per CTF 1.8, the `stream_id` field is mandatory if there's more | |
477 | than one defined stream. | |
478 | ||
479 | **Example**: | |
480 | ||
481 | ```yaml | |
482 | byte-order: le | |
483 | uuid: auto | |
484 | packet-header-type: | |
485 | class: struct | |
486 | fields: | |
487 | magic: uint32 | |
488 | uuid: | |
489 | class: array | |
490 | length: 16 | |
491 | element-type: uint8 | |
492 | stream_id: uint16 | |
fffd4c7d | 493 | ``` |
e5aa0be3 PP |
494 | |
495 | ||
496 | #### Stream object | |
497 | ||
498 | A CTF stream. | |
499 | ||
500 | **Properties**: | |
501 | ||
502 | | Property | Type | Description | Required? | Default value | | |
503 | |---|---|---|---|---| | |
504 | | `packet-context-type` | [Type object](#type-objects) or string (alias name) | Type of packet context (must be a [structure type object](#structure-type-object)) | Required | N/A | | |
505 | | `event-header-type` | [Type object]((#type-objects)) or string (alias name) | Type of event header (must be a [structure type object](#structure-type-object)) | Optional | No event header | | |
506 | | `event-context-type` | [Type object]((#type-objects)) or string (alias name) | Type of stream event context (must be a [structure type object](#structure-type-object)) | Optional | No stream event context | | |
507 | | `events` | Associative array of event names (string) to [event objects](#event-object) | Stream events | Required | N/A | | |
508 | ||
509 | Each field of the packet context structure type (`packet-context-type` property) | |
510 | corresponds to one parameter | |
511 | of the generated packet opening function (prefixed with `spc_`), except for the | |
512 | following special fields, which are automatically written if present: | |
513 | ||
514 | * `timestamp_begin` and `timestamp_end` (unsigned | |
515 | [integer type objects](#integer-type-object), with | |
516 | a clock value property mapping): resp. open and close timestamps | |
517 | * `packet_size` (unsigned [integer type object](#integer-type-object), | |
518 | mandatory): packet size | |
519 | * `content_size` (unsigned [integer type object](#integer-type-object), | |
520 | mandatory): content size | |
521 | * `events_discarded` (unsigned [integer type object](#integer-type-object)): | |
522 | number of discarded events so far | |
523 | ||
524 | The `timestamp_end` field must exist if the `timestamp_begin` field exists, | |
525 | and vice versa. | |
526 | ||
527 | Each field of the event header structure type (`event-header-type` property) | |
528 | corresponds to one parameter of the generated tracing function | |
529 | (prefixed with `eh_`) (for a given event), except for the following special | |
530 | fields, which are automatically written if present: | |
531 | ||
532 | * `id` (unsigned [integer type object](#integer-type-object)): event ID | |
533 | * `timestamp` (unsigned [integer type object](#integer-type-object), with | |
534 | a clock value property mapping): event timestamp | |
535 | ||
536 | The `id` field must exist if there's more than one defined event in the | |
537 | stream. | |
538 | ||
539 | Each field of the stream event context structure type (`event-context-type` | |
540 | property) corresponds to one parameter of the generated tracing function | |
541 | (prefixed with `seh_`) (for a given event). | |
542 | ||
543 | Each field name of the `packet-context-type`, `event-header-type`, | |
544 | and `event-context-type` properties must be a valid C identifier. | |
545 | ||
546 | The `events` property must contain at least one entry. | |
547 | ||
548 | **Example**: | |
549 | ||
550 | ```yaml | |
551 | packet-context-type: | |
552 | class: struct | |
553 | fields: | |
554 | timestamp_begin: clock-int | |
555 | timestamp_end: clock-int | |
556 | packet_size: uint32 | |
557 | content_size: uint32 | |
558 | events_discarded: uint16 | |
559 | my_custom_field: int12 | |
560 | event-header-type: | |
561 | class: struct | |
562 | fields: | |
563 | id: uint16 | |
564 | timestamp: clock-int | |
565 | event-context-type: | |
566 | class: struct | |
567 | fields: | |
568 | obj_id: uint8 | |
569 | events: | |
570 | msg_in: | |
571 | payload-type: msg-type | |
fffd4c7d PP |
572 | ``` |
573 | ||
fffd4c7d | 574 | |
e5aa0be3 | 575 | #### Event object |
fffd4c7d | 576 | |
e5aa0be3 | 577 | A CTF event. |
fffd4c7d | 578 | |
e5aa0be3 | 579 | **Properties**: |
fffd4c7d | 580 | |
e5aa0be3 PP |
581 | | Property | Type | Description | Required? | Default value | |
582 | |---|---|---|---|---| | |
583 | | `log-level` | String (predefined log level name) or integer (zero or positive) | Log level of this event | Optional | No log level | | |
584 | | `context-type` | [Type object](#type-objects) or string (alias name) | Type of event context (must be a [structure type object](#structure-type-object)) | Optional | No event context | | |
585 | | `payload-type` | [Type object](#type-objects) or string (alias name) | Type of event payload (must be a [structure type object](#structure-type-object)) | Required | N/A | | |
fffd4c7d | 586 | |
e5aa0be3 PP |
587 | Available log level names, for a given event, are defined by the |
588 | `log-levels` property of the [metadata object](#metadata-object) | |
589 | containing it. | |
590 | ||
591 | Each field of the event context structure type (`context-type` property) | |
592 | corresponds to one parameter | |
593 | of the generated tracing function (prefixed with `ec_`). | |
594 | ||
595 | Each field of the event payload structure type (`payload-type` property) | |
596 | corresponds to one parameter | |
597 | of the generated tracing function (prefixed with `ep_`). The event | |
598 | payload structure type must contain at least one field. | |
599 | ||
600 | Each field name of the `context-type` and `payload-type` properties must be a | |
601 | valid C identifier. | |
602 | ||
603 | **Example**: | |
604 | ||
605 | ```yaml | |
606 | log-level: error | |
607 | context-type: | |
608 | class: struct | |
609 | fields: | |
610 | msg_id: uint16 | |
611 | payload-type: | |
612 | class: struct | |
613 | fields: | |
614 | src: | |
615 | type: string | |
616 | dst: | |
617 | type: string | |
618 | payload_sz: uint32 | |
fffd4c7d PP |
619 | ``` |
620 | ||
fffd4c7d | 621 | |
e5aa0be3 | 622 | #### Type objects |
fffd4c7d | 623 | |
e5aa0be3 | 624 | Type objects represent CTF types. |
fffd4c7d | 625 | |
e5aa0be3 | 626 | **Common properties**: |
fffd4c7d | 627 | |
e5aa0be3 PP |
628 | | Property | Type | Description | Required? | Default value | |
629 | |---|---|---|---|---| | |
630 | | `class` | String | Type class | Required if `inherit` property is absent | N/A | | |
631 | | `inherit` | String | Name of type alias from which to inherit properties | Required if `class` property is absent | N/A | | |
fffd4c7d | 632 | |
e5aa0be3 | 633 | The accepted values for the `class` property are: |
fffd4c7d | 634 | |
e5aa0be3 PP |
635 | | `class` property value | CTF type | |
636 | |---|---| | |
637 | | `int`<br>`integer` | Integer type | | |
638 | | `flt`<br>`float`<br>`floating-point` | Floating point number type | | |
639 | | `enum`<br>`enumeration` | Enumeration type | | |
640 | | `str`<br>`string` | String type | | |
641 | | `struct`<br>`structure` | Structure type | | |
642 | | `array` | Array/sequence types | | |
643 | | `var`<br>`variant` | Variant type | | |
fffd4c7d | 644 | |
e5aa0be3 PP |
645 | The `inherit` property accepts the name of any previously defined |
646 | type alias. Any propery in a type object that inherits from another | |
647 | type object overrides the parent properties as follows: | |
fffd4c7d | 648 | |
e5aa0be3 PP |
649 | * Booleans, numbers, and strings: value of parent property with |
650 | the same name is replaced | |
651 | * Arrays: new elements are appended to parent array | |
652 | * Associative arrays: properties sharing the name of parent | |
653 | properties completely replace them; new properties are | |
654 | added to the parent associative array | |
fffd4c7d | 655 | |
fffd4c7d | 656 | |
e5aa0be3 | 657 | ##### Integer type object |
fffd4c7d | 658 | |
e5aa0be3 | 659 | A CTF integer type. |
fffd4c7d | 660 | |
e5aa0be3 | 661 | **Properties**: |
fffd4c7d | 662 | |
e5aa0be3 PP |
663 | | Property | Type | Description | Required? | Default value | |
664 | |---|---|---|---|---| | |
665 | | `size` | Integer (positive) | Size (bits) (1 to 64) | Required | N/A | | |
666 | | `align` | Integer (positive) | Alignment (bits) (power of two) | Optional | 8 if `size` property is a multiple of 8, else 1 | | |
667 | | `signed` | Boolean | Signedness | Optional | `false` (unsigned) | | |
668 | | `base` | Integer | Display radix (2, 8, 10, or 16) | Optional | 10 | | |
669 | | `byte-order` | String | Byte order (`le` for little-endian, `be` for big-endian, or `native` to use the byte order defined at the trace level) | Optional | `native` | | |
670 | | `property-mappings` | Array of [property mapping objects](#property-mapping-object) | Property mappings of this integer type | Optional | N/A | | |
fffd4c7d | 671 | |
e5aa0be3 | 672 | The `property-mappings` array property currently accepts only one element. |
fffd4c7d | 673 | |
e5aa0be3 | 674 | **Example**: |
fffd4c7d | 675 | |
e5aa0be3 PP |
676 | ```yaml |
677 | class: int | |
678 | size: 12 | |
679 | signed: false | |
680 | base: 8 | |
681 | byte-order: le | |
682 | property-mappings: | |
683 | - type: clock | |
684 | name: my_clock | |
685 | property: value | |
fffd4c7d | 686 | ``` |
fffd4c7d | 687 | |
e5aa0be3 PP |
688 | **Equivalent C type**: |
689 | ||
690 | * Unsigned: `uint8_t`, `uint16_t`, `uint32_t`, or `uint64_t`, depending on the | |
691 | `size` property | |
692 | * Signed: `int8_t`, `int16_t`, `int32_t`, or `int64_t`, depending on the | |
693 | `size` property | |
694 | ||
695 | ||
696 | ###### Property mapping object | |
697 | ||
698 | A property mapping object associates an integer type with a stateful | |
699 | object's property. When the integer type is decoded from a CTF binary | |
700 | stream, the associated object's property is updated. | |
701 | ||
702 | Currently, the only available stateful object's property is the | |
703 | current value of a given clock. | |
fffd4c7d | 704 | |
e5aa0be3 | 705 | **Properties**: |
fffd4c7d | 706 | |
e5aa0be3 PP |
707 | | Property | Type | Description | Required? | Default value | |
708 | |---|---|---|---|---| | |
709 | | `type` | String | Object type (always `clock`) | Required | N/A | | |
710 | | `name` | String | Clock name | Required | N/A | | |
711 | | `property` | String | Clock property name (always `value`) | Required | N/A | | |
fffd4c7d | 712 | |
e5aa0be3 | 713 | **Example**: |
fffd4c7d | 714 | |
e5aa0be3 PP |
715 | ```yaml |
716 | type: clock | |
717 | name: my_clock | |
718 | property: value | |
fffd4c7d | 719 | ``` |
e5aa0be3 PP |
720 | |
721 | ||
722 | ##### Floating point number type object | |
723 | ||
724 | A CTF floating point number type. | |
725 | ||
726 | **Properties**: | |
727 | ||
728 | | Property | Type | Description | Required? | Default value | | |
729 | |---|---|---|---|---| | |
730 | | `size` | [Floating point number type size object](#floating-point-number-type-size-object) | Size parameters | Required | N/A | | |
731 | | `align` | Integer (positive) | Alignment (bits) (power of two) | Optional | 8 | | |
732 | | `byte-order` | String | Byte order (`le` for little-endian, `be` for big-endian, or `native` to use the byte order defined at the trace level) | Optional | `native` | | |
733 | ||
734 | **Example**: | |
735 | ||
736 | ```yaml | |
737 | class: float | |
738 | size: | |
739 | exp: 11 | |
740 | mant: 53 | |
741 | align: 64 | |
742 | byte-order: be | |
fffd4c7d PP |
743 | ``` |
744 | ||
e5aa0be3 | 745 | **Equivalent C type**: |
fffd4c7d | 746 | |
e5aa0be3 PP |
747 | * 8-bit exponent, 24-bit mantissa, 32-bit alignment: `float` |
748 | * 11-bit exponent, 53-bit mantissa, 64-bit alignment: `double` | |
749 | * Every other combination: `uint64_t` | |
fffd4c7d | 750 | |
fffd4c7d | 751 | |
e5aa0be3 | 752 | ###### Floating point number type size object |
fffd4c7d | 753 | |
e5aa0be3 PP |
754 | The CTF floating point number type is encoded, in a binary stream, |
755 | following [IEEE 754-2008](https://en.wikipedia.org/wiki/IEEE_floating_point)'s | |
756 | interchange format. The required parameters are the exponent and | |
757 | significand sizes, in bits. In CTF, the _mantissa_ size includes the | |
758 | sign bit, whereas IEEE 754-2008's significand size does not include it. | |
fffd4c7d | 759 | |
e5aa0be3 | 760 | **Properties**: |
fffd4c7d | 761 | |
e5aa0be3 PP |
762 | | Property | Type | Description | Required? | Default value | |
763 | |---|---|---|---|---| | |
764 | | `exp` | Integer (positive) | Exponent size (bits) | Required | N/A | | |
765 | | `mant` | Integer (positive) | Mantissa size (significand size + 1) (bits) | Required | N/A | | |
fffd4c7d | 766 | |
e5aa0be3 PP |
767 | As per IEEE 754-2008, the sum of the `exp` and `mant` properties must be a |
768 | multiple of 32. | |
fffd4c7d | 769 | |
e5aa0be3 | 770 | The sum of the `exp` and `mant` properties must be lesser than or equal to 64. |
fffd4c7d | 771 | |
e5aa0be3 | 772 | **Example**: |
fffd4c7d | 773 | |
e5aa0be3 PP |
774 | ```yaml |
775 | exp: 8 | |
776 | mant: 24 | |
fffd4c7d PP |
777 | ``` |
778 | ||
fffd4c7d | 779 | |
e5aa0be3 | 780 | ##### Enumeration type object |
fffd4c7d | 781 | |
e5aa0be3 | 782 | A CTF enumeration type. |
fffd4c7d | 783 | |
e5aa0be3 PP |
784 | Each label of an enumeration type is mapped to a single value, or to a |
785 | range of values. | |
fffd4c7d | 786 | |
e5aa0be3 | 787 | **Properties**: |
fffd4c7d | 788 | |
e5aa0be3 PP |
789 | | Property | Type | Description | Required? | Default value | |
790 | |---|---|---|---|---| | |
791 | | `value-type` | [Integer type object](#integer-type-object) or string (alias name) | Supporting integer type | Required | N/A | | |
792 | | `members` | Array of [enumeration type member objects](#enumeration-type-member-object) | Enumeration members | Required | N/A | | |
fffd4c7d | 793 | |
e5aa0be3 PP |
794 | The `members` property must contain at least one element. If the member |
795 | is a string, its associated value is computed as follows: | |
fffd4c7d | 796 | |
e5aa0be3 PP |
797 | * If the member is the first one of the `members` array, its value |
798 | is 0. | |
799 | * If the previous member is a string, its value is the previous | |
800 | member's computed value + 1. | |
801 | * If the previous member is a single value member, its value is | |
802 | the previous member's value + 1. | |
803 | * If the previous member is a range member, its value is the previous | |
804 | member's upper bound + 1. | |
fffd4c7d | 805 | |
e5aa0be3 | 806 | The member values must not overlap each other. |
fffd4c7d | 807 | |
e5aa0be3 | 808 | **Example**: |
fffd4c7d | 809 | |
e5aa0be3 PP |
810 | ```yaml |
811 | class: enum | |
812 | value-type: uint8 | |
813 | members: | |
814 | - ZERO | |
815 | - ONE | |
816 | - TWO | |
817 | - label: SIX | |
818 | value: 6 | |
819 | - SE7EN | |
820 | - label: TWENTY TO FOURTY | |
821 | value: [10, 40] | |
822 | - FORTY-ONE | |
fffd4c7d PP |
823 | ``` |
824 | ||
e5aa0be3 PP |
825 | **Equivalent C type**: equivalent C type of supporting integer type |
826 | (see [integer type object documentation](#integer-type-object) above). | |
fffd4c7d | 827 | |
fffd4c7d | 828 | |
e5aa0be3 | 829 | ###### Enumeration type member object |
503819da | 830 | |
e5aa0be3 | 831 | The member of a CTF enumeration type. |
fffd4c7d | 832 | |
e5aa0be3 PP |
833 | If it's a string, the string is the member's label, and the members's |
834 | value depends on the last member's value (see explanation in | |
835 | [enumeration type object documentation](#enumeration-type-object) above). | |
fffd4c7d | 836 | |
e5aa0be3 | 837 | Otherwise, it's a complete member object, with the following properties: |
fffd4c7d | 838 | |
e5aa0be3 PP |
839 | | Property | Type | Description | Required? | Default value | |
840 | |---|---|---|---|---| | |
841 | | `label` | String | Member's label | Required | N/A | | |
842 | | `value` | Integer (single value) or array of two integers (range value) | Member's value | Required | N/A | | |
fffd4c7d | 843 | |
e5aa0be3 PP |
844 | If the `value` property is an array of two integers, the member's label is |
845 | associated to this range, both lower and upper bounds included. The array's | |
846 | first element must be lesser than or equal to the second element. | |
fffd4c7d | 847 | |
e5aa0be3 | 848 | **Example**: |
fffd4c7d | 849 | |
e5aa0be3 PP |
850 | ```yaml |
851 | label: my enum label | |
852 | value: [-25, 78] | |
fffd4c7d | 853 | ``` |
e5aa0be3 PP |
854 | |
855 | ||
856 | ##### String type object | |
857 | ||
858 | A CTF null-terminated string type. | |
859 | ||
860 | This object has no properties. | |
861 | ||
862 | **Example**: | |
863 | ||
864 | ```yaml | |
865 | class: string | |
fffd4c7d PP |
866 | ``` |
867 | ||
e5aa0be3 PP |
868 | **Equivalent C type**: `const char *`. |
869 | ||
870 | ||
871 | ##### Array type object | |
872 | ||
873 | A CTF array or sequence (variable-length array) type. | |
874 | ||
875 | **Properties**: | |
876 | ||
877 | | Property | Type | Description | Required? | Default value | | |
878 | |---|---|---|---|---| | |
879 | | `element-type` | [Type object](#type-objects) or string (alias name) | Type of array's elements | Required | N/A | | |
880 | | `length` | Positive integer (static array) or string (variable-length array) | Array type's length | Required | N/A | | |
881 | ||
882 | If the `length` property is a string, the array type has a | |
883 | variable length (CTF sequence). In this case, the property's value | |
884 | refers to a previous structure field. The `length` property's value | |
885 | may be prefixed with one of the following strings to indicate an | |
886 | absolute lookup within a previous (or current) dynamic scope: | |
887 | ||
888 | * `trace.packet.header.`: trace packet header | |
889 | * `stream.packet.context.`: stream packet context | |
890 | * `stream.event.header.`: stream event header | |
891 | * `stream.event.context.`: stream event context | |
892 | * `event.context.`: event context | |
893 | * `event.payload.`: event payload | |
894 | ||
895 | The pointed field must have an unsigned integer type. | |
896 | ||
897 | **Example** (16 bytes): | |
898 | ||
899 | ```yaml | |
900 | class: array | |
901 | length: 16 | |
902 | element-type: | |
903 | class: int | |
904 | size: 8 | |
fffd4c7d | 905 | ``` |
e5aa0be3 PP |
906 | |
907 | **Example** (variable-length array of null-terminated strings): | |
908 | ||
909 | ```yaml | |
910 | class: array | |
911 | length: previous_field | |
912 | element-type: | |
913 | class: string | |
fffd4c7d PP |
914 | ``` |
915 | ||
e5aa0be3 PP |
916 | |
917 | ##### Structure type object | |
918 | ||
919 | A CTF structure type, i.e. a list of fields, each field | |
920 | having a name and a CTF type. | |
921 | ||
922 | **Properties**: | |
923 | ||
924 | | Property | Type | Description | Required? | Default value | | |
925 | |---|---|---|---|---| | |
926 | | `min-align` | Integer (positive) | Minimum alignment (bits) (power of two) | Optional | 1 | | |
927 | | `fields` | Associative array of field names (string) to [type objects](#type-objects) or strings (alias names) | Structure type's fields | Optional | `{}` | | |
928 | ||
929 | The order of the entries in the `fields` property is important; it is in | |
930 | this order that the fields are serialized in binary streams. | |
931 | ||
932 | **Example**: | |
933 | ||
934 | ```yaml | |
935 | class: struct | |
936 | min-align: 32 | |
937 | fields: | |
938 | msg_id: uint8 | |
939 | src: | |
940 | class: string | |
941 | dst: | |
942 | class: string | |
fffd4c7d | 943 | ``` |
e5aa0be3 PP |
944 | |
945 | ||
946 | ##### Variant type object | |
947 | ||
948 | A CTF variant type, i.e. a tagged union of CTF types. | |
949 | ||
950 | **Properties**: | |
951 | ||
952 | | Property | Type | Description | Required? | Default value | | |
953 | |---|---|---|---|---| | |
954 | | `tag` | String | Variant type's tag | Required | N/A | | |
955 | | `types` | Associative array of strings to [type objects](#type-objects) or strings (alias names) | Possible types | Required | N/A | | |
956 | ||
957 | The `tag` property's value refers to a previous structure field. | |
958 | The value may be prefixed with one of the following strings to indicate | |
959 | an absolute lookup within a previous (or current) dynamic scope: | |
960 | ||
961 | * `trace.packet.header.`: trace packet header | |
962 | * `stream.packet.context.`: stream packet context | |
963 | * `stream.event.header.`: stream event header | |
964 | * `stream.event.context.`: stream event context | |
965 | * `event.context.`: event context | |
966 | * `event.payload.`: event payload | |
967 | ||
968 | The pointed field must have an enumeration type. Each type name in the | |
969 | `types` property must have its equivalent member's label in this | |
970 | enumeration type. This is how a variant's type is selected using the | |
971 | value of its tag. | |
972 | ||
973 | **Example**: | |
974 | ||
975 | ```yaml | |
976 | class: variant | |
977 | tag: my_choice | |
978 | types: | |
979 | a: | |
980 | class: string | |
981 | b: int32 | |
982 | c: | |
983 | class: float | |
984 | size: | |
985 | align: 32 | |
986 | exp: 8 | |
987 | mant: 24 | |
fffd4c7d PP |
988 | ``` |
989 | ||
990 | ||
f9ba3624 | 991 | ### Running the `barectf` command |
fffd4c7d PP |
992 | |
993 | Using the `barectf` command-line utility is easy. In its simplest form, | |
e5aa0be3 PP |
994 | it outputs a CTF metadata file and a few C files out of a |
995 | YAML configuration file: | |
fffd4c7d | 996 | |
e5aa0be3 | 997 | barectf config.yaml |
fffd4c7d | 998 | |
e5aa0be3 | 999 | will output, in the current working directory: |
fffd4c7d | 1000 | |
e5aa0be3 PP |
1001 | * `metadata`: CTF metadata file |
1002 | * `barectf-bitfield.h`: macros used by tracing functions to pack bits | |
fffd4c7d PP |
1003 | * `barectf.h`: other macros and prototypes of context/tracing functions |
1004 | * `barectf.c`: context/tracing functions | |
1005 | ||
e5aa0be3 PP |
1006 | `barectf_` is the default name of the files and the default prefix of |
1007 | barectf C functions and structures. The prefix is read from the | |
1008 | configuration file (see the | |
1009 | [configuration object documentation](#configuration-object)), but | |
1010 | you may override it on the command line: | |
fffd4c7d | 1011 | |
e5aa0be3 | 1012 | barectf --prefix my_app_ config.yaml |
fffd4c7d PP |
1013 | |
1014 | You may also output the files elsewhere: | |
1015 | ||
e5aa0be3 PP |
1016 | barectf --code-dir src --headers-dir include --metadata-dir ctf config.yaml |
1017 | ||
fffd4c7d | 1018 | |
e5aa0be3 | 1019 | ### Using the generated C code |
fffd4c7d PP |
1020 | |
1021 | This section assumes you ran `barectf` with no options: | |
1022 | ||
e5aa0be3 | 1023 | barectf config.yaml |
fffd4c7d | 1024 | |
e5aa0be3 PP |
1025 | The command generates C structures and functions to initialize |
1026 | barectf contexts, open packets, and close packets. It also generates as many | |
1027 | tracing functions as there are events defined in the YAML configuration | |
1028 | file. | |
fffd4c7d | 1029 | |
e5aa0be3 PP |
1030 | An application should never have to initialize barectf contexts, |
1031 | open packets, or close packets; this is the purpose of a specific barectf | |
1032 | platform, which wraps those calls in its own initialization and | |
1033 | finalization functions. | |
fffd4c7d | 1034 | |
e5aa0be3 PP |
1035 | The barectf project provides a few platforms in the [`platforms`](platforms) |
1036 | directory. Each one contains a `README.md` file explaining how to use | |
1037 | the platform. If you're planning to write your own platform, | |
1038 | read the next subsection. Otherwise, skip it. | |
fffd4c7d | 1039 | |
fffd4c7d | 1040 | |
e5aa0be3 | 1041 | #### Writing a barectf platform |
fffd4c7d | 1042 | |
e5aa0be3 | 1043 | A **_barectf platform_** is responsible for: |
fffd4c7d | 1044 | |
e5aa0be3 PP |
1045 | 1. Providing some initialization and finalization functions |
1046 | for the tracing infrastructure of the target. The initialization | |
1047 | function is responsible for initializing a barectf context, | |
1048 | providing the platform callback functions, and for opening the very | |
1049 | first stream packet(s). The finalization function is responsible | |
1050 | for closing, usually when not empty, the very last stream | |
1051 | packet(s). | |
1052 | 2. Implementing the platform callback functions to accomodate the target | |
1053 | system. The main purposes of those callback functions are: | |
1054 | * Getting the current value of clock(s). | |
1055 | * Doing something with a packet once it's full. This is how | |
1056 | a ring buffer of packets may be implemented. The platform | |
1057 | may also be naive and write the full packets to the file system | |
1058 | directly. | |
fffd4c7d | 1059 | |
e5aa0be3 PP |
1060 | Thus, the traced application itself should never have to call |
1061 | the barectf initialization, packet opening, and packet closing | |
1062 | funcions. The application only deals with initializing/finalizing | |
1063 | the platform, and calling the tracing functions. | |
fffd4c7d | 1064 | |
e5aa0be3 PP |
1065 | The following diagram shows how each part connects with |
1066 | each other: | |
fffd4c7d | 1067 | |
e5aa0be3 PP |
1068 | ![](http://0x3b.org/ss/placoderm625.png) |
1069 | ||
1070 | The following subsections explain what should exist in each | |
1071 | platform function. | |
fffd4c7d | 1072 | |
fffd4c7d | 1073 | |
e5aa0be3 | 1074 | ##### Platform initialization function |
fffd4c7d | 1075 | |
e5aa0be3 PP |
1076 | A barectf platform initialization function is responsible for |
1077 | initializing barectf context(s) (calling `barectf_init()`, | |
1078 | where `barectf_` is the configured prefix), and opening the very | |
1079 | first packet (calling `barectf_stream_open_packet()` with | |
1080 | target-specific parameters, for each stream, where `stream` is | |
1081 | the stream name). | |
1082 | ||
1083 | barectf generates one context C structure for each defined stream. | |
1084 | They all contain the same first member, a structure with common | |
1085 | properties. | |
1086 | ||
1087 | barectf generates a single context initialization function: | |
1088 | ||
1089 | ```c | |
1090 | void barectf_init( | |
1091 | void *ctx, | |
1092 | uint8_t *buf, | |
1093 | uint32_t buf_size, | |
1094 | struct barectf_platform_callbacks cbs, | |
1095 | void *data | |
1096 | ); | |
fffd4c7d | 1097 | ``` |
e5aa0be3 PP |
1098 | |
1099 | This function must be called with each stream-specific context | |
1100 | structure to be used afterwards. The parameters are: | |
1101 | ||
1102 | * `ctx`: stream-specific barectf context (allocated by caller) | |
1103 | * `buf`: buffer to use for this stream's packet (allocated by caller) | |
1104 | * `buf_size`: size of `buf` in bytes | |
1105 | * `cbs`: platform callback functions to be used with this | |
1106 | stream-specific context | |
1107 | * `data`: user data passed to platform callback functions (`cbs`) | |
1108 | ||
1109 | **Example**: | |
1110 | ||
1111 | ```c | |
1112 | #define BUF_SZ 4096 | |
1113 | ||
1114 | void platform_init(/* ... */) | |
1115 | { | |
1116 | struct barectf_my_stream_ctx *ctx; | |
1117 | uint8_t *buf; | |
1118 | struct my_data *my_data; | |
1119 | struct barectf_platform_callbacks cbs = { | |
1120 | /* ... */ | |
fffd4c7d | 1121 | }; |
e5aa0be3 PP |
1122 | |
1123 | ctx = platform_alloc(sizeof(*ctx)); | |
1124 | buf = platform_alloc(BUF_SZ); | |
1125 | my_data = platform_alloc(sizeof(*my_data)); | |
1126 | my_data->ctx = ctx; | |
1127 | barectf_init(ctx, buf, BUF_SZ, cbs, my_data); | |
1128 | ||
1129 | /* ... */ | |
1130 | } | |
fffd4c7d PP |
1131 | ``` |
1132 | ||
e5aa0be3 PP |
1133 | barectf generates one packet opening and one packet closing |
1134 | function per defined stream, since each stream may have custom | |
1135 | parameters at the packet opening time, and custom offsets of | |
1136 | fields to write at packet closing time. | |
1137 | ||
1138 | The platform initialization should open the very first packet | |
1139 | of each stream to use because the tracing functions expect the | |
1140 | current packet to be opened. | |
1141 | ||
1142 | Here's an example of a packet opening function prototype: | |
fffd4c7d PP |
1143 | |
1144 | ```c | |
e5aa0be3 PP |
1145 | void barectf_my_stream_open_packet( |
1146 | struct barectf_my_stream_ctx *ctx, | |
1147 | float spc_something | |
fffd4c7d PP |
1148 | ); |
1149 | ``` | |
1150 | ||
e5aa0be3 PP |
1151 | The function needs the stream-specific barectf context, as well as any |
1152 | custom trace packet header or stream packet context field; in this | |
1153 | last example, `something` is a floating point number stream packet context | |
1154 | field. | |
1155 | ||
1156 | ||
1157 | ##### barectf packet information API | |
1158 | ||
1159 | There's a small API to query stuff about the current packet of a | |
1160 | given barectf context: | |
1161 | ||
1162 | ```c | |
1163 | uint32_t barectf_packet_size(void *ctx); | |
1164 | int barectf_packet_is_full(void *ctx); | |
1165 | int barectf_packet_is_empty(void *ctx); | |
1166 | uint32_t barectf_packet_events_discarded(void *ctx); | |
1167 | uint8_t *barectf_packet_buf(void *ctx); | |
1168 | void barectf_packet_set_buf(void *ctx, uint8_t *buf, uint32_t buf_size); | |
1169 | uint32_t barectf_packet_buf_size(void *ctx); | |
1170 | int barectf_packet_is_open(void *ctx); | |
1171 | ``` | |
1172 | ||
1173 | `barectf_packet_is_full()` returns 1 if the context's current packet | |
1174 | is full (no space left for any event), 0 otherwise. | |
1175 | ||
1176 | `barectf_packet_is_empty()` returns 1 if the context's current packet | |
1177 | is empty (no recorded events), 0 otherwise. | |
1178 | ||
1179 | `barectf_packet_events_discarded()` returns the number of lost (discarded) | |
1180 | events _so far_ for a given stream. | |
1181 | ||
1182 | The buffer size (`buf_size` parameter of `barectf_packet_set_buf()` and | |
1183 | return value of `barectf_packet_buf_size()`) is always a number of bytes. | |
1184 | ||
1185 | `barectf_packet_is_open()` returns 1 if the context's current packet | |
1186 | is open (the packet opening function was called with this context). | |
fffd4c7d | 1187 | |
fffd4c7d | 1188 | |
e5aa0be3 PP |
1189 | ##### Platform callback functions |
1190 | ||
1191 | The callback functions to implement for a given platform are | |
1192 | in the generated `barectf_platform_callbacks` C structure. This | |
1193 | structure will contain: | |
1194 | ||
1195 | * One callback function per defined clock, using the clock's | |
1196 | return C type. Those functions must return the current clock | |
1197 | values. | |
1198 | * `is_backend_full()`: is the back-end full? If a new packet | |
1199 | is opened now, does it have its reserved space in the back-end? | |
1200 | Return 0 if it does, 1 otherwise. | |
1201 | * `open_packet()`: this callback function **must** call the relevant | |
1202 | packet opening function. | |
1203 | * `close_packet()`: this callback function **must** call the | |
1204 | relevant packet closing function _and_ copy/move the current packet | |
1205 | to the back-end. | |
1206 | ||
1207 | What exactly is a _back-end_ is left to the platform implementor. It | |
1208 | could be a ring buffer of packets, or it could be dumber: `close_packet()` | |
1209 | always appends the current packet to some medium, and `is_backend_full()` | |
1210 | always returns 0 (back-end is never full). | |
1211 | ||
1212 | Typically, if `is_backend_full()` returns 0, then the next | |
1213 | call to `close_packet()` should be able to write the current packet. | |
1214 | If `is_backend_full()` returns 1, there will be lost (discarded) | |
1215 | events. If a stream packet context has an `events_discarded` field, | |
1216 | it will be written to accordingly when a packet is closed. | |
1217 | ||
1218 | If a platform needs double buffering, `open_packet()` is the callback | |
1219 | function where packet buffers would be swapped (before calling | |
1220 | the barectf packet opening function). | |
1221 | ||
1222 | ||
1223 | ##### Platform finalization function | |
1224 | ||
1225 | The platform finalization function should be called by the application | |
1226 | when tracing is no more required. It is responsible for closing the | |
1227 | very last packet of each stream. | |
1228 | ||
1229 | Typically, assuming there's only one stream (named `my_stream` in this | |
1230 | example), the finalization function will look like this: | |
1231 | ||
1232 | ```c | |
1233 | void platform_tracing_finalize(struct platform_data *platform_data) | |
1234 | { | |
1235 | if (barectf_packet_is_open(platform_data->ctx) && | |
1236 | !barectf_packet_is_empty(platform_data->ctx)) { | |
1237 | barectf_my_stream_close_packet(platform_data->ctx); | |
1238 | ||
1239 | /* | |
1240 | * Do whatever is necessary here to write the packet | |
1241 | * to the platform's back-end. | |
1242 | */ | |
1243 | } | |
1244 | } | |
1245 | ``` | |
1246 | ||
1247 | That is: if the packet is still open (thus not closed and written yet) | |
1248 | _and_ it contains at least one event (not empty), close and write the last | |
1249 | packet. | |
1250 | ||
1251 | Note, however, that you might be interested in closing an open empty | |
1252 | packet, since its packet context could update the discarded events count | |
1253 | (if there were lost events between the last packet closing time and | |
1254 | now, which is quite possible if the back-end became full after closing | |
1255 | and writing the previous packet). | |
1256 | ||
1257 | ||
1258 | #### Calling the generated tracing functions | |
1259 | ||
1260 | Calling the generated tracing functions is what the traced application | |
1261 | actually does. | |
1262 | ||
1263 | For a given prefix named `barectf`, a given stream named `stream`, and | |
1264 | a given event named `event`, the generated tracing function name is | |
1265 | `barectf_stream_trace_event()`. | |
1266 | ||
1267 | The first parameter of a tracing function is always the stream-specific | |
1268 | barectf context. Then, in this order: | |
1269 | ||
1270 | * One parameter for each custom event header field | |
1271 | (prefixed with `seh_`) | |
1272 | * One parameter for each custom stream event context field | |
1273 | (prefixed with `sec_`) | |
1274 | * One parameter for each custom event context field | |
1275 | (prefixed with `ec_`) | |
1276 | * One parameter for each custom event payload field | |
1277 | (prefixed with `ep_`) | |
1278 | ||
1279 | A tracing function returns nothing: it either succeeds (the event | |
1280 | is serialized in the current packet) or fails when there's no | |
1281 | space left (the context's discarded events count is incremented). | |
1282 | ||
1283 | **Example**: | |
1284 | ||
1285 | Given the following [event object](#event-object), named `my_event`, | |
1286 | placed in a stream named `default` with no custom event header/stream event | |
1287 | context fields: | |
1288 | ||
1289 | ```yaml | |
1290 | context-type: | |
1291 | class: struct | |
1292 | fields: | |
1293 | msg_id: | |
1294 | class: int | |
1295 | size: 16 | |
1296 | payload-type: | |
1297 | class: struct | |
1298 | fields: | |
1299 | src: | |
1300 | class: string | |
1301 | dst: | |
1302 | class: string | |
1303 | a_id: | |
1304 | class: int | |
1305 | size: 3 | |
1306 | b_id: | |
1307 | class: int | |
1308 | size: 7 | |
1309 | signed: true | |
1310 | c_id: | |
1311 | class: int | |
1312 | size: 15 | |
1313 | amt: | |
1314 | class: float | |
1315 | align: 32 | |
1316 | size: | |
1317 | exp: 8 | |
1318 | mant: 24 | |
1319 | ``` | |
1320 | ||
1321 | barectf will generate the following tracing function prototype: | |
1322 | ||
1323 | ```c | |
1324 | /* trace (stream "default", event "my_event") */ | |
1325 | void barectf_default_trace_my_event( | |
1326 | struct barectf_default_ctx *ctx, | |
1327 | uint16_t ec_msg_id, | |
1328 | const char *ep_src, | |
1329 | const char *ep_dst, | |
1330 | uint8_t ep_a_id, | |
1331 | int8_t ep_b_id, | |
1332 | uint16_t ep_c_id, | |
1333 | float amt | |
1334 | ); | |
1335 | ``` | |
fffd4c7d PP |
1336 | |
1337 | ||
f9ba3624 | 1338 | ### Reading CTF traces |
fffd4c7d | 1339 | |
e5aa0be3 PP |
1340 | To form a complete CTF trace, the `metadata` file generated by the |
1341 | `barectf` command-line tool and the binary stream files generated | |
1342 | by the application (or by an external consumer, depending on the | |
1343 | platform) should be placed in the same directory. | |
fffd4c7d PP |
1344 | |
1345 | To read a CTF trace, use [Babeltrace](http://www.efficios.com/babeltrace). | |
e5aa0be3 PP |
1346 | Babeltrace is packaged by most major distributions as the `babeltrace` |
1347 | package. Babeltrace ships with a command-line utility that can convert a | |
1348 | CTF trace to human-readable text output. Also, it includes Python bindings | |
1349 | so that you may analyze a CTF trace using a custom script. | |
fffd4c7d PP |
1350 | |
1351 | In its simplest form, the `babeltrace` command-line converter is quite | |
1352 | easy to use: | |
1353 | ||
1354 | babeltrace /path/to/directory/containing/ctf/files | |
1355 | ||
e5aa0be3 | 1356 | See `babeltrace --help` and `man babeltrace` for more options. |