2000-08-29 Michael Snyder <msnyder@seadog.cygnus.com>
[deliverable/binutils-gdb.git] / bfd / elf.c
index a52d7933cd9296ed9eb2c91f188cf82c484a0da3..567be3639ecd2649070508e1557a6ca85316aa01 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -31,10 +31,8 @@ SECTION
        haven't bothered yet.
  */
 
-#ifdef __sparcv9
-#define _SYSCALL32     /* For Sparc64-cross-32 */
-#endif
-
+/* For sparc64-cross-sparc32.  */
+#define _SYSCALL32
 #include "bfd.h"
 #include "sysdep.h"
 #include "bfdlink.h"
@@ -657,13 +655,40 @@ _bfd_elf_print_private_bfd_data (abfd, farg)
            case DT_DEBUG: name = "DEBUG"; break;
            case DT_TEXTREL: name = "TEXTREL"; break;
            case DT_JMPREL: name = "JMPREL"; break;
-           case DT_AUXILIARY: name = "AUXILIARY"; stringp = true; break;
-           case DT_FILTER: name = "FILTER"; stringp = true; break;
+           case DT_BIND_NOW: name = "BIND_NOW"; break;
+           case DT_INIT_ARRAY: name = "INIT_ARRAY"; break;
+           case DT_FINI_ARRAY: name = "FINI_ARRAY"; break;
+           case DT_INIT_ARRAYSZ: name = "INIT_ARRAYSZ"; break;
+           case DT_FINI_ARRAYSZ: name = "FINI_ARRAYSZ"; break;
+           case DT_RUNPATH: name = "RUNPATH"; stringp = true; break;
+           case DT_FLAGS: name = "FLAGS"; break;
+           case DT_PREINIT_ARRAY: name = "PREINIT_ARRAY"; break;
+           case DT_PREINIT_ARRAYSZ: name = "PREINIT_ARRAYSZ"; break;
+           case DT_CHECKSUM: name = "CHECKSUM"; break;
+           case DT_PLTPADSZ: name = "PLTPADSZ"; break;
+           case DT_MOVEENT: name = "MOVEENT"; break;
+           case DT_MOVESZ: name = "MOVESZ"; break;
+           case DT_FEATURE: name = "FEATURE"; break;
+           case DT_POSFLAG_1: name = "POSFLAG_1"; break;
+           case DT_SYMINSZ: name = "SYMINSZ"; break;
+           case DT_SYMINENT: name = "SYMINENT"; break;
+           case DT_CONFIG: name = "CONFIG"; stringp = true; break;
+           case DT_DEPAUDIT: name = "DEPAUDIT"; stringp = true; break;
+           case DT_AUDIT: name = "AUDIT"; stringp = true; break;
+           case DT_PLTPAD: name = "PLTPAD"; break;
+           case DT_MOVETAB: name = "MOVETAB"; break;
+           case DT_SYMINFO: name = "SYMINFO"; break;
+           case DT_RELACOUNT: name = "RELACOUNT"; break;
+           case DT_RELCOUNT: name = "RELCOUNT"; break;
+           case DT_FLAGS_1: name = "FLAGS_1"; break;
            case DT_VERSYM: name = "VERSYM"; break;
            case DT_VERDEF: name = "VERDEF"; break;
            case DT_VERDEFNUM: name = "VERDEFNUM"; break;
            case DT_VERNEED: name = "VERNEED"; break;
            case DT_VERNEEDNUM: name = "VERNEEDNUM"; break;
+           case DT_AUXILIARY: name = "AUXILIARY"; stringp = true; break;
+           case DT_USED: name = "USED"; break;
+           case DT_FILTER: name = "FILTER"; stringp = true; break;
            }
 
          fprintf (f, "  %-11s ", name);
@@ -775,7 +800,7 @@ bfd_elf_print_symbol (abfd, filep, symbol, how)
 
        if (name == NULL)
          {
-           name = symbol->name;  
+           name = symbol->name;
            bfd_print_symbol_vandf ((PTR) file, symbol);
          }
 
@@ -954,7 +979,7 @@ _bfd_elf_link_hash_copy_indirect (dir, ind)
 }
 
 void
-_bfd_elf_link_hash_hide_symbol(info, h)
+_bfd_elf_link_hash_hide_symbol (info, h)
      struct bfd_link_info *info ATTRIBUTE_UNUSED;
      struct elf_link_hash_entry *h;
 {
@@ -980,6 +1005,7 @@ _bfd_elf_link_hash_table_init (table, abfd, newfunc)
   table->dynstr = NULL;
   table->bucketcount = 0;
   table->needed = NULL;
+  table->runpath = NULL;
   table->hgot = NULL;
   table->stab_info = NULL;
   table->dynlocal = NULL;
@@ -1023,6 +1049,16 @@ bfd_elf_set_dt_needed_name (abfd, name)
     elf_dt_name (abfd) = name;
 }
 
