* elf-bfd.h (elf_backend_emit_relocs): Change prototype to return
[deliverable/binutils-gdb.git] / bfd / elf.c
index ea712fb50a1f27b2924a2552f03ce5744707f4a2..c3339f93b7a66bd96635a513a60f20b44be276eb 100644 (file)
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -2,25 +2,24 @@
    Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002
    Free Software Foundation, Inc.
 
-This file is part of BFD, the Binary File Descriptor library.
+   This file is part of BFD, the Binary File Descriptor library.
 
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 2 of the License, or
+   (at your option) any later version.
 
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
 
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  */
 
-/*
-
-SECTION
+/*  SECTION
+    
        ELF backends
 
        BFD support for ELF formats is being worked on.
@@ -29,8 +28,7 @@ SECTION
 
        Documentation of the internals of the support code still needs
        to be written.  The code is changing quickly enough that we
-       haven't bothered yet.
- */
+       haven't bothered yet.  */
 
 /* For sparc64-cross-sparc32.  */
 #define _SYSCALL32
@@ -654,27 +652,44 @@ _bfd_elf_make_section_from_shdr (abfd, hdr, name)
                 offset plus size lies within the segment's memory
                 span and, if the section is loaded, the extent of the
                 loaded data lies within the extent of the segment.  
-                If the p_paddr field is not set, we don't alter the 
-                LMA.  */
+
+                Note - we used to check the p_paddr field as well, and
+                refuse to set the LMA if it was 0.  This is wrong
+                though, as a perfectly valid initialised segment can
+                have a p_paddr of zero.  Some architectures, eg ARM,
+                place special significance on the address 0 and
+                executables need to be able to have a segment which
+                covers this address.  */
              if (phdr->p_type == PT_LOAD
-                 && phdr->p_paddr
                  && (bfd_vma) hdr->sh_offset >= phdr->p_offset
                  && (hdr->sh_offset + hdr->sh_size
                      <= phdr->p_offset + phdr->p_memsz)
                  && ((flags & SEC_LOAD) == 0
-                     || (phdr->p_offset + phdr->p_filesz
-                         >= hdr->sh_offset + hdr->sh_size)))
+                     || (hdr->sh_offset + hdr->sh_size
+                         <= phdr->p_offset + phdr->p_filesz)))
                {
-                 /* We used to do a relative adjustment here, but
-                    that doesn't work if the segment is packed with
-                    code from multiple VMAs.  Instead we calculate
-                    the LMA absoultely, based on the LMA of the
-                    segment (it is assumed that the segment will
-                    contain sections with contiguous LMAs, even if
-                    the VMAs are not).  */
-                 newsect->lma = phdr->p_paddr
-                   + hdr->sh_offset - phdr->p_offset;
-                 break;
+                 if ((flags & SEC_LOAD) == 0)
+                   newsect->lma = (phdr->p_paddr
+                                   + hdr->sh_addr - phdr->p_vaddr);
+                 else
+                   /* We used to use the same adjustment for SEC_LOAD
+                      sections, but that doesn't work if the segment
+                      is packed with code from multiple VMAs.
+                      Instead we calculate the section LMA based on
+                      the segment LMA.  It is assumed that the
+                      segment will contain sections with contiguous
+                      LMAs, even if the VMAs are not.  */
+                   newsect->lma = (phdr->p_paddr
+                                   + hdr->sh_offset - phdr->p_offset);
+
+                 /* With contiguous segments, we can't tell from file
+                    offsets whether a section with zero size should
+                    be placed at the end of one segment or the
+                    beginning of the next.  Decide based on vaddr.  */
+                 if (hdr->sh_addr >= phdr->p_vaddr
+                     && (hdr->sh_addr + hdr->sh_size
+                         <= phdr->p_vaddr + phdr->p_memsz))
+                   break;
                }
            }
        }
@@ -799,6 +814,19 @@ _bfd_elf_merge_sections (abfd, info)
                         merge_sections_remove_hook);
   return true;
 }
+
+void
+_bfd_elf_link_just_syms (sec, info)
+     asection *sec;
+     struct bfd_link_info *info;
+{
+  sec->output_section = bfd_abs_section_ptr;
+  sec->output_offset = sec->vma;
+  if (!is_elf_hash_table (info))
+    return;
+
+  elf_section_data (sec)->sec_info_type = ELF_INFO_TYPE_JUST_SYMS;
+}
 \f
 /* Copy the program header and other data from one object module to
    another.  */
@@ -1345,13 +1373,13 @@ _bfd_elf_link_hash_table_create (abfd)
   struct elf_link_hash_table *ret;
   bfd_size_type amt = sizeof (struct elf_link_hash_table);
 
