Line 1... |
Line 1... |
/* IA-64 support for 64-bit ELF
|
/* IA-64 support for 64-bit ELF
|
Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
|
Copyright 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
|
Free Software Foundation, Inc.
|
2008, 2009 Free Software Foundation, Inc.
|
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
Contributed by David Mosberger-Tang <davidm@hpl.hp.com>
|
|
|
This file is part of BFD, the Binary File Descriptor library.
|
This file is part of BFD, the Binary File Descriptor library.
|
|
|
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
Line 161... |
Line 161... |
struct elfNN_ia64_link_hash_table
|
struct elfNN_ia64_link_hash_table
|
{
|
{
|
/* The main hash table. */
|
/* The main hash table. */
|
struct elf_link_hash_table root;
|
struct elf_link_hash_table root;
|
|
|
asection *got_sec; /* the linkage table section (or NULL) */
|
|
asection *rel_got_sec; /* dynamic relocation section for same */
|
|
asection *fptr_sec; /* function descriptor table (or NULL) */
|
asection *fptr_sec; /* function descriptor table (or NULL) */
|
asection *rel_fptr_sec; /* dynamic relocation section for same */
|
asection *rel_fptr_sec; /* dynamic relocation section for same */
|
asection *plt_sec; /* the primary plt section (or NULL) */
|
|
asection *pltoff_sec; /* private descriptors for plt (or NULL) */
|
asection *pltoff_sec; /* private descriptors for plt (or NULL) */
|
asection *rel_pltoff_sec; /* dynamic relocation section for same */
|
asection *rel_pltoff_sec; /* dynamic relocation section for same */
|
|
|
bfd_size_type minplt_entries; /* number of minplt entries */
|
bfd_size_type minplt_entries; /* number of minplt entries */
|
unsigned reltext : 1; /* are there relocs against readonly sections? */
|
unsigned reltext : 1; /* are there relocs against readonly sections? */
|
Line 613... |
Line 610... |
(((i) & OPCODE_BITS) == (0x5LL << OPCODE_SHIFT))
|
(((i) & OPCODE_BITS) == (0x5LL << OPCODE_SHIFT))
|
|
|
static bfd_boolean
|
static bfd_boolean
|
elfNN_ia64_relax_br (bfd_byte *contents, bfd_vma off)
|
elfNN_ia64_relax_br (bfd_byte *contents, bfd_vma off)
|
{
|
{
|
unsigned int template, mlx;
|
unsigned int template_val, mlx;
|
bfd_vma t0, t1, s0, s1, s2, br_code;
|
bfd_vma t0, t1, s0, s1, s2, br_code;
|
long br_slot;
|
long br_slot;
|
bfd_byte *hit_addr;
|
bfd_byte *hit_addr;
|
|
|
hit_addr = (bfd_byte *) (contents + off);
|
hit_addr = (bfd_byte *) (contents + off);
|
Line 627... |
Line 624... |
t1 = bfd_getl64 (hit_addr + 8);
|
t1 = bfd_getl64 (hit_addr + 8);
|
|
|
/* Check if we can turn br into brl. A label is always at the start
|
/* Check if we can turn br into brl. A label is always at the start
|
of the bundle. Even if there are predicates on NOPs, we still
|
of the bundle. Even if there are predicates on NOPs, we still
|
perform this optimization. */
|
perform this optimization. */
|
template = t0 & 0x1e;
|
template_val = t0 & 0x1e;
|
s0 = (t0 >> 5) & 0x1ffffffffffLL;
|
s0 = (t0 >> 5) & 0x1ffffffffffLL;
|
s1 = ((t0 >> 46) | (t1 << 18)) & 0x1ffffffffffLL;
|
s1 = ((t0 >> 46) | (t1 << 18)) & 0x1ffffffffffLL;
|
s2 = (t1 >> 23) & 0x1ffffffffffLL;
|
s2 = (t1 >> 23) & 0x1ffffffffffLL;
|
switch (br_slot)
|
switch (br_slot)
|
{
|
{
|
Line 643... |
Line 640... |
br_code = s0;
|
br_code = s0;
|
break;
|
break;
|
case 1:
|
case 1:
|
/* Check if slot 2 is NOP. Possible templates are MBB and BBB.
|
/* Check if slot 2 is NOP. Possible templates are MBB and BBB.
|
For BBB, slot 0 also has to be nop.b. */
|
For BBB, slot 0 also has to be nop.b. */
|
if (!((template == 0x12 /* MBB */
|
if (!((template_val == 0x12 /* MBB */
|
&& IS_NOP_B (s2))
|
&& IS_NOP_B (s2))
|
|| (template == 0x16 /* BBB */
|
|| (template_val == 0x16 /* BBB */
|
&& IS_NOP_B (s0)
|
&& IS_NOP_B (s0)
|
&& IS_NOP_B (s2))))
|
&& IS_NOP_B (s2))))
|
return FALSE;
|
return FALSE;
|
br_code = s1;
|
br_code = s1;
|
break;
|
break;
|
case 2:
|
case 2:
|
/* Check if slot 1 is NOP. Possible templates are MIB, MBB, BBB,
|
/* Check if slot 1 is NOP. Possible templates are MIB, MBB, BBB,
|
MMB and MFB. For BBB, slot 0 also has to be nop.b. */
|
MMB and MFB. For BBB, slot 0 also has to be nop.b. */
|
if (!((template == 0x10 /* MIB */
|
if (!((template_val == 0x10 /* MIB */
|
&& IS_NOP_I (s1))
|
&& IS_NOP_I (s1))
|
|| (template == 0x12 /* MBB */
|
|| (template_val == 0x12 /* MBB */
|
&& IS_NOP_B (s1))
|
&& IS_NOP_B (s1))
|
|| (template == 0x16 /* BBB */
|
|| (template_val == 0x16 /* BBB */
|
&& IS_NOP_B (s0)
|
&& IS_NOP_B (s0)
|
&& IS_NOP_B (s1))
|
&& IS_NOP_B (s1))
|
|| (template == 0x18 /* MMB */
|
|| (template_val == 0x18 /* MMB */
|
&& IS_NOP_M (s1))
|
&& IS_NOP_M (s1))
|
|| (template == 0x1c /* MFB */
|
|| (template_val == 0x1c /* MFB */
|
&& IS_NOP_F (s1))))
|
&& IS_NOP_F (s1))))
|
return FALSE;
|
return FALSE;
|
br_code = s2;
|
br_code = s2;
|
break;
|
break;
|
default:
|
default:
|
Line 687... |
Line 684... |
if (t0 & 0x1)
|
if (t0 & 0x1)
|
mlx = 0x5;
|
mlx = 0x5;
|
else
|
else
|
mlx = 0x4;
|
mlx = 0x4;
|
|
|
if (template == 0x16)
|
if (template_val == 0x16)
|
{
|
{
|
/* For BBB, we need to put nop.m in slot 0. We keep the original
|
/* For BBB, we need to put nop.m in slot 0. We keep the original
|
predicate only if slot 0 isn't br. */
|
predicate only if slot 0 isn't br. */
|
if (br_slot == 0)
|
if (br_slot == 0)
|
t0 = 0LL;
|
t0 = 0LL;
|
Line 716... |
Line 713... |
}
|
}
|
|
|
static void
|
static void
|
elfNN_ia64_relax_brl (bfd_byte *contents, bfd_vma off)
|
elfNN_ia64_relax_brl (bfd_byte *contents, bfd_vma off)
|
{
|
{
|
int template;
|
int template_val;
|
bfd_byte *hit_addr;
|
bfd_byte *hit_addr;
|
bfd_vma t0, t1, i0, i1, i2;
|
bfd_vma t0, t1, i0, i1, i2;
|
|
|
hit_addr = (bfd_byte *) (contents + off);
|
hit_addr = (bfd_byte *) (contents + off);
|
hit_addr -= (long) hit_addr & 0x3;
|
hit_addr -= (long) hit_addr & 0x3;
|
Line 735... |
Line 732... |
i2 = (t1 >> 23) & 0x0ffffffffffLL;
|
i2 = (t1 >> 23) & 0x0ffffffffffLL;
|
|
|
/* Turn a MLX bundle into a MBB bundle with the same stop-bit
|
/* Turn a MLX bundle into a MBB bundle with the same stop-bit
|
variety. */
|
variety. */
|
if (t0 & 0x1)
|
if (t0 & 0x1)
|
template = 0x13;
|
template_val = 0x13;
|
else
|
else
|
template = 0x12;
|
template_val = 0x12;
|
t0 = (i1 << 46) | (i0 << 5) | template;
|
t0 = (i1 << 46) | (i0 << 5) | template_val;
|
t1 = (i2 << 23) | (i1 >> 18);
|
t1 = (i2 << 23) | (i1 >> 18);
|
|
|
bfd_putl64 (t0, hit_addr);
|
bfd_putl64 (t0, hit_addr);
|
bfd_putl64 (t1, hit_addr + 8);
|
bfd_putl64 (t1, hit_addr + 8);
|
}
|
}
|
Line 784... |
Line 781... |
|
|
/* Assume we're not going to change any sizes, and we'll only need
|
/* Assume we're not going to change any sizes, and we'll only need
|
one pass. */
|
one pass. */
|
*again = FALSE;
|
*again = FALSE;
|
|
|
|
if (link_info->relocatable)
|
|
(*link_info->callbacks->einfo)
|
|
(_("%P%F: --relax and -r may not be used together\n"));
|
|
|
/* Don't even try to relax for non-ELF outputs. */
|
/* Don't even try to relax for non-ELF outputs. */
|
if (!is_elf_hash_table (link_info->hash))
|
if (!is_elf_hash_table (link_info->hash))
|
return FALSE;
|
return FALSE;
|
|
|
/* Nothing to do if there are no relocations or there is no need for
|
/* Nothing to do if there are no relocations or there is no need for
|
Line 926... |
Line 927... |
/* Internal branches shouldn't be sent to the PLT.
|
/* Internal branches shouldn't be sent to the PLT.
|
Leave this for now and we'll give an error later. */
|
Leave this for now and we'll give an error later. */
|
if (r_type != R_IA64_PCREL21B)
|
if (r_type != R_IA64_PCREL21B)
|
continue;
|
continue;
|
|
|
tsec = ia64_info->plt_sec;
|
tsec = ia64_info->root.splt;
|
toff = dyn_i->plt2_offset;
|
toff = dyn_i->plt2_offset;
|
BFD_ASSERT (irel->r_addend == 0);
|
BFD_ASSERT (irel->r_addend == 0);
|
}
|
}
|
|
|
/* Can't do anything else with dynamic symbols. */
|
/* Can't do anything else with dynamic symbols. */
|
Line 992... |
Line 993... |
|
|
reladdr = (sec->output_section->vma
|
reladdr = (sec->output_section->vma
|
+ sec->output_offset
|
+ sec->output_offset
|
+ roff) & (bfd_vma) -4;
|
+ roff) & (bfd_vma) -4;
|
|
|
|
/* The .plt section is aligned at 32byte and the .text section
|
|
is aligned at 64byte. The .text section is right after the
|
|
.plt section. After the first relaxation pass, linker may
|
|
increase the gap between the .plt and .text sections up
|
|
to 32byte. We assume linker will always insert 32byte
|
|
between the .plt and .text sections after the the first
|
|
relaxation pass. */
|
|
if (tsec == ia64_info->root.splt)
|
|
offset = -0x1000000 + 32;
|
|
else
|
|
offset = -0x1000000;
|
|
|
/* If the branch is in range, no need to do anything. */
|
/* If the branch is in range, no need to do anything. */
|
if ((bfd_signed_vma) (symaddr - reladdr) >= -0x1000000
|
if ((bfd_signed_vma) (symaddr - reladdr) >= offset
|
&& (bfd_signed_vma) (symaddr - reladdr) <= 0x0FFFFF0)
|
&& (bfd_signed_vma) (symaddr - reladdr) <= 0x0FFFFF0)
|
{
|
{
|
/* If the 60-bit branch is in 21-bit range, optimize it. */
|
/* If the 60-bit branch is in 21-bit range, optimize it. */
|
if (r_type == R_IA64_PCREL60B)
|
if (r_type == R_IA64_PCREL60B)
|
{
|
{
|
Line 1058... |
Line 1071... |
make a copy of the FULL_PLT entry. Otherwise, we'll have
|
make a copy of the FULL_PLT entry. Otherwise, we'll have
|
to use a `brl' insn to get where we're going. */
|
to use a `brl' insn to get where we're going. */
|
|
|
size_t size;
|
size_t size;
|
|
|
if (tsec == ia64_info->plt_sec)
|
if (tsec == ia64_info->root.splt)
|
size = sizeof (plt_full_entry);
|
size = sizeof (plt_full_entry);
|
else
|
else
|
size = oor_branch_size;
|
size = oor_branch_size;
|
|
|
/* Resize the current section to make room for the new branch. */
|
/* Resize the current section to make room for the new branch. */
|
Line 1078... |
Line 1091... |
contents = (bfd_byte *) bfd_realloc (contents, amt);
|
contents = (bfd_byte *) bfd_realloc (contents, amt);
|
if (contents == NULL)
|
if (contents == NULL)
|
goto error_return;
|
goto error_return;
|
sec->size = amt;
|
sec->size = amt;
|
|
|
if (tsec == ia64_info->plt_sec)
|
if (tsec == ia64_info->root.splt)
|
{
|
{
|
memcpy (contents + trampoff, plt_full_entry, size);
|
memcpy (contents + trampoff, plt_full_entry, size);
|
|
|
/* Hijack the old relocation for use as the PLTOFF reloc. */
|
/* Hijack the old relocation for use as the PLTOFF reloc. */
|
irel->r_info = ELFNN_R_INFO (ELFNN_R_SYM (irel->r_info),
|
irel->r_info = ELFNN_R_INFO (ELFNN_R_SYM (irel->r_info),
|
Line 1232... |
Line 1245... |
ia64_info->self_dtpmod_offset = (bfd_vma) -1;
|
ia64_info->self_dtpmod_offset = (bfd_vma) -1;
|
|
|
elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_global_data_got, &data);
|
elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_global_data_got, &data);
|
elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_global_fptr_got, &data);
|
elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_global_fptr_got, &data);
|
elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_local_got, &data);
|
elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_local_got, &data);
|
ia64_info->got_sec->size = data.ofs;
|
ia64_info->root.sgot->size = data.ofs;
|
|
|
if (ia64_info->root.dynamic_sections_created
|
if (ia64_info->root.dynamic_sections_created
|
&& ia64_info->rel_got_sec != NULL)
|
&& ia64_info->root.srelgot != NULL)
|
{
|
{
|
/* Resize .rela.got. */
|
/* Resize .rela.got. */
|
ia64_info->rel_got_sec->size = 0;
|
ia64_info->root.srelgot->size = 0;
|
if (link_info->shared
|
if (link_info->shared
|
&& ia64_info->self_dtpmod_offset != (bfd_vma) -1)
|
&& ia64_info->self_dtpmod_offset != (bfd_vma) -1)
|
ia64_info->rel_got_sec->size += sizeof (ElfNN_External_Rela);
|
ia64_info->root.srelgot->size += sizeof (ElfNN_External_Rela);
|
data.only_got = TRUE;
|
data.only_got = TRUE;
|
elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_dynrel_entries,
|
elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_dynrel_entries,
|
&data);
|
&data);
|
}
|
}
|
}
|
}
|
Line 1794... |
Line 1807... |
elfNN_ia64_local_htab_hash (const void *ptr)
|
elfNN_ia64_local_htab_hash (const void *ptr)
|
{
|
{
|
struct elfNN_ia64_local_hash_entry *entry
|
struct elfNN_ia64_local_hash_entry *entry
|
= (struct elfNN_ia64_local_hash_entry *) ptr;
|
= (struct elfNN_ia64_local_hash_entry *) ptr;
|
|
|
return (((entry->id & 0xff) << 24) | ((entry->id & 0xff00) << 8))
|
return ELF_LOCAL_SYMBOL_HASH (entry->id, entry->r_sym);
|
^ entry->r_sym ^ (entry->id >> 16);
|
|
}
|
}
|
|
|
/* Compare local hash entries. */
|
/* Compare local hash entries. */
|
|
|
static int
|
static int
|
Line 1985... |
Line 1997... |
if (! _bfd_elf_create_dynamic_sections (abfd, info))
|
if (! _bfd_elf_create_dynamic_sections (abfd, info))
|
return FALSE;
|
return FALSE;
|
|
|
ia64_info = elfNN_ia64_hash_table (info);
|
ia64_info = elfNN_ia64_hash_table (info);
|
|
|
ia64_info->plt_sec = bfd_get_section_by_name (abfd, ".plt");
|
|
ia64_info->got_sec = bfd_get_section_by_name (abfd, ".got");
|
|
|
|
{
|
{
|
flagword flags = bfd_get_section_flags (abfd, ia64_info->got_sec);
|
flagword flags = bfd_get_section_flags (abfd, ia64_info->root.sgot);
|
bfd_set_section_flags (abfd, ia64_info->got_sec, SEC_SMALL_DATA | flags);
|
bfd_set_section_flags (abfd, ia64_info->root.sgot,
|
|
SEC_SMALL_DATA | flags);
|
/* The .got section is always aligned at 8 bytes. */
|
/* The .got section is always aligned at 8 bytes. */
|
bfd_set_section_alignment (abfd, ia64_info->got_sec, 3);
|
bfd_set_section_alignment (abfd, ia64_info->root.sgot, 3);
|
}
|
}
|
|
|
if (!get_pltoff (abfd, info, ia64_info))
|
if (!get_pltoff (abfd, info, ia64_info))
|
return FALSE;
|
return FALSE;
|
|
|
Line 2009... |
Line 2019... |
if (s == NULL
|
if (s == NULL
|
|| !bfd_set_section_alignment (abfd, s, LOG_SECTION_ALIGN))
|
|| !bfd_set_section_alignment (abfd, s, LOG_SECTION_ALIGN))
|
return FALSE;
|
return FALSE;
|
ia64_info->rel_pltoff_sec = s;
|
ia64_info->rel_pltoff_sec = s;
|
|
|
s = bfd_make_section_with_flags (abfd, ".rela.got",
|
|
(SEC_ALLOC | SEC_LOAD
|
|
| SEC_HAS_CONTENTS
|
|
| SEC_IN_MEMORY
|
|
| SEC_LINKER_CREATED
|
|
| SEC_READONLY));
|
|
if (s == NULL
|
|
|| !bfd_set_section_alignment (abfd, s, LOG_SECTION_ALIGN))
|
|
return FALSE;
|
|
ia64_info->rel_got_sec = s;
|
|
|
|
return TRUE;
|
return TRUE;
|
}
|
}
|
|
|
/* Find and/or create a hash entry for local symbol. */
|
/* Find and/or create a hash entry for local symbol. */
|
static struct elfNN_ia64_local_hash_entry *
|
static struct elfNN_ia64_local_hash_entry *
|
Line 2031... |
Line 2030... |
bfd *abfd, const Elf_Internal_Rela *rel,
|
bfd *abfd, const Elf_Internal_Rela *rel,
|
bfd_boolean create)
|
bfd_boolean create)
|
{
|
{
|
struct elfNN_ia64_local_hash_entry e, *ret;
|
struct elfNN_ia64_local_hash_entry e, *ret;
|
asection *sec = abfd->sections;
|
asection *sec = abfd->sections;
|
hashval_t h = (((sec->id & 0xff) << 24) | ((sec->id & 0xff00) << 8))
|
hashval_t h = ELF_LOCAL_SYMBOL_HASH (sec->id,
|
^ ELFNN_R_SYM (rel->r_info) ^ (sec->id >> 16);
|
ELFNN_R_SYM (rel->r_info));
|
void **slot;
|
void **slot;
|
|
|
e.id = sec->id;
|
e.id = sec->id;
|
e.r_sym = ELFNN_R_SYM (rel->r_info);
|
e.r_sym = ELFNN_R_SYM (rel->r_info);
|
slot = htab_find_slot_with_hash (ia64_info->loc_hash_table, &e, h,
|
slot = htab_find_slot_with_hash (ia64_info->loc_hash_table, &e, h,
|
Line 2400... |
Line 2399... |
struct elfNN_ia64_link_hash_table *ia64_info)
|
struct elfNN_ia64_link_hash_table *ia64_info)
|
{
|
{
|
asection *got;
|
asection *got;
|
bfd *dynobj;
|
bfd *dynobj;
|
|
|
got = ia64_info->got_sec;
|
got = ia64_info->root.sgot;
|
if (!got)
|
if (!got)
|
{
|
{
|
flagword flags;
|
flagword flags;
|
|
|
dynobj = ia64_info->root.dynobj;
|
dynobj = ia64_info->root.dynobj;
|
if (!dynobj)
|
if (!dynobj)
|
ia64_info->root.dynobj = dynobj = abfd;
|
ia64_info->root.dynobj = dynobj = abfd;
|
if (!_bfd_elf_create_got_section (dynobj, info))
|
if (!_bfd_elf_create_got_section (dynobj, info))
|
return 0;
|
return 0;
|
|
|
got = bfd_get_section_by_name (dynobj, ".got");
|
got = ia64_info->root.sgot;
|
BFD_ASSERT (got);
|
|
ia64_info->got_sec = got;
|
|
|
|
/* The .got section is always aligned at 8 bytes. */
|
/* The .got section is always aligned at 8 bytes. */
|
if (!bfd_set_section_alignment (abfd, got, 3))
|
if (!bfd_set_section_alignment (abfd, got, 3))
|
return 0;
|
return 0;
|
|
|
Line 3312... |
Line 3309... |
{
|
{
|
if (!dyn_i->want_ltoff_fptr
|
if (!dyn_i->want_ltoff_fptr
|
|| !x->info->pie
|
|| !x->info->pie
|
|| dyn_i->h == NULL
|
|| dyn_i->h == NULL
|
|| dyn_i->h->root.type != bfd_link_hash_undefweak)
|
|| dyn_i->h->root.type != bfd_link_hash_undefweak)
|
ia64_info->rel_got_sec->size += sizeof (ElfNN_External_Rela);
|
ia64_info->root.srelgot->size += sizeof (ElfNN_External_Rela);
|
}
|
}
|
if ((dynamic_symbol || shared) && dyn_i->want_tprel)
|
if ((dynamic_symbol || shared) && dyn_i->want_tprel)
|
ia64_info->rel_got_sec->size += sizeof (ElfNN_External_Rela);
|
ia64_info->root.srelgot->size += sizeof (ElfNN_External_Rela);
|
if (dynamic_symbol && dyn_i->want_dtpmod)
|
if (dynamic_symbol && dyn_i->want_dtpmod)
|
ia64_info->rel_got_sec->size += sizeof (ElfNN_External_Rela);
|
ia64_info->root.srelgot->size += sizeof (ElfNN_External_Rela);
|
if (dynamic_symbol && dyn_i->want_dtprel)
|
if (dynamic_symbol && dyn_i->want_dtprel)
|
ia64_info->rel_got_sec->size += sizeof (ElfNN_External_Rela);
|
ia64_info->root.srelgot->size += sizeof (ElfNN_External_Rela);
|
|
|
if (x->only_got)
|
if (x->only_got)
|
return TRUE;
|
return TRUE;
|
|
|
if (ia64_info->rel_fptr_sec && dyn_i->want_fptr)
|
if (ia64_info->rel_fptr_sec && dyn_i->want_fptr)
|
Line 3453... |
Line 3450... |
sec->size = strlen (ELF_DYNAMIC_INTERPRETER) + 1;
|
sec->size = strlen (ELF_DYNAMIC_INTERPRETER) + 1;
|
}
|
}
|
|
|
/* Allocate the GOT entries. */
|
/* Allocate the GOT entries. */
|
|
|
if (ia64_info->got_sec)
|
if (ia64_info->root.sgot)
|
{
|
{
|
data.ofs = 0;
|
data.ofs = 0;
|
elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_global_data_got, &data);
|
elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_global_data_got, &data);
|
elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_global_fptr_got, &data);
|
elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_global_fptr_got, &data);
|
elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_local_got, &data);
|
elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_local_got, &data);
|
ia64_info->got_sec->size = data.ofs;
|
ia64_info->root.sgot->size = data.ofs;
|
}
|
}
|
|
|
/* Allocate the FPTR entries. */
|
/* Allocate the FPTR entries. */
|
|
|
if (ia64_info->fptr_sec)
|
if (ia64_info->fptr_sec)
|
Line 3498... |
Line 3495... |
there are no PLT entries since dynamic linker may assume the
|
there are no PLT entries since dynamic linker may assume the
|
reserved memory always exists. */
|
reserved memory always exists. */
|
|
|
BFD_ASSERT (ia64_info->root.dynamic_sections_created);
|
BFD_ASSERT (ia64_info->root.dynamic_sections_created);
|
|
|
ia64_info->plt_sec->size = data.ofs;
|
ia64_info->root.splt->size = data.ofs;
|
|
|
/* If we've got a .plt, we need some extra memory for the dynamic
|
/* If we've got a .plt, we need some extra memory for the dynamic
|
linker. We stuff these in .got.plt. */
|
linker. We stuff these in .got.plt. */
|
sec = bfd_get_section_by_name (dynobj, ".got.plt");
|
sec = bfd_get_section_by_name (dynobj, ".got.plt");
|
sec->size = 8 * PLT_RESERVED_WORDS;
|
sec->size = 8 * PLT_RESERVED_WORDS;
|
Line 3521... |
Line 3518... |
{
|
{
|
/* Allocate space for the dynamic relocations that turned out to be
|
/* Allocate space for the dynamic relocations that turned out to be
|
required. */
|
required. */
|
|
|
if (info->shared && ia64_info->self_dtpmod_offset != (bfd_vma) -1)
|
if (info->shared && ia64_info->self_dtpmod_offset != (bfd_vma) -1)
|
ia64_info->rel_got_sec->size += sizeof (ElfNN_External_Rela);
|
ia64_info->root.srelgot->size += sizeof (ElfNN_External_Rela);
|
data.only_got = FALSE;
|
data.only_got = FALSE;
|
elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_dynrel_entries, &data);
|
elfNN_ia64_dyn_sym_traverse (ia64_info, allocate_dynrel_entries, &data);
|
}
|
}
|
|
|
/* We have now determined the sizes of the various dynamic sections.
|
/* We have now determined the sizes of the various dynamic sections.
|
Line 3545... |
Line 3542... |
function which decides whether anything needs to go into
|
function which decides whether anything needs to go into
|
these sections. */
|
these sections. */
|
|
|
strip = (sec->size == 0);
|
strip = (sec->size == 0);
|
|
|
if (sec == ia64_info->got_sec)
|
if (sec == ia64_info->root.sgot)
|
strip = FALSE;
|
strip = FALSE;
|
else if (sec == ia64_info->rel_got_sec)
|
else if (sec == ia64_info->root.srelgot)
|
{
|
{
|
if (strip)
|
if (strip)
|
ia64_info->rel_got_sec = NULL;
|
ia64_info->root.srelgot = NULL;
|
else
|
else
|
/* We use the reloc_count field as a counter if we need to
|
/* We use the reloc_count field as a counter if we need to
|
copy relocs into the output file. */
|
copy relocs into the output file. */
|
sec->reloc_count = 0;
|
sec->reloc_count = 0;
|
}
|
}
|
Line 3570... |
Line 3567... |
else
|
else
|
/* We use the reloc_count field as a counter if we need to
|
/* We use the reloc_count field as a counter if we need to
|
copy relocs into the output file. */
|
copy relocs into the output file. */
|
sec->reloc_count = 0;
|
sec->reloc_count = 0;
|
}
|
}
|
else if (sec == ia64_info->plt_sec)
|
else if (sec == ia64_info->root.splt)
|
{
|
{
|
if (strip)
|
if (strip)
|
ia64_info->plt_sec = NULL;
|
ia64_info->root.splt = NULL;
|
}
|
}
|
else if (sec == ia64_info->pltoff_sec)
|
else if (sec == ia64_info->pltoff_sec)
|
{
|
{
|
if (strip)
|
if (strip)
|
ia64_info->pltoff_sec = NULL;
|
ia64_info->pltoff_sec = NULL;
|
Line 3942... |
Line 3939... |
asection *got_sec;
|
asection *got_sec;
|
bfd_boolean done;
|
bfd_boolean done;
|
bfd_vma got_offset;
|
bfd_vma got_offset;
|
|
|
ia64_info = elfNN_ia64_hash_table (info);
|
ia64_info = elfNN_ia64_hash_table (info);
|
got_sec = ia64_info->got_sec;
|
got_sec = ia64_info->root.sgot;
|
|
|
switch (dyn_r_type)
|
switch (dyn_r_type)
|
{
|
{
|
case R_IA64_TPREL64LSB:
|
case R_IA64_TPREL64LSB:
|
done = dyn_i->tprel_done;
|
done = dyn_i->tprel_done;
|
Line 4053... |
Line 4050... |
break;
|
break;
|
}
|
}
|
}
|
}
|
|
|
elfNN_ia64_install_dyn_reloc (abfd, NULL, got_sec,
|
elfNN_ia64_install_dyn_reloc (abfd, NULL, got_sec,
|
ia64_info->rel_got_sec,
|
ia64_info->root.srelgot,
|
got_offset, dyn_r_type,
|
got_offset, dyn_r_type,
|
dynindx, addend);
|
dynindx, addend);
|
}
|
}
|
}
|
}
|
|
|
Line 4186... |
Line 4183... |
|
|
static bfd_vma
|
static bfd_vma
|
elfNN_ia64_tprel_base (struct bfd_link_info *info)
|
elfNN_ia64_tprel_base (struct bfd_link_info *info)
|
{
|
{
|
asection *tls_sec = elf_hash_table (info)->tls_sec;
|
asection *tls_sec = elf_hash_table (info)->tls_sec;
|
|
|
BFD_ASSERT (tls_sec != NULL);
|
|
return tls_sec->vma - align_power ((bfd_vma) ARCH_SIZE / 4,
|
return tls_sec->vma - align_power ((bfd_vma) ARCH_SIZE / 4,
|
tls_sec->alignment_power);
|
tls_sec->alignment_power);
|
}
|
}
|
|
|
/* Return the base VMA address which should be subtracted from real addresses
|
/* Return the base VMA address which should be subtracted from real addresses
|
Line 4199... |
Line 4194... |
This is PT_TLS segment p_vaddr. */
|
This is PT_TLS segment p_vaddr. */
|
|
|
static bfd_vma
|
static bfd_vma
|
elfNN_ia64_dtprel_base (struct bfd_link_info *info)
|
elfNN_ia64_dtprel_base (struct bfd_link_info *info)
|
{
|
{
|
BFD_ASSERT (elf_hash_table (info)->tls_sec != NULL);
|
|
return elf_hash_table (info)->tls_sec->vma;
|
return elf_hash_table (info)->tls_sec->vma;
|
}
|
}
|
|
|
/* Called through qsort to sort the .IA_64.unwind section during a
|
/* Called through qsort to sort the .IA_64.unwind section during a
|
non-relocatable link. Set elfNN_ia64_unwind_entry_compare_bfd
|
non-relocatable link. Set elfNN_ia64_unwind_entry_compare_bfd
|
Line 4277... |
Line 4271... |
}
|
}
|
else
|
else
|
{
|
{
|
/* Pick a sensible value. */
|
/* Pick a sensible value. */
|
|
|
asection *got_sec = ia64_info->got_sec;
|
asection *got_sec = ia64_info->root.sgot;
|
|
|
/* Start with just the address of the .got. */
|
/* Start with just the address of the .got. */
|
if (got_sec)
|
if (got_sec)
|
gp_val = got_sec->output_section->vma;
|
gp_val = got_sec->output_section->vma;
|
else if (max_short_vma != 0)
|
else if (max_short_vma != 0)
|
Line 4830... |
Line 4824... |
if (dyn_i && dyn_i->want_plt2)
|
if (dyn_i && dyn_i->want_plt2)
|
{
|
{
|
/* Should have caught this earlier. */
|
/* Should have caught this earlier. */
|
BFD_ASSERT (rel->r_addend == 0);
|
BFD_ASSERT (rel->r_addend == 0);
|
|
|
value = (ia64_info->plt_sec->output_section->vma
|
value = (ia64_info->root.splt->output_section->vma
|
+ ia64_info->plt_sec->output_offset
|
+ ia64_info->root.splt->output_offset
|
+ dyn_i->plt2_offset);
|
+ dyn_i->plt2_offset);
|
}
|
}
|
else
|
else
|
{
|
{
|
/* Since there's no PLT entry, Validate that this is
|
/* Since there's no PLT entry, Validate that this is
|
Line 4969... |
Line 4963... |
break;
|
break;
|
|
|
case R_IA64_TPREL14:
|
case R_IA64_TPREL14:
|
case R_IA64_TPREL22:
|
case R_IA64_TPREL22:
|
case R_IA64_TPREL64I:
|
case R_IA64_TPREL64I:
|
|
if (elf_hash_table (info)->tls_sec == NULL)
|
|
goto missing_tls_sec;
|
value -= elfNN_ia64_tprel_base (info);
|
value -= elfNN_ia64_tprel_base (info);
|
r = elfNN_ia64_install_value (hit_addr, value, r_type);
|
r = elfNN_ia64_install_value (hit_addr, value, r_type);
|
break;
|
break;
|
|
|
case R_IA64_DTPREL14:
|
case R_IA64_DTPREL14:
|
Line 4980... |
Line 4976... |
case R_IA64_DTPREL64I:
|
case R_IA64_DTPREL64I:
|
case R_IA64_DTPREL32LSB:
|
case R_IA64_DTPREL32LSB:
|
case R_IA64_DTPREL32MSB:
|
case R_IA64_DTPREL32MSB:
|
case R_IA64_DTPREL64LSB:
|
case R_IA64_DTPREL64LSB:
|
case R_IA64_DTPREL64MSB:
|
case R_IA64_DTPREL64MSB:
|
|
if (elf_hash_table (info)->tls_sec == NULL)
|
|
goto missing_tls_sec;
|
value -= elfNN_ia64_dtprel_base (info);
|
value -= elfNN_ia64_dtprel_base (info);
|
r = elfNN_ia64_install_value (hit_addr, value, r_type);
|
r = elfNN_ia64_install_value (hit_addr, value, r_type);
|
break;
|
break;
|
|
|
case R_IA64_LTOFF_TPREL22:
|
case R_IA64_LTOFF_TPREL22:
|
Line 4998... |
Line 4996... |
{
|
{
|
default:
|
default:
|
case R_IA64_LTOFF_TPREL22:
|
case R_IA64_LTOFF_TPREL22:
|
if (!dynamic_symbol_p)
|
if (!dynamic_symbol_p)
|
{
|
{
|
|
if (elf_hash_table (info)->tls_sec == NULL)
|
|
goto missing_tls_sec;
|
if (!info->shared)
|
if (!info->shared)
|
value -= elfNN_ia64_tprel_base (info);
|
value -= elfNN_ia64_tprel_base (info);
|
else
|
else
|
{
|
{
|
r_addend += value - elfNN_ia64_dtprel_base (info);
|
r_addend += value - elfNN_ia64_dtprel_base (info);
|
Line 5015... |
Line 5015... |
value = 1;
|
value = 1;
|
got_r_type = R_IA64_DTPMOD64LSB;
|
got_r_type = R_IA64_DTPMOD64LSB;
|
break;
|
break;
|
case R_IA64_LTOFF_DTPREL22:
|
case R_IA64_LTOFF_DTPREL22:
|
if (!dynamic_symbol_p)
|
if (!dynamic_symbol_p)
|
|
{
|
|
if (elf_hash_table (info)->tls_sec == NULL)
|
|
goto missing_tls_sec;
|
value -= elfNN_ia64_dtprel_base (info);
|
value -= elfNN_ia64_dtprel_base (info);
|
|
}
|
got_r_type = R_IA64_DTPRELNNLSB;
|
got_r_type = R_IA64_DTPRELNNLSB;
|
break;
|
break;
|
}
|
}
|
dyn_i = get_dyn_sym_info (ia64_info, h, input_bfd, rel, FALSE);
|
dyn_i = get_dyn_sym_info (ia64_info, h, input_bfd, rel, FALSE);
|
value = set_got_entry (input_bfd, info, dyn_i, dynindx, r_addend,
|
value = set_got_entry (input_bfd, info, dyn_i, dynindx, r_addend,
|
Line 5066... |
Line 5070... |
|
|
case bfd_reloc_dangerous:
|
case bfd_reloc_dangerous:
|
case bfd_reloc_outofrange:
|
case bfd_reloc_outofrange:
|
case bfd_reloc_overflow:
|
case bfd_reloc_overflow:
|
default:
|
default:
|
|
missing_tls_sec:
|
{
|
{
|
const char *name;
|
const char *name;
|
|
|
if (h)
|
if (h)
|
name = h->root.root.string;
|
name = h->root.root.string;
|
Line 5077... |
Line 5082... |
name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym,
|
name = bfd_elf_sym_name (input_bfd, symtab_hdr, sym,
|
sym_sec);
|
sym_sec);
|
|
|
switch (r_type)
|
switch (r_type)
|
{
|
{
|
|
case R_IA64_TPREL14:
|
|
case R_IA64_TPREL22:
|
|
case R_IA64_TPREL64I:
|
|
case R_IA64_DTPREL14:
|
|
case R_IA64_DTPREL22:
|
|
case R_IA64_DTPREL64I:
|
|
case R_IA64_DTPREL32LSB:
|
|
case R_IA64_DTPREL32MSB:
|
|
case R_IA64_DTPREL64LSB:
|
|
case R_IA64_DTPREL64MSB:
|
|
case R_IA64_LTOFF_TPREL22:
|
|
case R_IA64_LTOFF_DTPMOD22:
|
|
case R_IA64_LTOFF_DTPREL22:
|
|
(*_bfd_error_handler)
|
|
(_("%B: missing TLS section for relocation %s against `%s' at 0x%lx in section `%A'."),
|
|
input_bfd, input_section, howto->name, name,
|
|
rel->r_offset);
|
|
break;
|
|
|
case R_IA64_PCREL21B:
|
case R_IA64_PCREL21B:
|
case R_IA64_PCREL21BI:
|
case R_IA64_PCREL21BI:
|
case R_IA64_PCREL21M:
|
case R_IA64_PCREL21M:
|
case R_IA64_PCREL21F:
|
case R_IA64_PCREL21F:
|
if (is_elf_hash_table (info->hash))
|
if (is_elf_hash_table (info->hash))
|
Line 5139... |
Line 5163... |
gp_val = _bfd_get_gp_value (output_bfd);
|
gp_val = _bfd_get_gp_value (output_bfd);
|
|
|
/* Initialize the minimal PLT entry. */
|
/* Initialize the minimal PLT entry. */
|
|
|
index = (dyn_i->plt_offset - PLT_HEADER_SIZE) / PLT_MIN_ENTRY_SIZE;
|
index = (dyn_i->plt_offset - PLT_HEADER_SIZE) / PLT_MIN_ENTRY_SIZE;
|
plt_sec = ia64_info->plt_sec;
|
plt_sec = ia64_info->root.splt;
|
loc = plt_sec->contents + dyn_i->plt_offset;
|
loc = plt_sec->contents + dyn_i->plt_offset;
|
|
|
memcpy (loc, plt_min_entry, PLT_MIN_ENTRY_SIZE);
|
memcpy (loc, plt_min_entry, PLT_MIN_ENTRY_SIZE);
|
elfNN_ia64_install_value (loc, index, R_IA64_IMM22);
|
elfNN_ia64_install_value (loc, index, R_IA64_IMM22);
|
elfNN_ia64_install_value (loc+2, -dyn_i->plt_offset, R_IA64_PCREL21B);
|
elfNN_ia64_install_value (loc+2, -dyn_i->plt_offset, R_IA64_PCREL21B);
|
Line 5268... |
Line 5292... |
|
|
bfd_elfNN_swap_dyn_out (abfd, &dyn, dyncon);
|
bfd_elfNN_swap_dyn_out (abfd, &dyn, dyncon);
|
}
|
}
|
|
|
/* Initialize the PLT0 entry. */
|
/* Initialize the PLT0 entry. */
|
if (ia64_info->plt_sec)
|
if (ia64_info->root.splt)
|
{
|
{
|
bfd_byte *loc = ia64_info->plt_sec->contents;
|
bfd_byte *loc = ia64_info->root.splt->contents;
|
bfd_vma pltres;
|
bfd_vma pltres;
|
|
|
memcpy (loc, plt_header, PLT_HEADER_SIZE);
|
memcpy (loc, plt_header, PLT_HEADER_SIZE);
|
|
|
pltres = (sgotplt->output_section->vma
|
pltres = (sgotplt->output_section->vma
|
Line 5577... |
Line 5601... |
asym->flags &= ~BSF_GLOBAL;
|
asym->flags &= ~BSF_GLOBAL;
|
break;
|
break;
|
}
|
}
|
}
|
}
|
|
|
|
static bfd_boolean
|
|
elfNN_vms_section_from_shdr (bfd *abfd,
|
|
Elf_Internal_Shdr *hdr,
|
|
const char *name,
|
|
int shindex)
|
|
{
|
|
asection *newsect;
|
|
|
|
switch (hdr->sh_type)
|
|
{
|
|
case SHT_IA_64_VMS_TRACE:
|
|
case SHT_IA_64_VMS_DEBUG:
|
|
case SHT_IA_64_VMS_DEBUG_STR:
|
|
break;
|
|
|
|
default:
|
|
return elfNN_ia64_section_from_shdr (abfd, hdr, name, shindex);
|
|
}
|
|
|
|
if (! _bfd_elf_make_section_from_shdr (abfd, hdr, name, shindex))
|
|
return FALSE;
|
|
newsect = hdr->bfd_section;
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static bfd_boolean
|
|
elfNN_vms_object_p (bfd *abfd)
|
|
{
|
|
Elf_Internal_Ehdr *i_ehdrp = elf_elfheader (abfd);
|
|
Elf_Internal_Phdr *i_phdr = elf_tdata (abfd)->phdr;
|
|
unsigned int i;
|
|
unsigned int num_text = 0;
|
|
unsigned int num_data = 0;
|
|
unsigned int num_rodata = 0;
|
|
char name[16];
|
|
|
|
if (!elfNN_ia64_object_p (abfd))
|
|
return FALSE;
|
|
|
|
for (i = 0; i < i_ehdrp->e_phnum; i++, i_phdr++)
|
|
{
|
|
/* Is there a section for this segment? */
|
|
bfd_vma base_vma = i_phdr->p_vaddr;
|
|
bfd_vma limit_vma = base_vma + i_phdr->p_filesz;
|
|
|
|
if (i_phdr->p_type != PT_LOAD)
|
|
continue;
|
|
|
|
again:
|
|
while (base_vma < limit_vma)
|
|
{
|
|
bfd_vma next_vma = limit_vma;
|
|
asection *nsec;
|
|
asection *sec;
|
|
flagword flags;
|
|
char *nname = NULL;
|
|
|
|
/* Find a section covering base_vma. */
|
|
for (sec = abfd->sections; sec != NULL; sec = sec->next)
|
|
{
|
|
if ((sec->flags & (SEC_ALLOC | SEC_LOAD)) == 0)
|
|
continue;
|
|
if (sec->vma <= base_vma && sec->vma + sec->size > base_vma)
|
|
{
|
|
base_vma = sec->vma + sec->size;
|
|
goto again;
|
|
}
|
|
if (sec->vma < next_vma && sec->vma + sec->size >= base_vma)
|
|
next_vma = sec->vma;
|
|
}
|
|
|
|
/* No section covering [base_vma; next_vma). Create a fake one. */
|
|
flags = SEC_ALLOC | SEC_LOAD | SEC_HAS_CONTENTS;
|
|
if (i_phdr->p_flags & PF_X)
|
|
{
|
|
flags |= SEC_CODE;
|
|
if (num_text++ == 0)
|
|
nname = ".text";
|
|
else
|
|
sprintf (name, ".text$%u", num_text);
|
|
}
|
|
else if ((i_phdr->p_flags & (PF_R | PF_W)) == PF_R)
|
|
{
|
|
flags |= SEC_READONLY;
|
|
sprintf (name, ".rodata$%u", num_rodata++);
|
|
}
|
|
else
|
|
{
|
|
flags |= SEC_DATA;
|
|
sprintf (name, ".data$%u", num_data++);
|
|
}
|
|
|
|
/* Allocate name. */
|
|
if (nname == NULL)
|
|
{
|
|
size_t name_len = strlen (name) + 1;
|
|
nname = bfd_alloc (abfd, name_len);
|
|
if (nname == NULL)
|
|
return FALSE;
|
|
memcpy (nname, name, name_len);
|
|
}
|
|
|
|
/* Create and fill new section. */
|
|
nsec = bfd_make_section_anyway_with_flags (abfd, nname, flags);
|
|
if (nsec == NULL)
|
|
return FALSE;
|
|
nsec->vma = base_vma;
|
|
nsec->size = next_vma - base_vma;
|
|
nsec->filepos = i_phdr->p_offset + (base_vma - i_phdr->p_vaddr);
|
|
|
|
base_vma = next_vma;
|
|
}
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
static void
|
|
elfNN_vms_post_process_headers (bfd *abfd,
|
|
struct bfd_link_info *info ATTRIBUTE_UNUSED)
|
|
{
|
|
Elf_Internal_Ehdr *i_ehdrp = elf_elfheader (abfd);
|
|
|
|
i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_OPENVMS;
|
|
i_ehdrp->e_ident[EI_ABIVERSION] = 2;
|
|
}
|
|
|
|
static bfd_boolean
|
|
elfNN_vms_section_processing (bfd *abfd ATTRIBUTE_UNUSED,
|
|
Elf_Internal_Shdr *hdr)
|
|
{
|
|
if (hdr->bfd_section != NULL)
|
|
{
|
|
const char *name = bfd_get_section_name (abfd, hdr->bfd_section);
|
|
|
|
if (strcmp (name, ".text") == 0)
|
|
hdr->sh_flags |= SHF_IA_64_VMS_SHARED;
|
|
else if ((strcmp (name, ".debug") == 0)
|
|
|| (strcmp (name, ".debug_abbrev") == 0)
|
|
|| (strcmp (name, ".debug_aranges") == 0)
|
|
|| (strcmp (name, ".debug_frame") == 0)
|
|
|| (strcmp (name, ".debug_info") == 0)
|
|
|| (strcmp (name, ".debug_loc") == 0)
|
|
|| (strcmp (name, ".debug_macinfo") == 0)
|
|
|| (strcmp (name, ".debug_pubnames") == 0)
|
|
|| (strcmp (name, ".debug_pubtypes") == 0))
|
|
hdr->sh_type = SHT_IA_64_VMS_DEBUG;
|
|
else if ((strcmp (name, ".debug_line") == 0)
|
|
|| (strcmp (name, ".debug_ranges") == 0))
|
|
hdr->sh_type = SHT_IA_64_VMS_TRACE;
|
|
else if (strcmp (name, ".debug_str") == 0)
|
|
hdr->sh_type = SHT_IA_64_VMS_DEBUG_STR;
|
|
else if (strcmp (name, ".vms_display_name_info") == 0)
|
|
{
|
|
int idx, symcount;
|
|
asymbol **syms;
|
|
struct elf_obj_tdata *t = elf_tdata (abfd);
|
|
int buf[2];
|
|
int demangler_sym_idx = -1;
|
|
|
|
symcount = bfd_get_symcount (abfd);
|
|
syms = bfd_get_outsymbols (abfd);
|
|
for (idx = 0; idx < symcount; idx++)
|
|
{
|
|
asymbol *sym;
|
|
sym = syms[idx];
|
|
if ((sym->flags & (BSF_DEBUGGING | BSF_DYNAMIC))
|
|
&& strchr (sym->name, '@')
|
|
&& (strcmp (sym->section->name, BFD_ABS_SECTION_NAME) == 0))
|
|
{
|
|
demangler_sym_idx = sym->udata.i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
hdr->sh_type = SHT_IA_64_VMS_DISPLAY_NAME_INFO;
|
|
hdr->sh_entsize = 4;
|
|
hdr->sh_addralign = 0;
|
|
hdr->sh_link = t->symtab_section;
|
|
|
|
/* Find symtab index of demangler routine and stuff it in
|
|
the second long word of section data. */
|
|
|
|
if (demangler_sym_idx > -1)
|
|
{
|
|
bfd_seek (abfd, hdr->sh_offset, SEEK_SET);
|
|
bfd_bread (buf, hdr->sh_size, abfd);
|
|
buf [1] = demangler_sym_idx;
|
|
bfd_seek (abfd, hdr->sh_offset, SEEK_SET);
|
|
bfd_bwrite (buf, hdr->sh_size, abfd);
|
|
}
|
|
}
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
/* The final processing done just before writing out a VMS IA-64 ELF
|
|
object file. */
|
|
|
|
static void
|
|
elfNN_vms_final_write_processing (bfd *abfd,
|
|
bfd_boolean linker ATTRIBUTE_UNUSED)
|
|
{
|
|
Elf_Internal_Shdr *hdr;
|
|
asection *s;
|
|
int unwind_info_sect_idx = 0;
|
|
|
|
for (s = abfd->sections; s; s = s->next)
|
|
{
|
|
hdr = &elf_section_data (s)->this_hdr;
|
|
|
|
if (strcmp (bfd_get_section_name (abfd, hdr->bfd_section),
|
|
".IA_64.unwind_info") == 0)
|
|
unwind_info_sect_idx = elf_section_data (s)->this_idx;
|
|
|
|
switch (hdr->sh_type)
|
|
{
|
|
case SHT_IA_64_UNWIND:
|
|
/* VMS requires sh_info to point to the unwind info section. */
|
|
hdr->sh_info = unwind_info_sect_idx;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (! elf_flags_init (abfd))
|
|
{
|
|
unsigned long flags = 0;
|
|
|
|
if (abfd->xvec->byteorder == BFD_ENDIAN_BIG)
|
|
flags |= EF_IA_64_BE;
|
|
if (bfd_get_mach (abfd) == bfd_mach_ia64_elf64)
|
|
flags |= EF_IA_64_ABI64;
|
|
|
|
elf_elfheader(abfd)->e_flags = flags;
|
|
elf_flags_init (abfd) = TRUE;
|
|
}
|
|
}
|
|
|
|
static bfd_boolean
|
|
elfNN_vms_close_and_cleanup (bfd *abfd)
|
|
{
|
|
if (bfd_get_format (abfd) == bfd_object)
|
|
{
|
|
long isize, irsize;
|
|
|
|
if (elf_shstrtab (abfd) != NULL)
|
|
_bfd_elf_strtab_free (elf_shstrtab (abfd));
|
|
|
|
/* Pad to 8 byte boundary for IPF/VMS. */
|
|
isize = bfd_get_size (abfd);
|
|
if ((irsize = isize/8*8) < isize)
|
|
{
|
|
int ishort = (irsize + 8) - isize;
|
|
bfd_seek (abfd, isize, SEEK_SET);
|
|
bfd_bwrite (bfd_zmalloc (ishort), ishort, abfd);
|
|
}
|
|
}
|
|
|
|
return _bfd_generic_close_and_cleanup (abfd);
|
|
}
|
|
|
#define TARGET_LITTLE_SYM bfd_elfNN_ia64_little_vec
|
#define TARGET_LITTLE_SYM bfd_elfNN_ia64_little_vec
|
#define TARGET_LITTLE_NAME "elfNN-ia64-little"
|
#define TARGET_LITTLE_NAME "elfNN-ia64-little"
|
#define TARGET_BIG_SYM bfd_elfNN_ia64_big_vec
|
#define TARGET_BIG_SYM bfd_elfNN_ia64_big_vec
|
#define TARGET_BIG_NAME "elfNN-ia64-big"
|
#define TARGET_BIG_NAME "elfNN-ia64-big"
|
Line 5709... |
Line 5994... |
#undef elfNN_bed
|
#undef elfNN_bed
|
#define elfNN_bed elfNN_ia64_hpux_bed
|
#define elfNN_bed elfNN_ia64_hpux_bed
|
|
|
#include "elfNN-target.h"
|
#include "elfNN-target.h"
|
|
|
|
/* VMS-specific vectors. */
|
|
|
|
#undef TARGET_LITTLE_SYM
|
|
#define TARGET_LITTLE_SYM bfd_elfNN_ia64_vms_vec
|
|
#undef TARGET_LITTLE_NAME
|
|
#define TARGET_LITTLE_NAME "elfNN-ia64-vms"
|
|
#undef TARGET_BIG_SYM
|
|
#undef TARGET_BIG_NAME
|
|
|
|
/* These are VMS specific functions. */
|
|
|
|
#undef elf_backend_object_p
|
|
#define elf_backend_object_p elfNN_vms_object_p
|
|
|
|
#undef elf_backend_section_from_shdr
|
|
#define elf_backend_section_from_shdr elfNN_vms_section_from_shdr
|
|
|
|
#undef elf_backend_post_process_headers
|
|
#define elf_backend_post_process_headers elfNN_vms_post_process_headers
|
|
|
|
#undef elf_backend_section_processing
|
|
#define elf_backend_section_processing elfNN_vms_section_processing
|
|
|
|
#undef elf_backend_final_write_processing
|
|
#define elf_backend_final_write_processing elfNN_vms_final_write_processing
|
|
|
|
#undef bfd_elfNN_close_and_cleanup
|
|
#define bfd_elfNN_close_and_cleanup elfNN_vms_close_and_cleanup
|
|
|
|
#undef elf_backend_section_from_bfd_section
|
|
|
|
#undef elf_backend_symbol_processing
|
|
|
#undef elf_backend_want_p_paddr_set_to_zero
|
#undef elf_backend_want_p_paddr_set_to_zero
|
|
|
No newline at end of file
|
No newline at end of file
|
|
#undef ELF_OSABI
|
|
#define ELF_OSABI ELFOSABI_OPENVMS
|
|
|
|
#undef ELF_MAXPAGESIZE
|
|
#define ELF_MAXPAGESIZE 0x10000 /* 64KB */
|
|
|
|
#undef elfNN_bed
|
|
#define elfNN_bed elfNN_ia64_vms_bed
|
|
|
|
#include "elfNN-target.h"
|
|
|
No newline at end of file
|
No newline at end of file
|