1 /* Maintenance of module list in libdwfl.
2 Copyright (C) 2005, 2006, 2007, 2008 Red Hat, Inc.
3 This file is part of elfutils.
5 This file is free software; you can redistribute it and/or modify
6 it under the terms of either
8 * the GNU Lesser General Public License as published by the Free
9 Software Foundation; either version 3 of the License, or (at
10 your option) any later version
14 * the GNU General Public License as published by the Free
15 Software Foundation; either version 2 of the License, or (at
16 your option) any later version
18 or both in parallel, as here.
20 elfutils is distributed in the hope that it will be useful, but
21 WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 General Public License for more details.
25 You should have received copies of the GNU General Public License and
26 the GNU Lesser General Public License along with this program. If
27 not, see <http://www.gnu.org/licenses/>. */
34 free_cu (struct dwfl_cu *cu)
36 if (cu->lines != NULL)
42 nofree (void *arg __attribute__ ((unused)))
47 free_file (struct dwfl_file *file)
51 /* Close the fd only on the last reference. */
52 if (file->elf != NULL && elf_end (file->elf) == 0 && file->fd != -1)
58 __libdwfl_module_free (Dwfl_Module *mod)
60 if (mod->lazy_cu_root != NULL)
61 tdestroy (mod->lazy_cu_root, nofree);
63 if (mod->aranges != NULL)
68 for (size_t i = 0; i < mod->ncu; ++i)
74 INTUSE(dwarf_end) (mod->dw);
77 ebl_closebackend (mod->ebl);
79 if (mod->debug.elf != mod->main.elf)
80 free_file (&mod->debug);
81 free_file (&mod->main);
83 if (mod->build_id_bits != NULL)
84 free (mod->build_id_bits);
91 dwfl_report_begin_add (Dwfl *dwfl __attribute__ ((unused)))
93 /* The lookup table will be cleared on demand, there is nothing we need
96 INTDEF (dwfl_report_begin_add)
99 dwfl_report_begin (Dwfl *dwfl)
101 /* Clear the segment lookup table. */
102 dwfl->lookup_elts = 0;
104 for (Dwfl_Module *m = dwfl->modulelist; m != NULL; m = m->next)
107 dwfl->offline_next_address = OFFLINE_REDZONE;
109 INTDEF (dwfl_report_begin)
111 /* Report that a module called NAME spans addresses [START, END).
112 Returns the module handle, either existing or newly allocated,
113 or returns a null pointer for an allocation error. */
115 dwfl_report_module (Dwfl *dwfl, const char *name,
116 GElf_Addr start, GElf_Addr end)
118 Dwfl_Module **tailp = &dwfl->modulelist, **prevp = tailp;
120 inline Dwfl_Module *use (Dwfl_Module *mod)
125 if (unlikely (dwfl->lookup_module != NULL))
127 free (dwfl->lookup_module);
128 dwfl->lookup_module = NULL;
134 for (Dwfl_Module *m = *prevp; m != NULL; m = *(prevp = &m->next))
136 if (m->low_addr == start && m->high_addr == end
137 && !strcmp (m->name, name))
139 /* This module is still here. Move it to the place in the list
140 after the last module already reported. */
150 Dwfl_Module *mod = calloc (1, sizeof *mod);
154 mod->name = strdup (name);
155 if (mod->name == NULL)
159 __libdwfl_seterrno (DWFL_E_NOMEM);
163 mod->low_addr = start;
164 mod->high_addr = end;
169 INTDEF (dwfl_report_module)
172 /* Finish reporting the current set of modules to the library.
173 If REMOVED is not null, it's called for each module that
174 existed before but was not included in the current report.
175 Returns a nonzero return value from the callback.
176 DWFL cannot be used until this function has returned zero. */
178 dwfl_report_end (Dwfl *dwfl,
179 int (*removed) (Dwfl_Module *, void *,
180 const char *, Dwarf_Addr,
184 Dwfl_Module **tailp = &dwfl->modulelist;
185 while (*tailp != NULL)
187 Dwfl_Module *m = *tailp;
188 if (m->gc && removed != NULL)
190 int result = (*removed) (MODCB_ARGS (m), arg);
197 __libdwfl_module_free (m);
205 INTDEF (dwfl_report_end)