X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Felfread.c;h=7b84ede6c7165f329f12667307e587b4c3a2f8e1;hb=31d99776c73d6fca13163da59c852b0fa99f89b8;hp=ea28d7c258a9d171fd35898a6bbc6446347edab2;hpb=d856f2ddfa3d037987610ecc0edbf75f31296971;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/elfread.c b/gdb/elfread.c index ea28d7c258..7b84ede6c7 100644 --- a/gdb/elfread.c +++ b/gdb/elfread.c @@ -26,6 +26,8 @@ #include "bfd.h" #include "gdb_string.h" #include "elf-bfd.h" +#include "elf/common.h" +#include "elf/internal.h" #include "elf/mips.h" #include "symtab.h" #include "symfile.h" @@ -51,6 +53,76 @@ struct elfinfo static void free_elfinfo (void *); +/* Locate the segments in ABFD. */ + +static struct symfile_segment_data * +elf_symfile_segments (bfd *abfd) +{ + Elf_Internal_Phdr *phdrs, **segments; + long phdrs_size; + int num_phdrs, num_segments, num_sections, i; + asection *sect; + struct symfile_segment_data *data; + + phdrs_size = bfd_get_elf_phdr_upper_bound (abfd); + if (phdrs_size == -1) + return NULL; + + phdrs = alloca (phdrs_size); + num_phdrs = bfd_get_elf_phdrs (abfd, phdrs); + if (num_phdrs == -1) + return NULL; + + num_segments = 0; + segments = alloca (sizeof (Elf_Internal_Phdr *) * num_phdrs); + for (i = 0; i < num_phdrs; i++) + if (phdrs[i].p_type == PT_LOAD) + segments[num_segments++] = &phdrs[i]; + + if (num_segments == 0) + return NULL; + + data = XZALLOC (struct symfile_segment_data); + data->num_segments = num_segments; + data->segment_bases = XCALLOC (num_segments, CORE_ADDR); + data->segment_sizes = XCALLOC (num_segments, CORE_ADDR); + + for (i = 0; i < num_segments; i++) + { + data->segment_bases[i] = segments[i]->p_vaddr; + data->segment_sizes[i] = segments[i]->p_memsz; + } + + num_sections = bfd_count_sections (abfd); + data->segment_info = XCALLOC (num_sections, int); + + for (i = 0, sect = abfd->sections; sect != NULL; i++, sect = sect->next) + { + int j; + CORE_ADDR vma; + + if ((bfd_get_section_flags (abfd, sect) & SEC_ALLOC) == 0) + continue; + + vma = bfd_get_section_vma (abfd, sect); + + for (j = 0; j < num_segments; j++) + if (segments[j]->p_memsz > 0 + && vma >= segments[j]->p_vaddr + && vma < segments[j]->p_vaddr + segments[j]->p_memsz) + { + data->segment_info[i] = j + 1; + break; + } + + if (bfd_get_section_size (sect) > 0 && j == num_segments) + warning (_("Loadable segment \"%s\" outside of ELF segments"), + bfd_section_name (abfd, sect)); + } + + return data; +} + /* We are called once per section from elf_symfile_read. We need to examine each section we are passed, check to see if it is something we are interested in processing, and @@ -741,6 +813,8 @@ static struct sym_fns elf_sym_fns = elf_symfile_read, /* sym_read: read a symbol file into symtab */ elf_symfile_finish, /* sym_finish: finished with file, cleanup */ default_symfile_offsets, /* sym_offsets: Translate ext. to int. relocation */ + elf_symfile_segments, /* sym_segments: Get segment information from + a file. */ NULL /* next: pointer to next struct sym_fns */ };