2 * Copyright (c) 2016-2018, Intel Corporation
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
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.
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.
32 #include "pt_compiler.h"
37 int pt_insn_changes_cpl(const struct pt_insn *insn,
38 const struct pt_insn_ext *iext)
45 switch (iext->iclass) {
54 case PTI_INST_SYSCALL:
55 case PTI_INST_SYSENTER:
56 case PTI_INST_SYSEXIT:
62 int pt_insn_changes_cr3(const struct pt_insn *insn,
63 const struct pt_insn_ext *iext)
70 switch (iext->iclass) {
74 case PTI_INST_MOV_CR3:
79 int pt_insn_is_branch(const struct pt_insn *insn,
80 const struct pt_insn_ext *iext)
87 switch (insn->iclass) {
102 int pt_insn_is_far_branch(const struct pt_insn *insn,
103 const struct pt_insn_ext *iext)
110 switch (insn->iclass) {
115 case ptic_far_return:
121 int pt_insn_binds_to_pip(const struct pt_insn *insn,
122 const struct pt_insn_ext *iext)
127 switch (iext->iclass) {
129 return pt_insn_is_far_branch(insn, iext);
131 case PTI_INST_MOV_CR3:
132 case PTI_INST_VMLAUNCH:
133 case PTI_INST_VMRESUME:
138 int pt_insn_binds_to_vmcs(const struct pt_insn *insn,
139 const struct pt_insn_ext *iext)
144 switch (iext->iclass) {
146 return pt_insn_is_far_branch(insn, iext);
148 case PTI_INST_VMPTRLD:
149 case PTI_INST_VMLAUNCH:
150 case PTI_INST_VMRESUME:
155 int pt_insn_is_ptwrite(const struct pt_insn *insn,
156 const struct pt_insn_ext *iext)
163 switch (insn->iclass) {
172 int pt_insn_next_ip(uint64_t *pip, const struct pt_insn *insn,
173 const struct pt_insn_ext *iext)
178 return -pte_internal;
180 ip = insn->ip + insn->size;
182 switch (insn->iclass) {
189 if (iext->variant.branch.is_direct) {
190 ip += iext->variant.branch.displacement;
196 return -pte_bad_query;
199 return -pte_bad_insn;
208 /* Retry decoding an instruction after a preceding decode error.
210 * Instruction length decode typically fails due to 'not enough
213 * This may be caused by partial updates of text sections
214 * represented via new image sections overlapping the original
215 * text section's image section. We stop reading memory at the
216 * end of the section so we do not read the full instruction if
217 * parts of it have been overwritten by the update.
219 * Try to read the remaining bytes and decode the instruction again. If we
220 * succeed, set @insn->truncated to indicate that the instruction is truncated
223 * Returns zero on success, a negative error code otherwise.
224 * Returns -pte_bad_insn if the instruction could not be decoded.
226 static int pt_insn_decode_retry(struct pt_insn *insn, struct pt_insn_ext *iext,
227 struct pt_image *image,
228 const struct pt_asid *asid)
230 int size, errcode, isid;
231 uint8_t isize, remaining;
234 return -pte_internal;
237 remaining = sizeof(insn->raw) - isize;
239 /* We failed for real if we already read the maximum number of bytes for
243 return -pte_bad_insn;
245 /* Read the remaining bytes from the image. */
246 size = pt_image_read(image, &isid, &insn->raw[isize], remaining, asid,
249 /* We should have gotten an error if we were not able to read at
250 * least one byte. Check this to guarantee termination.
253 return -pte_internal;
255 /* Preserve the original error if there are no more bytes. */
256 if (size == -pte_nomap)
257 size = -pte_bad_insn;
262 /* Add the newly read bytes to the instruction's size. */
263 insn->size += (uint8_t) size;
265 /* Store the new size to avoid infinite recursion in case instruction
266 * decode fails after length decode, which would set @insn->size to the
271 /* Try to decode the instruction again.
273 * If we fail again, we recursively retry again until we either fail to
274 * read more bytes or reach the maximum number of bytes for an
277 errcode = pt_ild_decode(insn, iext);
279 if (errcode != -pte_bad_insn)
282 /* If instruction length decode already determined the size,
283 * there's no point in reading more bytes.
285 if (insn->size != (uint8_t) size)
288 return pt_insn_decode_retry(insn, iext, image, asid);
291 /* We succeeded this time, so the instruction crosses image section
294 * This poses the question which isid to use for the instruction.
296 * To reconstruct exactly this instruction at a later time, we'd need to
297 * store all isids involved together with the number of bytes read for
298 * each isid. Since @insn already provides the exact bytes for this
299 * instruction, we assume that the isid will be used solely for source
300 * correlation. In this case, it should refer to the first byte of the
301 * instruction - as it already does.
308 int pt_insn_decode(struct pt_insn *insn, struct pt_insn_ext *iext,
309 struct pt_image *image, const struct pt_asid *asid)
314 return -pte_internal;
316 /* Read the memory at the current IP in the current address space. */
317 size = pt_image_read(image, &insn->isid, insn->raw, sizeof(insn->raw),
322 /* We initialize @insn->size to the maximal possible size. It will be
323 * set to the actual size during instruction decode.
325 insn->size = (uint8_t) size;
327 errcode = pt_ild_decode(insn, iext);
329 if (errcode != -pte_bad_insn)
332 /* If instruction length decode already determined the size,
333 * there's no point in reading more bytes.
335 if (insn->size != (uint8_t) size)
338 return pt_insn_decode_retry(insn, iext, image, asid);
344 int pt_insn_range_is_contiguous(uint64_t begin, uint64_t end,
345 enum pt_exec_mode mode, struct pt_image *image,
346 const struct pt_asid *asid, size_t steps)
348 struct pt_insn_ext iext;
351 memset(&insn, 0, sizeof(insn));
356 while (insn.ip != end) {
362 errcode = pt_insn_decode(&insn, &iext, image, asid);
366 errcode = pt_insn_next_ip(&insn.ip, &insn, &iext);