Add MN10300 linker relaxation support for symbol differences

This commit is contained in:
Nick Clifton 2007-10-19 17:31:31 +00:00
parent 97030eea00
commit bfff164249
32 changed files with 672 additions and 100 deletions

View File

@ -1,3 +1,22 @@
2007-10-19 Nick Clifton <nickc@redhat.com>
* config.bfd: Recognise am34-linux-gnu target.
* reloc.c: Add BFD_RELOC_MN10300_SYM_DIFF relocation.
* bfd-in2.h: Regenerate.
* libbfd.h: Regenerate.
* elf-m10300.c (elf_mn10300_howto): Add R_MN10300_SYM_DIFF.
(mn10300_reloc_map): Likewise.
(mn10300_elf_check_relocs): Do not create dynamic relocs for
symbol differences or relocations against absolute symbols.
(mn10300_elf_final_link_relocate): Likewise.
Handle R_MN10300_SYM_DIFF relocs.
(mn10300_elf_relocate_section): Fix for creating local copys of
dynamic relocs.
(mn10300_elf_relax_delete_bytes): Adjust symbols at the end of the
region. Adjust the size of function symbols.
(mn10300_elf_relax_section): Ignore symbols that are in discarded
sections.
2007-10-19 Nick Clifton <nickc@redhat.com>
* elf-m10300.c: Convert to ISO C.

View File

@ -2774,6 +2774,11 @@ in the instruction. */
/* Adjust by program base. */
BFD_RELOC_MN10300_RELATIVE,
/* Together with another reloc targeted at the same location,
allows for a value that is the difference of two symbols
in the same section. */
BFD_RELOC_MN10300_SYM_DIFF,
/* i386/elf relocations */
BFD_RELOC_386_GOT32,

View File

@ -71,6 +71,7 @@ esac
targ_cpu=`echo $targ | sed 's/^\([^-]*\)-\([^-]*\)-\(.*\)$/\1/'`
case "${targ_cpu}" in
alpha*) targ_archs=bfd_alpha_arch ;;
am34*|am33_2.0*) targ_archs=bfd_mn10300_arch ;;
arm*) targ_archs=bfd_arm_arch ;;
bfin*) targ_archs=bfd_bfin_arch ;;
c30*) targ_archs=bfd_tic30_arch ;;
@ -107,7 +108,6 @@ xscale*) targ_archs=bfd_arm_arch ;;
xtensa*) targ_archs=bfd_xtensa_arch ;;
z80|r800) targ_archs=bfd_z80_arch ;;
z8k*) targ_archs=bfd_z8k_arch ;;
am33_2.0) targ_archs=bfd_mn10300_arch ;;
*) targ_archs=bfd_${targ_cpu}_arch ;;
esac
@ -197,9 +197,10 @@ case "${targ}" in
;;
#endif /* BFD64 */
am33_2.0-*-linux*)
am34-*-linux* | am33_2.0-*-linux*)
targ_defvec=bfd_elf32_am33lin_vec
;;
arc-*-elf*)
targ_defvec=bfd_elf32_littlearc_vec
targ_selvecs=bfd_elf32_bigarc_vec

View File

