summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJing Yu <jingyu@google.com>2010-07-22 14:35:55 -0700
committerJing Yu <jingyu@google.com>2010-07-22 14:35:55 -0700
commit5755afadf580726c7d9a34c575930d21c54a1f0a (patch)
treed0224f80576d1f48229e4999a3b059e012e4bfae
parent289c95d00ec591cffa5b705641ffcbdacb7c0d5c (diff)
downloadtoolchain_binutils-5755afadf580726c7d9a34c575930d21c54a1f0a.zip
toolchain_binutils-5755afadf580726c7d9a34c575930d21c54a1f0a.tar.gz
toolchain_binutils-5755afadf580726c7d9a34c575930d21c54a1f0a.tar.bz2
A few binutils and gold patches to make gold and safe-icf work.
Change-Id: I805434f4f616c822c979081a5a71b607ecd6cf26
-rw-r--r--binutils-2.19/README.android80
-rwxr-xr-xbinutils-2.19/config.sub8
-rw-r--r--binutils-2.19/gold/arm-reloc-property.cc4
-rw-r--r--binutils-2.19/gold/arm-reloc-property.h7
-rw-r--r--binutils-2.19/gold/arm.cc376
-rw-r--r--binutils-2.19/gold/gc.h44
-rw-r--r--binutils-2.19/gold/i386.cc88
-rw-r--r--binutils-2.19/gold/icf.cc41
-rw-r--r--binutils-2.19/gold/icf.h6
-rw-r--r--binutils-2.19/gold/output.cc10
-rw-r--r--binutils-2.19/gold/output.h15
-rw-r--r--binutils-2.19/gold/symtab.cc10
-rw-r--r--binutils-2.19/gold/symtab.h2
-rw-r--r--binutils-2.19/gold/target-reloc.h4
-rw-r--r--binutils-2.19/gold/target.h14
-rw-r--r--binutils-2.19/gold/testsuite/Makefile.am27
-rw-r--r--binutils-2.19/gold/testsuite/Makefile.in61
-rw-r--r--binutils-2.19/gold/testsuite/icf_preemptible_functions_test.cc47
-rwxr-xr-xbinutils-2.19/gold/testsuite/icf_preemptible_functions_test.sh35
-rw-r--r--binutils-2.19/gold/testsuite/icf_safe_so_test.cc3
-rwxr-xr-xbinutils-2.19/gold/testsuite/icf_safe_so_test.sh60
-rw-r--r--binutils-2.19/gold/testsuite/icf_safe_test.cc8
-rwxr-xr-xbinutils-2.19/gold/testsuite/icf_safe_test.sh6
-rw-r--r--binutils-2.19/gold/testsuite/icf_string_merge_test.cc50
-rwxr-xr-xbinutils-2.19/gold/testsuite/icf_string_merge_test.sh37
-rw-r--r--binutils-2.19/gold/testsuite/icf_virtual_function_folding_test.cc70
-rw-r--r--binutils-2.19/gold/x86_64.cc11
-rw-r--r--binutils-2.19/ld/emultempl/armelf.em7
28 files changed, 971 insertions, 160 deletions
diff --git a/binutils-2.19/README.android b/binutils-2.19/README.android
index 1231282..b990281 100644
--- a/binutils-2.19/README.android
+++ b/binutils-2.19/README.android
@@ -1,3 +1,83 @@
+2010-07-15 Doug Kwan <dougkwan@google.com>
+
+ Backport upstream patches to enhance safe ICF and to fix
+ a linker crash and an EXIDX problem in the Linux kernel.
+
+ http://www.cygwin.com/ml/binutils-cvs/2010-06/msg00118.html
+ http://www.cygwin.com/ml/binutils-cvs/2010-06/msg00148.html
+ http://www.cygwin.com/ml/binutils-cvs/2010-07/msg00080.html
+
+ Changed file:
+
+ gold/arm-reloc-property.cc
+ gold/arm-reloc-property.h
+ gold/arm.cc
+ gold/icf.h
+ gold/output.cc
+ gold/output.h
+ gold/target.h
+
+2010-07-09 Jing Yu <jingyu@google.com>
+
+ Add support to androideabi target.
+ Backport the patch from binutils upstream.
+
+ Changed file:
+ config.sub
+
+2010-06-23 Doug Kwan <dougkwan@google.com>
+
+ Add dummy --icf option to ld for compatiblity with gold.
+
+ Changed file:
+
+ ld/emultempl/armelf.em
+
+2010-06-19 Doug Kwan <dougkwan@google.com>
+
+ Integrate CL 40547.
+
+ Changed files:
+
+ gold/gc.h
+ gold/i386.cc
+ gold/icf.cc
+ gold/icf.h
+ gold/symtab.cc
+ gold/symtab.h
+ gold/target-reloc.h
+ gold/testsuite/Makefile.am
+ gold/testsuite/Makefile.in
+ gold/testsuite/icf_preemptible_functions_test.cc
+ gold/testsuite/icf_preemptible_functions_test.sh
+ gold/testsuite/icf_safe_so_test.cc
+ gold/testsuite/icf_safe_so_test.sh
+ gold/testsuite/icf_safe_test.cc
+ gold/testsuite/icf_safe_test.sh
+ gold/testsuite/icf_string_merge_test.cc
+ gold/testsuite/icf_string_merge_test.sh
+ gold/testsuite/icf_virtual_function_folding_test.cc
+ gold/x86_64.cc
+
+2010-06-15 Doug Kwan <dougkwan@google.com>
+
+ Fix ARM kernel build breakage due to merging EABI flags from
+ empty objects. This is not yet up-stream.
+
+ Changed files:
+
+ gold/arm.cc
+
+2010-06-08 Doug Kwan <dougkwan@google.com>
+
+ Backport upstream patch to fix too many stubs problem.
+
+ http://sourceware.org/ml/binutils-cvs/2010-06/msg00027.html
+
+ Changed files:
+
+ gold/arm.cc
+
2010-06-02 Doug Kwan <dougkwan@google.com>
Backport upstream patches to support dual-linker configuration.
diff --git a/binutils-2.19/config.sub b/binutils-2.19/config.sub
index 63bfff0..bfbf61d 100755
--- a/binutils-2.19/config.sub
+++ b/binutils-2.19/config.sub
@@ -120,8 +120,9 @@ esac
# Here we must recognize all the valid KERNEL-OS combinations.
maybe_os=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\2/'`
case $maybe_os in
- nto-qnx* | linux-gnu* | linux-dietlibc | linux-newlib* | linux-uclibc* | \
- uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | knetbsd*-gnu* | netbsd*-gnu* | \
+ nto-qnx* | linux-gnu* | linux-android* | linux-dietlibc | linux-newlib* | \
+ linux-uclibc* | uclinux-uclibc* | uclinux-gnu* | kfreebsd*-gnu* | \
+ knetbsd*-gnu* | netbsd*-gnu* | \
storm-chaos* | os2-emx* | rtmk-nova*)
os=-$maybe_os
basic_machine=`echo $1 | sed 's/^\(.*\)-\([^-]*-[^-]*\)$/\1/'`
@@ -1258,7 +1259,8 @@ case $os in
| -udi* | -eabi* | -lites* | -ieee* | -go32* | -aux* \
| -chorusos* | -chorusrdb* \
| -cygwin* | -pe* | -psos* | -moss* | -proelf* | -rtems* \
- | -mingw32* | -linux-gnu* | -linux-newlib* | -linux-uclibc* \
+ | -mingw32* | -linux-gnu* | -linux-android* \
+ | -linux-newlib* | -linux-uclibc* \
| -uxpv* | -beos* | -mpeix* | -udk* \
| -interix* | -uwin* | -mks* | -rhapsody* | -darwin* | -opened* \
| -openstep* | -oskit* | -conix* | -pw32* | -nonstopux* \
diff --git a/binutils-2.19/gold/arm-reloc-property.cc b/binutils-2.19/gold/arm-reloc-property.cc
index 4f8fa9e..007653c 100644
--- a/binutils-2.19/gold/arm-reloc-property.cc
+++ b/binutils-2.19/gold/arm-reloc-property.cc
@@ -104,7 +104,8 @@ Arm_reloc_property::Arm_reloc_property(
relative_address_base_(RAB_NONE), is_deprecated_(is_deprecated),
is_implemented_(is_implemented), checks_overflow_(checks_overflow),
uses_got_entry_(false), uses_got_origin_(false), uses_plt_entry_(false),
- uses_thumb_bit_(false), uses_symbol_base_(false), uses_addend_(false)
+ uses_thumb_bit_(false), uses_symbol_base_(false), uses_addend_(false),
+ uses_symbol_(false)
{
// Set size and alignment of static and dynamic relocations.
if (rtype == RT_STATIC)
@@ -246,6 +247,7 @@ Arm_reloc_property::Arm_reloc_property(
}
gold_assert(node->is_leaf() && node->name() == "S");
+ this->uses_symbol_ = true;
delete root_node;
}
diff --git a/binutils-2.19/gold/arm-reloc-property.h b/binutils-2.19/gold/arm-reloc-property.h
index 349d862..e7d7f50 100644
--- a/binutils-2.19/gold/arm-reloc-property.h
+++ b/binutils-2.19/gold/arm-reloc-property.h
@@ -132,6 +132,11 @@ class Arm_reloc_property
uses_symbol_base() const
{ return this->uses_symbol_base_; }
+ // Whether relocation uses the symbol.
+ bool
+ uses_symbol() const
+ { return this->uses_symbol_; }
+
// Return the type of relative address base or RAB_NONE if this
// is not a relative addressing relocation.
Relative_address_base
@@ -273,6 +278,8 @@ class Arm_reloc_property
bool uses_symbol_base_ : 1;
// Whether this uses an addend.
bool uses_addend_ : 1;
+ // Whether this uses the symbol.
+ bool uses_symbol_ : 1;
};
// Arm_reloc_property_table. This table is used for looking up propeties
diff --git a/binutils-2.19/gold/arm.cc b/binutils-2.19/gold/arm.cc
index 76f28be..566e326 100644
--- a/binutils-2.19/gold/arm.cc
+++ b/binutils-2.19/gold/arm.cc
@@ -1320,7 +1320,10 @@ class Arm_output_section : public Output_section
Arm_output_section(const char* name, elfcpp::Elf_Word type,
elfcpp::Elf_Xword flags)
: Output_section(name, type, flags)
- { }
+ {
+ if (type == elfcpp::SHT_ARM_EXIDX)
+ this->set_always_keeps_input_sections();
+ }
~Arm_output_section()
{ }
@@ -1347,6 +1350,10 @@ class Arm_output_section : public Output_section
const Text_section_list& sorted_text_section,
Symbol_table* symtab);
+ // Link an EXIDX section into its corresponding text section.
+ void
+ set_exidx_section_link();
+
private:
// For convenience.
typedef Output_section::Input_section Input_section;
@@ -1371,7 +1378,7 @@ class Arm_exidx_input_section
Arm_exidx_input_section(Relobj* relobj, unsigned int shndx,
unsigned int link, uint32_t size, uint32_t addralign)
: relobj_(relobj), shndx_(shndx), link_(link), size_(size),
- addralign_(addralign)
+ addralign_(addralign), has_errors_(false)
{ }
~Arm_exidx_input_section()
@@ -1404,6 +1411,16 @@ class Arm_exidx_input_section
addralign() const
{ return this->addralign_; }
+ // Whether there are any errors in the EXIDX input section.
+ bool
+ has_errors() const
+ { return this->has_errors_; }
+
+ // Set has-errors flag.
+ void
+ set_has_errors()
+ { this->has_errors_ = true; }
+
private:
// Object containing this.
Relobj* relobj_;
@@ -1415,6 +1432,8 @@ class Arm_exidx_input_section
uint32_t size_;
// Address alignment of this. For ARM 32-bit is sufficient.
uint32_t addralign_;
+ // Whether this has any errors.
+ bool has_errors_;
};
// Arm_relobj class.
@@ -1576,6 +1595,22 @@ class Arm_relobj : public Sized_relobj<32, big_endian>
merge_flags_and_attributes() const
{ return this->merge_flags_and_attributes_; }
+ // Export list of EXIDX section indices.
+ void
+ get_exidx_shndx_list(std::vector<unsigned int>* list) const
+ {
+ list->clear();
+ for (Exidx_section_map::const_iterator p = this->exidx_section_map_.begin();
+ p != this->exidx_section_map_.end();
+ ++p)
+ {
+ if (p->second->shndx() == p->first)
+ list->push_back(p->first);
+ }
+ // Sort list to make result independent of implementation of map.
+ std::sort(list->begin(), list->end());
+ }
+
protected:
// Post constructor setup.
void
@@ -1648,7 +1683,8 @@ class Arm_relobj : public Sized_relobj<32, big_endian>
void
make_exidx_input_section(unsigned int shndx,
const elfcpp::Shdr<32, big_endian>& shdr,
- unsigned int text_shndx);
+ unsigned int text_shndx,
+ const elfcpp::Shdr<32, big_endian>& text_shdr);
// Return the output address of either a plain input section or a
// relaxed input section. SHNDX is the section index.
@@ -2104,6 +2140,23 @@ class Target_arm : public Sized_target<32, big_endian>
fix_cortex_a8_(false), cortex_a8_relocs_info_()
{ }
+ // Virtual function which is set to return true by a target if
+ // it can use relocation types to determine if a function's
+ // pointer is taken.
+ virtual bool
+ can_check_for_function_pointers() const
+ { return true; }
+
+ // Whether a section called SECTION_NAME may have function pointers to
+ // sections not eligible for safe ICF folding.
+ virtual bool
+ section_may_have_icf_unsafe_pointers(const char* section_name) const
+ {
+ return (!is_prefix_of(".ARM.exidx", section_name)
+ && !is_prefix_of(".ARM.extab", section_name)
+ && Target::section_may_have_icf_unsafe_pointers(section_name));
+ }
+
// Whether we can use BLX.
bool
may_use_blx() const
@@ -2460,8 +2513,7 @@ class Target_arm : public Sized_target<32, big_endian>
Output_section* ,
const elfcpp::Rel<32, big_endian>& ,
unsigned int ,
- const elfcpp::Sym<32, big_endian>&)
- { return false; }
+ const elfcpp::Sym<32, big_endian>&);
inline bool
global_reloc_may_be_function_pointer(Symbol_table* , Layout* , Target_arm* ,
@@ -2469,8 +2521,7 @@ class Target_arm : public Sized_target<32, big_endian>
unsigned int ,
Output_section* ,
const elfcpp::Rel<32, big_endian>& ,
- unsigned int , Symbol*)
- { return false; }
+ unsigned int , Symbol*);
private:
static void
@@ -2501,6 +2552,9 @@ class Target_arm : public Sized_target<32, big_endian>
|| sym->is_preemptible()));
}
+ inline bool
+ possible_function_pointer_reloc(unsigned int r_type);
+
// Whether we have issued an error about a non-PIC compilation.
bool issued_non_pic_error_;
};
@@ -2732,7 +2786,8 @@ class Target_arm : public Sized_target<32, big_endian>
// Fix .ARM.exidx section coverage.
void
- fix_exidx_coverage(Layout*, Arm_output_section<big_endian>*, Symbol_table*);
+ fix_exidx_coverage(Layout*, const Input_objects*,
+ Arm_output_section<big_endian>*, Symbol_table*);
// Functors for STL set.
struct output_section_address_less_than
@@ -5624,10 +5679,6 @@ void
Arm_output_section<big_endian>::append_text_sections_to_list(
Text_section_list* list)
{
- // We only care about text sections.
- if ((this->flags() & elfcpp::SHF_EXECINSTR) == 0)
- return;
-
gold_assert((this->flags() & elfcpp::SHF_ALLOC) != 0);
for (Input_section_list::const_iterator p = this->input_sections().begin();
@@ -5699,9 +5750,10 @@ Arm_output_section<big_endian>::fix_exidx_coverage(
const Arm_exidx_input_section* exidx_input_section =
arm_relobj->exidx_input_section_by_link(shndx);
- // If this text section has no EXIDX section, force an EXIDX_CANTUNWIND
- // entry pointing to the end of the last seen EXIDX section.
- if (exidx_input_section == NULL)
+ // If this text section has no EXIDX section or if the EXIDX section
+ // has errors, force an EXIDX_CANTUNWIND entry pointing to the end
+ // of the last seen EXIDX section.
+ if (exidx_input_section == NULL || exidx_input_section->has_errors())
{
exidx_fixup.add_exidx_cantunwind_as_needed();
continue;
@@ -5785,15 +5837,20 @@ Arm_output_section<big_endian>::fix_exidx_coverage(
if (processed_input_sections.find(Section_id(p->relobj(), p->shndx()))
== processed_input_sections.end())
{
- // We only discard a known EXIDX section because its linked
- // text section has been folded by ICF.
+ // We discard a known EXIDX section because its linked
+ // text section has been folded by ICF. We also discard an
+ // EXIDX section with error, the output does not matter in this
+ // case. We do this to avoid triggering asserts.
Arm_relobj<big_endian>* arm_relobj =
Arm_relobj<big_endian>::as_arm_relobj(p->relobj());
const Arm_exidx_input_section* exidx_input_section =
arm_relobj->exidx_input_section_by_shndx(p->shndx());
gold_assert(exidx_input_section != NULL);
- unsigned int text_shndx = exidx_input_section->link();
- gold_assert(symtab->is_section_folded(p->relobj(), text_shndx));
+ if (!exidx_input_section->has_errors())
+ {
+ unsigned int text_shndx = exidx_input_section->link();
+ gold_assert(symtab->is_section_folded(p->relobj(), text_shndx));
+ }
// Remove this from link. We also need to recount the
// local symbols.
@@ -5812,6 +5869,28 @@ Arm_output_section<big_endian>::fix_exidx_coverage(
this->set_section_offsets_need_adjustment();
}
+// Link EXIDX output sections to text output sections.
+
+template<bool big_endian>
+void
+Arm_output_section<big_endian>::set_exidx_section_link()
+{
+ gold_assert(this->type() == elfcpp::SHT_ARM_EXIDX);
+ if (!this->input_sections().empty())
+ {
+ Input_section_list::const_iterator p = this->input_sections().begin();
+ Arm_relobj<big_endian>* arm_relobj =
+ Arm_relobj<big_endian>::as_arm_relobj(p->relobj());
+ unsigned exidx_shndx = p->shndx();
+ const Arm_exidx_input_section* exidx_input_section =
+ arm_relobj->exidx_input_section_by_shndx(exidx_shndx);
+ gold_assert(exidx_input_section != NULL);
+ unsigned int text_shndx = exidx_input_section->link();
+ Output_section* os = arm_relobj->output_section(text_shndx);
+ this->set_link_section(os);
+ }
+}
+
// Arm_relobj methods.
// Determine if an input section is scannable for stub processing. SHDR is
@@ -6413,28 +6492,57 @@ void
Arm_relobj<big_endian>::make_exidx_input_section(
unsigned int shndx,
const elfcpp::Shdr<32, big_endian>& shdr,
- unsigned int text_shndx)
+ unsigned int text_shndx,
+ const elfcpp::Shdr<32, big_endian>& text_shdr)
{
- // Issue an error and ignore this EXIDX section if it points to a text
- // section already has an EXIDX section.
- if (this->exidx_section_map_[text_shndx] != NULL)
- {
- gold_error(_("EXIDX sections %u and %u both link to text section %u "
- "in %s"),
- shndx, this->exidx_section_map_[text_shndx]->shndx(),
- text_shndx, this->name().c_str());
- return;
- }
-
// Create an Arm_exidx_input_section object for this EXIDX section.
Arm_exidx_input_section* exidx_input_section =
new Arm_exidx_input_section(this, shndx, text_shndx, shdr.get_sh_size(),
shdr.get_sh_addralign());
- this->exidx_section_map_[text_shndx] = exidx_input_section;
- // Also map the EXIDX section index to this.
gold_assert(this->exidx_section_map_[shndx] == NULL);
this->exidx_section_map_[shndx] = exidx_input_section;
+
+ if (text_shndx == elfcpp::SHN_UNDEF || text_shndx >= this->shnum())
+ {
+ gold_error(_("EXIDX section %s(%u) links to invalid section %u in %s"),
+ this->section_name(shndx).c_str(), shndx, text_shndx,
+ this->name().c_str());
+ exidx_input_section->set_has_errors();
+ }
+ else if (this->exidx_section_map_[text_shndx] != NULL)
+ {
+ unsigned other_exidx_shndx =
+ this->exidx_section_map_[text_shndx]->shndx();
+ gold_error(_("EXIDX sections %s(%u) and %s(%u) both link to text section"
+ "%s(%u) in %s"),
+ this->section_name(shndx).c_str(), shndx,
+ this->section_name(other_exidx_shndx).c_str(),
+ other_exidx_shndx, this->section_name(text_shndx).c_str(),
+ text_shndx, this->name().c_str());
+ exidx_input_section->set_has_errors();
+ }
+ else
+ this->exidx_section_map_[text_shndx] = exidx_input_section;
+
+ // Check section flags of text section.
+ if ((text_shdr.get_sh_flags() & elfcpp::SHF_ALLOC) == 0)
+ {
+ gold_error(_("EXIDX section %s(%u) links to non-allocated section %s(%u) "
+ " in %s"),
+ this->section_name(shndx).c_str(), shndx,
+ this->section_name(text_shndx).c_str(), text_shndx,
+ this->name().c_str());
+ exidx_input_section->set_has_errors();
+ }
+ else if ((text_shdr.get_sh_flags() & elfcpp::SHF_EXECINSTR) == 0)
+ // I would like to make this an error but currenlty ld just ignores
+ // this.
+ gold_warning(_("EXIDX section %s(%u) links to non-executable section "
+ "%s(%u) in %s"),
+ this->section_name(shndx).c_str(), shndx,
+ this->section_name(text_shndx).c_str(), text_shndx,
+ this->name().c_str());
}
// Read the symbol information.
@@ -6504,19 +6612,21 @@ Arm_relobj<big_endian>::do_read_symbols(Read_symbols_data* sd)
else if (shdr.get_sh_type() == elfcpp::SHT_ARM_EXIDX)
{
unsigned int text_shndx = this->adjust_shndx(shdr.get_sh_link());
- if (text_shndx >= this->shnum())
- gold_error(_("EXIDX section %u linked to invalid section %u"),
- i, text_shndx);
- else if (text_shndx == elfcpp::SHN_UNDEF)
+ if (text_shndx == elfcpp::SHN_UNDEF)
deferred_exidx_sections.push_back(i);
else
- this->make_exidx_input_section(i, shdr, text_shndx);
+ {
+ elfcpp::Shdr<32, big_endian> text_shdr(pshdrs
+ + text_shndx * shdr_size);
+ this->make_exidx_input_section(i, shdr, text_shndx, text_shdr);
+ }
}
}
// This is rare.
if (!must_merge_flags_and_attributes)
{
+ gold_assert(deferred_exidx_sections.empty());
this->merge_flags_and_attributes_ = false;
return;
}
@@ -6572,15 +6682,14 @@ Arm_relobj<big_endian>::do_read_symbols(Read_symbols_data* sd)
{
unsigned int shndx = deferred_exidx_sections[i];
elfcpp::Shdr<32, big_endian> shdr(pshdrs + shndx * shdr_size);
- unsigned int text_shndx;
+ unsigned int text_shndx = elfcpp::SHN_UNDEF;
Reloc_map::const_iterator it = reloc_map.find(shndx);
- if (it != reloc_map.end()
- && find_linked_text_section(pshdrs + it->second * shdr_size,
- psyms, &text_shndx))
- this->make_exidx_input_section(shndx, shdr, text_shndx);
- else
- gold_error(_("EXIDX section %u has no linked text section."),
- shndx);
+ if (it != reloc_map.end())
+ find_linked_text_section(pshdrs + it->second * shdr_size,
+ psyms, &text_shndx);
+ elfcpp::Shdr<32, big_endian> text_shdr(pshdrs
+ + text_shndx * shdr_size);
+ this->make_exidx_input_section(shndx, shdr, text_shndx, text_shdr);
}
}
}
@@ -7672,6 +7781,72 @@ Target_arm<big_endian>::Scan::unsupported_reloc_global(
object->name().c_str(), r_type, gsym->demangled_name().c_str());
}
+template<bool big_endian>
+inline bool
+Target_arm<big_endian>::Scan::possible_function_pointer_reloc(
+ unsigned int r_type)
+{
+ switch (r_type)
+ {
+ case elfcpp::R_ARM_PC24:
+ case elfcpp::R_ARM_THM_CALL:
+ case elfcpp::R_ARM_PLT32:
+ case elfcpp::R_ARM_CALL:
+ case elfcpp::R_ARM_JUMP24:
+ case elfcpp::R_ARM_THM_JUMP24:
+ case elfcpp::R_ARM_SBREL31:
+ case elfcpp::R_ARM_PREL31:
+ case elfcpp::R_ARM_THM_JUMP19:
+ case elfcpp::R_ARM_THM_JUMP6:
+ case elfcpp::R_ARM_THM_JUMP11:
+ case elfcpp::R_ARM_THM_JUMP8:
+ // All the relocations above are branches except SBREL31 and PREL31.
+ return false;
+
+ default:
+ // Be conservative and assume this is a function pointer.
+ return true;
+ }
+}
+
+template<bool big_endian>
+inline bool
+Target_arm<big_endian>::Scan::local_reloc_may_be_function_pointer(
+ Symbol_table*,
+ Layout*,
+ Target_arm<big_endian>* target,
+ Sized_relobj<32, big_endian>*,
+ unsigned int,
+ Output_section*,
+ const elfcpp::Rel<32, big_endian>&,
+ unsigned int r_type,
+ const elfcpp::Sym<32, big_endian>&)
+{
+ r_type = target->get_real_reloc_type(r_type);
+ return possible_function_pointer_reloc(r_type);
+}
+
+template<bool big_endian>
+inline bool
+Target_arm<big_endian>::Scan::global_reloc_may_be_function_pointer(
+ Symbol_table*,
+ Layout*,
+ Target_arm<big_endian>* target,
+ Sized_relobj<32, big_endian>*,
+ unsigned int,
+ Output_section*,
+ const elfcpp::Rel<32, big_endian>&,
+ unsigned int r_type,
+ Symbol* gsym)
+{
+ // GOT is not a function.
+ if (strcmp(gsym->name(), "_GLOBAL_OFFSET_TABLE_") == 0)
+ return false;
+
+ r_type = target->get_real_reloc_type(r_type);
+ return possible_function_pointer_reloc(r_type);
+}
+
// Scan a relocation for a global symbol.
template<bool big_endian>
@@ -8090,6 +8265,7 @@ Target_arm<big_endian>::do_finalize_sections(
if (this->attributes_section_data_ == NULL)
this->attributes_section_data_ = new Attributes_section_data(NULL, 0);
+ bool merged_any_attributes = false;
// Merge processor-specific flags.
for (Input_objects::Relobj_iterator p = input_objects->relobj_begin();
p != input_objects->relobj_end();
@@ -8104,6 +8280,7 @@ Target_arm<big_endian>::do_finalize_sections(
arm_relobj->processor_specific_flags());
this->merge_object_attributes(arm_relobj->name().c_str(),
arm_relobj->attributes_section_data());
+ merged_any_attributes = true;
}
}
@@ -8118,6 +8295,7 @@ Target_arm<big_endian>::do_finalize_sections(
arm_dynobj->processor_specific_flags());
this->merge_object_attributes(arm_dynobj->name().c_str(),
arm_dynobj->attributes_section_data());
+ merged_any_attributes = true;
}
// Check BLX use.
@@ -8193,9 +8371,9 @@ Target_arm<big_endian>::do_finalize_sections(
}
}
- // Create an .ARM.attributes section unless we have no regular input
- // object. In that case the output will be empty.
- if (input_objects->number_of_relobjs() != 0)
+ // Create an .ARM.attributes section if we have merged any attributes
+ // from inputs.
+ if (merged_any_attributes)
{
Output_attributes_section_data* attributes_section =
new Output_attributes_section_data(*this->attributes_section_data_);
@@ -8204,6 +8382,17 @@ Target_arm<big_endian>::do_finalize_sections(
attributes_section, false, false, false,
false);
}
+
+ // Fix up links in section EXIDX headers.
+ for (Layout::Section_list::const_iterator p = layout->section_list().begin();
+ p != layout->section_list().end();
+ ++p)
+ if ((*p)->type() == elfcpp::SHT_ARM_EXIDX)
+ {
+ Arm_output_section<big_endian>* os =
+ Arm_output_section<big_endian>::as_arm_output_section(*p);
+ os->set_exidx_section_link();
+ }
}
// Return whether a direct absolute static relocation needs to be applied.
@@ -8306,6 +8495,13 @@ Target_arm<big_endian>::Relocate::relocate(
// be converted into an NOP.
is_weakly_undefined_without_plt = true;
}
+ else if (gsym->is_undefined() && reloc_property->uses_symbol())
+ {
+ // This relocation uses the symbol value but the symbol is
+ // undefined. Exit early and have the caller reporting an
+ // error.
+ return true;
+ }
else
{
// Set thumb bit if symbol:
@@ -10760,12 +10956,6 @@ Target_arm<big_endian>::do_relax(
bool stubs_always_after_branch = stub_group_size_param < 0;
section_size_type stub_group_size = abs(stub_group_size_param);
- // The Cortex-A8 erratum fix depends on stubs not being in the same 4K
- // page as the first half of a 32-bit branch straddling two 4K pages.
- // This is a crude way of enforcing that.
- if (this->fix_cortex_a8_)
- stubs_always_after_branch = true;
-
if (stub_group_size == 1)
{
// Default value.
@@ -10775,25 +10965,51 @@ Target_arm<big_endian>::do_relax(
// fixing cortex-a8 errata, the branch range has to be even smaller,
// since wide conditional branch has a range of +-1MB only.
//
- // This value is 24K less than that, which allows for 2025
+ // This value is 48K less than that, which allows for 4096
// 12-byte stubs. If we exceed that, then we will fail to link.
// The user will have to relink with an explicit group size
// option.
- if (this->fix_cortex_a8_)
- stub_group_size = 1024276;
- else
- stub_group_size = 4170000;
+ stub_group_size = 4145152;
+ }
+
+ // The Cortex-A8 erratum fix depends on stubs not being in the same 4K
+ // page as the first half of a 32-bit branch straddling two 4K pages.
+ // This is a crude way of enforcing that. In addition, long conditional
+ // branches of THUMB-2 have a range of +-1M. If we are fixing cortex-A8
+ // erratum, limit the group size to (1M - 12k) to avoid unreachable
+ // cortex-A8 stubs from long conditional branches.
+ if (this->fix_cortex_a8_)
+ {
+ stubs_always_after_branch = true;
+ const section_size_type cortex_a8_group_size = 1024 * (1024 - 12);
+ stub_group_size = std::max(stub_group_size, cortex_a8_group_size);
}
group_sections(layout, stub_group_size, stubs_always_after_branch);
// Also fix .ARM.exidx section coverage.
- Output_section* os = layout->find_output_section(".ARM.exidx");
- if (os != NULL && os->type() == elfcpp::SHT_ARM_EXIDX)
+ Arm_output_section<big_endian>* exidx_output_section = NULL;
+ for (Layout::Section_list::const_iterator p =
+ layout->section_list().begin();
+ p != layout->section_list().end();
+ ++p)
+ if ((*p)->type() == elfcpp::SHT_ARM_EXIDX)
+ {
+ if (exidx_output_section == NULL)
+ exidx_output_section =
+ Arm_output_section<big_endian>::as_arm_output_section(*p);
+ else
+ // We cannot handle this now.
+ gold_error(_("multiple SHT_ARM_EXIDX sections %s and %s in a "
+ "non-relocatable link"),
+ exidx_output_section->name(),
+ (*p)->name());
+ }
+
+ if (exidx_output_section != NULL)
{
- Arm_output_section<big_endian>* exidx_output_section =
- Arm_output_section<big_endian>::as_arm_output_section(os);
- this->fix_exidx_coverage(layout, exidx_output_section, symtab);
+ this->fix_exidx_coverage(layout, input_objects, exidx_output_section,
+ symtab);
done_exidx_fixup = true;
}
}
@@ -11244,6 +11460,7 @@ template<bool big_endian>
void
Target_arm<big_endian>::fix_exidx_coverage(
Layout* layout,
+ const Input_objects* input_objects,
Arm_output_section<big_endian>* exidx_section,
Symbol_table* symtab)
{
@@ -11256,15 +11473,30 @@ Target_arm<big_endian>::fix_exidx_coverage(
typedef std::set<Output_section*, output_section_address_less_than>
Sorted_output_section_list;
Sorted_output_section_list sorted_output_sections;
- Layout::Section_list section_list;
- layout->get_allocated_sections(&section_list);
- for (Layout::Section_list::const_iterator p = section_list.begin();
- p != section_list.end();
+
+ // Find out all the output sections of input sections pointed by
+ // EXIDX input sections.
+ for (Input_objects::Relobj_iterator p = input_objects->relobj_begin();
+ p != input_objects->relobj_end();
++p)
{
- // We only care about output sections that contain executable code.
- if (((*p)->flags() & elfcpp::SHF_EXECINSTR) != 0)
- sorted_output_sections.insert(*p);
+ Arm_relobj<big_endian>* arm_relobj =
+ Arm_relobj<big_endian>::as_arm_relobj(*p);
+ std::vector<unsigned int> shndx_list;
+ arm_relobj->get_exidx_shndx_list(&shndx_list);
+ for (size_t i = 0; i < shndx_list.size(); ++i)
+ {
+ const Arm_exidx_input_section* exidx_input_section =
+ arm_relobj->exidx_input_section_by_shndx(shndx_list[i]);
+ gold_assert(exidx_input_section != NULL);
+ if (!exidx_input_section->has_errors())
+ {
+ unsigned int text_shndx = exidx_input_section->link();
+ Output_section *os = arm_relobj->output_section(text_shndx);
+ if (os != NULL && (os->flags() & elfcpp::SHF_ALLOC) != 0)
+ sorted_output_sections.insert(os);
+ }
+ }
}
// Go over the output sections in ascending order of output addresses.
diff --git a/binutils-2.19/gold/gc.h b/binutils-2.19/gold/gc.h
index b79bd77..77ac6da 100644
--- a/binutils-2.19/gold/gc.h
+++ b/binutils-2.19/gold/gc.h
@@ -228,14 +228,14 @@ gc_process_relocs(
unsigned int shndx = lsym.get_st_shndx();
bool is_ordinary;
shndx = src_obj->adjust_sym_shndx(r_sym, shndx, &is_ordinary);
- if (!is_ordinary)
- continue;
dst_obj = src_obj;
dst_indx = shndx;
- Section_id dst_id(dst_obj, dst_indx);
if (is_icf_tracked)
{
- (*secvec).push_back(dst_id);
+ if (is_ordinary)
+ (*secvec).push_back(Section_id(dst_obj, dst_indx));
+ else
+ (*secvec).push_back(Section_id(NULL, 0));
(*symvec).push_back(NULL);
long long symvalue = static_cast<long long>(lsym.get_st_value());
(*addendvec).push_back(std::make_pair(symvalue,
@@ -247,7 +247,8 @@ gc_process_relocs(
// When doing safe folding, check to see if this relocation is that
// of a function pointer being taken.
- if (check_section_for_function_pointers
+ if (is_ordinary
+ && check_section_for_function_pointers
&& lsym.get_st_type() != elfcpp::STT_OBJECT
&& scan.local_reloc_may_be_function_pointer(symtab, NULL, NULL,
src_obj, src_indx,
@@ -256,7 +257,7 @@ gc_process_relocs(
symtab->icf()->set_section_has_function_pointers(
src_obj, lsym.get_st_shndx());
- if (shndx == src_indx)
+ if (!is_ordinary || shndx == src_indx)
continue;
}
else
@@ -265,16 +266,20 @@ gc_process_relocs(
gold_assert(gsym != NULL);
if (gsym->is_forwarder())
gsym = symtab->resolve_forwards(gsym);
- if (gsym->source() != Symbol::FROM_OBJECT)
- continue;
- bool is_ordinary;
- dst_obj = gsym->object();
- dst_indx = gsym->shndx(&is_ordinary);
- Section_id dst_id(dst_obj, dst_indx);
+
+ dst_obj = NULL;
+ dst_indx = 0;
+ bool is_ordinary = false;
+ if (gsym->source() == Symbol::FROM_OBJECT)
+ {
+ dst_obj = gsym->object();
+ dst_indx = gsym->shndx(&is_ordinary);
+ }
// When doing safe folding, check to see if this relocation is that
// of a function pointer being taken.
- if (check_section_for_function_pointers
+ if (gsym->source() == Symbol::FROM_OBJECT
+ && check_section_for_function_pointers
&& gsym->type() != elfcpp::STT_OBJECT
&& (!is_ordinary
|| scan.global_reloc_may_be_function_pointer(
@@ -282,9 +287,6 @@ gc_process_relocs(
r_type, gsym)))
symtab->icf()->set_section_has_function_pointers(dst_obj, dst_indx);
- if (!is_ordinary)
- continue;
-
// If the symbol name matches '__start_XXX' then the section with
// the C identifier like name 'XXX' should not be garbage collected.
// A similar treatment to symbols with the name '__stop_XXX'.
@@ -300,7 +302,10 @@ gc_process_relocs(
}
if (is_icf_tracked)
{
- (*secvec).push_back(dst_id);
+ if (is_ordinary && gsym->source() == Symbol::FROM_OBJECT)
+ (*secvec).push_back(Section_id(dst_obj, dst_indx));
+ else
+ (*secvec).push_back(Section_id(NULL, 0));
(*symvec).push_back(gsym);
Sized_symbol<size>* sized_gsym =
static_cast<Sized_symbol<size>* >(gsym);
@@ -312,6 +317,11 @@ gc_process_relocs(
convert_to_section_size_type(reloc.get_r_offset());
(*offsetvec).push_back(reloc_offset);
}
+
+ if (gsym->source() != Symbol::FROM_OBJECT)
+ continue;
+ if (!is_ordinary)
+ continue;
}
if (parameters->options().gc_sections())
{
diff --git a/binutils-2.19/gold/i386.cc b/binutils-2.19/gold/i386.cc
index eb4ef0a..e7b700c 100644
--- a/binutils-2.19/gold/i386.cc
+++ b/binutils-2.19/gold/i386.cc
@@ -64,6 +64,10 @@ class Target_i386 : public Target_freebsd<32, false>
got_mod_index_offset_(-1U), tls_base_symbol_defined_(false)
{ }
+ inline bool
+ can_check_for_function_pointers() const
+ { return true; }
+
// Process the relocations to determine unreferenced sections for
// garbage collection.
void
@@ -203,24 +207,27 @@ class Target_i386 : public Target_freebsd<32, false>
Symbol* gsym);
inline bool
- local_reloc_may_be_function_pointer(Symbol_table* , Layout* , Target_i386* ,
- Sized_relobj<32, false>* ,
- unsigned int ,
- Output_section* ,
- const elfcpp::Rel<32, false>& ,
- unsigned int ,
- const elfcpp::Sym<32, false>&)
- { return false; }
+ local_reloc_may_be_function_pointer(Symbol_table* symtab, Layout* layout,
+ Target_i386* target,
+ Sized_relobj<32, false>* object,
+ unsigned int data_shndx,
+ Output_section* output_section,
+ const elfcpp::Rel<32, false>& reloc,
+ unsigned int r_type,
+ const elfcpp::Sym<32, false>& lsym);
+
+ inline bool
+ global_reloc_may_be_function_pointer(Symbol_table* symtab, Layout* layout,
+ Target_i386* target,
+ Sized_relobj<32, false>* object,
+ unsigned int data_shndx,
+ Output_section* output_section,
+ const elfcpp::Rel<32, false>& reloc,
+ unsigned int r_type,
+ Symbol* gsym);
inline bool
- global_reloc_may_be_function_pointer(Symbol_table* , Layout* ,
- Target_i386* ,
- Sized_relobj<32, false>* ,
- unsigned int ,
- Output_section* ,
- const elfcpp::Rel<32, false>& ,
- unsigned int , Symbol*)
- { return false; }
+ possible_function_pointer_reloc(unsigned int r_type);
static void
unsupported_reloc_local(Sized_relobj<32, false>*, unsigned int r_type);
@@ -1234,6 +1241,55 @@ Target_i386::Scan::unsupported_reloc_global(Sized_relobj<32, false>* object,
object->name().c_str(), r_type, gsym->demangled_name().c_str());
}
+inline bool
+Target_i386::Scan::possible_function_pointer_reloc(unsigned int r_type)
+{
+ switch (r_type)
+ {
+ case elfcpp::R_386_32:
+ case elfcpp::R_386_16:
+ case elfcpp::R_386_8:
+ case elfcpp::R_386_GOTOFF:
+ case elfcpp::R_386_GOT32:
+ {
+ return true;
+ }
+ default:
+ return false;
+ }
+ return false;
+}
+
+inline bool
+Target_i386::Scan::local_reloc_may_be_function_pointer(
+ Symbol_table* ,
+ Layout* ,
+ Target_i386* ,
+ Sized_relobj<32, false>* ,
+ unsigned int ,
+ Output_section* ,
+ const elfcpp::Rel<32, false>& ,
+ unsigned int r_type,
+ const elfcpp::Sym<32, false>&)
+{
+ return possible_function_pointer_reloc(r_type);
+}
+
+inline bool
+Target_i386::Scan::global_reloc_may_be_function_pointer(
+ Symbol_table* ,
+ Layout* ,
+ Target_i386* ,
+ Sized_relobj<32, false>* ,
+ unsigned int ,
+ Output_section* ,
+ const elfcpp::Rel<32, false>& ,
+ unsigned int r_type,
+ Symbol*)
+{
+ return possible_function_pointer_reloc(r_type);
+}
+
// Scan a relocation for a global symbol.
inline void
diff --git a/binutils-2.19/gold/icf.cc b/binutils-2.19/gold/icf.cc
index ff2058c..47b6c60 100644
--- a/binutils-2.19/gold/icf.cc
+++ b/binutils-2.19/gold/icf.cc
@@ -263,8 +263,11 @@ get_section_contents(bool first_iteration,
{
Icf::Sections_reachable_info v =
(it_reloc_info_list->second).section_info;
+ // Stores the information of the symbol pointed to by the reloc.
Icf::Symbol_info s = (it_reloc_info_list->second).symbol_info;
+ // Stores the addend and the symbol value.
Icf::Addend_info a = (it_reloc_info_list->second).addend_info;
+ // Stores the offset of the reloc.
Icf::Offset_info o = (it_reloc_info_list->second).offset_info;
Icf::Sections_reachable_info::iterator it_v = v.begin();
Icf::Symbol_info::iterator it_s = s.begin();
@@ -285,6 +288,24 @@ get_section_contents(bool first_iteration,
static_cast<long long>((*it_a).first),
static_cast<long long>((*it_a).second),
static_cast<unsigned long long>(*it_o));
+
+ // If the symbol pointed to by the reloc is not in an ordinary
+ // section or if the symbol type is not FROM_OBJECT, then the
+ // object is NULL.
+ if (it_v->first == NULL)
+ {
+ if (first_iteration)
+ {
+ // If the symbol name is available, use it.
+ if ((*it_s) != NULL)
+ buffer.append((*it_s)->name());
+ // Append the addend.
+ buffer.append(addend_str);
+ buffer.append("@");
+ }
+ continue;
+ }
+
Section_id reloc_secn(it_v->first, it_v->second);
// If this reloc turns back and points to the same section,
@@ -304,7 +325,12 @@ get_section_contents(bool first_iteration,
symtab->icf()->section_to_int_map();
Icf::Uniq_secn_id_map::iterator section_id_map_it =
section_id_map.find(reloc_secn);
- if (section_id_map_it != section_id_map.end())
+ bool is_sym_preemptible = (*it_s != NULL
+ && !(*it_s)->is_from_dynobj()
+ && !(*it_s)->is_undefined()
+ && (*it_s)->is_preemptible());
+ if (!is_sym_preemptible
+ && section_id_map_it != section_id_map.end())
{
// This is a reloc to a section that might be folded.
if (num_tracked_relocs)
@@ -338,7 +364,14 @@ get_section_contents(bool first_iteration,
{
uint64_t entsize =
(it_v->first)->section_entsize(it_v->second);
- long long offset = it_a->first + it_a->second;
+ long long offset = it_a->first;
+
+ unsigned long long addend = it_a->second;
+ // Ignoring the addend when it is a negative value. See the
+ // comments in Merged_symbol_value::Value in object.h.
+ if (addend < 0xffffff00)
+ offset = offset + addend;
+
section_size_type secn_len;
const unsigned char* str_contents =
(it_v->first)->section_contents(it_v->second,
@@ -389,12 +422,12 @@ get_section_contents(bool first_iteration,
char*>(str_contents),
entsize);
}
+ buffer.append("@");
}
else if ((*it_s) != NULL)
{
// If symbol name is available use that.
- const char *sym_name = (*it_s)->name();
- buffer.append(sym_name);
+ buffer.append((*it_s)->name());
// Append the addend.
buffer.append(addend_str);
buffer.append("@");
diff --git a/binutils-2.19/gold/icf.h b/binutils-2.19/gold/icf.h
index c1db8e5..c968c9d 100644
--- a/binutils-2.19/gold/icf.h
+++ b/binutils-2.19/gold/icf.h
@@ -121,13 +121,13 @@ class Icf
// corresponding to taken function pointers. Ignores eh_frame
// and vtable sections.
inline bool
- check_section_for_function_pointers(std::string section_name,
+ check_section_for_function_pointers(const std::string& section_name,
Target* target)
{
return (parameters->options().icf_safe_folding()
&& target->can_check_for_function_pointers()
- && !is_prefix_of(".rodata._ZTV", section_name.c_str())
- && !is_prefix_of(".eh_frame", section_name.c_str()));
+ && target->section_may_have_icf_unsafe_pointers(
+ section_name.c_str()));
}
// Returns a map of a section to info (Reloc_info) about its relocations.
diff --git a/binutils-2.19/gold/output.cc b/binutils-2.19/gold/output.cc
index dbdad78..280b125 100644
--- a/binutils-2.19/gold/output.cc
+++ b/binutils-2.19/gold/output.cc
@@ -1944,6 +1944,7 @@ Output_section::Output_section(const char* name, elfcpp::Elf_Word type,
is_entsize_zero_(false),
section_offsets_need_adjustment_(false),
is_noload_(false),
+ always_keeps_input_sections_(false),
tls_offset_(0),
checkpoint_(NULL),
lookup_maps_(new Output_section_lookup_maps)
@@ -2032,8 +2033,10 @@ Output_section::add_input_section(Sized_relobj<size, big_endian>* object,
{
// Keep information about merged input sections for rebuilding fast
// lookup maps if we have sections-script or we do relaxation.
- bool keeps_input_sections =
- have_sections_script || parameters->target().may_relax();
+ bool keeps_input_sections = (this->always_keeps_input_sections_
+ || have_sections_script
+ || parameters->target().may_relax());
+
if (this->add_merge_input_section(object, shndx, sh_flags, entsize,
addralign, keeps_input_sections))
{
@@ -2087,7 +2090,8 @@ Output_section::add_input_section(Sized_relobj<size, big_endian>* object,
// track of sections, or if we are relaxing. Also, if this is a
// section which requires sorting, or which may require sorting in
// the future, we keep track of the sections.
- if (have_sections_script
+ if (this->always_keeps_input_sections_
+ || have_sections_script
|| !this->input_sections_.empty()
|| this->may_sort_attached_input_sections()
|| this->must_sort_attached_input_sections()
diff --git a/binutils-2.19/gold/output.h b/binutils-2.19/gold/output.h
index da321b6..28bcb65 100644
--- a/binutils-2.19/gold/output.h
+++ b/binutils-2.19/gold/output.h
@@ -3437,6 +3437,19 @@ class Output_section : public Output_data
input_sections() const
{ return this->input_sections_; }
+ // Whether this always keeps an input section list
+ bool
+ always_keeps_input_sections() const
+ { return this->always_keeps_input_sections_; }
+
+ // Always keep an input section list.
+ void
+ set_always_keeps_input_sections()
+ {
+ gold_assert(this->current_data_size_for_child() == 0);
+ this->always_keeps_input_sections_ = true;
+ }
+
private:
// We only save enough information to undo the effects of section layout.
class Checkpoint_output_section
@@ -3741,6 +3754,8 @@ class Output_section : public Output_data
bool section_offsets_need_adjustment_ : 1;
// Whether this is a NOLOAD section.
bool is_noload_ : 1;
+ // Whether this always keeps input section.
+ bool always_keeps_input_sections_ : 1;
// For SHT_TLS sections, the offset of this section relative to the base
// of the TLS segment.
uint64_t tls_offset_;
diff --git a/binutils-2.19/gold/symtab.cc b/binutils-2.19/gold/symtab.cc
index c2a811f..416a07c 100644
--- a/binutils-2.19/gold/symtab.cc
+++ b/binutils-2.19/gold/symtab.cc
@@ -306,7 +306,7 @@ Sized_symbol<size>::allocate_common(Output_data* od, Value_type value)
// table.
inline bool
-Symbol::should_add_dynsym_entry() const
+Symbol::should_add_dynsym_entry(Symbol_table* symtab) const
{
// If the symbol is used by a dynamic relocation, we need to add it.
if (this->needs_dynsym_entry())
@@ -324,7 +324,8 @@ Symbol::should_add_dynsym_entry() const
bool is_ordinary;
unsigned int shndx = this->shndx(&is_ordinary);
if (is_ordinary && shndx != elfcpp::SHN_UNDEF
- && !relobj->is_section_included(shndx))
+ && !relobj->is_section_included(shndx)
+ && !symtab->is_section_folded(relobj, shndx))
return false;
}
@@ -1072,7 +1073,8 @@ Symbol_table::add_from_relobj(
bool is_defined_in_discarded_section = false;
if (st_shndx != elfcpp::SHN_UNDEF
&& is_ordinary
- && !relobj->is_section_included(st_shndx))
+ && !relobj->is_section_included(st_shndx)
+ && !this->is_section_folded(relobj, st_shndx))
{
st_shndx = elfcpp::SHN_UNDEF;
is_defined_in_discarded_section = true;
@@ -2253,7 +2255,7 @@ Symbol_table::set_dynsym_indexes(unsigned int index,
// some symbols appear more than once in the symbol table, with
// and without a version.
- if (!sym->should_add_dynsym_entry())
+ if (!sym->should_add_dynsym_entry(this))
sym->set_dynsym_index(-1U);
else if (!sym->has_dynsym_index())
{
diff --git a/binutils-2.19/gold/symtab.h b/binutils-2.19/gold/symtab.h
index 1a81fd1..4a97461 100644
--- a/binutils-2.19/gold/symtab.h
+++ b/binutils-2.19/gold/symtab.h
@@ -274,7 +274,7 @@ class Symbol
// Return whether this symbol should be added to the dynamic symbol
// table.
bool
- should_add_dynsym_entry() const;
+ should_add_dynsym_entry(Symbol_table*) const;
// Return whether this symbol has been seen in a regular object.
bool
diff --git a/binutils-2.19/gold/target-reloc.h b/binutils-2.19/gold/target-reloc.h
index 0bd060b..34c13e8 100644
--- a/binutils-2.19/gold/target-reloc.h
+++ b/binutils-2.19/gold/target-reloc.h
@@ -83,7 +83,8 @@ scan_relocs(
shndx = object->adjust_sym_shndx(r_sym, shndx, &is_ordinary);
if (is_ordinary
&& shndx != elfcpp::SHN_UNDEF
- && !object->is_section_included(shndx))
+ && !object->is_section_included(shndx)
+ && !symtab->is_section_folded(object, shndx))
{
// RELOC is a relocation against a local symbol in a
// section we are discarding. We can ignore this
@@ -102,7 +103,6 @@ scan_relocs(
continue;
}
-
scan.local(symtab, layout, target, object, data_shndx,
output_section, reloc, r_type, lsym);
}
diff --git a/binutils-2.19/gold/target.h b/binutils-2.19/gold/target.h
index 02cbee2..563a365 100644
--- a/binutils-2.19/gold/target.h
+++ b/binutils-2.19/gold/target.h
@@ -71,6 +71,20 @@ class Target
can_check_for_function_pointers() const
{ return false; }
+ // Whether a section called SECTION_NAME may have function pointers to
+ // sections not eligible for safe ICF folding.
+ virtual bool
+ section_may_have_icf_unsafe_pointers(const char* section_name) const
+ {
+ // We recognize sections for normal vtables, construction vtables and
+ // EH frames.
+ return (!is_prefix_of(".rodata._ZTV", section_name)
+ && !is_prefix_of(".data.rel.ro._ZTV", section_name)
+ && !is_prefix_of(".rodata._ZTC", section_name)
+ && !is_prefix_of(".data.rel.ro._ZTC", section_name)
+ && !is_prefix_of(".eh_frame", section_name));
+ }
+
// Return the bit size that this target implements. This should
// return 32 or 64.
int
diff --git a/binutils-2.19/gold/testsuite/Makefile.am b/binutils-2.19/gold/testsuite/Makefile.am
index 34abf89..764ec26 100644
--- a/binutils-2.19/gold/testsuite/Makefile.am
+++ b/binutils-2.19/gold/testsuite/Makefile.am
@@ -193,6 +193,33 @@ icf_safe_so_test_1.stdout: icf_safe_so_test
icf_safe_so_test_2.stdout: icf_safe_so_test
$(TEST_READELF) -h icf_safe_so_test > icf_safe_so_test_2.stdout
+check_PROGRAMS += icf_virtual_function_folding_test
+MOSTLYCLEANFILES += icf_virtual_function_folding_test
+icf_virtual_function_folding_test.o: icf_virtual_function_folding_test.cc
+ $(CXXCOMPILE) -O0 -c -ffunction-sections -fPIE -g -o $@ $<
+icf_virtual_function_folding_test: icf_virtual_function_folding_test.o gcctestdir/ld
+ $(CXXLINK) -Bgcctestdir/ -Wl,--icf=all icf_virtual_function_folding_test.o -pie
+
+check_SCRIPTS += icf_preemptible_functions_test.sh
+check_DATA += icf_preemptible_functions_test.stdout
+MOSTLYCLEANFILES += icf_preemptible_functions_test
+icf_preemptible_functions_test.o: icf_preemptible_functions_test.cc
+ $(CXXCOMPILE) -O0 -c -ffunction-sections -fPIC -g -o $@ $<
+icf_preemptible_functions_test: icf_preemptible_functions_test.o gcctestdir/ld
+ $(CXXLINK) -Bgcctestdir/ -Wl,--icf=all icf_preemptible_functions_test.o -fPIC -shared
+icf_preemptible_functions_test.stdout: icf_preemptible_functions_test
+ $(TEST_NM) icf_preemptible_functions_test > icf_preemptible_functions_test.stdout
+
+check_SCRIPTS += icf_string_merge_test.sh
+check_DATA += icf_string_merge_test.stdout
+MOSTLYCLEANFILES += icf_string_merge_test
+icf_string_merge_test.o: icf_string_merge_test.cc
+ $(CXXCOMPILE) -O0 -c -ffunction-sections -fPIC -g -o $@ $<
+icf_string_merge_test: icf_string_merge_test.o gcctestdir/ld
+ $(CXXLINK) -Bgcctestdir/ -Wl,--icf=all icf_string_merge_test.o
+icf_string_merge_test.stdout: icf_string_merge_test
+ $(TEST_NM) icf_string_merge_test > icf_string_merge_test.stdout
+
check_PROGRAMS += basic_test
check_PROGRAMS += basic_static_test
check_PROGRAMS += basic_pic_test
diff --git a/binutils-2.19/gold/testsuite/Makefile.in b/binutils-2.19/gold/testsuite/Makefile.in
index 8815bc3..bc92bb4 100644
--- a/binutils-2.19/gold/testsuite/Makefile.in
+++ b/binutils-2.19/gold/testsuite/Makefile.in
@@ -62,6 +62,8 @@ check_PROGRAMS = object_unittest$(EXEEXT) binary_unittest$(EXEEXT) \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_keep_unique_test.sh \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_safe_test.sh \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_safe_so_test.sh \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_preemptible_functions_test.sh \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_string_merge_test.sh \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_shared.sh weak_plt.sh \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ debug_msg.sh undef_symbol.sh \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ ver_test_1.sh ver_test_2.sh \
@@ -91,6 +93,8 @@ check_PROGRAMS = object_unittest$(EXEEXT) binary_unittest$(EXEEXT) \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_safe_test_2.stdout \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_safe_so_test_1.stdout \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_safe_so_test_2.stdout \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_preemptible_functions_test.stdout \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_string_merge_test.stdout \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_shared.dbg \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ weak_plt_shared.so debug_msg.err \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ debug_msg_so.err \
@@ -112,10 +116,14 @@ check_PROGRAMS = object_unittest$(EXEEXT) binary_unittest$(EXEEXT) \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ gc_orphan_section_test icf_test \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_keep_unique_test \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_safe_test icf_safe_so_test \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_virtual_function_folding_test \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_preemptible_functions_test \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ icf_string_merge_test \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ two_file_shared.dbg \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ alt/weak_undef_lib.so
-@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_4 = basic_test \
-@GCC_TRUE@@NATIVE_LINKER_TRUE@ basic_static_test basic_pic_test \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@am__append_4 = icf_virtual_function_folding_test \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ basic_test basic_static_test \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ basic_pic_test \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ basic_static_pic_test \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ basic_pie_test constructor_test \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ constructor_static_test \
@@ -381,7 +389,8 @@ libgoldtest_a_LIBADD =
am_libgoldtest_a_OBJECTS = test.$(OBJEXT) testmain.$(OBJEXT) \
testfile.$(OBJEXT)
libgoldtest_a_OBJECTS = $(am_libgoldtest_a_OBJECTS)
-@GCC_TRUE@@NATIVE_LINKER_TRUE@am__EXEEXT_1 = basic_test$(EXEEXT) \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@am__EXEEXT_1 = icf_virtual_function_folding_test$(EXEEXT) \
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ basic_test$(EXEEXT) \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ basic_static_test$(EXEEXT) \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ basic_pic_test$(EXEEXT) \
@GCC_TRUE@@NATIVE_LINKER_TRUE@ basic_static_pic_test$(EXEEXT) \
@@ -653,6 +662,14 @@ flagstest_o_specialfile_and_compress_debug_sections_DEPENDENCIES = \
libgoldtest.a ../libgold.a ../../libiberty/libiberty.a \
$(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) \
$(am__DEPENDENCIES_1)
+icf_virtual_function_folding_test_SOURCES = \
+ icf_virtual_function_folding_test.c
+icf_virtual_function_folding_test_OBJECTS = \
+ icf_virtual_function_folding_test.$(OBJEXT)
+icf_virtual_function_folding_test_LDADD = $(LDADD)
+icf_virtual_function_folding_test_DEPENDENCIES = libgoldtest.a \
+ ../libgold.a ../../libiberty/libiberty.a $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1)
am__initpri1_SOURCES_DIST = initpri1.c
@CONSTRUCTOR_PRIORITY_TRUE@@GCC_TRUE@@NATIVE_LINKER_TRUE@am_initpri1_OBJECTS = initpri1.$(OBJEXT)
initpri1_OBJECTS = $(am_initpri1_OBJECTS)
@@ -1142,12 +1159,12 @@ SOURCES = $(libgoldtest_a_SOURCES) basic_pic_test.c basic_pie_test.c \
$(exclude_libs_test_SOURCES) \
flagstest_compress_debug_sections.c flagstest_o_specialfile.c \
flagstest_o_specialfile_and_compress_debug_sections.c \
- $(initpri1_SOURCES) $(justsyms_SOURCES) $(large_SOURCES) \
- local_labels_test.c many_sections_r_test.c \
- $(many_sections_test_SOURCES) $(object_unittest_SOURCES) \
- permission_test.c plugin_test_1.c plugin_test_2.c \
- plugin_test_3.c plugin_test_4.c plugin_test_5.c \
- $(protected_1_SOURCES) $(protected_2_SOURCES) \
+ icf_virtual_function_folding_test.c $(initpri1_SOURCES) \
+ $(justsyms_SOURCES) $(large_SOURCES) local_labels_test.c \
+ many_sections_r_test.c $(many_sections_test_SOURCES) \
+ $(object_unittest_SOURCES) permission_test.c plugin_test_1.c \
+ plugin_test_2.c plugin_test_3.c plugin_test_4.c \
+ plugin_test_5.c $(protected_1_SOURCES) $(protected_2_SOURCES) \
$(relro_script_test_SOURCES) $(relro_test_SOURCES) \
$(script_test_1_SOURCES) $(script_test_2_SOURCES) \
script_test_3.c $(searched_file_test_SOURCES) \
@@ -1201,6 +1218,7 @@ DIST_SOURCES = $(libgoldtest_a_SOURCES) basic_pic_test.c \
$(am__exclude_libs_test_SOURCES_DIST) \
flagstest_compress_debug_sections.c flagstest_o_specialfile.c \
flagstest_o_specialfile_and_compress_debug_sections.c \
+ icf_virtual_function_folding_test.c \
$(am__initpri1_SOURCES_DIST) $(am__justsyms_SOURCES_DIST) \
$(am__large_SOURCES_DIST) local_labels_test.c \
many_sections_r_test.c $(am__many_sections_test_SOURCES_DIST) \
@@ -1361,7 +1379,9 @@ host_vendor = @host_vendor@
htmldir = @htmldir@
includedir = @includedir@
infodir = @infodir@
+install_as_default = @install_as_default@
install_sh = @install_sh@
+installed_linker = @installed_linker@
libdir = @libdir@
libexecdir = @libexecdir@
localedir = @localedir@
@@ -1942,6 +1962,12 @@ exclude_libs_test$(EXEEXT): $(exclude_libs_test_OBJECTS) $(exclude_libs_test_DEP
@NATIVE_LINKER_FALSE@flagstest_o_specialfile_and_compress_debug_sections$(EXEEXT): $(flagstest_o_specialfile_and_compress_debug_sections_OBJECTS) $(flagstest_o_specialfile_and_compress_debug_sections_DEPENDENCIES)
@NATIVE_LINKER_FALSE@ @rm -f flagstest_o_specialfile_and_compress_debug_sections$(EXEEXT)
@NATIVE_LINKER_FALSE@ $(LINK) $(flagstest_o_specialfile_and_compress_debug_sections_OBJECTS) $(flagstest_o_specialfile_and_compress_debug_sections_LDADD) $(LIBS)
+@GCC_FALSE@icf_virtual_function_folding_test$(EXEEXT): $(icf_virtual_function_folding_test_OBJECTS) $(icf_virtual_function_folding_test_DEPENDENCIES)
+@GCC_FALSE@ @rm -f icf_virtual_function_folding_test$(EXEEXT)
+@GCC_FALSE@ $(LINK) $(icf_virtual_function_folding_test_OBJECTS) $(icf_virtual_function_folding_test_LDADD) $(LIBS)
+@NATIVE_LINKER_FALSE@icf_virtual_function_folding_test$(EXEEXT): $(icf_virtual_function_folding_test_OBJECTS) $(icf_virtual_function_folding_test_DEPENDENCIES)
+@NATIVE_LINKER_FALSE@ @rm -f icf_virtual_function_folding_test$(EXEEXT)
+@NATIVE_LINKER_FALSE@ $(LINK) $(icf_virtual_function_folding_test_OBJECTS) $(icf_virtual_function_folding_test_LDADD) $(LIBS)
initpri1$(EXEEXT): $(initpri1_OBJECTS) $(initpri1_DEPENDENCIES)
@rm -f initpri1$(EXEEXT)
$(initpri1_LINK) $(initpri1_OBJECTS) $(initpri1_LDADD) $(LIBS)
@@ -2231,6 +2257,7 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flagstest_compress_debug_sections.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flagstest_o_specialfile.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/flagstest_o_specialfile_and_compress_debug_sections.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/icf_virtual_function_folding_test.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/initpri1.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/justsyms_1.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/large-large.Po@am__quote@
@@ -2696,6 +2723,22 @@ uninstall-am:
@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_NM) icf_safe_so_test > icf_safe_so_test_1.stdout
@GCC_TRUE@@NATIVE_LINKER_TRUE@icf_safe_so_test_2.stdout: icf_safe_so_test
@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_READELF) -h icf_safe_so_test > icf_safe_so_test_2.stdout
+@GCC_TRUE@@NATIVE_LINKER_TRUE@icf_virtual_function_folding_test.o: icf_virtual_function_folding_test.cc
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -O0 -c -ffunction-sections -fPIE -g -o $@ $<
+@GCC_TRUE@@NATIVE_LINKER_TRUE@icf_virtual_function_folding_test: icf_virtual_function_folding_test.o gcctestdir/ld
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -Wl,--icf=all icf_virtual_function_folding_test.o -pie
+@GCC_TRUE@@NATIVE_LINKER_TRUE@icf_preemptible_functions_test.o: icf_preemptible_functions_test.cc
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -O0 -c -ffunction-sections -fPIC -g -o $@ $<
+@GCC_TRUE@@NATIVE_LINKER_TRUE@icf_preemptible_functions_test: icf_preemptible_functions_test.o gcctestdir/ld
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -Wl,--icf=all icf_preemptible_functions_test.o -fPIC -shared
+@GCC_TRUE@@NATIVE_LINKER_TRUE@icf_preemptible_functions_test.stdout: icf_preemptible_functions_test
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_NM) icf_preemptible_functions_test > icf_preemptible_functions_test.stdout
+@GCC_TRUE@@NATIVE_LINKER_TRUE@icf_string_merge_test.o: icf_string_merge_test.cc
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -O0 -c -ffunction-sections -fPIC -g -o $@ $<
+@GCC_TRUE@@NATIVE_LINKER_TRUE@icf_string_merge_test: icf_string_merge_test.o gcctestdir/ld
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXLINK) -Bgcctestdir/ -Wl,--icf=all icf_string_merge_test.o
+@GCC_TRUE@@NATIVE_LINKER_TRUE@icf_string_merge_test.stdout: icf_string_merge_test
+@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(TEST_NM) icf_string_merge_test > icf_string_merge_test.stdout
@GCC_TRUE@@NATIVE_LINKER_TRUE@basic_test.o: basic_test.cc
@GCC_TRUE@@NATIVE_LINKER_TRUE@ $(CXXCOMPILE) -O0 -c -o $@ $<
@GCC_TRUE@@NATIVE_LINKER_TRUE@basic_test: basic_test.o gcctestdir/ld
diff --git a/binutils-2.19/gold/testsuite/icf_preemptible_functions_test.cc b/binutils-2.19/gold/testsuite/icf_preemptible_functions_test.cc
new file mode 100644
index 0000000..35a96bc
--- /dev/null
+++ b/binutils-2.19/gold/testsuite/icf_preemptible_functions_test.cc
@@ -0,0 +1,47 @@
+// icf_preemptible_functions_test.cc -- a test case for gold
+
+// Copyright 2010 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.
+
+// The goal of this program is to verify that preemptible functions are
+// correctly handled by ICF. In this program, foo and bar should not
+// be folded although they are identical as zap or zip could be preempted.
+
+int zap()
+{
+ return 0;
+}
+
+int zip()
+{
+ return 0;
+}
+
+int foo()
+{
+ zap();
+ return 0;
+}
+
+int bar()
+{
+ zip();
+ return 0;
+}
diff --git a/binutils-2.19/gold/testsuite/icf_preemptible_functions_test.sh b/binutils-2.19/gold/testsuite/icf_preemptible_functions_test.sh
new file mode 100755
index 0000000..27cf459
--- /dev/null
+++ b/binutils-2.19/gold/testsuite/icf_preemptible_functions_test.sh
@@ -0,0 +1,35 @@
+# icf_preemptible_functions_test.sh -- test --icf=all
+
+# Copyright 2010 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.
+
+
+check()
+{
+ func_addr_1=`grep $2 $1 | awk '{print $1}'`
+ func_addr_2=`grep $3 $1 | awk '{print $1}'`
+ if [ $func_addr_1 = $func_addr_2 ]
+ then
+ echo "Identical Code Folding should not fold" $2 "and" $3
+ exit 1
+ fi
+}
+
+check icf_preemptible_functions_test.stdout "_Z3foov" "_Z3barv"
diff --git a/binutils-2.19/gold/testsuite/icf_safe_so_test.cc b/binutils-2.19/gold/testsuite/icf_safe_so_test.cc
index 5e4453b..0f50ad6 100644
--- a/binutils-2.19/gold/testsuite/icf_safe_so_test.cc
+++ b/binutils-2.19/gold/testsuite/icf_safe_so_test.cc
@@ -24,7 +24,8 @@
// in safe mode correctly folds functions in a shared object. The
// foo_* functions below should not be folded. For x86-64,
// foo_glob and bar_glob should be folded as their function pointers
-// are addresses of PLT entries in shared objects.
+// are addresses of PLT entries in shared objects. For 32-bit X86,
+// the hidden protected and internal symbols can be folded.
int __attribute__ ((visibility ("protected")))
foo_prot()
diff --git a/binutils-2.19/gold/testsuite/icf_safe_so_test.sh b/binutils-2.19/gold/testsuite/icf_safe_so_test.sh
index db2e73e..47ad390 100755
--- a/binutils-2.19/gold/testsuite/icf_safe_so_test.sh
+++ b/binutils-2.19/gold/testsuite/icf_safe_so_test.sh
@@ -25,8 +25,25 @@
# to verify if identical code folding in safe mode correctly folds
# functions in a shared object.
+error_if_symbol_absent()
+{
+ if ! is_symbol_present $1 $2;
+ then
+ echo "Symbol" $2 "not present, possibly folded."
+ exit 1
+ fi
+}
+
+is_symbol_present()
+{
+ grep $2 $1 > /dev/null 2>&1
+ return $?
+}
+
check_nofold()
{
+ error_if_symbol_absent $1 $2
+ error_if_symbol_absent $1 $3
func_addr_1=`grep $2 $1 | awk '{print $1}'`
func_addr_2=`grep $3 $1 | awk '{print $1}'`
if [ $func_addr_1 = $func_addr_2 ];
@@ -38,6 +55,16 @@ check_nofold()
check_fold()
{
+ if ! is_symbol_present $1 $2
+ then
+ return 0
+ fi
+
+ if ! is_symbol_present $1 $3
+ then
+ return 0
+ fi
+
func_addr_1=`grep $2 $1 | awk '{print $1}'`
func_addr_2=`grep $3 $1 | awk '{print $1}'`
if [ $func_addr_1 != $func_addr_2 ];
@@ -49,21 +76,30 @@ check_fold()
arch_specific_safe_fold()
{
- grep_x86_64=`grep -q "Advanced Micro Devices X86-64" $2`
- if [ $? == 0 ];
+ if [ $1 == 0 ];
then
- check_fold $1 $3 $4
+ check_fold $2 $3 $4
else
- check_nofold $1 $3 $4
+ check_nofold $2 $3 $4
fi
}
-check_nofold icf_safe_so_test_1.stdout "foo_prot" "foo_hidden"
-check_nofold icf_safe_so_test_1.stdout "foo_prot" "foo_internal"
-check_nofold icf_safe_so_test_1.stdout "foo_prot" "foo_static"
-check_nofold icf_safe_so_test_1.stdout "foo_hidden" "foo_internal"
-check_nofold icf_safe_so_test_1.stdout "foo_hidden" "foo_static"
-check_nofold icf_safe_so_test_1.stdout "foo_internal" "foo_static"
-arch_specific_safe_fold icf_safe_so_test_1.stdout icf_safe_so_test_2.stdout \
- "foo_glob" "bar_glob"
+X86_32_specific_safe_fold()
+{
+ grep -e "Intel 80386" $1 > /dev/null 2>&1
+ arch_specific_safe_fold $? $2 $3 $4
+}
+
+X86_64_specific_safe_fold()
+{
+ grep -e "Advanced Micro Devices X86-64" $1 > /dev/null 2>&1
+ arch_specific_safe_fold $? $2 $3 $4
+}
+X86_32_specific_safe_fold icf_safe_so_test_2.stdout icf_safe_so_test_1.stdout "foo_prot" "foo_hidden"
+X86_32_specific_safe_fold icf_safe_so_test_2.stdout icf_safe_so_test_1.stdout "foo_prot" "foo_internal"
+X86_32_specific_safe_fold icf_safe_so_test_2.stdout icf_safe_so_test_1.stdout "foo_prot" "foo_static"
+X86_32_specific_safe_fold icf_safe_so_test_2.stdout icf_safe_so_test_1.stdout "foo_hidden" "foo_internal"
+X86_32_specific_safe_fold icf_safe_so_test_2.stdout icf_safe_so_test_1.stdout "foo_hidden" "foo_static"
+X86_32_specific_safe_fold icf_safe_so_test_2.stdout icf_safe_so_test_1.stdout "foo_internal" "foo_static"
+check_nofold icf_safe_so_test_1.stdout "foo_glob" "bar_glob"
diff --git a/binutils-2.19/gold/testsuite/icf_safe_test.cc b/binutils-2.19/gold/testsuite/icf_safe_test.cc
index 3edb865..87294dc 100644
--- a/binutils-2.19/gold/testsuite/icf_safe_test.cc
+++ b/binutils-2.19/gold/testsuite/icf_safe_test.cc
@@ -22,10 +22,10 @@
// The goal of this program is to verify if identical code folding
// in safe mode correctly folds only ctors and dtors. kept_func_1 must
-// not be folded into kept_func_2 other than for X86-64 which can
-// use relocation types to determine if function pointers are taken.
-// kept_func_3 should never be folded as its pointer is taken. The ctor
-// and dtor of class A must be folded.
+// not be folded into kept_func_2 other than for X86 (32 and 64 bit)
+// which can use relocation types to determine if function pointers are
+// taken. kept_func_3 should never be folded as its pointer is taken.
+// The ctor and dtor of class A must be folded.
class A
{
diff --git a/binutils-2.19/gold/testsuite/icf_safe_test.sh b/binutils-2.19/gold/testsuite/icf_safe_test.sh
index 540dcc2..23e4e29 100755
--- a/binutils-2.19/gold/testsuite/icf_safe_test.sh
+++ b/binutils-2.19/gold/testsuite/icf_safe_test.sh
@@ -22,8 +22,8 @@
# The goal of this program is to verify if --icf=safe works as expected.
# File icf_safe_test.cc is in this test. This program checks if only
-# ctors and dtors are folded, except for x86-64, which uses relocation
-# types to detect if function pointers are taken.
+# ctors and dtors are folded, except for x86 (32 and 64 bit), which
+# uses relocation types to detect if function pointers are taken.
check_nofold()
{
@@ -49,7 +49,7 @@ check_fold()
arch_specific_safe_fold()
{
- grep_x86_64=`grep -q "Advanced Micro Devices X86-64" $2`
+ grep_x86=`grep -q -e "Advanced Micro Devices X86-64" -e "Intel 80386" $2`
if [ $? == 0 ];
then
check_fold $1 $3 $4
diff --git a/binutils-2.19/gold/testsuite/icf_string_merge_test.cc b/binutils-2.19/gold/testsuite/icf_string_merge_test.cc
new file mode 100644
index 0000000..b1e1191
--- /dev/null
+++ b/binutils-2.19/gold/testsuite/icf_string_merge_test.cc
@@ -0,0 +1,50 @@
+// icf_string_merge_test.cc -- a test case for gold
+
+// Copyright 2010 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.
+
+// The goal of this program is to verify is strings are handled correctly
+// by ICF. ICF inlines strings that can be merged. In some cases, the
+// addend of the relocation pointing to a string merge section must be
+// ignored. This program has no pair of identical functions that can be
+// folded. However, if the addend is not ignored then get2 and get3 will
+// become identical.
+
+const char* const str1 = "aaaaaaaaaastr1";
+const char* const str2 = "bbbbaaaaaastr1";
+const char* const str3 = "cccccaaaaastr1";
+
+const char* get1()
+{
+ return str1;
+}
+const char* get2()
+{
+ return str2;
+}
+
+const char* get3()
+{
+ return str3;
+}
+int main()
+{
+ return 0;
+}
diff --git a/binutils-2.19/gold/testsuite/icf_string_merge_test.sh b/binutils-2.19/gold/testsuite/icf_string_merge_test.sh
new file mode 100755
index 0000000..f22f212
--- /dev/null
+++ b/binutils-2.19/gold/testsuite/icf_string_merge_test.sh
@@ -0,0 +1,37 @@
+# icf_string_merge_test.sh -- test --icf=all
+
+# Copyright 2010 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.
+
+
+check()
+{
+ func_addr_1=`grep $2 $1 | awk '{print $1}'`
+ func_addr_2=`grep $3 $1 | awk '{print $1}'`
+ if [ $func_addr_1 = $func_addr_2 ]
+ then
+ echo "Identical Code Folding should not fold" $2 "and" $3
+ exit 1
+ fi
+}
+
+check icf_string_merge_test.stdout "get1" "get2"
+check icf_string_merge_test.stdout "get1" "get3"
+check icf_string_merge_test.stdout "get2" "get3"
diff --git a/binutils-2.19/gold/testsuite/icf_virtual_function_folding_test.cc b/binutils-2.19/gold/testsuite/icf_virtual_function_folding_test.cc
new file mode 100644
index 0000000..1ba3e73
--- /dev/null
+++ b/binutils-2.19/gold/testsuite/icf_virtual_function_folding_test.cc
@@ -0,0 +1,70 @@
+// icf_virtual_function_folding_test.cc -- a test case for gold
+
+// Copyright 2010 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.
+
+// Foo::fn1 is folded into fn2 with ICF. Since this file is linked as a
+// position independent executable, a dynamic reloc is needed
+// for the virtual call fn1 entry in the vtable. This test makes sure
+// the call to Foo::fn1 works correctly after the folding.
+
+int fn2(void *)
+{
+ return 0xA;
+}
+
+namespace
+{
+
+class Bar
+{
+ public:
+ virtual int fn1();
+};
+
+int Bar::fn1()
+{
+ return 123;
+}
+
+class Foo : public Bar
+{
+ virtual int fn1();
+};
+
+int Foo::fn1()
+{
+ return 0xA;
+}
+
+Bar* get()
+{
+ Bar *f = new Foo();
+ return f;
+}
+
+} // end of anonymous namespace.
+
+int main()
+{
+ Bar *f = get();
+ f->fn1();
+ return 0;
+}
diff --git a/binutils-2.19/gold/x86_64.cc b/binutils-2.19/gold/x86_64.cc
index e9dd5ae..9110278 100644
--- a/binutils-2.19/gold/x86_64.cc
+++ b/binutils-2.19/gold/x86_64.cc
@@ -1398,14 +1398,10 @@ Target_x86_64::Scan::unsupported_reloc_global(Sized_relobj<64, false>* object,
object->name().c_str(), r_type, gsym->demangled_name().c_str());
}
-// Returns true if this relocation type could be that of a function pointer
-// only if the target is not position-independent code.
+// Returns true if this relocation type could be that of a function pointer.
inline bool
Target_x86_64::Scan::possible_function_pointer_reloc(unsigned int r_type)
{
- if (parameters->options().shared())
- return false;
-
switch (r_type)
{
case elfcpp::R_X86_64_64:
@@ -1413,6 +1409,11 @@ Target_x86_64::Scan::possible_function_pointer_reloc(unsigned int r_type)
case elfcpp::R_X86_64_32S:
case elfcpp::R_X86_64_16:
case elfcpp::R_X86_64_8:
+ case elfcpp::R_X86_64_GOT64:
+ case elfcpp::R_X86_64_GOT32:
+ case elfcpp::R_X86_64_GOTPCREL64:
+ case elfcpp::R_X86_64_GOTPCREL:
+ case elfcpp::R_X86_64_GOTPLT64:
{
return true;
}
diff --git a/binutils-2.19/ld/emultempl/armelf.em b/binutils-2.19/ld/emultempl/armelf.em
index 4340a48..0fd9ab6 100644
--- a/binutils-2.19/ld/emultempl/armelf.em
+++ b/binutils-2.19/ld/emultempl/armelf.em
@@ -458,6 +458,7 @@ PARSE_AND_LIST_PROLOGUE='
#define OPTION_NO_WCHAR_SIZE_WARNING 313
#define OPTION_FIX_CORTEX_A8 314
#define OPTION_NO_FIX_CORTEX_A8 315
+#define OPTION_ICF 399
'
PARSE_AND_LIST_SHORTOPTS=p
@@ -479,6 +480,7 @@ PARSE_AND_LIST_LONGOPTS='
{ "no-wchar-size-warning", no_argument, NULL, OPTION_NO_WCHAR_SIZE_WARNING},
{ "fix-cortex-a8", no_argument, NULL, OPTION_FIX_CORTEX_A8 },
{ "no-fix-cortex-a8", no_argument, NULL, OPTION_NO_FIX_CORTEX_A8 },
+ { "icf", required_argument, NULL, OPTION_ICF },
'
PARSE_AND_LIST_OPTIONS='
@@ -506,6 +508,7 @@ PARSE_AND_LIST_OPTIONS='
the linker should choose suitable defaults.\n"
));
fprintf (file, _(" --[no-]fix-cortex-a8 Disable/enable Cortex-A8 Thumb-2 branch erratum fix\n"));
+ fprintf (file, _(" --icf=<value> Ignored for compatibility with gold.\n"));
'
PARSE_AND_LIST_ARGS_CASES='
@@ -585,6 +588,10 @@ PARSE_AND_LIST_ARGS_CASES='
case OPTION_NO_FIX_CORTEX_A8:
fix_cortex_a8 = 0;
break;
+
+ case OPTION_ICF:
+ /* For compatibility with gold. */
+ break;
'
# We have our own before_allocation etc. functions, but they call