+void
+bfd_elf_set_dt_needed_soname (abfd, name)
+     bfd *abfd;
+     const char *name;
+{
+  if (bfd_get_flavour (abfd) == bfd_target_elf_flavour
+      && bfd_get_format (abfd) == bfd_object)
+    elf_dt_soname (abfd) = name;
+}
+
 /* Get the list of DT_NEEDED entries for a link.  This is a hook for
    the linker ELF emulation code.  */
 
@@ -1036,6 +1072,19 @@ bfd_elf_get_needed_list (abfd, info)
   return elf_hash_table (info)->needed;
 }
 
+/* Get the list of DT_RPATH/DT_RUNPATH entries for a link.  This is a
+   hook for the linker ELF emulation code.  */
+
+struct bfd_link_needed_list *
+bfd_elf_get_runpath_list (abfd, info)
+     bfd *abfd ATTRIBUTE_UNUSED;
+     struct bfd_link_info *info;
+{
+  if (info->hash->creator->flavour != bfd_target_elf_flavour)
+    return NULL;
+  return elf_hash_table (info)->runpath;
+}
+
 /* Get the name actually used for a dynamic object for a link.  This
    is the SONAME entry if there is one.  Otherwise, it is the string
    passed to bfd_elf_set_dt_needed_name, or it is the filename.  */
@@ -1333,8 +1382,10 @@ bfd_section_from_shdr (abfd, shindex)
        /* If this reloc section does not use the main symbol table we
           don't treat it as a reloc section.  BFD can't adequately
           represent such a section, so at least for now, we don't
-          try.  We just present it as a normal section.  */
-       if (hdr->sh_link != elf_onesymtab (abfd))
+          try.  We just present it as a normal section.  We also 
+          can't use it as a reloc section if it points to the null
+          section. */
+       if (hdr->sh_link != elf_onesymtab (abfd) || hdr->sh_info == SHN_UNDEF)
          return _bfd_elf_make_section_from_shdr (abfd, hdr, name);
 
        if (! bfd_section_from_shdr (abfd, hdr->sh_info))
@@ -1759,22 +1810,6 @@ elf_fake_sections (abfd, asect, failedptrarg)
     *failedptr = true;
 }
 
-/* Get elf arch size (32 / 64).
-   Returns -1 if not elf.  */
-
-int
-bfd_elf_get_arch_size (abfd)
-     bfd *abfd;
-{
-  if (abfd->xvec->flavour != bfd_target_elf_flavour)
-    {
-      bfd_set_error (bfd_error_wrong_format);
-      return -1;
-    }
-
-  return (get_elf_backend_data (abfd))->s->arch_size;
-}
-
 /* Assign all ELF section numbers.  The dummy first section is handled here
    too.  The link/info pointers for the standard section types are filled
    in here too, while we're at it.  */
@@ -1921,7 +1956,7 @@ assign_section_numbers (abfd)
 
                  /* This is a .stab section.  */
                  elf_section_data (s)->this_hdr.sh_entsize =
-                   4 + 2 * bfd_elf_get_arch_size (abfd) / 8;
+                   4 + 2 * bfd_get_arch_size (abfd) / 8;
                }
            }
          break;
@@ -3251,7 +3286,7 @@ prep_headers (abfd)
       i_ehdrp->e_machine = EM_NONE;
       break;
     case bfd_arch_sparc:
-      if (bfd_elf_get_arch_size (abfd) == 64)
+      if (bfd_get_arch_size (abfd) == 64)
        i_ehdrp->e_machine = EM_SPARCV9;
       else
        i_ehdrp->e_machine = EM_SPARC;
@@ -3265,6 +3300,12 @@ prep_headers (abfd)
     case bfd_arch_ia64:
       i_ehdrp->e_machine = EM_IA_64;
       break;
+    case bfd_arch_m68hc11:
+      i_ehdrp->e_machine = EM_68HC11;
+      break;
+    case bfd_arch_m68hc12:
+      i_ehdrp->e_machine = EM_68HC12;
+      break;
     case bfd_arch_m68k:
       i_ehdrp->e_machine = EM_68K;
       break;
@@ -3332,6 +3373,9 @@ prep_headers (abfd)
     case bfd_arch_pj:
       i_ehdrp->e_machine = EM_PJ;
       break;
+    case bfd_arch_cris:
+      i_ehdrp->e_machine = EM_CRIS;
+      break;
       /* also note that EM_M32, AT&T WE32100 is unknown to bfd */
     default:
       i_ehdrp->e_machine = EM_NONE;
