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 35 #include "event.h" 36 #include "debug.h" 37 #include "util.h" 38 #include "probe-finder.h" 39 40 41 /* Dwarf_Die Linkage to parent Die */ 42 struct die_link { 43 struct die_link *parent; /* Parent die */ 44 Dwarf_Die die; /* Current die */ 45 }; 46 47 static Dwarf_Debug __dw_debug; 48 static Dwarf_Error __dw_error; 49 50 /* 51 * Generic dwarf analysis helpers 52 */ 53 54 #define X86_32_MAX_REGS 8 55 const char *x86_32_regs_table[X86_32_MAX_REGS] = { 56 "%ax", 57 "%cx", 58 "%dx", 59 "%bx", 60 "$stack", /* Stack address instead of %sp */ 61 "%bp", 62 "%si", 63 "%di", 64 }; 65 66 #define X86_64_MAX_REGS 16 67 const char *x86_64_regs_table[X86_64_MAX_REGS] = { 68 "%ax", 69 "%dx", 70 "%cx", 71 "%bx", 72 "%si", 73 "%di", 74 "%bp", 75 "%sp", 76 "%r8", 77 "%r9", 78 "%r10", 79 "%r11", 80 "%r12", 81 "%r13", 82 "%r14", 83 "%r15", 84 }; 85 86 /* TODO: switching by dwarf address size */ 87 #ifdef __x86_64__ 88 #define ARCH_MAX_REGS X86_64_MAX_REGS 89 #define arch_regs_table x86_64_regs_table 90 #else 91 #define ARCH_MAX_REGS X86_32_MAX_REGS 92 #define arch_regs_table x86_32_regs_table 93 #endif 94 95 /* Return architecture dependent register string (for kprobe-tracer) */ 96 static const char *get_arch_regstr(unsigned int n) 97 { 98 return (n <= ARCH_MAX_REGS) ? arch_regs_table[n] : NULL; 99 } 100 101 /* 102 * Compare the tail of two strings. 103 * Return 0 if whole of either string is same as another's tail part. 104 */ 105 static int strtailcmp(const char *s1, const char *s2) 106 { 107 int i1 = strlen(s1); 108 int i2 = strlen(s2); 109 while (--i1 >= 0 && --i2 >= 0) { 110 if (s1[i1] != s2[i2]) 111 return s1[i1] - s2[i2]; 112 } 113 return 0; 114 } 115 116 /* Find the fileno of the target file. */ 117 static Dwarf_Unsigned cu_find_fileno(Dwarf_Die cu_die, const char *fname) 118 { 119 Dwarf_Signed cnt, i; 120 Dwarf_Unsigned found = 0; 121 char **srcs; 122 int ret; 123 124 if (!fname) 125 return 0; 126 127 ret = dwarf_srcfiles(cu_die, &srcs, &cnt, &__dw_error); 128 if (ret == DW_DLV_OK) { 129 for (i = 0; i < cnt && !found; i++) { 130 if (strtailcmp(srcs[i], fname) == 0) 131 found = i + 1; 132 dwarf_dealloc(__dw_debug, srcs[i], DW_DLA_STRING); 133 } 134 for (; i < cnt; i++) 135 dwarf_dealloc(__dw_debug, srcs[i], DW_DLA_STRING); 136 dwarf_dealloc(__dw_debug, srcs, DW_DLA_LIST); 137 } 138 if (found) 139 pr_debug("found fno: %d\n", (int)found); 140 return found; 141 } 142 143 /* Compare diename and tname */ 144 static int die_compare_name(Dwarf_Die dw_die, const char *tname) 145 { 146 char *name; 147 int ret; 148 ret = dwarf_diename(dw_die, &name, &__dw_error); 149 DIE_IF(ret == DW_DLV_ERROR); 150 if (ret == DW_DLV_OK) { 151 ret = strcmp(tname, name); 152 dwarf_dealloc(__dw_debug, name, DW_DLA_STRING); 153 } else 154 ret = -1; 155 return ret; 156 } 157 158 /* Check the address is in the subprogram(function). */ 159 static int die_within_subprogram(Dwarf_Die sp_die, Dwarf_Addr addr, 160 Dwarf_Signed *offs) 161 { 162 Dwarf_Addr lopc, hipc; 163 int ret; 164 165 /* TODO: check ranges */ 166 ret = dwarf_lowpc(sp_die, &lopc, &__dw_error); 167 DIE_IF(ret == DW_DLV_ERROR); 168 if (ret == DW_DLV_NO_ENTRY) 169 return 0; 170 ret = dwarf_highpc(sp_die, &hipc, &__dw_error); 171 DIE_IF(ret != DW_DLV_OK); 172 if (lopc <= addr && addr < hipc) { 173 *offs = addr - lopc; 174 return 1; 175 } else 176 return 0; 177 } 178 179 /* Check the die is inlined function */ 180 static Dwarf_Bool die_inlined_subprogram(Dwarf_Die dw_die) 181 { 182 /* TODO: check strictly */ 183 Dwarf_Bool inl; 184 int ret; 185 186 ret = dwarf_hasattr(dw_die, DW_AT_inline, &inl, &__dw_error); 187 DIE_IF(ret == DW_DLV_ERROR); 188 return inl; 189 } 190 191 /* Get the offset of abstruct_origin */ 192 static Dwarf_Off die_get_abstract_origin(Dwarf_Die dw_die) 193 { 194 Dwarf_Attribute attr; 195 Dwarf_Off cu_offs; 196 int ret; 197 198 ret = dwarf_attr(dw_die, DW_AT_abstract_origin, &attr, &__dw_error); 199 DIE_IF(ret != DW_DLV_OK); 200 ret = dwarf_formref(attr, &cu_offs, &__dw_error); 201 DIE_IF(ret != DW_DLV_OK); 202 dwarf_dealloc(__dw_debug, attr, DW_DLA_ATTR); 203 return cu_offs; 204 } 205 206 /* Get entry pc(or low pc, 1st entry of ranges) of the die */ 207 static Dwarf_Addr die_get_entrypc(Dwarf_Die dw_die) 208 { 209 Dwarf_Attribute attr; 210 Dwarf_Addr addr; 211 Dwarf_Off offs; 212 Dwarf_Ranges *ranges; 213 Dwarf_Signed cnt; 214 int ret; 215 216 /* Try to get entry pc */ 217 ret = dwarf_attr(dw_die, DW_AT_entry_pc, &attr, &__dw_error); 218 DIE_IF(ret == DW_DLV_ERROR); 219 if (ret == DW_DLV_OK) { 220 ret = dwarf_formaddr(attr, &addr, &__dw_error); 221 DIE_IF(ret != DW_DLV_OK); 222 dwarf_dealloc(__dw_debug, attr, DW_DLA_ATTR); 223 return addr; 224 } 225 226 /* Try to get low pc */ 227 ret = dwarf_lowpc(dw_die, &addr, &__dw_error); 228 DIE_IF(ret == DW_DLV_ERROR); 229 if (ret == DW_DLV_OK) 230 return addr; 231 232 /* Try to get ranges */ 233 ret = dwarf_attr(dw_die, DW_AT_ranges, &attr, &__dw_error); 234 DIE_IF(ret != DW_DLV_OK); 235 ret = dwarf_formref(attr, &offs, &__dw_error); 236 DIE_IF(ret != DW_DLV_OK); 237 ret = dwarf_get_ranges(__dw_debug, offs, &ranges, &cnt, NULL, 238 &__dw_error); 239 DIE_IF(ret != DW_DLV_OK); 240 addr = ranges[0].dwr_addr1; 241 dwarf_ranges_dealloc(__dw_debug, ranges, cnt); 242 return addr; 243 } 244 245 /* 246 * Search a Die from Die tree. 247 * Note: cur_link->die should be deallocated in this function. 248 */ 249 static int __search_die_tree(struct die_link *cur_link, 250 int (*die_cb)(struct die_link *, void *), 251 void *data) 252 { 253 Dwarf_Die new_die; 254 struct die_link new_link; 255 int ret; 256 257 if (!die_cb) 258 return 0; 259 260 /* Check current die */ 261 while (!(ret = die_cb(cur_link, data))) { 262 /* Check child die */ 263 ret = dwarf_child(cur_link->die, &new_die, &__dw_error); 264 DIE_IF(ret == DW_DLV_ERROR); 265 if (ret == DW_DLV_OK) { 266 new_link.parent = cur_link; 267 new_link.die = new_die; 268 ret = __search_die_tree(&new_link, die_cb, data); 269 if (ret) 270 break; 271 } 272 273 /* Move to next sibling */ 274 ret = dwarf_siblingof(__dw_debug, cur_link->die, &new_die, 275 &__dw_error); 276 DIE_IF(ret == DW_DLV_ERROR); 277 dwarf_dealloc(__dw_debug, cur_link->die, DW_DLA_DIE); 278 cur_link->die = new_die; 279 if (ret == DW_DLV_NO_ENTRY) 280 return 0; 281 } 282 dwarf_dealloc(__dw_debug, cur_link->die, DW_DLA_DIE); 283 return ret; 284 } 285 286 /* Search a die in its children's die tree */ 287 static int search_die_from_children(Dwarf_Die parent_die, 288 int (*die_cb)(struct die_link *, void *), 289 void *data) 290 { 291 struct die_link new_link; 292 int ret; 293 294 new_link.parent = NULL; 295 ret = dwarf_child(parent_die, &new_link.die, &__dw_error); 296 DIE_IF(ret == DW_DLV_ERROR); 297 if (ret == DW_DLV_OK) 298 return __search_die_tree(&new_link, die_cb, data); 299 else 300 return 0; 301 } 302 303 /* Find a locdesc corresponding to the address */ 304 static int attr_get_locdesc(Dwarf_Attribute attr, Dwarf_Locdesc *desc, 305 Dwarf_Addr addr) 306 { 307 Dwarf_Signed lcnt; 308 Dwarf_Locdesc **llbuf; 309 int ret, i; 310 311 ret = dwarf_loclist_n(attr, &llbuf, &lcnt, &__dw_error); 312 DIE_IF(ret != DW_DLV_OK); 313 ret = DW_DLV_NO_ENTRY; 314 for (i = 0; i < lcnt; ++i) { 315 if (llbuf[i]->ld_lopc <= addr && 316 llbuf[i]->ld_hipc > addr) { 317 memcpy(desc, llbuf[i], sizeof(Dwarf_Locdesc)); 318 desc->ld_s = 319 malloc(sizeof(Dwarf_Loc) * llbuf[i]->ld_cents); 320 DIE_IF(desc->ld_s == NULL); 321 memcpy(desc->ld_s, llbuf[i]->ld_s, 322 sizeof(Dwarf_Loc) * llbuf[i]->ld_cents); 323 ret = DW_DLV_OK; 324 break; 325 } 326 dwarf_dealloc(__dw_debug, llbuf[i]->ld_s, DW_DLA_LOC_BLOCK); 327 dwarf_dealloc(__dw_debug, llbuf[i], DW_DLA_LOCDESC); 328 } 329 /* Releasing loop */ 330 for (; i < lcnt; ++i) { 331 dwarf_dealloc(__dw_debug, llbuf[i]->ld_s, DW_DLA_LOC_BLOCK); 332 dwarf_dealloc(__dw_debug, llbuf[i], DW_DLA_LOCDESC); 333 } 334 dwarf_dealloc(__dw_debug, llbuf, DW_DLA_LIST); 335 return ret; 336 } 337 338 /* Get decl_file attribute value (file number) */ 339 static Dwarf_Unsigned die_get_decl_file(Dwarf_Die sp_die) 340 { 341 Dwarf_Attribute attr; 342 Dwarf_Unsigned fno; 343 int ret; 344 345 ret = dwarf_attr(sp_die, DW_AT_decl_file, &attr, &__dw_error); 346 DIE_IF(ret != DW_DLV_OK); 347 dwarf_formudata(attr, &fno, &__dw_error); 348 DIE_IF(ret != DW_DLV_OK); 349 dwarf_dealloc(__dw_debug, attr, DW_DLA_ATTR); 350 return fno; 351 } 352 353 /* Get decl_line attribute value (line number) */ 354 static Dwarf_Unsigned die_get_decl_line(Dwarf_Die sp_die) 355 { 356 Dwarf_Attribute attr; 357 Dwarf_Unsigned lno; 358 int ret; 359 360 ret = dwarf_attr(sp_die, DW_AT_decl_line, &attr, &__dw_error); 361 DIE_IF(ret != DW_DLV_OK); 362 dwarf_formudata(attr, &lno, &__dw_error); 363 DIE_IF(ret != DW_DLV_OK); 364 dwarf_dealloc(__dw_debug, attr, DW_DLA_ATTR); 365 return lno; 366 } 367 368 /* 369 * Probe finder related functions 370 */ 371 372 /* Show a location */ 373 static void show_location(Dwarf_Loc *loc, struct probe_finder *pf) 374 { 375 Dwarf_Small op; 376 Dwarf_Unsigned regn; 377 Dwarf_Signed offs; 378 int deref = 0, ret; 379 const char *regs; 380 381 op = loc->lr_atom; 382 383 /* If this is based on frame buffer, set the offset */ 384 if (op == DW_OP_fbreg) { 385 deref = 1; 386 offs = (Dwarf_Signed)loc->lr_number; 387 op = pf->fbloc.ld_s[0].lr_atom; 388 loc = &pf->fbloc.ld_s[0]; 389 } else 390 offs = 0; 391 392 if (op >= DW_OP_breg0 && op <= DW_OP_breg31) { 393 regn = op - DW_OP_breg0; 394 offs += (Dwarf_Signed)loc->lr_number; 395 deref = 1; 396 } else if (op >= DW_OP_reg0 && op <= DW_OP_reg31) { 397 regn = op - DW_OP_reg0; 398 } else if (op == DW_OP_bregx) { 399 regn = loc->lr_number; 400 offs += (Dwarf_Signed)loc->lr_number2; 401 deref = 1; 402 } else if (op == DW_OP_regx) { 403 regn = loc->lr_number; 404 } else 405 die("Dwarf_OP %d is not supported.\n", op); 406 407 regs = get_arch_regstr(regn); 408 if (!regs) 409 die("%lld exceeds max register number.\n", regn); 410 411 if (deref) 412 ret = snprintf(pf->buf, pf->len, 413 " %s=%+lld(%s)", pf->var, offs, regs); 414 else 415 ret = snprintf(pf->buf, pf->len, " %s=%s", pf->var, regs); 416 DIE_IF(ret < 0); 417 DIE_IF(ret >= pf->len); 418 } 419 420 /* Show a variables in kprobe event format */ 421 static void show_variable(Dwarf_Die vr_die, struct probe_finder *pf) 422 { 423 Dwarf_Attribute attr; 424 Dwarf_Locdesc ld; 425 int ret; 426 427 ret = dwarf_attr(vr_die, DW_AT_location, &attr, &__dw_error); 428 if (ret != DW_DLV_OK) 429 goto error; 430 ret = attr_get_locdesc(attr, &ld, (pf->addr - pf->cu_base)); 431 if (ret != DW_DLV_OK) 432 goto error; 433 /* TODO? */ 434 DIE_IF(ld.ld_cents != 1); 435 show_location(&ld.ld_s[0], pf); 436 free(ld.ld_s); 437 dwarf_dealloc(__dw_debug, attr, DW_DLA_ATTR); 438 return ; 439 error: 440 die("Failed to find the location of %s at this address.\n" 441 " Perhaps, it has been optimized out.\n", pf->var); 442 } 443 444 static int variable_callback(struct die_link *dlink, void *data) 445 { 446 struct probe_finder *pf = (struct probe_finder *)data; 447 Dwarf_Half tag; 448 int ret; 449 450 ret = dwarf_tag(dlink->die, &tag, &__dw_error); 451 DIE_IF(ret == DW_DLV_ERROR); 452 if ((tag == DW_TAG_formal_parameter || 453 tag == DW_TAG_variable) && 454 (die_compare_name(dlink->die, pf->var) == 0)) { 455 show_variable(dlink->die, pf); 456 return 1; 457 } 458 /* TODO: Support struct members and arrays */ 459 return 0; 460 } 461 462 /* Find a variable in a subprogram die */ 463 static void find_variable(Dwarf_Die sp_die, struct probe_finder *pf) 464 { 465 int ret; 466 467 if (!is_c_varname(pf->var)) { 468 /* Output raw parameters */ 469 ret = snprintf(pf->buf, pf->len, " %s", pf->var); 470 DIE_IF(ret < 0); 471 DIE_IF(ret >= pf->len); 472 return ; 473 } 474 475 pr_debug("Searching '%s' variable in context.\n", pf->var); 476 /* Search child die for local variables and parameters. */ 477 ret = search_die_from_children(sp_die, variable_callback, pf); 478 if (!ret) 479 die("Failed to find '%s' in this function.\n", pf->var); 480 } 481 482 /* Get a frame base on the address */ 483 static void get_current_frame_base(Dwarf_Die sp_die, struct probe_finder *pf) 484 { 485 Dwarf_Attribute attr; 486 int ret; 487 488 ret = dwarf_attr(sp_die, DW_AT_frame_base, &attr, &__dw_error); 489 DIE_IF(ret != DW_DLV_OK); 490 ret = attr_get_locdesc(attr, &pf->fbloc, (pf->addr - pf->cu_base)); 491 DIE_IF(ret != DW_DLV_OK); 492 dwarf_dealloc(__dw_debug, attr, DW_DLA_ATTR); 493 } 494 495 static void free_current_frame_base(struct probe_finder *pf) 496 { 497 free(pf->fbloc.ld_s); 498 memset(&pf->fbloc, 0, sizeof(Dwarf_Locdesc)); 499 } 500 501 /* Show a probe point to output buffer */ 502 static void show_probepoint(Dwarf_Die sp_die, Dwarf_Signed offs, 503 struct probe_finder *pf) 504 { 505 struct probe_point *pp = pf->pp; 506 char *name; 507 char tmp[MAX_PROBE_BUFFER]; 508 int ret, i, len; 509 510 /* Output name of probe point */ 511 ret = dwarf_diename(sp_die, &name, &__dw_error); 512 DIE_IF(ret == DW_DLV_ERROR); 513 if (ret == DW_DLV_OK) { 514 ret = snprintf(tmp, MAX_PROBE_BUFFER, "%s+%u", name, 515 (unsigned int)offs); 516 /* Copy the function name if possible */ 517 if (!pp->function) { 518 pp->function = strdup(name); 519 pp->offset = offs; 520 } 521 dwarf_dealloc(__dw_debug, name, DW_DLA_STRING); 522 } else { 523 /* This function has no name. */ 524 ret = snprintf(tmp, MAX_PROBE_BUFFER, "0x%llx", pf->addr); 525 if (!pp->function) { 526 /* TODO: Use _stext */ 527 pp->function = strdup(""); 528 pp->offset = (int)pf->addr; 529 } 530 } 531 DIE_IF(ret < 0); 532 DIE_IF(ret >= MAX_PROBE_BUFFER); 533 len = ret; 534 pr_debug("Probe point found: %s\n", tmp); 535 536 /* Find each argument */ 537 get_current_frame_base(sp_die, pf); 538 for (i = 0; i < pp->nr_args; i++) { 539 pf->var = pp->args[i]; 540 pf->buf = &tmp[len]; 541 pf->len = MAX_PROBE_BUFFER - len; 542 find_variable(sp_die, pf); 543 len += strlen(pf->buf); 544 } 545 free_current_frame_base(pf); 546 547 pp->probes[pp->found] = strdup(tmp); 548 pp->found++; 549 } 550 551 static int probeaddr_callback(struct die_link *dlink, void *data) 552 { 553 struct probe_finder *pf = (struct probe_finder *)data; 554 Dwarf_Half tag; 555 Dwarf_Signed offs; 556 int ret; 557 558 ret = dwarf_tag(dlink->die, &tag, &__dw_error); 559 DIE_IF(ret == DW_DLV_ERROR); 560 /* Check the address is in this subprogram */ 561 if (tag == DW_TAG_subprogram && 562 die_within_subprogram(dlink->die, pf->addr, &offs)) { 563 show_probepoint(dlink->die, offs, pf); 564 return 1; 565 } 566 return 0; 567 } 568 569 /* Find probe point from its line number */ 570 static void find_by_line(struct probe_finder *pf) 571 { 572 Dwarf_Signed cnt, i, clm; 573 Dwarf_Line *lines; 574 Dwarf_Unsigned lineno = 0; 575 Dwarf_Addr addr; 576 Dwarf_Unsigned fno; 577 int ret; 578 579 ret = dwarf_srclines(pf->cu_die, &lines, &cnt, &__dw_error); 580 DIE_IF(ret != DW_DLV_OK); 581 582 for (i = 0; i < cnt; i++) { 583 ret = dwarf_line_srcfileno(lines[i], &fno, &__dw_error); 584 DIE_IF(ret != DW_DLV_OK); 585 if (fno != pf->fno) 586 continue; 587 588 ret = dwarf_lineno(lines[i], &lineno, &__dw_error); 589 DIE_IF(ret != DW_DLV_OK); 590 if (lineno != pf->lno) 591 continue; 592 593 ret = dwarf_lineoff(lines[i], &clm, &__dw_error); 594 DIE_IF(ret != DW_DLV_OK); 595 596 ret = dwarf_lineaddr(lines[i], &addr, &__dw_error); 597 DIE_IF(ret != DW_DLV_OK); 598 pr_debug("Probe line found: line[%d]:%u,%d addr:0x%llx\n", 599 (int)i, (unsigned)lineno, (int)clm, addr); 600 pf->addr = addr; 601 /* Search a real subprogram including this line, */ 602 ret = search_die_from_children(pf->cu_die, 603 probeaddr_callback, pf); 604 if (ret == 0) 605 die("Probe point is not found in subprograms.\n"); 606 /* Continuing, because target line might be inlined. */ 607 } 608 dwarf_srclines_dealloc(__dw_debug, lines, cnt); 609 } 610 611 /* Search function from function name */ 612 static int probefunc_callback(struct die_link *dlink, void *data) 613 { 614 struct probe_finder *pf = (struct probe_finder *)data; 615 struct probe_point *pp = pf->pp; 616 struct die_link *lk; 617 Dwarf_Signed offs; 618 Dwarf_Half tag; 619 int ret; 620 621 ret = dwarf_tag(dlink->die, &tag, &__dw_error); 622 DIE_IF(ret == DW_DLV_ERROR); 623 if (tag == DW_TAG_subprogram) { 624 if (die_compare_name(dlink->die, pp->function) == 0) { 625 if (pp->line) { /* Function relative line */ 626 pf->fno = die_get_decl_file(dlink->die); 627 pf->lno = die_get_decl_line(dlink->die) 628 + pp->line; 629 find_by_line(pf); 630 return 1; 631 } 632 if (die_inlined_subprogram(dlink->die)) { 633 /* Inlined function, save it. */ 634 ret = dwarf_die_CU_offset(dlink->die, 635 &pf->inl_offs, 636 &__dw_error); 637 DIE_IF(ret != DW_DLV_OK); 638 pr_debug("inline definition offset %lld\n", 639 pf->inl_offs); 640 return 0; /* Continue to search */ 641 } 642 /* Get probe address */ 643 pf->addr = die_get_entrypc(dlink->die); 644 pf->addr += pp->offset; 645 /* TODO: Check the address in this function */ 646 show_probepoint(dlink->die, pp->offset, pf); 647 return 1; /* Exit; no same symbol in this CU. */ 648 } 649 } else if (tag == DW_TAG_inlined_subroutine && pf->inl_offs) { 650 if (die_get_abstract_origin(dlink->die) == pf->inl_offs) { 651 /* Get probe address */ 652 pf->addr = die_get_entrypc(dlink->die); 653 pf->addr += pp->offset; 654 pr_debug("found inline addr: 0x%llx\n", pf->addr); 655 /* Inlined function. Get a real subprogram */ 656 for (lk = dlink->parent; lk != NULL; lk = lk->parent) { 657 tag = 0; 658 dwarf_tag(lk->die, &tag, &__dw_error); 659 DIE_IF(ret == DW_DLV_ERROR); 660 if (tag == DW_TAG_subprogram && 661 !die_inlined_subprogram(lk->die)) 662 goto found; 663 } 664 die("Failed to find real subprogram.\n"); 665 found: 666 /* Get offset from subprogram */ 667 ret = die_within_subprogram(lk->die, pf->addr, &offs); 668 DIE_IF(!ret); 669 show_probepoint(lk->die, offs, pf); 670 /* Continue to search */ 671 } 672 } 673 return 0; 674 } 675 676 static void find_by_func(struct probe_finder *pf) 677 { 678 search_die_from_children(pf->cu_die, probefunc_callback, pf); 679 } 680 681 /* Find a probe point */ 682 int find_probepoint(int fd, struct probe_point *pp) 683 { 684 Dwarf_Half addr_size = 0; 685 Dwarf_Unsigned next_cuh = 0; 686 int cu_number = 0, ret; 687 struct probe_finder pf = {.pp = pp}; 688 689 ret = dwarf_init(fd, DW_DLC_READ, 0, 0, &__dw_debug, &__dw_error); 690 if (ret != DW_DLV_OK) 691 return -ENOENT; 692 693 pp->found = 0; 694 while (++cu_number) { 695 /* Search CU (Compilation Unit) */ 696 ret = dwarf_next_cu_header(__dw_debug, NULL, NULL, NULL, 697 &addr_size, &next_cuh, &__dw_error); 698 DIE_IF(ret == DW_DLV_ERROR); 699 if (ret == DW_DLV_NO_ENTRY) 700 break; 701 702 /* Get the DIE(Debugging Information Entry) of this CU */ 703 ret = dwarf_siblingof(__dw_debug, 0, &pf.cu_die, &__dw_error); 704 DIE_IF(ret != DW_DLV_OK); 705 706 /* Check if target file is included. */ 707 if (pp->file) 708 pf.fno = cu_find_fileno(pf.cu_die, pp->file); 709 710 if (!pp->file || pf.fno) { 711 /* Save CU base address (for frame_base) */ 712 ret = dwarf_lowpc(pf.cu_die, &pf.cu_base, &__dw_error); 713 DIE_IF(ret == DW_DLV_ERROR); 714 if (ret == DW_DLV_NO_ENTRY) 715 pf.cu_base = 0; 716 if (pp->function) 717 find_by_func(&pf); 718 else { 719 pf.lno = pp->line; 720 find_by_line(&pf); 721 } 722 } 723 dwarf_dealloc(__dw_debug, pf.cu_die, DW_DLA_DIE); 724 } 725 ret = dwarf_finish(__dw_debug, &__dw_error); 726 DIE_IF(ret != DW_DLV_OK); 727 728 return pp->found; 729 } 730 731