Line data Source code
1 : /* Advance to next CU header.
2 : Copyright (C) 2002-2010 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 114065 : 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 *type_signaturep,
43 : Dwarf_Off *type_offsetp)
44 : {
45 114065 : const bool debug_types = type_signaturep != NULL;
46 114065 : const size_t sec_idx = debug_types ? IDX_debug_types : IDX_debug_info;
47 :
48 : /* Maybe there has been an error before. */
49 114065 : if (dwarf == NULL)
50 : return -1;
51 :
52 : /* If we reached the end before don't do anything. */
53 114065 : if (off == (Dwarf_Off) -1l
54 114065 : || unlikely (dwarf->sectiondata[sec_idx] == NULL)
55 : /* Make sure there is enough space in the .debug_info section
56 : for at least the initial word. We cannot test the rest since
57 : we don't know yet whether this is a 64-bit object or not. */
58 114065 : || unlikely (off + 4 >= dwarf->sectiondata[sec_idx]->d_size))
59 : {
60 172 : *next_off = (Dwarf_Off) -1l;
61 172 : return 1;
62 : }
63 :
64 : /* This points into the .debug_info section to the beginning of the
65 : CU entry. */
66 113893 : const unsigned char *data = dwarf->sectiondata[sec_idx]->d_buf;
67 113893 : const unsigned char *bytes = data + off;
68 :
69 : /* The format of the CU header is described in dwarf2p1 7.5.1:
70 :
71 : 1. A 4-byte or 12-byte unsigned integer representing the length
72 : of the .debug_info contribution for that compilation unit, not
73 : including the length field itself. In the 32-bit DWARF format,
74 : this is a 4-byte unsigned integer (which must be less than
75 : 0xfffffff0); in the 64-bit DWARF format, this consists of the
76 : 4-byte value 0xffffffff followed by an 8-byte unsigned integer
77 : that gives the actual length (see Section 7.2.2).
78 :
79 : 2. A 2-byte unsigned integer representing the version of the
80 : DWARF information for that compilation unit. For DWARF Version
81 : 2.1, the value in this field is 2.
82 :
83 : 3. A 4-byte or 8-byte unsigned offset into the .debug_abbrev
84 : section. This offset associates the compilation unit with a
85 : particular set of debugging information entry abbreviations. In
86 : the 32-bit DWARF format, this is a 4-byte unsigned length; in
87 : the 64-bit DWARF format, this is an 8-byte unsigned length (see
88 : Section 7.4).
89 :
90 : 4. A 1-byte unsigned integer representing the size in bytes of
91 : an address on the target architecture. If the system uses
92 : segmented addressing, this value represents the size of the
93 : offset portion of an address. */
94 114015 : uint64_t length = read_4ubyte_unaligned_inc (dwarf, bytes);
95 113893 : size_t offset_size = 4;
96 : /* Lengths of 0xfffffff0 - 0xffffffff are escape codes. Oxffffffff is
97 : used to indicate that 64-bit dwarf information is being used, the
98 : other values are currently reserved. */
99 113893 : if (length == DWARF3_LENGTH_64_BIT)
100 : offset_size = 8;
101 113893 : else if (unlikely (length >= DWARF3_LENGTH_MIN_ESCAPE_CODE
102 : && length <= DWARF3_LENGTH_MAX_ESCAPE_CODE))
103 : {
104 : invalid:
105 0 : __libdw_seterrno (DWARF_E_INVALID_DWARF);
106 0 : return -1;
107 : }
108 :
109 : /* Now we know how large the header is. */
110 113893 : if (unlikely (DIE_OFFSET_FROM_CU_OFFSET (off, offset_size, debug_types)
111 : >= dwarf->sectiondata[sec_idx]->d_size))
112 : {
113 0 : *next_off = -1;
114 0 : return 1;
115 : }
116 :
117 113893 : if (length == DWARF3_LENGTH_64_BIT)
118 : /* This is a 64-bit DWARF format. */
119 0 : length = read_8ubyte_unaligned_inc (dwarf, bytes);
120 :
121 : /* Read the version stamp. Always a 16-bit value. */
122 113893 : uint_fast16_t version = read_2ubyte_unaligned_inc (dwarf, bytes);
123 :
124 : /* Get offset in .debug_abbrev. Note that the size of the entry
125 : depends on whether this is a 32-bit or 64-bit DWARF definition. */
126 : uint64_t abbrev_offset;
127 113893 : if (__libdw_read_offset_inc (dwarf, sec_idx, &bytes, offset_size,
128 : &abbrev_offset, IDX_debug_abbrev, 0))
129 : return -1;
130 :
131 : /* The address size. Always an 8-bit value. */
132 113893 : uint8_t address_size = *bytes++;
133 :
134 113893 : if (debug_types)
135 : {
136 8 : uint64_t type_sig8 = read_8ubyte_unaligned_inc (dwarf, bytes);
137 :
138 : Dwarf_Off type_offset;
139 8 : if (__libdw_read_offset_inc (dwarf, sec_idx, &bytes, offset_size,
140 : &type_offset, sec_idx, 0))
141 0 : return -1;
142 :
143 : /* Validate that the TYPE_OFFSET points past the header. */
144 8 : if (unlikely (type_offset < (size_t) (bytes - (data + off))))
145 : goto invalid;
146 :
147 8 : *type_signaturep = type_sig8;
148 8 : if (type_offsetp != NULL)
149 4 : *type_offsetp = type_offset;
150 : }
151 :
152 : /* Store the header length. */
153 113893 : if (header_sizep != NULL)
154 103562 : *header_sizep = bytes - (data + off);
155 :
156 113893 : if (versionp != NULL)
157 11616 : *versionp = version;
158 :
159 113893 : if (abbrev_offsetp != NULL)
160 11636 : *abbrev_offsetp = abbrev_offset;
161 :
162 113893 : if (address_sizep != NULL)
163 11636 : *address_sizep = address_size;
164 :
165 : /* Store the offset size. */
166 113893 : if (offset_sizep != NULL)
167 11636 : *offset_sizep = offset_size;
168 :
169 : /* See definition of DIE_OFFSET_FROM_CU_OFFSET macro
170 : for an explanation of the trick in this expression. */
171 113893 : *next_off = off + 2 * offset_size - 4 + length;
172 :
173 113893 : return 0;
174 : }
175 : INTDEF(dwarf_next_unit)
176 :
177 : int
178 102388 : dwarf_nextcu (Dwarf *dwarf, Dwarf_Off off, Dwarf_Off *next_off,
179 : size_t *header_sizep, Dwarf_Off *abbrev_offsetp,
180 : uint8_t *address_sizep, uint8_t *offset_sizep)
181 : {
182 102388 : return INTUSE(dwarf_next_unit) (dwarf, off, next_off, header_sizep, NULL,
183 : abbrev_offsetp, address_sizep, offset_sizep,
184 : NULL, NULL);
185 : }
186 : INTDEF(dwarf_nextcu)
|