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