xref: /aosp_15_r20/external/elfutils/libdw/dwarf_getaranges.c (revision 7304104da70ce23c86437a01be71edd1a2d7f37e)
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