This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

RFC: Adding an extra field to Elf_Internal_Sym


I'm in the process of adding STT_GNU_IFUNC support for ARM, and the
main difficulty I'm facing is: how should Thumb STT_GNU_IFUNCs be
represented internally?  It looks like the cleanest approach might
be to add a new field to Elf_Internal_Sym.

First, the background.  ARM ELF files used to represent Thumb symbols
using a combination of an even symbol value and an ARM-specific symbol
type, STT_ARM_TFUNC.  However, the EABI instead specifies that Thumb
symbols should have an odd symbol value a normal STT_FUNC symbol type,
so that's what EABI-compliant objects use.

Rather than cope with both representations, BFD quite sensibly converts
them to the same form internally.  It then converts the other way if
necessary before writing symbols out.  (Actually, it now always uses
the EABI representation when writing out, and just supports the old
representation when reading in.)

At the moment, BFD uses the old even-valued STT_ARM_TFUNCs internally.
It converts the EABI odd-valued STT_FUNCs into this form when reading
them in.

The question then is how to extend this to STT_GNU_IFUNC.  The external
representation is easy: having odd-valued STT_GNU_IFUNCs is the only
sensible option given the EABI treatment of STT_FUNCs.  But the internal
option is a bit less clear.

One option is to use the odd-valued representation instead of the
even-valued one.  However, such a change would affect all BFD users,
because the value of a function "asymbol" would no longer be the first
byte of the function.  (And consequently, the sum of the symbol value
and the symbol size would no longer be the end of the function.)
I think we would need to provide something like:

    bfd_mask_function_value

-- and possibly other helper routines -- to strip the ISA encoding
from a function address.  Any BFD user that wants the true start or
end of a function, and that wants to be portable to ARM, would then
need to remember to call this function at the appropriate times.

I did try this, and even within binutils, it wasn't nice.

It might sound like odd-valued symbols would make the linker's job a bit
easier, since relocations involving Thumb symbols should resolve to odd
addresses.  However, even that turned out not be true.  Many of the ARM
relocations are defined in terms of:

   (S + A) | T

-- i.e. (symbol + addend) | Thumb-flag -- with the Thumbness being
applied after the addend rather than before.  For example, a relocation
against "thumb symbol + 1" should be odd-valued ("start of function + 1")
rather than even-valued ("start of function + 2").  This means that,
rather than replacing:

  reloc_value += addend;
  if (st_type == STT_ARM_TFUNC)
    value |= 1;

with:

  reloc_value += addend;

Thumb-encoded reloc_values would actually lead to:

  reloc_value = ((reloc_value & -2) + addend) | (reloc_value & 1);

Another drawback with this option is that MIPS uses even-valued function
symbols internally for MIPS16.  I suppose we'd either need to convert
both ports or introduce an inconsistency.

But if we stick with the even-valued representation internally,
how would Thumb STT_GNU_IFUNCs be represented?

One option is to add an internal-only st_type.  There is one free:
STT_LOPROC + 1.  But we'd then be scuppered if a real ARM-specific
st_type was defined in future.

Another option is to have an internal-only st_other, which AFAICT
has no ARM-specific uses.  The usual visibility stuff takes up
two bits, so we'd have six left to play with.  Even if a new
use of st_other was added, we could always switch to a different
bit for the internal representation.  (For the record, st_other
is what MIPS uses for MIPS16, so it is known to work.)

However, I'm reluctant in both cases to put an internal-only value
into fields that mirror external fields.  It would be too easy for the
"internal-only" value to accidentally slip out into an object.  And that
could even happen without us noticing for a while, especially in the
case of st_other.  We'd then have a compatibility problem.

One option I thought about was having a wider st_info internally,
so that ELF_ST_TYPE could have extra, internal-only, bits.
That would solve the accidental leakage problem, but I think
it would be confusing to have different ranges for internal
and external symbols.

So after all that, the safest approach seemed to be to add a new
field to Elf_Internal_Sym.  There is precedent for this in the
Elf_Internal_Shdr "bfd_section" and "contents" fields.  There's
also room, because there's a 16-bit gap between st_other and st_shndx.

The same information would need to be tracked in the elf hash table
entry, but there's room there too: the "unsigned int" bitfields are
now 34 bits in total, so we have 30 bits free without growing the
structure.

Here's a patch that implements this approach.  For the time being,
I've treated this internal field as an extension to the type,
and hard-coded that assumption in the generic ELF code rather
than add target hooks.  That can easily be changed if other targets
find a use for this field in future.

I've also only taken 8 bits out of the readily-available 16,
since that's all ARM needs.  Again, we could grow it in future
if necessary.

This approach does still need some changes to BFD users that already
use STT_ARM_TFUNC to check for Thumbness.  However, the changes needed
there are also the changes that would need to be made for any Thumb
STT_GNU_IFUNC support, and they would be restricted to ARM-specific
code.  If binutils is anything to go by, the changes are much less
invasive than they would be for odd-valued function symbols.

A corresponding (but simple) change would be needed in GDB.

Thoughts?  Is this too ugly for words? :-)

Richard


include/elf/
	* internal.h (elf_internal_sym): Add st_target_internal.
	* arm.h (arm_st_branch_type): New enum.
	(ARM_SYM_BRANCH_TYPE): New macro.

bfd/
	* elf-bfd.h (elf_link_hash_entry): Add target_internal.
	* elf.c (swap_out_syms): Set st_target_internal for each
	Elf_Internal_Sym.
	* elfcode.h (elf_swap_symbol_in): Likewise.
	* elf32-i370.c (i370_elf_finish_dynamic_sections): Likewise.
	* elf32-sh-symbian.c (sh_symbian_relocate_section): Likewise.
	* elf64-sparc.c (elf64_sparc_output_arch_syms): Likewise.
	* elfxx-sparc.c (_bfd_sparc_elf_size_dynamic_sections): Likewise.
	* elflink.c (elf_link_output_extsym): Likewise.
	(bfd_elf_final_link): Likewise.
	(elf_link_add_object_symbols): Copy st_target_internal
	to the hash table if we see a definition.
	(_bfd_elf_copy_link_hash_symbol_type): Copy target_internal.
	* elf32-arm.c (elf32_arm_stub_hash_entry): Replace st_type with
	a branch_type field.
	(a8_erratum_fix, a8_erratum_reloc): Likewise.
	(arm_type_of_stub): Replace actual_st_type with an
	actual_branch_type parameter.
	(arm_build_one_stub): Use branch types rather than st_types to
	determine the type of branch.
	(cortex_a8_erratum_scan): Likewise.
	(elf32_arm_size_stubs): Likewise.
	(bfd_elf32_arm_process_before_allocation): Likewise.
	(allocate_dynrelocs): Likewise.
	(elf32_arm_finish_dynamic_sections): Likewise.
	(elf32_arm_final_link_relocate): Replace sym_flags parameter with
	a branch_type parameter.
	(elf32_arm_relocate_section): Update call accordingly.
	(elf32_arm_adjust_dynamic_symbol): Don't check STT_ARM_TFUNC.
	(elf32_arm_output_map_sym): Initialize st_target_internal.
	(elf32_arm_output_stub_sym): Likewise.
	(elf32_arm_symbol_processing): Delete.
	(elf32_arm_swap_symbol_in): Convert STT_ARM_TFUNCs into STT_FUNCs.
	Use st_target_internal to record the branch type.
	(elf32_arm_swap_symbol_out): Use st_target_internal to test for
	Thumb functions.
	(elf32_arm_is_function_type): Delete.
	(elf_backend_symbol_processing): Likewise.
	(elf_backend_is_function_type): Likewise.

