perf probe: Use elfutils-libdw for analyzing debuginfo
authorMasami Hiramatsu <mhiramat@redhat.com>
Thu, 25 Feb 2010 13:35:42 +0000 (08:35 -0500)
committerIngo Molnar <mingo@elte.hu>
Thu, 25 Feb 2010 16:49:29 +0000 (17:49 +0100)
Newer gcc introduces newer & richer debuginfo, and only libdw
in elfutils project can support it. So perf probe moves onto
elfutils-libdw from libdwarf.

Changes in v3:
 - Cast Dwarf_Addr/Dwarf_Word to uintmax_t for printf-formats.
 - Recover a sign-prefix which was removed in v2 by mistake.

Changes in v2:
 - Fix a type-casting bug in Makefile.
 - Cast Dwarf_Addr/Dwarf_Word to unsigned long long for printf-formats.

Signed-off-by: Masami Hiramatsu <mhiramat@redhat.com>
Cc: systemtap <systemtap@sources.redhat.com>
Cc: DLE <dle-develop@lists.sourceforge.net>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Mike Galbraith <efault@gmx.de>
Cc: K.Prasad <prasad@linux.vnet.ibm.com>
Cc: Ulrich Drepper <drepper@redhat.com>
Cc: Roland McGrath <roland@redhat.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
LKML-Reference: <20100225133542.6725.34724.stgit@localhost6.localdomain6>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
tools/perf/Makefile
tools/perf/builtin-probe.c
tools/perf/util/probe-finder.c
tools/perf/util/probe-finder.h

index 54a5b50..2d53738 100644 (file)
@@ -500,12 +500,12 @@ else
        msg := $(error No libelf.h/libelf found, please install libelf-dev/elfutils-libelf-devel and glibc-dev[el]);
 endif
 
        msg := $(error No libelf.h/libelf found, please install libelf-dev/elfutils-libelf-devel and glibc-dev[el]);
 endif
 
-ifneq ($(shell sh -c "(echo '\#ifndef _MIPS_SZLONG'; echo '\#define _MIPS_SZLONG 0'; echo '\#endif'; echo '\#include <dwarf.h>'; echo '\#include <libdwarf.h>'; echo 'int main(void) { Dwarf_Debug dbg; Dwarf_Error err; Dwarf_Ranges *rng; dwarf_init(0, DW_DLC_READ, 0, 0, &dbg, &err); dwarf_get_ranges(dbg, 0, &rng, 0, 0, &err); return (long)dbg; }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/libdwarf -ldwarf -lelf -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y)
-       msg := $(warning No libdwarf.h found or old libdwarf.h found, disables dwarf support. Please install libdwarf-dev/libdwarf-devel >= 20081231);
-       BASIC_CFLAGS += -DNO_LIBDWARF
+ifneq ($(shell sh -c "(echo '\#include <dwarf.h>'; echo '\#include <libdw.h>'; echo 'int main(void) { Dwarf *dbg; dbg = dwarf_begin(0, DWARF_C_READ); return (long)dbg; }') | $(CC) -x c - $(ALL_CFLAGS) -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64 -I/usr/include/elfutils -ldw -lelf -o $(BITBUCKET) $(ALL_LDFLAGS) $(EXTLIBS) "$(QUIET_STDERR)" && echo y"), y)
+       msg := $(warning No libdw.h found or old libdw.h found, disables dwarf support. Please install elfutils-devel/elfutils-dev);
+       BASIC_CFLAGS += -DNO_DWARF_SUPPORT
 else
 else
-       BASIC_CFLAGS += -I/usr/include/libdwarf
-       EXTLIBS += -lelf -ldwarf
+       BASIC_CFLAGS += -I/usr/include/elfutils
+       EXTLIBS += -lelf -ldw
        LIB_OBJS += util/probe-finder.o
 endif
 
        LIB_OBJS += util/probe-finder.o
 endif
 
index c3e6119..d8d3f05 100644 (file)
@@ -128,7 +128,7 @@ static void evaluate_probe_point(struct probe_point *pp)
                    pp->function);
 }
 
                    pp->function);
 }
 
