aboutsummaryrefslogtreecommitdiff
path: root/bfd
diff options
context:
space:
mode:
authorPaul Brook <paul@codesourcery.com>2007-04-17 20:09:52 +0000
committerPaul Brook <paul@codesourcery.com>2007-04-17 20:09:52 +0000
commitfcb93ecfc25d0337944090414ed53da4dcdd6864 (patch)
treeb5c44efa1f04197add1b10c2520b78cfb190553f /bfd
parent06f9a1af70ed2722e575203073271ae39c071def (diff)
downloadfsf-binutils-gdb-fcb93ecfc25d0337944090414ed53da4dcdd6864.zip
fsf-binutils-gdb-fcb93ecfc25d0337944090414ed53da4dcdd6864.tar.gz
fsf-binutils-gdb-fcb93ecfc25d0337944090414ed53da4dcdd6864.tar.bz2
2007-04-17 Paul Brook <paul@codesourcery.com>
bfd/ * elf.c (_bfd_elf_is_function_type): New function. * elflink.c (_bfd_elf_merge_symbol): Use bed->is_function_type. (_bfd_elf_dynamic_symbol_p, _bfd_elf_symbol_refs_local_p, is_global_data_symbol_definition, elf_link_add_object_symbols): Ditto. * elf-bfd.h (elf_backend_data): Add is_function_type. (_bfd_elf_is_function_type): Add prototype. * elfxx-target.h (elf_backend_is_function_type): Add default definition. (elfNN_bed): Add elf_backend_is_function_type. * elf32-arm.c (elf32_arm_is_function_type): New function. (elf_backend_is_function_type): Define. ld/testsuite/ * ld-arm/preempt-app.s: New test. * ld-arm/preempt-app.sym: New. * ld-arm/arm-elf.exp: Add preempt-app.
Diffstat (limited to 'bfd')
-rw-r--r--bfd/ChangeLog14
-rw-r--r--bfd/elf-bfd.h5
-rw-r--r--bfd/elf.c11
-rw-r--r--bfd/elf32-arm.c8
-rw-r--r--bfd/elflink.c56
-rw-r--r--bfd/elfxx-target.h5
6 files changed, 84 insertions, 15 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 7d7838c..b670e62 100644
--- a/bfd/ChangeLog
+++ b/bfd/ChangeLog
@@ -1,3 +1,17 @@
+2007-04-17 Paul Brook <paul@codesourcery.com>
+
+ * elf.c (_bfd_elf_is_function_type): New function.
+ * elflink.c (_bfd_elf_merge_symbol): Use bed->is_function_type.
+ (_bfd_elf_dynamic_symbol_p, _bfd_elf_symbol_refs_local_p,
+ is_global_data_symbol_definition, elf_link_add_object_symbols): Ditto.
+ * elf-bfd.h (elf_backend_data): Add is_function_type.
+ (_bfd_elf_is_function_type): Add prototype.
+ * elfxx-target.h (elf_backend_is_function_type): Add default
+ definition.
+ (elfNN_bed): Add elf_backend_is_function_type.
+ * elf32-arm.c (elf32_arm_is_function_type): New function.
+ (elf_backend_is_function_type): Define.
+
2007-04-17 Daniel Jacobowitz <dan@codesourcery.com>
* elfxx-mips.c (_bfd_mips_elf_size_dynamic_sections): Put
diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h
index 4a01fe6..e9ee29b 100644
--- a/bfd/elf-bfd.h
+++ b/bfd/elf-bfd.h
@@ -1050,6 +1050,9 @@ struct elf_backend_data
/* Return TRUE if symbol should be hashed in the `.gnu.hash' section. */
bfd_boolean (*elf_hash_symbol) (struct elf_link_hash_entry *);
+ /* Return TRUE if type is a function symbol type. */
+ bfd_boolean (*is_function_type) (unsigned int type);
+
/* Used to handle bad SHF_LINK_ORDER input. */
bfd_error_handler_type link_order_error_handler;
@@ -1919,6 +1922,8 @@ extern struct elf_segment_map * _bfd_elf_make_dynamic_segment
extern bfd_boolean _bfd_elf_map_sections_to_segments
(bfd *, struct bfd_link_info *);
+extern bfd_boolean _bfd_elf_is_function_type (unsigned int);
+
/* Exported interface for writing elf corefile notes. */
extern char *elfcore_write_note
(bfd *, char *, int *, const char *, int, const void *, int);
diff --git a/bfd/elf.c b/bfd/elf.c
index 8007302..1f3408e 100644
--- a/bfd/elf.c
+++ b/bfd/elf.c
@@ -9167,3 +9167,14 @@ _bfd_elf_set_osabi (bfd * abfd,
i_ehdrp->e_ident[EI_OSABI] = get_elf_backend_data (abfd)->elf_osabi;
}
+
+
+/* Return TRUE for ELF symbol types that represent functions.
+ This is the default version of this function, which is sufficient for
+ most targets. It returns true if TYPE is STT_FUNC. */
+
+bfd_boolean
+_bfd_elf_is_function_type (unsigned int type)
+{
+ return (type == STT_FUNC);
+}
diff --git a/bfd/elf32-arm.c b/bfd/elf32-arm.c
index e8be0d5..10a6408 100644
--- a/bfd/elf32-arm.c
+++ b/bfd/elf32-arm.c
@@ -10557,6 +10557,13 @@ elf32_arm_additional_program_headers (bfd *abfd,
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 = {
sizeof (Elf32_External_Ehdr),
@@ -10643,6 +10650,7 @@ const struct elf_size_info elf32_arm_size_info = {
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
diff --git a/bfd/elflink.c b/bfd/elflink.c
index 0058002..807455e 100644
--- a/bfd/elflink.c
+++ b/bfd/elflink.c
@@ -947,6 +947,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
&& h->root.type != bfd_link_hash_undefweak
&& h->root.type != bfd_link_hash_common);
+ bed = get_elf_backend_data (abfd);
/* When we try to create a default indirect symbol from the dynamic
definition with the default version, we skip it if its type and
the type of existing regular definition mismatch. We only do it
@@ -961,7 +962,9 @@ _bfd_elf_merge_symbol (bfd *abfd,
&& (olddef || h->root.type == bfd_link_hash_common)
&& ELF_ST_TYPE (sym->st_info) != h->type
&& ELF_ST_TYPE (sym->st_info) != STT_NOTYPE
- && h->type != STT_NOTYPE)
+ && h->type != STT_NOTYPE
+ && !(bed->is_function_type (ELF_ST_TYPE (sym->st_info))
+ && bed->is_function_type (h->type)))
{
*skip = TRUE;
return TRUE;
@@ -1152,6 +1155,11 @@ _bfd_elf_merge_symbol (bfd *abfd,
if (olddef && newdyn)
oldweak = FALSE;
+ /* Allow changes between different types of funciton symbol. */
+ if (bed->is_function_type (ELF_ST_TYPE (sym->st_info))
+ && bed->is_function_type (h->type))
+ *type_change_ok = TRUE;
+
/* It's OK to change the type if either the existing symbol or the
new symbol is weak. A type change is also OK if the old symbol
is undefined and the new symbol is defined. */
@@ -1198,7 +1206,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
&& (sec->flags & SEC_ALLOC) != 0
&& (sec->flags & SEC_LOAD) == 0
&& sym->st_size > 0
- && ELF_ST_TYPE (sym->st_info) != STT_FUNC)
+ && !bed->is_function_type (ELF_ST_TYPE (sym->st_info)))
newdyncommon = TRUE;
else
newdyncommon = FALSE;
@@ -1210,14 +1218,13 @@ _bfd_elf_merge_symbol (bfd *abfd,
&& (h->root.u.def.section->flags & SEC_ALLOC) != 0
&& (h->root.u.def.section->flags & SEC_LOAD) == 0
&& h->size > 0
- && h->type != STT_FUNC)
+ && !bed->is_function_type (h->type))
olddyncommon = TRUE;
else
olddyncommon = FALSE;
/* We now know everything about the old and new symbols. We ask the
backend to check if we can merge them. */
- bed = get_elf_backend_data (abfd);
if (bed->merge_symbol
&& !bed->merge_symbol (info, sym_hash, h, sym, psec, pvalue,
pold_alignment, skip, override,
@@ -1272,7 +1279,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
&& (olddef
|| (h->root.type == bfd_link_hash_common
&& (newweak
- || ELF_ST_TYPE (sym->st_info) == STT_FUNC))))
+ || bed->is_function_type (ELF_ST_TYPE (sym->st_info))))))
{
*override = TRUE;
newdef = FALSE;
@@ -1327,7 +1334,7 @@ _bfd_elf_merge_symbol (bfd *abfd,
&& (newdef
|| (bfd_is_com_section (sec)
&& (oldweak
- || h->type == STT_FUNC)))
+ || bed->is_function_type (h->type))))
&& olddyn
&& olddef
&& h->def_dynamic)
@@ -2640,6 +2647,8 @@ _bfd_elf_dynamic_symbol_p (struct elf_link_hash_entry *h,
bfd_boolean ignore_protected)
{
bfd_boolean binding_stays_local_p;
+ const struct elf_backend_data *bed;
+ struct elf_link_hash_table *hash_table;
if (h == NULL)
return FALSE;
@@ -2665,10 +2674,16 @@ _bfd_elf_dynamic_symbol_p (struct elf_link_hash_entry *h,
return FALSE;
case STV_PROTECTED:
+ hash_table = elf_hash_table (info);
+ if (!is_elf_hash_table (hash_table))
+ return FALSE;
+
+ bed = get_elf_backend_data (hash_table->dynobj);
+
/* Proper resolution for function pointer equality may require
that these symbols perhaps be resolved dynamically, even though
we should be resolving them to the current module. */
- if (!ignore_protected || h->type != STT_FUNC)
+ if (!ignore_protected || !bed->is_function_type (h->type))
binding_stays_local_p = TRUE;
break;
@@ -2695,6 +2710,9 @@ _bfd_elf_symbol_refs_local_p (struct elf_link_hash_entry *h,
struct bfd_link_info *info,
bfd_boolean local_protected)
{
+ const struct elf_backend_data *bed;
+ struct elf_link_hash_table *hash_table;
+
/* If it's a local sym, of course we resolve locally. */
if (h == NULL)
return TRUE;
@@ -2731,8 +2749,14 @@ _bfd_elf_symbol_refs_local_p (struct elf_link_hash_entry *h,
if (ELF_ST_VISIBILITY (h->other) != STV_PROTECTED)
return TRUE;
+ hash_table = elf_hash_table (info);
+ if (!is_elf_hash_table (hash_table))
+ return TRUE;
+
+ bed = get_elf_backend_data (hash_table->dynobj);
+
/* STV_PROTECTED non-function symbols are local. */
- if (h->type != STT_FUNC)
+ if (!bed->is_function_type (h->type))
return TRUE;
/* Function pointer equality tests may require that STV_PROTECTED
@@ -2781,8 +2805,9 @@ is_global_data_symbol_definition (bfd *abfd ATTRIBUTE_UNUSED,
&& ELF_ST_BIND (sym->st_info) < STB_LOOS)
return FALSE;
+ bed = get_elf_backend_data (abfd);
/* Function symbols do not count. */
- if (ELF_ST_TYPE (sym->st_info) == STT_FUNC)
+ if (bed->is_function_type (ELF_ST_TYPE (sym->st_info)))
return FALSE;
/* If the section is undefined, then so is the symbol. */
@@ -2791,7 +2816,6 @@ is_global_data_symbol_definition (bfd *abfd ATTRIBUTE_UNUSED,
/* If the symbol is defined in the common section, then
it is a common definition and so does not count. */
- bed = get_elf_backend_data (abfd);
if (bed->common_definition (sym))
return FALSE;
@@ -3799,8 +3823,9 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
if it is not a function, because it might be the version
symbol itself. FIXME: What if it isn't? */
if ((iver.vs_vers & VERSYM_HIDDEN) != 0
- || (vernum > 1 && (! bfd_is_abs_section (sec)
- || ELF_ST_TYPE (isym->st_info) == STT_FUNC)))
+ || (vernum > 1
+ && (!bfd_is_abs_section (sec)
+ || bed->is_function_type (ELF_ST_TYPE (isym->st_info)))))
{
const char *verstr;
size_t namelen, verlen, newlen;
@@ -3947,7 +3972,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
if (dynamic
&& definition
&& (flags & BSF_WEAK) != 0
- && ELF_ST_TYPE (isym->st_info) != STT_FUNC
+ && !bed->is_function_type (ELF_ST_TYPE (isym->st_info))
&& is_elf_hash_table (htab)
&& h->u.weakdef == NULL)
{
@@ -4072,7 +4097,8 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
to be the size of the common symbol. The code just above
won't fix the size if a common symbol becomes larger. We
don't warn about a size change here, because that is
- covered by --warn-common. */
+ covered by --warn-common. Allow changed between different
+ function types. */
if (h->root.type == bfd_link_hash_common)
h->size = h->root.u.c.size;
@@ -4414,7 +4440,7 @@ elf_link_add_object_symbols (bfd *abfd, struct bfd_link_info *info)
h = *hpp;
if (h != NULL
&& h->root.type == bfd_link_hash_defined
- && h->type != STT_FUNC)
+ && !bed->is_function_type (h->type))
{
*sym_hash = h;
sym_hash++;
diff --git a/bfd/elfxx-target.h b/bfd/elfxx-target.h
index ea21b62..7b14781 100644
--- a/bfd/elfxx-target.h
+++ b/bfd/elfxx-target.h
@@ -587,6 +587,10 @@
#define elf_backend_hash_symbol _bfd_elf_hash_symbol
#endif
+#ifndef elf_backend_is_function_type
+#define elf_backend_is_function_type _bfd_elf_is_function_type
+#endif
+
extern const struct elf_size_info _bfd_elfNN_size_info;
static struct elf_backend_data elfNN_bed =
@@ -672,6 +676,7 @@ static struct elf_backend_data elfNN_bed =
elf_backend_common_section,
elf_backend_merge_symbol,
elf_backend_hash_symbol,
+ elf_backend_is_function_type,
elf_backend_link_order_error_handler,
elf_backend_relplt_name,
ELF_MACHINE_ALT1,