aboutsummaryrefslogtreecommitdiff
path: root/sideband/include/libipt-sb.h.in
blob: f538f96a40081133e729b04620d23ebed163d95c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
/*
 * Copyright (c) 2017-2019, Intel Corporation
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *
 *  * Redistributions of source code must retain the above copyright notice,
 *    this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright notice,
 *    this list of conditions and the following disclaimer in the documentation
 *    and/or other materials provided with the distribution.
 *  * Neither the name of Intel Corporation nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#ifndef LIBIPT_SB_H
#define LIBIPT_SB_H

#include <stddef.h>
#include <stdint.h>
#include <stdio.h>

#ifdef __cplusplus
extern "C" {
#endif

struct pt_image_section_cache;
struct pt_image;
struct pt_event;


/* A macro to mark functions as exported. */
#ifndef pt_sb_export
#  if defined(__GNUC__)
#    define pt_sb_export __attribute__((visibility("default")))
#  elif defined(_MSC_VER)
#    define pt_sb_export __declspec(dllimport)
#  else
#    error "unknown compiler"
#  endif
#endif


/** The header version. */
#define LIBIPT_SB_VERSION_MAJOR ${PT_VERSION_MAJOR}
#define LIBIPT_SB_VERSION_MINOR ${PT_VERSION_MINOR}
#define LIBIPT_SB_VERSION_PATCH ${PT_VERSION_PATCH}

#define LIBIPT_SB_VERSION ((LIBIPT_SB_VERSION_MAJOR << 8) +	\
			   LIBIPT_SB_VERSION_MINOR)


/* Sideband decode errors and warnings. */
enum pt_sb_error_code {
	/* No error.  Everything is OK. */
	ptse_ok,

	/* Sideband records have been lost. */
	ptse_lost,

	/* Trace has been lost. */
	ptse_trace_lost,

	/* An image section has been lost (ignored). */
	ptse_section_lost
};

/** Return a human readable error string. */
extern pt_sb_export const char *pt_sb_errstr(enum pt_sb_error_code);


/* An Intel(R) Processor Trace (Intel PT) sideband tracing session.
 *
 * The session serves one Intel PT decoder.
 *
 * It is not thread-safe.  It doesn't need to be.  If a trace stream is decoded
 * by multiple decoders in parallel, each decoder needs its own sideband tracing
 * session since each decoder will be looking at the trace at a different point
 * in time and may see a different memory image.
 *
 * A sideband tracing session contains all sideband decoders that are relevant
 * for that trace stream.  We distinguish primary and secondary sideband
 * channels:
 *
 * - primary sideband channels affect decode directly.
 *
 *     They actively change the Intel PT decoder's memory image on context
 *     switch sideband records.
 *
 *     For per-cpu trace decode, for example, the sideband channel of the cpu
 *     for which trace is being decoded is a primary sideband channel.
 *
 * - secondary sideband channels affect decode indirectly.
 *
 *     They maintain the memory image for different process contexts but do not
 *     actively switch the Intel PT decoder's memory image.  They typically
 *     ignore context switch sideband records.
 *
 *     They may still directly affect the Intel PT decoder's memory image by
 *     adding new sections while trace in that context is being decoded.
 *
 *     For per-cpu trace decode, for example, the sideband channels of other
 *     cpus are secondary sideband channels.
 */
struct pt_sb_session;

/* Allocate a tracing session.
 *
 * If @iscache is not NULL, it will be used for allocating new image sections.
 *
 * It is highly recommended to use an image section cache and to use the same
 * cache for related tracing sessions, e.g. for all cpus in a per-cpu trace.
 *
 * Returns a pointer to the new tracing session or NULL if out of memory.
 */
extern pt_sb_export struct pt_sb_session *
pt_sb_alloc(struct pt_image_section_cache *iscache);

/* Free a tracing session.
 *
 * Also frees all sideband decoders and memory images contained in @session.
 */
extern pt_sb_export void pt_sb_free(struct pt_sb_session *session);

/* Get the image section cache.
 *
 * Returns @session's image section cache provided at pt_sb_alloc().
 */
extern pt_sb_export struct pt_image_section_cache *
pt_sb_iscache(struct pt_sb_session *session);

