blob: 80c80a168e3625e7d2e481d8822546b95fa8e530 [file] [log] [blame]
Brian Silverman86497922018-02-10 19:28:39 -05001/* Recover relocatibility for addresses computed from debug information.
2 Copyright (C) 2005-2009, 2012 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#ifdef HAVE_CONFIG_H
30# include <config.h>
31#endif
32
33#include "libdwflP.h"
34#include <fcntl.h>
35#include <unistd.h>
36
37/* Since dwfl_report_elf lays out the sections already, this will only be
38 called when the section headers of the debuginfo file are being
39 consulted instead, or for the section placed at 0. With binutils
40 strip-to-debug, the symbol table is in the debuginfo file and relocation
41 looks there. */
42int
43dwfl_offline_section_address (Dwfl_Module *mod,
44 void **userdata __attribute__ ((unused)),
45 const char *modname __attribute__ ((unused)),
46 Dwarf_Addr base __attribute__ ((unused)),
47 const char *secname __attribute__ ((unused)),
48 Elf32_Word shndx,
49 const GElf_Shdr *shdr __attribute__ ((unused)),
50 Dwarf_Addr *addr)
51{
52 assert (mod->e_type == ET_REL);
53 assert (shdr->sh_addr == 0);
54 assert (shdr->sh_flags & SHF_ALLOC);
55 assert (shndx != 0);
56
57 if (mod->debug.elf == NULL)
58 /* We are only here because sh_addr is zero even though layout is complete.
59 The first section in the first file under -e is placed at 0. */
60 return 0;
61
62 /* The section numbers might not match between the two files.
63 The best we can rely on is the order of SHF_ALLOC sections. */
64
65 Elf_Scn *ourscn = elf_getscn (mod->debug.elf, shndx);
66 Elf_Scn *scn = NULL;
67 uint_fast32_t skip_alloc = 0;
68 while ((scn = elf_nextscn (mod->debug.elf, scn)) != ourscn)
69 {
70 assert (scn != NULL);
71 GElf_Shdr shdr_mem;
72 GElf_Shdr *sh = gelf_getshdr (scn, &shdr_mem);
73 if (unlikely (sh == NULL))
74 return -1;
75 if (sh->sh_flags & SHF_ALLOC)
76 ++skip_alloc;
77 }
78
79 scn = NULL;
80 while ((scn = elf_nextscn (mod->main.elf, scn)) != NULL)
81 {
82 GElf_Shdr shdr_mem;
83 GElf_Shdr *main_shdr = gelf_getshdr (scn, &shdr_mem);
84 if (unlikely (main_shdr == NULL))
85 return -1;
86 if ((main_shdr->sh_flags & SHF_ALLOC) && skip_alloc-- == 0)
87 {
88 assert (main_shdr->sh_flags == shdr->sh_flags);
89 *addr = main_shdr->sh_addr;
90 return 0;
91 }
92 }
93
94 /* This should never happen. */
95 return -1;
96}
97INTDEF (dwfl_offline_section_address)
98
99/* Forward declarations. */
100static Dwfl_Module *process_elf (Dwfl *dwfl, const char *name,
101 const char *file_name, int fd, Elf *elf);
102static Dwfl_Module *process_archive (Dwfl *dwfl, const char *name,
103 const char *file_name, int fd, Elf *elf,
104 int (*predicate) (const char *module,
105 const char *file));
106
107/* Report one module for an ELF file, or many for an archive.
108 Always consumes ELF and FD. */
109static Dwfl_Module *
110process_file (Dwfl *dwfl, const char *name, const char *file_name, int fd,
111 Elf *elf, int (*predicate) (const char *module,
112 const char *file))
113{
114 switch (elf_kind (elf))
115 {
116 default:
117 case ELF_K_NONE:
118 __libdwfl_seterrno (elf == NULL ? DWFL_E_LIBELF : DWFL_E_BADELF);
119 return NULL;
120
121 case ELF_K_ELF:
122 return process_elf (dwfl, name, file_name, fd, elf);
123
124 case ELF_K_AR:
125 return process_archive (dwfl, name, file_name, fd, elf, predicate);
126 }
127}
128
129/* Report the open ELF file as a module. Always consumes ELF and FD. */
130static Dwfl_Module *
131process_elf (Dwfl *dwfl, const char *name, const char *file_name, int fd,
132 Elf *elf)
133{
134 Dwfl_Module *mod = __libdwfl_report_elf (dwfl, name, file_name, fd, elf,
135 dwfl->offline_next_address, true,
136 false);
137 if (mod != NULL)
138 {
139 /* If this is an ET_EXEC file with fixed addresses, the address range
140 it consumed may or may not intersect with the arbitrary range we
141 will use for relocatable modules. Make sure we always use a free
142 range for the offline allocations. If this module did use
143 offline_next_address, it may have rounded it up for the module's
144 alignment requirements. */
145 if ((dwfl->offline_next_address >= mod->low_addr
146 || mod->low_addr - dwfl->offline_next_address < OFFLINE_REDZONE)
147 && dwfl->offline_next_address < mod->high_addr + OFFLINE_REDZONE)
148 dwfl->offline_next_address = mod->high_addr + OFFLINE_REDZONE;
149
150 /* Don't keep the file descriptor around. */
151 if (mod->main.fd != -1 && elf_cntl (mod->main.elf, ELF_C_FDREAD) == 0)
152 {
153 close (mod->main.fd);
154 mod->main.fd = -1;
155 }
156 }
157
158 return mod;
159}
160
161/* Always consumes MEMBER. Returns elf_next result on success.
162 For errors returns ELF_C_NULL with *MOD set to null. */
163static Elf_Cmd
164process_archive_member (Dwfl *dwfl, const char *name, const char *file_name,
165 int (*predicate) (const char *module, const char *file),
166 int fd, Elf *member, Dwfl_Module **mod)
167{
168 const Elf_Arhdr *h = elf_getarhdr (member);
169 if (unlikely (h == NULL))
170 {
171 __libdwfl_seterrno (DWFL_E_LIBELF);
172 fail:
173 elf_end (member);
174 *mod = NULL;
175 return ELF_C_NULL;
176 }
177
178 if (!strcmp (h->ar_name, "/") || !strcmp (h->ar_name, "//")
179 || !strcmp (h->ar_name, "/SYM64/"))
180 {
181 skip:;
182 /* Skip this and go to the next. */
183 Elf_Cmd result = elf_next (member);
184 elf_end (member);
185 return result;
186 }
187
188 char *member_name;
189 if (unlikely (asprintf (&member_name, "%s(%s)", file_name, h->ar_name) < 0))
190 {
191 nomem:
192 __libdwfl_seterrno (DWFL_E_NOMEM);
193 elf_end (member);
194 *mod = NULL;
195 return ELF_C_NULL;
196 }
197
198 char *module_name = NULL;
199 if (name == NULL || name[0] == '\0')
200 name = h->ar_name;
201 else if (unlikely (asprintf (&module_name, "%s:%s", name, h->ar_name) < 0))
202 {
203 free (member_name);
204 goto nomem;
205 }
206 else
207 name = module_name;
208
209 if (predicate != NULL)
210 {
211 /* Let the predicate decide whether to use this one. */
212 int want = (*predicate) (name, member_name);
213 if (want <= 0)
214 {
215 free (member_name);
216 free (module_name);
217 if (unlikely (want < 0))
218 {
219 __libdwfl_seterrno (DWFL_E_CB);
220 goto fail;
221 }
222 goto skip;
223 }
224 }
225
226 /* We let __libdwfl_report_elf cache the fd in mod->main.fd,
227 though it's the same fd for all the members.
228 On module teardown we will close it only on the last Elf reference. */
229 *mod = process_file (dwfl, name, member_name, fd, member, predicate);
230 free (member_name);
231 free (module_name);
232
233 if (*mod == NULL) /* process_file called elf_end. */
234 return ELF_C_NULL;
235
236 /* Advance the archive-reading offset for the next iteration. */
237 return elf_next (member);
238}
239
240/* Report each member of the archive as its own module. */
241static Dwfl_Module *
242process_archive (Dwfl *dwfl, const char *name, const char *file_name, int fd,
243 Elf *archive,
244 int (*predicate) (const char *module, const char *file))
245
246{
247 Dwfl_Module *mod = NULL;
248 Elf *member = elf_begin (fd, ELF_C_READ_MMAP_PRIVATE, archive);
249 if (unlikely (member == NULL)) /* Empty archive. */
250 {
251 __libdwfl_seterrno (DWFL_E_BADELF);
252 return NULL;
253 }
254
255 while (process_archive_member (dwfl, name, file_name, predicate,
256 fd, member, &mod) != ELF_C_NULL)
257 member = elf_begin (fd, ELF_C_READ_MMAP_PRIVATE, archive);
258
259 /* We can drop the archive Elf handle even if we're still using members
260 in live modules. When the last module's elf_end on a member returns
261 zero, that module will close FD. If no modules survived the predicate,
262 we are all done with the file right here. */
263 if (mod != NULL /* If no modules, caller will clean up. */
264 && elf_end (archive) == 0)
265 close (fd);
266
267 return mod;
268}
269
270Dwfl_Module *
271internal_function
272__libdwfl_report_offline (Dwfl *dwfl, const char *name,
273 const char *file_name, int fd, bool closefd,
274 int (*predicate) (const char *module,
275 const char *file))
276{
277 Elf *elf;
278 Dwfl_Error error = __libdw_open_file (&fd, &elf, closefd, true);
279 if (error != DWFL_E_NOERROR)
280 {
281 __libdwfl_seterrno (error);
282 return NULL;
283 }
284 Dwfl_Module *mod = process_file (dwfl, name, file_name, fd, elf, predicate);
285 if (mod == NULL)
286 {
287 elf_end (elf);
288 if (closefd)
289 close (fd);
290 }
291 return mod;
292}
293
294Dwfl_Module *
295dwfl_report_offline (Dwfl *dwfl, const char *name,
296 const char *file_name, int fd)
297{
298 if (dwfl == NULL)
299 return NULL;
300
301 bool closefd = false;
302 if (fd < 0)
303 {
304 closefd = true;
305 fd = open (file_name, O_RDONLY);
306 if (fd < 0)
307 {
308 __libdwfl_seterrno (DWFL_E_ERRNO);
309 return NULL;
310 }
311 }
312
313 return __libdwfl_report_offline (dwfl, name, file_name, fd, closefd, NULL);
314}
315INTDEF (dwfl_report_offline)