/* Support for HPPA 64-bit ELF
- Copyright 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
+ Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008
+ Free Software Foundation, Inc.
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
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
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. */
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
-#include "alloca-conf.h"
-#include "bfd.h"
#include "sysdep.h"
+#include "bfd.h"
#include "libbfd.h"
#include "elf-bfd.h"
#include "elf/hppa.h"
#include "libhppa.h"
#include "elf64-hppa.h"
+
+/* This is the code recommended in the autoconf documentation, almost
+ verbatim. */
+#ifndef __GNUC__
+# if HAVE_ALLOCA_H
+# include <alloca.h>
+# else
+# ifdef _AIX
+/* Indented so that pre-ansi C compilers will ignore it, rather than
+ choke on it. Some versions of AIX require this to be the first
+ thing in the file. */
+ #pragma alloca
+# else
+# ifndef alloca /* predefined by HP cc +Olibcalls */
+# if !defined (__STDC__) && !defined (__hpux)
+extern char *alloca ();
+# else
+extern void *alloca ();
+# endif /* __STDC__, __hpux */
+# endif /* alloca */
+# endif /* _AIX */
+# endif /* HAVE_ALLOCA_H */
+#else
+extern void *alloca (size_t);
+#endif /* __GNUC__ */
+
+
#define ARCH_SIZE 64
#define PLT_ENTRY_SIZE 0x10
typedef struct bfd_hash_entry *(*new_hash_entry_func)
PARAMS ((struct bfd_hash_entry *, struct bfd_hash_table *, const char *));
-static bfd_boolean elf64_hppa_dyn_hash_table_init
- PARAMS ((struct elf64_hppa_dyn_hash_table *ht, bfd *abfd,
- new_hash_entry_func new));
static struct bfd_hash_entry *elf64_hppa_new_dyn_hash_entry
PARAMS ((struct bfd_hash_entry *entry, struct bfd_hash_table *table,
const char *string));
PTR info));
static const char *get_dyn_name
- PARAMS ((asection *, struct elf_link_hash_entry *,
+ PARAMS ((bfd *, struct elf_link_hash_entry *,
const Elf_Internal_Rela *, char **, size_t *));
/* This must follow the definitions of the various derived linker
static bfd_boolean elf64_hppa_object_p
PARAMS ((bfd *));
-static bfd_boolean elf64_hppa_section_from_shdr
- PARAMS ((bfd *, Elf_Internal_Shdr *, const char *));
-
static void elf64_hppa_post_process_headers
PARAMS ((bfd *, struct bfd_link_info *));
PARAMS ((bfd *, struct bfd_link_info *,
struct elf_link_hash_entry *, Elf_Internal_Sym *));
-static int elf64_hppa_additional_program_headers
- PARAMS ((bfd *));
-
-static bfd_boolean elf64_hppa_modify_segment_map
- PARAMS ((bfd *, struct bfd_link_info *));
-
static enum elf_reloc_type_class elf64_hppa_reloc_type_class
PARAMS ((const Elf_Internal_Rela *));
PARAMS ((Elf_Internal_Sym *, int));
static bfd_boolean
-elf64_hppa_dyn_hash_table_init (ht, abfd, new)
- struct elf64_hppa_dyn_hash_table *ht;
- bfd *abfd ATTRIBUTE_UNUSED;
- new_hash_entry_func new;
+elf64_hppa_dyn_hash_table_init (struct elf64_hppa_dyn_hash_table *ht,
+ bfd *abfd ATTRIBUTE_UNUSED,
+ new_hash_entry_func new,
+ unsigned int entsize)
{
memset (ht, 0, sizeof (*ht));
- return bfd_hash_table_init (&ht->root, new);
+ return bfd_hash_table_init (&ht->root, new, entsize);
}
static struct bfd_hash_entry*
if (!ret)
return 0;
- /* Initialize our local data. All zeros, and definitely easier
- than setting 8 bit fields. */
- memset (ret, 0, sizeof (*ret));
-
/* Call the allocation method of the superclass. */
ret = ((struct elf64_hppa_dyn_hash_entry *)
bfd_hash_newfunc ((struct bfd_hash_entry *) ret, table, string));
+ /* Initialize our local data. All zeros. */
+ memset (&ret->dlt_offset, 0,
+ (sizeof (struct elf64_hppa_dyn_hash_entry)
+ - offsetof (struct elf64_hppa_dyn_hash_entry, dlt_offset)));
+
return &ret->root;
}
if (!ret)
return 0;
if (!_bfd_elf_link_hash_table_init (&ret->root, abfd,
- _bfd_elf_link_hash_newfunc))
+ _bfd_elf_link_hash_newfunc,
+ sizeof (struct elf_link_hash_entry)))
{
bfd_release (abfd, ret);
return 0;
}
if (!elf64_hppa_dyn_hash_table_init (&ret->dyn_hash_table, abfd,
- elf64_hppa_new_dyn_hash_entry))
+ elf64_hppa_new_dyn_hash_entry,
+ sizeof (struct elf64_hppa_dyn_hash_entry)))
return 0;
return &ret->root.root;
}
{
/* GCC on hppa-linux produces binaries with OSABI=Linux,
but the kernel produces corefiles with OSABI=SysV. */
- if (i_ehdrp->e_ident[EI_OSABI] != ELFOSABI_LINUX &&
- i_ehdrp->e_ident[EI_OSABI] != ELFOSABI_NONE) /* aka SYSV */
+ if (i_ehdrp->e_ident[EI_OSABI] != ELFOSABI_LINUX
+ && i_ehdrp->e_ident[EI_OSABI] != ELFOSABI_NONE) /* aka SYSV */
return FALSE;
}
else
{
- if (i_ehdrp->e_ident[EI_OSABI] != ELFOSABI_HPUX)
+ /* HPUX produces binaries with OSABI=HPUX,
+ but the kernel produces corefiles with OSABI=SysV. */
+ if (i_ehdrp->e_ident[EI_OSABI] != ELFOSABI_HPUX
+ && i_ehdrp->e_ident[EI_OSABI] != ELFOSABI_NONE) /* aka SYSV */
return FALSE;
}
case EFA_PARISC_1_1:
return bfd_default_set_arch_mach (abfd, bfd_arch_hppa, 11);
case EFA_PARISC_2_0:
- return bfd_default_set_arch_mach (abfd, bfd_arch_hppa, 20);
+ if (i_ehdrp->e_ident[EI_CLASS] == ELFCLASS64)
+ return bfd_default_set_arch_mach (abfd, bfd_arch_hppa, 25);
+ else
+ return bfd_default_set_arch_mach (abfd, bfd_arch_hppa, 20);
case EFA_PARISC_2_0 | EF_PARISC_WIDE:
return bfd_default_set_arch_mach (abfd, bfd_arch_hppa, 25);
}
/* Given section type (hdr->sh_type), return a boolean indicating
whether or not the section is an elf64-hppa specific section. */
static bfd_boolean
-elf64_hppa_section_from_shdr (abfd, hdr, name)
- bfd *abfd;
- Elf_Internal_Shdr *hdr;
- const char *name;
+elf64_hppa_section_from_shdr (bfd *abfd,
+ Elf_Internal_Shdr *hdr,
+ const char *name,
+ int shindex)
{
asection *newsect;
return FALSE;
}
- if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name))
+ if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex))
return FALSE;
newsect = hdr->bfd_section;
allocate memory as necessary, possibly reusing PBUF/PLEN. */
static const char *
-get_dyn_name (sec, h, rel, pbuf, plen)
- asection *sec;
+get_dyn_name (abfd, h, rel, pbuf, plen)
+ bfd *abfd;
struct elf_link_hash_entry *h;
const Elf_Internal_Rela *rel;
char **pbuf;
size_t *plen;
{
+ asection *sec = abfd->sections;
size_t nlen, tlen;
char *buf;
size_t len;
{
nlen = sprintf (buf, "%x:%lx",
sec->id & 0xffffffff,
- (long) ELF64_R_SYM (rel->r_info));
+ (unsigned long) ELF64_R_SYM (rel->r_info));
if (rel->r_addend)
{
buf[nlen++] = '+';
if (srel_name == NULL)
return FALSE;
- BFD_ASSERT ((strncmp (srel_name, ".rela", 5) == 0
+ BFD_ASSERT ((CONST_STRNEQ (srel_name, ".rela")
&& strcmp (bfd_get_section_name (abfd, sec),
- srel_name+5) == 0)
- || (strncmp (srel_name, ".rel", 4) == 0
+ srel_name + 5) == 0)
+ || (CONST_STRNEQ (srel_name, ".rel")
&& strcmp (bfd_get_section_name (abfd, sec),
- srel_name+4) == 0));
+ srel_name + 4) == 0));
dynobj = hppa_info->root.dynobj;
if (!dynobj)
srel = bfd_get_section_by_name (dynobj, srel_name);
if (srel == NULL)
{
- srel = bfd_make_section (dynobj, srel_name);
+ srel = bfd_make_section_with_flags (dynobj, srel_name,
+ (SEC_ALLOC
+ | SEC_LOAD
+ | SEC_HAS_CONTENTS
+ | SEC_IN_MEMORY
+ | SEC_LINKER_CREATED
+ | SEC_READONLY));
if (srel == NULL
- || !bfd_set_section_flags (dynobj, srel,
- (SEC_ALLOC
- | SEC_LOAD
- | SEC_HAS_CONTENTS
- | SEC_IN_MEMORY
- | SEC_LINKER_CREATED
- | SEC_READONLY))
|| !bfd_set_section_alignment (dynobj, srel, 3))
return FALSE;
}
asection *dlt, *plt, *stubs;
char *buf;
size_t buf_len;
- int sec_symndx;
+ unsigned int sec_symndx;
if (info->relocatable)
return TRUE;
isymend = local_syms + symtab_hdr->sh_info;
for (isym = local_syms; isym < isymend; isym++)
{
- if (isym->st_shndx > highest_shndx)
+ if (isym->st_shndx > highest_shndx
+ && isym->st_shndx < SHN_LORESERVE)
highest_shndx = isym->st_shndx;
}
/* If we did not find a section symbol for this section, then
something went terribly wrong above. */
- if (sec_symndx == -1)
+ if (sec_symndx == SHN_BAD)
return FALSE;
- sec_symndx = hppa_info->section_syms[sec_symndx];
+ if (sec_symndx < SHN_LORESERVE)
+ sec_symndx = hppa_info->section_syms[sec_symndx];
+ else
+ sec_symndx = 0;
}
else
sec_symndx = 0;
|| h->root.type == bfd_link_hash_warning)
h = (struct elf_link_hash_entry *) h->root.u.i.link;
- h->elf_link_hash_flags |= ELF_LINK_HASH_REF_REGULAR;
+ h->ref_regular = 1;
}
/* We can only get preliminary data on whether a symbol is
this may help reduce memory usage and processing time later. */
maybe_dynamic = FALSE;
if (h && ((info->shared
- && (!info->symbolic || info->unresolved_syms_in_shared_libs == RM_IGNORE))
- || ! (h->elf_link_hash_flags & ELF_LINK_HASH_DEF_REGULAR)
+ && (!info->symbolic
+ || info->unresolved_syms_in_shared_libs == RM_IGNORE))
+ || !h->def_regular
|| h->root.type == bfd_link_hash_defweak))
maybe_dynamic = TRUE;
continue;
/* Collect a canonical name for this address. */
- addr_name = get_dyn_name (sec, h, rel, &buf, &buf_len);
+ addr_name = get_dyn_name (abfd, h, rel, &buf, &buf_len);
/* Collect the canonical entry data for this address. */
dyn_h = elf64_hppa_dyn_hash_lookup (&hppa_info->dyn_hash_table,
/* This could be a local function that had its address taken, in
which case H will be NULL. */
if (h)
- h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
+ h->needs_plt = 1;
}
/* Add a new dynamic relocation to the chain of dynamic
section symbol for this section ends up in the dynamic
symbol table. */
if (info->shared && dynrel_type == R_PARISC_FPTR64
- && ! (_bfd_elf64_link_record_local_dynamic_symbol
+ && ! (bfd_elf_link_record_local_dynamic_symbol
(info, abfd, sec_symndx)))
return FALSE;
}
dyn_h->want_opd = 1;
/* Put a flag here for output_symbol_hook. */
dyn_h->st_shndx = -1;
- h->elf_link_hash_flags |= ELF_LINK_HASH_NEEDS_PLT;
+ h->needs_plt = 1;
}
return TRUE;
bfd *owner;
owner = (h ? h->root.u.def.section->owner : dyn_h->owner);
- if (! (_bfd_elf64_link_record_local_dynamic_symbol
+ if (! (bfd_elf_link_record_local_dynamic_symbol
(x->info, owner, dyn_h->sym_indx)))
return FALSE;
}
/* We never need an opd entry for a symbol which is not
defined by this output file. */
if (h && (h->root.type == bfd_link_hash_undefined
+ || h->root.type == bfd_link_hash_undefweak
|| h->root.u.def.section->output_section == NULL))
dyn_h->want_opd = 0;
&& (h == NULL || (h->dynindx == -1)))
{
bfd *owner;
- owner = (h ? h->root.u.def.section->owner : dyn_h->owner);
+ /* PR 6511: Default to using the dynamic symbol table. */
+ owner = (dyn_h->owner ? dyn_h->owner: h->root.u.def.section->owner);
- if (!_bfd_elf64_link_record_local_dynamic_symbol
+ if (!bfd_elf_link_record_local_dynamic_symbol
(x->info, owner, dyn_h->sym_indx))
return FALSE;
}
nh->root.u.def.value = h->root.u.def.value;
nh->root.u.def.section = h->root.u.def.section;
- if (! bfd_elf64_link_record_dynamic_symbol (x->info, nh))
+ if (! bfd_elf_link_record_dynamic_symbol (x->info, nh))
return FALSE;
}
Elf_Internal_Ehdr * i_ehdrp;
i_ehdrp = elf_elfheader (abfd);
-
- if (strcmp (bfd_get_target (abfd), "elf64-hppa-linux") == 0)
- {
- i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_LINUX;
- }
- else
- {
- i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_HPUX;
- i_ehdrp->e_ident[EI_ABIVERSION] = 1;
- }
+
+ i_ehdrp->e_ident[EI_OSABI] = get_elf_backend_data (abfd)->elf_osabi;
+ i_ehdrp->e_ident[EI_ABIVERSION] = 1;
}
/* Create function descriptor section (.opd). This section is called .opd
if (!dynobj)
hppa_info->root.dynobj = dynobj = abfd;
- opd = bfd_make_section (dynobj, ".opd");
+ opd = bfd_make_section_with_flags (dynobj, ".opd",
+ (SEC_ALLOC
+ | SEC_LOAD
+ | SEC_HAS_CONTENTS
+ | SEC_IN_MEMORY
+ | SEC_LINKER_CREATED));
if (!opd
- || !bfd_set_section_flags (dynobj, opd,
- (SEC_ALLOC
- | SEC_LOAD
- | SEC_HAS_CONTENTS
- | SEC_IN_MEMORY
- | SEC_LINKER_CREATED))
|| !bfd_set_section_alignment (abfd, opd, 3))
{
BFD_ASSERT (0);
if (!dynobj)
hppa_info->root.dynobj = dynobj = abfd;
- plt = bfd_make_section (dynobj, ".plt");
+ plt = bfd_make_section_with_flags (dynobj, ".plt",
+ (SEC_ALLOC
+ | SEC_LOAD
+ | SEC_HAS_CONTENTS
+ | SEC_IN_MEMORY
+ | SEC_LINKER_CREATED));
if (!plt
- || !bfd_set_section_flags (dynobj, plt,
- (SEC_ALLOC
- | SEC_LOAD
- | SEC_HAS_CONTENTS
- | SEC_IN_MEMORY
- | SEC_LINKER_CREATED))
|| !bfd_set_section_alignment (abfd, plt, 3))
{
BFD_ASSERT (0);
if (!dynobj)
hppa_info->root.dynobj = dynobj = abfd;
- dlt = bfd_make_section (dynobj, ".dlt");
+ dlt = bfd_make_section_with_flags (dynobj, ".dlt",
+ (SEC_ALLOC
+ | SEC_LOAD
+ | SEC_HAS_CONTENTS
+ | SEC_IN_MEMORY
+ | SEC_LINKER_CREATED));
if (!dlt
- || !bfd_set_section_flags (dynobj, dlt,
- (SEC_ALLOC
- | SEC_LOAD
- | SEC_HAS_CONTENTS
- | SEC_IN_MEMORY
- | SEC_LINKER_CREATED))
|| !bfd_set_section_alignment (abfd, dlt, 3))
{
BFD_ASSERT (0);
if (!dynobj)
hppa_info->root.dynobj = dynobj = abfd;
- stub = bfd_make_section (dynobj, ".stub");
+ stub = bfd_make_section_with_flags (dynobj, ".stub",
+ (SEC_ALLOC | SEC_LOAD
+ | SEC_HAS_CONTENTS
+ | SEC_IN_MEMORY
+ | SEC_READONLY
+ | SEC_LINKER_CREATED));
if (!stub
- || !bfd_set_section_flags (dynobj, stub,
- (SEC_ALLOC
- | SEC_LOAD
- | SEC_HAS_CONTENTS
- | SEC_IN_MEMORY
- | SEC_READONLY
- | SEC_LINKER_CREATED))
|| !bfd_set_section_alignment (abfd, stub, 3))
{
BFD_ASSERT (0);
if (! get_opd (abfd, info, elf64_hppa_hash_table (info)))
return FALSE;
- s = bfd_make_section(abfd, ".rela.dlt");
+ s = bfd_make_section_with_flags (abfd, ".rela.dlt",
+ (SEC_ALLOC | SEC_LOAD
+ | SEC_HAS_CONTENTS
+ | SEC_IN_MEMORY
+ | SEC_READONLY
+ | SEC_LINKER_CREATED));
if (s == NULL
- || !bfd_set_section_flags (abfd, s, (SEC_ALLOC | SEC_LOAD
- | SEC_HAS_CONTENTS
- | SEC_IN_MEMORY
- | SEC_READONLY
- | SEC_LINKER_CREATED))
|| !bfd_set_section_alignment (abfd, s, 3))
return FALSE;
elf64_hppa_hash_table (info)->dlt_rel_sec = s;
- s = bfd_make_section(abfd, ".rela.plt");
+ s = bfd_make_section_with_flags (abfd, ".rela.plt",
+ (SEC_ALLOC | SEC_LOAD
+ | SEC_HAS_CONTENTS
+ | SEC_IN_MEMORY
+ | SEC_READONLY
+ | SEC_LINKER_CREATED));
if (s == NULL
- || !bfd_set_section_flags (abfd, s, (SEC_ALLOC | SEC_LOAD
- | SEC_HAS_CONTENTS
- | SEC_IN_MEMORY
- | SEC_READONLY
- | SEC_LINKER_CREATED))
|| !bfd_set_section_alignment (abfd, s, 3))
return FALSE;
elf64_hppa_hash_table (info)->plt_rel_sec = s;
- s = bfd_make_section(abfd, ".rela.data");
+ s = bfd_make_section_with_flags (abfd, ".rela.data",
+ (SEC_ALLOC | SEC_LOAD
+ | SEC_HAS_CONTENTS
+ | SEC_IN_MEMORY
+ | SEC_READONLY
+ | SEC_LINKER_CREATED));
if (s == NULL
- || !bfd_set_section_flags (abfd, s, (SEC_ALLOC | SEC_LOAD
- | SEC_HAS_CONTENTS
- | SEC_IN_MEMORY
- | SEC_READONLY
- | SEC_LINKER_CREATED))
|| !bfd_set_section_alignment (abfd, s, 3))
return FALSE;
elf64_hppa_hash_table (info)->other_rel_sec = s;
- s = bfd_make_section(abfd, ".rela.opd");
+ s = bfd_make_section_with_flags (abfd, ".rela.opd",
+ (SEC_ALLOC | SEC_LOAD
+ | SEC_HAS_CONTENTS
+ | SEC_IN_MEMORY
+ | SEC_READONLY
+ | SEC_LINKER_CREATED));
if (s == NULL
- || !bfd_set_section_flags (abfd, s, (SEC_ALLOC | SEC_LOAD
- | SEC_HAS_CONTENTS
- | SEC_IN_MEMORY
- | SEC_READONLY
- | SEC_LINKER_CREATED))
|| !bfd_set_section_alignment (abfd, s, 3))
return FALSE;
elf64_hppa_hash_table (info)->opd_rel_sec = s;
if (!shared && rent->type == R_PARISC_FPTR64 && dyn_h->want_opd)
continue;
- hppa_info->other_rel_sec->_raw_size += sizeof (Elf64_External_Rela);
+ hppa_info->other_rel_sec->size += sizeof (Elf64_External_Rela);
/* Make sure this symbol gets into the dynamic symbol table if it is
not already recorded. ?!? This should not be in the loop since
the symbol need only be added once. */
if (dyn_h->h == 0
|| (dyn_h->h->dynindx == -1 && dyn_h->h->type != STT_PARISC_MILLI))
- if (!_bfd_elf64_link_record_local_dynamic_symbol
+ if (!bfd_elf_link_record_local_dynamic_symbol
(x->info, rent->sec->owner, dyn_h->sym_indx))
return FALSE;
}
/* Take care of the GOT and PLT relocations. */
if ((dynamic_symbol || shared) && dyn_h->want_dlt)
- hppa_info->dlt_rel_sec->_raw_size += sizeof (Elf64_External_Rela);
+ hppa_info->dlt_rel_sec->size += sizeof (Elf64_External_Rela);
/* If we are building a shared library, then every symbol that has an
opd entry will need an EPLT relocation to relocate the symbol's address
and __gp value based on the runtime load address. */
if (shared && dyn_h->want_opd)
- hppa_info->opd_rel_sec->_raw_size += sizeof (Elf64_External_Rela);
+ hppa_info->opd_rel_sec->size += sizeof (Elf64_External_Rela);
if (dyn_h->want_plt && dynamic_symbol)
{
else if (shared)
t = 2 * sizeof (Elf64_External_Rela);
- hppa_info->plt_rel_sec->_raw_size += t;
+ hppa_info->plt_rel_sec->size += t;
}
return TRUE;
/* If this is a weak symbol, and there is a real definition, the
processor independent code will have arranged for us to see the
real definition first, and we can just use the same value. */
- if (h->weakdef != NULL)
+ if (h->u.weakdef != NULL)
{
- BFD_ASSERT (h->weakdef->root.type == bfd_link_hash_defined
- || h->weakdef->root.type == bfd_link_hash_defweak);
- h->root.u.def.section = h->weakdef->root.u.def.section;
- h->root.u.def.value = h->weakdef->root.u.def.value;
+ BFD_ASSERT (h->u.weakdef->root.type == bfd_link_hash_defined
+ || h->u.weakdef->root.type == bfd_link_hash_defweak);
+ h->root.u.def.section = h->u.weakdef->root.u.def.section;
+ h->root.u.def.value = h->u.weakdef->root.u.def.value;
return TRUE;
}
{
s = bfd_get_section_by_name (dynobj, ".interp");
BFD_ASSERT (s != NULL);
- s->_raw_size = sizeof ELF_DYNAMIC_INTERPRETER;
+ s->size = sizeof ELF_DYNAMIC_INTERPRETER;
s->contents = (unsigned char *) ELF_DYNAMIC_INTERPRETER;
}
}
below. */
s = bfd_get_section_by_name (dynobj, ".rela.dlt");
if (s != NULL)
- s->_raw_size = 0;
+ s->size = 0;
}
/* Allocate the GOT entries. */
data.ofs = 0x0;
elf64_hppa_dyn_hash_traverse (&hppa_info->dyn_hash_table,
allocate_global_data_dlt, &data);
- hppa_info->dlt_sec->_raw_size = data.ofs;
+ hppa_info->dlt_sec->size = data.ofs;
data.ofs = 0x0;
elf64_hppa_dyn_hash_traverse (&hppa_info->dyn_hash_table,
allocate_global_data_plt, &data);
- hppa_info->plt_sec->_raw_size = data.ofs;
+ hppa_info->plt_sec->size = data.ofs;
data.ofs = 0x0;
elf64_hppa_dyn_hash_traverse (&hppa_info->dyn_hash_table,
allocate_global_data_stub, &data);
- hppa_info->stub_sec->_raw_size = data.ofs;
+ hppa_info->stub_sec->size = data.ofs;
}
/* Allocate space for entries in the .opd section. */
data.ofs = 0;
elf64_hppa_dyn_hash_traverse (&hppa_info->dyn_hash_table,
allocate_global_data_opd, &data);
- hppa_info->opd_sec->_raw_size = data.ofs;
+ hppa_info->opd_sec->size = data.ofs;
}
/* Now allocate space for dynamic relocations, if necessary. */
for (s = dynobj->sections; s != NULL; s = s->next)
{
const char *name;
- bfd_boolean strip;
if ((s->flags & SEC_LINKER_CREATED) == 0)
continue;
of the dynobj section names depend upon the input files. */
name = bfd_get_section_name (dynobj, s);
- strip = 0;
-
if (strcmp (name, ".plt") == 0)
{
- /* Strip this section if we don't need it; see the comment below. */
- if (s->_raw_size == 0)
- {
- strip = TRUE;
- }
- else
- {
- /* Remember whether there is a PLT. */
- plt = TRUE;
- }
+ /* Remember whether there is a PLT. */
+ plt = s->size != 0;
}
- else if (strcmp (name, ".dlt") == 0)
+ else if (strcmp (name, ".opd") == 0
+ || CONST_STRNEQ (name, ".dlt")
+ || strcmp (name, ".stub") == 0
+ || strcmp (name, ".got") == 0)
{
/* Strip this section if we don't need it; see the comment below. */
- if (s->_raw_size == 0)
- {
- strip = TRUE;
- }
}
- else if (strcmp (name, ".opd") == 0)
+ else if (CONST_STRNEQ (name, ".rela"))
{
- /* Strip this section if we don't need it; see the comment below. */
- if (s->_raw_size == 0)
- {
- strip = TRUE;
- }
- }
- else if (strncmp (name, ".rela", 5) == 0)
- {
- /* If we don't need this section, strip it from the output file.
- This is mostly to handle .rela.bss and .rela.plt. We must
- create both sections in create_dynamic_sections, because they
- must be created before the linker maps input sections to output
- sections. The linker does that before adjust_dynamic_symbol
- is called, and it is that function which decides whether
- anything needs to go into these sections. */
- if (s->_raw_size == 0)
- {
- /* If we don't need this section, strip it from the
- output file. This is mostly to handle .rela.bss and
- .rela.plt. We must create both sections in
- create_dynamic_sections, because they must be created
- before the linker maps input sections to output
- sections. The linker does that before
- adjust_dynamic_symbol is called, and it is that
- function which decides whether anything needs to go
- into these sections. */
- strip = TRUE;
- }
- else
+ if (s->size != 0)
{
asection *target;
s->reloc_count = 0;
}
}
- else if (strncmp (name, ".dlt", 4) != 0
- && strcmp (name, ".stub") != 0
- && strcmp (name, ".got") != 0)
+ else
{
/* It's not one of our sections, so don't allocate space. */
continue;
}
- if (strip)
+ if (s->size == 0)
{
- _bfd_strip_section_from_output (info, s);
+ /* If we don't need this section, strip it from the
+ output file. This is mostly to handle .rela.bss and
+ .rela.plt. We must create both sections in
+ create_dynamic_sections, because they must be created
+ before the linker maps input sections to output
+ sections. The linker does that before
+ adjust_dynamic_symbol is called, and it is that
+ function which decides whether anything needs to go
+ into these sections. */
+ s->flags |= SEC_EXCLUDE;
continue;
}
+ if ((s->flags & SEC_HAS_CONTENTS) == 0)
+ continue;
+
/* Allocate memory for the section contents if it has not
been allocated already. We use bfd_zalloc here in case
unused entries are not reclaimed before the section's
garbage. */
if (s->contents == NULL)
{
- s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->_raw_size);
- if (s->contents == NULL && s->_raw_size != 0)
+ s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->size);
+ if (s->contents == NULL)
return FALSE;
}
}
the PLT, it is how we communicate the __gp value of a load
module to the dynamic linker. */
#define add_dynamic_entry(TAG, VAL) \
- bfd_elf64_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL))
+ _bfd_elf_add_dynamic_entry (info, TAG, VAL)
if (!add_dynamic_entry (DT_HP_DLD_FLAGS, 0)
|| !add_dynamic_entry (DT_PLTGOT, 0))
hppa_info = elf64_hppa_hash_table (info);
dyn_h = elf64_hppa_dyn_hash_lookup (&hppa_info->dyn_hash_table,
name, FALSE, FALSE);
- if (dyn_h->h != h)
+ if (!dyn_h || dyn_h->h != h)
return TRUE;
/* Function symbols for which we created .opd entries *may* have been
into non-dynamic ones, so we initialize st_shndx to -1 in
mark_exported_functions and check to see if it was overwritten
here instead of just checking dyn_h->h->dynindx. */
- if (dyn_h && dyn_h->want_opd && dyn_h->st_shndx != -1)
+ if (dyn_h->want_opd && dyn_h->st_shndx != -1)
{
/* Restore the saved value and section index. */
sym->st_value = dyn_h->st_value;
the original values (in elf64_hppa_link_output_symbol_hook). */
if (dyn_h && dyn_h->want_opd)
{
- BFD_ASSERT (sopd != NULL)
+ BFD_ASSERT (sopd != NULL);
/* Save away the original value and section index so that we
can restore them later. */
Elf_Internal_Rela rel;
bfd_byte *loc;
- BFD_ASSERT (splt != NULL && spltrel != NULL)
+ BFD_ASSERT (splt != NULL && spltrel != NULL);
/* We do not actually care about the value in the PLT entry
if we are creating a shared library and the symbol is
int insn;
unsigned int max_offset;
- BFD_ASSERT (stub != NULL)
+ BFD_ASSERT (stub != NULL);
/* Install the generic stub template.
strcpy (new_name + 1, h->root.root.string);
nh = elf_link_hash_lookup (elf_hash_table (info),
- new_name, FALSE, FALSE, FALSE);
-
+ new_name, TRUE, TRUE, FALSE);
+
/* All we really want from the new symbol is its dynamic
symbol index. */
- dynindx = nh->dynindx;
+ if (nh)
+ dynindx = nh->dynindx;
}
rel.r_addend = 0;
BFD_ASSERT (sdyn != NULL);
dyncon = (Elf64_External_Dyn *) sdyn->contents;
- dynconend = (Elf64_External_Dyn *) (sdyn->contents + sdyn->_raw_size);
+ dynconend = (Elf64_External_Dyn *) (sdyn->contents + sdyn->size);
for (; dyncon < dynconend; dyncon++)
{
Elf_Internal_Dyn dyn;
case DT_PLTRELSZ:
s = hppa_info->plt_rel_sec;
- dyn.d_un.d_val = s->_raw_size;
+ dyn.d_un.d_val = s->size;
bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon);
break;
case DT_RELA:
s = hppa_info->other_rel_sec;
- if (! s || ! s->_raw_size)
+ if (! s || ! s->size)
s = hppa_info->dlt_rel_sec;
- if (! s || ! s->_raw_size)
+ if (! s || ! s->size)
s = hppa_info->opd_rel_sec;
dyn.d_un.d_ptr = s->output_section->vma + s->output_offset;
bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon);
case DT_RELASZ:
s = hppa_info->other_rel_sec;
- dyn.d_un.d_val = s->_raw_size;
+ dyn.d_un.d_val = s->size;
s = hppa_info->dlt_rel_sec;
- dyn.d_un.d_val += s->_raw_size;
+ dyn.d_un.d_val += s->size;
s = hppa_info->opd_rel_sec;
- dyn.d_un.d_val += s->_raw_size;
+ dyn.d_un.d_val += s->size;
/* There is some question about whether or not the size of
the PLT relocs should be included here. HP's tools do
it, so we'll emulate them. */
s = hppa_info->plt_rel_sec;
- dyn.d_un.d_val += s->_raw_size;
+ dyn.d_un.d_val += s->size;
bfd_elf64_swap_dyn_out (output_bfd, &dyn, dyncon);
break;
return TRUE;
}
+/* Support for core dump NOTE sections. */
+
+static bfd_boolean
+elf64_hppa_grok_prstatus (bfd *abfd, Elf_Internal_Note *note)
+{
+ int offset;
+ size_t size;
+
+ switch (note->descsz)
+ {
+ default:
+ return FALSE;
+
+ case 760: /* Linux/hppa */
+ /* pr_cursig */
+ elf_tdata (abfd)->core_signal = bfd_get_16 (abfd, note->descdata + 12);
+
+ /* pr_pid */
+ elf_tdata (abfd)->core_pid = bfd_get_32 (abfd, note->descdata + 32);
+
+ /* pr_reg */
+ offset = 112;
+ size = 640;
+
+ break;
+ }
+
+ /* Make a ".reg/999" section. */
+ return _bfd_elfcore_make_pseudosection (abfd, ".reg",
+ size, note->descpos + offset);
+}
+
+static bfd_boolean
+elf64_hppa_grok_psinfo (bfd *abfd, Elf_Internal_Note *note)
+{
+ char * command;
+ int n;
+
+ switch (note->descsz)
+ {
+ default:
+ return FALSE;
+
+ case 136: /* Linux/hppa elf_prpsinfo. */
+ elf_tdata (abfd)->core_program
+ = _bfd_elfcore_strndup (abfd, note->descdata + 40, 16);
+ elf_tdata (abfd)->core_command
+ = _bfd_elfcore_strndup (abfd, note->descdata + 56, 80);
+ }
+
+ /* Note that for some reason, a spurious space is tacked
+ onto the end of the args in some (at least one anyway)
+ implementations, so strip it off if it exists. */
+ command = elf_tdata (abfd)->core_command;
+ n = strlen (command);
+
+ if (0 < n && command[n - 1] == ' ')
+ command[n - 1] = '\0';
+
+ return TRUE;
+}
+
/* Return the number of additional phdrs we will need.
The generic ELF code only creates PT_PHDRs for executables. The HP
existence of a .interp section. */
static int
-elf64_hppa_additional_program_headers (abfd)
- bfd *abfd;
+elf64_hppa_additional_program_headers (bfd *abfd,
+ struct bfd_link_info *info ATTRIBUTE_UNUSED)
{
asection *s;
existence of a .interp section. */
static bfd_boolean
-elf64_hppa_modify_segment_map (abfd, info)
- bfd *abfd;
- struct bfd_link_info *info ATTRIBUTE_UNUSED;
+elf64_hppa_modify_segment_map (bfd *abfd,
+ struct bfd_link_info *info ATTRIBUTE_UNUSED)
{
struct elf_segment_map *m;
asection *s;
return type;
}
-static struct bfd_elf_special_section const elf64_hppa_special_sections[]=
+/* Support HP specific sections for core files. */
+static bfd_boolean
+elf64_hppa_section_from_phdr (bfd *abfd, Elf_Internal_Phdr *hdr, int index,
+ const char *typename)
+{
+ if (hdr->p_type == PT_HP_CORE_KERNEL)
+ {
+ asection *sect;
+
+ if (!_bfd_elf_make_section_from_phdr (abfd, hdr, index, typename))
+ return FALSE;
+
+ sect = bfd_make_section_anyway (abfd, ".kernel");
+ if (sect == NULL)
+ return FALSE;
+ sect->size = hdr->p_filesz;
+ sect->filepos = hdr->p_offset;
+ sect->flags = SEC_HAS_CONTENTS | SEC_READONLY;
+ return TRUE;
+ }
+
+ if (hdr->p_type == PT_HP_CORE_PROC)
+ {
+ int sig;
+
+ if (bfd_seek (abfd, hdr->p_offset, SEEK_SET) != 0)
+ return FALSE;
+ if (bfd_bread (&sig, 4, abfd) != 4)
+ return FALSE;
+
+ elf_tdata (abfd)->core_signal = sig;
+
+ if (!_bfd_elf_make_section_from_phdr (abfd, hdr, index, typename))
+ return FALSE;
+
+ /* GDB uses the ".reg" section to read register contents. */
+ return _bfd_elfcore_make_pseudosection (abfd, ".reg", hdr->p_filesz,
+ hdr->p_offset);
+ }
+
+ if (hdr->p_type == PT_HP_CORE_LOADABLE
+ || hdr->p_type == PT_HP_CORE_STACK
+ || hdr->p_type == PT_HP_CORE_MMF)
+ hdr->p_type = PT_LOAD;
+
+ return _bfd_elf_make_section_from_phdr (abfd, hdr, index, typename);
+}
+
+static const struct bfd_elf_special_section elf64_hppa_special_sections[] =
{
- { ".fini", 5, 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
- { ".init", 5, 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
- { NULL, 0, 0, 0, 0 }
+ { STRING_COMMA_LEN (".fini"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
+ { STRING_COMMA_LEN (".init"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
+ { STRING_COMMA_LEN (".plt"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_PARISC_SHORT },
+ { STRING_COMMA_LEN (".dlt"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_PARISC_SHORT },
+ { STRING_COMMA_LEN (".sdata"), 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_PARISC_SHORT },
+ { STRING_COMMA_LEN (".sbss"), 0, SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_PARISC_SHORT },
+ { STRING_COMMA_LEN (".tbss"), 0, SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_HP_TLS },
+ { NULL, 0, 0, 0, 0 }
};
/* The hash bucket size is the standard one, namely 4. */
ELFCLASS64, EV_CURRENT,
bfd_elf64_write_out_phdrs,
bfd_elf64_write_shdrs_and_ehdr,
+ bfd_elf64_checksum_contents,
bfd_elf64_write_relocs,
bfd_elf64_swap_symbol_in,
bfd_elf64_swap_symbol_out,
/* This is not strictly correct. The maximum page size for PA2.0 is
64M. But everything still uses 4k. */
#define ELF_MAXPAGESIZE 0x1000
+#define ELF_OSABI ELFOSABI_HPUX
+
#define bfd_elf64_bfd_reloc_type_lookup elf_hppa_reloc_type_lookup
+#define bfd_elf64_bfd_reloc_name_lookup elf_hppa_reloc_name_lookup
#define bfd_elf64_bfd_is_local_label_name elf_hppa_is_local_label_name
#define elf_info_to_howto elf_hppa_info_to_howto
#define elf_info_to_howto_rel elf_hppa_info_to_howto_rel
elf64_hppa_create_dynamic_sections
#define elf_backend_post_process_headers elf64_hppa_post_process_headers
+#define elf_backend_omit_section_dynsym \
+ ((bfd_boolean (*) (bfd *, struct bfd_link_info *, asection *)) bfd_true)
#define elf_backend_adjust_dynamic_symbol \
elf64_hppa_adjust_dynamic_symbol
elf64_hppa_finish_dynamic_symbol
#define elf_backend_finish_dynamic_sections \
elf64_hppa_finish_dynamic_sections
-
+#define elf_backend_grok_prstatus elf64_hppa_grok_prstatus
+#define elf_backend_grok_psinfo elf64_hppa_grok_psinfo
+
/* Stuff for the BFD linker: */
#define bfd_elf64_bfd_link_hash_table_create \
elf64_hppa_hash_table_create
#define elf_backend_reloc_type_class elf64_hppa_reloc_type_class
#define elf_backend_rela_normal 1
#define elf_backend_special_sections elf64_hppa_special_sections
+#define elf_backend_action_discarded elf_hppa_action_discarded
+#define elf_backend_section_from_phdr elf64_hppa_section_from_phdr
+
+#define elf64_bed elf64_hppa_hpux_bed
#include "elf64-target.h"
#define TARGET_BIG_SYM bfd_elf64_hppa_linux_vec
#undef TARGET_BIG_NAME
#define TARGET_BIG_NAME "elf64-hppa-linux"
+#undef ELF_OSABI
+#define ELF_OSABI ELFOSABI_LINUX
+#undef elf_backend_post_process_headers
+#define elf_backend_post_process_headers _bfd_elf_set_osabi
+#undef elf64_bed
+#define elf64_bed elf64_hppa_linux_bed
-#undef elf_backend_special_sections
-
-#define INCLUDED_TARGET_FILE 1
#include "elf64-target.h"