@@ -3579,16 +3623,20 @@ copy_private_bfd_data (ibfd, obfd)
      bfd *ibfd;
      bfd *obfd;
 {
-  Elf_Internal_Ehdr *iehdr;
-  struct elf_segment_map *mfirst;
-  struct elf_segment_map **pm;
-  struct elf_segment_map *m;
-  Elf_Internal_Phdr *p;
-  unsigned int i;
-  unsigned int num_segments;
-  boolean phdr_included = false;
-
-  if (bfd_get_flavour (ibfd) != bfd_target_elf_flavour
+  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;
+  asection *                section;
+  unsigned int              i;
+  unsigned int              num_segments;
+  boolean                   phdr_included = false;
+  bfd_vma                   maxpagesize;
+  struct elf_segment_map *  phdr_adjust_seg = NULL;
+  unsigned int              phdr_adjust_num = 0;
+
+  if (   bfd_get_flavour (ibfd) != bfd_target_elf_flavour
       || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
     return true;
 
@@ -3597,119 +3645,212 @@ copy_private_bfd_data (ibfd, obfd)
 
   iehdr = elf_elfheader (ibfd);
 
-  mfirst = NULL;
-  pm = &mfirst;
+  map_first = NULL;
+  pointer_to_map = & map_first;
 
   num_segments = elf_elfheader (ibfd)->e_phnum;
-
-#define IS_CONTAINED_BY(addr, len, bottom, phdr)                       \
-         ((addr) >= (bottom)                                           \
-          && (   ((addr) + (len)) <= ((bottom) + (phdr)->p_memsz)      \
-              || ((addr) + (len)) <= ((bottom) + (phdr)->p_filesz)))
+  maxpagesize = get_elf_backend_data (obfd)->maxpagesize;
+
+  /* Returns the end address of the segment + 1.  */
+#define SEGMENT_END(segment, start)                    \
+  (start + (segment->p_memsz > segment->p_filesz       \
+   ? segment->p_memsz : segment->p_filesz))
+
+  /* Returns true if the given section is contained within
+     the given segment.  VMA addresses are compared.  */
+#define IS_CONTAINED_BY_VMA(section, segment)          \
+  (section->vma >= segment->p_vaddr                    \
+   && (section->vma + section->_raw_size)              \
+   <= (SEGMENT_END (segment, segment->p_vaddr)))
+    
+  /* Returns true if the given section is contained within
+     the given segment.  LMA addresses are compared.  */
+#define IS_CONTAINED_BY_LMA(section, segment, base)    \
+    (section->lma >= base                              \
+     && (section->lma + section->_raw_size)            \
+     <= SEGMENT_END (segment, base))
 
   /* Special case: corefile "NOTE" section containing regs, prpsinfo etc. */
-
-#define IS_COREFILE_NOTE(p, s)                                          \
-           (p->p_type == PT_NOTE                                       \
-            && bfd_get_format (ibfd) == bfd_core                       \
-            && s->vma == 0 && s->lma == 0                              \
-            && (bfd_vma) s->filepos >= p->p_offset                     \
-            && (bfd_vma) s->filepos + s->_raw_size                     \
+#define IS_COREFILE_NOTE(p, s)                          \
+           (p->p_type == PT_NOTE                       \
+            && bfd_get_format (ibfd) == bfd_core       \
+            && s->vma == 0 && s->lma == 0              \
+            && (bfd_vma) s->filepos >= p->p_offset     \
+            && (bfd_vma) s->filepos + s->_raw_size     \
             <= p->p_offset + p->p_filesz)
 
   /* The complicated case when p_vaddr is 0 is to handle the Solaris
      linker, which generates a PT_INTERP section with p_vaddr and
      p_memsz set to 0.  */
-
-#define IS_SOLARIS_PT_INTERP(p, s)                                     \
-           (p->p_vaddr == 0                                            \
-            && p->p_filesz > 0                                         \
-            && (s->flags & SEC_HAS_CONTENTS) != 0                      \
-            && s->_raw_size > 0                                        \
-            && (bfd_vma) s->filepos >= p->p_offset                     \
-            && ((bfd_vma) s->filepos + s->_raw_size                    \
+#define IS_SOLARIS_PT_INTERP(p, s)                     \
+           (   p->p_vaddr == 0                         \
+            && p->p_filesz > 0                         \
+            && (s->flags & SEC_HAS_CONTENTS) != 0      \
+            && s->_raw_size > 0                        \
+            && (bfd_vma) s->filepos >= p->p_offset     \
+            && ((bfd_vma) s->filepos + s->_raw_size    \
                     <= p->p_offset + p->p_filesz))
 
+  /* Decide if the given section should be included in the given segment.
+     A section will be included if:
+       1. It is within the address space of the segment,
+       2. It is an allocated segment,
+       3. There is an output section associated with it,
+       4. The section has not already been allocated to a previous segment.  */
+#define INCLUDE_SECTION_IN_SEGMENT(section, segment)   \
+  ((((IS_CONTAINED_BY_VMA (section, segment)           \
+      || IS_SOLARIS_PT_INTERP (segment, section))      \
+     && (section->flags & SEC_ALLOC) != 0)             \
+    || IS_COREFILE_NOTE (segment, section))            \
+   && section->output_section != NULL                  \
+   && section->segment_mark == false)
+
+  /* Returns true iff seg1 starts after the end of seg2.  */
+#define SEGMENT_AFTER_SEGMENT(seg1, seg2)              \
+    (seg1->p_vaddr >= SEGMENT_END (seg2, seg2->p_vaddr))
+
+  /* Returns true iff seg1 and seg2 overlap.  */
+#define SEGMENT_OVERLAPS(seg1, seg2)                   \
+  (!(SEGMENT_AFTER_SEGMENT (seg1, seg2) || SEGMENT_AFTER_SEGMENT (seg2, seg1)))
+
+  /* Initialise the segment mark field.  */
+  for (section = ibfd->sections; section != NULL; section = section->next)
+    section->segment_mark = false;
+
   /* Scan through the segments specified in the program header
-     of the input BFD.  */
-  for (i = 0, p = elf_tdata (ibfd)->phdr; i < num_segments; i++, p++)
+     of the input BFD.  For this first scan we look for overlaps
+     in the loadable segments.  These can be created by wierd
+     parameters to objcopy.  */
+  for (i = 0, segment = elf_tdata (ibfd)->phdr;
+       i < num_segments;
+       i ++, segment ++)
     {
-      unsigned int csecs;
-      asection *s;
-      asection **sections;
-      asection *os;
-      unsigned int isec;
-      bfd_vma matching_lma;
-      bfd_vma suggested_lma;
       unsigned int j;
+      Elf_Internal_Phdr * segment2;
 
-      /* For each section in the input BFD, decide if it should be
-        included in the current segment.  A section will be included
-        if it is within the address space of the segment, and it is
-        an allocated segment, and there is an output section
-        associated with it.  */
-      csecs = 0;
-      for (s = ibfd->sections; s != NULL; s = s->next)
-       if (s->output_section != NULL)
-         {
-           if ((IS_CONTAINED_BY (s->vma, s->_raw_size, p->p_vaddr, p)
-                || IS_SOLARIS_PT_INTERP (p, s))
-               && (s->flags & SEC_ALLOC) != 0)
-             ++csecs;
-           else if (IS_COREFILE_NOTE (p, s))
-             ++csecs;
-         }
+      if (segment->p_type != PT_LOAD)
+       continue;
+      
+      /* Determine if this segment overlaps any previous segments.  */
+      for (j = 0, segment2 = elf_tdata (ibfd)->phdr; j < i; j ++, segment2 ++)
+       {
+         bfd_signed_vma extra_length;
+         
+         if (segment2->p_type != PT_LOAD
+             || ! SEGMENT_OVERLAPS (segment, segment2))
+           continue;
+         
+         /* Merge the two segments together.  */
+         if (segment2->p_vaddr < segment->p_vaddr)
+           {
+             /* Extend SEGMENT2 to include SEGMENT and then delete SEGMENT.  */
+             extra_length =
+               SEGMENT_END (segment, segment->p_vaddr)
+               - SEGMENT_END (segment2, segment2->p_vaddr);
+             
+             if (extra_length > 0)
+               {
+                 segment2->p_memsz  += extra_length;
+                 segment2->p_filesz += extra_length;
+               }
+             
+             segment->p_type = PT_NULL;
+             
+             /* Since we have deleted P we must restart the outer loop.  */
+             i = 0;
+             segment = elf_tdata (ibfd)->phdr;
+             break;
+           }
+         else
+           {
+             /* Extend SEGMENT to include SEGMENT2 and then delete SEGMENT2.  */
+             extra_length =
+               SEGMENT_END (segment2, segment2->p_vaddr)
+               - SEGMENT_END (segment, segment->p_vaddr);
+             
+             if (extra_length > 0)
+               {
+                 segment->p_memsz  += extra_length;
+                 segment->p_filesz += extra_length;
+               }
+             
+             segment2->p_type = PT_NULL;
+           }
+       }
+    }
+  
+  /* The second scan attempts to assign sections to segments.  */
+  for (i = 0, segment = elf_tdata (ibfd)->phdr;
+       i < num_segments;
+       i ++, segment ++)
+    {
+      unsigned int  section_count;
+      asection **   sections;
+      asection *    output_section;
+      unsigned int  isec;
+      bfd_vma       matching_lma;
+      bfd_vma       suggested_lma;
+      unsigned int  j;
+
+      if (segment->p_type == PT_NULL)
+       continue;
+      
+      /* Compute how many sections might be placed into this segment.  */
+      section_count = 0;
+      for (section = ibfd->sections; section != NULL; section = section->next)
+       if (INCLUDE_SECTION_IN_SEGMENT (section, segment))
+         ++ section_count;
 
       /* Allocate a segment map big enough to contain all of the
         sections we have selected.  */
-      m = ((struct elf_segment_map *)
+      map = ((struct elf_segment_map *)
           bfd_alloc (obfd,
                      (sizeof (struct elf_segment_map)
-                      + ((size_t) csecs - 1) * sizeof (asection *))));
-      if (m == NULL)
+                      + ((size_t) section_count - 1) * sizeof (asection *))));
+      if (map == NULL)
        return false;
 
       /* Initialise the fields of the segment map.  Default to
         using the physical address of the segment in the input BFD.  */
-      m->next          = NULL;
-      m->p_type        = p->p_type;
-      m->p_flags       = p->p_flags;
-      m->p_flags_valid = 1;
-      m->p_paddr       = p->p_paddr;
-      m->p_paddr_valid = 1;
+      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.  */
-      m->includes_filehdr = (p->p_offset == 0
-                            && p->p_filesz >= iehdr->e_ehsize);
+      map->includes_filehdr = (segment->p_offset == 0
+                              && segment->p_filesz >= iehdr->e_ehsize);
 
-      m->includes_phdrs = 0;
+      map->includes_phdrs = 0;
 
-      if (! phdr_included || p->p_type != PT_LOAD)
+      if (! phdr_included || segment->p_type != PT_LOAD)
        {
-         m->includes_phdrs =
-           (p->p_offset <= (bfd_vma) iehdr->e_phoff
-            && (p->p_offset + p->p_filesz
+         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 (p->p_type == PT_LOAD && m->includes_phdrs)
+         
+         if (segment->p_type == PT_LOAD && map->includes_phdrs)
            phdr_included = true;
        }
 
-      if (csecs == 0)
+      if (section_count == 0)
        {
          /* Special segments, such as the PT_PHDR segment, may contain
             no sections, but ordinary, loadable segments should contain
             something.  */
-
-         if (p->p_type == PT_LOAD)
+         if (segment->p_type == PT_LOAD)
              _bfd_error_handler
                (_("%s: warning: Empty loadable segment detected\n"),
                 bfd_get_filename (ibfd));
 
-         m->count = 0;
-         *pm = m;
-         pm = &m->next;
+         map->count = 0;
+         * pointer_to_map = map;
+         pointer_to_map = & map->next;
 
          continue;
        }
@@ -3742,7 +3883,8 @@ copy_private_bfd_data (ibfd, obfd)
         pointers that we are interested in.  As these sections get assigned
         to a segment, they are removed from this array.  */
 
-      sections = (asection **) bfd_malloc (sizeof (asection *) * csecs);
+      sections = (asection **) bfd_malloc
+       (sizeof (asection *) * section_count);
       if (sections == NULL)
        return false;
 
@@ -3752,70 +3894,67 @@ copy_private_bfd_data (ibfd, obfd)
         case, where the sections have not been moved, this means that
         we have completely filled the segment, and there is nothing
         more to do.  */
-
       isec = 0;
       matching_lma = 0;
       suggested_lma = 0;
 
-      for (j = 0, s = ibfd->sections; s != NULL; s = s->next)
+      for (j = 0, section = ibfd->sections;
+          section != NULL;
+          section = section->next)
        {
-         os = s->output_section;
-
-         if ((((IS_CONTAINED_BY (s->vma, s->_raw_size, p->p_vaddr, p)
-                || IS_SOLARIS_PT_INTERP (p, s))
-               && (s->flags & SEC_ALLOC) != 0)
-              || IS_COREFILE_NOTE (p, s))
-             && os != NULL)
+         if (INCLUDE_SECTION_IN_SEGMENT (section, segment))
            {
-             sections[j++] = s;
+             output_section = section->output_section;
+
+             sections[j ++] = section;
 
              /* The Solaris native linker always sets p_paddr to 0.
                 We try to catch that case here, and set it to the
                 correct value.  */
-             if (p->p_paddr == 0
-                 && p->p_vaddr != 0
+             if (segment->p_paddr == 0
+                 && segment->p_vaddr != 0
                  && isec == 0
-                 && os->lma != 0
-                 && (os->vma == (p->p_vaddr
-                                 + (m->includes_filehdr
-                                    ? iehdr->e_ehsize
-                                    : 0)
-                                 + (m->includes_phdrs
-                                    ? iehdr->e_phnum * iehdr->e_phentsize
-                                    : 0))))
-               m->p_paddr = p->p_vaddr;
+                 && output_section->lma != 0
+                 && (output_section->vma == (segment->p_vaddr
+                                             + (map->includes_filehdr
+                                                ? iehdr->e_ehsize
+                                                : 0)
+                                             + (map->includes_phdrs
+                                                ? iehdr->e_phnum * iehdr->e_phentsize
+                                                : 0))))
+               map->p_paddr = segment->p_vaddr;
 
              /* Match up the physical address of the segment with the
                 LMA address of the output section.  */
-             if (IS_CONTAINED_BY (os->lma, os->_raw_size, m->p_paddr, p)
-                 || IS_COREFILE_NOTE (p, s))
+             if (IS_CONTAINED_BY_LMA (output_section, segment, map->p_paddr)
+                 || IS_COREFILE_NOTE (segment, section))
                {
                  if (matching_lma == 0)
-                   matching_lma = os->lma;
+                   matching_lma = output_section->lma;
 
                  /* We assume that if the section fits within the segment
-                    that it does not overlap any other section within that
+                    then it does not overlap any other section within that
                     segment.  */
-                 m->sections[isec++] = os;
+                 map->sections[isec ++] = output_section;
                }
              else if (suggested_lma == 0)
-               suggested_lma = os->lma;
+               suggested_lma = output_section->lma;
            }
        }
 
-      BFD_ASSERT (j == csecs);
+      BFD_ASSERT (j == section_count);
 
       /* Step Two: Adjust the physical address of the current segment,
         if necessary.  */
-      if (isec == csecs)
+      if (isec == section_count)
        {
          /* All of the sections fitted within the segment as currently
             specified.  This is the default case.  Add the segment to
             the list of built segments and carry on to process the next
             program header in the input BFD.  */
-         m->count = csecs;
-         *pm = m;
-         pm = &m->next;
+         map->count = section_count;
+         * pointer_to_map = map;
+         pointer_to_map = & map->next;
 
          free (sections);
          continue;
@@ -3827,25 +3966,33 @@ copy_private_bfd_data (ibfd, obfd)
              /* At least one section fits inside the current segment.
                 Keep it, but modify its physical address to match the
                 LMA of the first section that fitted.  */
-
-             m->p_paddr = matching_lma;
+             map->p_paddr = matching_lma;
            }
          else
            {
              /* None of the sections fitted inside the current segment.
                 Change the current segment's physical address to match
                 the LMA of the first section.  */
-
-             m->p_paddr = suggested_lma;
+             map->p_paddr = suggested_lma;
            }
 
-         /* Offset the segment physical address from the lma to allow
-            for space taken up by elf headers.  */
-         if (m->includes_filehdr)
-           m->p_paddr -= iehdr->e_ehsize;
+         /* Offset the segment physical address from the lma
+            to allow for space taken up by elf headers.  */
+         if (map->includes_filehdr)
+           map->p_paddr -= iehdr->e_ehsize;
 
-         if (m->includes_phdrs)
-           m->p_paddr -= iehdr->e_phnum * iehdr->e_phentsize;
+         if (map->includes_phdrs)
+           {
+             map->p_paddr -= iehdr->e_phnum * iehdr->e_phentsize;
+
+             /* iehdr->e_phnum is just an estimate of the number
+                of program headers that we will need.  Make a note
+                here of the number we used and the segment we chose
+                to hold these headers, so that we can adjust the
+                offset when we know the correct value.  */
+             phdr_adjust_num = iehdr->e_phnum;
+             phdr_adjust_seg = map;
+           }
        }
 
       /* Step Three: Loop over the sections again, this time assigning
@@ -3858,97 +4005,99 @@ copy_private_bfd_data (ibfd, obfd)
       isec = 0;
       do
        {
-         m->count = 0;
+         map->count = 0;
          suggested_lma = 0;
 
          /* Fill the current segment with sections that fit.  */
-         for (j = 0; j < csecs; j++)
+         for (j = 0; j < section_count; j++)
            {
-             s = sections[j];
+             section = sections[j];
 
-             if (s == NULL)
+             if (section == NULL)
                continue;
 
-             os = s->output_section;
+             output_section = section->output_section;
 
-             if (IS_CONTAINED_BY (os->lma, os->_raw_size, m->p_paddr, p)
-                 || IS_COREFILE_NOTE (p, s))
+             BFD_ASSERT (output_section != NULL);
+             
+             if (IS_CONTAINED_BY_LMA (output_section, segment, map->p_paddr)
+                 || IS_COREFILE_NOTE (segment, section))
                {
-                 if (m->count == 0)
+                 if (map->count == 0)
                    {
                      /* If the first section in a segment does not start at
-                        the beginning of the segment, then something is wrong.  */
-                     if (os->lma != (m->p_paddr
-                                     + (m->includes_filehdr
-                                        ? iehdr->e_ehsize : 0)
-                                     + (m->includes_phdrs
-                                        ? iehdr->e_phnum * iehdr->e_phentsize
-                                        : 0)))
+                        the beginning of the segment, then something is
+                        wrong.  */
+                     if (output_section->lma !=
+                         (map->p_paddr
+                          + (map->includes_filehdr ? iehdr->e_ehsize : 0)
+                          + (map->includes_phdrs
+                             ? iehdr->e_phnum * iehdr->e_phentsize
+                             : 0)))
                        abort ();
                    }
                  else
                    {
                      asection * prev_sec;
-                     bfd_vma maxpagesize;
 
-                     prev_sec = m->sections[m->count - 1];
-                     maxpagesize = get_elf_backend_data (obfd)->maxpagesize;
+                     prev_sec = map->sections[map->count - 1];
 
                      /* If the gap between the end of the previous section
-                        and the start of this section is more than maxpagesize
-                        then we need to start a new segment.  */
-                     if (BFD_ALIGN (prev_sec->lma + prev_sec->_raw_size, maxpagesize)
-                         < BFD_ALIGN (os->lma, maxpagesize))
+                        and the start of this section is more than
+                        maxpagesize then we need to start a new segment.  */
+                     if ((BFD_ALIGN (prev_sec->lma + prev_sec->_raw_size, maxpagesize)
+                         < BFD_ALIGN (output_section->lma, maxpagesize))
+                         || ((prev_sec->lma + prev_sec->_raw_size) > output_section->lma))
                        {
                          if (suggested_lma == 0)
-                           suggested_lma = os->lma;
+                           suggested_lma = output_section->lma;
 
                          continue;
                        }
                    }
 
-                 m->sections[m->count++] = os;
+                 map->sections[map->count++] = output_section;
                  ++isec;
                  sections[j] = NULL;
+                 section->segment_mark = true;
                }
              else if (suggested_lma == 0)
-               suggested_lma = os->lma;
+               suggested_lma = output_section->lma;
            }
 
-         BFD_ASSERT (m->count > 0);
+         BFD_ASSERT (map->count > 0);
 
          /* Add the current segment to the list of built segments.  */
-         *pm = m;
-         pm = &m->next;
+         * pointer_to_map = map;
+         pointer_to_map = & map->next;
 
-         if (isec < csecs)
+         if (isec < section_count)
            {
              /* We still have not allocated all of the sections to
                 segments.  Create a new segment here, initialise it
                 and carry on looping.  */
-
-             m = ((struct elf_segment_map *)
-                  bfd_alloc (obfd,
-                             (sizeof (struct elf_segment_map)
-                              + ((size_t) csecs - 1) * sizeof (asection *))));
-             if (m == NULL)
+             map = ((struct elf_segment_map *)
+                    bfd_alloc (obfd,
+                               (sizeof (struct elf_segment_map)
+                                + ((size_t) section_count - 1)
+                                * sizeof (asection *))));
+             if (map == NULL)
                return false;
 
              /* Initialise the fields of the segment map.  Set the physical
                 physical address to the LMA of the first section that has
                 not yet been assigned.  */
-
-             m->next             = NULL;
-             m->p_type           = p->p_type;
-             m->p_flags          = p->p_flags;
-             m->p_flags_valid    = 1;
-             m->p_paddr          = suggested_lma;
-             m->p_paddr_valid    = 1;
-             m->includes_filehdr = 0;
-             m->includes_phdrs   = 0;
+             map->next             = NULL;
+             map->p_type           = segment->p_type;
+             map->p_flags          = segment->p_flags;
+             map->p_flags_valid    = 1;
+             map->p_paddr          = suggested_lma;
+             map->p_paddr_valid    = 1;
+             map->includes_filehdr = 0;
+             map->includes_phdrs   = 0;
            }
        }
-      while (isec < csecs);
+      while (isec < section_count);
 
       free (sections);
     }
@@ -3957,44 +4106,64 @@ copy_private_bfd_data (ibfd, obfd)
      p_paddr fields are zero.  When we try to objcopy or strip such a
      file, we get confused.  Check for this case, and if we find it
      reset the p_paddr_valid fields.  */
-  for (m = mfirst; m != NULL; m = m->next)
-    if (m->p_paddr != 0)
+  for (map = map_first; map != NULL; map = map->next)
+    if (map->p_paddr != 0)
       break;
-  if (m == NULL)
+  if (map == NULL)
     {
-      for (m = mfirst; m != NULL; m = m->next)
-       m->p_paddr_valid = 0;
+      for (map = map_first; map != NULL; map = map->next)
+       map->p_paddr_valid = 0;
     }
 
-  elf_tdata (obfd)->segment_map = mfirst;
+  elf_tdata (obfd)->segment_map = map_first;
 
+  /* If we had to estimate the number of program headers that were
+     going to be needed, then check our estimate know and adjust
+     the offset if necessary.  */
+  if (phdr_adjust_seg != NULL)
+    {
+      unsigned int count;
+      
+      for (count = 0, map = map_first; map != NULL; map = map->next)
+       count ++;
+
+      if (count > phdr_adjust_num)
+       phdr_adjust_seg->p_paddr
+         -= (count - phdr_adjust_num) * iehdr->e_phentsize;
+    }
+  
 #if 0
-  /* Final Step: Sort the segments into ascending order of physical address. */
-  if (mfirst != NULL)
+  /* Final Step: Sort the segments into ascending order of physical address.  */
+  if (map_first != NULL)
     {
-      struct elf_segment_map* prev;
+      struct elf_segment_map * prev;
 
-      prev = mfirst;
-      for (m = mfirst->next; m != NULL; prev = m, m = m->next)
+      prev = map_first;
+      for (map = map_first->next; map != NULL; prev = map, map = map->next)
        {
-         /* Yes I know - its a bubble sort....*/
-         if (m->next != NULL && (m->next->p_paddr < m->p_paddr))
+         /* Yes I know - its a bubble sort....  */
+         if (map->next != NULL && (map->next->p_paddr < map->p_paddr))
            {
-             /* swap m and m->next */
-             prev->next = m->next;
-             m->next = m->next->next;
-             prev->next->next = m;
+             /* Swap map and map->next.  */
+             prev->next = map->next;
+             map->next = map->next->next;
+             prev->next->next = map;
 
-             /* restart loop. */
-             m = mfirst;
+             /* Restart loop.  */
+             map = map_first;
            }
        }
     }
 #endif
 
-#undef IS_CONTAINED_BY
-#undef IS_SOLARIS_PT_INTERP
+#undef SEGMENT_END
+#undef IS_CONTAINED_BY_VMA
+#undef IS_CONTAINED_BY_LMA
 #undef IS_COREFILE_NOTE
+#undef IS_SOLARIS_PT_INTERP
+#undef INCLUDE_SECTION_IN_SEGMENT
+#undef SEGMENT_AFTER_SEGMENT
+#undef SEGMENT_OVERLAPS
   return true;
 }
 
@@ -5129,12 +5298,14 @@ elfcore_grok_prstatus (abfd, note)
   char* name;
   asection* sect;
   int raw_size;
+  int offset;
 
   if (note->descsz == sizeof (prstatus_t))
     {
       prstatus_t prstat;
 
       raw_size = sizeof (prstat.pr_reg);
+      offset   = offsetof (prstatus_t, pr_reg);
       memcpy (&prstat, note->descdata, sizeof (prstat));
 
       elf_tdata (abfd)->core_signal = prstat.pr_cursig;
@@ -5150,13 +5321,14 @@ elfcore_grok_prstatus (abfd, note)
       elf_tdata (abfd)->core_lwpid = prstat.pr_who;
 #endif
     }
-#if defined (__sparcv9)
+#if defined (HAVE_PRSTATUS32_T)
   else if (note->descsz == sizeof (prstatus32_t))
     {
       /* 64-bit host, 32-bit corefile */
       prstatus32_t prstat;
 
       raw_size = sizeof (prstat.pr_reg);
+      offset   = offsetof (prstatus32_t, pr_reg);
       memcpy (&prstat, note->descdata, sizeof (prstat));
 
       elf_tdata (abfd)->core_signal = prstat.pr_cursig;
@@ -5168,11 +5340,11 @@ elfcore_grok_prstatus (abfd, note)
         pr_who doesn't exist on:
         linux 2.[01]
         */
-#if defined (HAVE_PRSTATUS_T_PR_WHO)
+#if defined (HAVE_PRSTATUS32_T_PR_WHO)
       elf_tdata (abfd)->core_lwpid = prstat.pr_who;
 #endif
     }
-#endif /* __sparcv9 */
+#endif /* HAVE_PRSTATUS32_T */
   else
     {
       /* Fail - we don't know how to handle any other
@@ -5192,18 +5364,8 @@ elfcore_grok_prstatus (abfd, note)
   if (sect == NULL)
     return false;
 
-  if (note->descsz == sizeof (prstatus_t))
-    {
-      sect->_raw_size = raw_size;
-      sect->filepos = note->descpos + offsetof (prstatus_t, pr_reg);
-    }
-#if defined (__sparcv9)
-  else if (note->descsz == sizeof (prstatus32_t))
-    {
-      sect->_raw_size = raw_size;
-      sect->filepos = note->descpos + offsetof (prstatus32_t, pr_reg);
-    }
-#endif
+  sect->_raw_size = raw_size;
+  sect->filepos = note->descpos + offset;
 
   sect->flags = SEC_HAS_CONTENTS;
   sect->alignment_power = 2;
@@ -5283,14 +5445,14 @@ elfcore_grok_prxfpreg (abfd, note)
 
 #if defined (HAVE_PRPSINFO_T)
 typedef prpsinfo_t   elfcore_psinfo_t;
-#if defined (__sparcv9)        /* Sparc64 cross Sparc32 */
+#if defined (HAVE_PRPSINFO32_T)                /* Sparc64 cross Sparc32 */
 typedef prpsinfo32_t elfcore_psinfo32_t;
 #endif
 #endif
 
 #if defined (HAVE_PSINFO_T)
 typedef psinfo_t   elfcore_psinfo_t;
-#if defined (__sparcv9)        /* Sparc64 cross Sparc32 */
+#if defined (HAVE_PSINFO32_T)          /* Sparc64 cross Sparc32 */
 typedef psinfo32_t elfcore_psinfo32_t;
 #endif
 #endif
@@ -5336,7 +5498,7 @@ elfcore_grok_psinfo (abfd, note)
     {
       elfcore_psinfo_t psinfo;
 
-      memcpy (&psinfo, note->descdata, note->descsz);
+      memcpy (&psinfo, note->descdata, sizeof (psinfo));
 
       elf_tdata (abfd)->core_program
        = elfcore_strndup (abfd, psinfo.pr_fname, sizeof (psinfo.pr_fname));
@@ -5344,13 +5506,13 @@ elfcore_grok_psinfo (abfd, note)
       elf_tdata (abfd)->core_command
        = elfcore_strndup (abfd, psinfo.pr_psargs, sizeof (psinfo.pr_psargs));
     }
-#if defined (__sparcv9)
+#if defined (HAVE_PRPSINFO32_T) || defined (HAVE_PSINFO32_T)
   else if (note->descsz == sizeof (elfcore_psinfo32_t))
     {
       /* 64-bit host, 32-bit corefile */
       elfcore_psinfo32_t psinfo;
 
-      memcpy (&psinfo, note->descdata, note->descsz);
+      memcpy (&psinfo, note->descdata, sizeof (psinfo));
 
       elf_tdata (abfd)->core_program
        = elfcore_strndup (abfd, psinfo.pr_fname, sizeof (psinfo.pr_fname));
@@ -5398,7 +5560,7 @@ elfcore_grok_pstatus (abfd, note)
 
       elf_tdata (abfd)->core_pid = pstat.pr_pid;
     }
-#if defined (__sparcv9)
+#if defined (HAVE_PSTATUS32_T)
   else if (note->descsz == sizeof (pstatus32_t))
     {
       /* 64-bit host, 32-bit corefile */
This page took 0.056724 seconds and 4 git commands to generate.