| Line 1... | Line 1... | 
      
        | /* BFD back-end for HP PA-RISC ELF files.
 | /* BFD back-end for HP PA-RISC ELF files.
 | 
      
        |    Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1999, 2000, 2001,
 |    Copyright 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1999, 2000, 2001,
 | 
      
        |    2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
 |    2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
 | 
      
        |   |    Free Software Foundation, Inc.
 | 
      
        |  
 |  
 | 
      
        |    Original code by
 |    Original code by
 | 
      
        |         Center for Software Science
 |         Center for Software Science
 | 
      
        |         Department of Computer Science
 |         Department of Computer Science
 | 
      
        |         University of Utah
 |         University of Utah
 | 
      
        | Line 298... | Line 299... | 
      
        |   unsigned int has_22bit_branch:1;
 |   unsigned int has_22bit_branch:1;
 | 
      
        |  
 |  
 | 
      
        |   /* Set if we need a .plt stub to support lazy dynamic linking.  */
 |   /* Set if we need a .plt stub to support lazy dynamic linking.  */
 | 
      
        |   unsigned int need_plt_stub:1;
 |   unsigned int need_plt_stub:1;
 | 
      
        |  
 |  
 | 
      
        |   /* Small local sym to section mapping cache.  */
 |   /* Small local sym cache.  */
 | 
      
        |   struct sym_sec_cache sym_sec;
 |   struct sym_cache sym_cache;
 | 
      
        |  
 |  
 | 
      
        |   /* Data for LDM relocations.  */
 |   /* Data for LDM relocations.  */
 | 
      
        |   union
 |   union
 | 
      
        |   {
 |   {
 | 
      
        |     bfd_signed_vma refcount;
 |     bfd_signed_vma refcount;
 | 
      
        | Line 457... | Line 458... | 
      
        |   htab->multi_subspace = 0;
 |   htab->multi_subspace = 0;
 | 
      
        |   htab->has_12bit_branch = 0;
 |   htab->has_12bit_branch = 0;
 | 
      
        |   htab->has_17bit_branch = 0;
 |   htab->has_17bit_branch = 0;
 | 
      
        |   htab->has_22bit_branch = 0;
 |   htab->has_22bit_branch = 0;
 | 
      
        |   htab->need_plt_stub = 0;
 |   htab->need_plt_stub = 0;
 | 
      
        |   htab->sym_sec.abfd = NULL;
 |   htab->sym_cache.abfd = NULL;
 | 
      
        |   htab->tls_ldm_got.refcount = 0;
 |   htab->tls_ldm_got.refcount = 0;
 | 
      
        |  
 |  
 | 
      
        |   return &htab->etab.root;
 |   return &htab->etab.root;
 | 
      
        | }
 | }
 | 
      
        |  
 |  
 | 
      
        | Line 1008... | Line 1009... | 
      
        |  
 |  
 | 
      
        |   htab->splt = bfd_get_section_by_name (abfd, ".plt");
 |   htab->splt = bfd_get_section_by_name (abfd, ".plt");
 | 
      
        |   htab->srelplt = bfd_get_section_by_name (abfd, ".rela.plt");
 |   htab->srelplt = bfd_get_section_by_name (abfd, ".rela.plt");
 | 
      
        |  
 |  
 | 
      
        |   htab->sgot = bfd_get_section_by_name (abfd, ".got");
 |   htab->sgot = bfd_get_section_by_name (abfd, ".got");
 | 
      
        |   htab->srelgot = bfd_make_section_with_flags (abfd, ".rela.got",
 |   htab->srelgot = bfd_get_section_by_name (abfd, ".rela.got");
 | 
      
        |                                                (SEC_ALLOC
 |   | 
      
        |                                                 | SEC_LOAD
 |   | 
      
        |                                                 | SEC_HAS_CONTENTS
 |   | 
      
        |                                                 | SEC_IN_MEMORY
 |   | 
      
        |                                                 | SEC_LINKER_CREATED
 |   | 
      
        |                                                 | SEC_READONLY));
 |   | 
      
        |   if (htab->srelgot == NULL
 |   | 
      
        |       || ! bfd_set_section_alignment (abfd, htab->srelgot, 2))
 |   | 
      
        |     return FALSE;
 |   | 
      
        |  
 |  
 | 
      
        |   htab->sdynbss = bfd_get_section_by_name (abfd, ".dynbss");
 |   htab->sdynbss = bfd_get_section_by_name (abfd, ".dynbss");
 | 
      
        |   htab->srelbss = bfd_get_section_by_name (abfd, ".rela.bss");
 |   htab->srelbss = bfd_get_section_by_name (abfd, ".rela.bss");
 | 
      
        |  
 |  
 | 
      
        |   /* hppa-linux needs _GLOBAL_OFFSET_TABLE_ to be visible from the main
 |   /* hppa-linux needs _GLOBAL_OFFSET_TABLE_ to be visible from the main
 | 
      
        | Line 1110... | Line 1102... | 
      
        | {
 | {
 | 
      
        |   /* For now we don't support linker optimizations.  */
 |   /* For now we don't support linker optimizations.  */
 | 
      
        |   return r_type;
 |   return r_type;
 | 
      
        | }
 | }
 | 
      
        |  
 |  
 | 
      
        |   | /* Return a pointer to the local GOT, PLT and TLS reference counts
 | 
      
        |   |    for ABFD.  Returns NULL if the storage allocation fails.  */
 | 
      
        |   |  
 | 
      
        |   | static bfd_signed_vma *
 | 
      
        |   | hppa32_elf_local_refcounts (bfd *abfd)
 | 
      
        |   | {
 | 
      
        |   |   Elf_Internal_Shdr *symtab_hdr = &elf_tdata (abfd)->symtab_hdr;
 | 
      
        |   |   bfd_signed_vma *local_refcounts;
 | 
      
        |   |  
 | 
      
        |   |   local_refcounts = elf_local_got_refcounts (abfd);
 | 
      
        |   |   if (local_refcounts == NULL)
 | 
      
        |   |     {
 | 
      
        |   |       bfd_size_type size;
 | 
      
        |   |  
 | 
      
        |   |       /* Allocate space for local GOT and PLT reference
 | 
      
        |   |          counts.  Done this way to save polluting elf_obj_tdata
 | 
      
        |   |          with another target specific pointer.  */
 | 
      
        |   |       size = symtab_hdr->sh_info;
 | 
      
        |   |       size *= 2 * sizeof (bfd_signed_vma);
 | 
      
        |   |       /* Add in space to store the local GOT TLS types.  */
 | 
      
        |   |       size += symtab_hdr->sh_info;
 | 
      
        |   |       local_refcounts = bfd_zalloc (abfd, size);
 | 
      
        |   |       if (local_refcounts == NULL)
 | 
      
        |   |         return NULL;
 | 
      
        |   |       elf_local_got_refcounts (abfd) = local_refcounts;
 | 
      
        |   |       memset (hppa_elf_local_got_tls_type (abfd), GOT_UNKNOWN,
 | 
      
        |   |               symtab_hdr->sh_info);
 | 
      
        |   |     }
 | 
      
        |   |   return local_refcounts;
 | 
      
        |   | }
 | 
      
        |   |  
 | 
      
        |   |  
 | 
      
        | /* Look through the relocs for a section during the first phase, and
 | /* Look through the relocs for a section during the first phase, and
 | 
      
        |    calculate needed space in the global offset table, procedure linkage
 |    calculate needed space in the global offset table, procedure linkage
 | 
      
        |    table, and dynamic reloc sections.  At this point we haven't
 |    table, and dynamic reloc sections.  At this point we haven't
 | 
      
        |    necessarily read all the input files.  */
 |    necessarily read all the input files.  */
 | 
      
        |  
 |  
 | 
      
        | Line 1356... | Line 1380... | 
      
        |               else
 |               else
 | 
      
        |                 {
 |                 {
 | 
      
        |                   bfd_signed_vma *local_got_refcounts;
 |                   bfd_signed_vma *local_got_refcounts;
 | 
      
        |  
 |  
 | 
      
        |                   /* This is a global offset table entry for a local symbol.  */
 |                   /* This is a global offset table entry for a local symbol.  */
 | 
      
        |                   local_got_refcounts = elf_local_got_refcounts (abfd);
 |                   local_got_refcounts = hppa32_elf_local_refcounts (abfd);
 | 
      
        |                   if (local_got_refcounts == NULL)
 |   | 
      
        |                     {
 |   | 
      
        |                       bfd_size_type size;
 |   | 
      
        |  
 |   | 
      
        |                       /* Allocate space for local got offsets and local
 |   | 
      
        |                          plt offsets.  Done this way to save polluting
 |   | 
      
        |                          elf_obj_tdata with another target specific
 |   | 
      
        |                          pointer.  */
 |   | 
      
        |                       size = symtab_hdr->sh_info;
 |   | 
      
        |                       size *= 2 * sizeof (bfd_signed_vma);
 |   | 
      
        |                       /* Add in space to store the local GOT TLS types.  */
 |   | 
      
        |                       size += symtab_hdr->sh_info;
 |   | 
      
        |                       local_got_refcounts = bfd_zalloc (abfd, size);
 |   | 
      
        |                       if (local_got_refcounts == NULL)
 |                       if (local_got_refcounts == NULL)
 | 
      
        |                         return FALSE;
 |                         return FALSE;
 | 
      
        |                       elf_local_got_refcounts (abfd) = local_got_refcounts;
 |   | 
      
        |                       memset (hppa_elf_local_got_tls_type (abfd),
 |   | 
      
        |                           GOT_UNKNOWN, symtab_hdr->sh_info);
 |   | 
      
        |                     }
 |   | 
      
        |                   local_got_refcounts[r_symndx] += 1;
 |                   local_got_refcounts[r_symndx] += 1;
 | 
      
        |  
 |  
 | 
      
        |                   old_tls_type = hppa_elf_local_got_tls_type (abfd) [r_symndx];
 |                   old_tls_type = hppa_elf_local_got_tls_type (abfd) [r_symndx];
 | 
      
        |                 }
 |                 }
 | 
      
        |  
 |  
 | 
      
        | Line 1422... | Line 1429... | 
      
        |               else if (need_entry & PLT_PLABEL)
 |               else if (need_entry & PLT_PLABEL)
 | 
      
        |                 {
 |                 {
 | 
      
        |                   bfd_signed_vma *local_got_refcounts;
 |                   bfd_signed_vma *local_got_refcounts;
 | 
      
        |                   bfd_signed_vma *local_plt_refcounts;
 |                   bfd_signed_vma *local_plt_refcounts;
 | 
      
        |  
 |  
 | 
      
        |                   local_got_refcounts = elf_local_got_refcounts (abfd);
 |                   local_got_refcounts = hppa32_elf_local_refcounts (abfd);
 | 
      
        |                   if (local_got_refcounts == NULL)
 |   | 
      
        |                     {
 |   | 
      
        |                       bfd_size_type size;
 |   | 
      
        |  
 |   | 
      
        |                       /* Allocate space for local got offsets and local
 |   | 
      
        |                          plt offsets.  */
 |   | 
      
        |                       size = symtab_hdr->sh_info;
 |   | 
      
        |                       size *= 2 * sizeof (bfd_signed_vma);
 |   | 
      
        |                       /* Add in space to store the local GOT TLS types.  */
 |   | 
      
        |                       size += symtab_hdr->sh_info;
 |   | 
      
        |                       local_got_refcounts = bfd_zalloc (abfd, size);
 |   | 
      
        |                       if (local_got_refcounts == NULL)
 |                       if (local_got_refcounts == NULL)
 | 
      
        |                         return FALSE;
 |                         return FALSE;
 | 
      
        |                       elf_local_got_refcounts (abfd) = local_got_refcounts;
 |   | 
      
        |                     }
 |   | 
      
        |                   local_plt_refcounts = (local_got_refcounts
 |                   local_plt_refcounts = (local_got_refcounts
 | 
      
        |                                          + symtab_hdr->sh_info);
 |                                          + symtab_hdr->sh_info);
 | 
      
        |                   local_plt_refcounts[r_symndx] += 1;
 |                   local_plt_refcounts[r_symndx] += 1;
 | 
      
        |                 }
 |                 }
 | 
      
        |             }
 |             }
 | 
      
        | Line 1502... | Line 1496... | 
      
        |  
 |  
 | 
      
        |               /* Create a reloc section in dynobj and make room for
 |               /* Create a reloc section in dynobj and make room for
 | 
      
        |                  this reloc.  */
 |                  this reloc.  */
 | 
      
        |               if (sreloc == NULL)
 |               if (sreloc == NULL)
 | 
      
        |                 {
 |                 {
 | 
      
        |                   char *name;
 |   | 
      
        |                   bfd *dynobj;
 |   | 
      
        |  
 |   | 
      
        |                   name = (bfd_elf_string_from_elf_section
 |   | 
      
        |                           (abfd,
 |   | 
      
        |                            elf_elfheader (abfd)->e_shstrndx,
 |   | 
      
        |                            elf_section_data (sec)->rel_hdr.sh_name));
 |   | 
      
        |                   if (name == NULL)
 |   | 
      
        |                     {
 |   | 
      
        |                       (*_bfd_error_handler)
 |   | 
      
        |                         (_("Could not find relocation section for %s"),
 |   | 
      
        |                          sec->name);
 |   | 
      
        |                       bfd_set_error (bfd_error_bad_value);
 |   | 
      
        |                       return FALSE;
 |   | 
      
        |                     }
 |   | 
      
        |  
 |   | 
      
        |                   if (htab->etab.dynobj == NULL)
 |                   if (htab->etab.dynobj == NULL)
 | 
      
        |                     htab->etab.dynobj = abfd;
 |                     htab->etab.dynobj = abfd;
 | 
      
        |  
 |  
 | 
      
        |                   dynobj = htab->etab.dynobj;
 |                   sreloc = _bfd_elf_make_dynamic_reloc_section
 | 
      
        |                   sreloc = bfd_get_section_by_name (dynobj, name);
 |                     (sec, htab->etab.dynobj, 2, abfd, /*rela?*/ TRUE);
 | 
      
        |   |  
 | 
      
        |                   if (sreloc == NULL)
 |                   if (sreloc == NULL)
 | 
      
        |                     {
 |                     {
 | 
      
        |                       flagword flags;
 |                       bfd_set_error (bfd_error_bad_value);
 | 
      
        |  
 |   | 
      
        |                       flags = (SEC_HAS_CONTENTS | SEC_READONLY
 |   | 
      
        |                                | SEC_IN_MEMORY | SEC_LINKER_CREATED);
 |   | 
      
        |                       if ((sec->flags & SEC_ALLOC) != 0)
 |   | 
      
        |                         flags |= SEC_ALLOC | SEC_LOAD;
 |   | 
      
        |                       sreloc = bfd_make_section_with_flags (dynobj,
 |   | 
      
        |                                                             name,
 |   | 
      
        |                                                             flags);
 |   | 
      
        |                       if (sreloc == NULL
 |   | 
      
        |                           || !bfd_set_section_alignment (dynobj, sreloc, 2))
 |   | 
      
        |                         return FALSE;
 |                         return FALSE;
 | 
      
        |                     }
 |                     }
 | 
      
        |  
 |   | 
      
        |                   elf_section_data (sec)->sreloc = sreloc;
 |   | 
      
        |                 }
 |                 }
 | 
      
        |  
 |  
 | 
      
        |               /* If this is a global symbol, we count the number of
 |               /* If this is a global symbol, we count the number of
 | 
      
        |                  relocations we need for this symbol.  */
 |                  relocations we need for this symbol.  */
 | 
      
        |               if (hh != NULL)
 |               if (hh != NULL)
 | 
      
        | Line 1553... | Line 1520... | 
      
        |               else
 |               else
 | 
      
        |                 {
 |                 {
 | 
      
        |                   /* Track dynamic relocs needed for local syms too.
 |                   /* Track dynamic relocs needed for local syms too.
 | 
      
        |                      We really need local syms available to do this
 |                      We really need local syms available to do this
 | 
      
        |                      easily.  Oh well.  */
 |                      easily.  Oh well.  */
 | 
      
        |  
 |   | 
      
        |                   asection *sr;
 |                   asection *sr;
 | 
      
        |                   void *vpp;
 |                   void *vpp;
 | 
      
        |   |                   Elf_Internal_Sym *isym;
 | 
      
        |  
 |  
 | 
      
        |                   sr = bfd_section_from_r_symndx (abfd, &htab->sym_sec,
 |                   isym = bfd_sym_from_r_symndx (&htab->sym_cache,
 | 
      
        |                                                        sec, r_symndx);
 |                                                 abfd, r_symndx);
 | 
      
        |                   if (sr == NULL)
 |                   if (isym == NULL)
 | 
      
        |                     return FALSE;
 |                     return FALSE;
 | 
      
        |  
 |  
 | 
      
        |   |                   sr = bfd_section_from_elf_index (abfd, isym->st_shndx);
 | 
      
        |   |                   if (sr == NULL)
 | 
      
        |   |                     sr = sec;
 | 
      
        |   |  
 | 
      
        |                   vpp = &elf_section_data (sr)->local_dynrel;
 |                   vpp = &elf_section_data (sr)->local_dynrel;
 | 
      
        |                   hdh_head = (struct elf32_hppa_dyn_reloc_entry **) vpp;
 |                   hdh_head = (struct elf32_hppa_dyn_reloc_entry **) vpp;
 | 
      
        |                 }
 |                 }
 | 
      
        |  
 |  
 | 
      
        |               hdh_p = *hdh_head;
 |               hdh_p = *hdh_head;
 | 
      
        | Line 2974... | Line 2945... | 
      
        |                   if (r_indx < symtab_hdr->sh_info)
 |                   if (r_indx < symtab_hdr->sh_info)
 | 
      
        |                     {
 |                     {
 | 
      
        |                       /* It's a local symbol.  */
 |                       /* It's a local symbol.  */
 | 
      
        |                       Elf_Internal_Sym *sym;
 |                       Elf_Internal_Sym *sym;
 | 
      
        |                       Elf_Internal_Shdr *hdr;
 |                       Elf_Internal_Shdr *hdr;
 | 
      
        |   |                       unsigned int shndx;
 | 
      
        |  
 |  
 | 
      
        |                       sym = local_syms + r_indx;
 |                       sym = local_syms + r_indx;
 | 
      
        |                       hdr = elf_elfsections (input_bfd)[sym->st_shndx];
 |   | 
      
        |                       sym_sec = hdr->bfd_section;
 |   | 
      
        |                       if (ELF_ST_TYPE (sym->st_info) != STT_SECTION)
 |                       if (ELF_ST_TYPE (sym->st_info) != STT_SECTION)
 | 
      
        |                         sym_value = sym->st_value;
 |                         sym_value = sym->st_value;
 | 
      
        |   |                       shndx = sym->st_shndx;
 | 
      
        |   |                       if (shndx < elf_numsections (input_bfd))
 | 
      
        |   |                         {
 | 
      
        |   |                           hdr = elf_elfsections (input_bfd)[shndx];
 | 
      
        |   |                           sym_sec = hdr->bfd_section;
 | 
      
        |                       destination = (sym_value + irela->r_addend
 |                       destination = (sym_value + irela->r_addend
 | 
      
        |                                      + sym_sec->output_offset
 |                                      + sym_sec->output_offset
 | 
      
        |                                      + sym_sec->output_section->vma);
 |                                      + sym_sec->output_section->vma);
 | 
      
        |                     }
 |                     }
 | 
      
        |   |                     }
 | 
      
        |                   else
 |                   else
 | 
      
        |                     {
 |                     {
 | 
      
        |                       /* It's an external symbol.  */
 |                       /* It's an external symbol.  */
 | 
      
        |                       int e_indx;
 |                       int e_indx;
 | 
      
        |  
 |  
 | 
      
        | Line 3428... | Line 3404... | 
      
        |                error.  */
 |                error.  */
 | 
      
        |             (*_bfd_error_handler)
 |             (*_bfd_error_handler)
 | 
      
        |               (_("%B(%A+0x%lx): %s fixup for insn 0x%x is not supported in a non-shared link"),
 |               (_("%B(%A+0x%lx): %s fixup for insn 0x%x is not supported in a non-shared link"),
 | 
      
        |                input_bfd,
 |                input_bfd,
 | 
      
        |                input_section,
 |                input_section,
 | 
      
        |                offset,
 |                (long) offset,
 | 
      
        |                howto->name,
 |                howto->name,
 | 
      
        |                insn);
 |                insn);
 | 
      
        |         }
 |         }
 | 
      
        |       else if (orig_r_type == R_PARISC_DLTIND14F)
 |       else if (orig_r_type == R_PARISC_DLTIND14F)
 | 
      
        |         {
 |         {
 | 
      
        | Line 3592... | Line 3568... | 
      
        |     {
 |     {
 | 
      
        |       (*_bfd_error_handler)
 |       (*_bfd_error_handler)
 | 
      
        |         (_("%B(%A+0x%lx): cannot reach %s, recompile with -ffunction-sections"),
 |         (_("%B(%A+0x%lx): cannot reach %s, recompile with -ffunction-sections"),
 | 
      
        |          input_bfd,
 |          input_bfd,
 | 
      
        |          input_section,
 |          input_section,
 | 
      
        |          offset,
 |          (long) offset,
 | 
      
        |          hsh->bh_root.string);
 |          hsh->bh_root.string);
 | 
      
        |       bfd_set_error (bfd_error_bad_value);
 |       bfd_set_error (bfd_error_bad_value);
 | 
      
        |       return bfd_reloc_notsupported;
 |       return bfd_reloc_notsupported;
 | 
      
        |     }
 |     }
 | 
      
        |  
 |  
 |