]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commitdiff
gas/ELF: restrict visibility changes
authorJan Beulich <jbeulich@suse.com>
Fri, 8 May 2026 09:44:09 +0000 (11:44 +0200)
committerJan Beulich <jbeulich@suse.com>
Fri, 8 May 2026 09:44:09 +0000 (11:44 +0200)
Since the spec mandates that the most restricting visibility ought to
propagate when linking, the same rule should apply when assembling.

gas/config/obj-elf.c
gas/testsuite/gas/elf/elf.exp
gas/testsuite/gas/elf/pseudo.l
gas/testsuite/gas/elf/visibility.d [new file with mode: 0644]
gas/testsuite/gas/elf/visibility.l [new file with mode: 0644]
gas/testsuite/gas/elf/visibility.s [new file with mode: 0644]

index f884e577554a611de50ac84f0dc5e72c43aa7b39..062169064200630d8320ee8f838d2d02c8ef736d 100644 (file)
@@ -404,21 +404,24 @@ static void
 obj_elf_visibility (int visibility)
 {
   int c;
-  symbolS *symbolP;
-  asymbol *bfdsym;
-  elf_symbol_type *elfsym;
 
   do
     {
-      symbolP = get_sym_from_input_line_and_check ();
-
-      bfdsym = symbol_get_bfdsym (symbolP);
-      elfsym = elf_symbol_from (bfdsym);
+      symbolS *symbolP = get_sym_from_input_line_and_check ();
+      const asymbol *bfdsym = symbol_get_bfdsym (symbolP);
+      elf_symbol_type *elfsym = elf_symbol_from (bfdsym);
+      int current = ELF_ST_VISIBILITY (elfsym->internal_elf_sym.st_other);
 
       gas_assert (elfsym);
 
-      elfsym->internal_elf_sym.st_other &= ~3;
-      elfsym->internal_elf_sym.st_other |= visibility;
+      if (!current || visibility <= current)
+       {
+         elfsym->internal_elf_sym.st_other &= ~ELF_ST_VISIBILITY (~0);
+         elfsym->internal_elf_sym.st_other |= visibility;
+       }
+      else
+       as_warn (_("visibility of `%s' is already `%s'"), S_GET_NAME (symbolP),
+                current == STV_HIDDEN ? "hidden" : "internal");
 
       c = *input_line_pointer;
       if (c == ',')
index cf983057bf6b75f0cce3c013d1bd6564f2b5d901..2232e2d58d9986146b52bf36684d9be3ef70e588 100644 (file)
@@ -237,6 +237,7 @@ if { [is_elf_format] } then {
        # The alpha port uses .set for state, e.g. nomacro.
        run_dump_test "symtab"
     }
+    run_dump_test "visibility"
     run_dump_test "symver"
     run_dump_test "pr21661"
     run_dump_test "pr14891"
index 605f5b889b585728780854e880e7576978cc664a..667d6205d49467cb660ecb5750ed7363861ea25b 100644 (file)
@@ -4,6 +4,7 @@
 [^:]*:6: Error: Missing symbol name in directive
 [^:]*:8: Error: Missing symbol name in directive
 [^:]*:10: Error: Missing symbol name in directive
+[^:]*:10: Warning: visibility of .* is already .internal.
 [^:]*:12: Error: Missing symbol name in directive
 [^:]*:14: Error: Missing symbol name in directive
 [^:]*:14: Error: expected comma after name in .symver
diff --git a/gas/testsuite/gas/elf/visibility.d b/gas/testsuite/gas/elf/visibility.d
new file mode 100644 (file)
index 0000000..89c977d
--- /dev/null
@@ -0,0 +1,12 @@
+#name: diagnostics for visibility directives
+#readelf: -s -W
+#warning_output: visibility.l
+#target: [supports_gnu_unique]
+
+#...
+ +[0-9]+: +0+ +0 +(NOTYPE|OBJECT) +GLOBAL +INTERNAL +[1-9] +gd
+ +[0-9]+: +0+1 +0 +(NOTYPE|OBJECT) +WEAK +INTERNAL +[1-9] +wd
+ +[0-9]+: +0+2 +0 +OBJECT +UNIQUE +HIDDEN +[1-9] +gu
+ +[0-9]+: +0+ +0 +(NOTYPE|OBJECT) +GLOBAL +INTERNAL +UND +ge
+ +[0-9]+: +0+ +0 +(NOTYPE|OBJECT) +WEAK +HIDDEN +UND +we
+#pass
diff --git a/gas/testsuite/gas/elf/visibility.l b/gas/testsuite/gas/elf/visibility.l
new file mode 100644 (file)
index 0000000..db2f858
--- /dev/null
@@ -0,0 +1,5 @@
+[^:]*: Assembler messages:
+[^:]*:4: Warning: visibility of .gd. is already .internal.
+[^:]*:5: Warning: visibility of .gd. is already .internal.
+[^:]*:21: Warning: visibility of .ge. is already .hidden.
+[^:]*:26: Warning: visibility of .we. is already .hidden.
diff --git a/gas/testsuite/gas/elf/visibility.s b/gas/testsuite/gas/elf/visibility.s
new file mode 100644 (file)
index 0000000..01ced4a
--- /dev/null
@@ -0,0 +1,28 @@
+       .data
+       .global gd
+       .internal gd
+       .hidden gd
+       .protected gd
+gd:    .dc.b 0
+
+       .weak wd
+       .protected wd
+       .hidden wd
+       .internal wd
+wd:    .dc.b 0
+
+       .type gu, %gnu_unique_object
+       .hidden gu
+       .hidden gu
+gu:    .dc.b 0
+
+       .global ge
+       .hidden ge
+       .protected ge
+       .internal ge
+
+       .weak we
+       .hidden we
+       .protected we
+       .p2align 3
+       .dc.a we