1 // SPDX-License-Identifier: GPL-2.0 2 #include "data.h" 3 #include "debug.h" 4 #include "header.h" 5 #include "session.h" 6 #include "stat.h" 7 #include "tool.h" 8 #include "tsc.h" 9 #include <sys/mman.h> 10 #include <unistd.h> 11 12 #ifdef HAVE_ZSTD_SUPPORT 13 static int perf_session__process_compressed_event(struct perf_session *session, 14 union perf_event *event, u64 file_offset, 15 const char *file_path) 16 { 17 void *src; 18 size_t decomp_size, src_size; 19 u64 decomp_last_rem = 0; 20 size_t mmap_len, decomp_len = session->header.env.comp_mmap_len; 21 struct decomp *decomp, *decomp_last = session->active_decomp->decomp_last; 22 23 if (decomp_last) { 24 decomp_last_rem = decomp_last->size - decomp_last->head; 25 decomp_len += decomp_last_rem; 26 } 27 28 mmap_len = sizeof(struct decomp) + decomp_len; 29 decomp = mmap(NULL, mmap_len, PROT_READ|PROT_WRITE, 30 MAP_ANONYMOUS|MAP_PRIVATE, -1, 0); 31 if (decomp == MAP_FAILED) { 32 pr_err("Couldn't allocate memory for decompression\n"); 33 return -1; 34 } 35 36 decomp->file_pos = file_offset; 37 decomp->file_path = file_path; 38 decomp->mmap_len = mmap_len; 39 decomp->head = 0; 40 41 if (decomp_last_rem) { 42 memcpy(decomp->data, &(decomp_last->data[decomp_last->head]), decomp_last_rem); 43 decomp->size = decomp_last_rem; 44 } 45 46 src = (void *)event + sizeof(struct perf_record_compressed); 47 src_size = event->pack.header.size - sizeof(struct perf_record_compressed); 48 49 decomp_size = zstd_decompress_stream(session->active_decomp->zstd_decomp, src, src_size, 50 &(decomp->data[decomp_last_rem]), decomp_len - decomp_last_rem); 51 if (!decomp_size) { 52 munmap(decomp, mmap_len); 53 pr_err("Couldn't decompress data\n"); 54 return -1; 55 } 56 57 decomp->size += decomp_size; 58 59 if (session->active_decomp->decomp == NULL) 60 session->active_decomp->decomp = decomp; 61 else 62 session->active_decomp->decomp_last->next = decomp; 63 64 session->active_decomp->decomp_last = decomp; 65 66 pr_debug("decomp (B): %zd to %zd\n", src_size, decomp_size); 67 68 return 0; 69 } 70 #endif 71 72 static int process_event_synth_tracing_data_stub(struct perf_session *session 73 __maybe_unused, 74 union perf_event *event 75 __maybe_unused) 76 { 77 dump_printf(": unhandled!\n"); 78 return 0; 79 } 80 81 static int process_event_synth_attr_stub(const struct perf_tool *tool __maybe_unused, 82 union perf_event *event __maybe_unused, 83 struct evlist **pevlist 84 __maybe_unused) 85 { 86 dump_printf(": unhandled!\n"); 87 return 0; 88 } 89 90 static int process_event_synth_event_update_stub(const struct perf_tool *tool __maybe_unused, 91 union perf_event *event __maybe_unused, 92 struct evlist **pevlist 93 __maybe_unused) 94 { 95 if (dump_trace) 96 perf_event__fprintf_event_update(event, stdout); 97 98 dump_printf(": unhandled!\n"); 99 return 0; 100 } 101 102 int process_event_sample_stub(const struct perf_tool *tool __maybe_unused, 103 union perf_event *event __maybe_unused, 104 struct perf_sample *sample __maybe_unused, 105 struct evsel *evsel __maybe_unused, 106 struct machine *machine __maybe_unused) 107 { 108 dump_printf(": unhandled!\n"); 109 return 0; 110 } 111 112 static int process_event_stub(const struct perf_tool *tool __maybe_unused, 113 union perf_event *event __maybe_unused, 114 struct perf_sample *sample __maybe_unused, 115 struct machine *machine __maybe_unused) 116 { 117 dump_printf(": unhandled!\n"); 118 return 0; 119 } 120 121 static int process_finished_round_stub(const struct perf_tool *tool __maybe_unused, 122 union perf_event *event __maybe_unused, 123 struct ordered_events *oe __maybe_unused) 124 { 125 dump_printf(": unhandled!\n"); 126 return 0; 127 } 128 129 static int skipn(int fd, off_t n) 130 { 131 char buf[4096]; 132 ssize_t ret; 133 134 while (n > 0) { 135 ret = read(fd, buf, min(n, (off_t)sizeof(buf))); 136 if (ret <= 0) 137 return ret; 138 n -= ret; 139 } 140 141 return 0; 142 } 143 144 static s64 process_event_auxtrace_stub(struct perf_session *session __maybe_unused, 145 union perf_event *event) 146 { 147 dump_printf(": unhandled!\n"); 148 if (perf_data__is_pipe(session->data)) 149 skipn(perf_data__fd(session->data), event->auxtrace.size); 150 return event->auxtrace.size; 151 } 152 153 static int process_event_op2_stub(struct perf_session *session __maybe_unused, 154 union perf_event *event __maybe_unused) 155 { 156 dump_printf(": unhandled!\n"); 157 return 0; 158 } 159 160 161 static 162 int process_event_thread_map_stub(struct perf_session *session __maybe_unused, 163 union perf_event *event __maybe_unused) 164 { 165 if (dump_trace) 166 perf_event__fprintf_thread_map(event, stdout); 167 168 dump_printf(": unhandled!\n"); 169 return 0; 170 } 171 172 static 173 int process_event_cpu_map_stub(struct perf_session *session __maybe_unused, 174 union perf_event *event __maybe_unused) 175 { 176 if (dump_trace) 177 perf_event__fprintf_cpu_map(event, stdout); 178 179 dump_printf(": unhandled!\n"); 180 return 0; 181 } 182 183 static 184 int process_event_stat_config_stub(struct perf_session *session __maybe_unused, 185 union perf_event *event __maybe_unused) 186 { 187 if (dump_trace) 188 perf_event__fprintf_stat_config(event, stdout); 189 190 dump_printf(": unhandled!\n"); 191 return 0; 192 } 193 194 static int process_stat_stub(struct perf_session *perf_session __maybe_unused, 195 union perf_event *event) 196 { 197 if (dump_trace) 198 perf_event__fprintf_stat(event, stdout); 199 200 dump_printf(": unhandled!\n"); 201 return 0; 202 } 203 204 static int process_stat_round_stub(struct perf_session *perf_session __maybe_unused, 205 union perf_event *event) 206 { 207 if (dump_trace) 208 perf_event__fprintf_stat_round(event, stdout); 209 210 dump_printf(": unhandled!\n"); 211 return 0; 212 } 213 214 static int process_event_time_conv_stub(struct perf_session *perf_session __maybe_unused, 215 union perf_event *event) 216 { 217 if (dump_trace) 218 perf_event__fprintf_time_conv(event, stdout); 219 220 dump_printf(": unhandled!\n"); 221 return 0; 222 } 223 224 static int perf_session__process_compressed_event_stub(struct perf_session *session __maybe_unused, 225 union perf_event *event __maybe_unused, 226 u64 file_offset __maybe_unused, 227 const char *file_path __maybe_unused) 228 { 229 dump_printf(": unhandled!\n"); 230 return 0; 231 } 232 233 void perf_tool__init(struct perf_tool *tool, bool ordered_events) 234 { 235 tool->ordered_events = ordered_events; 236 tool->ordering_requires_timestamps = false; 237 tool->namespace_events = false; 238 tool->cgroup_events = false; 239 tool->no_warn = false; 240 tool->show_feat_hdr = SHOW_FEAT_NO_HEADER; 241 242 tool->sample = process_event_sample_stub; 243 tool->mmap = process_event_stub; 244 tool->mmap2 = process_event_stub; 245 tool->comm = process_event_stub; 246 tool->namespaces = process_event_stub; 247 tool->cgroup = process_event_stub; 248 tool->fork = process_event_stub; 249 tool->exit = process_event_stub; 250 tool->lost = perf_event__process_lost; 251 tool->lost_samples = perf_event__process_lost_samples; 252 tool->aux = perf_event__process_aux; 253 tool->itrace_start = perf_event__process_itrace_start; 254 tool->context_switch = perf_event__process_switch; 255 tool->ksymbol = perf_event__process_ksymbol; 256 tool->bpf = perf_event__process_bpf; 257 tool->text_poke = perf_event__process_text_poke; 258 tool->aux_output_hw_id = perf_event__process_aux_output_hw_id; 259 tool->read = process_event_sample_stub; 260 tool->throttle = process_event_stub; 261 tool->unthrottle = process_event_stub; 262 tool->attr = process_event_synth_attr_stub; 263 tool->event_update = process_event_synth_event_update_stub; 264 tool->tracing_data = process_event_synth_tracing_data_stub; 265 tool->build_id = process_event_op2_stub; 266 267 if (ordered_events) 268 tool->finished_round = perf_event__process_finished_round; 269 else 270 tool->finished_round = process_finished_round_stub; 271 272 tool->id_index = process_event_op2_stub; 273 tool->auxtrace_info = process_event_op2_stub; 274 tool->auxtrace = process_event_auxtrace_stub; 275 tool->auxtrace_error = process_event_op2_stub; 276 tool->thread_map = process_event_thread_map_stub; 277 tool->cpu_map = process_event_cpu_map_stub; 278 tool->stat_config = process_event_stat_config_stub; 279 tool->stat = process_stat_stub; 280 tool->stat_round = process_stat_round_stub; 281 tool->time_conv = process_event_time_conv_stub; 282 tool->feature = process_event_op2_stub; 283 #ifdef HAVE_ZSTD_SUPPORT 284 tool->compressed = perf_session__process_compressed_event; 285 #else 286 tool->compressed = perf_session__process_compressed_event_stub; 287 #endif 288 tool->finished_init = process_event_op2_stub; 289 } 290 291 bool perf_tool__compressed_is_stub(const struct perf_tool *tool) 292 { 293 return tool->compressed == perf_session__process_compressed_event_stub; 294 } 295