From e051745c838bf29e564fb2665339f97c8383b9e8 Mon Sep 17 00:00:00 2001 From: Cary Coutant Date: Tue, 8 Jul 2014 22:34:27 -0700 Subject: [PATCH] Fix --defsym to copy symbol attributes. Alan Modra committed a patch to Gnu ld to fix a problem encountered on PPC where the --defsym option wasn't copying the st_other bits to the newly-defined symbol. https://sourceware.org/ml/binutils/2014-07/msg00094.html Gold has the same problem, and additionally wasn't copying the symbol type. This patch fixes both problems, by copying the symbol type, visibility, and the remaining st_other bits to the new symbol for --defsym=sym1=sym2 assignments. gold/ * expression.cc (struct Expression::Expression_eval_info): Add new fields type_pointer, vis_pointer, and nonvis_pointer. (Expression::eval_maybe_dot): Add type_pointer, vis_pointer, and nonvis_pointer parameters. Adjust all calls. (Symbol_expression::value): Update type, visibility, and nonvis bits in caller. * script.cc (Symbol_assignment::sized_finalize): Update type, visibility, and remaining st_other bits for new symbol. * script.h: (Expression::eval_maybe_dot): Add type_pointer, vis_pointer, and nonvis_pointer parameters. * symtab.h (Symbol::set_type): New method. * testsuite/Makefile.am (defsym_test): New test. * testsuite/Makefile.in: Regenerate. * testsuite/defsym_test.c: New file. * testsuite/defsym_test.sh: New file. --- gold/ChangeLog | 19 +++++++++++++++ gold/expression.cc | 45 ++++++++++++++++++++++++++++++++--- gold/script.cc | 11 +++++++-- gold/script.h | 2 ++ gold/symtab.h | 5 ++++ gold/testsuite/Makefile.am | 11 +++++++++ gold/testsuite/Makefile.in | 19 ++++++++++++--- gold/testsuite/defsym_test.c | 15 ++++++++++++ gold/testsuite/defsym_test.sh | 40 +++++++++++++++++++++++++++++++ 9 files changed, 159 insertions(+), 8 deletions(-) create mode 100644 gold/testsuite/defsym_test.c create mode 100755 gold/testsuite/defsym_test.sh diff --git a/gold/ChangeLog b/gold/ChangeLog index 0bd14e41805..60d74719338 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,22 @@ +2014-07-08 Cary Coutant + + * expression.cc (struct Expression::Expression_eval_info): Add + new fields type_pointer, vis_pointer, and nonvis_pointer. + (Expression::eval_maybe_dot): Add type_pointer, vis_pointer, and + nonvis_pointer parameters. Adjust all calls. + (Symbol_expression::value): Update type, visibility, and nonvis bits + in caller. + * script.cc (Symbol_assignment::sized_finalize): Update type, + visibility, and remaining st_other bits for new symbol. + * script.h: (Expression::eval_maybe_dot): Add type_pointer, + vis_pointer, and nonvis_pointer parameters. + * symtab.h (Symbol::set_type): New method. + + * testsuite/Makefile.am (defsym_test): New test. + * testsuite/Makefile.in: Regenerate. + * testsuite/defsym_test.c: New file. + * testsuite/defsym_test.sh: New file. + 2014-07-08 Cary Coutant PR gold/15639 diff --git a/gold/expression.cc b/gold/expression.cc index bdf52fade0d..61a3eaf17e4 100644 --- a/gold/expression.cc +++ b/gold/expression.cc @@ -68,6 +68,12 @@ struct Expression::Expression_eval_info Output_section** result_section_pointer; // Pointer to where the alignment of the result should be stored. uint64_t* result_alignment_pointer; + // Pointer to where the type of the symbol on the RHS should be stored. + elfcpp::STT* type_pointer; + // Pointer to where the visibility of the symbol on the RHS should be stored. + elfcpp::STV* vis_pointer; + // Pointer to where the rest of the symbol's st_other field should be stored. + unsigned char* nonvis_pointer; }; // Evaluate an expression. @@ -76,8 +82,8 @@ uint64_t Expression::eval(const Symbol_table* symtab, const Layout* layout, bool check_assertions) { - return this->eval_maybe_dot(symtab, layout, check_assertions, - false, 0, NULL, NULL, NULL, false); + return this->eval_maybe_dot(symtab, layout, check_assertions, false, 0, + NULL, NULL, NULL, NULL, NULL, NULL, false); } // Evaluate an expression which may refer to the dot symbol. @@ -92,7 +98,7 @@ Expression::eval_with_dot(const Symbol_table* symtab, const Layout* layout, { return this->eval_maybe_dot(symtab, layout, check_assertions, true, dot_value, dot_section, result_section_pointer, - result_alignment_pointer, + result_alignment_pointer, NULL, NULL, NULL, is_section_dot_assignment); } @@ -105,6 +111,9 @@ Expression::eval_maybe_dot(const Symbol_table* symtab, const Layout* layout, uint64_t dot_value, Output_section* dot_section, Output_section** result_section_pointer, uint64_t* result_alignment_pointer, + elfcpp::STT* type_pointer, + elfcpp::STV* vis_pointer, + unsigned char* nonvis_pointer, bool is_section_dot_assignment) { Expression_eval_info eei; @@ -121,6 +130,12 @@ Expression::eval_maybe_dot(const Symbol_table* symtab, const Layout* layout, *result_section_pointer = NULL; eei.result_section_pointer = result_section_pointer; + // For symbol=symbol assignments, we need to track the type, visibility, + // and remaining st_other bits. + eei.type_pointer = type_pointer; + eei.vis_pointer = vis_pointer; + eei.nonvis_pointer = nonvis_pointer; + eei.result_alignment_pointer = result_alignment_pointer; uint64_t val = this->value(&eei); @@ -196,6 +211,12 @@ Symbol_expression::value(const Expression_eval_info* eei) if (eei->result_section_pointer != NULL) *eei->result_section_pointer = sym->output_section(); + if (eei->type_pointer != NULL) + *eei->type_pointer = sym->type(); + if (eei->vis_pointer != NULL) + *eei->vis_pointer = sym->visibility(); + if (eei->nonvis_pointer != NULL) + *eei->nonvis_pointer = sym->nonvis(); if (parameters->target().get_size() == 32) return eei->symtab->get_sized_symbol<32>(sym)->value(); @@ -271,6 +292,9 @@ class Unary_expression : public Expression eei->dot_section, arg_section_pointer, eei->result_alignment_pointer, + NULL, + NULL, + NULL, false); } @@ -351,6 +375,9 @@ class Binary_expression : public Expression eei->dot_section, section_pointer, alignment_pointer, + NULL, + NULL, + NULL, false); } @@ -366,6 +393,9 @@ class Binary_expression : public Expression eei->dot_section, section_pointer, alignment_pointer, + NULL, + NULL, + NULL, false); } @@ -517,6 +547,9 @@ class Trinary_expression : public Expression eei->dot_section, section_pointer, NULL, + NULL, + NULL, + NULL, false); } @@ -532,6 +565,9 @@ class Trinary_expression : public Expression eei->dot_section, section_pointer, alignment_pointer, + NULL, + NULL, + NULL, false); } @@ -547,6 +583,9 @@ class Trinary_expression : public Expression eei->dot_section, section_pointer, alignment_pointer, + NULL, + NULL, + NULL, false); } diff --git a/gold/script.cc b/gold/script.cc index b4a6aff55b2..eff9a81a6ce 100644 --- a/gold/script.cc +++ b/gold/script.cc @@ -980,12 +980,19 @@ Symbol_assignment::sized_finalize(Symbol_table* symtab, const Layout* layout, Output_section* dot_section) { Output_section* section; + elfcpp::STT type = elfcpp::STT_NOTYPE; + elfcpp::STV vis = elfcpp::STV_DEFAULT; + unsigned char nonvis = 0; uint64_t final_val = this->val_->eval_maybe_dot(symtab, layout, true, is_dot_available, dot_value, dot_section, - §ion, NULL, false); + §ion, NULL, &type, + &vis, &nonvis, false); Sized_symbol* ssym = symtab->get_sized_symbol(this->sym_); ssym->set_value(final_val); + ssym->set_type(type); + ssym->set_visibility(vis); + ssym->set_nonvis(nonvis); if (section != NULL) ssym->set_output_section(section); } @@ -1005,7 +1012,7 @@ Symbol_assignment::set_if_absolute(Symbol_table* symtab, const Layout* layout, uint64_t val = this->val_->eval_maybe_dot(symtab, layout, false, is_dot_available, dot_value, dot_section, &val_section, NULL, - false); + NULL, NULL, NULL, false); if (val_section != NULL && val_section != dot_section) return; diff --git a/gold/script.h b/gold/script.h index 49b3776cf94..99bba08a1ba 100644 --- a/gold/script.h +++ b/gold/script.h @@ -34,6 +34,7 @@ #include #include +#include "elfcpp.h" #include "script-sections.h" namespace gold @@ -111,6 +112,7 @@ class Expression bool is_dot_available, uint64_t dot_value, Output_section* dot_section, Output_section** result_section, uint64_t* result_alignment, + elfcpp::STT* type, elfcpp::STV* vis, unsigned char* nonvis, bool is_section_dot_assignment); // Print the expression to the FILE. This is for debugging. diff --git a/gold/symtab.h b/gold/symtab.h index ab5b5f97d7f..7984dd6ff84 100644 --- a/gold/symtab.h +++ b/gold/symtab.h @@ -215,6 +215,11 @@ class Symbol type() const { return this->type_; } + // Set the symbol type. + void + set_type(elfcpp::STT type) + { this->type_ = type; } + // Return true for function symbol. bool is_func() const diff --git a/gold/testsuite/Makefile.am b/gold/testsuite/Makefile.am index 379ac8a8f3b..5e1cd0d12d6 100644 --- a/gold/testsuite/Makefile.am +++ b/gold/testsuite/Makefile.am @@ -2253,6 +2253,17 @@ ehdr_start_test_5_CXXFLAGS = -DEHDR_START_USER_DEF ehdr_start_test_5_LDFLAGS = -Bgcctestdir/ ehdr_start_test_5_LDADD = +# Test that the --defsym option copies the symbol type and visibility. +check_SCRIPTS += defsym_test.sh +check_DATA += defsym_test.syms +MOSTLYCLEANFILES += defsym_test.syms +defsym_test.syms: defsym_test + $(TEST_READELF) -sW $< > $@ +defsym_test: defsym_test.o gcctestdir/ld + $(LINK) -Bgcctestdir/ -Wl,--defsym=bar=foo defsym_test.o +defsym_test.o: defsym_test.c + $(COMPILE) -c -o $@ $< + # End-to-end incremental linking tests. # Incremental linking is currently supported only on the x86_64 target. diff --git a/gold/testsuite/Makefile.in b/gold/testsuite/Makefile.in index 04a42e8dbbb..7d0f78b5959 100644 --- a/gold/testsuite/Makefile.in +++ b/gold/testsuite/Makefile.in @@ -568,9 +568,14 @@ check_PROGRAMS = $(am__EXEEXT_1) $(am__EXEEXT_2) $(am__EXEEXT_3) \ # Test that __ehdr_start is left undefined when the text segment is not # appropriately aligned. -@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_70 = ehdr_start_test_4.sh -@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_71 = ehdr_start_test_4.syms -@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_72 = ehdr_start_test_4 + +# Test that the --defsym option copies the symbol type and visibility. +@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_70 = ehdr_start_test_4.sh \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ defsym_test.sh +@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_71 = ehdr_start_test_4.syms \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ defsym_test.syms +@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_72 = ehdr_start_test_4 \ +@GCC_TRUE@@NATIVE_LINKER_TRUE@ defsym_test.syms @GCC_FALSE@ehdr_start_test_5_DEPENDENCIES = @NATIVE_LINKER_FALSE@ehdr_start_test_5_DEPENDENCIES = @@ -4132,6 +4137,8 @@ gdb_index_test_4.sh.log: gdb_index_test_4.sh @p='gdb_index_test_4.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post) ehdr_start_test_4.sh.log: ehdr_start_test_4.sh @p='ehdr_start_test_4.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post) +defsym_test.sh.log: defsym_test.sh + @p='defsym_test.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post) script_test_10.sh.log: script_test_10.sh @p='script_test_10.sh'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post) split_i386.sh.log: split_i386.sh @@ -5600,6 +5607,12 @@ uninstall-am: @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -Wl,-Ttext=0x100100 $< @GCC_TRUE@@NATIVE_LINKER_TRUE@ehdr_start_test_4.o: ehdr_start_test.cc @GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -c -DEHDR_START_WEAK -o $@ $< +@GCC_TRUE@@NATIVE_LINKER_TRUE@defsym_test.syms: defsym_test +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_READELF) -sW $< > $@ +@GCC_TRUE@@NATIVE_LINKER_TRUE@defsym_test: defsym_test.o gcctestdir/ld +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(LINK) -Bgcctestdir/ -Wl,--defsym=bar=foo defsym_test.o +@GCC_TRUE@@NATIVE_LINKER_TRUE@defsym_test.o: defsym_test.c +@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(COMPILE) -c -o $@ $< # End-to-end incremental linking tests. # Incremental linking is currently supported only on the x86_64 target. diff --git a/gold/testsuite/defsym_test.c b/gold/testsuite/defsym_test.c new file mode 100644 index 00000000000..0bf68b21b1e --- /dev/null +++ b/gold/testsuite/defsym_test.c @@ -0,0 +1,15 @@ +#include + +void foo (void) __attribute__ ((noinline, visibility ("hidden"))); + +void foo (void) { + printf("foo called.\n"); +} + +void bar(void); + +int main(void) { + foo(); + bar(); + return 0; +} diff --git a/gold/testsuite/defsym_test.sh b/gold/testsuite/defsym_test.sh new file mode 100755 index 00000000000..e83fa9f350f --- /dev/null +++ b/gold/testsuite/defsym_test.sh @@ -0,0 +1,40 @@ +#!/bin/sh + +# defsym_test.sh -- test that --defsym copies type and visiblity. + +# Copyright (C) 2014 Free Software Foundation, Inc. +# Written by Cary Coutant . + +# 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. + +check() +{ + if ! grep -q "$2" "$1" + then + echo "Did not find expected symbol in $1:" + echo " $2" + echo "" + echo "Actual output below:" + cat "$1" + exit 1 + fi +} + +check defsym_test.syms "FUNC *GLOBAL *HIDDEN *[0-9]* *bar" + +exit 0 -- 2.30.2