Loading...
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * intel_pt_log.c: Intel Processor Trace support
4 * Copyright (c) 2013-2014, Intel Corporation.
5 */
6
7#include <stdio.h>
8#include <stdint.h>
9#include <inttypes.h>
10#include <stdarg.h>
11#include <stdbool.h>
12#include <string.h>
13
14#include "intel-pt-log.h"
15#include "intel-pt-insn-decoder.h"
16
17#include "intel-pt-pkt-decoder.h"
18
19#define MAX_LOG_NAME 256
20
21static FILE *f;
22static char log_name[MAX_LOG_NAME];
23bool intel_pt_enable_logging;
24
25void *intel_pt_log_fp(void)
26{
27 return f;
28}
29
30void intel_pt_log_enable(void)
31{
32 intel_pt_enable_logging = true;
33}
34
35void intel_pt_log_disable(void)
36{
37 if (f)
38 fflush(f);
39 intel_pt_enable_logging = false;
40}
41
42void intel_pt_log_set_name(const char *name)
43{
44 strncpy(log_name, name, MAX_LOG_NAME - 5);
45 strcat(log_name, ".log");
46}
47
48static void intel_pt_print_data(const unsigned char *buf, int len, uint64_t pos,
49 int indent)
50{
51 int i;
52
53 for (i = 0; i < indent; i++)
54 fprintf(f, " ");
55
56 fprintf(f, " %08" PRIx64 ": ", pos);
57 for (i = 0; i < len; i++)
58 fprintf(f, " %02x", buf[i]);
59 for (; i < 16; i++)
60 fprintf(f, " ");
61 fprintf(f, " ");
62}
63
64static void intel_pt_print_no_data(uint64_t pos, int indent)
65{
66 int i;
67
68 for (i = 0; i < indent; i++)
69 fprintf(f, " ");
70
71 fprintf(f, " %08" PRIx64 ": ", pos);
72 for (i = 0; i < 16; i++)
73 fprintf(f, " ");
74 fprintf(f, " ");
75}
76
77static int intel_pt_log_open(void)
78{
79 if (!intel_pt_enable_logging)
80 return -1;
81
82 if (f)
83 return 0;
84
85 if (!log_name[0])
86 return -1;
87
88 f = fopen(log_name, "w+");
89 if (!f) {
90 intel_pt_enable_logging = false;
91 return -1;
92 }
93
94 return 0;
95}
96
97void __intel_pt_log_packet(const struct intel_pt_pkt *packet, int pkt_len,
98 uint64_t pos, const unsigned char *buf)
99{
100 char desc[INTEL_PT_PKT_DESC_MAX];
101
102 if (intel_pt_log_open())
103 return;
104
105 intel_pt_print_data(buf, pkt_len, pos, 0);
106 intel_pt_pkt_desc(packet, desc, INTEL_PT_PKT_DESC_MAX);
107 fprintf(f, "%s\n", desc);
108}
109
110void __intel_pt_log_insn(struct intel_pt_insn *intel_pt_insn, uint64_t ip)
111{
112 char desc[INTEL_PT_INSN_DESC_MAX];
113 size_t len = intel_pt_insn->length;
114
115 if (intel_pt_log_open())
116 return;
117
118 if (len > INTEL_PT_INSN_BUF_SZ)
119 len = INTEL_PT_INSN_BUF_SZ;
120 intel_pt_print_data(intel_pt_insn->buf, len, ip, 8);
121 if (intel_pt_insn_desc(intel_pt_insn, desc, INTEL_PT_INSN_DESC_MAX) > 0)
122 fprintf(f, "%s\n", desc);
123 else
124 fprintf(f, "Bad instruction!\n");
125}
126
127void __intel_pt_log_insn_no_data(struct intel_pt_insn *intel_pt_insn,
128 uint64_t ip)
129{
130 char desc[INTEL_PT_INSN_DESC_MAX];
131
132 if (intel_pt_log_open())
133 return;
134
135 intel_pt_print_no_data(ip, 8);
136 if (intel_pt_insn_desc(intel_pt_insn, desc, INTEL_PT_INSN_DESC_MAX) > 0)
137 fprintf(f, "%s\n", desc);
138 else
139 fprintf(f, "Bad instruction!\n");
140}
141
142void __intel_pt_log(const char *fmt, ...)
143{
144 va_list args;
145
146 if (intel_pt_log_open())
147 return;
148
149 va_start(args, fmt);
150 vfprintf(f, fmt, args);
151 va_end(args);
152}
1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * intel_pt_log.c: Intel Processor Trace support
4 * Copyright (c) 2013-2014, Intel Corporation.
5 */
6
7#include <stdio.h>
8#include <stdlib.h>
9#include <stdint.h>
10#include <inttypes.h>
11#include <stdarg.h>
12#include <stdbool.h>
13#include <string.h>
14
15#include <linux/zalloc.h>
16#include <linux/kernel.h>
17
18#include "intel-pt-log.h"
19#include "intel-pt-insn-decoder.h"
20
21#include "intel-pt-pkt-decoder.h"
22
23#define MAX_LOG_NAME 256
24
25#define DFLT_BUF_SZ (16 * 1024)
26
27struct log_buf {
28 char *buf;
29 size_t buf_sz;
30 size_t head;
31 bool wrapped;
32 FILE *backend;
33};
34
35static FILE *f;
36static char log_name[MAX_LOG_NAME];
37bool intel_pt_enable_logging;
38static bool intel_pt_dump_log_on_error;
39static unsigned int intel_pt_log_on_error_size;
40static struct log_buf log_buf;
41
42void *intel_pt_log_fp(void)
43{
44 return f;
45}
46
47void intel_pt_log_enable(bool dump_log_on_error, unsigned int log_on_error_size)
48{
49 intel_pt_enable_logging = true;
50 intel_pt_dump_log_on_error = dump_log_on_error;
51 intel_pt_log_on_error_size = log_on_error_size;
52}
53
54void intel_pt_log_disable(void)
55{
56 if (f)
57 fflush(f);
58 intel_pt_enable_logging = false;
59}
60
61void intel_pt_log_set_name(const char *name)
62{
63 strncpy(log_name, name, MAX_LOG_NAME - 5);
64 strcat(log_name, ".log");
65}
66
67static void intel_pt_print_data(const unsigned char *buf, int len, uint64_t pos,
68 int indent)
69{
70 int i;
71
72 for (i = 0; i < indent; i++)
73 fprintf(f, " ");
74
75 fprintf(f, " %08" PRIx64 ": ", pos);
76 for (i = 0; i < len; i++)
77 fprintf(f, " %02x", buf[i]);
78 for (; i < 16; i++)
79 fprintf(f, " ");
80 fprintf(f, " ");
81}
82
83static void intel_pt_print_no_data(uint64_t pos, int indent)
84{
85 int i;
86
87 for (i = 0; i < indent; i++)
88 fprintf(f, " ");
89
90 fprintf(f, " %08" PRIx64 ": ", pos);
91 for (i = 0; i < 16; i++)
92 fprintf(f, " ");
93 fprintf(f, " ");
94}
95
96static ssize_t log_buf__write(void *cookie, const char *buf, size_t size)
97{
98 struct log_buf *b = cookie;
99 size_t sz = size;
100
101 if (!b->buf)
102 return size;
103
104 while (sz) {
105 size_t space = b->buf_sz - b->head;
106 size_t n = min(space, sz);
107
108 memcpy(b->buf + b->head, buf, n);
109 sz -= n;
110 buf += n;
111 b->head += n;
112 if (sz && b->head >= b->buf_sz) {
113 b->head = 0;
114 b->wrapped = true;
115 }
116 }
117 return size;
118}
119
120static int log_buf__close(void *cookie)
121{
122 struct log_buf *b = cookie;
123
124 zfree(&b->buf);
125 return 0;
126}
127
128static FILE *log_buf__open(struct log_buf *b, FILE *backend, unsigned int sz)
129{
130 cookie_io_functions_t fns = {
131 .write = log_buf__write,
132 .close = log_buf__close,
133 };
134 FILE *file;
135
136 memset(b, 0, sizeof(*b));
137 b->buf_sz = sz;
138 b->buf = malloc(b->buf_sz);
139 b->backend = backend;
140 file = fopencookie(b, "a", fns);
141 if (!file)
142 zfree(&b->buf);
143 return file;
144}
145
146static bool remove_first_line(const char **p, size_t *n)
147{
148 for (; *n && **p != '\n'; ++*p, --*n)
149 ;
150 if (*n) {
151 *p += 1;
152 *n -= 1;
153 return true;
154 }
155 return false;
156}
157
158static void write_lines(const char *p, size_t n, FILE *fp, bool *remove_first)
159{
160 if (*remove_first)
161 *remove_first = !remove_first_line(&p, &n);
162 fwrite(p, n, 1, fp);
163}
164
165static void log_buf__dump(struct log_buf *b)
166{
167 bool remove_first = false;
168
169 if (!b->buf)
170 return;
171
172 fflush(f); /* Could update b->head and b->wrapped */
173 fprintf(b->backend, "Dumping debug log buffer\n");
174 if (b->wrapped) {
175 remove_first = true;
176 write_lines(b->buf + b->head, b->buf_sz - b->head, b->backend, &remove_first);
177 }
178 write_lines(b->buf, b->head, b->backend, &remove_first);
179 fprintf(b->backend, "End of debug log buffer dump\n");
180
181 b->head = 0;
182 b->wrapped = false;
183}
184
185void intel_pt_log_dump_buf(void)
186{
187 log_buf__dump(&log_buf);
188}
189
190static int intel_pt_log_open(void)
191{
192 if (!intel_pt_enable_logging)
193 return -1;
194
195 if (f)
196 return 0;
197
198 if (log_name[0])
199 f = fopen(log_name, "w+");
200 else
201 f = stdout;
202 if (f && intel_pt_dump_log_on_error)
203 f = log_buf__open(&log_buf, f, intel_pt_log_on_error_size);
204 if (!f) {
205 intel_pt_enable_logging = false;
206 return -1;
207 }
208
209 return 0;
210}
211
212void __intel_pt_log_packet(const struct intel_pt_pkt *packet, int pkt_len,
213 uint64_t pos, const unsigned char *buf)
214{
215 char desc[INTEL_PT_PKT_DESC_MAX];
216
217 if (intel_pt_log_open())
218 return;
219
220 intel_pt_print_data(buf, pkt_len, pos, 0);
221 intel_pt_pkt_desc(packet, desc, INTEL_PT_PKT_DESC_MAX);
222 fprintf(f, "%s\n", desc);
223}
224
225void __intel_pt_log_insn(struct intel_pt_insn *intel_pt_insn, uint64_t ip)
226{
227 char desc[INTEL_PT_INSN_DESC_MAX];
228 size_t len = intel_pt_insn->length;
229
230 if (intel_pt_log_open())
231 return;
232
233 if (len > INTEL_PT_INSN_BUF_SZ)
234 len = INTEL_PT_INSN_BUF_SZ;
235 intel_pt_print_data(intel_pt_insn->buf, len, ip, 8);
236 if (intel_pt_insn_desc(intel_pt_insn, desc, INTEL_PT_INSN_DESC_MAX) > 0)
237 fprintf(f, "%s\n", desc);
238 else
239 fprintf(f, "Bad instruction!\n");
240}
241
242void __intel_pt_log_insn_no_data(struct intel_pt_insn *intel_pt_insn,
243 uint64_t ip)
244{
245 char desc[INTEL_PT_INSN_DESC_MAX];
246
247 if (intel_pt_log_open())
248 return;
249
250 intel_pt_print_no_data(ip, 8);
251 if (intel_pt_insn_desc(intel_pt_insn, desc, INTEL_PT_INSN_DESC_MAX) > 0)
252 fprintf(f, "%s\n", desc);
253 else
254 fprintf(f, "Bad instruction!\n");
255}
256
257void __intel_pt_log(const char *fmt, ...)
258{
259 va_list args;
260
261 if (intel_pt_log_open())
262 return;
263
264 va_start(args, fmt);
265 vfprintf(f, fmt, args);
266 va_end(args);
267}