1*4248ae6eSIan Rogers // SPDX-License-Identifier: GPL-2.0 2*4248ae6eSIan Rogers #include "debug.h" 3*4248ae6eSIan Rogers #include "symbol_conf.h" 4*4248ae6eSIan Rogers #include "unwind.h" 5*4248ae6eSIan Rogers #include <linux/string.h> 6*4248ae6eSIan Rogers #include <string.h> 7*4248ae6eSIan Rogers #include <stdlib.h> 8*4248ae6eSIan Rogers 9*4248ae6eSIan Rogers int unwind__get_entries(unwind_entry_cb_t cb __maybe_unused, void *arg __maybe_unused, 10*4248ae6eSIan Rogers struct thread *thread __maybe_unused, 11*4248ae6eSIan Rogers struct perf_sample *data __maybe_unused, 12*4248ae6eSIan Rogers int max_stack __maybe_unused, 13*4248ae6eSIan Rogers bool best_effort __maybe_unused) 14*4248ae6eSIan Rogers { 15*4248ae6eSIan Rogers int ret = 0; 16*4248ae6eSIan Rogers 17*4248ae6eSIan Rogers #if defined(HAVE_LIBDW_SUPPORT) || defined(HAVE_LIBUNWIND_SUPPORT) 18*4248ae6eSIan Rogers if (symbol_conf.unwind_style[0] == UNWIND_STYLE_UNKNOWN) { 19*4248ae6eSIan Rogers int i = 0; 20*4248ae6eSIan Rogers #ifdef HAVE_LIBDW_SUPPORT 21*4248ae6eSIan Rogers symbol_conf.unwind_style[i++] = UNWIND_STYLE_LIBDW; 22*4248ae6eSIan Rogers #endif 23*4248ae6eSIan Rogers #ifdef HAVE_LIBUNWIND_SUPPORT 24*4248ae6eSIan Rogers symbol_conf.unwind_style[i++] = UNWIND_STYLE_LIBUNWIND; 25*4248ae6eSIan Rogers #endif 26*4248ae6eSIan Rogers } 27*4248ae6eSIan Rogers #endif //defined(HAVE_LIBDW_SUPPORT) || defined(HAVE_LIBUNWIND_SUPPORT) 28*4248ae6eSIan Rogers 29*4248ae6eSIan Rogers for (size_t i = 0; i < ARRAY_SIZE(symbol_conf.unwind_style); i++) { 30*4248ae6eSIan Rogers switch (symbol_conf.unwind_style[i]) { 31*4248ae6eSIan Rogers case UNWIND_STYLE_LIBDW: 32*4248ae6eSIan Rogers ret = libdw__get_entries(cb, arg, thread, data, max_stack, best_effort); 33*4248ae6eSIan Rogers break; 34*4248ae6eSIan Rogers case UNWIND_STYLE_LIBUNWIND: 35*4248ae6eSIan Rogers ret = libunwind__get_entries(cb, arg, thread, data, max_stack, best_effort); 36*4248ae6eSIan Rogers break; 37*4248ae6eSIan Rogers case UNWIND_STYLE_UNKNOWN: 38*4248ae6eSIan Rogers default: 39*4248ae6eSIan Rogers #if !defined(HAVE_LIBDW_SUPPORT) && !defined(HAVE_LIBUNWIND_SUPPORT) 40*4248ae6eSIan Rogers pr_warning_once( 41*4248ae6eSIan Rogers "Error: dwarf unwinding not supported, build perf with libdw or libunwind.\n"); 42*4248ae6eSIan Rogers #endif 43*4248ae6eSIan Rogers ret = 0; 44*4248ae6eSIan Rogers break; 45*4248ae6eSIan Rogers } 46*4248ae6eSIan Rogers if (ret > 0) { 47*4248ae6eSIan Rogers ret = 0; 48*4248ae6eSIan Rogers break; 49*4248ae6eSIan Rogers } 50*4248ae6eSIan Rogers if (ret < 0) 51*4248ae6eSIan Rogers break; 52*4248ae6eSIan Rogers } 53*4248ae6eSIan Rogers return ret; 54*4248ae6eSIan Rogers } 55*4248ae6eSIan Rogers 56*4248ae6eSIan Rogers int unwind__configure(const char *var, const char *value, void *cb __maybe_unused) 57*4248ae6eSIan Rogers { 58*4248ae6eSIan Rogers static const char * const unwind_style_names[] = { 59*4248ae6eSIan Rogers [UNWIND_STYLE_LIBDW] = "libdw", 60*4248ae6eSIan Rogers [UNWIND_STYLE_LIBUNWIND] = "libunwind", 61*4248ae6eSIan Rogers NULL 62*4248ae6eSIan Rogers }; 63*4248ae6eSIan Rogers char *s, *p, *saveptr; 64*4248ae6eSIan Rogers size_t i = 0; 65*4248ae6eSIan Rogers 66*4248ae6eSIan Rogers if (strcmp(var, "unwind.style")) 67*4248ae6eSIan Rogers return 0; 68*4248ae6eSIan Rogers 69*4248ae6eSIan Rogers if (!value) 70*4248ae6eSIan Rogers return -1; 71*4248ae6eSIan Rogers 72*4248ae6eSIan Rogers s = strdup(value); 73*4248ae6eSIan Rogers if (!s) 74*4248ae6eSIan Rogers return -1; 75*4248ae6eSIan Rogers 76*4248ae6eSIan Rogers memset(symbol_conf.unwind_style, 0, sizeof(symbol_conf.unwind_style)); 77*4248ae6eSIan Rogers 78*4248ae6eSIan Rogers p = strtok_r(s, ",", &saveptr); 79*4248ae6eSIan Rogers while (p && i < ARRAY_SIZE(symbol_conf.unwind_style)) { 80*4248ae6eSIan Rogers bool found = false; 81*4248ae6eSIan Rogers char *q = strim(p); 82*4248ae6eSIan Rogers 83*4248ae6eSIan Rogers for (size_t j = UNWIND_STYLE_LIBDW; j < MAX_UNWIND_STYLE; j++) { 84*4248ae6eSIan Rogers if (!strcasecmp(q, unwind_style_names[j])) { 85*4248ae6eSIan Rogers symbol_conf.unwind_style[i++] = j; 86*4248ae6eSIan Rogers found = true; 87*4248ae6eSIan Rogers break; 88*4248ae6eSIan Rogers } 89*4248ae6eSIan Rogers } 90*4248ae6eSIan Rogers if (!found) 91*4248ae6eSIan Rogers pr_warning("Unknown unwind style: %s\n", q); 92*4248ae6eSIan Rogers p = strtok_r(NULL, ",", &saveptr); 93*4248ae6eSIan Rogers } 94*4248ae6eSIan Rogers 95*4248ae6eSIan Rogers free(s); 96*4248ae6eSIan Rogers return 0; 97*4248ae6eSIan Rogers } 98*4248ae6eSIan Rogers 99*4248ae6eSIan Rogers int unwind__option(const struct option *opt __maybe_unused, 100*4248ae6eSIan Rogers const char *arg, 101*4248ae6eSIan Rogers int unset __maybe_unused) 102*4248ae6eSIan Rogers { 103*4248ae6eSIan Rogers return unwind__configure("unwind.style", arg, NULL); 104*4248ae6eSIan Rogers } 105