aboutsummaryrefslogtreecommitdiffstats
path: root/gcc-4.8.1/libbacktrace/elf.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc-4.8.1/libbacktrace/elf.c')
-rw-r--r--gcc-4.8.1/libbacktrace/elf.c904
1 files changed, 0 insertions, 904 deletions
diff --git a/gcc-4.8.1/libbacktrace/elf.c b/gcc-4.8.1/libbacktrace/elf.c
deleted file mode 100644
index ef9bcdfb4..000000000
--- a/gcc-4.8.1/libbacktrace/elf.c
+++ /dev/null
@@ -1,904 +0,0 @@
-/* elf.c -- Get debug data from an ELF file for backtraces.
- Copyright (C) 2012-2013 Free Software Foundation, Inc.
- Written by Ian Lance Taylor, Google.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are
-met:
-
- (1) Redistributions of source code must retain the above copyright
- notice, this list of conditions and the following disclaimer.
-
- (2) Redistributions in binary form must reproduce the above copyright
- notice, this list of conditions and the following disclaimer in
- the documentation and/or other materials provided with the
- distribution.
-
- (3) The name of the author may not be used to
- endorse or promote products derived from this software without
- specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
-INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
-SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
-STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
-IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE. */
-
-#include "config.h"
-
-#include <stdlib.h>
-#include <string.h>
-#include <sys/types.h>
-
-#ifdef HAVE_DL_ITERATE_PHDR
-#include <link.h>
-#endif
-
-#include "backtrace.h"
-#include "internal.h"
-
-#ifndef HAVE_DL_ITERATE_PHDR
-
-/* Dummy version of dl_iterate_phdr for systems that don't have it. */
-
-#define dl_phdr_info x_dl_phdr_info
-#define dl_iterate_phdr x_dl_iterate_phdr
-
-struct dl_phdr_info
-{
- uintptr_t dlpi_addr;
- const char *dlpi_name;
-};
-
-static int
-dl_iterate_phdr (int (*callback) (struct dl_phdr_info *,
- size_t, void *) ATTRIBUTE_UNUSED,
- void *data ATTRIBUTE_UNUSED)
-{
- return 0;
-}
-
-#endif /* ! defined (HAVE_DL_ITERATE_PHDR) */
-
-/* The configure script must tell us whether we are 32-bit or 64-bit
- ELF. We could make this code test and support either possibility,
- but there is no point. This code only works for the currently
- running executable, which means that we know the ELF mode at
- configure mode. */
-
-#if BACKTRACE_ELF_SIZE != 32 && BACKTRACE_ELF_SIZE != 64
-#error "Unknown BACKTRACE_ELF_SIZE"
-#endif
-
-/* <link.h> might #include <elf.h> which might define our constants
- with slightly different values. Undefine them to be safe. */
-
-#undef EI_NIDENT
-#undef EI_MAG0
-#undef EI_MAG1
-#undef EI_MAG2
-#undef EI_MAG3
-#undef EI_CLASS
-#undef EI_DATA
-#undef EI_VERSION
-#undef ELF_MAG0
-#undef ELF_MAG1
-#undef ELF_MAG2
-#undef ELF_MAG3
-#undef ELFCLASS32
-#undef ELFCLASS64
-#undef ELFDATA2LSB
-#undef ELFDATA2MSB
-#undef EV_CURRENT
-#undef SHN_LORESERVE
-#undef SHN_XINDEX
-#undef SHT_SYMTAB
-#undef SHT_STRTAB
-#undef SHT_DYNSYM
-#undef STT_FUNC
-
-/* Basic types. */
-
-typedef uint16_t b_elf_half; /* Elf_Half. */
-typedef uint32_t b_elf_word; /* Elf_Word. */
-typedef int32_t b_elf_sword; /* Elf_Sword. */
-
-#if BACKTRACE_ELF_SIZE == 32
-
-typedef uint32_t b_elf_addr; /* Elf_Addr. */
-typedef uint32_t b_elf_off; /* Elf_Off. */
-
-typedef uint32_t b_elf_wxword; /* 32-bit Elf_Word, 64-bit ELF_Xword. */
-
-#else
-
-typedef uint64_t b_elf_addr; /* Elf_Addr. */
-typedef uint64_t b_elf_off; /* Elf_Off. */
-typedef uint64_t b_elf_xword; /* Elf_Xword. */
-typedef int64_t b_elf_sxword; /* Elf_Sxword. */
-
-typedef uint64_t b_elf_wxword; /* 32-bit Elf_Word, 64-bit ELF_Xword. */
-
-#endif
-
-/* Data structures and associated constants. */
-
-#define EI_NIDENT 16
-
-typedef struct {
- unsigned char e_ident[EI_NIDENT]; /* ELF "magic number" */
- b_elf_half e_type; /* Identifies object file type */
- b_elf_half e_machine; /* Specifies required architecture */
- b_elf_word e_version; /* Identifies object file version */
- b_elf_addr e_entry; /* Entry point virtual address */
- b_elf_off e_phoff; /* Program header table file offset */
- b_elf_off e_shoff; /* Section header table file offset */
- b_elf_word e_flags; /* Processor-specific flags */
- b_elf_half e_ehsize; /* ELF header size in bytes */
- b_elf_half e_phentsize; /* Program header table entry size */
- b_elf_half e_phnum; /* Program header table entry count */
- b_elf_half e_shentsize; /* Section header table entry size */
- b_elf_half e_shnum; /* Section header table entry count */
- b_elf_half e_shstrndx; /* Section header string table index */
-} b_elf_ehdr; /* Elf_Ehdr. */
-
-#define EI_MAG0 0
-#define EI_MAG1 1
-#define EI_MAG2 2
-#define EI_MAG3 3
-#define EI_CLASS 4
-#define EI_DATA 5
-#define EI_VERSION 6
-
-#define ELFMAG0 0x7f
-#define ELFMAG1 'E'
-#define ELFMAG2 'L'
-#define ELFMAG3 'F'
-
-#define ELFCLASS32 1
-#define ELFCLASS64 2
-
-#define ELFDATA2LSB 1
-#define ELFDATA2MSB 2
-
-#define EV_CURRENT 1
-
-typedef struct {
- b_elf_word sh_name; /* Section name, index in string tbl */
- b_elf_word sh_type; /* Type of section */
- b_elf_wxword sh_flags; /* Miscellaneous section attributes */
- b_elf_addr sh_addr; /* Section virtual addr at execution */
- b_elf_off sh_offset; /* Section file offset */
- b_elf_wxword sh_size; /* Size of section in bytes */
- b_elf_word sh_link; /* Index of another section */
- b_elf_word sh_info; /* Additional section information */
- b_elf_wxword sh_addralign; /* Section alignment */
- b_elf_wxword sh_entsize; /* Entry size if section holds table */
-} b_elf_shdr; /* Elf_Shdr. */
-
-#define SHN_LORESERVE 0xFF00 /* Begin range of reserved indices */
-#define SHN_XINDEX 0xFFFF /* Section index is held elsewhere */
-
-#define SHT_SYMTAB 2
-#define SHT_STRTAB 3
-#define SHT_DYNSYM 11
-
-#if BACKTRACE_ELF_SIZE == 32
-
-typedef struct
-{
- b_elf_word st_name; /* Symbol name, index in string tbl */
- b_elf_addr st_value; /* Symbol value */
- b_elf_word st_size; /* Symbol size */
- unsigned char st_info; /* Symbol binding and type */
- unsigned char st_other; /* Visibility and other data */
- b_elf_half st_shndx; /* Symbol section index */
-} b_elf_sym; /* Elf_Sym. */
-
-#else /* BACKTRACE_ELF_SIZE != 32 */
-
-typedef struct
-{
- b_elf_word st_name; /* Symbol name, index in string tbl */
- unsigned char st_info; /* Symbol binding and type */
- unsigned char st_other; /* Visibility and other data */
- b_elf_half st_shndx; /* Symbol section index */
- b_elf_addr st_value; /* Symbol value */
- b_elf_xword st_size; /* Symbol size */
-} b_elf_sym; /* Elf_Sym. */
-
-#endif /* BACKTRACE_ELF_SIZE != 32 */
-
-#define STT_FUNC 2
-
-/* An index of ELF sections we care about. */
-
-enum debug_section
-{
- DEBUG_INFO,
- DEBUG_LINE,
- DEBUG_ABBREV,
- DEBUG_RANGES,
- DEBUG_STR,
- DEBUG_MAX
-};
-
-/* Names of sections, indexed by enum elf_section. */
-
-static const char * const debug_section_names[DEBUG_MAX] =
-{
- ".debug_info",
- ".debug_line",
- ".debug_abbrev",
- ".debug_ranges",
- ".debug_str"
-};
-
-/* Information we gather for the sections we care about. */
-
-struct debug_section_info
-{
- /* Section file offset. */
- off_t offset;
- /* Section size. */
- size_t size;
- /* Section contents, after read from file. */
- const unsigned char *data;
-};
-
-/* Information we keep for an ELF symbol. */
-
-struct elf_symbol
-{
- /* The name of the symbol. */
- const char *name;
- /* The address of the symbol. */
- uintptr_t address;
- /* The size of the symbol. */
- size_t size;
-};
-
-/* Information to pass to elf_syminfo. */
-
-struct elf_syminfo_data
-{
- /* Symbols for the next module. */
- struct elf_syminfo_data *next;
- /* The ELF symbols, sorted by address. */
- struct elf_symbol *symbols;
- /* The number of symbols. */
- size_t count;
-};
-
-/* A dummy callback function used when we can't find any debug info. */
-
-static int
-elf_nodebug (struct backtrace_state *state ATTRIBUTE_UNUSED,
- uintptr_t pc ATTRIBUTE_UNUSED,
- backtrace_full_callback callback ATTRIBUTE_UNUSED,
- backtrace_error_callback error_callback, void *data)
-{
- error_callback (data, "no debug info in ELF executable", -1);
- return 0;
-}
-
-/* A dummy callback function used when we can't find a symbol
- table. */
-
-static void
-elf_nosyms (struct backtrace_state *state ATTRIBUTE_UNUSED,
- uintptr_t pc ATTRIBUTE_UNUSED,
- backtrace_syminfo_callback callback ATTRIBUTE_UNUSED,
- backtrace_error_callback error_callback, void *data)
-{
- error_callback (data, "no symbol table in ELF executable", -1);
-}
-
-/* Compare struct elf_symbol for qsort. */
-
-static int
-elf_symbol_compare (const void *v1, const void *v2)
-{
- const struct elf_symbol *e1 = (const struct elf_symbol *) v1;
- const struct elf_symbol *e2 = (const struct elf_symbol *) v2;
-
- if (e1->address < e2->address)
- return -1;
- else if (e1->address > e2->address)
- return 1;
- else
- return 0;
-}
-
-/* Compare a PC against an elf_symbol for bsearch. We allocate one
- extra entry in the array so that this can look safely at the next
- entry. */
-
-static int
-elf_symbol_search (const void *vkey, const void *ventry)
-{
- const uintptr_t *key = (const uintptr_t *) vkey;
- const struct elf_symbol *entry = (const struct elf_symbol *) ventry;
- uintptr_t pc;
-
- pc = *key;
- if (pc < entry->address)
- return -1;
- else if (pc >= entry->address + entry->size)
- return 1;
- else
- return 0;
-}
-
-/* Initialize the symbol table info for elf_syminfo. */
-
-static int
-elf_initialize_syminfo (struct backtrace_state *state,
- const unsigned char *symtab_data, size_t symtab_size,
- const unsigned char *strtab, size_t strtab_size,
- backtrace_error_callback error_callback,
- void *data, struct elf_syminfo_data *sdata)
-{
- size_t sym_count;
- const b_elf_sym *sym;
- size_t elf_symbol_count;
- size_t elf_symbol_size;
- struct elf_symbol *elf_symbols;
- size_t i;
- unsigned int j;
-
- sym_count = symtab_size / sizeof (b_elf_sym);
-
- /* We only care about function symbols. Count them. */
- sym = (const b_elf_sym *) symtab_data;
- elf_symbol_count = 0;
- for (i = 0; i < sym_count; ++i, ++sym)
- {
- if ((sym->st_info & 0xf) == STT_FUNC)
- ++elf_symbol_count;
- }
-
- elf_symbol_size = elf_symbol_count * sizeof (struct elf_symbol);
- elf_symbols = ((struct elf_symbol *)
- backtrace_alloc (state, elf_symbol_size, error_callback,
- data));
- if (elf_symbols == NULL)
- return 0;
-
- sym = (const b_elf_sym *) symtab_data;
- j = 0;
- for (i = 0; i < sym_count; ++i, ++sym)
- {
- if ((sym->st_info & 0xf) != STT_FUNC)
- continue;
- if (sym->st_name >= strtab_size)
- {
- error_callback (data, "symbol string index out of range", 0);
- backtrace_free (state, elf_symbols, elf_symbol_size, error_callback,
- data);
- return 0;
- }
- elf_symbols[j].name = (const char *) strtab + sym->st_name;
- elf_symbols[j].address = sym->st_value;
- elf_symbols[j].size = sym->st_size;
- ++j;
- }
-
- qsort (elf_symbols, elf_symbol_count, sizeof (struct elf_symbol),
- elf_symbol_compare);
-
- sdata->next = NULL;
- sdata->symbols = elf_symbols;
- sdata->count = elf_symbol_count;
-
- return 1;
-}
-
-/* Add EDATA to the list in STATE. */
-
-static void
-elf_add_syminfo_data (struct backtrace_state *state,
- struct elf_syminfo_data *edata)
-{
- if (!state->threaded)
- {
- struct elf_syminfo_data **pp;
-
- for (pp = (struct elf_syminfo_data **) (void *) &state->syminfo_data;
- *pp != NULL;
- pp = &(*pp)->next)
- ;
- *pp = edata;
- }
- else
- {
- while (1)
- {
- struct elf_syminfo_data **pp;
-
- pp = (struct elf_syminfo_data **) (void *) &state->syminfo_data;
-
- while (1)
- {
- struct elf_syminfo_data *p;
-
- /* Atomic load. */
- p = *pp;
- while (!__sync_bool_compare_and_swap (pp, p, p))
- p = *pp;
-
- if (p == NULL)
- break;
-
- pp = &p->next;
- }
-
- if (__sync_bool_compare_and_swap (pp, NULL, edata))
- break;
- }
- }
-}
-
-/* Return the symbol name and value for a PC. */
-
-static void
-elf_syminfo (struct backtrace_state *state, uintptr_t pc,
- backtrace_syminfo_callback callback,
- backtrace_error_callback error_callback ATTRIBUTE_UNUSED,
- void *data)
-{
- struct elf_syminfo_data *edata;
- struct elf_symbol *sym;
-
- edata = (struct elf_syminfo_data *) state->syminfo_data;
- sym = ((struct elf_symbol *)
- bsearch (&pc, edata->symbols, edata->count,
- sizeof (struct elf_symbol), elf_symbol_search));
- if (sym == NULL)
- callback (data, pc, NULL, 0);
- else
- callback (data, pc, sym->name, sym->address);
-}
-
-/* Add the backtrace data for one ELF file. */
-
-static int
-elf_add (struct backtrace_state *state, int descriptor, uintptr_t base_address,
- backtrace_error_callback error_callback, void *data,
- fileline *fileline_fn, int *found_sym, int *found_dwarf)
-{
- struct backtrace_view ehdr_view;
- b_elf_ehdr ehdr;
- off_t shoff;
- unsigned int shnum;
- unsigned int shstrndx;
- struct backtrace_view shdrs_view;
- int shdrs_view_valid;
- const b_elf_shdr *shdrs;
- const b_elf_shdr *shstrhdr;
- size_t shstr_size;
- off_t shstr_off;
- struct backtrace_view names_view;
- int names_view_valid;
- const char *names;
- unsigned int symtab_shndx;
- unsigned int dynsym_shndx;
- unsigned int i;
- struct debug_section_info sections[DEBUG_MAX];
- struct backtrace_view symtab_view;
- int symtab_view_valid;
- struct backtrace_view strtab_view;
- int strtab_view_valid;
- off_t min_offset;
- off_t max_offset;
- struct backtrace_view debug_view;
- int debug_view_valid;
-
- *found_sym = 0;
- *found_dwarf = 0;
-
- shdrs_view_valid = 0;
- names_view_valid = 0;
- symtab_view_valid = 0;
- strtab_view_valid = 0;
- debug_view_valid = 0;
-
- if (!backtrace_get_view (state, descriptor, 0, sizeof ehdr, error_callback,
- data, &ehdr_view))
- goto fail;
-
- memcpy (&ehdr, ehdr_view.data, sizeof ehdr);
-
- backtrace_release_view (state, &ehdr_view, error_callback, data);
-
- if (ehdr.e_ident[EI_MAG0] != ELFMAG0
- || ehdr.e_ident[EI_MAG1] != ELFMAG1
- || ehdr.e_ident[EI_MAG2] != ELFMAG2
- || ehdr.e_ident[EI_MAG3] != ELFMAG3)
- {
- error_callback (data, "executable file is not ELF", 0);
- goto fail;
- }
- if (ehdr.e_ident[EI_VERSION] != EV_CURRENT)
- {
- error_callback (data, "executable file is unrecognized ELF version", 0);
- goto fail;
- }
-
-#if BACKTRACE_ELF_SIZE == 32
-#define BACKTRACE_ELFCLASS ELFCLASS32
-#else
-#define BACKTRACE_ELFCLASS ELFCLASS64
-#endif
-
- if (ehdr.e_ident[EI_CLASS] != BACKTRACE_ELFCLASS)
- {
- error_callback (data, "executable file is unexpected ELF class", 0);
- goto fail;
- }
-
- if (ehdr.e_ident[EI_DATA] != ELFDATA2LSB
- && ehdr.e_ident[EI_DATA] != ELFDATA2MSB)
- {
- error_callback (data, "executable file has unknown endianness", 0);
- goto fail;
- }
-
- shoff = ehdr.e_shoff;
- shnum = ehdr.e_shnum;
- shstrndx = ehdr.e_shstrndx;
-
- if ((shnum == 0 || shstrndx == SHN_XINDEX)
- && shoff != 0)
- {
- struct backtrace_view shdr_view;
- const b_elf_shdr *shdr;
-
- if (!backtrace_get_view (state, descriptor, shoff, sizeof shdr,
- error_callback, data, &shdr_view))
- goto fail;
-
- shdr = (const b_elf_shdr *) shdr_view.data;
-
- if (shnum == 0)
- shnum = shdr->sh_size;
-
- if (shstrndx == SHN_XINDEX)
- {
- shstrndx = shdr->sh_link;
-
- /* Versions of the GNU binutils between 2.12 and 2.18 did
- not handle objects with more than SHN_LORESERVE sections
- correctly. All large section indexes were offset by
- 0x100. There is more information at
- http://sourceware.org/bugzilla/show_bug.cgi?id-5900 .
- Fortunately these object files are easy to detect, as the
- GNU binutils always put the section header string table
- near the end of the list of sections. Thus if the
- section header string table index is larger than the
- number of sections, then we know we have to subtract
- 0x100 to get the real section index. */
- if (shstrndx >= shnum && shstrndx >= SHN_LORESERVE + 0x100)
- shstrndx -= 0x100;
- }
-
- backtrace_release_view (state, &shdr_view, error_callback, data);
- }
-
- /* To translate PC to file/line when using DWARF, we need to find
- the .debug_info and .debug_line sections. */
-
- /* Read the section headers, skipping the first one. */
-
- if (!backtrace_get_view (state, descriptor, shoff + sizeof (b_elf_shdr),
- (shnum - 1) * sizeof (b_elf_shdr),
- error_callback, data, &shdrs_view))
- goto fail;
- shdrs_view_valid = 1;
- shdrs = (const b_elf_shdr *) shdrs_view.data;
-
- /* Read the section names. */
-
- shstrhdr = &shdrs[shstrndx - 1];
- shstr_size = shstrhdr->sh_size;
- shstr_off = shstrhdr->sh_offset;
-
- if (!backtrace_get_view (state, descriptor, shstr_off, shstr_size,
- error_callback, data, &names_view))
- goto fail;
- names_view_valid = 1;
- names = (const char *) names_view.data;
-
- symtab_shndx = 0;
- dynsym_shndx = 0;
-
- memset (sections, 0, sizeof sections);
-
- /* Look for the symbol table. */
- for (i = 1; i < shnum; ++i)
- {
- const b_elf_shdr *shdr;
- unsigned int sh_name;
- const char *name;
- int j;
-
- shdr = &shdrs[i - 1];
-
- if (shdr->sh_type == SHT_SYMTAB)
- symtab_shndx = i;
- else if (shdr->sh_type == SHT_DYNSYM)
- dynsym_shndx = i;
-
- sh_name = shdr->sh_name;
- if (sh_name >= shstr_size)
- {
- error_callback (data, "ELF section name out of range", 0);
- goto fail;
- }
-
- name = names + sh_name;
-
- for (j = 0; j < (int) DEBUG_MAX; ++j)
- {
- if (strcmp (name, debug_section_names[j]) == 0)
- {
- sections[j].offset = shdr->sh_offset;
- sections[j].size = shdr->sh_size;
- break;
- }
- }
- }
-
- if (symtab_shndx == 0)
- symtab_shndx = dynsym_shndx;
- if (symtab_shndx != 0)
- {
- const b_elf_shdr *symtab_shdr;
- unsigned int strtab_shndx;
- const b_elf_shdr *strtab_shdr;
- struct elf_syminfo_data *sdata;
-
- symtab_shdr = &shdrs[symtab_shndx - 1];
- strtab_shndx = symtab_shdr->sh_link;
- if (strtab_shndx >= shnum)
- {
- error_callback (data,
- "ELF symbol table strtab link out of range", 0);
- goto fail;
- }
- strtab_shdr = &shdrs[strtab_shndx - 1];
-
- if (!backtrace_get_view (state, descriptor, symtab_shdr->sh_offset,
- symtab_shdr->sh_size, error_callback, data,
- &symtab_view))
- goto fail;
- symtab_view_valid = 1;
-
- if (!backtrace_get_view (state, descriptor, strtab_shdr->sh_offset,
- strtab_shdr->sh_size, error_callback, data,
- &strtab_view))
- goto fail;
- strtab_view_valid = 1;
-
- sdata = ((struct elf_syminfo_data *)
- backtrace_alloc (state, sizeof *sdata, error_callback, data));
- if (sdata == NULL)
- goto fail;
-
- if (!elf_initialize_syminfo (state,
- symtab_view.data, symtab_shdr->sh_size,
- strtab_view.data, strtab_shdr->sh_size,
- error_callback, data, sdata))
- {
- backtrace_free (state, sdata, sizeof *sdata, error_callback, data);
- goto fail;
- }
-
- /* We no longer need the symbol table, but we hold on to the
- string table permanently. */
- backtrace_release_view (state, &symtab_view, error_callback, data);
-
- *found_sym = 1;
-
- elf_add_syminfo_data (state, sdata);
- }
-
- /* FIXME: Need to handle compressed debug sections. */
-
- backtrace_release_view (state, &shdrs_view, error_callback, data);
- shdrs_view_valid = 0;
- backtrace_release_view (state, &names_view, error_callback, data);
- names_view_valid = 0;
-
- /* Read all the debug sections in a single view, since they are
- probably adjacent in the file. We never release this view. */
-
- min_offset = 0;
- max_offset = 0;
- for (i = 0; i < (int) DEBUG_MAX; ++i)
- {
- off_t end;
-
- if (min_offset == 0 || sections[i].offset < min_offset)
- min_offset = sections[i].offset;
- end = sections[i].offset + sections[i].size;
- if (end > max_offset)
- max_offset = end;
- }
- if (min_offset == 0 || max_offset == 0)
- {
- if (!backtrace_close (descriptor, error_callback, data))
- goto fail;
- *fileline_fn = elf_nodebug;
- return 1;
- }
-
- if (!backtrace_get_view (state, descriptor, min_offset,
- max_offset - min_offset,
- error_callback, data, &debug_view))
- goto fail;
- debug_view_valid = 1;
-
- /* We've read all we need from the executable. */
- if (!backtrace_close (descriptor, error_callback, data))
- goto fail;
- descriptor = -1;
-
- for (i = 0; i < (int) DEBUG_MAX; ++i)
- sections[i].data = ((const unsigned char *) debug_view.data
- + (sections[i].offset - min_offset));
-
- if (!backtrace_dwarf_add (state, base_address,
- sections[DEBUG_INFO].data,
- sections[DEBUG_INFO].size,
- sections[DEBUG_LINE].data,
- sections[DEBUG_LINE].size,
- sections[DEBUG_ABBREV].data,
- sections[DEBUG_ABBREV].size,
- sections[DEBUG_RANGES].data,
- sections[DEBUG_RANGES].size,
- sections[DEBUG_STR].data,
- sections[DEBUG_STR].size,
- ehdr.e_ident[EI_DATA] == ELFDATA2MSB,
- error_callback, data, fileline_fn))
- goto fail;
-
- *found_dwarf = 1;
-
- return 1;
-
- fail:
- if (shdrs_view_valid)
- backtrace_release_view (state, &shdrs_view, error_callback, data);
- if (names_view_valid)
- backtrace_release_view (state, &names_view, error_callback, data);
- if (symtab_view_valid)
- backtrace_release_view (state, &symtab_view, error_callback, data);
- if (strtab_view_valid)
- backtrace_release_view (state, &strtab_view, error_callback, data);
- if (debug_view_valid)
- backtrace_release_view (state, &debug_view, error_callback, data);
- if (descriptor != -1)
- backtrace_close (descriptor, error_callback, data);
- return 0;
-}
-
-/* Data passed to phdr_callback. */
-
-struct phdr_data
-{
- struct backtrace_state *state;
- backtrace_error_callback error_callback;
- void *data;
- fileline *fileline_fn;
- int *found_sym;
- int *found_dwarf;
-};
-
-/* Callback passed to dl_iterate_phdr. Load debug info from shared
- libraries. */
-
-static int
-phdr_callback (struct dl_phdr_info *info, size_t size ATTRIBUTE_UNUSED,
- void *pdata)
-{
- struct phdr_data *pd = (struct phdr_data *) pdata;
- int descriptor;
- int does_not_exist;
- fileline elf_fileline_fn;
- int found_dwarf;
-
- /* There is not much we can do if we don't have the module name. If
- the base address is 0, this is probably the executable, which we
- already loaded. */
- if (info->dlpi_name == NULL
- || info->dlpi_name[0] == '\0'
- || info->dlpi_addr == 0)
- return 0;
-
- descriptor = backtrace_open (info->dlpi_name, pd->error_callback, pd->data,
- &does_not_exist);
- if (descriptor < 0)
- return 0;
-
- if (elf_add (pd->state, descriptor, info->dlpi_addr, pd->error_callback,
- pd->data, &elf_fileline_fn, pd->found_sym, &found_dwarf))
- {
- if (found_dwarf)
- {
- *pd->found_dwarf = 1;
- *pd->fileline_fn = elf_fileline_fn;
- }
- }
-
- return 0;
-}
-
-/* Initialize the backtrace data we need from an ELF executable. At
- the ELF level, all we need to do is find the debug info
- sections. */
-
-int
-backtrace_initialize (struct backtrace_state *state, int descriptor,
- backtrace_error_callback error_callback,
- void *data, fileline *fileline_fn)
-{
- int found_sym;
- int found_dwarf;
- syminfo elf_syminfo_fn;
- fileline elf_fileline_fn;
- struct phdr_data pd;
-
- if (!elf_add (state, descriptor, 0, error_callback, data, &elf_fileline_fn,
- &found_sym, &found_dwarf))
- return 0;
-
- pd.state = state;
- pd.error_callback = error_callback;
- pd.data = data;
- pd.fileline_fn = fileline_fn;
- pd.found_sym = &found_sym;
- pd.found_dwarf = &found_dwarf;
-
- dl_iterate_phdr (phdr_callback, (void *) &pd);
-
- elf_syminfo_fn = found_sym ? elf_syminfo : elf_nosyms;
- if (!state->threaded)
- {
- if (state->syminfo_fn == NULL || found_sym)
- state->syminfo_fn = elf_syminfo_fn;
- }
- else
- {
- __sync_bool_compare_and_swap (&state->syminfo_fn, NULL, elf_syminfo_fn);
- if (found_sym)
- __sync_bool_compare_and_swap (&state->syminfo_fn, elf_nosyms,
- elf_syminfo_fn);
- }
-
- if (!state->threaded)
- {
- if (state->fileline_fn == NULL || state->fileline_fn == elf_nodebug)
- *fileline_fn = elf_fileline_fn;
- }
- else
- {
- fileline current_fn;
-
- /* Atomic load. */
- current_fn = state->fileline_fn;
- while (!__sync_bool_compare_and_swap (&state->fileline_fn, current_fn,
- current_fn))
- current_fn = state->fileline_fn;
- if (current_fn == NULL || current_fn == elf_nodebug)
- *fileline_fn = elf_fileline_fn;
- }
-
- return 1;
-}