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 <ctype.h> 34 #include <dwarf-regs.h> 35 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 /* 46 * Compare the tail of two strings. 47 * Return 0 if whole of either string is same as another's tail part. 48 */ 49 static int strtailcmp(const char *s1, const char *s2) 50 { 51 int i1 = strlen(s1); 52 int i2 = strlen(s2); 53 while (--i1 >= 0 && --i2 >= 0) { 54 if (s1[i1] != s2[i2]) 55 return s1[i1] - s2[i2]; 56 } 57 return 0; 58 } 59 60 /* Line number list operations */ 61 62 /* Add a line to line number list */ 63 static int line_list__add_line(struct list_head *head, int line) 64 { 65 struct line_node *ln; 66 struct list_head *p; 67 68 /* Reverse search, because new line will be the last one */ 69 list_for_each_entry_reverse(ln, head, list) { 70 if (ln->line < line) { 71 p = &ln->list; 72 goto found; 73 } else if (ln->line == line) /* Already exist */ 74 return 1; 75 } 76 /* List is empty, or the smallest entry */ 77 p = head; 78 found: 79 pr_debug("line list: add a line %u\n", line); 80 ln = zalloc(sizeof(struct line_node)); 81 if (ln == NULL) 82 return -ENOMEM; 83 ln->line = line; 84 INIT_LIST_HEAD(&ln->list); 85 list_add(&ln->list, p); 86 return 0; 87 } 88 89 /* Check if the line in line number list */ 90 static int line_list__has_line(struct list_head *head, int line) 91 { 92 struct line_node *ln; 93 94 /* Reverse search, because new line will be the last one */ 95 list_for_each_entry(ln, head, list) 96 if (ln->line == line) 97 return 1; 98 99 return 0; 100 } 101 102 /* Init line number list */ 103 static void line_list__init(struct list_head *head) 104 { 105 INIT_LIST_HEAD(head); 106 } 107 108 /* Free line number list */ 109 static void line_list__free(struct list_head *head) 110 { 111 struct line_node *ln; 112 while (!list_empty(head)) { 113 ln = list_first_entry(head, struct line_node, list); 114 list_del(&ln->list); 115 free(ln); 116 } 117 } 118 119 /* Dwarf wrappers */ 120 121 /* Find the realpath of the target file. */ 122 static const char *cu_find_realpath(Dwarf_Die *cu_die, const char *fname) 123 { 124 Dwarf_Files *files; 125 size_t nfiles, i; 126 const char *src = NULL; 127 int ret; 128 129 if (!fname) 130 return NULL; 131 132 ret = dwarf_getsrcfiles(cu_die, &files, &nfiles); 133 if (ret != 0) 134 return NULL; 135 136 for (i = 0; i < nfiles; i++) { 137 src = dwarf_filesrc(files, i, NULL, NULL); 138 if (strtailcmp(src, fname) == 0) 139 break; 140 } 141 if (i == nfiles) 142 return NULL; 143 return src; 144 } 145 146 /* Get DW_AT_comp_dir (should be NULL with older gcc) */ 147 static const char *cu_get_comp_dir(Dwarf_Die *cu_die) 148 { 149 Dwarf_Attribute attr; 150 if (dwarf_attr(cu_die, DW_AT_comp_dir, &attr) == NULL) 151 return NULL; 152 return dwarf_formstring(&attr); 153 } 154 155 /* Compare diename and tname */ 156 static bool die_compare_name(Dwarf_Die *dw_die, const char *tname) 157 { 158 const char *name; 159 name = dwarf_diename(dw_die); 160 return name ? (strcmp(tname, name) == 0) : false; 161 } 162 163 /* Get type die, but skip qualifiers and typedef */ 164 static Dwarf_Die *die_get_real_type(Dwarf_Die *vr_die, Dwarf_Die *die_mem) 165 { 166 Dwarf_Attribute attr; 167 int tag; 168 169 do { 170 if (dwarf_attr(vr_die, DW_AT_type, &attr) == NULL || 171 dwarf_formref_die(&attr, die_mem) == NULL) 172 return NULL; 173 174 tag = dwarf_tag(die_mem); 175 vr_die = die_mem; 176 } while (tag == DW_TAG_const_type || 177 tag == DW_TAG_restrict_type || 178 tag == DW_TAG_volatile_type || 179 tag == DW_TAG_shared_type || 180 tag == DW_TAG_typedef); 181 182 return die_mem; 183 } 184 185 static bool die_is_signed_type(Dwarf_Die *tp_die) 186 { 187 Dwarf_Attribute attr; 188 Dwarf_Word ret; 189 190 if (dwarf_attr(tp_die, DW_AT_encoding, &attr) == NULL || 191 dwarf_formudata(&attr, &ret) != 0) 192 return false; 193 194 return (ret == DW_ATE_signed_char || ret == DW_ATE_signed || 195 ret == DW_ATE_signed_fixed); 196 } 197 198 static int die_get_byte_size(Dwarf_Die *tp_die) 199 { 200 Dwarf_Attribute attr; 201 Dwarf_Word ret; 202 203 if (dwarf_attr(tp_die, DW_AT_byte_size, &attr) == NULL || 204 dwarf_formudata(&attr, &ret) != 0) 205 return 0; 206 207 return (int)ret; 208 } 209 210 /* Get data_member_location offset */ 211 static int die_get_data_member_location(Dwarf_Die *mb_die, Dwarf_Word *offs) 212 { 213 Dwarf_Attribute attr; 214 Dwarf_Op *expr; 215 size_t nexpr; 216 int ret; 217 218 if (dwarf_attr(mb_die, DW_AT_data_member_location, &attr) == NULL) 219 return -ENOENT; 220 221 if (dwarf_formudata(&attr, offs) != 0) { 222 /* DW_AT_data_member_location should be DW_OP_plus_uconst */ 223 ret = dwarf_getlocation(&attr, &expr, &nexpr); 224 if (ret < 0 || nexpr == 0) 225 return -ENOENT; 226 227 if (expr[0].atom != DW_OP_plus_uconst || nexpr != 1) { 228 pr_debug("Unable to get offset:Unexpected OP %x (%zd)\n", 229 expr[0].atom, nexpr); 230 return -ENOTSUP; 231 } 232 *offs = (Dwarf_Word)expr[0].number; 233 } 234 return 0; 235 } 236 237 /* Return values for die_find callbacks */ 238 enum { 239 DIE_FIND_CB_FOUND = 0, /* End of Search */ 240 DIE_FIND_CB_CHILD = 1, /* Search only children */ 241 DIE_FIND_CB_SIBLING = 2, /* Search only siblings */ 242 DIE_FIND_CB_CONTINUE = 3, /* Search children and siblings */ 243 }; 244 245 /* Search a child die */ 246 static Dwarf_Die *die_find_child(Dwarf_Die *rt_die, 247 int (*callback)(Dwarf_Die *, void *), 248 void *data, Dwarf_Die *die_mem) 249 { 250 Dwarf_Die child_die; 251 int ret; 252 253 ret = dwarf_child(rt_die, die_mem); 254 if (ret != 0) 255 return NULL; 256 257 do { 258 ret = callback(die_mem, data); 259 if (ret == DIE_FIND_CB_FOUND) 260 return die_mem; 261 262 if ((ret & DIE_FIND_CB_CHILD) && 263 die_find_child(die_mem, callback, data, &child_die)) { 264 memcpy(die_mem, &child_die, sizeof(Dwarf_Die)); 265 return die_mem; 266 } 267 } while ((ret & DIE_FIND_CB_SIBLING) && 268 dwarf_siblingof(die_mem, die_mem) == 0); 269 270 return NULL; 271 } 272 273 struct __addr_die_search_param { 274 Dwarf_Addr addr; 275 Dwarf_Die *die_mem; 276 }; 277 278 static int __die_search_func_cb(Dwarf_Die *fn_die, void *data) 279 { 280 struct __addr_die_search_param *ad = data; 281 282 if (dwarf_tag(fn_die) == DW_TAG_subprogram && 283 dwarf_haspc(fn_die, ad->addr)) { 284 memcpy(ad->die_mem, fn_die, sizeof(Dwarf_Die)); 285 return DWARF_CB_ABORT; 286 } 287 return DWARF_CB_OK; 288 } 289 290 /* Search a real subprogram including this line, */ 291 static Dwarf_Die *die_find_real_subprogram(Dwarf_Die *cu_die, Dwarf_Addr addr, 292 Dwarf_Die *die_mem) 293 { 294 struct __addr_die_search_param ad; 295 ad.addr = addr; 296 ad.die_mem = die_mem; 297 /* dwarf_getscopes can't find subprogram. */ 298 if (!dwarf_getfuncs(cu_die, __die_search_func_cb, &ad, 0)) 299 return NULL; 300 else 301 return die_mem; 302 } 303 304 /* die_find callback for inline function search */ 305 static int __die_find_inline_cb(Dwarf_Die *die_mem, void *data) 306 { 307 Dwarf_Addr *addr = data; 308 309 if (dwarf_tag(die_mem) == DW_TAG_inlined_subroutine && 310 dwarf_haspc(die_mem, *addr)) 311 return DIE_FIND_CB_FOUND; 312 313 return DIE_FIND_CB_CONTINUE; 314 } 315 316 /* Similar to dwarf_getfuncs, but returns inlined_subroutine if exists. */ 317 static Dwarf_Die *die_find_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr, 318 Dwarf_Die *die_mem) 319 { 320 return die_find_child(sp_die, __die_find_inline_cb, &addr, die_mem); 321 } 322 323 static int __die_find_variable_cb(Dwarf_Die *die_mem, void *data) 324 { 325 const char *name = data; 326 int tag; 327 328 tag = dwarf_tag(die_mem); 329 if ((tag == DW_TAG_formal_parameter || 330 tag == DW_TAG_variable) && 331 die_compare_name(die_mem, name)) 332 return DIE_FIND_CB_FOUND; 333 334 return DIE_FIND_CB_CONTINUE; 335 } 336 337 /* Find a variable called 'name' */ 338 static Dwarf_Die *die_find_variable(Dwarf_Die *sp_die, const char *name, 339 Dwarf_Die *die_mem) 340 { 341 return die_find_child(sp_die, __die_find_variable_cb, (void *)name, 342 die_mem); 343 } 344 345 static int __die_find_member_cb(Dwarf_Die *die_mem, void *data) 346 { 347 const char *name = data; 348 349 if ((dwarf_tag(die_mem) == DW_TAG_member) && 350 die_compare_name(die_mem, name)) 351 return DIE_FIND_CB_FOUND; 352 353 return DIE_FIND_CB_SIBLING; 354 } 355 356 /* Find a member called 'name' */ 357 static Dwarf_Die *die_find_member(Dwarf_Die *st_die, const char *name, 358 Dwarf_Die *die_mem) 359 { 360 return die_find_child(st_die, __die_find_member_cb, (void *)name, 361 die_mem); 362 } 363 364 /* 365 * Probe finder related functions 366 */ 367 368 static struct probe_trace_arg_ref *alloc_trace_arg_ref(long offs) 369 { 370 struct probe_trace_arg_ref *ref; 371 ref = zalloc(sizeof(struct probe_trace_arg_ref)); 372 if (ref != NULL) 373 ref->offset = offs; 374 return ref; 375 } 376 377 /* Show a location */ 378 static int convert_variable_location(Dwarf_Die *vr_die, struct probe_finder *pf) 379 { 380 Dwarf_Attribute attr; 381 Dwarf_Op *op; 382 size_t nops; 383 unsigned int regn; 384 Dwarf_Word offs = 0; 385 bool ref = false; 386 const char *regs; 387 struct probe_trace_arg *tvar = pf->tvar; 388 int ret; 389 390 /* TODO: handle more than 1 exprs */ 391 if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL || 392 dwarf_getlocation_addr(&attr, pf->addr, &op, &nops, 1) <= 0 || 393 nops == 0) { 394 /* TODO: Support const_value */ 395 pr_err("Failed to find the location of %s at this address.\n" 396 " Perhaps, it has been optimized out.\n", pf->pvar->var); 397 return -ENOENT; 398 } 399 400 if (op->atom == DW_OP_addr) { 401 /* Static variables on memory (not stack), make @varname */ 402 ret = strlen(dwarf_diename(vr_die)); 403 tvar->value = zalloc(ret + 2); 404 if (tvar->value == NULL) 405 return -ENOMEM; 406 snprintf(tvar->value, ret + 2, "@%s", dwarf_diename(vr_die)); 407 tvar->ref = alloc_trace_arg_ref((long)offs); 408 if (tvar->ref == NULL) 409 return -ENOMEM; 410 return 0; 411 } 412 413 /* If this is based on frame buffer, set the offset */ 414 if (op->atom == DW_OP_fbreg) { 415 if (pf->fb_ops == NULL) { 416 pr_warning("The attribute of frame base is not " 417 "supported.\n"); 418 return -ENOTSUP; 419 } 420 ref = true; 421 offs = op->number; 422 op = &pf->fb_ops[0]; 423 } 424 425 if (op->atom >= DW_OP_breg0 && op->atom <= DW_OP_breg31) { 426 regn = op->atom - DW_OP_breg0; 427 offs += op->number; 428 ref = true; 429 } else if (op->atom >= DW_OP_reg0 && op->atom <= DW_OP_reg31) { 430 regn = op->atom - DW_OP_reg0; 431 } else if (op->atom == DW_OP_bregx) { 432 regn = op->number; 433 offs += op->number2; 434 ref = true; 435 } else if (op->atom == DW_OP_regx) { 436 regn = op->number; 437 } else { 438 pr_warning("DW_OP %x is not supported.\n", op->atom); 439 return -ENOTSUP; 440 } 441 442 regs = get_arch_regstr(regn); 443 if (!regs) { 444 pr_warning("Mapping for DWARF register number %u missing on this architecture.", regn); 445 return -ERANGE; 446 } 447 448 tvar->value = strdup(regs); 449 if (tvar->value == NULL) 450 return -ENOMEM; 451 452 if (ref) { 453 tvar->ref = alloc_trace_arg_ref((long)offs); 454 if (tvar->ref == NULL) 455 return -ENOMEM; 456 } 457 return 0; 458 } 459 460 static int convert_variable_type(Dwarf_Die *vr_die, 461 struct probe_trace_arg *tvar, 462 const char *cast) 463 { 464 struct probe_trace_arg_ref **ref_ptr = &tvar->ref; 465 Dwarf_Die type; 466 char buf[16]; 467 int ret; 468 469 /* TODO: check all types */ 470 if (cast && strcmp(cast, "string") != 0) { 471 /* Non string type is OK */ 472 tvar->type = strdup(cast); 473 return (tvar->type == NULL) ? -ENOMEM : 0; 474 } 475 476 if (die_get_real_type(vr_die, &type) == NULL) { 477 pr_warning("Failed to get a type information of %s.\n", 478 dwarf_diename(vr_die)); 479 return -ENOENT; 480 } 481 482 pr_debug("%s type is %s.\n", 483 dwarf_diename(vr_die), dwarf_diename(&type)); 484 485 if (cast && strcmp(cast, "string") == 0) { /* String type */ 486 ret = dwarf_tag(&type); 487 if (ret != DW_TAG_pointer_type && 488 ret != DW_TAG_array_type) { 489 pr_warning("Failed to cast into string: " 490 "%s(%s) is not a pointer nor array.", 491 dwarf_diename(vr_die), dwarf_diename(&type)); 492 return -EINVAL; 493 } 494 if (ret == DW_TAG_pointer_type) { 495 if (die_get_real_type(&type, &type) == NULL) { 496 pr_warning("Failed to get a type information."); 497 return -ENOENT; 498 } 499 while (*ref_ptr) 500 ref_ptr = &(*ref_ptr)->next; 501 /* Add new reference with offset +0 */ 502 *ref_ptr = zalloc(sizeof(struct probe_trace_arg_ref)); 503 if (*ref_ptr == NULL) { 504 pr_warning("Out of memory error\n"); 505 return -ENOMEM; 506 } 507 } 508 if (!die_compare_name(&type, "char") && 509 !die_compare_name(&type, "unsigned char")) { 510 pr_warning("Failed to cast into string: " 511 "%s is not (unsigned) char *.", 512 dwarf_diename(vr_die)); 513 return -EINVAL; 514 } 515 tvar->type = strdup(cast); 516 return (tvar->type == NULL) ? -ENOMEM : 0; 517 } 518 519 ret = die_get_byte_size(&type) * 8; 520 if (ret) { 521 /* Check the bitwidth */ 522 if (ret > MAX_BASIC_TYPE_BITS) { 523 pr_info("%s exceeds max-bitwidth." 524 " Cut down to %d bits.\n", 525 dwarf_diename(&type), MAX_BASIC_TYPE_BITS); 526 ret = MAX_BASIC_TYPE_BITS; 527 } 528 529 ret = snprintf(buf, 16, "%c%d", 530 die_is_signed_type(&type) ? 's' : 'u', ret); 531 if (ret < 0 || ret >= 16) { 532 if (ret >= 16) 533 ret = -E2BIG; 534 pr_warning("Failed to convert variable type: %s\n", 535 strerror(-ret)); 536 return ret; 537 } 538 tvar->type = strdup(buf); 539 if (tvar->type == NULL) 540 return -ENOMEM; 541 } 542 return 0; 543 } 544 545 static int convert_variable_fields(Dwarf_Die *vr_die, const char *varname, 546 struct perf_probe_arg_field *field, 547 struct probe_trace_arg_ref **ref_ptr, 548 Dwarf_Die *die_mem) 549 { 550 struct probe_trace_arg_ref *ref = *ref_ptr; 551 Dwarf_Die type; 552 Dwarf_Word offs; 553 int ret, tag; 554 555 pr_debug("converting %s in %s\n", field->name, varname); 556 if (die_get_real_type(vr_die, &type) == NULL) { 557 pr_warning("Failed to get the type of %s.\n", varname); 558 return -ENOENT; 559 } 560 pr_debug2("Var real type: (%x)\n", (unsigned)dwarf_dieoffset(&type)); 561 tag = dwarf_tag(&type); 562 563 if (field->name[0] == '[' && 564 (tag == DW_TAG_array_type || tag == DW_TAG_pointer_type)) { 565 if (field->next) 566 /* Save original type for next field */ 567 memcpy(die_mem, &type, sizeof(*die_mem)); 568 /* Get the type of this array */ 569 if (die_get_real_type(&type, &type) == NULL) { 570 pr_warning("Failed to get the type of %s.\n", varname); 571 return -ENOENT; 572 } 573 pr_debug2("Array real type: (%x)\n", 574 (unsigned)dwarf_dieoffset(&type)); 575 if (tag == DW_TAG_pointer_type) { 576 ref = zalloc(sizeof(struct probe_trace_arg_ref)); 577 if (ref == NULL) 578 return -ENOMEM; 579 if (*ref_ptr) 580 (*ref_ptr)->next = ref; 581 else 582 *ref_ptr = ref; 583 } 584 ref->offset += die_get_byte_size(&type) * field->index; 585 if (!field->next) 586 /* Save vr_die for converting types */ 587 memcpy(die_mem, vr_die, sizeof(*die_mem)); 588 goto next; 589 } else if (tag == DW_TAG_pointer_type) { 590 /* Check the pointer and dereference */ 591 if (!field->ref) { 592 pr_err("Semantic error: %s must be referred by '->'\n", 593 field->name); 594 return -EINVAL; 595 } 596 /* Get the type pointed by this pointer */ 597 if (die_get_real_type(&type, &type) == NULL) { 598 pr_warning("Failed to get the type of %s.\n", varname); 599 return -ENOENT; 600 } 601 /* Verify it is a data structure */ 602 if (dwarf_tag(&type) != DW_TAG_structure_type) { 603 pr_warning("%s is not a data structure.\n", varname); 604 return -EINVAL; 605 } 606 607 ref = zalloc(sizeof(struct probe_trace_arg_ref)); 608 if (ref == NULL) 609 return -ENOMEM; 610 if (*ref_ptr) 611 (*ref_ptr)->next = ref; 612 else 613 *ref_ptr = ref; 614 } else { 615 /* Verify it is a data structure */ 616 if (tag != DW_TAG_structure_type) { 617 pr_warning("%s is not a data structure.\n", varname); 618 return -EINVAL; 619 } 620 if (field->name[0] == '[') { 621 pr_err("Semantic error: %s is not a pointor nor array.", 622 varname); 623 return -EINVAL; 624 } 625 if (field->ref) { 626 pr_err("Semantic error: %s must be referred by '.'\n", 627 field->name); 628 return -EINVAL; 629 } 630 if (!ref) { 631 pr_warning("Structure on a register is not " 632 "supported yet.\n"); 633 return -ENOTSUP; 634 } 635 } 636 637 if (die_find_member(&type, field->name, die_mem) == NULL) { 638 pr_warning("%s(tyep:%s) has no member %s.\n", varname, 639 dwarf_diename(&type), field->name); 640 return -EINVAL; 641 } 642 643 /* Get the offset of the field */ 644 ret = die_get_data_member_location(die_mem, &offs); 645 if (ret < 0) { 646 pr_warning("Failed to get the offset of %s.\n", field->name); 647 return ret; 648 } 649 ref->offset += (long)offs; 650 651 next: 652 /* Converting next field */ 653 if (field->next) 654 return convert_variable_fields(die_mem, field->name, 655 field->next, &ref, die_mem); 656 else 657 return 0; 658 } 659 660 /* Show a variables in kprobe event format */ 661 static int convert_variable(Dwarf_Die *vr_die, struct probe_finder *pf) 662 { 663 Dwarf_Die die_mem; 664 int ret; 665 666 pr_debug("Converting variable %s into trace event.\n", 667 dwarf_diename(vr_die)); 668 669 ret = convert_variable_location(vr_die, pf); 670 if (ret == 0 && pf->pvar->field) { 671 ret = convert_variable_fields(vr_die, pf->pvar->var, 672 pf->pvar->field, &pf->tvar->ref, 673 &die_mem); 674 vr_die = &die_mem; 675 } 676 if (ret == 0) 677 ret = convert_variable_type(vr_die, pf->tvar, pf->pvar->type); 678 /* *expr will be cached in libdw. Don't free it. */ 679 return ret; 680 } 681 682 /* Find a variable in a subprogram die */ 683 static int find_variable(Dwarf_Die *sp_die, struct probe_finder *pf) 684 { 685 Dwarf_Die vr_die, *scopes; 686 char buf[32], *ptr; 687 int ret, nscopes; 688 689 if (pf->pvar->name) 690 pf->tvar->name = strdup(pf->pvar->name); 691 else { 692 ret = synthesize_perf_probe_arg(pf->pvar, buf, 32); 693 if (ret < 0) 694 return ret; 695 ptr = strchr(buf, ':'); /* Change type separator to _ */ 696 if (ptr) 697 *ptr = '_'; 698 pf->tvar->name = strdup(buf); 699 } 700 if (pf->tvar->name == NULL) 701 return -ENOMEM; 702 703 if (!is_c_varname(pf->pvar->var)) { 704 /* Copy raw parameters */ 705 pf->tvar->value = strdup(pf->pvar->var); 706 if (pf->tvar->value == NULL) 707 return -ENOMEM; 708 if (pf->pvar->type) { 709 pf->tvar->type = strdup(pf->pvar->type); 710 if (pf->tvar->type == NULL) 711 return -ENOMEM; 712 } 713 return 0; 714 } 715 716 pr_debug("Searching '%s' variable in context.\n", 717 pf->pvar->var); 718 /* Search child die for local variables and parameters. */ 719 if (die_find_variable(sp_die, pf->pvar->var, &vr_die)) 720 ret = convert_variable(&vr_die, pf); 721 else { 722 /* Search upper class */ 723 nscopes = dwarf_getscopes_die(sp_die, &scopes); 724 if (nscopes > 0) { 725 ret = dwarf_getscopevar(scopes, nscopes, pf->pvar->var, 726 0, NULL, 0, 0, &vr_die); 727 if (ret >= 0) 728 ret = convert_variable(&vr_die, pf); 729 else 730 ret = -ENOENT; 731 free(scopes); 732 } else 733 ret = -ENOENT; 734 } 735 if (ret < 0) 736 pr_warning("Failed to find '%s' in this function.\n", 737 pf->pvar->var); 738 return ret; 739 } 740 741 /* Show a probe point to output buffer */ 742 static int convert_probe_point(Dwarf_Die *sp_die, struct probe_finder *pf) 743 { 744 struct probe_trace_event *tev; 745 Dwarf_Addr eaddr; 746 Dwarf_Die die_mem; 747 const char *name; 748 int ret, i; 749 Dwarf_Attribute fb_attr; 750 size_t nops; 751 752 if (pf->ntevs == pf->max_tevs) { 753 pr_warning("Too many( > %d) probe point found.\n", 754 pf->max_tevs); 755 return -ERANGE; 756 } 757 tev = &pf->tevs[pf->ntevs++]; 758 759 /* If no real subprogram, find a real one */ 760 if (!sp_die || dwarf_tag(sp_die) != DW_TAG_subprogram) { 761 sp_die = die_find_real_subprogram(&pf->cu_die, 762 pf->addr, &die_mem); 763 if (!sp_die) { 764 pr_warning("Failed to find probe point in any " 765 "functions.\n"); 766 return -ENOENT; 767 } 768 } 769 770 /* Copy the name of probe point */ 771 name = dwarf_diename(sp_die); 772 if (name) { 773 if (dwarf_entrypc(sp_die, &eaddr) != 0) { 774 pr_warning("Failed to get entry pc of %s\n", 775 dwarf_diename(sp_die)); 776 return -ENOENT; 777 } 778 tev->point.symbol = strdup(name); 779 if (tev->point.symbol == NULL) 780 return -ENOMEM; 781 tev->point.offset = (unsigned long)(pf->addr - eaddr); 782 } else 783 /* This function has no name. */ 784 tev->point.offset = (unsigned long)pf->addr; 785 786 pr_debug("Probe point found: %s+%lu\n", tev->point.symbol, 787 tev->point.offset); 788 789 /* Get the frame base attribute/ops */ 790 dwarf_attr(sp_die, DW_AT_frame_base, &fb_attr); 791 ret = dwarf_getlocation_addr(&fb_attr, pf->addr, &pf->fb_ops, &nops, 1); 792 if (ret <= 0 || nops == 0) { 793 pf->fb_ops = NULL; 794 #if _ELFUTILS_PREREQ(0, 142) 795 } else if (nops == 1 && pf->fb_ops[0].atom == DW_OP_call_frame_cfa && 796 pf->cfi != NULL) { 797 Dwarf_Frame *frame; 798 if (dwarf_cfi_addrframe(pf->cfi, pf->addr, &frame) != 0 || 799 dwarf_frame_cfa(frame, &pf->fb_ops, &nops) != 0) { 800 pr_warning("Failed to get CFA on 0x%jx\n", 801 (uintmax_t)pf->addr); 802 return -ENOENT; 803 } 804 #endif 805 } 806 807 /* Find each argument */ 808 tev->nargs = pf->pev->nargs; 809 tev->args = zalloc(sizeof(struct probe_trace_arg) * tev->nargs); 810 if (tev->args == NULL) 811 return -ENOMEM; 812 for (i = 0; i < pf->pev->nargs; i++) { 813 pf->pvar = &pf->pev->args[i]; 814 pf->tvar = &tev->args[i]; 815 ret = find_variable(sp_die, pf); 816 if (ret != 0) 817 return ret; 818 } 819 820 /* *pf->fb_ops will be cached in libdw. Don't free it. */ 821 pf->fb_ops = NULL; 822 return 0; 823 } 824 825 /* Find probe point from its line number */ 826 static int find_probe_point_by_line(struct probe_finder *pf) 827 { 828 Dwarf_Lines *lines; 829 Dwarf_Line *line; 830 size_t nlines, i; 831 Dwarf_Addr addr; 832 int lineno; 833 int ret = 0; 834 835 if (dwarf_getsrclines(&pf->cu_die, &lines, &nlines) != 0) { 836 pr_warning("No source lines found in this CU.\n"); 837 return -ENOENT; 838 } 839 840 for (i = 0; i < nlines && ret == 0; i++) { 841 line = dwarf_onesrcline(lines, i); 842 if (dwarf_lineno(line, &lineno) != 0 || 843 lineno != pf->lno) 844 continue; 845 846 /* TODO: Get fileno from line, but how? */ 847 if (strtailcmp(dwarf_linesrc(line, NULL, NULL), pf->fname) != 0) 848 continue; 849 850 if (dwarf_lineaddr(line, &addr) != 0) { 851 pr_warning("Failed to get the address of the line.\n"); 852 return -ENOENT; 853 } 854 pr_debug("Probe line found: line[%d]:%d addr:0x%jx\n", 855 (int)i, lineno, (uintmax_t)addr); 856 pf->addr = addr; 857 858 ret = convert_probe_point(NULL, pf); 859 /* Continuing, because target line might be inlined. */ 860 } 861 return ret; 862 } 863 864 /* Find lines which match lazy pattern */ 865 static int find_lazy_match_lines(struct list_head *head, 866 const char *fname, const char *pat) 867 { 868 char *fbuf, *p1, *p2; 869 int fd, line, nlines = -1; 870 struct stat st; 871 872 fd = open(fname, O_RDONLY); 873 if (fd < 0) { 874 pr_warning("Failed to open %s: %s\n", fname, strerror(-fd)); 875 return -errno; 876 } 877 878 if (fstat(fd, &st) < 0) { 879 pr_warning("Failed to get the size of %s: %s\n", 880 fname, strerror(errno)); 881 nlines = -errno; 882 goto out_close; 883 } 884 885 nlines = -ENOMEM; 886 fbuf = malloc(st.st_size + 2); 887 if (fbuf == NULL) 888 goto out_close; 889 if (read(fd, fbuf, st.st_size) < 0) { 890 pr_warning("Failed to read %s: %s\n", fname, strerror(errno)); 891 nlines = -errno; 892 goto out_free_fbuf; 893 } 894 fbuf[st.st_size] = '\n'; /* Dummy line */ 895 fbuf[st.st_size + 1] = '\0'; 896 p1 = fbuf; 897 line = 1; 898 nlines = 0; 899 while ((p2 = strchr(p1, '\n')) != NULL) { 900 *p2 = '\0'; 901 if (strlazymatch(p1, pat)) { 902 line_list__add_line(head, line); 903 nlines++; 904 } 905 line++; 906 p1 = p2 + 1; 907 } 908 out_free_fbuf: 909 free(fbuf); 910 out_close: 911 close(fd); 912 return nlines; 913 } 914 915 /* Find probe points from lazy pattern */ 916 static int find_probe_point_lazy(Dwarf_Die *sp_die, struct probe_finder *pf) 917 { 918 Dwarf_Lines *lines; 919 Dwarf_Line *line; 920 size_t nlines, i; 921 Dwarf_Addr addr; 922 Dwarf_Die die_mem; 923 int lineno; 924 int ret = 0; 925 926 if (list_empty(&pf->lcache)) { 927 /* Matching lazy line pattern */ 928 ret = find_lazy_match_lines(&pf->lcache, pf->fname, 929 pf->pev->point.lazy_line); 930 if (ret == 0) { 931 pr_debug("No matched lines found in %s.\n", pf->fname); 932 return 0; 933 } else if (ret < 0) 934 return ret; 935 } 936 937 if (dwarf_getsrclines(&pf->cu_die, &lines, &nlines) != 0) { 938 pr_warning("No source lines found in this CU.\n"); 939 return -ENOENT; 940 } 941 942 for (i = 0; i < nlines && ret >= 0; i++) { 943 line = dwarf_onesrcline(lines, i); 944 945 if (dwarf_lineno(line, &lineno) != 0 || 946 !line_list__has_line(&pf->lcache, lineno)) 947 continue; 948 949 /* TODO: Get fileno from line, but how? */ 950 if (strtailcmp(dwarf_linesrc(line, NULL, NULL), pf->fname) != 0) 951 continue; 952 953 if (dwarf_lineaddr(line, &addr) != 0) { 954 pr_debug("Failed to get the address of line %d.\n", 955 lineno); 956 continue; 957 } 958 if (sp_die) { 959 /* Address filtering 1: does sp_die include addr? */ 960 if (!dwarf_haspc(sp_die, addr)) 961 continue; 962 /* Address filtering 2: No child include addr? */ 963 if (die_find_inlinefunc(sp_die, addr, &die_mem)) 964 continue; 965 } 966 967 pr_debug("Probe line found: line[%d]:%d addr:0x%llx\n", 968 (int)i, lineno, (unsigned long long)addr); 969 pf->addr = addr; 970 971 ret = convert_probe_point(sp_die, pf); 972 /* Continuing, because target line might be inlined. */ 973 } 974 /* TODO: deallocate lines, but how? */ 975 return ret; 976 } 977 978 /* Callback parameter with return value */ 979 struct dwarf_callback_param { 980 void *data; 981 int retval; 982 }; 983 984 static int probe_point_inline_cb(Dwarf_Die *in_die, void *data) 985 { 986 struct dwarf_callback_param *param = data; 987 struct probe_finder *pf = param->data; 988 struct perf_probe_point *pp = &pf->pev->point; 989 Dwarf_Addr addr; 990 991 if (pp->lazy_line) 992 param->retval = find_probe_point_lazy(in_die, pf); 993 else { 994 /* Get probe address */ 995 if (dwarf_entrypc(in_die, &addr) != 0) { 996 pr_warning("Failed to get entry pc of %s.\n", 997 dwarf_diename(in_die)); 998 param->retval = -ENOENT; 999 return DWARF_CB_ABORT; 1000 } 1001 pf->addr = addr; 1002 pf->addr += pp->offset; 1003 pr_debug("found inline addr: 0x%jx\n", 1004 (uintmax_t)pf->addr); 1005 1006 param->retval = convert_probe_point(in_die, pf); 1007 if (param->retval < 0) 1008 return DWARF_CB_ABORT; 1009 } 1010 1011 return DWARF_CB_OK; 1012 } 1013 1014 /* Search function from function name */ 1015 static int probe_point_search_cb(Dwarf_Die *sp_die, void *data) 1016 { 1017 struct dwarf_callback_param *param = data; 1018 struct probe_finder *pf = param->data; 1019 struct perf_probe_point *pp = &pf->pev->point; 1020 1021 /* Check tag and diename */ 1022 if (dwarf_tag(sp_die) != DW_TAG_subprogram || 1023 !die_compare_name(sp_die, pp->function)) 1024 return DWARF_CB_OK; 1025 1026 pf->fname = dwarf_decl_file(sp_die); 1027 if (pp->line) { /* Function relative line */ 1028 dwarf_decl_line(sp_die, &pf->lno); 1029 pf->lno += pp->line; 1030 param->retval = find_probe_point_by_line(pf); 1031 } else if (!dwarf_func_inline(sp_die)) { 1032 /* Real function */ 1033 if (pp->lazy_line) 1034 param->retval = find_probe_point_lazy(sp_die, pf); 1035 else { 1036 if (dwarf_entrypc(sp_die, &pf->addr) != 0) { 1037 pr_warning("Failed to get entry pc of %s.\n", 1038 dwarf_diename(sp_die)); 1039 param->retval = -ENOENT; 1040 return DWARF_CB_ABORT; 1041 } 1042 pf->addr += pp->offset; 1043 /* TODO: Check the address in this function */ 1044 param->retval = convert_probe_point(sp_die, pf); 1045 } 1046 } else { 1047 struct dwarf_callback_param _param = {.data = (void *)pf, 1048 .retval = 0}; 1049 /* Inlined function: search instances */ 1050 dwarf_func_inline_instances(sp_die, probe_point_inline_cb, 1051 &_param); 1052 param->retval = _param.retval; 1053 } 1054 1055 return DWARF_CB_ABORT; /* Exit; no same symbol in this CU. */ 1056 } 1057 1058 static int find_probe_point_by_func(struct probe_finder *pf) 1059 { 1060 struct dwarf_callback_param _param = {.data = (void *)pf, 1061 .retval = 0}; 1062 dwarf_getfuncs(&pf->cu_die, probe_point_search_cb, &_param, 0); 1063 return _param.retval; 1064 } 1065 1066 /* Find probe_trace_events specified by perf_probe_event from debuginfo */ 1067 int find_probe_trace_events(int fd, struct perf_probe_event *pev, 1068 struct probe_trace_event **tevs, int max_tevs) 1069 { 1070 struct probe_finder pf = {.pev = pev, .max_tevs = max_tevs}; 1071 struct perf_probe_point *pp = &pev->point; 1072 Dwarf_Off off, noff; 1073 size_t cuhl; 1074 Dwarf_Die *diep; 1075 Dwarf *dbg; 1076 int ret = 0; 1077 1078 pf.tevs = zalloc(sizeof(struct probe_trace_event) * max_tevs); 1079 if (pf.tevs == NULL) 1080 return -ENOMEM; 1081 *tevs = pf.tevs; 1082 pf.ntevs = 0; 1083 1084 dbg = dwarf_begin(fd, DWARF_C_READ); 1085 if (!dbg) { 1086 pr_warning("No dwarf info found in the vmlinux - " 1087 "please rebuild with CONFIG_DEBUG_INFO=y.\n"); 1088 free(pf.tevs); 1089 *tevs = NULL; 1090 return -EBADF; 1091 } 1092 1093 #if _ELFUTILS_PREREQ(0, 142) 1094 /* Get the call frame information from this dwarf */ 1095 pf.cfi = dwarf_getcfi(dbg); 1096 #endif 1097 1098 off = 0; 1099 line_list__init(&pf.lcache); 1100 /* Loop on CUs (Compilation Unit) */ 1101 while (!dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL) && 1102 ret >= 0) { 1103 /* Get the DIE(Debugging Information Entry) of this CU */ 1104 diep = dwarf_offdie(dbg, off + cuhl, &pf.cu_die); 1105 if (!diep) 1106 continue; 1107 1108 /* Check if target file is included. */ 1109 if (pp->file) 1110 pf.fname = cu_find_realpath(&pf.cu_die, pp->file); 1111 else 1112 pf.fname = NULL; 1113 1114 if (!pp->file || pf.fname) { 1115 if (pp->function) 1116 ret = find_probe_point_by_func(&pf); 1117 else if (pp->lazy_line) 1118 ret = find_probe_point_lazy(NULL, &pf); 1119 else { 1120 pf.lno = pp->line; 1121 ret = find_probe_point_by_line(&pf); 1122 } 1123 } 1124 off = noff; 1125 } 1126 line_list__free(&pf.lcache); 1127 dwarf_end(dbg); 1128 1129 return (ret < 0) ? ret : pf.ntevs; 1130 } 1131 1132 /* Reverse search */ 1133 int find_perf_probe_point(int fd, unsigned long addr, 1134 struct perf_probe_point *ppt) 1135 { 1136 Dwarf_Die cudie, spdie, indie; 1137 Dwarf *dbg; 1138 Dwarf_Line *line; 1139 Dwarf_Addr laddr, eaddr; 1140 const char *tmp; 1141 int lineno, ret = 0; 1142 bool found = false; 1143 1144 dbg = dwarf_begin(fd, DWARF_C_READ); 1145 if (!dbg) 1146 return -EBADF; 1147 1148 /* Find cu die */ 1149 if (!dwarf_addrdie(dbg, (Dwarf_Addr)addr, &cudie)) { 1150 ret = -EINVAL; 1151 goto end; 1152 } 1153 1154 /* Find a corresponding line */ 1155 line = dwarf_getsrc_die(&cudie, (Dwarf_Addr)addr); 1156 if (line) { 1157 if (dwarf_lineaddr(line, &laddr) == 0 && 1158 (Dwarf_Addr)addr == laddr && 1159 dwarf_lineno(line, &lineno) == 0) { 1160 tmp = dwarf_linesrc(line, NULL, NULL); 1161 if (tmp) { 1162 ppt->line = lineno; 1163 ppt->file = strdup(tmp); 1164 if (ppt->file == NULL) { 1165 ret = -ENOMEM; 1166 goto end; 1167 } 1168 found = true; 1169 } 1170 } 1171 } 1172 1173 /* Find a corresponding function */ 1174 if (die_find_real_subprogram(&cudie, (Dwarf_Addr)addr, &spdie)) { 1175 tmp = dwarf_diename(&spdie); 1176 if (!tmp || dwarf_entrypc(&spdie, &eaddr) != 0) 1177 goto end; 1178 1179 if (ppt->line) { 1180 if (die_find_inlinefunc(&spdie, (Dwarf_Addr)addr, 1181 &indie)) { 1182 /* addr in an inline function */ 1183 tmp = dwarf_diename(&indie); 1184 if (!tmp) 1185 goto end; 1186 ret = dwarf_decl_line(&indie, &lineno); 1187 } else { 1188 if (eaddr == addr) { /* Function entry */ 1189 lineno = ppt->line; 1190 ret = 0; 1191 } else 1192 ret = dwarf_decl_line(&spdie, &lineno); 1193 } 1194 if (ret == 0) { 1195 /* Make a relative line number */ 1196 ppt->line -= lineno; 1197 goto found; 1198 } 1199 } 1200 /* We don't have a line number, let's use offset */ 1201 ppt->offset = addr - (unsigned long)eaddr; 1202 found: 1203 ppt->function = strdup(tmp); 1204 if (ppt->function == NULL) { 1205 ret = -ENOMEM; 1206 goto end; 1207 } 1208 found = true; 1209 } 1210 1211 end: 1212 dwarf_end(dbg); 1213 if (ret >= 0) 1214 ret = found ? 1 : 0; 1215 return ret; 1216 } 1217 1218 /* Add a line and store the src path */ 1219 static int line_range_add_line(const char *src, unsigned int lineno, 1220 struct line_range *lr) 1221 { 1222 /* Copy source path */ 1223 if (!lr->path) { 1224 lr->path = strdup(src); 1225 if (lr->path == NULL) 1226 return -ENOMEM; 1227 } 1228 return line_list__add_line(&lr->line_list, lineno); 1229 } 1230 1231 /* Search function declaration lines */ 1232 static int line_range_funcdecl_cb(Dwarf_Die *sp_die, void *data) 1233 { 1234 struct dwarf_callback_param *param = data; 1235 struct line_finder *lf = param->data; 1236 const char *src; 1237 int lineno; 1238 1239 src = dwarf_decl_file(sp_die); 1240 if (src && strtailcmp(src, lf->fname) != 0) 1241 return DWARF_CB_OK; 1242 1243 if (dwarf_decl_line(sp_die, &lineno) != 0 || 1244 (lf->lno_s > lineno || lf->lno_e < lineno)) 1245 return DWARF_CB_OK; 1246 1247 param->retval = line_range_add_line(src, lineno, lf->lr); 1248 if (param->retval < 0) 1249 return DWARF_CB_ABORT; 1250 return DWARF_CB_OK; 1251 } 1252 1253 static int find_line_range_func_decl_lines(struct line_finder *lf) 1254 { 1255 struct dwarf_callback_param param = {.data = (void *)lf, .retval = 0}; 1256 dwarf_getfuncs(&lf->cu_die, line_range_funcdecl_cb, ¶m, 0); 1257 return param.retval; 1258 } 1259 1260 /* Find line range from its line number */ 1261 static int find_line_range_by_line(Dwarf_Die *sp_die, struct line_finder *lf) 1262 { 1263 Dwarf_Lines *lines; 1264 Dwarf_Line *line; 1265 size_t nlines, i; 1266 Dwarf_Addr addr; 1267 int lineno, ret = 0; 1268 const char *src; 1269 Dwarf_Die die_mem; 1270 1271 line_list__init(&lf->lr->line_list); 1272 if (dwarf_getsrclines(&lf->cu_die, &lines, &nlines) != 0) { 1273 pr_warning("No source lines found in this CU.\n"); 1274 return -ENOENT; 1275 } 1276 1277 /* Search probable lines on lines list */ 1278 for (i = 0; i < nlines; i++) { 1279 line = dwarf_onesrcline(lines, i); 1280 if (dwarf_lineno(line, &lineno) != 0 || 1281 (lf->lno_s > lineno || lf->lno_e < lineno)) 1282 continue; 1283 1284 if (sp_die) { 1285 /* Address filtering 1: does sp_die include addr? */ 1286 if (dwarf_lineaddr(line, &addr) != 0 || 1287 !dwarf_haspc(sp_die, addr)) 1288 continue; 1289 1290 /* Address filtering 2: No child include addr? */ 1291 if (die_find_inlinefunc(sp_die, addr, &die_mem)) 1292 continue; 1293 } 1294 1295 /* TODO: Get fileno from line, but how? */ 1296 src = dwarf_linesrc(line, NULL, NULL); 1297 if (strtailcmp(src, lf->fname) != 0) 1298 continue; 1299 1300 ret = line_range_add_line(src, lineno, lf->lr); 1301 if (ret < 0) 1302 return ret; 1303 } 1304 1305 /* 1306 * Dwarf lines doesn't include function declarations. We have to 1307 * check functions list or given function. 1308 */ 1309 if (sp_die) { 1310 src = dwarf_decl_file(sp_die); 1311 if (src && dwarf_decl_line(sp_die, &lineno) == 0 && 1312 (lf->lno_s <= lineno && lf->lno_e >= lineno)) 1313 ret = line_range_add_line(src, lineno, lf->lr); 1314 } else 1315 ret = find_line_range_func_decl_lines(lf); 1316 1317 /* Update status */ 1318 if (ret >= 0) 1319 if (!list_empty(&lf->lr->line_list)) 1320 ret = lf->found = 1; 1321 else 1322 ret = 0; /* Lines are not found */ 1323 else { 1324 free(lf->lr->path); 1325 lf->lr->path = NULL; 1326 } 1327 return ret; 1328 } 1329 1330 static int line_range_inline_cb(Dwarf_Die *in_die, void *data) 1331 { 1332 struct dwarf_callback_param *param = data; 1333 1334 param->retval = find_line_range_by_line(in_die, param->data); 1335 return DWARF_CB_ABORT; /* No need to find other instances */ 1336 } 1337 1338 /* Search function from function name */ 1339 static int line_range_search_cb(Dwarf_Die *sp_die, void *data) 1340 { 1341 struct dwarf_callback_param *param = data; 1342 struct line_finder *lf = param->data; 1343 struct line_range *lr = lf->lr; 1344 1345 if (dwarf_tag(sp_die) == DW_TAG_subprogram && 1346 die_compare_name(sp_die, lr->function)) { 1347 lf->fname = dwarf_decl_file(sp_die); 1348 dwarf_decl_line(sp_die, &lr->offset); 1349 pr_debug("fname: %s, lineno:%d\n", lf->fname, lr->offset); 1350 lf->lno_s = lr->offset + lr->start; 1351 if (lf->lno_s < 0) /* Overflow */ 1352 lf->lno_s = INT_MAX; 1353 lf->lno_e = lr->offset + lr->end; 1354 if (lf->lno_e < 0) /* Overflow */ 1355 lf->lno_e = INT_MAX; 1356 pr_debug("New line range: %d to %d\n", lf->lno_s, lf->lno_e); 1357 lr->start = lf->lno_s; 1358 lr->end = lf->lno_e; 1359 if (dwarf_func_inline(sp_die)) { 1360 struct dwarf_callback_param _param; 1361 _param.data = (void *)lf; 1362 _param.retval = 0; 1363 dwarf_func_inline_instances(sp_die, 1364 line_range_inline_cb, 1365 &_param); 1366 param->retval = _param.retval; 1367 } else 1368 param->retval = find_line_range_by_line(sp_die, lf); 1369 return DWARF_CB_ABORT; 1370 } 1371 return DWARF_CB_OK; 1372 } 1373 1374 static int find_line_range_by_func(struct line_finder *lf) 1375 { 1376 struct dwarf_callback_param param = {.data = (void *)lf, .retval = 0}; 1377 dwarf_getfuncs(&lf->cu_die, line_range_search_cb, ¶m, 0); 1378 return param.retval; 1379 } 1380 1381 int find_line_range(int fd, struct line_range *lr) 1382 { 1383 struct line_finder lf = {.lr = lr, .found = 0}; 1384 int ret = 0; 1385 Dwarf_Off off = 0, noff; 1386 size_t cuhl; 1387 Dwarf_Die *diep; 1388 Dwarf *dbg; 1389 const char *comp_dir; 1390 1391 dbg = dwarf_begin(fd, DWARF_C_READ); 1392 if (!dbg) { 1393 pr_warning("No dwarf info found in the vmlinux - " 1394 "please rebuild with CONFIG_DEBUG_INFO=y.\n"); 1395 return -EBADF; 1396 } 1397 1398 /* Loop on CUs (Compilation Unit) */ 1399 while (!lf.found && ret >= 0) { 1400 if (dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL) != 0) 1401 break; 1402 1403 /* Get the DIE(Debugging Information Entry) of this CU */ 1404 diep = dwarf_offdie(dbg, off + cuhl, &lf.cu_die); 1405 if (!diep) 1406 continue; 1407 1408 /* Check if target file is included. */ 1409 if (lr->file) 1410 lf.fname = cu_find_realpath(&lf.cu_die, lr->file); 1411 else 1412 lf.fname = 0; 1413 1414 if (!lr->file || lf.fname) { 1415 if (lr->function) 1416 ret = find_line_range_by_func(&lf); 1417 else { 1418 lf.lno_s = lr->start; 1419 lf.lno_e = lr->end; 1420 ret = find_line_range_by_line(NULL, &lf); 1421 } 1422 } 1423 off = noff; 1424 } 1425 1426 /* Store comp_dir */ 1427 if (lf.found) { 1428 comp_dir = cu_get_comp_dir(&lf.cu_die); 1429 if (comp_dir) { 1430 lr->comp_dir = strdup(comp_dir); 1431 if (!lr->comp_dir) 1432 ret = -ENOMEM; 1433 } 1434 } 1435 1436 pr_debug("path: %s\n", lr->path); 1437 dwarf_end(dbg); 1438 1439 return (ret < 0) ? ret : lf.found; 1440 } 1441 1442