mirror of
https://github.com/DynamoRIO/dynamorio.git
synced 2026-10-12 02:02:04 +00:00
In https://github.com/llvm/llvm-project/pull/137112 clang-format changed its behavior to only recognize header guards with empty defines, breaking our formatting. We solve that by removing the superfluous "1" value from our header guard defines. Fixes #7757
280 lines
12 KiB
C
280 lines
12 KiB
C
/* ******************************************************
|
|
* Copyright (c) 2014-2025 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 VMware, 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.
|
|
*/
|
|
|
|
#ifndef _DR_ANNOTATION_H_
|
|
#define _DR_ANNOTATION_H_
|
|
|
|
#include "dr_tools.h"
|
|
|
|
/*********************************************************
|
|
* ROUTINES TO REGISTER ANNOTATION HANDLERS
|
|
*/
|
|
/**
|
|
* @file dr_annotation.h
|
|
* @brief Annotation handler registration routines.
|
|
*/
|
|
|
|
/**
|
|
* Facilitates returning a value from an annotation invocation in the target app. This
|
|
* function should be used within the annotation clean call, and the specified value will
|
|
* be received in the target app by the annotation caller. This function may be invoked
|
|
* multiple times, in which case only the last value will take effect.
|
|
*
|
|
* @param[in] value The return value (unsigned, pointer-sized) that will be received
|
|
* in the target app.
|
|
*/
|
|
static inline void
|
|
dr_annotation_set_return_value(reg_t value)
|
|
{
|
|
dr_mcontext_t mcontext;
|
|
void *dcontext = dr_get_current_drcontext();
|
|
mcontext.size = sizeof(dr_mcontext_t);
|
|
mcontext.flags = DR_MC_INTEGER;
|
|
dr_get_mcontext(dcontext, &mcontext);
|
|
mcontext.xax = value;
|
|
dr_set_mcontext(dcontext, &mcontext);
|
|
}
|
|
|
|
/**
|
|
* Synonyms for the Valgrind client request IDs (sequential from 0 for convenience).
|
|
*/
|
|
typedef enum _dr_valgrind_request_id_t {
|
|
/**
|
|
* Return true if running in DynamoRIO with Valgrind annotation support. No args.
|
|
*/
|
|
DR_VG_ID__RUNNING_ON_VALGRIND,
|
|
/**
|
|
* Request an immediate memory scan to look for leaks.
|
|
* Not relevant to core DR; provided for client use.
|
|
*/
|
|
DR_VG_ID__DO_LEAK_CHECK,
|
|
/**
|
|
* Indicate that the specified range of addresses should be considered defined if
|
|
* it is addressable. Not relevant to core DR; provided for client use.
|
|
*/
|
|
DR_VG_ID__MAKE_MEM_DEFINED_IF_ADDRESSABLE,
|
|
/**
|
|
* Request that DynamoRIO discard all fragments in the code cache that were
|
|
* translated from the specified range of addresses. The request takes 2 args,
|
|
* start and length. It is implemented in core DR with JIT optimization enabled,
|
|
* though clients may implement additional functionality.
|
|
*/
|
|
DR_VG_ID__DISCARD_TRANSLATIONS,
|
|
/**
|
|
* Indicate that the specified range of addresses should be considered undefined.
|
|
* Not relevant to core DR; provided for client use.
|
|
*/
|
|
DR_VG_ID__MAKE_MEM_UNDEFINED,
|
|
/**
|
|
* Indicate that the specified range of addresses should be considered defined.
|
|
* Not relevant to core DR; provided for client use.
|
|
*/
|
|
DR_VG_ID__MAKE_MEM_DEFINED,
|
|
/**
|
|
* Returns whether the specified range of addresses is addressable. Not currently
|
|
* implemented in core DR.
|
|
*/
|
|
DR_VG_ID__CHECK_MEM_IS_ADDRESSABLE,
|
|
/**
|
|
* Returns whether the specified range of addresses is defined. Not currently
|
|
* implemented in core DR.
|
|
*/
|
|
DR_VG_ID__CHECK_MEM_IS_DEFINED,
|
|
/**
|
|
* Identifies a custom heap allocation. Not relevant to core DR; provided for client
|
|
* use.
|
|
*/
|
|
DR_VG_ID__MALLOCLIKE_BLOCK,
|
|
/**
|
|
* Identifies a custom heap free. Not relevant to core DR; provided for client use.
|
|
*/
|
|
DR_VG_ID__FREELIKE_BLOCK,
|
|
/**
|
|
* Sentinel value for iterator convenience.
|
|
*/
|
|
DR_VG_ID__LAST
|
|
} dr_valgrind_request_id_t;
|
|
|
|
enum {
|
|
/**
|
|
* Defines the maximum number of arguments that can be passed to a Valgrind
|
|
* annotation, and accordingly specifies the length of the array
|
|
* vg_client_request_t.args.
|
|
*/
|
|
DR_VG_NUM_ARGS = 5,
|
|
};
|
|
|
|
/**
|
|
* Defines the Valgrind client request object, which is constructed by each instance of
|
|
* a Valgrind annotation in the target app. An instance is passed to Valgrind annotation
|
|
* callback functions to make the arguments available. Some arguments may be
|
|
* undefined for some Valgrind client requests; see the Valgrind documentation for each
|
|
* specific Valgrind client request for details about the arguments.
|
|
*/
|
|
typedef struct _dr_vg_client_request_t {
|
|
ptr_uint_t request;
|
|
ptr_uint_t args[DR_VG_NUM_ARGS];
|
|
ptr_uint_t default_result;
|
|
} dr_vg_client_request_t;
|
|
|
|
/**
|
|
* Defines the calling conventions that are supported for annotation functions
|
|
* (as they appear in the target app).
|
|
*/
|
|
typedef enum _dr_annotation_calling_convention_t {
|
|
DR_ANNOTATION_CALL_TYPE_FASTCALL, /**< calling convention "fastcall" */
|
|
#ifdef X64
|
|
/**
|
|
* The calling convention for vararg functions on x64, which must be "fastcall".
|
|
*/
|
|
DR_ANNOTATION_CALL_TYPE_VARARG = DR_ANNOTATION_CALL_TYPE_FASTCALL,
|
|
#else
|
|
DR_ANNOTATION_CALL_TYPE_STDCALL, /**< x86 calling convention "stdcall" */
|
|
/**
|
|
* The calling convention for vararg functions on x86, which must be "stdcall".
|
|
*/
|
|
DR_ANNOTATION_CALL_TYPE_VARARG = DR_ANNOTATION_CALL_TYPE_STDCALL,
|
|
#endif
|
|
DR_ANNOTATION_CALL_TYPE_LAST /**< Sentinel value for iterator convenience */
|
|
} dr_annotation_calling_convention_t;
|
|
|
|
DR_API
|
|
/**
|
|
* Register a handler for a DR annotation. When the annotation is encountered, it will
|
|
* be replaced with a clean call to the specified callee, which must have the specified
|
|
* number of arguments. Returns true on successful registration.
|
|
*
|
|
* @param[in] annotation_name The name of the annotation function as it appears in the
|
|
* target app's source code (unmangled).
|
|
* @param[in] callee The client function to call when an instance of the
|
|
* specified annotation is executed.
|
|
* @param[in] save_fpstate Indicates whether to save floating point state before
|
|
* making the clean call to the callee.
|
|
* @param[in] num_args The number of arguments in the annotation function (must
|
|
* also match the number of arguments in the callee).
|
|
* @param[in] call_type The calling convention of the annotation function as
|
|
* compiled in the target app (x86 only).
|
|
*/
|
|
bool
|
|
dr_annotation_register_call(const char *annotation_name, void *callee, bool save_fpstate,
|
|
uint num_args, dr_annotation_calling_convention_t call_type);
|
|
|
|
DR_API
|
|
/**
|
|
* Register a callback for a Valgrind client request id. When the request is encountered,
|
|
* the specified callback will be invoked by an internal routing function. Returns true
|
|
* on successful registration.
|
|
*
|
|
* @param[in] request_id The Valgrind request id for which to register.
|
|
* @param[in] annotation_callback The client function to call when an instance of the
|
|
* specified Valgrind client request is executed.
|
|
*/
|
|
bool
|
|
dr_annotation_register_valgrind(
|
|
dr_valgrind_request_id_t request_id,
|
|
ptr_uint_t (*annotation_callback)(dr_vg_client_request_t *request));
|
|
|
|
DR_API
|
|
/**
|
|
* Register a return value substitution for a DR annotation. When the annotation is
|
|
* encountered, it will be replaced with the specified return value. This function
|
|
* returns true on successful registration.
|
|
*
|
|
* @param[in] annotation_name The name of the annotation function as it appears in the
|
|
* target app's source code (unmangled).
|
|
* @param[in] return_value The value to return from every instance of the annotation.
|
|
*/
|
|
bool
|
|
dr_annotation_register_return(const char *annotation_name, void *return_value);
|
|
|
|
DR_API
|
|
/**
|
|
* Can only be called on an annotation already registered with
|
|
* dr_annotation_register_call(). When the annotation is encountered, the PC of
|
|
* the annotation interruption point will be available in DR scratch slot #SPILL_SLOT_2,
|
|
* which can be read with dr_read_saved_reg().
|
|
*
|
|
* @param[in] annotation_name The name of the annotation function as it appears in the
|
|
* target app's source code (unmangled).
|
|
*/
|
|
bool
|
|
dr_annotation_pass_pc(const char *annotation_name);
|
|
|
|
DR_API
|
|
/**
|
|
* Unregister the specified handler from a DR annotation. Instances of the annotation that
|
|
* have already been substituted with a clean call to the registered callee will remain in
|
|
* the code cache, but any newly encountered instances of the annotation will no longer be
|
|
* substituted with this callee. This function does nothing in the case that the
|
|
* specified callee was never registered for this annotation (or has already been
|
|
* unregistered). Returns true if the registration was successfully unregistered.
|
|
*
|
|
* @param[in] annotation_name The annotation function for which to unregister.
|
|
* @param[in] callee The callee to unregister.
|
|
*/
|
|
bool
|
|
dr_annotation_unregister_call(const char *annotation_name, void *callee);
|
|
|
|
DR_API
|
|
/**
|
|
* Unregister the (universal) return value from a DR annotation. Instances of the
|
|
* annotation that have already been substituted with the return value will remain in the
|
|
* code cache, but any newly encountered instances of the annotation will no longer be
|
|
* substituted. This function does nothing in the case that no return value is currently
|
|
* registered for the specified annotation (or has already been unregistered). Note that
|
|
* if another client has registered a return value, this function will remove that other
|
|
* client's registration. Returns true if the registration was successfully unregistered.
|
|
*
|
|
* @param[in] annotation_name The annotation function for which to unregister.
|
|
*/
|
|
bool
|
|
dr_annotation_unregister_return(const char *annotation_name);
|
|
|
|
DR_API
|
|
/**
|
|
* Unregister the specified callback from a Valgrind client request. The registered
|
|
* callback will not be invoked in association with this client request again (though if
|
|
* the same callback function is also registered for other Valgrind client requests, it
|
|
* will still be invoked in association with those client requests). This function does
|
|
* nothing in the case that no handler was ever registered for this callback function.
|
|
* Returns true if the registration was found and successfully unregistered.
|
|
*
|
|
* @param[in] request_id The request id for which to unregister (DR_VG__*).
|
|
* @param[in] annotation_callback The callback function to unregister.
|
|
*/
|
|
bool
|
|
dr_annotation_unregister_valgrind(
|
|
dr_valgrind_request_id_t request_id,
|
|
ptr_uint_t (*annotation_callback)(dr_vg_client_request_t *request));
|
|
|
|
#endif /* _DR_ANNOTATION_H_ */
|