]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
[Darwin, machopic 6/n] Fix for 67183
authoriains <iains@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 12 Oct 2019 19:41:50 +0000 (19:41 +0000)
committeriains <iains@138bc75d-0d04-0410-961f-82ee72b054a4>
Sat, 12 Oct 2019 19:41:50 +0000 (19:41 +0000)
When we're using the LLVM-based assembler (the default on modern Darwin)
the ordering of stubs and non-lazy symbol pointers is important.

Interleaving the output (current GCC behaviour) leads to crashes which
prevents us from building code with symbol stubs.

To resolve this, we order the output of stubs and symbol indirections:

 1. Any indirections in the data section
 2. Symbol stubs.
 3. Non-lazy symbol pointers.

At present, we still emit LTO sections after these.

gcc/ChangeLog:

2019-10-12  Iain Sandoe  <iain@sandoe.co.uk>

PR target/67183
* config/darwin.c (machopic_indirection): New field to flag
non-lazy-symbol-pointers in the data section.
(machopic_indirection_name): Compute if an indirection should
appear in the data section.
(machopic_output_data_section_indirection): New callback split
from machopic_output_indirection.
(machopic_output_stub_indirection): Likewise.
(machopic_output_indirection): Retain the code for non-lazy
symbol pointers in their regular section.
(machopic_finish): Use the new callbacks to order the indirection
output.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@276926 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/darwin.c

index 6320850a94633b27fb91db1a5b50e5f76d91fa97..161b58084a042c0ee5ce99f5a1827ecc9444fb91 100644 (file)
@@ -1,3 +1,28 @@
+2019-10-12  Iain Sandoe  <iain@sandoe.co.uk>
+
+       PR target/67183
+       * config/darwin.c (machopic_indirection): New field to flag
+       non-lazy-symbol-pointers in the data section.
+       (machopic_indirection_name): Compute if an indirection should
+       appear in the data section.
+       (machopic_output_data_section_indirection): New callback split
+       from machopic_output_indirection.
+       (machopic_output_stub_indirection): Likewise.
+       (machopic_output_indirection): Retain the code for non-lazy
+       symbol pointers in their regular section.
+       (machopic_finish): Use the new callbacks to order the indirection
+       output.
+
+2019-10-12  Iain Sandoe  <iain@sandoe.co.uk>
+
+       * config/darwin-protos.h (machopic_finish): Delete.
+       * config/darwin.c (machopic_finish): Make static.
+
+2019-10-12  Iain Sandoe  <iain@sandoe.co.uk>
+
+       * config/darwin.c (darwin_file_end): Only emit empty CTOR/DTOR
+       sections when building kernel extension code.
+
 2019-10-12  Palmer Dabbelt  <palmer@sifive.com>
 
        * doc/extend.texi (Alternate Keywords): Change "-std=c11" to "a
index 8efb14ebdb9d31bc8acfee74614058733584dd95..f6543fc99764a1061010c32a0f711a2b6f2307a0 100644 (file)
@@ -454,6 +454,13 @@ typedef struct GTY ((for_user)) machopic_indirection
   bool stub_p;
   /* True iff this stub or pointer has been referenced.  */
   bool used;
+  /* True iff a non-lazy symbol pointer should be emitted into the .data
+     section, rather than the non-lazy symbol pointers section.  The cases
+     for which this occurred seem to have been unintentional, and later
+     toolchains emit all of the indirections to the 'usual' section.  We
+     are keeping this in case it is necessary to preserve compatibility with
+     older toolchains.  */
+  bool nlsp_in_data_section;
 } machopic_indirection;
 
 struct indirection_hasher : ggc_ptr_hash<machopic_indirection>
@@ -590,6 +597,18 @@ machopic_indirection_name (rtx sym_ref, bool stub_p)
       p->ptr_name = xstrdup (buffer);
       p->stub_p = stub_p;
       p->used = false;
+      /* Here we are undoing a number of causes that placed some indirections
+        (apparently erroneously) into the .data section.  Specifically, some
+        symbols that are ABI mandated indirections and some hidden symbols
+        were being placed there - which cause difficulties with later
+        versions of ld64.
+      */
+      p->nlsp_in_data_section =
+          ! MACHO_SYMBOL_MUST_INDIRECT_P (sym_ref)
+       && ! MACHO_SYMBOL_HIDDEN_VIS_P (sym_ref)
+       && (machopic_symbol_defined_p (sym_ref)
+           || SYMBOL_REF_LOCAL_P (sym_ref))
+       && ! indirect_data (sym_ref);
       *slot = p;
     }
 
@@ -1069,121 +1088,140 @@ machopic_legitimize_pic_address (rtx orig, machine_mode mode, rtx reg)
   return pic_ref;
 }
 
-/* Output the stub or non-lazy pointer in *SLOT, if it has been used.
-   DATA is the FILE* for assembly output.  Called from
-   htab_traverse.  */
+/* Callbacks to output the stub or non-lazy pointers.
+   Each works on the item in *SLOT,if it has been used.
+   DATA is the FILE* for assembly output.
+   Called from htab_traverses, invoked from machopic_finish().  */
 
 int
