sje patch for 32-bit IA-64 ELF relocs for HPUX
[deliverable/binutils-gdb.git] / bfd / elfxx-ia64.c
index 6751e4acc1da3d161cbfce045dd80bd361a351b7..481834bb4db5db9c16001271a43421d4ff3eba7a 100644 (file)
@@ -1,5 +1,5 @@
 /* IA-64 support for 64-bit ELF
-   Copyright 1998, 1999, 2000 Free Software Foundation, Inc.
+   Copyright 1998, 1999, 2000, 2001 Free Software Foundation, Inc.
    Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
 
 This file is part of BFD, the Binary File Descriptor library.
@@ -157,14 +157,26 @@ static void elfNN_ia64_info_to_howto
 static boolean elfNN_ia64_relax_section
   PARAMS((bfd *abfd, asection *sec, struct bfd_link_info *link_info,
          boolean *again));
+static boolean is_unwind_section_name
+  PARAMS ((const char *));
 static boolean elfNN_ia64_section_from_shdr
   PARAMS ((bfd *, ElfNN_Internal_Shdr *, char *));
 static boolean elfNN_ia64_fake_sections
   PARAMS ((bfd *abfd, ElfNN_Internal_Shdr *hdr, asection *sec));
+static void elfNN_ia64_final_write_processing
+  PARAMS ((bfd *abfd, boolean linker));
 static boolean elfNN_ia64_add_symbol_hook
   PARAMS ((bfd *abfd, struct bfd_link_info *info, const Elf_Internal_Sym *sym,
           const char **namep, flagword *flagsp, asection **secp,
           bfd_vma *valp));
+static boolean elfNN_ia64_aix_vec 
+  PARAMS ((const bfd_target *vec));
+static boolean elfNN_ia64_aix_add_symbol_hook
+  PARAMS ((bfd *abfd, struct bfd_link_info *info, const Elf_Internal_Sym *sym,
+          const char **namep, flagword *flagsp, asection **secp,
+          bfd_vma *valp));
+static boolean elfNN_ia64_aix_link_add_symbols
+  PARAMS ((bfd *abfd, struct bfd_link_info *info));
 static int elfNN_ia64_additional_program_headers
   PARAMS ((bfd *abfd));
 static boolean elfNN_ia64_is_local_label_name
@@ -348,6 +360,8 @@ static reloc_howto_type ia64_howto_table[] =
 
     IA64_HOWTO (R_IA64_LTOFF_FPTR22, "LTOFF_FPTR22", 0, false, true),
     IA64_HOWTO (R_IA64_LTOFF_FPTR64I, "LTOFF_FPTR64I", 0, false, true),
+    IA64_HOWTO (R_IA64_LTOFF_FPTR32MSB, "LTOFF_FPTR32MSB", 2, false, true),
+    IA64_HOWTO (R_IA64_LTOFF_FPTR32LSB, "LTOFF_FPTR32LSB", 2, false, true),
     IA64_HOWTO (R_IA64_LTOFF_FPTR64MSB, "LTOFF_FPTR64MSB", 4, false, true),
     IA64_HOWTO (R_IA64_LTOFF_FPTR64LSB, "LTOFF_FPTR64LSB", 4, false, true),
 
@@ -468,6 +482,8 @@ elfNN_ia64_reloc_type_lookup (abfd, bfd_code)
 
     case BFD_RELOC_IA64_LTOFF_FPTR22:  rtype = R_IA64_LTOFF_FPTR22; break;
     case BFD_RELOC_IA64_LTOFF_FPTR64I: rtype = R_IA64_LTOFF_FPTR64I; break;
+    case BFD_RELOC_IA64_LTOFF_FPTR32MSB: rtype = R_IA64_LTOFF_FPTR32MSB; break;
+    case BFD_RELOC_IA64_LTOFF_FPTR32LSB: rtype = R_IA64_LTOFF_FPTR32LSB; break;
     case BFD_RELOC_IA64_LTOFF_FPTR64MSB: rtype = R_IA64_LTOFF_FPTR64MSB; break;
     case BFD_RELOC_IA64_LTOFF_FPTR64LSB: rtype = R_IA64_LTOFF_FPTR64LSB; break;
 
@@ -554,6 +570,9 @@ static const bfd_byte plt_full_entry[PLT_FULL_ENTRY_SIZE] =
 };
 
 #define ELF_DYNAMIC_INTERPRETER "/usr/lib/ld.so.1"
+#define AIX_DYNAMIC_INTERPRETER "/usr/lib/ia64l64/libc.so.1"
+#define DYNAMIC_INTERPRETER(abfd) \
+  (elfNN_ia64_aix_vec (abfd->xvec) ? AIX_DYNAMIC_INTERPRETER : ELF_DYNAMIC_INTERPRETER)
 
 /* Select out of range branch fixup type.  Note that Itanium does
    not support brl, and so it gets emulated by the kernel.  */
