~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/tools/perf/util/intel-pt-decoder/intel-pt-log.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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 
 27 struct log_buf {
 28         char                    *buf;
 29         size_t                  buf_sz;
 30         size_t                  head;
 31         bool                    wrapped;
 32         FILE                    *backend;
 33 };
 34 
 35 static FILE *f;
 36 static char log_name[MAX_LOG_NAME];
 37 bool intel_pt_enable_logging;
 38 static bool intel_pt_dump_log_on_error;
 39 static unsigned int intel_pt_log_on_error_size;
 40 static struct log_buf log_buf;
 41 
 42 void *intel_pt_log_fp(void)
 43 {
 44         return f;
 45 }
 46 
 47 void 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 
 54 void intel_pt_log_disable(void)
 55 {
 56         if (f)
 57                 fflush(f);
 58         intel_pt_enable_logging = false;
 59 }
 60 
 61 void 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 
 67 static 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 
 83 static 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 
 96 static 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 
120 static int log_buf__close(void *cookie)
121 {
122         struct log_buf *b = cookie;
123 
124         zfree(&b->buf);
125         return 0;
126 }
127 
128 static 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 
146 static 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 
158 static 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 
165 static 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 
185 void intel_pt_log_dump_buf(void)
186 {
187         log_buf__dump(&log_buf);
188 }
189 
190 static 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 
212 void __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 
225 void __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 
242 void __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 
257 void __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 }
268 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php