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