-#ifndef NO_LIBDWARF
+#ifndef NO_DWARF_SUPPORT
 static int open_vmlinux(void)
 {
        if (map__load(session.kmaps[MAP__FUNCTION], NULL) < 0) {
 static int open_vmlinux(void)
 {
        if (map__load(session.kmaps[MAP__FUNCTION], NULL) < 0) {
@@ -156,7 +156,7 @@ static const char * const probe_usage[] = {
        "perf probe [<options>] --add 'PROBEDEF' [--add 'PROBEDEF' ...]",
        "perf probe [<options>] --del '[GROUP:]EVENT' ...",
        "perf probe --list",
        "perf probe [<options>] --add 'PROBEDEF' [--add 'PROBEDEF' ...]",
        "perf probe [<options>] --del '[GROUP:]EVENT' ...",
        "perf probe --list",
-#ifndef NO_LIBDWARF
+#ifndef NO_DWARF_SUPPORT
        "perf probe --line 'LINEDESC'",
 #endif
        NULL
        "perf probe --line 'LINEDESC'",
 #endif
        NULL
@@ -165,7 +165,7 @@ static const char * const probe_usage[] = {
 static const struct option options[] = {
        OPT_BOOLEAN('v', "verbose", &verbose,
                    "be more verbose (show parsed arguments, etc)"),
 static const struct option options[] = {
        OPT_BOOLEAN('v', "verbose", &verbose,
                    "be more verbose (show parsed arguments, etc)"),
-#ifndef NO_LIBDWARF
+#ifndef NO_DWARF_SUPPORT
        OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
                   "file", "vmlinux pathname"),
 #endif
        OPT_STRING('k', "vmlinux", &symbol_conf.vmlinux_name,
                   "file", "vmlinux pathname"),
 #endif
@@ -174,7 +174,7 @@ static const struct option options[] = {
        OPT_CALLBACK('d', "del", NULL, "[GROUP:]EVENT", "delete a probe event.",
                opt_del_probe_event),
        OPT_CALLBACK('a', "add", NULL,
        OPT_CALLBACK('d', "del", NULL, "[GROUP:]EVENT", "delete a probe event.",
                opt_del_probe_event),
        OPT_CALLBACK('a', "add", NULL,
-#ifdef NO_LIBDWARF
+#ifdef NO_DWARF_SUPPORT
                "[EVENT=]FUNC[+OFFS|%return] [ARG ...]",
 #else
                "[EVENT=]FUNC[+OFFS|%return|:RLN][@SRC]|SRC:ALN [ARG ...]",
                "[EVENT=]FUNC[+OFFS|%return] [ARG ...]",
 #else
                "[EVENT=]FUNC[+OFFS|%return|:RLN][@SRC]|SRC:ALN [ARG ...]",
@@ -185,7 +185,7 @@ static const struct option options[] = {
                "\t\tFUNC:\tFunction name\n"
                "\t\tOFFS:\tOffset from function entry (in byte)\n"
                "\t\t%return:\tPut the probe at function return\n"
                "\t\tFUNC:\tFunction name\n"
                "\t\tOFFS:\tOffset from function entry (in byte)\n"
                "\t\t%return:\tPut the probe at function return\n"
-#ifdef NO_LIBDWARF
+#ifdef NO_DWARF_SUPPORT
                "\t\tARG:\tProbe argument (only \n"
 #else
                "\t\tSRC:\tSource code path\n"
                "\t\tARG:\tProbe argument (only \n"
 #else
                "\t\tSRC:\tSource code path\n"
@@ -197,7 +197,7 @@ static const struct option options[] = {
                opt_add_probe_event),
        OPT_BOOLEAN('f', "force", &session.force_add, "forcibly add events"
                    " with existing name"),
                opt_add_probe_event),
        OPT_BOOLEAN('f', "force", &session.force_add, "forcibly add events"
                    " with existing name"),
-#ifndef NO_LIBDWARF
+#ifndef NO_DWARF_SUPPORT
        OPT_CALLBACK('L', "line", NULL,
                     "FUNC[:RLN[+NUM|:RLN2]]|SRC:ALN[+NUM|:ALN2]",
                     "Show source code lines.", opt_show_lines),
        OPT_CALLBACK('L', "line", NULL,
                     "FUNC[:RLN[+NUM|:RLN2]]|SRC:ALN[+NUM|:ALN2]",
                     "Show source code lines.", opt_show_lines),
@@ -225,7 +225,7 @@ static void init_vmlinux(void)
 int cmd_probe(int argc, const char **argv, const char *prefix __used)
 {
        int i, ret;
 int cmd_probe(int argc, const char **argv, const char *prefix __used)
 {
        int i, ret;
-#ifndef NO_LIBDWARF
+#ifndef NO_DWARF_SUPPORT
        int fd;
 #endif
        struct probe_point *pp;
        int fd;
 #endif
        struct probe_point *pp;
@@ -261,7 +261,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
                return 0;
        }
 
                return 0;
        }
 
-#ifndef NO_LIBDWARF
+#ifndef NO_DWARF_SUPPORT
        if (session.show_lines) {
                if (session.nr_probe != 0 || session.dellist) {
                        pr_warning("  Error: Don't use --line with"
        if (session.show_lines) {
                if (session.nr_probe != 0 || session.dellist) {
                        pr_warning("  Error: Don't use --line with"
@@ -292,9 +292,9 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
        init_vmlinux();
 
        if (session.need_dwarf)
        init_vmlinux();
 
        if (session.need_dwarf)
-#ifdef NO_LIBDWARF
+#ifdef NO_DWARF_SUPPORT
                die("Debuginfo-analysis is not supported");
                die("Debuginfo-analysis is not supported");
-#else  /* !NO_LIBDWARF */
+#else  /* !NO_DWARF_SUPPORT */
                pr_debug("Some probes require debuginfo.\n");
 
        fd = open_vmlinux();
                pr_debug("Some probes require debuginfo.\n");
 
        fd = open_vmlinux();
@@ -335,7 +335,7 @@ int cmd_probe(int argc, const char **argv, const char *prefix __used)
        close(fd);
 
 end_dwarf:
        close(fd);
 
 end_dwarf:
-#endif /* !NO_LIBDWARF */
+#endif /* !NO_DWARF_SUPPORT */
 
        /* Synthesize probes without dwarf */
        for (i = 0; i < session.nr_probe; i++) {
 
        /* Synthesize probes without dwarf */
        for (i = 0; i < session.nr_probe; i++) {
index c819fd5..c422472 100644 (file)
@@ -44,8 +44,6 @@ struct die_link {
        Dwarf_Die die;                  /* Current die */
 };
 
        Dwarf_Die die;                  /* Current die */
 };
 
-static Dwarf_Debug __dw_debug;
-static Dwarf_Error __dw_error;
 
 /*
  * Generic dwarf analysis helpers
 
 /*
  * Generic dwarf analysis helpers
@@ -114,157 +112,114 @@ static int strtailcmp(const char *s1, const char *s2)
 }
 
 /* Find the fileno of the target file. */
 }
 
 /* Find the fileno of the target file. */
-static Dwarf_Unsigned cu_find_fileno(Dwarf_Die cu_die, const char *fname)
+static int cu_find_fileno(Dwarf_Die *cu_die, const char *fname)
 {
 {
-       Dwarf_Signed cnt, i;
-       Dwarf_Unsigned found = 0;
-       char **srcs;
+       Dwarf_Files *files;
+       size_t nfiles, i;
+       const char *src;
        int ret;
 
        if (!fname)
        int ret;
 
        if (!fname)
-               return 0;
+               return -EINVAL;
 
 
-       ret = dwarf_srcfiles(cu_die, &srcs, &cnt, &__dw_error);
-       if (ret == DW_DLV_OK) {
-               for (i = 0; i < cnt && !found; i++) {
-                       if (strtailcmp(srcs[i], fname) == 0)
-                               found = i + 1;
-                       dwarf_dealloc(__dw_debug, srcs[i], DW_DLA_STRING);
+       ret = dwarf_getsrcfiles(cu_die, &files, &nfiles);
+       if (ret == 0) {
+               for (i = 0; i < nfiles; i++) {
+                       src = dwarf_filesrc(files, i, NULL, NULL);
+                       if (strtailcmp(src, fname) == 0) {
+                               ret = (int)i;   /*???: +1 or not?*/
+                               break;
+                       }
                }
                }
-               for (; i < cnt; i++)
-                       dwarf_dealloc(__dw_debug, srcs[i], DW_DLA_STRING);
-               dwarf_dealloc(__dw_debug, srcs, DW_DLA_LIST);
+               if (ret)
+                       pr_debug("found fno: %d\n", ret);
        }
        }
-       if (found)
-               pr_debug("found fno: %d\n", (int)found);
-       return found;
+       return ret;
 }
 
 }
 
-static int cu_get_filename(Dwarf_Die cu_die, Dwarf_Unsigned fno, char **buf)
+struct __addr_die_search_param {
+       Dwarf_Addr      addr;
+       Dwarf_Die       *die_mem;
+};
+
+static int __die_search_func_cb(Dwarf_Die *fn_die, void *data)
 {
 {
-       Dwarf_Signed cnt, i;
-       char **srcs;
-       int ret = 0;
+       struct __addr_die_search_param *ad = data;
 
 
-       if (!buf || !fno)
-               return -EINVAL;
+       if (dwarf_tag(fn_die) == DW_TAG_subprogram &&
+           dwarf_haspc(fn_die, ad->addr)) {
+               memcpy(ad->die_mem, fn_die, sizeof(Dwarf_Die));
+               return DWARF_CB_ABORT;
+       }
+       return DWARF_CB_OK;
+}
 
 
-       ret = dwarf_srcfiles(cu_die, &srcs, &cnt, &__dw_error);
-       if (ret == DW_DLV_OK) {
-               if ((Dwarf_Unsigned)cnt > fno - 1) {
-                       *buf = strdup(srcs[fno - 1]);
-                       ret = 0;
-                       pr_debug("found filename: %s\n", *buf);
-               } else
-                       ret = -ENOENT;
-               for (i = 0; i < cnt; i++)
-                       dwarf_dealloc(__dw_debug, srcs[i], DW_DLA_STRING);
-               dwarf_dealloc(__dw_debug, srcs, DW_DLA_LIST);
-       } else
-               ret = -EINVAL;
-       return ret;
+/* Search a real subprogram including this line, */
+static Dwarf_Die *die_get_real_subprogram(Dwarf_Die *cu_die, Dwarf_Addr addr,
+                                         Dwarf_Die *die_mem)
+{
+       struct __addr_die_search_param ad;
+       ad.addr = addr;
+       ad.die_mem = die_mem;
+       /* dwarf_getscopes can't find subprogram. */
+       if (!dwarf_getfuncs(cu_die, __die_search_func_cb, &ad, 0))
+               return NULL;
+       else
+               return die_mem;
 }
 
 /* Compare diename and tname */
 }
 
 /* Compare diename and tname */
-static int die_compare_name(Dwarf_Die dw_die, const char *tname)
+static bool die_compare_name(Dwarf_Die *dw_die, const char *tname)
 {
 {
-       char *name;
-       int ret;
-       ret = dwarf_diename(dw_die, &name, &__dw_error);
-       DIE_IF(ret == DW_DLV_ERROR);
-       if (ret == DW_DLV_OK) {
-               ret = strcmp(tname, name);
-               dwarf_dealloc(__dw_debug, name, DW_DLA_STRING);
-       } else
-               ret = -1;
-       return ret;
+       const char *name;
+       name = dwarf_diename(dw_die);
+       DIE_IF(name == NULL);
+       return strcmp(tname, name);
 }
 
 /* Check the address is in the subprogram(function). */
 }
 
 /* Check the address is in the subprogram(function). */
-static int die_within_subprogram(Dwarf_Die sp_die, Dwarf_Addr addr,
-                                Dwarf_Signed *offs)
+static bool die_within_subprogram(Dwarf_Die *sp_die, Dwarf_Addr addr,
+                                size_t *offs)
 {
 {
-       Dwarf_Addr lopc, hipc;
+       Dwarf_Addr epc;
        int ret;
 
        int ret;
 
-       /* TODO: check ranges */
-       ret = dwarf_lowpc(sp_die, &lopc, &__dw_error);
-       DIE_IF(ret == DW_DLV_ERROR);
-       if (ret == DW_DLV_NO_ENTRY)
-               return 0;
-       ret = dwarf_highpc(sp_die, &hipc, &__dw_error);
-       DIE_IF(ret != DW_DLV_OK);
-       if (lopc <= addr && addr < hipc) {
-               *offs = addr - lopc;
-               return 1;
-       } else
-               return 0;
-}
+       ret = dwarf_haspc(sp_die, addr);
+       if (ret <= 0)
+               return false;
 
 
-/* Check the die is inlined function */
-static Dwarf_Bool die_inlined_subprogram(Dwarf_Die dw_die)
-{
-       /* TODO: check strictly */
-       Dwarf_Bool inl;
-       int ret;
+       if (offs) {
+               ret = dwarf_entrypc(sp_die, &epc);
+               DIE_IF(ret == -1);
+               *offs = addr - epc;
+       }
 
 
-       ret = dwarf_hasattr(dw_die, DW_AT_inline, &inl, &__dw_error);
-       DIE_IF(ret == DW_DLV_ERROR);
-       return inl;
+       return true;
 }
 
 }
 
-/* Get the offset of abstruct_origin */
-static Dwarf_Off die_get_abstract_origin(Dwarf_Die dw_die)
+/* Get entry pc(or low pc, 1st entry of ranges)  of the die */
+static Dwarf_Addr die_get_entrypc(Dwarf_Die *dw_die)
 {
 {
-       Dwarf_Attribute attr;
-       Dwarf_Off cu_offs;
+       Dwarf_Addr epc;
        int ret;
 
        int ret;
 
-       ret = dwarf_attr(dw_die, DW_AT_abstract_origin, &attr, &__dw_error);
-       DIE_IF(ret != DW_DLV_OK);
-       ret = dwarf_formref(attr, &cu_offs, &__dw_error);
-       DIE_IF(ret != DW_DLV_OK);
-       dwarf_dealloc(__dw_debug, attr, DW_DLA_ATTR);
-       return cu_offs;
+       ret = dwarf_entrypc(dw_die, &epc);
+       DIE_IF(ret == -1);
+       return epc;
 }
 
 }
 
-/* Get entry pc(or low pc, 1st entry of ranges)  of the die */
-static Dwarf_Addr die_get_entrypc(Dwarf_Die dw_die)
+/* Check if the abstract origin's address or not */
+static bool die_compare_abstract_origin(Dwarf_Die *in_die, void *origin_addr)
 {
        Dwarf_Attribute attr;
 {
        Dwarf_Attribute attr;
-       Dwarf_Addr addr;
-       Dwarf_Off offs;
-       Dwarf_Ranges *ranges;
-       Dwarf_Signed cnt;
-       int ret;
+       Dwarf_Die origin;
 
 
-       /* Try to get entry pc */
-       ret = dwarf_attr(dw_die, DW_AT_entry_pc, &attr, &__dw_error);
-       DIE_IF(ret == DW_DLV_ERROR);
-       if (ret == DW_DLV_OK) {
-               ret = dwarf_formaddr(attr, &addr, &__dw_error);
-               DIE_IF(ret != DW_DLV_OK);
-               dwarf_dealloc(__dw_debug, attr, DW_DLA_ATTR);
-               return addr;
-       }
+       if (!dwarf_attr(in_die, DW_AT_abstract_origin, &attr))
+               return false;
+       if (!dwarf_formref_die(&attr, &origin))
+               return false;
 
 
-       /* Try to get low pc */
-       ret = dwarf_lowpc(dw_die, &addr, &__dw_error);
-       DIE_IF(ret == DW_DLV_ERROR);
-       if (ret == DW_DLV_OK)
-               return addr;
-
-       /* Try to get ranges */
-       ret = dwarf_attr(dw_die, DW_AT_ranges, &attr, &__dw_error);
-       DIE_IF(ret != DW_DLV_OK);
-       ret = dwarf_formref(attr, &offs, &__dw_error);
-       DIE_IF(ret != DW_DLV_OK);
-       ret = dwarf_get_ranges(__dw_debug, offs, &ranges, &cnt, NULL,
-                               &__dw_error);
-       DIE_IF(ret != DW_DLV_OK);
-       addr = ranges[0].dwr_addr1;
-       dwarf_ranges_dealloc(__dw_debug, ranges, cnt);
-       return addr;
+       return origin.addr == origin_addr;
 }
 
 /*
 }
 
 /*
@@ -275,7 +230,6 @@ static int __search_die_tree(struct die_link *cur_link,
                             int (*die_cb)(struct die_link *, void *),
                             void *data)
 {
                             int (*die_cb)(struct die_link *, void *),
                             void *data)
 {
-       Dwarf_Die new_die;
        struct die_link new_link;
        int ret;
 
        struct die_link new_link;
        int ret;
 
@@ -285,31 +239,24 @@ static int __search_die_tree(struct die_link *cur_link,
        /* Check current die */
        while (!(ret = die_cb(cur_link, data))) {
                /* Check child die */
        /* Check current die */
        while (!(ret = die_cb(cur_link, data))) {
                /* Check child die */
-               ret = dwarf_child(cur_link->die, &new_die, &__dw_error);
-               DIE_IF(ret == DW_DLV_ERROR);
-               if (ret == DW_DLV_OK) {
+               ret = dwarf_child(&cur_link->die, &new_link.die);
+               if (ret == 0) {
                        new_link.parent = cur_link;
                        new_link.parent = cur_link;
-                       new_link.die = new_die;
                        ret = __search_die_tree(&new_link, die_cb, data);
                        if (ret)
                                break;
                }
 
                /* Move to next sibling */
                        ret = __search_die_tree(&new_link, die_cb, data);
                        if (ret)
                                break;
                }
 
                /* Move to next sibling */
-               ret = dwarf_siblingof(__dw_debug, cur_link->die, &new_die,
-                                     &__dw_error);
-               DIE_IF(ret == DW_DLV_ERROR);
-               dwarf_dealloc(__dw_debug, cur_link->die, DW_DLA_DIE);
-               cur_link->die = new_die;
-               if (ret == DW_DLV_NO_ENTRY)
+               ret = dwarf_siblingof(&cur_link->die, &cur_link->die);
+               if (ret != 0)
                        return 0;
        }
                        return 0;
        }
-       dwarf_dealloc(__dw_debug, cur_link->die, DW_DLA_DIE);
        return ret;
 }
 
 /* Search a die in its children's die tree */
        return ret;
 }
 
 /* Search a die in its children's die tree */
-static int search_die_from_children(Dwarf_Die parent_die,
+static int search_die_from_children(Dwarf_Die *parent_die,
                                    int (*die_cb)(struct die_link *, void *),
                                    void *data)
 {
                                    int (*die_cb)(struct die_link *, void *),
                                    void *data)
 {
@@ -317,125 +264,58 @@ static int search_die_from_children(Dwarf_Die parent_die,
        int ret;
 
        new_link.parent = NULL;
        int ret;
 
        new_link.parent = NULL;
-       ret = dwarf_child(parent_die, &new_link.die, &__dw_error);
-       DIE_IF(ret == DW_DLV_ERROR);
-       if (ret == DW_DLV_OK)
+       ret = dwarf_child(parent_die, &new_link.die);
+       if (ret == 0)
                return __search_die_tree(&new_link, die_cb, data);
        else
                return 0;
 }
 
                return __search_die_tree(&new_link, die_cb, data);
        else
                return 0;
 }
 
-/* Find a locdesc corresponding to the address */
-static int attr_get_locdesc(Dwarf_Attribute attr, Dwarf_Locdesc *desc,
-                           Dwarf_Addr addr)
-{
-       Dwarf_Signed lcnt;
-       Dwarf_Locdesc **llbuf;
-       int ret, i;
-
-       ret = dwarf_loclist_n(attr, &llbuf, &lcnt, &__dw_error);
-       DIE_IF(ret != DW_DLV_OK);
-       ret = DW_DLV_NO_ENTRY;
-       for (i = 0; i < lcnt; ++i) {
-               if (llbuf[i]->ld_lopc <= addr &&
-                   llbuf[i]->ld_hipc > addr) {
-                       memcpy(desc, llbuf[i], sizeof(Dwarf_Locdesc));
-                       desc->ld_s =
-                               malloc(sizeof(Dwarf_Loc) * llbuf[i]->ld_cents);
-                       DIE_IF(desc->ld_s == NULL);
-                       memcpy(desc->ld_s, llbuf[i]->ld_s,
-                               sizeof(Dwarf_Loc) * llbuf[i]->ld_cents);
-                       ret = DW_DLV_OK;
-                       break;
-               }
-               dwarf_dealloc(__dw_debug, llbuf[i]->ld_s, DW_DLA_LOC_BLOCK);
-               dwarf_dealloc(__dw_debug, llbuf[i], DW_DLA_LOCDESC);
-       }
-       /* Releasing loop */
-       for (; i < lcnt; ++i) {
-               dwarf_dealloc(__dw_debug, llbuf[i]->ld_s, DW_DLA_LOC_BLOCK);
-               dwarf_dealloc(__dw_debug, llbuf[i], DW_DLA_LOCDESC);
-       }
-       dwarf_dealloc(__dw_debug, llbuf, DW_DLA_LIST);
-       return ret;
-}
-
-/* Get decl_file attribute value (file number) */
-static Dwarf_Unsigned die_get_decl_file(Dwarf_Die sp_die)
-{
-       Dwarf_Attribute attr;
-       Dwarf_Unsigned fno;
-       int ret;
-
-       ret = dwarf_attr(sp_die, DW_AT_decl_file, &attr, &__dw_error);
-       DIE_IF(ret != DW_DLV_OK);
-       dwarf_formudata(attr, &fno, &__dw_error);
-       DIE_IF(ret != DW_DLV_OK);
-       dwarf_dealloc(__dw_debug, attr, DW_DLA_ATTR);
-       return fno;
-}
-
-/* Get decl_line attribute value (line number) */
-static Dwarf_Unsigned die_get_decl_line(Dwarf_Die sp_die)
-{
-       Dwarf_Attribute attr;
-       Dwarf_Unsigned lno;
-       int ret;
-
-       ret = dwarf_attr(sp_die, DW_AT_decl_line, &attr, &__dw_error);
-       DIE_IF(ret != DW_DLV_OK);
-       dwarf_formudata(attr, &lno, &__dw_error);
-       DIE_IF(ret != DW_DLV_OK);
-       dwarf_dealloc(__dw_debug, attr, DW_DLA_ATTR);
-       return lno;
-}
 
 /*
  * Probe finder related functions
  */
 
 /* Show a location */
 
 /*
  * Probe finder related functions
  */
 
 /* Show a location */
-static void show_location(Dwarf_Loc *loc, struct probe_finder *pf)
+static void show_location(Dwarf_Op *op, struct probe_finder *pf)
 {
 {
-       Dwarf_Small op;
-       Dwarf_Unsigned regn;
-       Dwarf_Signed offs;
+       unsigned int regn;
+       Dwarf_Word offs = 0;
        int deref = 0, ret;
        const char *regs;
 
        int deref = 0, ret;
        const char *regs;
 
-       op = loc->lr_atom;
-
+       /* TODO: support CFA */
        /* If this is based on frame buffer, set the offset */
        /* If this is based on frame buffer, set the offset */
-       if (op == DW_OP_fbreg) {
+       if (op->atom == DW_OP_fbreg) {
+               if (pf->fb_ops == NULL)
+                       die("The attribute of frame base is not supported.\n");
                deref = 1;
                deref = 1;
-               offs = (Dwarf_Signed)loc->lr_number;
-               op = pf->fbloc.ld_s[0].lr_atom;
-               loc = &pf->fbloc.ld_s[0];
-       } else
-               offs = 0;
+               offs = op->number;
+               op = &pf->fb_ops[0];
+       }
 
 
-       if (op >= DW_OP_breg0 && op <= DW_OP_breg31) {
-               regn = op - DW_OP_breg0;
-               offs += (Dwarf_Signed)loc->lr_number;
+       if (op->atom >= DW_OP_breg0 && op->atom <= DW_OP_breg31) {
+               regn = op->atom - DW_OP_breg0;
+               offs += op->number;
                deref = 1;
                deref = 1;
-       } else if (op >= DW_OP_reg0 && op <= DW_OP_reg31) {
-               regn = op - DW_OP_reg0;
-       } else if (op == DW_OP_bregx) {
-               regn = loc->lr_number;
-               offs += (Dwarf_Signed)loc->lr_number2;
+       } else if (op->atom >= DW_OP_reg0 && op->atom <= DW_OP_reg31) {
+               regn = op->atom - DW_OP_reg0;
+       } else if (op->atom == DW_OP_bregx) {
+               regn = op->number;
+               offs += op->number2;
                deref = 1;
                deref = 1;
-       } else if (op == DW_OP_regx) {
-               regn = loc->lr_number;
+       } else if (op->atom == DW_OP_regx) {
+               regn = op->number;
        } else
        } else
-               die("Dwarf_OP %d is not supported.", op);
+               die("DW_OP %d is not supported.", op->atom);
 
        regs = get_arch_regstr(regn);
        if (!regs)
 
        regs = get_arch_regstr(regn);
        if (!regs)
-               die("%lld exceeds max register number.", regn);
+               die("%u exceeds max register number.", regn);
 
        if (deref)
 
        if (deref)
-               ret = snprintf(pf->buf, pf->len,
-                                " %s=%+lld(%s)", pf->var, offs, regs);
+               ret = snprintf(pf->buf, pf->len, " %s=+%ju(%s)",
+                              pf->var, (uintmax_t)offs, regs);
        else
                ret = snprintf(pf->buf, pf->len, " %s=%s", pf->var, regs);
        DIE_IF(ret < 0);
        else
                ret = snprintf(pf->buf, pf->len, " %s=%s", pf->var, regs);
        DIE_IF(ret < 0);
@@ -443,41 +323,41 @@ static void show_location(Dwarf_Loc *loc, struct probe_finder *pf)
 }
 
 /* Show a variables in kprobe event format */
 }
 
 /* Show a variables in kprobe event format */
-static void show_variable(Dwarf_Die vr_die, struct probe_finder *pf)
+static void show_variable(Dwarf_Die *vr_die, struct probe_finder *pf)
 {
        Dwarf_Attribute attr;
 {
        Dwarf_Attribute attr;
-       Dwarf_Locdesc ld;
+       Dwarf_Op *expr;
+       size_t nexpr;
        int ret;
 
        int ret;
 
-       ret = dwarf_attr(vr_die, DW_AT_location, &attr, &__dw_error);
-       if (ret != DW_DLV_OK)
+       if (dwarf_attr(vr_die, DW_AT_location, &attr) == NULL)
                goto error;
                goto error;
-       ret = attr_get_locdesc(attr, &ld, (pf->addr - pf->cu_base));
-       if (ret != DW_DLV_OK)
+       /* TODO: handle more than 1 exprs */
+       ret = dwarf_getlocation_addr(&attr, (pf->addr - pf->cu_base),
+                                    &expr, &nexpr, 1);
+       if (ret <= 0 || nexpr == 0)
                goto error;
                goto error;
-       /* TODO? */
-       DIE_IF(ld.ld_cents != 1);
-       show_location(&ld.ld_s[0], pf);
-       free(ld.ld_s);
-       dwarf_dealloc(__dw_debug, attr, DW_DLA_ATTR);
+
+       show_location(expr, pf);
+       /* *expr will be cached in libdw. Don't free it. */
        return ;
 error:
        return ;
 error:
+       /* TODO: Support const_value */
        die("Failed to find the location of %s at this address.\n"
            " Perhaps, it has been optimized out.", pf->var);
 }
 
        die("Failed to find the location of %s at this address.\n"
            " Perhaps, it has been optimized out.", pf->var);
 }
 
-static int variable_callback(struct die_link *dlink, void *data)
+static int variable_search_cb(struct die_link *dlink, void *data)
 {
        struct probe_finder *pf = (struct probe_finder *)data;
 {
        struct probe_finder *pf = (struct probe_finder *)data;
-       Dwarf_Half tag;
-       int ret;
+       int tag;
 
 
-       ret = dwarf_tag(dlink->die, &tag, &__dw_error);
-       DIE_IF(ret == DW_DLV_ERROR);
+       tag = dwarf_tag(&dlink->die);
+       DIE_IF(tag < 0);
        if ((tag == DW_TAG_formal_parameter ||
             tag == DW_TAG_variable) &&
        if ((tag == DW_TAG_formal_parameter ||
             tag == DW_TAG_variable) &&
-           (die_compare_name(dlink->die, pf->var) == 0)) {
-               show_variable(dlink->die, pf);
+           (die_compare_name(&dlink->die, pf->var) == 0)) {
+               show_variable(&dlink->die, pf);
                return 1;
        }
        /* TODO: Support struct members and arrays */
                return 1;
        }
        /* TODO: Support struct members and arrays */
@@ -485,7 +365,7 @@ static int variable_callback(struct die_link *dlink, void *data)
 }
 
 /* Find a variable in a subprogram die */
 }
 
 /* Find a variable in a subprogram die */
-static void find_variable(Dwarf_Die sp_die, struct probe_finder *pf)
+static void find_variable(Dwarf_Die *sp_die, struct probe_finder *pf)
 {
        int ret;
 
 {
        int ret;
 
@@ -499,43 +379,25 @@ static void find_variable(Dwarf_Die sp_die, struct probe_finder *pf)
 
        pr_debug("Searching '%s' variable in context.\n", pf->var);
        /* Search child die for local variables and parameters. */
 
        pr_debug("Searching '%s' variable in context.\n", pf->var);
        /* Search child die for local variables and parameters. */
-       ret = search_die_from_children(sp_die, variable_callback, pf);
+       ret = search_die_from_children(sp_die, variable_search_cb, pf);
        if (!ret)
                die("Failed to find '%s' in this function.", pf->var);
 }
 
        if (!ret)
                die("Failed to find '%s' in this function.", pf->var);
 }
 
-/* Get a frame base on the address */
-static void get_current_frame_base(Dwarf_Die sp_die, struct probe_finder *pf)
-{
-       Dwarf_Attribute attr;
-       int ret;
-
-       ret = dwarf_attr(sp_die, DW_AT_frame_base, &attr, &__dw_error);
-       DIE_IF(ret != DW_DLV_OK);
-       ret = attr_get_locdesc(attr, &pf->fbloc, (pf->addr - pf->cu_base));
-       DIE_IF(ret != DW_DLV_OK);
-       dwarf_dealloc(__dw_debug, attr, DW_DLA_ATTR);
-}
-
-static void free_current_frame_base(struct probe_finder *pf)
-{
-       free(pf->fbloc.ld_s);
-       memset(&pf->fbloc, 0, sizeof(Dwarf_Locdesc));
-}
-
 /* Show a probe point to output buffer */
 /* Show a probe point to output buffer */
-static void show_probe_point(Dwarf_Die sp_die, Dwarf_Signed offs,
+static void show_probe_point(Dwarf_Die *sp_die, size_t offs,
                             struct probe_finder *pf)
 {
        struct probe_point *pp = pf->pp;
                             struct probe_finder *pf)
 {
        struct probe_point *pp = pf->pp;
-       char *name;
+       const char *name;
        char tmp[MAX_PROBE_BUFFER];
        int ret, i, len;
        char tmp[MAX_PROBE_BUFFER];
        int ret, i, len;
+       Dwarf_Attribute fb_attr;
+       size_t nops;
 
        /* Output name of probe point */
 
        /* Output name of probe point */
-       ret = dwarf_diename(sp_die, &name, &__dw_error);
-       DIE_IF(ret == DW_DLV_ERROR);
-       if (ret == DW_DLV_OK) {
+       name = dwarf_diename(sp_die);
+       if (name) {
                ret = snprintf(tmp, MAX_PROBE_BUFFER, "%s+%u", name,
                                (unsigned int)offs);
                /* Copy the function name if possible */
                ret = snprintf(tmp, MAX_PROBE_BUFFER, "%s+%u", name,
                                (unsigned int)offs);
                /* Copy the function name if possible */
@@ -543,14 +405,14 @@ static void show_probe_point(Dwarf_Die sp_die, Dwarf_Signed offs,
                        pp->function = strdup(name);
                        pp->offset = offs;
                }
                        pp->function = strdup(name);
                        pp->offset = offs;
                }
-               dwarf_dealloc(__dw_debug, name, DW_DLA_STRING);
        } else {
                /* This function has no name. */
        } else {
                /* This function has no name. */
-               ret = snprintf(tmp, MAX_PROBE_BUFFER, "0x%llx", pf->addr);
+               ret = snprintf(tmp, MAX_PROBE_BUFFER, "0x%jx",
+                              (uintmax_t)pf->addr);
                if (!pp->function) {
                        /* TODO: Use _stext */
                        pp->function = strdup("");
                if (!pp->function) {
                        /* TODO: Use _stext */
                        pp->function = strdup("");
-                       pp->offset = (int)pf->addr;
+                       pp->offset = (size_t)pf->addr;
                }
        }
        DIE_IF(ret < 0);
                }
        }
        DIE_IF(ret < 0);
@@ -558,8 +420,15 @@ static void show_probe_point(Dwarf_Die sp_die, Dwarf_Signed offs,
        len = ret;
        pr_debug("Probe point found: %s\n", tmp);
 
        len = ret;
        pr_debug("Probe point found: %s\n", tmp);
 
+       /* Get the frame base attribute/ops */
+       dwarf_attr(sp_die, DW_AT_frame_base, &fb_attr);
+       ret = dwarf_getlocation_addr(&fb_attr, (pf->addr - pf->cu_base),
+                                    &pf->fb_ops, &nops, 1);
+       if (ret <= 0 || nops == 0)
+               pf->fb_ops = NULL;
+
        /* Find each argument */
        /* Find each argument */
-       get_current_frame_base(sp_die, pf);
+       /* TODO: use dwarf_cfi_addrframe */
        for (i = 0; i < pp->nr_args; i++) {
                pf->var = pp->args[i];
                pf->buf = &tmp[len];
        for (i = 0; i < pp->nr_args; i++) {
                pf->var = pp->args[i];
                pf->buf = &tmp[len];
@@ -567,131 +436,106 @@ static void show_probe_point(Dwarf_Die sp_die, Dwarf_Signed offs,
                find_variable(sp_die, pf);
                len += strlen(pf->buf);
        }
                find_variable(sp_die, pf);
                len += strlen(pf->buf);
        }
-       free_current_frame_base(pf);
+
+       /* *pf->fb_ops will be cached in libdw. Don't free it. */
+       pf->fb_ops = NULL;
 
        pp->probes[pp->found] = strdup(tmp);
        pp->found++;
 }
 
 
        pp->probes[pp->found] = strdup(tmp);
        pp->found++;
 }
 
-static int probeaddr_callback(struct die_link *dlink, void *data)
-{
-       struct probe_finder *pf = (struct probe_finder *)data;
-       Dwarf_Half tag;
-       Dwarf_Signed offs;
-       int ret;
-
-       ret = dwarf_tag(dlink->die, &tag, &__dw_error);
-       DIE_IF(ret == DW_DLV_ERROR);
-       /* Check the address is in this subprogram */
-       if (tag == DW_TAG_subprogram &&
-           die_within_subprogram(dlink->die, pf->addr, &offs)) {
-               show_probe_point(dlink->die, offs, pf);
-               return 1;
-       }
-       return 0;
-}
-
 /* Find probe point from its line number */
 static void find_probe_point_by_line(struct probe_finder *pf)
 {
 /* Find probe point from its line number */
 static void find_probe_point_by_line(struct probe_finder *pf)
 {
-       Dwarf_Signed cnt, i, clm;
-       Dwarf_Line *lines;
-       Dwarf_Unsigned lineno = 0;
-       Dwarf_Addr addr;
-       Dwarf_Unsigned fno;
+       Dwarf_Lines *lines;
+       Dwarf_Line *line;
+       size_t nlines, i;
+       Dwarf_Addr addr, epc;
+       int lineno;
        int ret;
        int ret;
+       Dwarf_Die *sp_die, die_mem;
 
 
-       ret = dwarf_srclines(pf->cu_die, &lines, &cnt, &__dw_error);
-       DIE_IF(ret != DW_DLV_OK);
-
-       for (i = 0; i < cnt; i++) {
-               ret = dwarf_line_srcfileno(lines[i], &fno, &__dw_error);
-               DIE_IF(ret != DW_DLV_OK);
-               if (fno != pf->fno)
-                       continue;
+       ret = dwarf_getsrclines(&pf->cu_die, &lines, &nlines);
+       DIE_IF(ret != 0);
 
 
-               ret = dwarf_lineno(lines[i], &lineno, &__dw_error);
-               DIE_IF(ret != DW_DLV_OK);
+       for (i = 0; i < nlines; i++) {
+               line = dwarf_onesrcline(lines, i);
+               dwarf_lineno(line, &lineno);
                if (lineno != pf->lno)
                        continue;
 
                if (lineno != pf->lno)
                        continue;
 
-               ret = dwarf_lineoff(lines[i], &clm, &__dw_error);
-               DIE_IF(ret != DW_DLV_OK);
+               /* TODO: Get fileno from line, but how? */
+               if (strtailcmp(dwarf_linesrc(line, NULL, NULL), pf->fname) != 0)
+                       continue;
 
 
-               ret = dwarf_lineaddr(lines[i], &addr, &__dw_error);
-               DIE_IF(ret != DW_DLV_OK);
-               pr_debug("Probe line found: line[%d]:%u,%d addr:0x%llx\n",
-                        (int)i, (unsigned)lineno, (int)clm, addr);
+               ret = dwarf_lineaddr(line, &addr);
+               DIE_IF(ret != 0);
+               pr_debug("Probe line found: line[%d]:%d addr:0x%jx\n",
+                        (int)i, lineno, (uintmax_t)addr);
                pf->addr = addr;
                pf->addr = addr;
-               /* Search a real subprogram including this line, */
-               ret = search_die_from_children(pf->cu_die,
-                                              probeaddr_callback, pf);
-               if (ret == 0)
+
+               sp_die = die_get_real_subprogram(&pf->cu_die, addr, &die_mem);
+               if (!sp_die)
                        die("Probe point is not found in subprograms.");
                        die("Probe point is not found in subprograms.");
+               dwarf_entrypc(sp_die, &epc);
+               show_probe_point(sp_die, (size_t)(addr - epc), pf);
                /* Continuing, because target line might be inlined. */
        }
                /* Continuing, because target line might be inlined. */
        }
-       dwarf_srclines_dealloc(__dw_debug, lines, cnt);
 }
 
 }
 
+
 /* Search function from function name */
 /* Search function from function name */
-static int probefunc_callback(struct die_link *dlink, void *data)
+static int probe_point_search_cb(struct die_link *dlink, void *data)
 {
        struct probe_finder *pf = (struct probe_finder *)data;
        struct probe_point *pp = pf->pp;
        struct die_link *lk;
 {
        struct probe_finder *pf = (struct probe_finder *)data;
        struct probe_point *pp = pf->pp;
        struct die_link *lk;
-       Dwarf_Signed offs;
-       Dwarf_Half tag;
+       size_t offs;
+       int tag;
        int ret;
 
        int ret;
 
-       ret = dwarf_tag(dlink->die, &tag, &__dw_error);
-       DIE_IF(ret == DW_DLV_ERROR);
+       tag = dwarf_tag(&dlink->die);
        if (tag == DW_TAG_subprogram) {
        if (tag == DW_TAG_subprogram) {
-               if (die_compare_name(dlink->die, pp->function) == 0) {
+               if (die_compare_name(&dlink->die, pp->function) == 0) {
                        if (pp->line) { /* Function relative line */
                        if (pp->line) { /* Function relative line */
-                               pf->fno = die_get_decl_file(dlink->die);
-                               pf->lno = die_get_decl_line(dlink->die)
-                                        + pp->line;
+                               pf->fname = dwarf_decl_file(&dlink->die);
+                               dwarf_decl_line(&dlink->die, &pf->lno);
+                               pf->lno += pp->line;
                                find_probe_point_by_line(pf);
                                return 1;
                        }
                                find_probe_point_by_line(pf);
                                return 1;
                        }
-                       if (die_inlined_subprogram(dlink->die)) {
+                       if (dwarf_func_inline(&dlink->die)) {
                                /* Inlined function, save it. */
                                /* Inlined function, save it. */
-                               ret = dwarf_die_CU_offset(dlink->die,
-                                                         &pf->inl_offs,
-                                                         &__dw_error);
-                               DIE_IF(ret != DW_DLV_OK);
-                               pr_debug("inline definition offset %lld\n",
-                                        pf->inl_offs);
+                               pf->origin = dlink->die.addr;
                                return 0;       /* Continue to search */
                        }
                        /* Get probe address */
                                return 0;       /* Continue to search */
                        }
                        /* Get probe address */
-                       pf->addr = die_get_entrypc(dlink->die);
+                       pf->addr = die_get_entrypc(&dlink->die);
                        pf->addr += pp->offset;
                        /* TODO: Check the address in this function */
                        pf->addr += pp->offset;
                        /* TODO: Check the address in this function */
-                       show_probe_point(dlink->die, pp->offset, pf);
+                       show_probe_point(&dlink->die, pp->offset, pf);
                        return 1; /* Exit; no same symbol in this CU. */
                }
                        return 1; /* Exit; no same symbol in this CU. */
                }
-       } else if (tag == DW_TAG_inlined_subroutine && pf->inl_offs) {
-               if (die_get_abstract_origin(dlink->die) == pf->inl_offs) {
+       } else if (tag == DW_TAG_inlined_subroutine && pf->origin) {
+               if (die_compare_abstract_origin(&dlink->die, pf->origin)) {
                        /* Get probe address */
                        /* Get probe address */
-                       pf->addr = die_get_entrypc(dlink->die);
+                       pf->addr = die_get_entrypc(&dlink->die);
                        pf->addr += pp->offset;
                        pf->addr += pp->offset;
-                       pr_debug("found inline addr: 0x%llx\n", pf->addr);
+                       pr_debug("found inline addr: 0x%jx\n",
+                                (uintmax_t)pf->addr);
                        /* Inlined function. Get a real subprogram */
                        for (lk = dlink->parent; lk != NULL; lk = lk->parent) {
                        /* Inlined function. Get a real subprogram */
                        for (lk = dlink->parent; lk != NULL; lk = lk->parent) {
-                               tag = 0;
-                               dwarf_tag(lk->die, &tag, &__dw_error);
-                               DIE_IF(ret == DW_DLV_ERROR);
+                               tag = dwarf_tag(&lk->die);
                                if (tag == DW_TAG_subprogram &&
                                if (tag == DW_TAG_subprogram &&
-                                   !die_inlined_subprogram(lk->die))
+                                   !dwarf_func_inline(&lk->die))
                                        goto found;
                        }
                        die("Failed to find real subprogram.");
 found:
                        /* Get offset from subprogram */
                                        goto found;
                        }
                        die("Failed to find real subprogram.");
 found:
                        /* Get offset from subprogram */
-                       ret = die_within_subprogram(lk->die, pf->addr, &offs);
+                       ret = die_within_subprogram(&lk->die, pf->addr, &offs);
                        DIE_IF(!ret);
                        DIE_IF(!ret);
-                       show_probe_point(lk->die, offs, pf);
+                       show_probe_point(&lk->die, offs, pf);
                        /* Continue to search */
                }
        }
                        /* Continue to search */
                }
        }
@@ -700,43 +544,43 @@ found:
 
 static void find_probe_point_by_func(struct probe_finder *pf)
 {
 
 static void find_probe_point_by_func(struct probe_finder *pf)
 {
-       search_die_from_children(pf->cu_die, probefunc_callback, pf);
+       search_die_from_children(&pf->cu_die, probe_point_search_cb, pf);
 }
 
 /* Find a probe point */
 int find_probe_point(int fd, struct probe_point *pp)
 {
 }
 
 /* Find a probe point */
 int find_probe_point(int fd, struct probe_point *pp)
 {
-       Dwarf_Half addr_size = 0;
-       Dwarf_Unsigned next_cuh = 0;
-       int cu_number = 0, ret;
        struct probe_finder pf = {.pp = pp};
        struct probe_finder pf = {.pp = pp};
-
-       ret = dwarf_init(fd, DW_DLC_READ, 0, 0, &__dw_debug, &__dw_error);
-       if (ret != DW_DLV_OK)
+       int ret;
+       Dwarf_Off off, noff;
+       size_t cuhl;
+       Dwarf_Die *diep;
+       Dwarf *dbg;
+       int fno = 0;
+
+       dbg = dwarf_begin(fd, DWARF_C_READ);
+       if (!dbg)
                return -ENOENT;
 
        pp->found = 0;
                return -ENOENT;
 
        pp->found = 0;
-       while (++cu_number) {
-               /* Search CU (Compilation Unit) */
-               ret = dwarf_next_cu_header(__dw_debug, NULL, NULL, NULL,
-                       &addr_size, &next_cuh, &__dw_error);
-               DIE_IF(ret == DW_DLV_ERROR);
-               if (ret == DW_DLV_NO_ENTRY)
-                       break;
-
+       off = 0;
+       /* Loop on CUs (Compilation Unit) */
+       while (!dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL)) {
                /* Get the DIE(Debugging Information Entry) of this CU */
                /* Get the DIE(Debugging Information Entry) of this CU */
-               ret = dwarf_siblingof(__dw_debug, 0, &pf.cu_die, &__dw_error);
-               DIE_IF(ret != DW_DLV_OK);
+               diep = dwarf_offdie(dbg, off + cuhl, &pf.cu_die);
+               if (!diep)
+                       continue;
 
                /* Check if target file is included. */
                if (pp->file)
 
                /* Check if target file is included. */
                if (pp->file)
-                       pf.fno = cu_find_fileno(pf.cu_die, pp->file);
+                       fno = cu_find_fileno(&pf.cu_die, pp->file);
+               else
+                       fno = 0;
 
 
-               if (!pp->file || pf.fno) {
+               if (!pp->file || fno) {
                        /* Save CU base address (for frame_base) */
                        /* Save CU base address (for frame_base) */
-                       ret = dwarf_lowpc(pf.cu_die, &pf.cu_base, &__dw_error);
-                       DIE_IF(ret == DW_DLV_ERROR);
-                       if (ret == DW_DLV_NO_ENTRY)
+                       ret = dwarf_lowpc(&pf.cu_die, &pf.cu_base);
+                       if (ret != 0)
                                pf.cu_base = 0;
                        if (pp->function)
                                find_probe_point_by_func(&pf);
                                pf.cu_base = 0;
                        if (pp->function)
                                find_probe_point_by_func(&pf);
@@ -745,10 +589,9 @@ int find_probe_point(int fd, struct probe_point *pp)
                                find_probe_point_by_line(&pf);
                        }
                }
                                find_probe_point_by_line(&pf);
                        }
                }
-               dwarf_dealloc(__dw_debug, pf.cu_die, DW_DLA_DIE);
+               off = noff;
        }
        }
-       ret = dwarf_finish(__dw_debug, &__dw_error);
-       DIE_IF(ret != DW_DLV_OK);
+       dwarf_end(dbg);
 
        return pp->found;
 }
 
        return pp->found;
 }
@@ -781,69 +624,76 @@ found:
 /* Find line range from its line number */
 static void find_line_range_by_line(struct line_finder *lf)
 {
 /* Find line range from its line number */
 static void find_line_range_by_line(struct line_finder *lf)
 {
-       Dwarf_Signed cnt, i;
-       Dwarf_Line *lines;
-       Dwarf_Unsigned lineno = 0;
-       Dwarf_Unsigned fno;
+       Dwarf_Lines *lines;
+       Dwarf_Line *line;
+       size_t nlines, i;
        Dwarf_Addr addr;
        Dwarf_Addr addr;
+       int lineno;
        int ret;
        int ret;
+       const char *src;
 
        INIT_LIST_HEAD(&lf->lr->line_list);
 
        INIT_LIST_HEAD(&lf->lr->line_list);
-       ret = dwarf_srclines(lf->cu_die, &lines, &cnt, &__dw_error);
-       DIE_IF(ret != DW_DLV_OK);
+       ret = dwarf_getsrclines(&lf->cu_die, &lines, &nlines);
+       DIE_IF(ret != 0);
 
 
-       for (i = 0; i < cnt; i++) {
-               ret = dwarf_line_srcfileno(lines[i], &fno, &__dw_error);
-               DIE_IF(ret != DW_DLV_OK);
-               if (fno != lf->fno)
+       for (i = 0; i < nlines; i++) {
+               line = dwarf_onesrcline(lines, i);
+               dwarf_lineno(line, &lineno);
+               if (lf->lno_s > lineno || lf->lno_e < lineno)
                        continue;
 
                        continue;
 
-               ret = dwarf_lineno(lines[i], &lineno, &__dw_error);
-               DIE_IF(ret != DW_DLV_OK);
-               if (lf->lno_s > lineno || lf->lno_e < lineno)
+               /* TODO: Get fileno from line, but how? */
+               src = dwarf_linesrc(line, NULL, NULL);
+               if (strtailcmp(src, lf->fname) != 0)
                        continue;
 
                /* Filter line in the function address range */
                if (lf->addr_s && lf->addr_e) {
                        continue;
 
                /* Filter line in the function address range */
                if (lf->addr_s && lf->addr_e) {
-                       ret = dwarf_lineaddr(lines[i], &addr, &__dw_error);
-                       DIE_IF(ret != DW_DLV_OK);
+                       ret = dwarf_lineaddr(line, &addr);
+                       DIE_IF(ret != 0);
                        if (lf->addr_s > addr || lf->addr_e <= addr)
                                continue;
                }
                        if (lf->addr_s > addr || lf->addr_e <= addr)
                                continue;
                }
+               /* Copy real path */
+               if (!lf->lr->path)
+                       lf->lr->path = strdup(src);
                line_range_add_line(lf->lr, (unsigned int)lineno);
        }
                line_range_add_line(lf->lr, (unsigned int)lineno);
        }
-       dwarf_srclines_dealloc(__dw_debug, lines, cnt);
+       /* Update status */
        if (!list_empty(&lf->lr->line_list))
                lf->found = 1;
        if (!list_empty(&lf->lr->line_list))
                lf->found = 1;
+       else {
+               free(lf->lr->path);
+               lf->lr->path = NULL;
+       }
 }
 
 /* Search function from function name */
 }
 
 /* Search function from function name */
-static int linefunc_callback(struct die_link *dlink, void *data)
+static int line_range_search_cb(struct die_link *dlink, void *data)
 {
        struct line_finder *lf = (struct line_finder *)data;
        struct line_range *lr = lf->lr;
 {
        struct line_finder *lf = (struct line_finder *)data;
        struct line_range *lr = lf->lr;
-       Dwarf_Half tag;
+       int tag;
        int ret;
 
        int ret;
 
-       ret = dwarf_tag(dlink->die, &tag, &__dw_error);
-       DIE_IF(ret == DW_DLV_ERROR);
+       tag = dwarf_tag(&dlink->die);
        if (tag == DW_TAG_subprogram &&
        if (tag == DW_TAG_subprogram &&
-           die_compare_name(dlink->die, lr->function) == 0) {
+           die_compare_name(&dlink->die, lr->function) == 0) {
                /* Get the address range of this function */
                /* Get the address range of this function */
-               ret = dwarf_highpc(dlink->die, &lf->addr_e, &__dw_error);
-               if (ret == DW_DLV_OK)
-                       ret = dwarf_lowpc(dlink->die, &lf->addr_s, &__dw_error);
-               DIE_IF(ret == DW_DLV_ERROR);
-               if (ret == DW_DLV_NO_ENTRY) {
+               ret = dwarf_highpc(&dlink->die, &lf->addr_e);
+               if (ret == 0)
+                       ret = dwarf_lowpc(&dlink->die, &lf->addr_s);
+               if (ret != 0) {
                        lf->addr_s = 0;
                        lf->addr_e = 0;
                }
 
                        lf->addr_s = 0;
                        lf->addr_e = 0;
                }
 
-               lf->fno = die_get_decl_file(dlink->die);
-               lr->offset = die_get_decl_line(dlink->die);;
+               lf->fname = dwarf_decl_file(&dlink->die);
+               dwarf_decl_line(&dlink->die, &lr->offset);
+               pr_debug("fname: %s, lineno:%d\n", lf->fname, lr->offset);
                lf->lno_s = lr->offset + lr->start;
                if (!lr->end)
                lf->lno_s = lr->offset + lr->start;
                if (!lr->end)
-                       lf->lno_e = (Dwarf_Unsigned)-1;
+                       lf->lno_e = INT_MAX;
                else
                        lf->lno_e = lr->offset + lr->end;
                lr->start = lf->lno_s;
                else
                        lf->lno_e = lr->offset + lr->end;
                lr->start = lf->lno_s;
@@ -856,55 +706,57 @@ static int linefunc_callback(struct die_link *dlink, void *data)
 
 static void find_line_range_by_func(struct line_finder *lf)
 {
 
 static void find_line_range_by_func(struct line_finder *lf)
 {
-       search_die_from_children(lf->cu_die, linefunc_callback, lf);
+       search_die_from_children(&lf->cu_die, line_range_search_cb, lf);
 }
 
 int find_line_range(int fd, struct line_range *lr)
 {
 }
 
 int find_line_range(int fd, struct line_range *lr)
 {
-       Dwarf_Half addr_size = 0;
-       Dwarf_Unsigned next_cuh = 0;
+       struct line_finder lf = {.lr = lr, .found = 0};
        int ret;
        int ret;
-       struct line_finder lf = {.lr = lr};
-
-       ret = dwarf_init(fd, DW_DLC_READ, 0, 0, &__dw_debug, &__dw_error);
-       if (ret != DW_DLV_OK)
+       Dwarf_Off off = 0, noff;
+       size_t cuhl;
+       Dwarf_Die *diep;
+       Dwarf *dbg;
+       int fno;
+
+       dbg = dwarf_begin(fd, DWARF_C_READ);
+       if (!dbg)
                return -ENOENT;
 
                return -ENOENT;
 
+       /* Loop on CUs (Compilation Unit) */
        while (!lf.found) {
        while (!lf.found) {
-               /* Search CU (Compilation Unit) */
-               ret = dwarf_next_cu_header(__dw_debug, NULL, NULL, NULL,
-                       &addr_size, &next_cuh, &__dw_error);
-               DIE_IF(ret == DW_DLV_ERROR);
-               if (ret == DW_DLV_NO_ENTRY)
+               ret = dwarf_nextcu(dbg, off, &noff, &cuhl, NULL, NULL, NULL);
+               if (ret != 0)
                        break;
 
                /* Get the DIE(Debugging Information Entry) of this CU */
                        break;
 
                /* Get the DIE(Debugging Information Entry) of this CU */
-               ret = dwarf_siblingof(__dw_debug, 0, &lf.cu_die, &__dw_error);
-               DIE_IF(ret != DW_DLV_OK);
+               diep = dwarf_offdie(dbg, off + cuhl, &lf.cu_die);
+               if (!diep)
+                       continue;
 
                /* Check if target file is included. */
                if (lr->file)
 
                /* Check if target file is included. */
                if (lr->file)
-                       lf.fno = cu_find_fileno(lf.cu_die, lr->file);
+                       fno = cu_find_fileno(&lf.cu_die, lr->file);
+               else
+                       fno = 0;
 
 
-               if (!lr->file || lf.fno) {
+               if (!lr->file || fno) {
                        if (lr->function)
                                find_line_range_by_func(&lf);
                        else {
                        if (lr->function)
                                find_line_range_by_func(&lf);
                        else {
+                               lf.fname = lr->file;
                                lf.lno_s = lr->start;
                                if (!lr->end)
                                lf.lno_s = lr->start;
                                if (!lr->end)
-                                       lf.lno_e = (Dwarf_Unsigned)-1;
+                                       lf.lno_e = INT_MAX;
                                else
                                        lf.lno_e = lr->end;
                                find_line_range_by_line(&lf);
                        }
                                else
                                        lf.lno_e = lr->end;
                                find_line_range_by_line(&lf);
                        }
-                       /* Get the real file path */
-                       if (lf.found)
-                               cu_get_filename(lf.cu_die, lf.fno, &lr->path);
                }
                }
-               dwarf_dealloc(__dw_debug, lf.cu_die, DW_DLA_DIE);
+               off = noff;
        }
        }
-       ret = dwarf_finish(__dw_debug, &__dw_error);
-       DIE_IF(ret != DW_DLV_OK);
+       pr_debug("path: %lx\n", (unsigned long)lr->path);
+       dwarf_end(dbg);
        return lf.found;
 }
 
        return lf.found;
 }
 
index b2a2524..9dd4a88 100644 (file)
@@ -1,6 +1,7 @@
 #ifndef _PROBE_FINDER_H
 #define _PROBE_FINDER_H
 
 #ifndef _PROBE_FINDER_H
 #define _PROBE_FINDER_H
 
+#include <stdbool.h>
 #include "util.h"
 
 #define MAX_PATH_LEN            256
 #include "util.h"
 
 #define MAX_PATH_LEN            256
@@ -46,53 +47,48 @@ struct line_range {
        char                    *function;              /* Function name */
        unsigned int            start;                  /* Start line number */
        unsigned int            end;                    /* End line number */
        char                    *function;              /* Function name */
        unsigned int            start;                  /* Start line number */
        unsigned int            end;                    /* End line number */
-       unsigned int            offset;                 /* Start line offset */
+       int                     offset;                 /* Start line offset */
        char                    *path;                  /* Real path name */
        struct list_head        line_list;              /* Visible lines */
 };
 
        char                    *path;                  /* Real path name */
        struct list_head        line_list;              /* Visible lines */
 };
 
-#ifndef NO_LIBDWARF
+#ifndef NO_DWARF_SUPPORT
 extern int find_probe_point(int fd, struct probe_point *pp);
 extern int find_line_range(int fd, struct line_range *lr);
 
 extern int find_probe_point(int fd, struct probe_point *pp);
 extern int find_line_range(int fd, struct line_range *lr);
 
-/* Workaround for undefined _MIPS_SZLONG bug in libdwarf.h: */
-#ifndef _MIPS_SZLONG
-# define _MIPS_SZLONG          0
-#endif
-
 #include <dwarf.h>
 #include <dwarf.h>
-#include <libdwarf.h>
+#include <libdw.h>
 
 struct probe_finder {
 
 struct probe_finder {
-       struct probe_point      *pp;                    /* Target probe point */
+       struct probe_point      *pp;            /* Target probe point */
 
        /* For function searching */
 
        /* For function searching */
-       Dwarf_Addr              addr;                   /* Address */
-       Dwarf_Unsigned          fno;                    /* File number */
-       Dwarf_Unsigned          lno;                    /* Line number */
-       Dwarf_Off               inl_offs;               /* Inline offset */
-       Dwarf_Die               cu_die;                 /* Current CU */
+       Dwarf_Addr              addr;           /* Address */
+       const char              *fname;         /* File name */
+       int                     lno;            /* Line number */
+       void                    *origin;        /* Inline origin addr */
+       Dwarf_Die               cu_die;         /* Current CU */
 
        /* For variable searching */
 
        /* For variable searching */
-       Dwarf_Addr              cu_base;                /* Current CU base address */
-       Dwarf_Locdesc           fbloc;                  /* Location of Current Frame Base */
-       const char              *var;                   /* Current variable name */
-       char                    *buf;                   /* Current output buffer */
-       int                     len;                    /* Length of output buffer */
+       Dwarf_Op                *fb_ops;        /* Frame base attribute */
+       Dwarf_Addr              cu_base;        /* Current CU base address */
+       const char              *var;           /* Current variable name */
+       char                    *buf;           /* Current output buffer */
+       int                     len;            /* Length of output buffer */
 };
 
 struct line_finder {
 };
 
 struct line_finder {
-       struct line_range       *lr;                    /* Target line range */
-
-       Dwarf_Unsigned          fno;                    /* File number */
-       Dwarf_Unsigned          lno_s;                  /* Start line number */
-       Dwarf_Unsigned          lno_e;                  /* End line number */
-       Dwarf_Addr              addr_s;                 /* Start address */
-       Dwarf_Addr              addr_e;                 /* End address */
-       Dwarf_Die               cu_die;                 /* Current CU */
+       struct line_range       *lr;            /* Target line range */
+
+       const char              *fname;         /* File name */
+       int                     lno_s;          /* Start line number */
+       int                     lno_e;          /* End line number */
+       Dwarf_Addr              addr_s;         /* Start address */
+       Dwarf_Addr              addr_e;         /* End address */
+       Dwarf_Die               cu_die;         /* Current CU */
        int                     found;
 };
 
        int                     found;
 };
 
-#endif /* NO_LIBDWARF */
+#endif /* NO_DWARF_SUPPORT */
 
 #endif /*_PROBE_FINDER_H */
 
 #endif /*_PROBE_FINDER_H */