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