2 * Copyright (c) 2016-2019, 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 += (uint64_t) (int64_t)
191 iext->variant.branch.displacement;
197 return -pte_bad_query;
200 return -pte_bad_insn;
209 /* Retry decoding an instruction after a preceding decode error.
211 * Instruction length decode typically fails due to 'not enough
214 * This may be caused by partial updates of text sections
215 * represented via new image sections overlapping the original
216 * text section's image section. We stop reading memory at the
217 * end of the section so we do not read the full instruction if
218 * parts of it have been overwritten by the update.
220 * Try to read the remaining bytes and decode the instruction again. If we
221 * succeed, set @insn->truncated to indicate that the instruction is truncated
224 * Returns zero on success, a negative error code otherwise.
225 * Returns -pte_bad_insn if the instruction could not be decoded.
227 static int pt_insn_decode_retry(struct pt_insn *insn, struct pt_insn_ext *iext,
228 struct pt_image *image,
229 const struct pt_asid *asid)
231 int size, errcode, isid;
232 uint8_t isize, remaining;
235 return -pte_internal;
238 remaining = sizeof(insn->raw) - isize;
240 /* We failed for real if we already read the maximum number of bytes for
244 return -pte_bad_insn;
246 /* Read the remaining bytes from the image. */
247 size = pt_image_read(image, &isid, &insn->raw[isize], remaining, asid,
250 /* We should have gotten an error if we were not able to read at
251 * least one byte. Check this to guarantee termination.
254 return -pte_internal;
256 /* Preserve the original error if there are no more bytes. */
257 if (size == -pte_nomap)
258 size = -pte_bad_insn;
263 /* Add the newly read bytes to the instruction's size. */
264 insn->size += (uint8_t) size;
266 /* Store the new size to avoid infinite recursion in case instruction
267 * decode fails after length decode, which would set @insn->size to the
272 /* Try to decode the instruction again.
274 * If we fail again, we recursively retry again until we either fail to
275 * read more bytes or reach the maximum number of bytes for an
278 errcode = pt_ild_decode(insn, iext);
280 if (errcode != -pte_bad_insn)
283 /* If instruction length decode already determined the size,
284 * there's no point in reading more bytes.
286 if (insn->size != (uint8_t) size)
289 return pt_insn_decode_retry(insn, iext, image, asid);
292 /* We succeeded this time, so the instruction crosses image section
295 * This poses the question which isid to use for the instruction.
297 * To reconstruct exactly this instruction at a later time, we'd need to
298 * store all isids involved together with the number of bytes read for
299 * each isid. Since @insn already provides the exact bytes for this
300 * instruction, we assume that the isid will be used solely for source
301 * correlation. In this case, it should refer to the first byte of the
302 * instruction - as it already does.
309 int pt_insn_decode(struct pt_insn *insn, struct pt_insn_ext *iext,
310 struct pt_image *image, const struct pt_asid *asid)
315 return -pte_internal;
317 /* Read the memory at the current IP in the current address space. */
318 size = pt_image_read(image, &insn->isid, insn->raw, sizeof(insn->raw),
323 /* We initialize @insn->size to the maximal possible size. It will be
324 * set to the actual size during instruction decode.
326 insn->size = (uint8_t) size;
328 errcode = pt_ild_decode(insn, iext);
330 if (errcode != -pte_bad_insn)
333 /* If instruction length decode already determined the size,
334 * there's no point in reading more bytes.
336 if (insn->size != (uint8_t) size)
339 return pt_insn_decode_retry(insn, iext, image, asid);
345 int pt_insn_range_is_contiguous(uint64_t begin, uint64_t end,
346 enum pt_exec_mode mode, struct pt_image *image,
347 const struct pt_asid *asid, size_t steps)
349 struct pt_insn_ext iext;
352 memset(&insn, 0, sizeof(insn));
357 while (insn.ip != end) {
363 errcode = pt_insn_decode(&insn, &iext, image, asid);
367 errcode = pt_insn_next_ip(&insn.ip, &insn, &iext);