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