1*7304104dSAndroid Build Coastguard Worker /* Get attributes of the DIE.
2*7304104dSAndroid Build Coastguard Worker Copyright (C) 2004, 2005, 2008, 2009, 2014, 2017 Red Hat, Inc.
3*7304104dSAndroid Build Coastguard Worker This file is part of elfutils.
4*7304104dSAndroid Build Coastguard Worker Written by Ulrich Drepper <[email protected]>, 2004.
5*7304104dSAndroid Build Coastguard Worker
6*7304104dSAndroid Build Coastguard Worker This file is free software; you can redistribute it and/or modify
7*7304104dSAndroid Build Coastguard Worker it under the terms of either
8*7304104dSAndroid Build Coastguard Worker
9*7304104dSAndroid Build Coastguard Worker * the GNU Lesser General Public License as published by the Free
10*7304104dSAndroid Build Coastguard Worker Software Foundation; either version 3 of the License, or (at
11*7304104dSAndroid Build Coastguard Worker your option) any later version
12*7304104dSAndroid Build Coastguard Worker
13*7304104dSAndroid Build Coastguard Worker or
14*7304104dSAndroid Build Coastguard Worker
15*7304104dSAndroid Build Coastguard Worker * the GNU General Public License as published by the Free
16*7304104dSAndroid Build Coastguard Worker Software Foundation; either version 2 of the License, or (at
17*7304104dSAndroid Build Coastguard Worker your option) any later version
18*7304104dSAndroid Build Coastguard Worker
19*7304104dSAndroid Build Coastguard Worker or both in parallel, as here.
20*7304104dSAndroid Build Coastguard Worker
21*7304104dSAndroid Build Coastguard Worker elfutils is distributed in the hope that it will be useful, but
22*7304104dSAndroid Build Coastguard Worker WITHOUT ANY WARRANTY; without even the implied warranty of
23*7304104dSAndroid Build Coastguard Worker MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24*7304104dSAndroid Build Coastguard Worker General Public License for more details.
25*7304104dSAndroid Build Coastguard Worker
26*7304104dSAndroid Build Coastguard Worker You should have received copies of the GNU General Public License and
27*7304104dSAndroid Build Coastguard Worker the GNU Lesser General Public License along with this program. If
28*7304104dSAndroid Build Coastguard Worker not, see <http://www.gnu.org/licenses/>. */
29*7304104dSAndroid Build Coastguard Worker
30*7304104dSAndroid Build Coastguard Worker #ifdef HAVE_CONFIG_H
31*7304104dSAndroid Build Coastguard Worker # include <config.h>
32*7304104dSAndroid Build Coastguard Worker #endif
33*7304104dSAndroid Build Coastguard Worker
34*7304104dSAndroid Build Coastguard Worker #include "libdwP.h"
35*7304104dSAndroid Build Coastguard Worker
36*7304104dSAndroid Build Coastguard Worker
37*7304104dSAndroid Build Coastguard Worker ptrdiff_t
dwarf_getattrs(Dwarf_Die * die,int (* callback)(Dwarf_Attribute *,void *),void * arg,ptrdiff_t offset)38*7304104dSAndroid Build Coastguard Worker dwarf_getattrs (Dwarf_Die *die, int (*callback) (Dwarf_Attribute *, void *),
39*7304104dSAndroid Build Coastguard Worker void *arg, ptrdiff_t offset)
40*7304104dSAndroid Build Coastguard Worker {
41*7304104dSAndroid Build Coastguard Worker if (die == NULL)
42*7304104dSAndroid Build Coastguard Worker return -1l;
43*7304104dSAndroid Build Coastguard Worker
44*7304104dSAndroid Build Coastguard Worker if (unlikely (offset == 1))
45*7304104dSAndroid Build Coastguard Worker return 1;
46*7304104dSAndroid Build Coastguard Worker
47*7304104dSAndroid Build Coastguard Worker const unsigned char *die_addr = NULL;
48*7304104dSAndroid Build Coastguard Worker
49*7304104dSAndroid Build Coastguard Worker /* Find the abbreviation entry. */
50*7304104dSAndroid Build Coastguard Worker Dwarf_Abbrev *abbrevp = __libdw_dieabbrev (die, &die_addr);
51*7304104dSAndroid Build Coastguard Worker
52*7304104dSAndroid Build Coastguard Worker if (unlikely (abbrevp == DWARF_END_ABBREV))
53*7304104dSAndroid Build Coastguard Worker {
54*7304104dSAndroid Build Coastguard Worker __libdw_seterrno (DWARF_E_INVALID_DWARF);
55*7304104dSAndroid Build Coastguard Worker return -1l;
56*7304104dSAndroid Build Coastguard Worker }
57*7304104dSAndroid Build Coastguard Worker
58*7304104dSAndroid Build Coastguard Worker const unsigned char *endp = die->cu->endp;
59*7304104dSAndroid Build Coastguard Worker
60*7304104dSAndroid Build Coastguard Worker /* This is where the attributes start. */
61*7304104dSAndroid Build Coastguard Worker const unsigned char *attrp = abbrevp->attrp;
62*7304104dSAndroid Build Coastguard Worker const unsigned char *const offset_attrp = abbrevp->attrp + offset;
63*7304104dSAndroid Build Coastguard Worker
64*7304104dSAndroid Build Coastguard Worker /* Go over the list of attributes. */
65*7304104dSAndroid Build Coastguard Worker while (1)
66*7304104dSAndroid Build Coastguard Worker {
67*7304104dSAndroid Build Coastguard Worker /* Get attribute name and form. Dwarf_Abbrev was checked when
68*7304104dSAndroid Build Coastguard Worker created, so we can read unchecked. */
69*7304104dSAndroid Build Coastguard Worker Dwarf_Attribute attr;
70*7304104dSAndroid Build Coastguard Worker const unsigned char *remembered_attrp = attrp;
71*7304104dSAndroid Build Coastguard Worker
72*7304104dSAndroid Build Coastguard Worker get_uleb128_unchecked (attr.code, attrp);
73*7304104dSAndroid Build Coastguard Worker get_uleb128_unchecked (attr.form, attrp);
74*7304104dSAndroid Build Coastguard Worker
75*7304104dSAndroid Build Coastguard Worker /* We can stop if we found the attribute with value zero. */
76*7304104dSAndroid Build Coastguard Worker if (attr.code == 0 && attr.form == 0)
77*7304104dSAndroid Build Coastguard Worker /* Do not return 0 here - there would be no way to
78*7304104dSAndroid Build Coastguard Worker distinguish this value from the attribute at offset 0.
79*7304104dSAndroid Build Coastguard Worker Instead we return +1 which would never be a valid
80*7304104dSAndroid Build Coastguard Worker offset of an attribute. */
81*7304104dSAndroid Build Coastguard Worker return 1l;
82*7304104dSAndroid Build Coastguard Worker
83*7304104dSAndroid Build Coastguard Worker if (attr.form == DW_FORM_indirect)
84*7304104dSAndroid Build Coastguard Worker {
85*7304104dSAndroid Build Coastguard Worker get_uleb128 (attr.form, die_addr, endp);
86*7304104dSAndroid Build Coastguard Worker if (attr.form == DW_FORM_indirect ||
87*7304104dSAndroid Build Coastguard Worker attr.form == DW_FORM_implicit_const)
88*7304104dSAndroid Build Coastguard Worker {
89*7304104dSAndroid Build Coastguard Worker __libdw_seterrno (DWARF_E_INVALID_DWARF);
90*7304104dSAndroid Build Coastguard Worker return -1l;
91*7304104dSAndroid Build Coastguard Worker }
92*7304104dSAndroid Build Coastguard Worker }
93*7304104dSAndroid Build Coastguard Worker
94*7304104dSAndroid Build Coastguard Worker /* If we are not to OFFSET_ATTRP yet, we just have to skip
95*7304104dSAndroid Build Coastguard Worker the values of the intervening attributes. */
96*7304104dSAndroid Build Coastguard Worker if (remembered_attrp >= offset_attrp)
97*7304104dSAndroid Build Coastguard Worker {
98*7304104dSAndroid Build Coastguard Worker /* Fill in the rest. */
99*7304104dSAndroid Build Coastguard Worker if (attr.form == DW_FORM_implicit_const)
100*7304104dSAndroid Build Coastguard Worker attr.valp = (unsigned char *) attrp;
101*7304104dSAndroid Build Coastguard Worker else
102*7304104dSAndroid Build Coastguard Worker attr.valp = (unsigned char *) die_addr;
103*7304104dSAndroid Build Coastguard Worker attr.cu = die->cu;
104*7304104dSAndroid Build Coastguard Worker
105*7304104dSAndroid Build Coastguard Worker /* Now call the callback function. */
106*7304104dSAndroid Build Coastguard Worker if (callback (&attr, arg) != DWARF_CB_OK)
107*7304104dSAndroid Build Coastguard Worker /* Return the offset of the start of the attribute, so that
108*7304104dSAndroid Build Coastguard Worker dwarf_getattrs() can be restarted from this point if the
109*7304104dSAndroid Build Coastguard Worker caller so desires. */
110*7304104dSAndroid Build Coastguard Worker return remembered_attrp - abbrevp->attrp;
111*7304104dSAndroid Build Coastguard Worker }
112*7304104dSAndroid Build Coastguard Worker
113*7304104dSAndroid Build Coastguard Worker /* Skip over the rest of this attribute (if there is any). */
114*7304104dSAndroid Build Coastguard Worker if (attr.form != 0)
115*7304104dSAndroid Build Coastguard Worker {
116*7304104dSAndroid Build Coastguard Worker size_t len = __libdw_form_val_len (die->cu, attr.form, die_addr);
117*7304104dSAndroid Build Coastguard Worker if (unlikely (len == (size_t) -1l))
118*7304104dSAndroid Build Coastguard Worker /* Something wrong with the file. */
119*7304104dSAndroid Build Coastguard Worker return -1l;
120*7304104dSAndroid Build Coastguard Worker
121*7304104dSAndroid Build Coastguard Worker // __libdw_form_val_len will have done a bounds check.
122*7304104dSAndroid Build Coastguard Worker die_addr += len;
123*7304104dSAndroid Build Coastguard Worker
124*7304104dSAndroid Build Coastguard Worker if (attr.form == DW_FORM_implicit_const)
125*7304104dSAndroid Build Coastguard Worker {
126*7304104dSAndroid Build Coastguard Worker int64_t attr_value __attribute__((__unused__));
127*7304104dSAndroid Build Coastguard Worker get_sleb128_unchecked (attr_value, attrp);
128*7304104dSAndroid Build Coastguard Worker }
129*7304104dSAndroid Build Coastguard Worker }
130*7304104dSAndroid Build Coastguard Worker }
131*7304104dSAndroid Build Coastguard Worker /* NOTREACHED */
132*7304104dSAndroid Build Coastguard Worker }
133