@@ -900,6 +919,22 @@ elfNN_ia64_relax_section (abfd, sec, link_info, again)
   return false;
 }
 \f
+/* Return true if NAME is an unwind table section name.  */
+
+static inline boolean
+is_unwind_section_name (name)
+       const char *name;
+{
+  size_t len1, len2, len3;
+
+  len1 = sizeof (ELF_STRING_ia64_unwind) - 1;
+  len2 = sizeof (ELF_STRING_ia64_unwind_info) - 1;
+  len3 = sizeof (ELF_STRING_ia64_unwind_once) - 1;
+  return ((strncmp (name, ELF_STRING_ia64_unwind, len1) == 0
+          && strncmp (name, ELF_STRING_ia64_unwind_info, len2) != 0)
+         || strncmp (name, ELF_STRING_ia64_unwind_once, len3) == 0);
+}
+
 /* Handle an IA-64 specific section when reading an object file.  This
    is called when elfcode.h finds a section with an unknown type.  */
 
@@ -919,8 +954,6 @@ elfNN_ia64_section_from_shdr (abfd, hdr, name)
   switch (hdr->sh_type)
     {
     case SHT_IA_64_UNWIND:
-      if (strcmp (name, ELF_STRING_ia64_unwind) != 0)
-       return false;
       break;
 
     case SHT_IA_64_EXT:
@@ -968,8 +1001,13 @@ elfNN_ia64_fake_sections (abfd, hdr, sec)
 
   name = bfd_get_section_name (abfd, sec);
 
-  if (strcmp (name, ELF_STRING_ia64_unwind) == 0)
-    hdr->sh_type = SHT_IA_64_UNWIND;
+  if (is_unwind_section_name (name))
+    {
+      /* We don't have the sections numbered at this point, so sh_info
+        is set later, in elfNN_ia64_final_write_processing.  */
+      hdr->sh_type = SHT_IA_64_UNWIND;
+      hdr->sh_flags |= SHF_LINK_ORDER;
+    }
   else if (strcmp (name, ELF_STRING_ia64_archext) == 0)
     hdr->sh_type = SHT_IA_64_EXT;
   else if (strcmp (name, ".reloc") == 0)
@@ -999,6 +1037,70 @@ elfNN_ia64_fake_sections (abfd, hdr, sec)
   return true;
 }
 
+/* The final processing done just before writing out an IA-64 ELF
+   object file.  */
+
+static void
+elfNN_ia64_final_write_processing (abfd, linker)
+     bfd *abfd;
+     boolean linker ATTRIBUTE_UNUSED;
+{
+  Elf_Internal_Shdr *hdr;
+  const char *sname;
+  asection *text_sect, *s;
+  size_t len;
+
+  for (s = abfd->sections; s; s = s->next)
+    {
+      hdr = &elf_section_data (s)->this_hdr;
+      switch (hdr->sh_type)
+       {
+       case SHT_IA_64_UNWIND:
+         /* See comments in gas/config/tc-ia64.c:dot_endp on why we
+            have to do this.  */
+         sname = bfd_get_section_name (abfd, s);
+         len = sizeof (ELF_STRING_ia64_unwind) - 1;
+         if (sname && strncmp (sname, ELF_STRING_ia64_unwind, len) == 0)
+           {
+             sname += len;
+
+             if (sname[0] == '\0')
+               /* .IA_64.unwind -> .text */
+               text_sect = bfd_get_section_by_name (abfd, ".text");
+             else
+               /* .IA_64.unwindFOO -> FOO */
+               text_sect = bfd_get_section_by_name (abfd, sname);
+           }
+         else if (sname
+                  && (len = sizeof (ELF_STRING_ia64_unwind_once) - 1,
+                      strncmp (sname, ELF_STRING_ia64_unwind_once, len)) == 0)
+           {
+             /* .gnu.linkonce.ia64unw.FOO -> .gnu.linkonce.t.FOO */
+             size_t len2 = sizeof (".gnu.linkonce.t.") - 1;
+             char *once_name = alloca (len2 + strlen (sname) - len + 1);
+
+             memcpy (once_name, ".gnu.linkonce.t.", len2);
+             strcpy (once_name + len2, sname + len);
+             text_sect = bfd_get_section_by_name (abfd, once_name);
+           }
+         else
+           /* last resort: fall back on .text */
+           text_sect = bfd_get_section_by_name (abfd, ".text");
+
+         if (text_sect)
+           {
+             /* The IA-64 processor-specific ABI requires setting
+                sh_link to the unwind section, whereas HP-UX requires
+                sh_info to do so.  For maximum compatibility, we'll
+                set both for now... */
+             hdr->sh_link = elf_section_data (text_sect)->this_idx;
+             hdr->sh_info = elf_section_data (text_sect)->this_idx;
+           }
+         break;
+       }
+    }
+}
+
 /* Hook called by the linker routine which adds symbols from an object
    file.  We use it to put .comm items in .sbss, and not .bss.  */
 
