aboutsummaryrefslogtreecommitdiff
path: root/bfd/xcofflink.c
diff options
context:
space:
mode:
authorClément Chigot <clement.chigot@atos.net>2021-11-23 15:45:28 +0100
committerClément Chigot <clement.chigot@atos.net>2022-01-12 09:08:25 +0100
commita8bc481f352d61bb2962e983a1c1c1fdad0230b7 (patch)
tree0571c01cecab210414116d89f49e005de17a0404 /bfd/xcofflink.c
parent59e31fd742a53e8404039e1c4be4ba192672287c (diff)
downloadbinutils-a8bc481f352d61bb2962e983a1c1c1fdad0230b7.zip
binutils-a8bc481f352d61bb2962e983a1c1c1fdad0230b7.tar.gz
binutils-a8bc481f352d61bb2962e983a1c1c1fdad0230b7.tar.bz2
ld: add hidden and internal visibility support for XCOFF
This patch adds a primary support for hidden and internal visibility in GNU linker for XCOFF format. The protected visibility isn't yet supported. PR 22085 bfd/ChangeLog: * xcofflink.c (xcoff_dynamic_definition_p): Add hidden and internal visibility support. (xcoff_link_add_symbols): Likewise. (xcoff_auto_export_p): Likewise. (bfd_xcoff_export_symbol): Likewise. (xcoff_link_input_bfd): Likewise. ld/ChangeLog: * testsuite/ld-vsb/main.c: Adapt for XCOFF. * testsuite/ld-vsb/sh1.c: Likewse. * testsuite/ld-vsb/vsb.exp: Likewise. * testsuite/ld-vsb/visibility-1-xcoff-32.d: New test. * testsuite/ld-vsb/visibility-1-xcoff-64.d: New test. * testsuite/ld-vsb/visibility-2-xcoff-32.d: New test. * testsuite/ld-vsb/visibility-2-xcoff-64.d: New test. * testsuite/ld-vsb/xcoffvsb.dat: New test.
Diffstat (limited to 'bfd/xcofflink.c')
-rw-r--r--bfd/xcofflink.c50
1 files changed, 48 insertions, 2 deletions
diff --git a/bfd/xcofflink.c b/bfd/xcofflink.c
index ba07ba7..6e99472 100644
--- a/bfd/xcofflink.c
+++ b/bfd/xcofflink.c
@@ -798,10 +798,14 @@ xcoff_dynamic_definition_p (struct xcoff_link_hash_entry *h,
|| h->root.type == bfd_link_hash_undefweak))
return true;
- /* If H is currently undefined, LDSYM defines it. */
+ /* If H is currently undefined, LDSYM defines it.
+ However, if H has a hidden visibility, LDSYM must not
+ define it. */
if ((h->flags & XCOFF_DEF_DYNAMIC) == 0
&& (h->root.type == bfd_link_hash_undefined
- || h->root.type == bfd_link_hash_undefweak))
+ || h->root.type == bfd_link_hash_undefweak)
+ && (h->visibility != SYM_V_HIDDEN
+ && h->visibility != SYM_V_INTERNAL))
return true;
return false;
@@ -1243,6 +1247,7 @@ xcoff_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
bfd_byte *linenos;
} *reloc_info = NULL;
bfd_size_type amt;
+ unsigned short visibility;
keep_syms = obj_coff_keep_syms (abfd);
@@ -1480,6 +1485,9 @@ xcoff_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
}
}
+ /* Record visibility. */
+ visibility = sym.n_type & SYM_V_MASK;
+
/* Pick up the csect auxiliary information. */
if (sym.n_numaux == 0)
{
@@ -2058,6 +2066,22 @@ xcoff_link_add_symbols (bfd *abfd, struct bfd_link_info *info)
/* Try not to give this error too many times. */
(*sym_hash)->flags &= ~XCOFF_MULTIPLY_DEFINED;
}
+
+
+ /* If the symbol is hidden or internal, completely undo
+ any dynamic link state. */
+ if ((*sym_hash)->flags & XCOFF_DEF_DYNAMIC
+ && (visibility == SYM_V_HIDDEN
+ || visibility == SYM_V_INTERNAL))
+ (*sym_hash)->flags &= ~XCOFF_DEF_DYNAMIC;
+ else
+ {
+ /* Keep the most constraining visibility. */
+ unsigned short hvis = (*sym_hash)->visibility;
+ if (visibility && ( !hvis || visibility < hvis))
+ (*sym_hash)->visibility = visibility;
+ }
+
}
/* _bfd_generic_link_add_one_symbol may call the linker to
@@ -2650,6 +2674,11 @@ xcoff_auto_export_p (struct bfd_link_info *info,
if (h->root.root.string[0] == '.')
return false;
+ /* Don't export hidden or internal symbols. */
+ if (h->visibility == SYM_V_HIDDEN
+ || h->visibility == SYM_V_INTERNAL)
+ 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
@@ -3248,6 +3277,19 @@ bfd_xcoff_export_symbol (bfd *output_bfd,
if (bfd_get_flavour (output_bfd) != bfd_target_xcoff_flavour)
return true;
+ /* As AIX linker, symbols exported with hidden visibility are
+ silently ignored. */
+ if (h->visibility == SYM_V_HIDDEN)
+ return true;
+
+ if (h->visibility == SYM_V_INTERNAL)
+ {
+ _bfd_error_handler (_("%pB: cannot export internal symbol `%s`."),
+ output_bfd, h->root.root.string);
+ bfd_set_error (bfd_error_bad_value);
+ return false;
+ }
+
h->flags |= XCOFF_EXPORT;
/* FIXME: I'm not at all sure what syscall is supposed to mean, so
@@ -4572,6 +4614,10 @@ xcoff_link_input_bfd (struct xcoff_final_link_info *flinfo,
- (*csectpp)->vma);
}
+ /* Update visibility. */
+ isym.n_type &= ~SYM_V_MASK;
+ isym.n_type |= (*sym_hash)->visibility;
+
/* Output the symbol. */
bfd_coff_swap_sym_out (output_bfd, (void *) &isym, (void *) outsym);