* Copyright (c) 2014-2021 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_ 1
#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 currently implemented in core DR.
*/
DR_VG_ID__DO_LEAK_CHECK,
* Indicate that the specified range of addresses should be considered defined if
* it is addressable. Not currently implemented in core DR.
*/
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,
* 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,
#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,
* 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
} 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