Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757890AbbLCBWi (ORCPT ); Wed, 2 Dec 2015 20:22:38 -0500 Received: from LGEAMRELO12.lge.com ([156.147.23.52]:41845 "EHLO lgeamrelo12.lge.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755302AbbLCBWg convert rfc822-to-8bit (ORCPT ); Wed, 2 Dec 2015 20:22:36 -0500 X-Original-SENDERIP: 156.147.1.121 X-Original-MAILFROM: namhyung@kernel.org X-Original-SENDERIP: 165.244.98.76 X-Original-MAILFROM: namhyung@kernel.org X-Original-SENDERIP: 10.177.227.17 X-Original-MAILFROM: namhyung@kernel.org Date: Thu, 3 Dec 2015 10:15:56 +0900 From: Namhyung Kim To: =?utf-8?B?5bmz5p2+6ZuF5bezIC8gSElSQU1BVFXvvIxNQVNBTUk=?= CC: Arnaldo Carvalho de Melo , Ingo Molnar , Peter Zijlstra , Jiri Olsa , LKML , David Ahern , Frederic Weisbecker Subject: Re: [PATCH v3] perf tools: Introduce perf_thread for backtrace Message-ID: <20151203011556.GB4554@sejong> References: <20151202081605.GB26308@krava.brq.redhat.com> <1449070420-32401-1-git-send-email-namhyung@kernel.org> <50399556C9727B4D88A595C8584AAB375263F8A9@GSjpTKYDCembx32.service.hitachi.net> MIME-Version: 1.0 In-Reply-To: <50399556C9727B4D88A595C8584AAB375263F8A9@GSjpTKYDCembx32.service.hitachi.net> User-Agent: Mutt/1.5.24 (2015-08-30) X-MIMETrack: Itemize by SMTP Server on LGEKRMHUB05/LGE/LG Group(Release 8.5.3FP6|November 21, 2013) at 2015/12/03 10:22:33, Serialize by Router on LGEKRMHUB05/LGE/LG Group(Release 8.5.3FP6|November 21, 2013) at 2015/12/03 10:22:34 Content-Type: text/plain; charset="utf-8" Content-Disposition: inline Content-Transfer-Encoding: 8BIT Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 8169 Lines: 259 On Thu, Dec 03, 2015 at 12:15:12AM +0000, 平松雅巳 / HIRAMATU,MASAMI wrote: > >From: Namhyung Kim [mailto:namhyung@gmail.com] On Behalf Of Namhyung Kim > > > >Backtrace is a crucial info for debugging. And upcoming refcnt > >tracking facility also wants to use it. > > Note that the refcnt backtrace symbol resolution will work at > exit. This means that it can not depend on the feature in perf > tools itself. (and of course, since the refcnt tries to find unused > objects in perf tools at exit, if we use perf_thread, it will > detect the objects related to the perf_thread are leaked) Hmm.. right. I think we can leave the perf_thread outside of refcnt infrastructure. IOW it should be created before refcnt debugging is activated and released after refcnt is done. What do you think? Thanks, Namhyung > > > > >So instead of relying on glibc's backtrace_symbols[_fd] which misses > >some (static) functions , use our own symbol searching mechanism. To > >do that, add perf_thread global variable to keep its maps and symbols. > > > >The backtrace output from TUI is changed like below. (I made a key > >action to generate a segfault): > > > >Before: > > perf: Segmentation fault > > -------- backtrace -------- > > perf[0x544a8b] > > /usr/lib/libc.so.6(+0x33680)[0x7fc46420b680] > > perf[0x54041b] > > perf(perf_evlist__tui_browse_hists+0x91)[0x5432e1] > > perf(cmd_report+0x1d20)[0x43cb10] > > perf[0x487073] > > perf(main+0x62f)[0x42cb1f] > > /usr/lib/libc.so.6(__libc_start_main+0xf0)[0x7fc4641f8610] > > perf(_start+0x29)[0x42cc39] > > > >After: > > perf: Segmentation fault > > -------- backtrace -------- > > perf_evsel__hists_browse(+0x43b) in perf [0x54066b] > > perf_evlist__tui_browse_hists(+0x91) in perf [0x543531] > > cmd_report(+0x1d20) in perf [0x43cb50] > > run_builtin(+0x53) in perf [0x4870b3] > > main(+0x634) in perf [0x42cb54] > > __libc_start_main(+0xf0) in libc-2.22.so [0x7fea3577c610] > > _start(+0x29) in perf [0x42cc79] > > > >Cc: Frederic Weisbecker > >Cc: Masami Hiramatsu > >Signed-off-by: Namhyung Kim > >--- > >v3) check return value of create_perf_thread() > > > >v2) fallback to glibc's backtrace_symbols_fd() if failed > > > > tools/perf/perf.c | 10 +++++++- > > tools/perf/ui/tui/setup.c | 31 +++++++++++++++++++++-- > > tools/perf/util/util.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++ > > tools/perf/util/util.h | 5 ++++ > > 4 files changed, 106 insertions(+), 3 deletions(-) > > > >diff --git a/tools/perf/perf.c b/tools/perf/perf.c > >index 4bee53c3f796..f27dc5fa9534 100644 > >--- a/tools/perf/perf.c > >+++ b/tools/perf/perf.c > >@@ -604,6 +604,11 @@ int main(int argc, const char **argv) > > */ > > pthread__block_sigwinch(); > > > >+ if (create_perf_thread() < 0) { > >+ fprintf(stderr, "Failed to reserve information for backtrace\n"); > >+ goto out; > >+ } > >+ > > while (1) { > > static int done_help; > > int was_alias = run_argv(&argc, &argv); > >@@ -615,7 +620,7 @@ int main(int argc, const char **argv) > > fprintf(stderr, "Expansion of alias '%s' failed; " > > "'%s' is not a perf-command\n", > > cmd, argv[0]); > >- goto out; > >+ goto out_destroy; > > } > > if (!done_help) { > > cmd = argv[0] = help_unknown_cmd(cmd); > >@@ -626,6 +631,9 @@ int main(int argc, const char **argv) > > > > fprintf(stderr, "Failed to run command '%s': %s\n", > > cmd, strerror_r(errno, sbuf, sizeof(sbuf))); > >+ > >+out_destroy: > >+ destroy_perf_thread(); > > out: > > return 1; > > } > >diff --git a/tools/perf/ui/tui/setup.c b/tools/perf/ui/tui/setup.c > >index 7dfeba0a91f3..ba0ff1c4e6b7 100644 > >--- a/tools/perf/ui/tui/setup.c > >+++ b/tools/perf/ui/tui/setup.c > >@@ -13,6 +13,8 @@ > > #include "../libslang.h" > > #include "../keysyms.h" > > #include "tui.h" > >+#include "../../util/symbol.h" > >+#include "../../util/thread.h" > > > > static volatile int ui__need_resize; > > > >@@ -96,14 +98,39 @@ int ui__getch(int delay_secs) > > static void ui__signal_backtrace(int sig) > > { > > void *stackdump[32]; > >- size_t size; > >+ size_t size, i; > > > > ui__exit(false); > > psignal(sig, "perf"); > > > > printf("-------- backtrace --------\n"); > > size = backtrace(stackdump, ARRAY_SIZE(stackdump)); > >- backtrace_symbols_fd(stackdump, size, STDOUT_FILENO); > >+ /* skip first two stack frame (for this function and signal stack) */ > >+ for (i = 2; i < size; i++) { > >+ struct addr_location al = { > >+ .sym = NULL, > >+ }; > >+ > >+ /* valid callchain ends with 0 address */ > >+ if (stackdump[i] == NULL && i == (size - 1)) > >+ continue; > >+ > >+ thread__find_addr_location(perf_thread, PERF_RECORD_MISC_USER, > >+ MAP__FUNCTION, (long)stackdump[i], &al); > >+ > >+ if (!al.sym) > >+ break; > >+ > >+ printf("%s(+0x%"PRIx64") in %s [0x%lx]\n", al.sym->name, > >+ map__map_ip(al.map, (u64)stackdump[i]) - al.sym->start, > >+ al.map->dso->short_name, (unsigned long)stackdump[i]); > >+ } > >+ > >+ if (i != size) { > >+ printf("\nperf backtrace seems broken, try again with glibc\n"); > >+ printf("-------- backtrace --------\n"); > >+ backtrace_symbols_fd(stackdump, size, STDOUT_FILENO); > >+ } > > > > exit(0); > > } > >diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c > >index 75759aebc7b8..b1e591b13131 100644 > >--- a/tools/perf/util/util.c > >+++ b/tools/perf/util/util.c > >@@ -16,6 +16,9 @@ > > #include > > #include > > #include "callchain.h" > >+#include "machine.h" > >+#include "thread.h" > >+#include "thread_map.h" > > > > struct callchain_param callchain_param = { > > .mode = CHAIN_GRAPH_ABS, > >@@ -696,3 +699,63 @@ fetch_kernel_version(unsigned int *puint, char *str, > > *puint = (version << 16) + (patchlevel << 8) + sublevel; > > return 0; > > } > >+ > >+ > >+static int process_event(struct perf_tool *tool, union perf_event *event, > >+ struct perf_sample *sample, struct machine *machine) > >+{ > >+ switch (event->header.type) { > >+ case PERF_RECORD_COMM: > >+ return tool->comm(tool, event, sample, machine); > >+ case PERF_RECORD_MMAP: > >+ return tool->mmap(tool, event, sample, machine); > >+ case PERF_RECORD_MMAP2: > >+ return tool->mmap2(tool, event, sample, machine); > >+ default: > >+ break; > >+ } > >+ return 0; > >+} > >+ > >+struct thread *perf_thread; > >+ > >+int create_perf_thread(void) > >+{ > >+ struct perf_tool tool = { > >+ .comm = perf_event__process_comm, > >+ .mmap = perf_event__process_mmap, > >+ .mmap2 = perf_event__process_mmap2, > >+ }; > >+ struct thread_map *tm; > >+ struct machine *machine; > >+ int pid = getpid(); > >+ > >+ machine = machine__new_host(); > >+ if (machine == NULL) > >+ return -1; > >+ > >+ tm = thread_map__new_dummy(); > >+ if (tm == NULL) { > >+ machine__delete(machine); > >+ return -1; > >+ } > >+ > >+ thread_map__set_pid(tm, 0, pid); > >+ > >+ perf_event__synthesize_thread_map(&tool, tm, process_event, machine, > >+ false, 500); > >+ > >+ perf_thread = machine__find_thread(machine, pid, pid); > >+ BUG_ON(perf_thread == NULL); > >+ > >+ thread_map__put(tm); > >+ return 0; > >+} > >+ > >+void destroy_perf_thread(void) > >+{ > >+ struct machine *machine = perf_thread->mg->machine; > >+ > >+ machine__delete_threads(machine); > >+ machine__delete(machine); > >+} > >diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h > >index dcc659017976..769986044a7a 100644 > >--- a/tools/perf/util/util.h > >+++ b/tools/perf/util/util.h > >@@ -358,4 +358,9 @@ int fetch_kernel_version(unsigned int *puint, > > #define KVER_FMT "%d.%d.%d" > > #define KVER_PARAM(x) KVER_VERSION(x), KVER_PATCHLEVEL(x), KVER_SUBLEVEL(x) > > > >+extern struct thread *perf_thread; > >+ > >+int create_perf_thread(void); > >+void destroy_perf_thread(void); > >+ > > #endif /* GIT_COMPAT_UTIL_H */ > >-- > >2.6.2 > -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/