1 /* 2 * Copyright (c) 2016-2019, Intel Corporation 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are met: 6 * 7 * * Redistributions of source code must retain the above copyright notice, 8 * this list of conditions and the following disclaimer. 9 * * Redistributions in binary form must reproduce the above copyright notice, 10 * this list of conditions and the following disclaimer in the documentation 11 * and/or other materials provided with the distribution. 12 * * Neither the name of Intel Corporation nor the names of its contributors 13 * may be used to endorse or promote products derived from this software 14 * without specific prior written permission. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #ifndef PT_INSN_H 30 #define PT_INSN_H 31 32 #include <inttypes.h> 33 34 #include "intel-pt.h" 35 36 struct pt_insn_ext; 37 38 39 /* A finer-grain classification of instructions used internally. */ 40 typedef enum { 41 PTI_INST_INVALID, 42 43 PTI_INST_CALL_9A, 44 PTI_INST_CALL_FFr3, 45 PTI_INST_CALL_FFr2, 46 PTI_INST_CALL_E8, 47 PTI_INST_INT, 48 49 PTI_INST_INT3, 50 PTI_INST_INT1, 51 PTI_INST_INTO, 52 PTI_INST_IRET, /* includes IRETD and IRETQ (EOSZ determines) */ 53 54 PTI_INST_JMP_E9, 55 PTI_INST_JMP_EB, 56 PTI_INST_JMP_EA, 57 PTI_INST_JMP_FFr5, /* REXW? */ 58 PTI_INST_JMP_FFr4, 59 PTI_INST_JCC, 60 PTI_INST_JrCXZ, 61 PTI_INST_LOOP, 62 PTI_INST_LOOPE, /* aka Z */ 63 PTI_INST_LOOPNE, /* aka NE */ 64 65 PTI_INST_MOV_CR3, 66 67 PTI_INST_RET_C3, 68 PTI_INST_RET_C2, 69 PTI_INST_RET_CB, 70 PTI_INST_RET_CA, 71 72 PTI_INST_SYSCALL, 73 PTI_INST_SYSENTER, 74 PTI_INST_SYSEXIT, 75 PTI_INST_SYSRET, 76 77 PTI_INST_VMLAUNCH, 78 PTI_INST_VMRESUME, 79 PTI_INST_VMCALL, 80 PTI_INST_VMPTRLD, 81 82 PTI_INST_PTWRITE, 83 84 PTI_INST_LAST 85 } pti_inst_enum_t; 86 87 /* Information about an instruction we need internally in addition to the 88 * information provided in struct pt_insn. 89 */ 90 struct pt_insn_ext { 91 /* A more detailed instruction class. */ 92 pti_inst_enum_t iclass; 93 94 /* Instruction-specific information. */ 95 union { 96 /* For branch instructions. */ 97 struct { 98 /* The branch displacement. 99 * 100 * This is only valid for direct calls/jumps. 101 * 102 * The displacement is applied to the address of the 103 * instruction following the branch. 104 */ 105 int32_t displacement; 106 107 /* A flag saying whether the branch is direct. 108 * 109 * non-zero: direct 110 * zero: indirect 111 * 112 * This is expected to go away someday when we extend 113 * enum pt_insn_class to distinguish direct and indirect 114 * branches. 115 */ 116 uint8_t is_direct; 117 } branch; 118 } variant; 119 }; 120 121 122 /* Check if the instruction @insn/@iext changes the current privilege level. 123 * 124 * Returns non-zero if it does, zero if it doesn't (or @insn/@iext is NULL). 125 */ 126 extern int pt_insn_changes_cpl(const struct pt_insn *insn, 127 const struct pt_insn_ext *iext); 128 129 /* Check if the instruction @insn/@iext changes CR3. 130 * 131 * Returns non-zero if it does, zero if it doesn't (or @insn/@iext is NULL). 132 */ 133 extern int pt_insn_changes_cr3(const struct pt_insn *insn, 134 const struct pt_insn_ext *iext); 135 136 /* Check if the instruction @insn/@iext is a (near or far) branch. 137 * 138 * Returns non-zero if it is, zero if it isn't (or @insn/@iext is NULL). 139 */ 140 extern int pt_insn_is_branch(const struct pt_insn *insn, 141 const struct pt_insn_ext *iext); 142 143 /* Check if the instruction @insn/@iext is a far branch. 144 * 145 * Returns non-zero if it is, zero if it isn't (or @insn/@iext is NULL). 146 */ 147 extern int pt_insn_is_far_branch(const struct pt_insn *insn, 148 const struct pt_insn_ext *iext); 149 150 /* Check if the instruction @insn/@iext binds to a PIP packet. 151 * 152 * Returns non-zero if it does, zero if it doesn't (or @insn/@iext is NULL). 153 */ 154 extern int pt_insn_binds_to_pip(const struct pt_insn *insn, 155 const struct pt_insn_ext *iext); 156 157 /* Check if the instruction @insn/@iext binds to a VMCS packet. 158 * 159 * Returns non-zero if it does, zero if it doesn't (or @insn/@iext is NULL). 160 */ 161 extern int pt_insn_binds_to_vmcs(const struct pt_insn *insn, 162 const struct pt_insn_ext *iext); 163 164 /* Check if the instruction @insn/@iext is a ptwrite instruction. 165 * 166 * Returns non-zero if it is, zero if it isn't (or @insn/@iext is NULL). 167 */ 168 extern int pt_insn_is_ptwrite(const struct pt_insn *insn, 169 const struct pt_insn_ext *iext); 170 171 /* Determine the IP of the next instruction. 172 * 173 * Tries to determine the IP of the next instruction without using trace and 174 * provides it in @ip unless @ip is NULL. 175 * 176 * Returns zero on success, a negative error code otherwise. 177 * Returns -pte_bad_query if the IP can't be determined. 178 * Returns -pte_internal if @insn or @iext is NULL. 179 */ 180 extern int pt_insn_next_ip(uint64_t *ip, const struct pt_insn *insn, 181 const struct pt_insn_ext *iext); 182 183 /* Decode and analyze one instruction. 184 * 185 * Decodes the instructruction at @insn->ip in @insn->mode into @insn and @iext. 186 * 187 * If the instruction can not be decoded using a single memory read in a single 188 * section, sets @insn->truncated and reads the missing bytes from one or more 189 * other sections until either the instruction can be decoded or we're sure it 190 * is invalid. 191 * 192 * Returns the size in bytes on success, a negative error code otherwise. 193 * Returns -pte_bad_insn if the instruction could not be decoded. 194 */ 195 extern int pt_insn_decode(struct pt_insn *insn, struct pt_insn_ext *iext, 196 struct pt_image *image, const struct pt_asid *asid); 197 198 /* Determine if a range of instructions is contiguous. 199 * 200 * Try to proceed from IP @begin to IP @end in @asid without using trace. 201 * 202 * Returns a positive integer if we reach @end from @begin. 203 * Returns zero if we couldn't reach @end within @nsteps steps. 204 * Returns a negative error code otherwise. 205 */ 206 extern int pt_insn_range_is_contiguous(uint64_t begin, uint64_t end, 207 enum pt_exec_mode mode, 208 struct pt_image *image, 209 const struct pt_asid *asid, 210 size_t nsteps); 211 212 #endif /* PT_INSN_H */ 213