diff options
-rw-r--r-- | bfd/ChangeLog | 19 | ||||
-rw-r--r-- | bfd/bfd-in.h | 2 | ||||
-rw-r--r-- | bfd/bfd-in2.h | 2 | ||||
-rw-r--r-- | bfd/xcofflink.c | 173 | ||||
-rw-r--r-- | include/coff/ChangeLog | 5 | ||||
-rw-r--r-- | include/coff/xcoff.h | 7 | ||||
-rw-r--r-- | ld/ChangeLog | 12 | ||||
-rw-r--r-- | ld/emultempl/aix.em | 45 | ||||
-rw-r--r-- | ld/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | ld/testsuite/ld-powerpc/aix-export-1-all.dd | 11 | ||||
-rw-r--r-- | ld/testsuite/ld-powerpc/aix-export-1-full.dd | 21 | ||||
-rw-r--r-- | ld/testsuite/ld-powerpc/aix-export-1a.s | 14 | ||||
-rw-r--r-- | ld/testsuite/ld-powerpc/aix-export-1b.s | 9 | ||||
-rw-r--r-- | ld/testsuite/ld-powerpc/aix52.exp | 20 |
14 files changed, 290 insertions, 56 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 4bad45e..79e3cb4 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,5 +1,24 @@ 2009-03-14 Richard Sandiford <r.sandiford@uk.ibm.com> + * bfd-in.h (bfd_xcoff_size_dynamic_sections): Replace the + bfd_boolean export_defineds parameter with an unsigned int + auto_export_flags parameter. + * bfd-in2.h: Regenerate. + * xcofflink.c (xcoff_archive_contains_shared_object_p): New function, + split out from xcoff_build_ldsyms. + (xcoff_covered_by_expall_p): New function. + (xcoff_auto_export_p): New function, split out from xcoff_build_ldsyms + but with extra code to handle -bexpfull and -bexpall. + (xcoff_mark_auto_exports): New function. + (xcoff_build_ldsyms): Use xcoff_auto_export_p to decide whether + a function should be automatically exported. + (bfd_xcoff_size_dynamic_sections): Replace the export_defineds + parameter with an auto_export_flags parameter. Update ldinfo + accordingly. Use xcoff_mark_auto_exports to mark all automatically- + exported symbols. + +2009-03-14 Richard Sandiford <r.sandiford@uk.ibm.com> + * xcofflink.c (xcoff_mark_symbol_by_name): New function. (bfd_xcoff_size_dynamic_sections): Use it to mark the entry, init and fini functions. Do garbage collection for objects diff --git a/bfd/bfd-in.h b/bfd/bfd-in.h index 6b49013..5a3e13f 100644 --- a/bfd/bfd-in.h +++ b/bfd/bfd-in.h @@ -779,7 +779,7 @@ extern bfd_boolean bfd_xcoff_record_link_assignment extern bfd_boolean bfd_xcoff_size_dynamic_sections (bfd *, struct bfd_link_info *, const char *, const char *, unsigned long, unsigned long, unsigned long, bfd_boolean, - int, bfd_boolean, bfd_boolean, struct bfd_section **, bfd_boolean); + int, bfd_boolean, unsigned int, struct bfd_section **, bfd_boolean); extern bfd_boolean bfd_xcoff_link_generate_rtinit (bfd *, const char *, const char *, bfd_boolean); diff --git a/bfd/bfd-in2.h b/bfd/bfd-in2.h index 7e3defd..a173f56 100644 --- a/bfd/bfd-in2.h +++ b/bfd/bfd-in2.h @@ -786,7 +786,7 @@ extern bfd_boolean bfd_xcoff_record_link_assignment extern bfd_boolean bfd_xcoff_size_dynamic_sections (bfd *, struct bfd_link_info *, const char *, const char *, unsigned long, unsigned long, unsigned long, bfd_boolean, - int, bfd_boolean, bfd_boolean, struct bfd_section **, bfd_boolean); + int, bfd_boolean, unsigned int, struct bfd_section **, bfd_boolean); extern bfd_boolean bfd_xcoff_link_generate_rtinit (bfd *, const char *, const char *, bfd_boolean); diff --git a/bfd/xcofflink.c b/bfd/xcofflink.c index 3ca9b72..da5944e 100644 --- a/bfd/xcofflink.c +++ b/bfd/xcofflink.c @@ -2313,6 +2313,97 @@ xcoff_set_import_path (struct bfd_link_info *info, return TRUE; } +/* Return true if the given bfd contains at least one shared object. */ + +static bfd_boolean +xcoff_archive_contains_shared_object_p (bfd *archive) +{ + bfd *member; + + member = bfd_openr_next_archived_file (archive, NULL); + while (member != NULL && (member->flags & DYNAMIC) == 0) + member = bfd_openr_next_archived_file (archive, member); + return member != NULL; +} + +/* Symbol H qualifies for export by -bexpfull. Return true if it also + qualifies for export by -bexpall. */ + +static bfd_boolean +xcoff_covered_by_expall_p (struct xcoff_link_hash_entry *h) +{ + /* Exclude symbols beginning with '_'. */ + if (h->root.root.string[0] == '_') + return FALSE; + + /* Exclude archive members that would otherwise be unreferenced. */ + if ((h->flags & XCOFF_MARK) == 0 + && (h->root.type == bfd_link_hash_defined + || h->root.type == bfd_link_hash_defweak) + && h->root.u.def.section->owner != NULL + && h->root.u.def.section->owner->my_archive != NULL) + return FALSE; + + return TRUE; +} + +/* Return true if symbol H qualifies for the forms of automatic export + specified by AUTO_EXPORT_FLAGS. */ + +static bfd_boolean +xcoff_auto_export_p (struct xcoff_link_hash_entry *h, + unsigned int auto_export_flags) +{ + /* Don't automatically export things that were explicitly exported. */ + if ((h->flags & XCOFF_EXPORT) != 0) + return FALSE; + + /* Don't export things that we don't define. */ + if ((h->flags & XCOFF_DEF_REGULAR) == 0) + return FALSE; + + /* Don't export functions; export their descriptors instead. */ + if (h->root.root.string[0] == '.') + return FALSE; + + /* We don't export a symbol which is being defined by an object + included from an archive which contains a shared object. The + rationale is that if an archive contains both an unshared and + a shared object, then there must be some reason that the + unshared object is unshared, and we don't want to start + providing a shared version of it. In particular, this solves + a bug involving the _savefNN set of functions. gcc will call + those functions without providing a slot to restore the TOC, + so it is essential that these functions be linked in directly + and not from a shared object, which means that a shared + object which also happens to link them in must not export + them. This is confusing, but I haven't been able to think of + a different approach. Note that the symbols can, of course, + be exported explicitly. */ + if (h->root.type == bfd_link_hash_defined + || h->root.type == bfd_link_hash_defweak) + { + bfd *owner; + + owner = h->root.u.def.section->owner; + if (owner != NULL + && owner->my_archive != NULL + && xcoff_archive_contains_shared_object_p (owner->my_archive)) + return FALSE; + } + + /* Otherwise, all symbols are exported by -bexpfull. */ + if ((auto_export_flags & XCOFF_EXPFULL) != 0) + return TRUE; + + /* Despite its name, -bexpall exports most but not all symbols. */ + if ((auto_export_flags & XCOFF_EXPALL) != 0 + && xcoff_covered_by_expall_p (h)) + return TRUE; + + return FALSE; +} + /* Mark a symbol as not being garbage, including the section in which it is defined. */ @@ -2878,6 +2969,24 @@ bfd_xcoff_record_link_assignment (bfd *output_bfd, return TRUE; } +/* An xcoff_link_hash_traverse callback for which DATA points to an + xcoff_loader_info. Mark all symbols that should be automatically + exported. */ + +static bfd_boolean +xcoff_mark_auto_exports (struct xcoff_link_hash_entry *h, void *data) +{ + struct xcoff_loader_info *ldinfo; + + ldinfo = (struct xcoff_loader_info *) data; + if (xcoff_auto_export_p (h, ldinfo->auto_export_flags)) + { + if (!xcoff_mark_symbol (ldinfo->info, h)) + ldinfo->failed = TRUE; + } + return TRUE; +} + /* Add a symbol to the .loader symbols, if necessary. */ /* INPUT_BFD has an external symbol associated with hash table entry H @@ -2939,50 +3048,8 @@ xcoff_build_ldsyms (struct xcoff_link_hash_entry *h, void * p) /* If all defined symbols should be exported, mark them now. We don't want to export the actual functions, just the function descriptors. */ - if (ldinfo->export_defineds - && (h->flags & XCOFF_DEF_REGULAR) != 0 - && h->root.root.string[0] != '.') - { - bfd_boolean export; - - /* We don't export a symbol which is being defined by an object - included from an archive which contains a shared object. The - rationale is that if an archive contains both an unshared and - a shared object, then there must be some reason that the - unshared object is unshared, and we don't want to start - providing a shared version of it. In particular, this solves - a bug involving the _savefNN set of functions. gcc will call - those functions without providing a slot to restore the TOC, - so it is essential that these functions be linked in directly - and not from a shared object, which means that a shared - object which also happens to link them in must not export - them. This is confusing, but I haven't been able to think of - a different approach. Note that the symbols can, of course, - be exported explicitly. */ - export = TRUE; - if ((h->root.type == bfd_link_hash_defined - || h->root.type == bfd_link_hash_defweak) - && h->root.u.def.section->owner != NULL - && h->root.u.def.section->owner->my_archive != NULL) - { - bfd *arbfd, *member; - - arbfd = h->root.u.def.section->owner->my_archive; - member = bfd_openr_next_archived_file (arbfd, NULL); - while (member != NULL) - { - if ((member->flags & DYNAMIC) != 0) - { - export = FALSE; - break; - } - member = bfd_openr_next_archived_file (arbfd, member); - } - } - - if (export) - h->flags |= XCOFF_EXPORT; - } + if (xcoff_auto_export_p (h, ldinfo->auto_export_flags)) + h->flags |= XCOFF_EXPORT; /* We don't want to garbage collect symbols which are not defined in XCOFF files. This is a convenient place to mark them. */ @@ -3181,10 +3248,9 @@ xcoff_keep_symbol_p (struct bfd_link_info *info, bfd *input_bfd, -bmaxdata linker option). GC is whether to do garbage collection (the -bgc linker option). MODTYPE is the module type (the -bmodtype linker option). TEXTRO is whether the text section must - be read only (the -btextro linker option). EXPORT_DEFINEDS is - whether all defined symbols should be exported (the -unix linker - option). SPECIAL_SECTIONS is set by this routine to csects with - magic names like _end. */ + be read only (the -btextro linker option). AUTO_EXPORT_FLAGS + is a mask of XCOFF_EXPALL and XCOFF_EXPFULL. SPECIAL_SECTIONS + is set by this routine to csects with magic names like _end. */ bfd_boolean bfd_xcoff_size_dynamic_sections (bfd *output_bfd, @@ -3197,7 +3263,7 @@ bfd_xcoff_size_dynamic_sections (bfd *output_bfd, bfd_boolean gc, int modtype, bfd_boolean textro, - bfd_boolean export_defineds, + unsigned int auto_export_flags, asection **special_sections, bfd_boolean rtld) { @@ -3225,7 +3291,7 @@ bfd_xcoff_size_dynamic_sections (bfd *output_bfd, ldinfo.failed = FALSE; ldinfo.output_bfd = output_bfd; ldinfo.info = info; - ldinfo.export_defineds = export_defineds; + ldinfo.auto_export_flags = auto_export_flags; ldinfo.ldsym_count = 0; ldinfo.string_size = 0; ldinfo.strings = NULL; @@ -3328,6 +3394,13 @@ bfd_xcoff_size_dynamic_sections (bfd *output_bfd, if (info->fini_function != NULL && !xcoff_mark_symbol_by_name (info, info->fini_function, 0)) goto error_return; + if (auto_export_flags != 0) + { + xcoff_link_hash_traverse (xcoff_hash_table (info), + xcoff_mark_auto_exports, &ldinfo); + if (ldinfo.failed) + goto error_return; + } xcoff_sweep (info); xcoff_hash_table (info)->gc = TRUE; } diff --git a/include/coff/ChangeLog b/include/coff/ChangeLog index 09cd873..ba5fa3f 100644 --- a/include/coff/ChangeLog +++ b/include/coff/ChangeLog @@ -1,5 +1,10 @@ 2009-03-14 Richard Sandiford <r.sandiford@uk.ibm.com> + * xcoff.h (XCOFF_EXPALL, XCOFF_EXPFULL): New flags. + (xcoff_loader_info): Add auto_export_flags. + +2009-03-14 Richard Sandiford <r.sandiford@uk.ibm.com> + * internal.h (C_AIX_WEAKEXT): New macro. (C_WEAKEXT): Use the GNU definition in the generic part of the file, and conditionally reset it to C_AIX_WEAKEXT in the XCOFF part of diff --git a/include/coff/xcoff.h b/include/coff/xcoff.h index 4f9f7ed..4439dc9 100644 --- a/include/coff/xcoff.h +++ b/include/coff/xcoff.h @@ -394,6 +394,9 @@ struct xcoff_link_hash_table asection *special_sections[XCOFF_NUMBER_OF_SPECIAL_SECTIONS]; }; +/* These flags indicate which of -bexpall and -bexpfull are in effect. */ +#define XCOFF_EXPALL 1 +#define XCOFF_EXPFULL 2 /* This structure is used to pass information through xcoff_link_hash_traverse. */ @@ -409,8 +412,8 @@ struct xcoff_loader_info /* Link information structure. */ struct bfd_link_info *info; - /* Whether all defined symbols should be exported. */ - bfd_boolean export_defineds; + /* A mask of XCOFF_EXPALL and XCOFF_EXPFULL flags. */ + unsigned int auto_export_flags; /* Number of ldsym structures. */ size_t ldsym_count; diff --git a/ld/ChangeLog b/ld/ChangeLog index 40434eb..d41dd9b 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,5 +1,17 @@ 2009-03-14 Richard Sandiford <r.sandiford@uk.ibm.com> + * emultempl/aix.em (auto_export_flags): New variable. + (explicit_auto_export_flags): Likewise. + (OPTION_EXPALL, OPTION_EXPFULL): New enum values. + (OPTION_NOEXPALL, OPTION_NOEXPFULL): Likewise. + (gld${EMULATION_NAME}_add_options): Add -bexpall, -bexpfull, + -bnoexpall and -bnoexpfull. + (gld${EMULATION_NAME}_handle_option): Handle them. + (gld${EMULATION_NAME}_before_allocation): Update the call to + bfd_size_dynamic_sections. + +2009-03-14 Richard Sandiford <r.sandiford@uk.ibm.com> + * emultempl/aix.em (gld${EMULATION_NAME}_handle_option): Make -berok and -bernotok control link_info.unresolved_syms_in_objects and link_info.unresolved_syms_in_shared_libs instead of diff --git a/ld/emultempl/aix.em b/ld/emultempl/aix.em index a9f3884..8558660 100644 --- a/ld/emultempl/aix.em +++ b/ld/emultempl/aix.em @@ -84,6 +84,14 @@ static unsigned short modtype = ('1' << 8) | 'L'; permitted). */ static int textro; +/* A mask of XCOFF_EXPALL and XCOFF_EXPFULL flags, as set by their + associated -b and -bno options. */ +static unsigned int auto_export_flags; + +/* A mask of auto_export_flags bits that were explicitly set on the + command line. */ +static unsigned int explicit_auto_export_flags; + /* Whether to implement Unix like linker semantics. */ static int unix_ld; @@ -156,6 +164,8 @@ enum OPTION_AUTOIMP, OPTION_ERNOTOK, OPTION_EROK, + OPTION_EXPALL, + OPTION_EXPFULL, OPTION_EXPORT, OPTION_IMPORT, OPTION_INITFINI, @@ -164,6 +174,8 @@ enum OPTION_MAXSTACK, OPTION_MODTYPE, OPTION_NOAUTOIMP, + OPTION_NOEXPALL, + OPTION_NOEXPFULL, OPTION_NOSTRCMPCT, OPTION_PD, OPTION_PT, @@ -201,6 +213,8 @@ gld${EMULATION_NAME}_add_options {"bernotok", no_argument, NULL, OPTION_ERNOTOK}, {"berok", no_argument, NULL, OPTION_EROK}, {"berrmsg", no_argument, NULL, OPTION_IGNORE}, + {"bexpall", no_argument, NULL, OPTION_EXPALL}, + {"bexpfull", no_argument, NULL, OPTION_EXPFULL}, {"bexport", required_argument, NULL, OPTION_EXPORT}, {"bf", no_argument, NULL, OPTION_ERNOTOK}, {"bgc", no_argument, &gc, 1}, @@ -216,6 +230,8 @@ gld${EMULATION_NAME}_add_options {"bM", required_argument, NULL, OPTION_MODTYPE}, {"bmodtype", required_argument, NULL, OPTION_MODTYPE}, {"bnoautoimp", no_argument, NULL, OPTION_NOAUTOIMP}, + {"bnoexpall", no_argument, NULL, OPTION_NOEXPALL}, + {"bnoexpfull", no_argument, NULL, OPTION_NOEXPFULL}, {"bnodelcsect", no_argument, NULL, OPTION_IGNORE}, {"bnoentry", no_argument, NULL, OPTION_IGNORE}, {"bnogc", no_argument, &gc, 0}, @@ -388,6 +404,16 @@ gld${EMULATION_NAME}_handle_option (int optc) link_info.unresolved_syms_in_shared_libs = RM_IGNORE; break; + case OPTION_EXPALL: + auto_export_flags |= XCOFF_EXPALL; + explicit_auto_export_flags |= XCOFF_EXPALL; + break; + + case OPTION_EXPFULL: + auto_export_flags |= XCOFF_EXPFULL; + explicit_auto_export_flags |= XCOFF_EXPFULL; + break; + case OPTION_EXPORT: gld${EMULATION_NAME}_read_file (optarg, FALSE); break; @@ -444,6 +470,16 @@ gld${EMULATION_NAME}_handle_option (int optc) link_info.static_link = TRUE; break; + case OPTION_NOEXPALL: + auto_export_flags &= ~XCOFF_EXPALL; + explicit_auto_export_flags |= XCOFF_EXPALL; + break; + + case OPTION_NOEXPFULL: + auto_export_flags &= ~XCOFF_EXPFULL; + explicit_auto_export_flags |= XCOFF_EXPFULL; + break; + case OPTION_NOSTRCMPCT: link_info.traditional_format = TRUE; break; @@ -624,7 +660,7 @@ gld${EMULATION_NAME}_before_allocation (void) ".data", ".bss" }; - unsigned int i; + unsigned int i, flags; /* Handle the import and export files, if any. */ for (fl = import_files; fl != NULL; fl = fl->next) @@ -710,11 +746,16 @@ gld${EMULATION_NAME}_before_allocation (void) } } + /* Default to -bexpfull for SVR4-like semantics. */ + flags = (unix_ld ? XCOFF_EXPFULL : 0); + flags &= ~explicit_auto_export_flags; + flags |= auto_export_flags; + /* Let the XCOFF backend set up the .loader section. */ if (!bfd_xcoff_size_dynamic_sections (link_info.output_bfd, &link_info, libpath, entry_symbol.name, file_align, maxstack, maxdata, gc && !unix_ld ? TRUE : FALSE, - modtype, textro ? TRUE : FALSE, unix_ld, special_sections, + modtype, textro ? TRUE : FALSE, flags, special_sections, rtld ? TRUE : FALSE)) einfo ("%P%F: failed to set dynamic section sizes: %E\n"); diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog index a2cdc37..df1fd84 100644 --- a/ld/testsuite/ChangeLog +++ b/ld/testsuite/ChangeLog @@ -1,5 +1,11 @@ 2009-03-14 Richard Sandiford <r.sandiford@uk.ibm.com> + * ld-powerpc/aix-export-1-all.dd, ld-powerpc/aix-export-1-full.dd, + ld-powerpc/aix-export-1a.s, ld-powerpc/aix-export-1b.s: New tests. + * ld-powerpc/aix52.exp: Run them. + +2009-03-14 Richard Sandiford <r.sandiford@uk.ibm.com> + * ld-powerpc/aix-gc-1.s, ld-powerpc/aix-gc-1.ex, ld-powerpc/aix-gc-1-32.dd, ld-powerpc/aix-gc-1-64.dd, ld-powerpc/aix-weak-1-gcdso.dnd, ld-powerpc/aix-weak-1-gcdso.hd, diff --git a/ld/testsuite/ld-powerpc/aix-export-1-all.dd b/ld/testsuite/ld-powerpc/aix-export-1-all.dd new file mode 100644 index 0000000..90eec95 --- /dev/null +++ b/ld/testsuite/ld-powerpc/aix-export-1-all.dd @@ -0,0 +1,11 @@ + +.* + + +Disassembly of section \.data: + +0*10000000 <main1>: + *10000000: 10 00 00 04 .* + +0*10000004 <lib1>: + *10000004: 11 11 00 01 .* diff --git a/ld/testsuite/ld-powerpc/aix-export-1-full.dd b/ld/testsuite/ld-powerpc/aix-export-1-full.dd new file mode 100644 index 0000000..d300fa2 --- /dev/null +++ b/ld/testsuite/ld-powerpc/aix-export-1-full.dd @@ -0,0 +1,21 @@ + +.* + + +Disassembly of section .data: + +0*10000000 <main1>: + *10000000: 10 00 00 08 .* + +0*10000004 <_main2>: + *10000004: 10 00 00 0c .* + +0*10000008 <lib1>: + *10000008: 11 11 00 01 .* + +0*1000000c <_lib2>: + *1000000c: 11 11 00 02 .* + +0*10000010 <lib3>: + *10000010: 11 11 00 03 .* + *10000014: 00 00 00 00 .* diff --git a/ld/testsuite/ld-powerpc/aix-export-1a.s b/ld/testsuite/ld-powerpc/aix-export-1a.s new file mode 100644 index 0000000..69701e5 --- /dev/null +++ b/ld/testsuite/ld-powerpc/aix-export-1a.s @@ -0,0 +1,14 @@ + .globl lib1 + .csect lib1[RW] +lib1: + .long 0x11110001 + + .globl _lib2 + .csect _lib2[RW] +_lib2: + .long 0x11110002 + + .globl lib3 + .csect lib3[RW] +lib3: + .long 0x11110003 diff --git a/ld/testsuite/ld-powerpc/aix-export-1b.s b/ld/testsuite/ld-powerpc/aix-export-1b.s new file mode 100644 index 0000000..32c355d --- /dev/null +++ b/ld/testsuite/ld-powerpc/aix-export-1b.s @@ -0,0 +1,9 @@ + .globl main1 + .csect main1[RW] +main1: + .long lib1 + + .globl _main2 + .csect _main2[RW] +_main2: + .long _lib2 diff --git a/ld/testsuite/ld-powerpc/aix52.exp b/ld/testsuite/ld-powerpc/aix52.exp index 330de27..fb2307a 100644 --- a/ld/testsuite/ld-powerpc/aix52.exp +++ b/ld/testsuite/ld-powerpc/aix52.exp @@ -108,6 +108,26 @@ set aix52tests { {nm -D aix-no-dup-syms-1-dso.dnd} {objdump -R aix-no-dup-syms-1-dso.drd}} "aix-no-dup-syms-1.so"} + {"Export test 1 (archive)" "" + "" {aix-export-1a.s} + {} "libaix-export-1.a"} + + {"Export test 1 (object)" "-r" + "" {aix-export-1b.s} + {} "aix-export-1.o"} + + {"Export test 1 (-bexpall)" + "-shared -bexpall tmpdir/aix-export-1.o -Ltmpdir -laix-export-1" + "" {} + {{objdump -dj.data aix-export-1-all.dd}} + "aix-export-1-all.so"} + + {"Export test 1 (-bexpfull)" + "-shared -bexpfull tmpdir/aix-export-1.o -Ltmpdir -laix-export-1" + "" {} + {{objdump -dj.data aix-export-1-full.dd}} + "aix-export-1-full.so"} + {"Garbage collection test 1" "-shared -binitfini:init_function:fini_function -bE:aix-gc-1.ex" "" {aix-gc-1.s} |