-  ret = (struct elf_link_hash_table *) bfd_alloc (abfd, amt);
+  ret = (struct elf_link_hash_table *) bfd_malloc (amt);
   if (ret == (struct elf_link_hash_table *) NULL)
     return NULL;
 
   if (! _bfd_elf_link_hash_table_init (ret, abfd, _bfd_elf_link_hash_newfunc))
     {
-      bfd_release (abfd, ret);
+      free (ret);
       return NULL;
     }
 
@@ -1560,6 +1588,9 @@ bfd_section_from_shdr (abfd, shindex)
     case SHT_NOBITS:   /* .bss section.  */
     case SHT_HASH:     /* .hash section.  */
     case SHT_NOTE:     /* .note section.  */
+    case SHT_INIT_ARRAY:       /* .init_array section.  */
+    case SHT_FINI_ARRAY:       /* .fini_array section.  */
+    case SHT_PREINIT_ARRAY:    /* .preinit_array section.  */
       return _bfd_elf_make_section_from_shdr (abfd, hdr, name);
 
     case SHT_SYMTAB:           /* A symbol table */
@@ -2174,6 +2205,12 @@ elf_fake_sections (abfd, asect, failedptrarg)
       this_hdr->sh_type = SHT_REL;
       this_hdr->sh_entsize = bed->s->sizeof_rel;
     }
+  else if (strcmp (asect->name, ".init_array") == 0)
+    this_hdr->sh_type = SHT_INIT_ARRAY;
+  else if (strcmp (asect->name, ".fini_array") == 0)
+    this_hdr->sh_type = SHT_FINI_ARRAY;
+  else if (strcmp (asect->name, ".preinit_array") == 0)
+    this_hdr->sh_type = SHT_PREINIT_ARRAY;
   else if (strncmp (asect->name, ".note", 5) == 0)
     this_hdr->sh_type = SHT_NOTE;
   else if (strncmp (asect->name, ".stab", 5) == 0
@@ -2216,7 +2253,8 @@ elf_fake_sections (abfd, asect, failedptrarg)
       this_hdr->sh_entsize = 4;
     }
   else if ((asect->flags & SEC_ALLOC) != 0
-          && ((asect->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0))
+          && (((asect->flags & (SEC_LOAD | SEC_HAS_CONTENTS)) == 0)
+              || (asect->flags & SEC_NEVER_LOAD) != 0))
     this_hdr->sh_type = SHT_NOBITS;
   else
     this_hdr->sh_type = SHT_PROGBITS;
@@ -3856,7 +3894,6 @@ prep_headers (abfd)
   Elf_Internal_Ehdr *i_ehdrp;  /* Elf file header, internal form */
   Elf_Internal_Phdr *i_phdrp = 0; /* Program header table, internal form */
   Elf_Internal_Shdr **i_shdrp; /* Section header table, internal form */
-  int count;
   struct elf_strtab_hash *shstrtab;
   struct elf_backend_data *bed = get_elf_backend_data (abfd);
 
@@ -3879,12 +3916,6 @@ prep_headers (abfd)
     bfd_big_endian (abfd) ? ELFDATA2MSB : ELFDATA2LSB;
   i_ehdrp->e_ident[EI_VERSION] = bed->s->ev_current;
 
-  i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_NONE;
-  i_ehdrp->e_ident[EI_ABIVERSION] = 0;
-
-  for (count = EI_PAD; count < EI_NIDENT; count++)
-    i_ehdrp->e_ident[count] = 0;
-
   if ((abfd->flags & DYNAMIC) != 0)
     i_ehdrp->e_type = ET_DYN;
   else if ((abfd->flags & EXEC_P) != 0)
@@ -4150,7 +4181,7 @@ _bfd_elf_symbol_from_bfd_symbol (abfd, asym_ptr_ptr)
 #if DEBUG & 4
   {
     fprintf (stderr,
-            _("elf_symbol_from_bfd_symbol 0x%.8lx, name = %s, sym num = %d, flags = 0x%.8lx%s\n"),
+            "elf_symbol_from_bfd_symbol 0x%.8lx, name = %s, sym num = %d, flags = 0x%.8lx%s\n",
             (long) asym_ptr, asym_ptr->name, idx, flags,
             elf_symbol_flags (flags));
     fflush (stderr);
@@ -5097,7 +5128,9 @@ _bfd_elf_get_symtab_upper_bound (abfd)
   Elf_Internal_Shdr *hdr = &elf_tdata (abfd)->symtab_hdr;
 
   symcount = hdr->sh_size / get_elf_backend_data (abfd)->s->sizeof_sym;
-  symtab_size = (symcount - 1 + 1) * (sizeof (asymbol *));
+  symtab_size = (symcount + 1) * (sizeof (asymbol *));
+  if (symcount > 0)
+    symtab_size -= sizeof (asymbol *);
 
   return symtab_size;
 }
