--- /dev/null
+/* Get definition DIE of function.
+ Copyright (C) 2005 Red Hat, Inc.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <dwarf.h>
+#include "libdwP.h"
+
+
+Dwarf_Die *
+dwarf_func_die (Dwarf_Func *func, Dwarf_Die *die_mem)
+{
+ *die_mem = *func->die;
+ return die_mem;
+}
--- /dev/null
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+#include <dwarf.h>
+
+struct visitor_info
+{
+ void *die_addr;
+ int (*callback) (Dwarf_Die *, void *);
+ void *arg;
+};
+
+static int
+scope_visitor (unsigned int depth __attribute__ ((unused)),
+ Dwarf_Die *die, void *arg)
+{
+ struct visitor_info *const v = arg;
+
+ if (INTUSE(dwarf_tag) (die) != DW_TAG_inlined_subroutine)
+ return DWARF_CB_OK;
+
+ Dwarf_Attribute attr_mem;
+ Dwarf_Attribute *attr = INTUSE(dwarf_attr) (die, DW_AT_abstract_origin,
+ &attr_mem);
+ if (attr == NULL)
+ return DWARF_CB_OK;
+
+ Dwarf_Die origin_mem;
+ Dwarf_Die *origin = INTUSE(dwarf_formref_die) (attr, &origin_mem);
+ if (origin == NULL)
+ return DWARF_CB_ABORT;
+
+ if (origin->addr != v->die_addr)
+ return DWARF_CB_OK;
+
+ return (*v->callback) (die, v->arg);
+}
+
+int
+dwarf_func_inline (Dwarf_Func *func)
+{
+ Dwarf_Attribute attr_mem;
+ Dwarf_Word val;
+ if (INTUSE(dwarf_formudata) (INTUSE(dwarf_attr) (func->die, DW_AT_inline,
+ &attr_mem),
+ &val) == 0)
+ switch (val)
+ {
+ case DW_INL_not_inlined:
+ return 0;
+
+ case DW_INL_declared_not_inlined:
+ return -1;
+
+ case DW_INL_inlined:
+ case DW_INL_declared_inlined:
+ return 1;
+ }
+
+ return 0;
+}
+
+int
+dwarf_func_inline_instances (Dwarf_Func *func,
+ int (*callback) (Dwarf_Die *, void *),
+ void *arg)
+{
+ struct visitor_info v = { func->die->addr, callback, arg };
+ return __libdw_visit_scopes (0, func->cudie, &scope_visitor, &v);
+}
--- /dev/null
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include "libdwP.h"
+#include <dwarf.h>
+
+enum die_class { ignore, match, match_inline, walk, imported };
+
+static enum die_class
+classify_die (Dwarf_Die *die)
+{
+ switch (INTUSE(dwarf_tag) (die))
+ {
+ /* DIEs with addresses we can try to match. */
+ case DW_TAG_compile_unit:
+ case DW_TAG_module:
+ case DW_TAG_lexical_block:
+ case DW_TAG_with_stmt:
+ case DW_TAG_catch_block:
+ case DW_TAG_try_block:
+ case DW_TAG_entry_point:
+ return match;
+ case DW_TAG_inlined_subroutine:
+ return match_inline;
+ case DW_TAG_subprogram:
+ /* This might be a concrete out-of-line instance of an inline, in
+ which case it is not guaranteed to be owned by the right scope and
+ we will search for its origin as for DW_TAG_inlined_subroutine. */
+ return (INTUSE(dwarf_hasattr) (die, DW_AT_abstract_origin)
+ ? match_inline : match);
+
+ /* DIEs without addresses that can own DIEs with addresses. */
+ case DW_TAG_namespace:
+ return walk;
+
+ /* Special indirection required. */
+ case DW_TAG_imported_unit:
+ return imported;
+
+ /* Other DIEs we have no reason to descend. */
+ default:
+ break;
+ }
+ return ignore;
+}
+
+int
+__libdw_visit_scopes (depth, root, visit, arg)
+ unsigned int depth;
+ Dwarf_Die *root;
+ int (*visit) (unsigned int depth, Dwarf_Die *die, void *arg);
+ void *arg;
+{
+ Dwarf_Die child;
+ if (INTUSE(dwarf_child) (root, &child) != 0)
+ return -1;
+
+ do
+ {
+ int result = (*visit) (depth, &child, arg);
+ if (result != DWARF_CB_OK)
+ return result;
+
+ switch (classify_die (&child))
+ {
+ case match:
+ case match_inline:
+ case walk:
+ if (INTUSE(dwarf_haschildren) (&child))
+ {
+ result = __libdw_visit_scopes (depth + 1, &child, visit, arg);
+ if (result != DWARF_CB_OK)
+ return result;
+ }
+ break;
+
+ case imported:
+ {
+ /* This is imports another compilation unit to appear
+ as part of this one, inside the current scope.
+ Recurse to searesulth the referenced unit, but without
+ recording it as an inner scoping level. */
+
+ Dwarf_Attribute attr_mem;
+ Dwarf_Attribute *attr = INTUSE(dwarf_attr) (&child, DW_AT_import,
+ &attr_mem);
+ if (INTUSE(dwarf_formref_die) (attr, &child) != NULL)
+ {
+ result = __libdw_visit_scopes (depth + 1, &child, visit, arg);
+ if (result != 0)
+ return result;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ while (INTUSE(dwarf_siblingof) (&child, &child) == 0);
+
+ return 0;
+}