@@ -1038,6 +1140,111 @@ elfNN_ia64_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
   return true;
 }
 
+static boolean
+elfNN_ia64_aix_vec (const bfd_target *vec)
+{
+  extern const bfd_target bfd_elfNN_ia64_aix_little_vec;
+  extern const bfd_target bfd_elfNN_ia64_aix_big_vec;
+
+  return (/**/vec == & bfd_elfNN_ia64_aix_little_vec 
+         ||  vec == & bfd_elfNN_ia64_aix_big_vec);
+}
+
+/* Hook called by the linker routine which adds symbols from an object
+   file.  We use it to handle OS-specific symbols.  */
+
+static boolean
+elfNN_ia64_aix_add_symbol_hook (abfd, info, sym, namep, flagsp, secp, valp)
+     bfd *abfd;
+     struct bfd_link_info *info;
+     const Elf_Internal_Sym *sym;
+     const char **namep;
+     flagword *flagsp;
+     asection **secp;
+     bfd_vma *valp;
+{
+  if (strcmp (*namep, "__GLOB_DATA_PTR") == 0)
+    {
+      /* Define __GLOB_DATA_PTR when it is encountered.  This is expected to
+        be a linker-defined symbol by the Aix C runtime startup code. IBM sez
+        no one else should use it b/c it is undocumented.  */
+      struct elf_link_hash_entry *h;
+
+      h = (struct elf_link_hash_entry *) bfd_link_hash_lookup (info->hash, *namep, false, false, false);
+      if (h == NULL) 
+       {
+         struct elf_backend_data *bed;
+         struct elfNN_ia64_link_hash_table *ia64_info;
+
+         bed = get_elf_backend_data (abfd);
+         ia64_info = elfNN_ia64_hash_table (info);
+         
+         if (!(_bfd_generic_link_add_one_symbol
+               (info, abfd, *namep, BSF_GLOBAL, 
+                bfd_get_section_by_name (abfd, ".bss"),
+                bed->got_symbol_offset, (const char *) NULL, false,
+                bed->collect, (struct bfd_link_hash_entry **) &h)))
+           return false;
+         
+         h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
+         h->type = STT_OBJECT;
+         
+         if (! _bfd_elf_link_record_dynamic_symbol (info, h))
+           return false;
+       }
+
+      return true;
+    }
+  else if (sym->st_shndx == SHN_LOOS)
+    {
+      int i;
+      
+      /* SHN_AIX_SYSCALL: Treat this as any other symbol.  The special symbol
+        is only relevant when compiling code for extended system calls.
+        Replace the "special" section with .text, if possible. 
+        Note that these symbols are always assumed to be in .text. */
+      for (i = 1; i < elf_elfheader (abfd)->e_shnum; i++)
+       {
+         asection * sec = bfd_section_from_elf_index (abfd, i);
+         
+         if (sec && strcmp (sec->name, ".text") == 0)
+           {
+             *secp = sec;
+             break;
+           }
+       }
+
+      if (*secp == NULL)
+       *secp = bfd_abs_section_ptr;
+      
+      *valp = sym->st_size;
+      
+      return true;
+    }
+  else 
+    {
+      return elfNN_ia64_add_symbol_hook (abfd, info, sym, 
+                                        namep, flagsp, secp, valp);
+    }
+}
+
+boolean
+elfNN_ia64_aix_link_add_symbols (abfd, info)
+     bfd *abfd;
+     struct bfd_link_info *info;
+{
+  /* Make sure dynamic sections are always created.  */
+  if (! elf_hash_table (info)->dynamic_sections_created
+      && abfd->xvec == info->hash->creator)
+    {
+      if (! bfd_elfNN_link_create_dynamic_sections (abfd, info))
+       return false;
+    }
+
+  /* Now do the standard call.  */
+  return bfd_elfNN_bfd_link_add_symbols (abfd, info);
+}
+
 /* Return the number of additional phdrs we will need.  */
 
 static int