/* Get the kernel image.
 *
 * Returns a non-NULL image for the Operating System in @session.
 *
 * It is not clear, yet, how virtualization will be handled.
 *
 * The returned image will be freed when @session is freed with a call to
 * pt_sb_free().
 */
extern pt_sb_export struct pt_image *
pt_sb_kernel_image(struct pt_sb_session *session);

/* A sideband decode error/warning notifier.
 *
 * It will be called by sideband decoders to report @errcode encountered while
 * processing sideband at @offset in @filename.  Fatal errors will further cause
 * the sideband decoder to be removed.  Non-fatal errors and warnings will
 * otherwise be ignored.
 *
 * Positive @errcode numbers are enum pt_sb_error_code constants.
 * Negative @errcode numbers are enum pt_error_code constants.
 *
 * It shall return zero on success, a negative pt_error_code otherwise.
 */
typedef int (pt_sb_error_notifier_t)(int errcode,  const char *filename,
				     uint64_t offset, void *priv);

/* Install an error notifier.
 *
 * If @notifier is not NULL, will be called on errors and warnings encountered
 * by sideband decoders.
 *
 * Returns the previously installed notifier or NULL.
 */
extern pt_sb_export pt_sb_error_notifier_t *
pt_sb_notify_error(struct pt_sb_session *session,
		   pt_sb_error_notifier_t *notifier, void *priv);

/* Initialize newly added decoders.
 *
 * Initialize decoders that have been added since pt_sb_alloc() or since the
 * last pt_sb_init_decoders() call by fetching their first sideband record.
 *
 * Returns zero on success, a negative error code otherwise.
 */
extern pt_sb_export int pt_sb_init_decoders(struct pt_sb_session *session);

/* Apply an event to all sideband decoders contained in a session.
 *
 * Applies @event to all decoders in @session.  This may involve a series of
 * @apply and subsequent @fetch calls.  See comments on @apply and @fetch for
 * details.
 *
 * Decoders that return an error will be removed from @session and freed.
 *
 * Primary decoders are offered @image and may change it to point to a new
 * memory image.
 *
 * For debugging purposes, decoders are also asked to @print the current record
 * to @stream according to @flags.  Pass a NULL @stream to ask decoders to not
 * print anything.
 *
 * Returns zero on success, a negative error code otherwise.
 */
extern pt_sb_export int pt_sb_event(struct pt_sb_session *session,
				    struct pt_image **image,
				    const struct pt_event *event, size_t size,
				    FILE *stream, uint32_t flags);

/* Dump sideband records up to a given timestamp.
 *
 * Asks all sideband decoders in @session to @print their current record to
 * @stream according to @flags and @fetch the next record as long as the current
 * record's timestamp is smaller or equal to @tsc.
 *
 * Decoders that return an error will be removed from @session and freed.
 *
 * Returns zero on success, a negative error code otherwise.
 */
extern pt_sb_export int pt_sb_dump(struct pt_sb_session *session, FILE *stream,
				   uint32_t flags, uint64_t tsc);


/* A process context.
 *
 * We maintain a separate image per process so we can switch between them
 * easily.  Each image contains both user-space and kernel-space.
 *
 * Image sections are shared between processes using an image section cache.
 *
 * Process contexts are not thread-safe.  The process memory image changes over
 * time depending on sideband information.  Sections of trace between process
 * image changes can be decoded in parallel but threads will need to synchronize
 * across process image changes.
 */
struct pt_sb_context;

/* Get a context reference.
 *
 * Increment @context's use count.
 */
extern pt_sb_export int pt_sb_ctx_get(struct pt_sb_context *context);

/* Put a context reference.
 *
 * Decrement @context's use count and free @context when it reaches zero.
 */
extern pt_sb_export int pt_sb_ctx_put(struct pt_sb_context *context);

/* Get the context's memory image.
 *
 * The caller must hold a reference to @context as long as the image is used.
 *
 * Returns a non-NULL memory image for @context.
 */
extern pt_sb_export struct pt_image *
pt_sb_ctx_image(const struct pt_sb_context *context);

