From fcb93ecfc25d0337944090414ed53da4dcdd6864 Mon Sep 17 00:00:00 2001 From: Paul Brook Date: Tue, 17 Apr 2007 20:09:52 +0000 Subject: [PATCH] 2007-04-17 Paul Brook 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. --- bfd/ChangeLog | 14 ++++++++ bfd/elf-bfd.h | 5 +++ bfd/elf.c | 11 ++++++ bfd/elf32-arm.c | 8 +++++ bfd/elflink.c | 56 +++++++++++++++++++++-------- bfd/elfxx-target.h | 5 +++ ld/testsuite/ChangeLog | 6 ++++ ld/testsuite/ld-arm/arm-elf.exp | 4 +++ ld/testsuite/ld-arm/preempt-app.s | 27 ++++++++++++++ ld/testsuite/ld-arm/preempt-app.sym | 16 +++++++++ 10 files changed, 137 insertions(+), 15 deletions(-) create mode 100644 ld/testsuite/ld-arm/preempt-app.s create mode 100644 ld/testsuite/ld-arm/preempt-app.sym diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 7d7838c848b..b670e62c819 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,3 +1,17 @@ +2007-04-17 Paul Brook + + * 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 * elfxx-mips.c (_bfd_mips_elf_size_dynamic_sections): Put diff --git a/bfd/elf-bfd.h b/bfd/elf-bfd.h index 4a01fe6ceb6..e9ee29b12c3 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 80073022ecb..1f3408e3286 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 e8be0d5d927..10a64085f2f 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 0058002cdaf..807455ed948 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 ea21b625120..7b147817486 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, diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog index da49ab72005..5b5a4961581 100644 --- a/ld/testsuite/ChangeLog +++ b/ld/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2007-04-17 Paul Brook + + * 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 * ld-mips-elf/vxworks1-lib.td: New test. diff --git a/ld/testsuite/ld-arm/arm-elf.exp b/ld/testsuite/ld-arm/arm-elf.exp index 5844266323c..f28bd095d9d 100644 --- a/ld/testsuite/ld-arm/arm-elf.exp +++ b/ld/testsuite/ld-arm/arm-elf.exp @@ -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 diff --git a/ld/testsuite/ld-arm/preempt-app.s b/ld/testsuite/ld-arm/preempt-app.s new file mode 100644 index 00000000000..f1eccc2b0bb --- /dev/null +++ b/ld/testsuite/ld-arm/preempt-app.s @@ -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 diff --git a/ld/testsuite/ld-arm/preempt-app.sym b/ld/testsuite/ld-arm/preempt-app.sym new file mode 100644 index 00000000000..d8ebf3b4d8a --- /dev/null +++ b/ld/testsuite/ld-arm/preempt-app.sym @@ -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 -- 2.30.2