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