diff options
-rw-r--r-- | gcc/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/config/darwin.c | 37 | ||||
-rw-r--r-- | gcc/config/darwin.h | 9 |
3 files changed, 49 insertions, 5 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 80124c2..450086e 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2016-11-27 Iain Sandoe <iain@codesourcery.com> + + PR target/71767 + * config/darwin.c (imachopic_indirection_name): Make data + section indirections linker-visible. + * config/darwin.h (ASM_GENERATE_INTERNAL_LABEL): Make local + constant labels linker-visible. + 2016-11-26 Prathamesh Kulkarni <prathamesh.kulkarni@linaro.org> * tree.c (build_common_tree_nodes): Initialize ptrdiff_type_node. diff --git a/gcc/config/darwin.c b/gcc/config/darwin.c index e9ce6d2..1a67c4c 100644 --- a/gcc/config/darwin.c +++ b/gcc/config/darwin.c @@ -474,7 +474,31 @@ indirection_hasher::equal (machopic_indirection *s, const char *k) } /* Return the name of the non-lazy pointer (if STUB_P is false) or - stub (if STUB_B is true) corresponding to the given name. */ + stub (if STUB_B is true) corresponding to the given name. + + If we have a situation like: + +global_weak_symbol: + .... +Lnon_weak_local: + .... + + ld64 will be unable to split this into two atoms (because the "L" makes + the second symbol 'invisible'). This means that legitimate direct accesses + to the second symbol will appear to be non-allowed direct accesses to an + atom of type weak, global which are not allowed. + + To avoid this, we make the indirections have a leading 'l' (lower-case L) + which has a special meaning: linker can see this and use it to determine + atoms, but it is not placed into the final symbol table. + + The implementation here is somewhat heavy-handed in that it will also mark + indirections to the __IMPORT,__pointers section the same way which is + really unnecessary, since ld64 _can_ split those into atoms as they are + fixed size. FIXME: determine if this is a penalty worth extra code to + fix. + +*/ const char * machopic_indirection_name (rtx sym_ref, bool stub_p) @@ -485,6 +509,7 @@ machopic_indirection_name (rtx sym_ref, bool stub_p) machopic_indirection *p; bool needs_quotes; const char *suffix; + char L_or_l = 'L'; const char *prefix = user_label_prefix; const char *quote = ""; tree id; @@ -519,9 +544,13 @@ machopic_indirection_name (rtx sym_ref, bool stub_p) if (stub_p) suffix = STUB_SUFFIX; else - suffix = NON_LAZY_POINTER_SUFFIX; + { + suffix = NON_LAZY_POINTER_SUFFIX; + /* Let the linker see this. */ + L_or_l = 'l'; + } - buffer = XALLOCAVEC (char, strlen ("&L") + buffer = XALLOCAVEC (char, 2 /* strlen ("&L") or ("&l") */ + strlen (prefix) + namelen + strlen (suffix) @@ -529,7 +558,7 @@ machopic_indirection_name (rtx sym_ref, bool stub_p) + 1 /* '\0' */); /* Construct the name of the non-lazy pointer or stub. */ - sprintf (buffer, "&%sL%s%s%s%s", quote, prefix, name, suffix, quote); + sprintf (buffer, "&%s%c%s%s%s%s", quote, L_or_l, prefix, name, suffix, quote); if (!machopic_indirections) machopic_indirections = hash_table<indirection_hasher>::create_ggc (37); diff --git a/gcc/config/darwin.h b/gcc/config/darwin.h index 98d2382..045f70b 100644 --- a/gcc/config/darwin.h +++ b/gcc/config/darwin.h @@ -716,9 +716,16 @@ extern GTY(()) section * darwin_sections[NUM_DARWIN_SECTIONS]; { "weak_import", 0, 0, true, false, false, \ darwin_handle_weak_import_attribute, false } +/* Make local constant labels linker-visible, so that if one follows a + weak_global constant, ld64 will be able to separate the atoms. */ #undef ASM_GENERATE_INTERNAL_LABEL #define ASM_GENERATE_INTERNAL_LABEL(LABEL,PREFIX,NUM) \ - sprintf (LABEL, "*%s%ld", PREFIX, (long)(NUM)) + do { \ + if (strcmp ("LC", PREFIX) == 0) \ + sprintf (LABEL, "*%s%ld", "lC", (long)(NUM)); \ + else \ + sprintf (LABEL, "*%s%ld", PREFIX, (long)(NUM)); \ + } while (0) #undef TARGET_ASM_MARK_DECL_PRESERVED #define TARGET_ASM_MARK_DECL_PRESERVED darwin_mark_decl_preserved |