@ -446,6 +446,30 @@ static reloc_howto_type elf_mn10300_howto_table[] =
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
FALSE), /* pcrel_offset */
EMPTY_HOWTO (24),
EMPTY_HOWTO (25),
EMPTY_HOWTO (26),
EMPTY_HOWTO (27),
EMPTY_HOWTO (28),
EMPTY_HOWTO (29),
EMPTY_HOWTO (30),
EMPTY_HOWTO (31),
EMPTY_HOWTO (32),
HOWTO (R_MN10300_SYM_DIFF, /* type */
0, /* rightshift */
2, /* size (0 = byte, 1 = short, 2 = long) */
32, /* bitsize */
FALSE, /* pc_relative */
0, /* bitpos */
complain_overflow_dont,/* complain_on_overflow */
NULL, /* special handler. */
"R_MN10300_SYM_DIFF", /* name */
FALSE, /* partial_inplace */
0xffffffff, /* src_mask */
0xffffffff, /* dst_mask */
FALSE) /* pcrel_offset */
};
struct mn10300_reloc_map
@ -480,6 +504,7 @@ static const struct mn10300_reloc_map mn10300_reloc_map[] =
{ BFD_RELOC_MN10300_GLOB_DAT, R_MN10300_GLOB_DAT },
{ BFD_RELOC_MN10300_JMP_SLOT, R_MN10300_JMP_SLOT },
{ BFD_RELOC_MN10300_RELATIVE, R_MN10300_RELATIVE },
{ BFD_RELOC_MN10300_SYM_DIFF, R_MN10300_SYM_DIFF }
};
/* Create the GOT section. */
@ -619,6 +644,7 @@ mn10300_elf_check_relocs (bfd *abfd,
asection *sec,
const Elf_Internal_Rela *relocs)
{
bfd_boolean sym_diff_reloc_seen;
Elf_Internal_Shdr *symtab_hdr;
struct elf_link_hash_entry **sym_hashes;
const Elf_Internal_Rela *rel;
@ -642,6 +668,7 @@ mn10300_elf_check_relocs (bfd *abfd,
dynobj = elf_hash_table (info)->dynobj;
local_got_offsets = elf_local_got_offsets (abfd);
rel_end = relocs + sec->reloc_count;
sym_diff_reloc_seen = FALSE;
for (rel = relocs; rel < rel_end; rel++)
{
@ -814,53 +841,98 @@ mn10300_elf_check_relocs (bfd *abfd,
h->non_got_ref = 1;
break;
case R_MN10300_SYM_DIFF:
sym_diff_reloc_seen = TRUE;
break;
case R_MN10300_32:
if (h != NULL)
h->non_got_ref = 1;
/* If we are creating a shared library, then we need to copy
the reloc into the shared library. */
/* If we are creating a shared library, then we
need to copy the reloc into the shared library. */
if (info->shared
&& (sec->flags & SEC_ALLOC) != 0)
&& (sec->flags & SEC_ALLOC) != 0
/* Do not generate a dynamic reloc for a
reloc associated with a SYM_DIFF operation. */
&& ! sym_diff_reloc_seen)
{
/* When creating a shared object, we must copy these
reloc types into the output file. We create a reloc
section in dynobj and make room for this reloc. */
if (sreloc == NULL)
asection * sym_section = NULL;
/* Find the section containing the
symbol involved in the relocation. */
if (h == NULL)
{
const char * name;
Elf_Internal_Sym * isymbuf;
Elf_Internal_Sym * isym;
name = (bfd_elf_string_from_elf_section
(abfd,
elf_elfheader (abfd)->e_shstrndx,
elf_section_data (sec)->rel_hdr.sh_name));
if (name == NULL)
return FALSE;
BFD_ASSERT (CONST_STRNEQ (name, ".rela")
&& streq (bfd_get_section_name (abfd, sec), name + 5));
sreloc = bfd_get_section_by_name (dynobj, name);
if (sreloc == 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)
{
flagword flags;
flags = (SEC_HAS_CONTENTS | SEC_READONLY
| SEC_IN_MEMORY | SEC_LINKER_CREATED);
if ((sec->flags & SEC_ALLOC) != 0)
flags |= SEC_ALLOC | SEC_LOAD;
sreloc = bfd_make_section_with_flags (dynobj, name, flags);
if (sreloc == NULL
|| ! bfd_set_section_alignment (dynobj, sreloc, 2))
return FALSE;
isym = isymbuf + r_symndx;
/* All we care about is whether this local symbol is absolute. */
if (isym->st_shndx == SHN_ABS)
sym_section = bfd_abs_section_ptr;
}
}
else
{
if (h->root.type == bfd_link_hash_defined
|| h->root.type == bfd_link_hash_defweak)
sym_section = h->root.u.def.section;
}
sreloc->size += sizeof (Elf32_External_Rela);
/* If the symbol is absolute then the relocation can
be resolved during linking and there is no need for
a dynamic reloc. */
if (sym_section != bfd_abs_section_ptr)
{
/* When creating a shared object, we must copy these
reloc types into the output file. We create a reloc
section in dynobj and make room for this reloc. */
if (sreloc == NULL)
{
const char * name;
name = (bfd_elf_string_from_elf_section
(abfd,
elf_elfheader (abfd)->e_shstrndx,
elf_section_data (sec)->rel_hdr.sh_name));
if (name == NULL)
return FALSE;
BFD_ASSERT (CONST_STRNEQ (name, ".rela")
&& streq (bfd_get_section_name (abfd, sec), name + 5));
sreloc = bfd_get_section_by_name (dynobj, name);
if (sreloc == NULL)
{
flagword flags;
flags = (SEC_HAS_CONTENTS | SEC_READONLY
| SEC_IN_MEMORY | SEC_LINKER_CREATED);
if ((sec->flags & SEC_ALLOC) != 0)
flags |= SEC_ALLOC | SEC_LOAD;
sreloc = bfd_make_section_with_flags (dynobj, name, flags);
if (sreloc == NULL
|| ! bfd_set_section_alignment (dynobj, sreloc, 2))
return FALSE;
}
}
sreloc->size += sizeof (Elf32_External_Rela);
}
}
break;
}
if (ELF32_R_TYPE (rel->r_info) != R_MN10300_SYM_DIFF)
sym_diff_reloc_seen = FALSE;
}
return TRUE;
@ -904,6 +976,9 @@ mn10300_elf_final_link_relocate (reloc_howto_type *howto,
asection *sym_sec ATTRIBUTE_UNUSED,
int is_local ATTRIBUTE_UNUSED)
{
static asection * sym_diff_section;
static bfd_vma sym_diff_value;
bfd_boolean is_sym_diff_reloc;
unsigned long r_type = howto->type;
bfd_byte * hit_data = contents + offset;
bfd * dynobj;
@ -937,13 +1012,54 @@ mn10300_elf_final_link_relocate (reloc_howto_type *howto,
return bfd_reloc_dangerous;
}
is_sym_diff_reloc = FALSE;
if (sym_diff_section != NULL)
{
BFD_ASSERT (sym_diff_section == input_section);
switch (r_type)
{
case R_MN10300_32:
case R_MN10300_24:
case R_MN10300_16:
case R_MN10300_8:
value -= sym_diff_value;
sym_diff_section = NULL;
is_sym_diff_reloc = TRUE;
break;
default:
sym_diff_section = NULL;
break;
}
}
switch (r_type)
{
case R_MN10300_SYM_DIFF:
BFD_ASSERT (addend == 0);
/* Cache the input section and value.
The offset is unreliable, since relaxation may
have reduced the following reloc's offset. */
sym_diff_section = input_section;
sym_diff_value = value;
return bfd_reloc_ok;
case R_MN10300_NONE:
return bfd_reloc_ok;
case R_MN10300_32:
if (info->shared
/* Do not generate relocs when an R_MN10300_32 has been used
with an R_MN10300_SYM_DIFF to compute a difference of two
symbols. */
&& is_sym_diff_reloc == FALSE
/* Also, do not generate a reloc when the symbol associated
with the R_MN10300_32 reloc is absolute - there is no
need for a run time computation in this case. */
&& sym_sec != bfd_abs_section_ptr
/* If the section is not going to be allocated at load time
then there is no need to generate relocs for it. */
&& (input_section->flags & SEC_ALLOC) != 0)
{
Elf_Internal_Rela outrel;
@ -1370,6 +1486,10 @@ mn10300_elf_relocate_section (bfd *output_bfd,
&& elf_hash_table (info)->dynamic_sections_created
&& !SYMBOL_REFERENCES_LOCAL (info, hh))
|| (r_type == R_MN10300_32
/* _32 relocs in executables force _COPY relocs,
such that the address of the symbol ends up
being local. */
&& !info->executable
&& !SYMBOL_REFERENCES_LOCAL (info, hh)
&& ((input_section->flags & SEC_ALLOC) != 0
/* DWARF will emit R_MN10300_32 relocations
@ -1551,7 +1671,7 @@ static bfd_boolean
elf32_mn10300_count_hash_table_entries (struct bfd_hash_entry *gen_entry ATTRIBUTE_UNUSED,
void * in_args)
{
int *count = (int *)in_args;
int *count = (int *) in_args;
(*count) ++;
return TRUE;
@ -1576,9 +1696,9 @@ static int
sort_by_value (const void *va, const void *vb)
{
struct elf32_mn10300_link_hash_entry *a
= *(struct elf32_mn10300_link_hash_entry **)va;
= *(struct elf32_mn10300_link_hash_entry **) va;
struct elf32_mn10300_link_hash_entry *b
= *(struct elf32_mn10300_link_hash_entry **)vb;
= *(struct elf32_mn10300_link_hash_entry **) vb;
return a->value - b->value;
}
@ -1735,8 +1855,14 @@ mn10300_elf_relax_delete_bytes (bfd *abfd,
{
if (isym->st_shndx == sec_shndx
&& isym->st_value > addr
&& isym->st_value < toaddr)
&& isym->st_value <= toaddr)
isym->st_value -= count;
/* Adjust the function symbol's size as well. */
else if (isym->st_shndx == sec_shndx
&& ELF_ST_TYPE (isym->st_info) == STT_FUNC
&& isym->st_value + isym->st_size > addr
&& isym->st_value + isym->st_size <= toaddr)
isym->st_size -= count;
}
/* Now adjust the global symbols defined in this section. */
@ -1752,8 +1878,15 @@ mn10300_elf_relax_delete_bytes (bfd *abfd,
|| sym_hash->root.type == bfd_link_hash_defweak)
&& sym_hash->root.u.def.section == sec
&& sym_hash->root.u.def.value > addr
&& sym_hash->root.u.def.value < toaddr)
&& sym_hash->root.u.def.value <= toaddr)
sym_hash->root.u.def.value -= count;
/* Adjust the function symbol's size as well. */
else if (sym_hash->root.type == bfd_link_hash_defined
&& sym_hash->root.u.def.section == sec
&& sym_hash->type == STT_FUNC
&& sym_hash->root.u.def.value + sym_hash->size > addr
&& sym_hash->root.u.def.value + sym_hash->size <= toaddr)
sym_hash->size -= count;
}
return TRUE;
@ -1981,7 +2114,7 @@ mn10300_elf_relax_section (bfd *abfd,
local symbol in the global hash table. */
amt = strlen (sym_name) + 10;
new_name = bfd_malloc (amt);
if (new_name == 0)
if (new_name == NULL)
goto error_return;
sprintf (new_name, "%s_%08x", sym_name, sym_sec->id);
@ -2090,7 +2223,7 @@ mn10300_elf_relax_section (bfd *abfd,
local symbol in the global hash table. */
amt = strlen (sym_name) + 10;
new_name = bfd_malloc (amt);
if (new_name == 0)
if (new_name == NULL)
goto error_return;
sprintf (new_name, "%s_%08x", sym_name, sym_sec->id);
@ -2302,7 +2435,7 @@ mn10300_elf_relax_section (bfd *abfd,
local symbol in the global hash table. */
amt = strlen (sym_name) + 10;
new_name = bfd_malloc (amt);
if (new_name == 0)
if (new_name == NULL)
goto error_return;
sprintf (new_name, "%s_%08x", sym_name, sym_sec->id);
sym_name = new_name;
@ -2514,7 +2647,6 @@ mn10300_elf_relax_section (bfd *abfd,
asection *sym_sec = NULL;
const char *sym_name;
char *new_name;
bfd_vma saved_addend;
/* A local symbol. */
isym = isymbuf + ELF32_R_SYM (irel->r_info);
@ -2535,22 +2667,22 @@ mn10300_elf_relax_section (bfd *abfd,
&& ELF_ST_TYPE (isym->st_info) == STT_SECTION
&& sym_sec->sec_info_type == ELF_INFO_TYPE_MERGE)
{
bfd_vma saved_addend;
saved_addend = irel->r_addend;
symval = _bfd_elf_rela_local_sym (abfd, isym, &sym_sec, irel);
symval = _bfd_elf_rela_local_sym (abfd, isym, & sym_sec, irel);
symval += irel->r_addend;
irel->r_addend = saved_addend;
}
else
{
symval = (isym->st_value
+ sym_sec->output_section->vma
+ sym_sec->output_offset);
}
symval = (isym->st_value
+ sym_sec->output_section->vma
+ sym_sec->output_offset);
/* Tack on an ID so we can uniquely identify this
local symbol in the global hash table. */
new_name = bfd_malloc ((bfd_size_type) strlen (sym_name) + 10);
if (new_name == 0)
if (new_name == NULL)
goto error_return;
sprintf (new_name, "%s_%08x", sym_name, sym_sec->id);
sym_name = new_name;
@ -2576,6 +2708,10 @@ mn10300_elf_relax_section (bfd *abfd,
regular reloc processing. */
continue;
/* Check for a reference to a discarded symbol and ignore it. */
if (h->root.root.u.def.section->output_section == NULL)
continue;
symval = (h->root.root.u.def.value
+ h->root.root.u.def.section->output_section->vma
+ h->root.root.u.def.section->output_offset);
@ -3284,7 +3420,7 @@ mn10300_elf_relax_section (bfd *abfd,
case 0x93:
/* sp-based offsets are zero-extended. */
if (code >= 0x90 && code <= 0x93
&& (long)value < 0)
&& (long) value < 0)
continue;
/* Note that we've changed the relocation contents, etc. */
@ -3341,7 +3477,7 @@ mn10300_elf_relax_section (bfd *abfd,
/* mov imm16, an zero-extends the immediate. */
if (code == 0xdc
&& (long)value < 0)
&& (long) value < 0)
continue;
/* Note that we've changed the relocation contents, etc. */
@ -3422,12 +3558,12 @@ mn10300_elf_relax_section (bfd *abfd,
case 0xe3:
/* cmp imm16, an zero-extends the immediate. */
if (code == 0xdc
&& (long)value < 0)
&& (long) value < 0)
continue;
/* So do sp-based offsets. */
if (code >= 0xb0 && code <= 0xb3
&& (long)value < 0)
&& (long) value < 0)
continue;
/* Note that we've changed the relocation contents, etc. */

View File

@ -1046,6 +1046,7 @@ static const char *const bfd_reloc_code_real_names[] = { "@@uninitialized@@",
"BFD_RELOC_MN10300_GLOB_DAT",
"BFD_RELOC_MN10300_JMP_SLOT",
"BFD_RELOC_MN10300_RELATIVE",
"BFD_RELOC_MN10300_SYM_DIFF",
"BFD_RELOC_386_GOT32",
"BFD_RELOC_386_PLT32",

View File

@ -2361,6 +2361,12 @@ ENUM
BFD_RELOC_MN10300_RELATIVE
ENUMDOC
Adjust by program base.
ENUM
BFD_RELOC_MN10300_SYM_DIFF
ENUMDOC
Together with another reloc targeted at the same location,
allows for a value that is the difference of two symbols
in the same section.
COMMENT
ENUM

View File

@ -1,3 +1,24 @@
2007-10-19 Nick Clifton <nickc@redhat.com>
* expr.c (expr): Test md_allow_local_subtract (if defined) before
allowing the evaluation of an expression involving two symbols
defined in the same section.
* doc/internals.texi (md_allow_local_subtract): Document the new
macro.
* config/tc-mn10300.h (md_allow_local_subtract): Define.
(RELAX_EXPANSION_POSSIBLE): Define.
(MAX_RELOC_EXPANSION): Define.
(TC_FRAG_TYPE): Define.
* config/tc-mn10300.c (md_assemble): Mark fragments as containing code.
(tc_gen_reloc): Return an array of relocs. If necessary generate
two relocs to handle an expressions involving the difference of
two symbols.
(mn10300_fix_adjustable): Do not test TC_FORCE_RELOCATION_LOCAL
when then fixup is not pc-relative.
(mn10300_allow_local_subtract): New function. Determine when it
is safe to compute the difference between two symbols at assemble
time.
2007-10-19 Alan Modra <amodra@bigpond.net.au>
* config/tc-ppc.c (ppc_parse_name): Skip leading '%'.

View File

@ -2141,15 +2141,21 @@ keep_going:
dwarf2_emit_insn (size);
}
/* Label this frag as one that contains instructions. */
frag_now->tc_frag_data = TRUE;
}
/* If while processing a fixup, a reloc really needs to be created
then it is done here. */
arelent *
arelent **
tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixp)
{
static arelent * no_relocs = NULL;
static arelent * relocs[MAX_RELOC_EXPANSION + 1];
arelent *reloc;
reloc = xmalloc (sizeof (arelent));
reloc->howto = bfd_reloc_type_lookup (stdoutput, fixp->fx_r_type);
@ -2158,9 +2164,13 @@ tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixp)
as_bad_where (fixp->fx_file, fixp->fx_line,
_("reloc %d not supported by object file format"),
(int) fixp->fx_r_type);
return NULL;
free (reloc);
return & no_relocs;
}
reloc->address = fixp->fx_frag->fr_address + fixp->fx_where;
relocs[0] = reloc;
relocs[1] = NULL;
if (fixp->fx_subsy
&& S_GET_SEGMENT (fixp->fx_subsy) == absolute_section)
@ -2173,44 +2183,33 @@ tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixp)
{
reloc->sym_ptr_ptr = NULL;
/* If we got a difference between two symbols, and the
subtracted symbol is in the current section, use a
PC-relative relocation. If both symbols are in the same
section, the difference would have already been simplified
to a constant. */
/* If we have a difference between two (non-absolute) symbols we must
generate two relocs (one for each symbol) and allow the linker to
resolve them - relaxation may change the distances between symbols,
even local symbols defined in the same segment. */
if (S_GET_SEGMENT (fixp->fx_subsy) == seg)
{
arelent * reloc2 = xmalloc (sizeof * reloc);
relocs[0] = reloc2;
relocs[1] = reloc;
reloc2->address = reloc->address;
reloc2->howto = bfd_reloc_type_lookup (stdoutput, BFD_RELOC_MN10300_SYM_DIFF);
reloc2->addend = - S_GET_VALUE (fixp->fx_subsy);
reloc2->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
*reloc2->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_subsy);
reloc->addend = fixp->fx_offset;
if (S_GET_SEGMENT (fixp->fx_addsy) == absolute_section)
reloc->addend += S_GET_VALUE (fixp->fx_addsy);
reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
*reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
reloc->addend = (reloc->address - S_GET_VALUE (fixp->fx_subsy)
+ fixp->fx_offset);
switch (fixp->fx_r_type)
{
case BFD_RELOC_8:
reloc->howto = bfd_reloc_type_lookup (stdoutput,
BFD_RELOC_8_PCREL);
return reloc;
case BFD_RELOC_16:
reloc->howto = bfd_reloc_type_lookup (stdoutput,
BFD_RELOC_16_PCREL);
return reloc;
case BFD_RELOC_24:
reloc->howto = bfd_reloc_type_lookup (stdoutput,
BFD_RELOC_24_PCREL);
return reloc;
case BFD_RELOC_32:
reloc->howto = bfd_reloc_type_lookup (stdoutput,
BFD_RELOC_32_PCREL);
return reloc;
default:
/* Try to compute the absolute value below. */
break;
}
fixp->fx_pcrel = 0;
fixp->fx_done = 1;
return relocs;
}
if ((S_GET_SEGMENT (fixp->fx_addsy) != S_GET_SEGMENT (fixp->fx_subsy))
@ -2247,14 +2246,14 @@ tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixp)
default:
reloc->sym_ptr_ptr
= (asymbol **) bfd_abs_section_ptr->symbol_ptr_ptr;
return reloc;
return relocs;
}
}
if (reloc->sym_ptr_ptr)
free (reloc->sym_ptr_ptr);
free (reloc);
return NULL;
return & no_relocs;
}
else
{
@ -2262,7 +2261,7 @@ tc_gen_reloc (asection *seg ATTRIBUTE_UNUSED, fixS *fixp)
*reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
reloc->addend = fixp->fx_offset;
}
return reloc;
return relocs;
}
int
@ -2377,11 +2376,14 @@ md_apply_fix (fixS * fixP, valueT * valP, segT seg)
bfd_boolean
mn10300_fix_adjustable (struct fix *fixp)
{
if (TC_FORCE_RELOCATION_LOCAL (fixp))
return FALSE;
if (fixp->fx_r_type == BFD_RELOC_VTABLE_INHERIT
|| fixp->fx_r_type == BFD_RELOC_VTABLE_ENTRY)
if (fixp->fx_pcrel)
{
if (TC_FORCE_RELOCATION_LOCAL (fixp))
return FALSE;
}
/* Non-relative relocs can (and must) be adjusted if they do
not meet the criteria below, or the generic criteria. */
else if (TC_FORCE_RELOCATION (fixp))
return FALSE;
/* Do not adjust relocations involving symbols in code sections,
@ -2395,8 +2397,9 @@ mn10300_fix_adjustable (struct fix *fixp)
symbols, because they too break relaxation. We do want to adjust
other mergable symbols, like .rodata, because code relaxations
need section-relative symbols to properly relax them. */
if (! (S_GET_SEGMENT(fixp->fx_addsy)->flags & SEC_MERGE))
if (! (S_GET_SEGMENT (fixp->fx_addsy)->flags & SEC_MERGE))
return FALSE;
if (strncmp (S_GET_SEGMENT (fixp->fx_addsy)->name, ".debug", 6) == 0)
return FALSE;
@ -2502,3 +2505,60 @@ const pseudo_typeS md_pseudo_table[] =
{ "mn10300", set_arch_mach, MN103 },
{NULL, 0, 0}
};
/* Returns FALSE if there is some mn10300 specific reason why the
subtraction of two same-section symbols cannot be computed by
the assembler. */
bfd_boolean
mn10300_allow_local_subtract (expressionS * left, expressionS * right, segT section)
{
bfd_boolean result;
fragS * left_frag;
fragS * right_frag;
fragS * frag;
/* If we are not performing linker relaxation then we have nothing
to worry about. */
if (linkrelax == 0)
return TRUE;
/* If the symbols are not in a code section then they are OK. */
if ((section->flags & SEC_CODE) == 0)
return TRUE;
/* Otherwise we have to scan the fragments between the two symbols.
If any instructions are found then we have to assume that linker
relaxation may change their size and so we must delay resolving
the subtraction until the final link. */
left_frag = symbol_get_frag (left->X_add_symbol);
right_frag = symbol_get_frag (right->X_add_symbol);
if (left_frag == right_frag)
return ! left_frag->tc_frag_data;
result = TRUE;
for (frag = left_frag; frag != NULL; frag = frag->fr_next)
{
if (frag->tc_frag_data)
result = FALSE;
if (frag == right_frag)
break;
}
if (frag == NULL)
for (frag = right_frag; frag != NULL; frag = frag->fr_next)
{
if (frag->tc_frag_data)
result = FALSE;
if (frag == left_frag)
break;
}
if (frag == NULL)
/* The two symbols are on disjoint fragment chains
- we cannot possibly compute their difference. */
return FALSE;
return result;
}

