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