summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Sandiford <rsandifo@nildram.co.uk>2009-03-14 09:35:46 +0000
committerRichard Sandiford <rsandifo@nildram.co.uk>2009-03-14 09:35:46 +0000
commit657c135ae73f78f804caffd4216c7dd6ed83232c (patch)
treee37570c2ab4a32c3e13d1999e3516e61b25d4ce7
parent2bc16fa118ab4f519b21489539c048b4f3c475ec (diff)
downloadbinutils-redhat-657c135ae73f78f804caffd4216c7dd6ed83232c.tar.gz
include/coff/
* xcoff.h (XCOFF_EXPALL, XCOFF_EXPFULL): New flags. (xcoff_loader_info): Add auto_export_flags. bfd/ * 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. ld/ * 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. ld/testsuite/ * 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.
-rw-r--r--bfd/ChangeLog19
-rw-r--r--bfd/bfd-in.h2
-rw-r--r--bfd/bfd-in2.h2
-rw-r--r--bfd/xcofflink.c173
-rw-r--r--include/coff/ChangeLog5
-rw-r--r--include/coff/xcoff.h7
-rw-r--r--ld/ChangeLog12
-rw-r--r--ld/emultempl/aix.em45
-rw-r--r--ld/testsuite/ChangeLog6
-rw-r--r--ld/testsuite/ld-powerpc/aix-export-1-all.dd11
-rw-r--r--ld/testsuite/ld-powerpc/aix-export-1-full.dd21
-rw-r--r--ld/testsuite/ld-powerpc/aix-export-1a.s14
-rw-r--r--ld/testsuite/ld-powerpc/aix-export-1b.s9
-rw-r--r--ld/testsuite/ld-powerpc/aix52.exp20
14 files changed, 290 insertions, 56 deletions
diff --git a/bfd/ChangeLog b/bfd/ChangeLog
index 4bad45e1e6..79e3cb44c4 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 6b4901330f..5a3e13f1bb 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 7e3defde56..a173f568ed 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 3ca9b7287a..da5944eb81 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 09cd87322f..ba5fa3fe08 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 4f9f7edee7..4439dc99b1 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 40434ebe76..d41dd9b9de 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 a9f3884055..85586607b5 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 a2cdc378e6..df1fd84d68 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 0000000000..90eec95e97
--- /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 0000000000..d300fa2a86
--- /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 0000000000..69701e5d50
--- /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 0000000000..32c355dbd0
--- /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 330de27785..fb2307a6fd 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}