| /* |
| * 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 */ |