View File

@ -98,13 +98,21 @@ void mn10300_cons_fix_new PARAMS ((fragS *, int, int, expressionS *));
#define md_number_to_chars number_to_chars_littleendian
/* Don't bother to adjust relocs. */
/* #define tc_fix_adjustable(FIX) 0 */
#define tc_fix_adjustable(FIX) mn10300_fix_adjustable (FIX)
extern bfd_boolean mn10300_fix_adjustable PARAMS ((struct fix *));
extern bfd_boolean mn10300_fix_adjustable (struct fix *);
/* We do relaxing in the assembler as well as the linker. */
extern const struct relax_type md_relax_table[];
#define TC_GENERIC_RELAX_TABLE md_relax_table
#define DWARF2_LINE_MIN_INSN_LENGTH 1
/* The difference between same-section symbols may be affected by linker
relaxation, so do not resolve such expressions in the assembler. */
#define md_allow_local_subtract(l,r,s) mn10300_allow_local_subtract (l, r, s)
extern bfd_boolean mn10300_allow_local_subtract (expressionS *, expressionS *, segT);
#define RELOC_EXPANSION_POSSIBLE
#define MAX_RELOC_EXPANSION 2
#define TC_FRAG_TYPE bfd_boolean

View File

@ -1535,6 +1535,18 @@ The function should return the debug format that is preferred by the CPU
backend. This format will be used when generating assembler specific debug
information.
@item md_allow_local_subtract (@var{left}, @var{right}, @var{section})
If defined, GAS will call this macro when evaluating an expression which is the
difference of two symbols defined in the same section. It takes three
arguments: @code{expressioS * @var{left}} which is the symbolic expression on
the left hand side of the subtraction operation, @code{expressionS *
@var{right}} which is the symbolic expression on the right hand side of the
subtraction, and @code{segT @var{section}} which is the section containing the two
symbols. The macro should return a non-zero value if the expression should be
evaluated. Targets which implement link time relaxation which may change the
position of the two symbols relative to each other should ensure that this
macro returns zero in situations where this can occur.
@end table
@node Object format backend

