blob: 1fafa2185344644d7b2bfbdc43224bb6bd21bf1e [file] [log] [blame]
/* **********************************************************
* Copyright (c) 2011-2014 Google, Inc. All rights reserved.
* Copyright (c) 2000-2010 VMware, 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.
*/
/* Copyright (c) 2003-2007 Determina Corp. */
/* Copyright (c) 2001-2003 Massachusetts Institute of Technology */
/* Copyright (c) 2000-2001 Hewlett-Packard Company */
/* The machine-specific IR consists of instruction lists, instructions,
* operands, and opcodes. You can find related declarations and interface
* functions in corresponding headers.
*/
/* file "instr.h" -- instr_t specific definitions and utilities */
#ifndef _INSTR_H_
#define _INSTR_H_ 1
#include "opcode.h"
#include "opnd.h"
/* to avoid duplicating code we use our own exported macros */
#define DR_FAST_IR 1
/* drpreinject.dll doesn't link in instr_shared.c so we can't include our inline
* functions. We want to use our inline functions for the standalone decoder
* and everything else, so we single out drpreinject.
*/
#ifdef RC_IS_PRELOAD
# undef DR_FAST_IR
#endif
/* can't include decode.h, it includes us, just declare struct */
struct instr_info_t;
/* DR_API EXPORT TOFILE dr_ir_opcodes.h */
/* DR_API EXPORT BEGIN */
#ifdef API_EXPORT_ONLY
#ifdef X86
# include "dr_ir_opcodes_x86.h"
#elif defined(ARM)
# include "dr_ir_opcodes_arm.h"
#endif
#endif
/* DR_API EXPORT END */
/* If INSTR_INLINE is already defined, that means we've been included by
* instr_shared.c, which wants to use C99 extern inline. Otherwise, DR_FAST_IR
* determines whether our instr routines are inlined.
*/
/* Inlining macro controls. */
#ifndef INSTR_INLINE
# ifdef DR_FAST_IR
# define INSTR_INLINE inline
# else
# define INSTR_INLINE
# endif
#endif
/*************************
*** instr_t ***
*************************/
/* instr_t structure
* An instruction represented by instr_t can be in a number of states,
* depending on whether it points to raw bits that are valid,
* whether its operand and opcode fields are up to date, and whether
* its eflags field is up to date.
* Invariant: if opcode == OP_UNDECODED, raw bits should be valid.
* if opcode == OP_INVALID, raw bits may point to real bits,
* but they are not a valid instruction stream.
*
* CORRESPONDENCE WITH CGO LEVELS
* Level 0 = raw bits valid, !opcode_valid, decode_sizeof(instr) != instr->len
* opcode_valid is equivalent to opcode != OP_INVALID && opcode != OP_UNDECODED
* Level 1 = raw bits valid, !opcode_valid, decode_sizeof(instr) == instr->len
* Level 2 = raw bits valid, opcode_valid, !operands_valid
* (eflags info is auto-derived on demand so not an issue)
* Level 3 = raw bits valid, operands valid
* (we assume that if operands_valid then opcode_valid)
* Level 4 = !raw bits valid, operands valid
*
* Independent of these is whether its raw bits were allocated for
* the instr or not.
*/
/* DR_API EXPORT TOFILE dr_ir_instr.h */
/* For inlining, we need to expose some of these flags. We bracket the ones we
* want in export begin/end. AVOID_API_EXPORT does not work because there are
* nested ifdefs.
*/
/* DR_API EXPORT BEGIN */
#ifdef DR_FAST_IR
/* flags */
enum {
/* DR_API EXPORT END */
/* these first flags are shared with the LINK_ flags and are
* used to pass on info to link stubs
*/
/* used to determine type of indirect branch for exits */
INSTR_DIRECT_EXIT = LINK_DIRECT,
INSTR_INDIRECT_EXIT = LINK_INDIRECT,
INSTR_RETURN_EXIT = LINK_RETURN,
/* JMP|CALL marks an indirect jmp preceded by a call (== a PLT-style ind call)
* so use EXIT_IS_{JMP,CALL} rather than these raw bits
*/
INSTR_CALL_EXIT = LINK_CALL,
INSTR_JMP_EXIT = LINK_JMP,
INSTR_IND_JMP_PLT_EXIT = (INSTR_JMP_EXIT | INSTR_CALL_EXIT),
INSTR_FAR_EXIT = LINK_FAR,
INSTR_BRANCH_SPECIAL_EXIT = LINK_SPECIAL_EXIT,
#ifdef UNSUPPORTED_API
INSTR_BRANCH_TARGETS_PREFIX = LINK_TARGET_PREFIX,
#endif
#ifdef X64
/* PR 257963: since we don't store targets of ind branches, we need a flag
* so we know whether this is a trace cmp exit, which has its own ibl entry
*/
INSTR_TRACE_CMP_EXIT = LINK_TRACE_CMP,
#endif
#ifdef WINDOWS
INSTR_CALLBACK_RETURN = LINK_CALLBACK_RETURN,
#else
INSTR_NI_SYSCALL_INT = LINK_NI_SYSCALL_INT,
#endif
INSTR_NI_SYSCALL = LINK_NI_SYSCALL,
INSTR_NI_SYSCALL_ALL = LINK_NI_SYSCALL_ALL,
/* meta-flag */
EXIT_CTI_TYPES = (INSTR_DIRECT_EXIT | INSTR_INDIRECT_EXIT |
INSTR_RETURN_EXIT | INSTR_CALL_EXIT |
INSTR_JMP_EXIT |
INSTR_FAR_EXIT |
INSTR_BRANCH_SPECIAL_EXIT |
#ifdef UNSUPPORTED_API
INSTR_BRANCH_TARGETS_PREFIX |
#endif
#ifdef X64
INSTR_TRACE_CMP_EXIT |
#endif
#ifdef WINDOWS
INSTR_CALLBACK_RETURN |
#else
INSTR_NI_SYSCALL_INT |
#endif
INSTR_NI_SYSCALL),
/* instr_t-internal flags (not shared with LINK_) */
INSTR_OPERANDS_VALID = 0x00010000,
/* meta-flag */
INSTR_FIRST_NON_LINK_SHARED_FLAG = INSTR_OPERANDS_VALID,
INSTR_EFLAGS_VALID = 0x00020000,
INSTR_EFLAGS_6_VALID = 0x00040000,
INSTR_RAW_BITS_VALID = 0x00080000,
INSTR_RAW_BITS_ALLOCATED = 0x00100000,
/* DR_API EXPORT BEGIN */
INSTR_DO_NOT_MANGLE = 0x00200000,
/* DR_API EXPORT END */
INSTR_HAS_CUSTOM_STUB = 0x00400000,
/* used to indicate that an indirect call can be treated as a direct call */
INSTR_IND_CALL_DIRECT = 0x00800000,
#ifdef WINDOWS
/* used to indicate that a syscall should be executed via shared syscall */
INSTR_SHARED_SYSCALL = 0x01000000,
#endif
#ifdef CLIENT_INTERFACE
INSTR_CLOBBER_RETADDR = 0x02000000,
#endif
/* Signifies that this instruction may need to be hot patched and should
* therefore not cross a cache line. It is not necessary to set this for
* exit cti's or linkstubs since it is mainly intended for clients etc.
* Handling of this flag is not yet implemented */
INSTR_HOT_PATCHABLE = 0x04000000,
#ifdef DEBUG
/* case 9151: only report invalid instrs for normal code decoding */
INSTR_IGNORE_INVALID = 0x08000000,
#endif
/* Currently used for frozen coarse fragments with final jmps and
* jmps to ib stubs that are elided: we need the jmp instr there
* to build the linkstub_t but we do not want to emit it. */
INSTR_DO_NOT_EMIT = 0x10000000,
/* PR 251479: re-relativization support: is instr->rip_rel_pos valid? */
INSTR_RIP_REL_VALID = 0x20000000,
#ifdef X86
/* PR 278329: each instr stores its own mode */
INSTR_X86_MODE = 0x40000000,
#elif defined(ARM)
/* We assume we don't need to distinguish A64 from A32 as you cannot swap
* between them in user mode. Thus we only need one flag.
* XXX: we might want more power for drdecode, though the global isa_mode
* should be sufficient there.
*/
INSTR_THUMB_MODE = 0x40000000,
#endif
/* PR 267260: distinguish our own mangling from client-added instrs */
INSTR_OUR_MANGLING = 0x80000000,
/* DR_API EXPORT BEGIN */
};
#endif /* DR_FAST_IR */
/** Triggers used for conditionally executed instructions. */
typedef enum _dr_pred_type_t {
DR_PRED_NONE, /**< No predicate is present. */
#ifdef X86
DR_PRED_O, /**< x86 condition: overflow (OF=1). */
DR_PRED_NO, /**< x86 condition: no overflow (OF=0). */
DR_PRED_B, /**< x86 condition: below (CF=0). */
DR_PRED_NB, /**< x86 condition: not below (CF=1). */
DR_PRED_Z, /**< x86 condition: zero (ZF=1). */
DR_PRED_NZ, /**< x86 condition: not zero (ZF=0). */
DR_PRED_BE, /**< x86 condition: below or equal (CF=1 or ZF=1). */
DR_PRED_NBE, /**< x86 condition: not below or equal (CF=0 and ZF=0). */
DR_PRED_S, /**< x86 condition: sign (SF=1). */
DR_PRED_NS, /**< x86 condition: not sign (SF=0). */
DR_PRED_P, /**< x86 condition: parity (PF=1). */
DR_PRED_NP, /**< x86 condition: not parity (PF=0). */
DR_PRED_L, /**< x86 condition: less (SF != OF). */
DR_PRED_NL, /**< x86 condition: not less (SF=OF). */
DR_PRED_LE, /**< x86 condition: less or equal (ZF=1 or SF != OF). */
DR_PRED_NLE, /**< x86 condition: not less or equal (ZF=0 and SF=OF). */
/**
* x86 condition: special opcode-specific condition that depends on the
* values of the source operands. Thus, unlike all of the other conditions,
* the source operands will be accessed even if the condition then fails
* and the destinations are not touched. Any written eflags are
* unconditionally written, unlike regular destination operands.
*/
DR_PRED_COMPLEX,
#elif defined(ARM)
DR_PRED_EQ, /**< ARM condition: 0000 Equal (Z == 1) */
DR_PRED_NE, /**< ARM condition: 0001 Not equal (Z == 0) */
DR_PRED_CS, /**< ARM condition: 0010 Carry set (C == 1) */
DR_PRED_CC, /**< ARM condition: 0011 Carry clear (C == 0) */
DR_PRED_MI, /**< ARM condition: 0100 Minus, negative (N == 1) */
DR_PRED_PL, /**< ARM condition: 0101 Plus, positive or zero (N == 0) */
DR_PRED_VS, /**< ARM condition: 0110 Overflow (V == 1) */
DR_PRED_VC, /**< ARM condition: 0111 No overflow (V == 0) */
DR_PRED_HI, /**< ARM condition: 1000 Unsigned higher (C == 1 and Z == 0)*/
DR_PRED_LS, /**< ARM condition: 1001 Unsigned lower or same (C == 0 or Z == 1) */
DR_PRED_GE, /**< ARM condition: 1010 Signed >= (N == V) */
DR_PRED_LT, /**< ARM condition: 1011 Signed less than (N != V) */
DR_PRED_GT, /**< ARM condition: 1100 Signed greater than (Z == 0 and N == V)*/
DR_PRED_LE, /**< ARM condition: 1101 Signed <= (Z == 1 or N != V) */
DR_PRED_AL, /**< ARM condition: 1110 Always (unconditional) */
DR_PRED_OP, /**< ARM condition: 1111 Part of opcode */
#endif
} dr_pred_type_t;
/* DR_API EXPORT END */
/* These aren't composable, so we store them in as few bits as possible.
* The top 5 prefix bits hold the value (x86 needs 17 values).
* XXX: if we need more space we could compress the x86 values: they're
* all pos/neg pairs so we could store the pos/neg bit just once.
* XXX: if we want a slightly faster predication check we could take
* a dedicated PREFIX_PREDICATED bit.
*/
#define PREFIX_PRED_BITS 5
#define PREFIX_PRED_BITPOS (32 - PREFIX_PRED_BITS)
#define PREFIX_PRED_MASK \
(((1 << PREFIX_PRED_BITS)-1) << PREFIX_PRED_BITPOS) /*0xf8000000 */
/* DR_API EXPORT BEGIN */
/**
* Data slots available in a label (instr_create_label()) instruction
* for storing client-controlled data. Accessible via
* instr_get_label_data_area().
*/
typedef struct _dr_instr_label_data_t {
ptr_uint_t data[4]; /**< Generic fields for storing user-controlled data */
} dr_instr_label_data_t;
/**
* Bitmask values passed as flags to routines that ask about whether operands
* and condition codes are read or written. These flags determine how to treat
* conditionally executed instructions.
*/
typedef enum _dr_opnd_query_flags_t {
/**
* By default, routines that take in these flags will only consider
* destinations that are always written. Thus, all destinations are skipped
* for an instruction that is predicated and executes conditionally (see
* instr_is_predicated()). If this flag is set, a conditionally executed
* instruction's destinations are included just like any other
* instruction's.
*/
DR_QUERY_INCLUDE_COND_DSTS = 0x01,
/**
* By default, routines that take in these flags will only consider sources
* that are always read. Thus, all sources are skipped for an instruction
* that is predicated and executes conditionally (see
* instr_is_predicated()), except for predication conditions that involve
* the source operand values. If this flag is set, a conditionally executed
* instruction's sources are included just like any other instruction's.
*/
DR_QUERY_INCLUDE_COND_SRCS = 0x02,
/** The default value that typical liveness analysis would want to use. */
DR_QUERY_DEFAULT = DR_QUERY_INCLUDE_COND_SRCS,
/** Includes all operands whether conditional or not. */
DR_QUERY_INCLUDE_ALL = (DR_QUERY_INCLUDE_COND_DSTS|DR_QUERY_INCLUDE_COND_SRCS),
} dr_opnd_query_flags_t;
#ifdef DR_FAST_IR
/* DR_API EXPORT END */
/* FIXME: could shrink prefixes, eflags, opcode, and flags fields
* this struct isn't a memory bottleneck though b/c it isn't persistent
*/
/* DR_API EXPORT BEGIN */
/**
* instr_t type exposed for optional "fast IR" access. Note that DynamoRIO
* reserves the right to change this structure across releases and does
* not guarantee binary or source compatibility when this structure's fields
* are directly accessed. If the instr_ accessor routines are used, DynamoRIO does
* guarantee source compatibility, but not binary compatibility. If binary
* compatibility is desired, do not use the fast IR feature.
*/
struct _instr_t {
/* flags contains the constants defined above */
uint flags;
/* raw bits of length length are pointed to by the bytes field */
byte *bytes;
uint length;
/* translation target for this instr */
app_pc translation;
uint opcode;
#ifdef X64
/* PR 251479: offset into instr's raw bytes of rip-relative 4-byte displacement */
byte rip_rel_pos;
#endif
/* we dynamically allocate dst and src arrays b/c x86 instrs can have
* up to 8 of each of them, but most have <=2 dsts and <=3 srcs, and we
* use this struct for un-decoded instrs too
*/
byte num_dsts;
byte num_srcs;
union {
struct {
/* for efficiency everyone has a 1st src opnd, since we often just
* decode jumps, which all have a single source (==target)
* yes this is an extra 10 bytes, but the whole struct is still < 64 bytes!
*/
opnd_t src0;
opnd_t *srcs; /* this array has 2nd src and beyond */
opnd_t *dsts;
};
dr_instr_label_data_t label_data;
};
uint prefixes; /* data size, addr size, or lock prefix info */
uint eflags; /* contains EFLAGS_ bits, but amount of info varies
* depending on how instr was decoded/built */
/* this field is for the use of passes as an annotation.
* it is also used to hold the offset of an instruction when encoding
* pc-relative instructions. A small range of values is reserved for internal use
* by DR and cannot be used by clients; see DR_NOTE_FIRST_RESERVED in globals.h.
*/
void *note;
/* fields for building instructions into instruction lists */
instr_t *prev;
instr_t *next;
}; /* instr_t */
#endif /* DR_FAST_IR */
/****************************************************************************
* INSTR ROUTINES
*/
/**
* @file dr_ir_instr.h
* @brief Functions to create and manipulate instructions.
*/
/* DR_API EXPORT END */
DR_API
/**
* Returns an initialized instr_t allocated on the thread-local heap.
* Sets the x86/x64 mode of the returned instr_t to the mode of dcontext.
*/
/* For -x86_to_x64, sets the mode of the instr to the code cache mode instead of
the app mode. */
instr_t*
instr_create(dcontext_t *dcontext);
DR_API
/** Initializes \p instr.
* Sets the x86/x64 mode of \p instr to the mode of dcontext.
*/
void
instr_init(dcontext_t *dcontext, instr_t *instr);
DR_API
/**
* Deallocates all memory that was allocated by \p instr. This
* includes raw bytes allocated by instr_allocate_raw_bits() and
* operands allocated by instr_set_num_opnds(). Does not deallocate
* the storage for \p instr itself.
*/
void
instr_free(dcontext_t *dcontext, instr_t *instr);
DR_API
/**
* Performs both instr_free() and instr_init().
* \p instr must have been initialized.
*/
void
instr_reset(dcontext_t *dcontext, instr_t *instr);
DR_API
/**
* Frees all dynamically allocated storage that was allocated by \p instr,
* except for allocated bits.
* Also zeroes out \p instr's fields, except for raw bit fields,
* whether \p instr is instr_is_meta(), and the x86 mode of \p instr.
* \p instr must have been initialized.
*/
void
instr_reuse(dcontext_t *dcontext, instr_t *instr);
DR_API
/**
* Performs instr_free() and then deallocates the thread-local heap
* storage for \p instr.
*/
void
instr_destroy(dcontext_t *dcontext, instr_t *instr);
DR_API
INSTR_INLINE
/**
* Returns the next instr_t in the instrlist_t that contains \p instr.
* \note The next pointer for an instr_t is inside the instr_t data
* structure itself, making it impossible to have on instr_t in
* two different InstrLists (but removing the need for an extra data
* structure for each element of the instrlist_t).
*/
instr_t*
instr_get_next(instr_t *instr);
DR_API
INSTR_INLINE
/**
* Returns the next application (non-meta) instruction in the instruction list
* that contains \p instr.
*
* \note As opposed to instr_get_next(), this routine skips all meta
* instructions inserted by either DynamoRIO or its clients.
*
* \note We do recommend using this routine during the phase of application
* code analysis, as any meta instructions present are guaranteed to be ok
* to skip.
* However, the caution should be exercised if using this routine after any
* instrumentation insertion has already happened, as instrumentation might
* affect register usage or other factors being analyzed.
*/
instr_t *
instr_get_next_app(instr_t *instr);
DR_API
INSTR_INLINE
/** Returns the previous instr_t in the instrlist_t that contains \p instr. */
instr_t*
instr_get_prev(instr_t *instr);
DR_API
INSTR_INLINE
/** Sets the next field of \p instr to point to \p next. */
void
instr_set_next(instr_t *instr, instr_t *next);
DR_API
INSTR_INLINE
/** Sets the prev field of \p instr to point to \p prev. */
void
instr_set_prev(instr_t *instr, instr_t *prev);
DR_API
INSTR_INLINE
/**
* Gets the value of the user-controlled note field in \p instr.
* \note Important: is also used when emitting for targets that are other
* instructions. Thus it will be overwritten when calling instrlist_encode()
* or instrlist_encode_to_copy() with \p has_instr_jmp_targets set to true.
* \note The note field is copied (shallowly) by instr_clone().
*/
void *
instr_get_note(instr_t *instr);
DR_API
INSTR_INLINE
/** Sets the user-controlled note field in \p instr to \p value. */
void
instr_set_note(instr_t *instr, void *value);
DR_API
/** Return the taken target pc of the (direct branch) instruction. */
app_pc
instr_get_branch_target_pc(instr_t *cti_instr);
DR_API
/** Set the taken target pc of the (direct branch) instruction. */
void
instr_set_branch_target_pc(instr_t *cti_instr, app_pc pc);
DR_API
/**
* Returns true iff \p instr is a conditional branch, unconditional branch,
* or indirect branch with a program address target (NOT an instr_t address target)
* and \p instr is ok to mangle.
*/
#ifdef UNSUPPORTED_API
/**
* This routine does NOT try to decode an opcode in a Level 1 or Level
* 0 routine, and can thus be called on Level 0 routines.
*/
#endif
bool
instr_is_exit_cti(instr_t *instr);
DR_API
/** Return true iff \p instr's opcode is OP_int, OP_into, or OP_int3. */
bool
instr_is_interrupt(instr_t *instr);
#ifdef UNSUPPORTED_API
DR_API
/**
* Returns true iff \p instr has been marked as targeting the prefix of its
* target fragment.
*
* Some code manipulations need to store a target address in a
* register and then jump there, but need the register to be restored
* as well. DR provides a single-instruction prefix that is
* placed on all fragments (basic blocks as well as traces) that
* restores ecx. It is on traces for internal DR use. To have
* it added to basic blocks as well, call
* dr_add_prefixes_to_basic_blocks() during initialization.
*/
bool
instr_branch_targets_prefix(instr_t *instr);
DR_API
/**
* If \p val is true, indicates that \p instr's target fragment should be
* entered through its prefix, which restores ecx.
* If \p val is false, indicates that \p instr should target the normal entry
* point and not the prefix.
*
* Some code manipulations need to store a target address in a
* register and then jump there, but need the register to be restored
* as well. DR provides a single-instruction prefix that is
* placed on all fragments (basic blocks as well as traces) that
* restores ecx. It is on traces for internal DR use. To have
* it added to basic blocks as well, call
* dr_add_prefixes_to_basic_blocks() during initialization.
*/
void
instr_branch_set_prefix_target(instr_t *instr, bool val);
#endif /* UNSUPPORTED_API */
/* Returns true iff \p instr has been marked as a special fragment
* exit cti.
*/
bool
instr_branch_special_exit(instr_t *instr);
/* If \p val is true, indicates that \p instr is a special exit cti.
* If \p val is false, indicates otherwise.
*/
void
instr_branch_set_special_exit(instr_t *instr, bool val);
DR_API
INSTR_INLINE
/**
* Return true iff \p instr is an application (non-meta) instruction
* (see instr_set_app() for more information).
*/
bool
instr_is_app(instr_t *instr);
DR_API
/**
* Sets \p instr as an application (non-meta) instruction.
* An application instruction might be mangled by DR if necessary,
* e.g., to create an exit stub for a branch instruction.
* All application instructions that are added to basic blocks or
* traces should have their translation fields set (via
* #instr_set_translation()).
*/
void
instr_set_app(instr_t *instr);
DR_API
INSTR_INLINE
/**
* Return true iff \p instr is a meta instruction
* (see instr_set_meta() for more information).
*/
bool
instr_is_meta(instr_t *instr);
DR_API
/**
* Sets \p instr as a meta instruction.
* A meta instruction will not be mangled by DR in any way, which is necessary
* to have DR not create an exit stub for a branch instruction.
* Meta instructions should not fault (unless such faults are handled
* by the client) and are not considered
* application instructions but rather added instrumentation code (see
* #dr_register_bb_event() for further information).
*/
void
instr_set_meta(instr_t *instr);
DR_API
INSTR_INLINE
/**
* Return true iff \p instr is not a meta-instruction
* (see instr_set_app() for more information).
*
* \deprecated instr_is_app()/instr_is_meta() should be used instead.
*/
bool
instr_ok_to_mangle(instr_t *instr);
DR_API
/**
* Sets \p instr to "ok to mangle" if \p val is true and "not ok to
* mangle" if \p val is false.
*
* \deprecated instr_set_app()/instr_set_meta() should be used instead.
*/
void
instr_set_ok_to_mangle(instr_t *instr, bool val);
DR_API
/**
* A convenience routine that calls both
* #instr_set_meta (instr) and
* #instr_set_translation (instr, NULL).
*/
void
instr_set_meta_no_translation(instr_t *instr);
DR_API
#ifdef AVOID_API_EXPORT
/* This is hot internally, but unlikely to be used by clients. */
INSTR_INLINE
#endif
/** Return true iff \p instr is to be emitted into the cache. */
bool
instr_ok_to_emit(instr_t *instr);
DR_API
/**
* Set \p instr to "ok to emit" if \p val is true and "not ok to emit"
* if \p val is false. An instruction that should not be emitted is
* treated normally by DR for purposes of exits but is not placed into
* the cache. It is used for final jumps that are to be elided.
*/
void
instr_set_ok_to_emit(instr_t *instr, bool val);
#ifdef CUSTOM_EXIT_STUBS
DR_API
/**
* If \p instr is not an exit cti, does nothing.
* If \p instr is an exit cti, sets \p stub to be custom exit stub code
* that will be inserted in the exit stub prior to the normal exit
* stub code. If \p instr already has custom exit stub code, that
* existing instrlist_t is cleared and destroyed (using current thread's
* context). (If \p stub is NULL, any existing stub code is NOT destroyed.)
* The creator of the instrlist_t containing \p instr is
* responsible for destroying stub.
* \note Custom exit stubs containing control transfer instructions to
* other instructions inside a fragment besides the custom stub itself
* are not fully supported in that they will not be decoded from the
* cache properly as having instr_t targets.
*/
void
instr_set_exit_stub_code(instr_t *instr, instrlist_t *stub);
DR_API
/**
* Returns the custom exit stub code instruction list that has been
* set for this instruction. If none exists, returns NULL.
*/
instrlist_t *
instr_exit_stub_code(instr_t *instr);
#endif
DR_API
/**
* Returns the length of \p instr.
* As a side effect, if instr_is_app(instr) and \p instr's raw bits
* are invalid, encodes \p instr into bytes allocated with
* instr_allocate_raw_bits(), after which instr is marked as having
* valid raw bits.
*/
int
instr_length(dcontext_t *dcontext, instr_t *instr);
/* not exported */
void instr_shift_raw_bits(instr_t *instr, ssize_t offs);
int instr_exit_branch_type(instr_t *instr);
void instr_exit_branch_set_type(instr_t *instr, uint type);
DR_API
/** Returns number of bytes of heap used by \p instr. */
int
instr_mem_usage(instr_t *instr);
DR_API
/**
* Returns a copy of \p orig with separately allocated memory for
* operands and raw bytes if they were present in \p orig.
* Only a shallow copy of the \p note field is made.
*/
instr_t *
instr_clone(dcontext_t *dcontext, instr_t *orig);
DR_API
/**
* Convenience routine: calls
* - instr_create(dcontext)
* - instr_set_opcode(opcode)
* - instr_set_num_opnds(dcontext, instr, num_dsts, num_srcs)
*
* and returns the resulting instr_t.
*/
instr_t *
instr_build(dcontext_t *dcontext, int opcode, int num_dsts, int num_srcs);
DR_API
/**
* Convenience routine: calls
* - instr_create(dcontext)
* - instr_set_opcode(instr, opcode)
* - instr_allocate_raw_bits(dcontext, instr, num_bytes)
*
* and returns the resulting instr_t.
*/
instr_t *
instr_build_bits(dcontext_t *dcontext, int opcode, uint num_bytes);
DR_API
/**
* Returns true iff \p instr's opcode is NOT OP_INVALID.
* Not to be confused with an invalid opcode, which can be OP_INVALID or
* OP_UNDECODED. OP_INVALID means an instruction with no valid fields:
* raw bits (may exist but do not correspond to a valid instr), opcode,
* eflags, or operands. It could be an uninitialized
* instruction or the result of decoding an invalid sequence of bytes.
*/
bool
instr_valid(instr_t *instr);
DR_API
/** Get the original application PC of \p instr if it exists. */
app_pc
instr_get_app_pc(instr_t *instr);
DR_API
/** Returns \p instr's opcode (an OP_ constant). */
int
instr_get_opcode(instr_t *instr);
DR_API
/** Assumes \p opcode is an OP_ constant and sets it to be instr's opcode. */
void
instr_set_opcode(instr_t *instr, int opcode);
const struct instr_info_t *
instr_get_instr_info(instr_t *instr);
const struct instr_info_t *
get_instr_info(int opcode);
DR_API
INSTR_INLINE
/**
* Returns the number of source operands of \p instr.
*
* \note Addressing registers used in destination memory references
* (i.e., base, index, or segment registers) are not separately listed
* as source operands.
*/
int
instr_num_srcs(instr_t *instr);
DR_API
INSTR_INLINE
/**
* Returns the number of destination operands of \p instr.
*/
int
instr_num_dsts(instr_t *instr);
DR_API
/**
* Assumes that \p instr has been initialized but does not have any
* operands yet. Allocates storage for \p num_srcs source operands
* and \p num_dsts destination operands.
*/
void
instr_set_num_opnds(dcontext_t *dcontext, instr_t *instr, int num_dsts, int num_srcs);
DR_API
/**
* Returns \p instr's source operand at position \p pos (0-based).
*/
opnd_t
instr_get_src(instr_t *instr, uint pos);
DR_API
/**
* Returns \p instr's destination operand at position \p pos (0-based).
*/
opnd_t
instr_get_dst(instr_t *instr, uint pos);
DR_API
/**
* Sets \p instr's source operand at position \p pos to be \p opnd.
* Also calls instr_set_raw_bits_valid(\p instr, false) and
* instr_set_operands_valid(\p instr, true).
*/
void
instr_set_src(instr_t *instr, uint pos, opnd_t opnd);
DR_API
/**
* Sets \p instr's destination operand at position \p pos to be \p opnd.
* Also calls instr_set_raw_bits_valid(\p instr, false) and
* instr_set_operands_valid(\p instr, true).
*/
void
instr_set_dst(instr_t *instr, uint pos, opnd_t opnd);
DR_API
/**
* Assumes that \p cti_instr is a control transfer instruction
* Returns the first source operand of \p cti_instr (its target).
*/
opnd_t
instr_get_target(instr_t *cti_instr);
DR_API
/**
* Assumes that \p cti_instr is a control transfer instruction.
* Sets the first source operand of \p cti_instr to be \p target.
* Also calls instr_set_raw_bits_valid(\p instr, false) and
* instr_set_operands_valid(\p instr, true).
*/
void
instr_set_target(instr_t *cti_instr, opnd_t target);
#ifdef AVOID_API_EXPORT
INSTR_INLINE /* hot internally */
#endif
DR_API
/** Returns true iff \p instr's operands are up to date. */
bool
instr_operands_valid(instr_t *instr);
DR_API
/** Sets \p instr's operands to be valid if \p valid is true, invalid otherwise. */
void
instr_set_operands_valid(instr_t *instr, bool valid);
DR_API
/**
* Returns true iff \p instr's opcode is valid.
* If the opcode is ever set to other than OP_INVALID or OP_UNDECODED it is assumed
* to be valid. However, calling instr_get_opcode() will attempt to
* decode a valid opcode, hence the purpose of this routine.
*/
bool
instr_opcode_valid(instr_t *instr);
/******************************************************************
* Eflags validity is not exported! It's hidden. Calling get_eflags or
* get_arith_flags will make them valid if they're not.
*/
bool
instr_arith_flags_valid(instr_t *instr);
/* Sets instr's arithmetic flags (the 6 bottom eflags) to be valid if
* valid is true, invalid otherwise. */
void
instr_set_arith_flags_valid(instr_t *instr, bool valid);
/* Returns true iff instr's eflags are up to date. */
bool
instr_eflags_valid(instr_t *instr);
/* Sets instr's eflags to be valid if valid is true, invalid otherwise. */
void
instr_set_eflags_valid(instr_t *instr, bool valid);
uint
instr_eflags_conditionally(uint full_eflags, dr_pred_type_t pred,
dr_opnd_query_flags_t flags);
DR_API
/**
* Returns \p instr's eflags use as EFLAGS_ constants or'ed together.
* Which eflags are considered to be accessed for conditionally executed
* instructions are controlled by \p flags.
*/
uint
instr_get_eflags(instr_t *instr, dr_opnd_query_flags_t flags);
DR_API
/**
* Returns the eflags usage of instructions with opcode \p opcode,
* as EFLAGS_ constants or'ed together.
* If \p opcode is predicated (see instr_is_predicated()), the eflags may not
* always be accessed or written.
*/
uint
instr_get_opcode_eflags(int opcode);
DR_API
/**
* Returns \p instr's arithmetic flags (bottom 6 eflags) use
* as EFLAGS_ constants or'ed together.
* If \p instr's eflags behavior has not been calculated yet or is
* invalid, the entire eflags use is calculated and returned (not
* just the arithmetic flags).
* Which eflags are considered to be accessed for conditionally executed
* instructions are controlled by \p flags.
*/
uint
instr_get_arith_flags(instr_t *instr, dr_opnd_query_flags_t flags);
/*
******************************************************************/
DR_API
/**
* Assumes that \p instr does not currently have any raw bits allocated.
* Sets \p instr's raw bits to be \p length bytes starting at \p addr.
* Does not set the operands invalid.
*/
void
instr_set_raw_bits(instr_t *instr, byte * addr, uint length);
DR_API
/** Sets \p instr's raw bits to be valid if \p valid is true, invalid otherwise. */
void
instr_set_raw_bits_valid(instr_t *instr, bool valid);
#ifdef AVOID_API_EXPORT
INSTR_INLINE /* internal inline */
#endif
DR_API
/** Returns true iff \p instr's raw bits are a valid encoding of instr. */
bool
instr_raw_bits_valid(instr_t *instr);
#ifdef AVOID_API_EXPORT
INSTR_INLINE /* internal inline */
#endif
DR_API
/** Returns true iff \p instr has its own allocated memory for raw bits. */
bool
instr_has_allocated_bits(instr_t *instr);
#ifdef AVOID_API_EXPORT
INSTR_INLINE /* internal inline */
#endif
DR_API
/** Returns true iff \p instr's raw bits are not a valid encoding of \p instr. */
bool
instr_needs_encoding(instr_t *instr);
DR_API
/**
* Return true iff \p instr is not a meta-instruction that can fault
* (see instr_set_meta_may_fault() for more information).
*
* \deprecated Any meta instruction can fault if it has a non-NULL
* translation field and the client fully handles all of its faults,
* so this routine is no longer needed.
*/
bool
instr_is_meta_may_fault(instr_t *instr);
DR_API
/**
* \deprecated Any meta instruction can fault if it has a non-NULL
* translation field and the client fully handles all of its faults,
* so this routine is no longer needed.
*/
void
instr_set_meta_may_fault(instr_t *instr, bool val);
DR_API
/**
* Allocates \p num_bytes of memory for \p instr's raw bits.
* If \p instr currently points to raw bits, the allocated memory is
* initialized with the bytes pointed to.
* \p instr is then set to point to the allocated memory.
*/
void
instr_allocate_raw_bits(dcontext_t *dcontext, instr_t *instr, uint num_bytes);
DR_API
/**
* Sets the translation pointer for \p instr, used to recreate the
* application address corresponding to this instruction. When adding
* or modifying instructions that are to be considered application
* instructions (i.e., non meta-instructions: see #instr_is_app),
* the translation should always be set. Pick
* the application address that if executed will be equivalent to
* restarting \p instr. Currently the translation address must lie
* within the existing bounds of the containing code block.
* Returns the supplied \p instr (for easy chaining). Use
* #instr_get_app_pc to see the current value of the translation.
*/
instr_t *
instr_set_translation(instr_t *instr, app_pc addr);
DR_UNS_API
/**
* If the translation pointer is set for \p instr, returns that
* else returns NULL.
* \note The translation pointer is not automatically set when
* decoding instructions from raw bytes (via decode(), e.g.); it is
* set for instructions in instruction lists generated by DR (see
* dr_register_bb_event()).
*
*/
app_pc
instr_get_translation(instr_t *instr);
DR_API
/**
* Calling this function with \p instr makes it safe to keep the
* instruction around indefinitely when its raw bits point into the
* cache. The function allocates memory local to \p instr to hold a
* copy of the raw bits. If this was not done, the original raw bits
* could be deleted at some point. Making an instruction persistent
* is necessary if you want to keep it beyond returning from the call
* that produced the instruction.
*/
void
instr_make_persistent(dcontext_t *dcontext, instr_t *instr);
DR_API
/**
* Assumes that \p instr's raw bits are valid.
* Returns a pointer to \p instr's raw bits.
* \note A freshly-decoded instruction has valid raw bits that point to the
* address from which it was decoded. However, for instructions presented
* in the basic block or trace events, use instr_get_app_pc() to retrieve
* the corresponding application address, as the raw bits will not be set
* for instructions added after decoding, and may point to a different location
* for insructions that have been modified.
*/
byte *
instr_get_raw_bits(instr_t *instr);
DR_API
/** If \p instr has raw bits allocated, frees them. */
void
instr_free_raw_bits(dcontext_t *dcontext, instr_t *instr);
DR_API
/**
* Assumes that \p instr's raw bits are valid and have > \p pos bytes.
* Returns a pointer to \p instr's raw byte at position \p pos (beginning with 0).
*/
byte
instr_get_raw_byte(instr_t *instr, uint pos);
DR_API
/**
* Assumes that \p instr's raw bits are valid and allocated by \p instr
* and have > \p pos bytes.
* Sets instr's raw byte at position \p pos (beginning with 0) to the value \p byte.
*/
void
instr_set_raw_byte(instr_t *instr, uint pos, byte byte);
DR_API
/**
* Assumes that \p instr's raw bits are valid and allocated by \p instr
* and have >= num_bytes bytes.
* Copies the \p num_bytes beginning at start to \p instr's raw bits.
*/
void
instr_set_raw_bytes(instr_t *instr, byte *start, uint num_bytes);
DR_API
/**
* Assumes that \p instr's raw bits are valid and allocated by \p instr
* and have > pos+3 bytes.
* Sets the 4 bytes beginning at position \p pos (0-based) to the value word.
*/
void
instr_set_raw_word(instr_t *instr, uint pos, uint word);
DR_API
/**
* Assumes that \p instr's raw bits are valid and have > \p pos + 3 bytes.
* Returns the 4 bytes beginning at position \p pos (0-based).
*/
uint
instr_get_raw_word(instr_t *instr, uint pos);
DR_API
/**
* Assumes that \p prefix is a PREFIX_ constant.
* Ors \p instr's prefixes with \p prefix.
* Returns the supplied instr (for easy chaining).
*/
instr_t *
instr_set_prefix_flag(instr_t *instr, uint prefix);
DR_API
/**
* Assumes that \p prefix is a PREFIX_ constant.
* Returns true if \p instr's prefixes contain the flag \p prefix.
*/
bool
instr_get_prefix_flag(instr_t *instr, uint prefix);
/* NOT EXPORTED because we want to limit a client to seeing only the
* handful of PREFIX_ flags we're exporting.
* Assumes that prefix is a group of PREFIX_ constants or-ed together.
* Sets instr's prefixes to be exactly those flags in prefixes.
*/
void
instr_set_prefixes(instr_t *instr, uint prefixes);
/* NOT EXPORTED because we want to limit a client to seeing only the
* handful of PREFIX_ flags we're exporting.
* Returns instr's prefixes as PREFIX_ constants or-ed together.
*/
uint
instr_get_prefixes(instr_t *instr);
DR_API
/**
* Returns whether \p instr is predicated: i.e., whether its operation
* is conditional.
*/
bool
instr_is_predicated(instr_t *instr);
DR_API
/**
* Returns the DR_PRED_ constant for \p instr that describes what its
* conditional execution is dependent on.
*/
dr_pred_type_t
instr_get_predicate(instr_t *instr);
bool
instr_predicate_reads_srcs(dr_pred_type_t pred);
bool
instr_predicate_writes_eflags(dr_pred_type_t pred);
bool
instr_predicate_is_cond(dr_pred_type_t pred);
DR_API
/**
* Sets the predication for \p instr to the given DR_PRED_ constant.
* Returns \p instr if successful, or NULL if unsuccessful.
*/
instr_t *
instr_set_predicate(instr_t *instr, dr_pred_type_t pred);
/* DR_API EXPORT BEGIN */
/** This type holds the return values for instr_predicate_triggered(). */
typedef enum _dr_pred_trigger_t {
/** This instruction is not predicated. */
DR_PRED_TRIGGER_NOPRED,
/** The predicate matches and the instruction will execute. */
DR_PRED_TRIGGER_MATCH,
/** The predicate does not match and the instruction will not execute. */
DR_PRED_TRIGGER_MISMATCH,
/** It is unknown whether the predicate matches. */
DR_PRED_TRIGGER_UNKNOWN,
/** An invalid parameter was passed. */
DR_PRED_TRIGGER_INVALID,
} dr_pred_trigger_t;
/* DR_API EXPORT END */
DR_API
/**
* Given the machine context \p mc, returns whether or not the predicated
* instruction \p instr will execute.
* Currently condition-code predicates are supported and OP_bsf and
* OP_bsr from #DR_PRED_COMPLEX; other instances of #DR_PRED_COMPLEX
* are not supported.
* \p mc->flags must include #DR_MC_CONTROL for condition-code predicates,
* and additionally #DR_MC_INTEGER for OP_bsf and OP_bsr.
*
* \note More complex predicates will be added in the future and they may require
* additional state in \p mc.
*/
dr_pred_trigger_t
instr_predicate_triggered(instr_t *instr, dr_mcontext_t *mc);
/* DR_API EXPORT BEGIN */
#if defined(X86) && defined(X64)
/* DR_API EXPORT END */
DR_API
/**
* Each instruction stores whether it should be interpreted in 32-bit
* (x86) or 64-bit (x64) mode. This routine sets the mode for \p instr.
*
* \note For 64-bit DR builds only.
*
* \deprecated Replaced by instr_set_isa_mode().
*/
void
instr_set_x86_mode(instr_t *instr, bool x86);
DR_API
/**
* Returns true if \p instr is an x86 instruction (32-bit) and false
* if \p instr is an x64 instruction (64-bit).
*
* \note For 64-bit DR builds only.
*
* \deprecated Replaced by instr_get_isa_mode().
*/
bool
instr_get_x86_mode(instr_t *instr);
/* DR_API EXPORT BEGIN */
#endif
/* DR_API EXPORT END */
DR_API
/**
* Each instruction stores the processor mode under which it should be
* interpreted. This routine sets the mode for \p instr.
*/
bool
instr_set_isa_mode(instr_t *instr, dr_isa_mode_t mode);
DR_API
/**
* Each instruction stores the processor mode under which it should be
* interpreted. This routine returns the mode for \p instr.
*/
dr_isa_mode_t
instr_get_isa_mode(instr_t *instr);
/***********************************************************************/
/* decoding routines */
DR_UNS_API
/**
* If instr is at Level 0 (i.e., a bundled group of instrs as raw bits),
* expands instr into a sequence of Level 1 instrs using decode_raw() which
* are added in place to ilist.
* Returns the replacement of instr, if any expansion is performed
* (in which case the old instr is destroyed); otherwise returns
* instr unchanged.
*/
instr_t *
instr_expand(dcontext_t *dcontext, instrlist_t *ilist, instr_t *instr);
DR_UNS_API
/**
* Returns true if instr is at Level 0 (i.e. a bundled group of instrs
* as raw bits).
*/
bool
instr_is_level_0(instr_t *inst);
DR_UNS_API
/**
* If the next instr is at Level 0 (i.e., a bundled group of instrs as raw bits),
* expands it into a sequence of Level 1 instrs using decode_raw() which
* are added in place to ilist. Then returns the new next instr.
*/
instr_t *
instr_get_next_expanded(dcontext_t *dcontext, instrlist_t *ilist, instr_t *instr);
DR_UNS_API
/**
* If the prev instr is at Level 0 (i.e., a bundled group of instrs as raw bits),
* expands it into a sequence of Level 1 instrs using decode_raw() which
* are added in place to ilist. Then returns the new prev instr.
*/
instr_t *
instr_get_prev_expanded(dcontext_t *dcontext, instrlist_t *ilist, instr_t *instr);
DR_UNS_API
/**
* If instr is not already at the level of decode_cti, decodes enough
* from the raw bits pointed to by instr to bring it to that level.
* Assumes that instr is a single instr (i.e., NOT Level 0).
*
* decode_cti decodes only enough of instr to determine
* its size, its effects on the 6 arithmetic eflags, and whether it is
* a control-transfer instruction. If it is, the operands fields of
* instr are filled in. If not, only the raw bits fields of instr are
* filled in. This corresponds to a Level 3 decoding for control
* transfer instructions but a Level 1 decoding plus arithmetic eflags
* information for all other instructions.
*/
void
instr_decode_cti(dcontext_t *dcontext, instr_t *instr);
DR_UNS_API
/**
* If instr is not already at the level of decode_opcode, decodes enough
* from the raw bits pointed to by instr to bring it to that level.
* Assumes that instr is a single instr (i.e., NOT Level 0).
*
* decode_opcode decodes the opcode and eflags usage of the instruction.
* This corresponds to a Level 2 decoding.
*/
void
instr_decode_opcode(dcontext_t *dcontext, instr_t *instr);
DR_UNS_API
/**
* If instr is not already fully decoded, decodes enough
* from the raw bits pointed to by instr to bring it Level 3.
* Assumes that instr is a single instr (i.e., NOT Level 0).
*/
void
instr_decode(dcontext_t *dcontext, instr_t *instr);
/* Calls instr_decode() with the current dcontext. *Not* exported. Mostly
* useful as the slow path for IR routines that get inlined.
*/
instr_t *
instr_decode_with_current_dcontext(instr_t *instr);
/* DR_API EXPORT TOFILE dr_ir_instrlist.h */
DR_UNS_API
/**
* If the first instr is at Level 0 (i.e., a bundled group of instrs as raw bits),
* expands it into a sequence of Level 1 instrs using decode_raw() which
* are added in place to ilist. Then returns the new first instr.
*/
instr_t*
instrlist_first_expanded(dcontext_t *dcontext, instrlist_t *ilist);
DR_UNS_API
/**
* If the last instr is at Level 0 (i.e., a bundled group of instrs as raw bits),
* expands it into a sequence of Level 1 instrs using decode_raw() which
* are added in place to ilist. Then returns the new last instr.
*/
instr_t*
instrlist_last_expanded(dcontext_t *dcontext, instrlist_t *ilist);
DR_UNS_API
/**
* Brings all instrs in ilist up to the decode_cti level, and
* hooks up intra-ilist cti targets to use instr_t targets, by
* matching pc targets to each instruction's raw bits.
*
* decode_cti decodes only enough of instr to determine
* its size, its effects on the 6 arithmetic eflags, and whether it is
* a control-transfer instruction. If it is, the operands fields of
* instr are filled in. If not, only the raw bits fields of instr are
* filled in. This corresponds to a Level 3 decoding for control
* transfer instructions but a Level 1 decoding plus arithmetic eflags
* information for all other instructions.
*/
void
instrlist_decode_cti(dcontext_t *dcontext, instrlist_t *ilist);
/* DR_API EXPORT TOFILE dr_ir_instr.h */
/***********************************************************************/
/* utility functions */
DR_API
/**
* Shrinks all registers not used as addresses, and all immed integer and
* address sizes, to 16 bits.
* Does not shrink DR_REG_ESI or DR_REG_EDI used in string instructions.
*/
void
instr_shrink_to_16_bits(instr_t *instr);
/* DR_API EXPORT BEGIN */
#ifdef X64
/* DR_API EXPORT END */
DR_API
/**
* Shrinks all registers, including addresses, and all immed integer and
* address sizes, to 32 bits.
*
* \note For 64-bit DR builds only.
*/
void
instr_shrink_to_32_bits(instr_t *instr);
/* DR_API EXPORT BEGIN */
#endif
/* DR_API EXPORT END */
DR_API
/**
* Assumes that \p reg is a DR_REG_ constant.
* Returns true iff at least one of \p instr's operands references a
* register that overlaps \p reg.
*
* Returns false for multi-byte nops with an operand using reg.
*/
bool
instr_uses_reg(instr_t *instr, reg_id_t reg);
DR_API
/**
* Returns true iff at least one of \p instr's operands references a floating
* point register.
*/
bool
instr_uses_fp_reg(instr_t *instr);
DR_API
/**
* Assumes that \p reg is a DR_REG_ constant.
* Returns true iff at least one of \p instr's source operands references \p reg.
*
* Returns false for multi-byte nops with a source operand using reg.
*
* \note Use instr_reads_from_reg() to also consider addressing
* registers in destination operands.
*/
bool
instr_reg_in_src(instr_t *instr, reg_id_t reg);
DR_API
/**
* Assumes that \p reg is a DR_REG_ constant.
* Returns true iff at least one of \p instr's destination operands references \p reg.
*/
bool
instr_reg_in_dst(instr_t *instr, reg_id_t reg);
DR_API
/**
* Assumes that \p reg is a DR_REG_ constant.
* Returns true iff at least one of \p instr's destination operands is
* a register operand for a register that overlaps \p reg.
* Which operands are considered to be accessed for conditionally executed
* instructions are controlled by \p flags.
*/
bool
instr_writes_to_reg(instr_t *instr, reg_id_t reg, dr_opnd_query_flags_t flags);
DR_API
/**
* Assumes that reg is a DR_REG_ constant.
* Returns true iff at least one of instr's operands reads
* from a register that overlaps reg (checks both source operands
* and addressing registers used in destination operands).
*
* Returns false for multi-byte nops with an operand using reg.
*
* Which operands are considered to be accessed for conditionally executed
* instructions are controlled by \p flags.
*/
bool
instr_reads_from_reg(instr_t *instr, reg_id_t reg, dr_opnd_query_flags_t flags);
DR_API
/**
* Assumes that \p reg is a DR_REG_ constant.
* Returns true iff at least one of \p instr's destination operands is
* the same register (not enough to just overlap) as \p reg.
* Which operands are considered to be accessed for conditionally executed
* instructions are controlled by \p flags.
*/
bool
instr_writes_to_exact_reg(instr_t *instr, reg_id_t reg, dr_opnd_query_flags_t flags);
DR_API
/**
* Replaces all instances of \p old_opnd in \p instr's source operands with
* \p new_opnd (uses opnd_same() to detect sameness).
*/
bool
instr_replace_src_opnd(instr_t *instr, opnd_t old_opnd, opnd_t new_opnd);
DR_API
/**
* Returns true iff \p instr1 and \p instr2 have the same opcode, prefixes,
* and source and destination operands (uses opnd_same() to compare the operands).
*/
bool
instr_same(instr_t *instr1, instr_t *instr2);
DR_API
/**
* Returns true iff any of \p instr's source operands is a memory reference.
*
* Unlike opnd_is_memory_reference(), this routine conisders the
* semantics of the instruction and returns false for both multi-byte
* nops with a memory operand and for the #OP_lea instruction, as they
* do not really reference the memory. It does return true for
* prefetch instructions.
*
* If \p instr is predicated (see instr_is_predicated()), the memory reference
* may not always be accessed.
*/
bool
instr_reads_memory(instr_t *instr);
DR_API
/**
* Returns true iff any of \p instr's destination operands is a memory
* reference. If \p instr is predicated (see instr_is_predicated()), the
* destination may not always be written.
*/
bool
instr_writes_memory(instr_t *instr);
DR_API
/**
* Returns true iff \p instr writes to an xmm register and zeroes the top half
* of the corresponding ymm register as a result (some instructions preserve
* the top half while others zero it when writing to the bottom half).
* This zeroing will occur even if \p instr is predicated (see instr_is_predicated()).
*/
bool
instr_zeroes_ymmh(instr_t *instr);
/* DR_API EXPORT BEGIN */
#ifdef X64
/* DR_API EXPORT END */
DR_API
/**
* Returns true iff any of \p instr's operands is a rip-relative memory reference.
*
* \note For 64-bit DR builds only.
*/
bool
instr_has_rel_addr_reference(instr_t *instr);
DR_API
/**
* If any of \p instr's operands is a rip-relative memory reference, returns the
* address that reference targets. Else returns false.
*
* \note For 64-bit DR builds only.
*/
bool
instr_get_rel_addr_target(instr_t *instr, /*OUT*/ app_pc *target);
DR_API
/**
* If any of \p instr's destination operands is a rip-relative memory
* reference, returns the operand position. If there is no such
* destination operand, returns -1.
*
* \note For 64-bit DR builds only.
*/
int
instr_get_rel_addr_dst_idx(instr_t *instr);
DR_API
/**
* If any of \p instr's source operands is a rip-relative memory
* reference, returns the operand position. If there is no such
* source operand, returns -1.
*
* \note For 64-bit DR builds only.
*/
int
instr_get_rel_addr_src_idx(instr_t *instr);
/* We're not exposing the low-level rip_rel_pos routines directly to clients,
* who should only use this level 1-3 feature via decode_cti + encode.
*/
/* Returns true iff instr's raw bits are valid and the offset within
* those raw bits of a rip-relative displacement is set (to 0 if there
* is no such displacement).
*/
bool
instr_rip_rel_valid(instr_t *instr);
/* Sets whether instr's rip-relative displacement offset is valid. */
void
instr_set_rip_rel_valid(instr_t *instr, bool valid);
/* Assumes that instr_rip_rel_valid() is true.
* Returns the offset within the encoded bytes of instr of the
* displacement used for rip-relative addressing; returns 0
* if instr has no rip-relative operand.
* There can be at most one rip-relative operand in one instruction.
*/
uint
instr_get_rip_rel_pos(instr_t *instr);
/* Sets the offset within instr's encoded bytes of instr's
* rip-relative displacement (the offset should be 0 if there is no
* rip-relative operand) and marks it valid. \p pos must be less
* than 256.
*/
void
instr_set_rip_rel_pos(instr_t *instr, uint pos);
/* DR_API EXPORT BEGIN */
#endif /* X64 */
/* DR_API EXPORT END */
/* not exported: for PR 267260 */
bool
instr_is_our_mangling(instr_t *instr);
/* Sets whether instr came from our mangling. */
void
instr_set_our_mangling(instr_t *instr, bool ours);
DR_API
/**
* Returns NULL if none of \p instr's operands is a memory reference.
* Otherwise, returns the effective address of the first memory operand
* when the operands are considered in this order: destinations and then
* sources. The address is computed using the passed-in registers.
* \p mc->flags must include DR_MC_CONTROL and DR_MC_INTEGER.
* For instructions that use vector addressing (VSIB, introduced in AVX2),
* mc->flags must additionally include DR_MC_MULTIMEDIA.
*
* Like instr_reads_memory(), this routine does not consider
* multi-byte nops that use addressing operands, or the #OP_lea
* instruction's source operand, to be memory references.
*/
app_pc
instr_compute_address(instr_t *instr, dr_mcontext_t *mc);
app_pc
instr_compute_address_priv(instr_t *instr, priv_mcontext_t *mc);
DR_API
/**
* Performs address calculation in the same manner as
* instr_compute_address() but handles multiple memory operands. The
* \p index parameter should be initially set to 0 and then
* incremented with each successive call until this routine returns
* false, which indicates that there are no more memory operands. The
* address of each is computed in the same manner as
* instr_compute_address() and returned in \p addr; whether it is a
* write is returned in \p is_write. Either or both OUT variables can
* be NULL.
* \p mc->flags must include DR_MC_CONTROL and DR_MC_INTEGER.
* For instructions that use vector addressing (VSIB, introduced in AVX2),
* mc->flags must additionally include DR_MC_MULTIMEDIA.
*
* Like instr_reads_memory(), this routine does not consider
* multi-byte nops that use addressing operands, or the #OP_lea
* instruction's source operand, to be memory references.
*/
bool
instr_compute_address_ex(instr_t *instr, dr_mcontext_t *mc, uint index,
OUT app_pc *addr, OUT bool *write);
DR_API
/**
* Performs address calculation in the same manner as
* instr_compute_address_ex() with additional information
* of which opnd is used for address computation returned
* in \p pos. If \p pos is NULL, it is the same as
* instr_compute_address_ex().
*
* Like instr_reads_memory(), this routine does not consider
* multi-byte nops that use addressing operands, or the #OP_lea
* instruction's source operand, to be memory references.
*/
bool
instr_compute_address_ex_pos(instr_t *instr, dr_mcontext_t *mc, uint index,
OUT app_pc *addr, OUT bool *is_write,
OUT uint *pos);
bool
instr_compute_address_ex_priv(instr_t *instr, priv_mcontext_t *mc, uint index,
OUT app_pc *addr, OUT bool *write, OUT uint *pos);
DR_API
/**
* Calculates the size, in bytes, of the memory read or write of \p instr.
* If \p instr does not reference memory, or is invalid, returns 0.
* If \p instr is a repeated string instruction, considers only one iteration.
* If \p instr uses vector addressing (VSIB, introduced in AVX2), considers
* only the size of each separate memory access.
*/
uint
instr_memory_reference_size(instr_t *instr);
DR_API
/**
* \return a pointer to user-controlled data fields in a label instruction.
* These fields are available for use by clients for their own purposes.
* Returns NULL if \p instr is not a label instruction.
* \note These data fields are copied (shallowly) across instr_clone().
*/
dr_instr_label_data_t *
instr_get_label_data_area(instr_t *instr);
/* DR_API EXPORT TOFILE dr_ir_utils.h */
/* DR_API EXPORT BEGIN */
/***************************************************************************
* DECODE / DISASSEMBLY ROUTINES
*/
/* DR_API EXPORT END */
DR_API
/**
* Calculates the size, in bytes, of the memory read or write of
* the instr at \p pc. If the instruction is a repeating string instruction,
* considers only one iteration.
* Returns the pc of the following instruction.
* If the instruction at \p pc does not reference memory, or is invalid,
* returns NULL.
*/
app_pc
decode_memory_reference_size(dcontext_t *dcontext, app_pc pc, uint *size_in_bytes);
/* DR_API EXPORT TOFILE dr_ir_instr.h */
DR_API
/**
* Returns true iff \p instr is an IA-32/AMD64 "mov" instruction: either OP_mov_st,
* OP_mov_ld, OP_mov_imm, OP_mov_seg, or OP_mov_priv.
*/
bool
instr_is_mov(instr_t *instr);
DR_API
/**
* Returns true iff \p instr's opcode is OP_call, OP_call_far, OP_call_ind,
* or OP_call_far_ind.
*/
bool
instr_is_call(instr_t *instr);
DR_API
/** Returns true iff \p instr's opcode is OP_call or OP_call_far. */
bool
instr_is_call_direct(instr_t *instr);
DR_API
/** Returns true iff \p instr's opcode is OP_call. */
bool
instr_is_near_call_direct(instr_t *instr);
DR_API
/** Returns true iff \p instr's opcode is OP_call_ind or OP_call_far_ind. */
bool
instr_is_call_indirect(instr_t *instr);
DR_API
/** Returns true iff \p instr's opcode is OP_ret, OP_ret_far, or OP_iret. */
bool
instr_is_return(instr_t *instr);
DR_API
/**
* Returns true iff \p instr is a control transfer instruction of any kind
* This includes OP_jcc, OP_jcc_short, OP_loop*, OP_jecxz, OP_call*, and OP_jmp*.
*/
bool
instr_is_cti(instr_t *instr);
DR_API
/**
* Returns true iff \p instr is a control transfer instruction that takes an
* 8-bit offset: OP_loop*, OP_jecxz, OP_jmp_short, or OP_jcc_short
*/
#ifdef UNSUPPORTED_API
/**
* This routine does NOT try to decode an opcode in a Level 1 or Level
* 0 routine, and can thus be called on Level 0 routines.
*/
#endif
bool
instr_is_cti_short(instr_t *instr);
DR_API
/** Returns true iff \p instr is one of OP_loop* or OP_jecxz. */
bool
instr_is_cti_loop(instr_t *instr);
DR_API
/**
* Returns true iff \p instr's opcode is OP_loop* or OP_jecxz and instr has
* been transformed to a sequence of instruction that will allow a 32-bit
* offset.
* If \p pc != NULL, \p pc is expected to point the the beginning of the encoding of
* \p instr, and the following instructions are assumed to be encoded in sequence
* after \p instr.
* Otherwise, the encoding is expected to be found in \p instr's allocated bits.
*/
#ifdef UNSUPPORTED_API
/**
* This routine does NOT try to decode an opcode in a Level 1 or Level
* 0 routine, and can thus be called on Level 0 routines.
*/
#endif
bool
instr_is_cti_short_rewrite(instr_t *instr, byte *pc);
byte *
remangle_short_rewrite(dcontext_t *dcontext, instr_t *instr, byte *pc, app_pc target);
DR_API
/**
* Returns true iff \p instr is a conditional branch: OP_jcc, OP_jcc_short,
* OP_loop*, or OP_jecxz.
*/
bool
instr_is_cbr(instr_t *instr);
DR_API
/**
* Returns true iff \p instr is a multi-way (indirect) branch: OP_jmp_ind,
* OP_call_ind, OP_ret, OP_jmp_far_ind, OP_call_far_ind, OP_ret_far, or
* OP_iret.
*/
bool
instr_is_mbr(instr_t *instr);
DR_API
/**
* Returns true iff \p instr is an unconditional direct branch: OP_jmp,
* OP_jmp_short, or OP_jmp_far.
*/
bool
instr_is_ubr(instr_t *instr);
DR_API
/**
* Returns true iff \p instr is a near unconditional direct branch: OP_jmp,
* or OP_jmp_short.
*/
bool
instr_is_near_ubr(instr_t *instr);
DR_API
/**
* Returns true iff \p instr is a far control transfer instruction: OP_jmp_far,
* OP_call_far, OP_jmp_far_ind, OP_call_far_ind, OP_ret_far, or OP_iret.
*/
bool
instr_is_far_cti(instr_t *instr);
DR_API
/** Returns true if \p instr is an absolute call or jmp that is far. */
bool
instr_is_far_abs_cti(instr_t *instr);
DR_API
/**
* Returns true iff \p instr is used to implement system calls: OP_int with a
* source operand of 0x80 on linux or 0x2e on windows, or OP_sysenter,
* or OP_syscall, or #instr_is_wow64_syscall() for WOW64.
*/
bool
instr_is_syscall(instr_t *instr);
/* DR_API EXPORT BEGIN */
#ifdef WINDOWS
/* DR_API EXPORT END */
DR_API
/**
* Returns true iff \p instr is the indirect transfer from the 32-bit
* ntdll.dll to the wow64 system call emulation layer. This
* instruction will also return true for instr_is_syscall, as well as
* appear as an indirect call, so clients modifying indirect calls may
* want to avoid modifying this type.
*
* \note Windows-only
*/
bool
instr_is_wow64_syscall(instr_t *instr);
/* DR_API EXPORT BEGIN */
#endif
/* DR_API EXPORT END */
DR_API
/**
* Returns true iff \p instr is a prefetch instruction: OP_prefetchnta,
* OP_prefetchnt0, OP_prefetchnt1, OP_prefetchnt2, OP_prefetch, or
* OP_prefetchw.
*/
bool
instr_is_prefetch(instr_t *instr);
DR_API
/**
* Tries to identify common cases of moving a constant into either a
* register or a memory address.
* Returns true and sets \p *value to the constant being moved for the following
* cases: mov_imm, mov_st, and xor where the source equals the destination.
*/
bool
instr_is_mov_constant(instr_t *instr, ptr_int_t *value);
DR_API
/** Returns true iff \p instr is a floating point instruction. */
bool
instr_is_floating(instr_t *instr);
bool
instr_saves_float_pc(instr_t *instr);
/* DR_API EXPORT BEGIN */
/**
* Indicates which type of floating-point operation and instruction performs.
*/
typedef enum {
DR_FP_STATE, /**< Loads, stores, or queries general floating point state. */
DR_FP_MOVE, /**< Moves floating point values from one location to another. */
DR_FP_CONVERT, /**< Converts to or from floating point values. */
DR_FP_MATH, /**< Performs arithmetic or conditional operations. */
} dr_fp_type_t;
/* DR_API EXPORT END */
DR_API
/**
* Returns true iff \p instr is a floating point instruction.
* @param[in] instr The instruction to query
* @param[out] type If the return value is true and \p type is
* non-NULL, the type of the floating point operation is written to \p type.
*/
bool
instr_is_floating_ex(instr_t *instr, dr_fp_type_t *type);
DR_API
/** Returns true iff \p instr is part of Intel's MMX instructions. */
bool
instr_is_mmx(instr_t *instr);
DR_API
/** Returns true iff \p instr is part of Intel's SSE or SSE2 instructions. */
bool
instr_is_sse_or_sse2(instr_t *instr);
DR_API
/** Returns true iff \p instr is a "mov $imm -> (%esp)". */
bool
instr_is_mov_imm_to_tos(instr_t *instr);
DR_API
/** Returns true iff \p instr is a label meta-instruction. */
bool
instr_is_label(instr_t *instr);
DR_API
/** Returns true iff \p instr is an "undefined" instruction (ud2) */
bool
instr_is_undefined(instr_t *instr);
DR_API
/**
* Assumes that \p instr's opcode is OP_int and that either \p instr's
* operands or its raw bits are valid.
* Returns the first source operand if \p instr's operands are valid,
* else if \p instr's raw bits are valid returns the first raw byte.
*/
int
instr_get_interrupt_number(instr_t *instr);
DR_API
/**
* Assumes that \p instr is a conditional branch instruction
* Reverses the logic of \p instr's conditional
* e.g., changes OP_jb to OP_jnb.
* Works on cti_short_rewrite as well.
*/
void
instr_invert_cbr(instr_t *instr);
/* PR 266292 */
DR_API
/**
* Assumes that instr is a meta instruction (instr_is_meta())
* and an instr_is_cti_short() (8-bit reach). Converts instr's opcode
* to a long form (32-bit reach). If instr's opcode is OP_loop* or
* OP_jecxz, converts it to a sequence of multiple instructions (which
* is different from instr_is_cti_short_rewrite()). Each added instruction
* is marked instr_is_meta().
* Returns the long form of the instruction, which is identical to \p instr
* unless \p instr is OP_loop* or OP_jecxz, in which case the return value
* is the final instruction in the sequence, the one that has long reach.
* \note DR automatically converts app short ctis to long form.
*/
instr_t *
instr_convert_short_meta_jmp_to_long(dcontext_t *dcontext, instrlist_t *ilist,
instr_t *instr);
DR_API
/**
* Given \p eflags, returns whether or not the conditional branch, \p
* instr, would be taken.
*/
bool
instr_jcc_taken(instr_t *instr, reg_t eflags);
/* Given a machine state, returns whether or not the cbr instr would be taken
* if the state is before execution (pre == true) or after (pre == false).
* (not exported since machine state isn't)
*/
bool
instr_cbr_taken(instr_t *instr, priv_mcontext_t *mcontext, bool pre);
DR_API
/**
* Converts a cmovcc opcode \p cmovcc_opcode to the OP_jcc opcode that
* tests the same bits in eflags.
*/
int
instr_cmovcc_to_jcc(int cmovcc_opcode);
DR_API
/**
* Given \p eflags, returns whether or not the conditional move
* instruction \p instr would execute the move. The conditional move
* can be an OP_cmovcc or an OP_fcmovcc instruction.
*/
bool
instr_cmovcc_triggered(instr_t *instr, reg_t eflags);
/* utility routines that are in optimize.c */
opnd_t
instr_get_src_mem_access(instr_t *instr);
void
loginst(dcontext_t *dcontext, uint level, instr_t *instr, const char *string);
void
logopnd(dcontext_t *dcontext, uint level, opnd_t opnd, const char *string);
DR_API
/**
* Returns true if \p instr is one of a class of common nops.
* currently checks:
* - nop
* - nop reg/mem
* - xchg reg, reg
* - mov reg, reg
* - lea reg, (reg)
*/
bool
instr_is_nop(instr_t *instr);
DR_UNS_API
/**
* Convenience routine to create a nop of a certain size. If \p raw
* is true, sets raw bytes rather than filling in the operands or opcode.
*/
instr_t *
instr_create_nbyte_nop(dcontext_t *dcontext, uint num_bytes, bool raw);
DR_API
/**
* Convenience routine that returns an initialized instr_t allocated on the
* thread-local heap with opcode \p opcode and no sources or destinations.
*/
instr_t *
instr_create_0dst_0src(dcontext_t *dcontext, int opcode);
DR_API
/**
* Convenience routine that returns an initialized instr_t allocated on the
* thread-local heap with opcode \p opcode and a single source (\p src).
*/
instr_t *
instr_create_0dst_1src(dcontext_t *dcontext, int opcode,
opnd_t src);
DR_API
/**
* Convenience routine that returns an initialized instr_t allocated on the
* thread-local heap with opcode \p opcode and two sources (\p src1, \p src2).
*/
instr_t *
instr_create_0dst_2src(dcontext_t *dcontext, int opcode,
opnd_t src1, opnd_t src2);
DR_API
/**
* Convenience routine that returns an initialized instr_t allocated
* on the thread-local heap with opcode \p opcode and three sources
* (\p src1, \p src2, \p src3).
*/
instr_t *
instr_create_0dst_3src(dcontext_t *dcontext, int opcode,
opnd_t src1, opnd_t src2, opnd_t src3);
DR_API
/**
* Convenience routine that returns an initialized instr_t allocated
* on the thread-local heap with opcode \p opcode and four sources
* (\p src1, \p src2, \p src3, \p src4).
*/
instr_t *
instr_create_0dst_4src(dcontext_t *dcontext, int opcode,
opnd_t src1, opnd_t src2, opnd_t src3, opnd_t src4);
DR_API
/**
* Convenience routine that returns an initialized instr_t allocated on the
* thread-local heap with opcode \p opcode and one destination (\p dst).
*/
instr_t *
instr_create_1dst_0src(dcontext_t *dcontext, int opcode,
opnd_t dst);
DR_API
/**
* Convenience routine that returns an initialized instr_t allocated on the
* thread-local heap with opcode \p opcode, one destination(\p dst),
* and one source (\p src).
*/
instr_t *
instr_create_1dst_1src(dcontext_t *dcontext, int opcode,
opnd_t dst, opnd_t src);
DR_API
/**
* Convenience routine that returns an initialized instr_t allocated on the
* thread-local heap with opcode \p opcode, one destination (\p dst),
* and two sources (\p src1, \p src2).
*/
instr_t *
instr_create_1dst_2src(dcontext_t *dcontext, int opcode,
opnd_t dst, opnd_t src1, opnd_t src2);
DR_API
/**
* Convenience routine that returns an initialized instr_t allocated on the
* thread-local heap with opcode \p opcode, one destination (\p dst),
* and three sources (\p src1, \p src2, \p src3).
*/
instr_t *
instr_create_1dst_3src(dcontext_t *dcontext, int opcode,
opnd_t dst, opnd_t src1, opnd_t src2, opnd_t src3);
DR_API
/**
* Convenience routine that returns an initialized instr_t allocated on the
* thread-local heap with opcode \p opcode, one destination (\p dst),
* and four sources (\p src1, \p src2, \p src3, \p src4).
*/
instr_t *
instr_create_1dst_4src(dcontext_t *dcontext, int opcode,
opnd_t dst, opnd_t src1, opnd_t src2, opnd_t src3, opnd_t src4);
DR_API
/**
* Convenience routine that returns an initialized instr_t allocated on the
* thread-local heap with opcode \p opcode, one destination (\p dst),
* and five sources (\p src1, \p src2, \p src3, \p src4, \p src5).
*/
instr_t *
instr_create_1dst_5src(dcontext_t *dcontext, int opcode,
opnd_t dst, opnd_t src1, opnd_t src2, opnd_t src3,
opnd_t src4, opnd_t src5);
DR_API
/**
* Convenience routine that returns an initialized instr_t allocated on the
* thread-local heap with opcode \p opcode, two destinations (\p dst1, \p dst2)
* and no sources.
*/
instr_t *
instr_create_2dst_0src(dcontext_t *dcontext, int opcode,
opnd_t dst1, opnd_t dst2);
DR_API
/**
* Convenience routine that returns an initialized instr_t allocated on the
* thread-local heap with opcode \p opcode, two destinations (\p dst1, \p dst2)
* and one source (\p src).
*/
instr_t *
instr_create_2dst_1src(dcontext_t *dcontext, int opcode,
opnd_t dst1, opnd_t dst2, opnd_t src);
DR_API
/**
* Convenience routine that returns an initialized instr_t allocated on the
* thread-local heap with opcode \p opcode, two destinations (\p dst1, \p dst2)
* and two sources (\p src1, \p src2).
*/
instr_t *
instr_create_2dst_2src(dcontext_t *dcontext, int opcode,
opnd_t dst1, opnd_t dst2, opnd_t src1, opnd_t src2);
DR_API
/**
* Convenience routine that returns an initialized instr_t allocated on the
* thread-local heap with opcode \p opcode, two destinations (\p dst1, \p dst2)
* and three sources (\p src1, \p src2, \p src3).
*/
instr_t *
instr_create_2dst_3src(dcontext_t *dcontext, int opcode,
opnd_t dst1, opnd_t dst2,
opnd_t src1, opnd_t src2, opnd_t src3);
DR_API
/**
* Convenience routine that returns an initialized instr_t allocated on the
* thread-local heap with opcode \p opcode, two destinations (\p dst1, \p dst2)
* and four sources (\p src1, \p src2, \p src3, \p src4).
*/
instr_t *
instr_create_2dst_4src(dcontext_t *dcontext, int opcode,
opnd_t dst1, opnd_t dst2,
opnd_t src1, opnd_t src2, opnd_t src3, opnd_t src4);
DR_API
/**
* Convenience routine that returns an initialized instr_t allocated on the
* thread-local heap with opcode \p opcode, two destinations (\p dst1, \p dst2)
* and five sources (\p src1, \p src2, \p src3, \p src4, \p src5).
*/
instr_t *
instr_create_2dst_5src(dcontext_t *dcontext, int opcode,
opnd_t dst1, opnd_t dst2,
opnd_t src1, opnd_t src2, opnd_t src3, opnd_t src4, opnd_t src5);
DR_API
/**
* Convenience routine that returns an initialized instr_t allocated
* on the thread-local heap with opcode \p opcode, three destinations
* (\p dst1, \p dst2, \p dst3) and no sources.
*/
instr_t *
instr_create_3dst_0src(dcontext_t *dcontext, int opcode,
opnd_t dst1, opnd_t dst2, opnd_t dst3);
DR_API
/**
* Convenience routine that returns an initialized instr_t allocated
* on the thread-local heap with opcode \p opcode, three destinations
* (\p dst1, \p dst2, \p dst3) and two sources
* (\p src1, \p src2).
*/
instr_t *
instr_create_3dst_2src(dcontext_t *dcontext, int opcode,
opnd_t dst1, opnd_t dst2, opnd_t dst3,
opnd_t src1, opnd_t src2);
DR_API
/**
* Convenience routine that returns an initialized instr_t allocated
* on the thread-local heap with opcode \p opcode, three destinations
* (\p dst1, \p dst2, \p dst3) and three sources
* (\p src1, \p src2, \p src3).
*/
instr_t *
instr_create_3dst_3src(dcontext_t *dcontext, int opcode,
opnd_t dst1, opnd_t dst2, opnd_t dst3,
opnd_t src1, opnd_t src2, opnd_t src3);
DR_API
/**
* Convenience routine that returns an initialized instr_t allocated
* on the thread-local heap with opcode \p opcode, three destinations
* (\p dst1, \p dst2, \p dst3) and four sources
* (\p src1, \p src2, \p src3, \p src4).
*/
instr_t *
instr_create_3dst_4src(dcontext_t *dcontext, int opcode,
opnd_t dst1, opnd_t dst2, opnd_t dst3,
opnd_t src1, opnd_t src2, opnd_t src3, opnd_t src4);
DR_API
/**
* Convenience routine that returns an initialized instr_t allocated
* on the thread-local heap with opcode \p opcode, three destinations
* (\p dst1, \p dst2, \p dst3) and five sources
* (\p src1, \p src2, \p src3, \p src4, \p src5).
*/
instr_t *
instr_create_3dst_5src(dcontext_t *dcontext, int opcode,
opnd_t dst1, opnd_t dst2, opnd_t dst3,
opnd_t src1, opnd_t src2, opnd_t src3,
opnd_t src4, opnd_t src5);
DR_API
/**
* Convenience routine that returns an initialized instr_t allocated
* on the thread-local heap with opcode \p opcode, four destinations
* (\p dst1, \p dst2, \p dst3, \p dst4) and 1 source (\p src).
*/
instr_t *
instr_create_4dst_1src(dcontext_t *dcontext, int opcode,
opnd_t dst1, opnd_t dst2, opnd_t dst3, opnd_t dst4,
opnd_t src);
DR_API
/**
* Convenience routine that returns an initialized instr_t allocated
* on the thread-local heap with opcode \p opcode, four destinations
* (\p dst1, \p dst2, \p dst3, \p dst4) and four sources
* (\p src1, \p src2, \p src3, \p src4).
*/
instr_t *
instr_create_4dst_4src(dcontext_t *dcontext, int opcode,
opnd_t dst1, opnd_t dst2, opnd_t dst3, opnd_t dst4,
opnd_t src1, opnd_t src2, opnd_t src3, opnd_t src4);
DR_API
/**
* Convenience routine that returns an initialized instr_t allocated on the
* thread-local heap with opcode \p opcode, \p fixed_dsts destination operands,
* and \p fixed_srcs plus \p var_srcs source operands. The variable arguments
* must start with the (fixed) destinations, followed by the fixed sources,
* followed by the variable sources.
*/
instr_t *
instr_create_Ndst_Msrc_varsrc(dcontext_t *dcontext, int opcode, uint fixed_dsts,
uint fixed_srcs, uint var_srcs, ...);
DR_API
/**
* Convenience routine that returns an initialized instr_t allocated on the
* thread-local heap with opcode \p opcode, \p fixed_dsts plus \p var_dsts
* destination operands, and \p fixed_srcs source operands. The variable
* arguments must start with the fixed destinations, followed by the (fixed)
* sources, followed by the variable destinations.
*/
instr_t *
instr_create_Ndst_Msrc_vardst(dcontext_t *dcontext, int opcode, uint fixed_dsts,
uint fixed_srcs, uint var_dsts, ...);
DR_API
/** Convenience routine that returns an initialized instr_t for OP_popa. */
instr_t *
instr_create_popa(dcontext_t *dcontext);
DR_API
/** Convenience routine that returns an initialized instr_t for OP_pusha. */
instr_t *
instr_create_pusha(dcontext_t *dcontext);
/* build instructions from raw bits */
DR_UNS_API
/**
* Convenience routine that returns an initialized instr_t with invalid operands
* and allocated raw bits with 1 byte (byte).
*/
instr_t *
instr_create_raw_1byte(dcontext_t *dcontext, byte byte);
DR_UNS_API
/**
* Convenience routine that returns an initialized instr_t with invalid operands
* and allocated raw bits with 2 bytes (byte1, byte2).
*/
instr_t *
instr_create_raw_2bytes(dcontext_t *dcontext, byte byte1, byte byte2);
DR_UNS_API
/**
* Convenience routine that returns an initialized instr_t with invalid operands
* and allocated raw bits with 3 bytes (byte1, byte2, byte3).
*/
instr_t *
instr_create_raw_3bytes(dcontext_t *dcontext, byte byte1,
byte byte2, byte byte3);
DR_UNS_API
/**
* Convenience routine that returns an initialized instr_t with invalid operands
* and allocated raw bits with 4 bytes (byte1, byte2, byte3, byte4).
*/
instr_t *
instr_create_raw_4bytes(dcontext_t *dcontext, byte byte1,
byte byte2, byte byte3, byte byte4);
DR_UNS_API
/**
* Convenience routine that returns an initialized instr_t with invalid operands
* and allocated raw bits with 5 bytes (byte1, byte2, byte3, byte4, byte5).
*/
instr_t *
instr_create_raw_5bytes(dcontext_t *dcontext, byte byte1,
byte byte2, byte byte3, byte byte4, byte byte5);
DR_UNS_API
/**
* Convenience routine that returns an initialized instr_t with invalid operands
* and allocated raw bits with 6 bytes (byte1, byte2, byte3, byte4, byte5, byte6).
*/
instr_t *
instr_create_raw_6bytes(dcontext_t *dcontext, byte byte1, byte byte2,
byte byte3, byte byte4, byte byte5, byte byte6);
DR_UNS_API
/**
* Convenience routine that returns an initialized instr_t with invalid operands
* and allocated raw bits with 7 bytes (byte1, byte2, byte3, byte4, byte5, byte6,
* byte7).
*/
instr_t *
instr_create_raw_7bytes(dcontext_t *dcontext, byte byte1, byte byte2,
byte byte3, byte byte4, byte byte5,
byte byte6, byte byte7);
DR_UNS_API
/**
* Convenience routine that returns an initialized instr_t with invalid operands
* and allocated raw bits with 7 bytes (byte1, byte2, byte3, byte4, byte5, byte6,
* byte7, byte8).
*/
instr_t *
instr_create_raw_8bytes(dcontext_t *dcontext, byte byte1, byte byte2,
byte byte3, byte byte4, byte byte5,
byte byte6, byte byte7, byte byte8);
/* arch-specific routines */
int instr_length_arch(dcontext_t *dcontext, instr_t *instr);
bool opc_is_not_a_real_memory_load(int opc);
bool instr_compute_address_VSIB(instr_t *instr, priv_mcontext_t *mc, size_t mc_size,
dr_mcontext_flags_t mc_flags, opnd_t curop, uint index,
OUT bool *have_addr, OUT app_pc *addr, OUT bool *write);
uint instr_branch_type(instr_t *cti_instr);
bool opcode_is_call(int opc);
bool opcode_is_cbr(int opc);
bool opcode_is_mbr(int opc);
bool opcode_is_ubr(int opc);
/* private routines for spill code */
instr_t * instr_create_save_to_dcontext(dcontext_t *dcontext, reg_id_t reg, int offs);
instr_t * instr_create_save_immed_to_dcontext(dcontext_t *dcontext, int immed, int offs);
instr_t *
instr_create_save_immed_to_dc_via_reg(dcontext_t *dcontext, reg_id_t basereg,
int offs, ptr_int_t immed, opnd_size_t sz);
instr_t * instr_create_restore_from_dcontext(dcontext_t *dcontext, reg_id_t reg, int offs);
instr_t * instr_create_save_to_dc_via_reg(dcontext_t *dcontext, reg_id_t basereg,
reg_id_t reg, int offs);
instr_t * instr_create_restore_from_dc_via_reg(dcontext_t *dcontext, reg_id_t basereg,
reg_id_t reg, int offs);
instr_t * instr_create_jump_via_dcontext(dcontext_t *dcontext, int offs);
instr_t * instr_create_save_dynamo_stack(dcontext_t *dcontext);
instr_t * instr_create_restore_dynamo_stack(dcontext_t *dcontext);
bool instr_raw_is_tls_spill(byte *pc, reg_id_t reg, ushort offs);
bool instr_is_tls_spill(instr_t *instr, reg_id_t reg, ushort offs);
bool instr_is_tls_xcx_spill(instr_t *instr);
/* Pass REG_NULL to not care about the reg */
bool
instr_is_tls_restore(instr_t *instr, reg_id_t reg, ushort offs);
bool
instr_is_reg_spill_or_restore(dcontext_t *dcontext, instr_t *instr,
bool *tls, bool *spill, reg_id_t *reg);
/* N.B. : client meta routines (dr_insert_* etc.) should never use anything other
* then TLS_XAX_SLOT unless the client has specified a slot to use as we let the
* client use the rest. */
instr_t * instr_create_save_to_tls(dcontext_t *dcontext, reg_id_t reg, ushort offs);
instr_t * instr_create_restore_from_tls(dcontext_t *dcontext, reg_id_t reg, ushort offs);
/* For -x86_to_x64, we can spill to 64-bit extra registers (xref i#751). */
instr_t * instr_create_save_to_reg(dcontext_t *dcontext, reg_id_t reg1, reg_id_t reg2);
instr_t * instr_create_restore_from_reg(dcontext_t *dcontext,
reg_id_t reg1, reg_id_t reg2);
#ifdef X64
byte *
instr_raw_is_rip_rel_lea(byte *pc, byte *read_end);
#endif
/* DR_API EXPORT TOFILE dr_ir_instr.h */
/* DR_API EXPORT BEGIN */
/****************************************************************************
* EFLAGS/CONDITION CODES
*/
#ifdef X86
/* we only care about these 11 flags, and mostly only about the first 6
* we consider an undefined effect on a flag to be a write
*/
# define EFLAGS_READ_CF 0x00000001 /**< Reads CF (Carry Flag). */
# define EFLAGS_READ_PF 0x00000002 /**< Reads PF (Parity Flag). */
# define EFLAGS_READ_AF 0x00000004 /**< Reads AF (Auxiliary Carry Flag). */
# define EFLAGS_READ_ZF 0x00000008 /**< Reads ZF (Zero Flag). */
# define EFLAGS_READ_SF 0x00000010 /**< Reads SF (Sign Flag). */
# define EFLAGS_READ_TF 0x00000020 /**< Reads TF (Trap Flag). */
# define EFLAGS_READ_IF 0x00000040 /**< Reads IF (Interrupt Enable Flag). */
# define EFLAGS_READ_DF 0x00000080 /**< Reads DF (Direction Flag). */
# define EFLAGS_READ_OF 0x00000100 /**< Reads OF (Overflow Flag). */
# define EFLAGS_READ_NT 0x00000200 /**< Reads NT (Nested Task). */
# define EFLAGS_READ_RF 0x00000400 /**< Reads RF (Resume Flag). */
# define EFLAGS_WRITE_CF 0x00000800 /**< Writes CF (Carry Flag). */
# define EFLAGS_WRITE_PF 0x00001000 /**< Writes PF (Parity Flag). */
# define EFLAGS_WRITE_AF 0x00002000 /**< Writes AF (Auxiliary Carry Flag). */
# define EFLAGS_WRITE_ZF 0x00004000 /**< Writes ZF (Zero Flag). */
# define EFLAGS_WRITE_SF 0x00008000 /**< Writes SF (Sign Flag). */
# define EFLAGS_WRITE_TF 0x00010000 /**< Writes TF (Trap Flag). */
# define EFLAGS_WRITE_IF 0x00020000 /**< Writes IF (Interrupt Enable Flag). */
# define EFLAGS_WRITE_DF 0x00040000 /**< Writes DF (Direction Flag). */
# define EFLAGS_WRITE_OF 0x00080000 /**< Writes OF (Overflow Flag). */
# define EFLAGS_WRITE_NT 0x00100000 /**< Writes NT (Nested Task). */
# define EFLAGS_WRITE_RF 0x00200000 /**< Writes RF (Resume Flag). */
# define EFLAGS_READ_ALL 0x000007ff /**< Reads all flags. */
# define EFLAGS_WRITE_ALL 0x003ff800 /**< Writes all flags. */
/* 6 most common flags ("arithmetic flags"): CF, PF, AF, ZF, SF, OF */
/** Reads all 6 arithmetic flags (CF, PF, AF, ZF, SF, OF). */
# define EFLAGS_READ_6 0x0000011f
/** Writes all 6 arithmetic flags (CF, PF, AF, ZF, SF, OF). */
# define EFLAGS_WRITE_6 0x0008f800
/** Platform-independent macro for reads all arithmetic flags. */
# define EFLAGS_READ_ARITH EFLAGS_READ_6
/** Platform-independent macor for writes all arithmetic flags. */
# define EFLAGS_WRITE_ARITH EFLAGS_WRITE_6
/** Converts an EFLAGS_WRITE_* value to the corresponding EFLAGS_READ_* value. */
# define EFLAGS_WRITE_TO_READ(x) ((x) >> 11)
/** Converts an EFLAGS_READ_* value to the corresponding EFLAGS_WRITE_* value. */
# define EFLAGS_READ_TO_WRITE(x) ((x) << 11)
/**
* The actual bits in the eflags register that we care about:\n<pre>
* 11 10 9 8 7 6 5 4 3 2 1 0
* OF DF SF ZF AF PF CF </pre>
*/
enum {
EFLAGS_CF = 0x00000001, /**< The bit in the eflags register of CF (Carry Flag). */
EFLAGS_PF = 0x00000004, /**< The bit in the eflags register of PF (Parity Flag). */
EFLAGS_AF = 0x00000010, /**< The bit in the eflags register of AF (Aux Carry Flag). */
EFLAGS_ZF = 0x00000040, /**< The bit in the eflags register of ZF (Zero Flag). */
EFLAGS_SF = 0x00000080, /**< The bit in the eflags register of SF (Sign Flag). */
EFLAGS_DF = 0x00000400, /**< The bit in the eflags register of DF (Direction Flag). */
EFLAGS_OF = 0x00000800, /**< The bit in the eflags register of OF (Overflow Flag). */
};
#elif defined(ARM)
# define EFLAGS_READ_N 0x00000001 /**< Reads N (negative flag). */
# define EFLAGS_READ_Z 0x00000002 /**< Reads Z (zero flag). */
# define EFLAGS_READ_C 0x00000004 /**< Reads C (carry flag). */
# define EFLAGS_READ_V 0x00000008 /**< Reads V (overflow flag). */
# define EFLAGS_READ_Q 0x00000010 /**< Reads Q (saturation flag). */
# define EFLAGS_READ_GE 0x00000020 /**< Reads GE (>= for parallel arithmetic). */
# define EFLAGS_READ_NZCV (EFLAGS_READ_N | EFLAGS_READ_Z |\
EFLAGS_READ_C | EFLAGS_READ_V)
# define EFLAGS_READ_ALL EFLAGS_READ_NZCV /**< Reads all flags. */
# define EFLAGS_WRITE_N 0x00000040 /**< Reads N (negative). */
# define EFLAGS_WRITE_Z 0x00000080 /**< Reads Z (zero). */
# define EFLAGS_WRITE_C 0x00000100 /**< Reads C (carry). */
# define EFLAGS_WRITE_V 0x00000200 /**< Reads V (overflow). */
# define EFLAGS_WRITE_Q 0x00000400 /**< Reads Q (saturation). */
# define EFLAGS_WRITE_GE 0x00000800 /**< Reads GE (>= for parallel arithmetic). */
# define EFLAGS_WRITE_NZCV (EFLAGS_WRITE_N | EFLAGS_WRITE_Z |\
EFLAGS_WRITE_C | EFLAGS_WRITE_V)
# define EFLAGS_WRITE_ALL EFLAGS_WRITE_NZCV /**< Writes all flags. */
/** Platform-independent macro for reads all arithmetic flags. */
# define EFLAGS_READ_ARITH EFLAGS_READ_NZCV
/** Platform-independent macor for writes all arithmetic flags. */
# define EFLAGS_WRITE_ARITH EFLAGS_WRITE_NZCV
/** Converts an EFLAGS_WRITE_* value to the corresponding EFLAGS_READ_* value. */
# define EFLAGS_WRITE_TO_READ(x) ((x) >> 6)
/** Converts an EFLAGS_READ_* value to the corresponding EFLAGS_WRITE_* value. */
# define EFLAGS_READ_TO_WRITE(x) ((x) << 6)
/**
* The actual bits in the CPSR that we care about:\n<pre>
* 31 30 29 28 27 ... 19 18 17 16
* N Z C V Q GE[3:0] </pre>
*/
enum {
EFLAGS_N = 0x80000000, /**< The bit in the CPSR register of N (negative flag). */
EFLAGS_Z = 0x40000000, /**< The bit in the CPSR register of Z (zero flag). */
EFLAGS_C = 0x20000000, /**< The bit in the CPSR register of C (carry flag). */
EFLAGS_V = 0x10000000, /**< The bit in the CPSR register of V (overflow flag). */
EFLAGS_Q = 0x08000000, /**< The bit in the CPSR register of Q (saturation flag). */
EFLAGS_GE = 0x000f0000, /**< The bit in the CPSR register of GE[3:0]. */
};
#endif
/* DR_API EXPORT END */
/* even on x64, displacements are 32 bits, so we keep the "int" type and 4-byte size */
#define PC_RELATIVE_TARGET(addr) ( *((int *)(addr)) + (addr) + 4 )
/* length of our mangling of jecxz/loop*, beyond a possible addr prefix byte */
#define CTI_SHORT_REWRITE_LENGTH 9
#include "instr_inline.h"
#endif /* _INSTR_H_ */