xref: /aosp_15_r20/external/elfutils/libdw/dwarf_ranges.c (revision 7304104da70ce23c86437a01be71edd1a2d7f37e)
1*7304104dSAndroid Build Coastguard Worker /* Enumerate the PC ranges covered by a DIE.
2*7304104dSAndroid Build Coastguard Worker    Copyright (C) 2005, 2007, 2009, 2018 Red Hat, Inc.
3*7304104dSAndroid Build Coastguard Worker    This file is part of elfutils.
4*7304104dSAndroid Build Coastguard Worker 
5*7304104dSAndroid Build Coastguard Worker    This file is free software; you can redistribute it and/or modify
6*7304104dSAndroid Build Coastguard Worker    it under the terms of either
7*7304104dSAndroid Build Coastguard Worker 
8*7304104dSAndroid Build Coastguard Worker      * the GNU Lesser General Public License as published by the Free
9*7304104dSAndroid Build Coastguard Worker        Software Foundation; either version 3 of the License, or (at
10*7304104dSAndroid Build Coastguard Worker        your option) any later version
11*7304104dSAndroid Build Coastguard Worker 
12*7304104dSAndroid Build Coastguard Worker    or
13*7304104dSAndroid Build Coastguard Worker 
14*7304104dSAndroid Build Coastguard Worker      * the GNU General Public License as published by the Free
15*7304104dSAndroid Build Coastguard Worker        Software Foundation; either version 2 of the License, or (at
16*7304104dSAndroid Build Coastguard Worker        your option) any later version
17*7304104dSAndroid Build Coastguard Worker 
18*7304104dSAndroid Build Coastguard Worker    or both in parallel, as here.
19*7304104dSAndroid Build Coastguard Worker 
20*7304104dSAndroid Build Coastguard Worker    elfutils is distributed in the hope that it will be useful, but
21*7304104dSAndroid Build Coastguard Worker    WITHOUT ANY WARRANTY; without even the implied warranty of
22*7304104dSAndroid Build Coastguard Worker    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23*7304104dSAndroid Build Coastguard Worker    General Public License for more details.
24*7304104dSAndroid Build Coastguard Worker 
25*7304104dSAndroid Build Coastguard Worker    You should have received copies of the GNU General Public License and
26*7304104dSAndroid Build Coastguard Worker    the GNU Lesser General Public License along with this program.  If
27*7304104dSAndroid Build Coastguard Worker    not, see <http://www.gnu.org/licenses/>.  */
28*7304104dSAndroid Build Coastguard Worker 
29*7304104dSAndroid Build Coastguard Worker #ifdef HAVE_CONFIG_H
30*7304104dSAndroid Build Coastguard Worker # include <config.h>
31*7304104dSAndroid Build Coastguard Worker #endif
32*7304104dSAndroid Build Coastguard Worker 
33*7304104dSAndroid Build Coastguard Worker #include "libdwP.h"
34*7304104dSAndroid Build Coastguard Worker #include <dwarf.h>
35*7304104dSAndroid Build Coastguard Worker #include <assert.h>
36*7304104dSAndroid Build Coastguard Worker 
37*7304104dSAndroid Build Coastguard Worker /* Read up begin/end pair and increment read pointer.
38*7304104dSAndroid Build Coastguard Worker     - If it's normal range record, set up `*beginp' and `*endp' and return 0.
39*7304104dSAndroid Build Coastguard Worker     - If it's a default location, set `*beginp' (0), `*endp' (-1) and return 0.
40*7304104dSAndroid Build Coastguard Worker     - If it's base address selection record, set up `*basep' and return 1.
41*7304104dSAndroid Build Coastguard Worker     - If it's end of rangelist, don't set anything and return 2
42*7304104dSAndroid Build Coastguard Worker     - If an error occurs, don't set anything and return -1.  */
43*7304104dSAndroid Build Coastguard Worker internal_function int
__libdw_read_begin_end_pair_inc(Dwarf_CU * cu,int sec_index,const unsigned char ** addrp,const unsigned char * addrend,int width,Dwarf_Addr * beginp,Dwarf_Addr * endp,Dwarf_Addr * basep)44*7304104dSAndroid Build Coastguard Worker __libdw_read_begin_end_pair_inc (Dwarf_CU *cu, int sec_index,
45*7304104dSAndroid Build Coastguard Worker 				 const unsigned char **addrp,
46*7304104dSAndroid Build Coastguard Worker 				 const unsigned char *addrend,
47*7304104dSAndroid Build Coastguard Worker 				 int width,
48*7304104dSAndroid Build Coastguard Worker 				 Dwarf_Addr *beginp, Dwarf_Addr *endp,
49*7304104dSAndroid Build Coastguard Worker 				 Dwarf_Addr *basep)
50*7304104dSAndroid Build Coastguard Worker {
51*7304104dSAndroid Build Coastguard Worker   Dwarf *dbg = cu->dbg;
52*7304104dSAndroid Build Coastguard Worker   if (sec_index == IDX_debug_loc
53*7304104dSAndroid Build Coastguard Worker       && cu->version < 5
54*7304104dSAndroid Build Coastguard Worker       && cu->unit_type == DW_UT_split_compile)
55*7304104dSAndroid Build Coastguard Worker     {
56*7304104dSAndroid Build Coastguard Worker       /* GNU DebugFission.  */
57*7304104dSAndroid Build Coastguard Worker       const unsigned char *addr = *addrp;
58*7304104dSAndroid Build Coastguard Worker       if (addrend - addr < 1)
59*7304104dSAndroid Build Coastguard Worker 	goto invalid;
60*7304104dSAndroid Build Coastguard Worker 
61*7304104dSAndroid Build Coastguard Worker       const char code = *addr++;
62*7304104dSAndroid Build Coastguard Worker       uint64_t begin = 0, end = 0, base = *basep, addr_idx;
63*7304104dSAndroid Build Coastguard Worker       switch (code)
64*7304104dSAndroid Build Coastguard Worker 	{
65*7304104dSAndroid Build Coastguard Worker 	case DW_LLE_GNU_end_of_list_entry:
66*7304104dSAndroid Build Coastguard Worker 	  *addrp = addr;
67*7304104dSAndroid Build Coastguard Worker 	  return 2;
68*7304104dSAndroid Build Coastguard Worker 
69*7304104dSAndroid Build Coastguard Worker 	case DW_LLE_GNU_base_address_selection_entry:
70*7304104dSAndroid Build Coastguard Worker 	  if (addrend - addr < 1)
71*7304104dSAndroid Build Coastguard Worker 	    goto invalid;
72*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (addr_idx, addr, addrend);
73*7304104dSAndroid Build Coastguard Worker 	  if (__libdw_addrx (cu, addr_idx, &base) != 0)
74*7304104dSAndroid Build Coastguard Worker 	    return -1;
75*7304104dSAndroid Build Coastguard Worker 	  *basep = base;
76*7304104dSAndroid Build Coastguard Worker 	  *addrp = addr;
77*7304104dSAndroid Build Coastguard Worker 	  return 1;
78*7304104dSAndroid Build Coastguard Worker 
79*7304104dSAndroid Build Coastguard Worker 	case DW_LLE_GNU_start_end_entry:
80*7304104dSAndroid Build Coastguard Worker 	  if (addrend - addr < 1)
81*7304104dSAndroid Build Coastguard Worker 	    goto invalid;
82*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (addr_idx, addr, addrend);
83*7304104dSAndroid Build Coastguard Worker 	  if (__libdw_addrx (cu, addr_idx, &begin) != 0)
84*7304104dSAndroid Build Coastguard Worker 	    return -1;
85*7304104dSAndroid Build Coastguard Worker 	  if (addrend - addr < 1)
86*7304104dSAndroid Build Coastguard Worker 	    goto invalid;
87*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (addr_idx, addr, addrend);
88*7304104dSAndroid Build Coastguard Worker 	  if (__libdw_addrx (cu, addr_idx, &end) != 0)
89*7304104dSAndroid Build Coastguard Worker 	    return -1;
90*7304104dSAndroid Build Coastguard Worker 
91*7304104dSAndroid Build Coastguard Worker 	  *beginp = begin;
92*7304104dSAndroid Build Coastguard Worker 	  *endp = end;
93*7304104dSAndroid Build Coastguard Worker 	  *addrp = addr;
94*7304104dSAndroid Build Coastguard Worker 	  return 0;
95*7304104dSAndroid Build Coastguard Worker 
96*7304104dSAndroid Build Coastguard Worker 	case DW_LLE_GNU_start_length_entry:
97*7304104dSAndroid Build Coastguard Worker 	  if (addrend - addr < 1)
98*7304104dSAndroid Build Coastguard Worker 	    goto invalid;
99*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (addr_idx, addr, addrend);
100*7304104dSAndroid Build Coastguard Worker 	  if (__libdw_addrx (cu, addr_idx, &begin) != 0)
101*7304104dSAndroid Build Coastguard Worker 	    return -1;
102*7304104dSAndroid Build Coastguard Worker 	  if (addrend - addr < 4)
103*7304104dSAndroid Build Coastguard Worker 	    goto invalid;
104*7304104dSAndroid Build Coastguard Worker 	  end = read_4ubyte_unaligned_inc (dbg, addr);
105*7304104dSAndroid Build Coastguard Worker 
106*7304104dSAndroid Build Coastguard Worker 	  *beginp = begin;
107*7304104dSAndroid Build Coastguard Worker 	  *endp = begin + end;
108*7304104dSAndroid Build Coastguard Worker 	  *addrp = addr;
109*7304104dSAndroid Build Coastguard Worker 	  return 0;
110*7304104dSAndroid Build Coastguard Worker 
111*7304104dSAndroid Build Coastguard Worker 	default:
112*7304104dSAndroid Build Coastguard Worker 	  goto invalid;
113*7304104dSAndroid Build Coastguard Worker 	}
114*7304104dSAndroid Build Coastguard Worker     }
115*7304104dSAndroid Build Coastguard Worker   else if (sec_index == IDX_debug_ranges || sec_index == IDX_debug_loc)
116*7304104dSAndroid Build Coastguard Worker     {
117*7304104dSAndroid Build Coastguard Worker       Dwarf_Addr escape = (width == 8 ? (Elf64_Addr) -1
118*7304104dSAndroid Build Coastguard Worker 			   : (Elf64_Addr) (Elf32_Addr) -1);
119*7304104dSAndroid Build Coastguard Worker       Dwarf_Addr begin;
120*7304104dSAndroid Build Coastguard Worker       Dwarf_Addr end;
121*7304104dSAndroid Build Coastguard Worker 
122*7304104dSAndroid Build Coastguard Worker       const unsigned char *addr = *addrp;
123*7304104dSAndroid Build Coastguard Worker       if (addrend - addr < width * 2)
124*7304104dSAndroid Build Coastguard Worker 	{
125*7304104dSAndroid Build Coastguard Worker 	invalid:
126*7304104dSAndroid Build Coastguard Worker 	  __libdw_seterrno (DWARF_E_INVALID_DWARF);
127*7304104dSAndroid Build Coastguard Worker 	  return -1;
128*7304104dSAndroid Build Coastguard Worker 	}
129*7304104dSAndroid Build Coastguard Worker 
130*7304104dSAndroid Build Coastguard Worker       bool begin_relocated = READ_AND_RELOCATE (__libdw_relocate_address,
131*7304104dSAndroid Build Coastguard Worker 						begin);
132*7304104dSAndroid Build Coastguard Worker       bool end_relocated = READ_AND_RELOCATE (__libdw_relocate_address,
133*7304104dSAndroid Build Coastguard Worker 					      end);
134*7304104dSAndroid Build Coastguard Worker       *addrp = addr;
135*7304104dSAndroid Build Coastguard Worker 
136*7304104dSAndroid Build Coastguard Worker       /* Unrelocated escape for begin means base address selection.  */
137*7304104dSAndroid Build Coastguard Worker       if (begin == escape && !begin_relocated)
138*7304104dSAndroid Build Coastguard Worker 	{
139*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (end == escape))
140*7304104dSAndroid Build Coastguard Worker 	    goto invalid;
141*7304104dSAndroid Build Coastguard Worker 
142*7304104dSAndroid Build Coastguard Worker 	  *basep = end;
143*7304104dSAndroid Build Coastguard Worker 	  return 1;
144*7304104dSAndroid Build Coastguard Worker 	}
145*7304104dSAndroid Build Coastguard Worker 
146*7304104dSAndroid Build Coastguard Worker       /* Unrelocated pair of zeroes means end of range list.  */
147*7304104dSAndroid Build Coastguard Worker       if (begin == 0 && end == 0 && !begin_relocated && !end_relocated)
148*7304104dSAndroid Build Coastguard Worker 	return 2;
149*7304104dSAndroid Build Coastguard Worker 
150*7304104dSAndroid Build Coastguard Worker       /* Don't check for begin_relocated == end_relocated.  Serve the data
151*7304104dSAndroid Build Coastguard Worker 	 to the client even though it may be buggy.  */
152*7304104dSAndroid Build Coastguard Worker       *beginp = begin + *basep;
153*7304104dSAndroid Build Coastguard Worker       *endp = end + *basep;
154*7304104dSAndroid Build Coastguard Worker 
155*7304104dSAndroid Build Coastguard Worker       return 0;
156*7304104dSAndroid Build Coastguard Worker     }
157*7304104dSAndroid Build Coastguard Worker   else if (sec_index == IDX_debug_rnglists)
158*7304104dSAndroid Build Coastguard Worker     {
159*7304104dSAndroid Build Coastguard Worker       const unsigned char *addr = *addrp;
160*7304104dSAndroid Build Coastguard Worker       if (addrend - addr < 1)
161*7304104dSAndroid Build Coastguard Worker 	goto invalid;
162*7304104dSAndroid Build Coastguard Worker 
163*7304104dSAndroid Build Coastguard Worker       const char code = *addr++;
164*7304104dSAndroid Build Coastguard Worker       uint64_t begin = 0, end = 0, base = *basep, addr_idx;
165*7304104dSAndroid Build Coastguard Worker       switch (code)
166*7304104dSAndroid Build Coastguard Worker 	{
167*7304104dSAndroid Build Coastguard Worker 	case DW_RLE_end_of_list:
168*7304104dSAndroid Build Coastguard Worker 	  *addrp = addr;
169*7304104dSAndroid Build Coastguard Worker 	  return 2;
170*7304104dSAndroid Build Coastguard Worker 
171*7304104dSAndroid Build Coastguard Worker 	case DW_RLE_base_addressx:
172*7304104dSAndroid Build Coastguard Worker 	  if (addrend - addr < 1)
173*7304104dSAndroid Build Coastguard Worker 	    goto invalid;
174*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (addr_idx, addr, addrend);
175*7304104dSAndroid Build Coastguard Worker 	  if (__libdw_addrx (cu, addr_idx, &base) != 0)
176*7304104dSAndroid Build Coastguard Worker 	    return -1;
177*7304104dSAndroid Build Coastguard Worker 
178*7304104dSAndroid Build Coastguard Worker 	  *basep = base;
179*7304104dSAndroid Build Coastguard Worker 	  *addrp = addr;
180*7304104dSAndroid Build Coastguard Worker 	  return 1;
181*7304104dSAndroid Build Coastguard Worker 
182*7304104dSAndroid Build Coastguard Worker 	case DW_RLE_startx_endx:
183*7304104dSAndroid Build Coastguard Worker 	  if (addrend - addr < 1)
184*7304104dSAndroid Build Coastguard Worker 	    goto invalid;
185*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (addr_idx, addr, addrend);
186*7304104dSAndroid Build Coastguard Worker 	  if (__libdw_addrx (cu, addr_idx, &begin) != 0)
187*7304104dSAndroid Build Coastguard Worker 	    return -1;
188*7304104dSAndroid Build Coastguard Worker 	  if (addrend - addr < 1)
189*7304104dSAndroid Build Coastguard Worker 	    goto invalid;
190*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (addr_idx, addr, addrend);
191*7304104dSAndroid Build Coastguard Worker 	  if (__libdw_addrx (cu, addr_idx, &end) != 0)
192*7304104dSAndroid Build Coastguard Worker 	    return -1;
193*7304104dSAndroid Build Coastguard Worker 
194*7304104dSAndroid Build Coastguard Worker 	  *beginp = begin;
195*7304104dSAndroid Build Coastguard Worker 	  *endp = end;
196*7304104dSAndroid Build Coastguard Worker 	  *addrp = addr;
197*7304104dSAndroid Build Coastguard Worker 	  return 0;
198*7304104dSAndroid Build Coastguard Worker 
199*7304104dSAndroid Build Coastguard Worker 	case DW_RLE_startx_length:
200*7304104dSAndroid Build Coastguard Worker 	  if (addrend - addr < 1)
201*7304104dSAndroid Build Coastguard Worker 	    goto invalid;
202*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (addr_idx, addr, addrend);
203*7304104dSAndroid Build Coastguard Worker 	  if (__libdw_addrx (cu, addr_idx, &begin) != 0)
204*7304104dSAndroid Build Coastguard Worker 	    return -1;
205*7304104dSAndroid Build Coastguard Worker 	  if (addrend - addr < 1)
206*7304104dSAndroid Build Coastguard Worker 	    goto invalid;
207*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (end, addr, addrend);
208*7304104dSAndroid Build Coastguard Worker 
209*7304104dSAndroid Build Coastguard Worker 	  *beginp = begin;
210*7304104dSAndroid Build Coastguard Worker 	  *endp = begin + end;
211*7304104dSAndroid Build Coastguard Worker 	  *addrp = addr;
212*7304104dSAndroid Build Coastguard Worker 	  return 0;
213*7304104dSAndroid Build Coastguard Worker 
214*7304104dSAndroid Build Coastguard Worker 	case DW_RLE_offset_pair:
215*7304104dSAndroid Build Coastguard Worker 	  if (addrend - addr < 1)
216*7304104dSAndroid Build Coastguard Worker 	    goto invalid;
217*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (begin, addr, addrend);
218*7304104dSAndroid Build Coastguard Worker 	  if (addrend - addr < 1)
219*7304104dSAndroid Build Coastguard Worker 	    goto invalid;
220*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (end, addr, addrend);
221*7304104dSAndroid Build Coastguard Worker 
222*7304104dSAndroid Build Coastguard Worker 	  *beginp = begin + base;
223*7304104dSAndroid Build Coastguard Worker 	  *endp = end + base;
224*7304104dSAndroid Build Coastguard Worker 	  *addrp = addr;
225*7304104dSAndroid Build Coastguard Worker 	  return 0;
226*7304104dSAndroid Build Coastguard Worker 
227*7304104dSAndroid Build Coastguard Worker 	case DW_RLE_base_address:
228*7304104dSAndroid Build Coastguard Worker 	  if (addrend - addr < width)
229*7304104dSAndroid Build Coastguard Worker 	    goto invalid;
230*7304104dSAndroid Build Coastguard Worker 	  __libdw_read_address_inc (dbg, sec_index, &addr, width, &base);
231*7304104dSAndroid Build Coastguard Worker 
232*7304104dSAndroid Build Coastguard Worker 	  *basep = base;
233*7304104dSAndroid Build Coastguard Worker 	  *addrp = addr;
234*7304104dSAndroid Build Coastguard Worker 	  return 1;
235*7304104dSAndroid Build Coastguard Worker 
236*7304104dSAndroid Build Coastguard Worker 	case DW_RLE_start_end:
237*7304104dSAndroid Build Coastguard Worker 	  if (addrend - addr < 2 * width)
238*7304104dSAndroid Build Coastguard Worker 	    goto invalid;
239*7304104dSAndroid Build Coastguard Worker 	  __libdw_read_address_inc (dbg, sec_index, &addr, width, &begin);
240*7304104dSAndroid Build Coastguard Worker 	  __libdw_read_address_inc (dbg, sec_index, &addr, width, &end);
241*7304104dSAndroid Build Coastguard Worker 
242*7304104dSAndroid Build Coastguard Worker 	  *beginp = begin;
243*7304104dSAndroid Build Coastguard Worker 	  *endp = end;
244*7304104dSAndroid Build Coastguard Worker 	  *addrp = addr;
245*7304104dSAndroid Build Coastguard Worker 	  return 0;
246*7304104dSAndroid Build Coastguard Worker 
247*7304104dSAndroid Build Coastguard Worker 	case DW_RLE_start_length:
248*7304104dSAndroid Build Coastguard Worker 	  if (addrend - addr < width)
249*7304104dSAndroid Build Coastguard Worker 	    goto invalid;
250*7304104dSAndroid Build Coastguard Worker 	  __libdw_read_address_inc (dbg, sec_index, &addr, width, &begin);
251*7304104dSAndroid Build Coastguard Worker 	  if (addrend - addr < 1)
252*7304104dSAndroid Build Coastguard Worker 	    goto invalid;
253*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (end, addr, addrend);
254*7304104dSAndroid Build Coastguard Worker 
255*7304104dSAndroid Build Coastguard Worker 	  *beginp = begin;
256*7304104dSAndroid Build Coastguard Worker 	  *endp = begin + end;
257*7304104dSAndroid Build Coastguard Worker 	  *addrp = addr;
258*7304104dSAndroid Build Coastguard Worker 	  return 0;
259*7304104dSAndroid Build Coastguard Worker 
260*7304104dSAndroid Build Coastguard Worker 	default:
261*7304104dSAndroid Build Coastguard Worker 	  goto invalid;
262*7304104dSAndroid Build Coastguard Worker 	}
263*7304104dSAndroid Build Coastguard Worker     }
264*7304104dSAndroid Build Coastguard Worker   else if (sec_index == IDX_debug_loclists)
265*7304104dSAndroid Build Coastguard Worker     {
266*7304104dSAndroid Build Coastguard Worker       const unsigned char *addr = *addrp;
267*7304104dSAndroid Build Coastguard Worker       if (addrend - addr < 1)
268*7304104dSAndroid Build Coastguard Worker 	goto invalid;
269*7304104dSAndroid Build Coastguard Worker 
270*7304104dSAndroid Build Coastguard Worker       const char code = *addr++;
271*7304104dSAndroid Build Coastguard Worker       uint64_t begin = 0, end = 0, base = *basep, addr_idx;
272*7304104dSAndroid Build Coastguard Worker       switch (code)
273*7304104dSAndroid Build Coastguard Worker 	{
274*7304104dSAndroid Build Coastguard Worker 	case DW_LLE_end_of_list:
275*7304104dSAndroid Build Coastguard Worker 	  *addrp = addr;
276*7304104dSAndroid Build Coastguard Worker 	  return 2;
277*7304104dSAndroid Build Coastguard Worker 
278*7304104dSAndroid Build Coastguard Worker 	case DW_LLE_base_addressx:
279*7304104dSAndroid Build Coastguard Worker 	  if (addrend - addr < 1)
280*7304104dSAndroid Build Coastguard Worker 	    goto invalid;
281*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (addr_idx, addr, addrend);
282*7304104dSAndroid Build Coastguard Worker 	  if (__libdw_addrx (cu, addr_idx, &base) != 0)
283*7304104dSAndroid Build Coastguard Worker 	    return -1;
284*7304104dSAndroid Build Coastguard Worker 
285*7304104dSAndroid Build Coastguard Worker 	  *basep = base;
286*7304104dSAndroid Build Coastguard Worker 	  *addrp = addr;
287*7304104dSAndroid Build Coastguard Worker 	  return 1;
288*7304104dSAndroid Build Coastguard Worker 
289*7304104dSAndroid Build Coastguard Worker 	case DW_LLE_startx_endx:
290*7304104dSAndroid Build Coastguard Worker 	  if (addrend - addr < 1)
291*7304104dSAndroid Build Coastguard Worker 	    goto invalid;
292*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (addr_idx, addr, addrend);
293*7304104dSAndroid Build Coastguard Worker 	  if (__libdw_addrx (cu, addr_idx, &begin) != 0)
294*7304104dSAndroid Build Coastguard Worker 	    return -1;
295*7304104dSAndroid Build Coastguard Worker 	  if (addrend - addr < 1)
296*7304104dSAndroid Build Coastguard Worker 	    goto invalid;
297*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (addr_idx, addr, addrend);
298*7304104dSAndroid Build Coastguard Worker 	  if (__libdw_addrx (cu, addr_idx, &end) != 0)
299*7304104dSAndroid Build Coastguard Worker 	    return -1;
300*7304104dSAndroid Build Coastguard Worker 
301*7304104dSAndroid Build Coastguard Worker 	  *beginp = begin;
302*7304104dSAndroid Build Coastguard Worker 	  *endp = end;
303*7304104dSAndroid Build Coastguard Worker 	  *addrp = addr;
304*7304104dSAndroid Build Coastguard Worker 	  return 0;
305*7304104dSAndroid Build Coastguard Worker 
306*7304104dSAndroid Build Coastguard Worker 	case DW_LLE_startx_length:
307*7304104dSAndroid Build Coastguard Worker 	  if (addrend - addr < 1)
308*7304104dSAndroid Build Coastguard Worker 	    goto invalid;
309*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (addr_idx, addr, addrend);
310*7304104dSAndroid Build Coastguard Worker 	  if (__libdw_addrx (cu, addr_idx, &begin) != 0)
311*7304104dSAndroid Build Coastguard Worker 	    return -1;
312*7304104dSAndroid Build Coastguard Worker 	  if (addrend - addr < 1)
313*7304104dSAndroid Build Coastguard Worker 	    goto invalid;
314*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (end, addr, addrend);
315*7304104dSAndroid Build Coastguard Worker 
316*7304104dSAndroid Build Coastguard Worker 	  *beginp = begin;
317*7304104dSAndroid Build Coastguard Worker 	  *endp = begin + end;
318*7304104dSAndroid Build Coastguard Worker 	  *addrp = addr;
319*7304104dSAndroid Build Coastguard Worker 	  return 0;
320*7304104dSAndroid Build Coastguard Worker 
321*7304104dSAndroid Build Coastguard Worker 	case DW_LLE_offset_pair:
322*7304104dSAndroid Build Coastguard Worker 	  if (addrend - addr < 1)
323*7304104dSAndroid Build Coastguard Worker 	    goto invalid;
324*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (begin, addr, addrend);
325*7304104dSAndroid Build Coastguard Worker 	  if (addrend - addr < 1)
326*7304104dSAndroid Build Coastguard Worker 	    goto invalid;
327*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (end, addr, addrend);
328*7304104dSAndroid Build Coastguard Worker 
329*7304104dSAndroid Build Coastguard Worker 	  *beginp = begin + base;
330*7304104dSAndroid Build Coastguard Worker 	  *endp = end + base;
331*7304104dSAndroid Build Coastguard Worker 	  *addrp = addr;
332*7304104dSAndroid Build Coastguard Worker 	  return 0;
333*7304104dSAndroid Build Coastguard Worker 
334*7304104dSAndroid Build Coastguard Worker 	case DW_LLE_default_location:
335*7304104dSAndroid Build Coastguard Worker 	  *beginp = 0;
336*7304104dSAndroid Build Coastguard Worker 	  *endp = (Dwarf_Addr) -1;
337*7304104dSAndroid Build Coastguard Worker 	  *addrp = addr;
338*7304104dSAndroid Build Coastguard Worker 	  return 0;
339*7304104dSAndroid Build Coastguard Worker 
340*7304104dSAndroid Build Coastguard Worker 	case DW_LLE_base_address:
341*7304104dSAndroid Build Coastguard Worker 	  if (addrend - addr < width)
342*7304104dSAndroid Build Coastguard Worker 	    goto invalid;
343*7304104dSAndroid Build Coastguard Worker 	  __libdw_read_address_inc (dbg, sec_index, &addr, width, &base);
344*7304104dSAndroid Build Coastguard Worker 
345*7304104dSAndroid Build Coastguard Worker 	  *basep = base;
346*7304104dSAndroid Build Coastguard Worker 	  *addrp = addr;
347*7304104dSAndroid Build Coastguard Worker 	  return 1;
348*7304104dSAndroid Build Coastguard Worker 
349*7304104dSAndroid Build Coastguard Worker 	case DW_LLE_start_end:
350*7304104dSAndroid Build Coastguard Worker 	  if (addrend - addr < 2 * width)
351*7304104dSAndroid Build Coastguard Worker 	    goto invalid;
352*7304104dSAndroid Build Coastguard Worker 	  __libdw_read_address_inc (dbg, sec_index, &addr, width, &begin);
353*7304104dSAndroid Build Coastguard Worker 	  __libdw_read_address_inc (dbg, sec_index, &addr, width, &end);
354*7304104dSAndroid Build Coastguard Worker 
355*7304104dSAndroid Build Coastguard Worker 	  *beginp = begin;
356*7304104dSAndroid Build Coastguard Worker 	  *endp = end;
357*7304104dSAndroid Build Coastguard Worker 	  *addrp = addr;
358*7304104dSAndroid Build Coastguard Worker 	  return 0;
359*7304104dSAndroid Build Coastguard Worker 
360*7304104dSAndroid Build Coastguard Worker 	case DW_LLE_start_length:
361*7304104dSAndroid Build Coastguard Worker 	  if (addrend - addr < width)
362*7304104dSAndroid Build Coastguard Worker 	    goto invalid;
363*7304104dSAndroid Build Coastguard Worker 	  __libdw_read_address_inc (dbg, sec_index, &addr, width, &begin);
364*7304104dSAndroid Build Coastguard Worker 	  if (addrend - addr < 1)
365*7304104dSAndroid Build Coastguard Worker 	    goto invalid;
366*7304104dSAndroid Build Coastguard Worker 	  get_uleb128 (end, addr, addrend);
367*7304104dSAndroid Build Coastguard Worker 
368*7304104dSAndroid Build Coastguard Worker 	  *beginp = begin;
369*7304104dSAndroid Build Coastguard Worker 	  *endp = begin + end;
370*7304104dSAndroid Build Coastguard Worker 	  *addrp = addr;
371*7304104dSAndroid Build Coastguard Worker 	  return 0;
372*7304104dSAndroid Build Coastguard Worker 
373*7304104dSAndroid Build Coastguard Worker 	default:
374*7304104dSAndroid Build Coastguard Worker 	  goto invalid;
375*7304104dSAndroid Build Coastguard Worker 	}
376*7304104dSAndroid Build Coastguard Worker     }
377*7304104dSAndroid Build Coastguard Worker   else
378*7304104dSAndroid Build Coastguard Worker     {
379*7304104dSAndroid Build Coastguard Worker       __libdw_seterrno (DWARF_E_INVALID_DWARF);
380*7304104dSAndroid Build Coastguard Worker       return -1;
381*7304104dSAndroid Build Coastguard Worker     }
382*7304104dSAndroid Build Coastguard Worker }
383*7304104dSAndroid Build Coastguard Worker 
384*7304104dSAndroid Build Coastguard Worker static int
initial_offset(Dwarf_Attribute * attr,ptrdiff_t * offset)385*7304104dSAndroid Build Coastguard Worker initial_offset (Dwarf_Attribute *attr, ptrdiff_t *offset)
386*7304104dSAndroid Build Coastguard Worker {
387*7304104dSAndroid Build Coastguard Worker   size_t secidx = (attr->cu->version < 5
388*7304104dSAndroid Build Coastguard Worker 		   ? IDX_debug_ranges : IDX_debug_rnglists);
389*7304104dSAndroid Build Coastguard Worker 
390*7304104dSAndroid Build Coastguard Worker   Dwarf_Word start_offset;
391*7304104dSAndroid Build Coastguard Worker   if (attr->form == DW_FORM_rnglistx)
392*7304104dSAndroid Build Coastguard Worker     {
393*7304104dSAndroid Build Coastguard Worker       Dwarf_Word idx;
394*7304104dSAndroid Build Coastguard Worker       Dwarf_CU *cu = attr->cu;
395*7304104dSAndroid Build Coastguard Worker       const unsigned char *datap = attr->valp;
396*7304104dSAndroid Build Coastguard Worker       const unsigned char *endp = cu->endp;
397*7304104dSAndroid Build Coastguard Worker       if (datap >= endp)
398*7304104dSAndroid Build Coastguard Worker 	{
399*7304104dSAndroid Build Coastguard Worker 	  __libdw_seterrno (DWARF_E_INVALID_DWARF);
400*7304104dSAndroid Build Coastguard Worker 	  return -1;
401*7304104dSAndroid Build Coastguard Worker 	}
402*7304104dSAndroid Build Coastguard Worker       get_uleb128 (idx, datap, endp);
403*7304104dSAndroid Build Coastguard Worker 
404*7304104dSAndroid Build Coastguard Worker       Elf_Data *data = cu->dbg->sectiondata[secidx];
405*7304104dSAndroid Build Coastguard Worker       if (data == NULL && cu->unit_type == DW_UT_split_compile)
406*7304104dSAndroid Build Coastguard Worker 	{
407*7304104dSAndroid Build Coastguard Worker 	  cu = __libdw_find_split_unit (cu);
408*7304104dSAndroid Build Coastguard Worker 	  if (cu != NULL)
409*7304104dSAndroid Build Coastguard Worker 	    data = cu->dbg->sectiondata[secidx];
410*7304104dSAndroid Build Coastguard Worker 	}
411*7304104dSAndroid Build Coastguard Worker 
412*7304104dSAndroid Build Coastguard Worker       if (data == NULL)
413*7304104dSAndroid Build Coastguard Worker 	{
414*7304104dSAndroid Build Coastguard Worker 	  __libdw_seterrno (secidx == IDX_debug_ranges
415*7304104dSAndroid Build Coastguard Worker                             ? DWARF_E_NO_DEBUG_RANGES
416*7304104dSAndroid Build Coastguard Worker                             : DWARF_E_NO_DEBUG_RNGLISTS);
417*7304104dSAndroid Build Coastguard Worker 	  return -1;
418*7304104dSAndroid Build Coastguard Worker 	}
419*7304104dSAndroid Build Coastguard Worker 
420*7304104dSAndroid Build Coastguard Worker       Dwarf_Off range_base_off = __libdw_cu_ranges_base (cu);
421*7304104dSAndroid Build Coastguard Worker 
422*7304104dSAndroid Build Coastguard Worker       /* The section should at least contain room for one offset.  */
423*7304104dSAndroid Build Coastguard Worker       size_t sec_size = cu->dbg->sectiondata[secidx]->d_size;
424*7304104dSAndroid Build Coastguard Worker       size_t offset_size = cu->offset_size;
425*7304104dSAndroid Build Coastguard Worker       if (offset_size > sec_size)
426*7304104dSAndroid Build Coastguard Worker 	{
427*7304104dSAndroid Build Coastguard Worker 	invalid_offset:
428*7304104dSAndroid Build Coastguard Worker 	  __libdw_seterrno (DWARF_E_INVALID_OFFSET);
429*7304104dSAndroid Build Coastguard Worker 	  return -1;
430*7304104dSAndroid Build Coastguard Worker 	}
431*7304104dSAndroid Build Coastguard Worker 
432*7304104dSAndroid Build Coastguard Worker       /* And the base offset should be at least inside the section.  */
433*7304104dSAndroid Build Coastguard Worker       if (range_base_off > (sec_size - offset_size))
434*7304104dSAndroid Build Coastguard Worker 	goto invalid_offset;
435*7304104dSAndroid Build Coastguard Worker 
436*7304104dSAndroid Build Coastguard Worker       size_t max_idx = (sec_size - offset_size - range_base_off) / offset_size;
437*7304104dSAndroid Build Coastguard Worker       if (idx > max_idx)
438*7304104dSAndroid Build Coastguard Worker 	goto invalid_offset;
439*7304104dSAndroid Build Coastguard Worker 
440*7304104dSAndroid Build Coastguard Worker       datap = (cu->dbg->sectiondata[secidx]->d_buf
441*7304104dSAndroid Build Coastguard Worker 	       + range_base_off + (idx * offset_size));
442*7304104dSAndroid Build Coastguard Worker       if (offset_size == 4)
443*7304104dSAndroid Build Coastguard Worker 	start_offset = read_4ubyte_unaligned (cu->dbg, datap);
444*7304104dSAndroid Build Coastguard Worker       else
445*7304104dSAndroid Build Coastguard Worker 	start_offset = read_8ubyte_unaligned (cu->dbg, datap);
446*7304104dSAndroid Build Coastguard Worker 
447*7304104dSAndroid Build Coastguard Worker       start_offset += range_base_off;
448*7304104dSAndroid Build Coastguard Worker     }
449*7304104dSAndroid Build Coastguard Worker   else
450*7304104dSAndroid Build Coastguard Worker     {
451*7304104dSAndroid Build Coastguard Worker       if (__libdw_formptr (attr, secidx,
452*7304104dSAndroid Build Coastguard Worker 			   (secidx == IDX_debug_ranges
453*7304104dSAndroid Build Coastguard Worker 			    ? DWARF_E_NO_DEBUG_RANGES
454*7304104dSAndroid Build Coastguard Worker 			    : DWARF_E_NO_DEBUG_RNGLISTS),
455*7304104dSAndroid Build Coastguard Worker 			   NULL, &start_offset) == NULL)
456*7304104dSAndroid Build Coastguard Worker 	return -1;
457*7304104dSAndroid Build Coastguard Worker     }
458*7304104dSAndroid Build Coastguard Worker 
459*7304104dSAndroid Build Coastguard Worker   *offset = start_offset;
460*7304104dSAndroid Build Coastguard Worker   return 0;
461*7304104dSAndroid Build Coastguard Worker }
462*7304104dSAndroid Build Coastguard Worker 
463*7304104dSAndroid Build Coastguard Worker ptrdiff_t
dwarf_ranges(Dwarf_Die * die,ptrdiff_t offset,Dwarf_Addr * basep,Dwarf_Addr * startp,Dwarf_Addr * endp)464*7304104dSAndroid Build Coastguard Worker dwarf_ranges (Dwarf_Die *die, ptrdiff_t offset, Dwarf_Addr *basep,
465*7304104dSAndroid Build Coastguard Worker 	      Dwarf_Addr *startp, Dwarf_Addr *endp)
466*7304104dSAndroid Build Coastguard Worker {
467*7304104dSAndroid Build Coastguard Worker   if (die == NULL)
468*7304104dSAndroid Build Coastguard Worker     return -1;
469*7304104dSAndroid Build Coastguard Worker 
470*7304104dSAndroid Build Coastguard Worker   if (offset == 0
471*7304104dSAndroid Build Coastguard Worker       /* Usually there is a single contiguous range.  */
472*7304104dSAndroid Build Coastguard Worker       && INTUSE(dwarf_highpc) (die, endp) == 0
473*7304104dSAndroid Build Coastguard Worker       && INTUSE(dwarf_lowpc) (die, startp) == 0)
474*7304104dSAndroid Build Coastguard Worker     /* A offset into .debug_ranges will never be 1, it must be at least a
475*7304104dSAndroid Build Coastguard Worker        multiple of 4.  So we can return 1 as a special case value to mark
476*7304104dSAndroid Build Coastguard Worker        there are no ranges to look for on the next call.  */
477*7304104dSAndroid Build Coastguard Worker     return 1;
478*7304104dSAndroid Build Coastguard Worker 
479*7304104dSAndroid Build Coastguard Worker   if (offset == 1)
480*7304104dSAndroid Build Coastguard Worker     return 0;
481*7304104dSAndroid Build Coastguard Worker 
482*7304104dSAndroid Build Coastguard Worker   /* We have to look for a noncontiguous range.  */
483*7304104dSAndroid Build Coastguard Worker   Dwarf_CU *cu = die->cu;
484*7304104dSAndroid Build Coastguard Worker   if (cu == NULL)
485*7304104dSAndroid Build Coastguard Worker     {
486*7304104dSAndroid Build Coastguard Worker       __libdw_seterrno (DWARF_E_INVALID_DWARF);
487*7304104dSAndroid Build Coastguard Worker       return -1;
488*7304104dSAndroid Build Coastguard Worker     }
489*7304104dSAndroid Build Coastguard Worker 
490*7304104dSAndroid Build Coastguard Worker   size_t secidx = (cu->version < 5 ? IDX_debug_ranges : IDX_debug_rnglists);
491*7304104dSAndroid Build Coastguard Worker   const Elf_Data *d = cu->dbg->sectiondata[secidx];
492*7304104dSAndroid Build Coastguard Worker   if (cu->unit_type == DW_UT_split_compile && (d == NULL || is_cudie (die)))
493*7304104dSAndroid Build Coastguard Worker     {
494*7304104dSAndroid Build Coastguard Worker       Dwarf_CU *skel = __libdw_find_split_unit (cu);
495*7304104dSAndroid Build Coastguard Worker       if (skel != NULL && skel->dbg->sectiondata[secidx] != NULL)
496*7304104dSAndroid Build Coastguard Worker 	{
497*7304104dSAndroid Build Coastguard Worker 	  cu = skel;
498*7304104dSAndroid Build Coastguard Worker 	  d = cu->dbg->sectiondata[secidx];
499*7304104dSAndroid Build Coastguard Worker 	}
500*7304104dSAndroid Build Coastguard Worker     }
501*7304104dSAndroid Build Coastguard Worker 
502*7304104dSAndroid Build Coastguard Worker   const unsigned char *readp;
503*7304104dSAndroid Build Coastguard Worker   const unsigned char *readendp;
504*7304104dSAndroid Build Coastguard Worker   if (offset == 0)
505*7304104dSAndroid Build Coastguard Worker     {
506*7304104dSAndroid Build Coastguard Worker       Dwarf_Attribute attr_mem;
507*7304104dSAndroid Build Coastguard Worker       Dwarf_Attribute *attr = INTUSE(dwarf_attr) (die, DW_AT_ranges,
508*7304104dSAndroid Build Coastguard Worker 						  &attr_mem);
509*7304104dSAndroid Build Coastguard Worker       /* Note that above we use dwarf_attr, not dwarf_attr_integrate.
510*7304104dSAndroid Build Coastguard Worker 	 The only case where the ranges can come from another DIE
511*7304104dSAndroid Build Coastguard Worker 	 attribute are the split CU case. In that case we also have a
512*7304104dSAndroid Build Coastguard Worker 	 different CU to check against. But that is already set up
513*7304104dSAndroid Build Coastguard Worker 	 above using __libdw_find_split_unit.  */
514*7304104dSAndroid Build Coastguard Worker       if (attr == NULL
515*7304104dSAndroid Build Coastguard Worker 	  && is_cudie (die)
516*7304104dSAndroid Build Coastguard Worker 	  && die->cu->unit_type == DW_UT_split_compile)
517*7304104dSAndroid Build Coastguard Worker 	attr = INTUSE(dwarf_attr_integrate) (die, DW_AT_ranges, &attr_mem);
518*7304104dSAndroid Build Coastguard Worker       if (attr == NULL)
519*7304104dSAndroid Build Coastguard Worker 	/* No PC attributes in this DIE at all, so an empty range list.  */
520*7304104dSAndroid Build Coastguard Worker 	return 0;
521*7304104dSAndroid Build Coastguard Worker 
522*7304104dSAndroid Build Coastguard Worker       *basep = __libdw_cu_base_address (attr->cu);
523*7304104dSAndroid Build Coastguard Worker       if (*basep == (Dwarf_Addr) -1)
524*7304104dSAndroid Build Coastguard Worker 	return -1;
525*7304104dSAndroid Build Coastguard Worker 
526*7304104dSAndroid Build Coastguard Worker       if (initial_offset (attr, &offset) != 0)
527*7304104dSAndroid Build Coastguard Worker 	return -1;
528*7304104dSAndroid Build Coastguard Worker     }
529*7304104dSAndroid Build Coastguard Worker   else
530*7304104dSAndroid Build Coastguard Worker     {
531*7304104dSAndroid Build Coastguard Worker       if (__libdw_offset_in_section (cu->dbg,
532*7304104dSAndroid Build Coastguard Worker 				     secidx, offset, 1))
533*7304104dSAndroid Build Coastguard Worker 	return -1;
534*7304104dSAndroid Build Coastguard Worker     }
535*7304104dSAndroid Build Coastguard Worker 
536*7304104dSAndroid Build Coastguard Worker   readp = d->d_buf + offset;
537*7304104dSAndroid Build Coastguard Worker   readendp = d->d_buf + d->d_size;
538*7304104dSAndroid Build Coastguard Worker 
539*7304104dSAndroid Build Coastguard Worker   Dwarf_Addr begin;
540*7304104dSAndroid Build Coastguard Worker   Dwarf_Addr end;
541*7304104dSAndroid Build Coastguard Worker 
542*7304104dSAndroid Build Coastguard Worker  next:
543*7304104dSAndroid Build Coastguard Worker   switch (__libdw_read_begin_end_pair_inc (cu, secidx,
544*7304104dSAndroid Build Coastguard Worker 					   &readp, readendp,
545*7304104dSAndroid Build Coastguard Worker 					   cu->address_size,
546*7304104dSAndroid Build Coastguard Worker 					   &begin, &end, basep))
547*7304104dSAndroid Build Coastguard Worker     {
548*7304104dSAndroid Build Coastguard Worker     case 0:
549*7304104dSAndroid Build Coastguard Worker       break;
550*7304104dSAndroid Build Coastguard Worker     case 1:
551*7304104dSAndroid Build Coastguard Worker       goto next;
552*7304104dSAndroid Build Coastguard Worker     case 2:
553*7304104dSAndroid Build Coastguard Worker       return 0;
554*7304104dSAndroid Build Coastguard Worker     default:
555*7304104dSAndroid Build Coastguard Worker       return -1;
556*7304104dSAndroid Build Coastguard Worker     }
557*7304104dSAndroid Build Coastguard Worker 
558*7304104dSAndroid Build Coastguard Worker   *startp = begin;
559*7304104dSAndroid Build Coastguard Worker   *endp = end;
560*7304104dSAndroid Build Coastguard Worker   return readp - (unsigned char *) d->d_buf;
561*7304104dSAndroid Build Coastguard Worker }
562*7304104dSAndroid Build Coastguard Worker INTDEF (dwarf_ranges)
563