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