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:
parent
06f9a1af70
commit
fcb93ecfc2
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
11
bfd/elf.c
11
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);
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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++;
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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
|
||||
|
||||
27
ld/testsuite/ld-arm/preempt-app.s
Normal file
27
ld/testsuite/ld-arm/preempt-app.s
Normal 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
|
||||
16
ld/testsuite/ld-arm/preempt-app.sym
Normal file
16
ld/testsuite/ld-arm/preempt-app.sym
Normal 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
|
||||
Loading…
Reference in New Issue
Block a user