-machopic_output_indirection (machopic_indirection **slot, FILE *asm_out_file)
+machopic_output_data_section_indirection (machopic_indirection **slot,
+                                         FILE *asm_out_file)
 {
   machopic_indirection *p = *slot;
-  rtx symbol;
-  const char *sym_name;
-  const char *ptr_name;
 
-  if (!p->used)
+  if (!p->used || !p->nlsp_in_data_section)
     return 1;
 
-  symbol = p->symbol;
-  sym_name = XSTR (symbol, 0);
-  ptr_name = p->ptr_name;
+  rtx symbol = p->symbol;
+  /* The original symbol name.  */
+  const char *sym_name = XSTR (symbol, 0);
+  /* The name of the indirection symbol.  */
+  const char *ptr_name = p->ptr_name;
 
-  if (p->stub_p)
-    {
-      char *sym;
-      char *stub;
-      tree id;
+  switch_to_section (data_section);
+  assemble_align (GET_MODE_ALIGNMENT (Pmode));
+  assemble_label (asm_out_file, ptr_name);
+  assemble_integer (gen_rtx_SYMBOL_REF (Pmode, sym_name),
+                   GET_MODE_SIZE (Pmode),
+                   GET_MODE_ALIGNMENT (Pmode), 1);
 
-      id = maybe_get_identifier (sym_name);
-      if (id)
-       {
-         tree id_orig = id;
+  return 1;
+}
 
-         while (IDENTIFIER_TRANSPARENT_ALIAS (id))
-           id = TREE_CHAIN (id);
-         if (id != id_orig)
-           sym_name = IDENTIFIER_POINTER (id);
-       }
+int
+machopic_output_stub_indirection (machopic_indirection **slot,
+                                 FILE *asm_out_file)
+{
+  machopic_indirection *p = *slot;
 
-      sym = XALLOCAVEC (char, strlen (sym_name) + 2);
-      if (sym_name[0] == '*' || sym_name[0] == '&')
-       strcpy (sym, sym_name + 1);
-      else if (sym_name[0] == '-' || sym_name[0] == '+')
-       strcpy (sym, sym_name);
-      else
-       sprintf (sym, "%s%s", user_label_prefix, sym_name);
+  if (!p->used || !p->stub_p)
+    return 1;
 
-      stub = XALLOCAVEC (char, strlen (ptr_name) + 2);
-      if (ptr_name[0] == '*' || ptr_name[0] == '&')
-       strcpy (stub, ptr_name + 1);
-      else
-       sprintf (stub, "%s%s", user_label_prefix, ptr_name);
+  rtx symbol = p->symbol;
+  /* The original symbol name.  */
+  const char *sym_name = XSTR (symbol, 0);
+  /* The name of the stub symbol.  */
+  const char *ptr_name = p->ptr_name;
 
-      machopic_output_stub (asm_out_file, sym, stub);
-    }
-  else if (! indirect_data (symbol)
-          && ! MACHO_SYMBOL_MUST_INDIRECT_P (symbol)
-          && ! MACHO_SYMBOL_HIDDEN_VIS_P (symbol)
-          && (machopic_symbol_defined_p (symbol)
-              || SYMBOL_REF_LOCAL_P (symbol)))
+  tree id = maybe_get_identifier (sym_name);
+  if (id)
     {
-      switch_to_section (data_section);
-      assemble_align (GET_MODE_ALIGNMENT (Pmode));
-      assemble_label (asm_out_file, ptr_name);
-      assemble_integer (gen_rtx_SYMBOL_REF (Pmode, sym_name),
-                       GET_MODE_SIZE (Pmode),
-                       GET_MODE_ALIGNMENT (Pmode), 1);
+      tree id_orig = id;
+
+      while (IDENTIFIER_TRANSPARENT_ALIAS (id))
+       id = TREE_CHAIN (id);
+      if (id != id_orig)
+       sym_name = IDENTIFIER_POINTER (id);
     }
+
+  char *sym = XALLOCAVEC (char, strlen (sym_name) + 2);
+  if (sym_name[0] == '*' || sym_name[0] == '&')
+    strcpy (sym, sym_name + 1);
+  else if (sym_name[0] == '-' || sym_name[0] == '+')
+    strcpy (sym, sym_name);
   else
-    {
-      rtx init = const0_rtx;
+    sprintf (sym, "%s%s", user_label_prefix, sym_name);
+
+  char *stub = XALLOCAVEC (char, strlen (ptr_name) + 2);
+  if (ptr_name[0] == '*' || ptr_name[0] == '&')
+    strcpy (stub, ptr_name + 1);
+  else
+    sprintf (stub, "%s%s", user_label_prefix, ptr_name);
+
+  machopic_output_stub (asm_out_file, sym, stub);
+
+  return 1;
+}
+
+int
+machopic_output_indirection (machopic_indirection **slot, FILE *asm_out_file)
+{
+  machopic_indirection *p = *slot;
+
+  if (!p->used || p->stub_p || p->nlsp_in_data_section)
+    return 1;
+
+  rtx symbol = p->symbol;
+  /* The original symbol name.  */
+  const char *sym_name = XSTR (symbol, 0);
+  /* The nonlazy-stub symbol name.  */
+  const char *ptr_name = p->ptr_name;
 
-      switch_to_section (darwin_sections[machopic_nl_symbol_ptr_section]);
+  switch_to_section (darwin_sections[machopic_nl_symbol_ptr_section]);
 
-      /* Mach-O symbols are passed around in code through indirect
-        references and the original symbol_ref hasn't passed through
-        the generic handling and reference-catching in
-        output_operand, so we need to manually mark weak references
-        as such.  */
-      if (SYMBOL_REF_WEAK (symbol))
+  /* Mach-O symbols are passed around in code through indirect references and
+     the original symbol_ref hasn't passed through the generic handling and
+     reference-catching in output_operand, so we need to manually mark weak
+     references as such.  */
+
+  if (SYMBOL_REF_WEAK (symbol))
+    {
+      tree decl = SYMBOL_REF_DECL (symbol);
+      gcc_checking_assert (DECL_P (decl));
+
+      if (decl != NULL_TREE
+         && DECL_EXTERNAL (decl) && TREE_PUBLIC (decl)
+         /* Handle only actual external-only definitions, not
+            e.g. extern inline code or variables for which
+            storage has been allocated.  */
+         && !TREE_STATIC (decl))
        {
-         tree decl = SYMBOL_REF_DECL (symbol);
-         gcc_assert (DECL_P (decl));
-
-         if (decl != NULL_TREE
-             && DECL_EXTERNAL (decl) && TREE_PUBLIC (decl)
-             /* Handle only actual external-only definitions, not
-                e.g. extern inline code or variables for which
-                storage has been allocated.  */
-             && !TREE_STATIC (decl))
-           {
-             fputs ("\t.weak_reference ", asm_out_file);
-             assemble_name (asm_out_file, sym_name);
-             fputc ('\n', asm_out_file);
-           }
+         fputs ("\t.weak_reference ", asm_out_file);
+         assemble_name (asm_out_file, sym_name);
+         fputc ('\n', asm_out_file);
        }
+    }
 
-      assemble_name (asm_out_file, ptr_name);
-      fprintf (asm_out_file, ":\n");
+  assemble_name (asm_out_file, ptr_name);
+  fprintf (asm_out_file, ":\n");
 
-      fprintf (asm_out_file, "\t.indirect_symbol ");
-      assemble_name (asm_out_file, sym_name);
-      fprintf (asm_out_file, "\n");
+  fprintf (asm_out_file, "\t.indirect_symbol ");
+  assemble_name (asm_out_file, sym_name);
+  fprintf (asm_out_file, "\n");
 
-      /* Variables that are marked with MACHO_SYMBOL_FLAG_STATIC need to
-        have their symbol name instead of 0 in the second entry of
-        the non-lazy symbol pointer data structure when they are
-        defined.  This allows the runtime to rebind newer instances
-        of the translation unit with the original instance of the
-        symbol.  */
+  /* Variables that are marked with MACHO_SYMBOL_FLAG_STATIC need to
+     have their symbol name instead of 0 in the second entry of
+     the non-lazy symbol pointer data structure when they are
+     defined.  This allows the runtime to rebind newer instances
+     of the translation unit with the original instance of the
+     symbol.  */
 
-      if (MACHO_SYMBOL_STATIC_P (symbol)
-         && machopic_symbol_defined_p (symbol))
-       init = gen_rtx_SYMBOL_REF (Pmode, sym_name);
+  rtx init = const0_rtx;
+  if (MACHO_SYMBOL_STATIC_P (symbol) && machopic_symbol_defined_p (symbol))
+    init = gen_rtx_SYMBOL_REF (Pmode, sym_name);
 
-      assemble_integer (init, GET_MODE_SIZE (Pmode),
-                       GET_MODE_ALIGNMENT (Pmode), 1);
-    }
+  assemble_integer (init, GET_MODE_SIZE (Pmode),
+                   GET_MODE_ALIGNMENT (Pmode), 1);
 
   return 1;
 }
@@ -1191,9 +1229,19 @@ machopic_output_indirection (machopic_indirection **slot, FILE *asm_out_file)
 static void
 machopic_finish (FILE *asm_out_file)
 {
-  if (machopic_indirections)
-    machopic_indirections
-      ->traverse_noresize<FILE *, machopic_output_indirection> (asm_out_file);
+  if (!machopic_indirections)
+    return;
+
+  /* First output an symbol indirections that have been placed into .data
+     (we don't expect these now).  */
+  machopic_indirections->traverse_noresize
+    <FILE *, machopic_output_data_section_indirection> (asm_out_file);
+
+  machopic_indirections->traverse_noresize
+    <FILE *, machopic_output_stub_indirection> (asm_out_file);
+
+  machopic_indirections->traverse_noresize
+    <FILE *, machopic_output_indirection> (asm_out_file);
 }
 
 int