/* XSTORMY16-specific support for 32-bit ELF.
- Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+ Copyright (C) 2000, 2001, 2002 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
#include "libbfd.h"
#include "elf-bfd.h"
#include "elf/xstormy16.h"
+#include "libiberty.h"
/* Forward declarations. */
static reloc_howto_type * xstormy16_reloc_type_lookup
\f
/* Map BFD reloc types to XSTORMY16 ELF reloc types. */
-struct xstormy16_reloc_map
+typedef struct xstormy16_reloc_map
{
- bfd_reloc_code_real_type bfd_reloc_val;
- unsigned int xstormy16_reloc_val;
-};
+ bfd_reloc_code_real_type bfd_reloc_val;
+ unsigned int xstormy16_reloc_val;
+ reloc_howto_type * table;
+} reloc_map;
-static const struct xstormy16_reloc_map xstormy16_reloc_map [] =
+static const reloc_map xstormy16_reloc_map [] =
{
- { BFD_RELOC_NONE, R_XSTORMY16_NONE },
- { BFD_RELOC_32, R_XSTORMY16_32 },
- { BFD_RELOC_16, R_XSTORMY16_16 },
- { BFD_RELOC_8, R_XSTORMY16_8 },
- { BFD_RELOC_32_PCREL, R_XSTORMY16_PC32 },
- { BFD_RELOC_16_PCREL, R_XSTORMY16_PC16 },
- { BFD_RELOC_8_PCREL, R_XSTORMY16_PC8 },
- { BFD_RELOC_XSTORMY16_REL_12, R_XSTORMY16_REL_12 },
- { BFD_RELOC_XSTORMY16_24, R_XSTORMY16_24 },
- { BFD_RELOC_XSTORMY16_FPTR16, R_XSTORMY16_FPTR16 },
- { BFD_RELOC_VTABLE_INHERIT, R_XSTORMY16_GNU_VTINHERIT },
- { BFD_RELOC_VTABLE_ENTRY, R_XSTORMY16_GNU_VTENTRY },
+ { BFD_RELOC_NONE, R_XSTORMY16_NONE, xstormy16_elf_howto_table },
+ { BFD_RELOC_32, R_XSTORMY16_32, xstormy16_elf_howto_table },
+ { BFD_RELOC_16, R_XSTORMY16_16, xstormy16_elf_howto_table },
+ { BFD_RELOC_8, R_XSTORMY16_8, xstormy16_elf_howto_table },
+ { BFD_RELOC_32_PCREL, R_XSTORMY16_PC32, xstormy16_elf_howto_table },
+ { BFD_RELOC_16_PCREL, R_XSTORMY16_PC16, xstormy16_elf_howto_table },
+ { BFD_RELOC_8_PCREL, R_XSTORMY16_PC8, xstormy16_elf_howto_table },
+ { BFD_RELOC_XSTORMY16_REL_12, R_XSTORMY16_REL_12, xstormy16_elf_howto_table },
+ { BFD_RELOC_XSTORMY16_24, R_XSTORMY16_24, xstormy16_elf_howto_table },
+ { BFD_RELOC_XSTORMY16_FPTR16, R_XSTORMY16_FPTR16, xstormy16_elf_howto_table },
+ { BFD_RELOC_VTABLE_INHERIT, R_XSTORMY16_GNU_VTINHERIT, xstormy16_elf_howto_table2 },
+ { BFD_RELOC_VTABLE_ENTRY, R_XSTORMY16_GNU_VTENTRY, xstormy16_elf_howto_table2 },
};
static reloc_howto_type *
{
unsigned int i;
- for (i = sizeof (xstormy16_reloc_map) / sizeof (xstormy16_reloc_map[0]);
- --i;)
- if (xstormy16_reloc_map [i].bfd_reloc_val == code)
- return & xstormy16_elf_howto_table [xstormy16_reloc_map[i].xstormy16_reloc_val];
+ for (i = ARRAY_SIZE (xstormy16_reloc_map); --i;)
+ {
+ const reloc_map * entry;
+
+ entry = xstormy16_reloc_map + i;
+
+ if (entry->bfd_reloc_val == code)
+ return entry->table + (entry->xstormy16_reloc_val
+ - entry->table[0].type);
+ }
return NULL;
}
{
struct relax_plt_data *data = (struct relax_plt_data *) xdata;
+ if (h->root.type == bfd_link_hash_warning)
+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
if (h->plt.offset != (bfd_vma) -1)
{
bfd_vma address;
{
bfd_vma *entry = (bfd_vma *) xdata;
+ if (h->root.type == bfd_link_hash_warning)
+ h = (struct elf_link_hash_entry *) h->root.u.i.link;
+
if (h->plt.offset != (bfd_vma) -1)
{
h->plt.offset = *entry;
{
bfd_vma *local_plt_offsets = elf_local_got_offsets (ibfd);
Elf_Internal_Shdr *symtab_hdr;
+ Elf_Internal_Shdr *shndx_hdr;
Elf32_External_Sym *extsyms;
+ Elf_External_Sym_Shndx *shndx_buf;
unsigned int idx;
if (! local_plt_offsets)
continue;
symtab_hdr = &elf_tdata (ibfd)->symtab_hdr;
+ shndx_hdr = &elf_tdata (ibfd)->symtab_shndx_hdr;
if (symtab_hdr->contents != NULL)
extsyms = (Elf32_External_Sym *) symtab_hdr->contents;
else
{
- extsyms = (Elf32_External_Sym *) bfd_malloc (symtab_hdr->sh_size);
+ bfd_size_type amt;
+
+ amt = symtab_hdr->sh_info;
+ amt *= sizeof (Elf32_External_Sym);
+ extsyms = (Elf32_External_Sym *) bfd_malloc (amt);
if (extsyms == NULL)
return false;
if (bfd_seek (ibfd, symtab_hdr->sh_offset, SEEK_SET) != 0
- || (bfd_bread (extsyms, symtab_hdr->sh_size, ibfd)
- != symtab_hdr->sh_size))
+ || bfd_bread ((PTR) extsyms, amt, ibfd) != amt)
{
+ error_ret_free_extsyms:
free (extsyms);
return false;
}
}
+ shndx_buf = NULL;
+ if (shndx_hdr->sh_size != 0)
+ {
+ bfd_size_type amt;
+
+ 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_ret_free_extsyms;
+ if (bfd_seek (ibfd, shndx_hdr->sh_offset, SEEK_SET) != 0
+ || bfd_bread ((PTR) shndx_buf, amt, ibfd) != amt)
+ {
+ free (shndx_buf);
+ goto error_ret_free_extsyms;
+ }
+ shndx_hdr->contents = (bfd_byte *) shndx_buf;
+ }
+
for (idx = 0; idx < symtab_hdr->sh_info; ++idx)
{
+ Elf_External_Sym_Shndx *shndx;
Elf_Internal_Sym isym;
asection *tsec;
bfd_vma address;
if (local_plt_offsets[idx] == (bfd_vma) -1)
continue;
- bfd_elf32_swap_symbol_in (ibfd, extsyms + idx, &isym);
+ shndx = shndx_buf;
+ if (shndx != NULL)
+ shndx += idx;
+ bfd_elf32_swap_symbol_in (ibfd, extsyms + idx, shndx, &isym);
if (isym.st_shndx == SHN_UNDEF)
continue;
- else if (isym.st_shndx > 0 && isym.st_shndx < SHN_LORESERVE)
- tsec = bfd_section_from_elf_index (ibfd, isym.st_shndx);
else if (isym.st_shndx == SHN_ABS)
tsec = bfd_abs_section_ptr;
+ else if (isym.st_shndx == SHN_COMMON)
+ tsec = bfd_com_section_ptr;
else
- continue;
+ tsec = bfd_section_from_elf_index (ibfd, isym.st_shndx);
address = (tsec->output_section->vma
+ tsec->output_offset
}
}
- if (symtab_hdr->contents != extsyms)
+ if (shndx_buf != NULL)
+ free (shndx_buf);
+
+ if ((Elf32_External_Sym *) symtab_hdr->contents != extsyms)
free (extsyms);
}
}
else
{
- if (!(elf_bad_symtab (abfd)
- && ELF_ST_BIND (sym->st_info) != STB_LOCAL)
- && ! ((sym->st_shndx <= 0 || sym->st_shndx >= SHN_LORESERVE)
- && sym->st_shndx != SHN_COMMON))
- {
- return bfd_section_from_elf_index (abfd, sym->st_shndx);
- }
+ return bfd_section_from_elf_index (abfd, sym->st_shndx);
}
return NULL;