summaryrefslogtreecommitdiffstats
path: root/libdwfl/offline.c
diff options
context:
space:
mode:
Diffstat (limited to 'libdwfl/offline.c')
-rw-r--r--libdwfl/offline.c78
1 files changed, 78 insertions, 0 deletions
diff --git a/libdwfl/offline.c b/libdwfl/offline.c
new file mode 100644
index 00000000..05496399
--- /dev/null
+++ b/libdwfl/offline.c
@@ -0,0 +1,78 @@
+/* Recover relocatibility for addresses computed from debug information.
+ Copyright (C) 2005 Red Hat, Inc.
+
+ This program is Open Source software; you can redistribute it and/or
+ modify it under the terms of the Open Software License version 1.0 as
+ published by the Open Source Initiative.
+
+ You should have received a copy of the Open Software License along
+ with this program; if not, you may obtain a copy of the Open Software
+ License version 1.0 from http://www.opensource.org/licenses/osl.php or
+ by writing the Open Source Initiative c/o Lawrence Rosen, Esq.,
+ 3001 King Ranch Road, Ukiah, CA 95482. */
+
+#include "libdwflP.h"
+#include <unistd.h>
+
+/* Since dwfl_report_elf lays out the sections already, this will only be
+ called when the section headers of the debuginfo file are being
+ consulted instead. With binutils strip-to-debug, the symbol table
+ is in the debuginfo file and relocation looks there. */
+int
+dwfl_offline_section_address (Dwfl_Module *mod,
+ void **userdata __attribute__ ((unused)),
+ const char *modname __attribute__ ((unused)),
+ Dwarf_Addr base __attribute__ ((unused)),
+ const char *secname __attribute__ ((unused)),
+ Elf32_Word shndx,
+ const GElf_Shdr *shdr __attribute__ ((unused)),
+ Dwarf_Addr *addr)
+{
+ assert (mod->symfile != &mod->main);
+
+ GElf_Shdr shdr_mem;
+ GElf_Shdr *main_shdr = gelf_getshdr (elf_getscn (mod->main.elf, shndx),
+ &shdr_mem);
+ if (unlikely (main_shdr == NULL))
+ return -1;
+
+ assert (shdr->sh_addr == 0);
+ assert (shdr->sh_flags & SHF_ALLOC);
+ assert (main_shdr->sh_addr != 0);
+ assert (main_shdr->sh_flags == shdr->sh_flags);
+
+ *addr = main_shdr->sh_addr;
+ return 0;
+}
+INTDEF (dwfl_offline_section_address)
+
+Dwfl_Module *
+dwfl_report_offline (Dwfl *dwfl, const char *name,
+ const char *file_name, int fd)
+{
+ if (dwfl == NULL)
+ return NULL;
+
+ Dwfl_Module *mod = INTUSE(dwfl_report_elf) (dwfl, name, file_name, fd,
+ dwfl->offline_next_address);
+ if (mod != NULL)
+ {
+ /* If this is an ET_EXEC file with fixed addresses, the address range
+ it consumed may or may not intersect with the arbitrary range we
+ will use for relocatable modules. Make sure we always use a free
+ range for the offline allocations. */
+ if (dwfl->offline_next_address >= mod->low_addr
+ && dwfl->offline_next_address < mod->high_addr + OFFLINE_REDZONE)
+ dwfl->offline_next_address = mod->high_addr + OFFLINE_REDZONE;
+
+ /* Don't keep the file descriptor around. */
+ if (mod->main.fd != -1 && elf_cntl (mod->main.elf, ELF_C_FDREAD) == 0)
+ {
+ close (mod->main.fd);
+ mod->main.fd = -1;
+ }
+ }
+
+ return mod;
+}
+INTDEF (dwfl_report_offline)