gas/
	* config/tc-arm.c (arm_adjust_symtab): Set the branch type
	for Thumb symbols.

ld/
	* emultempl/armelf.em (gld${EMULATION_NAME}_finish): Check
	eh->target_internal.

opcodes/
	* arm-dis.c (get_sym_code_type): Don't check for STT_ARM_TFUNC.
	Use branch types instead.
	(print_insn): Likewise.

Index: include/elf/internal.h
===================================================================
--- include/elf/internal.h	2010-11-26 09:56:09.000000000 +0000
+++ include/elf/internal.h	2010-11-26 09:56:56.000000000 +0000
@@ -124,6 +124,7 @@ struct elf_internal_sym {
   unsigned long	st_name;		/* Symbol name, index in string tbl */
   unsigned char	st_info;		/* Type and binding attributes */
   unsigned char	st_other;		/* Visibilty, and target specific */
+  unsigned char st_target_internal;	/* Internal-only information */
   unsigned int  st_shndx;		/* Associated section index */
 };
 
Index: include/elf/arm.h
===================================================================
--- include/elf/arm.h	2010-11-26 09:56:09.000000000 +0000
+++ include/elf/arm.h	2010-11-26 09:56:56.000000000 +0000
@@ -319,4 +319,13 @@ #define ELF_STRING_ARM_unwind_info      
 #define ELF_STRING_ARM_unwind_once      ".gnu.linkonce.armexidx."
 #define ELF_STRING_ARM_unwind_info_once ".gnu.linkonce.armextab."
 
+enum arm_st_branch_type {
+  ST_BRANCH_TO_ARM,
+  ST_BRANCH_TO_THUMB,
+  ST_BRANCH_LONG
+};
+
+#define ARM_SYM_BRANCH_TYPE(SYM) \
+  ((enum arm_st_branch_type) (SYM)->st_target_internal)
+
 #endif /* _ELF_ARM_H */
Index: bfd/elf-bfd.h
===================================================================
--- bfd/elf-bfd.h	2010-11-26 09:56:09.000000000 +0000
+++ bfd/elf-bfd.h	2010-11-26 09:56:56.000000000 +0000
@@ -153,6 +153,9 @@ struct elf_link_hash_entry
   /* Symbol st_other value, symbol visibility.  */
   unsigned int other : 8;
 
+  /* The symbol's st_target_internal value (see Elf_Internal_Sym).  */
+  unsigned int target_internal : 8;
+
   /* Symbol is referenced by a non-shared object (other than the object
      in which it is defined).  */
   unsigned int ref_regular : 1;
Index: bfd/elf.c
===================================================================
--- bfd/elf.c	2010-11-26 09:56:09.000000000 +0000
+++ bfd/elf.c	2010-11-26 09:56:55.000000000 +0000
@@ -6522,6 +6522,7 @@ swap_out_syms (bfd *abfd,
     sym.st_info = 0;
     sym.st_other = 0;
     sym.st_shndx = SHN_UNDEF;
+    sym.st_target_internal = 0;
     bed->s->swap_symbol_out (abfd, &sym, outbound_syms, outbound_shndx);
     outbound_syms += bed->s->sizeof_sym;
     if (outbound_shndx != NULL)
@@ -6721,9 +6722,16 @@ swap_out_syms (bfd *abfd,
 	}
 
       if (type_ptr != NULL)
-	sym.st_other = type_ptr->internal_elf_sym.st_other;
+	{
+	  sym.st_other = type_ptr->internal_elf_sym.st_other;
+	  sym.st_target_internal
+	    = type_ptr->internal_elf_sym.st_target_internal;
+	}
       else
-	sym.st_other = 0;
+	{
+	  sym.st_other = 0;
+	  sym.st_target_internal = 0;
+	}
 
       bed->s->swap_symbol_out (abfd, &sym, outbound_syms, outbound_shndx);
       outbound_syms += bed->s->sizeof_sym;
Index: bfd/elfcode.h
===================================================================
--- bfd/elfcode.h	2010-11-26 09:56:09.000000000 +0000
+++ bfd/elfcode.h	2010-11-26 09:56:55.000000000 +0000
@@ -198,6 +198,7 @@ elf_swap_symbol_in (bfd *abfd,
     }
   else if (dst->st_shndx >= (SHN_LORESERVE & 0xffff))
     dst->st_shndx += SHN_LORESERVE - (SHN_LORESERVE & 0xffff);
+  dst->st_target_internal = 0;
   return TRUE;
 }
 
Index: bfd/elf32-i370.c
===================================================================
--- bfd/elf32-i370.c	2010-11-26 09:56:09.000000000 +0000
+++ bfd/elf32-i370.c	2010-11-26 09:56:55.000000000 +0000
@@ -962,6 +962,7 @@ i370_elf_finish_dynamic_sections (bfd *o
       sym.st_name = 0;
       sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION);
       sym.st_other = 0;