/* Map a file section into a context's image.
 *
 * Adds a section of @size bytes from @filename starting at @offset to @context's
 * image at @vaddr.
 *
 * Returns zero on success, a negative error code otherwise.
 */
extern pt_sb_export int pt_sb_ctx_mmap(struct pt_sb_session *session,
				       struct pt_sb_context *context,
				       const char *filename, uint64_t offset,
				       uint64_t size, uint64_t vaddr);

/* Switch to context's image.
 *
 * Install @context->image in @image.  The caller is responsible for holding a
 * reference to @context as long as its image is in use.
 *
 * Returns zero on success, a negative error code otherwise.
 */
extern pt_sb_export int
pt_sb_ctx_switch_to(struct pt_image **image, struct pt_sb_session *session,
		    const struct pt_sb_context *context);

/* A context switch notifier.
 *
 * It shall return zero on success, a negative pt_error_code otherwise.
 */
typedef int (pt_sb_ctx_switch_notifier_t)(const struct pt_sb_context *,
					  void *priv);

/* Install a context-switch notifier.
 *
 * If @notifier is not NULL, will be called with the switched-to context on a
 * context switch via pt_sb_ctx_switch_to().
 *
 * Returns the previously installed notifier or NULL.
 */
extern pt_sb_export pt_sb_ctx_switch_notifier_t *
pt_sb_notify_switch(struct pt_sb_session *session,
		    pt_sb_ctx_switch_notifier_t *notifier, void *priv);

/* Get the context for pid.
 *
 * Provide a non-NULL process context for @pid in @context.  This may create a
 * new context if no context for @pid exists in @session.  The new context is
 * populated with kernel image sections.
 *
 * This does not provide a new reference to @context.  Use pt_sb_ctx_get() if
 * you need to keep the context.
 *
 * Returns zero on success, a negative error code otherwise.
 */
extern pt_sb_export int
pt_sb_get_context_by_pid(struct pt_sb_context **context,
			 struct pt_sb_session *session, uint32_t pid);

/* Find a context by pid.
 *
 * Provide a non-NULL process context for @pid in @context if it exists in
 * @session.  This does not provide a new reference to @context.  Use
 * pt_sb_ctx_get() if you need to keep the context.
 *
 * Provide a NULL process context in @context if a context for @pid does not
 * exist in @session.
 *
 * Returns zero on success, a negative error code otherwise.
 */
extern pt_sb_export int
pt_sb_find_context_by_pid(struct pt_sb_context **context,
			  struct pt_sb_session *session, uint32_t pid);

/* Remove a context.
 *
 * Removes @context from @session and puts @session's reference to @context.
 * Future lookups won't find @context but it won't be freed until the last user
 * puts it.
 *
 * Returns zero on success, a negative error code otherwise.
 */
extern pt_sb_export int pt_sb_remove_context(struct pt_sb_session *session,
					     struct pt_sb_context *context);


/* A collection of print options. */
enum pt_sb_print_flag {
	/* Print sideband records in compact mode. */
	ptsbp_compact		= 1 << 0,

	/* Print sideband records in verbose mode. */
	ptsbp_verbose		= 1 << 1,

	/* Print the sideband filename. */
	ptsbp_filename		= 1 << 2,

	/* Print the offset into the sideband file. */
	ptsbp_file_offset	= 1 << 3,

	/* Print the sideband record's timestamp. */
	ptsbp_tsc		= 1 << 4

};

/* An Intel PT sideband decoder configuration. */
struct pt_sb_decoder_config {
	/* The size of the config structure in bytes. */
	size_t size;

	/* Fetch the next sideband record and provide its timestamp.
	 *
	 * Return zero on success, a negative error code otherwise.
	 */
	int (*fetch)(struct pt_sb_session *session, uint64_t *tsc, void *priv);

