1 /*
2 * Copyright (c) 2014-2018, 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_packet_decoder.h"
30 #include "pt_decoder_function.h"
31 #include "pt_packet.h"
32 #include "pt_sync.h"
33 #include "pt_config.h"
34 #include "pt_opcodes.h"
35
36 #include <string.h>
37 #include <stdlib.h>
38
39
pt_pkt_decoder_init(struct pt_packet_decoder * decoder,const struct pt_config * config)40 int pt_pkt_decoder_init(struct pt_packet_decoder *decoder,
41 const struct pt_config *config)
42 {
43 int errcode;
44
45 if (!decoder || !config)
46 return -pte_invalid;
47
48 memset(decoder, 0, sizeof(*decoder));
49
50 errcode = pt_config_from_user(&decoder->config, config);
51 if (errcode < 0)
52 return errcode;
53
54 return 0;
55 }
56
pt_pkt_alloc_decoder(const struct pt_config * config)57 struct pt_packet_decoder *pt_pkt_alloc_decoder(const struct pt_config *config)
58 {
59 struct pt_packet_decoder *decoder;
60 int errcode;
61
62 decoder = malloc(sizeof(*decoder));
63 if (!decoder)
64 return NULL;
65
66 errcode = pt_pkt_decoder_init(decoder, config);
67 if (errcode < 0) {
68 free(decoder);
69 return NULL;
70 }
71
72 return decoder;
73 }
74
pt_pkt_decoder_fini(struct pt_packet_decoder * decoder)75 void pt_pkt_decoder_fini(struct pt_packet_decoder *decoder)
76 {
77 (void) decoder;
78
79 /* Nothing to do. */
80 }
81
pt_pkt_free_decoder(struct pt_packet_decoder * decoder)82 void pt_pkt_free_decoder(struct pt_packet_decoder *decoder)
83 {
84 pt_pkt_decoder_fini(decoder);
85 free(decoder);
86 }
87
pt_pkt_sync_forward(struct pt_packet_decoder * decoder)88 int pt_pkt_sync_forward(struct pt_packet_decoder *decoder)
89 {
90 const uint8_t *pos, *sync;
91 int errcode;
92
93 if (!decoder)
94 return -pte_invalid;
95
96 sync = decoder->sync;
97 pos = decoder->pos;
98 if (!pos)
99 pos = decoder->config.begin;
100
101 if (pos == sync)
102 pos += ptps_psb;
103
104 errcode = pt_sync_forward(&sync, pos, &decoder->config);
105 if (errcode < 0)
106 return errcode;
107
108 decoder->sync = sync;
109 decoder->pos = sync;
110
111 return 0;
112 }
113
pt_pkt_sync_backward(struct pt_packet_decoder * decoder)114 int pt_pkt_sync_backward(struct pt_packet_decoder *decoder)
115 {
116 const uint8_t *pos, *sync;
117 int errcode;
118
119 if (!decoder)
120 return -pte_invalid;
121
122 pos = decoder->pos;
123 if (!pos)
124 pos = decoder->config.end;
125
126 errcode = pt_sync_backward(&sync, pos, &decoder->config);
127 if (errcode < 0)
128 return errcode;
129
130 decoder->sync = sync;
131 decoder->pos = sync;
132
133 return 0;
134 }
135
pt_pkt_sync_set(struct pt_packet_decoder * decoder,uint64_t offset)136 int pt_pkt_sync_set(struct pt_packet_decoder *decoder, uint64_t offset)
137 {
138 const uint8_t *begin, *end, *pos;
139
140 if (!decoder)
141 return -pte_invalid;
142
143 begin = decoder->config.begin;
144 end = decoder->config.end;
145 pos = begin + offset;
146
147 if (end < pos || pos < begin)
148 return -pte_eos;
149
150 decoder->sync = pos;
151 decoder->pos = pos;
152
153 return 0;
154 }
155
pt_pkt_get_offset(const struct pt_packet_decoder * decoder,uint64_t * offset)156 int pt_pkt_get_offset(const struct pt_packet_decoder *decoder, uint64_t *offset)
157 {
158 const uint8_t *begin, *pos;
159
160 if (!decoder || !offset)
161 return -pte_invalid;
162
163 begin = decoder->config.begin;
164 pos = decoder->pos;
165
166 if (!pos)
167 return -pte_nosync;
168
169 *offset = pos - begin;
170 return 0;
171 }
172
pt_pkt_get_sync_offset(const struct pt_packet_decoder * decoder,uint64_t * offset)173 int pt_pkt_get_sync_offset(const struct pt_packet_decoder *decoder,
174 uint64_t *offset)
175 {
176 const uint8_t *begin, *sync;
177
178 if (!decoder || !offset)
179 return -pte_invalid;
180
181 begin = decoder->config.begin;
182 sync = decoder->sync;
183
184 if (!sync)
185 return -pte_nosync;
186
187 *offset = sync - begin;
188 return 0;
189 }
190
191 const struct pt_config *
pt_pkt_get_config(const struct pt_packet_decoder * decoder)192 pt_pkt_get_config(const struct pt_packet_decoder *decoder)
193 {
194 if (!decoder)
195 return NULL;
196
197 return &decoder->config;
198 }
199
pkt_to_user(struct pt_packet * upkt,size_t size,const struct pt_packet * pkt)200 static inline int pkt_to_user(struct pt_packet *upkt, size_t size,
201 const struct pt_packet *pkt)
202 {
203 if (!upkt || !pkt)
204 return -pte_internal;
205
206 if (upkt == pkt)
207 return 0;
208
209 /* Zero out any unknown bytes. */
210 if (sizeof(*pkt) < size) {
211 memset(upkt + sizeof(*pkt), 0, size - sizeof(*pkt));
212
213 size = sizeof(*pkt);
214 }
215
216 memcpy(upkt, pkt, size);
217
218 return 0;
219 }
220
pt_pkt_next(struct pt_packet_decoder * decoder,struct pt_packet * packet,size_t psize)221 int pt_pkt_next(struct pt_packet_decoder *decoder, struct pt_packet *packet,
222 size_t psize)
223 {
224 const struct pt_decoder_function *dfun;
225 struct pt_packet pkt, *ppkt;
226 int errcode, size;
227
228 if (!packet || !decoder)
229 return -pte_invalid;
230
231 ppkt = psize == sizeof(pkt) ? packet : &pkt;
232
233 errcode = pt_df_fetch(&dfun, decoder->pos, &decoder->config);
234 if (errcode < 0)
235 return errcode;
236
237 if (!dfun)
238 return -pte_internal;
239
240 if (!dfun->packet)
241 return -pte_internal;
242
243 size = dfun->packet(decoder, ppkt);
244 if (size < 0)
245 return size;
246
247 errcode = pkt_to_user(packet, psize, ppkt);
248 if (errcode < 0)
249 return errcode;
250
251 decoder->pos += size;
252
253 return size;
254 }
255
pt_pkt_decode_unknown(struct pt_packet_decoder * decoder,struct pt_packet * packet)256 int pt_pkt_decode_unknown(struct pt_packet_decoder *decoder,
257 struct pt_packet *packet)
258 {
259 int size;
260
261 if (!decoder)
262 return -pte_internal;
263
264 size = pt_pkt_read_unknown(packet, decoder->pos, &decoder->config);
265 if (size < 0)
266 return size;
267
268 return size;
269 }
270
pt_pkt_decode_pad(struct pt_packet_decoder * decoder,struct pt_packet * packet)271 int pt_pkt_decode_pad(struct pt_packet_decoder *decoder,
272 struct pt_packet *packet)
273 {
274 (void) decoder;
275
276 if (!packet)
277 return -pte_internal;
278
279 packet->type = ppt_pad;
280 packet->size = ptps_pad;
281
282 return ptps_pad;
283 }
284
pt_pkt_decode_psb(struct pt_packet_decoder * decoder,struct pt_packet * packet)285 int pt_pkt_decode_psb(struct pt_packet_decoder *decoder,
286 struct pt_packet *packet)
287 {
288 int size;
289
290 if (!decoder)
291 return -pte_internal;
292
293 size = pt_pkt_read_psb(decoder->pos, &decoder->config);
294 if (size < 0)
295 return size;
296
297 packet->type = ppt_psb;
298 packet->size = (uint8_t) size;
299
300 return size;
301 }
302
pt_pkt_decode_tip(struct pt_packet_decoder * decoder,struct pt_packet * packet)303 int pt_pkt_decode_tip(struct pt_packet_decoder *decoder,
304 struct pt_packet *packet)
305 {
306 int size;
307
308 if (!decoder || !packet)
309 return -pte_internal;
310
311 size = pt_pkt_read_ip(&packet->payload.ip, decoder->pos,
312 &decoder->config);
313 if (size < 0)
314 return size;
315
316 packet->type = ppt_tip;
317 packet->size = (uint8_t) size;
318
319 return size;
320 }
321
pt_pkt_decode_tnt_8(struct pt_packet_decoder * decoder,struct pt_packet * packet)322 int pt_pkt_decode_tnt_8(struct pt_packet_decoder *decoder,
323 struct pt_packet *packet)
324 {
325 int size;
326
327 if (!decoder || !packet)
328 return -pte_internal;
329
330 size = pt_pkt_read_tnt_8(&packet->payload.tnt, decoder->pos,
331 &decoder->config);
332 if (size < 0)
333 return size;
334
335 packet->type = ppt_tnt_8;
336 packet->size = (uint8_t) size;
337
338 return size;
339 }
340
pt_pkt_decode_tnt_64(struct pt_packet_decoder * decoder,struct pt_packet * packet)341 int pt_pkt_decode_tnt_64(struct pt_packet_decoder *decoder,
342 struct pt_packet *packet)
343 {
344 int size;
345
346 if (!decoder || !packet)
347 return -pte_internal;
348
349 size = pt_pkt_read_tnt_64(&packet->payload.tnt, decoder->pos,
350 &decoder->config);
351 if (size < 0)
352 return size;
353
354 packet->type = ppt_tnt_64;
355 packet->size = (uint8_t) size;
356
357 return size;
358 }
359
pt_pkt_decode_tip_pge(struct pt_packet_decoder * decoder,struct pt_packet * packet)360 int pt_pkt_decode_tip_pge(struct pt_packet_decoder *decoder,
361 struct pt_packet *packet)
362 {
363 int size;
364
365 if (!decoder || !packet)
366 return -pte_internal;
367
368 size = pt_pkt_read_ip(&packet->payload.ip, decoder->pos,
369 &decoder->config);
370 if (size < 0)
371 return size;
372
373 packet->type = ppt_tip_pge;
374 packet->size = (uint8_t) size;
375
376 return size;
377 }
378
pt_pkt_decode_tip_pgd(struct pt_packet_decoder * decoder,struct pt_packet * packet)379 int pt_pkt_decode_tip_pgd(struct pt_packet_decoder *decoder,
380 struct pt_packet *packet)
381 {
382 int size;
383
384 if (!decoder || !packet)
385 return -pte_internal;
386
387 size = pt_pkt_read_ip(&packet->payload.ip, decoder->pos,
388 &decoder->config);
389 if (size < 0)
390 return size;
391
392 packet->type = ppt_tip_pgd;
393 packet->size = (uint8_t) size;
394
395 return size;
396 }
397
pt_pkt_decode_fup(struct pt_packet_decoder * decoder,struct pt_packet * packet)398 int pt_pkt_decode_fup(struct pt_packet_decoder *decoder,
399 struct pt_packet *packet)
400 {
401 int size;
402
403 if (!decoder || !packet)
404 return -pte_internal;
405
406 size = pt_pkt_read_ip(&packet->payload.ip, decoder->pos,
407 &decoder->config);
408 if (size < 0)
409 return size;
410
411 packet->type = ppt_fup;
412 packet->size = (uint8_t) size;
413
414 return size;
415 }
416
pt_pkt_decode_pip(struct pt_packet_decoder * decoder,struct pt_packet * packet)417 int pt_pkt_decode_pip(struct pt_packet_decoder *decoder,
418 struct pt_packet *packet)
419 {
420 int size;
421
422 if (!decoder || !packet)
423 return -pte_internal;
424
425 size = pt_pkt_read_pip(&packet->payload.pip, decoder->pos,
426 &decoder->config);
427 if (size < 0)
428 return size;
429
430 packet->type = ppt_pip;
431 packet->size = (uint8_t) size;
432
433 return size;
434 }
435
pt_pkt_decode_ovf(struct pt_packet_decoder * decoder,struct pt_packet * packet)436 int pt_pkt_decode_ovf(struct pt_packet_decoder *decoder,
437 struct pt_packet *packet)
438 {
439 (void) decoder;
440
441 if (!packet)
442 return -pte_internal;
443
444 packet->type = ppt_ovf;
445 packet->size = ptps_ovf;
446
447 return ptps_ovf;
448 }
449
pt_pkt_decode_mode(struct pt_packet_decoder * decoder,struct pt_packet * packet)450 int pt_pkt_decode_mode(struct pt_packet_decoder *decoder,
451 struct pt_packet *packet)
452 {
453 int size;
454
455 if (!decoder || !packet)
456 return -pte_internal;
457
458 size = pt_pkt_read_mode(&packet->payload.mode, decoder->pos,
459 &decoder->config);
460 if (size < 0)
461 return size;
462
463 packet->type = ppt_mode;
464 packet->size = (uint8_t) size;
465
466 return size;
467 }
468
pt_pkt_decode_psbend(struct pt_packet_decoder * decoder,struct pt_packet * packet)469 int pt_pkt_decode_psbend(struct pt_packet_decoder *decoder,
470 struct pt_packet *packet)
471 {
472 (void) decoder;
473
474 if (!packet)
475 return -pte_internal;
476
477 packet->type = ppt_psbend;
478 packet->size = ptps_psbend;
479
480 return ptps_psbend;
481 }
482
pt_pkt_decode_tsc(struct pt_packet_decoder * decoder,struct pt_packet * packet)483 int pt_pkt_decode_tsc(struct pt_packet_decoder *decoder,
484 struct pt_packet *packet)
485 {
486 int size;
487
488 if (!decoder || !packet)
489 return -pte_internal;
490
491 size = pt_pkt_read_tsc(&packet->payload.tsc, decoder->pos,
492 &decoder->config);
493 if (size < 0)
494 return size;
495
496 packet->type = ppt_tsc;
497 packet->size = (uint8_t) size;
498
499 return size;
500 }
501
pt_pkt_decode_cbr(struct pt_packet_decoder * decoder,struct pt_packet * packet)502 int pt_pkt_decode_cbr(struct pt_packet_decoder *decoder,
503 struct pt_packet *packet)
504 {
505 int size;
506
507 if (!decoder || !packet)
508 return -pte_internal;
509
510 size = pt_pkt_read_cbr(&packet->payload.cbr, decoder->pos,
511 &decoder->config);
512 if (size < 0)
513 return size;
514
515 packet->type = ppt_cbr;
516 packet->size = (uint8_t) size;
517
518 return size;
519 }
520
pt_pkt_decode_tma(struct pt_packet_decoder * decoder,struct pt_packet * packet)521 int pt_pkt_decode_tma(struct pt_packet_decoder *decoder,
522 struct pt_packet *packet)
523 {
524 int size;
525
526 if (!decoder || !packet)
527 return -pte_internal;
528
529 size = pt_pkt_read_tma(&packet->payload.tma, decoder->pos,
530 &decoder->config);
531 if (size < 0)
532 return size;
533
534 packet->type = ppt_tma;
535 packet->size = (uint8_t) size;
536
537 return size;
538 }
539
pt_pkt_decode_mtc(struct pt_packet_decoder * decoder,struct pt_packet * packet)540 int pt_pkt_decode_mtc(struct pt_packet_decoder *decoder,
541 struct pt_packet *packet)
542 {
543 int size;
544
545 if (!decoder || !packet)
546 return -pte_internal;
547
548 size = pt_pkt_read_mtc(&packet->payload.mtc, decoder->pos,
549 &decoder->config);
550 if (size < 0)
551 return size;
552
553 packet->type = ppt_mtc;
554 packet->size = (uint8_t) size;
555
556 return size;
557 }
558
pt_pkt_decode_cyc(struct pt_packet_decoder * decoder,struct pt_packet * packet)559 int pt_pkt_decode_cyc(struct pt_packet_decoder *decoder,
560 struct pt_packet *packet)
561 {
562 int size;
563
564 if (!decoder || !packet)
565 return -pte_internal;
566
567 size = pt_pkt_read_cyc(&packet->payload.cyc, decoder->pos,
568 &decoder->config);
569 if (size < 0)
570 return size;
571
572 packet->type = ppt_cyc;
573 packet->size = (uint8_t) size;
574
575 return size;
576 }
577
pt_pkt_decode_stop(struct pt_packet_decoder * decoder,struct pt_packet * packet)578 int pt_pkt_decode_stop(struct pt_packet_decoder *decoder,
579 struct pt_packet *packet)
580 {
581 (void) decoder;
582
583 if (!packet)
584 return -pte_internal;
585
586 packet->type = ppt_stop;
587 packet->size = ptps_stop;
588
589 return ptps_stop;
590 }
591
pt_pkt_decode_vmcs(struct pt_packet_decoder * decoder,struct pt_packet * packet)592 int pt_pkt_decode_vmcs(struct pt_packet_decoder *decoder,
593 struct pt_packet *packet)
594 {
595 int size;
596
597 if (!decoder || !packet)
598 return -pte_internal;
599
600 size = pt_pkt_read_vmcs(&packet->payload.vmcs, decoder->pos,
601 &decoder->config);
602 if (size < 0)
603 return size;
604
605 packet->type = ppt_vmcs;
606 packet->size = (uint8_t) size;
607
608 return size;
609 }
610
pt_pkt_decode_mnt(struct pt_packet_decoder * decoder,struct pt_packet * packet)611 int pt_pkt_decode_mnt(struct pt_packet_decoder *decoder,
612 struct pt_packet *packet)
613 {
614 int size;
615
616 if (!decoder || !packet)
617 return -pte_internal;
618
619 size = pt_pkt_read_mnt(&packet->payload.mnt, decoder->pos,
620 &decoder->config);
621 if (size < 0)
622 return size;
623
624 packet->type = ppt_mnt;
625 packet->size = (uint8_t) size;
626
627 return size;
628 }
629
pt_pkt_decode_exstop(struct pt_packet_decoder * decoder,struct pt_packet * packet)630 int pt_pkt_decode_exstop(struct pt_packet_decoder *decoder,
631 struct pt_packet *packet)
632 {
633 int size;
634
635 if (!decoder || !packet)
636 return -pte_internal;
637
638 size = pt_pkt_read_exstop(&packet->payload.exstop, decoder->pos,
639 &decoder->config);
640 if (size < 0)
641 return size;
642
643 packet->type = ppt_exstop;
644 packet->size = (uint8_t) size;
645
646 return size;
647 }
648
pt_pkt_decode_mwait(struct pt_packet_decoder * decoder,struct pt_packet * packet)649 int pt_pkt_decode_mwait(struct pt_packet_decoder *decoder,
650 struct pt_packet *packet)
651 {
652 int size;
653
654 if (!decoder || !packet)
655 return -pte_internal;
656
657 size = pt_pkt_read_mwait(&packet->payload.mwait, decoder->pos,
658 &decoder->config);
659 if (size < 0)
660 return size;
661
662 packet->type = ppt_mwait;
663 packet->size = (uint8_t) size;
664
665 return size;
666 }
667
pt_pkt_decode_pwre(struct pt_packet_decoder * decoder,struct pt_packet * packet)668 int pt_pkt_decode_pwre(struct pt_packet_decoder *decoder,
669 struct pt_packet *packet)
670 {
671 int size;
672
673 if (!decoder || !packet)
674 return -pte_internal;
675
676 size = pt_pkt_read_pwre(&packet->payload.pwre, decoder->pos,
677 &decoder->config);
678 if (size < 0)
679 return size;
680
681 packet->type = ppt_pwre;
682 packet->size = (uint8_t) size;
683
684 return size;
685 }
686
pt_pkt_decode_pwrx(struct pt_packet_decoder * decoder,struct pt_packet * packet)687 int pt_pkt_decode_pwrx(struct pt_packet_decoder *decoder,
688 struct pt_packet *packet)
689 {
690 int size;
691
692 if (!decoder || !packet)
693 return -pte_internal;
694
695 size = pt_pkt_read_pwrx(&packet->payload.pwrx, decoder->pos,
696 &decoder->config);
697 if (size < 0)
698 return size;
699
700 packet->type = ppt_pwrx;
701 packet->size = (uint8_t) size;
702
703 return size;
704 }
705
pt_pkt_decode_ptw(struct pt_packet_decoder * decoder,struct pt_packet * packet)706 int pt_pkt_decode_ptw(struct pt_packet_decoder *decoder,
707 struct pt_packet *packet)
708 {
709 int size;
710
711 if (!decoder || !packet)
712 return -pte_internal;
713
714 size = pt_pkt_read_ptw(&packet->payload.ptw, decoder->pos,
715 &decoder->config);
716 if (size < 0)
717 return size;
718
719 packet->type = ppt_ptw;
720 packet->size = (uint8_t) size;
721
722 return size;
723 }
724