2007-09-23 Jan Kratochvil * elfcode.h (NAME(_bfd_elf,bfd_from_remote_memory)): New variables X_SHDR_SHSTRTAB and I_SHDR_SHSTRTAB. Fixed the CONTENTS_SIZE trimming check for its aligned size between the last segment and still before the section header end. Added variables check to cover also the section header string table. --- gdb-7.4.50.20120120-orig/bfd/elfcode.h 2012-02-29 09:17:08.000000000 +0100 +++ gdb-7.4.50.20120120/bfd/elfcode.h 2012-02-29 10:23:03.000000000 +0100 @@ -1621,6 +1621,8 @@ NAME(_bfd_elf,bfd_from_remote_memory) Elf_Internal_Ehdr i_ehdr; /* Elf file header, internal form */ Elf_External_Phdr *x_phdrs; Elf_Internal_Phdr *i_phdrs, *last_phdr; + Elf_External_Shdr *x_shdrs; + Elf_Internal_Shdr *i_shdrs; bfd *nbfd; struct bfd_in_memory *bim; int contents_size; @@ -1740,24 +1742,46 @@ NAME(_bfd_elf,bfd_from_remote_memory) /* Trim the last segment so we don't bother with zeros in the last page that are off the end of the file. However, if the extra bit in that - page includes the section headers, keep them. */ - if ((bfd_vma) contents_size > last_phdr->p_offset + last_phdr->p_filesz - && (bfd_vma) contents_size >= (i_ehdr.e_shoff - + i_ehdr.e_shnum * i_ehdr.e_shentsize)) + page includes the section headers os the section header string table, + keep them. */ + if ((bfd_vma) contents_size > last_phdr->p_offset + last_phdr->p_filesz) + contents_size = last_phdr->p_offset + last_phdr->p_filesz; + + if ((bfd_vma) contents_size < i_ehdr.e_shoff + + i_ehdr.e_shnum * i_ehdr.e_shentsize) + contents_size = i_ehdr.e_shoff + i_ehdr.e_shnum * i_ehdr.e_shentsize; + + /* Verify also all the sections fit into CONTENTS_SIZE. */ + + x_shdrs = bfd_malloc (i_ehdr.e_shnum * (sizeof *x_shdrs + sizeof *i_shdrs)); + if (x_shdrs == NULL) { - contents_size = last_phdr->p_offset + last_phdr->p_filesz; - if ((bfd_vma) contents_size < (i_ehdr.e_shoff - + i_ehdr.e_shnum * i_ehdr.e_shentsize)) - contents_size = i_ehdr.e_shoff + i_ehdr.e_shnum * i_ehdr.e_shentsize; + free (x_phdrs); + bfd_set_error (bfd_error_no_memory); + return NULL; } + err = target_read_memory (ehdr_vma + i_ehdr.e_shoff, (bfd_byte *) x_shdrs, + i_ehdr.e_shnum * sizeof *x_shdrs); + if (err) + i_shdrs = NULL; else - contents_size = last_phdr->p_offset + last_phdr->p_filesz; + { + i_shdrs = (Elf_Internal_Shdr *) &x_shdrs[i_ehdr.e_shnum]; + for (i = 0; i < i_ehdr.e_shnum; ++i) + { + elf_swap_shdr_in (templ, &x_shdrs[i], &i_shdrs[i]); + + if ((bfd_vma) contents_size < i_shdrs[i].sh_offset + i_shdrs[i].sh_size) + contents_size = i_shdrs[i].sh_offset + i_shdrs[i].sh_size; + } + } /* Now we know the size of the whole image we want read in. */ contents = (bfd_byte *) bfd_zmalloc (contents_size); if (contents == NULL) { free (x_phdrs); + free (x_shdrs); bfd_set_error (bfd_error_no_memory); return NULL; } @@ -1776,6 +1800,7 @@ NAME(_bfd_elf,bfd_from_remote_memory) if (err) { free (x_phdrs); + free (x_shdrs); free (contents); bfd_set_error (bfd_error_system_call); errno = err; @@ -1784,10 +1809,32 @@ NAME(_bfd_elf,bfd_from_remote_memory) } free (x_phdrs); - /* If the segments visible in memory didn't include the section headers, + if (i_shdrs) + { + memcpy (contents + i_ehdr.e_shoff, x_shdrs, + i_ehdr.e_shnum * sizeof *x_shdrs); + + for (i = 0; i < i_ehdr.e_shnum; ++i) + { + bfd_vma start = i_shdrs[i].sh_offset; + bfd_vma end = i_shdrs[i].sh_offset + i_shdrs[i].sh_size; + + if (end > (bfd_vma) contents_size) + end = contents_size; + err = target_read_memory (ehdr_vma + start, contents + start, + end - start); + if (err) + { + i_shdrs = NULL; + break; + } + } + } + free (x_shdrs); + + /* If the segments readable in memory didn't include the section headers, then clear them from the file header. */ - if ((bfd_vma) contents_size < (i_ehdr.e_shoff - + i_ehdr.e_shnum * i_ehdr.e_shentsize)) + if (i_shdrs == NULL) { memset (&x_ehdr.e_shoff, 0, sizeof x_ehdr.e_shoff); memset (&x_ehdr.e_shnum, 0, sizeof x_ehdr.e_shnum);