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 : 3708 : free_cu (struct dwfl_cu *cu)
35 : : {
36 [ + + ]: 3708 : if (cu->lines != NULL)
37 : 12 : free (cu->lines);
38 : 3708 : free (cu);
39 : 3708 : }
40 : :
41 : : static void
42 : 3708 : nofree (void *arg __attribute__ ((unused)))
43 : : {
44 : 3708 : }
45 : :
46 : : static void
47 : 50204 : free_file (struct dwfl_file *file)
48 : : {
49 : 50204 : free (file->name);
50 : :
51 : : /* Close the fd only on the last reference. */
52 [ + + ][ + - ]: 50204 : if (file->elf != NULL && elf_end (file->elf) == 0 && file->fd != -1)
[ + + ]
53 : 5024 : close (file->fd);
54 : 50204 : }
55 : :
56 : : void
57 : : internal_function
58 : 50146 : __libdwfl_module_free (Dwfl_Module *mod)
59 : : {
60 [ + + ]: 50146 : if (mod->lazy_cu_root != NULL)
61 : 33 : tdestroy (mod->lazy_cu_root, nofree);
62 : :
63 [ + + ]: 50146 : if (mod->aranges != NULL)
64 : 3 : free (mod->aranges);
65 : :
66 [ + + ]: 50146 : if (mod->cu != NULL)
67 : : {
68 [ + + ]: 3741 : for (size_t i = 0; i < mod->ncu; ++i)
69 : 3708 : free_cu (mod->cu[i]);
70 : 33 : free (mod->cu);
71 : : }
72 : :
73 [ + + ]: 50146 : if (mod->dw != NULL)
74 : 5079 : INTUSE(dwarf_end) (mod->dw);
75 : :
76 [ + + ]: 50146 : if (mod->ebl != NULL)
77 : 54 : ebl_closebackend (mod->ebl);
78 : :
79 [ + + ]: 50146 : if (mod->debug.elf != mod->main.elf)
80 : 58 : free_file (&mod->debug);
81 : 50146 : free_file (&mod->main);
82 : :
83 [ + + ]: 50146 : if (mod->build_id_bits != NULL)
84 : 21 : free (mod->build_id_bits);
85 : :
86 : 50146 : free (mod->name);
87 : 50146 : free (mod);
88 : 50146 : }
89 : :
90 : : void
91 : 0 : dwfl_report_begin_add (Dwfl *dwfl __attribute__ ((unused)))
92 : : {
93 : : /* The lookup table will be cleared on demand, there is nothing we need
94 : : to do here. */
95 : 0 : }
96 : : INTDEF (dwfl_report_begin_add)
97 : :
98 : : void
99 : 5 : dwfl_report_begin (Dwfl *dwfl)
100 : : {
101 : : /* Clear the segment lookup table. */
102 : 5 : dwfl->lookup_elts = 0;
103 : :
104 [ + + ]: 9 : for (Dwfl_Module *m = dwfl->modulelist; m != NULL; m = m->next)
105 : 4 : m->gc = true;
106 : :
107 : 5 : dwfl->offline_next_address = OFFLINE_REDZONE;
108 : 5 : }
109 : : INTDEF (dwfl_report_begin)
110 : :
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. */
114 : : Dwfl_Module *
115 : 50181 : dwfl_report_module (Dwfl *dwfl, const char *name,
116 : : GElf_Addr start, GElf_Addr end)
117 : : {
118 : 50181 : Dwfl_Module **tailp = &dwfl->modulelist, **prevp = tailp;
119 : :
120 : 50181 : inline Dwfl_Module *use (Dwfl_Module *mod)
121 : : {
122 : 50181 : mod->next = *tailp;
123 : 50181 : *tailp = mod;
124 : :
125 [ - + ]: 50181 : if (unlikely (dwfl->lookup_module != NULL))
126 : : {
127 : 0 : free (dwfl->lookup_module);
128 : 0 : dwfl->lookup_module = NULL;
129 : : }
130 : :
131 : 50181 : return mod;
132 : : }
133 : :
134 [ + + ]: 275271 : for (Dwfl_Module *m = *prevp; m != NULL; m = *(prevp = &m->next))
135 : : {
136 [ + + ][ + - ]: 225094 : if (m->low_addr == start && m->high_addr == end
137 [ + - ]: 4 : && !strcmp (m->name, name))
138 : : {
139 : : /* This module is still here. Move it to the place in the list
140 : : after the last module already reported. */
141 : 4 : *prevp = m->next;
142 : 4 : m->gc = false;
143 : 4 : return use (m);
144 : : }
145 : :
146 [ + - ]: 225090 : if (! m->gc)
147 : 225090 : tailp = &m->next;
148 : : }
149 : :
150 : 50177 : Dwfl_Module *mod = calloc (1, sizeof *mod);
151 [ + - ]: 50177 : if (mod == NULL)
152 : : goto nomem;
153 : :
154 : 50177 : mod->name = strdup (name);
155 [ - + ]: 50177 : if (mod->name == NULL)
156 : : {
157 : 0 : free (mod);
158 : : nomem:
159 : 0 : __libdwfl_seterrno (DWFL_E_NOMEM);
160 : 0 : return NULL;
161 : : }
162 : :
163 : 50177 : mod->low_addr = start;
164 : 50177 : mod->high_addr = end;
165 : 50177 : mod->dwfl = dwfl;
166 : :
167 : 50181 : return use (mod);
168 : : }
169 : : INTDEF (dwfl_report_module)
170 : :
171 : :
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. */
177 : : int
178 : 5142 : dwfl_report_end (Dwfl *dwfl,
179 : : int (*removed) (Dwfl_Module *, void *,
180 : : const char *, Dwarf_Addr,
181 : : void *arg),
182 : : void *arg)
183 : : {
184 : 5142 : Dwfl_Module **tailp = &dwfl->modulelist;
185 [ + + ]: 55323 : while (*tailp != NULL)
186 : : {
187 : 50181 : Dwfl_Module *m = *tailp;
188 [ - + ][ # # ]: 50181 : if (m->gc && removed != NULL)
189 : : {
190 : 0 : int result = (*removed) (MODCB_ARGS (m), arg);
191 [ # # ]: 0 : if (result != 0)
192 : : return result;
193 : : }
194 [ - + ]: 50181 : if (m->gc)
195 : : {
196 : 0 : *tailp = m->next;
197 : 0 : __libdwfl_module_free (m);
198 : : }
199 : : else
200 : 50181 : tailp = &m->next;
201 : : }
202 : :
203 : : return 0;
204 : : }
205 : : INTDEF (dwfl_report_end)
|