+      sym.st_target_internal = 0;
 
       for (s = output_bfd->sections; s != NULL; s = s->next)
 	{
Index: bfd/elf32-sh-symbian.c
===================================================================
--- bfd/elf32-sh-symbian.c	2010-11-26 09:56:09.000000000 +0000
+++ bfd/elf32-sh-symbian.c	2010-11-26 09:56:55.000000000 +0000
@@ -492,6 +492,7 @@ sh_symbian_relocate_section (bfd *      
 	      new_sym.st_info  = ELF_ST_INFO (STB_GLOBAL, STT_FUNC);
 	      new_sym.st_other = ELF_ST_VISIBILITY (STV_DEFAULT);
 	      new_sym.st_shndx = SHN_UNDEF;
+	      new_sym.st_target_internal = 0;
 
 	      if (! _bfd_elf_merge_symbol (input_bfd, info,
 					   ptr->new_name, & new_sym,
Index: bfd/elf64-sparc.c
===================================================================
--- bfd/elf64-sparc.c	2010-11-26 09:56:09.000000000 +0000
+++ bfd/elf64-sparc.c	2010-11-26 09:56:55.000000000 +0000
@@ -591,6 +591,7 @@ elf64_sparc_output_arch_syms (bfd *outpu
 	sym.st_other = 0;
 	sym.st_info = ELF_ST_INFO (app_regs [reg].bind, STT_REGISTER);
 	sym.st_shndx = app_regs [reg].shndx;
+	sym.st_target_internal = 0;
 	if ((*func) (finfo, app_regs [reg].name, &sym,
 		     sym.st_shndx == SHN_ABS
 		     ? bfd_abs_section_ptr : bfd_und_section_ptr,
Index: bfd/elfxx-sparc.c
===================================================================
--- bfd/elfxx-sparc.c	2010-11-26 09:56:09.000000000 +0000
+++ bfd/elfxx-sparc.c	2010-11-26 09:56:56.000000000 +0000
@@ -2743,6 +2743,7 @@ #define add_dynamic_entry(TAG, VAL) \
 		entry->isym.st_info = ELF_ST_INFO (app_regs [reg].bind,
 						   STT_REGISTER);
 		entry->isym.st_shndx = app_regs [reg].shndx;
+		entry->isym.st_target_internal = 0;
 		entry->next = NULL;
 		entry->input_bfd = output_bfd;
 		entry->input_indx = -1;
Index: bfd/elflink.c
===================================================================
--- bfd/elflink.c	2010-11-26 09:56:09.000000000 +0000
+++ bfd/elflink.c	2010-11-26 09:56:56.000000000 +0000
@@ -4396,6 +4396,9 @@ elf_link_add_object_symbols (bfd *abfd, 
 	      dynsym = FALSE;
 	    }
 
+	  if (definition)
+	    h->target_internal = isym->st_target_internal;
+
 	  /* Check to see if we need to add an indirect symbol for
 	     the default name.  */
 	  if (definition || h->root.type == bfd_link_hash_common)
@@ -8724,6 +8727,7 @@ elf_link_output_extsym (struct elf_link_
     sym.st_info = ELF_ST_INFO (STB_WEAK, h->type);
   else
     sym.st_info = ELF_ST_INFO (STB_GLOBAL, h->type);
+  sym.st_target_internal = h->target_internal;
 
   switch (h->root.type)
     {
@@ -10512,6 +10516,7 @@ bfd_elf_final_link (bfd *abfd, struct bf
       elfsym.st_info = 0;
       elfsym.st_other = 0;
       elfsym.st_shndx = SHN_UNDEF;
+      elfsym.st_target_internal = 0;
       if (elf_link_output_sym (&finfo, NULL, &elfsym, bfd_und_section_ptr,
 			       NULL) != 1)
 	goto error_return;
@@ -10529,6 +10534,7 @@ bfd_elf_final_link (bfd *abfd, struct bf
       elfsym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION);
       elfsym.st_other = 0;
       elfsym.st_value = 0;
+      elfsym.st_target_internal = 0;
       for (i = 1; i < elf_numsections (abfd); i++)
 	{
 	  o = bfd_section_from_elf_index (abfd, i);
@@ -10752,6 +10758,7 @@ bfd_elf_final_link (bfd *abfd, struct bf
 	  sym.st_name = 0;
 	  sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_SECTION);
 	  sym.st_other = 0;
+	  sym.st_target_internal = 0;
 
 	  for (s = abfd->sections; s != NULL; s = s->next)
 	    {
@@ -12695,4 +12702,5 @@ _bfd_elf_copy_link_hash_symbol_type (bfd
   struct elf_link_hash_entry *ehsrc = (struct elf_link_hash_entry *)hsrc;
 
   ehdest->type = ehsrc->type;
+  ehdest->target_internal = ehsrc->target_internal;
 }
Index: bfd/elf32-arm.c
===================================================================
--- bfd/elf32-arm.c	2010-11-26 09:56:09.000000000 +0000
+++ bfd/elf32-arm.c	2010-11-26 11:30:47.000000000 +0000
@@ -2279,8 +2279,8 @@ struct elf32_arm_stub_hash_entry
   /* The symbol table entry, if any, that this was derived from.  */
   struct elf32_arm_link_hash_entry *h;
 
-  /* Destination symbol type (STT_ARM_TFUNC, ...) */
-  unsigned char st_type;
+  /* Type of branch.  */
+  enum arm_st_branch_type branch_type;
 
   /* Where this stub is being called from, or, in the case of combined
      stub sections, the first input section in the group.  */
@@ -2400,7 +2400,7 @@ struct a8_erratum_fix {
   unsigned long orig_insn;
   char *stub_name;
   enum elf32_arm_stub_type stub_type;
-  int st_type;
+  enum arm_st_branch_type branch_type;
 };
 
 /* A table of relocs applied to branches which might trigger Cortex-A8
@@ -2412,7 +2412,7 @@ struct a8_erratum_reloc {
   struct elf32_arm_link_hash_entry *hash;
   const char *sym_name;
   unsigned int r_type;
-  unsigned char st_type;
+  enum arm_st_branch_type branch_type;
   bfd_boolean non_a8_stub;
 };
 
@@ -3014,7 +3014,7 @@ arm_stub_is_thumb (enum elf32_arm_stub_t
 arm_type_of_stub (struct bfd_link_info *info,
 		  asection *input_sec,
 		  const Elf_Internal_Rela *rel,
-		  int *actual_st_type,
+		  enum arm_st_branch_type *actual_branch_type,
 		  struct elf32_arm_link_hash_entry *hash,
 		  bfd_vma destination,
 		  asection *sym_sec,
@@ -3029,11 +3029,9 @@ arm_type_of_stub (struct bfd_link_info *
   int thumb_only;
   enum elf32_arm_stub_type stub_type = arm_stub_none;
   int use_plt = 0;
-  int st_type = *actual_st_type;
+  enum arm_st_branch_type branch_type = *actual_branch_type;
 
-  /* We don't know the actual type of destination in case it is of
-     type STT_SECTION: give up.  */
-  if (st_type == STT_SECTION)
+  if (branch_type == ST_BRANCH_LONG)
     return stub_type;
 
   globals = elf32_arm_hash_table (info);
@@ -3070,7 +3068,7 @@ arm_type_of_stub (struct bfd_link_info *
       destination = (globals->root.splt->output_section->vma
 		     + globals->root.splt->output_offset
 		     + hash->root.plt.offset);
-      st_type = STT_FUNC;
+      branch_type = ST_BRANCH_TO_ARM;
     }
 
   branch_offset = (bfd_signed_vma)(destination - location);
@@ -3091,12 +3089,12 @@ arm_type_of_stub (struct bfd_link_info *
 	  || (thumb2
 	      && (branch_offset > THM2_MAX_FWD_BRANCH_OFFSET
 		  || (branch_offset < THM2_MAX_BWD_BRANCH_OFFSET)))
-	  || ((st_type != STT_ARM_TFUNC)
+	  || (branch_type == ST_BRANCH_TO_ARM
 	      && (((r_type == R_ARM_THM_CALL) && !globals->use_blx)
 		  || (r_type == R_ARM_THM_JUMP24))
 	      && !use_plt))
 	{
-	  if (st_type == STT_ARM_TFUNC)
+	  if (branch_type == ST_BRANCH_TO_THUMB)
 	    {
 	      /* Thumb to thumb.  */
 	      if (!thumb_only)
@@ -3172,7 +3170,7 @@ arm_type_of_stub (struct bfd_link_info *
 	   || r_type == R_ARM_JUMP24
 	   || r_type == R_ARM_PLT32)
     {
-      if (st_type == STT_ARM_TFUNC)
+      if (branch_type == ST_BRANCH_TO_THUMB)
 	{
 	  /* Arm to thumb.  */
 
@@ -3227,7 +3225,7 @@ arm_type_of_stub (struct bfd_link_info *
 
   /* If a stub is needed, record the actual destination type.  */
   if (stub_type != arm_stub_none)
-    *actual_st_type = st_type;
+    *actual_branch_type = branch_type;
 
   return stub_type;
 }
@@ -3429,7 +3427,8 @@ put_thumb_insn (struct elf32_arm_link_ha
 static bfd_reloc_status_type elf32_arm_final_link_relocate
   (reloc_howto_type *, bfd *, bfd *, asection *, bfd_byte *,
    Elf_Internal_Rela *, bfd_vma, struct bfd_link_info *, asection *,
-   const char *, int, struct elf_link_hash_entry *, bfd_boolean *, char **);
+   const char *, enum arm_st_branch_type, struct elf_link_hash_entry *,
+   bfd_boolean *, char **);
 
 static unsigned int
 arm_stub_required_alignment (enum elf32_arm_stub_type stub_type)
@@ -3578,7 +3577,7 @@ #define MAXRELOCS 2
   BFD_ASSERT (size == stub_entry->stub_size);
 
   /* Destination is Thumb. Force bit 0 to 1 to reflect this.  */
-  if (stub_entry->st_type == STT_ARM_TFUNC)
+  if (stub_entry->branch_type == ST_BRANCH_TO_THUMB)
     sym_value |= 1;
 
   /* Assume there is at least one and at most MAXRELOCS entries to relocate
@@ -3594,9 +3593,9 @@ #define MAXRELOCS 2
 	Elf_Internal_Rela rel;
 	bfd_boolean unresolved_reloc;
 	char *error_message;
-	int sym_flags
-	  = (template_sequence[stub_reloc_idx[i]].r_type != R_ARM_THM_XPC22)
-	    ? STT_ARM_TFUNC : 0;
+	enum arm_st_branch_type branch_type
+	  = (template_sequence[stub_reloc_idx[i]].r_type != R_ARM_THM_XPC22
+	     ? ST_BRANCH_TO_THUMB : ST_BRANCH_TO_ARM);
 	bfd_vma points_to = sym_value + stub_entry->target_addend;
 
 	rel.r_offset = stub_entry->stub_offset + stub_reloc_offset[i];
@@ -3620,7 +3619,7 @@ #define MAXRELOCS 2
 	elf32_arm_final_link_relocate (elf32_arm_howto_from_type
 	    (template_sequence[stub_reloc_idx[i]].r_type),
 	  stub_bfd, info->output_bfd, stub_sec, stub_sec->contents, &rel,
-	  points_to, info, stub_entry->target_section, "", sym_flags,
+	  points_to, info, stub_entry->target_section, "", branch_type,
 	  (struct elf_link_hash_entry *) stub_entry->h, &unresolved_reloc,
 	  &error_message);
       }
@@ -3640,7 +3639,8 @@ #define MAXRELOCS 2
 	elf32_arm_final_link_relocate (elf32_arm_howto_from_type
 	    (template_sequence[stub_reloc_idx[i]].r_type),
 	  stub_bfd, info->output_bfd, stub_sec, stub_sec->contents, &rel,
-	  points_to, info, stub_entry->target_section, "", stub_entry->st_type,
+	  points_to, info, stub_entry->target_section, "",
+	  stub_entry->branch_type,
 	  (struct elf_link_hash_entry *) stub_entry->h, &unresolved_reloc,
 	  &error_message);
       }
@@ -4096,7 +4096,8 @@ cortex_a8_erratum_scan (bfd *input_bfd,
 
 		      if (found->r_type == R_ARM_THM_CALL)
 			{
-			  if (found->st_type != STT_ARM_TFUNC || use_plt)
+			  if (found->branch_type == ST_BRANCH_TO_ARM
+			      || use_plt)
 			    force_target_arm = TRUE;
 			  else
 			    force_target_thumb = TRUE;
@@ -4233,8 +4234,8 @@ cortex_a8_erratum_scan (bfd *input_bfd,
                           a8_fixes[num_a8_fixes].orig_insn = insn;
                           a8_fixes[num_a8_fixes].stub_name = stub_name;
                           a8_fixes[num_a8_fixes].stub_type = stub_type;
-                          a8_fixes[num_a8_fixes].st_type =
-			    is_blx ? STT_FUNC : STT_ARM_TFUNC;
+                          a8_fixes[num_a8_fixes].branch_type =
+			    is_blx ? ST_BRANCH_TO_ARM : ST_BRANCH_TO_THUMB;
 
                           num_a8_fixes++;
                         }
@@ -4405,7 +4406,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
 		  const char *sym_name;
 		  char *stub_name;
 		  const asection *id_sec;
-		  int st_type;
+		  enum arm_st_branch_type branch_type;
 		  bfd_boolean created_stub = FALSE;
 
 		  r_type = ELF32_R_TYPE (irela->r_info);
@@ -4476,7 +4477,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
 		      destination = (sym_value + irela->r_addend
 				     + sym_sec->output_offset
 				     + sym_sec->output_section->vma);
-		      st_type = ELF_ST_TYPE (sym->st_info);
+		      branch_type = ARM_SYM_BRANCH_TYPE (sym);
 		      sym_name
 			= bfd_elf_string_from_elf_section (input_bfd,
 							   symtab_hdr->sh_link,
@@ -4556,7 +4557,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
 			  bfd_set_error (bfd_error_bad_value);
 			  goto error_ret_free_internal;
 			}
-		      st_type = ELF_ST_TYPE (hash->root.type);
+		      branch_type = hash->root.target_internal;
 		      sym_name = hash->root.root.root.string;
 		    }
 
@@ -4564,7 +4565,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
 		    {
 		      /* Determine what (if any) linker stub is needed.  */
 		      stub_type = arm_type_of_stub (info, section, irela,
-						    &st_type, hash,
+						    &branch_type, hash,
 						    destination, sym_sec,
 						    input_bfd, sym_name);
 		      if (stub_type == arm_stub_none)
@@ -4606,7 +4607,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
                       stub_entry->target_section = sym_sec;
                       stub_entry->stub_type = stub_type;
                       stub_entry->h = hash;
-                      stub_entry->st_type = st_type;
+                      stub_entry->branch_type = branch_type;
 
                       if (sym_name == NULL)
                 	sym_name = "unnamed";
@@ -4622,14 +4623,14 @@ elf32_arm_size_stubs (bfd *output_bfd,
 
                       /* For historical reasons, use the existing names for
                 	 ARM-to-Thumb and Thumb-to-ARM stubs.  */
-                      if ( ((r_type == (unsigned int) R_ARM_THM_CALL)
-                            || (r_type == (unsigned int) R_ARM_THM_JUMP24))
-                           && st_type != STT_ARM_TFUNC)
+                      if ((r_type == (unsigned int) R_ARM_THM_CALL
+			   || r_type == (unsigned int) R_ARM_THM_JUMP24)
+			  && branch_type == ST_BRANCH_TO_ARM)
                 	sprintf (stub_entry->output_name,
                         	 THUMB2ARM_GLUE_ENTRY_NAME, sym_name);
-                      else if ( ((r_type == (unsigned int) R_ARM_CALL)
-                        	 || (r_type == (unsigned int) R_ARM_JUMP24))
-                               && st_type == STT_ARM_TFUNC)
+                      else if ((r_type == (unsigned int) R_ARM_CALL
+			       || r_type == (unsigned int) R_ARM_JUMP24)
+			       && branch_type == ST_BRANCH_TO_THUMB)
                 	sprintf (stub_entry->output_name,
                         	 ARM2THUMB_GLUE_ENTRY_NAME, sym_name);
                       else
@@ -4671,7 +4672,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
                           a8_relocs[num_a8_relocs].from = from;
                           a8_relocs[num_a8_relocs].destination = destination;
                           a8_relocs[num_a8_relocs].r_type = r_type;
-                          a8_relocs[num_a8_relocs].st_type = st_type;
+                          a8_relocs[num_a8_relocs].branch_type = branch_type;
                           a8_relocs[num_a8_relocs].sym_name = sym_name;
                           a8_relocs[num_a8_relocs].non_a8_stub = created_stub;
                           a8_relocs[num_a8_relocs].hash = hash;
@@ -4776,7 +4777,7 @@ elf32_arm_size_stubs (bfd *output_bfd,
           stub_entry->target_value = a8_fixes[i].offset;
           stub_entry->target_addend = a8_fixes[i].addend;
           stub_entry->orig_insn = a8_fixes[i].orig_insn;
-	  stub_entry->st_type = a8_fixes[i].st_type;
+	  stub_entry->branch_type = a8_fixes[i].branch_type;
 
           size = find_stub_size_and_template (a8_fixes[i].stub_type,
                                               &template_sequence,
@@ -5541,7 +5542,7 @@ bfd_elf32_arm_process_before_allocation 
 	      /* This one is a call from arm code.  We need to look up
 	         the target of the call.  If it is a thumb target, we
 	         insert glue.  */
-	      if (ELF_ST_TYPE (h->type) == STT_ARM_TFUNC)
+	      if (h->target_internal == ST_BRANCH_TO_THUMB)
 		record_arm_to_thumb_glue (link_info, h);
 	      break;
 
@@ -6825,7 +6826,7 @@ elf32_arm_final_link_relocate (reloc_how
 			       struct bfd_link_info *       info,
 			       asection *                   sym_sec,
 			       const char *                 sym_name,
-			       int		            sym_flags,
+			       enum arm_st_branch_type     branch_type,
 			       struct elf_link_hash_entry * h,
 			       bfd_boolean *                unresolved_reloc_p,
 			       char **                      error_message)
@@ -7000,7 +7001,7 @@ elf32_arm_final_link_relocate (reloc_how
 	      int symbol;
 
 	      /* This symbol is local, or marked to become local.  */
-	      if (sym_flags == STT_ARM_TFUNC)
+	      if (branch_type == ST_BRANCH_TO_THUMB)
 		value |= 1;
 	      if (globals->symbian_p)
 		{
@@ -7080,7 +7081,7 @@ elf32_arm_final_link_relocate (reloc_how
 	      /* Check for Arm calling Arm function.  */
 	      /* FIXME: Should we translate the instruction into a BL
 		 instruction instead ?  */
-	      if (sym_flags != STT_ARM_TFUNC)
+	      if (branch_type != ST_BRANCH_TO_THUMB)
 		(*_bfd_error_handler)
 		  (_("\%B: Warning: Arm BLX instruction targets Arm function '%s'."),
 		   input_bfd,
@@ -7089,7 +7090,7 @@ elf32_arm_final_link_relocate (reloc_how
 	  else if (r_type == R_ARM_PC24)
 	    {
 	      /* Check for Arm calling Thumb function.  */
-	      if (sym_flags == STT_ARM_TFUNC)
+	      if (branch_type == ST_BRANCH_TO_THUMB)
 		{
 		  if (elf32_arm_to_thumb_stub (info, sym_name, input_bfd,
 					       output_bfd, input_section,
@@ -7113,7 +7114,7 @@ elf32_arm_final_link_relocate (reloc_how
 
 	      hash = (struct elf32_arm_link_hash_entry *) h;
 	      stub_type = arm_type_of_stub (info, input_section, rel,
-					    &sym_flags, hash,
+					    &branch_type, hash,
 					    value, sym_sec,
 					    input_bfd, sym_name);
 
@@ -7145,7 +7146,7 @@ elf32_arm_final_link_relocate (reloc_how
 		      *unresolved_reloc_p = FALSE;
 		      /* The PLT entry is in ARM mode, regardless of the
 			 target function.  */
-		      sym_flags = STT_FUNC;
+		      branch_type = ST_BRANCH_TO_ARM;
 		    }
 		}
 	    }
@@ -7212,7 +7213,7 @@ elf32_arm_final_link_relocate (reloc_how
 	      if (r_type == R_ARM_CALL)
 		{
 		  /* Set the H bit in the BLX instruction.  */
-		  if (sym_flags == STT_ARM_TFUNC)
+		  if (branch_type == ST_BRANCH_TO_THUMB)
 		    {
 		      if (addend)
 			value |= (1 << 24);
@@ -7223,7 +7224,7 @@ elf32_arm_final_link_relocate (reloc_how
 		  /* Select the correct instruction (BL or BLX).  */
 		  /* Only if we are not handling a BL to a stub. In this
 		     case, mode switching is performed by the stub.  */
-		  if (sym_flags == STT_ARM_TFUNC && !stub_entry)
+		  if (branch_type == ST_BRANCH_TO_THUMB && !stub_entry)
 		    value |= (1 << 28);
 		  else
 		    {
@@ -7237,7 +7238,7 @@ elf32_arm_final_link_relocate (reloc_how
 
 	case R_ARM_ABS32:
 	  value += addend;
-	  if (sym_flags == STT_ARM_TFUNC)
+	  if (branch_type == ST_BRANCH_TO_THUMB)
 	    value |= 1;
 	  break;
 
@@ -7247,7 +7248,7 @@ elf32_arm_final_link_relocate (reloc_how
 
 	case R_ARM_REL32:
 	  value += addend;
-	  if (sym_flags == STT_ARM_TFUNC)
+	  if (branch_type == ST_BRANCH_TO_THUMB)
 	    value |= 1;
 	  value -= (input_section->output_section->vma
 		    + input_section->output_offset + rel->r_offset);
@@ -7271,7 +7272,7 @@ elf32_arm_final_link_relocate (reloc_how
 	    }
 	  value &= 0x7fffffff;
 	  value |= (bfd_get_32 (input_bfd, hit_data) & 0x80000000);
-	  if (sym_flags == STT_ARM_TFUNC)
+	  if (branch_type == ST_BRANCH_TO_THUMB)
 	    value |= 1;
 	  break;
 	}
@@ -7491,7 +7492,7 @@ elf32_arm_final_link_relocate (reloc_how
 	    /* Check for Thumb to Thumb call.  */
 	    /* FIXME: Should we translate the instruction into a BL
 	       instruction instead ?  */
-	    if (sym_flags == STT_ARM_TFUNC)
+	    if (branch_type == ST_BRANCH_TO_THUMB)
 	      (*_bfd_error_handler)
 		(_("%B: Warning: Thumb BLX instruction targets thumb function '%s'."),
 		 input_bfd,
@@ -7503,7 +7504,7 @@ elf32_arm_final_link_relocate (reloc_how
 	       If it is a call relative to a section name, then it is not a
 	       function call at all, but rather a long jump.  Calls through
 	       the PLT do not require stubs.  */
-	    if (sym_flags != STT_ARM_TFUNC && sym_flags != STT_SECTION
+	    if (branch_type == ST_BRANCH_TO_ARM
 		&& (h == NULL || splt == NULL
 		    || h->plt.offset == (bfd_vma) -1))
 	      {
@@ -7524,7 +7525,8 @@ elf32_arm_final_link_relocate (reloc_how
 		      return bfd_reloc_dangerous;
 		  }
 	      }
-	    else if (sym_flags == STT_ARM_TFUNC && globals->use_blx
+	    else if (branch_type == ST_BRANCH_TO_THUMB
+		     && globals->use_blx
 		     && r_type == R_ARM_THM_CALL)
 	      {
 		/* Make sure this is a BL.  */
@@ -7543,7 +7545,7 @@ elf32_arm_final_link_relocate (reloc_how
 	    hash = (struct elf32_arm_link_hash_entry *) h;
 
 	    stub_type = arm_type_of_stub (info, input_section, rel,
-					  &sym_flags, hash, value, sym_sec,
+					  &branch_type, hash, value, sym_sec,
 					  input_bfd, sym_name);
 
 	    if (stub_type != arm_stub_none)
@@ -7565,7 +7567,7 @@ elf32_arm_final_link_relocate (reloc_how
 		  {
 		    if ((stub_entry
 			 && !arm_stub_is_thumb (stub_entry->stub_type))
-			|| (sym_flags != STT_ARM_TFUNC))
+			|| branch_type != ST_BRANCH_TO_THUMB)
 		      lower_insn = (lower_insn & ~0x1000) | 0x0800;
 		  }
 	      }
@@ -7587,13 +7589,13 @@ elf32_arm_final_link_relocate (reloc_how
 		   the BL to a BLX instruction to call the ARM-mode
 		   PLT entry.  */
 		lower_insn = (lower_insn & ~0x1000) | 0x0800;
-		sym_flags = STT_FUNC;
+		branch_type = ST_BRANCH_TO_ARM;
 	      }
 	    else
 	      {
 		/* Target the Thumb stub before the ARM PLT entry.  */
 		value -= PLT_THUMB_STUB_SIZE;
-		sym_flags = STT_ARM_TFUNC;
+		branch_type = ST_BRANCH_TO_THUMB;
 	      }
 	    *unresolved_reloc_p = FALSE;
 	  }
@@ -7821,7 +7823,7 @@ elf32_arm_final_link_relocate (reloc_how
       /* If we are addressing a Thumb function, we need to adjust the
 	 address by one, so that attempts to call the function pointer will
 	 correctly interpret it as Thumb code.  */
-      if (sym_flags == STT_ARM_TFUNC)
+      if (branch_type == ST_BRANCH_TO_THUMB)
 	value += 1;
 
       /* Note that sgot->output_offset is not involved in this
@@ -7886,7 +7888,7 @@ elf32_arm_final_link_relocate (reloc_how
 		     adjust the address by one, so that attempts to
 		     call the function pointer will correctly
 		     interpret it as Thumb code.  */
-		  if (sym_flags == STT_ARM_TFUNC)
+		  if (branch_type == ST_BRANCH_TO_THUMB)
 		    value |= 1;
 
 		  bfd_put_32 (output_bfd, value, sgot->contents + off);
@@ -7918,7 +7920,7 @@ elf32_arm_final_link_relocate (reloc_how
 		 adjust the address by one, so that attempts to
 		 call the function pointer will correctly
 		 interpret it as Thumb code.  */
-	      if (sym_flags == STT_ARM_TFUNC)
+	      if (branch_type == ST_BRANCH_TO_THUMB)
 		value |= 1;
 
 	      if (globals->use_rel)
@@ -8243,7 +8245,7 @@ elf32_arm_final_link_relocate (reloc_how
 	if (r_type == R_ARM_MOVW_BREL && value >= 0x10000)
           return bfd_reloc_overflow;
 
-	if (sym_flags == STT_ARM_TFUNC)
+	if (branch_type == ST_BRANCH_TO_THUMB)
 	  value |= 1;
 
 	if (r_type == R_ARM_MOVT_ABS || r_type == R_ARM_MOVT_PREL
@@ -8293,7 +8295,7 @@ elf32_arm_final_link_relocate (reloc_how
 	if (r_type == R_ARM_THM_MOVW_BREL && value >= 0x10000)
           return bfd_reloc_overflow;
 
-	if (sym_flags == STT_ARM_TFUNC)
+	if (branch_type == ST_BRANCH_TO_THUMB)
 	  value |= 1;
 
 	if (r_type == R_ARM_THM_MOVT_ABS || r_type == R_ARM_THM_MOVT_PREL
@@ -8410,7 +8412,7 @@ elf32_arm_final_link_relocate (reloc_how
 
         /* If the target symbol is a Thumb function, then set the
            Thumb bit in the address.  */
-	if (sym_flags == STT_ARM_TFUNC)
+	if (branch_type == ST_BRANCH_TO_THUMB)
 	  signed_value |= 1;
 
         /* Calculate the value of the relevant G_n, in encoded
@@ -9035,8 +9037,8 @@ elf32_arm_relocate_section (bfd *       
       r = elf32_arm_final_link_relocate (howto, input_bfd, output_bfd,
 					 input_section, contents, rel,
 					 relocation, info, sec, name,
-					 (h ? ELF_ST_TYPE (h->type) :
-					  ELF_ST_TYPE (sym->st_info)), h,
+					 (h ? h->target_internal
+					  : ARM_SYM_BRANCH_TYPE (sym)), h,
 					 &unresolved_reloc, &error_message);
 
       /* Dynamic relocs are not propagated for SEC_DEBUGGING sections
@@ -11267,8 +11269,7 @@ elf32_arm_adjust_dynamic_symbol (struct 
   /* If this is a function, put it in the procedure linkage table.  We
      will fill in the contents of the procedure linkage table later,
      when we know the address of the .got section.  */
-  if (h->type == STT_FUNC || h->type == STT_ARM_TFUNC
-      || h->needs_plt)
+  if (h->type == STT_FUNC || h->needs_plt)
     {
       if (h->plt.refcount <= 0
 	  || SYMBOL_CALLS_LOCAL (info, h)
@@ -11443,8 +11444,7 @@ allocate_dynrelocs (struct elf_link_hash
 	      /* Make sure the function is not marked as Thumb, in case
 		 it is the target of an ABS32 relocation, which will
 		 point to the PLT entry.  */
-	      if (ELF_ST_TYPE (h->type) == STT_ARM_TFUNC)
-		h->type = ELF_ST_INFO (ELF_ST_BIND (h->type), STT_FUNC);
+	      h->target_internal = ST_BRANCH_TO_ARM;
 	    }
 
 	  /* Make room for this entry.  */
@@ -11561,7 +11561,7 @@ allocate_dynrelocs (struct elf_link_hash
   /* Allocate stubs for exported Thumb functions on v4t.  */
   if (!htab->use_blx && h->dynindx != -1
       && h->def_regular
-      && ELF_ST_TYPE (h->type) == STT_ARM_TFUNC
+      && h->target_internal == ST_BRANCH_TO_THUMB
       && ELF_ST_VISIBILITY (h->other) == STV_DEFAULT)
     {
       struct elf_link_hash_entry * th;
@@ -11579,12 +11579,14 @@ allocate_dynrelocs (struct elf_link_hash
 					NULL, TRUE, FALSE, &bh);
 
       myh = (struct elf_link_hash_entry *) bh;
-      myh->type = ELF_ST_INFO (STB_LOCAL, STT_ARM_TFUNC);
+      myh->type = ELF_ST_INFO (STB_LOCAL, STT_FUNC);
       myh->forced_local = 1;
+      myh->target_internal = ST_BRANCH_TO_THUMB;
       eh->export_glue = myh;
       th = record_arm_to_thumb_glue (info, h);
       /* Point the symbol at the stub.  */
       h->type = ELF_ST_INFO (ELF_ST_BIND (h->type), STT_FUNC);
+      h->target_internal = ST_BRANCH_TO_ARM;
       h->root.u.def.section = th->root.u.def.section;
       h->root.u.def.value = th->root.u.def.value & ~1;
     }
@@ -12490,8 +12492,7 @@ elf32_arm_finish_dynamic_sections (bfd *
 
 		  eh = elf_link_hash_lookup (elf_hash_table (info), name,
 					     FALSE, FALSE, TRUE);
-		  if (eh != NULL
-		      && ELF_ST_TYPE (eh->type) == STT_ARM_TFUNC)
+		  if (eh != NULL && eh->target_internal == ST_BRANCH_TO_THUMB)
 		    {
 		      dyn.d_un.d_val |= 1;
 		      bfd_elf32_swap_dyn_out (output_bfd, &dyn, dyncon);
@@ -12771,6 +12772,7 @@ elf32_arm_output_map_sym (output_arch_sy
   sym.st_other = 0;
   sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_NOTYPE);
   sym.st_shndx = osi->sec_shndx;
+  sym.st_target_internal = 0;
   elf32_arm_section_map_add (osi->sec, names[type][1], offset);
   return osi->func (osi->finfo, names[type], &sym, osi->sec, NULL) == 1;
 }
@@ -12870,6 +12872,7 @@ elf32_arm_output_stub_sym (output_arch_s
   sym.st_other = 0;
   sym.st_info = ELF_ST_INFO (STB_LOCAL, STT_FUNC);
   sym.st_shndx = osi->sec_shndx;
+  sym.st_target_internal = 0;
   return osi->func (osi->finfo, name, &sym, osi->sec, NULL) == 1;
 }
 
@@ -13594,19 +13597,6 @@ elf32_arm_write_section (bfd *output_bfd
   return FALSE;
 }
 
-/* Display STT_ARM_TFUNC symbols as functions.  */
-
-static void
-elf32_arm_symbol_processing (bfd *abfd ATTRIBUTE_UNUSED,
-			     asymbol *asym)
-{
-  elf_symbol_type *elfsym = (elf_symbol_type *) asym;
-
-  if (ELF_ST_TYPE (elfsym->internal_elf_sym.st_info) == STT_ARM_TFUNC)
-    elfsym->symbol.flags |= BSF_FUNCTION;
-}
-
-
 /* Mangle thumb function symbols as we read them in.  */
 
 static bfd_boolean
@@ -13619,13 +13609,23 @@ elf32_arm_swap_symbol_in (bfd * abfd,
     return FALSE;
 
   /* New EABI objects mark thumb function symbols by setting the low bit of
-     the address.  Turn these into STT_ARM_TFUNC.  */
+     the address.  */
   if ((ELF_ST_TYPE (dst->st_info) == STT_FUNC)
       && (dst->st_value & 1))
     {
-      dst->st_info = ELF_ST_INFO (ELF_ST_BIND (dst->st_info), STT_ARM_TFUNC);
       dst->st_value &= ~(bfd_vma) 1;
+      dst->st_target_internal = ST_BRANCH_TO_THUMB;
+    }
+  else if (ELF_ST_TYPE (dst->st_info) == STT_ARM_TFUNC)
+    {
+      dst->st_info = ELF_ST_INFO (ELF_ST_BIND (dst->st_info), STT_FUNC);
+      dst->st_target_internal = ST_BRANCH_TO_THUMB;
     }
+  else if (ELF_ST_TYPE (dst->st_info) == STT_SECTION)
+    dst->st_target_internal = ST_BRANCH_LONG;
+  else
+    dst->st_target_internal = ST_BRANCH_TO_ARM;
+
   return TRUE;
 }
 
@@ -13644,7 +13644,7 @@ elf32_arm_swap_symbol_out (bfd *abfd,
      of the address set, as per the new EABI.  We do this unconditionally
      because objcopy does not set the elf header flags until after
      it writes out the symbol table.  */
-  if (ELF_ST_TYPE (src->st_info) == STT_ARM_TFUNC)
+  if (src->st_target_internal == ST_BRANCH_TO_THUMB)
     {
       newsym = *src;
       newsym.st_info = ELF_ST_INFO (ELF_ST_BIND (src->st_info), STT_FUNC);
@@ -13717,14 +13717,6 @@ elf32_arm_additional_program_headers (bf
     return 0;
 }
 
-/* We have two function types: STT_FUNC and STT_ARM_TFUNC.  */
-
-static bfd_boolean
-elf32_arm_is_function_type (unsigned int type)
-{
-  return (type == STT_FUNC) || (type == STT_ARM_TFUNC);
-}
-
 /* We use this to override swap_symbol_in and swap_symbol_out.  */
 const struct elf_size_info elf32_arm_size_info =
 {
@@ -13804,13 +13796,11 @@ #define elf_backend_fake_sections  		elf
 #define elf_backend_section_from_shdr  		elf32_arm_section_from_shdr
 #define elf_backend_final_write_processing      elf32_arm_final_write_processing
 #define elf_backend_copy_indirect_symbol        elf32_arm_copy_indirect_symbol
-#define elf_backend_symbol_processing		elf32_arm_symbol_processing
 #define elf_backend_size_info			elf32_arm_size_info
 #define elf_backend_modify_segment_map		elf32_arm_modify_segment_map
 #define elf_backend_additional_program_headers  elf32_arm_additional_program_headers
 #define elf_backend_output_arch_local_syms      elf32_arm_output_arch_local_syms
 #define elf_backend_begin_write_processing      elf32_arm_begin_write_processing
-#define elf_backend_is_function_type		elf32_arm_is_function_type
 
 #define elf_backend_can_refcount       1
 #define elf_backend_can_gc_sections    1
Index: gas/config/tc-arm.c
===================================================================
--- gas/config/tc-arm.c	2010-11-26 09:56:09.000000000 +0000
+++ gas/config/tc-arm.c	2010-11-26 11:04:30.000000000 +0000
@@ -21949,8 +21949,8 @@ arm_adjust_symtab (void)
 	      /* If it's a .thumb_func, declare it as so,
 		 otherwise tag label as .code 16.  */
 	      if (THUMB_IS_FUNC (sym))
-		elf_sym->internal_elf_sym.st_info =
-		  ELF_ST_INFO (bind, STT_ARM_TFUNC);
+		elf_sym->internal_elf_sym.st_target_internal
+		  = ST_BRANCH_TO_THUMB;
 	      else if (EF_ARM_EABI_VERSION (meabi_flags) < EF_ARM_EABI_VER4)
 		elf_sym->internal_elf_sym.st_info =
 		  ELF_ST_INFO (bind, STT_ARM_16BIT);
Index: ld/emultempl/armelf.em
===================================================================
--- ld/emultempl/armelf.em	2010-11-26 09:56:09.000000000 +0000
+++ ld/emultempl/armelf.em	2010-11-26 09:56:56.000000000 +0000
@@ -404,7 +404,7 @@ gld${EMULATION_NAME}_finish (void)
       h = bfd_link_hash_lookup (link_info.hash, entry_symbol.name,
 				FALSE, FALSE, TRUE);
       eh = (struct elf_link_hash_entry *)h;
-      if (!h || ELF_ST_TYPE(eh->type) != STT_ARM_TFUNC)
+      if (!h || eh->target_internal != ST_BRANCH_TO_THUMB)
 	return;
     }
 
Index: opcodes/arm-dis.c
===================================================================
--- opcodes/arm-dis.c	2010-11-26 09:56:09.000000000 +0000
+++ opcodes/arm-dis.c	2010-11-26 09:56:56.000000000 +0000
@@ -4525,9 +4525,12 @@ get_sym_code_type (struct disassemble_in
   type = ELF_ST_TYPE (es->internal_elf_sym.st_info);
 
   /* If the symbol has function type then use that.  */
-  if (type == STT_FUNC || type == STT_ARM_TFUNC)
+  if (type == STT_FUNC)
     {
-      *map_type = (type == STT_ARM_TFUNC) ? MAP_THUMB : MAP_ARM;
+      if (ARM_SYM_BRANCH_TYPE (&es->internal_elf_sym) == ST_BRANCH_TO_THUMB)
+	*map_type = MAP_THUMB;
+      else
+	*map_type = MAP_ARM;
       return TRUE;
     }
 
@@ -4807,7 +4810,9 @@ print_insn (bfd_vma pc, struct disassemb
 	  es = *(elf_symbol_type **)(info->symbols);
 	  type = ELF_ST_TYPE (es->internal_elf_sym.st_info);
 
-	  is_thumb = (type == STT_ARM_TFUNC) || (type == STT_ARM_16BIT);
+	  is_thumb = ((ARM_SYM_BRANCH_TYPE (&es->internal_elf_sym)
+		       == ST_BRANCH_TO_THUMB)
+		      || type == STT_ARM_16BIT);
 	}
     }
 


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]