/* Ubicom IP2xxx specific support for 32-bit ELF
- Copyright 2000, 2001, 2002, 2003, 2004, 2005
- Free Software Foundation, Inc.
+ Copyright (C) 2000-2016 Free Software Foundation, Inc.
This file is part of BFD, the Binary File Descriptor library.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
MA 02110-1301, USA. */
-#include "bfd.h"
#include "sysdep.h"
+#include "bfd.h"
#include "libbfd.h"
#include "elf-bfd.h"
#include "elf/ip2k.h"
pr) /* pcrel_offset */
/* This reloc does nothing. */
- IP2K_HOWTO (R_IP2K_NONE, 0,2,32, FALSE, 0, "R_IP2K_NONE", 0, 0),
+ IP2K_HOWTO (R_IP2K_NONE, 0,3,0, FALSE, 0, "R_IP2K_NONE", 0, 0),
/* A 16 bit absolute relocation. */
IP2K_HOWTO (R_IP2K_16, 0,1,16, FALSE, 0, "R_IP2K_16", 0, 0xffff),
/* A 32 bit absolute relocation. */
return NULL;
}
+static reloc_howto_type *
+ip2k_reloc_name_lookup (bfd *abfd ATTRIBUTE_UNUSED, const char *r_name)
+{
+ unsigned int i;
+
+ for (i = 0;
+ i < sizeof (ip2k_elf_howto_table) / sizeof (ip2k_elf_howto_table[0]);
+ i++)
+ if (ip2k_elf_howto_table[i].name != NULL
+ && strcasecmp (ip2k_elf_howto_table[i].name, r_name) == 0)
+ return &ip2k_elf_howto_table[i];
+
+ return NULL;
+}
+
static void
ip2k_get_mem (bfd *abfd ATTRIBUTE_UNUSED,
bfd_byte *addr,
bfd_byte *contents)
{
bfd_byte code[4];
- int index = 0;
-
+ int table_index = 0;
+
/* Check current page-jmp. */
if (addr + 4 > sec->size)
return -1;
if ((! IS_PAGE_OPCODE (code + 0))
|| (! IS_JMP_OPCODE (code + 2)))
return -1;
-
+
/* Search back. */
while (1)
{
ip2k_get_mem (abfd, contents + addr - 4, 4, code);
if ((IS_ADD_W_WREG_OPCODE (code + 0))
&& (IS_ADD_PCL_W_OPCODE (code + 2)))
- return index;
+ return table_index;
if ((! IS_PAGE_OPCODE (code + 0))
|| (! IS_JMP_OPCODE (code + 2)))
return -1;
- index++;
+ table_index++;
addr -= 4;
}
}
bfd_byte *contents)
{
bfd_byte code[16];
- int index = 0;
-
+ int table_index = 0;
+
/* Check current page-jmp. */
if (addr + 4 > sec->size)
return -1;
if ((! IS_PAGE_OPCODE (code + 0))
|| (! IS_JMP_OPCODE (code + 2)))
return -1;
-
+
/* Search back. */
while (1)
{
&& (IS_INC_1SP_OPCODE (code + 10))
&& (IS_PAGE_OPCODE (code + 12))
&& (IS_JMP_OPCODE (code + 14)))
- return index;
+ return table_index;
if ((IS_ADD_W_WREG_OPCODE (code + 2))
&& (IS_SNC_OPCODE (code + 4))
&& (IS_SNC_OPCODE (code + 10))
&& (IS_INC_1SP_OPCODE (code + 12))
&& (IS_JMP_OPCODE (code + 14)))
- return index;
-
+ return table_index;
+
if ((! IS_PAGE_OPCODE (code + 0))
|| (! IS_JMP_OPCODE (code + 2)))
return -1;
- index++;
+ table_index++;
addr -= 4;
}
}
Elf_Internal_Shdr *symtab_hdr;
Elf_Internal_Sym *isymbuf, *isym, *isymend;
unsigned int shndx;
- bfd_byte *contents;
Elf_Internal_Rela *irel, *irelend, *irelbase;
struct elf_link_hash_entry **sym_hashes;
struct elf_link_hash_entry **end_hashes;
shndx = _bfd_elf_section_from_bfd_section (abfd, sec);
- contents = elf_section_data (sec)->this_hdr.contents;
-
irelbase = elf_section_data (sec)->relocs;
irelend = irelbase + sec->reloc_count;
if (ELF32_R_SYM (irel->r_info) < symtab_hdr->sh_info)
{
asection *sym_sec;
-
+
/* A local symbol. */
isym = isymbuf + ELF32_R_SYM (irel->r_info);
sym_sec = bfd_section_from_elf_index (abfd, isym->st_shndx);
-
+
if (sym_sec == sec)
{
const char *name;
- unsigned long strx;
- unsigned char type, other;
- unsigned short desc;
+ unsigned char type;
bfd_vma value;
bfd_vma baseaddr = BASEADDR (sec);
bfd_vma symval = BASEADDR (sym_sec) + isym->st_value
+ irel->r_addend;
-
+
if ((baseaddr + addr) <= symval
&& symval <= (baseaddr + endaddr))
irel->r_addend += count;
/* Go hunt up a function and fix its line info if needed. */
- stabp = stabcontents + irel->r_offset - 8;
+ stabp = stabcontents + irel->r_offset - 8;
/* Go pullout the stab entry. */
- strx = bfd_h_get_32 (abfd, stabp + STRDXOFF);
type = bfd_h_get_8 (abfd, stabp + TYPEOFF);
- other = bfd_h_get_8 (abfd, stabp + OTHEROFF);
- desc = bfd_h_get_16 (abfd, stabp + DESCOFF);
value = bfd_h_get_32 (abfd, stabp + VALOFF);
-
+
name = bfd_get_stab_name (type);
-
+
if (strcmp (name, "FUN") == 0)
{
int function_adjusted = 0;
for (;stabp < stabend; stabp += STABSIZE)
{
/* Go pullout the stab entry. */
- strx = bfd_h_get_32 (abfd, stabp + STRDXOFF);
type = bfd_h_get_8 (abfd, stabp + TYPEOFF);
- other = bfd_h_get_8 (abfd, stabp + OTHEROFF);
- desc = bfd_h_get_16 (abfd, stabp + DESCOFF);
value = bfd_h_get_32 (abfd, stabp + VALOFF);
name = bfd_get_stab_name (type);
{
/* Adjust the value. */
value += count;
-
+
/* We need to put it back. */
bfd_h_put_32 (abfd, value,stabp + VALOFF);
}
/* Delete the PAGE insn. */
if (!ip2k_elf_relax_delete_bytes (abfd, sec, irel->r_offset, 2))
return FALSE;
-
+
/* Modified => will need to iterate relaxation again. */
*again = TRUE;
-
+
return TRUE;
}
Elf_Internal_Rela *ireltest = irel;
bfd_byte code[4];
bfd_vma addr;
-
+
/* Test all page instructions. */
addr = irel->r_offset;
while (1)
Elf_Internal_Rela *ireltest = irel;
bfd_byte code[12];
bfd_vma addr;
-
+
/* Test all page instructions. */
addr = irel->r_offset;
Elf_Internal_Rela *irel;
int switch_table_128;
int switch_table_256;
-
+
/* Walk thru the section looking for relaxation opportunities. */
for (irel = misc->irelbase; irel < irelend; irel++)
{
static bfd_boolean new_pass = FALSE;
static bfd_boolean changed = FALSE;
struct misc misc;
- asection *stab;
/* Assume nothing changes. */
*again = FALSE;
/* We don't have to do anything for a relocatable link,
if this section does not have relocs, or if this is
not a code section. */
- if (link_info->relocatable
+ if (bfd_link_relocatable (link_info)
|| (sec->flags & SEC_RELOC) == 0
|| sec->reloc_count == 0
|| (sec->flags & SEC_CODE) == 0)
if (internal_relocs == NULL)
goto error_return;
- /* Make sure the stac.rela stuff gets read in. */
- stab = bfd_get_section_by_name (abfd, ".stab");
-
- if (stab)
- {
- /* So stab does exits. */
- Elf_Internal_Rela * irelbase;
-
- irelbase = _bfd_elf_link_read_relocs (abfd, stab, NULL, NULL,
- link_info->keep_memory);
- }
-
/* Get section contents cached copy if it exists. */
if (contents == NULL)
{
unsigned int r_type;
r_type = ELF32_R_TYPE (dst->r_info);
+ if (r_type >= (unsigned int) R_IP2K_max)
+ {
+ _bfd_error_handler (_("%B: invalid IP2K reloc number: %d"), abfd, r_type);
+ r_type = 0;
+ }
cache_ptr->howto = & ip2k_elf_howto_table [r_type];
}
Elf_Internal_Rela *rel;
Elf_Internal_Rela *relend;
- if (info->relocatable)
- return TRUE;
-
symtab_hdr = & elf_tdata (input_bfd)->symtab_hdr;
sym_hashes = elf_sym_hashes (input_bfd);
relend = relocs + input_section->reloc_count;
const char * name = NULL;
int r_type;
- /* This is a final link. */
r_type = ELF32_R_TYPE (rel->r_info);
r_symndx = ELF32_R_SYM (rel->r_info);
- howto = ip2k_elf_howto_table + ELF32_R_TYPE (rel->r_info);
+ howto = ip2k_elf_howto_table + r_type;
h = NULL;
sym = NULL;
sec = NULL;
}
else
{
- bfd_boolean warned;
+ bfd_boolean warned, ignored;
bfd_boolean unresolved_reloc;
RELOC_FOR_GLOBAL_SYMBOL (info, input_bfd, input_section, rel,
r_symndx, symtab_hdr, sym_hashes,
h, sec, relocation,
- unresolved_reloc, warned);
+ unresolved_reloc, warned, ignored);
name = h->root.root.string;
}
+ if (sec != NULL && discarded_section (sec))
+ RELOC_AGAINST_DISCARDED_SECTION (info, input_bfd, input_section,
+ rel, 1, relend, howto, 0, contents);
+
+ if (bfd_link_relocatable (info))
+ continue;
+
/* Finally, the sole IP2K-specific part. */
r = ip2k_final_link_relocate (howto, input_bfd, input_section,
contents, rel, relocation);
return TRUE;
}
-static asection *
-ip2k_elf_gc_mark_hook (asection *sec,
- struct bfd_link_info *info ATTRIBUTE_UNUSED,
- Elf_Internal_Rela *rel,
- struct elf_link_hash_entry *h,
- Elf_Internal_Sym *sym)
-{
- if (h != NULL)
- {
- switch (ELF32_R_TYPE (rel->r_info))
- {
- default:
- switch (h->root.type)
- {
- case bfd_link_hash_defined:
- case bfd_link_hash_defweak:
- return h->root.u.def.section;
-
- case bfd_link_hash_common:
- return h->root.u.c.p->section;
-
- default:
- break;
- }
- }
- }
- else
- {
- if (!(elf_bad_symtab (sec->owner)
- && 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 (sec->owner, sym->st_shndx);
- }
- return NULL;
-}
-
-static bfd_boolean
-ip2k_elf_gc_sweep_hook (bfd *abfd ATTRIBUTE_UNUSED,
- struct bfd_link_info *info ATTRIBUTE_UNUSED,
- asection *sec ATTRIBUTE_UNUSED,
- const Elf_Internal_Rela *relocs ATTRIBUTE_UNUSED)
-{
- /* We don't use got and plt entries for ip2k. */
- return TRUE;
-}
-
-#define TARGET_BIG_SYM bfd_elf32_ip2k_vec
+#define TARGET_BIG_SYM ip2k_elf32_vec
#define TARGET_BIG_NAME "elf32-ip2k"
#define ELF_ARCH bfd_arch_ip2k
#define elf_backend_can_gc_sections 1
#define elf_backend_rela_normal 1
-#define elf_backend_gc_mark_hook ip2k_elf_gc_mark_hook
-#define elf_backend_gc_sweep_hook ip2k_elf_gc_sweep_hook
#define elf_backend_relocate_section ip2k_elf_relocate_section
#define elf_symbol_leading_char '_'
#define bfd_elf32_bfd_reloc_type_lookup ip2k_reloc_type_lookup
+#define bfd_elf32_bfd_reloc_name_lookup ip2k_reloc_name_lookup
#define bfd_elf32_bfd_relax_section ip2k_elf_relax_section
#include "elf32-target.h"