1*7304104dSAndroid Build Coastguard Worker /* Maintenance of module list in libdwfl.
2*7304104dSAndroid Build Coastguard Worker Copyright (C) 2005, 2006, 2007, 2008, 2014, 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 #include "cfi.h"
35*7304104dSAndroid Build Coastguard Worker #include <search.h>
36*7304104dSAndroid Build Coastguard Worker
37*7304104dSAndroid Build Coastguard Worker static void
free_cu(struct dwfl_cu * cu)38*7304104dSAndroid Build Coastguard Worker free_cu (struct dwfl_cu *cu)
39*7304104dSAndroid Build Coastguard Worker {
40*7304104dSAndroid Build Coastguard Worker if (cu->lines != NULL)
41*7304104dSAndroid Build Coastguard Worker free (cu->lines);
42*7304104dSAndroid Build Coastguard Worker free (cu);
43*7304104dSAndroid Build Coastguard Worker }
44*7304104dSAndroid Build Coastguard Worker
45*7304104dSAndroid Build Coastguard Worker static void
nofree(void * arg)46*7304104dSAndroid Build Coastguard Worker nofree (void *arg __attribute__ ((unused)))
47*7304104dSAndroid Build Coastguard Worker {
48*7304104dSAndroid Build Coastguard Worker }
49*7304104dSAndroid Build Coastguard Worker
50*7304104dSAndroid Build Coastguard Worker static void
free_file(struct dwfl_file * file)51*7304104dSAndroid Build Coastguard Worker free_file (struct dwfl_file *file)
52*7304104dSAndroid Build Coastguard Worker {
53*7304104dSAndroid Build Coastguard Worker free (file->name);
54*7304104dSAndroid Build Coastguard Worker
55*7304104dSAndroid Build Coastguard Worker /* Close the fd only on the last reference. */
56*7304104dSAndroid Build Coastguard Worker if (file->elf != NULL && elf_end (file->elf) == 0 && file->fd != -1)
57*7304104dSAndroid Build Coastguard Worker close (file->fd);
58*7304104dSAndroid Build Coastguard Worker }
59*7304104dSAndroid Build Coastguard Worker
60*7304104dSAndroid Build Coastguard Worker void
61*7304104dSAndroid Build Coastguard Worker internal_function
__libdwfl_module_free(Dwfl_Module * mod)62*7304104dSAndroid Build Coastguard Worker __libdwfl_module_free (Dwfl_Module *mod)
63*7304104dSAndroid Build Coastguard Worker {
64*7304104dSAndroid Build Coastguard Worker if (mod->lazy_cu_root != NULL)
65*7304104dSAndroid Build Coastguard Worker tdestroy (mod->lazy_cu_root, nofree);
66*7304104dSAndroid Build Coastguard Worker
67*7304104dSAndroid Build Coastguard Worker if (mod->aranges != NULL)
68*7304104dSAndroid Build Coastguard Worker free (mod->aranges);
69*7304104dSAndroid Build Coastguard Worker
70*7304104dSAndroid Build Coastguard Worker if (mod->cu != NULL)
71*7304104dSAndroid Build Coastguard Worker {
72*7304104dSAndroid Build Coastguard Worker for (size_t i = 0; i < mod->ncu; ++i)
73*7304104dSAndroid Build Coastguard Worker free_cu (mod->cu[i]);
74*7304104dSAndroid Build Coastguard Worker free (mod->cu);
75*7304104dSAndroid Build Coastguard Worker }
76*7304104dSAndroid Build Coastguard Worker
77*7304104dSAndroid Build Coastguard Worker /* We might have primed the Dwarf_CFI ebl cache with our own ebl
78*7304104dSAndroid Build Coastguard Worker in __libdwfl_set_cfi. Make sure we don't free it twice. */
79*7304104dSAndroid Build Coastguard Worker if (mod->eh_cfi != NULL)
80*7304104dSAndroid Build Coastguard Worker {
81*7304104dSAndroid Build Coastguard Worker if (mod->eh_cfi->ebl != NULL && mod->eh_cfi->ebl == mod->ebl)
82*7304104dSAndroid Build Coastguard Worker mod->eh_cfi->ebl = NULL;
83*7304104dSAndroid Build Coastguard Worker dwarf_cfi_end (mod->eh_cfi);
84*7304104dSAndroid Build Coastguard Worker }
85*7304104dSAndroid Build Coastguard Worker
86*7304104dSAndroid Build Coastguard Worker if (mod->dwarf_cfi != NULL)
87*7304104dSAndroid Build Coastguard Worker {
88*7304104dSAndroid Build Coastguard Worker if (mod->dwarf_cfi->ebl != NULL && mod->dwarf_cfi->ebl == mod->ebl)
89*7304104dSAndroid Build Coastguard Worker mod->dwarf_cfi->ebl = NULL;
90*7304104dSAndroid Build Coastguard Worker /* We don't need to explicitly destroy the dwarf_cfi.
91*7304104dSAndroid Build Coastguard Worker That will be done by dwarf_end. */
92*7304104dSAndroid Build Coastguard Worker }
93*7304104dSAndroid Build Coastguard Worker
94*7304104dSAndroid Build Coastguard Worker if (mod->dw != NULL)
95*7304104dSAndroid Build Coastguard Worker {
96*7304104dSAndroid Build Coastguard Worker INTUSE(dwarf_end) (mod->dw);
97*7304104dSAndroid Build Coastguard Worker if (mod->alt != NULL)
98*7304104dSAndroid Build Coastguard Worker {
99*7304104dSAndroid Build Coastguard Worker INTUSE(dwarf_end) (mod->alt);
100*7304104dSAndroid Build Coastguard Worker if (mod->alt_elf != NULL)
101*7304104dSAndroid Build Coastguard Worker elf_end (mod->alt_elf);
102*7304104dSAndroid Build Coastguard Worker if (mod->alt_fd != -1)
103*7304104dSAndroid Build Coastguard Worker close (mod->alt_fd);
104*7304104dSAndroid Build Coastguard Worker }
105*7304104dSAndroid Build Coastguard Worker }
106*7304104dSAndroid Build Coastguard Worker
107*7304104dSAndroid Build Coastguard Worker if (mod->ebl != NULL)
108*7304104dSAndroid Build Coastguard Worker ebl_closebackend (mod->ebl);
109*7304104dSAndroid Build Coastguard Worker
110*7304104dSAndroid Build Coastguard Worker if (mod->debug.elf != mod->main.elf)
111*7304104dSAndroid Build Coastguard Worker free_file (&mod->debug);
112*7304104dSAndroid Build Coastguard Worker free_file (&mod->main);
113*7304104dSAndroid Build Coastguard Worker free_file (&mod->aux_sym);
114*7304104dSAndroid Build Coastguard Worker
115*7304104dSAndroid Build Coastguard Worker if (mod->build_id_bits != NULL)
116*7304104dSAndroid Build Coastguard Worker free (mod->build_id_bits);
117*7304104dSAndroid Build Coastguard Worker
118*7304104dSAndroid Build Coastguard Worker if (mod->reloc_info != NULL)
119*7304104dSAndroid Build Coastguard Worker free (mod->reloc_info);
120*7304104dSAndroid Build Coastguard Worker
121*7304104dSAndroid Build Coastguard Worker free (mod->name);
122*7304104dSAndroid Build Coastguard Worker free (mod->elfpath);
123*7304104dSAndroid Build Coastguard Worker free (mod);
124*7304104dSAndroid Build Coastguard Worker }
125*7304104dSAndroid Build Coastguard Worker
126*7304104dSAndroid Build Coastguard Worker void
dwfl_report_begin_add(Dwfl * dwfl)127*7304104dSAndroid Build Coastguard Worker dwfl_report_begin_add (Dwfl *dwfl __attribute__ ((unused)))
128*7304104dSAndroid Build Coastguard Worker {
129*7304104dSAndroid Build Coastguard Worker /* The lookup table will be cleared on demand, there is nothing we need
130*7304104dSAndroid Build Coastguard Worker to do here. */
131*7304104dSAndroid Build Coastguard Worker }
INTDEF(dwfl_report_begin_add)132*7304104dSAndroid Build Coastguard Worker INTDEF (dwfl_report_begin_add)
133*7304104dSAndroid Build Coastguard Worker
134*7304104dSAndroid Build Coastguard Worker void
135*7304104dSAndroid Build Coastguard Worker dwfl_report_begin (Dwfl *dwfl)
136*7304104dSAndroid Build Coastguard Worker {
137*7304104dSAndroid Build Coastguard Worker /* Clear the segment lookup table. */
138*7304104dSAndroid Build Coastguard Worker dwfl->lookup_elts = 0;
139*7304104dSAndroid Build Coastguard Worker
140*7304104dSAndroid Build Coastguard Worker for (Dwfl_Module *m = dwfl->modulelist; m != NULL; m = m->next)
141*7304104dSAndroid Build Coastguard Worker m->gc = true;
142*7304104dSAndroid Build Coastguard Worker
143*7304104dSAndroid Build Coastguard Worker dwfl->offline_next_address = OFFLINE_REDZONE;
144*7304104dSAndroid Build Coastguard Worker }
INTDEF(dwfl_report_begin)145*7304104dSAndroid Build Coastguard Worker INTDEF (dwfl_report_begin)
146*7304104dSAndroid Build Coastguard Worker
147*7304104dSAndroid Build Coastguard Worker static inline Dwfl_Module *
148*7304104dSAndroid Build Coastguard Worker use (Dwfl_Module *mod, Dwfl_Module **tailp, Dwfl *dwfl)
149*7304104dSAndroid Build Coastguard Worker {
150*7304104dSAndroid Build Coastguard Worker mod->next = *tailp;
151*7304104dSAndroid Build Coastguard Worker *tailp = mod;
152*7304104dSAndroid Build Coastguard Worker
153*7304104dSAndroid Build Coastguard Worker if (unlikely (dwfl->lookup_module != NULL))
154*7304104dSAndroid Build Coastguard Worker {
155*7304104dSAndroid Build Coastguard Worker free (dwfl->lookup_module);
156*7304104dSAndroid Build Coastguard Worker dwfl->lookup_module = NULL;
157*7304104dSAndroid Build Coastguard Worker }
158*7304104dSAndroid Build Coastguard Worker
159*7304104dSAndroid Build Coastguard Worker return mod;
160*7304104dSAndroid Build Coastguard Worker }
161*7304104dSAndroid Build Coastguard Worker
162*7304104dSAndroid Build Coastguard Worker /* Report that a module called NAME spans addresses [START, END).
163*7304104dSAndroid Build Coastguard Worker Returns the module handle, either existing or newly allocated,
164*7304104dSAndroid Build Coastguard Worker or returns a null pointer for an allocation error. */
165*7304104dSAndroid Build Coastguard Worker Dwfl_Module *
dwfl_report_module(Dwfl * dwfl,const char * name,GElf_Addr start,GElf_Addr end)166*7304104dSAndroid Build Coastguard Worker dwfl_report_module (Dwfl *dwfl, const char *name,
167*7304104dSAndroid Build Coastguard Worker GElf_Addr start, GElf_Addr end)
168*7304104dSAndroid Build Coastguard Worker {
169*7304104dSAndroid Build Coastguard Worker Dwfl_Module **tailp = &dwfl->modulelist, **prevp = tailp;
170*7304104dSAndroid Build Coastguard Worker
171*7304104dSAndroid Build Coastguard Worker for (Dwfl_Module *m = *prevp; m != NULL; m = *(prevp = &m->next))
172*7304104dSAndroid Build Coastguard Worker {
173*7304104dSAndroid Build Coastguard Worker if (m->low_addr == start && m->high_addr == end
174*7304104dSAndroid Build Coastguard Worker && !strcmp (m->name, name))
175*7304104dSAndroid Build Coastguard Worker {
176*7304104dSAndroid Build Coastguard Worker /* This module is still here. Move it to the place in the list
177*7304104dSAndroid Build Coastguard Worker after the last module already reported. */
178*7304104dSAndroid Build Coastguard Worker *prevp = m->next;
179*7304104dSAndroid Build Coastguard Worker m->gc = false;
180*7304104dSAndroid Build Coastguard Worker return use (m, tailp, dwfl);
181*7304104dSAndroid Build Coastguard Worker }
182*7304104dSAndroid Build Coastguard Worker
183*7304104dSAndroid Build Coastguard Worker if (! m->gc)
184*7304104dSAndroid Build Coastguard Worker tailp = &m->next;
185*7304104dSAndroid Build Coastguard Worker }
186*7304104dSAndroid Build Coastguard Worker
187*7304104dSAndroid Build Coastguard Worker Dwfl_Module *mod = calloc (1, sizeof *mod);
188*7304104dSAndroid Build Coastguard Worker if (mod == NULL)
189*7304104dSAndroid Build Coastguard Worker goto nomem;
190*7304104dSAndroid Build Coastguard Worker
191*7304104dSAndroid Build Coastguard Worker mod->name = strdup (name);
192*7304104dSAndroid Build Coastguard Worker if (mod->name == NULL)
193*7304104dSAndroid Build Coastguard Worker {
194*7304104dSAndroid Build Coastguard Worker free (mod);
195*7304104dSAndroid Build Coastguard Worker nomem:
196*7304104dSAndroid Build Coastguard Worker __libdwfl_seterrno (DWFL_E_NOMEM);
197*7304104dSAndroid Build Coastguard Worker return NULL;
198*7304104dSAndroid Build Coastguard Worker }
199*7304104dSAndroid Build Coastguard Worker
200*7304104dSAndroid Build Coastguard Worker mod->low_addr = start;
201*7304104dSAndroid Build Coastguard Worker mod->high_addr = end;
202*7304104dSAndroid Build Coastguard Worker mod->dwfl = dwfl;
203*7304104dSAndroid Build Coastguard Worker
204*7304104dSAndroid Build Coastguard Worker return use (mod, tailp, dwfl);
205*7304104dSAndroid Build Coastguard Worker }
INTDEF(dwfl_report_module)206*7304104dSAndroid Build Coastguard Worker INTDEF (dwfl_report_module)
207*7304104dSAndroid Build Coastguard Worker
208*7304104dSAndroid Build Coastguard Worker
209*7304104dSAndroid Build Coastguard Worker /* Finish reporting the current set of modules to the library.
210*7304104dSAndroid Build Coastguard Worker If REMOVED is not null, it's called for each module that
211*7304104dSAndroid Build Coastguard Worker existed before but was not included in the current report.
212*7304104dSAndroid Build Coastguard Worker Returns a nonzero return value from the callback.
213*7304104dSAndroid Build Coastguard Worker DWFL cannot be used until this function has returned zero. */
214*7304104dSAndroid Build Coastguard Worker int
215*7304104dSAndroid Build Coastguard Worker dwfl_report_end (Dwfl *dwfl,
216*7304104dSAndroid Build Coastguard Worker int (*removed) (Dwfl_Module *, void *,
217*7304104dSAndroid Build Coastguard Worker const char *, Dwarf_Addr,
218*7304104dSAndroid Build Coastguard Worker void *arg),
219*7304104dSAndroid Build Coastguard Worker void *arg)
220*7304104dSAndroid Build Coastguard Worker {
221*7304104dSAndroid Build Coastguard Worker Dwfl_Module **tailp = &dwfl->modulelist;
222*7304104dSAndroid Build Coastguard Worker while (*tailp != NULL)
223*7304104dSAndroid Build Coastguard Worker {
224*7304104dSAndroid Build Coastguard Worker Dwfl_Module *m = *tailp;
225*7304104dSAndroid Build Coastguard Worker if (m->gc && removed != NULL)
226*7304104dSAndroid Build Coastguard Worker {
227*7304104dSAndroid Build Coastguard Worker int result = (*removed) (MODCB_ARGS (m), arg);
228*7304104dSAndroid Build Coastguard Worker if (result != 0)
229*7304104dSAndroid Build Coastguard Worker return result;
230*7304104dSAndroid Build Coastguard Worker }
231*7304104dSAndroid Build Coastguard Worker if (m->gc)
232*7304104dSAndroid Build Coastguard Worker {
233*7304104dSAndroid Build Coastguard Worker *tailp = m->next;
234*7304104dSAndroid Build Coastguard Worker __libdwfl_module_free (m);
235*7304104dSAndroid Build Coastguard Worker }
236*7304104dSAndroid Build Coastguard Worker else
237*7304104dSAndroid Build Coastguard Worker tailp = &m->next;
238*7304104dSAndroid Build Coastguard Worker }
239*7304104dSAndroid Build Coastguard Worker
240*7304104dSAndroid Build Coastguard Worker return 0;
241*7304104dSAndroid Build Coastguard Worker }
242*7304104dSAndroid Build Coastguard Worker INTDEF (dwfl_report_end)
243