@@ -1052,10 +1259,10 @@ elfNN_ia64_additional_program_headers (abfd)
   if (s && (s->flags & SEC_LOAD))
     ++ret;
 
-  /* See if we need a PT_IA_64_UNWIND segment.  */
-  s = bfd_get_section_by_name (abfd, ELF_STRING_ia64_unwind);
-  if (s && (s->flags & SEC_LOAD))
-    ++ret;
+  /* Count how many PT_IA_64_UNWIND segments we need.  */
+  for (s = abfd->sections; s; s = s->next)
+    if (is_unwind_section_name(s->name) && (s->flags & SEC_LOAD))
+      ++ret;
 
   return ret;
 }
@@ -1065,6 +1272,7 @@ elfNN_ia64_modify_segment_map (abfd)
      bfd *abfd;
 {
   struct elf_segment_map *m, **pm;
+  Elf_Internal_Shdr *hdr;
   asection *s;
 
   /* If we need a PT_IA_64_ARCHEXT segment, it must come before
@@ -1097,29 +1305,36 @@ elfNN_ia64_modify_segment_map (abfd)
        }
     }
 
-  /* Install the PT_IA_64_UNWIND segment, if needed.  */
-  s = bfd_get_section_by_name (abfd, ELF_STRING_ia64_unwind);
-  if (s && (s->flags & SEC_LOAD))
+  /* Install PT_IA_64_UNWIND segments, if needed.  */
+  for (s = abfd->sections; s; s = s->next)
     {
-      for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
-       if (m->p_type == PT_IA_64_UNWIND)
-         break;
-      if (m == NULL)
+      hdr = &elf_section_data (s)->this_hdr;
+      if (hdr->sh_type != SHT_IA_64_UNWIND)
+       continue;
+
+      if (s && (s->flags & SEC_LOAD))
        {
-         m = (struct elf_segment_map *) bfd_zalloc (abfd, sizeof *m);
+         for (m = elf_tdata (abfd)->segment_map; m != NULL; m = m->next)
+           if (m->p_type == PT_IA_64_UNWIND && m->sections[0] == s)
+             break;
+
          if (m == NULL)
-           return false;
+           {
+             m = (struct elf_segment_map *) bfd_zalloc (abfd, sizeof *m);
+             if (m == NULL)
+               return false;
 
-         m->p_type = PT_IA_64_UNWIND;
-         m->count = 1;
-         m->sections[0] = s;
-         m->next = NULL;
+             m->p_type = PT_IA_64_UNWIND;
+             m->count = 1;
+             m->sections[0] = s;
+             m->next = NULL;
 
-         /* We want to put it last.  */
-         pm = &elf_tdata (abfd)->segment_map;
-         while (*pm != NULL)
-           pm = &(*pm)->next;
-         *pm = m;
+             /* We want to put it last.  */
+             pm = &elf_tdata (abfd)->segment_map;
+             while (*pm != NULL)
+               pm = &(*pm)->next;
+             *pm = m;
+           }
        }
     }
 
@@ -1181,8 +1396,12 @@ elfNN_ia64_dynamic_symbol_p (h, info)
 
   if (h->dynindx == -1)
     return false;
-  if (ELF_ST_VISIBILITY (h->other) != STV_DEFAULT)
-    return false;
+  switch (ELF_ST_VISIBILITY (h->other))
+    {
+    case STV_INTERNAL:
+    case STV_HIDDEN:
+      return false;
+    }
 
   if (h->root.type == bfd_link_hash_undefweak
       || h->root.type == bfd_link_hash_defweak)
@@ -1321,7 +1540,8 @@ elfNN_ia64_hash_hide_symbol (info, xh)
   h = (struct elfNN_ia64_link_hash_entry *)xh;
 
   h->root.elf_link_hash_flags &= ~ELF_LINK_HASH_NEEDS_PLT;
-  h->root.dynindx = -1;
+  if ((h->root.elf_link_hash_flags & ELF_LINK_FORCED_LOCAL) != 0)
+    h->root.dynindx = -1;
 
   for (dyn_i = h->info; dyn_i; dyn_i = dyn_i->next)
     dyn_i->want_plt2 = 0;
@@ -1776,7 +1996,8 @@ elfNN_ia64_check_relocs (abfd, info, sec, relocs)
       maybe_dynamic = false;
       if (h && ((info->shared && ! info->symbolic)
                || ! (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)
-               || h->root.type == bfd_link_hash_defweak))
+               || h->root.type == bfd_link_hash_defweak
+               || elfNN_ia64_aix_vec (abfd->xvec)))
        maybe_dynamic = true;
 
       need_entry = 0;
