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"
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 *));
{
/* 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;
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;
}
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;
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->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
+ || strncmp (name, ".dlt", 4) == 0
+ || strcmp (name, ".stub") == 0
+ || strcmp (name, ".got") == 0)
{
/* Strip this section if we don't need it; see the comment below. */
- if (s->size == 0)
- {
- strip = TRUE;
- }
- }
- else if (strcmp (name, ".opd") == 0)
- {
- /* Strip this section if we don't need it; see the comment below. */
- if (s->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->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
if (s->contents == NULL)
{
s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->size);
- if (s->contents == NULL && s->size != 0)
+ if (s->contents == NULL)
return FALSE;
}
}
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 }
+ { ".fini", 5, 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
+ { ".init", 5, 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE },
+ { ".plt", 4, 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_PARISC_SHORT },
+ { ".dlt", 4, 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_PARISC_SHORT },
+ { ".sdata", 6, 0, SHT_PROGBITS, SHF_ALLOC + SHF_WRITE + SHF_PARISC_SHORT },
+ { ".sbss", 5, 0, SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_PARISC_SHORT },
+ { ".tbss", 5, 0, SHT_NOBITS, SHF_ALLOC + SHF_WRITE + SHF_PARISC_WEAKORDER },
+ { NULL, 0, 0, 0, 0 }
};
/* The hash bucket size is the standard one, namely 4. */
#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
#include "elf64-target.h"