This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH v2] gas/ELF: don't accumulate .type settings


Recently a patch was submitted for a Xen Project test harness binary to
override the compiler specified @object to @func (see [1]). In a reply I
suggested we shouldn't make ourselves dependent on currently unspecified
behavior of gas here: It accumulates all requests, and then
bfd/elf.c:swap_out_syms(), in an apparently ad hoc manner, prioritizes
certain flags over others.

Make the behavior predictable: Generally the last .type is what counts.
Exceptions are directives which set multiple bits (TLS, IFUNC, and
UNIQUE): Subsequent directives requesting just the more generic bit
(i.e. FUNC following IFUNC) won't clear the more specific one.  Warn
about incompatible changes, except from/to STT_NOTYPE.

Also add a new target hook, which hppa wants to use right away afaict.

In the course of adding the warning I ran into two ld testsuite
failures.  I can only assume that it was a copy-and-paste mistake that
lead to the same symbol having its type set twice.

[1] https://lists.xenproject.org/archives/html/xen-devel/2019-05/msg01980.html

gas/
2019-07-03  Jan Beulich  <jbeulich@suse.com>

	* config/obj-elf.c (obj_elf_type): Check for conflicts between
	old and new types.
	* config/tc-hppa.h (md_elf_symbol_type_change): New.
	* doc/as.texi: Mention warning behavior for the ELF flavor of
	.type.
	* testsuite/gas/elf/type-2.e, testsuite/gas/elf/type-2.l,
	testsuite/gas/elf/type-2.s: New.
	* testsuite/gas/elf/elf.exp: Run new test.

ld/
2019-07-03  Jan Beulich  <jbeulich@suse.com>

	* testsuite/ld-elf/group9.s: Correct argument of .type.

--- a/gas/config/obj-elf.c
+++ b/gas/config/obj-elf.c
@@ -2069,7 +2069,38 @@ obj_elf_type (int ignore ATTRIBUTE_UNUSE
    if (*input_line_pointer == '"')
      ++input_line_pointer;
  
-  elfsym->symbol.flags |= type;
+#ifdef md_elf_symbol_type_change
+  if (!md_elf_symbol_type_change (sym, elfsym, type))
+#endif
+    {
+      flagword mask = BSF_FUNCTION | BSF_OBJECT;
+
+      if (type != BSF_FUNCTION)
+	mask |= BSF_GNU_INDIRECT_FUNCTION;
+      if (type != BSF_OBJECT)
+	{
+	  mask |= BSF_GNU_UNIQUE | BSF_THREAD_LOCAL;
+
+	  if (S_IS_COMMON (sym))
+	    {
+	      as_bad (_("cannot change type of common symbol '%s'"),
+		      S_GET_NAME (sym));
+	      mask = type = 0;
+	    }
+	}
+
+      /* Don't warn when changing to STT_NOTYPE.  */
+      if (type)
+	{
+	  flagword new = (elfsym->symbol.flags & ~mask) | type;
+
+	  if (new != (elfsym->symbol.flags | type))
+	    as_warn (_("symbol '%s' already has its type set"), S_GET_NAME (sym));
+	  elfsym->symbol.flags = new;
+	}
+      else
+	elfsym->symbol.flags &= ~mask;
+    }
  
    demand_empty_rest_of_line ();
  }
--- a/gas/config/tc-hppa.h
+++ b/gas/config/tc-hppa.h
@@ -177,6 +177,14 @@ int hppa_fix_adjustable (struct fix *);
         ), BSF_FUNCTION)							\
     : -1)
  