@@ -1790,6 +2011,8 @@ elfNN_ia64_check_relocs (abfd, info, sec, relocs)
 
        case R_IA64_LTOFF_FPTR22:
        case R_IA64_LTOFF_FPTR64I:
+       case R_IA64_LTOFF_FPTR32MSB:
+       case R_IA64_LTOFF_FPTR32LSB:
        case R_IA64_LTOFF_FPTR64MSB:
        case R_IA64_LTOFF_FPTR64LSB:
          need_entry = NEED_FPTR | NEED_GOT | NEED_LTOFF_FPTR;
@@ -1800,7 +2023,7 @@ elfNN_ia64_check_relocs (abfd, info, sec, relocs)
        case R_IA64_FPTR32LSB:
        case R_IA64_FPTR64MSB:
        case R_IA64_FPTR64LSB:
-         if (info->shared || h)
+         if (info->shared || h || elfNN_ia64_aix_vec (abfd->xvec))
            need_entry = NEED_FPTR | NEED_DYNREL;
          else
            need_entry = NEED_FPTR;
@@ -1849,7 +2072,10 @@ elfNN_ia64_check_relocs (abfd, info, sec, relocs)
        case R_IA64_DIR64MSB:
        case R_IA64_DIR64LSB:
          /* Shared objects will always need at least a REL relocation.  */
-         if (info->shared || maybe_dynamic)
+         if (info->shared || maybe_dynamic
+             || (elfNN_ia64_aix_vec (abfd->xvec)
+                 && (!h || strcmp (h->root.root.string,
+                                   "__GLOB_DATA_PTR") != 0)))
            need_entry = NEED_DYNREL;
          dynrel_type = R_IA64_DIR64LSB;
          break;
@@ -1913,7 +2139,9 @@ elfNN_ia64_check_relocs (abfd, info, sec, relocs)
          /* FPTRs for shared libraries are allocated by the dynamic
             linker.  Make sure this local symbol will appear in the
             dynamic symbol table.  */
