14ea42b18SMasami Hiramatsu /* 24ea42b18SMasami Hiramatsu * probe-finder.c : C expression to kprobe event converter 34ea42b18SMasami Hiramatsu * 44ea42b18SMasami Hiramatsu * Written by Masami Hiramatsu <mhiramat@redhat.com> 54ea42b18SMasami Hiramatsu * 64ea42b18SMasami Hiramatsu * This program is free software; you can redistribute it and/or modify 74ea42b18SMasami Hiramatsu * it under the terms of the GNU General Public License as published by 84ea42b18SMasami Hiramatsu * the Free Software Foundation; either version 2 of the License, or 94ea42b18SMasami Hiramatsu * (at your option) any later version. 104ea42b18SMasami Hiramatsu * 114ea42b18SMasami Hiramatsu * This program is distributed in the hope that it will be useful, 124ea42b18SMasami Hiramatsu * but WITHOUT ANY WARRANTY; without even the implied warranty of 134ea42b18SMasami Hiramatsu * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 144ea42b18SMasami Hiramatsu * GNU General Public License for more details. 154ea42b18SMasami Hiramatsu * 164ea42b18SMasami Hiramatsu * You should have received a copy of the GNU General Public License 174ea42b18SMasami Hiramatsu * along with this program; if not, write to the Free Software 184ea42b18SMasami Hiramatsu * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 194ea42b18SMasami Hiramatsu * 204ea42b18SMasami Hiramatsu */ 214ea42b18SMasami Hiramatsu 224ea42b18SMasami Hiramatsu #include <sys/utsname.h> 234ea42b18SMasami Hiramatsu #include <sys/types.h> 244ea42b18SMasami Hiramatsu #include <sys/stat.h> 254ea42b18SMasami Hiramatsu #include <fcntl.h> 264ea42b18SMasami Hiramatsu #include <errno.h> 274ea42b18SMasami Hiramatsu #include <stdio.h> 284ea42b18SMasami Hiramatsu #include <unistd.h> 294ea42b18SMasami Hiramatsu #include <getopt.h> 304ea42b18SMasami Hiramatsu #include <stdlib.h> 314ea42b18SMasami Hiramatsu #include <string.h> 324ea42b18SMasami Hiramatsu #include <stdarg.h> 334ea42b18SMasami Hiramatsu #include <ctype.h> 34*074fc0e4SMasami Hiramatsu 35*074fc0e4SMasami Hiramatsu #include "util.h" 364ea42b18SMasami Hiramatsu #include "probe-finder.h" 374ea42b18SMasami Hiramatsu 384ea42b18SMasami Hiramatsu 394ea42b18SMasami Hiramatsu /* Dwarf_Die Linkage to parent Die */ 404ea42b18SMasami Hiramatsu struct die_link { 414ea42b18SMasami Hiramatsu struct die_link *parent; /* Parent die */ 424ea42b18SMasami Hiramatsu Dwarf_Die die; /* Current die */ 434ea42b18SMasami Hiramatsu }; 444ea42b18SMasami Hiramatsu 454ea42b18SMasami Hiramatsu static Dwarf_Debug __dw_debug; 464ea42b18SMasami Hiramatsu static Dwarf_Error __dw_error; 474ea42b18SMasami Hiramatsu 484ea42b18SMasami Hiramatsu /* 494ea42b18SMasami Hiramatsu * Generic dwarf analysis helpers 504ea42b18SMasami Hiramatsu */ 514ea42b18SMasami Hiramatsu 524ea42b18SMasami Hiramatsu #define X86_32_MAX_REGS 8 534ea42b18SMasami Hiramatsu const char *x86_32_regs_table[X86_32_MAX_REGS] = { 544ea42b18SMasami Hiramatsu "%ax", 554ea42b18SMasami Hiramatsu "%cx", 564ea42b18SMasami Hiramatsu "%dx", 574ea42b18SMasami Hiramatsu "%bx", 584ea42b18SMasami Hiramatsu "$stack", /* Stack address instead of %sp */ 594ea42b18SMasami Hiramatsu "%bp", 604ea42b18SMasami Hiramatsu "%si", 614ea42b18SMasami Hiramatsu "%di", 624ea42b18SMasami Hiramatsu }; 634ea42b18SMasami Hiramatsu 644ea42b18SMasami Hiramatsu #define X86_64_MAX_REGS 16 654ea42b18SMasami Hiramatsu const char *x86_64_regs_table[X86_64_MAX_REGS] = { 664ea42b18SMasami Hiramatsu "%ax", 674ea42b18SMasami Hiramatsu "%dx", 684ea42b18SMasami Hiramatsu "%cx", 694ea42b18SMasami Hiramatsu "%bx", 704ea42b18SMasami Hiramatsu "%si", 714ea42b18SMasami Hiramatsu "%di", 724ea42b18SMasami Hiramatsu "%bp", 734ea42b18SMasami Hiramatsu "%sp", 744ea42b18SMasami Hiramatsu "%r8", 754ea42b18SMasami Hiramatsu "%r9", 764ea42b18SMasami Hiramatsu "%r10", 774ea42b18SMasami Hiramatsu "%r11", 784ea42b18SMasami Hiramatsu "%r12", 794ea42b18SMasami Hiramatsu "%r13", 804ea42b18SMasami Hiramatsu "%r14", 814ea42b18SMasami Hiramatsu "%r15", 824ea42b18SMasami Hiramatsu }; 834ea42b18SMasami Hiramatsu 844ea42b18SMasami Hiramatsu /* TODO: switching by dwarf address size */ 854ea42b18SMasami Hiramatsu #ifdef __x86_64__ 864ea42b18SMasami Hiramatsu #define ARCH_MAX_REGS X86_64_MAX_REGS 874ea42b18SMasami Hiramatsu #define arch_regs_table x86_64_regs_table 884ea42b18SMasami Hiramatsu #else 894ea42b18SMasami Hiramatsu #define ARCH_MAX_REGS X86_32_MAX_REGS 904ea42b18SMasami Hiramatsu #define arch_regs_table x86_32_regs_table 914ea42b18SMasami Hiramatsu #endif 924ea42b18SMasami Hiramatsu 934ea42b18SMasami Hiramatsu /* Return architecture dependent register string (for kprobe-tracer) */ 944ea42b18SMasami Hiramatsu static const char *get_arch_regstr(unsigned int n) 954ea42b18SMasami Hiramatsu { 964ea42b18SMasami Hiramatsu return (n <= ARCH_MAX_REGS) ? arch_regs_table[n] : NULL; 974ea42b18SMasami Hiramatsu } 984ea42b18SMasami Hiramatsu 994ea42b18SMasami Hiramatsu /* 1004ea42b18SMasami Hiramatsu * Compare the tail of two strings. 1014ea42b18SMasami Hiramatsu * Return 0 if whole of either string is same as another's tail part. 1024ea42b18SMasami Hiramatsu */ 1034ea42b18SMasami Hiramatsu static int strtailcmp(const char *s1, const char *s2) 1044ea42b18SMasami Hiramatsu { 1054ea42b18SMasami Hiramatsu int i1 = strlen(s1); 1064ea42b18SMasami Hiramatsu int i2 = strlen(s2); 1074ea42b18SMasami Hiramatsu while (--i1 > 0 && --i2 > 0) { 1084ea42b18SMasami Hiramatsu if (s1[i1] != s2[i2]) 1094ea42b18SMasami Hiramatsu return s1[i1] - s2[i2]; 1104ea42b18SMasami Hiramatsu } 1114ea42b18SMasami Hiramatsu return 0; 1124ea42b18SMasami Hiramatsu } 1134ea42b18SMasami Hiramatsu 1144ea42b18SMasami Hiramatsu /* Find the fileno of the target file. */ 1154ea42b18SMasami Hiramatsu static Dwarf_Unsigned die_get_fileno(Dwarf_Die cu_die, const char *fname) 1164ea42b18SMasami Hiramatsu { 1174ea42b18SMasami Hiramatsu Dwarf_Signed cnt, i; 1184ea42b18SMasami Hiramatsu Dwarf_Unsigned found = 0; 1194ea42b18SMasami Hiramatsu char **srcs; 1204ea42b18SMasami Hiramatsu int ret; 1214ea42b18SMasami Hiramatsu 1224ea42b18SMasami Hiramatsu if (!fname) 1234ea42b18SMasami Hiramatsu return 0; 1244ea42b18SMasami Hiramatsu 1254ea42b18SMasami Hiramatsu ret = dwarf_srcfiles(cu_die, &srcs, &cnt, &__dw_error); 1264ea42b18SMasami Hiramatsu if (ret == DW_DLV_OK) { 1274ea42b18SMasami Hiramatsu for (i = 0; i < cnt && !found; i++) { 1284ea42b18SMasami Hiramatsu if (strtailcmp(srcs[i], fname) == 0) 1294ea42b18SMasami Hiramatsu found = i + 1; 1304ea42b18SMasami Hiramatsu dwarf_dealloc(__dw_debug, srcs[i], DW_DLA_STRING); 1314ea42b18SMasami Hiramatsu } 1324ea42b18SMasami Hiramatsu for (; i < cnt; i++) 1334ea42b18SMasami Hiramatsu dwarf_dealloc(__dw_debug, srcs[i], DW_DLA_STRING); 1344ea42b18SMasami Hiramatsu dwarf_dealloc(__dw_debug, srcs, DW_DLA_LIST); 1354ea42b18SMasami Hiramatsu } 1364ea42b18SMasami Hiramatsu if (found) 1374ea42b18SMasami Hiramatsu debug("found fno: %d\n", (int)found); 1384ea42b18SMasami Hiramatsu return found; 1394ea42b18SMasami Hiramatsu } 1404ea42b18SMasami Hiramatsu 1414ea42b18SMasami Hiramatsu /* Compare diename and tname */ 142*074fc0e4SMasami Hiramatsu static int die_compare_name(Dwarf_Die dw_die, const char *tname) 1434ea42b18SMasami Hiramatsu { 1444ea42b18SMasami Hiramatsu char *name; 1454ea42b18SMasami Hiramatsu int ret; 146*074fc0e4SMasami Hiramatsu ret = dwarf_diename(dw_die, &name, &__dw_error); 1474ea42b18SMasami Hiramatsu ERR_IF(ret == DW_DLV_ERROR); 1484ea42b18SMasami Hiramatsu if (ret == DW_DLV_OK) { 1494ea42b18SMasami Hiramatsu ret = strcmp(tname, name); 1504ea42b18SMasami Hiramatsu dwarf_dealloc(__dw_debug, name, DW_DLA_STRING); 1514ea42b18SMasami Hiramatsu } else 1524ea42b18SMasami Hiramatsu ret = -1; 1534ea42b18SMasami Hiramatsu return ret; 1544ea42b18SMasami Hiramatsu } 1554ea42b18SMasami Hiramatsu 1564ea42b18SMasami Hiramatsu /* Check the address is in the subprogram(function). */ 1574ea42b18SMasami Hiramatsu static int die_within_subprogram(Dwarf_Die sp_die, Dwarf_Addr addr, 1584ea42b18SMasami Hiramatsu Dwarf_Signed *offs) 1594ea42b18SMasami Hiramatsu { 1604ea42b18SMasami Hiramatsu Dwarf_Addr lopc, hipc; 1614ea42b18SMasami Hiramatsu int ret; 1624ea42b18SMasami Hiramatsu 1634ea42b18SMasami Hiramatsu /* TODO: check ranges */ 1644ea42b18SMasami Hiramatsu ret = dwarf_lowpc(sp_die, &lopc, &__dw_error); 1654ea42b18SMasami Hiramatsu ERR_IF(ret == DW_DLV_ERROR); 1664ea42b18SMasami Hiramatsu if (ret == DW_DLV_NO_ENTRY) 1674ea42b18SMasami Hiramatsu return 0; 1684ea42b18SMasami Hiramatsu ret = dwarf_highpc(sp_die, &hipc, &__dw_error); 1694ea42b18SMasami Hiramatsu ERR_IF(ret != DW_DLV_OK); 1704ea42b18SMasami Hiramatsu if (lopc <= addr && addr < hipc) { 1714ea42b18SMasami Hiramatsu *offs = addr - lopc; 1724ea42b18SMasami Hiramatsu return 1; 1734ea42b18SMasami Hiramatsu } else 1744ea42b18SMasami Hiramatsu return 0; 1754ea42b18SMasami Hiramatsu } 1764ea42b18SMasami Hiramatsu 1774ea42b18SMasami Hiramatsu /* Check the die is inlined function */ 178*074fc0e4SMasami Hiramatsu static Dwarf_Bool die_inlined_subprogram(Dwarf_Die dw_die) 1794ea42b18SMasami Hiramatsu { 1804ea42b18SMasami Hiramatsu /* TODO: check strictly */ 1814ea42b18SMasami Hiramatsu Dwarf_Bool inl; 1824ea42b18SMasami Hiramatsu int ret; 1834ea42b18SMasami Hiramatsu 184*074fc0e4SMasami Hiramatsu ret = dwarf_hasattr(dw_die, DW_AT_inline, &inl, &__dw_error); 1854ea42b18SMasami Hiramatsu ERR_IF(ret == DW_DLV_ERROR); 1864ea42b18SMasami Hiramatsu return inl; 1874ea42b18SMasami Hiramatsu } 1884ea42b18SMasami Hiramatsu 1894ea42b18SMasami Hiramatsu /* Get the offset of abstruct_origin */ 190*074fc0e4SMasami Hiramatsu static Dwarf_Off die_get_abstract_origin(Dwarf_Die dw_die) 1914ea42b18SMasami Hiramatsu { 1924ea42b18SMasami Hiramatsu Dwarf_Attribute attr; 1934ea42b18SMasami Hiramatsu Dwarf_Off cu_offs; 1944ea42b18SMasami Hiramatsu int ret; 1954ea42b18SMasami Hiramatsu 196*074fc0e4SMasami Hiramatsu ret = dwarf_attr(dw_die, DW_AT_abstract_origin, &attr, &__dw_error); 1974ea42b18SMasami Hiramatsu ERR_IF(ret != DW_DLV_OK); 1984ea42b18SMasami Hiramatsu ret = dwarf_formref(attr, &cu_offs, &__dw_error); 1994ea42b18SMasami Hiramatsu ERR_IF(ret != DW_DLV_OK); 2004ea42b18SMasami Hiramatsu dwarf_dealloc(__dw_debug, attr, DW_DLA_ATTR); 2014ea42b18SMasami Hiramatsu return cu_offs; 2024ea42b18SMasami Hiramatsu } 2034ea42b18SMasami Hiramatsu 2044ea42b18SMasami Hiramatsu /* Get entry pc(or low pc, 1st entry of ranges) of the die */ 205*074fc0e4SMasami Hiramatsu static Dwarf_Addr die_get_entrypc(Dwarf_Die dw_die) 2064ea42b18SMasami Hiramatsu { 2074ea42b18SMasami Hiramatsu Dwarf_Attribute attr; 2084ea42b18SMasami Hiramatsu Dwarf_Addr addr; 2094ea42b18SMasami Hiramatsu Dwarf_Off offs; 2104ea42b18SMasami Hiramatsu Dwarf_Ranges *ranges; 2114ea42b18SMasami Hiramatsu Dwarf_Signed cnt; 2124ea42b18SMasami Hiramatsu int ret; 2134ea42b18SMasami Hiramatsu 2144ea42b18SMasami Hiramatsu /* Try to get entry pc */ 215*074fc0e4SMasami Hiramatsu ret = dwarf_attr(dw_die, DW_AT_entry_pc, &attr, &__dw_error); 2164ea42b18SMasami Hiramatsu ERR_IF(ret == DW_DLV_ERROR); 2174ea42b18SMasami Hiramatsu if (ret == DW_DLV_OK) { 2184ea42b18SMasami Hiramatsu ret = dwarf_formaddr(attr, &addr, &__dw_error); 2194ea42b18SMasami Hiramatsu ERR_IF(ret != DW_DLV_OK); 2204ea42b18SMasami Hiramatsu dwarf_dealloc(__dw_debug, attr, DW_DLA_ATTR); 2214ea42b18SMasami Hiramatsu return addr; 2224ea42b18SMasami Hiramatsu } 2234ea42b18SMasami Hiramatsu 2244ea42b18SMasami Hiramatsu /* Try to get low pc */ 225*074fc0e4SMasami Hiramatsu ret = dwarf_lowpc(dw_die, &addr, &__dw_error); 2264ea42b18SMasami Hiramatsu ERR_IF(ret == DW_DLV_ERROR); 2274ea42b18SMasami Hiramatsu if (ret == DW_DLV_OK) 2284ea42b18SMasami Hiramatsu return addr; 2294ea42b18SMasami Hiramatsu 2304ea42b18SMasami Hiramatsu /* Try to get ranges */ 231*074fc0e4SMasami Hiramatsu ret = dwarf_attr(dw_die, DW_AT_ranges, &attr, &__dw_error); 2324ea42b18SMasami Hiramatsu ERR_IF(ret != DW_DLV_OK); 2334ea42b18SMasami Hiramatsu ret = dwarf_formref(attr, &offs, &__dw_error); 2344ea42b18SMasami Hiramatsu ERR_IF(ret != DW_DLV_OK); 2354ea42b18SMasami Hiramatsu ret = dwarf_get_ranges(__dw_debug, offs, &ranges, &cnt, NULL, 2364ea42b18SMasami Hiramatsu &__dw_error); 2374ea42b18SMasami Hiramatsu ERR_IF(ret != DW_DLV_OK); 2384ea42b18SMasami Hiramatsu addr = ranges[0].dwr_addr1; 2394ea42b18SMasami Hiramatsu dwarf_ranges_dealloc(__dw_debug, ranges, cnt); 2404ea42b18SMasami Hiramatsu return addr; 2414ea42b18SMasami Hiramatsu } 2424ea42b18SMasami Hiramatsu 2434ea42b18SMasami Hiramatsu /* 2444ea42b18SMasami Hiramatsu * Search a Die from Die tree. 2454ea42b18SMasami Hiramatsu * Note: cur_link->die should be deallocated in this function. 2464ea42b18SMasami Hiramatsu */ 2474ea42b18SMasami Hiramatsu static int __search_die_tree(struct die_link *cur_link, 2484ea42b18SMasami Hiramatsu int (*die_cb)(struct die_link *, void *), 2494ea42b18SMasami Hiramatsu void *data) 2504ea42b18SMasami Hiramatsu { 2514ea42b18SMasami Hiramatsu Dwarf_Die new_die; 2524ea42b18SMasami Hiramatsu struct die_link new_link; 2534ea42b18SMasami Hiramatsu int ret; 2544ea42b18SMasami Hiramatsu 2554ea42b18SMasami Hiramatsu if (!die_cb) 2564ea42b18SMasami Hiramatsu return 0; 2574ea42b18SMasami Hiramatsu 2584ea42b18SMasami Hiramatsu /* Check current die */ 2594ea42b18SMasami Hiramatsu while (!(ret = die_cb(cur_link, data))) { 2604ea42b18SMasami Hiramatsu /* Check child die */ 2614ea42b18SMasami Hiramatsu ret = dwarf_child(cur_link->die, &new_die, &__dw_error); 2624ea42b18SMasami Hiramatsu ERR_IF(ret == DW_DLV_ERROR); 2634ea42b18SMasami Hiramatsu if (ret == DW_DLV_OK) { 2644ea42b18SMasami Hiramatsu new_link.parent = cur_link; 2654ea42b18SMasami Hiramatsu new_link.die = new_die; 2664ea42b18SMasami Hiramatsu ret = __search_die_tree(&new_link, die_cb, data); 2674ea42b18SMasami Hiramatsu if (ret) 2684ea42b18SMasami Hiramatsu break; 2694ea42b18SMasami Hiramatsu } 2704ea42b18SMasami Hiramatsu 2714ea42b18SMasami Hiramatsu /* Move to next sibling */ 2724ea42b18SMasami Hiramatsu ret = dwarf_siblingof(__dw_debug, cur_link->die, &new_die, 2734ea42b18SMasami Hiramatsu &__dw_error); 2744ea42b18SMasami Hiramatsu ERR_IF(ret == DW_DLV_ERROR); 2754ea42b18SMasami Hiramatsu dwarf_dealloc(__dw_debug, cur_link->die, DW_DLA_DIE); 2764ea42b18SMasami Hiramatsu cur_link->die = new_die; 2774ea42b18SMasami Hiramatsu if (ret == DW_DLV_NO_ENTRY) 2784ea42b18SMasami Hiramatsu return 0; 2794ea42b18SMasami Hiramatsu } 2804ea42b18SMasami Hiramatsu dwarf_dealloc(__dw_debug, cur_link->die, DW_DLA_DIE); 2814ea42b18SMasami Hiramatsu return ret; 2824ea42b18SMasami Hiramatsu } 2834ea42b18SMasami Hiramatsu 2844ea42b18SMasami Hiramatsu /* Search a die in its children's die tree */ 2854ea42b18SMasami Hiramatsu static int search_die_from_children(Dwarf_Die parent_die, 2864ea42b18SMasami Hiramatsu int (*die_cb)(struct die_link *, void *), 2874ea42b18SMasami Hiramatsu void *data) 2884ea42b18SMasami Hiramatsu { 2894ea42b18SMasami Hiramatsu struct die_link new_link; 2904ea42b18SMasami Hiramatsu int ret; 2914ea42b18SMasami Hiramatsu 2924ea42b18SMasami Hiramatsu new_link.parent = NULL; 2934ea42b18SMasami Hiramatsu ret = dwarf_child(parent_die, &new_link.die, &__dw_error); 2944ea42b18SMasami Hiramatsu ERR_IF(ret == DW_DLV_ERROR); 2954ea42b18SMasami Hiramatsu if (ret == DW_DLV_OK) 2964ea42b18SMasami Hiramatsu return __search_die_tree(&new_link, die_cb, data); 2974ea42b18SMasami Hiramatsu else 2984ea42b18SMasami Hiramatsu return 0; 2994ea42b18SMasami Hiramatsu } 3004ea42b18SMasami Hiramatsu 3014ea42b18SMasami Hiramatsu /* Find a locdesc corresponding to the address */ 3024ea42b18SMasami Hiramatsu static int attr_get_locdesc(Dwarf_Attribute attr, Dwarf_Locdesc *desc, 3034ea42b18SMasami Hiramatsu Dwarf_Addr addr) 3044ea42b18SMasami Hiramatsu { 3054ea42b18SMasami Hiramatsu Dwarf_Signed lcnt; 3064ea42b18SMasami Hiramatsu Dwarf_Locdesc **llbuf; 3074ea42b18SMasami Hiramatsu int ret, i; 3084ea42b18SMasami Hiramatsu 3094ea42b18SMasami Hiramatsu ret = dwarf_loclist_n(attr, &llbuf, &lcnt, &__dw_error); 3104ea42b18SMasami Hiramatsu ERR_IF(ret != DW_DLV_OK); 3114ea42b18SMasami Hiramatsu ret = DW_DLV_NO_ENTRY; 3124ea42b18SMasami Hiramatsu for (i = 0; i < lcnt; ++i) { 3134ea42b18SMasami Hiramatsu if (llbuf[i]->ld_lopc <= addr && 3144ea42b18SMasami Hiramatsu llbuf[i]->ld_hipc > addr) { 3154ea42b18SMasami Hiramatsu memcpy(desc, llbuf[i], sizeof(Dwarf_Locdesc)); 3164ea42b18SMasami Hiramatsu desc->ld_s = 3174ea42b18SMasami Hiramatsu malloc(sizeof(Dwarf_Loc) * llbuf[i]->ld_cents); 3184ea42b18SMasami Hiramatsu ERR_IF(desc->ld_s == NULL); 3194ea42b18SMasami Hiramatsu memcpy(desc->ld_s, llbuf[i]->ld_s, 3204ea42b18SMasami Hiramatsu sizeof(Dwarf_Loc) * llbuf[i]->ld_cents); 3214ea42b18SMasami Hiramatsu ret = DW_DLV_OK; 3224ea42b18SMasami Hiramatsu break; 3234ea42b18SMasami Hiramatsu } 3244ea42b18SMasami Hiramatsu dwarf_dealloc(__dw_debug, llbuf[i]->ld_s, DW_DLA_LOC_BLOCK); 3254ea42b18SMasami Hiramatsu dwarf_dealloc(__dw_debug, llbuf[i], DW_DLA_LOCDESC); 3264ea42b18SMasami Hiramatsu } 3274ea42b18SMasami Hiramatsu /* Releasing loop */ 3284ea42b18SMasami Hiramatsu for (; i < lcnt; ++i) { 3294ea42b18SMasami Hiramatsu dwarf_dealloc(__dw_debug, llbuf[i]->ld_s, DW_DLA_LOC_BLOCK); 3304ea42b18SMasami Hiramatsu dwarf_dealloc(__dw_debug, llbuf[i], DW_DLA_LOCDESC); 3314ea42b18SMasami Hiramatsu } 3324ea42b18SMasami Hiramatsu dwarf_dealloc(__dw_debug, llbuf, DW_DLA_LIST); 3334ea42b18SMasami Hiramatsu return ret; 3344ea42b18SMasami Hiramatsu } 3354ea42b18SMasami Hiramatsu 3364ea42b18SMasami Hiramatsu /* 3374ea42b18SMasami Hiramatsu * Probe finder related functions 3384ea42b18SMasami Hiramatsu */ 3394ea42b18SMasami Hiramatsu 3404ea42b18SMasami Hiramatsu /* Show a location */ 3414ea42b18SMasami Hiramatsu static void show_location(Dwarf_Loc *loc, struct probe_finder *pf) 3424ea42b18SMasami Hiramatsu { 3434ea42b18SMasami Hiramatsu Dwarf_Small op; 3444ea42b18SMasami Hiramatsu Dwarf_Unsigned regn; 3454ea42b18SMasami Hiramatsu Dwarf_Signed offs; 3464ea42b18SMasami Hiramatsu int deref = 0, ret; 3474ea42b18SMasami Hiramatsu const char *regs; 3484ea42b18SMasami Hiramatsu 3494ea42b18SMasami Hiramatsu op = loc->lr_atom; 3504ea42b18SMasami Hiramatsu 3514ea42b18SMasami Hiramatsu /* If this is based on frame buffer, set the offset */ 3524ea42b18SMasami Hiramatsu if (op == DW_OP_fbreg) { 3534ea42b18SMasami Hiramatsu deref = 1; 3544ea42b18SMasami Hiramatsu offs = (Dwarf_Signed)loc->lr_number; 3554ea42b18SMasami Hiramatsu op = pf->fbloc.ld_s[0].lr_atom; 3564ea42b18SMasami Hiramatsu loc = &pf->fbloc.ld_s[0]; 3574ea42b18SMasami Hiramatsu } else 3584ea42b18SMasami Hiramatsu offs = 0; 3594ea42b18SMasami Hiramatsu 3604ea42b18SMasami Hiramatsu if (op >= DW_OP_breg0 && op <= DW_OP_breg31) { 3614ea42b18SMasami Hiramatsu regn = op - DW_OP_breg0; 3624ea42b18SMasami Hiramatsu offs += (Dwarf_Signed)loc->lr_number; 3634ea42b18SMasami Hiramatsu deref = 1; 3644ea42b18SMasami Hiramatsu } else if (op >= DW_OP_reg0 && op <= DW_OP_reg31) { 3654ea42b18SMasami Hiramatsu regn = op - DW_OP_reg0; 3664ea42b18SMasami Hiramatsu } else if (op == DW_OP_bregx) { 3674ea42b18SMasami Hiramatsu regn = loc->lr_number; 3684ea42b18SMasami Hiramatsu offs += (Dwarf_Signed)loc->lr_number2; 3694ea42b18SMasami Hiramatsu deref = 1; 3704ea42b18SMasami Hiramatsu } else if (op == DW_OP_regx) { 3714ea42b18SMasami Hiramatsu regn = loc->lr_number; 3724ea42b18SMasami Hiramatsu } else 373*074fc0e4SMasami Hiramatsu die("Dwarf_OP %d is not supported.\n", op); 3744ea42b18SMasami Hiramatsu 3754ea42b18SMasami Hiramatsu regs = get_arch_regstr(regn); 3764ea42b18SMasami Hiramatsu if (!regs) 377*074fc0e4SMasami Hiramatsu die("%lld exceeds max register number.\n", regn); 3784ea42b18SMasami Hiramatsu 3794ea42b18SMasami Hiramatsu if (deref) 3804ea42b18SMasami Hiramatsu ret = snprintf(pf->buf, pf->len, 3814ea42b18SMasami Hiramatsu " %s=%+lld(%s)", pf->var, offs, regs); 3824ea42b18SMasami Hiramatsu else 3834ea42b18SMasami Hiramatsu ret = snprintf(pf->buf, pf->len, " %s=%s", pf->var, regs); 3844ea42b18SMasami Hiramatsu ERR_IF(ret < 0); 3854ea42b18SMasami Hiramatsu ERR_IF(ret >= pf->len); 3864ea42b18SMasami Hiramatsu } 3874ea42b18SMasami Hiramatsu 3884ea42b18SMasami Hiramatsu /* Show a variables in kprobe event format */ 3894ea42b18SMasami Hiramatsu static void show_variable(Dwarf_Die vr_die, struct probe_finder *pf) 3904ea42b18SMasami Hiramatsu { 3914ea42b18SMasami Hiramatsu Dwarf_Attribute attr; 3924ea42b18SMasami Hiramatsu Dwarf_Locdesc ld; 3934ea42b18SMasami Hiramatsu int ret; 3944ea42b18SMasami Hiramatsu 3954ea42b18SMasami Hiramatsu ret = dwarf_attr(vr_die, DW_AT_location, &attr, &__dw_error); 3964ea42b18SMasami Hiramatsu if (ret != DW_DLV_OK) 3974ea42b18SMasami Hiramatsu goto error; 3984ea42b18SMasami Hiramatsu ret = attr_get_locdesc(attr, &ld, (pf->addr - pf->cu_base)); 3994ea42b18SMasami Hiramatsu if (ret != DW_DLV_OK) 4004ea42b18SMasami Hiramatsu goto error; 4014ea42b18SMasami Hiramatsu /* TODO? */ 4024ea42b18SMasami Hiramatsu ERR_IF(ld.ld_cents != 1); 4034ea42b18SMasami Hiramatsu show_location(&ld.ld_s[0], pf); 4044ea42b18SMasami Hiramatsu free(ld.ld_s); 4054ea42b18SMasami Hiramatsu dwarf_dealloc(__dw_debug, attr, DW_DLA_ATTR); 4064ea42b18SMasami Hiramatsu return ; 4074ea42b18SMasami Hiramatsu error: 408*074fc0e4SMasami Hiramatsu die("Failed to find the location of %s at this address.\n" 409*074fc0e4SMasami Hiramatsu " Perhaps, it has been optimized out.\n", pf->var); 4104ea42b18SMasami Hiramatsu } 4114ea42b18SMasami Hiramatsu 4124ea42b18SMasami Hiramatsu static int variable_callback(struct die_link *dlink, void *data) 4134ea42b18SMasami Hiramatsu { 4144ea42b18SMasami Hiramatsu struct probe_finder *pf = (struct probe_finder *)data; 4154ea42b18SMasami Hiramatsu Dwarf_Half tag; 4164ea42b18SMasami Hiramatsu int ret; 4174ea42b18SMasami Hiramatsu 4184ea42b18SMasami Hiramatsu ret = dwarf_tag(dlink->die, &tag, &__dw_error); 4194ea42b18SMasami Hiramatsu ERR_IF(ret == DW_DLV_ERROR); 4204ea42b18SMasami Hiramatsu if ((tag == DW_TAG_formal_parameter || 4214ea42b18SMasami Hiramatsu tag == DW_TAG_variable) && 4224ea42b18SMasami Hiramatsu (die_compare_name(dlink->die, pf->var) == 0)) { 4234ea42b18SMasami Hiramatsu show_variable(dlink->die, pf); 4244ea42b18SMasami Hiramatsu return 1; 4254ea42b18SMasami Hiramatsu } 4264ea42b18SMasami Hiramatsu /* TODO: Support struct members and arrays */ 4274ea42b18SMasami Hiramatsu return 0; 4284ea42b18SMasami Hiramatsu } 4294ea42b18SMasami Hiramatsu 4304ea42b18SMasami Hiramatsu /* Find a variable in a subprogram die */ 4314ea42b18SMasami Hiramatsu static void find_variable(Dwarf_Die sp_die, struct probe_finder *pf) 4324ea42b18SMasami Hiramatsu { 4334ea42b18SMasami Hiramatsu int ret; 4344ea42b18SMasami Hiramatsu 4354ea42b18SMasami Hiramatsu if (!is_c_varname(pf->var)) { 4364ea42b18SMasami Hiramatsu /* Output raw parameters */ 4374ea42b18SMasami Hiramatsu ret = snprintf(pf->buf, pf->len, " %s", pf->var); 4384ea42b18SMasami Hiramatsu ERR_IF(ret < 0); 4394ea42b18SMasami Hiramatsu ERR_IF(ret >= pf->len); 4404ea42b18SMasami Hiramatsu return ; 4414ea42b18SMasami Hiramatsu } 4424ea42b18SMasami Hiramatsu 4434ea42b18SMasami Hiramatsu debug("Searching '%s' variable in context.\n", pf->var); 4444ea42b18SMasami Hiramatsu /* Search child die for local variables and parameters. */ 4454ea42b18SMasami Hiramatsu ret = search_die_from_children(sp_die, variable_callback, pf); 4464ea42b18SMasami Hiramatsu if (!ret) 447*074fc0e4SMasami Hiramatsu die("Failed to find '%s' in this function.\n", pf->var); 4484ea42b18SMasami Hiramatsu } 4494ea42b18SMasami Hiramatsu 4504ea42b18SMasami Hiramatsu /* Get a frame base on the address */ 4514ea42b18SMasami Hiramatsu static void get_current_frame_base(Dwarf_Die sp_die, struct probe_finder *pf) 4524ea42b18SMasami Hiramatsu { 4534ea42b18SMasami Hiramatsu Dwarf_Attribute attr; 4544ea42b18SMasami Hiramatsu int ret; 4554ea42b18SMasami Hiramatsu 4564ea42b18SMasami Hiramatsu ret = dwarf_attr(sp_die, DW_AT_frame_base, &attr, &__dw_error); 4574ea42b18SMasami Hiramatsu ERR_IF(ret != DW_DLV_OK); 4584ea42b18SMasami Hiramatsu ret = attr_get_locdesc(attr, &pf->fbloc, (pf->addr - pf->cu_base)); 4594ea42b18SMasami Hiramatsu ERR_IF(ret != DW_DLV_OK); 4604ea42b18SMasami Hiramatsu dwarf_dealloc(__dw_debug, attr, DW_DLA_ATTR); 4614ea42b18SMasami Hiramatsu } 4624ea42b18SMasami Hiramatsu 4634ea42b18SMasami Hiramatsu static void free_current_frame_base(struct probe_finder *pf) 4644ea42b18SMasami Hiramatsu { 4654ea42b18SMasami Hiramatsu free(pf->fbloc.ld_s); 4664ea42b18SMasami Hiramatsu memset(&pf->fbloc, 0, sizeof(Dwarf_Locdesc)); 4674ea42b18SMasami Hiramatsu } 4684ea42b18SMasami Hiramatsu 4694ea42b18SMasami Hiramatsu /* Show a probe point to output buffer */ 4704ea42b18SMasami Hiramatsu static void show_probepoint(Dwarf_Die sp_die, Dwarf_Signed offs, 4714ea42b18SMasami Hiramatsu struct probe_finder *pf) 4724ea42b18SMasami Hiramatsu { 4734ea42b18SMasami Hiramatsu struct probe_point *pp = pf->pp; 4744ea42b18SMasami Hiramatsu char *name; 4754ea42b18SMasami Hiramatsu char tmp[MAX_PROBE_BUFFER]; 4764ea42b18SMasami Hiramatsu int ret, i, len; 4774ea42b18SMasami Hiramatsu 4784ea42b18SMasami Hiramatsu /* Output name of probe point */ 4794ea42b18SMasami Hiramatsu ret = dwarf_diename(sp_die, &name, &__dw_error); 4804ea42b18SMasami Hiramatsu ERR_IF(ret == DW_DLV_ERROR); 4814ea42b18SMasami Hiramatsu if (ret == DW_DLV_OK) { 4824ea42b18SMasami Hiramatsu ret = snprintf(tmp, MAX_PROBE_BUFFER, "%s+%u", name, 4834ea42b18SMasami Hiramatsu (unsigned int)offs); 4844ea42b18SMasami Hiramatsu dwarf_dealloc(__dw_debug, name, DW_DLA_STRING); 4854ea42b18SMasami Hiramatsu } else { 4864ea42b18SMasami Hiramatsu /* This function has no name. */ 4874ea42b18SMasami Hiramatsu ret = snprintf(tmp, MAX_PROBE_BUFFER, "0x%llx", pf->addr); 4884ea42b18SMasami Hiramatsu } 4894ea42b18SMasami Hiramatsu ERR_IF(ret < 0); 4904ea42b18SMasami Hiramatsu ERR_IF(ret >= MAX_PROBE_BUFFER); 4914ea42b18SMasami Hiramatsu len = ret; 4924ea42b18SMasami Hiramatsu 4934ea42b18SMasami Hiramatsu /* Find each argument */ 4944ea42b18SMasami Hiramatsu get_current_frame_base(sp_die, pf); 4954ea42b18SMasami Hiramatsu for (i = 0; i < pp->nr_args; i++) { 4964ea42b18SMasami Hiramatsu pf->var = pp->args[i]; 4974ea42b18SMasami Hiramatsu pf->buf = &tmp[len]; 4984ea42b18SMasami Hiramatsu pf->len = MAX_PROBE_BUFFER - len; 4994ea42b18SMasami Hiramatsu find_variable(sp_die, pf); 5004ea42b18SMasami Hiramatsu len += strlen(pf->buf); 5014ea42b18SMasami Hiramatsu } 5024ea42b18SMasami Hiramatsu free_current_frame_base(pf); 5034ea42b18SMasami Hiramatsu 5044ea42b18SMasami Hiramatsu pp->probes[pp->found] = strdup(tmp); 5054ea42b18SMasami Hiramatsu pp->found++; 5064ea42b18SMasami Hiramatsu } 5074ea42b18SMasami Hiramatsu 5084ea42b18SMasami Hiramatsu static int probeaddr_callback(struct die_link *dlink, void *data) 5094ea42b18SMasami Hiramatsu { 5104ea42b18SMasami Hiramatsu struct probe_finder *pf = (struct probe_finder *)data; 5114ea42b18SMasami Hiramatsu Dwarf_Half tag; 5124ea42b18SMasami Hiramatsu Dwarf_Signed offs; 5134ea42b18SMasami Hiramatsu int ret; 5144ea42b18SMasami Hiramatsu 5154ea42b18SMasami Hiramatsu ret = dwarf_tag(dlink->die, &tag, &__dw_error); 5164ea42b18SMasami Hiramatsu ERR_IF(ret == DW_DLV_ERROR); 5174ea42b18SMasami Hiramatsu /* Check the address is in this subprogram */ 5184ea42b18SMasami Hiramatsu if (tag == DW_TAG_subprogram && 5194ea42b18SMasami Hiramatsu die_within_subprogram(dlink->die, pf->addr, &offs)) { 5204ea42b18SMasami Hiramatsu show_probepoint(dlink->die, offs, pf); 5214ea42b18SMasami Hiramatsu return 1; 5224ea42b18SMasami Hiramatsu } 5234ea42b18SMasami Hiramatsu return 0; 5244ea42b18SMasami Hiramatsu } 5254ea42b18SMasami Hiramatsu 5264ea42b18SMasami Hiramatsu /* Find probe point from its line number */ 5274ea42b18SMasami Hiramatsu static void find_by_line(Dwarf_Die cu_die, struct probe_finder *pf) 5284ea42b18SMasami Hiramatsu { 5294ea42b18SMasami Hiramatsu struct probe_point *pp = pf->pp; 5304ea42b18SMasami Hiramatsu Dwarf_Signed cnt, i; 5314ea42b18SMasami Hiramatsu Dwarf_Line *lines; 5324ea42b18SMasami Hiramatsu Dwarf_Unsigned lineno = 0; 5334ea42b18SMasami Hiramatsu Dwarf_Addr addr; 5344ea42b18SMasami Hiramatsu Dwarf_Unsigned fno; 5354ea42b18SMasami Hiramatsu int ret; 5364ea42b18SMasami Hiramatsu 5374ea42b18SMasami Hiramatsu ret = dwarf_srclines(cu_die, &lines, &cnt, &__dw_error); 5384ea42b18SMasami Hiramatsu ERR_IF(ret != DW_DLV_OK); 5394ea42b18SMasami Hiramatsu 5404ea42b18SMasami Hiramatsu for (i = 0; i < cnt; i++) { 5414ea42b18SMasami Hiramatsu ret = dwarf_line_srcfileno(lines[i], &fno, &__dw_error); 5424ea42b18SMasami Hiramatsu ERR_IF(ret != DW_DLV_OK); 5434ea42b18SMasami Hiramatsu if (fno != pf->fno) 5444ea42b18SMasami Hiramatsu continue; 5454ea42b18SMasami Hiramatsu 5464ea42b18SMasami Hiramatsu ret = dwarf_lineno(lines[i], &lineno, &__dw_error); 5474ea42b18SMasami Hiramatsu ERR_IF(ret != DW_DLV_OK); 5484ea42b18SMasami Hiramatsu if (lineno != (Dwarf_Unsigned)pp->line) 5494ea42b18SMasami Hiramatsu continue; 5504ea42b18SMasami Hiramatsu 5514ea42b18SMasami Hiramatsu ret = dwarf_lineaddr(lines[i], &addr, &__dw_error); 5524ea42b18SMasami Hiramatsu ERR_IF(ret != DW_DLV_OK); 5534ea42b18SMasami Hiramatsu debug("Probe point found: 0x%llx\n", addr); 5544ea42b18SMasami Hiramatsu pf->addr = addr; 5554ea42b18SMasami Hiramatsu /* Search a real subprogram including this line, */ 5564ea42b18SMasami Hiramatsu ret = search_die_from_children(cu_die, probeaddr_callback, pf); 5574ea42b18SMasami Hiramatsu if (ret == 0) 558*074fc0e4SMasami Hiramatsu die("Probe point is not found in subprograms.\n"); 5594ea42b18SMasami Hiramatsu /* Continuing, because target line might be inlined. */ 5604ea42b18SMasami Hiramatsu } 5614ea42b18SMasami Hiramatsu dwarf_srclines_dealloc(__dw_debug, lines, cnt); 5624ea42b18SMasami Hiramatsu } 5634ea42b18SMasami Hiramatsu 5644ea42b18SMasami Hiramatsu /* Search function from function name */ 5654ea42b18SMasami Hiramatsu static int probefunc_callback(struct die_link *dlink, void *data) 5664ea42b18SMasami Hiramatsu { 5674ea42b18SMasami Hiramatsu struct probe_finder *pf = (struct probe_finder *)data; 5684ea42b18SMasami Hiramatsu struct probe_point *pp = pf->pp; 5694ea42b18SMasami Hiramatsu struct die_link *lk; 5704ea42b18SMasami Hiramatsu Dwarf_Signed offs; 5714ea42b18SMasami Hiramatsu Dwarf_Half tag; 5724ea42b18SMasami Hiramatsu int ret; 5734ea42b18SMasami Hiramatsu 5744ea42b18SMasami Hiramatsu ret = dwarf_tag(dlink->die, &tag, &__dw_error); 5754ea42b18SMasami Hiramatsu ERR_IF(ret == DW_DLV_ERROR); 5764ea42b18SMasami Hiramatsu if (tag == DW_TAG_subprogram) { 5774ea42b18SMasami Hiramatsu if (die_compare_name(dlink->die, pp->function) == 0) { 5784ea42b18SMasami Hiramatsu if (die_inlined_subprogram(dlink->die)) { 5794ea42b18SMasami Hiramatsu /* Inlined function, save it. */ 5804ea42b18SMasami Hiramatsu ret = dwarf_die_CU_offset(dlink->die, 5814ea42b18SMasami Hiramatsu &pf->inl_offs, 5824ea42b18SMasami Hiramatsu &__dw_error); 5834ea42b18SMasami Hiramatsu ERR_IF(ret != DW_DLV_OK); 5844ea42b18SMasami Hiramatsu debug("inline definition offset %lld\n", 5854ea42b18SMasami Hiramatsu pf->inl_offs); 5864ea42b18SMasami Hiramatsu return 0; 5874ea42b18SMasami Hiramatsu } 5884ea42b18SMasami Hiramatsu /* Get probe address */ 5894ea42b18SMasami Hiramatsu pf->addr = die_get_entrypc(dlink->die); 5904ea42b18SMasami Hiramatsu pf->addr += pp->offset; 5914ea42b18SMasami Hiramatsu /* TODO: Check the address in this function */ 5924ea42b18SMasami Hiramatsu show_probepoint(dlink->die, pp->offset, pf); 5934ea42b18SMasami Hiramatsu /* Continue to search */ 5944ea42b18SMasami Hiramatsu } 5954ea42b18SMasami Hiramatsu } else if (tag == DW_TAG_inlined_subroutine && pf->inl_offs) { 5964ea42b18SMasami Hiramatsu if (die_get_abstract_origin(dlink->die) == pf->inl_offs) { 5974ea42b18SMasami Hiramatsu /* Get probe address */ 5984ea42b18SMasami Hiramatsu pf->addr = die_get_entrypc(dlink->die); 5994ea42b18SMasami Hiramatsu pf->addr += pp->offset; 6004ea42b18SMasami Hiramatsu debug("found inline addr: 0x%llx\n", pf->addr); 6014ea42b18SMasami Hiramatsu /* Inlined function. Get a real subprogram */ 6024ea42b18SMasami Hiramatsu for (lk = dlink->parent; lk != NULL; lk = lk->parent) { 6034ea42b18SMasami Hiramatsu tag = 0; 6044ea42b18SMasami Hiramatsu dwarf_tag(lk->die, &tag, &__dw_error); 6054ea42b18SMasami Hiramatsu ERR_IF(ret == DW_DLV_ERROR); 6064ea42b18SMasami Hiramatsu if (tag == DW_TAG_subprogram && 6074ea42b18SMasami Hiramatsu !die_inlined_subprogram(lk->die)) 6084ea42b18SMasami Hiramatsu goto found; 6094ea42b18SMasami Hiramatsu } 610*074fc0e4SMasami Hiramatsu die("Failed to find real subprogram.\n"); 6114ea42b18SMasami Hiramatsu found: 6124ea42b18SMasami Hiramatsu /* Get offset from subprogram */ 6134ea42b18SMasami Hiramatsu ret = die_within_subprogram(lk->die, pf->addr, &offs); 6144ea42b18SMasami Hiramatsu ERR_IF(!ret); 6154ea42b18SMasami Hiramatsu show_probepoint(lk->die, offs, pf); 6164ea42b18SMasami Hiramatsu /* Continue to search */ 6174ea42b18SMasami Hiramatsu } 6184ea42b18SMasami Hiramatsu } 6194ea42b18SMasami Hiramatsu return 0; 6204ea42b18SMasami Hiramatsu } 6214ea42b18SMasami Hiramatsu 6224ea42b18SMasami Hiramatsu static void find_by_func(Dwarf_Die cu_die, struct probe_finder *pf) 6234ea42b18SMasami Hiramatsu { 6244ea42b18SMasami Hiramatsu search_die_from_children(cu_die, probefunc_callback, pf); 6254ea42b18SMasami Hiramatsu } 6264ea42b18SMasami Hiramatsu 6274ea42b18SMasami Hiramatsu /* Find a probe point */ 6284ea42b18SMasami Hiramatsu int find_probepoint(int fd, struct probe_point *pp) 6294ea42b18SMasami Hiramatsu { 6304ea42b18SMasami Hiramatsu Dwarf_Half addr_size = 0; 6314ea42b18SMasami Hiramatsu Dwarf_Unsigned next_cuh = 0; 6324ea42b18SMasami Hiramatsu Dwarf_Die cu_die = 0; 6334ea42b18SMasami Hiramatsu int cu_number = 0, ret; 6344ea42b18SMasami Hiramatsu struct probe_finder pf = {.pp = pp}; 6354ea42b18SMasami Hiramatsu 6364ea42b18SMasami Hiramatsu ret = dwarf_init(fd, DW_DLC_READ, 0, 0, &__dw_debug, &__dw_error); 6374ea42b18SMasami Hiramatsu if (ret != DW_DLV_OK) 638*074fc0e4SMasami Hiramatsu die("Failed to call dwarf_init(). Maybe, not a dwarf file.\n"); 6394ea42b18SMasami Hiramatsu 6404ea42b18SMasami Hiramatsu pp->found = 0; 6414ea42b18SMasami Hiramatsu while (++cu_number) { 6424ea42b18SMasami Hiramatsu /* Search CU (Compilation Unit) */ 6434ea42b18SMasami Hiramatsu ret = dwarf_next_cu_header(__dw_debug, NULL, NULL, NULL, 6444ea42b18SMasami Hiramatsu &addr_size, &next_cuh, &__dw_error); 6454ea42b18SMasami Hiramatsu ERR_IF(ret == DW_DLV_ERROR); 6464ea42b18SMasami Hiramatsu if (ret == DW_DLV_NO_ENTRY) 6474ea42b18SMasami Hiramatsu break; 6484ea42b18SMasami Hiramatsu 6494ea42b18SMasami Hiramatsu /* Get the DIE(Debugging Information Entry) of this CU */ 6504ea42b18SMasami Hiramatsu ret = dwarf_siblingof(__dw_debug, 0, &cu_die, &__dw_error); 6514ea42b18SMasami Hiramatsu ERR_IF(ret != DW_DLV_OK); 6524ea42b18SMasami Hiramatsu 6534ea42b18SMasami Hiramatsu /* Check if target file is included. */ 6544ea42b18SMasami Hiramatsu if (pp->file) 6554ea42b18SMasami Hiramatsu pf.fno = die_get_fileno(cu_die, pp->file); 6564ea42b18SMasami Hiramatsu 6574ea42b18SMasami Hiramatsu if (!pp->file || pf.fno) { 6584ea42b18SMasami Hiramatsu /* Save CU base address (for frame_base) */ 6594ea42b18SMasami Hiramatsu ret = dwarf_lowpc(cu_die, &pf.cu_base, &__dw_error); 6604ea42b18SMasami Hiramatsu ERR_IF(ret == DW_DLV_ERROR); 6614ea42b18SMasami Hiramatsu if (ret == DW_DLV_NO_ENTRY) 6624ea42b18SMasami Hiramatsu pf.cu_base = 0; 6634ea42b18SMasami Hiramatsu if (pp->line) 6644ea42b18SMasami Hiramatsu find_by_line(cu_die, &pf); 6654ea42b18SMasami Hiramatsu if (pp->function) 6664ea42b18SMasami Hiramatsu find_by_func(cu_die, &pf); 6674ea42b18SMasami Hiramatsu } 6684ea42b18SMasami Hiramatsu dwarf_dealloc(__dw_debug, cu_die, DW_DLA_DIE); 6694ea42b18SMasami Hiramatsu } 6704ea42b18SMasami Hiramatsu ret = dwarf_finish(__dw_debug, &__dw_error); 6714ea42b18SMasami Hiramatsu ERR_IF(ret != DW_DLV_OK); 6724ea42b18SMasami Hiramatsu 6734ea42b18SMasami Hiramatsu return pp->found; 6744ea42b18SMasami Hiramatsu } 6754ea42b18SMasami Hiramatsu 676