PARAMS((bfd *abfd, asection *sec, struct bfd_link_info *link_info,
boolean *again));
static boolean is_unwind_section_name
- PARAMS ((const char *));
+ PARAMS ((bfd *abfd, const char *));
static boolean elfNN_ia64_section_from_shdr
PARAMS ((bfd *, ElfNN_Internal_Shdr *, char *));
static boolean elfNN_ia64_section_flags
PARAMS ((bfd *abfd, struct bfd_link_info *info));
static boolean elfNN_ia64_set_private_flags
PARAMS ((bfd *abfd, flagword flags));
-static boolean elfNN_ia64_copy_private_bfd_data
- PARAMS ((bfd *ibfd, bfd *obfd));
static boolean elfNN_ia64_merge_private_bfd_data
PARAMS ((bfd *ibfd, bfd *obfd));
static boolean elfNN_ia64_print_private_bfd_data
PARAMS ((bfd *abfd, PTR ptr));
static enum elf_reloc_type_class elfNN_ia64_reloc_type_class
PARAMS ((const Elf_Internal_Rela *));
+static boolean elfNN_ia64_hpux_vec
+ PARAMS ((const bfd_target *vec));
+static void elfNN_hpux_post_process_headers
+ PARAMS ((bfd *abfd, struct bfd_link_info *info));
+boolean elfNN_hpux_backend_section_from_bfd_section
+ PARAMS ((bfd *abfd, asection *sec, int *retval));
\f
/* ia64-specific relocation */
tsec = bfd_abs_section_ptr;
else if (isym.st_shndx == SHN_COMMON)
tsec = bfd_com_section_ptr;
+ else if (isym.st_shndx == SHN_IA_64_ANSI_COMMON)
+ tsec = bfd_com_section_ptr;
else
tsec = bfd_section_from_elf_index (abfd, isym.st_shndx);
/* Return true if NAME is an unwind table section name. */
static inline boolean
-is_unwind_section_name (name)
+is_unwind_section_name (abfd, name)
+ bfd *abfd;
const char *name;
{
size_t len1, len2, len3;
+ if (elfNN_ia64_hpux_vec (abfd->xvec)
+ && !strcmp (name, ELF_STRING_ia64_unwind_hdr))
+ return false;
+
len1 = sizeof (ELF_STRING_ia64_unwind) - 1;
len2 = sizeof (ELF_STRING_ia64_unwind_info) - 1;
len3 = sizeof (ELF_STRING_ia64_unwind_once) - 1;
switch (hdr->sh_type)
{
case SHT_IA_64_UNWIND:
+ case SHT_INIT_ARRAY:
+ case SHT_FINI_ARRAY:
+ case SHT_PREINIT_ARRAY:
+ case SHT_IA_64_HP_OPT_ANOT:
break;
case SHT_IA_64_EXT:
name = bfd_get_section_name (abfd, sec);
- if (is_unwind_section_name (name))
+ if (is_unwind_section_name (abfd, name))
{
/* We don't have the sections numbered at this point, so sh_info
is set later, in elfNN_ia64_final_write_processing. */
}
else if (strcmp (name, ELF_STRING_ia64_archext) == 0)
hdr->sh_type = SHT_IA_64_EXT;
+ else if (strcmp (name, ".init_array") == 0)
+ hdr->sh_type = SHT_INIT_ARRAY;
+ else if (strcmp (name, ".fini_array") == 0)
+ hdr->sh_type = SHT_FINI_ARRAY;
+ else if (strcmp (name, ".preinit_array") == 0)
+ hdr->sh_type = SHT_PREINIT_ARRAY;
+ else if (strcmp (name, ".HP.opt_annot") == 0)
+ hdr->sh_type = SHT_IA_64_HP_OPT_ANOT;
else if (strcmp (name, ".reloc") == 0)
/*
* This is an ugly, but unfortunately necessary hack that is
{
/* .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);
+ char *once_name = bfd_malloc (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);
+ if (once_name != NULL)
+ {
+ memcpy (once_name, ".gnu.linkonce.t.", len2);
+ strcpy (once_name + len2, sname + len);
+ text_sect = bfd_get_section_by_name (abfd, once_name);
+ free (once_name);
+ }
+ else
+ /* Should only happen if we run out of memory, in
+ which case we're probably toast anyway. Try to
+ cope by finding the section the slow way. */
+ for (text_sect = abfd->sections;
+ text_sect != NULL;
+ text_sect = text_sect->next)
+ {
+ if (strncmp (bfd_section_name (abfd, text_sect),
+ ".gnu.linkonce.t.", len2) == 0
+ && strcmp (bfd_section_name (abfd, text_sect) + len2,
+ sname + len) == 0)
+ break;
+ }
}
else
/* last resort: fall back on .text */
/* 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))
+ if (is_unwind_section_name (abfd, s->name) && (s->flags & SEC_LOAD))
++ret;
return ret;
struct elf_segment_map *m, **pm;
Elf_Internal_Shdr *hdr;
asection *s;
+ boolean unwind_found;
+ asection *unwind_sec;
/* If we need a PT_IA_64_ARCHEXT segment, it must come before
all PT_LOAD segments. */
if (s && (s->flags & SEC_LOAD))
{
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->p_type == PT_IA_64_UNWIND)
+ {
+ /* Look through all sections in the unwind segment
+ for a match since there may be multiple sections
+ to a segment. */
+
+ unwind_sec = m->sections[0];
+ unwind_found = false;
+ while (unwind_sec != NULL && !unwind_found)
+ {
+ if (unwind_sec == s)
+ unwind_found = true;
+ else
+ unwind_sec = unwind_sec -> next;
+ }
+ if (unwind_found)
+ break;
+ }
if (m == NULL)
{
{
char *addr_name;
size_t len;
+ struct elfNN_ia64_local_hash_entry *ret;
/* Construct a string for use in the elfNN_ia64_local_hash_table.
name describes what was once anonymous memory. */
len = sizeof (void*)*2 + 1 + sizeof (bfd_vma)*4 + 1 + 1;
len += 10; /* %p slop */
- addr_name = alloca (len);
+ addr_name = bfd_malloc (len);
+ if (addr_name == NULL)
+ return 0;
sprintf (addr_name, "%p:%lx",
(void *) abfd, (unsigned long) ELFNN_R_SYM (rel->r_info));
/* Collect the canonical entry data for this address. */
- return elfNN_ia64_local_hash_lookup (&ia64_info->loc_hash_table,
- addr_name, create, create);
+ ret = elfNN_ia64_local_hash_lookup (&ia64_info->loc_hash_table,
+ addr_name, create, create);
+ free (addr_name);
+ return ret;
}
/* Find and/or create a descriptor for dynamic symbol info. This will
return true;
}
-/* Copy backend specific data from one object module to another */
-static boolean
-elfNN_ia64_copy_private_bfd_data (ibfd, obfd)
- bfd *ibfd, *obfd;
-{
- if ( bfd_get_flavour (ibfd) != bfd_target_elf_flavour
- || bfd_get_flavour (obfd) != bfd_target_elf_flavour)
- return true;
-
- BFD_ASSERT (!elf_flags_init (obfd)
- || (elf_elfheader (obfd)->e_flags
- == elf_elfheader (ibfd)->e_flags));
-
- elf_elfheader (obfd)->e_flags = elf_elfheader (ibfd)->e_flags;
- elf_flags_init (obfd) = true;
- return true;
-}
-
/* Merge backend specific data from an object file to the output
object file when linking. */
static boolean
return reloc_class_normal;
}
}
+
+static boolean
+elfNN_ia64_hpux_vec (const bfd_target *vec)
+{
+ extern const bfd_target bfd_elfNN_ia64_hpux_big_vec;
+ return (vec == & bfd_elfNN_ia64_hpux_big_vec);
+}
+
+static void
+elfNN_hpux_post_process_headers (abfd, info)
+ bfd *abfd;
+ struct bfd_link_info *info ATTRIBUTE_UNUSED;
+{
+ Elf_Internal_Ehdr *i_ehdrp = elf_elfheader (abfd);
+
+ i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_HPUX;
+ i_ehdrp->e_ident[EI_ABIVERSION] = 1;
+}
+
+boolean
+elfNN_hpux_backend_section_from_bfd_section (abfd, sec, retval)
+ bfd *abfd ATTRIBUTE_UNUSED;
+ asection *sec;
+ int *retval;
+{
+ if (bfd_is_com_section (sec))
+ {
+ *retval = SHN_IA_64_ANSI_COMMON;
+ return true;
+ }
+ return false;
+}
\f
#define TARGET_LITTLE_SYM bfd_elfNN_ia64_little_vec
#define TARGET_LITTLE_NAME "elfNN-ia64-little"
#define bfd_elfNN_bfd_final_link \
elfNN_ia64_final_link
-#define bfd_elfNN_bfd_copy_private_bfd_data \
- elfNN_ia64_copy_private_bfd_data
#define bfd_elfNN_bfd_merge_private_bfd_data \
elfNN_ia64_merge_private_bfd_data
#define bfd_elfNN_bfd_set_private_flags \
#define elfNN_bed elfNN_ia64_aix_bed
#include "elfNN-target.h"
+
+/* HPUX-specific vectors. */
+
+#undef TARGET_LITTLE_SYM
+#undef TARGET_LITTLE_NAME
+#undef TARGET_BIG_SYM
+#define TARGET_BIG_SYM bfd_elfNN_ia64_hpux_big_vec
+#undef TARGET_BIG_NAME
+#define TARGET_BIG_NAME "elfNN-ia64-hpux-big"
+
+#undef elf_backend_post_process_headers
+#define elf_backend_post_process_headers elfNN_hpux_post_process_headers
+
+#undef elf_backend_section_from_bfd_section
+#define elf_backend_section_from_bfd_section elfNN_hpux_backend_section_from_bfd_section
+
+#undef ELF_MAXPAGESIZE
+#define ELF_MAXPAGESIZE 0x1000 /* 1K */
+
+#undef elfNN_bed
+#define elfNN_bed elfNN_ia64_hpux_bed
+
+#include "elfNN-target.h"