@@ -5117,7 +5150,9 @@ _bfd_elf_get_dynamic_symtab_upper_bound (abfd)
     }
 
   symcount = hdr->sh_size / get_elf_backend_data (abfd)->s->sizeof_sym;
-  symtab_size = (symcount - 1 + 1) * (sizeof (asymbol *));
+  symtab_size = (symcount + 1) * (sizeof (asymbol *));
+  if (symcount > 0)
+    symtab_size -= sizeof (asymbol *);
 
   return symtab_size;
 }
@@ -6150,6 +6185,8 @@ elfcore_grok_psinfo (abfd, note)
 #endif /* defined (HAVE_PRPSINFO_T) || defined (HAVE_PSINFO_T) */
 
 #if defined (HAVE_PSTATUS_T)
+static boolean elfcore_grok_pstatus PARAMS ((bfd *, Elf_Internal_Note *));
+
 static boolean
 elfcore_grok_pstatus (abfd, note)
      bfd *abfd;
@@ -6187,6 +6224,8 @@ elfcore_grok_pstatus (abfd, note)
 #endif /* defined (HAVE_PSTATUS_T) */
 
 #if defined (HAVE_LWPSTATUS_T)
+static boolean elfcore_grok_lwpstatus PARAMS ((bfd *, Elf_Internal_Note *));
+
 static boolean
 elfcore_grok_lwpstatus (abfd, note)
      bfd *abfd;
@@ -6282,7 +6321,7 @@ elfcore_grok_win32pstatus (abfd, note)
   if (note->descsz < sizeof (pstatus))
     return true;
 
-  memcpy (&pstatus, note->descdata, note->descsz);
+  memcpy (&pstatus, note->descdata, sizeof (pstatus));
 
   switch (pstatus.data_type)
     {
@@ -6417,7 +6456,7 @@ elfcore_netbsd_get_lwpid (note, lwpidp)
   cp = strchr (note->namedata, '@');
   if (cp != NULL)
     {
-      *lwpidp = atoi(cp);
+      *lwpidp = atoi(cp + 1);
       return true;
     }
   return false;
@@ -6600,6 +6639,38 @@ elfcore_write_prstatus (abfd, buf, bufsiz, pid, cursig, gregs)
 }
 #endif /* HAVE_PRSTATUS_T */
 
+#if defined (HAVE_LWPSTATUS_T)
+char *
+elfcore_write_lwpstatus (abfd, buf, bufsiz, pid, cursig, gregs)
+     bfd *abfd;
+     char *buf;
+     int *bufsiz;
+     long pid;
+     int cursig;
+     void *gregs;
+{
+  lwpstatus_t lwpstat;
+  char *note_name = "CORE";
+
+  memset (&lwpstat, 0, sizeof (lwpstat));
+  lwpstat.pr_lwpid  = pid >> 16;
+  lwpstat.pr_cursig = cursig;
+#if defined (HAVE_LWPSTATUS_T_PR_REG)
+  memcpy (lwpstat.pr_reg, gregs, sizeof (lwpstat.pr_reg));
+#elif defined (HAVE_LWPSTATUS_T_PR_CONTEXT)
+#if !defined(gregs)
+  memcpy (lwpstat.pr_context.uc_mcontext.gregs,
+         gregs, sizeof (lwpstat.pr_context.uc_mcontext.gregs));
+#else
+  memcpy (lwpstat.pr_context.uc_mcontext.__gregs,
+         gregs, sizeof (lwpstat.pr_context.uc_mcontext.__gregs));
+#endif
+#endif
+  return elfcore_write_note (abfd, buf, bufsiz, note_name, 
+                            NT_LWPSTATUS, &lwpstat, sizeof (lwpstat));
+}
+#endif /* HAVE_LWPSTATUS_T */
+
 #if defined (HAVE_PSTATUS_T)
 char *
 elfcore_write_pstatus (abfd, buf, bufsiz, pid, cursig, gregs)
@@ -6613,11 +6684,11 @@ elfcore_write_pstatus (abfd, buf, bufsiz, pid, cursig, gregs)
   pstatus_t pstat;
   char *note_name = "CORE";
 
-  memset (&pstat, 0, sizeof (prstat));
-  pstat.pr_pid = pid;
-  memcpy (pstat.pr_reg, gregs, sizeof (pstat.pr_reg));
-  return elfcore_write_note (abfd, buf, bufsiz, 
-                            note_name, NT_PSTATUS, &pstat, sizeof (pstat));
+  memset (&pstat, 0, sizeof (pstat));
+  pstat.pr_pid = pid & 0xffff;
+  buf = elfcore_write_note (abfd, buf, bufsiz, note_name, 
+                           NT_PSTATUS, &pstat, sizeof (pstat));
+  return buf;
 }
 #endif /* HAVE_PSTATUS_T */
 
This page took 0.034207 seconds and 4 git commands to generate.