View File

@ -1738,6 +1738,9 @@ expr (int rankarg, /* Larger # is higher rank. */
&& right.X_op == O_symbol
&& resultP->X_op == O_symbol
&& retval == rightseg
#ifdef md_allow_local_subtract
&& md_allow_local_subtract (resultP, & right, rightseg)
#endif
&& (SEG_NORMAL (rightseg)
|| right.X_add_symbol == resultP->X_add_symbol)
&& frag_offset_fixed_p (symbol_get_frag (resultP->X_add_symbol),

View File

@ -1,3 +1,9 @@
2007-10-19 Nick Clifton <nickc@redhat.com>
* gas/mn10300/basic.exp: Run pr997 test.
* gas/mn10300/pr997.s: New test.
* gas/mn10300/pr887.l: Expected output.
2007-10-17 Nathan Sidwell <nathan@codesourcery.com>
* gas/m68k/mcf-movsr.s: New.

View File

@ -1801,6 +1801,7 @@ if [istarget mn10300*-*-*] then {
do_am33_8
run_list_test "movpc" ""
run_list_test "pr997" "-a"
run_dump_test "am33-2"
run_dump_test "relax"

View File

@ -0,0 +1,20 @@
GAS LISTING .*/pr997.s.*page 1
1.*.data
2.*
3 0000 68656C6C.*msg:.*.asciz "hello world.\\n"
3 6F20776F
3 726C642E
3 0A00
4.*msglen = .-msg-1
5.*msglen=msglen & 0xff
.*GAS LISTING.*/pr997.s.*page 2
DEFINED SYMBOLS
.*/pr997.s:3.*.data:0+00 msg
.*/pr997.s:4.*\*ABS\*:0+0d msglen
NO UNDEFINED SYMBOLS

View File

@ -0,0 +1,5 @@
.data
msg: .asciz "hello world.\n"
msglen = .-msg-1
msglen=msglen & 0xff

View File

@ -1,3 +1,7 @@
2007-10-19 Nick Clifton <nickc@redhat.com>
* mn10300.h: Add R_MN10300_SYM_DIFF reloc.
2007-10-18 Roland McGrath <roland@redhat.com>
* common.h (NT_PPC_VMX): New macro.

View File

@ -50,6 +50,7 @@ START_RELOC_NUMBERS (elf_mn10300_reloc_type)
RELOC_NUMBER (R_MN10300_GLOB_DAT, 21)
RELOC_NUMBER (R_MN10300_JMP_SLOT, 22)
RELOC_NUMBER (R_MN10300_RELATIVE, 23)
RELOC_NUMBER (R_MN10300_SYM_DIFF, 33)
END_RELOC_NUMBERS (R_MN10300_MAX)
/* Machine variant if we know it. This field was invented at Cygnus,

View File

@ -1,3 +1,7 @@
2007-10-19 Nick Clifton <nickc@redhat.com>
* configure.tgt: Add support for am34-linux-gnu target.
2007-10-17 Zack Weinberg <zack@codesourcery.com>
* ldlang.c (lang_check_section_addresses): Also report size of

View File

@ -400,6 +400,7 @@ mips*-*-sysv4*) targ_emul=elf32btsmip
mmix-*-*) targ_emul=mmo
targ_extra_emuls=elf64mmix
;;
am34-*-linux*) targ_emul=elf32am33lin ;;
am33_2.0-*-linux*) targ_emul=elf32am33lin ;;
mn10200-*-*) targ_emul=mn10200 ;;
mn10300-*-*) targ_emul=mn10300

View File

@ -1,3 +1,19 @@
2007-10-19 Nick Clifton <nickc@redhat.com>
* ld-mn10300: New test directory.
* ld-mn10300/mn10300.exp: Run the new tests.
* ld-mn10300/i112045-1.s: Linker relaxation test.
* ld-mn10300/i112045-1.d: Expected disassembly.
* ld-mn10300/i112045-2.s: Linker relaxation test.
* ld-mn10300/i112045-2.d: Expected disassembly.
* ld-mn10300/i126256-1.c: Test source.
* ld-mn10300/i126256-2.c: Test source.
* ld-mn10300/i135409.s: Linker relaxation test.
* ld-mn10300/i135409.d: Expected symbol table contents.
* ld-mn10300/i136434.s: Linker string section merge test.
* ld-mn10300/i136434.d: Expected disassembly.
* ld-mn10300/i136434-2.s: Test source file.
2007-10-17 Zack Weinberg <zack@codesourcery.com>
Daniel Jacobowitz <dan@codesourcery.com>
Mark Shinwell <shinwell@codesourcery.com>

View File

@ -0,0 +1,22 @@
tmpdir/i112045-1.x: file format elf32-.*
Disassembly of section .text:
0+0 <_start>:
0: fc d0 f8 0f[ ]+add 4088,a0
4: 00 00
6: cb[ ]+nop[ ]+
7: cb[ ]+nop[ ]+
0+08 <L01>:
8: fc d0 2b 01[ ]+add 299,a0
c: 00 00
e: cb[ ]+nop[ ]+
f: cb[ ]+nop[ ]+
0+010 <L02>:
10: fc d0 08 00[ ]+add 8,a0
14: 00 00
16: cb[ ]+nop[ ]+
17: cb[ ]+nop[ ]+

View File

@ -0,0 +1,14 @@
.text
.global _start
_start:
add 0x1000 - L01, A0
nop
nop
L01:
add L01 + 0x123, A0
nop
nop
L02:
add L02 - L01, A0
nop
nop

View File

@ -0,0 +1,6 @@
tmpdir/i112045-2.x: file format elf32-.*
DYNAMIC RELOCATION RECORDS
OFFSET TYPE VALUE
[0-9a-f]+ R_MN10300_RELATIVE \*ABS\*\+0x[0-9a-f]+

View File

@ -0,0 +1,12 @@
.section .data
L01:
.long L04 - L01
L02:
.long L04 - L02
L03:
.long L04 - L03
L04:
.long L04
.long L00
.equ L00, 0xff

View File

@ -0,0 +1,7 @@
void
sub0 (int i)
{
extern int sub (int);
sub (i);
}

View File

@ -0,0 +1,5 @@
int
sub (int i)
{
return i + 10;
}

View File

@ -0,0 +1,11 @@
Symbol table '.symtab' contains .. entries:
Num: Value Size Type Bind Vis Ndx Name
#...
..: 0[0-9a-f]+[ ]+7 FUNC LOCAL DEFAULT . _func
#...
..: 0[0-9a-f]+[ ]+0 NOTYPE LOCAL DEFAULT . A
..: 0[0-9a-f]+[ ]+7 FUNC GLOBAL DEFAULT . _func2
#...
..: 0[0-9a-f]+[ ]+0 NOTYPE GLOBAL DEFAULT . BOTTOM
#...

View File

@ -0,0 +1,29 @@
.text
nop
.global _start
_start:
.type _func, @function
_func:
mov L001,A1
nop
A:
mov L001,A1
.size _func, . - _func
.global _func2
_func2:
.type _func2, @function
mov L001,A1
nop
mov L001,A1
.size _func2, . - _func2
.global BOTTOM
BOTTOM:
.data
L001:

View File

@ -0,0 +1,16 @@
.section .text
.global _bar
.type _bar,@function
_bar:
mov .LC1,d0
mov .LC2,d1
nop
.section .rodata.str1.1,"aMS",@progbits,1
.LC1:
.rept 32768
.byte 'a'
.endr
.byte 0
.LC2:
.string "abc\n"

View File

@ -0,0 +1,16 @@
tmpdir/i36434.x: file format elf32-.*
Disassembly of section .text:
08000000 <_start>:
8000000: fc cd 18 80 mov 134250520,d1
8000004: 00 08
8000006: cb nop
08000007 <_bar>:
8000007: fc cc 14 00 mov 134217748,d0
800000b: 00 08
800000d: fc cd 15 80 mov 134250517,d1
8000011: 00 08
8000013: cb nop

View File

@ -0,0 +1,10 @@
.section .text
.global _start
.type _start,@function
_start:
mov .LC2,d1
nop
.section .rodata.str1.1,"aMS",@progbits,1
.LC2:
.string "\n"

View File

@ -0,0 +1,94 @@
# Expect script for ld-mn10300 tests
# Copyright (C) 2007 Free Software Foundation
#
# This file 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 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
if {!([istarget "am3*-*-*"]) && !([istarget "mn10300*-*-*"]) } {
return
}
# Set up a list as described in ld-lib.exp
set am33_tests {
{
"am33 string merging"
"--relax -Ttext 0x8000000"
""
{ "i36434.s" "i36434-2.s" }
{ {objdump -dz i36434.d} }
"i36434.x"
}
{
"difference of two symbols"
"-Ttext 0"
""
{ "i112045-1.s" }
{ {objdump -d i112045-1.d} }
"i112045-1.x"
}
{
"(shared) difference of two symbols"
"-shared"
""
{ "i112045-2.s" }
{ {objdump -R i112045-2.d} }
"i112045-2.x"
}
{
"adjustment of symbols due to relaxation"
"-Tdata 1f -relax"
""
{ "i135409.s" }
{ {readelf --syms i135409.d } }
"i135409.x"
}
}
run_ld_link_tests $am33_tests
proc i126256-test { } {
global CC
global ld
global srcdir
global subdir
set tmpdir tmpdir
set testname "Issue 126256 - seg fault whilst linking one shared library into another when relaxation is enabled."
if { ![ld_compile "$CC -mrelax -fPIC" $srcdir/$subdir/i126256-1.c $tmpdir/i126256-1.o] } {
unresolved $testname
return
}
if { ![ld_compile "$CC -mrelax -fPIC" $srcdir/$subdir/i126256-2.c $tmpdir/i126256-2.o] } {
unresolved $testname
return
}
if { ![ld_simple_link $ld $tmpdir/i126256-1.so "-shared $tmpdir/i126256-1.o -e 0"]} {
unresolved $testname
return
}
if { ![ld_simple_link $ld $tmpdir/i126256-2.so "--relax -shared $tmpdir/i126256-2.o $tmpdir/i126256-1.so -e 0"]} {
fail $testname
return
}
pass $testname
}
i126256-test