+/* Handle type change from .type pseudo: Zap STT_PARISC_MILLI when
+   switching to a non-function type.  */
+#define md_elf_symbol_type_change(sym, elf, type)			\
+  ((type) != BSF_FUNCTION						\
+   && (((elf)->internal_elf_sym.st_info = 				\
+	ELF_ST_INFO (ELF_ST_BIND ((elf)->internal_elf_sym.st_info),	\
+		     STT_NOTYPE)), 0))
+
  #define tc_frob_symbol(sym,punt) \
    { \
      if ((S_GET_SEGMENT (sym) == bfd_und_section_ptr \
--- a/gas/doc/as.texi
+++ b/gas/doc/as.texi
@@ -7215,6 +7215,10 @@ systems).
  
  @end table
  
+Changing between incompatible types other than from/to STT_NOTYPE will
+result in a diagnostic.  An intermediate change to STT_NOTYPE will silence
+this.
+
  Note: Some targets support extra types in addition to those listed above.
  
  @end ifset
--- a/gas/testsuite/gas/elf/elf.exp
+++ b/gas/testsuite/gas/elf/elf.exp
@@ -230,6 +230,7 @@ if { [is_elf_format] } then {
      } else {
  	run_dump_test ifunc-1
  	run_elf_list_test "type" "" "" "-s" "| grep \"1 *\\\[FIONTCU\\\]\""
+	run_elf_list_test "type-2" "" "--warn" "-s" "| grep \"0 *\\\[FIONT\\\]\""
      }
  
      run_dump_test "section6"
--- /dev/null
+++ b/gas/testsuite/gas/elf/type-2.e
@@ -0,0 +1,10 @@
+ +.+: 0+0 +0 +NOTYPE +LOCAL +DEFAULT +UND *
+ +.+: 0+0 +0 +OBJECT +LOCAL +DEFAULT +. test1
+ +.+: 0+1 +0 +FUNC +LOCAL +DEFAULT +. test2
+ +.+: 0+2 +0 +NOTYPE +LOCAL +DEFAULT +. test3
+ +.+: 0+3 +0 +NOTYPE +LOCAL +DEFAULT +. test4
+ +.+: 0+4 +0 +NOTYPE +LOCAL +DEFAULT +. test5
+ +.+: 0+5 +0 +NOTYPE +LOCAL +DEFAULT +. test6
+ +.+: 0+6 +0 +OBJECT +LOCAL +DEFAULT +. test7
+ +.+: 0+7 +0 +TLS +LOCAL +DEFAULT +. test8
+ +.+: 0+8 +0 +IFUNC +LOCAL +DEFAULT +. test9
--- /dev/null
+++ b/gas/testsuite/gas/elf/type-2.l
@@ -0,0 +1,3 @@
+.*: Assembler messages:
+.*:4: Warning: .*
+.*:9: Warning: .*
--- /dev/null
+++ b/gas/testsuite/gas/elf/type-2.s
@@ -0,0 +1,49 @@
+	.text
+
+	.type	test1,%function
+	.type	test1,%object
+test1:
+	.byte	0x0
+
+	.type	test2,%object
+	.type	test2,%function
+test2:
+	.byte	0x0
+
+	.type	test3,%object
+	.type	test3,%notype
+test3:
+	.byte	0x0
+
+	.type	test4,%function
+	.type	test4,%notype
+test4:
+	.byte	0x0
+
+	.type	test5,%tls_object
+	.type	test5,%notype
+test5:
+	.byte	0x0
+
+	.type	test6,%gnu_indirect_function
+	.type	test6,%notype
+test6:
+	.byte	0x0
+
+	.type	test7,%function
+	.type	test7,%notype
+	.type	test7,%object
+test7:
+	.byte	0x0
+
+	.type	test8,%object
+	.type	test8,%tls_object
+	.type	test8,%object
+test8:
+	.byte	0x0
+
+	.type	test9,%function
+	.type	test9,%gnu_indirect_function
+	.type	test9,%function
+test9:
+	.byte	0x0
--- a/ld/testsuite/ld-elf/group9.s
+++ b/ld/testsuite/ld-elf/group9.s
@@ -5,7 +5,7 @@ foo:
  	.byte 0
  	.section	.data.foo,"axG",%progbits,foo,comdat
  	.globl foo.data
-	.type	foo,%object
+	.type	foo.data,%object
  foo.data:
  	.byte 0
  	.section	.text.bar,"axG",%progbits,bar,comdat

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]