bfd/
authorH.J. Lu <hjl.tools@gmail.com>
Fri, 10 Feb 2006 15:04:19 +0000 (15:04 +0000)
committerH.J. Lu <hjl.tools@gmail.com>
Fri, 10 Feb 2006 15:04:19 +0000 (15:04 +0000)
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.

binutils/

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.

include/elf/

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.

bfd/ChangeLog
bfd/elf.c
binutils/ChangeLog
binutils/readelf.c
include/elf/ChangeLog
include/elf/internal.h

index c943726..6ba2531 100644 (file)
@@ -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,
index 53ed0ed..59dd56f 100644 (file)
--- 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
index 982523a..90257f8 100644 (file)
@@ -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.
index a10dc41..208b6d4 100644 (file)
@@ -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));
            }
 
index fca9b33..bd14181 100644 (file)
@@ -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 ...
index 7e13d54..e4eba7d 100644 (file)
@@ -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 */