1*7304104dSAndroid Build Coastguard Worker /* Return list address ranges.
2*7304104dSAndroid Build Coastguard Worker Copyright (C) 2000-2010, 2016, 2017 Red Hat, Inc.
3*7304104dSAndroid Build Coastguard Worker Copyright (C) 2023 Mark J. Wielaard <[email protected]>
4*7304104dSAndroid Build Coastguard Worker This file is part of elfutils.
5*7304104dSAndroid Build Coastguard Worker Written by Ulrich Drepper <[email protected]>, 2000.
6*7304104dSAndroid Build Coastguard Worker
7*7304104dSAndroid Build Coastguard Worker This file is free software; you can redistribute it and/or modify
8*7304104dSAndroid Build Coastguard Worker it under the terms of either
9*7304104dSAndroid Build Coastguard Worker
10*7304104dSAndroid Build Coastguard Worker * the GNU Lesser General Public License as published by the Free
11*7304104dSAndroid Build Coastguard Worker Software Foundation; either version 3 of the License, or (at
12*7304104dSAndroid Build Coastguard Worker your option) any later version
13*7304104dSAndroid Build Coastguard Worker
14*7304104dSAndroid Build Coastguard Worker or
15*7304104dSAndroid Build Coastguard Worker
16*7304104dSAndroid Build Coastguard Worker * the GNU General Public License as published by the Free
17*7304104dSAndroid Build Coastguard Worker Software Foundation; either version 2 of the License, or (at
18*7304104dSAndroid Build Coastguard Worker your option) any later version
19*7304104dSAndroid Build Coastguard Worker
20*7304104dSAndroid Build Coastguard Worker or both in parallel, as here.
21*7304104dSAndroid Build Coastguard Worker
22*7304104dSAndroid Build Coastguard Worker elfutils is distributed in the hope that it will be useful, but
23*7304104dSAndroid Build Coastguard Worker WITHOUT ANY WARRANTY; without even the implied warranty of
24*7304104dSAndroid Build Coastguard Worker MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25*7304104dSAndroid Build Coastguard Worker General Public License for more details.
26*7304104dSAndroid Build Coastguard Worker
27*7304104dSAndroid Build Coastguard Worker You should have received copies of the GNU General Public License and
28*7304104dSAndroid Build Coastguard Worker the GNU Lesser General Public License along with this program. If
29*7304104dSAndroid Build Coastguard Worker not, see <http://www.gnu.org/licenses/>. */
30*7304104dSAndroid Build Coastguard Worker
31*7304104dSAndroid Build Coastguard Worker #ifdef HAVE_CONFIG_H
32*7304104dSAndroid Build Coastguard Worker # include <config.h>
33*7304104dSAndroid Build Coastguard Worker #endif
34*7304104dSAndroid Build Coastguard Worker
35*7304104dSAndroid Build Coastguard Worker #include <stdlib.h>
36*7304104dSAndroid Build Coastguard Worker #include "libdwP.h"
37*7304104dSAndroid Build Coastguard Worker #include <dwarf.h>
38*7304104dSAndroid Build Coastguard Worker
39*7304104dSAndroid Build Coastguard Worker struct arangelist
40*7304104dSAndroid Build Coastguard Worker {
41*7304104dSAndroid Build Coastguard Worker Dwarf_Arange arange;
42*7304104dSAndroid Build Coastguard Worker struct arangelist *next;
43*7304104dSAndroid Build Coastguard Worker };
44*7304104dSAndroid Build Coastguard Worker
45*7304104dSAndroid Build Coastguard Worker /* Compare by Dwarf_Arange.addr, given pointers into an array of pointeers. */
46*7304104dSAndroid Build Coastguard Worker static int
compare_aranges(const void * a,const void * b)47*7304104dSAndroid Build Coastguard Worker compare_aranges (const void *a, const void *b)
48*7304104dSAndroid Build Coastguard Worker {
49*7304104dSAndroid Build Coastguard Worker struct arangelist *const *p1 = a, *const *p2 = b;
50*7304104dSAndroid Build Coastguard Worker struct arangelist *l1 = *p1, *l2 = *p2;
51*7304104dSAndroid Build Coastguard Worker if (l1->arange.addr != l2->arange.addr)
52*7304104dSAndroid Build Coastguard Worker return (l1->arange.addr < l2->arange.addr) ? -1 : 1;
53*7304104dSAndroid Build Coastguard Worker return 0;
54*7304104dSAndroid Build Coastguard Worker }
55*7304104dSAndroid Build Coastguard Worker
56*7304104dSAndroid Build Coastguard Worker /* Convert ARANGELIST into Dwarf_Aranges and store at ARANGES. */
57*7304104dSAndroid Build Coastguard Worker static bool
finalize_aranges(Dwarf * dbg,Dwarf_Aranges ** aranges,size_t * naranges,struct arangelist * arangelist,unsigned int narangelist)58*7304104dSAndroid Build Coastguard Worker finalize_aranges (Dwarf *dbg, Dwarf_Aranges **aranges, size_t *naranges,
59*7304104dSAndroid Build Coastguard Worker struct arangelist *arangelist, unsigned int narangelist)
60*7304104dSAndroid Build Coastguard Worker {
61*7304104dSAndroid Build Coastguard Worker /* Allocate the array for the result. */
62*7304104dSAndroid Build Coastguard Worker void *buf = libdw_alloc (dbg, Dwarf_Aranges,
63*7304104dSAndroid Build Coastguard Worker sizeof (Dwarf_Aranges)
64*7304104dSAndroid Build Coastguard Worker + narangelist * sizeof (Dwarf_Arange), 1);
65*7304104dSAndroid Build Coastguard Worker
66*7304104dSAndroid Build Coastguard Worker /* First use the buffer for the pointers, and sort the entries.
67*7304104dSAndroid Build Coastguard Worker We'll write the pointers in the end of the buffer, and then
68*7304104dSAndroid Build Coastguard Worker copy into the buffer from the beginning so the overlap works. */
69*7304104dSAndroid Build Coastguard Worker eu_static_assert (sizeof (Dwarf_Arange) >= sizeof (Dwarf_Arange *));
70*7304104dSAndroid Build Coastguard Worker struct arangelist **sortaranges
71*7304104dSAndroid Build Coastguard Worker = (buf + sizeof (Dwarf_Aranges)
72*7304104dSAndroid Build Coastguard Worker + ((sizeof (Dwarf_Arange) - sizeof sortaranges[0]) * narangelist));
73*7304104dSAndroid Build Coastguard Worker
74*7304104dSAndroid Build Coastguard Worker /* The list is in LIFO order and usually they come in clumps with
75*7304104dSAndroid Build Coastguard Worker ascending addresses. So fill from the back to probably start with
76*7304104dSAndroid Build Coastguard Worker runs already in order before we sort. */
77*7304104dSAndroid Build Coastguard Worker unsigned int i = narangelist;
78*7304104dSAndroid Build Coastguard Worker while (i-- > 0)
79*7304104dSAndroid Build Coastguard Worker {
80*7304104dSAndroid Build Coastguard Worker sortaranges[i] = arangelist;
81*7304104dSAndroid Build Coastguard Worker arangelist = arangelist->next;
82*7304104dSAndroid Build Coastguard Worker }
83*7304104dSAndroid Build Coastguard Worker
84*7304104dSAndroid Build Coastguard Worker /* Something went wrong if narangelist is less then the actual length
85*7304104dSAndroid Build Coastguard Worker of arangelist. */
86*7304104dSAndroid Build Coastguard Worker if (arangelist != NULL)
87*7304104dSAndroid Build Coastguard Worker {
88*7304104dSAndroid Build Coastguard Worker __libdw_seterrno (DWARF_E_UNKNOWN_ERROR);
89*7304104dSAndroid Build Coastguard Worker return false;
90*7304104dSAndroid Build Coastguard Worker }
91*7304104dSAndroid Build Coastguard Worker
92*7304104dSAndroid Build Coastguard Worker /* Sort by ascending address. */
93*7304104dSAndroid Build Coastguard Worker qsort (sortaranges, narangelist, sizeof sortaranges[0], &compare_aranges);
94*7304104dSAndroid Build Coastguard Worker
95*7304104dSAndroid Build Coastguard Worker /* Now that they are sorted, put them in the final array.
96*7304104dSAndroid Build Coastguard Worker The buffers overlap, so we've clobbered the early elements
97*7304104dSAndroid Build Coastguard Worker of SORTARANGES by the time we're reading the later ones. */
98*7304104dSAndroid Build Coastguard Worker *aranges = buf;
99*7304104dSAndroid Build Coastguard Worker (*aranges)->dbg = dbg;
100*7304104dSAndroid Build Coastguard Worker (*aranges)->naranges = narangelist;
101*7304104dSAndroid Build Coastguard Worker if (naranges != NULL)
102*7304104dSAndroid Build Coastguard Worker *naranges = narangelist;
103*7304104dSAndroid Build Coastguard Worker for (i = 0; i < narangelist; ++i)
104*7304104dSAndroid Build Coastguard Worker {
105*7304104dSAndroid Build Coastguard Worker struct arangelist *elt = sortaranges[i];
106*7304104dSAndroid Build Coastguard Worker (*aranges)->info[i] = elt->arange;
107*7304104dSAndroid Build Coastguard Worker free (elt);
108*7304104dSAndroid Build Coastguard Worker }
109*7304104dSAndroid Build Coastguard Worker
110*7304104dSAndroid Build Coastguard Worker return true;
111*7304104dSAndroid Build Coastguard Worker }
112*7304104dSAndroid Build Coastguard Worker
113*7304104dSAndroid Build Coastguard Worker int
__libdw_getdieranges(Dwarf * dbg,Dwarf_Aranges ** aranges,size_t * naranges)114*7304104dSAndroid Build Coastguard Worker __libdw_getdieranges (Dwarf *dbg, Dwarf_Aranges **aranges, size_t *naranges)
115*7304104dSAndroid Build Coastguard Worker {
116*7304104dSAndroid Build Coastguard Worker if (dbg == NULL)
117*7304104dSAndroid Build Coastguard Worker return -1;
118*7304104dSAndroid Build Coastguard Worker
119*7304104dSAndroid Build Coastguard Worker if (dbg->dieranges != NULL)
120*7304104dSAndroid Build Coastguard Worker {
121*7304104dSAndroid Build Coastguard Worker *aranges = dbg->dieranges;
122*7304104dSAndroid Build Coastguard Worker if (naranges != NULL)
123*7304104dSAndroid Build Coastguard Worker *naranges = dbg->dieranges->naranges;
124*7304104dSAndroid Build Coastguard Worker return 0;
125*7304104dSAndroid Build Coastguard Worker }
126*7304104dSAndroid Build Coastguard Worker
127*7304104dSAndroid Build Coastguard Worker struct arangelist *arangelist = NULL;
128*7304104dSAndroid Build Coastguard Worker unsigned int narangelist = 0;
129*7304104dSAndroid Build Coastguard Worker
130*7304104dSAndroid Build Coastguard Worker Dwarf_CU *cu = NULL;
131*7304104dSAndroid Build Coastguard Worker while (INTUSE(dwarf_get_units) (dbg, cu, &cu, NULL, NULL, NULL, NULL) == 0)
132*7304104dSAndroid Build Coastguard Worker {
133*7304104dSAndroid Build Coastguard Worker Dwarf_Addr base;
134*7304104dSAndroid Build Coastguard Worker Dwarf_Addr low;
135*7304104dSAndroid Build Coastguard Worker Dwarf_Addr high;
136*7304104dSAndroid Build Coastguard Worker
137*7304104dSAndroid Build Coastguard Worker Dwarf_Die cudie = CUDIE (cu);
138*7304104dSAndroid Build Coastguard Worker
139*7304104dSAndroid Build Coastguard Worker /* Skip CUs that only contain type information. */
140*7304104dSAndroid Build Coastguard Worker if (!INTUSE(dwarf_hasattr) (&cudie, DW_AT_low_pc)
141*7304104dSAndroid Build Coastguard Worker && !INTUSE(dwarf_hasattr) (&cudie, DW_AT_ranges))
142*7304104dSAndroid Build Coastguard Worker continue;
143*7304104dSAndroid Build Coastguard Worker
144*7304104dSAndroid Build Coastguard Worker ptrdiff_t offset = 0;
145*7304104dSAndroid Build Coastguard Worker
146*7304104dSAndroid Build Coastguard Worker /* Add arange for each range list entry or high_pc and low_pc. */
147*7304104dSAndroid Build Coastguard Worker while ((offset = INTUSE(dwarf_ranges) (&cudie, offset,
148*7304104dSAndroid Build Coastguard Worker &base, &low, &high)) > 0)
149*7304104dSAndroid Build Coastguard Worker {
150*7304104dSAndroid Build Coastguard Worker if (offset == -1)
151*7304104dSAndroid Build Coastguard Worker {
152*7304104dSAndroid Build Coastguard Worker __libdw_seterrno (DWARF_E_INVALID_DWARF);
153*7304104dSAndroid Build Coastguard Worker goto fail;
154*7304104dSAndroid Build Coastguard Worker }
155*7304104dSAndroid Build Coastguard Worker
156*7304104dSAndroid Build Coastguard Worker struct arangelist *new_arange = malloc (sizeof *new_arange);
157*7304104dSAndroid Build Coastguard Worker if (unlikely (new_arange == NULL))
158*7304104dSAndroid Build Coastguard Worker {
159*7304104dSAndroid Build Coastguard Worker __libdw_seterrno (DWARF_E_NOMEM);
160*7304104dSAndroid Build Coastguard Worker goto fail;
161*7304104dSAndroid Build Coastguard Worker }
162*7304104dSAndroid Build Coastguard Worker
163*7304104dSAndroid Build Coastguard Worker new_arange->arange.addr = low;
164*7304104dSAndroid Build Coastguard Worker new_arange->arange.length = (Dwarf_Word) (high - low);
165*7304104dSAndroid Build Coastguard Worker new_arange->arange.offset = __libdw_first_die_off_from_cu (cu);
166*7304104dSAndroid Build Coastguard Worker
167*7304104dSAndroid Build Coastguard Worker new_arange->next = arangelist;
168*7304104dSAndroid Build Coastguard Worker arangelist = new_arange;
169*7304104dSAndroid Build Coastguard Worker ++narangelist;
170*7304104dSAndroid Build Coastguard Worker }
171*7304104dSAndroid Build Coastguard Worker }
172*7304104dSAndroid Build Coastguard Worker
173*7304104dSAndroid Build Coastguard Worker if (narangelist == 0)
174*7304104dSAndroid Build Coastguard Worker {
175*7304104dSAndroid Build Coastguard Worker if (naranges != NULL)
176*7304104dSAndroid Build Coastguard Worker *naranges = 0;
177*7304104dSAndroid Build Coastguard Worker *aranges = NULL;
178*7304104dSAndroid Build Coastguard Worker return 0;
179*7304104dSAndroid Build Coastguard Worker }
180*7304104dSAndroid Build Coastguard Worker
181*7304104dSAndroid Build Coastguard Worker if (!finalize_aranges (dbg, aranges, naranges, arangelist, narangelist))
182*7304104dSAndroid Build Coastguard Worker goto fail;
183*7304104dSAndroid Build Coastguard Worker
184*7304104dSAndroid Build Coastguard Worker dbg->dieranges = *aranges;
185*7304104dSAndroid Build Coastguard Worker return 0;
186*7304104dSAndroid Build Coastguard Worker
187*7304104dSAndroid Build Coastguard Worker fail:
188*7304104dSAndroid Build Coastguard Worker while (arangelist != NULL)
189*7304104dSAndroid Build Coastguard Worker {
190*7304104dSAndroid Build Coastguard Worker struct arangelist *next = arangelist->next;
191*7304104dSAndroid Build Coastguard Worker free (arangelist);
192*7304104dSAndroid Build Coastguard Worker arangelist = next;
193*7304104dSAndroid Build Coastguard Worker }
194*7304104dSAndroid Build Coastguard Worker return -1;
195*7304104dSAndroid Build Coastguard Worker }
196*7304104dSAndroid Build Coastguard Worker
197*7304104dSAndroid Build Coastguard Worker int
dwarf_getaranges(Dwarf * dbg,Dwarf_Aranges ** aranges,size_t * naranges)198*7304104dSAndroid Build Coastguard Worker dwarf_getaranges (Dwarf *dbg, Dwarf_Aranges **aranges, size_t *naranges)
199*7304104dSAndroid Build Coastguard Worker {
200*7304104dSAndroid Build Coastguard Worker if (dbg == NULL)
201*7304104dSAndroid Build Coastguard Worker return -1;
202*7304104dSAndroid Build Coastguard Worker
203*7304104dSAndroid Build Coastguard Worker if (dbg->aranges != NULL)
204*7304104dSAndroid Build Coastguard Worker {
205*7304104dSAndroid Build Coastguard Worker *aranges = dbg->aranges;
206*7304104dSAndroid Build Coastguard Worker if (naranges != NULL)
207*7304104dSAndroid Build Coastguard Worker *naranges = dbg->aranges->naranges;
208*7304104dSAndroid Build Coastguard Worker return 0;
209*7304104dSAndroid Build Coastguard Worker }
210*7304104dSAndroid Build Coastguard Worker
211*7304104dSAndroid Build Coastguard Worker if (dbg->sectiondata[IDX_debug_aranges] == NULL)
212*7304104dSAndroid Build Coastguard Worker {
213*7304104dSAndroid Build Coastguard Worker /* No such section. */
214*7304104dSAndroid Build Coastguard Worker *aranges = NULL;
215*7304104dSAndroid Build Coastguard Worker if (naranges != NULL)
216*7304104dSAndroid Build Coastguard Worker *naranges = 0;
217*7304104dSAndroid Build Coastguard Worker return 0;
218*7304104dSAndroid Build Coastguard Worker }
219*7304104dSAndroid Build Coastguard Worker
220*7304104dSAndroid Build Coastguard Worker if (dbg->sectiondata[IDX_debug_aranges]->d_buf == NULL)
221*7304104dSAndroid Build Coastguard Worker return -1;
222*7304104dSAndroid Build Coastguard Worker
223*7304104dSAndroid Build Coastguard Worker struct arangelist *arangelist = NULL;
224*7304104dSAndroid Build Coastguard Worker unsigned int narangelist = 0;
225*7304104dSAndroid Build Coastguard Worker
226*7304104dSAndroid Build Coastguard Worker const unsigned char *readp = dbg->sectiondata[IDX_debug_aranges]->d_buf;
227*7304104dSAndroid Build Coastguard Worker const unsigned char *readendp
228*7304104dSAndroid Build Coastguard Worker = readp + dbg->sectiondata[IDX_debug_aranges]->d_size;
229*7304104dSAndroid Build Coastguard Worker
230*7304104dSAndroid Build Coastguard Worker while (readp < readendp)
231*7304104dSAndroid Build Coastguard Worker {
232*7304104dSAndroid Build Coastguard Worker const unsigned char *hdrstart = readp;
233*7304104dSAndroid Build Coastguard Worker
234*7304104dSAndroid Build Coastguard Worker /* Each entry starts with a header:
235*7304104dSAndroid Build Coastguard Worker
236*7304104dSAndroid Build Coastguard Worker 1. A 4-byte or 12-byte length containing the length of the
237*7304104dSAndroid Build Coastguard Worker set of entries for this compilation unit, not including the
238*7304104dSAndroid Build Coastguard Worker length field itself. [...]
239*7304104dSAndroid Build Coastguard Worker
240*7304104dSAndroid Build Coastguard Worker 2. A 2-byte version identifier containing the value 2 for
241*7304104dSAndroid Build Coastguard Worker DWARF Version 2.1.
242*7304104dSAndroid Build Coastguard Worker
243*7304104dSAndroid Build Coastguard Worker 3. A 4-byte or 8-byte offset into the .debug_info section. [...]
244*7304104dSAndroid Build Coastguard Worker
245*7304104dSAndroid Build Coastguard Worker 4. A 1-byte unsigned integer containing the size in bytes of
246*7304104dSAndroid Build Coastguard Worker an address (or the offset portion of an address for segmented
247*7304104dSAndroid Build Coastguard Worker addressing) on the target system.
248*7304104dSAndroid Build Coastguard Worker
249*7304104dSAndroid Build Coastguard Worker 5. A 1-byte unsigned integer containing the size in bytes of
250*7304104dSAndroid Build Coastguard Worker a segment descriptor on the target system. */
251*7304104dSAndroid Build Coastguard Worker if (unlikely (readp + 4 > readendp))
252*7304104dSAndroid Build Coastguard Worker goto invalid;
253*7304104dSAndroid Build Coastguard Worker
254*7304104dSAndroid Build Coastguard Worker Dwarf_Word length = read_4ubyte_unaligned_inc (dbg, readp);
255*7304104dSAndroid Build Coastguard Worker unsigned int length_bytes = 4;
256*7304104dSAndroid Build Coastguard Worker if (length == DWARF3_LENGTH_64_BIT)
257*7304104dSAndroid Build Coastguard Worker {
258*7304104dSAndroid Build Coastguard Worker if (unlikely (readp + 8 > readendp))
259*7304104dSAndroid Build Coastguard Worker goto invalid;
260*7304104dSAndroid Build Coastguard Worker
261*7304104dSAndroid Build Coastguard Worker length = read_8ubyte_unaligned_inc (dbg, readp);
262*7304104dSAndroid Build Coastguard Worker length_bytes = 8;
263*7304104dSAndroid Build Coastguard Worker }
264*7304104dSAndroid Build Coastguard Worker else if (unlikely (length >= DWARF3_LENGTH_MIN_ESCAPE_CODE
265*7304104dSAndroid Build Coastguard Worker && length <= DWARF3_LENGTH_MAX_ESCAPE_CODE))
266*7304104dSAndroid Build Coastguard Worker goto invalid;
267*7304104dSAndroid Build Coastguard Worker
268*7304104dSAndroid Build Coastguard Worker const unsigned char *endp = readp + length;
269*7304104dSAndroid Build Coastguard Worker if (unlikely (endp > readendp))
270*7304104dSAndroid Build Coastguard Worker goto invalid;
271*7304104dSAndroid Build Coastguard Worker
272*7304104dSAndroid Build Coastguard Worker if (unlikely (readp + 2 > readendp))
273*7304104dSAndroid Build Coastguard Worker goto invalid;
274*7304104dSAndroid Build Coastguard Worker
275*7304104dSAndroid Build Coastguard Worker unsigned int version = read_2ubyte_unaligned_inc (dbg, readp);
276*7304104dSAndroid Build Coastguard Worker if (version != 2)
277*7304104dSAndroid Build Coastguard Worker {
278*7304104dSAndroid Build Coastguard Worker invalid:
279*7304104dSAndroid Build Coastguard Worker __libdw_seterrno (DWARF_E_INVALID_DWARF);
280*7304104dSAndroid Build Coastguard Worker fail:
281*7304104dSAndroid Build Coastguard Worker while (arangelist != NULL)
282*7304104dSAndroid Build Coastguard Worker {
283*7304104dSAndroid Build Coastguard Worker struct arangelist *next = arangelist->next;
284*7304104dSAndroid Build Coastguard Worker free (arangelist);
285*7304104dSAndroid Build Coastguard Worker arangelist = next;
286*7304104dSAndroid Build Coastguard Worker }
287*7304104dSAndroid Build Coastguard Worker return -1;
288*7304104dSAndroid Build Coastguard Worker }
289*7304104dSAndroid Build Coastguard Worker
290*7304104dSAndroid Build Coastguard Worker Dwarf_Word offset = 0;
291*7304104dSAndroid Build Coastguard Worker if (__libdw_read_offset_inc (dbg,
292*7304104dSAndroid Build Coastguard Worker IDX_debug_aranges, &readp,
293*7304104dSAndroid Build Coastguard Worker length_bytes, &offset, IDX_debug_info, 4))
294*7304104dSAndroid Build Coastguard Worker goto fail;
295*7304104dSAndroid Build Coastguard Worker
296*7304104dSAndroid Build Coastguard Worker /* Next up two bytes for address and segment size. */
297*7304104dSAndroid Build Coastguard Worker if (readp + 2 > readendp)
298*7304104dSAndroid Build Coastguard Worker goto invalid;
299*7304104dSAndroid Build Coastguard Worker
300*7304104dSAndroid Build Coastguard Worker unsigned int address_size = *readp++;
301*7304104dSAndroid Build Coastguard Worker if (unlikely (address_size != 4 && address_size != 8))
302*7304104dSAndroid Build Coastguard Worker goto invalid;
303*7304104dSAndroid Build Coastguard Worker
304*7304104dSAndroid Build Coastguard Worker /* We don't actually support segment selectors. */
305*7304104dSAndroid Build Coastguard Worker unsigned int segment_size = *readp++;
306*7304104dSAndroid Build Coastguard Worker if (segment_size != 0)
307*7304104dSAndroid Build Coastguard Worker goto invalid;
308*7304104dSAndroid Build Coastguard Worker
309*7304104dSAndroid Build Coastguard Worker /* Round the address to the next multiple of 2*address_size. */
310*7304104dSAndroid Build Coastguard Worker readp += ((2 * address_size - ((readp - hdrstart) % (2 * address_size)))
311*7304104dSAndroid Build Coastguard Worker % (2 * address_size));
312*7304104dSAndroid Build Coastguard Worker
313*7304104dSAndroid Build Coastguard Worker while (1)
314*7304104dSAndroid Build Coastguard Worker {
315*7304104dSAndroid Build Coastguard Worker Dwarf_Word range_address;
316*7304104dSAndroid Build Coastguard Worker Dwarf_Word range_length;
317*7304104dSAndroid Build Coastguard Worker
318*7304104dSAndroid Build Coastguard Worker if (__libdw_read_address_inc (dbg, IDX_debug_aranges, &readp,
319*7304104dSAndroid Build Coastguard Worker address_size, &range_address))
320*7304104dSAndroid Build Coastguard Worker goto fail;
321*7304104dSAndroid Build Coastguard Worker
322*7304104dSAndroid Build Coastguard Worker if (readp + address_size > readendp)
323*7304104dSAndroid Build Coastguard Worker goto invalid;
324*7304104dSAndroid Build Coastguard Worker
325*7304104dSAndroid Build Coastguard Worker if (address_size == 4)
326*7304104dSAndroid Build Coastguard Worker range_length = read_4ubyte_unaligned_inc (dbg, readp);
327*7304104dSAndroid Build Coastguard Worker else
328*7304104dSAndroid Build Coastguard Worker range_length = read_8ubyte_unaligned_inc (dbg, readp);
329*7304104dSAndroid Build Coastguard Worker
330*7304104dSAndroid Build Coastguard Worker /* Two zero values mark the end. But in some cases (bugs)
331*7304104dSAndroid Build Coastguard Worker there might be such entries in the middle of the table.
332*7304104dSAndroid Build Coastguard Worker Ignore and continue, we'll check the actual length of
333*7304104dSAndroid Build Coastguard Worker the table to see if we are really at the end. */
334*7304104dSAndroid Build Coastguard Worker if (range_address == 0 && range_length == 0)
335*7304104dSAndroid Build Coastguard Worker {
336*7304104dSAndroid Build Coastguard Worker if (readp >= endp)
337*7304104dSAndroid Build Coastguard Worker break;
338*7304104dSAndroid Build Coastguard Worker else
339*7304104dSAndroid Build Coastguard Worker continue;
340*7304104dSAndroid Build Coastguard Worker }
341*7304104dSAndroid Build Coastguard Worker
342*7304104dSAndroid Build Coastguard Worker /* We don't use alloca for these temporary structures because
343*7304104dSAndroid Build Coastguard Worker the total number of them can be quite large. */
344*7304104dSAndroid Build Coastguard Worker struct arangelist *new_arange = malloc (sizeof *new_arange);
345*7304104dSAndroid Build Coastguard Worker if (unlikely (new_arange == NULL))
346*7304104dSAndroid Build Coastguard Worker {
347*7304104dSAndroid Build Coastguard Worker __libdw_seterrno (DWARF_E_NOMEM);
348*7304104dSAndroid Build Coastguard Worker goto fail;
349*7304104dSAndroid Build Coastguard Worker }
350*7304104dSAndroid Build Coastguard Worker
351*7304104dSAndroid Build Coastguard Worker new_arange->arange.addr = range_address;
352*7304104dSAndroid Build Coastguard Worker new_arange->arange.length = range_length;
353*7304104dSAndroid Build Coastguard Worker
354*7304104dSAndroid Build Coastguard Worker /* We store the actual CU DIE offset, not the CU header offset. */
355*7304104dSAndroid Build Coastguard Worker Dwarf_CU *cu = __libdw_findcu (dbg, offset, false);
356*7304104dSAndroid Build Coastguard Worker if (unlikely (cu == NULL))
357*7304104dSAndroid Build Coastguard Worker {
358*7304104dSAndroid Build Coastguard Worker /* We haven't gotten a chance to link in the new_arange
359*7304104dSAndroid Build Coastguard Worker into the arangelist, don't leak it. */
360*7304104dSAndroid Build Coastguard Worker free (new_arange);
361*7304104dSAndroid Build Coastguard Worker goto fail;
362*7304104dSAndroid Build Coastguard Worker }
363*7304104dSAndroid Build Coastguard Worker new_arange->arange.offset = __libdw_first_die_off_from_cu (cu);
364*7304104dSAndroid Build Coastguard Worker
365*7304104dSAndroid Build Coastguard Worker new_arange->next = arangelist;
366*7304104dSAndroid Build Coastguard Worker arangelist = new_arange;
367*7304104dSAndroid Build Coastguard Worker ++narangelist;
368*7304104dSAndroid Build Coastguard Worker
369*7304104dSAndroid Build Coastguard Worker /* Sanity-check the data. */
370*7304104dSAndroid Build Coastguard Worker if (unlikely (new_arange->arange.offset
371*7304104dSAndroid Build Coastguard Worker >= dbg->sectiondata[IDX_debug_info]->d_size))
372*7304104dSAndroid Build Coastguard Worker goto invalid;
373*7304104dSAndroid Build Coastguard Worker }
374*7304104dSAndroid Build Coastguard Worker }
375*7304104dSAndroid Build Coastguard Worker
376*7304104dSAndroid Build Coastguard Worker if (narangelist == 0)
377*7304104dSAndroid Build Coastguard Worker {
378*7304104dSAndroid Build Coastguard Worker if (naranges != NULL)
379*7304104dSAndroid Build Coastguard Worker *naranges = 0;
380*7304104dSAndroid Build Coastguard Worker *aranges = NULL;
381*7304104dSAndroid Build Coastguard Worker return 0;
382*7304104dSAndroid Build Coastguard Worker }
383*7304104dSAndroid Build Coastguard Worker
384*7304104dSAndroid Build Coastguard Worker if (!finalize_aranges (dbg, aranges, naranges, arangelist, narangelist))
385*7304104dSAndroid Build Coastguard Worker goto fail;
386*7304104dSAndroid Build Coastguard Worker
387*7304104dSAndroid Build Coastguard Worker dbg->aranges = *aranges;
388*7304104dSAndroid Build Coastguard Worker return 0;
389*7304104dSAndroid Build Coastguard Worker }
390*7304104dSAndroid Build Coastguard Worker INTDEF(dwarf_getaranges)
391