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 #include "pt_insn.h"
30 #include "pt_ild.h"
31 #include "pt_image.h"
32 #include "pt_compiler.h"
33
34 #include "intel-pt.h"
35
36
pt_insn_changes_cpl(const struct pt_insn * insn,const struct pt_insn_ext * iext)37 int pt_insn_changes_cpl(const struct pt_insn *insn,
38 const struct pt_insn_ext *iext)
39 {
40 (void) insn;
41
42 if (!iext)
43 return 0;
44
45 switch (iext->iclass) {
46 default:
47 return 0;
48
49 case PTI_INST_INT:
50 case PTI_INST_INT3:
51 case PTI_INST_INT1:
52 case PTI_INST_INTO:
53 case PTI_INST_IRET:
54 case PTI_INST_SYSCALL:
55 case PTI_INST_SYSENTER:
56 case PTI_INST_SYSEXIT:
57 case PTI_INST_SYSRET:
58 return 1;
59 }
60 }
61
pt_insn_changes_cr3(const struct pt_insn * insn,const struct pt_insn_ext * iext)62 int pt_insn_changes_cr3(const struct pt_insn *insn,
63 const struct pt_insn_ext *iext)
64 {
65 (void) insn;
66
67 if (!iext)
68 return 0;
69
70 switch (iext->iclass) {
71 default:
72 return 0;
73
74 case PTI_INST_MOV_CR3:
75 return 1;
76 }
77 }
78
pt_insn_is_branch(const struct pt_insn * insn,const struct pt_insn_ext * iext)79 int pt_insn_is_branch(const struct pt_insn *insn,
80 const struct pt_insn_ext *iext)
81 {
82 (void) iext;
83
84 if (!insn)
85 return 0;
86
87 switch (insn->iclass) {
88 default:
89 return 0;
90
91 case ptic_call:
92 case ptic_return:
93 case ptic_jump:
94 case ptic_cond_jump:
95 case ptic_far_call:
96 case ptic_far_return:
97 case ptic_far_jump:
98 return 1;
99 }
100 }
101
pt_insn_is_far_branch(const struct pt_insn * insn,const struct pt_insn_ext * iext)102 int pt_insn_is_far_branch(const struct pt_insn *insn,
103 const struct pt_insn_ext *iext)
104 {
105 (void) iext;
106
107 if (!insn)
108 return 0;
109
110 switch (insn->iclass) {
111 default:
112 return 0;
113
114 case ptic_far_call:
115 case ptic_far_return:
116 case ptic_far_jump:
117 return 1;
118 }
119 }
120
pt_insn_binds_to_pip(const struct pt_insn * insn,const struct pt_insn_ext * iext)121 int pt_insn_binds_to_pip(const struct pt_insn *insn,
122 const struct pt_insn_ext *iext)
123 {
124 if (!iext)
125 return 0;
126
127 switch (iext->iclass) {
128 default:
129 return pt_insn_is_far_branch(insn, iext);
130
131 case PTI_INST_MOV_CR3:
132 case PTI_INST_VMLAUNCH:
133 case PTI_INST_VMRESUME:
134 return 1;
135 }
136 }
137
pt_insn_binds_to_vmcs(const struct pt_insn * insn,const struct pt_insn_ext * iext)138 int pt_insn_binds_to_vmcs(const struct pt_insn *insn,
139 const struct pt_insn_ext *iext)
140 {
141 if (!iext)
142 return 0;
143
144 switch (iext->iclass) {
145 default:
146 return pt_insn_is_far_branch(insn, iext);
147
148 case PTI_INST_VMPTRLD:
149 case PTI_INST_VMLAUNCH:
150 case PTI_INST_VMRESUME:
151 return 1;
152 }
153 }
154
pt_insn_is_ptwrite(const struct pt_insn * insn,const struct pt_insn_ext * iext)155 int pt_insn_is_ptwrite(const struct pt_insn *insn,
156 const struct pt_insn_ext *iext)
157 {
158 (void) iext;
159
160 if (!insn)
161 return 0;
162
163 switch (insn->iclass) {
164 default:
165 return 0;
166
167 case ptic_ptwrite:
168 return 1;
169 }
170 }
171
pt_insn_next_ip(uint64_t * pip,const struct pt_insn * insn,const struct pt_insn_ext * iext)172 int pt_insn_next_ip(uint64_t *pip, const struct pt_insn *insn,
173 const struct pt_insn_ext *iext)
174 {
175 uint64_t ip;
176
177 if (!insn || !iext)
178 return -pte_internal;
179
180 ip = insn->ip + insn->size;
181
182 switch (insn->iclass) {
183 case ptic_ptwrite:
184 case ptic_other:
185 break;
186
187 case ptic_call:
188 case ptic_jump:
189 if (iext->variant.branch.is_direct) {
190 ip += (uint64_t) (int64_t)
191 iext->variant.branch.displacement;
192 break;
193 }
194
195 fallthrough;
196 default:
197 return -pte_bad_query;
198
199 case ptic_error:
200 return -pte_bad_insn;
201 }
202
203 if (pip)
204 *pip = ip;
205
206 return 0;
207 }
208
209 /* Retry decoding an instruction after a preceding decode error.
210 *
211 * Instruction length decode typically fails due to 'not enough
212 * bytes'.
213 *
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.
219 *
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
222 * in @insn->isid.
223 *
224 * Returns zero on success, a negative error code otherwise.
225 * Returns -pte_bad_insn if the instruction could not be decoded.
226 */
pt_insn_decode_retry(struct pt_insn * insn,struct pt_insn_ext * iext,struct pt_image * image,const struct pt_asid * asid)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)
230 {
231 int size, errcode, isid;
232 uint8_t isize, remaining;
233
234 if (!insn)
235 return -pte_internal;
236
237 isize = insn->size;
238 remaining = sizeof(insn->raw) - isize;
239
240 /* We failed for real if we already read the maximum number of bytes for
241 * an instruction.
242 */
243 if (!remaining)
244 return -pte_bad_insn;
245
246 /* Read the remaining bytes from the image. */
247 size = pt_image_read(image, &isid, &insn->raw[isize], remaining, asid,
248 insn->ip + isize);
249 if (size <= 0) {
250 /* We should have gotten an error if we were not able to read at
251 * least one byte. Check this to guarantee termination.
252 */
253 if (!size)
254 return -pte_internal;
255
256 /* Preserve the original error if there are no more bytes. */
257 if (size == -pte_nomap)
258 size = -pte_bad_insn;
259
260 return size;
261 }
262
263 /* Add the newly read bytes to the instruction's size. */
264 insn->size += (uint8_t) size;
265
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
268 * actual length.
269 */
270 size = insn->size;
271
272 /* Try to decode the instruction again.
273 *
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
276 * instruction.
277 */
278 errcode = pt_ild_decode(insn, iext);
279 if (errcode < 0) {
280 if (errcode != -pte_bad_insn)
281 return errcode;
282
283 /* If instruction length decode already determined the size,
284 * there's no point in reading more bytes.
285 */
286 if (insn->size != (uint8_t) size)
287 return errcode;
288
289 return pt_insn_decode_retry(insn, iext, image, asid);
290 }
291
292 /* We succeeded this time, so the instruction crosses image section
293 * boundaries.
294 *
295 * This poses the question which isid to use for the instruction.
296 *
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.
303 */
304 insn->truncated = 1;
305
306 return errcode;
307 }
308
pt_insn_decode(struct pt_insn * insn,struct pt_insn_ext * iext,struct pt_image * image,const struct pt_asid * asid)309 int pt_insn_decode(struct pt_insn *insn, struct pt_insn_ext *iext,
310 struct pt_image *image, const struct pt_asid *asid)
311 {
312 int size, errcode;
313
314 if (!insn)
315 return -pte_internal;
316
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),
319 asid, insn->ip);
320 if (size < 0)
321 return size;
322
323 /* We initialize @insn->size to the maximal possible size. It will be
324 * set to the actual size during instruction decode.
325 */
326 insn->size = (uint8_t) size;
327
328 errcode = pt_ild_decode(insn, iext);
329 if (errcode < 0) {
330 if (errcode != -pte_bad_insn)
331 return errcode;
332
333 /* If instruction length decode already determined the size,
334 * there's no point in reading more bytes.
335 */
336 if (insn->size != (uint8_t) size)
337 return errcode;
338
339 return pt_insn_decode_retry(insn, iext, image, asid);
340 }
341
342 return errcode;
343 }
344
pt_insn_range_is_contiguous(uint64_t begin,uint64_t end,enum pt_exec_mode mode,struct pt_image * image,const struct pt_asid * asid,size_t steps)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)
348 {
349 struct pt_insn_ext iext;
350 struct pt_insn insn;
351
352 memset(&insn, 0, sizeof(insn));
353
354 insn.mode = mode;
355 insn.ip = begin;
356
357 while (insn.ip != end) {
358 int errcode;
359
360 if (!steps--)
361 return 0;
362
363 errcode = pt_insn_decode(&insn, &iext, image, asid);
364 if (errcode < 0)
365 return errcode;
366
367 errcode = pt_insn_next_ip(&insn.ip, &insn, &iext);
368 if (errcode < 0)
369 return errcode;
370 }
371
372 return 1;
373 }
374