Fix copy relocations against protected symbols from:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=65248
This commit is contained in:
parent
212399f8da
commit
d396365815
|
@ -42532,6 +42532,9 @@ ix86_memmodel_check (unsigned HOST_WIDE_INT val)
|
|||
#if TARGET_MACHO
|
||||
#undef TARGET_BINDS_LOCAL_P
|
||||
#define TARGET_BINDS_LOCAL_P darwin_binds_local_p
|
||||
#else
|
||||
#undef TARGET_BINDS_LOCAL_P
|
||||
#define TARGET_BINDS_LOCAL_P default_binds_local_p_2
|
||||
#endif
|
||||
#if TARGET_DLLIMPORT_DECL_ATTRIBUTES
|
||||
#undef TARGET_BINDS_LOCAL_P
|
||||
|
|
|
@ -583,6 +583,7 @@ extern void default_asm_output_anchor (rtx);
|
|||
extern bool default_use_anchors_for_symbol_p (const_rtx);
|
||||
extern bool default_binds_local_p (const_tree);
|
||||
extern bool default_binds_local_p_1 (const_tree, int);
|
||||
extern bool default_binds_local_p_2 (const_tree);
|
||||
extern void default_globalize_label (FILE *, const char *);
|
||||
extern void default_globalize_decl_name (FILE *, tree);
|
||||
extern void default_emit_unwind_label (FILE *, tree, int, int);
|
||||
|
|
|
@ -6620,95 +6620,106 @@ resolution_local_p (enum ld_plugin_symbol_resolution resolution)
|
|||
|
||||
/* Assume ELF-ish defaults, since that's pretty much the most liberal
|
||||
wrt cross-module name binding. */
|
||||
|
||||
bool
|
||||
default_binds_local_p (const_tree exp)
|
||||
static bool
|
||||
default_binds_local_p_3 (const_tree exp, bool shlib, bool weak_dominate,
|
||||
bool extern_protected_data)
|
||||
{
|
||||
return default_binds_local_p_1 (exp, flag_shlib);
|
||||
}
|
||||
|
||||
bool
|
||||
default_binds_local_p_1 (const_tree exp, int shlib)
|
||||
{
|
||||
bool local_p;
|
||||
bool resolved_locally = false;
|
||||
bool resolved_to_local_def = false;
|
||||
|
||||
/* With resolution file in hands, take look into resolutions.
|
||||
We can't just return true for resolved_locally symbols,
|
||||
because dynamic linking might overwrite symbols
|
||||
in shared libraries. */
|
||||
if (TREE_CODE (exp) == VAR_DECL && TREE_PUBLIC (exp)
|
||||
&& (TREE_STATIC (exp) || DECL_EXTERNAL (exp)))
|
||||
{
|
||||
struct varpool_node *vnode = varpool_get_node (exp);
|
||||
if (vnode && resolution_local_p (vnode->symbol.resolution))
|
||||
resolved_locally = true;
|
||||
if (vnode
|
||||
&& resolution_to_local_definition_p (vnode->symbol.resolution))
|
||||
resolved_to_local_def = true;
|
||||
}
|
||||
else if (TREE_CODE (exp) == FUNCTION_DECL && TREE_PUBLIC (exp))
|
||||
{
|
||||
struct cgraph_node *node = cgraph_get_node (exp);
|
||||
if (node
|
||||
&& resolution_local_p (node->symbol.resolution))
|
||||
resolved_locally = true;
|
||||
if (node
|
||||
&& resolution_to_local_definition_p (node->symbol.resolution))
|
||||
resolved_to_local_def = true;
|
||||
}
|
||||
|
||||
/* A non-decl is an entry in the constant pool. */
|
||||
if (!DECL_P (exp))
|
||||
local_p = true;
|
||||
return true;
|
||||
|
||||
/* Weakrefs may not bind locally, even though the weakref itself is always
|
||||
static and therefore local. Similarly, the resolver for ifunc functions
|
||||
might resolve to a non-local function.
|
||||
FIXME: We can resolve the weakref case more curefuly by looking at the
|
||||
weakref alias. */
|
||||
else if (lookup_attribute ("weakref", DECL_ATTRIBUTES (exp))
|
||||
if (lookup_attribute ("weakref", DECL_ATTRIBUTES (exp))
|
||||
|| (TREE_CODE (exp) == FUNCTION_DECL
|
||||
&& lookup_attribute ("ifunc", DECL_ATTRIBUTES (exp))))
|
||||
local_p = false;
|
||||
return false;
|
||||
|
||||
/* Static variables are always local. */
|
||||
else if (! TREE_PUBLIC (exp))
|
||||
local_p = true;
|
||||
/* A variable is local if the user has said explicitly that it will
|
||||
be. */
|
||||
else if ((DECL_VISIBILITY_SPECIFIED (exp)
|
||||
|| resolved_to_local_def)
|
||||
&& DECL_VISIBILITY (exp) != VISIBILITY_DEFAULT)
|
||||
local_p = true;
|
||||
/* Variables defined outside this object might not be local. */
|
||||
else if (DECL_EXTERNAL (exp) && !resolved_locally)
|
||||
local_p = false;
|
||||
/* If defined in this object and visibility is not default, must be
|
||||
local. */
|
||||
else if (DECL_VISIBILITY (exp) != VISIBILITY_DEFAULT)
|
||||
local_p = true;
|
||||
/* Default visibility weak data can be overridden by a strong symbol
|
||||
in another module and so are not local. */
|
||||
else if (DECL_WEAK (exp)
|
||||
&& !resolved_locally)
|
||||
local_p = false;
|
||||
if (! TREE_PUBLIC (exp))
|
||||
return true;
|
||||
|
||||
/* With resolution file in hand, take look into resolutions.
|
||||
We can't just return true for resolved_locally symbols,
|
||||
because dynamic linking might overwrite symbols
|
||||
in shared libraries. */
|
||||
bool resolved_locally = false;
|
||||
bool defined_locally = !DECL_EXTERNAL (exp);
|
||||
if (TREE_CODE (exp) == VAR_DECL && TREE_PUBLIC (exp)
|
||||
&& (TREE_STATIC (exp) || DECL_EXTERNAL (exp)))
|
||||
{
|
||||
struct varpool_node *vnode = varpool_get_node (exp);
|
||||
if (vnode && vnode->symbol.in_other_partition)
|
||||
defined_locally = true;
|
||||
if (vnode && resolution_to_local_definition_p (vnode->symbol.resolution))
|
||||
defined_locally = resolved_locally = true;
|
||||
else if (vnode && resolution_local_p (vnode->symbol.resolution))
|
||||
resolved_locally = true;
|
||||
}
|
||||
if (defined_locally && weak_dominate && !shlib)
|
||||
resolved_locally = true;
|
||||
|
||||
/* Undefined weak symbols are never defined locally. */
|
||||
if (DECL_WEAK (exp) && !defined_locally)
|
||||
return false;
|
||||
|
||||
/* A symbol is local if the user has said explicitly that it will be,
|
||||
or if we have a definition for the symbol. We cannot infer visibility
|
||||
for undefined symbols. */
|
||||
if (DECL_VISIBILITY (exp) != VISIBILITY_DEFAULT
|
||||
&& (TREE_CODE (exp) == FUNCTION_DECL
|
||||
|| !extern_protected_data
|
||||
|| DECL_VISIBILITY (exp) != VISIBILITY_PROTECTED)
|
||||
&& (DECL_VISIBILITY_SPECIFIED (exp) || defined_locally))
|
||||
return true;
|
||||
|
||||
/* If PIC, then assume that any global name can be overridden by
|
||||
symbols resolved from other modules. */
|
||||
else if (shlib)
|
||||
local_p = false;
|
||||
if (shlib)
|
||||
return false;
|
||||
|
||||
/* Variables defined outside this object might not be local. */
|
||||
if (DECL_EXTERNAL (exp) && !resolved_locally)
|
||||
return false;
|
||||
|
||||
/* Non-dominant weak symbols are not defined locally. */
|
||||
if (DECL_WEAK (exp) && !resolved_locally)
|
||||
return false;
|
||||
|
||||
/* Uninitialized COMMON variable may be unified with symbols
|
||||
resolved from other modules. */
|
||||
else if (DECL_COMMON (exp)
|
||||
&& !resolved_locally
|
||||
&& (DECL_INITIAL (exp) == NULL
|
||||
|| DECL_INITIAL (exp) == error_mark_node))
|
||||
local_p = false;
|
||||
if (DECL_COMMON (exp)
|
||||
&& !resolved_locally
|
||||
&& (DECL_INITIAL (exp) == NULL
|
||||
|| (!in_lto_p && DECL_INITIAL (exp) == error_mark_node)))
|
||||
return false;
|
||||
|
||||
/* Otherwise we're left with initialized (or non-common) global data
|
||||
which is of necessity defined locally. */
|
||||
else
|
||||
local_p = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
return local_p;
|
||||
bool
|
||||
default_binds_local_p (const_tree exp)
|
||||
{
|
||||
return default_binds_local_p_3 (exp, flag_shlib != 0, true, false);
|
||||
}
|
||||
|
||||
bool
|
||||
default_binds_local_p_1 (const_tree exp, int shlib)
|
||||
{
|
||||
return default_binds_local_p_3 (exp, shlib != 0, false, false);
|
||||
}
|
||||
|
||||
/* Similar to default_binds_local_p, but protected data may be
|
||||
external. */
|
||||
bool
|
||||
default_binds_local_p_2 (const_tree exp)
|
||||
{
|
||||
return default_binds_local_p_3 (exp, flag_shlib != 0, true, true);
|
||||
}
|
||||
|
||||
/* Return true when references to DECL must bind to current definition in
|
||||
|
|
Loading…
Reference in New Issue