]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/processor-trace/libipt/src/pt_last_ip.c
Merge OpenSSL 1.1.1d.
[FreeBSD/FreeBSD.git] / contrib / processor-trace / libipt / src / pt_last_ip.c
1 /*
2  * Copyright (c) 2013-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_last_ip.h"
30
31 #include "intel-pt.h"
32
33
34 void pt_last_ip_init(struct pt_last_ip *last_ip)
35 {
36         if (!last_ip)
37                 return;
38
39         last_ip->ip = 0ull;
40         last_ip->have_ip = 0;
41         last_ip->suppressed = 0;
42 }
43
44 int pt_last_ip_query(uint64_t *ip, const struct pt_last_ip *last_ip)
45 {
46         if (!last_ip)
47                 return -pte_internal;
48
49         if (!last_ip->have_ip) {
50                 if (ip)
51                         *ip = 0ull;
52                 return -pte_noip;
53         }
54
55         if (last_ip->suppressed) {
56                 if (ip)
57                         *ip = 0ull;
58                 return -pte_ip_suppressed;
59         }
60
61         if (ip)
62                 *ip = last_ip->ip;
63
64         return 0;
65 }
66
67 /* Sign-extend a uint64_t value. */
68 static uint64_t sext(uint64_t val, uint8_t sign)
69 {
70         uint64_t signbit, mask;
71
72         signbit = 1ull << (sign - 1);
73         mask = ~0ull << sign;
74
75         return val & signbit ? val | mask : val & ~mask;
76 }
77
78 int pt_last_ip_update_ip(struct pt_last_ip *last_ip,
79                          const struct pt_packet_ip *packet,
80                          const struct pt_config *config)
81 {
82         (void) config;
83
84         if (!last_ip || !packet)
85                 return -pte_internal;
86
87         switch (packet->ipc) {
88         case pt_ipc_suppressed:
89                 last_ip->suppressed = 1;
90                 return 0;
91
92         case pt_ipc_sext_48:
93                 last_ip->ip = sext(packet->ip, 48);
94                 last_ip->have_ip = 1;
95                 last_ip->suppressed = 0;
96                 return 0;
97
98         case pt_ipc_update_16:
99                 last_ip->ip = (last_ip->ip & ~0xffffull)
100                         | (packet->ip & 0xffffull);
101                 last_ip->have_ip = 1;
102                 last_ip->suppressed = 0;
103                 return 0;
104
105         case pt_ipc_update_32:
106                 last_ip->ip = (last_ip->ip & ~0xffffffffull)
107                         | (packet->ip & 0xffffffffull);
108                 last_ip->have_ip = 1;
109                 last_ip->suppressed = 0;
110                 return 0;
111
112         case pt_ipc_update_48:
113                 last_ip->ip = (last_ip->ip & ~0xffffffffffffull)
114                         | (packet->ip & 0xffffffffffffull);
115                 last_ip->have_ip = 1;
116                 last_ip->suppressed = 0;
117                 return 0;
118
119         case pt_ipc_full:
120                 last_ip->ip = packet->ip;
121                 last_ip->have_ip = 1;
122                 last_ip->suppressed = 0;
123                 return 0;
124         }
125
126         return -pte_bad_packet;
127 }