xref: /aosp_15_r20/external/elfutils/libdwfl/cu.c (revision 7304104da70ce23c86437a01be71edd1a2d7f37e)
1*7304104dSAndroid Build Coastguard Worker /* Keeping track of DWARF compilation units in libdwfl.
2*7304104dSAndroid Build Coastguard Worker    Copyright (C) 2005-2010, 2015, 2016, 2017 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 "libdwflP.h"
34*7304104dSAndroid Build Coastguard Worker #include "libdwP.h"
35*7304104dSAndroid Build Coastguard Worker #include "memory-access.h"
36*7304104dSAndroid Build Coastguard Worker #include <search.h>
37*7304104dSAndroid Build Coastguard Worker 
38*7304104dSAndroid Build Coastguard Worker 
39*7304104dSAndroid Build Coastguard Worker static inline Dwarf_Arange *
dwar(Dwfl_Module * mod,unsigned int idx)40*7304104dSAndroid Build Coastguard Worker dwar (Dwfl_Module *mod, unsigned int idx)
41*7304104dSAndroid Build Coastguard Worker {
42*7304104dSAndroid Build Coastguard Worker   return &mod->dw->dieranges->info[mod->aranges[idx].arange];
43*7304104dSAndroid Build Coastguard Worker }
44*7304104dSAndroid Build Coastguard Worker 
45*7304104dSAndroid Build Coastguard Worker 
46*7304104dSAndroid Build Coastguard Worker static Dwfl_Error
addrarange(Dwfl_Module * mod,Dwarf_Addr addr,struct dwfl_arange ** arange)47*7304104dSAndroid Build Coastguard Worker addrarange (Dwfl_Module *mod, Dwarf_Addr addr, struct dwfl_arange **arange)
48*7304104dSAndroid Build Coastguard Worker {
49*7304104dSAndroid Build Coastguard Worker   if (mod->aranges == NULL)
50*7304104dSAndroid Build Coastguard Worker     {
51*7304104dSAndroid Build Coastguard Worker       struct dwfl_arange *aranges = NULL;
52*7304104dSAndroid Build Coastguard Worker       Dwarf_Aranges *dwaranges = NULL;
53*7304104dSAndroid Build Coastguard Worker       size_t naranges;
54*7304104dSAndroid Build Coastguard Worker       if (__libdw_getdieranges (mod->dw, &dwaranges, &naranges) != 0)
55*7304104dSAndroid Build Coastguard Worker 	return DWFL_E_LIBDW;
56*7304104dSAndroid Build Coastguard Worker 
57*7304104dSAndroid Build Coastguard Worker       /* If the module has no aranges (when no code is included) we
58*7304104dSAndroid Build Coastguard Worker 	 allocate nothing.  */
59*7304104dSAndroid Build Coastguard Worker       if (naranges != 0)
60*7304104dSAndroid Build Coastguard Worker 	{
61*7304104dSAndroid Build Coastguard Worker 	  aranges = malloc (naranges * sizeof *aranges);
62*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (aranges == NULL))
63*7304104dSAndroid Build Coastguard Worker 	    return DWFL_E_NOMEM;
64*7304104dSAndroid Build Coastguard Worker 
65*7304104dSAndroid Build Coastguard Worker 	  /* libdw has sorted its list by address, which is how we want it.
66*7304104dSAndroid Build Coastguard Worker 	     But the sorted list is full of not-quite-contiguous runs pointing
67*7304104dSAndroid Build Coastguard Worker 	     to the same CU.  We don't care about the little gaps inside the
68*7304104dSAndroid Build Coastguard Worker 	     module, we'll consider them part of the surrounding CU anyway.
69*7304104dSAndroid Build Coastguard Worker 	     Collect our own array with just one record for each run of ranges
70*7304104dSAndroid Build Coastguard Worker 	     pointing to one CU.  */
71*7304104dSAndroid Build Coastguard Worker 
72*7304104dSAndroid Build Coastguard Worker 	  naranges = 0;
73*7304104dSAndroid Build Coastguard Worker 	  Dwarf_Off lastcu = 0;
74*7304104dSAndroid Build Coastguard Worker 	  for (size_t i = 0; i < dwaranges->naranges; ++i)
75*7304104dSAndroid Build Coastguard Worker 	    if (i == 0 || dwaranges->info[i].offset != lastcu)
76*7304104dSAndroid Build Coastguard Worker 	      {
77*7304104dSAndroid Build Coastguard Worker 		aranges[naranges].arange = i;
78*7304104dSAndroid Build Coastguard Worker 		aranges[naranges].cu = NULL;
79*7304104dSAndroid Build Coastguard Worker 		++naranges;
80*7304104dSAndroid Build Coastguard Worker 		lastcu = dwaranges->info[i].offset;
81*7304104dSAndroid Build Coastguard Worker 	      }
82*7304104dSAndroid Build Coastguard Worker 	}
83*7304104dSAndroid Build Coastguard Worker 
84*7304104dSAndroid Build Coastguard Worker       /* Store the final array, which is probably much smaller than before.  */
85*7304104dSAndroid Build Coastguard Worker       mod->naranges = naranges;
86*7304104dSAndroid Build Coastguard Worker       if (naranges > 0)
87*7304104dSAndroid Build Coastguard Worker         mod->aranges = (realloc (aranges, naranges * sizeof aranges[0])
88*7304104dSAndroid Build Coastguard Worker 			?: aranges);
89*7304104dSAndroid Build Coastguard Worker       else if (aranges != NULL)
90*7304104dSAndroid Build Coastguard Worker 	free (aranges);
91*7304104dSAndroid Build Coastguard Worker       mod->lazycu += naranges;
92*7304104dSAndroid Build Coastguard Worker     }
93*7304104dSAndroid Build Coastguard Worker 
94*7304104dSAndroid Build Coastguard Worker   /* The address must be inside the module to begin with.  */
95*7304104dSAndroid Build Coastguard Worker   addr = dwfl_deadjust_dwarf_addr (mod, addr);
96*7304104dSAndroid Build Coastguard Worker 
97*7304104dSAndroid Build Coastguard Worker   /* The ranges are sorted by address, so we can use binary search.  */
98*7304104dSAndroid Build Coastguard Worker   size_t l = 0, u = mod->naranges;
99*7304104dSAndroid Build Coastguard Worker   while (l < u)
100*7304104dSAndroid Build Coastguard Worker     {
101*7304104dSAndroid Build Coastguard Worker       size_t idx = (l + u) / 2;
102*7304104dSAndroid Build Coastguard Worker       Dwarf_Addr start = dwar (mod, idx)->addr;
103*7304104dSAndroid Build Coastguard Worker       if (addr < start)
104*7304104dSAndroid Build Coastguard Worker 	{
105*7304104dSAndroid Build Coastguard Worker 	  u = idx;
106*7304104dSAndroid Build Coastguard Worker 	  continue;
107*7304104dSAndroid Build Coastguard Worker 	}
108*7304104dSAndroid Build Coastguard Worker       else if (addr > start)
109*7304104dSAndroid Build Coastguard Worker 	{
110*7304104dSAndroid Build Coastguard Worker 	  if (idx + 1 < mod->naranges)
111*7304104dSAndroid Build Coastguard Worker 	    {
112*7304104dSAndroid Build Coastguard Worker 	      if (addr >= dwar (mod, idx + 1)->addr)
113*7304104dSAndroid Build Coastguard Worker 		{
114*7304104dSAndroid Build Coastguard Worker 		  l = idx + 1;
115*7304104dSAndroid Build Coastguard Worker 		  continue;
116*7304104dSAndroid Build Coastguard Worker 		}
117*7304104dSAndroid Build Coastguard Worker 	    }
118*7304104dSAndroid Build Coastguard Worker 	  else
119*7304104dSAndroid Build Coastguard Worker 	    {
120*7304104dSAndroid Build Coastguard Worker 	      /* It might be in the last range.  */
121*7304104dSAndroid Build Coastguard Worker 	      const Dwarf_Arange *last
122*7304104dSAndroid Build Coastguard Worker 		= &mod->dw->dieranges->info[mod->dw->dieranges->naranges - 1];
123*7304104dSAndroid Build Coastguard Worker 	      if (addr > last->addr + last->length)
124*7304104dSAndroid Build Coastguard Worker 		break;
125*7304104dSAndroid Build Coastguard Worker 	    }
126*7304104dSAndroid Build Coastguard Worker 	}
127*7304104dSAndroid Build Coastguard Worker 
128*7304104dSAndroid Build Coastguard Worker       *arange = &mod->aranges[idx];
129*7304104dSAndroid Build Coastguard Worker       return DWFL_E_NOERROR;
130*7304104dSAndroid Build Coastguard Worker     }
131*7304104dSAndroid Build Coastguard Worker 
132*7304104dSAndroid Build Coastguard Worker   return DWFL_E_ADDR_OUTOFRANGE;
133*7304104dSAndroid Build Coastguard Worker }
134*7304104dSAndroid Build Coastguard Worker 
135*7304104dSAndroid Build Coastguard Worker 
136*7304104dSAndroid Build Coastguard Worker static void
nofree(void * arg)137*7304104dSAndroid Build Coastguard Worker nofree (void *arg)
138*7304104dSAndroid Build Coastguard Worker {
139*7304104dSAndroid Build Coastguard Worker   struct dwfl_cu *cu = arg;
140*7304104dSAndroid Build Coastguard Worker   if (cu == (void *) -1l)
141*7304104dSAndroid Build Coastguard Worker     return;
142*7304104dSAndroid Build Coastguard Worker 
143*7304104dSAndroid Build Coastguard Worker   assert (cu->mod->lazycu == 0);
144*7304104dSAndroid Build Coastguard Worker }
145*7304104dSAndroid Build Coastguard Worker 
146*7304104dSAndroid Build Coastguard Worker /* One reason fewer to keep the lazy lookup table for CUs.  */
147*7304104dSAndroid Build Coastguard Worker static inline void
less_lazy(Dwfl_Module * mod)148*7304104dSAndroid Build Coastguard Worker less_lazy (Dwfl_Module *mod)
149*7304104dSAndroid Build Coastguard Worker {
150*7304104dSAndroid Build Coastguard Worker   if (--mod->lazycu > 0)
151*7304104dSAndroid Build Coastguard Worker     return;
152*7304104dSAndroid Build Coastguard Worker 
153*7304104dSAndroid Build Coastguard Worker   /* We know about all the CUs now, we don't need this table.  */
154*7304104dSAndroid Build Coastguard Worker   tdestroy (mod->lazy_cu_root, nofree);
155*7304104dSAndroid Build Coastguard Worker   mod->lazy_cu_root = NULL;
156*7304104dSAndroid Build Coastguard Worker }
157*7304104dSAndroid Build Coastguard Worker 
158*7304104dSAndroid Build Coastguard Worker static inline Dwarf_Off
cudie_offset(const struct dwfl_cu * cu)159*7304104dSAndroid Build Coastguard Worker cudie_offset (const struct dwfl_cu *cu)
160*7304104dSAndroid Build Coastguard Worker {
161*7304104dSAndroid Build Coastguard Worker   return __libdw_first_die_off_from_cu (cu->die.cu);
162*7304104dSAndroid Build Coastguard Worker }
163*7304104dSAndroid Build Coastguard Worker 
164*7304104dSAndroid Build Coastguard Worker static int
compare_cukey(const void * a,const void * b)165*7304104dSAndroid Build Coastguard Worker compare_cukey (const void *a, const void *b)
166*7304104dSAndroid Build Coastguard Worker {
167*7304104dSAndroid Build Coastguard Worker   Dwarf_Off a_off = cudie_offset (a);
168*7304104dSAndroid Build Coastguard Worker   Dwarf_Off b_off = cudie_offset (b);
169*7304104dSAndroid Build Coastguard Worker   return (a_off < b_off) ? -1 : ((a_off > b_off) ? 1 : 0);
170*7304104dSAndroid Build Coastguard Worker }
171*7304104dSAndroid Build Coastguard Worker 
172*7304104dSAndroid Build Coastguard Worker /* Intern the CU if necessary.  */
173*7304104dSAndroid Build Coastguard Worker static Dwfl_Error
intern_cu(Dwfl_Module * mod,Dwarf_Off cuoff,struct dwfl_cu ** result)174*7304104dSAndroid Build Coastguard Worker intern_cu (Dwfl_Module *mod, Dwarf_Off cuoff, struct dwfl_cu **result)
175*7304104dSAndroid Build Coastguard Worker {
176*7304104dSAndroid Build Coastguard Worker   if (unlikely (cuoff + 4 >= mod->dw->sectiondata[IDX_debug_info]->d_size))
177*7304104dSAndroid Build Coastguard Worker     {
178*7304104dSAndroid Build Coastguard Worker       if (likely (mod->lazycu == 1))
179*7304104dSAndroid Build Coastguard Worker 	{
180*7304104dSAndroid Build Coastguard Worker 	  /* This is the EOF marker.  Now we have interned all the CUs.
181*7304104dSAndroid Build Coastguard Worker 	     One increment in MOD->lazycu counts not having hit EOF yet.  */
182*7304104dSAndroid Build Coastguard Worker 	  *result = (void *) -1;
183*7304104dSAndroid Build Coastguard Worker 	  less_lazy (mod);
184*7304104dSAndroid Build Coastguard Worker 	  return DWFL_E_NOERROR;
185*7304104dSAndroid Build Coastguard Worker 	}
186*7304104dSAndroid Build Coastguard Worker       else
187*7304104dSAndroid Build Coastguard Worker 	{
188*7304104dSAndroid Build Coastguard Worker 	  /* Unexpected EOF, most likely a bogus aranges.  */
189*7304104dSAndroid Build Coastguard Worker 	  return (DWFL_E (LIBDW, DWARF_E_INVALID_DWARF));
190*7304104dSAndroid Build Coastguard Worker 	}
191*7304104dSAndroid Build Coastguard Worker     }
192*7304104dSAndroid Build Coastguard Worker 
193*7304104dSAndroid Build Coastguard Worker   /* Make sure the cuoff points to a real DIE.  */
194*7304104dSAndroid Build Coastguard Worker   Dwarf_Die cudie;
195*7304104dSAndroid Build Coastguard Worker   Dwarf_Die *die = INTUSE(dwarf_offdie) (mod->dw, cuoff, &cudie);
196*7304104dSAndroid Build Coastguard Worker   if (die == NULL)
197*7304104dSAndroid Build Coastguard Worker     return DWFL_E_LIBDW;
198*7304104dSAndroid Build Coastguard Worker 
199*7304104dSAndroid Build Coastguard Worker   struct dwfl_cu key;
200*7304104dSAndroid Build Coastguard Worker   key.die.cu = die->cu;
201*7304104dSAndroid Build Coastguard Worker   struct dwfl_cu **found = tsearch (&key, &mod->lazy_cu_root, &compare_cukey);
202*7304104dSAndroid Build Coastguard Worker   if (unlikely (found == NULL))
203*7304104dSAndroid Build Coastguard Worker     return DWFL_E_NOMEM;
204*7304104dSAndroid Build Coastguard Worker 
205*7304104dSAndroid Build Coastguard Worker   if (*found == &key || *found == NULL)
206*7304104dSAndroid Build Coastguard Worker     {
207*7304104dSAndroid Build Coastguard Worker       /* This is a new entry, meaning we haven't looked at this CU.  */
208*7304104dSAndroid Build Coastguard Worker 
209*7304104dSAndroid Build Coastguard Worker       *found = NULL;
210*7304104dSAndroid Build Coastguard Worker 
211*7304104dSAndroid Build Coastguard Worker       struct dwfl_cu *cu = malloc (sizeof *cu);
212*7304104dSAndroid Build Coastguard Worker       if (unlikely (cu == NULL))
213*7304104dSAndroid Build Coastguard Worker 	return DWFL_E_NOMEM;
214*7304104dSAndroid Build Coastguard Worker 
215*7304104dSAndroid Build Coastguard Worker       cu->mod = mod;
216*7304104dSAndroid Build Coastguard Worker       cu->next = NULL;
217*7304104dSAndroid Build Coastguard Worker       cu->lines = NULL;
218*7304104dSAndroid Build Coastguard Worker       cu->die = cudie;
219*7304104dSAndroid Build Coastguard Worker 
220*7304104dSAndroid Build Coastguard Worker       struct dwfl_cu **newvec = realloc (mod->cu, ((mod->ncu + 1)
221*7304104dSAndroid Build Coastguard Worker 						   * sizeof (mod->cu[0])));
222*7304104dSAndroid Build Coastguard Worker       if (newvec == NULL)
223*7304104dSAndroid Build Coastguard Worker 	{
224*7304104dSAndroid Build Coastguard Worker 	  free (cu);
225*7304104dSAndroid Build Coastguard Worker 	  return DWFL_E_NOMEM;
226*7304104dSAndroid Build Coastguard Worker 	}
227*7304104dSAndroid Build Coastguard Worker       mod->cu = newvec;
228*7304104dSAndroid Build Coastguard Worker 
229*7304104dSAndroid Build Coastguard Worker       mod->cu[mod->ncu++] = cu;
230*7304104dSAndroid Build Coastguard Worker       if (cu->die.cu->start == 0)
231*7304104dSAndroid Build Coastguard Worker 	mod->first_cu = cu;
232*7304104dSAndroid Build Coastguard Worker 
233*7304104dSAndroid Build Coastguard Worker       *found = cu;
234*7304104dSAndroid Build Coastguard Worker     }
235*7304104dSAndroid Build Coastguard Worker 
236*7304104dSAndroid Build Coastguard Worker   *result = *found;
237*7304104dSAndroid Build Coastguard Worker   return DWFL_E_NOERROR;
238*7304104dSAndroid Build Coastguard Worker }
239*7304104dSAndroid Build Coastguard Worker 
240*7304104dSAndroid Build Coastguard Worker 
241*7304104dSAndroid Build Coastguard Worker /* Traverse all the CUs in the module.  */
242*7304104dSAndroid Build Coastguard Worker 
243*7304104dSAndroid Build Coastguard Worker Dwfl_Error
244*7304104dSAndroid Build Coastguard Worker internal_function
__libdwfl_nextcu(Dwfl_Module * mod,struct dwfl_cu * lastcu,struct dwfl_cu ** cu)245*7304104dSAndroid Build Coastguard Worker __libdwfl_nextcu (Dwfl_Module *mod, struct dwfl_cu *lastcu,
246*7304104dSAndroid Build Coastguard Worker 		  struct dwfl_cu **cu)
247*7304104dSAndroid Build Coastguard Worker {
248*7304104dSAndroid Build Coastguard Worker   Dwarf_Off cuoff;
249*7304104dSAndroid Build Coastguard Worker   struct dwfl_cu **nextp;
250*7304104dSAndroid Build Coastguard Worker 
251*7304104dSAndroid Build Coastguard Worker   if (lastcu == NULL)
252*7304104dSAndroid Build Coastguard Worker     {
253*7304104dSAndroid Build Coastguard Worker       /* Start the traversal.  */
254*7304104dSAndroid Build Coastguard Worker       cuoff = 0;
255*7304104dSAndroid Build Coastguard Worker       nextp = &mod->first_cu;
256*7304104dSAndroid Build Coastguard Worker     }
257*7304104dSAndroid Build Coastguard Worker   else
258*7304104dSAndroid Build Coastguard Worker     {
259*7304104dSAndroid Build Coastguard Worker       /* Continue following LASTCU.  */
260*7304104dSAndroid Build Coastguard Worker       cuoff = lastcu->die.cu->end;
261*7304104dSAndroid Build Coastguard Worker       nextp = &lastcu->next;
262*7304104dSAndroid Build Coastguard Worker     }
263*7304104dSAndroid Build Coastguard Worker 
264*7304104dSAndroid Build Coastguard Worker   if (*nextp == NULL)
265*7304104dSAndroid Build Coastguard Worker     {
266*7304104dSAndroid Build Coastguard Worker       size_t cuhdrsz;
267*7304104dSAndroid Build Coastguard Worker       Dwarf_Off nextoff;
268*7304104dSAndroid Build Coastguard Worker       int end = INTUSE(dwarf_nextcu) (mod->dw, cuoff, &nextoff, &cuhdrsz,
269*7304104dSAndroid Build Coastguard Worker 				      NULL, NULL, NULL);
270*7304104dSAndroid Build Coastguard Worker       if (end < 0)
271*7304104dSAndroid Build Coastguard Worker 	return DWFL_E_LIBDW;
272*7304104dSAndroid Build Coastguard Worker       if (end > 0)
273*7304104dSAndroid Build Coastguard Worker 	{
274*7304104dSAndroid Build Coastguard Worker 	  *cu = NULL;
275*7304104dSAndroid Build Coastguard Worker 	  return DWFL_E_NOERROR;
276*7304104dSAndroid Build Coastguard Worker 	}
277*7304104dSAndroid Build Coastguard Worker 
278*7304104dSAndroid Build Coastguard Worker       Dwfl_Error result = intern_cu (mod, cuoff + cuhdrsz, nextp);
279*7304104dSAndroid Build Coastguard Worker       if (result != DWFL_E_NOERROR)
280*7304104dSAndroid Build Coastguard Worker 	return result;
281*7304104dSAndroid Build Coastguard Worker 
282*7304104dSAndroid Build Coastguard Worker       if (*nextp != (void *) -1
283*7304104dSAndroid Build Coastguard Worker 	  && (*nextp)->next == NULL && nextoff == (Dwarf_Off) -1l)
284*7304104dSAndroid Build Coastguard Worker 	(*nextp)->next = (void *) -1l;
285*7304104dSAndroid Build Coastguard Worker     }
286*7304104dSAndroid Build Coastguard Worker 
287*7304104dSAndroid Build Coastguard Worker   *cu = *nextp == (void *) -1l ? NULL : *nextp;
288*7304104dSAndroid Build Coastguard Worker   return DWFL_E_NOERROR;
289*7304104dSAndroid Build Coastguard Worker }
290*7304104dSAndroid Build Coastguard Worker 
291*7304104dSAndroid Build Coastguard Worker 
292*7304104dSAndroid Build Coastguard Worker /* Intern the CU arange points to, if necessary.  */
293*7304104dSAndroid Build Coastguard Worker 
294*7304104dSAndroid Build Coastguard Worker static Dwfl_Error
arangecu(Dwfl_Module * mod,struct dwfl_arange * arange,struct dwfl_cu ** cu)295*7304104dSAndroid Build Coastguard Worker arangecu (Dwfl_Module *mod, struct dwfl_arange *arange, struct dwfl_cu **cu)
296*7304104dSAndroid Build Coastguard Worker {
297*7304104dSAndroid Build Coastguard Worker   if (arange->cu == NULL)
298*7304104dSAndroid Build Coastguard Worker     {
299*7304104dSAndroid Build Coastguard Worker       const Dwarf_Arange *dwarange = &mod->dw->dieranges->info[arange->arange];
300*7304104dSAndroid Build Coastguard Worker       Dwfl_Error result = intern_cu (mod, dwarange->offset, &arange->cu);
301*7304104dSAndroid Build Coastguard Worker       if (result != DWFL_E_NOERROR)
302*7304104dSAndroid Build Coastguard Worker 	return result;
303*7304104dSAndroid Build Coastguard Worker       assert (arange->cu != NULL && arange->cu != (void *) -1l);
304*7304104dSAndroid Build Coastguard Worker       less_lazy (mod);		/* Each arange with null ->cu counts once.  */
305*7304104dSAndroid Build Coastguard Worker     }
306*7304104dSAndroid Build Coastguard Worker 
307*7304104dSAndroid Build Coastguard Worker   *cu = arange->cu;
308*7304104dSAndroid Build Coastguard Worker   return DWFL_E_NOERROR;
309*7304104dSAndroid Build Coastguard Worker }
310*7304104dSAndroid Build Coastguard Worker 
311*7304104dSAndroid Build Coastguard Worker Dwfl_Error
312*7304104dSAndroid Build Coastguard Worker internal_function
__libdwfl_addrcu(Dwfl_Module * mod,Dwarf_Addr addr,struct dwfl_cu ** cu)313*7304104dSAndroid Build Coastguard Worker __libdwfl_addrcu (Dwfl_Module *mod, Dwarf_Addr addr, struct dwfl_cu **cu)
314*7304104dSAndroid Build Coastguard Worker {
315*7304104dSAndroid Build Coastguard Worker   struct dwfl_arange *arange;
316*7304104dSAndroid Build Coastguard Worker   return addrarange (mod, addr, &arange) ?: arangecu (mod, arange, cu);
317*7304104dSAndroid Build Coastguard Worker }
318