Line 1... |
Line 1... |
/* AVR-specific support for 32-bit ELF
|
/* AVR-specific support for 32-bit ELF
|
Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2006, 2007
|
Copyright 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
|
Free Software Foundation, Inc.
|
Free Software Foundation, Inc.
|
Contributed by Denis Chertykov <denisc@overta.ru>
|
Contributed by Denis Chertykov <denisc@overta.ru>
|
|
|
This file is part of BFD, the Binary File Descriptor library.
|
This file is part of BFD, the Binary File Descriptor library.
|
|
|
Line 852... |
Line 852... |
/* Check for overflow. */
|
/* Check for overflow. */
|
if (srel < -2048 || srel > 2047)
|
if (srel < -2048 || srel > 2047)
|
{
|
{
|
/* Relative distance is too large. */
|
/* Relative distance is too large. */
|
|
|
/* Always apply WRAPAROUND for avr2 and avr4. */
|
/* Always apply WRAPAROUND for avr2, avr25, and avr4. */
|
switch (bfd_get_mach (input_bfd))
|
switch (bfd_get_mach (input_bfd))
|
{
|
{
|
case bfd_mach_avr2:
|
case bfd_mach_avr2:
|
|
case bfd_mach_avr25:
|
case bfd_mach_avr4:
|
case bfd_mach_avr4:
|
break;
|
break;
|
|
|
default:
|
default:
|
return bfd_reloc_overflow;
|
return bfd_reloc_overflow;
|
Line 1294... |
Line 1295... |
|
|
case bfd_mach_avr1:
|
case bfd_mach_avr1:
|
val = E_AVR_MACH_AVR1;
|
val = E_AVR_MACH_AVR1;
|
break;
|
break;
|
|
|
|
case bfd_mach_avr25:
|
|
val = E_AVR_MACH_AVR25;
|
|
break;
|
|
|
case bfd_mach_avr3:
|
case bfd_mach_avr3:
|
val = E_AVR_MACH_AVR3;
|
val = E_AVR_MACH_AVR3;
|
break;
|
break;
|
|
|
|
case bfd_mach_avr31:
|
|
val = E_AVR_MACH_AVR31;
|
|
break;
|
|
|
|
case bfd_mach_avr35:
|
|
val = E_AVR_MACH_AVR35;
|
|
break;
|
|
|
case bfd_mach_avr4:
|
case bfd_mach_avr4:
|
val = E_AVR_MACH_AVR4;
|
val = E_AVR_MACH_AVR4;
|
break;
|
break;
|
|
|
case bfd_mach_avr5:
|
case bfd_mach_avr5:
|
val = E_AVR_MACH_AVR5;
|
val = E_AVR_MACH_AVR5;
|
break;
|
break;
|
|
|
|
case bfd_mach_avr51:
|
|
val = E_AVR_MACH_AVR51;
|
|
break;
|
|
|
case bfd_mach_avr6:
|
case bfd_mach_avr6:
|
val = E_AVR_MACH_AVR6;
|
val = E_AVR_MACH_AVR6;
|
break;
|
break;
|
}
|
}
|
|
|
Line 1340... |
Line 1357... |
|
|
case E_AVR_MACH_AVR1:
|
case E_AVR_MACH_AVR1:
|
e_set = bfd_mach_avr1;
|
e_set = bfd_mach_avr1;
|
break;
|
break;
|
|
|
|
case E_AVR_MACH_AVR25:
|
|
e_set = bfd_mach_avr25;
|
|
break;
|
|
|
case E_AVR_MACH_AVR3:
|
case E_AVR_MACH_AVR3:
|
e_set = bfd_mach_avr3;
|
e_set = bfd_mach_avr3;
|
break;
|
break;
|
|
|
|
case E_AVR_MACH_AVR31:
|
|
e_set = bfd_mach_avr31;
|
|
break;
|
|
|
|
case E_AVR_MACH_AVR35:
|
|
e_set = bfd_mach_avr35;
|
|
break;
|
|
|
case E_AVR_MACH_AVR4:
|
case E_AVR_MACH_AVR4:
|
e_set = bfd_mach_avr4;
|
e_set = bfd_mach_avr4;
|
break;
|
break;
|
|
|
case E_AVR_MACH_AVR5:
|
case E_AVR_MACH_AVR5:
|
e_set = bfd_mach_avr5;
|
e_set = bfd_mach_avr5;
|
break;
|
break;
|
|
|
|
case E_AVR_MACH_AVR51:
|
|
e_set = bfd_mach_avr51;
|
|
break;
|
|
|
case E_AVR_MACH_AVR6:
|
case E_AVR_MACH_AVR6:
|
e_set = bfd_mach_avr6;
|
e_set = bfd_mach_avr6;
|
break;
|
break;
|
}
|
}
|
}
|
}
|
Line 1380... |
Line 1413... |
bfd_byte *contents;
|
bfd_byte *contents;
|
Elf_Internal_Rela *irel, *irelend;
|
Elf_Internal_Rela *irel, *irelend;
|
Elf_Internal_Rela *irelalign;
|
Elf_Internal_Rela *irelalign;
|
Elf_Internal_Sym *isym;
|
Elf_Internal_Sym *isym;
|
Elf_Internal_Sym *isymbuf = NULL;
|
Elf_Internal_Sym *isymbuf = NULL;
|
Elf_Internal_Sym *isymend;
|
|
bfd_vma toaddr;
|
bfd_vma toaddr;
|
struct elf_link_hash_entry **sym_hashes;
|
struct elf_link_hash_entry **sym_hashes;
|
struct elf_link_hash_entry **end_hashes;
|
struct elf_link_hash_entry **end_hashes;
|
unsigned int symcount;
|
unsigned int symcount;
|
|
|
Line 1518... |
Line 1550... |
}
|
}
|
}
|
}
|
|
|
/* Adjust the local symbols defined in this section. */
|
/* Adjust the local symbols defined in this section. */
|
isym = (Elf_Internal_Sym *) symtab_hdr->contents;
|
isym = (Elf_Internal_Sym *) symtab_hdr->contents;
|
|
/* Fix PR 9841, there may be no local symbols. */
|
|
if (isym != NULL)
|
|
{
|
|
Elf_Internal_Sym *isymend;
|
|
|
isymend = isym + symtab_hdr->sh_info;
|
isymend = isym + symtab_hdr->sh_info;
|
for (; isym < isymend; isym++)
|
for (; isym < isymend; isym++)
|
{
|
{
|
if (isym->st_shndx == sec_shndx
|
if (isym->st_shndx == sec_shndx
|
&& isym->st_value > addr
|
&& isym->st_value > addr
|
&& isym->st_value < toaddr)
|
&& isym->st_value < toaddr)
|
isym->st_value -= count;
|
isym->st_value -= count;
|
}
|
}
|
|
}
|
|
|
/* Now adjust the global symbols defined in this section. */
|
/* Now adjust the global symbols defined in this section. */
|
symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
|
symcount = (symtab_hdr->sh_size / sizeof (Elf32_External_Sym)
|
- symtab_hdr->sh_info);
|
- symtab_hdr->sh_info);
|
sym_hashes = elf_sym_hashes (abfd);
|
sym_hashes = elf_sym_hashes (abfd);
|
Line 1594... |
Line 1632... |
Elf_Internal_Sym *isymbuf = NULL;
|
Elf_Internal_Sym *isymbuf = NULL;
|
static asection *last_input_section = NULL;
|
static asection *last_input_section = NULL;
|
static Elf_Internal_Rela *last_reloc = NULL;
|
static Elf_Internal_Rela *last_reloc = NULL;
|
struct elf32_avr_link_hash_table *htab;
|
struct elf32_avr_link_hash_table *htab;
|
|
|
|
if (link_info->relocatable)
|
|
(*link_info->callbacks->einfo)
|
|
(_("%P%F: --relax and -r may not be used together\n"));
|
|
|
htab = avr_link_hash_table (link_info);
|
htab = avr_link_hash_table (link_info);
|
if (htab == NULL)
|
if (htab == NULL)
|
return FALSE;
|
return FALSE;
|
|
|
/* Assume nothing changes. */
|
/* Assume nothing changes. */
|
Line 2032... |
Line 2074... |
_bfd_elf_section_from_bfd_section (abfd, sec);
|
_bfd_elf_section_from_bfd_section (abfd, sec);
|
|
|
/* Check for local symbols. */
|
/* Check for local symbols. */
|
isym = (Elf_Internal_Sym *) symtab_hdr->contents;
|
isym = (Elf_Internal_Sym *) symtab_hdr->contents;
|
isymend = isym + symtab_hdr->sh_info;
|
isymend = isym + symtab_hdr->sh_info;
|
for (; isym < isymend; isym++)
|
/* PR 6019: There may not be any local symbols. */
|
|
for (; isym != NULL && isym < isymend; isym++)
|
{
|
{
|
if (isym->st_value == section_offset_of_ret_insn
|
if (isym->st_value == section_offset_of_ret_insn
|
&& isym->st_shndx == sec_shndx)
|
&& isym->st_shndx == sec_shndx)
|
{
|
{
|
deleting_ret_is_safe = 0;
|
deleting_ret_is_safe = 0;
|
Line 2587... |
Line 2630... |
get_local_syms (bfd *input_bfd, struct bfd_link_info *info)
|
get_local_syms (bfd *input_bfd, struct bfd_link_info *info)
|
{
|
{
|
unsigned int bfd_indx;
|
unsigned int bfd_indx;
|
Elf_Internal_Sym *local_syms, **all_local_syms;
|
Elf_Internal_Sym *local_syms, **all_local_syms;
|
struct elf32_avr_link_hash_table *htab = avr_link_hash_table (info);
|
struct elf32_avr_link_hash_table *htab = avr_link_hash_table (info);
|
|
bfd_size_type amt;
|
|
|
if (htab == NULL)
|
if (htab == NULL)
|
return -1;
|
return -1;
|
|
|
/* We want to read in symbol extension records only once. To do this
|
/* We want to read in symbol extension records only once. To do this
|
we need to read in the local symbols in parallel and save them for
|
we need to read in the local symbols in parallel and save them for
|
later use; so hold pointers to the local symbols in an array. */
|
later use; so hold pointers to the local symbols in an array. */
|
bfd_size_type amt = sizeof (Elf_Internal_Sym *) * htab->bfd_count;
|
amt = sizeof (Elf_Internal_Sym *) * htab->bfd_count;
|
all_local_syms = bfd_zmalloc (amt);
|
all_local_syms = bfd_zmalloc (amt);
|
htab->all_local_syms = all_local_syms;
|
htab->all_local_syms = all_local_syms;
|
if (all_local_syms == NULL)
|
if (all_local_syms == NULL)
|
return -1;
|
return -1;
|
|
|
Line 2755... |
Line 2799... |
if (r_indx < symtab_hdr->sh_info)
|
if (r_indx < symtab_hdr->sh_info)
|
{
|
{
|
/* It's a local symbol. */
|
/* It's a local symbol. */
|
Elf_Internal_Sym *sym;
|
Elf_Internal_Sym *sym;
|
Elf_Internal_Shdr *hdr;
|
Elf_Internal_Shdr *hdr;
|
|
unsigned int shndx;
|
|
|
sym = local_syms + r_indx;
|
sym = local_syms + r_indx;
|
hdr = elf_elfsections (input_bfd)[sym->st_shndx];
|
|
sym_sec = hdr->bfd_section;
|
|
if (ELF_ST_TYPE (sym->st_info) != STT_SECTION)
|
if (ELF_ST_TYPE (sym->st_info) != STT_SECTION)
|
sym_value = sym->st_value;
|
sym_value = sym->st_value;
|
|
shndx = sym->st_shndx;
|
|
if (shndx < elf_numsections (input_bfd))
|
|
{
|
|
hdr = elf_elfsections (input_bfd)[shndx];
|
|
sym_sec = hdr->bfd_section;
|
destination = (sym_value + irela->r_addend
|
destination = (sym_value + irela->r_addend
|
+ sym_sec->output_offset
|
+ sym_sec->output_offset
|
+ sym_sec->output_section->vma);
|
+ sym_sec->output_section->vma);
|
}
|
}
|
|
}
|
else
|
else
|
{
|
{
|
/* It's an external symbol. */
|
/* It's an external symbol. */
|
int e_indx;
|
int e_indx;
|
|
|