|
@@ -44,8 +44,6 @@ struct die_link {
|
|
|
Dwarf_Die die; /* Current die */
|
|
|
};
|
|
|
|
|
|
-static Dwarf_Debug __dw_debug;
|
|
|
-static Dwarf_Error __dw_error;
|
|
|
|
|
|
/*
|
|
|
* Generic dwarf analysis helpers
|
|
@@ -114,157 +112,114 @@ static int strtailcmp(const char *s1, const char *s2)
|
|
|
}
|
|
|
|
|
|
/* 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)
|
|
|
- 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 */
|
|
|
-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). */
|
|
|
-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;
|
|
|
|
|
|
- /* 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;
|
|
|
|
|
|
- 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_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)
|
|
|
{
|
|
|
- Dwarf_Die new_die;
|
|
|
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 */
|
|
|
- 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.die = new_die;
|
|
|
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;
|
|
|
}
|
|
|
- dwarf_dealloc(__dw_debug, cur_link->die, DW_DLA_DIE);
|
|
|
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)
|
|
|
{
|
|
@@ -317,125 +264,58 @@ static int search_die_from_children(Dwarf_Die parent_die,
|
|
|
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;
|
|
|
}
|
|
|
|
|
|
-/* 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 */
|
|
|
-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;
|
|
|
|
|
|
- op = loc->lr_atom;
|
|
|
-
|
|
|
+ /* TODO: support CFA */
|
|
|
/* 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;
|
|
|
- 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;
|
|
|
- } 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;
|
|
|
- } else if (op == DW_OP_regx) {
|
|
|
- regn = loc->lr_number;
|
|
|
+ } else if (op->atom == DW_OP_regx) {
|
|
|
+ regn = op->number;
|
|
|
} 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)
|
|
|
- die("%lld exceeds max register number.", regn);
|
|
|
+ die("%u exceeds max register number.", regn);
|
|
|
|
|
|
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);
|
|
@@ -443,41 +323,41 @@ static void show_location(Dwarf_Loc *loc, struct probe_finder *pf)
|
|
|
}
|
|
|
|
|
|
/* 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_Locdesc ld;
|
|
|
+ Dwarf_Op *expr;
|
|
|
+ size_t nexpr;
|
|
|
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;
|
|
|
- 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;
|
|
|
- /* 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:
|
|
|
+ /* TODO: Support const_value */
|
|
|
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;
|
|
|
- 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) &&
|
|
|
- (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 */
|
|
@@ -485,7 +365,7 @@ static int variable_callback(struct die_link *dlink, void *data)
|
|
|
}
|
|
|
|
|
|
/* 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;
|
|
|
|
|
@@ -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. */
|
|
|
- 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);
|
|
|
}
|
|
|
|
|
|
-/* 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 */
|
|
|
-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;
|
|
|
- char *name;
|
|
|
+ const char *name;
|
|
|
char tmp[MAX_PROBE_BUFFER];
|
|
|
int ret, i, len;
|
|
|
+ Dwarf_Attribute fb_attr;
|
|
|
+ size_t nops;
|
|
|
|
|
|
/* 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 */
|
|
@@ -543,14 +405,14 @@ static void show_probe_point(Dwarf_Die sp_die, Dwarf_Signed offs,
|
|
|
pp->function = strdup(name);
|
|
|
pp->offset = offs;
|
|
|
}
|
|
|
- dwarf_dealloc(__dw_debug, name, DW_DLA_STRING);
|
|
|
} 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("");
|
|
|
- pp->offset = (int)pf->addr;
|
|
|
+ pp->offset = (size_t)pf->addr;
|
|
|
}
|
|
|
}
|
|
|
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);
|
|
|
|
|
|
+ /* 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 */
|
|
|
- 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];
|
|
@@ -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);
|
|
|
}
|
|
|
- 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++;
|
|
|
}
|
|
|
|
|
|
-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)
|
|
|
{
|
|
|
- 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;
|
|
|
+ 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;
|
|
|
|
|
|
- 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;
|
|
|
- /* 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.");
|
|
|
+ dwarf_entrypc(sp_die, &epc);
|
|
|
+ show_probe_point(sp_die, (size_t)(addr - epc), pf);
|
|
|
/* Continuing, because target line might be inlined. */
|
|
|
}
|
|
|
- dwarf_srclines_dealloc(__dw_debug, lines, cnt);
|
|
|
}
|
|
|
|
|
|
+
|
|
|
/* 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;
|
|
|
- Dwarf_Signed offs;
|
|
|
- Dwarf_Half tag;
|
|
|
+ size_t offs;
|
|
|
+ int tag;
|
|
|
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 (die_compare_name(dlink->die, pp->function) == 0) {
|
|
|
+ if (die_compare_name(&dlink->die, pp->function) == 0) {
|
|
|
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;
|
|
|
}
|
|
|
- if (die_inlined_subprogram(dlink->die)) {
|
|
|
+ if (dwarf_func_inline(&dlink->die)) {
|
|
|
/* 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 */
|
|
|
- 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 */
|
|
|
- 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. */
|
|
|
}
|
|
|
- } 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 */
|
|
|
- pf->addr = die_get_entrypc(dlink->die);
|
|
|
+ pf->addr = die_get_entrypc(&dlink->die);
|
|
|
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) {
|
|
|
- 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 &&
|
|
|
- !die_inlined_subprogram(lk->die))
|
|
|
+ !dwarf_func_inline(&lk->die))
|
|
|
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);
|
|
|
- show_probe_point(lk->die, offs, pf);
|
|
|
+ show_probe_point(&lk->die, offs, pf);
|
|
|
/* Continue to search */
|
|
|
}
|
|
|
}
|
|
@@ -700,43 +544,43 @@ found:
|
|
|
|
|
|
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)
|
|
|
{
|
|
|
- Dwarf_Half addr_size = 0;
|
|
|
- Dwarf_Unsigned next_cuh = 0;
|
|
|
- int cu_number = 0, ret;
|
|
|
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;
|
|
|
- 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 */
|
|
|
- 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)
|
|
|
- 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) */
|
|
|
- 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);
|
|
@@ -745,10 +589,9 @@ int find_probe_point(int fd, struct probe_point *pp)
|
|
|
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;
|
|
|
}
|
|
@@ -781,69 +624,76 @@ found:
|
|
|
/* 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;
|
|
|
+ int lineno;
|
|
|
int ret;
|
|
|
+ const char *src;
|
|
|
|
|
|
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;
|
|
|
|
|
|
- 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) {
|
|
|
- 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;
|
|
|
}
|
|
|
+ /* Copy real path */
|
|
|
+ if (!lf->lr->path)
|
|
|
+ lf->lr->path = strdup(src);
|
|
|
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;
|
|
|
+ else {
|
|
|
+ free(lf->lr->path);
|
|
|
+ lf->lr->path = NULL;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/* 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;
|
|
|
- Dwarf_Half tag;
|
|
|
+ int tag;
|
|
|
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 &&
|
|
|
- die_compare_name(dlink->die, lr->function) == 0) {
|
|
|
+ die_compare_name(&dlink->die, lr->function) == 0) {
|
|
|
/* 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->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_e = (Dwarf_Unsigned)-1;
|
|
|
+ lf->lno_e = INT_MAX;
|
|
|
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)
|
|
|
{
|
|
|
- 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)
|
|
|
{
|
|
|
- Dwarf_Half addr_size = 0;
|
|
|
- Dwarf_Unsigned next_cuh = 0;
|
|
|
+ struct line_finder lf = {.lr = lr, .found = 0};
|
|
|
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;
|
|
|
|
|
|
+ /* Loop on CUs (Compilation Unit) */
|
|
|
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 */
|
|
|
- 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)
|
|
|
- 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 {
|
|
|
+ lf.fname = lr->file;
|
|
|
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);
|
|
|
}
|
|
|
- /* 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;
|
|
|
}
|
|
|
|