]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
[Darwin, machopic] Fix for 67183
authorIain Sandoe <iain@sandoe.co.uk>
Tue, 29 Oct 2019 20:16:28 +0000 (20:16 +0000)
committerIain Sandoe <iains@gcc.gnu.org>
Tue, 29 Oct 2019 20:16:28 +0000 (20:16 +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.

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

Backport from mainline
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.

From-SVN: r277587

gcc/ChangeLog
gcc/config/darwin.c

index 899f4dbda6332b394bfce5981e88575e0dd8f4ac..c0fd65a3365434726c59105c66a6ab48f648583e 100644 (file)
@@ -1,3 +1,21 @@
+2019-10-29  Iain Sandoe  <iain@sandoe.co.uk>
+
+       Backport from mainline
+       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-29  Iain Sandoe  <iain@sandoe.co.uk>
 
        Backport from mainline
index e6a424449a62d3d3ad6326c960ee50aade204b04..541f45894650284b1bafc46310ee72ac9b75cbdd 100644 (file)
@@ -451,6 +451,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>
@@ -587,6 +594,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;
     }
 
@@ -1073,121 +1092,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;
 }
@@ -1195,9 +1233,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