blob: 26a6bd664dd55b1b284018c044ca1dc72f452933 [file] [log] [blame]
Roland McGrathd17fac72005-08-23 08:20:21 +00001/* Recover relocatibility for addresses computed from debug information.
Petr Machatae1873142012-08-01 21:37:52 +02002 Copyright (C) 2005-2009, 2012 Red Hat, Inc.
Mark Wielaardde2ed972012-06-05 17:15:16 +02003 This file is part of elfutils.
Roland McGrathd17fac72005-08-23 08:20:21 +00004
Mark Wielaardde2ed972012-06-05 17:15:16 +02005 This file is free software; you can redistribute it and/or modify
6 it under the terms of either
Roland McGrathd17fac72005-08-23 08:20:21 +00007
Mark Wielaardde2ed972012-06-05 17:15:16 +02008 * 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
Ulrich Drepper361df7d2006-04-04 21:38:57 +000021 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
Mark Wielaardde2ed972012-06-05 17:15:16 +020025 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/>. */
Roland McGrathd17fac72005-08-23 08:20:21 +000028
29#include "libdwflP.h"
Ulrich Drepperb597dfa2007-10-16 05:21:27 +000030#include <fcntl.h>
Roland McGrathd17fac72005-08-23 08:20:21 +000031#include <unistd.h>
32
33/* Since dwfl_report_elf lays out the sections already, this will only be
34 called when the section headers of the debuginfo file are being
Roland McGrathe4c22ea2007-10-23 13:07:39 +000035 consulted instead, or for the section placed at 0. With binutils
36 strip-to-debug, the symbol table is in the debuginfo file and relocation
37 looks there. */
Roland McGrathd17fac72005-08-23 08:20:21 +000038int
39dwfl_offline_section_address (Dwfl_Module *mod,
40 void **userdata __attribute__ ((unused)),
41 const char *modname __attribute__ ((unused)),
42 Dwarf_Addr base __attribute__ ((unused)),
43 const char *secname __attribute__ ((unused)),
44 Elf32_Word shndx,
45 const GElf_Shdr *shdr __attribute__ ((unused)),
46 Dwarf_Addr *addr)
47{
Roland McGrath9aa8ef72007-05-18 08:59:43 +000048 assert (mod->e_type == ET_REL);
Roland McGrathd17fac72005-08-23 08:20:21 +000049 assert (shdr->sh_addr == 0);
50 assert (shdr->sh_flags & SHF_ALLOC);
Roland McGrathd17fac72005-08-23 08:20:21 +000051
Roland McGrathe4c22ea2007-10-23 13:07:39 +000052 if (mod->debug.elf == NULL)
53 /* We are only here because sh_addr is zero even though layout is complete.
54 The first section in the first file under -e is placed at 0. */
55 return 0;
56
Roland McGrath9aa8ef72007-05-18 08:59:43 +000057 /* The section numbers might not match between the two files.
58 The best we can rely on is the order of SHF_ALLOC sections. */
59
Ulrich Drepperb597dfa2007-10-16 05:21:27 +000060 Elf_Scn *ourscn = elf_getscn (mod->debug.elf, shndx);
Roland McGrath9aa8ef72007-05-18 08:59:43 +000061 Elf_Scn *scn = NULL;
62 uint_fast32_t skip_alloc = 0;
Ulrich Drepperb597dfa2007-10-16 05:21:27 +000063 while ((scn = elf_nextscn (mod->debug.elf, scn)) != ourscn)
Roland McGrath9aa8ef72007-05-18 08:59:43 +000064 {
65 assert (scn != NULL);
66 GElf_Shdr shdr_mem;
67 GElf_Shdr *sh = gelf_getshdr (scn, &shdr_mem);
68 if (unlikely (sh == NULL))
69 return -1;
70 if (sh->sh_flags & SHF_ALLOC)
71 ++skip_alloc;
72 }
73
74 scn = NULL;
75 while ((scn = elf_nextscn (mod->main.elf, scn)) != NULL)
76 {
77 GElf_Shdr shdr_mem;
Ulrich Drepperb597dfa2007-10-16 05:21:27 +000078 GElf_Shdr *main_shdr = gelf_getshdr (scn, &shdr_mem);
Roland McGrath9aa8ef72007-05-18 08:59:43 +000079 if (unlikely (main_shdr == NULL))
80 return -1;
81 if ((main_shdr->sh_flags & SHF_ALLOC) && skip_alloc-- == 0)
82 {
83 assert (main_shdr->sh_flags == shdr->sh_flags);
84 *addr = main_shdr->sh_addr;
85 return 0;
86 }
87 }
88
89 /* This should never happen. */
90 return -1;
Roland McGrathd17fac72005-08-23 08:20:21 +000091}
92INTDEF (dwfl_offline_section_address)
93
Ulrich Drepperb597dfa2007-10-16 05:21:27 +000094/* Forward declarations. */
95static Dwfl_Module *process_elf (Dwfl *dwfl, const char *name,
96 const char *file_name, int fd, Elf *elf);
97static Dwfl_Module *process_archive (Dwfl *dwfl, const char *name,
98 const char *file_name, int fd, Elf *elf,
99 int (*predicate) (const char *module,
100 const char *file));
Roland McGrathd17fac72005-08-23 08:20:21 +0000101
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000102/* Report one module for an ELF file, or many for an archive.
103 Always consumes ELF and FD. */
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000104static Dwfl_Module *
105process_file (Dwfl *dwfl, const char *name, const char *file_name, int fd,
106 Elf *elf, int (*predicate) (const char *module,
107 const char *file))
108{
109 switch (elf_kind (elf))
110 {
111 default:
112 case ELF_K_NONE:
113 __libdwfl_seterrno (elf == NULL ? DWFL_E_LIBELF : DWFL_E_BADELF);
114 return NULL;
115
116 case ELF_K_ELF:
117 return process_elf (dwfl, name, file_name, fd, elf);
118
119 case ELF_K_AR:
120 return process_archive (dwfl, name, file_name, fd, elf, predicate);
121 }
122}
123
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000124/* Report the open ELF file as a module. Always consumes ELF and FD. */
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000125static Dwfl_Module *
126process_elf (Dwfl *dwfl, const char *name, const char *file_name, int fd,
127 Elf *elf)
128{
129 Dwfl_Module *mod = __libdwfl_report_elf (dwfl, name, file_name, fd, elf,
Roland McGrath5453abf2009-02-10 17:33:49 -0800130 dwfl->offline_next_address, false);
Roland McGrathd17fac72005-08-23 08:20:21 +0000131 if (mod != NULL)
132 {
133 /* If this is an ET_EXEC file with fixed addresses, the address range
134 it consumed may or may not intersect with the arbitrary range we
135 will use for relocatable modules. Make sure we always use a free
Roland McGrath687d7e92006-02-27 04:53:00 +0000136 range for the offline allocations. If this module did use
137 offline_next_address, it may have rounded it up for the module's
138 alignment requirements. */
139 if ((dwfl->offline_next_address >= mod->low_addr
140 || mod->low_addr - dwfl->offline_next_address < OFFLINE_REDZONE)
Roland McGrathd17fac72005-08-23 08:20:21 +0000141 && dwfl->offline_next_address < mod->high_addr + OFFLINE_REDZONE)
142 dwfl->offline_next_address = mod->high_addr + OFFLINE_REDZONE;
143
144 /* Don't keep the file descriptor around. */
145 if (mod->main.fd != -1 && elf_cntl (mod->main.elf, ELF_C_FDREAD) == 0)
146 {
147 close (mod->main.fd);
148 mod->main.fd = -1;
149 }
150 }
151
152 return mod;
153}
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000154
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000155/* Always consumes MEMBER. Returns elf_next result on success.
156 For errors returns ELF_C_NULL with *MOD set to null. */
157static Elf_Cmd
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000158process_archive_member (Dwfl *dwfl, const char *name, const char *file_name,
159 int (*predicate) (const char *module, const char *file),
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000160 int fd, Elf *member, Dwfl_Module **mod)
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000161{
162 const Elf_Arhdr *h = elf_getarhdr (member);
163 if (unlikely (h == NULL))
164 {
165 __libdwfl_seterrno (DWFL_E_LIBELF);
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000166 fail:
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000167 elf_end (member);
168 *mod = NULL;
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000169 return ELF_C_NULL;
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000170 }
171
Petr Machatae1873142012-08-01 21:37:52 +0200172 if (!strcmp (h->ar_name, "/") || !strcmp (h->ar_name, "//")
173 || !strcmp (h->ar_name, "/SYM64/"))
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000174 {
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000175 skip:;
176 /* Skip this and go to the next. */
177 Elf_Cmd result = elf_next (member);
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000178 elf_end (member);
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000179 return result;
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000180 }
181
182 char *member_name;
183 if (unlikely (asprintf (&member_name, "%s(%s)", file_name, h->ar_name) < 0))
184 {
185 nomem:
186 __libdwfl_seterrno (DWFL_E_NOMEM);
187 elf_end (member);
188 *mod = NULL;
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000189 return ELF_C_NULL;
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000190 }
191
192 char *module_name = NULL;
193 if (name == NULL || name[0] == '\0')
194 name = h->ar_name;
195 else if (unlikely (asprintf (&module_name, "%s:%s", name, h->ar_name) < 0))
196 {
197 free (member_name);
198 goto nomem;
199 }
200 else
201 name = module_name;
202
203 if (predicate != NULL)
204 {
205 /* Let the predicate decide whether to use this one. */
206 int want = (*predicate) (name, member_name);
207 if (want <= 0)
208 {
209 free (member_name);
210 free (module_name);
211 if (unlikely (want < 0))
212 {
213 __libdwfl_seterrno (DWFL_E_CB);
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000214 goto fail;
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000215 }
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000216 goto skip;
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000217 }
218 }
219
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000220 /* We let __libdwfl_report_elf cache the fd in mod->main.fd,
221 though it's the same fd for all the members.
222 On module teardown we will close it only on the last Elf reference. */
223 *mod = process_file (dwfl, name, member_name, fd, member, predicate);
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000224 free (member_name);
225 free (module_name);
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000226
227 if (*mod == NULL) /* process_file called elf_end. */
228 return ELF_C_NULL;
229
230 /* Advance the archive-reading offset for the next iteration. */
231 return elf_next (member);
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000232}
233
234/* Report each member of the archive as its own module. */
235static Dwfl_Module *
236process_archive (Dwfl *dwfl, const char *name, const char *file_name, int fd,
237 Elf *archive,
238 int (*predicate) (const char *module, const char *file))
239
240{
241 Dwfl_Module *mod = NULL;
Roland McGrathb28a8942008-12-11 02:09:28 -0800242 Elf *member = elf_begin (fd, ELF_C_READ_MMAP_PRIVATE, archive);
243 if (unlikely (member == NULL)) /* Empty archive. */
244 {
245 __libdwfl_seterrno (DWFL_E_BADELF);
246 return NULL;
247 }
248
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000249 while (process_archive_member (dwfl, name, file_name, predicate,
Roland McGrathb28a8942008-12-11 02:09:28 -0800250 fd, member, &mod) != ELF_C_NULL)
251 member = elf_begin (fd, ELF_C_READ_MMAP_PRIVATE, archive);
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000252
253 /* We can drop the archive Elf handle even if we're still using members
254 in live modules. When the last module's elf_end on a member returns
255 zero, that module will close FD. If no modules survived the predicate,
256 we are all done with the file right here. */
Roland McGrathb28a8942008-12-11 02:09:28 -0800257 if (mod != NULL /* If no modules, caller will clean up. */
258 && elf_end (archive) == 0)
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000259 close (fd);
Roland McGrathe4c22ea2007-10-23 13:07:39 +0000260
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000261 return mod;
262}
263
264Dwfl_Module *
265internal_function
266__libdwfl_report_offline (Dwfl *dwfl, const char *name,
267 const char *file_name, int fd, bool closefd,
268 int (*predicate) (const char *module,
269 const char *file))
270{
Roland McGrathbca43152009-01-05 23:59:32 -0800271 Elf *elf;
272 Dwfl_Error error = __libdw_open_file (&fd, &elf, closefd, true);
273 if (error != DWFL_E_NOERROR)
274 {
275 __libdwfl_seterrno (error);
276 return NULL;
277 }
Ulrich Drepperb597dfa2007-10-16 05:21:27 +0000278 Dwfl_Module *mod = process_file (dwfl, name, file_name, fd, elf, predicate);
279 if (mod == NULL)
280 {
281 elf_end (elf);
282 if (closefd)
283 close (fd);
284 }
285 return mod;
286}
287
288Dwfl_Module *
289dwfl_report_offline (Dwfl *dwfl, const char *name,
290 const char *file_name, int fd)
291{
292 if (dwfl == NULL)
293 return NULL;
294
295 bool closefd = false;
296 if (fd < 0)
297 {
298 closefd = true;
299 fd = open64 (file_name, O_RDONLY);
300 if (fd < 0)
301 {
302 __libdwfl_seterrno (DWFL_E_ERRNO);
303 return NULL;
304 }
305 }
306
307 return __libdwfl_report_offline (dwfl, name, file_name, fd, closefd, NULL);
308}
Roland McGrathd17fac72005-08-23 08:20:21 +0000309INTDEF (dwfl_report_offline)