Branch data Line data Source code
1 : : /* Get abbreviation at given offset.
2 : : Copyright (C) 2003, 2004, 2005, 2006 Red Hat, Inc.
3 : : This file is part of elfutils.
4 : : Written by Ulrich Drepper <drepper@redhat.com>, 2003.
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 <assert.h>
35 : : #include <dwarf.h>
36 : : #include "libdwP.h"
37 : :
38 : :
39 : : Dwarf_Abbrev *
40 : : internal_function
41 : 933353 : __libdw_getabbrev (dbg, cu, offset, lengthp, result)
42 : : Dwarf *dbg;
43 : : struct Dwarf_CU *cu;
44 : : Dwarf_Off offset;
45 : : size_t *lengthp;
46 : : Dwarf_Abbrev *result;
47 : : {
48 : : /* Don't fail if there is not .debug_abbrev section. */
49 [ + - ]: 933353 : if (dbg->sectiondata[IDX_debug_abbrev] == NULL)
50 : : return NULL;
51 : :
52 [ - + ]: 933353 : if (offset >= dbg->sectiondata[IDX_debug_abbrev]->d_size)
53 : : {
54 : 0 : __libdw_seterrno (DWARF_E_INVALID_OFFSET);
55 : : return NULL;
56 : : }
57 : :
58 : 933353 : const unsigned char *abbrevp
59 : 933353 : = (unsigned char *) dbg->sectiondata[IDX_debug_abbrev]->d_buf + offset;
60 : :
61 [ + + ]: 933353 : if (*abbrevp == '\0')
62 : : /* We are past the last entry. */
63 : : return DWARF_END_ABBREV;
64 : :
65 : : /* 7.5.3 Abbreviations Tables
66 : :
67 : : [...] Each declaration begins with an unsigned LEB128 number
68 : : representing the abbreviation code itself. [...] The
69 : : abbreviation code is followed by another unsigned LEB128
70 : : number that encodes the entry's tag. [...]
71 : :
72 : : [...] Following the tag encoding is a 1-byte value that
73 : : determines whether a debugging information entry using this
74 : : abbreviation has child entries or not. [...]
75 : :
76 : : [...] Finally, the child encoding is followed by a series of
77 : : attribute specifications. Each attribute specification
78 : : consists of two parts. The first part is an unsigned LEB128
79 : : number representing the attribute's name. The second part is
80 : : an unsigned LEB128 number representing the attribute's form. */
81 : 932005 : const unsigned char *start_abbrevp = abbrevp;
82 : : unsigned int code;
83 [ + + ]: 932005 : get_uleb128 (code, abbrevp);
84 : :
85 : : /* Check whether this code is already in the hash table. */
86 : 932005 : bool foundit = false;
87 : 932005 : Dwarf_Abbrev *abb = NULL;
88 [ + + ]: 932005 : if (cu == NULL
89 [ + - ]: 867223 : || (abb = Dwarf_Abbrev_Hash_find (&cu->abbrev_hash, code, NULL)) == NULL)
90 : : {
91 [ + + ]: 932005 : if (result == NULL)
92 [ + + ]: 867223 : abb = libdw_typed_alloc (dbg, Dwarf_Abbrev);
93 : : else
94 : : abb = result;
95 : : }
96 : : else
97 : : {
98 : 0 : foundit = true;
99 : :
100 [ # # ]: 0 : assert (abb->offset == offset);
101 : :
102 : : /* If the caller doesn't need the length we are done. */
103 [ # # ]: 0 : if (lengthp == NULL)
104 : : goto out;
105 : : }
106 : :
107 : : /* If there is already a value in the hash table we are going to
108 : : overwrite its content. This must not be a problem, since the
109 : : content better be the same. */
110 : 932005 : abb->code = code;
111 [ + + ]: 932005 : get_uleb128 (abb->tag, abbrevp);
112 : 932005 : abb->has_children = *abbrevp++ == DW_CHILDREN_yes;
113 : 932005 : abb->attrp = (unsigned char *) abbrevp;
114 : 932005 : abb->offset = offset;
115 : :
116 : : /* Skip over all the attributes and count them while doing so. */
117 : 932005 : abb->attrcnt = 0;
118 : : unsigned int attrname;
119 : : unsigned int attrform;
120 : : do
121 : : {
122 [ + + ]: 4680778 : get_uleb128 (attrname, abbrevp);
123 [ + + ]: 4680778 : get_uleb128 (attrform, abbrevp);
124 : : }
125 [ + + ][ + - ]: 4680778 : while (attrname != 0 && attrform != 0 && ++abb->attrcnt);
126 : :
127 : : /* Return the length to the caller if she asked for it. */
128 [ + - ]: 932005 : if (lengthp != NULL)
129 : 932005 : *lengthp = abbrevp - start_abbrevp;
130 : :
131 : : /* Add the entry to the hash table. */
132 [ + + ]: 932005 : if (cu != NULL && ! foundit)
133 : 933353 : (void) Dwarf_Abbrev_Hash_insert (&cu->abbrev_hash, abb->code, abb);
134 : :
135 : : out:
136 : : return abb;
137 : : }
138 : :
139 : :
140 : : Dwarf_Abbrev *
141 : 69 : dwarf_getabbrev (die, offset, lengthp)
142 : : Dwarf_Die *die;
143 : : Dwarf_Off offset;
144 : : size_t *lengthp;
145 : : {
146 : 69 : return __libdw_getabbrev (die->cu->dbg, die->cu,
147 : 69 : die->cu->orig_abbrev_offset + offset, lengthp,
148 : : NULL);
149 : : }
|