-         if (!h && info->shared)
+         if (!h && (info->shared
+                    /* AIX also needs one */
+                    || elfNN_ia64_aix_vec (abfd->xvec)))
            {
              if (! (_bfd_elfNN_link_record_local_dynamic_symbol
                     (info, abfd, r_symndx)))
@@ -1969,7 +2197,10 @@ allocate_global_data_got (dyn_i, data)
 
   if (dyn_i->want_got
       && ! dyn_i->want_fptr
-      && elfNN_ia64_dynamic_symbol_p (dyn_i->h, x->info))
+      && (elfNN_ia64_dynamic_symbol_p (dyn_i->h, x->info)
+         || (elfNN_ia64_aix_vec (x->info->hash->creator)
+             && (!dyn_i->h || strcmp (dyn_i->h->root.root.string,
+                                      "__GLOB_DATA_PTR") != 0))))
      {
        dyn_i->got_offset = x->ofs;
        x->ofs += 8;
@@ -1988,7 +2219,8 @@ allocate_global_fptr_got (dyn_i, data)
 
   if (dyn_i->want_got
       && dyn_i->want_fptr
-      && elfNN_ia64_dynamic_symbol_p (dyn_i->h, x->info))
+      && (elfNN_ia64_dynamic_symbol_p (dyn_i->h, x->info)
+         || elfNN_ia64_aix_vec (x->info->hash->creator)))
     {
       dyn_i->got_offset = x->ofs;
       x->ofs += 8;
@@ -2006,7 +2238,8 @@ allocate_local_got (dyn_i, data)
   struct elfNN_ia64_allocate_data *x = (struct elfNN_ia64_allocate_data *)data;
 
   if (dyn_i->want_got
-      && ! elfNN_ia64_dynamic_symbol_p (dyn_i->h, x->info))
+      && ! (elfNN_ia64_dynamic_symbol_p (dyn_i->h, x->info)
+           || elfNN_ia64_aix_vec (x->info->hash->creator)))
     {
       dyn_i->got_offset = x->ofs;
       x->ofs += 8;
@@ -2052,7 +2285,12 @@ allocate_fptr (dyn_i, data)
               || h->root.type == bfd_link_hash_warning)
          h = (struct elf_link_hash_entry *) h->root.u.i.link;
 
