xref: /aosp_15_r20/external/elfutils/libdwfl/dwfl_module.c (revision 7304104da70ce23c86437a01be71edd1a2d7f37e)
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