From: Iain Sandoe Date: Sat, 12 Oct 2019 19:41:50 +0000 (+0000) Subject: [Darwin, machopic 6/n] Fix for 67183 X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=c89d7d19a2aa333684e5bf744ae3b813c6054d63;p=gcc.git [Darwin, machopic 6/n] Fix for 67183 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 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: r276926 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6320850a946..161b58084a0 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,28 @@ +2019-10-12 Iain Sandoe + + 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 + + * config/darwin-protos.h (machopic_finish): Delete. + * config/darwin.c (machopic_finish): Make static. + +2019-10-12 Iain Sandoe + + * config/darwin.c (darwin_file_end): Only emit empty CTOR/DTOR + sections when building kernel extension code. + 2019-10-12 Palmer Dabbelt * doc/extend.texi (Alternate Keywords): Change "-std=c11" to "a diff --git a/gcc/config/darwin.c b/gcc/config/darwin.c index 8efb14ebdb9..f6543fc9976 100644 --- a/gcc/config/darwin.c +++ b/gcc/config/darwin.c @@ -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 @@ -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 (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 + (asm_out_file); + + machopic_indirections->traverse_noresize + (asm_out_file); + + machopic_indirections->traverse_noresize + (asm_out_file); } int