1/* 2 * intel_pt_log.c: Intel Processor Trace support 3 * Copyright (c) 2013-2014, Intel Corporation. 4 * 5 * This program is free software; you can redistribute it and/or modify it 6 * under the terms and conditions of the GNU General Public License, 7 * version 2, as published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12 * more details. 13 * 14 */ 15 16#include <stdio.h> 17#include <stdint.h> 18#include <inttypes.h> 19#include <stdarg.h> 20#include <stdbool.h> 21#include <string.h> 22 23#include "intel-pt-log.h" 24#include "intel-pt-insn-decoder.h" 25 26#include "intel-pt-pkt-decoder.h" 27 28#define MAX_LOG_NAME 256 29 30static FILE *f; 31static char log_name[MAX_LOG_NAME]; 32bool intel_pt_enable_logging; 33 34void intel_pt_log_enable(void) 35{ 36 intel_pt_enable_logging = true; 37} 38 39void intel_pt_log_disable(void) 40{ 41 if (f) 42 fflush(f); 43 intel_pt_enable_logging = false; 44} 45 46void intel_pt_log_set_name(const char *name) 47{ 48 strncpy(log_name, name, MAX_LOG_NAME - 5); 49 strcat(log_name, ".log"); 50} 51 52static void intel_pt_print_data(const unsigned char *buf, int len, uint64_t pos, 53 int indent) 54{ 55 int i; 56 57 for (i = 0; i < indent; i++) 58 fprintf(f, " "); 59 60 fprintf(f, " %08" PRIx64 ": ", pos); 61 for (i = 0; i < len; i++) 62 fprintf(f, " %02x", buf[i]); 63 for (; i < 16; i++) 64 fprintf(f, " "); 65 fprintf(f, " "); 66} 67 68static void intel_pt_print_no_data(uint64_t pos, 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 < 16; i++) 77 fprintf(f, " "); 78 fprintf(f, " "); 79} 80 81static int intel_pt_log_open(void) 82{ 83 if (!intel_pt_enable_logging) 84 return -1; 85 86 if (f) 87 return 0; 88 89 if (!log_name[0]) 90 return -1; 91 92 f = fopen(log_name, "w+"); 93 if (!f) { 94 intel_pt_enable_logging = false; 95 return -1; 96 } 97 98 return 0; 99} 100 101void __intel_pt_log_packet(const struct intel_pt_pkt *packet, int pkt_len, 102 uint64_t pos, const unsigned char *buf) 103{ 104 char desc[INTEL_PT_PKT_DESC_MAX]; 105 106 if (intel_pt_log_open()) 107 return; 108 109 intel_pt_print_data(buf, pkt_len, pos, 0); 110 intel_pt_pkt_desc(packet, desc, INTEL_PT_PKT_DESC_MAX); 111 fprintf(f, "%s\n", desc); 112} 113 114void __intel_pt_log_insn(struct intel_pt_insn *intel_pt_insn, uint64_t ip) 115{ 116 char desc[INTEL_PT_INSN_DESC_MAX]; 117 size_t len = intel_pt_insn->length; 118 119 if (intel_pt_log_open()) 120 return; 121 122 if (len > INTEL_PT_INSN_DBG_BUF_SZ) 123 len = INTEL_PT_INSN_DBG_BUF_SZ; 124 intel_pt_print_data(intel_pt_insn->buf, len, ip, 8); 125 if (intel_pt_insn_desc(intel_pt_insn, desc, INTEL_PT_INSN_DESC_MAX) > 0) 126 fprintf(f, "%s\n", desc); 127 else 128 fprintf(f, "Bad instruction!\n"); 129} 130 131void __intel_pt_log_insn_no_data(struct intel_pt_insn *intel_pt_insn, 132 uint64_t ip) 133{ 134 char desc[INTEL_PT_INSN_DESC_MAX]; 135 136 if (intel_pt_log_open()) 137 return; 138 139 intel_pt_print_no_data(ip, 8); 140 if (intel_pt_insn_desc(intel_pt_insn, desc, INTEL_PT_INSN_DESC_MAX) > 0) 141 fprintf(f, "%s\n", desc); 142 else 143 fprintf(f, "Bad instruction!\n"); 144} 145 146void __intel_pt_log(const char *fmt, ...) 147{ 148 va_list args; 149 150 if (intel_pt_log_open()) 151 return; 152 153 va_start(args, fmt); 154 vfprintf(f, fmt, args); 155 va_end(args); 156} 157