Line data Source code
1 : /* Advance to next CU header.
2 : Copyright (C) 2002-2010, 2016, 2017 Red Hat, Inc.
3 : This file is part of elfutils.
4 : Written by Ulrich Drepper <drepper@redhat.com>, 2002.
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 : #include <dwarf.h>
36 :
37 :
38 : int
39 11744 : dwarf_next_unit (Dwarf *dwarf, Dwarf_Off off, Dwarf_Off *next_off,
40 : size_t *header_sizep, Dwarf_Half *versionp,
41 : Dwarf_Off *abbrev_offsetp, uint8_t *address_sizep,
42 : uint8_t *offset_sizep, uint64_t *v4_type_signaturep,
43 : Dwarf_Off *v4_type_offsetp)
44 : {
45 11744 : const bool v4_debug_types = v4_type_signaturep != NULL;
46 11744 : return __libdw_next_unit (dwarf, v4_debug_types, off, next_off,
47 : header_sizep, versionp, NULL,
48 : abbrev_offsetp, address_sizep, offset_sizep,
49 : v4_type_signaturep, v4_type_offsetp);
50 : }
51 : INTDEF(dwarf_next_unit)
52 :
53 : int
54 : internal_function
55 28236 : __libdw_next_unit (Dwarf *dwarf, bool v4_debug_types, Dwarf_Off off,
56 : Dwarf_Off *next_off, size_t *header_sizep,
57 : Dwarf_Half *versionp, uint8_t *unit_typep,
58 : Dwarf_Off *abbrev_offsetp, uint8_t *address_sizep,
59 : uint8_t *offset_sizep, uint64_t *unit_id8p,
60 : Dwarf_Off *subdie_offsetp)
61 : {
62 : /* Note that debug_type units come from .debug_types in DWARF < 5 and
63 : from .debug_info in DWARF >= 5. If the user requested the
64 : v4_type_signature we return from .debug_types always. If no signature
65 : is requested we return units (any type) from .debug_info. */
66 28236 : const size_t sec_idx = v4_debug_types ? IDX_debug_types : IDX_debug_info;
67 :
68 : /* Maybe there has been an error before. */
69 28236 : if (dwarf == NULL)
70 : return -1;
71 :
72 : /* If we reached the end before don't do anything. */
73 28236 : if (off == (Dwarf_Off) -1l
74 28236 : || unlikely (dwarf->sectiondata[sec_idx] == NULL)
75 : /* Make sure there is enough space in the .debug_info section
76 : for at least the initial word. We cannot test the rest since
77 : we don't know yet whether this is a 64-bit object or not. */
78 28213 : || unlikely (off + 4 >= dwarf->sectiondata[sec_idx]->d_size))
79 : {
80 208 : *next_off = (Dwarf_Off) -1l;
81 208 : return 1;
82 : }
83 :
84 : /* This points into the .debug_info or .debug_types section to the
85 : beginning of the CU entry. */
86 28028 : const unsigned char *data = dwarf->sectiondata[sec_idx]->d_buf;
87 28028 : const unsigned char *bytes = data + off;
88 28028 : const unsigned char *bytes_end = data + dwarf->sectiondata[sec_idx]->d_size;
89 :
90 : /* The format of the CU header is described in dwarf2p1 7.5.1 and
91 : changed in DWARFv5 (to include unit type, switch location of some
92 : fields and add some optional fields).
93 :
94 : 1. A 4-byte or 12-byte unsigned integer representing the length
95 : of the .debug_info contribution for that compilation unit, not
96 : including the length field itself. In the 32-bit DWARF format,
97 : this is a 4-byte unsigned integer (which must be less than
98 : 0xfffffff0); in the 64-bit DWARF format, this consists of the
99 : 4-byte value 0xffffffff followed by an 8-byte unsigned integer
100 : that gives the actual length (see Section 7.2.2). This field
101 : indicates whether this unit is 32-bit of 64-bit DWARF, which
102 : affects all other offset fields in this header.
103 :
104 : 2. A 2-byte unsigned integer representing the version of the
105 : DWARF information for that compilation unit. For DWARF Version
106 : 2.1, the value in this field is 2 (3 for v3, 4 for v4, 5 for v5).
107 : This fields determines the order of the next fields and whether
108 : there are any optional fields in this header.
109 :
110 : 3. For DWARF 2, 3 and 4 (including v4 type units):
111 : A 4-byte or 8-byte unsigned offset into the .debug_abbrev
112 : section. This offset associates the compilation unit with a
113 : particular set of debugging information entry abbreviations. In
114 : the 32-bit DWARF format, this is a 4-byte unsigned length; in
115 : the 64-bit DWARF format, this is an 8-byte unsigned length (see
116 : Section 7.4).
117 :
118 : For DWARF 5:
119 : A 1-byte unsigned integer representing the unit (header) type.
120 : This field determines what the optional fields in the header
121 : represent. If this is an unknown unit type then we cannot
122 : assume anything about the rest of the unit (header).
123 :
124 : 4. For all DWARF versions (including v4 type units):
125 : A 1-byte unsigned integer representing the size in bytes of
126 : an address on the target architecture. If the system uses
127 : segmented addressing, this value represents the size of the
128 : offset portion of an address. This is the last field in the header
129 : for DWARF versions 2, 3 and 4 (except for v4 type units).
130 :
131 : 5. For DWARF 5 only (this is field 3 for DWARF 2, 3, 4 and v4 types):
132 : A 4-byte or 8-byte unsigned offset into the .debug_abbrev
133 : section. This offset associates the compilation unit with a
134 : particular set of debugging information entry abbreviations. In
135 : the 32-bit DWARF format, this is a 4-byte unsigned length; in
136 : the 64-bit DWARF format, this is an 8-byte unsigned length.
137 :
138 : 6. For v4 type units (this is really field 5 for v4 types) and
139 : DWARF 5 optional (skeleton, split_compile, type and
140 : split_type): An 8 byte (opaque) integer constant value. For
141 : v4 and v5 type units this is the type signature. For skeleton
142 : and split compile units this is the compilation ID.
143 :
144 : 7. For v4 type units (this is really field 6 for v4 types) and
145 : DWARF 5 optional (type and split_type) and v4 type units:
146 : A 4-byte or 8-byte unsigned offset. In the 32-bit DWARF format,
147 : this is a 4-byte unsigned length; in the 64-bit DWARF format,
148 : this is an 8-byte unsigned length. This is the type DIE offset
149 : (which is not necessarily the first DIE in the unit).
150 : */
151 :
152 28028 : uint64_t length = read_4ubyte_unaligned_inc (dwarf, bytes);
153 28028 : size_t offset_size = 4;
154 : /* Lengths of 0xfffffff0 - 0xffffffff are escape codes. Oxffffffff is
155 : used to indicate that 64-bit dwarf information is being used, the
156 : other values are currently reserved. */
157 28028 : if (length == DWARF3_LENGTH_64_BIT)
158 : offset_size = 8;
159 28028 : else if (unlikely (length >= DWARF3_LENGTH_MIN_ESCAPE_CODE
160 : && length <= DWARF3_LENGTH_MAX_ESCAPE_CODE))
161 : {
162 0 : invalid:
163 0 : __libdw_seterrno (DWARF_E_INVALID_DWARF);
164 0 : return -1;
165 : }
166 :
167 28028 : if (length == DWARF3_LENGTH_64_BIT)
168 : {
169 : /* This is a 64-bit DWARF format. */
170 0 : if (bytes_end - bytes < 8)
171 : goto invalid;
172 0 : length = read_8ubyte_unaligned_inc (dwarf, bytes);
173 : }
174 :
175 : /* Read the version stamp. Always a 16-bit value. */
176 28028 : if (bytes_end - bytes < 2)
177 : goto invalid;
178 28028 : uint_fast16_t version = read_2ubyte_unaligned_inc (dwarf, bytes);
179 :
180 : /* We keep unit_type at zero for older DWARF since we cannot
181 : easily guess whether it is a compile or partial unit. */
182 28028 : uint8_t unit_type = 0;
183 28028 : if (version >= 5)
184 : {
185 109 : if (bytes_end - bytes < 1)
186 : goto invalid;
187 109 : unit_type = *bytes++;
188 : }
189 :
190 : /* All these are optional. */
191 28028 : Dwarf_Off subdie_off = 0;
192 28028 : uint64_t sig_id = 0;
193 28028 : Dwarf_Off abbrev_offset = 0;
194 28028 : uint8_t address_size = 0;
195 :
196 28028 : if (version < 2 || version > 5
197 28028 : || (version == 5 && ! (unit_type == DW_UT_compile
198 109 : || unit_type == DW_UT_partial
199 : || unit_type == DW_UT_skeleton
200 77 : || unit_type == DW_UT_split_compile
201 0 : || unit_type == DW_UT_type
202 0 : || unit_type == DW_UT_split_type)))
203 : {
204 : /* We cannot really know more about the header. Just report
205 : the length of the unit, version and unit type. */
206 : goto done;
207 : }
208 :
209 : /* We have to guess the unit_type. But we don't have a real CUDIE. */
210 28028 : if (version < 5)
211 27919 : unit_type = v4_debug_types ? DW_UT_type : DW_UT_compile;
212 :
213 : /* Now we know how large the header is (should be). */
214 28028 : if (unlikely (__libdw_first_die_from_cu_start (off, offset_size, version,
215 : unit_type)
216 : >= dwarf->sectiondata[sec_idx]->d_size))
217 : {
218 0 : *next_off = -1;
219 0 : return 1;
220 : }
221 :
222 : /* The address size. Always an 8-bit value.
223 : Comes after abbrev_offset for version < 5, otherwise unit type
224 : and address size (if a known unit type) comes before abbrev_offset. */
225 28028 : if (version >= 5)
226 109 : address_size = *bytes++;
227 :
228 : /* Get offset in .debug_abbrev. Note that the size of the entry
229 : depends on whether this is a 32-bit or 64-bit DWARF definition. */
230 28028 : if (__libdw_read_offset_inc (dwarf, sec_idx, &bytes, offset_size,
231 : &abbrev_offset, IDX_debug_abbrev, 0))
232 : return -1;
233 :
234 28028 : if (version < 5)
235 27919 : address_size = *bytes++;
236 :
237 : /* Extra fields, signature/id and type offset/padding. */
238 28028 : if (v4_debug_types
239 28002 : || (version >= 5
240 218 : && (unit_type == DW_UT_skeleton || unit_type == DW_UT_split_compile
241 109 : || unit_type == DW_UT_type || unit_type == DW_UT_split_type)))
242 : {
243 103 : sig_id = read_8ubyte_unaligned_inc (dwarf, bytes);
244 :
245 206 : if ((v4_debug_types
246 103 : || unit_type == DW_UT_type || unit_type == DW_UT_split_type))
247 : {
248 26 : if (__libdw_read_offset_inc (dwarf, sec_idx, &bytes, offset_size,
249 : &subdie_off, sec_idx, 0))
250 : return -1;
251 :
252 : /* Validate that the TYPE_OFFSET points past the header. */
253 26 : if (unlikely (subdie_off < (size_t) (bytes - (data + off))))
254 : goto invalid;
255 : }
256 : }
257 :
258 28028 : done:
259 28028 : if (unit_id8p != NULL)
260 16497 : *unit_id8p = sig_id;
261 :
262 28028 : if (subdie_offsetp != NULL)
263 16491 : *subdie_offsetp = subdie_off;
264 :
265 : /* Store the header length. This is really how much we have read
266 : from the header. If we didn't recognize the unit type the
267 : header might actually be bigger. */
268 28028 : if (header_sizep != NULL)
269 11539 : *header_sizep = bytes - (data + off);
270 :
271 28028 : if (versionp != NULL)
272 16491 : *versionp = version;
273 :
274 28028 : if (unit_typep != NULL)
275 16489 : *unit_typep = unit_type;
276 :
277 28028 : if (abbrev_offsetp != NULL)
278 17413 : *abbrev_offsetp = abbrev_offset;
279 :
280 28028 : if (address_sizep != NULL)
281 17413 : *address_sizep = address_size;
282 :
283 : /* Store the offset size. */
284 28028 : if (offset_sizep != NULL)
285 17413 : *offset_sizep = offset_size;
286 :
287 : /* The length of the unit doesn't include the length field itself.
288 : The length field is either, with offset == 4: 2 * 4 - 4 == 4,
289 : or with offset == 8: 2 * 8 - 4 == 12. */
290 28028 : *next_off = off + 2 * offset_size - 4 + length;
291 :
292 : /* This means that the length field is bogus, but return the CU anyway.
293 : We just won't return anything after this. */
294 28028 : if (*next_off <= off)
295 0 : *next_off = (Dwarf_Off) -1;
296 :
297 : return 0;
298 : }
299 :
300 : int
301 11710 : dwarf_nextcu (Dwarf *dwarf, Dwarf_Off off, Dwarf_Off *next_off,
302 : size_t *header_sizep, Dwarf_Off *abbrev_offsetp,
303 : uint8_t *address_sizep, uint8_t *offset_sizep)
304 : {
305 11710 : return INTUSE(dwarf_next_unit) (dwarf, off, next_off, header_sizep, NULL,
306 : abbrev_offsetp, address_sizep, offset_sizep,
307 : NULL, NULL);
308 : }
309 : INTDEF(dwarf_nextcu)
|