* Copyright (c) 2016-2023 Google, Inc. All rights reserved.
* **********************************************************/
* 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 Google, Inc. 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 VMWARE, INC. 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.
*/
* interacting with drmemtrace.
*/
#ifndef _DRMEMTRACE_H_
#define _DRMEMTRACE_H_ 1
* @file drmemtrace.h
* @brief Header for customizing the DrMemtrace tracer.
*/
#ifdef __cplusplus
extern "C" {
#endif
namespace dynamorio {
namespace drmemtrace {
typedef enum {
DRMEMTRACE_SUCCESS,
DRMEMTRACE_ERROR,
DRMEMTRACE_ERROR_INVALID_PARAMETER,
DRMEMTRACE_ERROR_NOT_IMPLEMENTED,
} drmemtrace_status_t;
* Name of drmgr instrumentation pass priorities for app2app, analysis, insert,
* and instru2instru.
*/
#define DRMGR_PRIORITY_NAME_MEMTRACE "memtrace"
DR_EXPORT
* To support statically linking multiple clients on UNIX, dr_client_main() inside
* drmemtrace is a weak symbol which just calls the real initializer
* drmemtrace_client_main(). An enclosing application can override dr_client_main()
* and invoke drmemtrace_client_main() explicitly at a time of its choosing.
*/
void
drmemtrace_client_main(client_id_t id, int argc, const char *argv[]);
* Function for file open.
* The file access mode is set by the \p mode_flags argument which is drawn from
* the DR_FILE_* defines ORed together. Returns INVALID_FILE if unsuccessful.
* The example behavior is described in dr_open_file();
*
* @param[in] fname The filename to open.
* @param[in] mode_flags The DR_FILE_* flags for file open.
*
* \return the opened file id.
*
* \note For additional parameters with the thread and window identifiers,
* use #drmemtrace_open_file_ex_func_t and drmemtrace_replace_file_ops_ex().
*/
typedef file_t (*drmemtrace_open_file_func_t)(const char *fname, uint mode_flags);
* Function for extended file open.
* The file access mode is set by the \p mode_flags argument which is drawn from
* the DR_FILE_* defines ORed together. Returns INVALID_FILE if unsuccessful.
* The example behavior is described in dr_open_file();
*
* @param[in] fname The filename to open.
* @param[in] mode_flags The DR_FILE_* flags for file open.
* @param[in] thread_id The application thread id targeted by this file.
* For special files (drmemtrace_get_modlist_path(), drmemtrace_get_funclist_path(),
* drmemtrace_get_encoding_path(), or PT files), this will be 0.
* @param[in] window_id The tracing window id for this file.
* For special files (drmemtrace_get_modlist_path(), drmemtrace_get_funclist_path(),
* drmemtrace_get_encoding_path(), or PT files), this will be -1.
*
* \return the opened file id.
*/
typedef file_t (*drmemtrace_open_file_ex_func_t)(const char *fname, uint mode_flags,
thread_id_t thread_id, int64 window_id);
* Function for file read.
* Reads up to \p count bytes from file \p file into \p buf.
* Returns the actual number read.
* The example behavior is described in dr_read_file();
*
* @param[in] file The file to be read from.
* @param[in] buf The buffer to be read to.
* @param[in] count The number of bytes to be read.
*
* \return the actual number of bytes read.
*/
typedef ssize_t (*drmemtrace_read_file_func_t)(file_t file, void *buf, size_t count);
* Function for file write.
* Writes \p count bytes from \p data to file \p file.
* Returns the actual number written.
* The example behavior is described in dr_write_file();
*
* @param[in] file The file to be written.
* @param[in] data The data to be written.
* @param[in] count The number of bytes to be written.
*
* \return the actual number of bytes written.
*/
typedef ssize_t (*drmemtrace_write_file_func_t)(file_t file, const void *data,
size_t count);
* Function for file close.
* The example behavior is described in dr_close_file();
*
* @param[in] file The file to be closed.
*/
typedef void (*drmemtrace_close_file_func_t)(file_t file);
* Function for directory creation.
* The example behavior is described in dr_create_dir();
*
* @param[in] dir The directory name for creation.
*
* \return whether successful.
*/
typedef bool (*drmemtrace_create_dir_func_t)(const char *dir);
DR_EXPORT
* Registers functions to replace the default file operations for offline tracing.
* If tracing windows are used and separate files per window are not meant to
* be supported by "open_file_func", it is up to the user to set \p -no_split_windows.
*
* \note The caller is responsible for the transparency and isolation of using
* those functions, which will be called in the middle of arbitrary
* application code.
*
* \note For additional file open parameters with the thread and window identifiers,
* use drmemtrace_replace_file_ops_ex().
*/
drmemtrace_status_t
drmemtrace_replace_file_ops(drmemtrace_open_file_func_t open_file_func,
drmemtrace_read_file_func_t read_file_func,
drmemtrace_write_file_func_t write_file_func,
drmemtrace_close_file_func_t close_file_func,
drmemtrace_create_dir_func_t create_dir_func);
* Function for buffer handoff. Rather than writing a buffer to a
* file when it is full, instead this handoff function gives ownership
* to the callee. The tracer allocates a new buffer and uses it for
* further tracing. The callee is responsible for writing out the
* buffer and for freeing it by calling dr_raw_mem_free().
*
* @param[in] file The file identifier returned by \p open_file_func or
* or drmemtrace_replace_file_ops() was not called then from dr_open_file()
* for the per-thread trace file.
* @param[in] data The start address of the buffer.
* @param[in] data_size The size of valid trace data in the buffer.
* @param[in] alloc_size The allocated size of the buffer.
*
* \return whether successful. Failure is considered unrecoverable.
*/
typedef bool (*drmemtrace_handoff_func_t)(file_t file, void *data, size_t data_size,
size_t alloc_size);
* Function for process exit. This is called during the tracer shutdown, giving
* a control point where DR memory may be accessed, which is not possible when
* acting after dr_app_stop_and_cleanup().
*
* @param[in] arg The \p exit_func_arg passed to drmemtrace_buffer_handoff().
*/
typedef void (*drmemtrace_exit_func_t)(void *arg);
DR_EXPORT
* Registers a function to replace the default file write operation
* for offline tracing and requests that buffer ownership be
* transferred. The regular file open and close routines (or their
* replacements from drmemtrace_replace_file_ops()) will be called,
* but instead of writing to the files (or calling the \p
* write_file_func), the provided \p handoff_func will be called
* instead. The callee is responsible for writing out the buffer and
* for freeing it by calling dr_raw_mem_free(). The amount of
* legitimate data is in \p data_size and the total allocated size of
* the buffer is in \p alloc_size. Any space in between is available
* for use by the callee. The return value of \p handoff_cb indicates
* whether successful or not: failure will be treated as fatal and
* unrecoverable.
*
* The module list data, written to the first file opened, is not
* subject to this ownership transfer and uses the \p write_file_func.
*
* Because DR memory will be freed in dr_app_stop_and_cleanup(), an
* exit callback is provided for a control point to process and free
* the buffers. When dr_app_stop_and_cleanup() is used, \p exit_func
* will be called (and passed \p exit_func_arg) after the other
* application threads are already native.
*
* \note The caller is responsible for the transparency and isolation of using
* these functions, which will be called in the middle of arbitrary
* application code.
*/
drmemtrace_status_t
drmemtrace_buffer_handoff(drmemtrace_handoff_func_t handoff_func,
drmemtrace_exit_func_t exit_func, void *exit_func_arg);
* Structure holding all the file replacement operations for passing to
* drmemtrace_replace_file_ops_ex().
*/
typedef struct {
size_t size;
drmemtrace_open_file_ex_func_t open_file_ex_func;
drmemtrace_read_file_func_t read_file_func;
* Replacement for file writing. Only one of this or \p handoff_buf should be set.
*/
drmemtrace_write_file_func_t write_file_func;
drmemtrace_close_file_func_t close_file_func;
drmemtrace_create_dir_func_t create_dir_func;
* Replacement for file writing where a new buffer is used each time.
* Only one of this or \p write_file should be set.
* See drmemtrace_buffer_handoff().
*/
drmemtrace_handoff_func_t handoff_buf_func;
drmemtrace_exit_func_t exit_func;
void *exit_arg;
} drmemtrace_replace_file_ops_t;
DR_EXPORT
* Combines drmemtrace_replace_file_ops() and drmemtrace_buffer_handoff() and
* provides a file open function which takes two extra parameters.
*/
drmemtrace_status_t
drmemtrace_replace_file_ops_ex(drmemtrace_replace_file_ops_t *ops);
DR_EXPORT
* Retrieves the full path to the output directory in -offline mode
* where data is being written.
*/
drmemtrace_status_t
drmemtrace_get_output_path(OUT const char **path);
DR_EXPORT
* Retrieves the full path to the file in -offline mode where module data is written.
* The basename of the file is
* #DRMEMTRACE_MODULE_LIST_FILENAME. Its creation can be customized using
* drmemtrace_custom_module_data() with corresponding post-processing with
* raw2trace_t::handle_custom_data().
*/
drmemtrace_status_t
drmemtrace_get_modlist_path(OUT const char **path);
DR_EXPORT
* Retrieves the full path to the file in -offline mode where function tracing
* information is written. The basename of the file is
* #DRMEMTRACE_FUNCTION_LIST_FILENAME. Each "library!symbol" function that was traced
* occupies one line of the file, with comma-separated values preceding it: its
* numeric identifier used in trace entries; the number of its arguments that are
* recorded; its address in hexadecimal format; and optional flags such as \"noret\".
* For example:
*
* 4,1,0x7fff2348ac,libc!malloc
* 5,1,0x7fff267d52,noret,libc!free
*
* There can be multiple symbols mapping to the same address and thus to the sam
* identifier; each will have its own line in the file.
*/
drmemtrace_status_t
drmemtrace_get_funclist_path(OUT const char **path);
DR_EXPORT
* Retrieves the full path to the file in -offline mode where
* non-module instruction encoding data is written. The basename of
* the file is #DRMEMTRACE_ENCODING_FILENAME. It contains binary data
* read by the raw2trace tool.
*/
drmemtrace_status_t
drmemtrace_get_encoding_path(OUT const char **path);
DR_EXPORT
* Adds custom data stored with each module in the module list produced for
* offline trace post-processing. The \p load_cb is called for each segment
* of each new module (with \p seg_idx indicating the segment number, starting at 0),
* and its return value is the data that is stored. That data is later printed
* to a string with \p print_cb, which should return the number of characters
* printed or -1 on error. The data is freed with \p free_cb. Each is called
* separately for each segment of each module.
*
* On the post-processing side, the user should create a custom post-processor
* by linking with raw2trace and calling raw2trace_t::handle_custom_data() to provide
* parsing and processing routines for the custom data.
*/
drmemtrace_status_t
drmemtrace_custom_module_data(void *(*load_cb)(module_data_t *module, int seg_idx),
int (*print_cb)(void *data, char *dst, size_t max_len),
void (*free_cb)(void *data));
* Activates thread filtering. The \p should_trace_thread_cb will be
* called once for each new thread, with \p user_value passed in for \p
* user_data. If it returns false, that thread will *not* be traced at
* all; if it returns true, that thread will be traced normally. Returns
* whether the filter was successfully installed. \note This feature is
* currently only supported for x86.
* This routine should be called during initialization, before any
* instrumentation is added. To filter out the calling thread (the initial
* application thread) this should be called prior to DR initialization
* (via the start/stop API). Only a single call to this routine is
* supported.
*/
drmemtrace_status_t
drmemtrace_filter_threads(bool (*should_trace_thread_cb)(thread_id_t tid,
void *user_data),
void *user_value);
DR_EXPORT
* Fetch the timestamp from a raw trace bundle. The API checks if the bundle
* is a thread start or not, and fetches the timestamp from the appropriate
* location.
* Returns DRMEMTRACE_ERROR_INVALID_PARAMETER if the pointer parameters are
* null or if the trace is too short.
*/
drmemtrace_status_t
drmemtrace_get_timestamp_from_offline_trace(const void *trace, size_t trace_size,
OUT uint64 *timestamp);
}
}
#ifdef __cplusplus
}
#endif
#endif