aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--bfd/ChangeLog10
-rw-r--r--bfd/elf.c191
-rw-r--r--binutils/ChangeLog6
-rw-r--r--binutils/readelf.c19
-rw-r--r--include/elf/ChangeLog6
-rw-r--r--include/elf/internal.h25
6 files changed, 229 insertions, 28 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index c943726..6ba2531 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,4 +1,12 @@
-2006-01-26 Nathan Sidwell <nathan@codesourcery.com>
+2006-02-10 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR binutils/2258
+ * elf.c (copy_private_bfd_data): Renamed to ...
+ (rewrite_elf_program_header): This.
+ (copy_elf_program_header): New function.
+ (copy_private_bfd_data): Likewise.
+
+2006-02-07 Nathan Sidwell <nathan@codesourcery.com>
* archures.c (bfd_mach_mcf5200, bfd_mach_mcf5206e,
bfd_mach_mcf5307, bfd_mach_mcf5407, bfd_mach_mcf528x,
diff --git a/bfd/elf.c b/bfd/elf.c
index 53ed0ed..59dd56f 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -5045,10 +5045,10 @@ _bfd_elf_symbol_from_bfd_symbol (bfd *abfd, asymbol **asym_ptr_ptr)
return idx;
}
-/* Copy private BFD data. This copies any program header information. */
+/* Rewrite program header information. */
static bfd_boolean
-copy_private_bfd_data (bfd *ibfd, bfd *obfd)
+rewrite_elf_program_header (bfd *ibfd, bfd *obfd)
{
Elf_Internal_Ehdr *iehdr;
struct elf_segment_map *map;
@@ -5064,13 +5064,6 @@ copy_private_bfd_data (bfd *ibfd, bfd *obfd)
unsigned int phdr_adjust_num = 0;
const struct elf_backend_data *bed;
- if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
- || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
- return TRUE;
-
- if (elf_tdata (ibfd)->phdr == NULL)
- return TRUE;
-
bed = get_elf_backend_data (ibfd);
iehdr = elf_elfheader (ibfd);
@@ -5630,6 +5623,186 @@ copy_private_bfd_data (bfd *ibfd, bfd *obfd)
return TRUE;
}
+/* Copy ELF program header information. */
+
+static bfd_boolean
+copy_elf_program_header (bfd *ibfd, bfd *obfd)
+{
+ Elf_Internal_Ehdr *iehdr;
+ struct elf_segment_map *map;
+ struct elf_segment_map *map_first;
+ struct elf_segment_map **pointer_to_map;
+ Elf_Internal_Phdr *segment;
+ unsigned int i;
+ unsigned int num_segments;
+ bfd_boolean phdr_included = FALSE;
+
+ iehdr = elf_elfheader (ibfd);
+
+ map_first = NULL;
+ pointer_to_map = &map_first;
+
+ num_segments = elf_elfheader (ibfd)->e_phnum;
+ for (i = 0, segment = elf_tdata (ibfd)->phdr;
+ i < num_segments;
+ i++, segment++)
+ {
+ asection *section;
+ unsigned int section_count;
+ bfd_size_type amt;
+ Elf_Internal_Shdr *this_hdr;
+
+ /* FIXME: Do we need to copy PT_NULL segment? */
+ if (segment->p_type == PT_NULL)
+ continue;
+
+ /* Compute how many sections are in this segment. */
+ for (section = ibfd->sections, section_count = 0;
+ section != NULL;
+ section = section->next)
+ {
+ this_hdr = &(elf_section_data(section)->this_hdr);
+ if (ELF_IS_SECTION_IN_SEGMENT_FILE (this_hdr, segment))
+ section_count++;
+ }
+
+ /* Allocate a segment map big enough to contain
+ all of the sections we have selected. */
+ amt = sizeof (struct elf_segment_map);
+ if (section_count != 0)
+ amt += ((bfd_size_type) section_count - 1) * sizeof (asection *);
+ map = bfd_alloc (obfd, amt);
+ if (map == NULL)
+ return FALSE;
+
+ /* Initialize the fields of the output segment map with the
+ input segment. */
+ map->next = NULL;
+ map->p_type = segment->p_type;
+ map->p_flags = segment->p_flags;
+ map->p_flags_valid = 1;
+ map->p_paddr = segment->p_paddr;
+ map->p_paddr_valid = 1;
+
+ /* Determine if this segment contains the ELF file header
+ and if it contains the program headers themselves. */
+ map->includes_filehdr = (segment->p_offset == 0
+ && segment->p_filesz >= iehdr->e_ehsize);
+
+ map->includes_phdrs = 0;
+ if (! phdr_included || segment->p_type != PT_LOAD)
+ {
+ map->includes_phdrs =
+ (segment->p_offset <= (bfd_vma) iehdr->e_phoff
+ && (segment->p_offset + segment->p_filesz
+ >= ((bfd_vma) iehdr->e_phoff
+ + iehdr->e_phnum * iehdr->e_phentsize)));
+
+ if (segment->p_type == PT_LOAD && map->includes_phdrs)
+ phdr_included = TRUE;
+ }
+
+ if (section_count != 0)
+ {
+ unsigned int isec = 0;
+
+ for (section = ibfd->sections;
+ section != NULL;
+ section = section->next)
+ {
+ this_hdr = &(elf_section_data(section)->this_hdr);
+ if (ELF_IS_SECTION_IN_SEGMENT_FILE (this_hdr, segment))
+ map->sections[isec++] = section->output_section;
+ }
+ }
+
+ map->count = section_count;
+ *pointer_to_map = map;
+ pointer_to_map = &map->next;
+ }
+
+ elf_tdata (obfd)->segment_map = map_first;
+ return TRUE;
+}
+
+/* Copy private BFD data. This copies or rewrites ELF program header
+ information. */
+
+static bfd_boolean
+copy_private_bfd_data (bfd *ibfd, bfd *obfd)
+{
+ Elf_Internal_Phdr *segment;
+
+ if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
+ || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
+ return TRUE;
+
+ if (elf_tdata (ibfd)->phdr == NULL)
+ return TRUE;
+
+ if (ibfd->xvec == obfd->xvec)
+ {
+ /* Check if any sections in the input BFD covered by ELF program
+ header are changed. */
+ asection *section, *osec;
+ unsigned int i, num_segments;
+ Elf_Internal_Shdr *this_hdr;
+
+ /* Initialize the segment mark field. */
+ for (section = obfd->sections; section != NULL;
+ section = section->next)
+ section->segment_mark = FALSE;
+
+ num_segments = elf_elfheader (ibfd)->e_phnum;
+ for (i = 0, segment = elf_tdata (ibfd)->phdr;
+ i < num_segments;
+ i++, segment++)
+ {
+ for (section = ibfd->sections;
+ section != NULL; section = section->next)
+ {
+ /* We mark the output section so that we know it comes
+ from the input BFD. */
+ osec = section->output_section;
+ if (osec)
+ osec->segment_mark = TRUE;
+
+ /* Check if this section is covered by the segment. */
+ this_hdr = &(elf_section_data(section)->this_hdr);
+ if (ELF_IS_SECTION_IN_SEGMENT_FILE (this_hdr, segment))
+ {
+ /* FIXME: Check if its output section is changed or
+ removed. What else do we need to check? */
+ if (osec == NULL
+ || section->flags != osec->flags
+ || section->lma != osec->lma
+ || section->vma != osec->vma
+ || section->size != osec->size
+ || section->rawsize != osec->rawsize
+ || section->alignment_power != osec->alignment_power)
+ goto rewrite;
+ }
+ }
+ }
+
+ /* Check to see if any output section doesn't come from the
+ input BFD. */
+ for (section = obfd->sections; section != NULL;
+ section = section->next)
+ {
+ if (section->segment_mark == FALSE)
+ goto rewrite;
+ else
+ section->segment_mark = FALSE;
+ }
+
+ return copy_elf_program_header (ibfd, obfd);
+ }
+
+rewrite:
+ return rewrite_elf_program_header (ibfd, obfd);
+}
+
/* Initialize private output section information from input section. */
bfd_boolean
diff --git a/binutils/ChangeLog b/binutils/ChangeLog
index 982523a..90257f8 100644
--- a/binutils/ChangeLog
+++ b/binutils/ChangeLog
@@ -1,3 +1,9 @@
+2006-02-10 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR binutils/2258
+ * readelf.c (process_program_headers): Use
+ ELF_IS_SECTION_IN_SEGMENT_MEMORY.
+
2006-02-09 Eric Botcazou <ebotcazou@libertysurf.fr>
* configure.in (CHECK_DECLS): Add snprintf and vsnprintf.
diff --git a/binutils/readelf.c b/binutils/readelf.c
index a10dc41..208b6d4 100644
--- a/binutils/readelf.c
+++ b/binutils/readelf.c
@@ -3447,24 +3447,7 @@ process_program_headers (FILE *file)
for (j = 1; j < elf_header.e_shnum; j++, section++)
{
- if (section->sh_size > 0
- /* PT_TLS segment contains only SHF_TLS sections. */
- && (segment->p_type != PT_TLS
- || (section->sh_flags & SHF_TLS) != 0)
- /* Compare allocated sections by VMA, unallocated
- sections by file offset. */
- && (section->sh_flags & SHF_ALLOC
- ? (section->sh_addr >= segment->p_vaddr
- && section->sh_addr + section->sh_size
- <= segment->p_vaddr + segment->p_memsz)
- : ((bfd_vma) section->sh_offset >= segment->p_offset
- && (section->sh_offset + section->sh_size
- <= segment->p_offset + segment->p_filesz)))
- /* .tbss is special. It doesn't contribute memory space
- to normal segments. */
- && (!((section->sh_flags & SHF_TLS) != 0
- && section->sh_type == SHT_NOBITS)
- || segment->p_type == PT_TLS))
+ if (ELF_IS_SECTION_IN_SEGMENT_MEMORY(section, segment))
printf ("%s ", SECTION_NAME (section));
}
diff --git a/include/elf/ChangeLog b/include/elf/ChangeLog
index fca9b33..bd14181 100644
--- a/include/elf/ChangeLog
+++ b/include/elf/ChangeLog
@@ -1,3 +1,9 @@
+2006-02-10 H.J. Lu <hongjiu.lu@intel.com>
+
+ PR binutils/2258
+ * internal.h (ELF_IS_SECTION_IN_SEGMENT_FILE): New.
+ (ELF_IS_SECTION_IN_SEGMENT_MEMORY): Likewise.
+
2006-02-07 Nathan Sidwell <nathan@codesourcery.com>
* m68k.h (EF_CPU32, EF_M68000, EF_CFV4E): Rename to ...
diff --git a/include/elf/internal.h b/include/elf/internal.h
index 7e13d54..e4eba7d 100644
--- a/include/elf/internal.h
+++ b/include/elf/internal.h
@@ -251,4 +251,29 @@ struct elf_segment_map
asection *sections[1];
};
+/* Decide if the given sec_hdr is in the given segment in file. */
+#define ELF_IS_SECTION_IN_SEGMENT_FILE(sec_hdr, segment) \
+ (sec_hdr->sh_size > 0 \
+ /* PT_TLS segment contains only SHF_TLS sections. */ \
+ && (segment->p_type != PT_TLS \
+ || (sec_hdr->sh_flags & SHF_TLS) != 0) \
+ /* Compare allocated sec_hdrs by VMA, unallocated sec_hdrs \
+ by file offset. */ \
+ && (sec_hdr->sh_flags & SHF_ALLOC \
+ ? (sec_hdr->sh_addr >= segment->p_vaddr \
+ && sec_hdr->sh_addr + sec_hdr->sh_size \
+ <= segment->p_vaddr + segment->p_memsz) \
+ : ((bfd_vma) sec_hdr->sh_offset >= segment->p_offset \
+ && (sec_hdr->sh_offset + sec_hdr->sh_size \
+ <= segment->p_offset + segment->p_filesz))))
+
+/* Decide if the given sec_hdr is in the given segment in memory. */
+#define ELF_IS_SECTION_IN_SEGMENT_MEMORY(sec_hdr, segment) \
+ (ELF_IS_SECTION_IN_SEGMENT_FILE (sec_hdr, segment) \
+ /* .tbss is special. It doesn't contribute memory space to \
+ normal segments. */ \
+ && (!((sec_hdr->sh_flags & SHF_TLS) != 0 \
+ && sec_hdr->sh_type == SHT_NOBITS) \
+ || segment->p_type == PT_TLS))
+
#endif /* _ELF_INTERNAL_H */