brintos

brintos / linux-shallow public Read only

0
0
Text · 5.1 KiB · ef55d62 Raw
268 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 * intel_pt_log.c: Intel Processor Trace support4 * 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 25624 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	else201		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	else239		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	else254		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}268