blob: 55b998cfd63b57ed7e763327dc2987d051751c0a [file] [log] [blame]
/* **********************************************************
* Copyright (c) 2010-2021 Google, Inc. All rights reserved.
* **********************************************************/
/* drutil: DynamoRIO Instrumentation Utilities
* Derived from Dr. Memory: the memory debugger
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License, and no later version.
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
/* DynamoRIO Instrumentation Utilities Extension */
#ifndef _DRUTIL_H_
#define _DRUTIL_H_ 1
/**
* @file drutil.h
* @brief Header for DynamoRIO Instrumentation Utilities Extension
*/
#ifdef __cplusplus
extern "C" {
#endif
/**
* \addtogroup drutil Instrumentation Utilities
*/
/**@{*/ /* begin doxygen group */
/***************************************************************************
* INIT
*/
DR_EXPORT
/**
* Initializes the drutil extension. Must be called prior to any of the
* other routines. Can be called multiple times (by separate components,
* normally) but each call must be paired with a corresponding call to
* drutil_exit().
*
* \return whether successful.
*/
bool
drutil_init(void);
DR_EXPORT
/**
* Cleans up the drutil extension.
*/
void
drutil_exit(void);
/***************************************************************************
* MEMORY TRACING
*/
DR_EXPORT
/**
* Inserts instructions prior to \p where in \p bb that determine and
* store the memory address referred to by \p memref into the register
* \p dst. May clobber the register \p scratch. Supports far memory
* references. For far memory references via DS and ES, we assume that
* the segment base is 0.
*
* All registers used in \p memref must hold their original
* application values in order for the proper address to be computed
* into \p dst. The \p dst register may overlap with the registers
* used in \p memref. On ARM, \p scratch must be different from those used
* in \p memref (as well as from \p dst).
* On x86, \p scratch will not be used unless \p memref is a far reference
* that either uses \p dst or is a base-disp with both a base and an index,
* or \p memref is a reference in the #OP_xlat instruction.
*
* To obtain each memory address referenced in a single-instruction
* string loop, use drutil_expand_rep_string() to transform such loops
* into regular loops containing (non-loop) string instructions.
*
* \return whether successful.
*/
bool
drutil_insert_get_mem_addr(void *drcontext, instrlist_t *bb, instr_t *where,
opnd_t memref, reg_id_t dst, reg_id_t scratch);
DR_EXPORT
/**
* Identical to drutil_insert_get_mem_addr() except it returns in the optional
* OUT parameter \p scratch_used whether or not \p scratch was written to.
*/
bool
drutil_insert_get_mem_addr_ex(void *drcontext, instrlist_t *bb, instr_t *where,
opnd_t memref, reg_id_t dst, reg_id_t scratch,
DR_PARAM_OUT bool *scratch_used);
DR_EXPORT
/**
* Returns the size of the memory reference \p memref in bytes.
* To handle OP_enter, requires the containing instruction \p inst
* to be passed in.
* For single-instruction string loops, returns the size referenced
* by each iteration.
*
* If the instruction is part of the xsave family of instructions, this
* returns an incomplete computation of the xsave instruction's written
* xsave area's size. Specifically, it
*
* - Ignores the user state mask components set in edx:eax, because they are
* dynamic values. The real output size of xsave depends on the instruction's
* user state mask AND the user state mask as supported by the CPU based on
* the XCR0 control register.
* - Ignores supervisor state component PT
* (enabled/disabled by user state component mask bit 8).
* - Ignores the user state component PKRU state
* (enabled/disabled by user state component mask bit 9).
* - Ignores the xsaveopt flavor of xsave.
* - Ignores the xsavec flavor of xsave (compacted format).
*
* It computes the expected size for the standard format of the x87 user state
* component (enabled/disabled by user state component mask bit 0), the SSE user
* state component (bit 1), the AVX user state component (bit 2), the MPX user
* state components (bit 2 and 3) and the AVX-512 user state component (bit 7).
*/
uint
drutil_opnd_mem_size_in_bytes(opnd_t memref, instr_t *inst);
DR_EXPORT
/**
* Expands single-instruction string loops (those using the \p rep or
* \p repne prefixes) into regular loops to simplify memory usage
* analysis. This is accomplished by arranging for each
* single-instruction string loop to occupy a basic block by itself
* (by truncating the prior block before the loop, and truncating
* instructions after the loop) and then exanding it into a
* multi-instruction loop.
*
* Clients applying this expansion are encouraged to use emulation-aware
* instrumentation via drmgr_orig_app_instr_for_fetch() and
* drmgr_orig_app_instr_for_operands() in order to observe the original
* string loop opcode with the expanded memory operands.
*
* WARNING: The added multi-instruction loop contains several
* control-transfer instructions and is not straight-line code, which
* can complicate subsequent analysis routines.
*
* WARNING: The added instructions have translations that are in the
* middle of the original string loop instruction. This is to prevent
* passes that match exact addresses from having multiple hits and
* doing something like inserting 6 clean calls.
*
* WARNING: The added instructions include a jecxz instruction which
* will not be transformed into a 32-bit-reach instruction: thus,
* excessive added instrumentation may result in a reachability problem.
*
* The client must use the \p drmgr Extension to order its
* instrumentation in order to use this function. This function must
* be called from the application-to-application ("app2app") stage
* (see drmgr_register_bb_app2app_event()).
*
* This transformation is deterministic, so the caller can return
* DR_EMIT_DEFAULT from its event.
*
* \return whether successful.
*/
bool
drutil_expand_rep_string(void *drcontext, instrlist_t *bb);
DR_EXPORT
/**
* Identical to drutil_expand_rep_string() but returns additional information.
*
* @param[in] drcontext The opaque context
* @param[in] bb Instruction list passed to the app2app event
* @param[out] expanded Whether any expansion occurred
* @param[out] stringop The string instruction in the expanded loop
*
* \return whether successful.
*/
bool
drutil_expand_rep_string_ex(void *drcontext, instrlist_t *bb, DR_PARAM_OUT bool *expanded,
DR_PARAM_OUT instr_t **stringop);
DR_EXPORT
/**
* Returns whether the given instr is a stringop loop.
*
* @param[in] inst The instr to inspect.
*
* \return whether given instr is a stringop loop.
*/
bool
drutil_instr_is_stringop_loop(instr_t *inst);
/**@}*/ /* end doxygen group */
#ifdef __cplusplus
}
#endif
#endif /* _DRUTIL_H_ */