-      if (x->info->shared)
+      if (x->info->shared
+         /* AIX needs an FPTR in this case. */
+         || (elfNN_ia64_aix_vec (x->info->hash->creator)
+             && (!h
+                 || h->root.type == bfd_link_hash_defined
+                 || h->root.type == bfd_link_hash_defweak)))
        {
          if (h && h->dynindx == -1)
            {
@@ -2175,7 +2413,11 @@ allocate_dynrel_entries (dyn_i, data)
   boolean dynamic_symbol, shared;
 
   ia64_info = elfNN_ia64_hash_table (x->info);
-  dynamic_symbol = elfNN_ia64_dynamic_symbol_p (dyn_i->h, x->info);
+  dynamic_symbol = elfNN_ia64_dynamic_symbol_p (dyn_i->h, x->info)
+    || (elfNN_ia64_aix_vec (x->info->hash->creator)
+       /* Don't allocate an entry for __GLOB_DATA_PTR */
+       && (!dyn_i->h || strcmp (dyn_i->h->root.root.string,
+         "__GLOB_DATA_PTR") != 0));
   shared = x->info->shared;
 
   /* Take care of the normal data relocations.  */
@@ -2292,8 +2534,8 @@ elfNN_ia64_size_dynamic_sections (output_bfd, info)
     {
       sec = bfd_get_section_by_name (dynobj, ".interp");
       BFD_ASSERT (sec != NULL);
-      sec->contents = (bfd_byte *) ELF_DYNAMIC_INTERPRETER;
-      sec->_raw_size = strlen (ELF_DYNAMIC_INTERPRETER) + 1;
+      sec->contents = (bfd_byte *) DYNAMIC_INTERPRETER (output_bfd);
+      sec->_raw_size = strlen (DYNAMIC_INTERPRETER (output_bfd)) + 1;
     }
 
   /* Allocate the GOT entries.  */
@@ -2578,6 +2820,7 @@ elfNN_ia64_install_value (abfd, hit_addr, val, r_type)
     case R_IA64_GPREL32MSB:
     case R_IA64_FPTR32MSB:
     case R_IA64_PCREL32MSB:
+    case R_IA64_LTOFF_FPTR32MSB:
     case R_IA64_SEGREL32MSB:
     case R_IA64_SECREL32MSB:
     case R_IA64_LTV32MSB:
@@ -2588,6 +2831,7 @@ elfNN_ia64_install_value (abfd, hit_addr, val, r_type)
     case R_IA64_GPREL32LSB:
     case R_IA64_FPTR32LSB:
     case R_IA64_PCREL32LSB:
+    case R_IA64_LTOFF_FPTR32LSB:
     case R_IA64_SEGREL32LSB:
     case R_IA64_SECREL32LSB:
     case R_IA64_LTV32LSB:
@@ -2799,6 +3043,7 @@ set_got_entry (abfd, info, dyn_i, dynindx, addend, value, dyn_r_type)
       /* Install a dynamic relocation if needed.  */
       if (info->shared
           || elfNN_ia64_dynamic_symbol_p (dyn_i->h, info)
+         || elfNN_ia64_aix_vec (abfd->xvec)
          || (dynindx != -1 && dyn_r_type == R_IA64_FPTR64LSB))
        {
          if (dynindx == -1)
@@ -3072,6 +3317,13 @@ elfNN_ia64_final_link (abfd, info)
        }
 
       _bfd_set_gp_value (abfd, gp_val);
+
+      if (gp)
+       {
+         gp->root.type = bfd_link_hash_defined;
+         gp->root.u.def.value = gp_val;
+         gp->root.u.def.section = bfd_abs_section_ptr;
+       }
     }
 
   /* If we're producing a final executable, we need to sort the contents
@@ -3281,7 +3533,11 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
        case R_IA64_DIR64MSB:
        case R_IA64_DIR64LSB:
          /* Install a dynamic relocation for this reloc.  */
-         if ((dynamic_symbol_p || info->shared)
+         if ((dynamic_symbol_p || info->shared
+              || (elfNN_ia64_aix_vec (info->hash->creator)
+                  /* Don't emit relocs for __GLOB_DATA_PTR on AIX. */
+                  && (!h || strcmp (h->root.root.string, 
+                                    "__GLOB_DATA_PTR") != 0)))
              && (input_section->flags & SEC_ALLOC) != 0)
            {
              unsigned int dyn_r_type;
@@ -3333,6 +3589,8 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
                  addend = value;
                }
 
+             if (elfNN_ia64_aix_vec (info->hash->creator))
+               rel->r_addend = value;
              elfNN_ia64_install_dyn_reloc (output_bfd, info, input_section,
                                            srel, rel->r_offset, dyn_r_type,
                                            dynindx, addend);
@@ -3428,6 +3686,8 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
 
        case R_IA64_LTOFF_FPTR22:
        case R_IA64_LTOFF_FPTR64I:
+       case R_IA64_LTOFF_FPTR32MSB:
+       case R_IA64_LTOFF_FPTR32LSB:
        case R_IA64_LTOFF_FPTR64MSB:
        case R_IA64_LTOFF_FPTR64LSB:
          {
@@ -3472,7 +3732,8 @@ elfNN_ia64_relocate_section (output_bfd, info, input_bfd, input_section,
        case R_IA64_PCREL64MSB:
        case R_IA64_PCREL64LSB:
          /* Install a dynamic relocation for this reloc.  */
-         if (dynamic_symbol_p)
+         if (dynamic_symbol_p
+             || elfNN_ia64_aix_vec (info->hash->creator))
            {
              BFD_ASSERT (srel != NULL);
 
@@ -4065,6 +4326,8 @@ elfNN_ia64_print_private_bfd_data (abfd, ptr)
        elfNN_ia64_section_flags
 #define elf_backend_fake_sections \
        elfNN_ia64_fake_sections
+#define elf_backend_final_write_processing \
+       elfNN_ia64_final_write_processing
 #define elf_backend_add_symbol_hook \
        elfNN_ia64_add_symbol_hook
 #define elf_backend_additional_program_headers \
@@ -4124,3 +4387,24 @@ elfNN_ia64_print_private_bfd_data (abfd, ptr)
 #define elf_backend_hide_symbol                elfNN_ia64_hash_hide_symbol
 
 #include "elfNN-target.h"
+
+/* AIX-specific vectors.  */
+
+#undef  TARGET_LITTLE_SYM
+#define TARGET_LITTLE_SYM              bfd_elfNN_ia64_aix_little_vec
+#undef  TARGET_LITTLE_NAME
+#define TARGET_LITTLE_NAME             "elfNN-ia64-aix-little"
+#undef  TARGET_BIG_SYM
+#define TARGET_BIG_SYM                 bfd_elfNN_ia64_aix_big_vec
+#undef  TARGET_BIG_NAME
+#define TARGET_BIG_NAME                        "elfNN-ia64-aix-big"
+
+#undef  elf_backend_add_symbol_hook
+#define elf_backend_add_symbol_hook    elfNN_ia64_aix_add_symbol_hook
+
+#undef  bfd_elfNN_bfd_link_add_symbols
+#define bfd_elfNN_bfd_link_add_symbols         elfNN_ia64_aix_link_add_symbols
+
+#define elfNN_bed elfNN_ia64_aix_bed
+
+#include "elfNN-target.h"
This page took 0.031809 seconds and 4 git commands to generate.