Branch data Line data Source code
1 : : /* Maintenance of module list in libdwfl.
2 : : Copyright (C) 2005, 2006, 2007, 2008 Red Hat, Inc.
3 : : This file is part of elfutils.
4 : :
5 : : This file is free software; you can redistribute it and/or modify
6 : : it under the terms of either
7 : :
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
11 : :
12 : : or
13 : :
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
17 : :
18 : : or both in parallel, as here.
19 : :
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.
24 : :
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/>. */
28 : :
29 : : #include "libdwflP.h"
30 : : #include <search.h>
31 : : #include <unistd.h>
32 : :
33 : : static void
34 : 4426 : free_cu (struct dwfl_cu *cu)
35 : : {
36 [ + + ]: 4426 : if (cu->lines != NULL)
37 : 28 : free (cu->lines);
38 : 4426 : free (cu);
39 : 4426 : }
40 : :
41 : : static void
42 : 4426 : nofree (void *arg __attribute__ ((unused)))
43 : : {
44 : 4426 : }
45 : :
46 : : static void
47 : 100508 : free_file (struct dwfl_file *file)
48 : : {
49 : 100508 : free (file->name);
50 : :
51 : : /* Close the fd only on the last reference. */
52 [ + + ][ + - ]: 100508 : if (file->elf != NULL && elf_end (file->elf) == 0 && file->fd != -1)
[ + + ]
53 : 5063 : close (file->fd);
54 : 100508 : }
55 : :
56 : : void
57 : : internal_function
58 : 50201 : __libdwfl_module_free (Dwfl_Module *mod)
59 : : {
60 [ + + ]: 50201 : if (mod->lazy_cu_root != NULL)
61 : 49 : tdestroy (mod->lazy_cu_root, nofree);
62 : :
63 [ + + ]: 50201 : if (mod->aranges != NULL)
64 : 23 : free (mod->aranges);
65 : :
66 [ + + ]: 50201 : if (mod->cu != NULL)
67 : : {
68 [ + + ]: 4475 : for (size_t i = 0; i < mod->ncu; ++i)
69 : 4426 : free_cu (mod->cu[i]);
70 : 49 : free (mod->cu);
71 : : }
72 : :
73 [ + + ]: 50201 : if (mod->dw != NULL)
74 : 5103 : INTUSE(dwarf_end) (mod->dw);
75 : :
76 [ + + ]: 50201 : if (mod->ebl != NULL)
77 : 58 : ebl_closebackend (mod->ebl);
78 : :
79 [ + + ]: 50201 : if (mod->debug.elf != mod->main.elf)
80 : 106 : free_file (&mod->debug);
81 : 50201 : free_file (&mod->main);
82 : 50201 : free_file (&mod->aux_sym);
83 : :
84 [ + + ]: 50201 : if (mod->build_id_bits != NULL)
85 : 52 : free (mod->build_id_bits);
86 : :
87 : 50201 : free (mod->name);
88 : 50201 : free (mod);
89 : 50201 : }
90 : :
91 : : void
92 : 0 : dwfl_report_begin_add (Dwfl *dwfl __attribute__ ((unused)))
93 : : {
94 : : /* The lookup table will be cleared on demand, there is nothing we need
95 : : to do here. */
96 : 0 : }
97 : : INTDEF (dwfl_report_begin_add)
98 : :
99 : : void
100 : 5 : dwfl_report_begin (Dwfl *dwfl)
101 : : {
102 : : /* Clear the segment lookup table. */
103 : 5 : dwfl->lookup_elts = 0;
104 : :
105 [ + + ]: 9 : for (Dwfl_Module *m = dwfl->modulelist; m != NULL; m = m->next)
106 : 4 : m->gc = true;
107 : :
108 : 5 : dwfl->offline_next_address = OFFLINE_REDZONE;
109 : 5 : }
110 : : INTDEF (dwfl_report_begin)
111 : :
112 : : /* Report that a module called NAME spans addresses [START, END).
113 : : Returns the module handle, either existing or newly allocated,
114 : : or returns a null pointer for an allocation error. */
115 : : Dwfl_Module *
116 : 50205 : dwfl_report_module (Dwfl *dwfl, const char *name,
117 : : GElf_Addr start, GElf_Addr end)
118 : : {
119 : 50205 : Dwfl_Module **tailp = &dwfl->modulelist, **prevp = tailp;
120 : :
121 : 50205 : inline Dwfl_Module *use (Dwfl_Module *mod)
122 : : {
123 : 50205 : mod->next = *tailp;
124 : 50205 : *tailp = mod;
125 : :
126 [ - + ]: 50205 : if (unlikely (dwfl->lookup_module != NULL))
127 : : {
128 : 0 : free (dwfl->lookup_module);
129 : 0 : dwfl->lookup_module = NULL;
130 : : }
131 : :
132 : 50205 : return mod;
133 : : }
134 : :
135 [ + + ]: 275295 : for (Dwfl_Module *m = *prevp; m != NULL; m = *(prevp = &m->next))
136 : : {
137 [ + + ][ + - ]: 225094 : if (m->low_addr == start && m->high_addr == end
138 [ + - ]: 4 : && !strcmp (m->name, name))
139 : : {
140 : : /* This module is still here. Move it to the place in the list
141 : : after the last module already reported. */
142 : 4 : *prevp = m->next;
143 : 4 : m->gc = false;
144 : 4 : return use (m);
145 : : }
146 : :
147 [ + - ]: 225090 : if (! m->gc)
148 : 225090 : tailp = &m->next;
149 : : }
150 : :
151 : 50201 : Dwfl_Module *mod = calloc (1, sizeof *mod);
152 [ + - ]: 50201 : if (mod == NULL)
153 : : goto nomem;
154 : :
155 : 50201 : mod->name = strdup (name);
156 [ - + ]: 50201 : if (mod->name == NULL)
157 : : {
158 : 0 : free (mod);
159 : : nomem:
160 : 0 : __libdwfl_seterrno (DWFL_E_NOMEM);
161 : 0 : return NULL;
162 : : }
163 : :
164 : 50201 : mod->low_addr = start;
165 : 50201 : mod->high_addr = end;
166 : 50201 : mod->dwfl = dwfl;
167 : :
168 : 50205 : return use (mod);
169 : : }
170 : : INTDEF (dwfl_report_module)
171 : :
172 : :
173 : : /* Finish reporting the current set of modules to the library.
174 : : If REMOVED is not null, it's called for each module that
175 : : existed before but was not included in the current report.
176 : : Returns a nonzero return value from the callback.
177 : : DWFL cannot be used until this function has returned zero. */
178 : : int
179 : 5166 : dwfl_report_end (Dwfl *dwfl,
180 : : int (*removed) (Dwfl_Module *, void *,
181 : : const char *, Dwarf_Addr,
182 : : void *arg),
183 : : void *arg)
184 : : {
185 : 5166 : Dwfl_Module **tailp = &dwfl->modulelist;
186 [ + + ]: 55371 : while (*tailp != NULL)
187 : : {
188 : 50205 : Dwfl_Module *m = *tailp;
189 [ - + ][ # # ]: 50205 : if (m->gc && removed != NULL)
190 : : {
191 : 0 : int result = (*removed) (MODCB_ARGS (m), arg);
192 [ # # ]: 0 : if (result != 0)
193 : : return result;
194 : : }
195 [ - + ]: 50205 : if (m->gc)
196 : : {
197 : 0 : *tailp = m->next;
198 : 0 : __libdwfl_module_free (m);
199 : : }
200 : : else
201 : 50205 : tailp = &m->next;
202 : : }
203 : :
204 : : return 0;
205 : : }
206 : : INTDEF (dwfl_report_end)
|