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