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_fp(void) 35 { 36 return f; 37 } 38 39 void intel_pt_log_enable(void) 40 { 41 intel_pt_enable_logging = true; 42 } 43 44 void intel_pt_log_disable(void) 45 { 46 if (f) 47 fflush(f); 48 intel_pt_enable_logging = false; 49 } 50 51 void intel_pt_log_set_name(const char *name) 52 { 53 strncpy(log_name, name, MAX_LOG_NAME - 5); 54 strcat(log_name, ".log"); 55 } 56 57 static void intel_pt_print_data(const unsigned char *buf, int len, uint64_t pos, 58 int indent) 59 { 60 int i; 61 62 for (i = 0; i < indent; i++) 63 fprintf(f, " "); 64 65 fprintf(f, " %08" PRIx64 ": ", pos); 66 for (i = 0; i < len; i++) 67 fprintf(f, " %02x", buf[i]); 68 for (; i < 16; i++) 69 fprintf(f, " "); 70 fprintf(f, " "); 71 } 72 73 static void intel_pt_print_no_data(uint64_t pos, int indent) 74 { 75 int i; 76 77 for (i = 0; i < indent; i++) 78 fprintf(f, " "); 79 80 fprintf(f, " %08" PRIx64 ": ", pos); 81 for (i = 0; i < 16; i++) 82 fprintf(f, " "); 83 fprintf(f, " "); 84 } 85 86 static int intel_pt_log_open(void) 87 { 88 if (!intel_pt_enable_logging) 89 return -1; 90 91 if (f) 92 return 0; 93 94 if (!log_name[0]) 95 return -1; 96 97 f = fopen(log_name, "w+"); 98 if (!f) { 99 intel_pt_enable_logging = false; 100 return -1; 101 } 102 103 return 0; 104 } 105 106 void __intel_pt_log_packet(const struct intel_pt_pkt *packet, int pkt_len, 107 uint64_t pos, const unsigned char *buf) 108 { 109 char desc[INTEL_PT_PKT_DESC_MAX]; 110 111 if (intel_pt_log_open()) 112 return; 113 114 intel_pt_print_data(buf, pkt_len, pos, 0); 115 intel_pt_pkt_desc(packet, desc, INTEL_PT_PKT_DESC_MAX); 116 fprintf(f, "%s\n", desc); 117 } 118 119 void __intel_pt_log_insn(struct intel_pt_insn *intel_pt_insn, uint64_t ip) 120 { 121 char desc[INTEL_PT_INSN_DESC_MAX]; 122 size_t len = intel_pt_insn->length; 123 124 if (intel_pt_log_open()) 125 return; 126 127 if (len > INTEL_PT_INSN_BUF_SZ) 128 len = INTEL_PT_INSN_BUF_SZ; 129 intel_pt_print_data(intel_pt_insn->buf, len, ip, 8); 130 if (intel_pt_insn_desc(intel_pt_insn, desc, INTEL_PT_INSN_DESC_MAX) > 0) 131 fprintf(f, "%s\n", desc); 132 else 133 fprintf(f, "Bad instruction!\n"); 134 } 135 136 void __intel_pt_log_insn_no_data(struct intel_pt_insn *intel_pt_insn, 137 uint64_t ip) 138 { 139 char desc[INTEL_PT_INSN_DESC_MAX]; 140 141 if (intel_pt_log_open()) 142 return; 143 144 intel_pt_print_no_data(ip, 8); 145 if (intel_pt_insn_desc(intel_pt_insn, desc, INTEL_PT_INSN_DESC_MAX) > 0) 146 fprintf(f, "%s\n", desc); 147 else 148 fprintf(f, "Bad instruction!\n"); 149 } 150 151 void __intel_pt_log(const char *fmt, ...) 152 { 153 va_list args; 154 155 if (intel_pt_log_open()) 156 return; 157 158 va_start(args, fmt); 159 vfprintf(f, fmt, args); 160 va_end(args); 161 } 162