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>
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;
}
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;
}
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