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}
153