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