	/* Apply the current sideband record.
	 *
	 * For master sideband channels, @image will be non-NULL and point to
	 * the image object that is currently used.  If the image shall be
	 * switched, set @image to the new image to be used.
	 *
	 * For secondary sideband channels, @image will be NULL.
	 *
	 * The @event argument points to a pt_event object.  Unknown event types
	 * shall be ignored.
	 *
	 * Initially, it will be passed to sideband decoders in the order of
	 * their next record's timestamp.  It must only be applied to the
	 * current sideband record.
	 *
	 * If the record's timestamp is smaller or equal to the event's
	 * timestamp, @fetch will be called to fetch the next sideband record,
	 * and @apply will be called again for the new sideband record with the
	 * same @event.
	 *
	 * This repeats until the @event's timestamp is smaller than the current
	 * record's timestamp.
	 *
	 * The event will then be passed to all sideband decoders irrespective
	 * of their next record's timestamp.  This allows sideband decoders to
	 * postpone actions until a suitable event.
	 *
	 * Return zero on success, a negative error code otherwise.
	 */
	int (*apply)(struct pt_sb_session *session, struct pt_image **image,
		     const struct pt_event *event, void *priv);

	/* Print the current sideband record.
	 *
	 * The output shall be determined based on @flags, which is a bit-vector
	 * of enum pt_sb_print_flag.  A value of zero means that only errors
	 * shall be printed.
	 *
	 * Return zero on success, a negative error code otherwise.
	 */
	int (*print)(struct pt_sb_session *session, FILE *stream,
		     uint32_t flags, void *priv);

	/* Destroy the private data. */
	void (*dtor)(void *priv);

	/* Decoder-specific private data. */
	void *priv;

	/* A collection of configuration flags saying:
	 *
	 * - whether this is a primary decoder (secondary if clear).
	 */
	uint32_t primary:1;
};

/* Add an Intel PT sideband decoder.
 *
 * Allocate a new sideband decoder based on @config and add it to @session.
 *
 * The sideband decoder will automatically be freed when @session is freed with
 * a call to pt_sb_free() or when it is removed from @session after returning an
 * error from one of its callback functions.
 *
 * Returns zero on success, a negative pt_error_code otherwise.
 */
extern pt_sb_export int
pt_sb_alloc_decoder(struct pt_sb_session *session,
		    const struct pt_sb_decoder_config *config);


/* The configuration for a Linux perf event sideband decoder. */
struct pt_sb_pevent_config {
	/* The size of the config structure in bytes. */
	size_t size;

	/* The name of the file containing the sideband data. */
	const char *filename;

	/* The offset into the file from which to start reading. */
	size_t begin;

	/* The optional end offset into the file at which to stop reading.
	 *
	 * Zero means read until the end of the file.
	 */
	size_t end;

	/* The optional system root directory.
	 *
	 * If not NULL, this is prepended to every filename referenced in perf
	 * event sideband records.
	 */
	const char *sysroot;

	/* The optional 64-bit vdso. */
	const char *vdso_x64;

	/* The optional x32 vdso. */
	const char *vdso_x32;

	/* The optional 32-bit vdso. */
	const char *vdso_ia32;

	/* An offset to be subtracted from every perf event record timestamp.
	 *
	 * This applies perf event records a little bit earlier to compensate
	 * for too coarse timing.
	 */
	uint64_t tsc_offset;

	/* The respective field in struct perf_event_attr.
	 *
	 * We require sample_id_all in struct perf_event_attr to be set.
	 */
	uint64_t sample_type;

	/* The start address of the kernel.
	 *
	 * This is used to distinguish kernel from user addresses:
	 *
	 *   kernel >= @kernel_start
	 *   user   <  @kernel_start
	 *
	 * Set to UINT64_MAX if ring-0 is not being traced.
	 */
	uint64_t kernel_start;

	/* The respective fields in struct perf_event_mmap_page. */
	uint16_t time_shift;
	uint32_t time_mult;
	uint64_t time_zero;

	/* A collection of configuration flags saying:
	 *
	 * - whether this is a primary decoder (secondary if clear).
	 */
	uint32_t primary:1;
};

/* Allocate a Linux perf event sideband decoder.
 *
 * Allocates a sideband decoder for the Linux perf event format based on @config
 * and adds it to @session.
 *
 * Returns zero on success, a negative error code otherwise.
 */
extern pt_sb_export int
pt_sb_alloc_pevent_decoder(struct pt_sb_session *session,
			   const struct pt_sb_pevent_config *config);

#ifdef __cplusplus
}
#endif

#endif /* LIBIPT_SB_H */