summaryrefslogtreecommitdiff
path: root/libdw/dwarf_func_inline.c
blob: 99e656ffbc0e5fb29c8f0d5afae66e37b73e16d1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#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)),
	       struct Dwarf_Die_Chain *die, void *arg)
{
  struct visitor_info *const v = arg;

  if (INTUSE(dwarf_tag) (&die->die) != DW_TAG_inlined_subroutine)
    return DWARF_CB_OK;

  Dwarf_Attribute attr_mem;
  Dwarf_Attribute *attr = INTUSE(dwarf_attr) (&die->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->die, v->arg);
}

int
dwarf_func_inline (Dwarf_Die *func)
{
  Dwarf_Attribute attr_mem;
  Dwarf_Word val;
  if (INTUSE(dwarf_formudata) (INTUSE(dwarf_attr) (func, 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_Die *func,
			     int (*callback) (Dwarf_Die *, void *),
			     void *arg)
{
  struct visitor_info v = { func->addr, callback, arg };
  struct Dwarf_Die_Chain cu = { .die = CUDIE (func->cu), .parent = NULL };
  return __libdw_visit_scopes (0, &cu, &scope_visitor, NULL, &v);
}