Linker plugins should be aware of --defsym during symbol resolution
Sriraman Tallam via binutils
binutils@sourceware.org
Mon Feb 12 18:06:00 GMT 2018
Ping.
include/plugin-api.h (LDPR_LINKER_REDEFINED): New enum value.
gold/
* expression.cc (Symbol_expression::is_symbol_in_expression):
New method.
(Unary_expression::is_symbol_in_expression): New method.
(Binary_expression::is_symbol_in_expression): New method.
(Trinary_expression::is_symbol_in_expression): New method.
* plugin.cc (is_referenced_from_outside): Check if the symbol is
used in a defsym expression.
(get_symbol_resolution_info): Fix symbol resolution if defined or
used in defsyms.
* script.cc (Script_options::is_defsym_def): New method.
(Script_options::is_defsym_use): New method.
* script.h (Expression::is_symbol_in_expression): New method.
(Symbol_assignment::is_defsym): New method.
(Symbol_assignment::value): New method.
(Script_options::is_defsym_def): New method.
(Script_options::is_defsym_use): New method.
* testsuite/Makefile.am (plugin_test_defsym): New test.
* testsuite/Makefile.in: Regenerate.
* testsuite/plugin_test.c: Check for new symbol resolution.
* testsuite/plugin_test_defsym.sh: New script.
* testsuite/plugin_test_defsym.c: New test source.
On Fri, Feb 2, 2018 at 4:33 PM, Sriraman Tallam <tmsriram@google.com> wrote:
> Hello,
>
> I have a patch that fixes symbol resolutions when defined or used
> in defsym expressions. Please take a look.
>
> include/plugin-api.h (LDPR_LINKER_REDEFINED): New enum value.
>
> gold/
> * expression.cc (Symbol_expression::is_symbol_in_expression):
> New method.
> (Unary_expression::is_symbol_in_expression): New method.
> (Binary_expression::is_symbol_in_expression): New method.
> (Trinary_expression::is_symbol_in_expression): New method.
> * plugin.cc (is_referenced_from_outside): Check if the symbol is
> used in a defsym expression.
> (get_symbol_resolution_info): Fix symbol resolution if defined or
> used in defsyms.
> * script.cc (Script_options::is_defsym_def): New method.
> (Script_options::is_defsym_use): New method.
> * script.h (Expression::is_symbol_in_expression): New method.
> (Symbol_assignment::is_defsym): New method.
> (Symbol_assignment::value): New method.
> (Script_options::is_defsym_def): New method.
> (Script_options::is_defsym_use): New method.
> * testsuite/Makefile.am (plugin_test_defsym): New test.
> * testsuite/Makefile.in: Regenerate.
> * testsuite/plugin_test.c: Check for new symbol resolution.
> * testsuite/plugin_test_defsym.sh: New script.
> * testsuite/plugin_test_defsym.c: New test source.
>
>
> Thanks
> Sri
-------------- next part --------------
include/plugin-api.h (LDPR_LINKER_REDEFINED): New enum value.
gold/
* expression.cc (Symbol_expression::is_symbol_in_expression):
New method.
(Unary_expression::is_symbol_in_expression): New method.
(Binary_expression::is_symbol_in_expression): New method.
(Trinary_expression::is_symbol_in_expression): New method.
* plugin.cc (is_referenced_from_outside): Check if the symbol is
used in a defsym expression.
(get_symbol_resolution_info): Fix symbol resolution if defined or
used in defsyms.
* script.cc (Script_options::is_defsym_def): New method.
(Script_options::is_defsym_use): New method.
* script.h (Expression::is_symbol_in_expression): New method.
(Symbol_assignment::is_defsym): New method.
(Symbol_assignment::value): New method.
(Script_options::is_defsym_def): New method.
(Script_options::is_defsym_use): New method.
* testsuite/Makefile.am (plugin_test_defsym): New test.
* testsuite/Makefile.in: Regenerate.
* testsuite/plugin_test.c: Check for new symbol resolution.
* testsuite/plugin_test_defsym.sh: New script.
* testsuite/plugin_test_defsym.c: New test source.
diff --git a/gold/expression.cc b/gold/expression.cc
index d764cc2a9d..bf65304833 100644
--- a/gold/expression.cc
+++ b/gold/expression.cc
@@ -205,6 +205,12 @@ class Symbol_expression : public Expression
uint64_t
value(const Expression_eval_info*);
+ bool
+ is_symbol_in_expression(const char* name)
+ {
+ return this->name_ == name;
+ }
+
void
print(FILE* f) const
{ fprintf(f, "%s", this->name_.c_str()); }
@@ -318,6 +324,10 @@ class Unary_expression : public Expression
arg_print(FILE* f) const
{ this->arg_->print(f); }
+ bool
+ is_symbol_in_expression(const char* name)
+ { return this->arg_->is_symbol_in_expression(name); }
+
private:
Expression* arg_;
};
@@ -437,6 +447,13 @@ class Binary_expression : public Expression
fprintf(f, ")");
}
+ bool
+ is_symbol_in_expression(const char* name)
+ {
+ return (this->left_->is_symbol_in_expression(name) ||
+ this->right_->is_symbol_in_expression(name));
+ }
+
private:
Expression* left_;
Expression* right_;
@@ -622,6 +639,12 @@ class Trinary_expression : public Expression
arg3_print(FILE* f) const
{ this->arg3_->print(f); }
+ bool
+ is_symbol_in_expression(const char* name)
+ { return (this->arg1_->is_symbol_in_expression(name) ||
+ this->arg2_->is_symbol_in_expression(name) ||
+ this->arg3_->is_symbol_in_expression(name)); }
+
private:
Expression* arg1_;
Expression* arg2_;
diff --git a/gold/plugin.cc b/gold/plugin.cc
index 02fef25dda..7fd42821af 100644
--- a/gold/plugin.cc
+++ b/gold/plugin.cc
@@ -942,6 +942,9 @@ is_referenced_from_outside(Symbol* lsym)
return true;
if (parameters->options().is_undefined(lsym->name()))
return true;
+ Layout* layout = parameters->options().plugins()->layout();
+ if (layout->script_options()->is_defsym_use(lsym->name()))
+ return true;
return false;
}
@@ -989,6 +992,8 @@ Pluginobj::get_symbol_resolution_info(Symbol_table* symtab,
return version > 2 ? LDPS_NO_SYMS : LDPS_OK;
}
+ Layout *layout = parameters->options().plugins()->layout();
+
for (int i = 0; i < nsyms; i++)
{
ld_plugin_symbol* isym = &syms[i];
@@ -997,9 +1002,16 @@ Pluginobj::get_symbol_resolution_info(Symbol_table* symtab,
lsym = symtab->resolve_forwards(lsym);
ld_plugin_symbol_resolution res = LDPR_UNKNOWN;
- if (lsym->is_undefined())
- // The symbol remains undefined.
- res = LDPR_UNDEF;
+ if (layout->script_options()->is_defsym_def(lsym->name()))
+ {
+ // The symbol is redefined.
+ res = LDPR_LINKER_REDEFINED;
+ }
+ else if (lsym->is_undefined())
+ {
+ // The symbol remains undefined.
+ res = LDPR_UNDEF;
+ }
else if (isym->def == LDPK_UNDEF
|| isym->def == LDPK_WEAKUNDEF
|| isym->def == LDPK_COMMON)
diff --git a/gold/script.cc b/gold/script.cc
index db243cf435..e0a8d9a742 100644
--- a/gold/script.cc
+++ b/gold/script.cc
@@ -1112,6 +1112,33 @@ Script_options::is_pending_assignment(const char* name)
return false;
}
+// Returns trus if symbol with NAME is redefined by defsym.
+
+bool Script_options::is_defsym_def(const char* name)
+{
+ for (Symbol_assignments::iterator p = this->symbol_assignments_.begin();
+ p != this->symbol_assignments_.end();
+ ++p)
+ if ((*p)->is_defsym() && (*p)->name() == name)
+ return true;
+ return false;
+}
+
+// Returns trus if symbol with NAME is used in a defsym expression.
+
+bool
+Script_options::is_defsym_use(const char* name)
+{
+ for (Symbol_assignments::iterator p = this->symbol_assignments_.begin();
+ p != this->symbol_assignments_.end();
+ ++p)
+ {
+ if ((*p)->is_defsym() && (*p)->value()->is_symbol_in_expression(name))
+ return true;
+ }
+ return false;
+}
+
// Add a symbol to be defined.
void
diff --git a/gold/script.h b/gold/script.h
index ec8ce8e110..2159f9f7e7 100644
--- a/gold/script.h
+++ b/gold/script.h
@@ -129,13 +129,18 @@ class Expression
virtual uint64_t
value(const Expression_eval_info*) = 0;
+ // Return true if symbol is part of the expression.
+ // The child class that uses this symbol returns true.
+ virtual bool
+ is_symbol_in_expression(const char*)
+ { return false; }
+
private:
// May not be copied.
Expression(const Expression&);
Expression& operator=(const Expression&);
};
-
// Version_script_info stores information parsed from the version
// script, either provided by --version-script or as part of a linker
// script. A single Version_script_info object per target is owned by
@@ -344,6 +349,14 @@ class Symbol_assignment
void
finalize(Symbol_table*, const Layout*);
+ bool
+ is_defsym() const
+ { return is_defsym_; }
+
+ Expression *
+ value() const
+ { return val_; }
+
// Finalize the symbol value when it can refer to the dot symbol.
void
finalize_with_dot(Symbol_table*, const Layout*, uint64_t dot_value,
@@ -454,6 +467,14 @@ class Script_options
bool
define_symbol(const char* definition);
+ // Returns true if symbol is defined via defsym.
+ bool
+ is_defsym_def(const char *name);
+
+ // Returns true if symbol is used in a defsym.
+ bool
+ is_defsym_use(const char *name);
+
// Create sections required by any linker scripts.
void
create_script_sections(Layout*);
diff --git a/gold/testsuite/Makefile.am b/gold/testsuite/Makefile.am
index 16cae8004c..b94182856e 100644
--- a/gold/testsuite/Makefile.am
+++ b/gold/testsuite/Makefile.am
@@ -2332,6 +2332,19 @@ plugin_test_start_lib: unused.o plugin_start_lib_test.o plugin_start_lib_test_2.
plugin_test_start_lib.err: plugin_test_start_lib
@touch plugin_test_start_lib.err
+check_PROGRAMS += plugin_test_defsym
+check_SCRIPTS += plugin_test_defsym.sh
+check_DATA += plugin_test_defsym.err
+MOSTLYCLEANFILES += plugin_test_defsym.err
+plugin_test_defsym.syms: plugin_test_defsym.o
+ $(TEST_READELF) -sW $< >$@ 2>/dev/null
+plugin_test_defsym.o: plugin_test_defsym.c
+ $(COMPILE) -c -o $@ $<
+plugin_test_defsym: plugin_test_defsym.o plugin_test_defsym.syms gcctestdir/ld plugin_test.so
+ $(CXXLINK) -Bgcctestdir/ -Wl,--no-demangle,--plugin,"./plugin_test.so" \
+ -Wl,--defsym,bar=foo+2 plugin_test_defsym.syms 2>plugin_test_defsym.err
+plugin_test_defsym.err: plugin_test_defsym
+ @touch plugin_test_defsym.err
plugin_start_lib_test_2.syms: plugin_start_lib_test_2.o
$(TEST_READELF) -sW $< >$@ 2>/dev/null
diff --git a/gold/testsuite/plugin_test.c b/gold/testsuite/plugin_test.c
index c6df7b6f7d..b92fb8acf5 100644
--- a/gold/testsuite/plugin_test.c
+++ b/gold/testsuite/plugin_test.c
@@ -476,6 +476,9 @@ all_symbols_read_hook(void)
case LDPR_RESOLVED_DYN:
res = "RESOLVED_DYN";
break;
+ case LDPR_LINKER_REDEFINED:
+ res = "LINKER_REDEFINED";
+ break;
default:
res = "?";
break;
diff --git a/gold/testsuite/plugin_test_defsym.c b/gold/testsuite/plugin_test_defsym.c
index e69de29bb2..a3c3b962f3 100644
--- a/gold/testsuite/plugin_test_defsym.c
+++ b/gold/testsuite/plugin_test_defsym.c
@@ -0,0 +1,32 @@
+/* plugin_test_defsym.c -- a test case for gold
+
+ Copyright (C) 2018 onwards Free Software Foundation, Inc.
+ Written by Sriraman Tallam <tmsriram@google.com>
+
+ This file is part of gold.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+ MA 02110-1301, USA. */
+
+int foo(void);
+int foo(void) {
+ return 0;
+}
+
+int bar(void);
+
+int main(void) {
+ return bar();
+}
diff --git a/gold/testsuite/plugin_test_defsym.sh b/gold/testsuite/plugin_test_defsym.sh
index e69de29bb2..3eb6446433 100755
--- a/gold/testsuite/plugin_test_defsym.sh
+++ b/gold/testsuite/plugin_test_defsym.sh
@@ -0,0 +1,52 @@
+#!/bin/sh
+
+# plugin_test_defsym.sh -- a test case for the plugin API.
+
+# Copyright (C) 2018 onwards Free Software Foundation, Inc.
+# Written by Sriraman Tallam <tmsriram@google.com>.
+
+# This file is part of gold.
+
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+
+# This file goes with plugin_test.c, a simple plug-in library that
+# exercises the basic interfaces and prints out version numbers and
+# options passed to the plugin.
+
+# This checks if the symbol resolution withe export dynamic symbol is
+# as expected.
+
+check()
+{
+ if ! grep -q "$2" "$1"
+ then
+ echo "Did not find expected output in $1:"
+ echo " $2"
+ echo ""
+ echo "Actual output below:"
+ cat "$1"
+ exit 1
+ fi
+}
+
+check plugin_test_defsym.err "API version:"
+check plugin_test_defsym.err "gold version:"
+check plugin_test_defsym.err "plugin_test_defsym.syms: claim file hook called"
+check plugin_test_defsym.err "plugin_test_defsym.syms: bar: LINKER_REDEFINED"
+check plugin_test_defsym.err "plugin_test_defsym.syms: foo: PREVAILING_DEF_REG"
+check plugin_test_defsym.err "cleanup hook called"
+
+exit 0
diff --git a/include/plugin-api.h b/include/plugin-api.h
index 03e21f4a0c..6c02947699 100644
--- a/include/plugin-api.h
+++ b/include/plugin-api.h
@@ -162,7 +162,11 @@ enum ld_plugin_symbol_resolution
references from regular objects. It is only referenced from IR
code, but the symbol is exported and may be referenced from
a dynamic object (not seen at link time). */
- LDPR_PREVAILING_DEF_IRONLY_EXP
+ LDPR_PREVAILING_DEF_IRONLY_EXP,
+
+ /* This symbol has been redefined by the linker, typically using
+ defsym. */
+ LDPR_LINKER_REDEFINED,
};
/* The plugin library's "claim file" handler. */
More information about the Binutils
mailing list