static boolean elf64_alpha_object_p
PARAMS((bfd *));
static boolean elf64_alpha_section_from_shdr
- PARAMS((bfd *, Elf64_Internal_Shdr *, char *));
+ PARAMS((bfd *, Elf64_Internal_Shdr *, const char *));
static boolean elf64_alpha_section_flags
PARAMS((flagword *, Elf64_Internal_Shdr *));
static boolean elf64_alpha_fake_sections
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;
- Elf64_External_Sym *free_extsyms = NULL;
- Elf_External_Sym_Shndx *shndx_buf = NULL;
+ Elf_Internal_Sym *isymbuf = NULL;
struct alpha_elf_got_entry **local_got_entries;
struct alpha_relax_info info;
struct elf_link_tls_segment tls_segment;
(abfd, sec, (PTR) NULL, (Elf_Internal_Rela *) NULL,
link_info->keep_memory));
if (internal_relocs == NULL)
- goto error_return;
- if (! link_info->keep_memory)
- free_relocs = internal_relocs;
+ return false;
memset(&info, 0, sizeof (info));
info.abfd = abfd;
info.contents = (bfd_byte *) bfd_malloc (sec->_raw_size);
if (info.contents == NULL)
goto error_return;
- free_contents = info.contents;
if (! bfd_get_section_contents (abfd, sec, info.contents,
(file_ptr) 0, sec->_raw_size))
goto error_return;
}
- /* Read this BFD's symbols. */
- if (symtab_hdr->contents != NULL)
- extsyms = (Elf64_External_Sym *) symtab_hdr->contents;
- else
- {
- bfd_size_type amt = symtab_hdr->sh_info * 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_bread ((PTR) extsyms, amt, abfd) != amt)
- goto error_return;
- }
-
- shndx_hdr = &elf_tdata (abfd)->symtab_shndx_hdr;
- if (shndx_hdr->sh_size != 0)
- {
- bfd_size_type amt;
- amt = symtab_hdr->sh_info * 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;
- }
-
/* Compute the TLS segment information. The version normally found in
elf_hash_table (link_info)->tls_segment isn't built until final_link.
??? Probably should look into extracting this into a common function. */
for (irel = internal_relocs; irel < irelend; irel++)
{
bfd_vma symval;
- Elf_Internal_Sym isym;
struct alpha_elf_got_entry *gotent;
unsigned long r_type = ELF64_R_TYPE (irel->r_info);
if (ELF64_R_SYM (irel->r_info) < symtab_hdr->sh_info)
{
/* A local symbol. */
- Elf64_External_Sym *esym;
- Elf_External_Sym_Shndx *shndx;
+ Elf_Internal_Sym *isym;
+
+ /* Read this BFD's local symbols. */
+ if (isymbuf == NULL)
+ {
+ isymbuf = (Elf_Internal_Sym *) symtab_hdr->contents;
+ if (isymbuf == NULL)
+ isymbuf = bfd_elf_get_elf_syms (abfd, symtab_hdr,
+ symtab_hdr->sh_info, 0,
+ NULL, NULL, NULL);
+ if (isymbuf == NULL)
+ goto error_return;
+ }
- 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)
+ isym = isymbuf + ELF64_R_SYM (irel->r_info);
+ if (isym->st_shndx == SHN_UNDEF)
continue;
- else if (isym.st_shndx == SHN_ABS)
+ else if (isym->st_shndx == SHN_ABS)
info.tsec = bfd_abs_section_ptr;
- else if (isym.st_shndx == SHN_COMMON)
+ else if (isym->st_shndx == SHN_COMMON)
info.tsec = bfd_com_section_ptr;
else
- info.tsec = bfd_section_from_elf_index (abfd, isym.st_shndx);
+ info.tsec = bfd_section_from_elf_index (abfd, isym->st_shndx);
info.h = NULL;
- info.other = isym.st_other;
+ info.other = isym->st_other;
info.first_gotent = &local_got_entries[ELF64_R_SYM(irel->r_info)];
- symval = isym.st_value;
+ symval = isym->st_value;
}
else
{
if (!elf64_alpha_size_rela_got_section (link_info))
return false;
- if (info.changed_relocs)
- elf_section_data (sec)->relocs = internal_relocs;
- else if (free_relocs != NULL)
- free (free_relocs);
+ if (isymbuf != NULL
+ && symtab_hdr->contents != (unsigned char *) isymbuf)
+ {
+ if (!link_info->keep_memory)
+ free (isymbuf);
+ else
+ {
+ /* Cache the symbols for elf_link_input_bfd. */
+ symtab_hdr->contents = (unsigned char *) isymbuf;
+ }
+ }
- if (info.changed_contents)
- elf_section_data (sec)->this_hdr.contents = info.contents;
- else if (free_contents != NULL)
+ if (info.contents != NULL
+ && elf_section_data (sec)->this_hdr.contents != info.contents)
{
- if (! link_info->keep_memory)
- free (free_contents);
+ if (!info.changed_contents && !link_info->keep_memory)
+ free (info.contents);
else
{
/* Cache the section contents for elf_link_input_bfd. */
}
}
- if (shndx_buf != NULL)
- free (shndx_buf);
-
- if (free_extsyms != NULL)
+ if (elf_section_data (sec)->relocs != internal_relocs)
{
- if (! link_info->keep_memory)
- free (free_extsyms);
+ if (!info.changed_relocs)
+ free (internal_relocs);
else
- {
- /* Cache the symbols for elf_link_input_bfd. */
- symtab_hdr->contents = (unsigned char *) extsyms;
- }
+ elf_section_data (sec)->relocs = internal_relocs;
}
*again = info.changed_contents || info.changed_relocs;
return true;
error_return:
- if (free_relocs != NULL)
- free (free_relocs);
- if (free_contents != NULL)
- free (free_contents);
- if (shndx_buf != NULL)
- free (shndx_buf);
- if (free_extsyms != NULL)
- free (free_extsyms);
+ if (isymbuf != NULL
+ && symtab_hdr->contents != (unsigned char *) isymbuf)
+ free (isymbuf);
+ if (info.contents != NULL
+ && elf_section_data (sec)->this_hdr.contents != info.contents)
+ free (info.contents);
+ if (internal_relocs != NULL
+ && elf_section_data (sec)->relocs != internal_relocs)
+ free (internal_relocs);
return false;
}
\f
elf64_alpha_section_from_shdr (abfd, hdr, name)
bfd *abfd;
Elf64_Internal_Shdr *hdr;
- char *name;
+ const char *name;
{
asection *newsect;
{
asection *s;
struct elf_link_hash_entry *h;
+ struct bfd_link_hash_entry *bh;
/* We need to create .plt, .rela.plt, .got, and .rela.got sections. */
/* Define the symbol _PROCEDURE_LINKAGE_TABLE_ at the start of the
.plt section. */
- h = NULL;
+ bh = NULL;
if (! (_bfd_generic_link_add_one_symbol
(info, abfd, "_PROCEDURE_LINKAGE_TABLE_", BSF_GLOBAL, s,
(bfd_vma) 0, (const char *) NULL, false,
- get_elf_backend_data (abfd)->collect,
- (struct bfd_link_hash_entry **) &h)))
+ get_elf_backend_data (abfd)->collect, &bh)))
return false;
+ h = (struct elf_link_hash_entry *) bh;
h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
h->type = STT_OBJECT;
dynobj's .got section. We don't do this in the linker script
because we don't want to define the symbol if we are not creating
a global offset table. */
- h = NULL;
+ bh = NULL;
if (!(_bfd_generic_link_add_one_symbol
(info, abfd, "_GLOBAL_OFFSET_TABLE_", BSF_GLOBAL,
alpha_elf_tdata(abfd)->got, (bfd_vma) 0, (const char *) NULL,
- false, get_elf_backend_data (abfd)->collect,
- (struct bfd_link_hash_entry **) &h)))
+ false, get_elf_backend_data (abfd)->collect, &bh)))
return false;
+ h = (struct elf_link_hash_entry *) bh;
h->elf_link_hash_flags |= ELF_LINK_HASH_DEF_REGULAR;
h->type = STT_OBJECT;
if (ext_hdr == NULL && swap->external_hdr_size != 0)
goto error_return;
- if (bfd_get_section_contents (abfd, section, ext_hdr, (file_ptr) 0,
- swap->external_hdr_size)
- == false)
+ if (! bfd_get_section_contents (abfd, section, ext_hdr, (file_ptr) 0,
+ swap->external_hdr_size))
goto error_return;
symhdr = &debug->symbolic_header;
size *= sizeof (struct alpha_elf_got_entry *);
local_got_entries
- = (struct alpha_elf_got_entry **) bfd_alloc (abfd, size);
+ = (struct alpha_elf_got_entry **) bfd_zalloc (abfd, size);
if (!local_got_entries)
return NULL;
- memset (local_got_entries, 0, (size_t) size);
alpha_elf_tdata (abfd)->local_got_entries = local_got_entries;
}
{
rin = ri->next;
for (rs = rsh; rs ; rs = rs->next)
- if (ri->rtype == rs->rtype)
+ if (ri->rtype == rs->rtype && ri->srel == rs->srel)
{
rs->count += ri->count;
goto found_reloc;
return false;
}
- if (!add_dynamic_entry (DT_PLTGOT, 0))
- return false;
-
if (relplt)
{
- if (!add_dynamic_entry (DT_PLTRELSZ, 0)
+ if (!add_dynamic_entry (DT_PLTGOT, 0)
+ || !add_dynamic_entry (DT_PLTRELSZ, 0)
|| !add_dynamic_entry (DT_PLTREL, DT_RELA)
|| !add_dynamic_entry (DT_JMPREL, 0))
return false;
case STO_ALPHA_NOPV:
break;
case STO_ALPHA_STD_GPLOAD:
- addend += 8;
+ value += 8;
break;
default:
if (h != NULL)
\f
/* Use a non-standard hash bucket size of 8. */
-const struct elf_size_info alpha_elf_size_info =
+static const struct elf_size_info alpha_elf_size_info =
{
sizeof (Elf64_External_Ehdr),
sizeof (Elf64_External_Phdr),
bfd_elf64_write_out_phdrs,
bfd_elf64_write_shdrs_and_ehdr,
bfd_elf64_write_relocs,
+ bfd_elf64_swap_symbol_in,
bfd_elf64_swap_symbol_out,
bfd_elf64_slurp_reloc_table,
bfd_elf64_slurp_symbol_table,
#define elf_backend_plt_header_size PLT_HEADER_SIZE
#include "elf64-target.h"
+\f
+/* FreeBSD support. */
+
+#undef TARGET_LITTLE_SYM
+#define TARGET_LITTLE_SYM bfd_elf64_alpha_freebsd_vec
+#undef TARGET_LITTLE_NAME
+#define TARGET_LITTLE_NAME "elf64-alpha-freebsd"
+
+/* The kernel recognizes executables as valid only if they carry a
+ "FreeBSD" label in the ELF header. So we put this label on all
+ executables and (for simplicity) also all other object files. */
+
+static void elf64_alpha_fbsd_post_process_headers
+ PARAMS ((bfd *, struct bfd_link_info *));
+
+static void
+elf64_alpha_fbsd_post_process_headers (abfd, link_info)
+ bfd * abfd;
+ struct bfd_link_info * link_info ATTRIBUTE_UNUSED;
+{
+ Elf_Internal_Ehdr * i_ehdrp; /* ELF file header, internal form. */
+
+ i_ehdrp = elf_elfheader (abfd);
+
+ /* Put an ABI label supported by FreeBSD >= 4.1. */
+ i_ehdrp->e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
+#ifdef OLD_FREEBSD_ABI_LABEL
+ /* The ABI label supported by FreeBSD <= 4.0 is quite nonstandard. */
+ memcpy (&i_ehdrp->e_ident[EI_ABIVERSION], "FreeBSD", 8);
+#endif
+}
+
+#undef elf_backend_post_process_headers
+#define elf_backend_post_process_headers \
+ elf64_alpha_fbsd_post_process_headers
+
+#define elf64_bed elf64_alpha_fbsd_bed
+
+#include "elf64-target.h"