Back to home page

OSCL-LXR

 
 

    


0001 #include <errno.h>
0002 #include <fcntl.h>
0003 #include <inttypes.h>
0004 #include <linux/kernel.h>
0005 #include <linux/types.h>
0006 #include <perf/cpumap.h>
0007 #include <sys/types.h>
0008 #include <sys/stat.h>
0009 #include <unistd.h>
0010 #include <uapi/linux/mman.h> /* To get things like MAP_HUGETLB even on older libc headers */
0011 #include <linux/perf_event.h>
0012 #include <linux/zalloc.h>
0013 #include "cpumap.h"
0014 #include "dso.h"
0015 #include "event.h"
0016 #include "debug.h"
0017 #include "hist.h"
0018 #include "machine.h"
0019 #include "sort.h"
0020 #include "string2.h"
0021 #include "strlist.h"
0022 #include "thread.h"
0023 #include "thread_map.h"
0024 #include "time-utils.h"
0025 #include <linux/ctype.h>
0026 #include "map.h"
0027 #include "util/namespaces.h"
0028 #include "symbol.h"
0029 #include "symbol/kallsyms.h"
0030 #include "asm/bug.h"
0031 #include "stat.h"
0032 #include "session.h"
0033 #include "bpf-event.h"
0034 #include "print_binary.h"
0035 #include "tool.h"
0036 #include "../perf.h"
0037 
0038 static const char *perf_event__names[] = {
0039     [0]                 = "TOTAL",
0040     [PERF_RECORD_MMAP]          = "MMAP",
0041     [PERF_RECORD_MMAP2]         = "MMAP2",
0042     [PERF_RECORD_LOST]          = "LOST",
0043     [PERF_RECORD_COMM]          = "COMM",
0044     [PERF_RECORD_EXIT]          = "EXIT",
0045     [PERF_RECORD_THROTTLE]          = "THROTTLE",
0046     [PERF_RECORD_UNTHROTTLE]        = "UNTHROTTLE",
0047     [PERF_RECORD_FORK]          = "FORK",
0048     [PERF_RECORD_READ]          = "READ",
0049     [PERF_RECORD_SAMPLE]            = "SAMPLE",
0050     [PERF_RECORD_AUX]           = "AUX",
0051     [PERF_RECORD_ITRACE_START]      = "ITRACE_START",
0052     [PERF_RECORD_LOST_SAMPLES]      = "LOST_SAMPLES",
0053     [PERF_RECORD_SWITCH]            = "SWITCH",
0054     [PERF_RECORD_SWITCH_CPU_WIDE]       = "SWITCH_CPU_WIDE",
0055     [PERF_RECORD_NAMESPACES]        = "NAMESPACES",
0056     [PERF_RECORD_KSYMBOL]           = "KSYMBOL",
0057     [PERF_RECORD_BPF_EVENT]         = "BPF_EVENT",
0058     [PERF_RECORD_CGROUP]            = "CGROUP",
0059     [PERF_RECORD_TEXT_POKE]         = "TEXT_POKE",
0060     [PERF_RECORD_AUX_OUTPUT_HW_ID]      = "AUX_OUTPUT_HW_ID",
0061     [PERF_RECORD_HEADER_ATTR]       = "ATTR",
0062     [PERF_RECORD_HEADER_EVENT_TYPE]     = "EVENT_TYPE",
0063     [PERF_RECORD_HEADER_TRACING_DATA]   = "TRACING_DATA",
0064     [PERF_RECORD_HEADER_BUILD_ID]       = "BUILD_ID",
0065     [PERF_RECORD_FINISHED_ROUND]        = "FINISHED_ROUND",
0066     [PERF_RECORD_ID_INDEX]          = "ID_INDEX",
0067     [PERF_RECORD_AUXTRACE_INFO]     = "AUXTRACE_INFO",
0068     [PERF_RECORD_AUXTRACE]          = "AUXTRACE",
0069     [PERF_RECORD_AUXTRACE_ERROR]        = "AUXTRACE_ERROR",
0070     [PERF_RECORD_THREAD_MAP]        = "THREAD_MAP",
0071     [PERF_RECORD_CPU_MAP]           = "CPU_MAP",
0072     [PERF_RECORD_STAT_CONFIG]       = "STAT_CONFIG",
0073     [PERF_RECORD_STAT]          = "STAT",
0074     [PERF_RECORD_STAT_ROUND]        = "STAT_ROUND",
0075     [PERF_RECORD_EVENT_UPDATE]      = "EVENT_UPDATE",
0076     [PERF_RECORD_TIME_CONV]         = "TIME_CONV",
0077     [PERF_RECORD_HEADER_FEATURE]        = "FEATURE",
0078     [PERF_RECORD_COMPRESSED]        = "COMPRESSED",
0079     [PERF_RECORD_FINISHED_INIT]     = "FINISHED_INIT",
0080 };
0081 
0082 const char *perf_event__name(unsigned int id)
0083 {
0084     if (id >= ARRAY_SIZE(perf_event__names))
0085         return "INVALID";
0086     if (!perf_event__names[id])
0087         return "UNKNOWN";
0088     return perf_event__names[id];
0089 }
0090 
0091 struct process_symbol_args {
0092     const char *name;
0093     u64    start;
0094 };
0095 
0096 static int find_symbol_cb(void *arg, const char *name, char type,
0097               u64 start)
0098 {
0099     struct process_symbol_args *args = arg;
0100 
0101     /*
0102      * Must be a function or at least an alias, as in PARISC64, where "_text" is
0103      * an 'A' to the same address as "_stext".
0104      */
0105     if (!(kallsyms__is_function(type) ||
0106           type == 'A') || strcmp(name, args->name))
0107         return 0;
0108 
0109     args->start = start;
0110     return 1;
0111 }
0112 
0113 int kallsyms__get_function_start(const char *kallsyms_filename,
0114                  const char *symbol_name, u64 *addr)
0115 {
0116     struct process_symbol_args args = { .name = symbol_name, };
0117 
0118     if (kallsyms__parse(kallsyms_filename, &args, find_symbol_cb) <= 0)
0119         return -1;
0120 
0121     *addr = args.start;
0122     return 0;
0123 }
0124 
0125 void perf_event__read_stat_config(struct perf_stat_config *config,
0126                   struct perf_record_stat_config *event)
0127 {
0128     unsigned i;
0129 
0130     for (i = 0; i < event->nr; i++) {
0131 
0132         switch (event->data[i].tag) {
0133 #define CASE(__term, __val)                 \
0134         case PERF_STAT_CONFIG_TERM__##__term:       \
0135             config->__val = event->data[i].val; \
0136             break;
0137 
0138         CASE(AGGR_MODE, aggr_mode)
0139         CASE(SCALE,     scale)
0140         CASE(INTERVAL,  interval)
0141 #undef CASE
0142         default:
0143             pr_warning("unknown stat config term %" PRI_lu64 "\n",
0144                    event->data[i].tag);
0145         }
0146     }
0147 }
0148 
0149 size_t perf_event__fprintf_comm(union perf_event *event, FILE *fp)
0150 {
0151     const char *s;
0152 
0153     if (event->header.misc & PERF_RECORD_MISC_COMM_EXEC)
0154         s = " exec";
0155     else
0156         s = "";
0157 
0158     return fprintf(fp, "%s: %s:%d/%d\n", s, event->comm.comm, event->comm.pid, event->comm.tid);
0159 }
0160 
0161 size_t perf_event__fprintf_namespaces(union perf_event *event, FILE *fp)
0162 {
0163     size_t ret = 0;
0164     struct perf_ns_link_info *ns_link_info;
0165     u32 nr_namespaces, idx;
0166 
0167     ns_link_info = event->namespaces.link_info;
0168     nr_namespaces = event->namespaces.nr_namespaces;
0169 
0170     ret += fprintf(fp, " %d/%d - nr_namespaces: %u\n\t\t[",
0171                event->namespaces.pid,
0172                event->namespaces.tid,
0173                nr_namespaces);
0174 
0175     for (idx = 0; idx < nr_namespaces; idx++) {
0176         if (idx && (idx % 4 == 0))
0177             ret += fprintf(fp, "\n\t\t ");
0178 
0179         ret  += fprintf(fp, "%u/%s: %" PRIu64 "/%#" PRIx64 "%s", idx,
0180                 perf_ns__name(idx), (u64)ns_link_info[idx].dev,
0181                 (u64)ns_link_info[idx].ino,
0182                 ((idx + 1) != nr_namespaces) ? ", " : "]\n");
0183     }
0184 
0185     return ret;
0186 }
0187 
0188 size_t perf_event__fprintf_cgroup(union perf_event *event, FILE *fp)
0189 {
0190     return fprintf(fp, " cgroup: %" PRI_lu64 " %s\n",
0191                event->cgroup.id, event->cgroup.path);
0192 }
0193 
0194 int perf_event__process_comm(struct perf_tool *tool __maybe_unused,
0195                  union perf_event *event,
0196                  struct perf_sample *sample,
0197                  struct machine *machine)
0198 {
0199     return machine__process_comm_event(machine, event, sample);
0200 }
0201 
0202 int perf_event__process_namespaces(struct perf_tool *tool __maybe_unused,
0203                    union perf_event *event,
0204                    struct perf_sample *sample,
0205                    struct machine *machine)
0206 {
0207     return machine__process_namespaces_event(machine, event, sample);
0208 }
0209 
0210 int perf_event__process_cgroup(struct perf_tool *tool __maybe_unused,
0211                    union perf_event *event,
0212                    struct perf_sample *sample,
0213                    struct machine *machine)
0214 {
0215     return machine__process_cgroup_event(machine, event, sample);
0216 }
0217 
0218 int perf_event__process_lost(struct perf_tool *tool __maybe_unused,
0219                  union perf_event *event,
0220                  struct perf_sample *sample,
0221                  struct machine *machine)
0222 {
0223     return machine__process_lost_event(machine, event, sample);
0224 }
0225 
0226 int perf_event__process_aux(struct perf_tool *tool __maybe_unused,
0227                 union perf_event *event,
0228                 struct perf_sample *sample __maybe_unused,
0229                 struct machine *machine)
0230 {
0231     return machine__process_aux_event(machine, event);
0232 }
0233 
0234 int perf_event__process_itrace_start(struct perf_tool *tool __maybe_unused,
0235                      union perf_event *event,
0236                      struct perf_sample *sample __maybe_unused,
0237                      struct machine *machine)
0238 {
0239     return machine__process_itrace_start_event(machine, event);
0240 }
0241 
0242 int perf_event__process_aux_output_hw_id(struct perf_tool *tool __maybe_unused,
0243                      union perf_event *event,
0244                      struct perf_sample *sample __maybe_unused,
0245                      struct machine *machine)
0246 {
0247     return machine__process_aux_output_hw_id_event(machine, event);
0248 }
0249 
0250 int perf_event__process_lost_samples(struct perf_tool *tool __maybe_unused,
0251                      union perf_event *event,
0252                      struct perf_sample *sample,
0253                      struct machine *machine)
0254 {
0255     return machine__process_lost_samples_event(machine, event, sample);
0256 }
0257 
0258 int perf_event__process_switch(struct perf_tool *tool __maybe_unused,
0259                    union perf_event *event,
0260                    struct perf_sample *sample __maybe_unused,
0261                    struct machine *machine)
0262 {
0263     return machine__process_switch_event(machine, event);
0264 }
0265 
0266 int perf_event__process_ksymbol(struct perf_tool *tool __maybe_unused,
0267                 union perf_event *event,
0268                 struct perf_sample *sample __maybe_unused,
0269                 struct machine *machine)
0270 {
0271     return machine__process_ksymbol(machine, event, sample);
0272 }
0273 
0274 int perf_event__process_bpf(struct perf_tool *tool __maybe_unused,
0275                 union perf_event *event,
0276                 struct perf_sample *sample,
0277                 struct machine *machine)
0278 {
0279     return machine__process_bpf(machine, event, sample);
0280 }
0281 
0282 int perf_event__process_text_poke(struct perf_tool *tool __maybe_unused,
0283                   union perf_event *event,
0284                   struct perf_sample *sample,
0285                   struct machine *machine)
0286 {
0287     return machine__process_text_poke(machine, event, sample);
0288 }
0289 
0290 size_t perf_event__fprintf_mmap(union perf_event *event, FILE *fp)
0291 {
0292     return fprintf(fp, " %d/%d: [%#" PRI_lx64 "(%#" PRI_lx64 ") @ %#" PRI_lx64 "]: %c %s\n",
0293                event->mmap.pid, event->mmap.tid, event->mmap.start,
0294                event->mmap.len, event->mmap.pgoff,
0295                (event->header.misc & PERF_RECORD_MISC_MMAP_DATA) ? 'r' : 'x',
0296                event->mmap.filename);
0297 }
0298 
0299 size_t perf_event__fprintf_mmap2(union perf_event *event, FILE *fp)
0300 {
0301     if (event->header.misc & PERF_RECORD_MISC_MMAP_BUILD_ID) {
0302         char sbuild_id[SBUILD_ID_SIZE];
0303         struct build_id bid;
0304 
0305         build_id__init(&bid, event->mmap2.build_id,
0306                    event->mmap2.build_id_size);
0307         build_id__sprintf(&bid, sbuild_id);
0308 
0309         return fprintf(fp, " %d/%d: [%#" PRI_lx64 "(%#" PRI_lx64 ") @ %#" PRI_lx64
0310                    " <%s>]: %c%c%c%c %s\n",
0311                    event->mmap2.pid, event->mmap2.tid, event->mmap2.start,
0312                    event->mmap2.len, event->mmap2.pgoff, sbuild_id,
0313                    (event->mmap2.prot & PROT_READ) ? 'r' : '-',
0314                    (event->mmap2.prot & PROT_WRITE) ? 'w' : '-',
0315                    (event->mmap2.prot & PROT_EXEC) ? 'x' : '-',
0316                    (event->mmap2.flags & MAP_SHARED) ? 's' : 'p',
0317                    event->mmap2.filename);
0318     } else {
0319         return fprintf(fp, " %d/%d: [%#" PRI_lx64 "(%#" PRI_lx64 ") @ %#" PRI_lx64
0320                    " %02x:%02x %"PRI_lu64" %"PRI_lu64"]: %c%c%c%c %s\n",
0321                    event->mmap2.pid, event->mmap2.tid, event->mmap2.start,
0322                    event->mmap2.len, event->mmap2.pgoff, event->mmap2.maj,
0323                    event->mmap2.min, event->mmap2.ino,
0324                    event->mmap2.ino_generation,
0325                    (event->mmap2.prot & PROT_READ) ? 'r' : '-',
0326                    (event->mmap2.prot & PROT_WRITE) ? 'w' : '-',
0327                    (event->mmap2.prot & PROT_EXEC) ? 'x' : '-',
0328                    (event->mmap2.flags & MAP_SHARED) ? 's' : 'p',
0329                    event->mmap2.filename);
0330     }
0331 }
0332 
0333 size_t perf_event__fprintf_thread_map(union perf_event *event, FILE *fp)
0334 {
0335     struct perf_thread_map *threads = thread_map__new_event(&event->thread_map);
0336     size_t ret;
0337 
0338     ret = fprintf(fp, " nr: ");
0339 
0340     if (threads)
0341         ret += thread_map__fprintf(threads, fp);
0342     else
0343         ret += fprintf(fp, "failed to get threads from event\n");
0344 
0345     perf_thread_map__put(threads);
0346     return ret;
0347 }
0348 
0349 size_t perf_event__fprintf_cpu_map(union perf_event *event, FILE *fp)
0350 {
0351     struct perf_cpu_map *cpus = cpu_map__new_data(&event->cpu_map.data);
0352     size_t ret;
0353 
0354     ret = fprintf(fp, ": ");
0355 
0356     if (cpus)
0357         ret += cpu_map__fprintf(cpus, fp);
0358     else
0359         ret += fprintf(fp, "failed to get cpumap from event\n");
0360 
0361     perf_cpu_map__put(cpus);
0362     return ret;
0363 }
0364 
0365 int perf_event__process_mmap(struct perf_tool *tool __maybe_unused,
0366                  union perf_event *event,
0367                  struct perf_sample *sample,
0368                  struct machine *machine)
0369 {
0370     return machine__process_mmap_event(machine, event, sample);
0371 }
0372 
0373 int perf_event__process_mmap2(struct perf_tool *tool __maybe_unused,
0374                  union perf_event *event,
0375                  struct perf_sample *sample,
0376                  struct machine *machine)
0377 {
0378     return machine__process_mmap2_event(machine, event, sample);
0379 }
0380 
0381 size_t perf_event__fprintf_task(union perf_event *event, FILE *fp)
0382 {
0383     return fprintf(fp, "(%d:%d):(%d:%d)\n",
0384                event->fork.pid, event->fork.tid,
0385                event->fork.ppid, event->fork.ptid);
0386 }
0387 
0388 int perf_event__process_fork(struct perf_tool *tool __maybe_unused,
0389                  union perf_event *event,
0390                  struct perf_sample *sample,
0391                  struct machine *machine)
0392 {
0393     return machine__process_fork_event(machine, event, sample);
0394 }
0395 
0396 int perf_event__process_exit(struct perf_tool *tool __maybe_unused,
0397                  union perf_event *event,
0398                  struct perf_sample *sample,
0399                  struct machine *machine)
0400 {
0401     return machine__process_exit_event(machine, event, sample);
0402 }
0403 
0404 size_t perf_event__fprintf_aux(union perf_event *event, FILE *fp)
0405 {
0406     return fprintf(fp, " offset: %#"PRI_lx64" size: %#"PRI_lx64" flags: %#"PRI_lx64" [%s%s%s]\n",
0407                event->aux.aux_offset, event->aux.aux_size,
0408                event->aux.flags,
0409                event->aux.flags & PERF_AUX_FLAG_TRUNCATED ? "T" : "",
0410                event->aux.flags & PERF_AUX_FLAG_OVERWRITE ? "O" : "",
0411                event->aux.flags & PERF_AUX_FLAG_PARTIAL   ? "P" : "");
0412 }
0413 
0414 size_t perf_event__fprintf_itrace_start(union perf_event *event, FILE *fp)
0415 {
0416     return fprintf(fp, " pid: %u tid: %u\n",
0417                event->itrace_start.pid, event->itrace_start.tid);
0418 }
0419 
0420 size_t perf_event__fprintf_aux_output_hw_id(union perf_event *event, FILE *fp)
0421 {
0422     return fprintf(fp, " hw_id: %#"PRI_lx64"\n",
0423                event->aux_output_hw_id.hw_id);
0424 }
0425 
0426 size_t perf_event__fprintf_switch(union perf_event *event, FILE *fp)
0427 {
0428     bool out = event->header.misc & PERF_RECORD_MISC_SWITCH_OUT;
0429     const char *in_out = !out ? "IN         " :
0430         !(event->header.misc & PERF_RECORD_MISC_SWITCH_OUT_PREEMPT) ?
0431                     "OUT        " : "OUT preempt";
0432 
0433     if (event->header.type == PERF_RECORD_SWITCH)
0434         return fprintf(fp, " %s\n", in_out);
0435 
0436     return fprintf(fp, " %s  %s pid/tid: %5d/%-5d\n",
0437                in_out, out ? "next" : "prev",
0438                event->context_switch.next_prev_pid,
0439                event->context_switch.next_prev_tid);
0440 }
0441 
0442 static size_t perf_event__fprintf_lost(union perf_event *event, FILE *fp)
0443 {
0444     return fprintf(fp, " lost %" PRI_lu64 "\n", event->lost.lost);
0445 }
0446 
0447 size_t perf_event__fprintf_ksymbol(union perf_event *event, FILE *fp)
0448 {
0449     return fprintf(fp, " addr %" PRI_lx64 " len %u type %u flags 0x%x name %s\n",
0450                event->ksymbol.addr, event->ksymbol.len,
0451                event->ksymbol.ksym_type,
0452                event->ksymbol.flags, event->ksymbol.name);
0453 }
0454 
0455 size_t perf_event__fprintf_bpf(union perf_event *event, FILE *fp)
0456 {
0457     return fprintf(fp, " type %u, flags %u, id %u\n",
0458                event->bpf.type, event->bpf.flags, event->bpf.id);
0459 }
0460 
0461 static int text_poke_printer(enum binary_printer_ops op, unsigned int val,
0462                  void *extra, FILE *fp)
0463 {
0464     bool old = *(bool *)extra;
0465 
0466     switch ((int)op) {
0467     case BINARY_PRINT_LINE_BEGIN:
0468         return fprintf(fp, "            %s bytes:", old ? "Old" : "New");
0469     case BINARY_PRINT_NUM_DATA:
0470         return fprintf(fp, " %02x", val);
0471     case BINARY_PRINT_LINE_END:
0472         return fprintf(fp, "\n");
0473     default:
0474         return 0;
0475     }
0476 }
0477 
0478 size_t perf_event__fprintf_text_poke(union perf_event *event, struct machine *machine, FILE *fp)
0479 {
0480     struct perf_record_text_poke_event *tp = &event->text_poke;
0481     size_t ret;
0482     bool old;
0483 
0484     ret = fprintf(fp, " %" PRI_lx64 " ", tp->addr);
0485     if (machine) {
0486         struct addr_location al;
0487 
0488         al.map = maps__find(machine__kernel_maps(machine), tp->addr);
0489         if (al.map && map__load(al.map) >= 0) {
0490             al.addr = al.map->map_ip(al.map, tp->addr);
0491             al.sym = map__find_symbol(al.map, al.addr);
0492             if (al.sym)
0493                 ret += symbol__fprintf_symname_offs(al.sym, &al, fp);
0494         }
0495     }
0496     ret += fprintf(fp, " old len %u new len %u\n", tp->old_len, tp->new_len);
0497     old = true;
0498     ret += binary__fprintf(tp->bytes, tp->old_len, 16, text_poke_printer,
0499                    &old, fp);
0500     old = false;
0501     ret += binary__fprintf(tp->bytes + tp->old_len, tp->new_len, 16,
0502                    text_poke_printer, &old, fp);
0503     return ret;
0504 }
0505 
0506 size_t perf_event__fprintf(union perf_event *event, struct machine *machine, FILE *fp)
0507 {
0508     size_t ret = fprintf(fp, "PERF_RECORD_%s",
0509                  perf_event__name(event->header.type));
0510 
0511     switch (event->header.type) {
0512     case PERF_RECORD_COMM:
0513         ret += perf_event__fprintf_comm(event, fp);
0514         break;
0515     case PERF_RECORD_FORK:
0516     case PERF_RECORD_EXIT:
0517         ret += perf_event__fprintf_task(event, fp);
0518         break;
0519     case PERF_RECORD_MMAP:
0520         ret += perf_event__fprintf_mmap(event, fp);
0521         break;
0522     case PERF_RECORD_NAMESPACES:
0523         ret += perf_event__fprintf_namespaces(event, fp);
0524         break;
0525     case PERF_RECORD_CGROUP:
0526         ret += perf_event__fprintf_cgroup(event, fp);
0527         break;
0528     case PERF_RECORD_MMAP2:
0529         ret += perf_event__fprintf_mmap2(event, fp);
0530         break;
0531     case PERF_RECORD_AUX:
0532         ret += perf_event__fprintf_aux(event, fp);
0533         break;
0534     case PERF_RECORD_ITRACE_START:
0535         ret += perf_event__fprintf_itrace_start(event, fp);
0536         break;
0537     case PERF_RECORD_SWITCH:
0538     case PERF_RECORD_SWITCH_CPU_WIDE:
0539         ret += perf_event__fprintf_switch(event, fp);
0540         break;
0541     case PERF_RECORD_LOST:
0542         ret += perf_event__fprintf_lost(event, fp);
0543         break;
0544     case PERF_RECORD_KSYMBOL:
0545         ret += perf_event__fprintf_ksymbol(event, fp);
0546         break;
0547     case PERF_RECORD_BPF_EVENT:
0548         ret += perf_event__fprintf_bpf(event, fp);
0549         break;
0550     case PERF_RECORD_TEXT_POKE:
0551         ret += perf_event__fprintf_text_poke(event, machine, fp);
0552         break;
0553     case PERF_RECORD_AUX_OUTPUT_HW_ID:
0554         ret += perf_event__fprintf_aux_output_hw_id(event, fp);
0555         break;
0556     default:
0557         ret += fprintf(fp, "\n");
0558     }
0559 
0560     return ret;
0561 }
0562 
0563 int perf_event__process(struct perf_tool *tool __maybe_unused,
0564             union perf_event *event,
0565             struct perf_sample *sample,
0566             struct machine *machine)
0567 {
0568     return machine__process_event(machine, event, sample);
0569 }
0570 
0571 struct map *thread__find_map(struct thread *thread, u8 cpumode, u64 addr,
0572                  struct addr_location *al)
0573 {
0574     struct maps *maps = thread->maps;
0575     struct machine *machine = maps->machine;
0576     bool load_map = false;
0577 
0578     al->maps = maps;
0579     al->thread = thread;
0580     al->addr = addr;
0581     al->cpumode = cpumode;
0582     al->filtered = 0;
0583 
0584     if (machine == NULL) {
0585         al->map = NULL;
0586         return NULL;
0587     }
0588 
0589     if (cpumode == PERF_RECORD_MISC_KERNEL && perf_host) {
0590         al->level = 'k';
0591         al->maps = maps = machine__kernel_maps(machine);
0592         load_map = true;
0593     } else if (cpumode == PERF_RECORD_MISC_USER && perf_host) {
0594         al->level = '.';
0595     } else if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest) {
0596         al->level = 'g';
0597         al->maps = maps = machine__kernel_maps(machine);
0598         load_map = true;
0599     } else if (cpumode == PERF_RECORD_MISC_GUEST_USER && perf_guest) {
0600         al->level = 'u';
0601     } else {
0602         al->level = 'H';
0603         al->map = NULL;
0604 
0605         if ((cpumode == PERF_RECORD_MISC_GUEST_USER ||
0606             cpumode == PERF_RECORD_MISC_GUEST_KERNEL) &&
0607             !perf_guest)
0608             al->filtered |= (1 << HIST_FILTER__GUEST);
0609         if ((cpumode == PERF_RECORD_MISC_USER ||
0610             cpumode == PERF_RECORD_MISC_KERNEL) &&
0611             !perf_host)
0612             al->filtered |= (1 << HIST_FILTER__HOST);
0613 
0614         return NULL;
0615     }
0616 
0617     al->map = maps__find(maps, al->addr);
0618     if (al->map != NULL) {
0619         /*
0620          * Kernel maps might be changed when loading symbols so loading
0621          * must be done prior to using kernel maps.
0622          */
0623         if (load_map)
0624             map__load(al->map);
0625         al->addr = al->map->map_ip(al->map, al->addr);
0626     }
0627 
0628     return al->map;
0629 }
0630 
0631 /*
0632  * For branch stacks or branch samples, the sample cpumode might not be correct
0633  * because it applies only to the sample 'ip' and not necessary to 'addr' or
0634  * branch stack addresses. If possible, use a fallback to deal with those cases.
0635  */
0636 struct map *thread__find_map_fb(struct thread *thread, u8 cpumode, u64 addr,
0637                 struct addr_location *al)
0638 {
0639     struct map *map = thread__find_map(thread, cpumode, addr, al);
0640     struct machine *machine = thread->maps->machine;
0641     u8 addr_cpumode = machine__addr_cpumode(machine, cpumode, addr);
0642 
0643     if (map || addr_cpumode == cpumode)
0644         return map;
0645 
0646     return thread__find_map(thread, addr_cpumode, addr, al);
0647 }
0648 
0649 struct symbol *thread__find_symbol(struct thread *thread, u8 cpumode,
0650                    u64 addr, struct addr_location *al)
0651 {
0652     al->sym = NULL;
0653     if (thread__find_map(thread, cpumode, addr, al))
0654         al->sym = map__find_symbol(al->map, al->addr);
0655     return al->sym;
0656 }
0657 
0658 struct symbol *thread__find_symbol_fb(struct thread *thread, u8 cpumode,
0659                       u64 addr, struct addr_location *al)
0660 {
0661     al->sym = NULL;
0662     if (thread__find_map_fb(thread, cpumode, addr, al))
0663         al->sym = map__find_symbol(al->map, al->addr);
0664     return al->sym;
0665 }
0666 
0667 static bool check_address_range(struct intlist *addr_list, int addr_range,
0668                 unsigned long addr)
0669 {
0670     struct int_node *pos;
0671 
0672     intlist__for_each_entry(pos, addr_list) {
0673         if (addr >= pos->i && addr < pos->i + addr_range)
0674             return true;
0675     }
0676 
0677     return false;
0678 }
0679 
0680 /*
0681  * Callers need to drop the reference to al->thread, obtained in
0682  * machine__findnew_thread()
0683  */
0684 int machine__resolve(struct machine *machine, struct addr_location *al,
0685              struct perf_sample *sample)
0686 {
0687     struct thread *thread;
0688 
0689     if (symbol_conf.guest_code && !machine__is_host(machine))
0690         thread = machine__findnew_guest_code(machine, sample->pid);
0691     else
0692         thread = machine__findnew_thread(machine, sample->pid, sample->tid);
0693     if (thread == NULL)
0694         return -1;
0695 
0696     dump_printf(" ... thread: %s:%d\n", thread__comm_str(thread), thread->tid);
0697     thread__find_map(thread, sample->cpumode, sample->ip, al);
0698     dump_printf(" ...... dso: %s\n",
0699             al->map ? al->map->dso->long_name :
0700             al->level == 'H' ? "[hypervisor]" : "<not found>");
0701 
0702     if (thread__is_filtered(thread))
0703         al->filtered |= (1 << HIST_FILTER__THREAD);
0704 
0705     al->sym = NULL;
0706     al->cpu = sample->cpu;
0707     al->socket = -1;
0708     al->srcline = NULL;
0709 
0710     if (al->cpu >= 0) {
0711         struct perf_env *env = machine->env;
0712 
0713         if (env && env->cpu)
0714             al->socket = env->cpu[al->cpu].socket_id;
0715     }
0716 
0717     if (al->map) {
0718         struct dso *dso = al->map->dso;
0719 
0720         if (symbol_conf.dso_list &&
0721             (!dso || !(strlist__has_entry(symbol_conf.dso_list,
0722                           dso->short_name) ||
0723                    (dso->short_name != dso->long_name &&
0724                 strlist__has_entry(symbol_conf.dso_list,
0725                            dso->long_name))))) {
0726             al->filtered |= (1 << HIST_FILTER__DSO);
0727         }
0728 
0729         al->sym = map__find_symbol(al->map, al->addr);
0730     } else if (symbol_conf.dso_list) {
0731         al->filtered |= (1 << HIST_FILTER__DSO);
0732     }
0733 
0734     if (symbol_conf.sym_list) {
0735         int ret = 0;
0736         char al_addr_str[32];
0737         size_t sz = sizeof(al_addr_str);
0738 
0739         if (al->sym) {
0740             ret = strlist__has_entry(symbol_conf.sym_list,
0741                         al->sym->name);
0742         }
0743         if (!ret && al->sym) {
0744             snprintf(al_addr_str, sz, "0x%"PRIx64,
0745                 al->map->unmap_ip(al->map, al->sym->start));
0746             ret = strlist__has_entry(symbol_conf.sym_list,
0747                         al_addr_str);
0748         }
0749         if (!ret && symbol_conf.addr_list && al->map) {
0750             unsigned long addr = al->map->unmap_ip(al->map, al->addr);
0751 
0752             ret = intlist__has_entry(symbol_conf.addr_list, addr);
0753             if (!ret && symbol_conf.addr_range) {
0754                 ret = check_address_range(symbol_conf.addr_list,
0755                               symbol_conf.addr_range,
0756                               addr);
0757             }
0758         }
0759 
0760         if (!ret)
0761             al->filtered |= (1 << HIST_FILTER__SYMBOL);
0762     }
0763 
0764     return 0;
0765 }
0766 
0767 /*
0768  * The preprocess_sample method will return with reference counts for the
0769  * in it, when done using (and perhaps getting ref counts if needing to
0770  * keep a pointer to one of those entries) it must be paired with
0771  * addr_location__put(), so that the refcounts can be decremented.
0772  */
0773 void addr_location__put(struct addr_location *al)
0774 {
0775     thread__zput(al->thread);
0776 }
0777 
0778 bool is_bts_event(struct perf_event_attr *attr)
0779 {
0780     return attr->type == PERF_TYPE_HARDWARE &&
0781            (attr->config & PERF_COUNT_HW_BRANCH_INSTRUCTIONS) &&
0782            attr->sample_period == 1;
0783 }
0784 
0785 bool sample_addr_correlates_sym(struct perf_event_attr *attr)
0786 {
0787     if (attr->type == PERF_TYPE_SOFTWARE &&
0788         (attr->config == PERF_COUNT_SW_PAGE_FAULTS ||
0789          attr->config == PERF_COUNT_SW_PAGE_FAULTS_MIN ||
0790          attr->config == PERF_COUNT_SW_PAGE_FAULTS_MAJ))
0791         return true;
0792 
0793     if (is_bts_event(attr))
0794         return true;
0795 
0796     return false;
0797 }
0798 
0799 void thread__resolve(struct thread *thread, struct addr_location *al,
0800              struct perf_sample *sample)
0801 {
0802     thread__find_map_fb(thread, sample->cpumode, sample->addr, al);
0803 
0804     al->cpu = sample->cpu;
0805     al->sym = NULL;
0806 
0807     if (al->map)
0808         al->sym = map__find_symbol(al->map, al->addr);
0809 }