/* Alpha specific support for 64-bit ELF
- Copyright 1996, 1997, 1998, 1999, 2000, 2001
+ Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002
Free Software Foundation, Inc.
Contributed by Richard Henderson <rth@tamu.edu>.
static Elf_Internal_Rela * elf64_alpha_find_reloc_at_ofs
PARAMS ((Elf_Internal_Rela *, Elf_Internal_Rela *, bfd_vma, int));
static enum elf_reloc_type_class elf64_alpha_reloc_type_class
- PARAMS ((int));
+ PARAMS ((const Elf_Internal_Rela *));
\f
struct alpha_elf_link_hash_entry
{
bfd *gotobj;
/* the addend in effect for this entry. */
- bfd_signed_vma addend;
+ bfd_vma addend;
/* the .got offset for this entry. */
int got_offset;
int flags;
- /* An additional flag. */
+ /* Additional flags. */
#define ALPHA_ELF_GOT_ENTRY_RELOCS_DONE 0x10
+#define ALPHA_ELF_GOT_ENTRY_RELOCS_XLATED 0x20
int use_count;
} *got_entries;
bfd *abfd;
{
struct alpha_elf_link_hash_table *ret;
+ bfd_size_type amt = sizeof (struct alpha_elf_link_hash_table);
- ret = ((struct alpha_elf_link_hash_table *)
- bfd_zalloc (abfd, sizeof (struct alpha_elf_link_hash_table)));
+ ret = (struct alpha_elf_link_hash_table *) bfd_zalloc (abfd, amt);
if (ret == (struct alpha_elf_link_hash_table *) NULL)
return NULL;
elf64_alpha_mkobject (abfd)
bfd *abfd;
{
- abfd->tdata.any = bfd_zalloc (abfd, sizeof (struct alpha_elf_obj_tdata));
+ bfd_size_type amt = sizeof (struct alpha_elf_obj_tdata);
+ abfd->tdata.any = bfd_zalloc (abfd, amt);
if (abfd->tdata.any == NULL)
return false;
return true;
{
/* Allocate our special target data. */
struct alpha_elf_obj_tdata *new_tdata;
- new_tdata = bfd_zalloc (abfd, sizeof (struct alpha_elf_obj_tdata));
+ bfd_size_type amt = sizeof (struct alpha_elf_obj_tdata);
+ new_tdata = bfd_zalloc (abfd, amt);
if (new_tdata == NULL)
return false;
new_tdata->root = *abfd->tdata.elf_obj_data;
false,
0,
0,
- true)
+ true),
+
+ /* A 21 bit branch that adjusts for gp loads. */
+ HOWTO (R_ALPHA_BRSGP, /* type */
+ 2, /* rightshift */
+ 2, /* size (0 = byte, 1 = short, 2 = long) */
+ 21, /* bitsize */
+ true, /* pc_relative */
+ 0, /* bitpos */
+ complain_overflow_signed, /* complain_on_overflow */
+ 0, /* special_function */
+ "BRSGP", /* name */
+ false, /* partial_inplace */
+ 0x1fffff, /* src_mask */
+ 0x1fffff, /* dst_mask */
+ true), /* pcrel_offset */
};
/* A relocation function which doesn't do anything. */
| (((gpdisp >> 16) + ((gpdisp >> 15) & 1)) & 0xffff));
i_lda = (i_lda & 0xffff0000) | (gpdisp & 0xffff);
- bfd_put_32 (abfd, i_ldah, p_ldah);
- bfd_put_32 (abfd, i_lda, p_lda);
+ bfd_put_32 (abfd, (bfd_vma) i_ldah, p_ldah);
+ bfd_put_32 (abfd, (bfd_vma) i_lda, p_lda);
return ret;
}
{BFD_RELOC_ALPHA_GPREL_HI16, R_ALPHA_GPRELHIGH},
{BFD_RELOC_ALPHA_GPREL_LO16, R_ALPHA_GPRELLOW},
{BFD_RELOC_GPREL16, R_ALPHA_GPREL16},
+ {BFD_RELOC_ALPHA_BRSGP, R_ALPHA_BRSGP},
};
/* Given a BFD reloc type, return a HOWTO structure. */
#define OP_LDQ 0x29
#define OP_BR 0x30
#define OP_BSR 0x34
-#define INSN_UNOP 0x2fe00000
+#define INSN_UNOP 0x2ffe0000
struct alpha_relax_info
{
{
((*_bfd_error_handler)
("%s: %s+0x%lx: warning: LITERAL relocation against unexpected insn",
- bfd_get_filename (info->abfd), info->sec->name,
- (unsigned long)irel->r_offset));
+ bfd_archive_filename (info->abfd), info->sec->name,
+ (unsigned long) irel->r_offset));
return irel;
}
{
if (ELF64_R_TYPE (urel->r_info) != R_ALPHA_LITUSE)
break;
- if (urel->r_addend >= 0 && urel->r_addend <= 3)
+ if (urel->r_addend <= 3)
flags |= 1 << urel->r_addend;
}
urel->r_addend = irel->r_addend;
info->changed_relocs = true;
- bfd_put_32 (info->abfd, insn, info->contents + urel->r_offset);
+ bfd_put_32 (info->abfd, (bfd_vma) insn,
+ info->contents + urel->r_offset);
info->changed_contents = true;
}
irel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info),
R_ALPHA_GPRELHIGH);
lit_insn = (OP_LDAH << 26) | (lit_insn & 0x03ff0000);
- bfd_put_32 (info->abfd, lit_insn,
+ bfd_put_32 (info->abfd, (bfd_vma) lit_insn,
info->contents + irel->r_offset);
lit_reused = true;
info->changed_contents = true;
/* FIXME: sanity check the insn for byte op. Check that the
literal dest reg is indeed Rb in the byte insn. */
- insn = (insn & ~0x001ff000) | ((symval & 7) << 13) | 0x1000;
+ insn &= ~ (unsigned) 0x001ff000;
+ insn |= ((symval & 7) << 13) | 0x1000;
urel->r_info = ELF64_R_INFO (0, R_ALPHA_NONE);
urel->r_addend = 0;
info->changed_relocs = true;
- bfd_put_32 (info->abfd, insn, info->contents + urel->r_offset);
+ bfd_put_32 (info->abfd, (bfd_vma) insn,
+ info->contents + urel->r_offset);
info->changed_contents = true;
break;
else
all_optimized = false;
- bfd_put_32 (info->abfd, insn, info->contents + urel->r_offset);
+ bfd_put_32 (info->abfd, (bfd_vma) insn,
+ info->contents + urel->r_offset);
/* Kill any HINT reloc that might exist for this insn. */
xrel = (elf64_alpha_find_reloc_at_ofs
In that case the insn would use $27 as the base. */
if (ldah == 0x27ba0000 && lda == 0x23bd0000)
{
- bfd_put_32 (info->abfd, INSN_UNOP, p_ldah);
- bfd_put_32 (info->abfd, INSN_UNOP, p_lda);
+ bfd_put_32 (info->abfd, (bfd_vma) INSN_UNOP, p_ldah);
+ bfd_put_32 (info->abfd, (bfd_vma) INSN_UNOP, p_lda);
gpdisp->r_info = ELF64_R_INFO (0, R_ALPHA_NONE);
info->changed_contents = true;
irel->r_info = ELF64_R_INFO (0, R_ALPHA_NONE);
info->changed_relocs = true;
- bfd_put_32 (info->abfd, INSN_UNOP, info->contents + irel->r_offset);
+ bfd_put_32 (info->abfd, (bfd_vma) INSN_UNOP,
+ info->contents + irel->r_offset);
info->changed_contents = true;
}
}
{
((*_bfd_error_handler)
("%s: %s+0x%lx: warning: LITERAL relocation against unexpected insn",
- bfd_get_filename (info->abfd), info->sec->name,
+ bfd_archive_filename (info->abfd), info->sec->name,
(unsigned long) irel->r_offset));
return true;
}
`ldq R,X(gp)' for `lda R,Y(gp)'. */
insn = (OP_LDA << 26) | (insn & 0x03ff0000);
- bfd_put_32 (info->abfd, insn, info->contents + irel->r_offset);
+ bfd_put_32 (info->abfd, (bfd_vma) insn, info->contents + irel->r_offset);
info->changed_contents = true;
irel->r_info = ELF64_R_INFO (ELF64_R_SYM (irel->r_info), R_ALPHA_GPREL16);
boolean *again;
{
Elf_Internal_Shdr *symtab_hdr;
+ Elf_Internal_Shdr *shndx_hdr;
Elf_Internal_Rela *internal_relocs;
Elf_Internal_Rela *free_relocs = NULL;
Elf_Internal_Rela *irel, *irelend;
bfd_byte *free_contents = NULL;
Elf64_External_Sym *extsyms = NULL;
Elf64_External_Sym *free_extsyms = NULL;
+ Elf_External_Sym_Shndx *shndx_buf = NULL;
struct alpha_elf_got_entry **local_got_entries;
struct alpha_relax_info info;
/* Read this BFD's symbols if we haven't done so already. */
if (extsyms == NULL)
{
+ bfd_size_type amt;
+
if (symtab_hdr->contents != NULL)
extsyms = (Elf64_External_Sym *) symtab_hdr->contents;
else
{
- extsyms = ((Elf64_External_Sym *)
- bfd_malloc (symtab_hdr->sh_size));
+ amt = symtab_hdr->sh_info;
+ amt *= sizeof (Elf64_External_Sym);
+ extsyms = (Elf64_External_Sym *) bfd_malloc (amt);
if (extsyms == NULL)
goto error_return;
free_extsyms = extsyms;
if (bfd_seek (abfd, symtab_hdr->sh_offset, SEEK_SET) != 0
- || (bfd_read (extsyms, 1, symtab_hdr->sh_size, abfd)
- != symtab_hdr->sh_size))
+ || bfd_bread ((PTR) extsyms, amt, abfd) != amt)
+ goto error_return;
+ }
+
+ shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
+ if (shndx_hdr->sh_size != 0)
+ {
+ amt = symtab_hdr->sh_info;
+ amt *= sizeof (Elf_External_Sym_Shndx);
+ shndx_buf = (Elf_External_Sym_Shndx *) bfd_malloc (amt);
+ if (shndx_buf == NULL)
+ goto error_return;
+ if (bfd_seek (abfd, shndx_hdr->sh_offset, SEEK_SET) != 0
+ || bfd_bread ((PTR) shndx_buf, amt, abfd) != amt)
goto error_return;
}
}
if (ELF64_R_SYM (irel->r_info) < symtab_hdr->sh_info)
{
/* A local symbol. */
- bfd_elf64_swap_symbol_in (abfd,
- extsyms + ELF64_R_SYM (irel->r_info),
- &isym);
+ Elf64_External_Sym *esym;
+ Elf_External_Sym_Shndx *shndx;
+
+ esym = extsyms + ELF64_R_SYM (irel->r_info);
+ shndx = shndx_buf + (shndx_buf ? ELF64_R_SYM (irel->r_info) : 0);
+ bfd_elf64_swap_symbol_in (abfd, esym, shndx, &isym);
if (isym.st_shndx == SHN_UNDEF)
info.tsec = bfd_und_section_ptr;
- else if (isym.st_shndx > 0 && isym.st_shndx < SHN_LORESERVE)
- info.tsec = bfd_section_from_elf_index (abfd, isym.st_shndx);
else if (isym.st_shndx == SHN_ABS)
info.tsec = bfd_abs_section_ptr;
else if (isym.st_shndx == SHN_COMMON)
info.tsec = bfd_com_section_ptr;
else
- continue; /* who knows. */
+ info.tsec = bfd_section_from_elf_index (abfd, isym.st_shndx);
info.h = NULL;
info.other = isym.st_other;
}
}
+ if (shndx_buf != NULL)
+ free (shndx_buf);
+
if (free_extsyms != NULL)
{
if (! link_info->keep_memory)
else
{
/* Cache the symbols for elf_link_input_bfd. */
- symtab_hdr->contents = extsyms;
+ symtab_hdr->contents = (unsigned char *) extsyms;
}
}
free (free_relocs);
if (free_contents != NULL)
free (free_contents);
+ if (shndx_buf != NULL)
+ free (shndx_buf);
if (free_extsyms != NULL)
free (free_extsyms);
return false;
\f
/* PLT/GOT Stuff */
#define PLT_HEADER_SIZE 32
-#define PLT_HEADER_WORD1 0xc3600000 /* br $27,.+4 */
-#define PLT_HEADER_WORD2 0xa77b000c /* ldq $27,12($27) */
-#define PLT_HEADER_WORD3 0x47ff041f /* nop */
-#define PLT_HEADER_WORD4 0x6b7b0000 /* jmp $27,($27) */
+#define PLT_HEADER_WORD1 (bfd_vma) 0xc3600000 /* br $27,.+4 */
+#define PLT_HEADER_WORD2 (bfd_vma) 0xa77b000c /* ldq $27,12($27) */
+#define PLT_HEADER_WORD3 (bfd_vma) 0x47ff041f /* nop */
+#define PLT_HEADER_WORD4 (bfd_vma) 0x6b7b0000 /* jmp $27,($27) */
#define PLT_ENTRY_SIZE 12
#define PLT_ENTRY_WORD1 0xc3800000 /* br $28, plt0 */
swap = get_elf_backend_data (abfd)->elf_backend_ecoff_debug_swap;
memset (debug, 0, sizeof (*debug));
- ext_hdr = (char *) bfd_malloc ((size_t) swap->external_hdr_size);
+ ext_hdr = (char *) bfd_malloc (swap->external_hdr_size);
if (ext_hdr == NULL && swap->external_hdr_size != 0)
goto error_return;
debug->ptr = NULL; \
else \
{ \
- debug->ptr = (type) bfd_malloc ((size_t) (size * symhdr->count)); \
+ bfd_size_type amt = (bfd_size_type) size * symhdr->count; \
+ debug->ptr = (type) bfd_malloc (amt); \
if (debug->ptr == NULL) \
goto error_return; \
if (bfd_seek (abfd, (file_ptr) symhdr->offset, SEEK_SET) != 0 \
- || (bfd_read (debug->ptr, size, symhdr->count, \
- abfd) != size * symhdr->count)) \
+ || bfd_bread (debug->ptr, amt, abfd) != amt) \
goto error_return; \
}
char *fraw_src;
char *fraw_end;
struct fdr *fdr_ptr;
+ bfd_size_type amt = sizeof (struct mips_elf_find_line);
- fi = ((struct mips_elf_find_line *)
- bfd_zalloc (abfd, sizeof (struct mips_elf_find_line)));
+ fi = (struct mips_elf_find_line *) bfd_zalloc (abfd, amt);
if (fi == NULL)
{
msec->flags = origflags;
}
/* Swap in the FDR information. */
- fi->d.fdr = ((struct fdr *)
- bfd_alloc (abfd,
- (fi->d.symbolic_header.ifdMax *
- sizeof (struct fdr))));
+ amt = fi->d.symbolic_header.ifdMax * sizeof (struct fdr);
+ fi->d.fdr = (struct fdr *) bfd_alloc (abfd, amt);
if (fi->d.fdr == NULL)
{
msec->flags = origflags;
struct alpha_elf_got_entry **local_got_entries;
const Elf_Internal_Rela *rel, *relend;
int got_created;
+ bfd_size_type amt;
if (info->relocateable)
return true;
if (!gotent)
{
+ amt = sizeof (struct alpha_elf_got_entry);
gotent = ((struct alpha_elf_got_entry *)
- bfd_alloc (abfd,
- sizeof (struct alpha_elf_got_entry)));
+ bfd_alloc (abfd, amt));
if (!gotent)
return false;
/* This is a local .got entry -- record for merge. */
if (!local_got_entries)
{
- size_t size;
- size = (symtab_hdr->sh_info
- * sizeof (struct alpha_elf_got_entry *));
+ bfd_size_type size;
+ size = symtab_hdr->sh_info;
+ size *= sizeof (struct alpha_elf_got_entry *);
local_got_entries = ((struct alpha_elf_got_entry **)
bfd_alloc (abfd, size));
if (!local_got_entries)
return false;
- memset (local_got_entries, 0, size);
+ memset (local_got_entries, 0, (size_t) size);
alpha_elf_tdata (abfd)->local_got_entries =
local_got_entries;
}
continue;
if (!gotent)
{
+ amt = sizeof (struct alpha_elf_got_entry);
gotent = ((struct alpha_elf_got_entry *)
- bfd_alloc (abfd,
- sizeof (struct alpha_elf_got_entry)));
+ bfd_alloc (abfd, amt));
if (!gotent)
return false;
case R_ALPHA_GPREL32:
case R_ALPHA_GPRELHIGH:
case R_ALPHA_GPRELLOW:
+ case R_ALPHA_BRSGP:
/* We don't actually use the .got here, but the sections must
be created before the linker maps input sections to output
sections. */
sreloc = bfd_get_section_by_name (dynobj, rel_sec_name);
if (sreloc == NULL)
{
+ flagword flags;
+
sreloc = bfd_make_section (dynobj, rel_sec_name);
+ flags = (SEC_HAS_CONTENTS | SEC_IN_MEMORY
+ | SEC_LINKER_CREATED | SEC_READONLY);
+ if (sec->flags & SEC_ALLOC)
+ flags |= SEC_ALLOC | SEC_LOAD;
if (sreloc == NULL
- || !bfd_set_section_flags (dynobj, sreloc,
- (((sec->flags
- & SEC_ALLOC)
- ? (SEC_ALLOC
- | SEC_LOAD) : 0)
- | SEC_HAS_CONTENTS
- | SEC_IN_MEMORY
- | SEC_LINKER_CREATED
- | SEC_READONLY))
+ || !bfd_set_section_flags (dynobj, sreloc, flags)
|| !bfd_set_section_alignment (dynobj, sreloc, 3))
return false;
}
if (!rent)
{
- rent = ((struct alpha_elf_reloc_entry *)
- bfd_alloc (abfd,
- sizeof (struct alpha_elf_reloc_entry)));
+ amt = sizeof (struct alpha_elf_reloc_entry);
+ rent = (struct alpha_elf_reloc_entry *) bfd_alloc (abfd, amt);
if (!rent)
return false;
rent->srel = sreloc;
rent->rtype = r_type;
rent->count = 1;
- rent->reltext = (sec->flags & SEC_READONLY) != 0;
+ rent->reltext = ((sec->flags & (SEC_READONLY | SEC_ALLOC))
+ == (SEC_READONLY | SEC_ALLOC));
rent->next = h->reloc_entries;
h->reloc_entries = rent;
/* Now that we've seen all of the input symbols, finalize our decision
about whether this symbol should get a .plt entry. */
- if (h->root.type != bfd_link_hash_undefweak
- && alpha_elf_dynamic_symbol_p (h, info)
+ if (alpha_elf_dynamic_symbol_p (h, info)
&& ((h->type == STT_FUNC
&& !(ah->flags & ALPHA_ELF_LINK_HASH_LU_ADDR))
|| (h->type == STT_NOTYPE
/* Yikes! A single object file has too many entries. */
(*_bfd_error_handler)
(_("%s: .got subsegment exceeds 64K (size %d)"),
- bfd_get_filename (i),
+ bfd_archive_filename (i),
alpha_elf_tdata (this_got)->total_got_entries * 8);
return false;
}
else
{
/* Allocate memory for the section contents. */
- s->contents = (bfd_byte *) bfd_zalloc(dynobj, s->_raw_size);
+ s->contents = (bfd_byte *) bfd_zalloc (dynobj, s->_raw_size);
if (s->contents == NULL && s->_raw_size != 0)
return false;
}
must add the entries now so that we get the correct size for
the .dynamic section. The DT_DEBUG entry is filled in by the
dynamic linker and used by the debugger. */
+#define add_dynamic_entry(TAG, VAL) \
+ bfd_elf64_add_dynamic_entry (info, (bfd_vma) (TAG), (bfd_vma) (VAL))
+
if (!info->shared)
{
- if (!bfd_elf64_add_dynamic_entry (info, DT_DEBUG, 0))
+ if (!add_dynamic_entry (DT_DEBUG, 0))
return false;
}
- if (! bfd_elf64_add_dynamic_entry (info, DT_PLTGOT, 0))
+ if (!add_dynamic_entry (DT_PLTGOT, 0))
return false;
if (relplt)
{
- if (! bfd_elf64_add_dynamic_entry (info, DT_PLTRELSZ, 0)
- || ! bfd_elf64_add_dynamic_entry (info, DT_PLTREL, DT_RELA)
- || ! bfd_elf64_add_dynamic_entry (info, DT_JMPREL, 0))
+ if (!add_dynamic_entry (DT_PLTRELSZ, 0)
+ || !add_dynamic_entry (DT_PLTREL, DT_RELA)
+ || !add_dynamic_entry (DT_JMPREL, 0))
return false;
}
- if (! bfd_elf64_add_dynamic_entry (info, DT_RELA, 0)
- || ! bfd_elf64_add_dynamic_entry (info, DT_RELASZ, 0)
- || ! bfd_elf64_add_dynamic_entry (info, DT_RELAENT,
- sizeof (Elf64_External_Rela)))
+ if (!add_dynamic_entry (DT_RELA, 0)
+ || !add_dynamic_entry (DT_RELASZ, 0)
+ || !add_dynamic_entry (DT_RELAENT, sizeof (Elf64_External_Rela)))
return false;
if (info->flags & DF_TEXTREL)
{
- if (! bfd_elf64_add_dynamic_entry (info, DT_TEXTREL, 0))
+ if (!add_dynamic_entry (DT_TEXTREL, 0))
return false;
}
}
+#undef add_dynamic_entry
return true;
}
struct alpha_elf_link_hash_entry *h;
Elf_Internal_Sym *sym;
bfd_vma relocation;
- bfd_signed_vma addend;
+ bfd_vma addend;
bfd_reloc_status_type r;
r_type = ELF64_R_TYPE(rel->r_info);
{
sym = local_syms + r_symndx;
sec = local_sections[r_symndx];
- relocation = (sec->output_section->vma
- + sec->output_offset
- + sym->st_value);
+ relocation = _bfd_elf_rela_local_sym (output_bfd, sym, sec, rel);
}
else
{
}
else if (h->root.root.type == bfd_link_hash_undefweak)
relocation = 0;
- else if (info->shared && !info->symbolic
+ else if (info->shared
+ && (!info->symbolic || info->allow_shlib_undefined)
&& !info->no_undefined
&& ELF_ST_VISIBILITY (h->root.other) == STV_DEFAULT)
relocation = 0;
gotent = (alpha_elf_tdata(input_bfd)->
local_got_entries[r_symndx]);
dynamic_symbol = false;
+
+ /* Need to adjust local GOT entries' addends for SEC_MERGE
+ unless it has been done already. */
+ if ((sec->flags & SEC_MERGE)
+ && ELF_ST_TYPE (sym->st_info) == STT_SECTION
+ && (elf_section_data (sec)->sec_info_type
+ == ELF_INFO_TYPE_MERGE)
+ && (gotent->flags & ALPHA_ELF_GOT_ENTRY_RELOCS_XLATED) == 0)
+ {
+ struct alpha_elf_got_entry *ent;
+ asection *msec;
+
+ for (ent = gotent; ent; ent = ent->next)
+ {
+ ent->flags |= ALPHA_ELF_GOT_ENTRY_RELOCS_XLATED;
+ if (ent->use_count == 0)
+ continue;
+ msec = sec;
+ ent->addend =
+ _bfd_merged_section_offset (output_bfd, &msec,
+ elf_section_data (sec)->
+ sec_info,
+ sym->st_value
+ + ent->addend,
+ (bfd_vma) 0);
+ ent->addend -= sym->st_value;
+ ent->addend += msec->output_section->vma
+ + msec->output_offset
+ - sec->output_section->vma
+ - sec->output_offset;
+ }
+ }
}
BFD_ASSERT(gotent != NULL);
/* Initialize the .got entry's value. */
if (!(gotent->flags & ALPHA_ELF_GOT_ENTRY_RELOCS_DONE))
{
- bfd_put_64 (output_bfd, relocation+addend,
+ bfd_put_64 (output_bfd, relocation + addend,
sgot->contents + gotent->got_offset);
/* If the symbol has been forced local, output a
+ sgot->output_offset
+ gotent->got_offset);
outrel.r_info = ELF64_R_INFO(0, R_ALPHA_RELATIVE);
- outrel.r_addend = relocation+addend;
+ outrel.r_addend = relocation + addend;
bfd_elf64_swap_reloca_out (output_bfd, &outrel,
((Elf64_External_Rela *)
{
(*_bfd_error_handler)
(_("%s: gp-relative relocation against dynamic symbol %s"),
- bfd_get_filename (input_bfd), h->root.root.root.string);
+ bfd_archive_filename (input_bfd), h->root.root.root.string);
ret_val = false;
}
BFD_ASSERT(gp != 0);
{
(*_bfd_error_handler)
(_("%s: gp-relative relocation against dynamic symbol %s"),
- bfd_get_filename (input_bfd), h->root.root.root.string);
+ bfd_archive_filename (input_bfd), h->root.root.root.string);
ret_val = false;
}
BFD_ASSERT(gp != 0);
addend -= 4;
goto default_reloc;
+ case R_ALPHA_BRSGP:
+ {
+ int other;
+ const char *name;
+
+ /* The regular PC-relative stuff measures from the start of
+ the instruction rather than the end. */
+ addend -= 4;
+
+ /* The source and destination gp must be the same. */
+ if (h != NULL
+ && gotobj != alpha_elf_tdata (sec->owner)->gotobj)
+ {
+ if (h != NULL)
+ name = h->root.root.root.string;
+ else
+ {
+ name = (bfd_elf_string_from_elf_section
+ (input_bfd, symtab_hdr->sh_link, sym->st_name));
+ if (name == NULL)
+ name = _("<unknown>");
+ else if (name[0] == 0)
+ name = bfd_section_name (input_bfd, sec);
+ }
+ (*_bfd_error_handler)
+ (_("%s: change in gp: BRSGP %s"),
+ bfd_archive_filename (input_bfd), name);
+ ret_val = false;
+ }
+
+ /* The symbol should be marked either NOPV or STD_GPLOAD. */
+ if (h != NULL)
+ other = h->root.other;
+ else
+ other = sym->st_other;
+ switch (other & STO_ALPHA_STD_GPLOAD)
+ {
+ case STO_ALPHA_NOPV:
+ break;
+ case STO_ALPHA_STD_GPLOAD:
+ addend += 8;
+ break;
+ default:
+ if (h != NULL)
+ name = h->root.root.root.string;
+ else
+ {
+ name = (bfd_elf_string_from_elf_section
+ (input_bfd, symtab_hdr->sh_link, sym->st_name));
+ if (name == NULL)
+ name = _("<unknown>");
+ else if (name[0] == 0)
+ name = bfd_section_name (input_bfd, sec);
+ }
+ (*_bfd_error_handler)
+ (_("%s: !samegp reloc against symbol without .prologue: %s"),
+ bfd_archive_filename (input_bfd), name);
+ ret_val = false;
+ break;
+ }
+
+ goto default_reloc;
+ }
+
case R_ALPHA_REFLONG:
case R_ALPHA_REFQUAD:
{
Elf_Internal_Rela outrel;
- boolean skip;
/* Careful here to remember RELATIVE relocations for global
variables for symbolic shared objects. */
outrel.r_addend = addend;
addend = 0, relocation = 0;
}
- else if (info->shared && (input_section->flags & SEC_ALLOC))
+ else if (info->shared
+ && r_symndx != 0
+ && (input_section->flags & SEC_ALLOC))
{
outrel.r_info = ELF64_R_INFO(0, R_ALPHA_RELATIVE);
outrel.r_addend = relocation + addend;
BFD_ASSERT(srel != NULL);
}
- skip = false;
-
- if (elf_section_data (input_section)->stab_info == NULL)
- outrel.r_offset = rel->r_offset;
- else
- {
- bfd_vma off;
-
- off = (_bfd_stab_section_offset
- (output_bfd, &elf_hash_table (info)->stab_info,
- input_section,
- &elf_section_data (input_section)->stab_info,
- rel->r_offset));
- if (off == (bfd_vma) -1)
- skip = true;
- outrel.r_offset = off;
- }
-
- if (! skip)
+ outrel.r_offset =
+ _bfd_elf_section_offset (output_bfd, info, input_section,
+ rel->r_offset);
+ if (outrel.r_offset != (bfd_vma) -1)
outrel.r_offset += (input_section->output_section->vma
+ input_section->output_offset);
else
{
const char *name;
+ /* Don't warn if the overflow is due to pc relative reloc
+ against discarded section. Section optimization code should
+ handle it. */
+
+ if (r_symndx < symtab_hdr->sh_info
+ && sec != NULL && howto->pc_relative
+ && elf_discarded_section (sec))
+ break;
+
if (h != NULL)
name = h->root.root.root.string;
else
/* Fill in the entry in the procedure linkage table. */
{
- unsigned insn1, insn2, insn3;
+ bfd_vma insn1, insn2, insn3;
insn1 = PLT_ENTRY_WORD1 | ((-(h->plt.offset + 4) >> 2) & 0x1fffff);
insn2 = PLT_ENTRY_WORD2;
bfd_put_32 (output_bfd, PLT_HEADER_WORD4, splt->contents + 12);
/* The next two words will be filled in by ld.so */
- bfd_put_64 (output_bfd, 0, splt->contents + 16);
- bfd_put_64 (output_bfd, 0, splt->contents + 24);
+ bfd_put_64 (output_bfd, (bfd_vma) 0, splt->contents + 16);
+ bfd_put_64 (output_bfd, (bfd_vma) 0, splt->contents + 24);
elf_section_data (splt->output_section)->this_hdr.sh_entsize =
PLT_HEADER_SIZE;
sgot = alpha_elf_tdata(i)->got;
if (! bfd_set_section_contents (abfd, sgot->output_section,
- sgot->contents, sgot->output_offset,
+ sgot->contents,
+ (file_ptr) sgot->output_offset,
sgot->_raw_size))
return false;
}
}
static enum elf_reloc_type_class
-elf64_alpha_reloc_type_class (type)
- int type;
+elf64_alpha_reloc_type_class (rela)
+ const Elf_Internal_Rela *rela;
{
- switch (type)
+ switch ((int) ELF64_R_TYPE (rela->r_info))
{
case R_ALPHA_RELATIVE:
return reloc_class_relative;