1 // SPDX-License-Identifier: GPL-2.0 2 #include "srcline.h" 3 #include "addr2line.h" 4 #include "dso.h" 5 #include "callchain.h" 6 #include "libbfd.h" 7 #include "llvm.h" 8 #include "symbol.h" 9 #include "libdw.h" 10 #include "debug.h" 11 #include "util.h" 12 13 #include <inttypes.h> 14 #include <string.h> 15 #include <linux/string.h> 16 #include <linux/zalloc.h> 17 18 bool srcline_full_filename; 19 20 char *srcline__unknown = (char *)"??:0"; 21 22 static const char *srcline_dso_name(struct dso *dso) 23 { 24 const char *dso_name; 25 26 if (dso__symsrc_filename(dso)) 27 dso_name = dso__symsrc_filename(dso); 28 else 29 dso_name = dso__long_name(dso); 30 31 if (dso_name[0] == '[') 32 return NULL; 33 34 if (is_perf_pid_map_name(dso_name)) 35 return NULL; 36 37 return dso_name; 38 } 39 40 int inline_list__append(struct symbol *symbol, char *srcline, struct inline_node *node) 41 { 42 struct inline_list *ilist; 43 44 ilist = zalloc(sizeof(*ilist)); 45 if (ilist == NULL) 46 return -1; 47 48 ilist->symbol = symbol; 49 ilist->srcline = srcline; 50 51 if (callchain_param.order == ORDER_CALLEE) 52 list_add_tail(&ilist->list, &node->val); 53 else 54 list_add(&ilist->list, &node->val); 55 56 return 0; 57 } 58 59 int inline_list__append_tail(struct symbol *symbol, char *srcline, struct inline_node *node) 60 { 61 struct inline_list *ilist; 62 63 ilist = zalloc(sizeof(*ilist)); 64 if (ilist == NULL) 65 return -1; 66 67 ilist->symbol = symbol; 68 ilist->srcline = srcline; 69 70 if (callchain_param.order == ORDER_CALLEE) 71 list_add(&ilist->list, &node->val); 72 else 73 list_add_tail(&ilist->list, &node->val); 74 75 return 0; 76 } 77 78 char *srcline_from_fileline(const char *file, unsigned int line) 79 { 80 char *srcline; 81 82 if (!file) 83 return NULL; 84 85 if (!srcline_full_filename) 86 file = perf_basename(file); 87 88 if (asprintf(&srcline, "%s:%u", file, line) < 0) 89 return NULL; 90 91 return srcline; 92 } 93 94 struct symbol *new_inline_sym(struct dso *dso, 95 struct symbol *base_sym, 96 const char *funcname) 97 { 98 struct symbol *inline_sym; 99 char *demangled = NULL; 100 101 if (!funcname) 102 funcname = "??"; 103 104 if (dso) { 105 demangled = dso__demangle_sym(dso, 0, funcname); 106 if (demangled) 107 funcname = demangled; 108 } 109 110 if (base_sym && strcmp(funcname, base_sym->name) == 0) { 111 /* reuse the real, existing symbol */ 112 inline_sym = base_sym; 113 /* ensure that we don't alias an inlined symbol, which could 114 * lead to double frees in inline_node__delete 115 */ 116 assert(!base_sym->inlined); 117 } else { 118 /* create a fake symbol for the inline frame */ 119 inline_sym = symbol__new(base_sym ? base_sym->start : 0, 120 base_sym ? (base_sym->end - base_sym->start) : 0, 121 base_sym ? base_sym->binding : 0, 122 base_sym ? base_sym->type : 0, 123 funcname); 124 if (inline_sym) 125 inline_sym->inlined = 1; 126 } 127 128 free(demangled); 129 130 return inline_sym; 131 } 132 133 static int addr2line(const char *dso_name, u64 addr, char **file, unsigned int *line_nr, 134 struct dso *dso, bool unwind_inlines, struct inline_node *node, 135 struct symbol *sym) 136 { 137 int ret = 0; 138 139 if (symbol_conf.addr2line_style[0] == A2L_STYLE_UNKNOWN) { 140 int i = 0; 141 142 /* Default addr2line fallback order. */ 143 #ifdef HAVE_LIBDW_SUPPORT 144 symbol_conf.addr2line_style[i++] = A2L_STYLE_LIBDW; 145 #endif 146 #ifdef HAVE_LIBLLVM_SUPPORT 147 symbol_conf.addr2line_style[i++] = A2L_STYLE_LLVM; 148 #endif 149 #ifdef HAVE_LIBBFD_SUPPORT 150 symbol_conf.addr2line_style[i++] = A2L_STYLE_LIBBFD; 151 #endif 152 symbol_conf.addr2line_style[i++] = A2L_STYLE_CMD; 153 } 154 155 for (size_t i = 0; i < ARRAY_SIZE(symbol_conf.addr2line_style); i++) { 156 switch (symbol_conf.addr2line_style[i]) { 157 case A2L_STYLE_LIBDW: 158 ret = libdw__addr2line(addr, file, line_nr, dso, unwind_inlines, 159 node, sym); 160 break; 161 case A2L_STYLE_LLVM: 162 ret = llvm__addr2line(dso_name, addr, file, line_nr, dso, unwind_inlines, 163 node, sym); 164 break; 165 case A2L_STYLE_LIBBFD: 166 ret = libbfd__addr2line(dso_name, addr, file, line_nr, dso, unwind_inlines, 167 node, sym); 168 break; 169 case A2L_STYLE_CMD: 170 ret = cmd__addr2line(dso_name, addr, file, line_nr, dso, unwind_inlines, 171 node, sym); 172 break; 173 case A2L_STYLE_UNKNOWN: 174 default: 175 break; 176 } 177 if (ret > 0) 178 return ret; 179 } 180 181 return 0; 182 } 183 184 int addr2line_configure(const char *var, const char *value, void *cb __maybe_unused) 185 { 186 static const char * const a2l_style_names[] = { 187 [A2L_STYLE_LIBDW] = "libdw", 188 [A2L_STYLE_LLVM] = "llvm", 189 [A2L_STYLE_LIBBFD] = "libbfd", 190 [A2L_STYLE_CMD] = "addr2line", 191 NULL 192 }; 193 194 char *s, *p, *saveptr; 195 size_t i = 0; 196 197 if (strcmp(var, "addr2line.style")) 198 return 0; 199 200 if (!value) 201 return -1; 202 203 s = strdup(value); 204 if (!s) 205 return -1; 206 207 p = strtok_r(s, ",", &saveptr); 208 while (p && i < ARRAY_SIZE(symbol_conf.addr2line_style)) { 209 bool found = false; 210 char *q = strim(p); 211 212 for (size_t j = A2L_STYLE_LIBDW; j < MAX_A2L_STYLE; j++) { 213 if (!strcasecmp(q, a2l_style_names[j])) { 214 symbol_conf.addr2line_style[i++] = j; 215 found = true; 216 break; 217 } 218 } 219 if (!found) 220 pr_warning("Unknown addr2line style: %s\n", q); 221 p = strtok_r(NULL, ",", &saveptr); 222 } 223 224 free(s); 225 return 0; 226 } 227 228 static struct inline_node *addr2inlines(const char *dso_name, u64 addr, 229 struct dso *dso, struct symbol *sym) 230 { 231 struct inline_node *node; 232 233 node = zalloc(sizeof(*node)); 234 if (node == NULL) { 235 perror("not enough memory for the inline node"); 236 return NULL; 237 } 238 239 INIT_LIST_HEAD(&node->val); 240 node->addr = addr; 241 242 addr2line(dso_name, addr, /*file=*/NULL, /*line_nr=*/NULL, dso, 243 /*unwind_inlines=*/true, node, sym); 244 245 return node; 246 } 247 248 /* 249 * Number of addr2line failures (without success) before disabling it for that 250 * dso. 251 */ 252 #define A2L_FAIL_LIMIT 123 253 254 char *__get_srcline(struct dso *dso, u64 addr, struct symbol *sym, 255 bool show_sym, bool show_addr, bool unwind_inlines, 256 u64 ip) 257 { 258 char *file = NULL; 259 unsigned line = 0; 260 char *srcline; 261 const char *dso_name; 262 263 if (!dso__has_srcline(dso)) 264 goto out; 265 266 dso_name = srcline_dso_name(dso); 267 if (dso_name == NULL) 268 goto out_err; 269 270 if (!addr2line(dso_name, addr, &file, &line, dso, 271 unwind_inlines, /*node=*/NULL, sym)) 272 goto out_err; 273 274 srcline = srcline_from_fileline(file, line); 275 free(file); 276 277 if (!srcline) 278 goto out_err; 279 280 dso__set_a2l_fails(dso, 0); 281 282 return srcline; 283 284 out_err: 285 dso__set_a2l_fails(dso, dso__a2l_fails(dso) + 1); 286 if (dso__a2l_fails(dso) > A2L_FAIL_LIMIT) { 287 dso__set_has_srcline(dso, false); 288 dso__free_a2l(dso); 289 } 290 out: 291 if (!show_addr) 292 return (show_sym && sym) ? 293 strndup(sym->name, sym->namelen) : SRCLINE_UNKNOWN; 294 295 if (sym) { 296 if (asprintf(&srcline, "%s+%" PRIu64, show_sym ? sym->name : "", 297 ip - sym->start) < 0) 298 return SRCLINE_UNKNOWN; 299 } else if (asprintf(&srcline, "%s[%" PRIx64 "]", dso__short_name(dso), addr) < 0) 300 return SRCLINE_UNKNOWN; 301 return srcline; 302 } 303 304 /* Returns filename and fills in line number in line */ 305 char *get_srcline_split(struct dso *dso, u64 addr, unsigned *line) 306 { 307 char *file = NULL; 308 const char *dso_name; 309 310 if (!dso__has_srcline(dso)) 311 return NULL; 312 313 dso_name = srcline_dso_name(dso); 314 if (dso_name == NULL) 315 goto out_err; 316 317 if (!addr2line(dso_name, addr, &file, line, dso, /*unwind_inlines=*/true, 318 /*node=*/NULL, /*sym=*/NULL)) 319 goto out_err; 320 321 dso__set_a2l_fails(dso, 0); 322 return file; 323 324 out_err: 325 dso__set_a2l_fails(dso, dso__a2l_fails(dso) + 1); 326 if (dso__a2l_fails(dso) > A2L_FAIL_LIMIT) { 327 dso__set_has_srcline(dso, false); 328 dso__free_a2l(dso); 329 } 330 331 return NULL; 332 } 333 334 void zfree_srcline(char **srcline) 335 { 336 if (*srcline == NULL) 337 return; 338 339 if (*srcline != SRCLINE_UNKNOWN) 340 free(*srcline); 341 342 *srcline = NULL; 343 } 344 345 char *get_srcline(struct dso *dso, u64 addr, struct symbol *sym, 346 bool show_sym, bool show_addr, u64 ip) 347 { 348 return __get_srcline(dso, addr, sym, show_sym, show_addr, false, ip); 349 } 350 351 struct srcline_node { 352 u64 addr; 353 char *srcline; 354 struct rb_node rb_node; 355 }; 356 357 void srcline__tree_insert(struct rb_root_cached *tree, u64 addr, char *srcline) 358 { 359 struct rb_node **p = &tree->rb_root.rb_node; 360 struct rb_node *parent = NULL; 361 struct srcline_node *i, *node; 362 bool leftmost = true; 363 364 node = zalloc(sizeof(struct srcline_node)); 365 if (!node) { 366 perror("not enough memory for the srcline node"); 367 return; 368 } 369 370 node->addr = addr; 371 node->srcline = srcline; 372 373 while (*p != NULL) { 374 parent = *p; 375 i = rb_entry(parent, struct srcline_node, rb_node); 376 if (addr < i->addr) 377 p = &(*p)->rb_left; 378 else { 379 p = &(*p)->rb_right; 380 leftmost = false; 381 } 382 } 383 rb_link_node(&node->rb_node, parent, p); 384 rb_insert_color_cached(&node->rb_node, tree, leftmost); 385 } 386 387 char *srcline__tree_find(struct rb_root_cached *tree, u64 addr) 388 { 389 struct rb_node *n = tree->rb_root.rb_node; 390 391 while (n) { 392 struct srcline_node *i = rb_entry(n, struct srcline_node, 393 rb_node); 394 395 if (addr < i->addr) 396 n = n->rb_left; 397 else if (addr > i->addr) 398 n = n->rb_right; 399 else 400 return i->srcline; 401 } 402 403 return NULL; 404 } 405 406 void srcline__tree_delete(struct rb_root_cached *tree) 407 { 408 struct srcline_node *pos; 409 struct rb_node *next = rb_first_cached(tree); 410 411 while (next) { 412 pos = rb_entry(next, struct srcline_node, rb_node); 413 next = rb_next(&pos->rb_node); 414 rb_erase_cached(&pos->rb_node, tree); 415 zfree_srcline(&pos->srcline); 416 zfree(&pos); 417 } 418 } 419 420 struct inline_node *dso__parse_addr_inlines(struct dso *dso, u64 addr, 421 struct symbol *sym) 422 { 423 const char *dso_name; 424 425 dso_name = srcline_dso_name(dso); 426 if (dso_name == NULL) 427 return NULL; 428 429 return addr2inlines(dso_name, addr, dso, sym); 430 } 431 432 void inline_node__delete(struct inline_node *node) 433 { 434 struct inline_list *ilist, *tmp; 435 436 list_for_each_entry_safe(ilist, tmp, &node->val, list) { 437 list_del_init(&ilist->list); 438 zfree_srcline(&ilist->srcline); 439 /* only the inlined symbols are owned by the list */ 440 if (ilist->symbol && ilist->symbol->inlined) 441 symbol__delete(ilist->symbol); 442 free(ilist); 443 } 444 445 free(node); 446 } 447 448 void inlines__tree_insert(struct rb_root_cached *tree, 449 struct inline_node *inlines) 450 { 451 struct rb_node **p = &tree->rb_root.rb_node; 452 struct rb_node *parent = NULL; 453 const u64 addr = inlines->addr; 454 struct inline_node *i; 455 bool leftmost = true; 456 457 while (*p != NULL) { 458 parent = *p; 459 i = rb_entry(parent, struct inline_node, rb_node); 460 if (addr < i->addr) 461 p = &(*p)->rb_left; 462 else { 463 p = &(*p)->rb_right; 464 leftmost = false; 465 } 466 } 467 rb_link_node(&inlines->rb_node, parent, p); 468 rb_insert_color_cached(&inlines->rb_node, tree, leftmost); 469 } 470 471 struct inline_node *inlines__tree_find(struct rb_root_cached *tree, u64 addr) 472 { 473 struct rb_node *n = tree->rb_root.rb_node; 474 475 while (n) { 476 struct inline_node *i = rb_entry(n, struct inline_node, 477 rb_node); 478 479 if (addr < i->addr) 480 n = n->rb_left; 481 else if (addr > i->addr) 482 n = n->rb_right; 483 else 484 return i; 485 } 486 487 return NULL; 488 } 489 490 void inlines__tree_delete(struct rb_root_cached *tree) 491 { 492 struct inline_node *pos; 493 struct rb_node *next = rb_first_cached(tree); 494 495 while (next) { 496 pos = rb_entry(next, struct inline_node, rb_node); 497 next = rb_next(&pos->rb_node); 498 rb_erase_cached(&pos->rb_node, tree); 499 inline_node__delete(pos); 500 } 501 } 502