+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.
/* 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,
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 ;;
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
;;
#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
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
{ 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. */
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;
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++)
{
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)
- {
- 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;
+ asection * sym_section = NULL;
- BFD_ASSERT (CONST_STRNEQ (name, ".rela")
- && streq (bfd_get_section_name (abfd, sec), name + 5));
+ /* Find the section containing the
+ symbol involved in the relocation. */
+ if (h == NULL)
+ {
+ Elf_Internal_Sym * isymbuf;
+ Elf_Internal_Sym * isym;
+
+ 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)
+ {
+ 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 = bfd_get_section_by_name (dynobj, name);
+ /* 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)
{
- flagword flags;
+ const char * name;
- 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))
+ 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);
+ 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;
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;
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;
&& 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
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;
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;
}
{
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. */
|| 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;
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);
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);
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;
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);
&& 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;
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);
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. */
/* 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. */
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. */
"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",
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
+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 '%'.
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);
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)
{
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)
{
- 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);
+ arelent * reloc2 = xmalloc (sizeof * reloc);
- switch (fixp->fx_r_type)
- {
- case BFD_RELOC_8:
- reloc->howto = bfd_reloc_type_lookup (stdoutput,
- BFD_RELOC_8_PCREL);
- return reloc;
+ relocs[0] = reloc2;
+ relocs[1] = reloc;
- case BFD_RELOC_16:
- reloc->howto = bfd_reloc_type_lookup (stdoutput,
- BFD_RELOC_16_PCREL);
- return 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);
- case BFD_RELOC_24:
- reloc->howto = bfd_reloc_type_lookup (stdoutput,
- BFD_RELOC_24_PCREL);
- return reloc;
+ reloc->addend = fixp->fx_offset;
+ if (S_GET_SEGMENT (fixp->fx_addsy) == absolute_section)
+ reloc->addend += S_GET_VALUE (fixp->fx_addsy);
- case BFD_RELOC_32:
- reloc->howto = bfd_reloc_type_lookup (stdoutput,
- BFD_RELOC_32_PCREL);
- return reloc;
+ reloc->sym_ptr_ptr = xmalloc (sizeof (asymbol *));
+ *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
- 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))
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
{
*reloc->sym_ptr_ptr = symbol_get_bfdsym (fixp->fx_addsy);
reloc->addend = fixp->fx_offset;
}
- return reloc;
+ return relocs;
}
int
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,
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;
{ "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;
+}
#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
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
&& 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),
+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.
do_am33_8
run_list_test "movpc" ""
+ run_list_test "pr997" "-a"
run_dump_test "am33-2"
run_dump_test "relax"
--- /dev/null
+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
--- /dev/null
+ .data
+
+msg: .asciz "hello world.\n"
+msglen = .-msg-1
+msglen=msglen & 0xff
+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.
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,
+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
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
+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>
--- /dev/null
+
+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[ ]+
--- /dev/null
+ .text
+ .global _start
+_start:
+ add 0x1000 - L01, A0
+ nop
+ nop
+L01:
+ add L01 + 0x123, A0
+ nop
+ nop
+L02:
+ add L02 - L01, A0
+ nop
+ nop
--- /dev/null
+
+tmpdir/i112045-2.x: file format elf32-.*
+
+DYNAMIC RELOCATION RECORDS
+OFFSET TYPE VALUE
+[0-9a-f]+ R_MN10300_RELATIVE \*ABS\*\+0x[0-9a-f]+
--- /dev/null
+ .section .data
+L01:
+ .long L04 - L01
+L02:
+ .long L04 - L02
+L03:
+ .long L04 - L03
+L04:
+ .long L04
+ .long L00
+ .equ L00, 0xff
+
--- /dev/null
+void
+sub0 (int i)
+{
+ extern int sub (int);
+
+ sub (i);
+}
--- /dev/null
+int
+sub (int i)
+{
+ return i + 10;
+}
--- /dev/null
+
+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
+#...
--- /dev/null
+ .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:
+
--- /dev/null
+ .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"
--- /dev/null
+
+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
--- /dev/null
+ .section .text
+ .global _start
+ .type _start,@function
+_start:
+ mov .LC2,d1
+ nop
+
+ .section .rodata.str1.1,"aMS",@progbits,1
+.LC2:
+ .string "\n"
--- /dev/null
+# 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