From nobody Wed Dec 17 12:44:26 2025 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id EADD7C4167B for ; Mon, 27 Nov 2023 22:16:56 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S233471AbjK0WQr (ORCPT ); Mon, 27 Nov 2023 17:16:47 -0500 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:43996 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233711AbjK0WKV (ORCPT ); Mon, 27 Nov 2023 17:10:21 -0500 Received: from mail-yb1-xb49.google.com (mail-yb1-xb49.google.com [IPv6:2607:f8b0:4864:20::b49]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C00281FE7 for ; Mon, 27 Nov 2023 14:09:59 -0800 (PST) Received: by mail-yb1-xb49.google.com with SMTP id 3f1490d57ef6-daed1e15daeso5780295276.1 for ; Mon, 27 Nov 2023 14:09:59 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1701122999; x=1701727799; darn=vger.kernel.org; h=to:from:subject:references:mime-version:message-id:in-reply-to:date :from:to:cc:subject:date:message-id:reply-to; bh=CftX/1r0rIaPLpzJmFDw1qiY7uQQ2dJF/l5A87og7iU=; b=3CyNGRRDVuO9YT/X+SjYjRfolcoeB7Z97DFmNGikkDAwRzR3pP939I5S6SwEiNe06x RG9d1iR162s4wM8xLatYPBAl7AnCKptKu0Uqb3YXjEQ98z1/v+bWYHwwNV0KzVOmVv0R v07brK0Y2uV+NSxnhBBxkRTOHldy7t6mM38Ee9Dmu04Kwr83sw+A5zqQtLzgJjQHpb5z dEVjosCguv5k9qn5OQTRf/zE+nzGkuxj7rjKU4IqXX3bw4+ppz3Q658ACWRn4TU2T3kg Yl4RBHuMxP8cjVyvUOJ2WXWT4kEhxntXczp+ucF0f19giIa7b2cKhiSdCPh4oIBVDsW5 ENjA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1701122999; x=1701727799; h=to:from:subject:references:mime-version:message-id:in-reply-to:date :x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=CftX/1r0rIaPLpzJmFDw1qiY7uQQ2dJF/l5A87og7iU=; b=YDCs4Qw0dzRxoG0RmK/JcuVGqXCTMMk8xMba8ehY7i+SboQ/cLdBv/uFBCQi9Vs+wx 2G36ibUYttMUIxltz0kjglIfz7GoXk5zmQubdHD7gfb4RcGKiGKPEq2+btrIalR+xpj0 VKdoTgGWYUhyJGFQrQ9QB1wW2bAack37SHvG98mtT8ffSvO8HfKKZKP+UX+W1m64piF8 TSrAQKlDrzWf3di1bvW/kIyZas+QPLtHJhe1IUyCoIm8g2orSuX9zTbEGvjn9zPSKQ4Z Z4a554JJtZ6EOn87B/WPBann5LDB62Zaaq6EngSrjpmsVTE/eysrT2I/4NGgc+AGXPJT OS5Q== X-Gm-Message-State: AOJu0Yzco3LqEzLFy9AtROdbNx+iFJEGHrpRaDdNHx0obFE4HTl1e5Qd VdJyBM/gntzblRFCB47CxWOyZLJHgkFy X-Google-Smtp-Source: AGHT+IF4dXaRo+/kWdzxB7L7hJU49KFfZCB8PmZOi7bzt/sXgBhb7HF28yKgKScWa8gTXQliE9YKmZLxEmfP X-Received: from irogers.svl.corp.google.com ([2620:15c:2a3:200:829:6e77:9093:f39b]) (user=irogers job=sendgmr) by 2002:a5b:f0b:0:b0:db4:5eed:8907 with SMTP id x11-20020a5b0f0b000000b00db45eed8907mr374977ybr.8.1701122998686; Mon, 27 Nov 2023 14:09:58 -0800 (PST) Date: Mon, 27 Nov 2023 14:08:27 -0800 In-Reply-To: <20231127220902.1315692-1-irogers@google.com> Message-Id: <20231127220902.1315692-16-irogers@google.com> Mime-Version: 1.0 References: <20231127220902.1315692-1-irogers@google.com> X-Mailer: git-send-email 2.43.0.rc1.413.gea7ed67945-goog Subject: [PATCH v5 15/50] perf maps: Add maps__for_each_map to call a function on each entry From: Ian Rogers To: Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Mark Rutland , Alexander Shishkin , Jiri Olsa , Namhyung Kim , Ian Rogers , Adrian Hunter , Nick Terrell , Kan Liang , Andi Kleen , Kajol Jain , Athira Rajeev , Huacai Chen , Masami Hiramatsu , Vincent Whitchurch , "Steinar H. Gunderson" , Liam Howlett , Miguel Ojeda , Colin Ian King , Dmitrii Dolgov <9erthalion6@gmail.com>, Yang Jihong , Ming Wang , James Clark , K Prateek Nayak , Sean Christopherson , Leo Yan , Ravi Bangoria , German Gomez , Changbin Du , Paolo Bonzini , Li Dong , Sandipan Das , liuwenyu , linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, Guilherme Amadio Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Most current uses of maps don't take the rwsem introducing a risk that the maps will change during iteration. Introduce maps__for_each_map that iterates the entries under the read lock of the rwsem. This replaces the maps__for_each_entry macro that is moved into maps.c. maps__for_each_entry_safe will be replaced in a later change. Signed-off-by: Ian Rogers Acked-by: Namhyung Kim --- tools/perf/arch/x86/util/event.c | 103 +++++++------ tools/perf/builtin-report.c | 54 ++++--- tools/perf/tests/maps.c | 61 +++++--- tools/perf/tests/vmlinux-kallsyms.c | 181 ++++++++++++----------- tools/perf/util/machine.c | 53 ++++--- tools/perf/util/maps.c | 102 ++++++++----- tools/perf/util/maps.h | 6 +- tools/perf/util/probe-event.c | 40 +++-- tools/perf/util/symbol.c | 36 ++--- tools/perf/util/synthetic-events.c | 118 ++++++++------- tools/perf/util/thread.c | 35 +++-- tools/perf/util/unwind-libunwind-local.c | 34 +++-- tools/perf/util/vdso.c | 35 +++-- 13 files changed, 508 insertions(+), 350 deletions(-) diff --git a/tools/perf/arch/x86/util/event.c b/tools/perf/arch/x86/util/ev= ent.c index 5741ffe47312..e65b7dbe27fb 100644 --- a/tools/perf/arch/x86/util/event.c +++ b/tools/perf/arch/x86/util/event.c @@ -14,66 +14,79 @@ =20 #if defined(__x86_64__) =20 -int perf_event__synthesize_extra_kmaps(struct perf_tool *tool, - perf_event__handler_t process, - struct machine *machine) +struct perf_event__synthesize_extra_kmaps_cb_args { + struct perf_tool *tool; + perf_event__handler_t process; + struct machine *machine; + union perf_event *event; +}; + +static int perf_event__synthesize_extra_kmaps_cb(struct map *map, void *da= ta) { - int rc =3D 0; - struct map_rb_node *pos; - struct maps *kmaps =3D machine__kernel_maps(machine); - union perf_event *event =3D zalloc(sizeof(event->mmap) + - machine->id_hdr_size); + struct perf_event__synthesize_extra_kmaps_cb_args *args =3D data; + union perf_event *event =3D args->event; + struct kmap *kmap; + size_t size; =20 - if (!event) { - pr_debug("Not enough memory synthesizing mmap event " - "for extra kernel maps\n"); - return -1; - } + if (!__map__is_extra_kernel_map(map)) + return 0; =20 - maps__for_each_entry(kmaps, pos) { - struct kmap *kmap; - size_t size; - struct map *map =3D pos->map; + kmap =3D map__kmap(map); =20 - if (!__map__is_extra_kernel_map(map)) - continue; + size =3D sizeof(event->mmap) - sizeof(event->mmap.filename) + + PERF_ALIGN(strlen(kmap->name) + 1, sizeof(u64)) + + args->machine->id_hdr_size; =20 - kmap =3D map__kmap(map); + memset(event, 0, size); =20 - size =3D sizeof(event->mmap) - sizeof(event->mmap.filename) + - PERF_ALIGN(strlen(kmap->name) + 1, sizeof(u64)) + - machine->id_hdr_size; + event->mmap.header.type =3D PERF_RECORD_MMAP; =20 - memset(event, 0, size); + /* + * kernel uses 0 for user space maps, see kernel/perf_event.c + * __perf_event_mmap + */ + if (machine__is_host(args->machine)) + event->header.misc =3D PERF_RECORD_MISC_KERNEL; + else + event->header.misc =3D PERF_RECORD_MISC_GUEST_KERNEL; =20 - event->mmap.header.type =3D PERF_RECORD_MMAP; + event->mmap.header.size =3D size; =20 - /* - * kernel uses 0 for user space maps, see kernel/perf_event.c - * __perf_event_mmap - */ - if (machine__is_host(machine)) - event->header.misc =3D PERF_RECORD_MISC_KERNEL; - else - event->header.misc =3D PERF_RECORD_MISC_GUEST_KERNEL; + event->mmap.start =3D map__start(map); + event->mmap.len =3D map__size(map); + event->mmap.pgoff =3D map__pgoff(map); + event->mmap.pid =3D args->machine->pid; =20 - event->mmap.header.size =3D size; + strlcpy(event->mmap.filename, kmap->name, PATH_MAX); =20 - event->mmap.start =3D map__start(map); - event->mmap.len =3D map__size(map); - event->mmap.pgoff =3D map__pgoff(map); - event->mmap.pid =3D machine->pid; + if (perf_tool__process_synth_event(args->tool, event, args->machine, args= ->process) !=3D 0) + return -1; =20 - strlcpy(event->mmap.filename, kmap->name, PATH_MAX); + return 0; +} =20 - if (perf_tool__process_synth_event(tool, event, machine, - process) !=3D 0) { - rc =3D -1; - break; - } +int perf_event__synthesize_extra_kmaps(struct perf_tool *tool, + perf_event__handler_t process, + struct machine *machine) +{ + int rc; + struct maps *kmaps =3D machine__kernel_maps(machine); + struct perf_event__synthesize_extra_kmaps_cb_args args =3D { + .tool =3D tool, + .process =3D process, + .machine =3D machine, + .event =3D zalloc(sizeof(args.event->mmap) + machine->id_hdr_size), + }; + + if (!args.event) { + pr_debug("Not enough memory synthesizing mmap event " + "for extra kernel maps\n"); + return -1; } =20 - free(event); + rc =3D maps__for_each_map(kmaps, perf_event__synthesize_extra_kmaps_cb, &= args); + + free(args.event); return rc; } =20 diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 121a2781323c..a5d7bc5b843f 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c @@ -859,27 +859,47 @@ static struct task *tasks_list(struct task *task, str= uct machine *machine) return tasks_list(parent_task, machine); } =20 -static size_t maps__fprintf_task(struct maps *maps, int indent, FILE *fp) +struct maps__fprintf_task_args { + int indent; + FILE *fp; + size_t printed; +}; + +static int maps__fprintf_task_cb(struct map *map, void *data) { - size_t printed =3D 0; - struct map_rb_node *rb_node; + struct maps__fprintf_task_args *args =3D data; + const struct dso *dso =3D map__dso(map); + u32 prot =3D map__prot(map); + int ret; =20 - maps__for_each_entry(maps, rb_node) { - struct map *map =3D rb_node->map; - const struct dso *dso =3D map__dso(map); - u32 prot =3D map__prot(map); + ret =3D fprintf(args->fp, + "%*s %" PRIx64 "-%" PRIx64 " %c%c%c%c %08" PRIx64 " %" PRIu64 " %s\n", + args->indent, "", map__start(map), map__end(map), + prot & PROT_READ ? 'r' : '-', + prot & PROT_WRITE ? 'w' : '-', + prot & PROT_EXEC ? 'x' : '-', + map__flags(map) ? 's' : 'p', + map__pgoff(map), + dso->id.ino, dso->name); =20 - printed +=3D fprintf(fp, "%*s %" PRIx64 "-%" PRIx64 " %c%c%c%c %08" PRI= x64 " %" PRIu64 " %s\n", - indent, "", map__start(map), map__end(map), - prot & PROT_READ ? 'r' : '-', - prot & PROT_WRITE ? 'w' : '-', - prot & PROT_EXEC ? 'x' : '-', - map__flags(map) ? 's' : 'p', - map__pgoff(map), - dso->id.ino, dso->name); - } + if (ret < 0) + return ret; + + args->printed +=3D ret; + return 0; +} + +static size_t maps__fprintf_task(struct maps *maps, int indent, FILE *fp) +{ + struct maps__fprintf_task_args args =3D { + .indent =3D indent, + .fp =3D fp, + .printed =3D 0, + }; + + maps__for_each_map(maps, maps__fprintf_task_cb, &args); =20 - return printed; + return args.printed; } =20 static void task__print_level(struct task *task, FILE *fp, int level) diff --git a/tools/perf/tests/maps.c b/tools/perf/tests/maps.c index 5bb1123a91a7..bb3fbfe5a73e 100644 --- a/tools/perf/tests/maps.c +++ b/tools/perf/tests/maps.c @@ -14,44 +14,59 @@ struct map_def { u64 end; }; =20 +struct check_maps_cb_args { + struct map_def *merged; + unsigned int i; +}; + +static int check_maps_cb(struct map *map, void *data) +{ + struct check_maps_cb_args *args =3D data; + struct map_def *merged =3D &args->merged[args->i]; + + if (map__start(map) !=3D merged->start || + map__end(map) !=3D merged->end || + strcmp(map__dso(map)->name, merged->name) || + refcount_read(map__refcnt(map)) !=3D 1) { + return 1; + } + args->i++; + return 0; +} + +static int failed_cb(struct map *map, void *data __maybe_unused) +{ + pr_debug("\tstart: %" PRIu64 " end: %" PRIu64 " name: '%s' refcnt: %d\n", + map__start(map), + map__end(map), + map__dso(map)->name, + refcount_read(map__refcnt(map))); + + return 0; +} + static int check_maps(struct map_def *merged, unsigned int size, struct ma= ps *maps) { - struct map_rb_node *rb_node; - unsigned int i =3D 0; bool failed =3D false; =20 if (maps__nr_maps(maps) !=3D size) { pr_debug("Expected %d maps, got %d", size, maps__nr_maps(maps)); failed =3D true; } else { - maps__for_each_entry(maps, rb_node) { - struct map *map =3D rb_node->map; - - if (map__start(map) !=3D merged[i].start || - map__end(map) !=3D merged[i].end || - strcmp(map__dso(map)->name, merged[i].name) || - refcount_read(map__refcnt(map)) !=3D 1) { - failed =3D true; - } - i++; - } + struct check_maps_cb_args args =3D { + .merged =3D merged, + .i =3D 0, + }; + failed =3D maps__for_each_map(maps, check_maps_cb, &args); } if (failed) { pr_debug("Expected:\n"); - for (i =3D 0; i < size; i++) { + for (unsigned int i =3D 0; i < size; i++) { pr_debug("\tstart: %" PRIu64 " end: %" PRIu64 " name: '%s' refcnt: 1\n", merged[i].start, merged[i].end, merged[i].name); } pr_debug("Got:\n"); - maps__for_each_entry(maps, rb_node) { - struct map *map =3D rb_node->map; - - pr_debug("\tstart: %" PRIu64 " end: %" PRIu64 " name: '%s' refcnt: %d\n= ", - map__start(map), - map__end(map), - map__dso(map)->name, - refcount_read(map__refcnt(map))); - } + maps__for_each_map(maps, failed_cb, NULL); } return failed ? TEST_FAIL : TEST_OK; } diff --git a/tools/perf/tests/vmlinux-kallsyms.c b/tools/perf/tests/vmlinux= -kallsyms.c index 1078a93b01aa..822f893e67d5 100644 --- a/tools/perf/tests/vmlinux-kallsyms.c +++ b/tools/perf/tests/vmlinux-kallsyms.c @@ -112,18 +112,92 @@ static bool is_ignored_symbol(const char *name, char = type) return false; } =20 +struct test__vmlinux_matches_kallsyms_cb_args { + struct machine kallsyms; + struct map *vmlinux_map; + bool header_printed; +}; + +static int test__vmlinux_matches_kallsyms_cb1(struct map *map, void *data) +{ + struct test__vmlinux_matches_kallsyms_cb_args *args =3D data; + struct dso *dso =3D map__dso(map); + /* + * If it is the kernel, kallsyms is always "[kernel.kallsyms]", while + * the kernel will have the path for the vmlinux file being used, so use + * the short name, less descriptive but the same ("[kernel]" in both + * cases. + */ + struct map *pair =3D maps__find_by_name(args->kallsyms.kmaps, + (dso->kernel ? dso->short_name : dso->name)); + + if (pair) + map__set_priv(pair, 1); + else { + if (!args->header_printed) { + pr_info("WARN: Maps only in vmlinux:\n"); + args->header_printed =3D true; + } + map__fprintf(map, stderr); + } + return 0; +} + +static int test__vmlinux_matches_kallsyms_cb2(struct map *map, void *data) +{ + struct test__vmlinux_matches_kallsyms_cb_args *args =3D data; + struct map *pair; + u64 mem_start =3D map__unmap_ip(args->vmlinux_map, map__start(map)); + u64 mem_end =3D map__unmap_ip(args->vmlinux_map, map__end(map)); + + pair =3D maps__find(args->kallsyms.kmaps, mem_start); + if (pair =3D=3D NULL || map__priv(pair)) + return 0; + + if (map__start(pair) =3D=3D mem_start) { + struct dso *dso =3D map__dso(map); + + if (!args->header_printed) { + pr_info("WARN: Maps in vmlinux with a different name in kallsyms:\n"); + args->header_printed =3D true; + } + + pr_info("WARN: %" PRIx64 "-%" PRIx64 " %" PRIx64 " %s in kallsyms as", + map__start(map), map__end(map), map__pgoff(map), dso->name); + if (mem_end !=3D map__end(pair)) + pr_info(":\nWARN: *%" PRIx64 "-%" PRIx64 " %" PRIx64, + map__start(pair), map__end(pair), map__pgoff(pair)); + pr_info(" %s\n", dso->name); + map__set_priv(pair, 1); + } + return 0; +} + +static int test__vmlinux_matches_kallsyms_cb3(struct map *map, void *data) +{ + struct test__vmlinux_matches_kallsyms_cb_args *args =3D data; + + if (!map__priv(map)) { + if (!args->header_printed) { + pr_info("WARN: Maps only in kallsyms:\n"); + args->header_printed =3D true; + } + map__fprintf(map, stderr); + } + return 0; +} + static int test__vmlinux_matches_kallsyms(struct test_suite *test __maybe_= unused, int subtest __maybe_unused) { int err =3D TEST_FAIL; struct rb_node *nd; struct symbol *sym; - struct map *kallsyms_map, *vmlinux_map; - struct map_rb_node *rb_node; - struct machine kallsyms, vmlinux; + struct map *kallsyms_map; + struct machine vmlinux; struct maps *maps; u64 mem_start, mem_end; - bool header_printed; + struct test__vmlinux_matches_kallsyms_cb_args args; =20 /* * Step 1: @@ -131,7 +205,7 @@ static int test__vmlinux_matches_kallsyms(struct test_s= uite *test __maybe_unused * Init the machines that will hold kernel, modules obtained from * both vmlinux + .ko files and from /proc/kallsyms split by modules. */ - machine__init(&kallsyms, "", HOST_KERNEL_ID); + machine__init(&args.kallsyms, "", HOST_KERNEL_ID); machine__init(&vmlinux, "", HOST_KERNEL_ID); =20 maps =3D machine__kernel_maps(&vmlinux); @@ -143,7 +217,7 @@ static int test__vmlinux_matches_kallsyms(struct test_s= uite *test __maybe_unused * load /proc/kallsyms. Also create the modules maps from /proc/modules * and find the .ko files that match them in /lib/modules/`uname -r`/. */ - if (machine__create_kernel_maps(&kallsyms) < 0) { + if (machine__create_kernel_maps(&args.kallsyms) < 0) { pr_debug("machine__create_kernel_maps failed"); err =3D TEST_SKIP; goto out; @@ -160,7 +234,7 @@ static int test__vmlinux_matches_kallsyms(struct test_s= uite *test __maybe_unused * be compacted against the list of modules found in the "vmlinux" * code and with the one got from /proc/modules from the "kallsyms" code. */ - if (machine__load_kallsyms(&kallsyms, "/proc/kallsyms") <=3D 0) { + if (machine__load_kallsyms(&args.kallsyms, "/proc/kallsyms") <=3D 0) { pr_debug("machine__load_kallsyms failed"); err =3D TEST_SKIP; goto out; @@ -174,7 +248,7 @@ static int test__vmlinux_matches_kallsyms(struct test_s= uite *test __maybe_unused * to see if the running kernel was relocated by checking if it has the * same value in the vmlinux file we load. */ - kallsyms_map =3D machine__kernel_map(&kallsyms); + kallsyms_map =3D machine__kernel_map(&args.kallsyms); =20 /* * Step 5: @@ -186,7 +260,7 @@ static int test__vmlinux_matches_kallsyms(struct test_s= uite *test __maybe_unused goto out; } =20 - vmlinux_map =3D machine__kernel_map(&vmlinux); + args.vmlinux_map =3D machine__kernel_map(&vmlinux); =20 /* * Step 6: @@ -213,7 +287,7 @@ static int test__vmlinux_matches_kallsyms(struct test_s= uite *test __maybe_unused * in the kallsyms dso. For the ones that are in both, check its names and * end addresses too. */ - map__for_each_symbol(vmlinux_map, sym, nd) { + map__for_each_symbol(args.vmlinux_map, sym, nd) { struct symbol *pair, *first_pair; =20 sym =3D rb_entry(nd, struct symbol, rb_node); @@ -221,10 +295,10 @@ static int test__vmlinux_matches_kallsyms(struct test= _suite *test __maybe_unused if (sym->start =3D=3D sym->end) continue; =20 - mem_start =3D map__unmap_ip(vmlinux_map, sym->start); - mem_end =3D map__unmap_ip(vmlinux_map, sym->end); + mem_start =3D map__unmap_ip(args.vmlinux_map, sym->start); + mem_end =3D map__unmap_ip(args.vmlinux_map, sym->end); =20 - first_pair =3D machine__find_kernel_symbol(&kallsyms, mem_start, NULL); + first_pair =3D machine__find_kernel_symbol(&args.kallsyms, mem_start, NU= LL); pair =3D first_pair; =20 if (pair && UM(pair->start) =3D=3D mem_start) { @@ -253,7 +327,8 @@ static int test__vmlinux_matches_kallsyms(struct test_s= uite *test __maybe_unused */ continue; } else { - pair =3D machine__find_kernel_symbol_by_name(&kallsyms, sym->name, NUL= L); + pair =3D machine__find_kernel_symbol_by_name(&args.kallsyms, + sym->name, NULL); if (pair) { if (UM(pair->start) =3D=3D mem_start) goto next_pair; @@ -267,7 +342,7 @@ static int test__vmlinux_matches_kallsyms(struct test_s= uite *test __maybe_unused =20 continue; } - } else if (mem_start =3D=3D map__end(kallsyms.vmlinux_map)) { + } else if (mem_start =3D=3D map__end(args.kallsyms.vmlinux_map)) { /* * Ignore aliases to _etext, i.e. to the end of the kernel text area, * such as __indirect_thunk_end. @@ -289,78 +364,18 @@ static int test__vmlinux_matches_kallsyms(struct test= _suite *test __maybe_unused if (verbose <=3D 0) goto out; =20 - header_printed =3D false; - - maps__for_each_entry(maps, rb_node) { - struct map *map =3D rb_node->map; - struct dso *dso =3D map__dso(map); - /* - * If it is the kernel, kallsyms is always "[kernel.kallsyms]", while - * the kernel will have the path for the vmlinux file being used, - * so use the short name, less descriptive but the same ("[kernel]" in - * both cases. - */ - struct map *pair =3D maps__find_by_name(kallsyms.kmaps, (dso->kernel ? - dso->short_name : - dso->name)); - if (pair) { - map__set_priv(pair, 1); - } else { - if (!header_printed) { - pr_info("WARN: Maps only in vmlinux:\n"); - header_printed =3D true; - } - map__fprintf(map, stderr); - } - } - - header_printed =3D false; - - maps__for_each_entry(maps, rb_node) { - struct map *pair, *map =3D rb_node->map; - - mem_start =3D map__unmap_ip(vmlinux_map, map__start(map)); - mem_end =3D map__unmap_ip(vmlinux_map, map__end(map)); + args.header_printed =3D false; + maps__for_each_map(maps, test__vmlinux_matches_kallsyms_cb1, &args); =20 - pair =3D maps__find(kallsyms.kmaps, mem_start); - if (pair =3D=3D NULL || map__priv(pair)) - continue; - - if (map__start(pair) =3D=3D mem_start) { - struct dso *dso =3D map__dso(map); - - if (!header_printed) { - pr_info("WARN: Maps in vmlinux with a different name in kallsyms:\n"); - header_printed =3D true; - } - - pr_info("WARN: %" PRIx64 "-%" PRIx64 " %" PRIx64 " %s in kallsyms as", - map__start(map), map__end(map), map__pgoff(map), dso->name); - if (mem_end !=3D map__end(pair)) - pr_info(":\nWARN: *%" PRIx64 "-%" PRIx64 " %" PRIx64, - map__start(pair), map__end(pair), map__pgoff(pair)); - pr_info(" %s\n", dso->name); - map__set_priv(pair, 1); - } - } - - header_printed =3D false; - - maps =3D machine__kernel_maps(&kallsyms); + args.header_printed =3D false; + maps__for_each_map(maps, test__vmlinux_matches_kallsyms_cb2, &args); =20 - maps__for_each_entry(maps, rb_node) { - struct map *map =3D rb_node->map; + args.header_printed =3D false; + maps =3D machine__kernel_maps(&args.kallsyms); + maps__for_each_map(maps, test__vmlinux_matches_kallsyms_cb3, &args); =20 - if (!map__priv(map)) { - if (!header_printed) { - pr_info("WARN: Maps only in kallsyms:\n"); - header_printed =3D true; - } - map__fprintf(map, stderr); - } - } out: - machine__exit(&kallsyms); + machine__exit(&args.kallsyms); machine__exit(&vmlinux); return err; } diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c index b6831a1f909d..3c967295c9a3 100644 --- a/tools/perf/util/machine.c +++ b/tools/perf/util/machine.c @@ -1286,33 +1286,46 @@ static u64 find_entry_trampoline(struct dso *dso) #define X86_64_CPU_ENTRY_AREA_SIZE 0x2c000 #define X86_64_ENTRY_TRAMPOLINE 0x6000 =20 +struct machine__map_x86_64_entry_trampolines_args { + struct maps *kmaps; + bool found; +}; + +static int machine__map_x86_64_entry_trampolines_cb(struct map *map, void = *data) +{ + struct machine__map_x86_64_entry_trampolines_args *args =3D data; + struct map *dest_map; + struct kmap *kmap =3D __map__kmap(map); + + if (!kmap || !is_entry_trampoline(kmap->name)) + return 0; + + dest_map =3D maps__find(args->kmaps, map__pgoff(map)); + if (dest_map !=3D map) + map__set_pgoff(map, map__map_ip(dest_map, map__pgoff(map))); + + args->found =3D true; + return 0; +} + /* Map x86_64 PTI entry trampolines */ int machine__map_x86_64_entry_trampolines(struct machine *machine, struct dso *kernel) { - struct maps *kmaps =3D machine__kernel_maps(machine); + struct machine__map_x86_64_entry_trampolines_args args =3D { + .kmaps =3D machine__kernel_maps(machine), + .found =3D false, + }; int nr_cpus_avail, cpu; - bool found =3D false; - struct map_rb_node *rb_node; u64 pgoff; =20 /* * In the vmlinux case, pgoff is a virtual address which must now be * mapped to a vmlinux offset. */ - maps__for_each_entry(kmaps, rb_node) { - struct map *dest_map, *map =3D rb_node->map; - struct kmap *kmap =3D __map__kmap(map); - - if (!kmap || !is_entry_trampoline(kmap->name)) - continue; + maps__for_each_map(args.kmaps, machine__map_x86_64_entry_trampolines_cb, = &args); =20 - dest_map =3D maps__find(kmaps, map__pgoff(map)); - if (dest_map !=3D map) - map__set_pgoff(map, map__map_ip(dest_map, map__pgoff(map))); - found =3D true; - } - if (found || machine->trampolines_mapped) + if (args.found || machine->trampolines_mapped) return 0; =20 pgoff =3D find_entry_trampoline(kernel); @@ -3395,16 +3408,8 @@ int machine__for_each_dso(struct machine *machine, m= achine__dso_t fn, void *priv int machine__for_each_kernel_map(struct machine *machine, machine__map_t f= n, void *priv) { struct maps *maps =3D machine__kernel_maps(machine); - struct map_rb_node *pos; - int err =3D 0; =20 - maps__for_each_entry(maps, pos) { - err =3D fn(pos->map, priv); - if (err !=3D 0) { - break; - } - } - return err; + return maps__for_each_map(maps, fn, priv); } =20 bool machine__is_lock_function(struct machine *machine, u64 addr) diff --git a/tools/perf/util/maps.c b/tools/perf/util/maps.c index 9a011aed4b75..00e6589bba10 100644 --- a/tools/perf/util/maps.c +++ b/tools/perf/util/maps.c @@ -10,6 +10,9 @@ #include "ui/ui.h" #include "unwind.h" =20 +#define maps__for_each_entry(maps, map) \ + for (map =3D maps__first(maps); map; map =3D map_rb_node__next(map)) + static void maps__init(struct maps *maps, struct machine *machine) { refcount_set(maps__refcnt(maps), 1); @@ -196,6 +199,21 @@ void maps__put(struct maps *maps) RC_CHK_PUT(maps); } =20 +int maps__for_each_map(struct maps *maps, int (*cb)(struct map *map, void = *data), void *data) +{ + struct map_rb_node *pos; + int ret =3D 0; + + down_read(maps__lock(maps)); + maps__for_each_entry(maps, pos) { + ret =3D cb(pos->map, data); + if (ret) + break; + } + up_read(maps__lock(maps)); + return ret; +} + struct symbol *maps__find_symbol(struct maps *maps, u64 addr, struct map *= *mapp) { struct map *map =3D maps__find(maps, addr); @@ -210,31 +228,40 @@ struct symbol *maps__find_symbol(struct maps *maps, u= 64 addr, struct map **mapp) return NULL; } =20 -struct symbol *maps__find_symbol_by_name(struct maps *maps, const char *na= me, struct map **mapp) -{ +struct maps__find_symbol_by_name_args { + struct map **mapp; + const char *name; struct symbol *sym; - struct map_rb_node *pos; +}; =20 - down_read(maps__lock(maps)); +static int maps__find_symbol_by_name_cb(struct map *map, void *data) +{ + struct maps__find_symbol_by_name_args *args =3D data; =20 - maps__for_each_entry(maps, pos) { - sym =3D map__find_symbol_by_name(pos->map, name); + args->sym =3D map__find_symbol_by_name(map, args->name); + if (!args->sym) + return 0; =20 - if (sym =3D=3D NULL) - continue; - if (!map__contains_symbol(pos->map, sym)) { - sym =3D NULL; - continue; - } - if (mapp !=3D NULL) - *mapp =3D pos->map; - goto out; + if (!map__contains_symbol(map, args->sym)) { + args->sym =3D NULL; + return 0; } =20 - sym =3D NULL; -out: - up_read(maps__lock(maps)); - return sym; + if (args->mapp !=3D NULL) + *args->mapp =3D map__get(map); + return 1; +} + +struct symbol *maps__find_symbol_by_name(struct maps *maps, const char *na= me, struct map **mapp) +{ + struct maps__find_symbol_by_name_args args =3D { + .mapp =3D mapp, + .name =3D name, + .sym =3D NULL, + }; + + maps__for_each_map(maps, maps__find_symbol_by_name_cb, &args); + return args.sym; } =20 int maps__find_ams(struct maps *maps, struct addr_map_symbol *ams) @@ -253,25 +280,34 @@ int maps__find_ams(struct maps *maps, struct addr_map= _symbol *ams) return ams->ms.sym ? 0 : -1; } =20 -size_t maps__fprintf(struct maps *maps, FILE *fp) -{ - size_t printed =3D 0; - struct map_rb_node *pos; +struct maps__fprintf_args { + FILE *fp; + size_t printed; +}; =20 - down_read(maps__lock(maps)); +static int maps__fprintf_cb(struct map *map, void *data) +{ + struct maps__fprintf_args *args =3D data; =20 - maps__for_each_entry(maps, pos) { - printed +=3D fprintf(fp, "Map:"); - printed +=3D map__fprintf(pos->map, fp); - if (verbose > 2) { - printed +=3D dso__fprintf(map__dso(pos->map), fp); - printed +=3D fprintf(fp, "--\n"); - } + args->printed +=3D fprintf(args->fp, "Map:"); + args->printed +=3D map__fprintf(map, args->fp); + if (verbose > 2) { + args->printed +=3D dso__fprintf(map__dso(map), args->fp); + args->printed +=3D fprintf(args->fp, "--\n"); } + return 0; +} =20 - up_read(maps__lock(maps)); +size_t maps__fprintf(struct maps *maps, FILE *fp) +{ + struct maps__fprintf_args args =3D { + .fp =3D fp, + .printed =3D 0, + }; + + maps__for_each_map(maps, maps__fprintf_cb, &args); =20 - return printed; + return args.printed; } =20 int maps__fixup_overlappings(struct maps *maps, struct map *map, FILE *fp) diff --git a/tools/perf/util/maps.h b/tools/perf/util/maps.h index a689149be8c4..8ac30cdaf5bd 100644 --- a/tools/perf/util/maps.h +++ b/tools/perf/util/maps.h @@ -36,9 +36,6 @@ struct map_rb_node *map_rb_node__next(struct map_rb_node = *node); struct map_rb_node *maps__find_node(struct maps *maps, struct map *map); struct map *maps__find(struct maps *maps, u64 addr); =20 -#define maps__for_each_entry(maps, map) \ - for (map =3D maps__first(maps); map; map =3D map_rb_node__next(map)) - #define maps__for_each_entry_safe(maps, map, next) \ for (map =3D maps__first(maps), next =3D map_rb_node__next(map); map; \ map =3D next, next =3D map_rb_node__next(map)) @@ -81,6 +78,9 @@ static inline void __maps__zput(struct maps **map) =20 #define maps__zput(map) __maps__zput(&map) =20 +/* Iterate over map calling cb for each entry. */ +int maps__for_each_map(struct maps *maps, int (*cb)(struct map *map, void = *data), void *data); + static inline struct rb_root *maps__entries(struct maps *maps) { return &RC_CHK_ACCESS(maps)->entries; diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index 1a5b7fa459b2..a1a796043691 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c @@ -149,10 +149,32 @@ static int kernel_get_symbol_address_by_name(const ch= ar *name, u64 *addr, return 0; } =20 +struct kernel_get_module_map_cb_args { + const char *module; + struct map *result; +}; + +static int kernel_get_module_map_cb(struct map *map, void *data) +{ + struct kernel_get_module_map_cb_args *args =3D data; + struct dso *dso =3D map__dso(map); + const char *short_name =3D dso->short_name; /* short_name is "[module]" */ + u16 short_name_len =3D dso->short_name_len; + + if (strncmp(short_name + 1, args->module, short_name_len - 2) =3D=3D 0 && + args->module[short_name_len - 2] =3D=3D '\0') { + args->result =3D map__get(map); + return 1; + } + return 0; +} + static struct map *kernel_get_module_map(const char *module) { - struct maps *maps =3D machine__kernel_maps(host_machine); - struct map_rb_node *pos; + struct kernel_get_module_map_cb_args args =3D { + .module =3D module, + .result =3D NULL, + }; =20 /* A file path -- this is an offline module */ if (module && strchr(module, '/')) @@ -164,19 +186,9 @@ static struct map *kernel_get_module_map(const char *m= odule) return map__get(map); } =20 - maps__for_each_entry(maps, pos) { - /* short_name is "[module]" */ - struct dso *dso =3D map__dso(pos->map); - const char *short_name =3D dso->short_name; - u16 short_name_len =3D dso->short_name_len; + maps__for_each_map(machine__kernel_maps(host_machine), kernel_get_module_= map_cb, &args); =20 - if (strncmp(short_name + 1, module, - short_name_len - 2) =3D=3D 0 && - module[short_name_len - 2] =3D=3D '\0') { - return map__get(pos->map); - } - } - return NULL; + return args.result; } =20 struct map *get_target_map(const char *target, struct nsinfo *nsi, bool us= er) diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index 1cc42b8d8afb..72f03b875478 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c @@ -1114,33 +1114,35 @@ int compare_proc_modules(const char *from, const ch= ar *to) return ret; } =20 +static int do_validate_kcore_modules_cb(struct map *old_map, void *data) +{ + struct rb_root *modules =3D data; + struct module_info *mi; + struct dso *dso; + + if (!__map__is_kmodule(old_map)) + return 0; + + dso =3D map__dso(old_map); + /* Module must be in memory at the same address */ + mi =3D find_module(dso->short_name, modules); + if (!mi || mi->start !=3D map__start(old_map)) + return -EINVAL; + + return 0; +} + static int do_validate_kcore_modules(const char *filename, struct maps *km= aps) { struct rb_root modules =3D RB_ROOT; - struct map_rb_node *old_node; int err; =20 err =3D read_proc_modules(filename, &modules); if (err) return err; =20 - maps__for_each_entry(kmaps, old_node) { - struct map *old_map =3D old_node->map; - struct module_info *mi; - struct dso *dso; + err =3D maps__for_each_map(kmaps, do_validate_kcore_modules_cb, &modules); =20 - if (!__map__is_kmodule(old_map)) { - continue; - } - dso =3D map__dso(old_map); - /* Module must be in memory at the same address */ - mi =3D find_module(dso->short_name, &modules); - if (!mi || mi->start !=3D map__start(old_map)) { - err =3D -EINVAL; - goto out; - } - } -out: delete_modules(&modules); return err; } diff --git a/tools/perf/util/synthetic-events.c b/tools/perf/util/synthetic= -events.c index 7cc38f2a0e9e..cdab6aa04917 100644 --- a/tools/perf/util/synthetic-events.c +++ b/tools/perf/util/synthetic-events.c @@ -666,18 +666,74 @@ int perf_event__synthesize_cgroups(struct perf_tool *= tool __maybe_unused, } #endif =20 +struct perf_event__synthesize_modules_maps_cb_args { + struct perf_tool *tool; + perf_event__handler_t process; + struct machine *machine; + union perf_event *event; +}; + +static int perf_event__synthesize_modules_maps_cb(struct map *map, void *d= ata) +{ + struct perf_event__synthesize_modules_maps_cb_args *args =3D data; + union perf_event *event =3D args->event; + struct dso *dso; + size_t size; + + if (!__map__is_kmodule(map)) + return 0; + + dso =3D map__dso(map); + if (symbol_conf.buildid_mmap2) { + size =3D PERF_ALIGN(dso->long_name_len + 1, sizeof(u64)); + event->mmap2.header.type =3D PERF_RECORD_MMAP2; + event->mmap2.header.size =3D (sizeof(event->mmap2) - + (sizeof(event->mmap2.filename) - size)); + memset(event->mmap2.filename + size, 0, args->machine->id_hdr_size); + event->mmap2.header.size +=3D args->machine->id_hdr_size; + event->mmap2.start =3D map__start(map); + event->mmap2.len =3D map__size(map); + event->mmap2.pid =3D args->machine->pid; + + memcpy(event->mmap2.filename, dso->long_name, dso->long_name_len + 1); + + perf_record_mmap2__read_build_id(&event->mmap2, args->machine, false); + } else { + size =3D PERF_ALIGN(dso->long_name_len + 1, sizeof(u64)); + event->mmap.header.type =3D PERF_RECORD_MMAP; + event->mmap.header.size =3D (sizeof(event->mmap) - + (sizeof(event->mmap.filename) - size)); + memset(event->mmap.filename + size, 0, args->machine->id_hdr_size); + event->mmap.header.size +=3D args->machine->id_hdr_size; + event->mmap.start =3D map__start(map); + event->mmap.len =3D map__size(map); + event->mmap.pid =3D args->machine->pid; + + memcpy(event->mmap.filename, dso->long_name, dso->long_name_len + 1); + } + + if (perf_tool__process_synth_event(args->tool, event, args->machine, args= ->process) !=3D 0) + return -1; + + return 0; +} + int perf_event__synthesize_modules(struct perf_tool *tool, perf_event__han= dler_t process, struct machine *machine) { - int rc =3D 0; - struct map_rb_node *pos; + int rc; struct maps *maps =3D machine__kernel_maps(machine); - union perf_event *event; - size_t size =3D symbol_conf.buildid_mmap2 ? - sizeof(event->mmap2) : sizeof(event->mmap); + struct perf_event__synthesize_modules_maps_cb_args args =3D { + .tool =3D tool, + .process =3D process, + .machine =3D machine, + }; + size_t size =3D symbol_conf.buildid_mmap2 + ? sizeof(args.event->mmap2) + : sizeof(args.event->mmap); =20 - event =3D zalloc(size + machine->id_hdr_size); - if (event =3D=3D NULL) { + args.event =3D zalloc(size + machine->id_hdr_size); + if (args.event =3D=3D NULL) { pr_debug("Not enough memory synthesizing mmap event " "for kernel modules\n"); return -1; @@ -688,53 +744,13 @@ int perf_event__synthesize_modules(struct perf_tool *= tool, perf_event__handler_t * __perf_event_mmap */ if (machine__is_host(machine)) - event->header.misc =3D PERF_RECORD_MISC_KERNEL; + args.event->header.misc =3D PERF_RECORD_MISC_KERNEL; else - event->header.misc =3D PERF_RECORD_MISC_GUEST_KERNEL; - - maps__for_each_entry(maps, pos) { - struct map *map =3D pos->map; - struct dso *dso; + args.event->header.misc =3D PERF_RECORD_MISC_GUEST_KERNEL; =20 - if (!__map__is_kmodule(map)) - continue; + rc =3D maps__for_each_map(maps, perf_event__synthesize_modules_maps_cb, &= args); =20 - dso =3D map__dso(map); - if (symbol_conf.buildid_mmap2) { - size =3D PERF_ALIGN(dso->long_name_len + 1, sizeof(u64)); - event->mmap2.header.type =3D PERF_RECORD_MMAP2; - event->mmap2.header.size =3D (sizeof(event->mmap2) - - (sizeof(event->mmap2.filename) - size)); - memset(event->mmap2.filename + size, 0, machine->id_hdr_size); - event->mmap2.header.size +=3D machine->id_hdr_size; - event->mmap2.start =3D map__start(map); - event->mmap2.len =3D map__size(map); - event->mmap2.pid =3D machine->pid; - - memcpy(event->mmap2.filename, dso->long_name, dso->long_name_len + 1); - - perf_record_mmap2__read_build_id(&event->mmap2, machine, false); - } else { - size =3D PERF_ALIGN(dso->long_name_len + 1, sizeof(u64)); - event->mmap.header.type =3D PERF_RECORD_MMAP; - event->mmap.header.size =3D (sizeof(event->mmap) - - (sizeof(event->mmap.filename) - size)); - memset(event->mmap.filename + size, 0, machine->id_hdr_size); - event->mmap.header.size +=3D machine->id_hdr_size; - event->mmap.start =3D map__start(map); - event->mmap.len =3D map__size(map); - event->mmap.pid =3D machine->pid; - - memcpy(event->mmap.filename, dso->long_name, dso->long_name_len + 1); - } - - if (perf_tool__process_synth_event(tool, event, machine, process) !=3D 0= ) { - rc =3D -1; - break; - } - } - - free(event); + free(args.event); return rc; } =20 diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c index b9c2039c4230..b6986a81aa6d 100644 --- a/tools/perf/util/thread.c +++ b/tools/perf/util/thread.c @@ -349,34 +349,33 @@ int thread__insert_map(struct thread *thread, struct = map *map) return maps__insert(thread__maps(thread), map); } =20 -static int __thread__prepare_access(struct thread *thread) +struct thread__prepare_access_maps_cb_args { + int err; + struct maps *maps; +}; + +static int thread__prepare_access_maps_cb(struct map *map, void *data) { bool initialized =3D false; - int err =3D 0; - struct maps *maps =3D thread__maps(thread); - struct map_rb_node *rb_node; - - down_read(maps__lock(maps)); - - maps__for_each_entry(maps, rb_node) { - err =3D unwind__prepare_access(thread__maps(thread), rb_node->map, &init= ialized); - if (err || initialized) - break; - } + struct thread__prepare_access_maps_cb_args *args =3D data; =20 - up_read(maps__lock(maps)); + args->err =3D unwind__prepare_access(args->maps, map, &initialized); =20 - return err; + return (args->err || initialized) ? 1 : 0; } =20 static int thread__prepare_access(struct thread *thread) { - int err =3D 0; + struct thread__prepare_access_maps_cb_args args =3D { + .err =3D 0, + }; =20 - if (dwarf_callchain_users) - err =3D __thread__prepare_access(thread); + if (dwarf_callchain_users) { + args.maps =3D thread__maps(thread); + maps__for_each_map(thread__maps(thread), thread__prepare_access_maps_cb,= &args); + } =20 - return err; + return args.err; } =20 static int thread__clone_maps(struct thread *thread, struct thread *parent= , bool do_maps_clone) diff --git a/tools/perf/util/unwind-libunwind-local.c b/tools/perf/util/unw= ind-libunwind-local.c index c0641882fd2f..228f1565bd0b 100644 --- a/tools/perf/util/unwind-libunwind-local.c +++ b/tools/perf/util/unwind-libunwind-local.c @@ -302,12 +302,31 @@ static int unwind_spec_ehframe(struct dso *dso, struc= t machine *machine, return 0; } =20 +struct read_unwind_spec_eh_frame_maps_cb_args { + struct dso *dso; + u64 base_addr; +}; + +static int read_unwind_spec_eh_frame_maps_cb(struct map *map, void *data) +{ + + struct read_unwind_spec_eh_frame_maps_cb_args *args =3D data; + + if (map__dso(map) =3D=3D args->dso && map__start(map) < args->base_addr) + args->base_addr =3D map__start(map); + + return 0; +} + + static int read_unwind_spec_eh_frame(struct dso *dso, struct unwind_info *= ui, u64 *table_data, u64 *segbase, u64 *fde_count) { - struct map_rb_node *map_node; - u64 base_addr =3D UINT64_MAX; + struct read_unwind_spec_eh_frame_maps_cb_args args =3D { + .dso =3D dso, + .base_addr =3D UINT64_MAX, + }; int ret, fd; =20 if (dso->data.eh_frame_hdr_offset =3D=3D 0) { @@ -325,16 +344,11 @@ static int read_unwind_spec_eh_frame(struct dso *dso,= struct unwind_info *ui, return -EINVAL; } =20 - maps__for_each_entry(thread__maps(ui->thread), map_node) { - struct map *map =3D map_node->map; - u64 start =3D map__start(map); + maps__for_each_map(thread__maps(ui->thread), read_unwind_spec_eh_frame_ma= ps_cb, &args); =20 - if (map__dso(map) =3D=3D dso && start < base_addr) - base_addr =3D start; - } - base_addr -=3D dso->data.elf_base_addr; + args.base_addr -=3D dso->data.elf_base_addr; /* Address of .eh_frame_hdr */ - *segbase =3D base_addr + dso->data.eh_frame_hdr_addr; + *segbase =3D args.base_addr + dso->data.eh_frame_hdr_addr; ret =3D unwind_spec_ehframe(dso, ui->machine, dso->data.eh_frame_hdr_offs= et, table_data, fde_count); if (ret) diff --git a/tools/perf/util/vdso.c b/tools/perf/util/vdso.c index ae3eee69b659..df8963796187 100644 --- a/tools/perf/util/vdso.c +++ b/tools/perf/util/vdso.c @@ -140,23 +140,34 @@ static struct dso *__machine__addnew_vdso(struct mach= ine *machine, const char *s return dso; } =20 +struct machine__thread_dso_type_maps_cb_args { + struct machine *machine; + enum dso_type dso_type; +}; + +static int machine__thread_dso_type_maps_cb(struct map *map, void *data) +{ + struct machine__thread_dso_type_maps_cb_args *args =3D data; + struct dso *dso =3D map__dso(map); + + if (!dso || dso->long_name[0] !=3D '/') + return 0; + + args->dso_type =3D dso__type(dso, args->machine); + return (args->dso_type !=3D DSO__TYPE_UNKNOWN) ? 1 : 0; +} + static enum dso_type machine__thread_dso_type(struct machine *machine, struct thread *thread) { - enum dso_type dso_type =3D DSO__TYPE_UNKNOWN; - struct map_rb_node *rb_node; - - maps__for_each_entry(thread__maps(thread), rb_node) { - struct dso *dso =3D map__dso(rb_node->map); + struct machine__thread_dso_type_maps_cb_args args =3D { + .machine =3D machine, + .dso_type =3D DSO__TYPE_UNKNOWN, + }; =20 - if (!dso || dso->long_name[0] !=3D '/') - continue; - dso_type =3D dso__type(dso, machine); - if (dso_type !=3D DSO__TYPE_UNKNOWN) - break; - } + maps__for_each_map(thread__maps(thread), machine__thread_dso_type_maps_cb= , &args); =20 - return dso_type; + return args.dso_type; } =20 #if BITS_PER_LONG =3D=3D 64 --=20 2.43.0.rc1.413.gea7ed67945-goog