1 /* 2 * probe-finder.c : C expression to kprobe event converter 3 * 4 * Written by Masami Hiramatsu <mhiramat@redhat.com> 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 19 * 20 */ 21 22 #include <sys/utsname.h> 23 #include <sys/types.h> 24 #include <sys/stat.h> 25 #include <fcntl.h> 26 #include <errno.h> 27 #include <stdio.h> 28 #include <unistd.h> 29 #include <stdlib.h> 30 #include <string.h> 31 #include <stdarg.h> 32 #include <dwarf-regs.h> 33 34 #include <linux/bitops.h> 35 #include "event.h" 36 #include "dso.h" 37 #include "debug.h" 38 #include "intlist.h" 39 #include "util.h" 40 #include "symbol.h" 41 #include "probe-finder.h" 42 43 /* Kprobe tracer basic type is up to u64 */ 44 #define MAX_BASIC_TYPE_BITS 64 45 46 /* Dwarf FL wrappers */ 47 static char *debuginfo_path; /* Currently dummy */ 48 49 static const Dwfl_Callbacks offline_callbacks = { 50 .find_debuginfo = dwfl_standard_find_debuginfo, 51 .debuginfo_path = &debuginfo_path, 52 53 .section_address = dwfl_offline_section_address, 54 55 /* We use this table for core files too. */ 56 .find_elf = dwfl_build_id_find_elf, 57 }; 58 59 /* Get a Dwarf from offline image */ 60 static int debuginfo__init_offline_dwarf(struct debuginfo *dbg, 61 const char *path) 62 { 63 int fd; 64 65 fd = open(path, O_RDONLY); 66 if (fd < 0) 67 return fd; 68 69 dbg->dwfl = dwfl_begin(&offline_callbacks); 70 if (!dbg->dwfl) 71 goto error; 72 73 dbg->mod = dwfl_report_offline(dbg->dwfl, "", "", fd); 74 if (!dbg->mod) 75 goto error; 76 77 dbg->dbg = dwfl_module_getdwarf(dbg->mod, &dbg->bias); 78 if (!dbg->dbg) 79 goto error; 80 81 return 0; 82 error: 83 if (dbg->dwfl) 84 dwfl_end(dbg->dwfl); 85 else 86 close(fd); 87 memset(dbg, 0, sizeof(*dbg)); 88 89 return -ENOENT; 90 } 91 92 static struct debuginfo *__debuginfo__new(const char *path) 93 { 94 struct debuginfo *dbg = zalloc(sizeof(*dbg)); 95 if (!dbg) 96 return NULL; 97 98 if (debuginfo__init_offline_dwarf(dbg, path) < 0) 99 zfree(&dbg); 100 if (dbg) 101 pr_debug("Open Debuginfo file: %s\n", path); 102 return dbg; 103 } 104 105 enum dso_binary_type distro_dwarf_types[] = { 106 DSO_BINARY_TYPE__FEDORA_DEBUGINFO, 107 DSO_BINARY_TYPE__UBUNTU_DEBUGINFO, 108 DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO, 109 DSO_BINARY_TYPE__BUILDID_DEBUGINFO, 110 DSO_BINARY_TYPE__NOT_FOUND, 111 }; 112 113 struct debuginfo *debuginfo__new(const char *path) 114 { 115 enum dso_binary_type *type; 116 char buf[PATH_MAX], nil = '\0'; 117 struct dso *dso; 118 struct debuginfo *dinfo = NULL; 119 120 /* Try to open distro debuginfo files */ 121 dso = dso__new(path); 122 if (!dso) 123 goto out; 124 125 for (type = distro_dwarf_types; 126 !dinfo && *type != DSO_BINARY_TYPE__NOT_FOUND; 127 type++) { 128 if (dso__read_binary_type_filename(dso, *type, &nil, 129 buf, PATH_MAX) < 0) 130 continue; 131 dinfo = __debuginfo__new(buf); 132 } 133 dso__put(dso); 134 135 out: 136 /* if failed to open all distro debuginfo, open given binary */ 137 return dinfo ? : __debuginfo__new(path); 138 } 139 140 void debuginfo__delete(struct debuginfo *dbg) 141 { 142 if (dbg) { 143 if (dbg->dwfl) 144 dwfl_end(dbg->dwfl); 145 free(dbg); 146 } 147 } 148 149 /* 150 * Probe finder related functions 151 */ 152 153 static struct probe_trace_arg_ref *alloc_trace_arg_ref(long offs) 154 { 155 struct probe_trace_arg_ref *ref; 156 ref = zalloc(sizeof(struct probe_trace_arg_ref)); 157 if (ref != NULL) 158 ref->offset = offs; 159 return ref; 160 } 161 162 /* 163 * Convert a location into trace_arg. 164 * If tvar == NULL, this just checks variable can be converted. 165 * If fentry == true and vr_die is a parameter, do huristic search 166 * for the location fuzzed by function entry mcount. 167 */ 168 static int convert_variable_location(Dwarf_Die *vr_die, Dwarf_Addr addr, 169 Dwarf_Op *fb_ops, Dwarf_Die *sp_die, 170 struct probe_trace_arg *tvar) 171 { 172 Dwarf_Attribute attr; 173 Dwarf_Addr tmp = 0; 174 Dwarf_Op *op; 175 size_t nops; 176 unsigned int regn; 177 Dwarf_Word offs = 0; 178 bool ref = false; 179 const char *regs; 180 int ret, ret2 = 0; 181 182 if (dwarf_attr(vr_die, DW_AT_external, &attr) != NULL) 183 goto static_var; 184 185 /* TODO: handle more than 1 exprs */ 186 if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL) 187 return -EINVAL; /* Broken DIE ? */ 188 if (dwarf_getlocation_addr(&attr, addr, &op, &nops, 1) <= 0) { 189 ret = dwarf_entrypc(sp_die, &tmp); 190 if (ret) 191 return -ENOENT; 192 193 if (probe_conf.show_location_range && 194 (dwarf_tag(vr_die) == DW_TAG_variable)) { 195 ret2 = -ERANGE; 196 } else if (addr != tmp || 197 dwarf_tag(vr_die) != DW_TAG_formal_parameter) { 198 return -ENOENT; 199 } 200 201 ret = dwarf_highpc(sp_die, &tmp); 202 if (ret) 203 return -ENOENT; 204 /* 205 * This is fuzzed by fentry mcount. We try to find the 206 * parameter location at the earliest address. 207 */ 208 for (addr += 1; addr <= tmp; addr++) { 209 if (dwarf_getlocation_addr(&attr, addr, &op, 210 &nops, 1) > 0) 211 goto found; 212 } 213 return -ENOENT; 214 } 215 found: 216 if (nops == 0) 217 /* TODO: Support const_value */ 218 return -ENOENT; 219 220 if (op->atom == DW_OP_addr) { 221 static_var: 222 if (!tvar) 223 return ret2; 224 /* Static variables on memory (not stack), make @varname */ 225 ret = strlen(dwarf_diename(vr_die)); 226 tvar->value = zalloc(ret + 2); 227 if (tvar->value == NULL) 228 return -ENOMEM; 229 snprintf(tvar->value, ret + 2, "@%s", dwarf_diename(vr_die)); 230 tvar->ref = alloc_trace_arg_ref((long)offs); 231 if (tvar->ref == NULL) 232 return -ENOMEM; 233 return ret2; 234 } 235 236 /* If this is based on frame buffer, set the offset */ 237 if (op->atom == DW_OP_fbreg) { 238 if (fb_ops == NULL) 239 return -ENOTSUP; 240 ref = true; 241 offs = op->number; 242 op = &fb_ops[0]; 243 } 244 245 if (op->atom >= DW_OP_breg0 && op->atom <= DW_OP_breg31) { 246 regn = op->atom - DW_OP_breg0; 247 offs += op->number; 248 ref = true; 249 } else if (op->atom >= DW_OP_reg0 && op->atom <= DW_OP_reg31) { 250 regn = op->atom - DW_OP_reg0; 251 } else if (op->atom == DW_OP_bregx) { 252 regn = op->number; 253 offs += op->number2; 254 ref = true; 255 } else if (op->atom == DW_OP_regx) { 256 regn = op->number; 257 } else { 258 pr_debug("DW_OP %x is not supported.\n", op->atom); 259 return -ENOTSUP; 260 } 261 262 if (!tvar) 263 return ret2; 264 265 regs = get_arch_regstr(regn); 266 if (!regs) { 267 /* This should be a bug in DWARF or this tool */ 268 pr_warning("Mapping for the register number %u " 269 "missing on this architecture.\n", regn); 270 return -ENOTSUP; 271 } 272 273 tvar->value = strdup(regs); 274 if (tvar->value == NULL) 275 return -ENOMEM; 276 277 if (ref) { 278 tvar->ref = alloc_trace_arg_ref((long)offs); 279 if (tvar->ref == NULL) 280 return -ENOMEM; 281 } 282 return ret2; 283 } 284 285 #define BYTES_TO_BITS(nb) ((nb) * BITS_PER_LONG / sizeof(long)) 286 287 static int convert_variable_type(Dwarf_Die *vr_die, 288 struct probe_trace_arg *tvar, 289 const char *cast) 290 { 291 struct probe_trace_arg_ref **ref_ptr = &tvar->ref; 292 Dwarf_Die type; 293 char buf[16]; 294 char sbuf[STRERR_BUFSIZE]; 295 int bsize, boffs, total; 296 int ret; 297 298 /* TODO: check all types */ 299 if (cast && strcmp(cast, "string") != 0) { 300 /* Non string type is OK */ 301 tvar->type = strdup(cast); 302 return (tvar->type == NULL) ? -ENOMEM : 0; 303 } 304 305 bsize = dwarf_bitsize(vr_die); 306 if (bsize > 0) { 307 /* This is a bitfield */ 308 boffs = dwarf_bitoffset(vr_die); 309 total = dwarf_bytesize(vr_die); 310 if (boffs < 0 || total < 0) 311 return -ENOENT; 312 ret = snprintf(buf, 16, "b%d@%d/%zd", bsize, boffs, 313 BYTES_TO_BITS(total)); 314 goto formatted; 315 } 316 317 if (die_get_real_type(vr_die, &type) == NULL) { 318 pr_warning("Failed to get a type information of %s.\n", 319 dwarf_diename(vr_die)); 320 return -ENOENT; 321 } 322 323 pr_debug("%s type is %s.\n", 324 dwarf_diename(vr_die), dwarf_diename(&type)); 325 326 if (cast && strcmp(cast, "string") == 0) { /* String type */ 327 ret = dwarf_tag(&type); 328 if (ret != DW_TAG_pointer_type && 329 ret != DW_TAG_array_type) { 330 pr_warning("Failed to cast into string: " 331 "%s(%s) is not a pointer nor array.\n", 332 dwarf_diename(vr_die), dwarf_diename(&type)); 333 return -EINVAL; 334 } 335 if (die_get_real_type(&type, &type) == NULL) { 336 pr_warning("Failed to get a type" 337 " information.\n"); 338 return -ENOENT; 339 } 340 if (ret == DW_TAG_pointer_type) { 341 while (*ref_ptr) 342 ref_ptr = &(*ref_ptr)->next; 343 /* Add new reference with offset +0 */ 344 *ref_ptr = zalloc(sizeof(struct probe_trace_arg_ref)); 345 if (*ref_ptr == NULL) { 346 pr_warning("Out of memory error\n"); 347 return -ENOMEM; 348 } 349 } 350 if (!die_compare_name(&type, "char") && 351 !die_compare_name(&type, "unsigned char")) { 352 pr_warning("Failed to cast into string: " 353 "%s is not (unsigned) char *.\n", 354 dwarf_diename(vr_die)); 355 return -EINVAL; 356 } 357 tvar->type = strdup(cast); 358 return (tvar->type == NULL) ? -ENOMEM : 0; 359 } 360 361 ret = dwarf_bytesize(&type); 362 if (ret <= 0) 363 /* No size ... try to use default type */ 364 return 0; 365 ret = BYTES_TO_BITS(ret); 366 367 /* Check the bitwidth */ 368 if (ret > MAX_BASIC_TYPE_BITS) { 369 pr_info("%s exceeds max-bitwidth. Cut down to %d bits.\n", 370 dwarf_diename(&type), MAX_BASIC_TYPE_BITS); 371 ret = MAX_BASIC_TYPE_BITS; 372 } 373 ret = snprintf(buf, 16, "%c%d", 374 die_is_signed_type(&type) ? 's' : 'u', ret); 375 376 formatted: 377 if (ret < 0 || ret >= 16) { 378 if (ret >= 16) 379 ret = -E2BIG; 380 pr_warning("Failed to convert variable type: %s\n", 381 strerror_r(-ret, sbuf, sizeof(sbuf))); 382 return ret; 383 } 384 tvar->type = strdup(buf); 385 if (tvar->type == NULL) 386 return -ENOMEM; 387 return 0; 388 } 389 390 static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname, 391 struct perf_probe_arg_field *field, 392 struct probe_trace_arg_ref **ref_ptr, 393 Dwarf_Die *die_mem) 394 { 395 struct probe_trace_arg_ref *ref = *ref_ptr; 396 Dwarf_Die type; 397 Dwarf_Word offs; 398 int ret, tag; 399 400 pr_debug("converting %s in %s\n", field->name, varname); 401 if (die_get_real_type(vr_die, &type) == NULL) { 402 pr_warning("Failed to get the type of %s.\n", varname); 403 return -ENOENT; 404 } 405 pr_debug2("Var real type: (%x)\n", (unsigned)dwarf_dieoffset(&type)); 406 tag = dwarf_tag(&type); 407 408 if (field->name[0] == '[' && 409 (tag == DW_TAG_array_type || tag == DW_TAG_pointer_type)) { 410 if (field->next) 411 /* Save original type for next field */ 412 memcpy(die_mem, &type, sizeof(*die_mem)); 413 /* Get the type of this array */ 414 if (die_get_real_type(&type, &type) == NULL) { 415 pr_warning("Failed to get the type of %s.\n", varname); 416 return -ENOENT; 417 } 418 pr_debug2("Array real type: (%x)\n", 419 (unsigned)dwarf_dieoffset(&type)); 420 if (tag == DW_TAG_pointer_type) { 421 ref = zalloc(sizeof(struct probe_trace_arg_ref)); 422 if (ref == NULL) 423 return -ENOMEM; 424 if (*ref_ptr) 425 (*ref_ptr)->next = ref; 426 else 427 *ref_ptr = ref; 428 } 429 ref->offset += dwarf_bytesize(&type) * field->index; 430 if (!field->next) 431 /* Save vr_die for converting types */ 432 memcpy(die_mem, vr_die, sizeof(*die_mem)); 433 goto next; 434 } else if (tag == DW_TAG_pointer_type) { 435 /* Check the pointer and dereference */ 436 if (!field->ref) { 437 pr_err("Semantic error: %s must be referred by '->'\n", 438 field->name); 439 return -EINVAL; 440 } 441 /* Get the type pointed by this pointer */ 442 if (die_get_real_type(&type, &type) == NULL) { 443 pr_warning("Failed to get the type of %s.\n", varname); 444 return -ENOENT; 445 } 446 /* Verify it is a data structure */ 447 tag = dwarf_tag(&type); 448 if (tag != DW_TAG_structure_type && tag != DW_TAG_union_type) { 449 pr_warning("%s is not a data structure nor an union.\n", 450 varname); 451 return -EINVAL; 452 } 453 454 ref = zalloc(sizeof(struct probe_trace_arg_ref)); 455 if (ref == NULL) 456 return -ENOMEM; 457 if (*ref_ptr) 458 (*ref_ptr)->next = ref; 459 else 460 *ref_ptr = ref; 461 } else { 462 /* Verify it is a data structure */ 463 if (tag != DW_TAG_structure_type && tag != DW_TAG_union_type) { 464 pr_warning("%s is not a data structure nor an union.\n", 465 varname); 466 return -EINVAL; 467 } 468 if (field->name[0] == '[') { 469 pr_err("Semantic error: %s is not a pointer" 470 " nor array.\n", varname); 471 return -EINVAL; 472 } 473 /* While prcessing unnamed field, we don't care about this */ 474 if (field->ref && dwarf_diename(vr_die)) { 475 pr_err("Semantic error: %s must be referred by '.'\n", 476 field->name); 477 return -EINVAL; 478 } 479 if (!ref) { 480 pr_warning("Structure on a register is not " 481 "supported yet.\n"); 482 return -ENOTSUP; 483 } 484 } 485 486 if (die_find_member(&type, field->name, die_mem) == NULL) { 487 pr_warning("%s(type:%s) has no member %s.\n", varname, 488 dwarf_diename(&type), field->name); 489 return -EINVAL; 490 } 491 492 /* Get the offset of the field */ 493 if (tag == DW_TAG_union_type) { 494 offs = 0; 495 } else { 496 ret = die_get_data_member_location(die_mem, &offs); 497 if (ret < 0) { 498 pr_warning("Failed to get the offset of %s.\n", 499 field->name); 500 return ret; 501 } 502 } 503 ref->offset += (long)offs; 504 505 /* If this member is unnamed, we need to reuse this field */ 506 if (!dwarf_diename(die_mem)) 507 return convert_variable_fields(die_mem, varname, field, 508 &ref, die_mem); 509 510 next: 511 /* Converting next field */ 512 if (field->next) 513 return convert_variable_fields(die_mem, field->name, 514 field->next, &ref, die_mem); 515 else 516 return 0; 517 } 518 519 /* Show a variables in kprobe event format */ 520 static int convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf) 521 { 522 Dwarf_Die die_mem; 523 int ret; 524 525 pr_debug("Converting variable %s into trace event.\n", 526 dwarf_diename(vr_die)); 527 528 ret = convert_variable_location(vr_die, pf->addr, pf->fb_ops, 529 &pf->sp_die, pf->tvar); 530 if (ret == -ENOENT || ret == -EINVAL) { 531 pr_err("Failed to find the location of the '%s' variable at this address.\n" 532 " Perhaps it has been optimized out.\n" 533 " Use -V with the --range option to show '%s' location range.\n", 534 pf->pvar->var, pf->pvar->var); 535 } else if (ret == -ENOTSUP) 536 pr_err("Sorry, we don't support this variable location yet.\n"); 537 else if (ret == 0 && pf->pvar->field) { 538 ret = convert_variable_fields(vr_die, pf->pvar->var, 539 pf->pvar->field, &pf->tvar->ref, 540 &die_mem); 541 vr_die = &die_mem; 542 } 543 if (ret == 0) 544 ret = convert_variable_type(vr_die, pf->tvar, pf->pvar->type); 545 /* *expr will be cached in libdw. Don't free it. */ 546 return ret; 547 } 548 549 /* Find a variable in a scope DIE */ 550 static int find_variable(Dwarf_Die *sc_die, struct probe_finder *pf) 551 { 552 Dwarf_Die vr_die; 553 char buf[32], *ptr; 554 int ret = 0; 555 556 /* Copy raw parameters */ 557 if (!is_c_varname(pf->pvar->var)) 558 return copy_to_probe_trace_arg(pf->tvar, pf->pvar); 559 560 if (pf->pvar->name) 561 pf->tvar->name = strdup(pf->pvar->name); 562 else { 563 ret = synthesize_perf_probe_arg(pf->pvar, buf, 32); 564 if (ret < 0) 565 return ret; 566 ptr = strchr(buf, ':'); /* Change type separator to _ */ 567 if (ptr) 568 *ptr = '_'; 569 pf->tvar->name = strdup(buf); 570 } 571 if (pf->tvar->name == NULL) 572 return -ENOMEM; 573 574 pr_debug("Searching '%s' variable in context.\n", pf->pvar->var); 575 /* Search child die for local variables and parameters. */ 576 if (!die_find_variable_at(sc_die, pf->pvar->var, pf->addr, &vr_die)) { 577 /* Search again in global variables */ 578 if (!die_find_variable_at(&pf->cu_die, pf->pvar->var, 579 0, &vr_die)) { 580 pr_warning("Failed to find '%s' in this function.\n", 581 pf->pvar->var); 582 ret = -ENOENT; 583 } 584 } 585 if (ret >= 0) 586 ret = convert_variable(&vr_die, pf); 587 588 return ret; 589 } 590 591 /* Convert subprogram DIE to trace point */ 592 static int convert_to_trace_point(Dwarf_Die *sp_die, Dwfl_Module *mod, 593 Dwarf_Addr paddr, bool retprobe, 594 struct probe_trace_point *tp) 595 { 596 Dwarf_Addr eaddr, highaddr; 597 GElf_Sym sym; 598 const char *symbol; 599 600 /* Verify the address is correct */ 601 if (dwarf_entrypc(sp_die, &eaddr) != 0) { 602 pr_warning("Failed to get entry address of %s\n", 603 dwarf_diename(sp_die)); 604 return -ENOENT; 605 } 606 if (dwarf_highpc(sp_die, &highaddr) != 0) { 607 pr_warning("Failed to get end address of %s\n", 608 dwarf_diename(sp_die)); 609 return -ENOENT; 610 } 611 if (paddr > highaddr) { 612 pr_warning("Offset specified is greater than size of %s\n", 613 dwarf_diename(sp_die)); 614 return -EINVAL; 615 } 616 617 symbol = dwarf_diename(sp_die); 618 if (!symbol) { 619 /* Try to get the symbol name from symtab */ 620 symbol = dwfl_module_addrsym(mod, paddr, &sym, NULL); 621 if (!symbol) { 622 pr_warning("Failed to find symbol at 0x%lx\n", 623 (unsigned long)paddr); 624 return -ENOENT; 625 } 626 eaddr = sym.st_value; 627 } 628 tp->offset = (unsigned long)(paddr - eaddr); 629 tp->address = (unsigned long)paddr; 630 tp->symbol = strdup(symbol); 631 if (!tp->symbol) 632 return -ENOMEM; 633 634 /* Return probe must be on the head of a subprogram */ 635 if (retprobe) { 636 if (eaddr != paddr) { 637 pr_warning("Return probe must be on the head of" 638 " a real function.\n"); 639 return -EINVAL; 640 } 641 tp->retprobe = true; 642 } 643 644 return 0; 645 } 646 647 /* Call probe_finder callback with scope DIE */ 648 static int call_probe_finder(Dwarf_Die *sc_die, struct probe_finder *pf) 649 { 650 Dwarf_Attribute fb_attr; 651 size_t nops; 652 int ret; 653 654 if (!sc_die) { 655 pr_err("Caller must pass a scope DIE. Program error.\n"); 656 return -EINVAL; 657 } 658 659 /* If not a real subprogram, find a real one */ 660 if (!die_is_func_def(sc_die)) { 661 if (!die_find_realfunc(&pf->cu_die, pf->addr, &pf->sp_die)) { 662 if (die_find_tailfunc(&pf->cu_die, pf->addr, &pf->sp_die)) { 663 pr_warning("Ignoring tail call from %s\n", 664 dwarf_diename(&pf->sp_die)); 665 return 0; 666 } else { 667 pr_warning("Failed to find probe point in any " 668 "functions.\n"); 669 return -ENOENT; 670 } 671 } 672 } else 673 memcpy(&pf->sp_die, sc_die, sizeof(Dwarf_Die)); 674 675 /* Get the frame base attribute/ops from subprogram */ 676 dwarf_attr(&pf->sp_die, DW_AT_frame_base, &fb_attr); 677 ret = dwarf_getlocation_addr(&fb_attr, pf->addr, &pf->fb_ops, &nops, 1); 678 if (ret <= 0 || nops == 0) { 679 pf->fb_ops = NULL; 680 #if _ELFUTILS_PREREQ(0, 142) 681 } else if (nops == 1 && pf->fb_ops[0].atom == DW_OP_call_frame_cfa && 682 pf->cfi != NULL) { 683 Dwarf_Frame *frame; 684 if (dwarf_cfi_addrframe(pf->cfi, pf->addr, &frame) != 0 || 685 dwarf_frame_cfa(frame, &pf->fb_ops, &nops) != 0) { 686 pr_warning("Failed to get call frame on 0x%jx\n", 687 (uintmax_t)pf->addr); 688 return -ENOENT; 689 } 690 #endif 691 } 692 693 /* Call finder's callback handler */ 694 ret = pf->callback(sc_die, pf); 695 696 /* *pf->fb_ops will be cached in libdw. Don't free it. */ 697 pf->fb_ops = NULL; 698 699 return ret; 700 } 701 702 struct find_scope_param { 703 const char *function; 704 const char *file; 705 int line; 706 int diff; 707 Dwarf_Die *die_mem; 708 bool found; 709 }; 710 711 static int find_best_scope_cb(Dwarf_Die *fn_die, void *data) 712 { 713 struct find_scope_param *fsp = data; 714 const char *file; 715 int lno; 716 717 /* Skip if declared file name does not match */ 718 if (fsp->file) { 719 file = dwarf_decl_file(fn_die); 720 if (!file || strcmp(fsp->file, file) != 0) 721 return 0; 722 } 723 /* If the function name is given, that's what user expects */ 724 if (fsp->function) { 725 if (die_match_name(fn_die, fsp->function)) { 726 memcpy(fsp->die_mem, fn_die, sizeof(Dwarf_Die)); 727 fsp->found = true; 728 return 1; 729 } 730 } else { 731 /* With the line number, find the nearest declared DIE */ 732 dwarf_decl_line(fn_die, &lno); 733 if (lno < fsp->line && fsp->diff > fsp->line - lno) { 734 /* Keep a candidate and continue */ 735 fsp->diff = fsp->line - lno; 736 memcpy(fsp->die_mem, fn_die, sizeof(Dwarf_Die)); 737 fsp->found = true; 738 } 739 } 740 return 0; 741 } 742 743 /* Find an appropriate scope fits to given conditions */ 744 static Dwarf_Die *find_best_scope(struct probe_finder *pf, Dwarf_Die *die_mem) 745 { 746 struct find_scope_param fsp = { 747 .function = pf->pev->point.function, 748 .file = pf->fname, 749 .line = pf->lno, 750 .diff = INT_MAX, 751 .die_mem = die_mem, 752 .found = false, 753 }; 754 755 cu_walk_functions_at(&pf->cu_die, pf->addr, find_best_scope_cb, &fsp); 756 757 return fsp.found ? die_mem : NULL; 758 } 759 760 static int probe_point_line_walker(const char *fname, int lineno, 761 Dwarf_Addr addr, void *data) 762 { 763 struct probe_finder *pf = data; 764 Dwarf_Die *sc_die, die_mem; 765 int ret; 766 767 if (lineno != pf->lno || strtailcmp(fname, pf->fname) != 0) 768 return 0; 769 770 pf->addr = addr; 771 sc_die = find_best_scope(pf, &die_mem); 772 if (!sc_die) { 773 pr_warning("Failed to find scope of probe point.\n"); 774 return -ENOENT; 775 } 776 777 ret = call_probe_finder(sc_die, pf); 778 779 /* Continue if no error, because the line will be in inline function */ 780 return ret < 0 ? ret : 0; 781 } 782 783 /* Find probe point from its line number */ 784 static int find_probe_point_by_line(struct probe_finder *pf) 785 { 786 return die_walk_lines(&pf->cu_die, probe_point_line_walker, pf); 787 } 788 789 /* Find lines which match lazy pattern */ 790 static int find_lazy_match_lines(struct intlist *list, 791 const char *fname, const char *pat) 792 { 793 FILE *fp; 794 char *line = NULL; 795 size_t line_len; 796 ssize_t len; 797 int count = 0, linenum = 1; 798 char sbuf[STRERR_BUFSIZE]; 799 800 fp = fopen(fname, "r"); 801 if (!fp) { 802 pr_warning("Failed to open %s: %s\n", fname, 803 strerror_r(errno, sbuf, sizeof(sbuf))); 804 return -errno; 805 } 806 807 while ((len = getline(&line, &line_len, fp)) > 0) { 808 809 if (line[len - 1] == '\n') 810 line[len - 1] = '\0'; 811 812 if (strlazymatch(line, pat)) { 813 intlist__add(list, linenum); 814 count++; 815 } 816 linenum++; 817 } 818 819 if (ferror(fp)) 820 count = -errno; 821 free(line); 822 fclose(fp); 823 824 if (count == 0) 825 pr_debug("No matched lines found in %s.\n", fname); 826 return count; 827 } 828 829 static int probe_point_lazy_walker(const char *fname, int lineno, 830 Dwarf_Addr addr, void *data) 831 { 832 struct probe_finder *pf = data; 833 Dwarf_Die *sc_die, die_mem; 834 int ret; 835 836 if (!intlist__has_entry(pf->lcache, lineno) || 837 strtailcmp(fname, pf->fname) != 0) 838 return 0; 839 840 pr_debug("Probe line found: line:%d addr:0x%llx\n", 841 lineno, (unsigned long long)addr); 842 pf->addr = addr; 843 pf->lno = lineno; 844 sc_die = find_best_scope(pf, &die_mem); 845 if (!sc_die) { 846 pr_warning("Failed to find scope of probe point.\n"); 847 return -ENOENT; 848 } 849 850 ret = call_probe_finder(sc_die, pf); 851 852 /* 853 * Continue if no error, because the lazy pattern will match 854 * to other lines 855 */ 856 return ret < 0 ? ret : 0; 857 } 858 859 /* Find probe points from lazy pattern */ 860 static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf) 861 { 862 int ret = 0; 863 char *fpath; 864 865 if (intlist__empty(pf->lcache)) { 866 const char *comp_dir; 867 868 comp_dir = cu_get_comp_dir(&pf->cu_die); 869 ret = get_real_path(pf->fname, comp_dir, &fpath); 870 if (ret < 0) { 871 pr_warning("Failed to find source file path.\n"); 872 return ret; 873 } 874 875 /* Matching lazy line pattern */ 876 ret = find_lazy_match_lines(pf->lcache, fpath, 877 pf->pev->point.lazy_line); 878 free(fpath); 879 if (ret <= 0) 880 return ret; 881 } 882 883 return die_walk_lines(sp_die, probe_point_lazy_walker, pf); 884 } 885 886 static int probe_point_inline_cb(Dwarf_Die *in_die, void *data) 887 { 888 struct probe_finder *pf = data; 889 struct perf_probe_point *pp = &pf->pev->point; 890 Dwarf_Addr addr; 891 int ret; 892 893 if (pp->lazy_line) 894 ret = find_probe_point_lazy(in_die, pf); 895 else { 896 /* Get probe address */ 897 if (dwarf_entrypc(in_die, &addr) != 0) { 898 pr_warning("Failed to get entry address of %s.\n", 899 dwarf_diename(in_die)); 900 return -ENOENT; 901 } 902 pf->addr = addr; 903 pf->addr += pp->offset; 904 pr_debug("found inline addr: 0x%jx\n", 905 (uintmax_t)pf->addr); 906 907 ret = call_probe_finder(in_die, pf); 908 } 909 910 return ret; 911 } 912 913 /* Callback parameter with return value for libdw */ 914 struct dwarf_callback_param { 915 void *data; 916 int retval; 917 }; 918 919 /* Search function from function name */ 920 static int probe_point_search_cb(Dwarf_Die *sp_die, void *data) 921 { 922 struct dwarf_callback_param *param = data; 923 struct probe_finder *pf = param->data; 924 struct perf_probe_point *pp = &pf->pev->point; 925 926 /* Check tag and diename */ 927 if (!die_is_func_def(sp_die) || 928 !die_match_name(sp_die, pp->function)) 929 return DWARF_CB_OK; 930 931 /* Check declared file */ 932 if (pp->file && strtailcmp(pp->file, dwarf_decl_file(sp_die))) 933 return DWARF_CB_OK; 934 935 pr_debug("Matched function: %s\n", dwarf_diename(sp_die)); 936 pf->fname = dwarf_decl_file(sp_die); 937 if (pp->line) { /* Function relative line */ 938 dwarf_decl_line(sp_die, &pf->lno); 939 pf->lno += pp->line; 940 param->retval = find_probe_point_by_line(pf); 941 } else if (die_is_func_instance(sp_die)) { 942 /* Instances always have the entry address */ 943 dwarf_entrypc(sp_die, &pf->addr); 944 /* Real function */ 945 if (pp->lazy_line) 946 param->retval = find_probe_point_lazy(sp_die, pf); 947 else { 948 pf->addr += pp->offset; 949 /* TODO: Check the address in this function */ 950 param->retval = call_probe_finder(sp_die, pf); 951 } 952 } else if (!probe_conf.no_inlines) { 953 /* Inlined function: search instances */ 954 param->retval = die_walk_instances(sp_die, 955 probe_point_inline_cb, (void *)pf); 956 /* This could be a non-existed inline definition */ 957 if (param->retval == -ENOENT && strisglob(pp->function)) 958 param->retval = 0; 959 } 960 961 /* We need to find other candidates */ 962 if (strisglob(pp->function) && param->retval >= 0) { 963 param->retval = 0; /* We have to clear the result */ 964 return DWARF_CB_OK; 965 } 966 967 return DWARF_CB_ABORT; /* Exit; no same symbol in this CU. */ 968 } 969 970 static int find_probe_point_by_func(struct probe_finder *pf) 971 { 972 struct dwarf_callback_param _param = {.data = (void *)pf, 973 .retval = 0}; 974 dwarf_getfuncs(&pf->cu_die, probe_point_search_cb, &_param, 0); 975 return _param.retval; 976 } 977 978 struct pubname_callback_param { 979 char *function; 980 char *file; 981 Dwarf_Die *cu_die; 982 Dwarf_Die *sp_die; 983 int found; 984 }; 985 986 static int pubname_search_cb(Dwarf *dbg, Dwarf_Global *gl, void *data) 987 { 988 struct pubname_callback_param *param = data; 989 990 if (dwarf_offdie(dbg, gl->die_offset, param->sp_die)) { 991 if (dwarf_tag(param->sp_die) != DW_TAG_subprogram) 992 return DWARF_CB_OK; 993 994 if (die_match_name(param->sp_die, param->function)) { 995 if (!dwarf_offdie(dbg, gl->cu_offset, param->cu_die)) 996 return DWARF_CB_OK; 997 998 if (param->file && 999 strtailcmp(param->file, dwarf_decl_file(param->sp_die))) 1000 return DWARF_CB_OK; 1001 1002 param->found = 1; 1003 return DWARF_CB_ABORT; 1004 } 1005 } 1006 1007 return DWARF_CB_OK; 1008 } 1009 1010 /* Find probe points from debuginfo */ 1011 static int debuginfo__find_probes(struct debuginfo *dbg, 1012 struct probe_finder *pf) 1013 { 1014 struct perf_probe_point *pp = &pf->pev->point; 1015 Dwarf_Off off, noff; 1016 size_t cuhl; 1017 Dwarf_Die *diep; 1018 int ret = 0; 1019 1020 #if _ELFUTILS_PREREQ(0, 142) 1021 Elf *elf; 1022 GElf_Ehdr ehdr; 1023 GElf_Shdr shdr; 1024 1025 /* Get the call frame information from this dwarf */ 1026 elf = dwarf_getelf(dbg->dbg); 1027 if (elf == NULL) 1028 return -EINVAL; 1029 1030 if (gelf_getehdr(elf, &ehdr) == NULL) 1031 return -EINVAL; 1032 1033 if (elf_section_by_name(elf, &ehdr, &shdr, ".eh_frame", NULL) && 1034 shdr.sh_type == SHT_PROGBITS) { 1035 pf->cfi = dwarf_getcfi_elf(elf); 1036 } else { 1037 pf->cfi = dwarf_getcfi(dbg->dbg); 1038 } 1039 #endif 1040 1041 off = 0; 1042 pf->lcache = intlist__new(NULL); 1043 if (!pf->lcache) 1044 return -ENOMEM; 1045 1046 /* Fastpath: lookup by function name from .debug_pubnames section */ 1047 if (pp->function && !strisglob(pp->function)) { 1048 struct pubname_callback_param pubname_param = { 1049 .function = pp->function, 1050 .file = pp->file, 1051 .cu_die = &pf->cu_die, 1052 .sp_die = &pf->sp_die, 1053 .found = 0, 1054 }; 1055 struct dwarf_callback_param probe_param = { 1056 .data = pf, 1057 }; 1058 1059 dwarf_getpubnames(dbg->dbg, pubname_search_cb, 1060 &pubname_param, 0); 1061 if (pubname_param.found) { 1062 ret = probe_point_search_cb(&pf->sp_die, &probe_param); 1063 if (ret) 1064 goto found; 1065 } 1066 } 1067 1068 /* Loop on CUs (Compilation Unit) */ 1069 while (!dwarf_nextcu(dbg->dbg, off, &noff, &cuhl, NULL, NULL, NULL)) { 1070 /* Get the DIE(Debugging Information Entry) of this CU */ 1071 diep = dwarf_offdie(dbg->dbg, off + cuhl, &pf->cu_die); 1072 if (!diep) 1073 continue; 1074 1075 /* Check if target file is included. */ 1076 if (pp->file) 1077 pf->fname = cu_find_realpath(&pf->cu_die, pp->file); 1078 else 1079 pf->fname = NULL; 1080 1081 if (!pp->file || pf->fname) { 1082 if (pp->function) 1083 ret = find_probe_point_by_func(pf); 1084 else if (pp->lazy_line) 1085 ret = find_probe_point_lazy(&pf->cu_die, pf); 1086 else { 1087 pf->lno = pp->line; 1088 ret = find_probe_point_by_line(pf); 1089 } 1090 if (ret < 0) 1091 break; 1092 } 1093 off = noff; 1094 } 1095 1096 found: 1097 intlist__delete(pf->lcache); 1098 pf->lcache = NULL; 1099 1100 return ret; 1101 } 1102 1103 struct local_vars_finder { 1104 struct probe_finder *pf; 1105 struct perf_probe_arg *args; 1106 bool vars; 1107 int max_args; 1108 int nargs; 1109 int ret; 1110 }; 1111 1112 /* Collect available variables in this scope */ 1113 static int copy_variables_cb(Dwarf_Die *die_mem, void *data) 1114 { 1115 struct local_vars_finder *vf = data; 1116 struct probe_finder *pf = vf->pf; 1117 int tag; 1118 1119 tag = dwarf_tag(die_mem); 1120 if (tag == DW_TAG_formal_parameter || 1121 (tag == DW_TAG_variable && vf->vars)) { 1122 if (convert_variable_location(die_mem, vf->pf->addr, 1123 vf->pf->fb_ops, &pf->sp_die, 1124 NULL) == 0) { 1125 vf->args[vf->nargs].var = (char *)dwarf_diename(die_mem); 1126 if (vf->args[vf->nargs].var == NULL) { 1127 vf->ret = -ENOMEM; 1128 return DIE_FIND_CB_END; 1129 } 1130 pr_debug(" %s", vf->args[vf->nargs].var); 1131 vf->nargs++; 1132 } 1133 } 1134 1135 if (dwarf_haspc(die_mem, vf->pf->addr)) 1136 return DIE_FIND_CB_CONTINUE; 1137 else 1138 return DIE_FIND_CB_SIBLING; 1139 } 1140 1141 static int expand_probe_args(Dwarf_Die *sc_die, struct probe_finder *pf, 1142 struct perf_probe_arg *args) 1143 { 1144 Dwarf_Die die_mem; 1145 int i; 1146 int n = 0; 1147 struct local_vars_finder vf = {.pf = pf, .args = args, .vars = false, 1148 .max_args = MAX_PROBE_ARGS, .ret = 0}; 1149 1150 for (i = 0; i < pf->pev->nargs; i++) { 1151 /* var never be NULL */ 1152 if (strcmp(pf->pev->args[i].var, PROBE_ARG_VARS) == 0) 1153 vf.vars = true; 1154 else if (strcmp(pf->pev->args[i].var, PROBE_ARG_PARAMS) != 0) { 1155 /* Copy normal argument */ 1156 args[n] = pf->pev->args[i]; 1157 n++; 1158 continue; 1159 } 1160 pr_debug("Expanding %s into:", pf->pev->args[i].var); 1161 vf.nargs = n; 1162 /* Special local variables */ 1163 die_find_child(sc_die, copy_variables_cb, (void *)&vf, 1164 &die_mem); 1165 pr_debug(" (%d)\n", vf.nargs - n); 1166 if (vf.ret < 0) 1167 return vf.ret; 1168 n = vf.nargs; 1169 } 1170 return n; 1171 } 1172 1173 /* Add a found probe point into trace event list */ 1174 static int add_probe_trace_event(Dwarf_Die *sc_die, struct probe_finder *pf) 1175 { 1176 struct trace_event_finder *tf = 1177 container_of(pf, struct trace_event_finder, pf); 1178 struct probe_trace_event *tev; 1179 struct perf_probe_arg *args; 1180 int ret, i; 1181 1182 /* Check number of tevs */ 1183 if (tf->ntevs == tf->max_tevs) { 1184 pr_warning("Too many( > %d) probe point found.\n", 1185 tf->max_tevs); 1186 return -ERANGE; 1187 } 1188 tev = &tf->tevs[tf->ntevs++]; 1189 1190 /* Trace point should be converted from subprogram DIE */ 1191 ret = convert_to_trace_point(&pf->sp_die, tf->mod, pf->addr, 1192 pf->pev->point.retprobe, &tev->point); 1193 if (ret < 0) 1194 return ret; 1195 1196 tev->point.realname = strdup(dwarf_diename(sc_die)); 1197 if (!tev->point.realname) 1198 return -ENOMEM; 1199 1200 pr_debug("Probe point found: %s+%lu\n", tev->point.symbol, 1201 tev->point.offset); 1202 1203 /* Expand special probe argument if exist */ 1204 args = zalloc(sizeof(struct perf_probe_arg) * MAX_PROBE_ARGS); 1205 if (args == NULL) 1206 return -ENOMEM; 1207 1208 ret = expand_probe_args(sc_die, pf, args); 1209 if (ret < 0) 1210 goto end; 1211 1212 tev->nargs = ret; 1213 tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs); 1214 if (tev->args == NULL) { 1215 ret = -ENOMEM; 1216 goto end; 1217 } 1218 1219 /* Find each argument */ 1220 for (i = 0; i < tev->nargs; i++) { 1221 pf->pvar = &args[i]; 1222 pf->tvar = &tev->args[i]; 1223 /* Variable should be found from scope DIE */ 1224 ret = find_variable(sc_die, pf); 1225 if (ret != 0) 1226 break; 1227 } 1228 1229 end: 1230 free(args); 1231 return ret; 1232 } 1233 1234 /* Find probe_trace_events specified by perf_probe_event from debuginfo */ 1235 int debuginfo__find_trace_events(struct debuginfo *dbg, 1236 struct perf_probe_event *pev, 1237 struct probe_trace_event **tevs) 1238 { 1239 struct trace_event_finder tf = { 1240 .pf = {.pev = pev, .callback = add_probe_trace_event}, 1241 .max_tevs = probe_conf.max_probes, .mod = dbg->mod}; 1242 int ret; 1243 1244 /* Allocate result tevs array */ 1245 *tevs = zalloc(sizeof(struct probe_trace_event) * tf.max_tevs); 1246 if (*tevs == NULL) 1247 return -ENOMEM; 1248 1249 tf.tevs = *tevs; 1250 tf.ntevs = 0; 1251 1252 ret = debuginfo__find_probes(dbg, &tf.pf); 1253 if (ret < 0) { 1254 zfree(tevs); 1255 return ret; 1256 } 1257 1258 return (ret < 0) ? ret : tf.ntevs; 1259 } 1260 1261 /* Collect available variables in this scope */ 1262 static int collect_variables_cb(Dwarf_Die *die_mem, void *data) 1263 { 1264 struct available_var_finder *af = data; 1265 struct variable_list *vl; 1266 int tag, ret; 1267 1268 vl = &af->vls[af->nvls - 1]; 1269 1270 tag = dwarf_tag(die_mem); 1271 if (tag == DW_TAG_formal_parameter || 1272 tag == DW_TAG_variable) { 1273 ret = convert_variable_location(die_mem, af->pf.addr, 1274 af->pf.fb_ops, &af->pf.sp_die, 1275 NULL); 1276 if (ret == 0 || ret == -ERANGE) { 1277 int ret2; 1278 bool externs = !af->child; 1279 struct strbuf buf; 1280 1281 strbuf_init(&buf, 64); 1282 1283 if (probe_conf.show_location_range) { 1284 if (!externs) { 1285 if (ret) 1286 strbuf_addf(&buf, "[INV]\t"); 1287 else 1288 strbuf_addf(&buf, "[VAL]\t"); 1289 } else 1290 strbuf_addf(&buf, "[EXT]\t"); 1291 } 1292 1293 ret2 = die_get_varname(die_mem, &buf); 1294 1295 if (!ret2 && probe_conf.show_location_range && 1296 !externs) { 1297 strbuf_addf(&buf, "\t"); 1298 ret2 = die_get_var_range(&af->pf.sp_die, 1299 die_mem, &buf); 1300 } 1301 1302 pr_debug("Add new var: %s\n", buf.buf); 1303 if (ret2 == 0) { 1304 strlist__add(vl->vars, 1305 strbuf_detach(&buf, NULL)); 1306 } 1307 strbuf_release(&buf); 1308 } 1309 } 1310 1311 if (af->child && dwarf_haspc(die_mem, af->pf.addr)) 1312 return DIE_FIND_CB_CONTINUE; 1313 else 1314 return DIE_FIND_CB_SIBLING; 1315 } 1316 1317 /* Add a found vars into available variables list */ 1318 static int add_available_vars(Dwarf_Die *sc_die, struct probe_finder *pf) 1319 { 1320 struct available_var_finder *af = 1321 container_of(pf, struct available_var_finder, pf); 1322 struct variable_list *vl; 1323 Dwarf_Die die_mem; 1324 int ret; 1325 1326 /* Check number of tevs */ 1327 if (af->nvls == af->max_vls) { 1328 pr_warning("Too many( > %d) probe point found.\n", af->max_vls); 1329 return -ERANGE; 1330 } 1331 vl = &af->vls[af->nvls++]; 1332 1333 /* Trace point should be converted from subprogram DIE */ 1334 ret = convert_to_trace_point(&pf->sp_die, af->mod, pf->addr, 1335 pf->pev->point.retprobe, &vl->point); 1336 if (ret < 0) 1337 return ret; 1338 1339 pr_debug("Probe point found: %s+%lu\n", vl->point.symbol, 1340 vl->point.offset); 1341 1342 /* Find local variables */ 1343 vl->vars = strlist__new(NULL, NULL); 1344 if (vl->vars == NULL) 1345 return -ENOMEM; 1346 af->child = true; 1347 die_find_child(sc_die, collect_variables_cb, (void *)af, &die_mem); 1348 1349 /* Find external variables */ 1350 if (!probe_conf.show_ext_vars) 1351 goto out; 1352 /* Don't need to search child DIE for external vars. */ 1353 af->child = false; 1354 die_find_child(&pf->cu_die, collect_variables_cb, (void *)af, &die_mem); 1355 1356 out: 1357 if (strlist__empty(vl->vars)) { 1358 strlist__delete(vl->vars); 1359 vl->vars = NULL; 1360 } 1361 1362 return ret; 1363 } 1364 1365 /* 1366 * Find available variables at given probe point 1367 * Return the number of found probe points. Return 0 if there is no 1368 * matched probe point. Return <0 if an error occurs. 1369 */ 1370 int debuginfo__find_available_vars_at(struct debuginfo *dbg, 1371 struct perf_probe_event *pev, 1372 struct variable_list **vls) 1373 { 1374 struct available_var_finder af = { 1375 .pf = {.pev = pev, .callback = add_available_vars}, 1376 .mod = dbg->mod, 1377 .max_vls = probe_conf.max_probes}; 1378 int ret; 1379 1380 /* Allocate result vls array */ 1381 *vls = zalloc(sizeof(struct variable_list) * af.max_vls); 1382 if (*vls == NULL) 1383 return -ENOMEM; 1384 1385 af.vls = *vls; 1386 af.nvls = 0; 1387 1388 ret = debuginfo__find_probes(dbg, &af.pf); 1389 if (ret < 0) { 1390 /* Free vlist for error */ 1391 while (af.nvls--) { 1392 zfree(&af.vls[af.nvls].point.symbol); 1393 strlist__delete(af.vls[af.nvls].vars); 1394 } 1395 zfree(vls); 1396 return ret; 1397 } 1398 1399 return (ret < 0) ? ret : af.nvls; 1400 } 1401 1402 /* Reverse search */ 1403 int debuginfo__find_probe_point(struct debuginfo *dbg, unsigned long addr, 1404 struct perf_probe_point *ppt) 1405 { 1406 Dwarf_Die cudie, spdie, indie; 1407 Dwarf_Addr _addr = 0, baseaddr = 0; 1408 const char *fname = NULL, *func = NULL, *basefunc = NULL, *tmp; 1409 int baseline = 0, lineno = 0, ret = 0; 1410 1411 /* Find cu die */ 1412 if (!dwarf_addrdie(dbg->dbg, (Dwarf_Addr)addr, &cudie)) { 1413 pr_warning("Failed to find debug information for address %lx\n", 1414 addr); 1415 ret = -EINVAL; 1416 goto end; 1417 } 1418 1419 /* Find a corresponding line (filename and lineno) */ 1420 cu_find_lineinfo(&cudie, addr, &fname, &lineno); 1421 /* Don't care whether it failed or not */ 1422 1423 /* Find a corresponding function (name, baseline and baseaddr) */ 1424 if (die_find_realfunc(&cudie, (Dwarf_Addr)addr, &spdie)) { 1425 /* Get function entry information */ 1426 func = basefunc = dwarf_diename(&spdie); 1427 if (!func || 1428 dwarf_entrypc(&spdie, &baseaddr) != 0 || 1429 dwarf_decl_line(&spdie, &baseline) != 0) { 1430 lineno = 0; 1431 goto post; 1432 } 1433 1434 fname = dwarf_decl_file(&spdie); 1435 if (addr == (unsigned long)baseaddr) { 1436 /* Function entry - Relative line number is 0 */ 1437 lineno = baseline; 1438 goto post; 1439 } 1440 1441 /* Track down the inline functions step by step */ 1442 while (die_find_top_inlinefunc(&spdie, (Dwarf_Addr)addr, 1443 &indie)) { 1444 /* There is an inline function */ 1445 if (dwarf_entrypc(&indie, &_addr) == 0 && 1446 _addr == addr) { 1447 /* 1448 * addr is at an inline function entry. 1449 * In this case, lineno should be the call-site 1450 * line number. (overwrite lineinfo) 1451 */ 1452 lineno = die_get_call_lineno(&indie); 1453 fname = die_get_call_file(&indie); 1454 break; 1455 } else { 1456 /* 1457 * addr is in an inline function body. 1458 * Since lineno points one of the lines 1459 * of the inline function, baseline should 1460 * be the entry line of the inline function. 1461 */ 1462 tmp = dwarf_diename(&indie); 1463 if (!tmp || 1464 dwarf_decl_line(&indie, &baseline) != 0) 1465 break; 1466 func = tmp; 1467 spdie = indie; 1468 } 1469 } 1470 /* Verify the lineno and baseline are in a same file */ 1471 tmp = dwarf_decl_file(&spdie); 1472 if (!tmp || strcmp(tmp, fname) != 0) 1473 lineno = 0; 1474 } 1475 1476 post: 1477 /* Make a relative line number or an offset */ 1478 if (lineno) 1479 ppt->line = lineno - baseline; 1480 else if (basefunc) { 1481 ppt->offset = addr - (unsigned long)baseaddr; 1482 func = basefunc; 1483 } 1484 1485 /* Duplicate strings */ 1486 if (func) { 1487 ppt->function = strdup(func); 1488 if (ppt->function == NULL) { 1489 ret = -ENOMEM; 1490 goto end; 1491 } 1492 } 1493 if (fname) { 1494 ppt->file = strdup(fname); 1495 if (ppt->file == NULL) { 1496 zfree(&ppt->function); 1497 ret = -ENOMEM; 1498 goto end; 1499 } 1500 } 1501 end: 1502 if (ret == 0 && (fname || func)) 1503 ret = 1; /* Found a point */ 1504 return ret; 1505 } 1506 1507 /* Add a line and store the src path */ 1508 static int line_range_add_line(const char *src, unsigned int lineno, 1509 struct line_range *lr) 1510 { 1511 /* Copy source path */ 1512 if (!lr->path) { 1513 lr->path = strdup(src); 1514 if (lr->path == NULL) 1515 return -ENOMEM; 1516 } 1517 return intlist__add(lr->line_list, lineno); 1518 } 1519 1520 static int line_range_walk_cb(const char *fname, int lineno, 1521 Dwarf_Addr addr __maybe_unused, 1522 void *data) 1523 { 1524 struct line_finder *lf = data; 1525 int err; 1526 1527 if ((strtailcmp(fname, lf->fname) != 0) || 1528 (lf->lno_s > lineno || lf->lno_e < lineno)) 1529 return 0; 1530 1531 err = line_range_add_line(fname, lineno, lf->lr); 1532 if (err < 0 && err != -EEXIST) 1533 return err; 1534 1535 return 0; 1536 } 1537 1538 /* Find line range from its line number */ 1539 static int find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf) 1540 { 1541 int ret; 1542 1543 ret = die_walk_lines(sp_die ?: &lf->cu_die, line_range_walk_cb, lf); 1544 1545 /* Update status */ 1546 if (ret >= 0) 1547 if (!intlist__empty(lf->lr->line_list)) 1548 ret = lf->found = 1; 1549 else 1550 ret = 0; /* Lines are not found */ 1551 else { 1552 zfree(&lf->lr->path); 1553 } 1554 return ret; 1555 } 1556 1557 static int line_range_inline_cb(Dwarf_Die *in_die, void *data) 1558 { 1559 int ret = find_line_range_by_line(in_die, data); 1560 1561 /* 1562 * We have to check all instances of inlined function, because 1563 * some execution paths can be optimized out depends on the 1564 * function argument of instances. However, if an error occurs, 1565 * it should be handled by the caller. 1566 */ 1567 return ret < 0 ? ret : 0; 1568 } 1569 1570 /* Search function definition from function name */ 1571 static int line_range_search_cb(Dwarf_Die *sp_die, void *data) 1572 { 1573 struct dwarf_callback_param *param = data; 1574 struct line_finder *lf = param->data; 1575 struct line_range *lr = lf->lr; 1576 1577 /* Check declared file */ 1578 if (lr->file && strtailcmp(lr->file, dwarf_decl_file(sp_die))) 1579 return DWARF_CB_OK; 1580 1581 if (die_is_func_def(sp_die) && 1582 die_match_name(sp_die, lr->function)) { 1583 lf->fname = dwarf_decl_file(sp_die); 1584 dwarf_decl_line(sp_die, &lr->offset); 1585 pr_debug("fname: %s, lineno:%d\n", lf->fname, lr->offset); 1586 lf->lno_s = lr->offset + lr->start; 1587 if (lf->lno_s < 0) /* Overflow */ 1588 lf->lno_s = INT_MAX; 1589 lf->lno_e = lr->offset + lr->end; 1590 if (lf->lno_e < 0) /* Overflow */ 1591 lf->lno_e = INT_MAX; 1592 pr_debug("New line range: %d to %d\n", lf->lno_s, lf->lno_e); 1593 lr->start = lf->lno_s; 1594 lr->end = lf->lno_e; 1595 if (!die_is_func_instance(sp_die)) 1596 param->retval = die_walk_instances(sp_die, 1597 line_range_inline_cb, lf); 1598 else 1599 param->retval = find_line_range_by_line(sp_die, lf); 1600 return DWARF_CB_ABORT; 1601 } 1602 return DWARF_CB_OK; 1603 } 1604 1605 static int find_line_range_by_func(struct line_finder *lf) 1606 { 1607 struct dwarf_callback_param param = {.data = (void *)lf, .retval = 0}; 1608 dwarf_getfuncs(&lf->cu_die, line_range_search_cb, ¶m, 0); 1609 return param.retval; 1610 } 1611 1612 int debuginfo__find_line_range(struct debuginfo *dbg, struct line_range *lr) 1613 { 1614 struct line_finder lf = {.lr = lr, .found = 0}; 1615 int ret = 0; 1616 Dwarf_Off off = 0, noff; 1617 size_t cuhl; 1618 Dwarf_Die *diep; 1619 const char *comp_dir; 1620 1621 /* Fastpath: lookup by function name from .debug_pubnames section */ 1622 if (lr->function) { 1623 struct pubname_callback_param pubname_param = { 1624 .function = lr->function, .file = lr->file, 1625 .cu_die = &lf.cu_die, .sp_die = &lf.sp_die, .found = 0}; 1626 struct dwarf_callback_param line_range_param = { 1627 .data = (void *)&lf, .retval = 0}; 1628 1629 dwarf_getpubnames(dbg->dbg, pubname_search_cb, 1630 &pubname_param, 0); 1631 if (pubname_param.found) { 1632 line_range_search_cb(&lf.sp_die, &line_range_param); 1633 if (lf.found) 1634 goto found; 1635 } 1636 } 1637 1638 /* Loop on CUs (Compilation Unit) */ 1639 while (!lf.found && ret >= 0) { 1640 if (dwarf_nextcu(dbg->dbg, off, &noff, &cuhl, 1641 NULL, NULL, NULL) != 0) 1642 break; 1643 1644 /* Get the DIE(Debugging Information Entry) of this CU */ 1645 diep = dwarf_offdie(dbg->dbg, off + cuhl, &lf.cu_die); 1646 if (!diep) 1647 continue; 1648 1649 /* Check if target file is included. */ 1650 if (lr->file) 1651 lf.fname = cu_find_realpath(&lf.cu_die, lr->file); 1652 else 1653 lf.fname = 0; 1654 1655 if (!lr->file || lf.fname) { 1656 if (lr->function) 1657 ret = find_line_range_by_func(&lf); 1658 else { 1659 lf.lno_s = lr->start; 1660 lf.lno_e = lr->end; 1661 ret = find_line_range_by_line(NULL, &lf); 1662 } 1663 } 1664 off = noff; 1665 } 1666 1667 found: 1668 /* Store comp_dir */ 1669 if (lf.found) { 1670 comp_dir = cu_get_comp_dir(&lf.cu_die); 1671 if (comp_dir) { 1672 lr->comp_dir = strdup(comp_dir); 1673 if (!lr->comp_dir) 1674 ret = -ENOMEM; 1675 } 1676 } 1677 1678 pr_debug("path: %s\n", lr->path); 1679 return (ret < 0) ? ret : lf.found; 1680 } 1681 1682 /* 1683 * Find a src file from a DWARF tag path. Prepend optional source path prefix 1684 * and chop off leading directories that do not exist. Result is passed back as 1685 * a newly allocated path on success. 1686 * Return 0 if file was found and readable, -errno otherwise. 1687 */ 1688 int get_real_path(const char *raw_path, const char *comp_dir, 1689 char **new_path) 1690 { 1691 const char *prefix = symbol_conf.source_prefix; 1692 1693 if (!prefix) { 1694 if (raw_path[0] != '/' && comp_dir) 1695 /* If not an absolute path, try to use comp_dir */ 1696 prefix = comp_dir; 1697 else { 1698 if (access(raw_path, R_OK) == 0) { 1699 *new_path = strdup(raw_path); 1700 return *new_path ? 0 : -ENOMEM; 1701 } else 1702 return -errno; 1703 } 1704 } 1705 1706 *new_path = malloc((strlen(prefix) + strlen(raw_path) + 2)); 1707 if (!*new_path) 1708 return -ENOMEM; 1709 1710 for (;;) { 1711 sprintf(*new_path, "%s/%s", prefix, raw_path); 1712 1713 if (access(*new_path, R_OK) == 0) 1714 return 0; 1715 1716 if (!symbol_conf.source_prefix) { 1717 /* In case of searching comp_dir, don't retry */ 1718 zfree(new_path); 1719 return -errno; 1720 } 1721 1722 switch (errno) { 1723 case ENAMETOOLONG: 1724 case ENOENT: 1725 case EROFS: 1726 case EFAULT: 1727 raw_path = strchr(++raw_path, '/'); 1728 if (!raw_path) { 1729 zfree(new_path); 1730 return -ENOENT; 1731 } 1732 continue; 1733 1734 default: 1735 zfree(new_path); 1736 return -errno; 1737 } 1738 } 1739 } 1740