1 /* Return list address ranges.
2 Copyright (C) 2000-2010, 2016, 2017 Red Hat, Inc.
3 This file is part of elfutils.
4 Written by Ulrich Drepper <drepper@redhat.com>, 2000.
6 This file is free software; you can redistribute it and/or modify
7 it under the terms of either
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
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
19 or both in parallel, as here.
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.
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/>. */
42 struct arangelist *next;
45 /* Compare by Dwarf_Arange.addr, given pointers into an array of pointeers. */
47 compare_aranges (const void *a, const void *b)
49 struct arangelist *const *p1 = a, *const *p2 = b;
50 struct arangelist *l1 = *p1, *l2 = *p2;
51 if (l1->arange.addr != l2->arange.addr)
52 return (l1->arange.addr < l2->arange.addr) ? -1 : 1;
57 dwarf_getaranges (Dwarf *dbg, Dwarf_Aranges **aranges, size_t *naranges)
62 if (dbg->aranges != NULL)
64 *aranges = dbg->aranges;
66 *naranges = dbg->aranges->naranges;
70 if (dbg->sectiondata[IDX_debug_aranges] == NULL)
72 /* No such section. */
79 if (dbg->sectiondata[IDX_debug_aranges]->d_buf == NULL)
82 struct arangelist *arangelist = NULL;
83 unsigned int narangelist = 0;
85 const unsigned char *readp = dbg->sectiondata[IDX_debug_aranges]->d_buf;
86 const unsigned char *readendp
87 = readp + dbg->sectiondata[IDX_debug_aranges]->d_size;
89 while (readp < readendp)
91 const unsigned char *hdrstart = readp;
93 /* Each entry starts with a header:
95 1. A 4-byte or 12-byte length containing the length of the
96 set of entries for this compilation unit, not including the
97 length field itself. [...]
99 2. A 2-byte version identifier containing the value 2 for
102 3. A 4-byte or 8-byte offset into the .debug_info section. [...]
104 4. A 1-byte unsigned integer containing the size in bytes of
105 an address (or the offset portion of an address for segmented
106 addressing) on the target system.
108 5. A 1-byte unsigned integer containing the size in bytes of
109 a segment descriptor on the target system. */
110 if (unlikely (readp + 4 > readendp))
113 Dwarf_Word length = read_4ubyte_unaligned_inc (dbg, readp);
114 unsigned int length_bytes = 4;
115 if (length == DWARF3_LENGTH_64_BIT)
117 if (unlikely (readp + 8 > readendp))
120 length = read_8ubyte_unaligned_inc (dbg, readp);
123 else if (unlikely (length >= DWARF3_LENGTH_MIN_ESCAPE_CODE
124 && length <= DWARF3_LENGTH_MAX_ESCAPE_CODE))
127 if (unlikely (readp + 2 > readendp))
130 unsigned int version = read_2ubyte_unaligned_inc (dbg, readp);
134 __libdw_seterrno (DWARF_E_INVALID_DWARF);
136 while (arangelist != NULL)
138 struct arangelist *next = arangelist->next;
145 Dwarf_Word offset = 0;
146 if (__libdw_read_offset_inc (dbg,
147 IDX_debug_aranges, &readp,
148 length_bytes, &offset, IDX_debug_info, 4))
151 /* Next up two bytes for address and segment size. */
152 if (readp + 2 > readendp)
155 unsigned int address_size = *readp++;
156 if (unlikely (address_size != 4 && address_size != 8))
159 /* We don't actually support segment selectors. */
160 unsigned int segment_size = *readp++;
161 if (segment_size != 0)
164 /* Round the address to the next multiple of 2*address_size. */
165 readp += ((2 * address_size - ((readp - hdrstart) % (2 * address_size)))
166 % (2 * address_size));
170 Dwarf_Word range_address;
171 Dwarf_Word range_length;
173 if (__libdw_read_address_inc (dbg, IDX_debug_aranges, &readp,
174 address_size, &range_address))
177 if (readp + address_size > readendp)
180 if (address_size == 4)
181 range_length = read_4ubyte_unaligned_inc (dbg, readp);
183 range_length = read_8ubyte_unaligned_inc (dbg, readp);
185 /* Two zero values mark the end. */
186 if (range_address == 0 && range_length == 0)
189 /* We don't use alloca for these temporary structures because
190 the total number of them can be quite large. */
191 struct arangelist *new_arange = malloc (sizeof *new_arange);
192 if (unlikely (new_arange == NULL))
194 __libdw_seterrno (DWARF_E_NOMEM);
198 new_arange->arange.addr = range_address;
199 new_arange->arange.length = range_length;
201 /* We store the actual CU DIE offset, not the CU header offset. */
202 Dwarf_CU *cu = __libdw_findcu (dbg, offset, false);
203 if (unlikely (cu == NULL))
205 /* We haven't gotten a chance to link in the new_arange
206 into the arangelist, don't leak it. */
210 new_arange->arange.offset = __libdw_first_die_off_from_cu (cu);
212 new_arange->next = arangelist;
213 arangelist = new_arange;
216 /* Sanity-check the data. */
217 if (unlikely (new_arange->arange.offset
218 >= dbg->sectiondata[IDX_debug_info]->d_size))
223 if (narangelist == 0)
225 assert (arangelist == NULL);
226 if (naranges != NULL)
232 /* Allocate the array for the result. */
233 void *buf = libdw_alloc (dbg, Dwarf_Aranges,
234 sizeof (Dwarf_Aranges)
235 + narangelist * sizeof (Dwarf_Arange), 1);
237 /* First use the buffer for the pointers, and sort the entries.
238 We'll write the pointers in the end of the buffer, and then
239 copy into the buffer from the beginning so the overlap works. */
240 assert (sizeof (Dwarf_Arange) >= sizeof (Dwarf_Arange *));
241 struct arangelist **sortaranges
242 = (buf + sizeof (Dwarf_Aranges)
243 + ((sizeof (Dwarf_Arange) - sizeof sortaranges[0]) * narangelist));
245 /* The list is in LIFO order and usually they come in clumps with
246 ascending addresses. So fill from the back to probably start with
247 runs already in order before we sort. */
248 unsigned int i = narangelist;
251 sortaranges[i] = arangelist;
252 arangelist = arangelist->next;
254 assert (arangelist == NULL);
256 /* Sort by ascending address. */
257 qsort (sortaranges, narangelist, sizeof sortaranges[0], &compare_aranges);
259 /* Now that they are sorted, put them in the final array.
260 The buffers overlap, so we've clobbered the early elements
261 of SORTARANGES by the time we're reading the later ones. */
263 (*aranges)->dbg = dbg;
264 (*aranges)->naranges = narangelist;
265 dbg->aranges = *aranges;
266 if (naranges != NULL)
267 *naranges = narangelist;
268 for (i = 0; i < narangelist; ++i)
270 struct arangelist *elt = sortaranges[i];
271 (*aranges)->info[i] = elt->arange;
277 INTDEF(dwarf_getaranges)