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