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 30 static FILE *f; 31 static char log_name[MAX_LOG_NAME]; 32 bool intel_pt_enable_logging; 33 34 void intel_pt_log_enable(void) 35 { 36 intel_pt_enable_logging = true; 37 } 38 39 void intel_pt_log_disable(void) 40 { 41 if (f) 42 fflush(f); 43 intel_pt_enable_logging = false; 44 } 45 46 void 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 52 static 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 68 static 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 81 static 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 101 void __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 114 void __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 131 void __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 146 void __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