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