From 858ef0ce3bae131931bd6f1c24fab4acb90f89df Mon Sep 17 00:00:00 2001 From: Richard Sandiford Date: Sat, 14 Mar 2009 09:17:32 +0000 Subject: include/coff/ * xcoff.h (XCOFF_CALLED, XCOFF_IMPORT): Update comments. (XCOFF_WAS_UNDEFINED): New flag. (xcoff_link_hash_table): Add an "rtld" field. bfd/ * coff-rs6000.c (xcoff_ppc_relocate_section): Report relocations against undefined symbols if the symbol's XCOFF_WAS_UNDEFINED flag is set. Assert that all undefined symbols are either imported or defined by a dynamic object. * coff64-rs6000.c (xcoff64_ppc_relocate_section): Likewise. * xcofflink.c (xcoff_link_add_symbols): Extend function-symbol handling to all relocations. Only set XCOFF_CALLED for function symbols. (xcoff_find_function): New function, split out from... (bfd_xcoff_export_symbol) ...here. (xcoff_set_import_path): New function, split out from... (bfd_xcoff_import_symbol): ...here. Remove assertion for old meaning of XCOFF_CALLED. (xcoff_mark_symbol): If we mark an undefined and unimported symbol, find some way of defining it. If the symbol is a function descriptor, fill in its definition automatically. If the symbol is a function, mark its descriptor and allocate room for global linkage code. Otherwise mark the symbol as implicitly imported. Move the code for creating function descriptors from... (xcoff_build_ldsyms): ...here. Use XCOFF_WAS_UNDEFINED to check for symbols that were implicitly defined. (xcoff_mark): Don't count any dynamic relocations against function symbols. (bfd_xcoff_size_dynamic_sections): Save the rtld parameter in the xcoff link info. (xcoff_link_input_bfd): Remove handling of undefined and unexported symbols. ld/ * 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 force_make_executable. ld/testsuite/ * ld-powerpc/aix-glink-1.ex, ld-powerpc/aix-glink-1.s, ld-powerpc/aix-glink-1-32.dd, ld-powerpc/aix-glink-1-64.dd, ld-powerpc/aix-glink-1-32.d, ld-powerpc/aix-glink-1-64.d: New tests. * ld-powerpc/aix52.exp: Run them. --- bfd/ChangeLog | 30 ++ bfd/coff-rs6000.c | 25 +- bfd/coff64-rs6000.c | 25 +- bfd/xcofflink.c | 446 ++++++++++++++++-------------- include/coff/ChangeLog | 6 + include/coff/xcoff.h | 10 +- ld/ChangeLog | 7 + ld/emultempl/aix.em | 6 +- ld/testsuite/ChangeLog | 7 + ld/testsuite/ld-powerpc/aix-glink-1-32.d | 5 + ld/testsuite/ld-powerpc/aix-glink-1-32.dd | 44 +++ ld/testsuite/ld-powerpc/aix-glink-1-64.d | 5 + ld/testsuite/ld-powerpc/aix-glink-1-64.dd | 49 ++++ ld/testsuite/ld-powerpc/aix-glink-1.ex | 2 + ld/testsuite/ld-powerpc/aix-glink-1.s | 21 ++ ld/testsuite/ld-powerpc/aix52.exp | 6 + 16 files changed, 463 insertions(+), 231 deletions(-) create mode 100644 ld/testsuite/ld-powerpc/aix-glink-1-32.d create mode 100644 ld/testsuite/ld-powerpc/aix-glink-1-32.dd create mode 100644 ld/testsuite/ld-powerpc/aix-glink-1-64.d create mode 100644 ld/testsuite/ld-powerpc/aix-glink-1-64.dd create mode 100644 ld/testsuite/ld-powerpc/aix-glink-1.ex create mode 100644 ld/testsuite/ld-powerpc/aix-glink-1.s diff --git a/bfd/ChangeLog b/bfd/ChangeLog index 818054c..477d2f7 100644 --- a/bfd/ChangeLog +++ b/bfd/ChangeLog @@ -1,5 +1,35 @@ 2009-03-14 Richard Sandiford + * coff-rs6000.c (xcoff_ppc_relocate_section): Report relocations + against undefined symbols if the symbol's XCOFF_WAS_UNDEFINED + flag is set. Assert that all undefined symbols are either + imported or defined by a dynamic object. + * coff64-rs6000.c (xcoff64_ppc_relocate_section): Likewise. + * xcofflink.c (xcoff_link_add_symbols): Extend function-symbol + handling to all relocations. Only set XCOFF_CALLED for function + symbols. + (xcoff_find_function): New function, split out from... + (bfd_xcoff_export_symbol) ...here. + (xcoff_set_import_path): New function, split out from... + (bfd_xcoff_import_symbol): ...here. Remove assertion for old + meaning of XCOFF_CALLED. + (xcoff_mark_symbol): If we mark an undefined and unimported + symbol, find some way of defining it. If the symbol is a function + descriptor, fill in its definition automatically. If the symbol + is a function, mark its descriptor and allocate room for global + linkage code. Otherwise mark the symbol as implicitly imported. + Move the code for creating function descriptors from... + (xcoff_build_ldsyms): ...here. Use XCOFF_WAS_UNDEFINED to + check for symbols that were implicitly defined. + (xcoff_mark): Don't count any dynamic relocations against + function symbols. + (bfd_xcoff_size_dynamic_sections): Save the rtld parameter + in the xcoff link info. + (xcoff_link_input_bfd): Remove handling of undefined and + unexported symbols. + +2009-03-14 Richard Sandiford + * coff-rs6000.c (xcoff_reloc_type_br): Make the branch absolute if the target is absolute. Fix comment typo. (xcoff_ppc_relocate_section): Remove FIXME. diff --git a/bfd/coff-rs6000.c b/bfd/coff-rs6000.c index 0a849d1..7002485 100644 --- a/bfd/coff-rs6000.c +++ b/bfd/coff-rs6000.c @@ -3447,6 +3447,17 @@ xcoff_ppc_relocate_section (output_bfd, info, input_bfd, } else { + if (info->unresolved_syms_in_objects != RM_IGNORE + && (h->flags & XCOFF_WAS_UNDEFINED) != 0) + { + if (! ((*info->callbacks->undefined_symbol) + (info, h->root.root.string, + input_bfd, input_section, + rel->r_vaddr - input_section->vma, + (info->unresolved_syms_in_objects + == RM_GENERATE_ERROR)))) + return FALSE; + } if (h->root.type == bfd_link_hash_defined || h->root.type == bfd_link_hash_defweak) { @@ -3462,17 +3473,11 @@ xcoff_ppc_relocate_section (output_bfd, info, input_bfd, + sec->output_offset); } - else if ((0 == (h->flags & (XCOFF_DEF_DYNAMIC | XCOFF_IMPORT))) - && ! info->relocatable) + else { - if (! ((*info->callbacks->undefined_symbol) - (info, h->root.root.string, input_bfd, input_section, - rel->r_vaddr - input_section->vma, TRUE))) - return FALSE; - - /* Don't try to process the reloc. It can't help, and - it may generate another error. */ - continue; + BFD_ASSERT (info->relocatable + || (h->flags & XCOFF_DEF_DYNAMIC) != 0 + || (h->flags & XCOFF_IMPORT) != 0); } } } diff --git a/bfd/coff64-rs6000.c b/bfd/coff64-rs6000.c index 71a02c2..6be1583 100644 --- a/bfd/coff64-rs6000.c +++ b/bfd/coff64-rs6000.c @@ -1293,6 +1293,17 @@ xcoff64_ppc_relocate_section (output_bfd, info, input_bfd, } else { + if (info->unresolved_syms_in_objects != RM_IGNORE + && (h->flags & XCOFF_WAS_UNDEFINED) != 0) + { + if (! ((*info->callbacks->undefined_symbol) + (info, h->root.root.string, + input_bfd, input_section, + rel->r_vaddr - input_section->vma, + (info->unresolved_syms_in_objects + == RM_GENERATE_ERROR)))) + return FALSE; + } if (h->root.type == bfd_link_hash_defined || h->root.type == bfd_link_hash_defweak) { @@ -1307,17 +1318,11 @@ xcoff64_ppc_relocate_section (output_bfd, info, input_bfd, val = (sec->output_section->vma + sec->output_offset); } - else if ((0 == (h->flags & (XCOFF_DEF_DYNAMIC | XCOFF_IMPORT))) - && ! info->relocatable) + else { - if (! ((*info->callbacks->undefined_symbol) - (info, h->root.root.string, input_bfd, input_section, - rel->r_vaddr - input_section->vma, TRUE))) - return FALSE; - - /* Don't try to process the reloc. It can't help, and - it may generate another error. */ - continue; + BFD_ASSERT (info->relocatable + || (h->flags & XCOFF_DEF_DYNAMIC) != 0 + || (h->flags & XCOFF_IMPORT) != 0); } } } diff --git a/bfd/xcofflink.c b/bfd/xcofflink.c index 0a38ac3..d651e3a 100644 --- a/bfd/xcofflink.c +++ b/bfd/xcofflink.c @@ -1845,19 +1845,16 @@ xcoff_link_add_symbols (bfd *abfd, struct bfd_link_info *info) goto error_return; } - /* We identify all symbols which are called, so that we - can create glue code for calls to functions imported - from dynamic objects. */ + /* We identify all function symbols that are the target + of a relocation, so that we can create glue code for + functions imported from dynamic objects. */ if (info->output_bfd->xvec == abfd->xvec && *rel_csect != bfd_und_section_ptr - && (rel->r_type == R_BR - || rel->r_type == R_RBR) && obj_xcoff_sym_hashes (abfd)[rel->r_symndx] != NULL) { struct xcoff_link_hash_entry *h; h = obj_xcoff_sym_hashes (abfd)[rel->r_symndx]; - h->flags |= XCOFF_CALLED; /* If the symbol name starts with a period, it is the code of a function. If the symbol is currently undefined, then add an undefined symbol @@ -1890,11 +1887,12 @@ xcoff_link_add_symbols (bfd *abfd, struct bfd_link_info *info) hds = (struct xcoff_link_hash_entry *) bh; } hds->flags |= XCOFF_DESCRIPTOR; - BFD_ASSERT ((hds->flags & XCOFF_CALLED) == 0 - && (h->flags & XCOFF_DESCRIPTOR) == 0); + BFD_ASSERT ((h->flags & XCOFF_DESCRIPTOR) == 0); hds->descriptor = h; h->descriptor = hds; } + if (h->root.root.string[0] == '.') + h->flags |= XCOFF_CALLED; } } @@ -2203,6 +2201,94 @@ _bfd_xcoff_bfd_link_add_symbols (bfd *abfd, struct bfd_link_info *info) } } +/* If symbol H has not been interpreted as a function descriptor, + see whether it should be. Set up its descriptor information if so. */ + +static bfd_boolean +xcoff_find_function (struct bfd_link_info *info, + struct xcoff_link_hash_entry *h) +{ + if ((h->flags & XCOFF_DESCRIPTOR) == 0 + && h->root.root.string[0] != '.') + { + char *fnname; + struct xcoff_link_hash_entry *hfn; + bfd_size_type amt; + + amt = strlen (h->root.root.string) + 2; + fnname = bfd_malloc (amt); + if (fnname == NULL) + return FALSE; + fnname[0] = '.'; + strcpy (fnname + 1, h->root.root.string); + hfn = xcoff_link_hash_lookup (xcoff_hash_table (info), + fnname, FALSE, FALSE, TRUE); + free (fnname); + if (hfn != NULL + && hfn->smclas == XMC_PR + && (hfn->root.type == bfd_link_hash_defined + || hfn->root.type == bfd_link_hash_defweak)) + { + h->flags |= XCOFF_DESCRIPTOR; + h->descriptor = hfn; + hfn->descriptor = h; + } + } + return TRUE; +} + +/* H is an imported symbol. Set the import module's path, file and member + to IMPATH, IMPFILE and IMPMEMBER respectively. All three are null if + no specific import module is specified. */ + +static bfd_boolean +xcoff_set_import_path (struct bfd_link_info *info, + struct xcoff_link_hash_entry *h, + const char *imppath, const char *impfile, + const char *impmember) +{ + unsigned int c; + struct xcoff_import_file **pp; + + /* We overload the ldindx field to hold the l_ifile value for this + symbol. */ + BFD_ASSERT (h->ldsym == NULL); + BFD_ASSERT ((h->flags & XCOFF_BUILT_LDSYM) == 0); + if (imppath == NULL) + h->ldindx = -1; + else + { + /* We start c at 1 because the first entry in the import list is + reserved for the library search path. */ + for (pp = &xcoff_hash_table (info)->imports, c = 1; + *pp != NULL; + pp = &(*pp)->next, ++c) + { + if (strcmp ((*pp)->path, imppath) == 0 + && strcmp ((*pp)->file, impfile) == 0 + && strcmp ((*pp)->member, impmember) == 0) + break; + } + + if (*pp == NULL) + { + struct xcoff_import_file *n; + bfd_size_type amt = sizeof (* n); + + n = bfd_alloc (info->output_bfd, amt); + if (n == NULL) + return FALSE; + n->next = NULL; + n->path = imppath; + n->file = impfile; + n->member = impmember; + *pp = n; + } + h->ldindx = c; + } + return TRUE; +} + /* Mark a symbol as not being garbage, including the section in which it is defined. */ @@ -2213,6 +2299,136 @@ xcoff_mark_symbol (struct bfd_link_info *info, struct xcoff_link_hash_entry *h) return TRUE; h->flags |= XCOFF_MARK; + + /* If we're marking an undefined symbol, try find some way of + defining it. */ + if (!info->relocatable + && (h->flags & XCOFF_IMPORT) == 0 + && (h->flags & XCOFF_DEF_REGULAR) == 0 + && (h->root.type == bfd_link_hash_undefined + || h->root.type == bfd_link_hash_undefweak)) + { + /* First check whether this symbol can be interpreted as an + undefined function descriptor for a defined function symbol. */ + if (!xcoff_find_function (info, h)) + return FALSE; + + if ((h->flags & XCOFF_DESCRIPTOR) != 0 + && (h->descriptor->root.type == bfd_link_hash_defined + || h->descriptor->root.type == bfd_link_hash_defweak)) + { + /* This is a descriptor for a defined symbol, but the input + objects have not defined the descriptor itself. Fill in + the definition automatically. + + Note that we do this even if we found a dynamic definition + of H. The local function definition logically overrides + the dynamic one. */ + asection *sec; + + sec = xcoff_hash_table (info)->descriptor_section; + h->root.type = bfd_link_hash_defined; + h->root.u.def.section = sec; + h->root.u.def.value = sec->size; + h->smclas = XMC_DS; + h->flags |= XCOFF_DEF_REGULAR; + + /* The size of the function descriptor depends on whether this + is xcoff32 (12) or xcoff64 (24). */ + sec->size += bfd_xcoff_function_descriptor_size (sec->owner); + + /* A function descriptor uses two relocs: one for the + associated code, and one for the TOC address. */ + xcoff_hash_table (info)->ldrel_count += 2; + sec->reloc_count += 2; + + /* Mark the function itself. */ + if (!xcoff_mark_symbol (info, h->descriptor)) + return FALSE; + + /* We handle writing out the contents of the descriptor in + xcoff_write_global_symbol. */ + } + else if ((h->flags & XCOFF_CALLED) != 0) + { + /* This is a function symbol for which we need to create + linkage code. */ + asection *sec; + struct xcoff_link_hash_entry *hds; + + /* Mark the descriptor (and its TOC section). */ + hds = h->descriptor; + BFD_ASSERT ((hds->root.type == bfd_link_hash_undefined + || hds->root.type == bfd_link_hash_undefweak) + && (hds->flags & XCOFF_DEF_REGULAR) == 0); + if (!xcoff_mark_symbol (info, hds)) + return FALSE; + + /* Treat this symbol as undefined if the descriptor was. */ + if ((hds->flags & XCOFF_WAS_UNDEFINED) != 0) + h->flags |= XCOFF_WAS_UNDEFINED; + + /* Allocate room for the global linkage code itself. */ + sec = xcoff_hash_table (info)->linkage_section; + h->root.type = bfd_link_hash_defined; + h->root.u.def.section = sec; + h->root.u.def.value = sec->size; + h->smclas = XMC_GL; + h->flags |= XCOFF_DEF_REGULAR; + sec->size += bfd_xcoff_glink_code_size (info->output_bfd); + + /* The global linkage code requires a TOC entry for the + descriptor. */ + if (hds->toc_section == NULL) + { + int byte_size; + + /* 32 vs 64 + xcoff32 uses 4 bytes in the toc. + xcoff64 uses 8 bytes in the toc. */ + if (bfd_xcoff_is_xcoff64 (info->output_bfd)) + byte_size = 8; + else if (bfd_xcoff_is_xcoff32 (info->output_bfd)) + byte_size = 4; + else + return FALSE; + + /* Allocate room in the fallback TOC section. */ + hds->toc_section = xcoff_hash_table (info)->toc_section; + hds->u.toc_offset = hds->toc_section->size; + hds->toc_section->size += byte_size; + if (!xcoff_mark (info, hds->toc_section)) + return FALSE; + + /* Allocate room for a static and dynamic R_TOC + relocation. */ + ++xcoff_hash_table (info)->ldrel_count; + ++hds->toc_section->reloc_count; + + /* Set the index to -2 to force this symbol to + get written out. */ + hds->indx = -2; + hds->flags |= XCOFF_SET_TOC | XCOFF_LDREL; + } + } + else if ((h->flags & XCOFF_DEF_DYNAMIC) == 0) + { + /* Record that the symbol was undefined, then import it. + -brtl links use a special fake import file. */ + h->flags |= XCOFF_WAS_UNDEFINED | XCOFF_IMPORT; + if (xcoff_hash_table (info)->rtld) + { + if (!xcoff_set_import_path (info, h, "", "..", "")) + return FALSE; + } + else + { + if (!xcoff_set_import_path (info, h, NULL, NULL, NULL)) + return FALSE; + } + } + } + if (h->root.type == bfd_link_hash_defined || h->root.type == bfd_link_hash_defweak) { @@ -2320,15 +2536,9 @@ xcoff_mark (struct bfd_link_info *info, asection *sec) || h->root.type == bfd_link_hash_defined || h->root.type == bfd_link_hash_defweak || h->root.type == bfd_link_hash_common - || ((h->flags & XCOFF_CALLED) != 0 - && (h->root.type == bfd_link_hash_undefined - || h->root.type == bfd_link_hash_undefweak) - && h->root.root.string[0] == '.' - && h->descriptor != NULL - && ((h->descriptor->flags & XCOFF_DEF_DYNAMIC) != 0 - || ((h->descriptor->flags & XCOFF_IMPORT) != 0 - && (h->descriptor->flags - & XCOFF_DEF_REGULAR) == 0)))) + /* We will always provide a local definition of + function symbols. */ + || (h->flags & XCOFF_CALLED) != 0) break; /* Fall through. */ case R_POS: @@ -2483,8 +2693,7 @@ bfd_xcoff_import_symbol (bfd *output_bfd, hds->root.u.undef.abfd = h->root.u.undef.abfd; } hds->flags |= XCOFF_DESCRIPTOR; - BFD_ASSERT ((hds->flags & XCOFF_CALLED) == 0 - && (h->flags & XCOFF_DESCRIPTOR) == 0); + BFD_ASSERT ((h->flags & XCOFF_DESCRIPTOR) == 0); hds->descriptor = h; h->descriptor = hds; } @@ -2516,46 +2725,8 @@ bfd_xcoff_import_symbol (bfd *output_bfd, h->root.u.def.value = val; } - /* We overload the ldindx field to hold the l_ifile value for this - symbol. */ - BFD_ASSERT (h->ldsym == NULL); - BFD_ASSERT ((h->flags & XCOFF_BUILT_LDSYM) == 0); - if (imppath == NULL) - h->ldindx = -1; - else - { - unsigned int c; - struct xcoff_import_file **pp; - - /* We start c at 1 because the first entry in the import list is - reserved for the library search path. */ - for (pp = &xcoff_hash_table (info)->imports, c = 1; - *pp != NULL; - pp = &(*pp)->next, ++c) - { - if (strcmp ((*pp)->path, imppath) == 0 - && strcmp ((*pp)->file, impfile) == 0 - && strcmp ((*pp)->member, impmember) == 0) - break; - } - - if (*pp == NULL) - { - struct xcoff_import_file *n; - bfd_size_type amt = sizeof (* n); - - n = bfd_alloc (output_bfd, amt); - if (n == NULL) - return FALSE; - n->next = NULL; - n->path = imppath; - n->file = impfile; - n->member = impmember; - *pp = n; - } - - h->ldindx = c; - } + if (!xcoff_set_import_path (info, h, imppath, impfile, impmember)) + return FALSE; return TRUE; } @@ -2577,34 +2748,6 @@ bfd_xcoff_export_symbol (bfd *output_bfd, /* FIXME: I'm not at all sure what syscall is supposed to mean, so I'm just going to ignore it until somebody explains it. */ - /* See if this is a function descriptor. It may be one even though - it is not so marked. */ - if ((h->flags & XCOFF_DESCRIPTOR) == 0 - && h->root.root.string[0] != '.') - { - char *fnname; - struct xcoff_link_hash_entry *hfn; - bfd_size_type amt = strlen (h->root.root.string) + 2; - - fnname = bfd_malloc (amt); - if (fnname == NULL) - return FALSE; - fnname[0] = '.'; - strcpy (fnname + 1, h->root.root.string); - hfn = xcoff_link_hash_lookup (xcoff_hash_table (info), - fnname, FALSE, FALSE, TRUE); - free (fnname); - if (hfn != NULL - && hfn->smclas == XMC_PR - && (hfn->root.type == bfd_link_hash_defined - || hfn->root.type == bfd_link_hash_defweak)) - { - h->flags |= XCOFF_DESCRIPTOR; - h->descriptor = hfn; - hfn->descriptor = h; - } - } - /* Make sure we don't garbage collect this symbol. */ if (! xcoff_mark_symbol (info, h)) return FALSE; @@ -2767,115 +2910,16 @@ xcoff_build_ldsyms (struct xcoff_link_hash_entry *h, void * p) != ldinfo->info->output_bfd->xvec))) h->flags |= XCOFF_MARK; - /* If this symbol is called and defined in a dynamic object, or it - is imported, then we need to set up global linkage code for it. - (Unless we did garbage collection and we didn't need this - symbol.) */ - if ((h->flags & XCOFF_CALLED) != 0 - && (h->root.type == bfd_link_hash_undefined - || h->root.type == bfd_link_hash_undefweak) - && h->root.root.string[0] == '.' - && h->descriptor != NULL - && ((h->descriptor->flags & XCOFF_DEF_DYNAMIC) != 0 - || ((h->descriptor->flags & XCOFF_IMPORT) != 0 - && (h->descriptor->flags & XCOFF_DEF_REGULAR) == 0)) - && (! xcoff_hash_table (ldinfo->info)->gc - || (h->flags & XCOFF_MARK) != 0)) - { - asection *sec; - struct xcoff_link_hash_entry *hds; - - sec = xcoff_hash_table (ldinfo->info)->linkage_section; - h->root.type = bfd_link_hash_defined; - h->root.u.def.section = sec; - h->root.u.def.value = sec->size; - h->smclas = XMC_GL; - h->flags |= XCOFF_DEF_REGULAR; - sec->size += bfd_xcoff_glink_code_size(ldinfo->output_bfd); - - /* The global linkage code requires a TOC entry for the - descriptor. */ - hds = h->descriptor; - BFD_ASSERT ((hds->root.type == bfd_link_hash_undefined - || hds->root.type == bfd_link_hash_undefweak) - && (hds->flags & XCOFF_DEF_REGULAR) == 0); - hds->flags |= XCOFF_MARK; - if (hds->toc_section == NULL) - { - int byte_size; - - /* 32 vs 64 - xcoff32 uses 4 bytes in the toc. - xcoff64 uses 8 bytes in the toc. */ - if (bfd_xcoff_is_xcoff64 (ldinfo->output_bfd)) - byte_size = 8; - else if (bfd_xcoff_is_xcoff32 (ldinfo->output_bfd)) - byte_size = 4; - else - return FALSE; - - hds->toc_section = xcoff_hash_table (ldinfo->info)->toc_section; - hds->u.toc_offset = hds->toc_section->size; - hds->toc_section->size += byte_size; - ++xcoff_hash_table (ldinfo->info)->ldrel_count; - ++hds->toc_section->reloc_count; - hds->indx = -2; - hds->flags |= XCOFF_SET_TOC | XCOFF_LDREL; - - /* We need to call xcoff_build_ldsyms recursively here, - because we may already have passed hds on the traversal. */ - xcoff_build_ldsyms (hds, p); - } - } - /* If this symbol is exported, but not defined, we need to try to define it. */ if ((h->flags & XCOFF_EXPORT) != 0 - && (h->flags & XCOFF_IMPORT) == 0 - && (h->flags & XCOFF_DEF_REGULAR) == 0 - && (h->flags & XCOFF_DEF_DYNAMIC) == 0 - && (h->root.type == bfd_link_hash_undefined - || h->root.type == bfd_link_hash_undefweak)) + && (h->flags & XCOFF_WAS_UNDEFINED) != 0) { - if ((h->flags & XCOFF_DESCRIPTOR) != 0 - && (h->descriptor->root.type == bfd_link_hash_defined - || h->descriptor->root.type == bfd_link_hash_defweak)) - { - asection *sec; - - /* This is an undefined function descriptor associated with - a defined entry point. We can build up a function - descriptor ourselves. Believe it or not, the AIX linker - actually does this, and there are cases where we need to - do it as well. */ - sec = xcoff_hash_table (ldinfo->info)->descriptor_section; - h->root.type = bfd_link_hash_defined; - h->root.u.def.section = sec; - h->root.u.def.value = sec->size; - h->smclas = XMC_DS; - h->flags |= XCOFF_DEF_REGULAR; - - /* The size of the function descriptor depends if this is an - xcoff32 (12) or xcoff64 (24). */ - sec->size += - bfd_xcoff_function_descriptor_size(ldinfo->output_bfd); - - /* A function descriptor uses two relocs: one for the - associated code, and one for the TOC address. */ - xcoff_hash_table (ldinfo->info)->ldrel_count += 2; - sec->reloc_count += 2; - - /* We handle writing out the contents of the descriptor in - xcoff_write_global_symbol. */ - } - else - { - (*_bfd_error_handler) - (_("warning: attempt to export undefined symbol `%s'"), - h->root.root.string); - h->ldsym = NULL; - return TRUE; - } + (*_bfd_error_handler) + (_("warning: attempt to export undefined symbol `%s'"), + h->root.root.string); + h->ldsym = NULL; + return TRUE; } /* If this is still a common symbol, and it wasn't garbage @@ -3017,6 +3061,7 @@ bfd_xcoff_size_dynamic_sections (bfd *output_bfd, xcoff_hash_table (info)->file_align = file_align; xcoff_hash_table (info)->textro = textro; + xcoff_hash_table (info)->rtld = rtld; hentry = NULL; if (entry != NULL) @@ -4318,7 +4363,6 @@ xcoff_link_input_bfd (struct xcoff_final_link_info *finfo, { struct xcoff_link_hash_entry *h = NULL; struct internal_ldrel ldrel; - bfd_boolean quiet; *rel_hash = NULL; @@ -4451,7 +4495,6 @@ xcoff_link_input_bfd (struct xcoff_final_link_info *finfo, } } - quiet = FALSE; switch (irel->r_type) { default: @@ -4507,17 +4550,7 @@ xcoff_link_input_bfd (struct xcoff_final_link_info *finfo, } else { - if (! finfo->info->relocatable - && (h->flags & XCOFF_DEF_DYNAMIC) == 0 - && (h->flags & XCOFF_IMPORT) == 0) - { - /* We already called the undefined_symbol - callback for this relocation, in - _bfd_ppc_xcoff_relocate_section. Don't - issue any more warnings. */ - quiet = TRUE; - } - if (h->ldindx < 0 && ! quiet) + if (h->ldindx < 0) { (*_bfd_error_handler) (_("%B: `%s' in loader reloc but not loader sym"), @@ -4531,8 +4564,7 @@ xcoff_link_input_bfd (struct xcoff_final_link_info *finfo, ldrel.l_rtype = (irel->r_size << 8) | irel->r_type; ldrel.l_rsecnm = o->output_section->target_index; if (xcoff_hash_table (finfo->info)->textro - && strcmp (o->output_section->name, ".text") == 0 - && ! quiet) + && strcmp (o->output_section->name, ".text") == 0) { (*_bfd_error_handler) (_("%B: loader reloc in read-only section %A"), diff --git a/include/coff/ChangeLog b/include/coff/ChangeLog index 53bf7e5..91118a1 100644 --- a/include/coff/ChangeLog +++ b/include/coff/ChangeLog @@ -1,3 +1,9 @@ +2009-03-14 Richard Sandiford + + * xcoff.h (XCOFF_CALLED, XCOFF_IMPORT): Update comments. + (XCOFF_WAS_UNDEFINED): New flag. + (xcoff_link_hash_table): Add an "rtld" field. + 2008-12-23 Johan Olmutz Nielsen * ti.h (COFF_ADJUST_SCNHDR_OUT_PRE): Define. diff --git a/include/coff/xcoff.h b/include/coff/xcoff.h index 7c1eef5..7e32d7a 100644 --- a/include/coff/xcoff.h +++ b/include/coff/xcoff.h @@ -291,11 +291,12 @@ struct xcoff_link_hash_entry #define XCOFF_LDREL 0x00000008 /* Symbol is the entry point. */ #define XCOFF_ENTRY 0x00000010 -/* Symbol is called; this is, it appears in a R_BR reloc. */ +/* Symbol is for a function and is the target of a relocation. + The relocation may or may not be a branch-type relocation. */ #define XCOFF_CALLED 0x00000020 /* Symbol needs the TOC entry filled in. */ #define XCOFF_SET_TOC 0x00000040 -/* Symbol is explicitly imported. */ +/* Symbol is implicitly or explicitly imported. */ #define XCOFF_IMPORT 0x00000080 /* Symbol is explicitly exported. */ #define XCOFF_EXPORT 0x00000100 @@ -315,6 +316,8 @@ struct xcoff_link_hash_entry #define XCOFF_SYSCALL32 0x00008000 /* Symbol is an imported 64 bit syscall. */ #define XCOFF_SYSCALL64 0x00010000 +/* Symbol was not explicitly defined by the time it was marked. */ +#define XCOFF_WAS_UNDEFINED 0x00020000 /* The XCOFF linker hash table. */ @@ -368,6 +371,9 @@ struct xcoff_link_hash_table /* Whether the .text section must be read-only. */ bfd_boolean textro; + /* Whether -brtl was specified. */ + bfd_boolean rtld; + /* Whether garbage collection was done. */ bfd_boolean gc; diff --git a/ld/ChangeLog b/ld/ChangeLog index fb3b552..40434eb 100644 --- a/ld/ChangeLog +++ b/ld/ChangeLog @@ -1,5 +1,12 @@ 2009-03-14 Richard Sandiford + * 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 + force_make_executable. + +2009-03-14 Richard Sandiford + * emultempl/aix.em (gld${EMULATION_NAME}_before_parse): Set config.dynamic_link to TRUE. diff --git a/ld/emultempl/aix.em b/ld/emultempl/aix.em index 90465f2..a9f3884 100644 --- a/ld/emultempl/aix.em +++ b/ld/emultempl/aix.em @@ -379,11 +379,13 @@ gld${EMULATION_NAME}_handle_option (int optc) break; case OPTION_ERNOTOK: - force_make_executable = FALSE; + link_info.unresolved_syms_in_objects = RM_GENERATE_ERROR; + link_info.unresolved_syms_in_shared_libs = RM_GENERATE_ERROR; break; case OPTION_EROK: - force_make_executable = TRUE; + link_info.unresolved_syms_in_objects = RM_IGNORE; + link_info.unresolved_syms_in_shared_libs = RM_IGNORE; break; case OPTION_EXPORT: diff --git a/ld/testsuite/ChangeLog b/ld/testsuite/ChangeLog index 55e3a92..bc20d02 100644 --- a/ld/testsuite/ChangeLog +++ b/ld/testsuite/ChangeLog @@ -1,5 +1,12 @@ 2009-03-14 Richard Sandiford + * ld-powerpc/aix-glink-1.ex, ld-powerpc/aix-glink-1.s, + ld-powerpc/aix-glink-1-32.dd, ld-powerpc/aix-glink-1-64.dd, + ld-powerpc/aix-glink-1-32.d, ld-powerpc/aix-glink-1-64.d: New tests. + * ld-powerpc/aix52.exp: Run them. + +2009-03-14 Richard Sandiford + * ld-powerpc/aix-abs-branch-1.im, ld-powerpc/aix-abs-branch-1.ex, ld-powerpc/aix-abs-branch-1.s, ld-powerpc/aix-abs-branch-1.dd: New test. diff --git a/ld/testsuite/ld-powerpc/aix-glink-1-32.d b/ld/testsuite/ld-powerpc/aix-glink-1-32.d new file mode 100644 index 0000000..129845f --- /dev/null +++ b/ld/testsuite/ld-powerpc/aix-glink-1-32.d @@ -0,0 +1,5 @@ +#name: Glink test 1 (error) (32-bit) +#source: aix-glink-1.s +#as: -a32 +#ld: -b32 -bM:SRE -bnogc +#error: undefined reference to `\.ext' diff --git a/ld/testsuite/ld-powerpc/aix-glink-1-32.dd b/ld/testsuite/ld-powerpc/aix-glink-1-32.dd new file mode 100644 index 0000000..33cf812 --- /dev/null +++ b/ld/testsuite/ld-powerpc/aix-glink-1-32.dd @@ -0,0 +1,44 @@ + +.* + + +Disassembly of section \.text: + +10000000 <\.f1>: +10000000: 4e 80 00 20 br + +10000004 <\.f2>: +10000004: 48 00 00 05 bl 10000008 <\.f3> + +10000008 <\.f3>: +10000008: 4e 80 00 20 br + +1000000c <\.ext>: +1000000c: 81 82 00 00 l r12,0\(r2\) +10000010: 90 41 00 14 st r2,20\(r1\) +10000014: 80 0c 00 00 l r0,0\(r12\) +10000018: 80 4c 00 04 l r2,4\(r12\) +1000001c: 7c 09 03 a6 mtctr r0 +10000020: 4e 80 04 20 bctr +10000024: 00 00 00 00 \.long 0x0 +10000028: 00 0c 80 00 \.long 0xc8000 +1000002c: 00 00 00 00 \.long 0x0 + +Disassembly of section \.data: + +20000000 : +20000000: 20 00 00 08 .* +20000004: 10 00 00 0c .* + +20000008 : +20000008: 10 00 00 00 .* +2000000c: 20 00 00 20 .* +20000010: 00 00 00 00 .* + +20000014 : +20000014: 10 00 00 04 .* +20000018: 20 00 00 20 .* +2000001c: 00 00 00 00 .* + +20000020 : + \.\.\. diff --git a/ld/testsuite/ld-powerpc/aix-glink-1-64.d b/ld/testsuite/ld-powerpc/aix-glink-1-64.d new file mode 100644 index 0000000..b8ee35f --- /dev/null +++ b/ld/testsuite/ld-powerpc/aix-glink-1-64.d @@ -0,0 +1,5 @@ +#name: Glink test 1 (error) (64-bit) +#source: aix-glink-1.s +#as: -a64 +#ld: -b64 -bM:SRE -bnogc +#error: undefined reference to `\.ext' diff --git a/ld/testsuite/ld-powerpc/aix-glink-1-64.dd b/ld/testsuite/ld-powerpc/aix-glink-1-64.dd new file mode 100644 index 0000000..b5a557c --- /dev/null +++ b/ld/testsuite/ld-powerpc/aix-glink-1-64.dd @@ -0,0 +1,49 @@ + +.* + + +Disassembly of section \.text: + +0000000010000000 <\.f1>: + 10000000: 4e 80 00 20 blr + +0000000010000004 <\.f2>: + 10000004: 48 00 00 05 bl 10000008 <\.f3> + +0000000010000008 <\.f3>: + 10000008: 4e 80 00 20 blr + +000000001000000c <\.ext>: + 1000000c: e9 82 00 00 ld r12,0\(r2\) + 10000010: f8 41 00 28 std r2,40\(r1\) + 10000014: e8 0c 00 00 ld r0,0\(r12\) + 10000018: e8 4c 00 08 ld r2,8\(r12\) + 1000001c: 7c 09 03 a6 mtctr r0 + 10000020: 4e 80 04 20 bctr + 10000024: 00 00 00 00 \.long 0x0 + 10000028: 00 0c a0 00 \.long 0xca000 + 1000002c: 00 00 00 00 \.long 0x0 + 10000030: 00 00 00 18 \.long 0x18 + +Disassembly of section \.data: + +0000000020000000 : + 20000000: 20 00 00 08 .* + 20000004: 10 00 00 0c .* + +0000000020000008 : + 20000008: 00 00 00 00 .* + 2000000c: 10 00 00 00 .* + 20000010: 00 00 00 00 .* + 20000014: 20 00 00 38 .* + \.\.\. + +0000000020000020 : + 20000020: 00 00 00 00 .* + 20000024: 10 00 00 04 .* + 20000028: 00 00 00 00 .* + 2000002c: 20 00 00 38 .* + \.\.\. + +0000000020000038 : + \.\.\. diff --git a/ld/testsuite/ld-powerpc/aix-glink-1.ex b/ld/testsuite/ld-powerpc/aix-glink-1.ex new file mode 100644 index 0000000..643cdf3 --- /dev/null +++ b/ld/testsuite/ld-powerpc/aix-glink-1.ex @@ -0,0 +1,2 @@ +f2 +foo diff --git a/ld/testsuite/ld-powerpc/aix-glink-1.s b/ld/testsuite/ld-powerpc/aix-glink-1.s new file mode 100644 index 0000000..f7901b2 --- /dev/null +++ b/ld/testsuite/ld-powerpc/aix-glink-1.s @@ -0,0 +1,21 @@ + .toc + .globl .f1 + .csect .f1[PR] +.f1: + blr + + .globl .f2 + .csect .f2[PR] +.f2: + bl .f3 + + .globl .f3 + .csect .f3[PR] +.f3: + blr + + .globl foo + .csect foo[RW] +foo: + .long f1 + .long .ext diff --git a/ld/testsuite/ld-powerpc/aix52.exp b/ld/testsuite/ld-powerpc/aix52.exp index 632d0b9..41a2045 100644 --- a/ld/testsuite/ld-powerpc/aix52.exp +++ b/ld/testsuite/ld-powerpc/aix52.exp @@ -91,6 +91,12 @@ set aix52tests { "" {aix-core-sec-3.s} {{objdump -h aix-core-sec-3.hd}} "aix-core-sec-3.so"} + + {"Glink test 1" + "-shared -bE:aix-glink-1.ex --unresolved-symbols=ignore-all" + "" {aix-glink-1.s} + {{objdump {-D -j.text -j.data} aix-glink-1-SIZE.dd}} + "aix-glink-1.so"} } foreach test $aix52tests { -- cgit v1.1