xref: /aosp_15_r20/external/elfutils/libdwfl/segment.c (revision 7304104da70ce23c86437a01be71edd1a2d7f37e)
1*7304104dSAndroid Build Coastguard Worker /* Manage address space lookup table for libdwfl.
2*7304104dSAndroid Build Coastguard Worker    Copyright (C) 2008, 2009, 2010, 2013, 2015 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 
35*7304104dSAndroid Build Coastguard Worker GElf_Addr
36*7304104dSAndroid Build Coastguard Worker internal_function
__libdwfl_segment_start(Dwfl * dwfl,GElf_Addr start)37*7304104dSAndroid Build Coastguard Worker __libdwfl_segment_start (Dwfl *dwfl, GElf_Addr start)
38*7304104dSAndroid Build Coastguard Worker {
39*7304104dSAndroid Build Coastguard Worker   if (dwfl->segment_align > 1)
40*7304104dSAndroid Build Coastguard Worker     start &= -dwfl->segment_align;
41*7304104dSAndroid Build Coastguard Worker   return start;
42*7304104dSAndroid Build Coastguard Worker }
43*7304104dSAndroid Build Coastguard Worker 
44*7304104dSAndroid Build Coastguard Worker GElf_Addr
45*7304104dSAndroid Build Coastguard Worker internal_function
__libdwfl_segment_end(Dwfl * dwfl,GElf_Addr end)46*7304104dSAndroid Build Coastguard Worker __libdwfl_segment_end (Dwfl *dwfl, GElf_Addr end)
47*7304104dSAndroid Build Coastguard Worker {
48*7304104dSAndroid Build Coastguard Worker   if (dwfl->segment_align > 1)
49*7304104dSAndroid Build Coastguard Worker     end = (end + dwfl->segment_align - 1) & -dwfl->segment_align;
50*7304104dSAndroid Build Coastguard Worker   return end;
51*7304104dSAndroid Build Coastguard Worker }
52*7304104dSAndroid Build Coastguard Worker 
53*7304104dSAndroid Build Coastguard Worker static bool
insert(Dwfl * dwfl,size_t i,GElf_Addr start,GElf_Addr end,int segndx)54*7304104dSAndroid Build Coastguard Worker insert (Dwfl *dwfl, size_t i, GElf_Addr start, GElf_Addr end, int segndx)
55*7304104dSAndroid Build Coastguard Worker {
56*7304104dSAndroid Build Coastguard Worker   bool need_start = (i == 0 || dwfl->lookup_addr[i - 1] != start);
57*7304104dSAndroid Build Coastguard Worker   bool need_end = (i + 1 >= dwfl->lookup_elts
58*7304104dSAndroid Build Coastguard Worker 		   || dwfl->lookup_addr[i + 1] != end);
59*7304104dSAndroid Build Coastguard Worker   size_t need = need_start + need_end;
60*7304104dSAndroid Build Coastguard Worker   if (need == 0)
61*7304104dSAndroid Build Coastguard Worker     return false;
62*7304104dSAndroid Build Coastguard Worker 
63*7304104dSAndroid Build Coastguard Worker   if (dwfl->lookup_alloc - dwfl->lookup_elts < need)
64*7304104dSAndroid Build Coastguard Worker     {
65*7304104dSAndroid Build Coastguard Worker       size_t n = dwfl->lookup_alloc == 0 ? 16 : dwfl->lookup_alloc * 2;
66*7304104dSAndroid Build Coastguard Worker       GElf_Addr *naddr = realloc (dwfl->lookup_addr, sizeof naddr[0] * n);
67*7304104dSAndroid Build Coastguard Worker       if (unlikely (naddr == NULL))
68*7304104dSAndroid Build Coastguard Worker 	return true;
69*7304104dSAndroid Build Coastguard Worker       int *nsegndx = realloc (dwfl->lookup_segndx, sizeof nsegndx[0] * n);
70*7304104dSAndroid Build Coastguard Worker       if (unlikely (nsegndx == NULL))
71*7304104dSAndroid Build Coastguard Worker 	{
72*7304104dSAndroid Build Coastguard Worker 	  if (naddr != dwfl->lookup_addr)
73*7304104dSAndroid Build Coastguard Worker 	    free (naddr);
74*7304104dSAndroid Build Coastguard Worker 	  return true;
75*7304104dSAndroid Build Coastguard Worker 	}
76*7304104dSAndroid Build Coastguard Worker       dwfl->lookup_alloc = n;
77*7304104dSAndroid Build Coastguard Worker       dwfl->lookup_addr = naddr;
78*7304104dSAndroid Build Coastguard Worker       dwfl->lookup_segndx = nsegndx;
79*7304104dSAndroid Build Coastguard Worker 
80*7304104dSAndroid Build Coastguard Worker       if (dwfl->lookup_module != NULL)
81*7304104dSAndroid Build Coastguard Worker 	{
82*7304104dSAndroid Build Coastguard Worker 	  /* Make sure this array is big enough too.  */
83*7304104dSAndroid Build Coastguard Worker 	  Dwfl_Module **old = dwfl->lookup_module;
84*7304104dSAndroid Build Coastguard Worker 	  dwfl->lookup_module = realloc (dwfl->lookup_module,
85*7304104dSAndroid Build Coastguard Worker 					 sizeof dwfl->lookup_module[0] * n);
86*7304104dSAndroid Build Coastguard Worker 	  if (unlikely (dwfl->lookup_module == NULL))
87*7304104dSAndroid Build Coastguard Worker 	    {
88*7304104dSAndroid Build Coastguard Worker 	      free (old);
89*7304104dSAndroid Build Coastguard Worker 	      return true;
90*7304104dSAndroid Build Coastguard Worker 	    }
91*7304104dSAndroid Build Coastguard Worker 	}
92*7304104dSAndroid Build Coastguard Worker     }
93*7304104dSAndroid Build Coastguard Worker 
94*7304104dSAndroid Build Coastguard Worker   if (unlikely (i < dwfl->lookup_elts))
95*7304104dSAndroid Build Coastguard Worker     {
96*7304104dSAndroid Build Coastguard Worker       const size_t move = dwfl->lookup_elts - i;
97*7304104dSAndroid Build Coastguard Worker       memmove (&dwfl->lookup_addr[i + need], &dwfl->lookup_addr[i],
98*7304104dSAndroid Build Coastguard Worker 	       move * sizeof dwfl->lookup_addr[0]);
99*7304104dSAndroid Build Coastguard Worker       memmove (&dwfl->lookup_segndx[i + need], &dwfl->lookup_segndx[i],
100*7304104dSAndroid Build Coastguard Worker 	       move * sizeof dwfl->lookup_segndx[0]);
101*7304104dSAndroid Build Coastguard Worker       if (dwfl->lookup_module != NULL)
102*7304104dSAndroid Build Coastguard Worker 	memmove (&dwfl->lookup_module[i + need], &dwfl->lookup_module[i],
103*7304104dSAndroid Build Coastguard Worker 		 move * sizeof dwfl->lookup_module[0]);
104*7304104dSAndroid Build Coastguard Worker     }
105*7304104dSAndroid Build Coastguard Worker 
106*7304104dSAndroid Build Coastguard Worker   if (need_start)
107*7304104dSAndroid Build Coastguard Worker     {
108*7304104dSAndroid Build Coastguard Worker       dwfl->lookup_addr[i] = start;
109*7304104dSAndroid Build Coastguard Worker       dwfl->lookup_segndx[i] = segndx;
110*7304104dSAndroid Build Coastguard Worker       if (dwfl->lookup_module != NULL)
111*7304104dSAndroid Build Coastguard Worker 	dwfl->lookup_module[i] = NULL;
112*7304104dSAndroid Build Coastguard Worker       ++i;
113*7304104dSAndroid Build Coastguard Worker     }
114*7304104dSAndroid Build Coastguard Worker   else
115*7304104dSAndroid Build Coastguard Worker     dwfl->lookup_segndx[i - 1] = segndx;
116*7304104dSAndroid Build Coastguard Worker 
117*7304104dSAndroid Build Coastguard Worker   if (need_end)
118*7304104dSAndroid Build Coastguard Worker     {
119*7304104dSAndroid Build Coastguard Worker       dwfl->lookup_addr[i] = end;
120*7304104dSAndroid Build Coastguard Worker       dwfl->lookup_segndx[i] = -1;
121*7304104dSAndroid Build Coastguard Worker       if (dwfl->lookup_module != NULL)
122*7304104dSAndroid Build Coastguard Worker 	dwfl->lookup_module[i] = NULL;
123*7304104dSAndroid Build Coastguard Worker     }
124*7304104dSAndroid Build Coastguard Worker 
125*7304104dSAndroid Build Coastguard Worker   dwfl->lookup_elts += need;
126*7304104dSAndroid Build Coastguard Worker 
127*7304104dSAndroid Build Coastguard Worker   return false;
128*7304104dSAndroid Build Coastguard Worker }
129*7304104dSAndroid Build Coastguard Worker 
130*7304104dSAndroid Build Coastguard Worker static int
lookup(Dwfl * dwfl,GElf_Addr address,int hint)131*7304104dSAndroid Build Coastguard Worker lookup (Dwfl *dwfl, GElf_Addr address, int hint)
132*7304104dSAndroid Build Coastguard Worker {
133*7304104dSAndroid Build Coastguard Worker   if (hint >= 0
134*7304104dSAndroid Build Coastguard Worker       && address >= dwfl->lookup_addr[hint]
135*7304104dSAndroid Build Coastguard Worker       && ((size_t) hint + 1 == dwfl->lookup_elts
136*7304104dSAndroid Build Coastguard Worker 	  || address < dwfl->lookup_addr[hint + 1]))
137*7304104dSAndroid Build Coastguard Worker     return hint;
138*7304104dSAndroid Build Coastguard Worker 
139*7304104dSAndroid Build Coastguard Worker   /* Do binary search on the array indexed by module load address.  */
140*7304104dSAndroid Build Coastguard Worker   size_t l = 0, u = dwfl->lookup_elts;
141*7304104dSAndroid Build Coastguard Worker   while (l < u)
142*7304104dSAndroid Build Coastguard Worker     {
143*7304104dSAndroid Build Coastguard Worker       size_t idx = (l + u) / 2;
144*7304104dSAndroid Build Coastguard Worker       if (address < dwfl->lookup_addr[idx])
145*7304104dSAndroid Build Coastguard Worker 	u = idx;
146*7304104dSAndroid Build Coastguard Worker       else
147*7304104dSAndroid Build Coastguard Worker 	{
148*7304104dSAndroid Build Coastguard Worker 	  l = idx + 1;
149*7304104dSAndroid Build Coastguard Worker 	  if (l == dwfl->lookup_elts || address < dwfl->lookup_addr[l])
150*7304104dSAndroid Build Coastguard Worker 	    return idx;
151*7304104dSAndroid Build Coastguard Worker 	}
152*7304104dSAndroid Build Coastguard Worker     }
153*7304104dSAndroid Build Coastguard Worker 
154*7304104dSAndroid Build Coastguard Worker   return -1;
155*7304104dSAndroid Build Coastguard Worker }
156*7304104dSAndroid Build Coastguard Worker 
157*7304104dSAndroid Build Coastguard Worker static bool
reify_segments(Dwfl * dwfl)158*7304104dSAndroid Build Coastguard Worker reify_segments (Dwfl *dwfl)
159*7304104dSAndroid Build Coastguard Worker {
160*7304104dSAndroid Build Coastguard Worker   int hint = -1;
161*7304104dSAndroid Build Coastguard Worker   int highest = -1;
162*7304104dSAndroid Build Coastguard Worker   bool fixup = false;
163*7304104dSAndroid Build Coastguard Worker   for (Dwfl_Module *mod = dwfl->modulelist; mod != NULL; mod = mod->next)
164*7304104dSAndroid Build Coastguard Worker     if (! mod->gc)
165*7304104dSAndroid Build Coastguard Worker       {
166*7304104dSAndroid Build Coastguard Worker 	const GElf_Addr start = __libdwfl_segment_start (dwfl, mod->low_addr);
167*7304104dSAndroid Build Coastguard Worker 	const GElf_Addr end = __libdwfl_segment_end (dwfl, mod->high_addr);
168*7304104dSAndroid Build Coastguard Worker 	bool resized = false;
169*7304104dSAndroid Build Coastguard Worker 
170*7304104dSAndroid Build Coastguard Worker 	int idx = lookup (dwfl, start, hint);
171*7304104dSAndroid Build Coastguard Worker 	if (unlikely (idx < 0))
172*7304104dSAndroid Build Coastguard Worker 	  {
173*7304104dSAndroid Build Coastguard Worker 	    /* Module starts below any segment.  Insert a low one.  */
174*7304104dSAndroid Build Coastguard Worker 	    if (unlikely (insert (dwfl, 0, start, end, -1)))
175*7304104dSAndroid Build Coastguard Worker 	      return true;
176*7304104dSAndroid Build Coastguard Worker 	    idx = 0;
177*7304104dSAndroid Build Coastguard Worker 	    resized = true;
178*7304104dSAndroid Build Coastguard Worker 	  }
179*7304104dSAndroid Build Coastguard Worker 	else if (dwfl->lookup_addr[idx] > start)
180*7304104dSAndroid Build Coastguard Worker 	  {
181*7304104dSAndroid Build Coastguard Worker 	    /* The module starts in the middle of this segment.  Split it.  */
182*7304104dSAndroid Build Coastguard Worker 	    if (unlikely (insert (dwfl, idx + 1, start, end,
183*7304104dSAndroid Build Coastguard Worker 				  dwfl->lookup_segndx[idx])))
184*7304104dSAndroid Build Coastguard Worker 	      return true;
185*7304104dSAndroid Build Coastguard Worker 	    ++idx;
186*7304104dSAndroid Build Coastguard Worker 	    resized = true;
187*7304104dSAndroid Build Coastguard Worker 	  }
188*7304104dSAndroid Build Coastguard Worker 	else if (dwfl->lookup_addr[idx] < start)
189*7304104dSAndroid Build Coastguard Worker 	  {
190*7304104dSAndroid Build Coastguard Worker 	    /* The module starts past the end of this segment.
191*7304104dSAndroid Build Coastguard Worker 	       Add a new one.  */
192*7304104dSAndroid Build Coastguard Worker 	    if (unlikely (insert (dwfl, idx + 1, start, end, -1)))
193*7304104dSAndroid Build Coastguard Worker 	      return true;
194*7304104dSAndroid Build Coastguard Worker 	    ++idx;
195*7304104dSAndroid Build Coastguard Worker 	    resized = true;
196*7304104dSAndroid Build Coastguard Worker 	  }
197*7304104dSAndroid Build Coastguard Worker 
198*7304104dSAndroid Build Coastguard Worker 	if ((size_t) idx + 1 < dwfl->lookup_elts
199*7304104dSAndroid Build Coastguard Worker 	    && end < dwfl->lookup_addr[idx + 1])
200*7304104dSAndroid Build Coastguard Worker 	  {
201*7304104dSAndroid Build Coastguard Worker 	    /* The module ends in the middle of this segment.  Split it.  */
202*7304104dSAndroid Build Coastguard Worker 	    if (unlikely (insert (dwfl, idx + 1,
203*7304104dSAndroid Build Coastguard Worker 				  end, dwfl->lookup_addr[idx + 1], -1)))
204*7304104dSAndroid Build Coastguard Worker 	      return true;
205*7304104dSAndroid Build Coastguard Worker 	    resized = true;
206*7304104dSAndroid Build Coastguard Worker 	  }
207*7304104dSAndroid Build Coastguard Worker 
208*7304104dSAndroid Build Coastguard Worker 	if (dwfl->lookup_module == NULL)
209*7304104dSAndroid Build Coastguard Worker 	  {
210*7304104dSAndroid Build Coastguard Worker 	    dwfl->lookup_module = calloc (dwfl->lookup_alloc,
211*7304104dSAndroid Build Coastguard Worker 					  sizeof dwfl->lookup_module[0]);
212*7304104dSAndroid Build Coastguard Worker 	    if (unlikely (dwfl->lookup_module == NULL))
213*7304104dSAndroid Build Coastguard Worker 	      return true;
214*7304104dSAndroid Build Coastguard Worker 	  }
215*7304104dSAndroid Build Coastguard Worker 
216*7304104dSAndroid Build Coastguard Worker 	/* Cache a backpointer in the module.  */
217*7304104dSAndroid Build Coastguard Worker 	mod->segment = idx;
218*7304104dSAndroid Build Coastguard Worker 
219*7304104dSAndroid Build Coastguard Worker 	/* Put MOD in the table for each segment that's inside it.  */
220*7304104dSAndroid Build Coastguard Worker 	do
221*7304104dSAndroid Build Coastguard Worker 	  dwfl->lookup_module[idx++] = mod;
222*7304104dSAndroid Build Coastguard Worker 	while ((size_t) idx < dwfl->lookup_elts
223*7304104dSAndroid Build Coastguard Worker 	       && dwfl->lookup_addr[idx] < end);
224*7304104dSAndroid Build Coastguard Worker 	assert (dwfl->lookup_module[mod->segment] == mod);
225*7304104dSAndroid Build Coastguard Worker 
226*7304104dSAndroid Build Coastguard Worker 	if (resized && idx - 1 >= highest)
227*7304104dSAndroid Build Coastguard Worker 	  /* Expanding the lookup tables invalidated backpointers
228*7304104dSAndroid Build Coastguard Worker 	     we've already stored.  Reset those ones.  */
229*7304104dSAndroid Build Coastguard Worker 	  fixup = true;
230*7304104dSAndroid Build Coastguard Worker 
231*7304104dSAndroid Build Coastguard Worker 	highest = idx - 1;
232*7304104dSAndroid Build Coastguard Worker 	hint = (size_t) idx < dwfl->lookup_elts ? idx : -1;
233*7304104dSAndroid Build Coastguard Worker       }
234*7304104dSAndroid Build Coastguard Worker 
235*7304104dSAndroid Build Coastguard Worker   if (fixup)
236*7304104dSAndroid Build Coastguard Worker     /* Reset backpointer indices invalidated by table insertions.  */
237*7304104dSAndroid Build Coastguard Worker     for (size_t idx = 0; idx < dwfl->lookup_elts; ++idx)
238*7304104dSAndroid Build Coastguard Worker       if (dwfl->lookup_module[idx] != NULL)
239*7304104dSAndroid Build Coastguard Worker 	dwfl->lookup_module[idx]->segment = idx;
240*7304104dSAndroid Build Coastguard Worker 
241*7304104dSAndroid Build Coastguard Worker   return false;
242*7304104dSAndroid Build Coastguard Worker }
243*7304104dSAndroid Build Coastguard Worker 
244*7304104dSAndroid Build Coastguard Worker int
dwfl_addrsegment(Dwfl * dwfl,Dwarf_Addr address,Dwfl_Module ** mod)245*7304104dSAndroid Build Coastguard Worker dwfl_addrsegment (Dwfl *dwfl, Dwarf_Addr address, Dwfl_Module **mod)
246*7304104dSAndroid Build Coastguard Worker {
247*7304104dSAndroid Build Coastguard Worker   if (unlikely (dwfl == NULL))
248*7304104dSAndroid Build Coastguard Worker     return -1;
249*7304104dSAndroid Build Coastguard Worker 
250*7304104dSAndroid Build Coastguard Worker   if (unlikely (dwfl->lookup_module == NULL)
251*7304104dSAndroid Build Coastguard Worker       && mod != NULL
252*7304104dSAndroid Build Coastguard Worker       && unlikely (reify_segments (dwfl)))
253*7304104dSAndroid Build Coastguard Worker     {
254*7304104dSAndroid Build Coastguard Worker       __libdwfl_seterrno (DWFL_E_NOMEM);
255*7304104dSAndroid Build Coastguard Worker       return -1;
256*7304104dSAndroid Build Coastguard Worker     }
257*7304104dSAndroid Build Coastguard Worker 
258*7304104dSAndroid Build Coastguard Worker   int idx = lookup (dwfl, address, -1);
259*7304104dSAndroid Build Coastguard Worker   if (likely (mod != NULL))
260*7304104dSAndroid Build Coastguard Worker     {
261*7304104dSAndroid Build Coastguard Worker       if (unlikely (idx < 0) || unlikely (dwfl->lookup_module == NULL))
262*7304104dSAndroid Build Coastguard Worker 	*mod = NULL;
263*7304104dSAndroid Build Coastguard Worker       else
264*7304104dSAndroid Build Coastguard Worker 	{
265*7304104dSAndroid Build Coastguard Worker 	  *mod = dwfl->lookup_module[idx];
266*7304104dSAndroid Build Coastguard Worker 
267*7304104dSAndroid Build Coastguard Worker 	  /* If this segment does not have a module, but the address is
268*7304104dSAndroid Build Coastguard Worker 	     the upper boundary of the previous segment's module, use that.  */
269*7304104dSAndroid Build Coastguard Worker 	  if (*mod == NULL && idx > 0 && dwfl->lookup_addr[idx] == address)
270*7304104dSAndroid Build Coastguard Worker 	    {
271*7304104dSAndroid Build Coastguard Worker 	      *mod = dwfl->lookup_module[idx - 1];
272*7304104dSAndroid Build Coastguard Worker 	      if (*mod != NULL && (*mod)->high_addr != address)
273*7304104dSAndroid Build Coastguard Worker 		*mod = NULL;
274*7304104dSAndroid Build Coastguard Worker 	    }
275*7304104dSAndroid Build Coastguard Worker 	}
276*7304104dSAndroid Build Coastguard Worker     }
277*7304104dSAndroid Build Coastguard Worker 
278*7304104dSAndroid Build Coastguard Worker   if (likely (idx >= 0))
279*7304104dSAndroid Build Coastguard Worker     /* Translate internal segment table index to user segment index.  */
280*7304104dSAndroid Build Coastguard Worker     idx = dwfl->lookup_segndx[idx];
281*7304104dSAndroid Build Coastguard Worker 
282*7304104dSAndroid Build Coastguard Worker   return idx;
283*7304104dSAndroid Build Coastguard Worker }
INTDEF(dwfl_addrsegment)284*7304104dSAndroid Build Coastguard Worker INTDEF (dwfl_addrsegment)
285*7304104dSAndroid Build Coastguard Worker 
286*7304104dSAndroid Build Coastguard Worker int
287*7304104dSAndroid Build Coastguard Worker dwfl_report_segment (Dwfl *dwfl, int ndx, const GElf_Phdr *phdr, GElf_Addr bias,
288*7304104dSAndroid Build Coastguard Worker 		     const void *ident)
289*7304104dSAndroid Build Coastguard Worker {
290*7304104dSAndroid Build Coastguard Worker   /* This was previously used for coalescing segments, but it was buggy since
291*7304104dSAndroid Build Coastguard Worker      day one.  We don't use it anymore.  */
292*7304104dSAndroid Build Coastguard Worker   (void)ident;
293*7304104dSAndroid Build Coastguard Worker 
294*7304104dSAndroid Build Coastguard Worker   if (dwfl == NULL)
295*7304104dSAndroid Build Coastguard Worker     return -1;
296*7304104dSAndroid Build Coastguard Worker 
297*7304104dSAndroid Build Coastguard Worker   if (ndx < 0)
298*7304104dSAndroid Build Coastguard Worker     ndx = dwfl->next_segndx;
299*7304104dSAndroid Build Coastguard Worker 
300*7304104dSAndroid Build Coastguard Worker   if (phdr->p_align > 1 && (dwfl->segment_align <= 1 ||
301*7304104dSAndroid Build Coastguard Worker 			    phdr->p_align < dwfl->segment_align))
302*7304104dSAndroid Build Coastguard Worker     dwfl->segment_align = phdr->p_align;
303*7304104dSAndroid Build Coastguard Worker 
304*7304104dSAndroid Build Coastguard Worker   if (unlikely (dwfl->lookup_module != NULL))
305*7304104dSAndroid Build Coastguard Worker     {
306*7304104dSAndroid Build Coastguard Worker       free (dwfl->lookup_module);
307*7304104dSAndroid Build Coastguard Worker       dwfl->lookup_module = NULL;
308*7304104dSAndroid Build Coastguard Worker     }
309*7304104dSAndroid Build Coastguard Worker 
310*7304104dSAndroid Build Coastguard Worker   GElf_Addr start = __libdwfl_segment_start (dwfl, bias + phdr->p_vaddr);
311*7304104dSAndroid Build Coastguard Worker   GElf_Addr end = __libdwfl_segment_end (dwfl,
312*7304104dSAndroid Build Coastguard Worker 					 bias + phdr->p_vaddr + phdr->p_memsz);
313*7304104dSAndroid Build Coastguard Worker 
314*7304104dSAndroid Build Coastguard Worker   /* Normally just appending keeps us sorted.  */
315*7304104dSAndroid Build Coastguard Worker 
316*7304104dSAndroid Build Coastguard Worker   size_t i = dwfl->lookup_elts;
317*7304104dSAndroid Build Coastguard Worker   while (i > 0 && unlikely (start < dwfl->lookup_addr[i - 1]))
318*7304104dSAndroid Build Coastguard Worker     --i;
319*7304104dSAndroid Build Coastguard Worker 
320*7304104dSAndroid Build Coastguard Worker   if (unlikely (insert (dwfl, i, start, end, ndx)))
321*7304104dSAndroid Build Coastguard Worker     {
322*7304104dSAndroid Build Coastguard Worker       __libdwfl_seterrno (DWFL_E_NOMEM);
323*7304104dSAndroid Build Coastguard Worker       return -1;
324*7304104dSAndroid Build Coastguard Worker     }
325*7304104dSAndroid Build Coastguard Worker 
326*7304104dSAndroid Build Coastguard Worker   dwfl->next_segndx = ndx + 1;
327*7304104dSAndroid Build Coastguard Worker 
328*7304104dSAndroid Build Coastguard Worker   return ndx;
329*7304104dSAndroid Build Coastguard Worker }
330*7304104dSAndroid Build Coastguard Worker INTDEF (dwfl_report_segment)
331