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.
This commit is contained in:
Paul Brook 2007-04-17 20:09:52 +00:00
parent 06f9a1af70
commit fcb93ecfc2
10 changed files with 137 additions and 15 deletions

View File

@ -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

View File

@ -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);

View File

@ -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);
}

View File

@ -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

View File

@ -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++;

View File

@ -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,

View File

@ -1,3 +1,9 @@
2007-04-17 Paul Brook <paul@codesourcery.com>
* ld-arm/preempt-app.s: New test.
* ld-arm/preempt-app.sym: New.
* ld-arm/arm-elf.exp: Add preempt-app.
2007-04-12 Richard Sandiford <richard@codesourcery.com>
* ld-mips-elf/vxworks1-lib.td: New test.

View File

@ -159,6 +159,10 @@ set armelftests {
{"arm-pic-veneer" "-static -T arm.ld --pic-veneer" "" {arm-pic-veneer.s}
{{objdump -d arm-pic-veneer.d}}
"arm-pic-veneer"}
{"Preempt Thumb symbol" "tmpdir/mixed-lib.so -T arm-dyn.ld --use-blx" ""
{preempt-app.s}
{{readelf -Ds preempt-app.sym}}
"preempt-app"}
}
run_ld_link_tests $armelftests

View File

@ -0,0 +1,27 @@
@ Preempt an ARM shared library function with a Thumb function
@ in the application.
.text
.p2align 4
.globl _start
_start:
mov ip, sp
stmdb sp!, {r11, ip, lr, pc}
bl lib_func1
ldmia sp, {r11, sp, lr}
bx lr
.p2align 4
.globl app_func2
.type app_func2,%function
app_func2:
bx lr
.p2align 4
.globl lib_func1
.type lib_func1,%function
.thumb_func
lib_func1:
bx lr
.data
.long data_obj

View File

@ -0,0 +1,16 @@
Symbol table for image:
Num Buc: Value Size Type Bind Vis Ndx Name
.. ..: ........ 0 NOTYPE GLOBAL DEFAULT ABS _edata
.. ..: ........ 0 NOTYPE GLOBAL DEFAULT ABS __bss_start__
.. ..: ........ 0 NOTYPE GLOBAL DEFAULT ABS _end
.. ..: ........ 4 OBJECT GLOBAL DEFAULT 10 data_obj
.. ..: ........ 0 NOTYPE GLOBAL DEFAULT ABS __bss_end__
.. ..: .......1 20 FUNC GLOBAL DEFAULT 6 lib_func1
.. ..: ........ 0 NOTYPE GLOBAL DEFAULT ABS __exidx_start
.. ..: ........ 0 NOTYPE GLOBAL DEFAULT 9 __data_start
.. ..: ........ 0 NOTYPE GLOBAL DEFAULT ABS __end__
.. ..: ........ 0 NOTYPE GLOBAL DEFAULT ABS __bss_start
.. ..: .......0 0 FUNC GLOBAL DEFAULT 6 app_func2
.. ..: ........ 0 NOTYPE GLOBAL DEFAULT ABS _bss_end__
.. ..: ........ 0 NOTYPE GLOBAL DEFAULT ABS __exidx_end