binutils/binutils-2.20.51.0.10-updat...

8000 lines
266 KiB
Diff

diff -rcp ../binutils-2.20.51.0.10.original/elfcpp/i386.h elfcpp/i386.h
*** ../binutils-2.20.51.0.10.original/elfcpp/i386.h 2010-08-10 15:13:23.000000000 +0100
--- elfcpp/i386.h 2010-08-10 15:14:09.000000000 +0100
***************
*** 1,6 ****
// i386.h -- ELF definitions specific to EM_386 -*- C++ -*-
! // Copyright 2006, 2007, Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of elfcpp.
--- 1,6 ----
// i386.h -- ELF definitions specific to EM_386 -*- C++ -*-
! // Copyright 2006, 2007, 2010 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of elfcpp.
*************** enum
*** 85,90 ****
--- 85,91 ----
R_386_TLS_DESC_CALL = 40, // Marker of call through TLS desc for relaxation
R_386_TLS_DESC = 41, // TLS descriptor containing pointer to code and
// to argument, returning TLS offset for symbol
+ R_386_IRELATIVE = 42, // Adjust indirectly by program base
// Used by Intel.
R_386_USED_BY_INTEL_200 = 200,
// GNU vtable garbage collection extensions.
diff -rcp ../binutils-2.20.51.0.10.original/elfcpp/powerpc.h elfcpp/powerpc.h
*** ../binutils-2.20.51.0.10.original/elfcpp/powerpc.h 2010-08-10 15:13:23.000000000 +0100
--- elfcpp/powerpc.h 2010-08-10 15:14:09.000000000 +0100
***************
*** 1,6 ****
// powerpc.h -- ELF definitions specific to EM_PPC and EM_PPC64 -*- C++ -*-
! // Copyright 2008, Free Software Foundation, Inc.
// Written by David S. Miller <davem@davemloft.net>.
// This file is part of elfcpp.
--- 1,6 ----
// powerpc.h -- ELF definitions specific to EM_PPC and EM_PPC64 -*- C++ -*-
! // Copyright 2008, 2010 Free Software Foundation, Inc.
// Written by David S. Miller <davem@davemloft.net>.
// This file is part of elfcpp.
*************** enum
*** 165,174 ****
R_PPC_EMB_RELST_HA = 114,
R_PPC_EMB_BIT_FLD = 115,
R_PPC_EMB_RELSDA = 116,
! R_PPC_RELAX32 = 245,
! R_PPC_RELAX32PC = 246,
! R_PPC_RELAX32_PLT = 247,
! R_PPC_RELAX32PC_PLT = 248,
R_PPC_REL16 = 249,
R_PPC_REL16_LO = 250,
R_PPC_REL16_HI = 251,
--- 165,172 ----
R_PPC_EMB_RELST_HA = 114,
R_PPC_EMB_BIT_FLD = 115,
R_PPC_EMB_RELSDA = 116,
!
! R_POWERPC_IRELATIVE = 248,
R_PPC_REL16 = 249,
R_PPC_REL16_LO = 250,
R_PPC_REL16_HI = 251,
diff -rcp ../binutils-2.20.51.0.10.original/elfcpp/sparc.h elfcpp/sparc.h
*** ../binutils-2.20.51.0.10.original/elfcpp/sparc.h 2010-08-10 15:13:23.000000000 +0100
--- elfcpp/sparc.h 2010-08-10 15:14:09.000000000 +0100
***************
*** 1,6 ****
// sparc.h -- ELF definitions specific to EM_SPARC -*- C++ -*-
! // Copyright 2008, Free Software Foundation, Inc.
// Written by David S. Miller <davem@davemloft.net>.
// This file is part of elfcpp.
--- 1,6 ----
// sparc.h -- ELF definitions specific to EM_SPARC -*- C++ -*-
! // Copyright 2008, 2010 Free Software Foundation, Inc.
// Written by David S. Miller <davem@davemloft.net>.
// This file is part of elfcpp.
*************** enum
*** 141,146 ****
--- 141,148 ----
R_SPARC_SIZE32 = 86, // size of symbol, 32-bit
R_SPARC_SIZE64 = 87, // size of symbol, 64-bit
+ R_SPARC_IRELATIVE = 249, // Adjust indirectly by program base
+
// GNU vtable garbage collection extensions.
R_SPARC_GNU_VTINHERIT = 250,
R_SPARC_GNU_VTENTRY = 251,
diff -rcp ../binutils-2.20.51.0.10.original/elfcpp/x86_64.h elfcpp/x86_64.h
*** ../binutils-2.20.51.0.10.original/elfcpp/x86_64.h 2010-08-10 15:13:23.000000000 +0100
--- elfcpp/x86_64.h 2010-08-10 15:14:09.000000000 +0100
***************
*** 1,6 ****
// x86-64.h -- ELF definitions specific to EM_X86_64 -*- C++ -*-
! // Copyright 2006, 2007, Free Software Foundation, Inc.
// Written by Andrew Chatham.
// This file is part of elfcpp.
--- 1,6 ----
// x86-64.h -- ELF definitions specific to EM_X86_64 -*- C++ -*-
! // Copyright 2006, 2007, 2010 Free Software Foundation, Inc.
// Written by Andrew Chatham.
// This file is part of elfcpp.
*************** enum
*** 90,98 ****
R_X86_64_GOTPC32_TLSDESC = 34, // 32-bit PC relative to TLS descriptor in GOT
R_X86_64_TLSDESC_CALL = 35, // Relaxable call through TLS descriptor
R_X86_64_TLSDESC = 36, // 2 by 64-bit TLS descriptor
// GNU vtable garbage collection extensions.
! R_386_GNU_VTINHERIT = 250,
! R_386_GNU_VTENTRY = 251
};
} // End namespace elfcpp.
--- 90,99 ----
R_X86_64_GOTPC32_TLSDESC = 34, // 32-bit PC relative to TLS descriptor in GOT
R_X86_64_TLSDESC_CALL = 35, // Relaxable call through TLS descriptor
R_X86_64_TLSDESC = 36, // 2 by 64-bit TLS descriptor
+ R_X86_64_IRELATIVE = 37, // Adjust indirectly by program base
// GNU vtable garbage collection extensions.
! R_X86_64_GNU_VTINHERIT = 250,
! R_X86_64_GNU_VTENTRY = 251
};
} // End namespace elfcpp.
diff -rcp ../binutils-2.20.51.0.10.original/gold/archive.cc gold/archive.cc
*** ../binutils-2.20.51.0.10.original/gold/archive.cc 2010-08-10 15:11:28.000000000 +0100
--- gold/archive.cc 2010-08-10 15:14:02.000000000 +0100
***************
*** 36,41 ****
--- 36,42 ----
#include "readsyms.h"
#include "symtab.h"
#include "object.h"
+ #include "layout.h"
#include "archive.h"
#include "plugin.h"
*************** Archive::read_symbols(off_t off)
*** 603,610 ****
}
Archive::Should_include
! Archive::should_include_member(Symbol_table* symtab, const char* sym_name,
! Symbol** symp, std::string* why, char** tmpbufp,
size_t* tmpbuflen)
{
// In an object file, and therefore in an archive map, an
--- 604,612 ----
}
Archive::Should_include
! Archive::should_include_member(Symbol_table* symtab, Layout* layout,
! const char* sym_name, Symbol** symp,
! std::string* why, char** tmpbufp,
size_t* tmpbuflen)
{
// In an object file, and therefore in an archive map, an
*************** Archive::should_include_member(Symbol_ta
*** 648,660 ****
if (sym == NULL)
{
// Check whether the symbol was named in a -u option.
! if (!parameters->options().is_undefined(sym_name))
! return Archive::SHOULD_INCLUDE_UNKNOWN;
! else
{
*why = "-u ";
*why += sym_name;
}
}
else if (!sym->is_undefined())
return Archive::SHOULD_INCLUDE_NO;
--- 650,671 ----
if (sym == NULL)
{
// Check whether the symbol was named in a -u option.
! if (parameters->options().is_undefined(sym_name))
{
*why = "-u ";
*why += sym_name;
}
+ else if (layout->script_options()->is_referenced(sym_name))
+ {
+ size_t alc = 100 + strlen(sym_name);
+ char* buf = new char[alc];
+ snprintf(buf, alc, _("script or expression reference to %s"),
+ sym_name);
+ *why = buf;
+ delete[] buf;
+ }
+ else
+ return Archive::SHOULD_INCLUDE_UNKNOWN;
}
else if (!sym->is_undefined())
return Archive::SHOULD_INCLUDE_NO;
*************** Archive::add_symbols(Symbol_table* symta
*** 726,733 ****
Symbol* sym;
std::string why;
Archive::Should_include t =
! Archive::should_include_member(symtab, sym_name, &sym, &why,
! &tmpbuf, &tmpbuflen);
if (t == Archive::SHOULD_INCLUDE_NO
|| t == Archive::SHOULD_INCLUDE_YES)
--- 737,744 ----
Symbol* sym;
std::string why;
Archive::Should_include t =
! Archive::should_include_member(symtab, layout, sym_name, &sym,
! &why, &tmpbuf, &tmpbuflen);
if (t == Archive::SHOULD_INCLUDE_NO
|| t == Archive::SHOULD_INCLUDE_YES)
*************** Archive::include_member(Symbol_table* sy
*** 853,863 ****
&& this->searched_for()
&& obj == NULL
&& unconfigured)
! {
! if (obj != NULL)
! delete obj;
! return false;
! }
if (obj == NULL)
return true;
--- 864,870 ----
&& this->searched_for()
&& obj == NULL
&& unconfigured)
! return false;
if (obj == NULL)
return true;
*************** Archive::include_member(Symbol_table* sy
*** 874,880 ****
}
if (!input_objects->add_object(obj))
! delete obj;
else
{
{
--- 881,893 ----
}
if (!input_objects->add_object(obj))
! {
! // If this is an external member of a thin archive, unlock the
! // file.
! if (obj->offset() == 0)
! obj->unlock(this->task_);
! delete obj;
! }
else
{
{
*************** Lib_group::add_symbols(Symbol_table* sym
*** 1013,1018 ****
--- 1026,1032 ----
&& (member.sd_ == NULL || member.sd_->symbol_names != NULL))
{
Archive::Should_include t = obj->should_include_member(symtab,
+ layout,
member.sd_,
&why);
diff -rcp ../binutils-2.20.51.0.10.original/gold/archive.h gold/archive.h
*** ../binutils-2.20.51.0.10.original/gold/archive.h 2010-08-10 15:12:04.000000000 +0100
--- gold/archive.h 2010-08-10 15:14:02.000000000 +0100
*************** class Archive
*** 176,182 ****
};
static Should_include
! should_include_member(Symbol_table* symtab, const char* sym_name,
Symbol** symp, std::string* why, char** tmpbufp,
size_t* tmpbuflen);
--- 176,182 ----
};
static Should_include
! should_include_member(Symbol_table* symtab, Layout*, const char* sym_name,
Symbol** symp, std::string* why, char** tmpbufp,
size_t* tmpbuflen);
diff -rcp ../binutils-2.20.51.0.10.original/gold/arm.cc gold/arm.cc
*** ../binutils-2.20.51.0.10.original/gold/arm.cc 2010-08-10 15:11:28.000000000 +0100
--- gold/arm.cc 2010-08-10 15:14:02.000000000 +0100
*************** class Arm_output_section : public Output
*** 1324,1330 ****
Arm_output_section(const char* name, elfcpp::Elf_Word type,
elfcpp::Elf_Xword flags)
: Output_section(name, type, flags)
! { }
~Arm_output_section()
{ }
--- 1324,1333 ----
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()
{ }
*************** class Arm_output_section : public Output
*** 1352,1357 ****
--- 1355,1364 ----
Symbol_table* symtab,
bool merge_exidx_entries);
+ // Link an EXIDX section into its corresponding text section.
+ void
+ set_exidx_section_link();
+
private:
// For convenience.
typedef Output_section::Input_section Input_section;
*************** class Arm_exidx_input_section
*** 1376,1382 ****
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)
{ }
~Arm_exidx_input_section()
--- 1383,1389 ----
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), has_errors_(false)
{ }
~Arm_exidx_input_section()
*************** class Arm_exidx_input_section
*** 1409,1414 ****
--- 1416,1431 ----
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_;
*************** class Arm_exidx_input_section
*** 1420,1425 ****
--- 1437,1444 ----
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.
*************** class Arm_relobj : public Sized_relobj<3
*** 1581,1586 ****
--- 1600,1621 ----
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
*************** class Arm_relobj : public Sized_relobj<3
*** 1653,1659 ****
void
make_exidx_input_section(unsigned int shndx,
const elfcpp::Shdr<32, big_endian>& shdr,
! unsigned int text_shndx);
// Return the output address of either a plain input section or a
// relaxed input section. SHNDX is the section index.
--- 1688,1695 ----
void
make_exidx_input_section(unsigned int shndx,
const elfcpp::Shdr<32, big_endian>& shdr,
! 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.
*************** class Target_arm : public Sized_target<3
*** 2764,2770 ****
// Fix .ARM.exidx section coverage.
void
! fix_exidx_coverage(Layout*, Arm_output_section<big_endian>*, Symbol_table*);
// Functors for STL set.
struct output_section_address_less_than
--- 2800,2807 ----
// Fix .ARM.exidx section coverage.
void
! fix_exidx_coverage(Layout*, const Input_objects*,
! Arm_output_section<big_endian>*, Symbol_table*);
// Functors for STL set.
struct output_section_address_less_than
*************** Target_arm<big_endian>::got_section(Symb
*** 4116,4137 ****
this->got_ = new Arm_output_data_got<big_endian>(symtab, layout);
! Output_section* os;
! os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
! (elfcpp::SHF_ALLOC
! | elfcpp::SHF_WRITE),
! this->got_, false, false, false,
! true);
// The old GNU linker creates a .got.plt section. We just
// create another set of data in the .got section. Note that we
// always create a PLT if we create a GOT, although the PLT
// might be empty.
this->got_plt_ = new Output_data_space(4, "** GOT PLT");
! os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
! (elfcpp::SHF_ALLOC
! | elfcpp::SHF_WRITE),
! this->got_plt_, false, false,
! false, false);
// The first three entries are reserved.
this->got_plt_->set_current_data_size(3 * 4);
--- 4153,4172 ----
this->got_ = new Arm_output_data_got<big_endian>(symtab, layout);
! layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
! (elfcpp::SHF_ALLOC
! | elfcpp::SHF_WRITE),
! this->got_, ORDER_RELRO, true);
!
// The old GNU linker creates a .got.plt section. We just
// create another set of data in the .got section. Note that we
// always create a PLT if we create a GOT, although the PLT
// might be empty.
this->got_plt_ = new Output_data_space(4, "** GOT PLT");
! layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
! (elfcpp::SHF_ALLOC
! | elfcpp::SHF_WRITE),
! this->got_plt_, ORDER_DATA, false);
// The first three entries are reserved.
this->got_plt_->set_current_data_size(3 * 4);
*************** Target_arm<big_endian>::rel_dyn_section(
*** 4159,4166 ****
gold_assert(layout != NULL);
this->rel_dyn_ = new Reloc_section(parameters->options().combreloc());
layout->add_output_section_data(".rel.dyn", elfcpp::SHT_REL,
! elfcpp::SHF_ALLOC, this->rel_dyn_, true,
! false, false, false);
}
return this->rel_dyn_;
}
--- 4194,4201 ----
gold_assert(layout != NULL);
this->rel_dyn_ = new Reloc_section(parameters->options().combreloc());
layout->add_output_section_data(".rel.dyn", elfcpp::SHT_REL,
! elfcpp::SHF_ALLOC, this->rel_dyn_,
! ORDER_DYNAMIC_RELOCS, false);
}
return this->rel_dyn_;
}
*************** void
*** 5657,5666 ****
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();
--- 5692,5697 ----
*************** Arm_output_section<big_endian>::fix_exid
*** 5733,5741 ****
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)
{
exidx_fixup.add_exidx_cantunwind_as_needed();
continue;
--- 5764,5773 ----
const Arm_exidx_input_section* exidx_input_section =
arm_relobj->exidx_input_section_by_link(shndx);
! // 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;
*************** Arm_output_section<big_endian>::fix_exid
*** 5819,5833 ****
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.
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));
// Remove this from link. We also need to recount the
// local symbols.
--- 5851,5870 ----
if (processed_input_sections.find(Section_id(p->relobj(), p->shndx()))
== processed_input_sections.end())
{
! // 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);
! 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.
*************** Arm_output_section<big_endian>::fix_exid
*** 5846,5851 ****
--- 5883,5910 ----
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
*************** void
*** 6447,6474 ****
Arm_relobj<big_endian>::make_exidx_input_section(
unsigned int shndx,
const elfcpp::Shdr<32, big_endian>& shdr,
! unsigned int text_shndx)
{
- // 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;
}
// Read the symbol information.
--- 6506,6562 ----
Arm_relobj<big_endian>::make_exidx_input_section(
unsigned int shndx,
const elfcpp::Shdr<32, big_endian>& shdr,
! unsigned int text_shndx,
! const elfcpp::Shdr<32, big_endian>& text_shdr)
{
// 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());
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.
*************** Arm_relobj<big_endian>::do_read_symbols(
*** 6538,6556 ****
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)
deferred_exidx_sections.push_back(i);
else
! this->make_exidx_input_section(i, shdr, text_shndx);
}
}
// This is rare.
if (!must_merge_flags_and_attributes)
{
this->merge_flags_and_attributes_ = false;
return;
}
--- 6626,6646 ----
else if (shdr.get_sh_type() == elfcpp::SHT_ARM_EXIDX)
{
unsigned int text_shndx = this->adjust_shndx(shdr.get_sh_link());
! if (text_shndx == elfcpp::SHN_UNDEF)
deferred_exidx_sections.push_back(i);
else
! {
! 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;
}
*************** Arm_relobj<big_endian>::do_read_symbols(
*** 6606,6620 ****
{
unsigned int shndx = deferred_exidx_sections[i];
elfcpp::Shdr<32, big_endian> shdr(pshdrs + shndx * shdr_size);
! unsigned int text_shndx;
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);
}
}
}
--- 6696,6709 ----
{
unsigned int shndx = deferred_exidx_sections[i];
elfcpp::Shdr<32, big_endian> shdr(pshdrs + shndx * shdr_size);
! 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);
! elfcpp::Shdr<32, big_endian> text_shdr(pshdrs
! + text_shndx * shdr_size);
! this->make_exidx_input_section(shndx, shdr, text_shndx, text_shdr);
}
}
}
*************** Output_data_plt_arm<big_endian>::Output_
*** 7069,7076 ****
{
this->rel_ = new Reloc_section(false);
layout->add_output_section_data(".rel.plt", elfcpp::SHT_REL,
! elfcpp::SHF_ALLOC, this->rel_, true, false,
! false, false);
}
template<bool big_endian>
--- 7158,7165 ----
{
this->rel_ = new Reloc_section(false);
layout->add_output_section_data(".rel.plt", elfcpp::SHT_REL,
! elfcpp::SHF_ALLOC, this->rel_,
! ORDER_DYNAMIC_PLT_RELOCS, false);
}
template<bool big_endian>
*************** Target_arm<big_endian>::make_plt_entry(S
*** 7232,7238 ****
layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS,
(elfcpp::SHF_ALLOC
| elfcpp::SHF_EXECINSTR),
! this->plt_, false, false, false, false);
}
this->plt_->add_entry(gsym);
}
--- 7321,7327 ----
layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS,
(elfcpp::SHF_ALLOC
| elfcpp::SHF_EXECINSTR),
! this->plt_, ORDER_PLT, false);
}
this->plt_->add_entry(gsym);
}
*************** Target_arm<big_endian>::gc_process_reloc
*** 8124,8130 ****
typedef Target_arm<big_endian> Arm;
typedef typename Target_arm<big_endian>::Scan Scan;
! gold::gc_process_relocs<32, big_endian, Arm, elfcpp::SHT_REL, Scan>(
symtab,
layout,
this,
--- 8213,8220 ----
typedef Target_arm<big_endian> Arm;
typedef typename Target_arm<big_endian>::Scan Scan;
! gold::gc_process_relocs<32, big_endian, Arm, elfcpp::SHT_REL, Scan,
! typename Target_arm::Relocatable_size_for_reloc>(
symtab,
layout,
this,
*************** Target_arm<big_endian>::do_finalize_sect
*** 8292,8299 ****
== NULL);
Output_segment* exidx_segment =
layout->make_output_segment(elfcpp::PT_ARM_EXIDX, elfcpp::PF_R);
! exidx_segment->add_output_section(exidx_section, elfcpp::PF_R,
! false);
}
}
--- 8382,8389 ----
== NULL);
Output_segment* exidx_segment =
layout->make_output_segment(elfcpp::PT_ARM_EXIDX, elfcpp::PF_R);
! exidx_segment->add_output_section_to_nonload(exidx_section,
! elfcpp::PF_R);
}
}
*************** Target_arm<big_endian>::do_finalize_sect
*** 8305,8313 ****
new Output_attributes_section_data(*this->attributes_section_data_);
layout->add_output_section_data(".ARM.attributes",
elfcpp::SHT_ARM_ATTRIBUTES, 0,
! attributes_section, false, false, false,
false);
}
}
// Return whether a direct absolute static relocation needs to be applied.
--- 8395,8414 ----
new Output_attributes_section_data(*this->attributes_section_data_);
layout->add_output_section_data(".ARM.attributes",
elfcpp::SHT_ARM_ATTRIBUTES, 0,
! attributes_section, ORDER_INVALID,
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.
*************** Target_arm<big_endian>::do_relax(
*** 10971,10982 ****
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 =
! Arm_output_section<big_endian>::as_arm_output_section(os);
! this->fix_exidx_coverage(layout, exidx_output_section, symtab);
done_exidx_fixup = true;
}
}
--- 11072,11099 ----
group_sections(layout, stub_group_size, stubs_always_after_branch);
// Also fix .ARM.exidx section coverage.
! 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)
{
! this->fix_exidx_coverage(layout, input_objects, exidx_output_section,
! symtab);
done_exidx_fixup = true;
}
}
*************** template<bool big_endian>
*** 11427,11432 ****
--- 11544,11550 ----
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)
{
*************** Target_arm<big_endian>::fix_exidx_covera
*** 11439,11453 ****
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();
++p)
{
! // We only care about output sections that contain executable code.
! if (((*p)->flags() & elfcpp::SHF_EXECINSTR) != 0)
! sorted_output_sections.insert(*p);
}
// Go over the output sections in ascending order of output addresses.
--- 11557,11586 ----
typedef std::set<Output_section*, output_section_address_less_than>
Sorted_output_section_list;
Sorted_output_section_list sorted_output_sections;
!
! // 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)
{
! 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 -rcp ../binutils-2.20.51.0.10.original/gold/common.cc gold/common.cc
*** ../binutils-2.20.51.0.10.original/gold/common.cc 2010-08-10 15:12:03.000000000 +0100
--- gold/common.cc 2010-08-10 15:14:02.000000000 +0100
*************** Symbol_table::do_allocate_commons_list(
*** 298,305 ****
Output_data_space *poc = new Output_data_space(addralign, ds_name);
Output_section *os = layout->add_output_section_data(name,
elfcpp::SHT_NOBITS,
! flags, poc, false,
! false, false, false);
if (os != NULL)
{
if (commons_section_type == COMMONS_SMALL)
--- 298,306 ----
Output_data_space *poc = new Output_data_space(addralign, ds_name);
Output_section *os = layout->add_output_section_data(name,
elfcpp::SHT_NOBITS,
! flags, poc,
! ORDER_INVALID,
! false);
if (os != NULL)
{
if (commons_section_type == COMMONS_SMALL)
diff -rcp ../binutils-2.20.51.0.10.original/gold/compressed_output.cc gold/compressed_output.cc
*** ../binutils-2.20.51.0.10.original/gold/compressed_output.cc 2010-08-10 15:11:28.000000000 +0100
--- gold/compressed_output.cc 2010-08-10 15:14:02.000000000 +0100
***************
*** 1,6 ****
! // compressed_output.cc -- manage compressed output sections for gold
! // Copyright 2007, 2008 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
--- 1,6 ----
! // compressed_output.cc -- manage compressed debug sections for gold
! // Copyright 2007, 2008, 2010 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
***************
*** 33,38 ****
--- 33,40 ----
namespace gold
{
+ #ifdef HAVE_ZLIB_H
+
// Compress UNCOMPRESSED_DATA of size UNCOMPRESSED_SIZE. Returns true
// if it successfully compressed, false if it failed for any reason
// (including not having zlib support in the library). If it returns
*************** namespace gold
*** 42,49 ****
// "ZLIB", and 8 bytes indicating the uncompressed size, in big-endian
// order.
- #ifdef HAVE_ZLIB_H
-
static bool
zlib_compress(const unsigned char* uncompressed_data,
unsigned long uncompressed_size,
--- 44,49 ----
*************** zlib_compress(const unsigned char* uncom
*** 81,86 ****
--- 81,129 ----
}
}
+ // Decompress COMPRESSED_DATA of size COMPRESSED_SIZE, into a buffer
+ // UNCOMPRESSED_DATA of size UNCOMPRESSED_SIZE. Returns TRUE if it
+ // decompressed successfully, false if it failed. The buffer, of
+ // appropriate size, is provided by the caller, and is typically part
+ // of the memory-mapped output file.
+
+ static bool
+ zlib_decompress(const unsigned char* compressed_data,
+ unsigned long compressed_size,
+ unsigned char* uncompressed_data,
+ unsigned long uncompressed_size)
+ {
+ z_stream strm;
+ int rc;
+
+ /* It is possible the section consists of several compressed
+ buffers concatenated together, so we uncompress in a loop. */
+ strm.zalloc = NULL;
+ strm.zfree = NULL;
+ strm.opaque = NULL;
+ strm.avail_in = compressed_size;
+ strm.next_in = const_cast<Bytef*>(compressed_data);
+ strm.avail_out = uncompressed_size;
+
+ rc = inflateInit(&strm);
+ while (strm.avail_in > 0)
+ {
+ if (rc != Z_OK)
+ return false;
+ strm.next_out = ((Bytef*) uncompressed_data
+ + (uncompressed_size - strm.avail_out));
+ rc = inflate(&strm, Z_FINISH);
+ if (rc != Z_STREAM_END)
+ return false;
+ rc = inflateReset(&strm);
+ }
+ rc = inflateEnd(&strm);
+ if (rc != Z_OK || strm.avail_out != 0)
+ return false;
+
+ return true;
+ }
+
#else // !defined(HAVE_ZLIB_H)
static bool
*************** zlib_compress(const unsigned char*, unsi
*** 90,97 ****
--- 133,194 ----
return false;
}
+ static bool
+ zlib_decompress(const unsigned char*, unsigned long,
+ unsigned char*, unsigned long)
+ {
+ return false;
+ }
+
#endif // !defined(HAVE_ZLIB_H)
+ // Read the compression header of a compressed debug section and return
+ // the uncompressed size.
+
+ uint64_t
+ get_uncompressed_size(const unsigned char* compressed_data,
+ section_size_type compressed_size)
+ {
+ const unsigned int zlib_header_size = 12;
+
+ /* Verify the compression header. Currently, we support only zlib
+ compression, so it should be "ZLIB" followed by the uncompressed
+ section size, 8 bytes in big-endian order. */
+ if (compressed_size >= zlib_header_size
+ && strncmp(reinterpret_cast<const char*>(compressed_data),
+ "ZLIB", 4) == 0)
+ return elfcpp::Swap_unaligned<64, true>::readval(compressed_data + 4);
+ return -1ULL;
+ }
+
+ // Decompress a compressed debug section directly into the output file.
+
+ bool
+ decompress_input_section(const unsigned char* compressed_data,
+ unsigned long compressed_size,
+ unsigned char* uncompressed_data,
+ unsigned long uncompressed_size)
+ {
+ const unsigned int zlib_header_size = 12;
+
+ /* Verify the compression header. Currently, we support only zlib
+ compression, so it should be "ZLIB" followed by the uncompressed
+ section size, 8 bytes in big-endian order. */
+ if (compressed_size >= zlib_header_size
+ && strncmp(reinterpret_cast<const char*>(compressed_data),
+ "ZLIB", 4) == 0)
+ {
+ unsigned long uncompressed_size_check =
+ elfcpp::Swap_unaligned<64, true>::readval(compressed_data + 4);
+ gold_assert(uncompressed_size_check == uncompressed_size);
+ return zlib_decompress(compressed_data + zlib_header_size,
+ compressed_size - zlib_header_size,
+ uncompressed_data,
+ uncompressed_size);
+ }
+ return false;
+ }
+
// Class Output_compressed_section.
// Set the final data size of a compressed section. This is where
diff -rcp ../binutils-2.20.51.0.10.original/gold/compressed_output.h gold/compressed_output.h
*** ../binutils-2.20.51.0.10.original/gold/compressed_output.h 2010-08-10 15:11:28.000000000 +0100
--- gold/compressed_output.h 2010-08-10 15:14:02.000000000 +0100
***************
*** 1,6 ****
// compressed_output.h -- compressed output sections for gold -*- C++ -*-
! // Copyright 2007, 2008 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
--- 1,6 ----
// compressed_output.h -- compressed output sections for gold -*- C++ -*-
! // Copyright 2007, 2008, 2010 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
*************** namespace gold
*** 37,42 ****
--- 37,54 ----
class General_options;
+ // Read the compression header of a compressed debug section and return
+ // the uncompressed size.
+
+ extern uint64_t
+ get_uncompressed_size(const unsigned char*, section_size_type);
+
+ // Decompress a compressed debug section directly into the output file.
+
+ extern bool
+ decompress_input_section(const unsigned char*, unsigned long, unsigned char*,
+ unsigned long);
+
// This is used for a section whose data should be compressed. It is
// a regular Output_section which computes its contents into a buffer
// and then postprocesses it.
diff -rcp ../binutils-2.20.51.0.10.original/gold/configure.ac gold/configure.ac
*** ../binutils-2.20.51.0.10.original/gold/configure.ac 2010-08-10 15:12:03.000000000 +0100
--- gold/configure.ac 2010-08-10 15:14:02.000000000 +0100
*************** AC_CONFIG_SRCDIR(gold.cc)
*** 7,13 ****
AC_CANONICAL_TARGET
! AM_INIT_AUTOMAKE([no-dist])
AM_CONFIG_HEADER(config.h:config.in)
--- 7,13 ----
AC_CANONICAL_TARGET
! AM_INIT_AUTOMAKE([no-dist parallel-tests])
AM_CONFIG_HEADER(config.h:config.in)
diff -rcp ../binutils-2.20.51.0.10.original/gold/copy-relocs.cc gold/copy-relocs.cc
*** ../binutils-2.20.51.0.10.original/gold/copy-relocs.cc 2010-08-10 15:11:28.000000000 +0100
--- gold/copy-relocs.cc 2010-08-10 15:14:02.000000000 +0100
*************** Copy_relocs<sh_type, size, big_endian>::
*** 141,148 ****
layout->add_output_section_data(".bss",
elfcpp::SHT_NOBITS,
elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE,
! this->dynbss_, false, false, false,
! false);
}
Output_data_space* dynbss = this->dynbss_;
--- 141,147 ----
layout->add_output_section_data(".bss",
elfcpp::SHT_NOBITS,
elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE,
! this->dynbss_, ORDER_BSS, false);
}
Output_data_space* dynbss = this->dynbss_;
diff -rcp ../binutils-2.20.51.0.10.original/gold/descriptors.cc gold/descriptors.cc
*** ../binutils-2.20.51.0.10.original/gold/descriptors.cc 2010-08-10 15:12:03.000000000 +0100
--- gold/descriptors.cc 2010-08-10 15:14:02.000000000 +0100
*************** Descriptors::open(int descriptor, const
*** 113,120 ****
{
Hold_lock hl(*this->lock_);
! gold_error(_("file %s was removed during the link"),
! this->open_descriptors_[descriptor].name);
}
errno = ENOENT;
--- 113,119 ----
{
Hold_lock hl(*this->lock_);
! gold_error(_("file %s was removed during the link"), name);
}
errno = ENOENT;
diff -rcp ../binutils-2.20.51.0.10.original/gold/dwarf_reader.cc gold/dwarf_reader.cc
*** ../binutils-2.20.51.0.10.original/gold/dwarf_reader.cc 2010-08-10 15:11:43.000000000 +0100
--- gold/dwarf_reader.cc 2010-08-10 15:14:02.000000000 +0100
***************
*** 32,37 ****
--- 32,38 ----
#include "reloc.h"
#include "dwarf_reader.h"
#include "int_encoding.h"
+ #include "compressed_output.h"
namespace gold {
*************** Sized_dwarf_line_info<size, big_endian>:
*** 80,85 ****
--- 81,101 ----
if (this->buffer_ == NULL)
return;
+ section_size_type uncompressed_size = 0;
+ unsigned char* uncompressed_data = NULL;
+ if (object->section_is_compressed(debug_shndx, &uncompressed_size))
+ {
+ uncompressed_data = new unsigned char[uncompressed_size];
+ if (!decompress_input_section(this->buffer_,
+ this->buffer_end_ - this->buffer_,
+ uncompressed_data,
+ uncompressed_size))
+ object->error(_("could not decompress section %s"),
+ object->section_name(debug_shndx).c_str());
+ this->buffer_ = uncompressed_data;
+ this->buffer_end_ = this->buffer_ + uncompressed_size;
+ }
+
// Find the relocation section for ".debug_line".
// We expect these for relobjs (.o's) but not dynobjs (.so's).
bool got_relocs = false;
diff -rcp ../binutils-2.20.51.0.10.original/gold/dynobj.cc gold/dynobj.cc
*** ../binutils-2.20.51.0.10.original/gold/dynobj.cc 2010-08-10 15:12:03.000000000 +0100
--- gold/dynobj.cc 2010-08-10 15:14:02.000000000 +0100
*************** Sized_dynobj<size, big_endian>::do_add_s
*** 753,760 ****
template<int size, bool big_endian>
Archive::Should_include
! Sized_dynobj<size, big_endian>::do_should_include_member(
! Symbol_table*, Read_symbols_data*, std::string*)
{
return Archive::SHOULD_INCLUDE_YES;
}
--- 753,762 ----
template<int size, bool big_endian>
Archive::Should_include
! Sized_dynobj<size, big_endian>::do_should_include_member(Symbol_table*,
! Layout*,
! Read_symbols_data*,
! std::string*)
{
return Archive::SHOULD_INCLUDE_YES;
}
diff -rcp ../binutils-2.20.51.0.10.original/gold/dynobj.h gold/dynobj.h
*** ../binutils-2.20.51.0.10.original/gold/dynobj.h 2010-08-10 15:11:43.000000000 +0100
--- gold/dynobj.h 2010-08-10 15:14:02.000000000 +0100
*************** class Sized_dynobj : public Dynobj
*** 178,184 ****
do_add_symbols(Symbol_table*, Read_symbols_data*, Layout*);
Archive::Should_include
! do_should_include_member(Symbol_table* symtab, Read_symbols_data*,
std::string* why);
// Get the size of a section.
--- 178,184 ----
do_add_symbols(Symbol_table*, Read_symbols_data*, Layout*);
Archive::Should_include
! do_should_include_member(Symbol_table* symtab, Layout*, Read_symbols_data*,
std::string* why);
// Get the size of a section.
diff -rcp ../binutils-2.20.51.0.10.original/gold/fileread.cc gold/fileread.cc
*** ../binutils-2.20.51.0.10.original/gold/fileread.cc 2010-08-10 15:11:28.000000000 +0100
--- gold/fileread.cc 2010-08-10 15:14:02.000000000 +0100
*************** File_read::get_mtime()
*** 841,857 ****
#endif
}
! // Try to find a file in the extra search dirs. Returns true on success.
! static bool
! try_extra_search_path(int* pindex, const Input_file_argument* input_argument,
! std::string filename, std::string* found_name,
! std::string* namep) {
if (input_argument->extra_search_path() == NULL)
return false;
std::string name = input_argument->extra_search_path();
! if (!IS_DIR_SEPARATOR (name[name.length() - 1]))
name += '/';
name += filename;
--- 841,859 ----
#endif
}
! // Try to find a file in the extra search dirs. Returns true on success.
! bool
! Input_file::try_extra_search_path(int* pindex,
! const Input_file_argument* input_argument,
! std::string filename, std::string* found_name,
! std::string* namep)
! {
if (input_argument->extra_search_path() == NULL)
return false;
std::string name = input_argument->extra_search_path();
! if (!IS_DIR_SEPARATOR(name[name.length() - 1]))
name += '/';
name += filename;
*************** try_extra_search_path(int* pindex, const
*** 873,882 ****
// In each, we look in extra_search_path + library_path to find
// the file location, rather than the current directory.
! static bool
! find_file(const Dirsearch& dirpath, int* pindex,
! const Input_file_argument* input_argument, bool* is_in_sysroot,
! std::string* found_name, std::string* namep)
{
std::string name;
--- 875,885 ----
// In each, we look in extra_search_path + library_path to find
// the file location, rather than the current directory.
! bool
! Input_file::find_file(const Dirsearch& dirpath, int* pindex,
! const Input_file_argument* input_argument,
! bool* is_in_sysroot,
! std::string* found_name, std::string* namep)
{
std::string name;
*************** find_file(const Dirsearch& dirpath, int*
*** 914,924 ****
else
n1 = input_argument->name();
! if (try_extra_search_path(pindex, input_argument, n1, found_name, namep))
return true;
! if (!n2.empty() && try_extra_search_path(pindex, input_argument, n2,
! found_name, namep))
return true;
// It is not in the extra_search_path.
--- 917,929 ----
else
n1 = input_argument->name();
! if (Input_file::try_extra_search_path(pindex, input_argument, n1,
! found_name, namep))
return true;
! if (!n2.empty() && Input_file::try_extra_search_path(pindex,
! input_argument, n2,
! found_name, namep))
return true;
// It is not in the extra_search_path.
*************** bool
*** 969,976 ****
Input_file::open(const Dirsearch& dirpath, const Task* task, int *pindex)
{
std::string name;
! if (!find_file(dirpath, pindex, this->input_argument_, &this->is_in_sysroot_,
! &this->found_name_, &name))
return false;
// Now that we've figured out where the file lives, try to open it.
--- 974,981 ----
Input_file::open(const Dirsearch& dirpath, const Task* task, int *pindex)
{
std::string name;
! if (!Input_file::find_file(dirpath, pindex, this->input_argument_,
! &this->is_in_sysroot_, &this->found_name_, &name))
return false;
// Now that we've figured out where the file lives, try to open it.
diff -rcp ../binutils-2.20.51.0.10.original/gold/fileread.h gold/fileread.h
*** ../binutils-2.20.51.0.10.original/gold/fileread.h 2010-08-10 15:11:40.000000000 +0100
--- gold/fileread.h 2010-08-10 15:14:02.000000000 +0100
*************** class Input_file
*** 565,570 ****
--- 565,584 ----
format() const
{ return this->format_; }
+ // Try to find a file in the extra search dirs. Returns true on success.
+ static bool
+ try_extra_search_path(int* pindex,
+ const Input_file_argument* input_argument,
+ std::string filename, std::string* found_name,
+ std::string* namep);
+
+ // Find the actual file.
+ static bool
+ find_file(const Dirsearch& dirpath, int* pindex,
+ const Input_file_argument* input_argument,
+ bool* is_in_sysroot,
+ std::string* found_name, std::string* namep);
+
private:
Input_file(const Input_file&);
Input_file& operator=(const Input_file&);
diff -rcp ../binutils-2.20.51.0.10.original/gold/gc.h gold/gc.h
*** ../binutils-2.20.51.0.10.original/gold/gc.h 2010-08-10 15:11:43.000000000 +0100
--- gold/gc.h 2010-08-10 15:14:02.000000000 +0100
*************** struct Symbols_data
*** 151,156 ****
--- 151,170 ----
section_size_type symbol_names_size;
};
+ // Relocations of type SHT_REL store the addend value in their bytes.
+ // This function returns the size of the embedded addend which is
+ // nothing but the size of the relocation.
+
+ template<typename Classify_reloc>
+ inline unsigned int
+ get_embedded_addend_size(int sh_type, int r_type, Relobj* obj)
+ {
+ if (sh_type != elfcpp::SHT_REL)
+ return 0;
+ Classify_reloc classify_reloc;
+ return classify_reloc.get_size_for_reloc(r_type, obj);
+ }
+
// This function implements the generic part of reloc
// processing to map a section to all the sections it
// references through relocs. It is called only during
*************** struct Symbols_data
*** 158,164 ****
// folding (--icf).
template<int size, bool big_endian, typename Target_type, int sh_type,
! typename Scan>
inline void
gc_process_relocs(
Symbol_table* symtab,
--- 172,178 ----
// folding (--icf).
template<int size, bool big_endian, typename Target_type, int sh_type,
! typename Scan, typename Classify_reloc>
inline void
gc_process_relocs(
Symbol_table* symtab,
*************** gc_process_relocs(
*** 185,190 ****
--- 199,205 ----
Icf::Symbol_info* symvec = NULL;
Icf::Addend_info* addendvec = NULL;
Icf::Offset_info* offsetvec = NULL;
+ Icf::Reloc_addend_size_info* reloc_addend_size_vec = NULL;
bool is_icf_tracked = false;
const char* cident_section_name = NULL;
*************** gc_process_relocs(
*** 205,210 ****
--- 220,226 ----
symvec = &reloc_info->symbol_info;
addendvec = &reloc_info->addend_info;
offsetvec = &reloc_info->offset_info;
+ reloc_addend_size_vec = &reloc_info->reloc_addend_size_info;
}
check_section_for_function_pointers =
*************** gc_process_relocs(
*** 243,248 ****
--- 259,267 ----
uint64_t reloc_offset =
convert_to_section_size_type(reloc.get_r_offset());
(*offsetvec).push_back(reloc_offset);
+ (*reloc_addend_size_vec).push_back(
+ get_embedded_addend_size<Classify_reloc>(sh_type, r_type,
+ src_obj));
}
// When doing safe folding, check to see if this relocation is that
*************** gc_process_relocs(
*** 316,321 ****
--- 335,343 ----
uint64_t reloc_offset =
convert_to_section_size_type(reloc.get_r_offset());
(*offsetvec).push_back(reloc_offset);
+ (*reloc_addend_size_vec).push_back(
+ get_embedded_addend_size<Classify_reloc>(sh_type, r_type,
+ src_obj));
}
if (gsym->source() != Symbol::FROM_OBJECT)
diff -rcp ../binutils-2.20.51.0.10.original/gold/gold.cc gold/gold.cc
*** ../binutils-2.20.51.0.10.original/gold/gold.cc 2010-08-10 15:11:28.000000000 +0100
--- gold/gold.cc 2010-08-10 15:14:02.000000000 +0100
*************** queue_middle_tasks(const General_options
*** 309,315 ****
Mapfile* mapfile)
{
// Add any symbols named with -u options to the symbol table.
! symtab->add_undefined_symbols_from_command_line();
// If garbage collection was chosen, relocs have been read and processed
// at this point by pre_middle_tasks. Layout can then be done for all
--- 309,315 ----
Mapfile* mapfile)
{
// Add any symbols named with -u options to the symbol table.
! symtab->add_undefined_symbols_from_command_line(layout);
// If garbage collection was chosen, relocs have been read and processed
// at this point by pre_middle_tasks. Layout can then be done for all
*************** queue_middle_tasks(const General_options
*** 333,339 ****
}
}
// Symbols named with -u should not be considered garbage.
! symtab->gc_mark_undef_symbols();
gold_assert(symtab->gc() != NULL);
// Do a transitive closure on all references to determine the worklist.
symtab->gc()->do_transitive_closure();
--- 333,339 ----
}
}
// Symbols named with -u should not be considered garbage.
! symtab->gc_mark_undef_symbols(layout);
gold_assert(symtab->gc() != NULL);
// Do a transitive closure on all references to determine the worklist.
symtab->gc()->do_transitive_closure();
diff -rcp ../binutils-2.20.51.0.10.original/gold/i386.cc gold/i386.cc
*** ../binutils-2.20.51.0.10.original/gold/i386.cc 2010-08-10 15:11:58.000000000 +0100
--- gold/i386.cc 2010-08-10 15:14:03.000000000 +0100
***************
*** 1,6 ****
// i386.cc -- i386 target support for gold.
! // Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
--- 1,6 ----
// i386.cc -- i386 target support for gold.
! // Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
*************** class Target_i386 : public Target_freebs
*** 59,66 ****
Target_i386()
: Target_freebsd<32, false>(&i386_info),
! got_(NULL), plt_(NULL), got_plt_(NULL), global_offset_table_(NULL),
! rel_dyn_(NULL), copy_relocs_(elfcpp::R_386_COPY), dynbss_(NULL),
got_mod_index_offset_(-1U), tls_base_symbol_defined_(false)
{ }
--- 59,67 ----
Target_i386()
: Target_freebsd<32, false>(&i386_info),
! got_(NULL), plt_(NULL), got_plt_(NULL), got_tlsdesc_(NULL),
! global_offset_table_(NULL), rel_dyn_(NULL),
! copy_relocs_(elfcpp::R_386_COPY), dynbss_(NULL),
got_mod_index_offset_(-1U), tls_base_symbol_defined_(false)
{ }
*************** class Target_i386 : public Target_freebs
*** 385,390 ****
--- 386,399 ----
return this->got_plt_;
}
+ // Get the GOT section for TLSDESC entries.
+ Output_data_got<32, false>*
+ got_tlsdesc_section() const
+ {
+ gold_assert(this->got_tlsdesc_ != NULL);
+ return this->got_tlsdesc_;
+ }
+
// Create a PLT entry for a global symbol.
void
make_plt_entry(Symbol_table*, Layout*, Symbol*);
*************** class Target_i386 : public Target_freebs
*** 447,452 ****
--- 456,463 ----
Output_data_plt_i386* plt_;
// The GOT PLT section.
Output_data_space* got_plt_;
+ // The GOT section for TLSDESC relocations.
+ Output_data_got<32, false>* got_tlsdesc_;
// The _GLOBAL_OFFSET_TABLE_ symbol.
Symbol* global_offset_table_;
// The dynamic reloc section.
*************** Target_i386::got_section(Symbol_table* s
*** 494,512 ****
this->got_ = new Output_data_got<32, false>();
! Output_section* os;
! os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
! (elfcpp::SHF_ALLOC
! | elfcpp::SHF_WRITE),
! this->got_, false, true, true,
! false);
this->got_plt_ = new Output_data_space(4, "** GOT PLT");
! os = layout->add_output_section_data(".got.plt", elfcpp::SHT_PROGBITS,
! (elfcpp::SHF_ALLOC
! | elfcpp::SHF_WRITE),
! this->got_plt_, false, false, false,
! true);
// The first three entries are reserved.
this->got_plt_->set_current_data_size(3 * 4);
--- 505,521 ----
this->got_ = new Output_data_got<32, false>();
! layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
! (elfcpp::SHF_ALLOC
! | elfcpp::SHF_WRITE),
! this->got_, ORDER_RELRO_LAST, true);
this->got_plt_ = new Output_data_space(4, "** GOT PLT");
! layout->add_output_section_data(".got.plt", elfcpp::SHT_PROGBITS,
! (elfcpp::SHF_ALLOC
! | elfcpp::SHF_WRITE),
! this->got_plt_, ORDER_NON_RELRO_FIRST,
! false);
// The first three entries are reserved.
this->got_plt_->set_current_data_size(3 * 4);
*************** Target_i386::got_section(Symbol_table* s
*** 523,528 ****
--- 532,546 ----
elfcpp::STB_LOCAL,
elfcpp::STV_HIDDEN, 0,
false, false);
+
+ // If there are any TLSDESC relocations, they get GOT entries in
+ // .got.plt after the jump slot entries.
+ this->got_tlsdesc_ = new Output_data_got<32, false>();
+ layout->add_output_section_data(".got.plt", elfcpp::SHT_PROGBITS,
+ (elfcpp::SHF_ALLOC
+ | elfcpp::SHF_WRITE),
+ this->got_tlsdesc_,
+ ORDER_NON_RELRO_FIRST, false);
}
return this->got_;
*************** Target_i386::rel_dyn_section(Layout* lay
*** 538,545 ****
gold_assert(layout != NULL);
this->rel_dyn_ = new Reloc_section(parameters->options().combreloc());
layout->add_output_section_data(".rel.dyn", elfcpp::SHT_REL,
! elfcpp::SHF_ALLOC, this->rel_dyn_, true,
! false, false, false);
}
return this->rel_dyn_;
}
--- 556,563 ----
gold_assert(layout != NULL);
this->rel_dyn_ = new Reloc_section(parameters->options().combreloc());
layout->add_output_section_data(".rel.dyn", elfcpp::SHT_REL,
! elfcpp::SHF_ALLOC, this->rel_dyn_,
! ORDER_DYNAMIC_RELOCS, false);
}
return this->rel_dyn_;
}
*************** Output_data_plt_i386::Output_data_plt_i3
*** 621,628 ****
{
this->rel_ = new Reloc_section(false);
layout->add_output_section_data(".rel.plt", elfcpp::SHT_REL,
! elfcpp::SHF_ALLOC, this->rel_, true,
! false, false, false);
}
void
--- 639,646 ----
{
this->rel_ = new Reloc_section(false);
layout->add_output_section_data(".rel.plt", elfcpp::SHT_REL,
! elfcpp::SHF_ALLOC, this->rel_,
! ORDER_DYNAMIC_PLT_RELOCS, false);
}
void
*************** Output_data_plt_i386::rel_tls_desc(Layou
*** 674,680 ****
this->tls_desc_rel_ = new Reloc_section(false);
layout->add_output_section_data(".rel.plt", elfcpp::SHT_REL,
elfcpp::SHF_ALLOC, this->tls_desc_rel_,
! true, false, false, false);
gold_assert(this->tls_desc_rel_->output_section() ==
this->rel_->output_section());
}
--- 692,698 ----
this->tls_desc_rel_ = new Reloc_section(false);
layout->add_output_section_data(".rel.plt", elfcpp::SHT_REL,
elfcpp::SHF_ALLOC, this->tls_desc_rel_,
! ORDER_DYNAMIC_PLT_RELOCS, false);
gold_assert(this->tls_desc_rel_->output_section() ==
this->rel_->output_section());
}
*************** Target_i386::make_plt_entry(Symbol_table
*** 825,831 ****
layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS,
(elfcpp::SHF_ALLOC
| elfcpp::SHF_EXECINSTR),
! this->plt_, false, false, false, false);
}
this->plt_->add_entry(gsym);
--- 843,849 ----
layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS,
(elfcpp::SHF_ALLOC
| elfcpp::SHF_EXECINSTR),
! this->plt_, ORDER_PLT, false);
}
this->plt_->add_entry(gsym);
*************** Target_i386::Scan::local(Symbol_table* s
*** 1119,1127 ****
target->define_tls_base_symbol(symtab, layout);
if (optimized_type == tls::TLSOPT_NONE)
{
! // Create a double GOT entry with an R_386_TLS_DESC reloc.
! Output_data_got<32, false>* got
! = target->got_section(symtab, layout);
unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
if (!object->local_has_got_offset(r_sym, GOT_TYPE_TLS_DESC))
{
--- 1137,1149 ----
target->define_tls_base_symbol(symtab, layout);
if (optimized_type == tls::TLSOPT_NONE)
{
! // Create a double GOT entry with an R_386_TLS_DESC
! // reloc. The R_386_TLS_DESC reloc is resolved
! // lazily, so the GOT entry needs to be in an area in
! // .got.plt, not .got. Call got_section to make sure
! // the section has been created.
! target->got_section(symtab, layout);
! Output_data_got<32, false>* got = target->got_tlsdesc_section();
unsigned int r_sym = elfcpp::elf_r_sym<32>(reloc.get_r_info());
if (!object->local_has_got_offset(r_sym, GOT_TYPE_TLS_DESC))
{
*************** Target_i386::Scan::global(Symbol_table*
*** 1503,1511 ****
target->define_tls_base_symbol(symtab, layout);
if (optimized_type == tls::TLSOPT_NONE)
{
! // Create a double GOT entry with an R_386_TLS_DESC reloc.
! Output_data_got<32, false>* got
! = target->got_section(symtab, layout);
Reloc_section* rt = target->rel_tls_desc_section(layout);
got->add_global_pair_with_rel(gsym, GOT_TYPE_TLS_DESC, rt,
elfcpp::R_386_TLS_DESC, 0);
--- 1525,1537 ----
target->define_tls_base_symbol(symtab, layout);
if (optimized_type == tls::TLSOPT_NONE)
{
! // Create a double GOT entry with an R_386_TLS_DESC
! // reloc. The R_386_TLS_DESC reloc is resolved
! // lazily, so the GOT entry needs to be in an area in
! // .got.plt, not .got. Call got_section to make sure
! // the section has been created.
! target->got_section(symtab, layout);
! Output_data_got<32, false>* got = target->got_tlsdesc_section();
Reloc_section* rt = target->rel_tls_desc_section(layout);
got->add_global_pair_with_rel(gsym, GOT_TYPE_TLS_DESC, rt,
elfcpp::R_386_TLS_DESC, 0);
*************** Target_i386::gc_process_relocs(Symbol_ta
*** 1626,1632 ****
const unsigned char* plocal_symbols)
{
gold::gc_process_relocs<32, false, Target_i386, elfcpp::SHT_REL,
! Target_i386::Scan>(
symtab,
layout,
this,
--- 1652,1659 ----
const unsigned char* plocal_symbols)
{
gold::gc_process_relocs<32, false, Target_i386, elfcpp::SHT_REL,
! Target_i386::Scan,
! Target_i386::Relocatable_size_for_reloc>(
symtab,
layout,
this,
*************** Target_i386::Relocate::relocate_tls(cons
*** 2047,2064 ****
unsigned int got_type = (optimized_type == tls::TLSOPT_TO_IE
? GOT_TYPE_TLS_NOFFSET
: GOT_TYPE_TLS_DESC);
! unsigned int got_offset;
if (gsym != NULL)
{
gold_assert(gsym->has_got_offset(got_type));
! got_offset = gsym->got_offset(got_type) - target->got_size();
}
else
{
unsigned int r_sym = elfcpp::elf_r_sym<32>(rel.get_r_info());
gold_assert(object->local_has_got_offset(r_sym, got_type));
! got_offset = (object->local_got_offset(r_sym, got_type)
! - target->got_size());
}
if (optimized_type == tls::TLSOPT_TO_IE)
{
--- 2074,2100 ----
unsigned int got_type = (optimized_type == tls::TLSOPT_TO_IE
? GOT_TYPE_TLS_NOFFSET
: GOT_TYPE_TLS_DESC);
! unsigned int got_offset = 0;
! if (r_type == elfcpp::R_386_TLS_GOTDESC
! && optimized_type == tls::TLSOPT_NONE)
! {
! // We created GOT entries in the .got.tlsdesc portion of
! // the .got.plt section, but the offset stored in the
! // symbol is the offset within .got.tlsdesc.
! got_offset = (target->got_size()
! + target->got_plt_section()->data_size());
! }
if (gsym != NULL)
{
gold_assert(gsym->has_got_offset(got_type));
! got_offset += gsym->got_offset(got_type) - target->got_size();
}
else
{
unsigned int r_sym = elfcpp::elf_r_sym<32>(rel.get_r_info());
gold_assert(object->local_has_got_offset(r_sym, got_type));
! got_offset += (object->local_got_offset(r_sym, got_type)
! - target->got_size());
}
if (optimized_type == tls::TLSOPT_TO_IE)
{
diff -rcp ../binutils-2.20.51.0.10.original/gold/icf.cc gold/icf.cc
*** ../binutils-2.20.51.0.10.original/gold/icf.cc 2010-08-10 15:11:43.000000000 +0100
--- gold/icf.cc 2010-08-10 15:14:03.000000000 +0100
***************
*** 145,150 ****
--- 145,152 ----
#include "symtab.h"
#include "libiberty.h"
#include "demangle.h"
+ #include "elfcpp.h"
+ #include "int_encoding.h"
namespace gold
{
*************** get_section_contents(bool first_iteratio
*** 269,280 ****
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();
Icf::Addend_info::iterator it_a = a.begin();
Icf::Offset_info::iterator it_o = o.begin();
! for (; it_v != v.end(); ++it_v, ++it_s, ++it_a, ++it_o)
{
// ADDEND_STR stores the symbol value and addend and offset,
// each atmost 16 hex digits long. it_a points to a pair
--- 271,286 ----
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::Reloc_addend_size_info reloc_addend_size_info =
+ (it_reloc_info_list->second).reloc_addend_size_info;
Icf::Sections_reachable_info::iterator it_v = v.begin();
Icf::Symbol_info::iterator it_s = s.begin();
Icf::Addend_info::iterator it_a = a.begin();
Icf::Offset_info::iterator it_o = o.begin();
+ Icf::Reloc_addend_size_info::iterator it_addend_size =
+ reloc_addend_size_info.begin();
! for (; it_v != v.end(); ++it_v, ++it_s, ++it_a, ++it_o, ++it_addend_size)
{
// ADDEND_STR stores the symbol value and addend and offset,
// each atmost 16 hex digits long. it_a points to a pair
*************** get_section_contents(bool first_iteratio
*** 372,377 ****
--- 378,423 ----
if (addend < 0xffffff00)
offset = offset + addend;
+ // For SHT_REL relocation sections, the addend is stored in the
+ // text section at the relocation offset.
+ uint64_t reloc_addend_value = 0;
+ const unsigned char* reloc_addend_ptr =
+ contents + static_cast<unsigned long long>(*it_o);
+ switch(*it_addend_size)
+ {
+ case 0:
+ {
+ break;
+ }
+ case 1:
+ {
+ reloc_addend_value =
+ read_from_pointer<8>(reloc_addend_ptr);
+ break;
+ }
+ case 2:
+ {
+ reloc_addend_value =
+ read_from_pointer<16>(reloc_addend_ptr);
+ break;
+ }
+ case 4:
+ {
+ reloc_addend_value =
+ read_from_pointer<32>(reloc_addend_ptr);
+ break;
+ }
+ case 8:
+ {
+ reloc_addend_value =
+ read_from_pointer<64>(reloc_addend_ptr);
+ break;
+ }
+ default:
+ gold_unreachable();
+ }
+ offset = offset + reloc_addend_value;
+
section_size_type secn_len;
const unsigned char* str_contents =
(it_v->first)->section_contents(it_v->second,
diff -rcp ../binutils-2.20.51.0.10.original/gold/icf.h gold/icf.h
*** ../binutils-2.20.51.0.10.original/gold/icf.h 2010-08-10 15:12:03.000000000 +0100
--- gold/icf.h 2010-08-10 15:14:03.000000000 +0100
*************** class Icf
*** 43,48 ****
--- 43,49 ----
typedef std::vector<Symbol*> Symbol_info;
typedef std::vector<std::pair<long long, long long> > Addend_info;
typedef std::vector<uint64_t> Offset_info;
+ typedef std::vector<unsigned int> Reloc_addend_size_info;
typedef Unordered_map<Section_id,
unsigned int,
Section_id_hash> Uniq_secn_id_map;
*************** class Icf
*** 57,62 ****
--- 58,64 ----
// This stores the symbol value and the addend for a reloc.
Addend_info addend_info;
Offset_info offset_info;
+ Reloc_addend_size_info reloc_addend_size_info;
} Reloc_info;
typedef Unordered_map<Section_id, Reloc_info,
diff -rcp ../binutils-2.20.51.0.10.original/gold/int_encoding.h gold/int_encoding.h
*** ../binutils-2.20.51.0.10.original/gold/int_encoding.h 2010-08-10 15:11:40.000000000 +0100
--- gold/int_encoding.h 2010-08-10 15:14:03.000000000 +0100
*************** void insert_into_vector(std::vector<unsi
*** 77,82 ****
--- 77,96 ----
destination->insert(destination->end(), buffer, buffer + valsize / 8);
}
+ // Read a possibly unaligned integer of SIZE from SOURCE.
+
+ template <int valsize>
+ typename elfcpp::Valtype_base<valsize>::Valtype
+ read_from_pointer(const unsigned char* source)
+ {
+ typename elfcpp::Valtype_base<valsize>::Valtype return_value;
+ if (parameters->target().is_big_endian())
+ return_value = elfcpp::Swap_unaligned<valsize, true>::readval(source);
+ else
+ return_value = elfcpp::Swap_unaligned<valsize, false>::readval(source);
+ return return_value;
+ }
+
// Read a possibly unaligned integer of SIZE. Update SOURCE after read.
template <int valsize>
diff -rcp ../binutils-2.20.51.0.10.original/gold/layout.cc gold/layout.cc
*** ../binutils-2.20.51.0.10.original/gold/layout.cc 2010-08-10 15:12:03.000000000 +0100
--- gold/layout.cc 2010-08-10 15:14:03.000000000 +0100
*************** Layout::find_output_segment(elfcpp::PT t
*** 409,417 ****
Output_section*
Layout::get_output_section(const char* name, Stringpool::Key name_key,
elfcpp::Elf_Word type, elfcpp::Elf_Xword flags,
! bool is_interp, bool is_dynamic_linker_section,
! bool is_relro, bool is_last_relro,
! bool is_first_non_relro)
{
elfcpp::Elf_Xword lookup_flags = flags;
--- 409,415 ----
Output_section*
Layout::get_output_section(const char* name, Stringpool::Key name_key,
elfcpp::Elf_Word type, elfcpp::Elf_Xword flags,
! Output_section_order order, bool is_relro)
{
elfcpp::Elf_Xword lookup_flags = flags;
*************** Layout::get_output_section(const char* n
*** 460,468 ****
}
if (os == NULL)
! os = this->make_output_section(name, type, flags, is_interp,
! is_dynamic_linker_section, is_relro,
! is_last_relro, is_first_non_relro);
ins.first->second = os;
return os;
}
--- 458,465 ----
}
if (os == NULL)
! os = this->make_output_section(name, type, flags, order, is_relro);
!
ins.first->second = os;
return os;
}
*************** Layout::get_output_section(const char* n
*** 482,490 ****
Output_section*
Layout::choose_output_section(const Relobj* relobj, const char* name,
elfcpp::Elf_Word type, elfcpp::Elf_Xword flags,
! bool is_input_section, bool is_interp,
! bool is_dynamic_linker_section, bool is_relro,
! bool is_last_relro, bool is_first_non_relro)
{
// We should not see any input sections after we have attached
// sections to segments.
--- 479,486 ----
Output_section*
Layout::choose_output_section(const Relobj* relobj, const char* name,
elfcpp::Elf_Word type, elfcpp::Elf_Xword flags,
! bool is_input_section, Output_section_order order,
! bool is_relro)
{
// We should not see any input sections after we have attached
// sections to segments.
*************** Layout::choose_output_section(const Relo
*** 546,555 ****
name = this->namepool_.add(name, false, NULL);
! Output_section* os =
! this->make_output_section(name, type, flags, is_interp,
! is_dynamic_linker_section, is_relro,
! is_last_relro, is_first_non_relro);
os->set_found_in_sections_clause();
// Special handling for NOLOAD sections.
--- 542,550 ----
name = this->namepool_.add(name, false, NULL);
! Output_section* os = this->make_output_section(name, type, flags,
! order, is_relro);
!
os->set_found_in_sections_clause();
// Special handling for NOLOAD sections.
*************** Layout::choose_output_section(const Relo
*** 591,599 ****
// Find or make the output section. The output section is selected
// based on the section name, type, and flags.
! return this->get_output_section(name, name_key, type, flags, is_interp,
! is_dynamic_linker_section, is_relro,
! is_last_relro, is_first_non_relro);
}
// Return the output section to use for input section SHNDX, with name
--- 586,592 ----
// Find or make the output section. The output section is selected
// based on the section name, type, and flags.
! return this->get_output_section(name, name_key, type, flags, order, is_relro);
}
// Return the output section to use for input section SHNDX, with name
*************** Layout::layout(Sized_relobj<size, big_en
*** 647,660 ****
&& (shdr.get_sh_flags() & elfcpp::SHF_GROUP) != 0)
{
name = this->namepool_.add(name, true, NULL);
! os = this->make_output_section(name, sh_type, shdr.get_sh_flags(), false,
! false, false, false, false);
}
else
{
os = this->choose_output_section(object, name, sh_type,
! shdr.get_sh_flags(), true, false,
! false, false, false, false);
if (os == NULL)
return NULL;
}
--- 640,653 ----
&& (shdr.get_sh_flags() & elfcpp::SHF_GROUP) != 0)
{
name = this->namepool_.add(name, true, NULL);
! os = this->make_output_section(name, sh_type, shdr.get_sh_flags(),
! ORDER_INVALID, false);
}
else
{
os = this->choose_output_section(object, name, sh_type,
! shdr.get_sh_flags(), true,
! ORDER_INVALID, false);
if (os == NULL)
return NULL;
}
*************** Layout::layout_reloc(Sized_relobj<size,
*** 709,721 ****
if (!parameters->options().relocatable()
|| (data_section->flags() & elfcpp::SHF_GROUP) == 0)
os = this->choose_output_section(object, name.c_str(), sh_type,
! shdr.get_sh_flags(), false, false,
! false, false, false, false);
else
{
const char* n = this->namepool_.add(name.c_str(), true, NULL);
os = this->make_output_section(n, sh_type, shdr.get_sh_flags(),
! false, false, false, false, false);
}
os->set_should_link_to_symtab();
--- 702,714 ----
if (!parameters->options().relocatable()
|| (data_section->flags() & elfcpp::SHF_GROUP) == 0)
os = this->choose_output_section(object, name.c_str(), sh_type,
! shdr.get_sh_flags(), false,
! ORDER_INVALID, false);
else
{
const char* n = this->namepool_.add(name.c_str(), true, NULL);
os = this->make_output_section(n, sh_type, shdr.get_sh_flags(),
! ORDER_INVALID, false);
}
os->set_should_link_to_symtab();
*************** Layout::layout_group(Symbol_table* symta
*** 764,771 ****
Output_section* os = this->make_output_section(group_section_name,
elfcpp::SHT_GROUP,
shdr.get_sh_flags(),
! false, false, false,
! false, false);
// We need to find a symbol with the signature in the symbol table.
// If we don't find one now, we need to look again later.
--- 757,763 ----
Output_section* os = this->make_output_section(group_section_name,
elfcpp::SHT_GROUP,
shdr.get_sh_flags(),
! ORDER_INVALID, false);
// We need to find a symbol with the signature in the symbol table.
// If we don't find one now, we need to look again later.
*************** Layout::layout_eh_frame(Sized_relobj<siz
*** 815,826 ****
gold_assert((shdr.get_sh_flags() & elfcpp::SHF_ALLOC) != 0);
const char* const name = ".eh_frame";
! Output_section* os = this->choose_output_section(object,
! name,
elfcpp::SHT_PROGBITS,
! elfcpp::SHF_ALLOC,
! false, false, false,
! false, false, false);
if (os == NULL)
return NULL;
--- 807,816 ----
gold_assert((shdr.get_sh_flags() & elfcpp::SHF_ALLOC) != 0);
const char* const name = ".eh_frame";
! Output_section* os = this->choose_output_section(object, name,
elfcpp::SHT_PROGBITS,
! elfcpp::SHF_ALLOC, false,
! ORDER_EHFRAME, false);
if (os == NULL)
return NULL;
*************** Layout::layout_eh_frame(Sized_relobj<siz
*** 832,843 ****
if (parameters->options().eh_frame_hdr())
{
Output_section* hdr_os =
! this->choose_output_section(NULL,
! ".eh_frame_hdr",
elfcpp::SHT_PROGBITS,
! elfcpp::SHF_ALLOC,
! false, false, false,
! false, false, false);
if (hdr_os != NULL)
{
--- 822,831 ----
if (parameters->options().eh_frame_hdr())
{
Output_section* hdr_os =
! this->choose_output_section(NULL, ".eh_frame_hdr",
elfcpp::SHT_PROGBITS,
! elfcpp::SHF_ALLOC, false,
! ORDER_EHFRAME, false);
if (hdr_os != NULL)
{
*************** Layout::layout_eh_frame(Sized_relobj<siz
*** 852,858 ****
Output_segment* hdr_oseg;
hdr_oseg = this->make_output_segment(elfcpp::PT_GNU_EH_FRAME,
elfcpp::PF_R);
! hdr_oseg->add_output_section(hdr_os, elfcpp::PF_R, false);
}
this->eh_frame_data_->set_eh_frame_hdr(hdr_posd);
--- 840,847 ----
Output_segment* hdr_oseg;
hdr_oseg = this->make_output_segment(elfcpp::PT_GNU_EH_FRAME,
elfcpp::PF_R);
! hdr_oseg->add_output_section_to_nonload(hdr_os,
! elfcpp::PF_R);
}
this->eh_frame_data_->set_eh_frame_hdr(hdr_posd);
*************** Output_section*
*** 905,919 ****
Layout::add_output_section_data(const char* name, elfcpp::Elf_Word type,
elfcpp::Elf_Xword flags,
Output_section_data* posd,
! bool is_dynamic_linker_section,
! bool is_relro, bool is_last_relro,
! bool is_first_non_relro)
{
Output_section* os = this->choose_output_section(NULL, name, type, flags,
! false, false,
! is_dynamic_linker_section,
! is_relro, is_last_relro,
! is_first_non_relro);
if (os != NULL)
os->add_output_section_data(posd);
return os;
--- 894,903 ----
Layout::add_output_section_data(const char* name, elfcpp::Elf_Word type,
elfcpp::Elf_Xword flags,
Output_section_data* posd,
! Output_section_order order, bool is_relro)
{
Output_section* os = this->choose_output_section(NULL, name, type, flags,
! false, order, is_relro);
if (os != NULL)
os->add_output_section_data(posd);
return os;
*************** Layout::section_flags_to_segment(elfcpp:
*** 944,964 ****
static bool
is_compressible_debug_section(const char* secname)
{
! return (strncmp(secname, ".debug", sizeof(".debug") - 1) == 0);
}
// Make a new Output_section, and attach it to segments as
! // appropriate. IS_INTERP is true if this is the .interp section.
! // IS_DYNAMIC_LINKER_SECTION is true if this section is used by the
! // dynamic linker. IS_RELRO is true if this is a relro section.
! // IS_LAST_RELRO is true if this is the last relro section.
! // IS_FIRST_NON_RELRO is true if this is the first non relro section.
Output_section*
Layout::make_output_section(const char* name, elfcpp::Elf_Word type,
! elfcpp::Elf_Xword flags, bool is_interp,
! bool is_dynamic_linker_section, bool is_relro,
! bool is_last_relro, bool is_first_non_relro)
{
Output_section* os;
if ((flags & elfcpp::SHF_ALLOC) == 0
--- 928,954 ----
static bool
is_compressible_debug_section(const char* secname)
{
! return (is_prefix_of(".debug", secname));
! }
!
! // We may see compressed debug sections in input files. Return TRUE
! // if this is the name of a compressed debug section.
!
! bool
! is_compressed_debug_section(const char* secname)
! {
! return (is_prefix_of(".zdebug", secname));
}
// Make a new Output_section, and attach it to segments as
! // appropriate. ORDER is the order in which this section should
! // appear in the output segment. IS_RELRO is true if this is a relro
! // (read-only after relocations) section.
Output_section*
Layout::make_output_section(const char* name, elfcpp::Elf_Word type,
! elfcpp::Elf_Xword flags,
! Output_section_order order, bool is_relro)
{
Output_section* os;
if ((flags & elfcpp::SHF_ALLOC) == 0
*************** Layout::make_output_section(const char*
*** 991,1006 ****
os = target->make_output_section(name, type, flags);
}
! if (is_interp)
! os->set_is_interp();
! if (is_dynamic_linker_section)
! os->set_is_dynamic_linker_section();
if (is_relro)
os->set_is_relro();
! if (is_last_relro)
! os->set_is_last_relro();
! if (is_first_non_relro)
! os->set_is_first_non_relro();
parameters->target().new_output_section(os);
--- 981,1019 ----
os = target->make_output_section(name, type, flags);
}
! // With -z relro, we have to recognize the special sections by name.
! // There is no other way.
! bool is_relro_local = false;
! if (!this->script_options_->saw_sections_clause()
! && parameters->options().relro()
! && type == elfcpp::SHT_PROGBITS
! && (flags & elfcpp::SHF_ALLOC) != 0
! && (flags & elfcpp::SHF_WRITE) != 0)
! {
! if (strcmp(name, ".data.rel.ro") == 0)
! is_relro = true;
! else if (strcmp(name, ".data.rel.ro.local") == 0)
! {
! is_relro = true;
! is_relro_local = true;
! }
! else if (type == elfcpp::SHT_INIT_ARRAY
! || type == elfcpp::SHT_FINI_ARRAY
! || type == elfcpp::SHT_PREINIT_ARRAY)
! is_relro = true;
! else if (strcmp(name, ".ctors") == 0
! || strcmp(name, ".dtors") == 0
! || strcmp(name, ".jcr") == 0)
! is_relro = true;
! }
!
if (is_relro)
os->set_is_relro();
!
! if (order == ORDER_INVALID && (flags & elfcpp::SHF_ALLOC) != 0)
! order = this->default_section_order(os, is_relro_local);
!
! os->set_order(order);
parameters->target().new_output_section(os);
*************** Layout::make_output_section(const char*
*** 1016,1038 ****
|| strcmp(name, ".fini_array") == 0))
os->set_may_sort_attached_input_sections();
- // With -z relro, we have to recognize the special sections by name.
- // There is no other way.
- if (!this->script_options_->saw_sections_clause()
- && parameters->options().relro()
- && type == elfcpp::SHT_PROGBITS
- && (flags & elfcpp::SHF_ALLOC) != 0
- && (flags & elfcpp::SHF_WRITE) != 0)
- {
- if (strcmp(name, ".data.rel.ro") == 0)
- os->set_is_relro();
- else if (strcmp(name, ".data.rel.ro.local") == 0)
- {
- os->set_is_relro();
- os->set_is_relro_local();
- }
- }
-
// Check for .stab*str sections, as .stab* sections need to link to
// them.
if (type == elfcpp::SHT_STRTAB
--- 1029,1034 ----
*************** Layout::make_output_section(const char*
*** 1050,1055 ****
--- 1046,1119 ----
return os;
}
+ // Return the default order in which a section should be placed in an
+ // output segment. This function captures a lot of the ideas in
+ // ld/scripttempl/elf.sc in the GNU linker. Note that the order of a
+ // linker created section is normally set when the section is created;
+ // this function is used for input sections.
+
+ Output_section_order
+ Layout::default_section_order(Output_section* os, bool is_relro_local)
+ {
+ gold_assert((os->flags() & elfcpp::SHF_ALLOC) != 0);
+ bool is_write = (os->flags() & elfcpp::SHF_WRITE) != 0;
+ bool is_execinstr = (os->flags() & elfcpp::SHF_EXECINSTR) != 0;
+ bool is_bss = false;
+
+ switch (os->type())
+ {
+ default:
+ case elfcpp::SHT_PROGBITS:
+ break;
+ case elfcpp::SHT_NOBITS:
+ is_bss = true;
+ break;
+ case elfcpp::SHT_RELA:
+ case elfcpp::SHT_REL:
+ if (!is_write)
+ return ORDER_DYNAMIC_RELOCS;
+ break;
+ case elfcpp::SHT_HASH:
+ case elfcpp::SHT_DYNAMIC:
+ case elfcpp::SHT_SHLIB:
+ case elfcpp::SHT_DYNSYM:
+ case elfcpp::SHT_GNU_HASH:
+ case elfcpp::SHT_GNU_verdef:
+ case elfcpp::SHT_GNU_verneed:
+ case elfcpp::SHT_GNU_versym:
+ if (!is_write)
+ return ORDER_DYNAMIC_LINKER;
+ break;
+ case elfcpp::SHT_NOTE:
+ return is_write ? ORDER_RW_NOTE : ORDER_RO_NOTE;
+ }
+
+ if ((os->flags() & elfcpp::SHF_TLS) != 0)
+ return is_bss ? ORDER_TLS_BSS : ORDER_TLS_DATA;
+
+ if (!is_bss && !is_write)
+ {
+ if (is_execinstr)
+ {
+ if (strcmp(os->name(), ".init") == 0)
+ return ORDER_INIT;
+ else if (strcmp(os->name(), ".fini") == 0)
+ return ORDER_FINI;
+ }
+ return is_execinstr ? ORDER_TEXT : ORDER_READONLY;
+ }
+
+ if (os->is_relro())
+ return is_relro_local ? ORDER_RELRO_LOCAL : ORDER_RELRO;
+
+ if (os->is_small_section())
+ return is_bss ? ORDER_SMALL_BSS : ORDER_SMALL_DATA;
+ if (os->is_large_section())
+ return is_bss ? ORDER_LARGE_BSS : ORDER_LARGE_DATA;
+
+ return is_bss ? ORDER_BSS : ORDER_DATA;
+ }
+
// Attach output sections to segments. This is called after we have
// seen all the input sections.
*************** Layout::attach_allocated_section_to_segm
*** 1139,1145 ****
break;
}
! (*p)->add_output_section(os, seg_flags, true);
break;
}
--- 1203,1209 ----
break;
}
! (*p)->add_output_section_to_load(this, os, seg_flags);
break;
}
*************** Layout::attach_allocated_section_to_segm
*** 1149,1155 ****
seg_flags);
if (os->is_large_data_section())
oseg->set_is_large_data_segment();
! oseg->add_output_section(os, seg_flags, true);
if (is_address_set)
oseg->set_addresses(addr, addr);
}
--- 1213,1219 ----
seg_flags);
if (os->is_large_data_section())
oseg->set_is_large_data_segment();
! oseg->add_output_section_to_load(this, os, seg_flags);
if (is_address_set)
oseg->set_addresses(addr, addr);
}
*************** Layout::attach_allocated_section_to_segm
*** 1167,1173 ****
&& (((*p)->flags() & elfcpp::PF_W)
== (seg_flags & elfcpp::PF_W)))
{
! (*p)->add_output_section(os, seg_flags, false);
break;
}
}
--- 1231,1237 ----
&& (((*p)->flags() & elfcpp::PF_W)
== (seg_flags & elfcpp::PF_W)))
{
! (*p)->add_output_section_to_nonload(os, seg_flags);
break;
}
}
*************** Layout::attach_allocated_section_to_segm
*** 1176,1182 ****
{
Output_segment* oseg = this->make_output_segment(elfcpp::PT_NOTE,
seg_flags);
! oseg->add_output_section(os, seg_flags, false);
}
}
--- 1240,1246 ----
{
Output_segment* oseg = this->make_output_segment(elfcpp::PT_NOTE,
seg_flags);
! oseg->add_output_section_to_nonload(os, seg_flags);
}
}
*************** Layout::attach_allocated_section_to_segm
*** 1186,1192 ****
{
if (this->tls_segment_ == NULL)
this->make_output_segment(elfcpp::PT_TLS, seg_flags);
! this->tls_segment_->add_output_section(os, seg_flags, false);
}
// If -z relro is in effect, and we see a relro section, we create a
--- 1250,1256 ----
{
if (this->tls_segment_ == NULL)
this->make_output_segment(elfcpp::PT_TLS, seg_flags);
! this->tls_segment_->add_output_section_to_nonload(os, seg_flags);
}
// If -z relro is in effect, and we see a relro section, we create a
*************** Layout::attach_allocated_section_to_segm
*** 1196,1202 ****
gold_assert(seg_flags == (elfcpp::PF_R | elfcpp::PF_W));
if (this->relro_segment_ == NULL)
this->make_output_segment(elfcpp::PT_GNU_RELRO, seg_flags);
! this->relro_segment_->add_output_section(os, seg_flags, false);
}
}
--- 1260,1266 ----
gold_assert(seg_flags == (elfcpp::PF_R | elfcpp::PF_W));
if (this->relro_segment_ == NULL)
this->make_output_segment(elfcpp::PT_GNU_RELRO, seg_flags);
! this->relro_segment_->add_output_section_to_nonload(os, seg_flags);
}
}
*************** Layout::make_output_section_for_script(
*** 1212,1219 ****
if (section_type == Script_sections::ST_NOLOAD)
sh_flags = 0;
Output_section* os = this->make_output_section(name, elfcpp::SHT_PROGBITS,
! sh_flags, false,
! false, false, false, false);
os->set_found_in_sections_clause();
if (section_type == Script_sections::ST_NOLOAD)
os->set_is_noload();
--- 1276,1283 ----
if (section_type == Script_sections::ST_NOLOAD)
sh_flags = 0;
Output_section* os = this->make_output_section(name, elfcpp::SHT_PROGBITS,
! sh_flags, ORDER_INVALID,
! false);
os->set_found_in_sections_clause();
if (section_type == Script_sections::ST_NOLOAD)
os->set_is_noload();
*************** Layout::create_initial_dynamic_sections(
*** 1285,1292 ****
elfcpp::SHT_DYNAMIC,
(elfcpp::SHF_ALLOC
| elfcpp::SHF_WRITE),
! false, false, true,
! true, false, false);
this->dynamic_symbol_ =
symtab->define_in_output_data("_DYNAMIC", NULL, Symbol_table::PREDEFINED,
--- 1349,1356 ----
elfcpp::SHT_DYNAMIC,
(elfcpp::SHF_ALLOC
| elfcpp::SHF_WRITE),
! false, ORDER_RELRO,
! true);
this->dynamic_symbol_ =
symtab->define_in_output_data("_DYNAMIC", NULL, Symbol_table::PREDEFINED,
*************** Layout::relaxation_loop_body(
*** 1591,1607 ****
|| this->script_options_->saw_sections_clause());
// If the address of the load segment we found has been set by
! // --section-start rather than by a script, then we don't want to
! // use it for the file and segment headers.
if (load_seg != NULL
&& load_seg->are_addresses_set()
! && !this->script_options_->saw_sections_clause())
! load_seg = NULL;
// Lay out the segment headers.
if (!parameters->options().relocatable())
{
gold_assert(segment_headers != NULL);
if (load_seg != NULL)
load_seg->add_initial_output_data(segment_headers);
if (phdr_seg != NULL)
--- 1655,1695 ----
|| this->script_options_->saw_sections_clause());
// If the address of the load segment we found has been set by
! // --section-start rather than by a script, then adjust the VMA and
! // LMA downward if possible to include the file and section headers.
! uint64_t header_gap = 0;
if (load_seg != NULL
&& load_seg->are_addresses_set()
! && !this->script_options_->saw_sections_clause()
! && !parameters->options().relocatable())
! {
! file_header->finalize_data_size();
! segment_headers->finalize_data_size();
! size_t sizeof_headers = (file_header->data_size()
! + segment_headers->data_size());
! const uint64_t abi_pagesize = target->abi_pagesize();
! uint64_t hdr_paddr = load_seg->paddr() - sizeof_headers;
! hdr_paddr &= ~(abi_pagesize - 1);
! uint64_t subtract = load_seg->paddr() - hdr_paddr;
! if (load_seg->paddr() < subtract || load_seg->vaddr() < subtract)
! load_seg = NULL;
! else
! {
! load_seg->set_addresses(load_seg->vaddr() - subtract,
! load_seg->paddr() - subtract);
! header_gap = subtract - sizeof_headers;
! }
! }
// Lay out the segment headers.
if (!parameters->options().relocatable())
{
gold_assert(segment_headers != NULL);
+ if (header_gap != 0 && load_seg != NULL)
+ {
+ Output_data_zero_fill* z = new Output_data_zero_fill(header_gap, 1);
+ load_seg->add_initial_output_data(z);
+ }
if (load_seg != NULL)
load_seg->add_initial_output_data(segment_headers);
if (phdr_seg != NULL)
*************** Layout::create_note(const char* name, in
*** 1971,1982 ****
memcpy(buffer + 3 * (size / 8), name, namesz);
elfcpp::Elf_Xword flags = 0;
if (allocate)
! flags = elfcpp::SHF_ALLOC;
Output_section* os = this->choose_output_section(NULL, section_name,
elfcpp::SHT_NOTE,
! flags, false, false,
! false, false, false, false);
if (os == NULL)
return NULL;
--- 2059,2073 ----
memcpy(buffer + 3 * (size / 8), name, namesz);
elfcpp::Elf_Xword flags = 0;
+ Output_section_order order = ORDER_INVALID;
if (allocate)
! {
! flags = elfcpp::SHF_ALLOC;
! order = ORDER_RO_NOTE;
! }
Output_section* os = this->choose_output_section(NULL, section_name,
elfcpp::SHT_NOTE,
! flags, false, order, false);
if (os == NULL)
return NULL;
*************** Layout::create_executable_stack_info()
*** 2055,2062 ****
elfcpp::Elf_Xword flags = 0;
if (is_stack_executable)
flags |= elfcpp::SHF_EXECINSTR;
! this->make_output_section(name, elfcpp::SHT_PROGBITS, flags, false,
! false, false, false, false);
}
else
{
--- 2146,2153 ----
elfcpp::Elf_Xword flags = 0;
if (is_stack_executable)
flags |= elfcpp::SHF_EXECINSTR;
! this->make_output_section(name, elfcpp::SHT_PROGBITS, flags,
! ORDER_INVALID, false);
}
else
{
*************** Layout::create_incremental_info_sections
*** 2217,2223 ****
Output_section* inputs_os =
this->make_output_section(incremental_inputs_name,
elfcpp::SHT_GNU_INCREMENTAL_INPUTS, 0,
! false, false, false, false, false);
Output_section_data* posd =
this->incremental_inputs_->create_incremental_inputs_section_data();
inputs_os->add_output_section_data(posd);
--- 2308,2314 ----
Output_section* inputs_os =
this->make_output_section(incremental_inputs_name,
elfcpp::SHT_GNU_INCREMENTAL_INPUTS, 0,
! ORDER_INVALID, false);
Output_section_data* posd =
this->incremental_inputs_->create_incremental_inputs_section_data();
inputs_os->add_output_section_data(posd);
*************** Layout::create_incremental_info_sections
*** 2227,2234 ****
this->namepool_.add(".gnu_incremental_strtab", false, NULL);
Output_section* strtab_os = this->make_output_section(incremental_strtab_name,
elfcpp::SHT_STRTAB,
! 0, false, false,
! false, false, false);
Output_data_strtab* strtab_data =
new Output_data_strtab(this->incremental_inputs_->get_stringpool());
strtab_os->add_output_section_data(strtab_data);
--- 2318,2325 ----
this->namepool_.add(".gnu_incremental_strtab", false, NULL);
Output_section* strtab_os = this->make_output_section(incremental_strtab_name,
elfcpp::SHT_STRTAB,
! 0, ORDER_INVALID,
! false);
Output_data_strtab* strtab_data =
new Output_data_strtab(this->incremental_inputs_->get_stringpool());
strtab_os->add_output_section_data(strtab_data);
*************** Layout::segment_precedes(const Output_se
*** 2321,2328 ****
if (section_count1 > 0 && section_count2 == 0)
return false;
! uint64_t paddr1 = seg1->first_section_load_address();
! uint64_t paddr2 = seg2->first_section_load_address();
if (paddr1 != paddr2)
return paddr1 < paddr2;
}
--- 2412,2419 ----
if (section_count1 > 0 && section_count2 == 0)
return false;
! uint64_t paddr1 = seg1->paddr();
! uint64_t paddr2 = seg2->paddr();
if (paddr1 != paddr2)
return paddr1 < paddr2;
}
*************** Layout::create_symtab_sections(const Inp
*** 2848,2855 ****
const char* symtab_name = this->namepool_.add(".symtab", false, NULL);
Output_section* osymtab = this->make_output_section(symtab_name,
elfcpp::SHT_SYMTAB,
! 0, false, false,
! false, false, false);
this->symtab_section_ = osymtab;
Output_section_data* pos = new Output_data_fixed_space(off - startoff,
--- 2939,2946 ----
const char* symtab_name = this->namepool_.add(".symtab", false, NULL);
Output_section* osymtab = this->make_output_section(symtab_name,
elfcpp::SHT_SYMTAB,
! 0, ORDER_INVALID,
! false);
this->symtab_section_ = osymtab;
Output_section_data* pos = new Output_data_fixed_space(off - startoff,
*************** Layout::create_symtab_sections(const Inp
*** 2870,2877 ****
false, NULL);
Output_section* osymtab_xindex =
this->make_output_section(symtab_xindex_name,
! elfcpp::SHT_SYMTAB_SHNDX, 0, false,
! false, false, false, false);
size_t symcount = (off - startoff) / symsize;
this->symtab_xindex_ = new Output_symtab_xindex(symcount);
--- 2961,2968 ----
false, NULL);
Output_section* osymtab_xindex =
this->make_output_section(symtab_xindex_name,
! elfcpp::SHT_SYMTAB_SHNDX, 0,
! ORDER_INVALID, false);
size_t symcount = (off - startoff) / symsize;
this->symtab_xindex_ = new Output_symtab_xindex(symcount);
*************** Layout::create_symtab_sections(const Inp
*** 2893,2900 ****
const char* strtab_name = this->namepool_.add(".strtab", false, NULL);
Output_section* ostrtab = this->make_output_section(strtab_name,
elfcpp::SHT_STRTAB,
! 0, false, false,
! false, false, false);
Output_section_data* pstr = new Output_data_strtab(&this->sympool_);
ostrtab->add_output_section_data(pstr);
--- 2984,2991 ----
const char* strtab_name = this->namepool_.add(".strtab", false, NULL);
Output_section* ostrtab = this->make_output_section(strtab_name,
elfcpp::SHT_STRTAB,
! 0, ORDER_INVALID,
! false);
Output_section_data* pstr = new Output_data_strtab(&this->sympool_);
ostrtab->add_output_section_data(pstr);
*************** Layout::create_shstrtab()
*** 2922,2929 ****
const char* name = this->namepool_.add(".shstrtab", false, NULL);
Output_section* os = this->make_output_section(name, elfcpp::SHT_STRTAB, 0,
! false, false, false, false,
! false);
if (strcmp(parameters->options().compress_debug_sections(), "none") != 0)
{
--- 3013,3019 ----
const char* name = this->namepool_.add(".shstrtab", false, NULL);
Output_section* os = this->make_output_section(name, elfcpp::SHT_STRTAB, 0,
! ORDER_INVALID, false);
if (strcmp(parameters->options().compress_debug_sections(), "none") != 0)
{
*************** Layout::create_dynamic_symtab(const Inpu
*** 3040,3047 ****
Output_section* dynsym = this->choose_output_section(NULL, ".dynsym",
elfcpp::SHT_DYNSYM,
elfcpp::SHF_ALLOC,
! false, false, true,
! false, false, false);
Output_section_data* odata = new Output_data_fixed_space(index * symsize,
align,
--- 3130,3138 ----
Output_section* dynsym = this->choose_output_section(NULL, ".dynsym",
elfcpp::SHT_DYNSYM,
elfcpp::SHF_ALLOC,
! false,
! ORDER_DYNAMIC_LINKER,
! false);
Output_section_data* odata = new Output_data_fixed_space(index * symsize,
align,
*************** Layout::create_dynamic_symtab(const Inpu
*** 3071,3077 ****
this->choose_output_section(NULL, ".dynsym_shndx",
elfcpp::SHT_SYMTAB_SHNDX,
elfcpp::SHF_ALLOC,
! false, false, true, false, false, false);
this->dynsym_xindex_ = new Output_symtab_xindex(index);
--- 3162,3168 ----
this->choose_output_section(NULL, ".dynsym_shndx",
elfcpp::SHT_SYMTAB_SHNDX,
elfcpp::SHF_ALLOC,
! false, ORDER_DYNAMIC_LINKER, false);
this->dynsym_xindex_ = new Output_symtab_xindex(index);
*************** Layout::create_dynamic_symtab(const Inpu
*** 3094,3101 ****
Output_section* dynstr = this->choose_output_section(NULL, ".dynstr",
elfcpp::SHT_STRTAB,
elfcpp::SHF_ALLOC,
! false, false, true,
! false, false, false);
Output_section_data* strdata = new Output_data_strtab(&this->dynpool_);
dynstr->add_output_section_data(strdata);
--- 3185,3193 ----
Output_section* dynstr = this->choose_output_section(NULL, ".dynstr",
elfcpp::SHT_STRTAB,
elfcpp::SHF_ALLOC,
! false,
! ORDER_DYNAMIC_LINKER,
! false);
Output_section_data* strdata = new Output_data_strtab(&this->dynpool_);
dynstr->add_output_section_data(strdata);
*************** Layout::create_dynamic_symtab(const Inpu
*** 3118,3129 ****
Dynobj::create_elf_hash_table(*pdynamic_symbols, local_symcount,
&phash, &hashlen);
! Output_section* hashsec = this->choose_output_section(NULL, ".hash",
! elfcpp::SHT_HASH,
! elfcpp::SHF_ALLOC,
! false, false, true,
! false, false,
! false);
Output_section_data* hashdata = new Output_data_const_buffer(phash,
hashlen,
--- 3210,3219 ----
Dynobj::create_elf_hash_table(*pdynamic_symbols, local_symcount,
&phash, &hashlen);
! Output_section* hashsec =
! this->choose_output_section(NULL, ".hash", elfcpp::SHT_HASH,
! elfcpp::SHF_ALLOC, false,
! ORDER_DYNAMIC_LINKER, false);
Output_section_data* hashdata = new Output_data_const_buffer(phash,
hashlen,
*************** Layout::create_dynamic_symtab(const Inpu
*** 3145,3156 ****
Dynobj::create_gnu_hash_table(*pdynamic_symbols, local_symcount,
&phash, &hashlen);
! Output_section* hashsec = this->choose_output_section(NULL, ".gnu.hash",
! elfcpp::SHT_GNU_HASH,
! elfcpp::SHF_ALLOC,
! false, false, true,
! false, false,
! false);
Output_section_data* hashdata = new Output_data_const_buffer(phash,
hashlen,
--- 3235,3244 ----
Dynobj::create_gnu_hash_table(*pdynamic_symbols, local_symcount,
&phash, &hashlen);
! Output_section* hashsec =
! this->choose_output_section(NULL, ".gnu.hash", elfcpp::SHT_GNU_HASH,
! elfcpp::SHF_ALLOC, false,
! ORDER_DYNAMIC_LINKER, false);
Output_section_data* hashdata = new Output_data_const_buffer(phash,
hashlen,
*************** Layout::sized_create_version_sections(
*** 3253,3260 ****
Output_section* vsec = this->choose_output_section(NULL, ".gnu.version",
elfcpp::SHT_GNU_versym,
elfcpp::SHF_ALLOC,
! false, false, true,
! false, false, false);
unsigned char* vbuf;
unsigned int vsize;
--- 3341,3349 ----
Output_section* vsec = this->choose_output_section(NULL, ".gnu.version",
elfcpp::SHT_GNU_versym,
elfcpp::SHF_ALLOC,
! false,
! ORDER_DYNAMIC_LINKER,
! false);
unsigned char* vbuf;
unsigned int vsize;
*************** Layout::sized_create_version_sections(
*** 3279,3286 ****
vdsec= this->choose_output_section(NULL, ".gnu.version_d",
elfcpp::SHT_GNU_verdef,
elfcpp::SHF_ALLOC,
! false, false, true, false, false,
! false);
unsigned char* vdbuf;
unsigned int vdsize;
--- 3368,3374 ----
vdsec= this->choose_output_section(NULL, ".gnu.version_d",
elfcpp::SHT_GNU_verdef,
elfcpp::SHF_ALLOC,
! false, ORDER_DYNAMIC_LINKER, false);
unsigned char* vdbuf;
unsigned int vdsize;
*************** Layout::sized_create_version_sections(
*** 3305,3312 ****
vnsec = this->choose_output_section(NULL, ".gnu.version_r",
elfcpp::SHT_GNU_verneed,
elfcpp::SHF_ALLOC,
! false, false, true, false, false,
! false);
unsigned char* vnbuf;
unsigned int vnsize;
--- 3393,3399 ----
vnsec = this->choose_output_section(NULL, ".gnu.version_r",
elfcpp::SHT_GNU_verneed,
elfcpp::SHF_ALLOC,
! false, ORDER_DYNAMIC_LINKER, false);
unsigned char* vnbuf;
unsigned int vnsize;
*************** Layout::create_interp(const Target* targ
*** 3346,3360 ****
Output_section* osec = this->choose_output_section(NULL, ".interp",
elfcpp::SHT_PROGBITS,
elfcpp::SHF_ALLOC,
! false, true, true,
! false, false, false);
osec->add_output_section_data(odata);
if (!this->script_options_->saw_phdrs_clause())
{
Output_segment* oseg = this->make_output_segment(elfcpp::PT_INTERP,
elfcpp::PF_R);
! oseg->add_output_section(osec, elfcpp::PF_R, false);
}
}
--- 3433,3447 ----
Output_section* osec = this->choose_output_section(NULL, ".interp",
elfcpp::SHT_PROGBITS,
elfcpp::SHF_ALLOC,
! false, ORDER_INTERP,
! false);
osec->add_output_section_data(odata);
if (!this->script_options_->saw_phdrs_clause())
{
Output_segment* oseg = this->make_output_segment(elfcpp::PT_INTERP,
elfcpp::PF_R);
! oseg->add_output_section_to_nonload(osec, elfcpp::PF_R);
}
}
*************** Layout::finish_dynamic_section(const Inp
*** 3462,3470 ****
Output_segment* oseg = this->make_output_segment(elfcpp::PT_DYNAMIC,
(elfcpp::PF_R
| elfcpp::PF_W));
! oseg->add_output_section(this->dynamic_section_,
! elfcpp::PF_R | elfcpp::PF_W,
! false);
}
Output_data_dynamic* const odyn = this->dynamic_data_;
--- 3549,3556 ----
Output_segment* oseg = this->make_output_segment(elfcpp::PT_DYNAMIC,
(elfcpp::PF_R
| elfcpp::PF_W));
! oseg->add_output_section_to_nonload(this->dynamic_section_,
! elfcpp::PF_R | elfcpp::PF_W);
}
Output_data_dynamic* const odyn = this->dynamic_data_;
*************** Layout::finish_dynamic_section(const Inp
*** 3562,3568 ****
++p)
{
if (((*p)->flags() & elfcpp::PF_W) == 0
! && (*p)->dynamic_reloc_count() > 0)
{
have_textrel = true;
break;
--- 3648,3654 ----
++p)
{
if (((*p)->flags() & elfcpp::PF_W) == 0
! && (*p)->has_dynamic_reloc())
{
have_textrel = true;
break;
*************** Layout::finish_dynamic_section(const Inp
*** 3581,3587 ****
{
if (((*p)->flags() & elfcpp::SHF_ALLOC) != 0
&& ((*p)->flags() & elfcpp::SHF_WRITE) == 0
! && ((*p)->dynamic_reloc_count() > 0))
{
have_textrel = true;
break;
--- 3667,3673 ----
{
if (((*p)->flags() & elfcpp::SHF_ALLOC) != 0
&& ((*p)->flags() & elfcpp::SHF_WRITE) == 0
! && ((*p)->has_dynamic_reloc()))
{
have_textrel = true;
break;
*************** Layout::output_section_name(const char*
*** 3772,3777 ****
--- 3858,3877 ----
}
}
+ // Compressed debug sections should be mapped to the corresponding
+ // uncompressed section.
+ if (is_compressed_debug_section(name))
+ {
+ size_t len = strlen(name);
+ char *uncompressed_name = new char[len];
+ uncompressed_name[0] = '.';
+ gold_assert(name[0] == '.' && name[1] == 'z');
+ strncpy(&uncompressed_name[1], &name[2], len - 2);
+ uncompressed_name[len - 1] = '\0';
+ *plen = len - 1;
+ return uncompressed_name;
+ }
+
return name;
}
diff -rcp ../binutils-2.20.51.0.10.original/gold/layout.h gold/layout.h
*** ../binutils-2.20.51.0.10.original/gold/layout.h 2010-08-10 15:12:04.000000000 +0100
--- gold/layout.h 2010-08-10 15:14:03.000000000 +0100
*************** class Output_reduced_debug_info_section;
*** 59,64 ****
--- 59,68 ----
class Eh_frame;
class Target;
+ // Return TRUE if SECNAME is the name of a compressed debug section.
+ extern bool
+ is_compressed_debug_section(const char* secname);
+
// This task function handles mapping the input sections to output
// sections and laying them out in memory.
*************** class Kept_section
*** 282,287 ****
--- 286,392 ----
} u_;
};
+ // The ordering for output sections. This controls how output
+ // sections are ordered within a PT_LOAD output segment.
+
+ enum Output_section_order
+ {
+ // Unspecified. Used for non-load segments. Also used for the file
+ // and segment headers.
+ ORDER_INVALID,
+
+ // The PT_INTERP section should come first, so that the dynamic
+ // linker can pick it up quickly.
+ ORDER_INTERP,
+
+ // Loadable read-only note sections come next so that the PT_NOTE
+ // segment is on the first page of the executable.
+ ORDER_RO_NOTE,
+
+ // Put read-only sections used by the dynamic linker early in the
+ // executable to minimize paging.
+ ORDER_DYNAMIC_LINKER,
+
+ // Put reloc sections used by the dynamic linker after other
+ // sections used by the dynamic linker; otherwise, objcopy and strip
+ // get confused.
+ ORDER_DYNAMIC_RELOCS,
+
+ // Put the PLT reloc section after the other dynamic relocs;
+ // otherwise, prelink gets confused.
+ ORDER_DYNAMIC_PLT_RELOCS,
+
+ // The .init section.
+ ORDER_INIT,
+
+ // The PLT.
+ ORDER_PLT,
+
+ // The regular text sections.
+ ORDER_TEXT,
+
+ // The .fini section.
+ ORDER_FINI,
+
+ // The read-only sections.
+ ORDER_READONLY,
+
+ // The exception frame sections.
+ ORDER_EHFRAME,
+
+ // The TLS sections come first in the data section.
+ ORDER_TLS_DATA,
+ ORDER_TLS_BSS,
+
+ // Local RELRO (read-only after relocation) sections come before
+ // non-local RELRO sections. This data will be fully resolved by
+ // the prelinker.
+ ORDER_RELRO_LOCAL,
+
+ // Non-local RELRO sections are grouped together after local RELRO
+ // sections. All RELRO sections must be adjacent so that they can
+ // all be put into a PT_GNU_RELRO segment.
+ ORDER_RELRO,
+
+ // We permit marking exactly one output section as the last RELRO
+ // section. We do this so that the read-only GOT can be adjacent to
+ // the writable GOT.
+ ORDER_RELRO_LAST,
+
+ // Similarly, we permit marking exactly one output section as the
+ // first non-RELRO section.
+ ORDER_NON_RELRO_FIRST,
+
+ // The regular data sections come after the RELRO sections.
+ ORDER_DATA,
+
+ // Large data sections normally go in large data segments.
+ ORDER_LARGE_DATA,
+
+ // Group writable notes so that we can have a single PT_NOTE
+ // segment.
+ ORDER_RW_NOTE,
+
+ // The small data sections must be at the end of the data sections,
+ // so that they can be adjacent to the small BSS sections.
+ ORDER_SMALL_DATA,
+
+ // The BSS sections start here.
+
+ // The small BSS sections must be at the start of the BSS sections,
+ // so that they can be adjacent to the small data sections.
+ ORDER_SMALL_BSS,
+
+ // The regular BSS sections.
+ ORDER_BSS,
+
+ // The large BSS sections come after the other BSS sections.
+ ORDER_LARGE_BSS,
+
+ // Maximum value.
+ ORDER_MAX
+ };
+
// This class handles the details of laying out input sections.
class Layout
*************** class Layout
*** 367,384 ****
layout_gnu_stack(bool seen_gnu_stack, uint64_t gnu_stack_flags);
// Add an Output_section_data to the layout. This is used for
! // special sections like the GOT section. IS_DYNAMIC_LINKER_SECTION
! // is true for sections which are used by the dynamic linker, such
! // as dynamic reloc sections. IS_RELRO is true for relro sections.
! // IS_LAST_RELRO is true for the last relro section.
! // IS_FIRST_NON_RELRO is true for the first section after the relro
! // sections.
Output_section*
add_output_section_data(const char* name, elfcpp::Elf_Word type,
elfcpp::Elf_Xword flags,
! Output_section_data*, bool is_dynamic_linker_section,
! bool is_relro, bool is_last_relro,
! bool is_first_non_relro);
// Increase the size of the relro segment by this much.
void
--- 472,485 ----
layout_gnu_stack(bool seen_gnu_stack, uint64_t gnu_stack_flags);
// Add an Output_section_data to the layout. This is used for
! // special sections like the GOT section. ORDER is where the
! // section should wind up in the output segment. IS_RELRO is true
! // for relro sections.
Output_section*
add_output_section_data(const char* name, elfcpp::Elf_Word type,
elfcpp::Elf_Xword flags,
! Output_section_data*, Output_section_order order,
! bool is_relro);
// Increase the size of the relro segment by this much.
void
*************** class Layout
*** 451,456 ****
--- 552,558 ----
{
// Debugging sections can only be recognized by name.
return (strncmp(name, ".debug", sizeof(".debug") - 1) == 0
+ || strncmp(name, ".zdebug", sizeof(".zdebug") - 1) == 0
|| strncmp(name, ".gnu.linkonce.wi.",
sizeof(".gnu.linkonce.wi.") - 1) == 0
|| strncmp(name, ".line", sizeof(".line") - 1) == 0
*************** class Layout
*** 783,811 ****
Output_section*
get_output_section(const char* name, Stringpool::Key name_key,
elfcpp::Elf_Word type, elfcpp::Elf_Xword flags,
! bool is_interp, bool is_dynamic_linker_section,
! bool is_relro, bool is_last_relro,
! bool is_first_non_relro);
// Choose the output section for NAME in RELOBJ.
Output_section*
choose_output_section(const Relobj* relobj, const char* name,
elfcpp::Elf_Word type, elfcpp::Elf_Xword flags,
! bool is_input_section, bool is_interp,
! bool is_dynamic_linker_section, bool is_relro,
! bool is_last_relro, bool is_first_non_relro);
// Create a new Output_section.
Output_section*
make_output_section(const char* name, elfcpp::Elf_Word type,
! elfcpp::Elf_Xword flags, bool is_interp,
! bool is_dynamic_linker_section, bool is_relro,
! bool is_last_relro, bool is_first_non_relro);
// Attach a section to a segment.
void
attach_section_to_segment(Output_section*);
// Attach an allocated section to a segment.
void
attach_allocated_section_to_segment(Output_section*);
--- 885,913 ----
Output_section*
get_output_section(const char* name, Stringpool::Key name_key,
elfcpp::Elf_Word type, elfcpp::Elf_Xword flags,
! Output_section_order order, bool is_relro);
// Choose the output section for NAME in RELOBJ.
Output_section*
choose_output_section(const Relobj* relobj, const char* name,
elfcpp::Elf_Word type, elfcpp::Elf_Xword flags,
! bool is_input_section, Output_section_order order,
! bool is_relro);
// Create a new Output_section.
Output_section*
make_output_section(const char* name, elfcpp::Elf_Word type,
! elfcpp::Elf_Xword flags, Output_section_order order,
! bool is_relro);
// Attach a section to a segment.
void
attach_section_to_segment(Output_section*);
+ // Get section order.
+ Output_section_order
+ default_section_order(Output_section*, bool is_relro_local);
+
// Attach an allocated section to a segment.
void
attach_allocated_section_to_segment(Output_section*);
diff -rcp ../binutils-2.20.51.0.10.original/gold/Makefile.in gold/Makefile.in
*** ../binutils-2.20.51.0.10.original/gold/Makefile.in 2010-08-10 15:11:28.000000000 +0100
--- gold/Makefile.in 2010-08-10 15:14:03.000000000 +0100
*************** RECURSIVE_TARGETS = all-recursive check-
*** 147,157 ****
RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
distclean-recursive maintainer-clean-recursive
AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
! $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS
ETAGS = etags
CTAGS = ctags
am__tty_colors = \
red=; grn=; lgn=; blu=; std=
DIST_SUBDIRS = $(SUBDIRS)
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
--- 147,227 ----
RECURSIVE_CLEAN_TARGETS = mostlyclean-recursive clean-recursive \
distclean-recursive maintainer-clean-recursive
AM_RECURSIVE_TARGETS = $(RECURSIVE_TARGETS:-recursive=) \
! $(RECURSIVE_CLEAN_TARGETS:-recursive=) tags TAGS ctags CTAGS \
! check check-html recheck recheck-html
ETAGS = etags
CTAGS = ctags
am__tty_colors = \
red=; grn=; lgn=; blu=; std=
+ am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+ am__vpath_adj = case $$p in \
+ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+ *) f=$$p;; \
+ esac;
+ am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+ am__install_max = 40
+ am__nobase_strip_setup = \
+ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+ am__nobase_strip = \
+ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+ am__nobase_list = $(am__nobase_strip_setup); \
+ for p in $$list; do echo "$$p $$p"; done | \
+ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+ if (++n[$$2] == $(am__install_max)) \
+ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+ END { for (dir in files) print dir, files[dir] }'
+ am__base_list = \
+ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+ # Restructured Text title and section.
+ am__rst_title = sed 's/.*/ & /;h;s/./=/g;p;x;p;g;p;s/.*//'
+ am__rst_section = sed 'p;s/./=/g;p;g'
+ # Put stdin (possibly several lines separated by ". ") in a box.
+ am__text_box = $(AWK) '{ \
+ n = split($$0, lines, "\\. "); max = 0; \
+ for (i = 1; i <= n; ++i) \
+ if (max < length(lines[i])) \
+ max = length(lines[i]); \
+ for (i = 0; i < max; ++i) line = line "="; \
+ print line; \
+ for (i = 1; i <= n; ++i) if (lines[i]) print lines[i];\
+ print line; \
+ }'
+ # Solaris 10 'make', and several other traditional 'make' implementations,
+ # pass "-e" to $(SHELL). This contradicts POSIX. Work around the problem
+ # by disabling -e (using the XSI extension "set +e") if it's set.
+ am__sh_e_setup = case $$- in *e*) set +e;; esac
+ # To be inserted before the command running the test. Creates the
+ # directory for the log if needed. Stores in $dir the directory
+ # containing $f, in $tst the test, in $log the log, and passes
+ # TESTS_ENVIRONMENT. Save and restore TERM around use of
+ # TESTS_ENVIRONMENT, in case that unsets it.
+ am__check_pre = \
+ $(am__sh_e_setup); \
+ $(am__vpath_adj_setup) $(am__vpath_adj) \
+ srcdir=$(srcdir); export srcdir; \
+ rm -f $@-t; \
+ trap 'st=$$?; rm -f '\''$(abs_builddir)/$@-t'\''; (exit $$st); exit $$st' \
+ 1 2 13 15; \
+ am__odir=`echo "./$@" | sed 's|/[^/]*$$||'`; \
+ test "x$$am__odir" = x. || $(MKDIR_P) "$$am__odir" || exit $$?; \
+ if test -f "./$$f"; then dir=./; \
+ elif test -f "$$f"; then dir=; \
+ else dir="$(srcdir)/"; fi; \
+ tst=$$dir$$f; log='$@'; __SAVED_TERM=$$TERM; \
+ $(TESTS_ENVIRONMENT)
+ RECHECK_LOGS = $(TEST_LOGS)
+ TEST_SUITE_LOG = test-suite.log
+ TEST_SUITE_HTML = $(TEST_SUITE_LOG:.log=.html)
+ TEST_EXTENSIONS = @EXEEXT@ .test
+ LOG_COMPILE = $(LOG_COMPILER) $(AM_LOG_FLAGS) $(LOG_FLAGS)
+ am__test_logs1 = $(TESTS:=.log)
+ am__test_logs2 = $(am__test_logs1:@EXEEXT@.log=.log)
+ TEST_LOGS = $(am__test_logs2:.test.log=.log)
+ TEST_LOG_COMPILE = $(TEST_LOG_COMPILER) $(AM_TEST_LOG_FLAGS) \
+ $(TEST_LOG_FLAGS)
+ TEST_LOGS_TMP = $(TEST_LOGS:.log=.log-t)
DIST_SUBDIRS = $(SUBDIRS)
ACLOCAL = @ACLOCAL@
AMTAR = @AMTAR@
*************** all: config.h
*** 453,459 ****
$(MAKE) $(AM_MAKEFLAGS) all-recursive
.SUFFIXES:
! .SUFFIXES: .c .cc .o .obj .y
am--refresh:
@:
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
--- 523,529 ----
$(MAKE) $(AM_MAKEFLAGS) all-recursive
.SUFFIXES:
! .SUFFIXES: .c .cc .html .log .o .obj .test .test$(EXEEXT) .y
am--refresh:
@:
$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
*************** GTAGS:
*** 774,870 ****
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
! check-TESTS: $(TESTS)
! @failed=0; all=0; xfail=0; xpass=0; skip=0; \
! srcdir=$(srcdir); export srcdir; \
! list=' $(TESTS) '; \
! $(am__tty_colors); \
! if test -n "$$list"; then \
! for tst in $$list; do \
! if test -f ./$$tst; then dir=./; \
! elif test -f $$tst; then dir=; \
! else dir="$(srcdir)/"; fi; \
! if $(TESTS_ENVIRONMENT) $${dir}$$tst; then \
! all=`expr $$all + 1`; \
! case " $(XFAIL_TESTS) " in \
! *[\ \ ]$$tst[\ \ ]*) \
! xpass=`expr $$xpass + 1`; \
! failed=`expr $$failed + 1`; \
! col=$$red; res=XPASS; \
! ;; \
! *) \
! col=$$grn; res=PASS; \
! ;; \
! esac; \
! elif test $$? -ne 77; then \
! all=`expr $$all + 1`; \
! case " $(XFAIL_TESTS) " in \
! *[\ \ ]$$tst[\ \ ]*) \
! xfail=`expr $$xfail + 1`; \
! col=$$lgn; res=XFAIL; \
! ;; \
! *) \
! failed=`expr $$failed + 1`; \
! col=$$red; res=FAIL; \
! ;; \
! esac; \
! else \
! skip=`expr $$skip + 1`; \
! col=$$blu; res=SKIP; \
! fi; \
! echo "$${col}$$res$${std}: $$tst"; \
! done; \
! if test "$$all" -eq 1; then \
! tests="test"; \
! All=""; \
! else \
! tests="tests"; \
! All="All "; \
! fi; \
! if test "$$failed" -eq 0; then \
! if test "$$xfail" -eq 0; then \
! banner="$$All$$all $$tests passed"; \
! else \
! if test "$$xfail" -eq 1; then failures=failure; else failures=failures; fi; \
! banner="$$All$$all $$tests behaved as expected ($$xfail expected $$failures)"; \
! fi; \
! else \
! if test "$$xpass" -eq 0; then \
! banner="$$failed of $$all $$tests failed"; \
! else \
! if test "$$xpass" -eq 1; then passes=pass; else passes=passes; fi; \
! banner="$$failed of $$all $$tests did not behave as expected ($$xpass unexpected $$passes)"; \
! fi; \
! fi; \
! dashes="$$banner"; \
! skipped=""; \
! if test "$$skip" -ne 0; then \
! if test "$$skip" -eq 1; then \
! skipped="($$skip test was not run)"; \
! else \
! skipped="($$skip tests were not run)"; \
! fi; \
! test `echo "$$skipped" | wc -c` -le `echo "$$banner" | wc -c` || \
! dashes="$$skipped"; \
! fi; \
! report=""; \
! if test "$$failed" -ne 0 && test -n "$(PACKAGE_BUGREPORT)"; then \
! report="Please report to $(PACKAGE_BUGREPORT)"; \
! test `echo "$$report" | wc -c` -le `echo "$$banner" | wc -c` || \
! dashes="$$report"; \
! fi; \
! dashes=`echo "$$dashes" | sed s/./=/g`; \
! if test "$$failed" -eq 0; then \
! echo "$$grn$$dashes"; \
! else \
! echo "$$red$$dashes"; \
! fi; \
! echo "$$banner"; \
! test -z "$$skipped" || echo "$$skipped"; \
! test -z "$$report" || echo "$$report"; \
! echo "$$dashes$$std"; \
! test "$$failed" -eq 0; \
! else :; fi
check-am: all-am
$(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS)
$(MAKE) $(AM_MAKEFLAGS) check-TESTS
--- 844,1008 ----
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
! # To be appended to the command running the test. Handle the stdout
! # and stderr redirection, and catch the exit status.
! am__check_post = \
! >$@-t 2>&1; \
! estatus=$$?; \
! if test -n '$(DISABLE_HARD_ERRORS)' \
! && test $$estatus -eq 99; then \
! estatus=1; \
! fi; \
! TERM=$$__SAVED_TERM; export TERM; \
! $(am__tty_colors); \
! xfailed=PASS; \
! case " $(XFAIL_TESTS) " in \
! *[\ \ ]$$f[\ \ ]* | *[\ \ ]$$dir$$f[\ \ ]*) \
! xfailed=XFAIL;; \
! esac; \
! case $$estatus:$$xfailed in \
! 0:XFAIL) col=$$red; res=XPASS;; \
! 0:*) col=$$grn; res=PASS ;; \
! 77:*) col=$$blu; res=SKIP ;; \
! 99:*) col=$$red; res=FAIL ;; \
! *:XFAIL) col=$$lgn; res=XFAIL;; \
! *:*) col=$$red; res=FAIL ;; \
! esac; \
! echo "$${col}$$res$${std}: $$f"; \
! echo "$$res: $$f (exit: $$estatus)" | \
! $(am__rst_section) >$@; \
! cat $@-t >>$@; \
! rm -f $@-t
!
! $(TEST_SUITE_LOG): $(TEST_LOGS)
! @$(am__sh_e_setup); \
! list='$(TEST_LOGS)'; \
! results=`for f in $$list; do \
! read line < $$f && echo "$$line" || echo FAIL; \
! done`; \
! all=`echo "$$results" | sed '/^$$/d' | wc -l | sed -e 's/^[ ]*//'`; \
! fail=`echo "$$results" | grep -c '^FAIL'`; \
! pass=`echo "$$results" | grep -c '^PASS'`; \
! skip=`echo "$$results" | grep -c '^SKIP'`; \
! xfail=`echo "$$results" | grep -c '^XFAIL'`; \
! xpass=`echo "$$results" | grep -c '^XPASS'`; \
! failures=`expr $$fail + $$xpass`; \
! all=`expr $$all - $$skip`; \
! if test "$$all" -eq 1; then tests=test; All=; \
! else tests=tests; All="All "; fi; \
! case fail=$$fail:xpass=$$xpass:xfail=$$xfail in \
! fail=0:xpass=0:xfail=0) \
! msg="$$All$$all $$tests passed. "; \
! exit=true;; \
! fail=0:xpass=0:xfail=*) \
! msg="$$All$$all $$tests behaved as expected"; \
! if test "$$xfail" -eq 1; then xfailures=failure; \
! else xfailures=failures; fi; \
! msg="$$msg ($$xfail expected $$xfailures). "; \
! exit=true;; \
! fail=*:xpass=0:xfail=*) \
! msg="$$fail of $$all $$tests failed. "; \
! exit=false;; \
! fail=*:xpass=*:xfail=*) \
! msg="$$failures of $$all $$tests did not behave as expected"; \
! if test "$$xpass" -eq 1; then xpasses=pass; \
! else xpasses=passes; fi; \
! msg="$$msg ($$xpass unexpected $$xpasses). "; \
! exit=false;; \
! *) \
! echo >&2 "incorrect case"; exit 4;; \
! esac; \
! if test "$$skip" -ne 0; then \
! if test "$$skip" -eq 1; then \
! msg="$$msg($$skip test was not run). "; \
! else \
! msg="$$msg($$skip tests were not run). "; \
! fi; \
! fi; \
! { \
! echo "$(PACKAGE_STRING): $(subdir)/$(TEST_SUITE_LOG)" | \
! $(am__rst_title); \
! echo "$$msg"; \
! echo; \
! echo ".. contents:: :depth: 2"; \
! echo; \
! for f in $$list; do \
! read line < $$f; \
! case $$line in \
! PASS:*|XFAIL:*);; \
! *) echo; cat $$f;; \
! esac; \
! done; \
! } >$(TEST_SUITE_LOG).tmp; \
! mv $(TEST_SUITE_LOG).tmp $(TEST_SUITE_LOG); \
! if test "$$failures" -ne 0; then \
! msg="$${msg}See $(subdir)/$(TEST_SUITE_LOG). "; \
! if test -n "$(PACKAGE_BUGREPORT)"; then \
! msg="$${msg}Please report to $(PACKAGE_BUGREPORT). "; \
! fi; \
! fi; \
! test x"$$VERBOSE" = x || $$exit || cat $(TEST_SUITE_LOG); \
! $(am__tty_colors); \
! if $$exit; then \
! echo $(ECHO_N) "$$grn$(ECHO_C)"; \
! else \
! echo $(ECHO_N) "$$red$(ECHO_C)"; \
! fi; \
! echo "$$msg" | $(am__text_box); \
! echo $(ECHO_N) "$$std$(ECHO_C)"; \
! $$exit
!
! # Run all the tests.
! check-TESTS:
! @list='$(RECHECK_LOGS)'; test -z "$$list" || rm -f $$list
! @test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
! @set_logs=; if test "X$(TEST_LOGS)" = X.log; then \
! set_logs=TEST_LOGS=; \
! fi; \
! $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_LOG) $$set_logs
!
! .log.html:
! @list='$(RST2HTML) $$RST2HTML rst2html rst2html.py'; \
! for r2h in $$list; do \
! if ($$r2h --version) >/dev/null 2>&1; then \
! R2H=$$r2h; \
! fi; \
! done; \
! if test -z "$$R2H"; then \
! echo >&2 "cannot find rst2html, cannot create $@"; \
! exit 2; \
! fi; \
! $$R2H $< >$@.tmp
! @mv $@.tmp $@
!
! # Be sure to run check first, and then to convert the result.
! # Beware of concurrent executions. Run "check" not "check-TESTS", as
! # check-SCRIPTS and other dependencies are rebuilt by the former only.
! # And expect check to fail.
! check-html:
! @if $(MAKE) $(AM_MAKEFLAGS) check; then \
! rv=0; else rv=$$?; \
! fi; \
! $(MAKE) $(AM_MAKEFLAGS) $(TEST_SUITE_HTML) || exit 4; \
! exit $$rv
! recheck recheck-html:
! @target=`echo $@ | sed 's,^re,,'`; \
! list='$(TEST_LOGS)'; \
! list=`for f in $$list; do \
! test -f $$f || continue; \
! if read line < $$f; then \
! case $$line in FAIL*|XPASS*) echo $$f;; esac; \
! else echo $$f; fi; \
! done | tr '\012\015' ' '`; \
! $(MAKE) $(AM_MAKEFLAGS) $$target AM_MAKEFLAGS='$(AM_MAKEFLAGS) TEST_LOGS="'"$$list"'"'
! bootstrap-test.log: bootstrap-test
! @p='bootstrap-test'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
! bootstrap-test-r.log: bootstrap-test-r
! @p='bootstrap-test-r'; $(am__check_pre) $(LOG_COMPILE) "$$tst" $(am__check_post)
! .test.log:
! @p='$<'; $(am__check_pre) $(TEST_LOG_COMPILE) "$$tst" $(am__check_post)
! @am__EXEEXT_TRUE@.test$(EXEEXT).log:
! @am__EXEEXT_TRUE@ @p='$<'; $(am__check_pre) $(TEST_LOG_COMPILE) "$$tst" $(am__check_post)
check-am: all-am
$(MAKE) $(AM_MAKEFLAGS) $(check_PROGRAMS)
$(MAKE) $(AM_MAKEFLAGS) check-TESTS
*************** install-strip:
*** 887,892 ****
--- 1025,1034 ----
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
+ -test -z "$(TEST_LOGS)" || rm -f $(TEST_LOGS)
+ -test -z "$(TEST_LOGS_TMP)" || rm -f $(TEST_LOGS_TMP)
+ -test -z "$(TEST_SUITE_HTML)" || rm -f $(TEST_SUITE_HTML)
+ -test -z "$(TEST_SUITE_LOG)" || rm -f $(TEST_SUITE_LOG)
clean-generic:
*************** ps-am:
*** 973,983 ****
uninstall-am:
.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) all check-am \
! ctags-recursive install-am install-strip tags-recursive
.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
! all all-am am--refresh check check-TESTS check-am clean \
! clean-checkPROGRAMS clean-generic clean-noinstLIBRARIES \
clean-noinstPROGRAMS ctags ctags-recursive distclean \
distclean-compile distclean-generic distclean-hdr \
distclean-tags dvi dvi-am html html-am info info-am install \
--- 1115,1126 ----
uninstall-am:
.MAKE: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) all check-am \
! check-html ctags-recursive install-am install-strip recheck \
! recheck-html tags-recursive
.PHONY: $(RECURSIVE_CLEAN_TARGETS) $(RECURSIVE_TARGETS) CTAGS GTAGS \
! all all-am am--refresh check check-TESTS check-am check-html \
! clean clean-checkPROGRAMS clean-generic clean-noinstLIBRARIES \
clean-noinstPROGRAMS ctags ctags-recursive distclean \
distclean-compile distclean-generic distclean-hdr \
distclean-tags dvi dvi-am html html-am info info-am install \
*************** uninstall-am:
*** 988,995 ****
install-ps install-ps-am install-strip installcheck \
installcheck-am installdirs installdirs-am maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-compile \
! mostlyclean-generic pdf pdf-am ps ps-am tags tags-recursive \
! uninstall uninstall-am
# Use an explicit dependency for the bison generated header file.
--- 1131,1138 ----
install-ps install-ps-am install-strip installcheck \
installcheck-am installdirs installdirs-am maintainer-clean \
maintainer-clean-generic mostlyclean mostlyclean-compile \
! mostlyclean-generic pdf pdf-am ps ps-am recheck recheck-html \
! tags tags-recursive uninstall uninstall-am
# Use an explicit dependency for the bison generated header file.
diff -rcp ../binutils-2.20.51.0.10.original/gold/merge.cc gold/merge.cc
*** ../binutils-2.20.51.0.10.original/gold/merge.cc 2010-08-10 15:11:43.000000000 +0100
--- gold/merge.cc 2010-08-10 15:14:03.000000000 +0100
***************
*** 1,6 ****
// merge.cc -- handle section merging for gold
! // Copyright 2006, 2007, 2008 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
--- 1,6 ----
// merge.cc -- handle section merging for gold
! // Copyright 2006, 2007, 2008, 2010 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
***************
*** 26,31 ****
--- 26,32 ----
#include <algorithm>
#include "merge.h"
+ #include "compressed_output.h"
namespace gold
{
*************** bool
*** 404,415 ****
Output_merge_data::do_add_input_section(Relobj* object, unsigned int shndx)
{
section_size_type len;
const unsigned char* p = object->section_contents(shndx, &len, false);
section_size_type entsize = convert_to_section_size_type(this->entsize());
if (len % entsize != 0)
! return false;
this->input_count_ += len / entsize;
--- 405,433 ----
Output_merge_data::do_add_input_section(Relobj* object, unsigned int shndx)
{
section_size_type len;
+ section_size_type uncompressed_size = 0;
+ unsigned char* uncompressed_data = NULL;
const unsigned char* p = object->section_contents(shndx, &len, false);
+ if (object->section_is_compressed(shndx, &uncompressed_size))
+ {
+ uncompressed_data = new unsigned char[uncompressed_size];
+ if (!decompress_input_section(p, len, uncompressed_data,
+ uncompressed_size))
+ object->error(_("could not decompress section %s"),
+ object->section_name(shndx).c_str());
+ p = uncompressed_data;
+ len = uncompressed_size;
+ }
+
section_size_type entsize = convert_to_section_size_type(this->entsize());
if (len % entsize != 0)
! {
! if (uncompressed_data != NULL)
! delete[] uncompressed_data;
! return false;
! }
this->input_count_ += len / entsize;
*************** Output_merge_data::do_add_input_section(
*** 438,443 ****
--- 456,464 ----
if (this->keeps_input_sections())
record_input_section(object, shndx);
+ if (uncompressed_data != NULL)
+ delete[] uncompressed_data;
+
return true;
}
*************** Output_merge_string<Char_type>::do_add_i
*** 495,550 ****
unsigned int shndx)
{
section_size_type len;
const unsigned char* pdata = object->section_contents(shndx, &len, false);
const Char_type* p = reinterpret_cast<const Char_type*>(pdata);
const Char_type* pend = p + len / sizeof(Char_type);
if (len % sizeof(Char_type) != 0)
{
object->error(_("mergeable string section length not multiple of "
"character size"));
return false;
}
size_t count = 0;
// The index I is in bytes, not characters.
section_size_type i = 0;
! while (i < len)
{
! const Char_type* pl;
! for (pl = p; *pl != 0; ++pl)
! {
! if (pl >= pend)
! {
! gold_warning(_("%s: last entry in mergeable string section '%s' "
! "not null terminated"),
! object->name().c_str(),
! object->section_name(shndx).c_str());
! break;
! }
! }
Stringpool::Key key;
! const Char_type* str = this->stringpool_.add_with_length(p, pl - p, true,
! &key);
! section_size_type bytelen_with_null = ((pl - p) + 1) * sizeof(Char_type);
! this->merged_strings_.push_back(Merged_string(object, shndx, i, str,
! bytelen_with_null, key));
!
! p = pl + 1;
! i += bytelen_with_null;
! ++count;
}
this->input_count_ += count;
// For script processing, we keep the input sections.
if (this->keeps_input_sections())
record_input_section(object, shndx);
return true;
}
--- 516,613 ----
unsigned int shndx)
{
section_size_type len;
+ section_size_type uncompressed_size = 0;
+ unsigned char* uncompressed_data = NULL;
const unsigned char* pdata = object->section_contents(shndx, &len, false);
+ if (object->section_is_compressed(shndx, &uncompressed_size))
+ {
+ uncompressed_data = new unsigned char[uncompressed_size];
+ if (!decompress_input_section(pdata, len, uncompressed_data,
+ uncompressed_size))
+ object->error(_("could not decompress section %s"),
+ object->section_name(shndx).c_str());
+ pdata = uncompressed_data;
+ len = uncompressed_size;
+ }
+
const Char_type* p = reinterpret_cast<const Char_type*>(pdata);
const Char_type* pend = p + len / sizeof(Char_type);
+ const Char_type* pend0 = pend;
if (len % sizeof(Char_type) != 0)
{
object->error(_("mergeable string section length not multiple of "
"character size"));
+ if (uncompressed_data != NULL)
+ delete[] uncompressed_data;
return false;
}
+ if (pend[-1] != 0)
+ {
+ gold_warning(_("%s: last entry in mergeable string section '%s' "
+ "not null terminated"),
+ object->name().c_str(),
+ object->section_name(shndx).c_str());
+ // Find the end of the last NULL-terminated string in the buffer.
+ while (pend0 > p && pend0[-1] != 0)
+ --pend0;
+ }
+
+ Merged_strings_list* merged_strings_list =
+ new Merged_strings_list(object, shndx);
+ this->merged_strings_lists_.push_back(merged_strings_list);
+ Merged_strings& merged_strings = merged_strings_list->merged_strings;
+
+ // Count the number of strings in the section and size the list.
size_t count = 0;
+ for (const Char_type* pt = p; pt < pend0; pt += string_length(pt) + 1)
+ ++count;
+ if (pend0 < pend)
+ ++count;
+ merged_strings.reserve(count + 1);
// The index I is in bytes, not characters.
section_size_type i = 0;
! while (p < pend0)
{
! size_t len = string_length(p);
!
! Stringpool::Key key;
! this->stringpool_.add_with_length(p, len, true, &key);
!
! merged_strings.push_back(Merged_string(i, key));
!
! p += len + 1;
! i += (len + 1) * sizeof(Char_type);
! }
! if (p < pend)
! {
! size_t len = pend - p;
Stringpool::Key key;
! this->stringpool_.add_with_length(p, len, true, &key);
! merged_strings.push_back(Merged_string(i, key));
!
! i += (len + 1) * sizeof(Char_type);
}
+ // Record the last offset in the input section so that we can
+ // compute the length of the last string.
+ merged_strings.push_back(Merged_string(i, 0));
+
this->input_count_ += count;
+ this->input_size_ += len;
// For script processing, we keep the input sections.
if (this->keeps_input_sections())
record_input_section(object, shndx);
+ if (uncompressed_data != NULL)
+ delete[] uncompressed_data;
+
return true;
}
*************** Output_merge_string<Char_type>::finalize
*** 557,576 ****
{
this->stringpool_.set_string_offsets();
! for (typename Merged_strings::const_iterator p =
! this->merged_strings_.begin();
! p != this->merged_strings_.end();
! ++p)
! {
! section_offset_type offset =
! this->stringpool_.get_offset_from_key(p->stringpool_key);
! this->add_mapping(p->object, p->shndx, p->offset, p->length, offset);
}
// Save some memory. This also ensures that this function will work
// if called twice, as may happen if Layout::set_segment_offsets
// finds a better alignment.
! this->merged_strings_.clear();
return this->stringpool_.get_strtab_size();
}
--- 620,653 ----
{
this->stringpool_.set_string_offsets();
! for (typename Merged_strings_lists::const_iterator l =
! this->merged_strings_lists_.begin();
! l != this->merged_strings_lists_.end();
! ++l)
! {
! section_offset_type last_input_offset = 0;
! section_offset_type last_output_offset = 0;
! for (typename Merged_strings::const_iterator p =
! (*l)->merged_strings.begin();
! p != (*l)->merged_strings.end();
! ++p)
! {
! section_size_type length = p->offset - last_input_offset;
! if (length > 0)
! this->add_mapping((*l)->object, (*l)->shndx, last_input_offset,
! length, last_output_offset);
! last_input_offset = p->offset;
! if (p->stringpool_key != 0)
! last_output_offset =
! this->stringpool_.get_offset_from_key(p->stringpool_key);
! }
! delete *l;
}
// Save some memory. This also ensures that this function will work
// if called twice, as may happen if Layout::set_segment_offsets
// finds a better alignment.
! this->merged_strings_lists_.clear();
return this->stringpool_.get_strtab_size();
}
*************** Output_merge_string<Char_type>::do_print
*** 641,647 ****
{
char buf[200];
snprintf(buf, sizeof buf, "%s merged %s", section_name, this->string_name());
! fprintf(stderr, _("%s: %s input: %zu\n"),
program_name, buf, this->input_count_);
this->stringpool_.print_stats(buf);
}
--- 718,726 ----
{
char buf[200];
snprintf(buf, sizeof buf, "%s merged %s", section_name, this->string_name());
! fprintf(stderr, _("%s: %s input bytes: %zu\n"),
! program_name, buf, this->input_size_);
! fprintf(stderr, _("%s: %s input strings: %zu\n"),
program_name, buf, this->input_count_);
this->stringpool_.print_stats(buf);
}
diff -rcp ../binutils-2.20.51.0.10.original/gold/merge.h gold/merge.h
*** ../binutils-2.20.51.0.10.original/gold/merge.h 2010-08-10 15:12:03.000000000 +0100
--- gold/merge.h 2010-08-10 15:14:03.000000000 +0100
*************** class Output_merge_string : public Outpu
*** 462,468 ****
public:
Output_merge_string(uint64_t addralign)
: Output_merge_base(sizeof(Char_type), addralign), stringpool_(),
! merged_strings_(), input_count_(0)
{
gold_assert(addralign <= sizeof(Char_type));
this->stringpool_.set_no_zero_null();
--- 462,468 ----
public:
Output_merge_string(uint64_t addralign)
: Output_merge_base(sizeof(Char_type), addralign), stringpool_(),
! merged_strings_lists_(), input_count_(0), input_size_(0)
{
gold_assert(addralign <= sizeof(Char_type));
this->stringpool_.set_no_zero_null();
*************** class Output_merge_string : public Outpu
*** 531,566 ****
// index and offset to strings.
struct Merged_string
{
- // The input object where the string was found.
- Relobj* object;
- // The input section in the input object.
- unsigned int shndx;
// The offset in the input section.
section_offset_type offset;
- // The string itself, a pointer into a Stringpool.
- const Char_type* string;
- // The length of the string in bytes, including the null terminator.
- size_t length;
// The key in the Stringpool.
Stringpool::Key stringpool_key;
! Merged_string(Relobj *objecta, unsigned int shndxa,
! section_offset_type offseta, const Char_type* stringa,
! size_t lengtha, Stringpool::Key stringpool_keya)
! : object(objecta), shndx(shndxa), offset(offseta), string(stringa),
! length(lengtha), stringpool_key(stringpool_keya)
{ }
};
typedef std::vector<Merged_string> Merged_strings;
// As we see the strings, we add them to a Stringpool.
Stringpool_template<Char_type> stringpool_;
// Map from a location in an input object to an entry in the
// Stringpool.
! Merged_strings merged_strings_;
// The number of entries seen in input files.
size_t input_count_;
};
} // End namespace gold.
--- 531,573 ----
// index and offset to strings.
struct Merged_string
{
// The offset in the input section.
section_offset_type offset;
// The key in the Stringpool.
Stringpool::Key stringpool_key;
! Merged_string(section_offset_type offseta, Stringpool::Key stringpool_keya)
! : offset(offseta), stringpool_key(stringpool_keya)
{ }
};
typedef std::vector<Merged_string> Merged_strings;
+ struct Merged_strings_list
+ {
+ // The input object where the strings were found.
+ Relobj* object;
+ // The input section in the input object.
+ unsigned int shndx;
+ // The list of merged strings.
+ Merged_strings merged_strings;
+
+ Merged_strings_list(Relobj* objecta, unsigned int shndxa)
+ : object(objecta), shndx(shndxa), merged_strings()
+ { }
+ };
+
+ typedef std::vector<Merged_strings_list*> Merged_strings_lists;
+
// As we see the strings, we add them to a Stringpool.
Stringpool_template<Char_type> stringpool_;
// Map from a location in an input object to an entry in the
// Stringpool.
! Merged_strings_lists merged_strings_lists_;
// The number of entries seen in input files.
size_t input_count_;
+ // The total size of input sections.
+ size_t input_size_;
};
} // End namespace gold.
diff -rcp ../binutils-2.20.51.0.10.original/gold/object.cc gold/object.cc
*** ../binutils-2.20.51.0.10.original/gold/object.cc 2010-08-10 15:11:28.000000000 +0100
--- gold/object.cc 2010-08-10 15:14:03.000000000 +0100
***************
*** 39,44 ****
--- 39,45 ----
#include "object.h"
#include "dynobj.h"
#include "plugin.h"
+ #include "compressed_output.h"
namespace gold
{
*************** Sized_relobj<size, big_endian>::Sized_re
*** 367,373 ****
local_got_offsets_(),
kept_comdat_sections_(),
has_eh_frame_(false),
! discarded_eh_frame_shndx_(-1U)
{
}
--- 368,377 ----
local_got_offsets_(),
kept_comdat_sections_(),
has_eh_frame_(false),
! discarded_eh_frame_shndx_(-1U),
! deferred_layout_(),
! deferred_layout_relocs_(),
! compressed_sections_()
{
}
*************** Sized_relobj<size, big_endian>::find_eh_
*** 495,500 ****
--- 499,548 ----
return false;
}
+ // Build a table for any compressed debug sections, mapping each section index
+ // to the uncompressed size.
+
+ template<int size, bool big_endian>
+ Compressed_section_map*
+ build_compressed_section_map(
+ const unsigned char* pshdrs,
+ unsigned int shnum,
+ const char* names,
+ section_size_type names_size,
+ Sized_relobj<size, big_endian>* obj)
+ {
+ Compressed_section_map* uncompressed_sizes = new Compressed_section_map();
+ const unsigned int shdr_size = elfcpp::Elf_sizes<size>::shdr_size;
+ const unsigned char* p = pshdrs + shdr_size;
+ for (unsigned int i = 1; i < shnum; ++i, p += shdr_size)
+ {
+ typename elfcpp::Shdr<size, big_endian> shdr(p);
+ if (shdr.get_sh_type() == elfcpp::SHT_PROGBITS
+ && (shdr.get_sh_flags() & elfcpp::SHF_ALLOC) == 0)
+ {
+ if (shdr.get_sh_name() >= names_size)
+ {
+ obj->error(_("bad section name offset for section %u: %lu"),
+ i, static_cast<unsigned long>(shdr.get_sh_name()));
+ continue;
+ }
+
+ const char* name = names + shdr.get_sh_name();
+ if (is_compressed_debug_section(name))
+ {
+ section_size_type len;
+ const unsigned char* contents =
+ obj->section_contents(i, &len, false);
+ uint64_t uncompressed_size = get_uncompressed_size(contents, len);
+ if (uncompressed_size != -1ULL)
+ (*uncompressed_sizes)[i] =
+ convert_to_section_size_type(uncompressed_size);
+ }
+ }
+ }
+ return uncompressed_sizes;
+ }
+
// Read the sections and symbols from an object file.
template<int size, bool big_endian>
*************** Sized_relobj<size, big_endian>::do_read_
*** 514,519 ****
--- 562,571 ----
if (this->find_eh_frame(pshdrs, names, sd->section_names_size))
this->has_eh_frame_ = true;
}
+ if (memmem(names, sd->section_names_size, ".zdebug_", 8) != NULL)
+ this->compressed_sections_ =
+ build_compressed_section_map(pshdrs, this->shnum(), names,
+ sd->section_names_size, this);
sd->symbols = NULL;
sd->symbols_size = 0;
*************** Sized_relobj<size, big_endian>::do_add_s
*** 1562,1567 ****
--- 1614,1620 ----
template<int size, bool big_endian>
Archive::Should_include
Sized_relobj<size, big_endian>::do_should_include_member(Symbol_table* symtab,
+ Layout* layout,
Read_symbols_data* sd,
std::string* why)
{
*************** Sized_relobj<size, big_endian>::do_shoul
*** 1587,1593 ****
unsigned int st_name = sym.get_st_name();
const char* name = sym_names + st_name;
Symbol* symbol;
! Archive::Should_include t = Archive::should_include_member(symtab, name,
&symbol, why,
&tmpbuf,
&tmpbuflen);
--- 1640,1648 ----
unsigned int st_name = sym.get_st_name();
const char* name = sym_names + st_name;
Symbol* symbol;
! Archive::Should_include t = Archive::should_include_member(symtab,
! layout,
! name,
&symbol, why,
&tmpbuf,
&tmpbuflen);
diff -rcp ../binutils-2.20.51.0.10.original/gold/object.h gold/object.h
*** ../binutils-2.20.51.0.10.original/gold/object.h 2010-08-10 15:11:43.000000000 +0100
--- gold/object.h 2010-08-10 15:14:03.000000000 +0100
*************** class Object
*** 405,413 ****
// Add symbol information to the global symbol table.
Archive::Should_include
! should_include_member(Symbol_table* symtab, Read_symbols_data* sd,
! std::string* why)
! { return this->do_should_include_member(symtab, sd, why); }
// Functions and types for the elfcpp::Elf_file interface. This
// permit us to use Object as the File template parameter for
--- 405,413 ----
// Add symbol information to the global symbol table.
Archive::Should_include
! should_include_member(Symbol_table* symtab, Layout* layout,
! Read_symbols_data* sd, std::string* why)
! { return this->do_should_include_member(symtab, layout, sd, why); }
// Functions and types for the elfcpp::Elf_file interface. This
// permit us to use Object as the File template parameter for
*************** class Object
*** 518,523 ****
--- 518,530 ----
set_no_export(bool value)
{ this->no_export_ = value; }
+ // Return TRUE if the section is a compressed debug section, and set
+ // *UNCOMPRESSED_SIZE to the size of the uncompressed data.
+ bool
+ section_is_compressed(unsigned int shndx,
+ section_size_type* uncompressed_size) const
+ { return this->do_section_is_compressed(shndx, uncompressed_size); }
+
protected:
// Returns NULL for Objects that are not plugin objects. This method
// is overridden in the Pluginobj class.
*************** class Object
*** 539,545 ****
do_add_symbols(Symbol_table*, Read_symbols_data*, Layout*) = 0;
virtual Archive::Should_include
! do_should_include_member(Symbol_table* symtab, Read_symbols_data*,
std::string* why) = 0;
// Return the location of the contents of a section. Implemented by
--- 546,552 ----
do_add_symbols(Symbol_table*, Read_symbols_data*, Layout*) = 0;
virtual Archive::Should_include
! do_should_include_member(Symbol_table* symtab, Layout*, Read_symbols_data*,
std::string* why) = 0;
// Return the location of the contents of a section. Implemented by
*************** class Object
*** 628,633 ****
--- 635,646 ----
bool
handle_split_stack_section(const char* name);
+ // Return TRUE if the section is a compressed debug section, and set
+ // *UNCOMPRESSED_SIZE to the size of the uncompressed data.
+ virtual bool
+ do_section_is_compressed(unsigned int, section_size_type*) const
+ { return false; }
+
private:
// This class may not be copied.
Object(const Object&);
*************** class Reloc_symbol_changes
*** 1406,1411 ****
--- 1419,1428 ----
std::vector<Symbol*> vec_;
};
+ // Type for mapping section index to uncompressed size.
+
+ typedef std::map<unsigned int, section_size_type> Compressed_section_map;
+
// A regular object file. This is size and endian specific.
template<int size, bool big_endian>
*************** class Sized_relobj : public Relobj
*** 1606,1612 ****
do_add_symbols(Symbol_table*, Read_symbols_data*, Layout*);
Archive::Should_include
! do_should_include_member(Symbol_table* symtab, Read_symbols_data*,
std::string* why);
// Read the relocs.
--- 1623,1629 ----
do_add_symbols(Symbol_table*, Read_symbols_data*, Layout*);
Archive::Should_include
! do_should_include_member(Symbol_table* symtab, Layout*, Read_symbols_data*,
std::string* why);
// Read the relocs.
*************** class Sized_relobj : public Relobj
*** 1781,1787 ****
void
set_output_local_symbol_count(unsigned int value)
{ this->output_local_symbol_count_ = value; }
!
private:
// For convenience.
typedef Sized_relobj<size, big_endian> This;
--- 1798,1823 ----
void
set_output_local_symbol_count(unsigned int value)
{ this->output_local_symbol_count_ = value; }
!
! // Return TRUE if the section is a compressed debug section, and set
! // *UNCOMPRESSED_SIZE to the size of the uncompressed data.
! bool
! do_section_is_compressed(unsigned int shndx,
! section_size_type* uncompressed_size) const
! {
! if (this->compressed_sections_ == NULL)
! return false;
! Compressed_section_map::const_iterator p =
! this->compressed_sections_->find(shndx);
! if (p != this->compressed_sections_->end())
! {
! if (uncompressed_size != NULL)
! *uncompressed_size = p->second;
! return true;
! }
! return false;
! }
!
private:
// For convenience.
typedef Sized_relobj<size, big_endian> This;
*************** class Sized_relobj : public Relobj
*** 2024,2029 ****
--- 2060,2067 ----
std::vector<Deferred_layout> deferred_layout_;
// The list of relocation sections whose layout was deferred.
std::vector<Deferred_layout> deferred_layout_relocs_;
+ // For compressed debug sections, map section index to uncompressed size.
+ Compressed_section_map* compressed_sections_;
};
// A class to manage the list of all objects.
diff -rcp ../binutils-2.20.51.0.10.original/gold/output.cc gold/output.cc
*** ../binutils-2.20.51.0.10.original/gold/output.cc 2010-08-10 15:11:46.000000000 +0100
--- gold/output.cc 2010-08-10 15:14:03.000000000 +0100
*************** Output_section::Output_section(const cha
*** 1917,1922 ****
--- 1917,1923 ----
info_(0),
type_(type),
flags_(flags),
+ order_(ORDER_INVALID),
out_shndx_(-1U),
symtab_index_(0),
dynsym_index_(0),
*************** Output_section::Output_section(const cha
*** 1938,1954 ****
must_sort_attached_input_sections_(false),
attached_input_sections_are_sorted_(false),
is_relro_(false),
- is_relro_local_(false),
- is_last_relro_(false),
- is_first_non_relro_(false),
is_small_section_(false),
is_large_section_(false),
- is_interp_(false),
- is_dynamic_linker_section_(false),
generate_code_fills_at_write_(false),
is_entsize_zero_(false),
section_offsets_need_adjustment_(false),
is_noload_(false),
tls_offset_(0),
checkpoint_(NULL),
lookup_maps_(new Output_section_lookup_maps)
--- 1939,1951 ----
must_sort_attached_input_sections_(false),
attached_input_sections_are_sorted_(false),
is_relro_(false),
is_small_section_(false),
is_large_section_(false),
generate_code_fills_at_write_(false),
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)
*************** Output_section::add_input_section(Layout
*** 2038,2045 ****
{
// 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();
if (this->add_merge_input_section(object, shndx, sh_flags, entsize,
addralign, keeps_input_sections))
{
--- 2035,2044 ----
{
// Keep information about merged input sections for rebuilding fast
// lookup maps if we have sections-script or we do relaxation.
! 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))
{
*************** Output_section::add_input_section(Layout
*** 2086,2093 ****
}
}
this->set_current_data_size_for_child(aligned_offset_in_section
! + shdr.get_sh_size());
// We need to keep track of this section if we are already keeping
// track of sections, or if we are relaxing. Also, if this is a
--- 2085,2097 ----
}
}
+ section_size_type input_section_size = shdr.get_sh_size();
+ section_size_type uncompressed_size;
+ if (object->section_is_compressed(shndx, &uncompressed_size))
+ input_section_size = uncompressed_size;
+
this->set_current_data_size_for_child(aligned_offset_in_section
! + input_section_size);
// We need to keep track of this section if we are already keeping
// track of sections, or if we are relaxing. Also, if this is a
*************** Output_section::add_input_section(Layout
*** 2095,2101 ****
// the future, we keep track of the sections. If the
// --section-ordering-file option is used to specify the order of
// sections, we need to keep track of sections.
! if (have_sections_script
|| !this->input_sections_.empty()
|| this->may_sort_attached_input_sections()
|| this->must_sort_attached_input_sections()
--- 2099,2106 ----
// the future, we keep track of the sections. If the
// --section-ordering-file option is used to specify the order of
// sections, we need to keep track of sections.
! 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()
*************** Output_section::print_merge_stats()
*** 3400,3408 ****
// Output segment methods.
Output_segment::Output_segment(elfcpp::Elf_Word type, elfcpp::Elf_Word flags)
! : output_data_(),
! output_bss_(),
! vaddr_(0),
paddr_(0),
memsz_(0),
max_align_(0),
--- 3405,3411 ----
// Output segment methods.
Output_segment::Output_segment(elfcpp::Elf_Word type, elfcpp::Elf_Word flags)
! : vaddr_(0),
paddr_(0),
memsz_(0),
max_align_(0),
*************** Output_segment::Output_segment(elfcpp::E
*** 3421,3713 ****
this->flags_ = elfcpp::PF_R;
}
! // Add an Output_section to an Output_segment.
void
! Output_segment::add_output_section(Output_section* os,
! elfcpp::Elf_Word seg_flags,
! bool do_sort)
{
gold_assert((os->flags() & elfcpp::SHF_ALLOC) != 0);
gold_assert(!this->is_max_align_known_);
gold_assert(os->is_large_data_section() == this->is_large_data_segment());
- gold_assert(this->type() == elfcpp::PT_LOAD || !do_sort);
this->update_flags_for_output_section(seg_flags);
! Output_segment::Output_data_list* pdl;
! if (os->type() == elfcpp::SHT_NOBITS)
! pdl = &this->output_bss_;
else
! pdl = &this->output_data_;
!
! // Note that while there may be many input sections in an output
! // section, there are normally only a few output sections in an
! // output segment. The loops below are expected to be fast.
!
! // So that PT_NOTE segments will work correctly, we need to ensure
! // that all SHT_NOTE sections are adjacent.
! if (os->type() == elfcpp::SHT_NOTE && !pdl->empty())
! {
! Output_segment::Output_data_list::iterator p = pdl->end();
! do
! {
! --p;
! if ((*p)->is_section_type(elfcpp::SHT_NOTE))
! {
! ++p;
! pdl->insert(p, os);
! return;
! }
! }
! while (p != pdl->begin());
! }
!
! // Similarly, so that PT_TLS segments will work, we need to group
! // SHF_TLS sections. An SHF_TLS/SHT_NOBITS section is a special
! // case: we group the SHF_TLS/SHT_NOBITS sections right after the
! // SHF_TLS/SHT_PROGBITS sections. This lets us set up PT_TLS
! // correctly. SHF_TLS sections get added to both a PT_LOAD segment
! // and the PT_TLS segment; we do this grouping only for the PT_LOAD
! // segment.
! if (this->type_ != elfcpp::PT_TLS
! && (os->flags() & elfcpp::SHF_TLS) != 0)
! {
! pdl = &this->output_data_;
! if (!pdl->empty())
! {
! bool nobits = os->type() == elfcpp::SHT_NOBITS;
! bool sawtls = false;
! Output_segment::Output_data_list::iterator p = pdl->end();
! gold_assert(p != pdl->begin());
! do
! {
! --p;
! bool insert;
! if ((*p)->is_section_flag_set(elfcpp::SHF_TLS))
! {
! sawtls = true;
! // Put a NOBITS section after the first TLS section.
! // Put a PROGBITS section after the first
! // TLS/PROGBITS section.
! insert = nobits || !(*p)->is_section_type(elfcpp::SHT_NOBITS);
! }
! else
! {
! // If we've gone past the TLS sections, but we've
! // seen a TLS section, then we need to insert this
! // section now.
! insert = sawtls;
! }
!
! if (insert)
! {
! ++p;
! pdl->insert(p, os);
! return;
! }
! }
! while (p != pdl->begin());
! }
!
! // There are no TLS sections yet; put this one at the requested
! // location in the section list.
! }
!
! if (do_sort)
! {
! // For the PT_GNU_RELRO segment, we need to group relro
! // sections, and we need to put them before any non-relro
! // sections. Any relro local sections go before relro non-local
! // sections. One section may be marked as the last relro
! // section.
! if (os->is_relro())
! {
! gold_assert(pdl == &this->output_data_);
! Output_segment::Output_data_list::iterator p;
! for (p = pdl->begin(); p != pdl->end(); ++p)
! {
! if (!(*p)->is_section())
! break;
! Output_section* pos = (*p)->output_section();
! if (!pos->is_relro()
! || (os->is_relro_local() && !pos->is_relro_local())
! || (!os->is_last_relro() && pos->is_last_relro()))
! break;
! }
!
! pdl->insert(p, os);
! return;
! }
! // One section may be marked as the first section which follows
! // the relro sections.
! if (os->is_first_non_relro())
! {
! gold_assert(pdl == &this->output_data_);
! Output_segment::Output_data_list::iterator p;
! for (p = pdl->begin(); p != pdl->end(); ++p)
! {
! if (!(*p)->is_section())
! break;
! Output_section* pos = (*p)->output_section();
! if (!pos->is_relro())
! break;
! }
! pdl->insert(p, os);
! return;
! }
! }
! // Small data sections go at the end of the list of data sections.
! // If OS is not small, and there are small sections, we have to
! // insert it before the first small section.
! if (os->type() != elfcpp::SHT_NOBITS
! && !os->is_small_section()
! && !pdl->empty()
! && pdl->back()->is_section()
! && pdl->back()->output_section()->is_small_section())
! {
! for (Output_segment::Output_data_list::iterator p = pdl->begin();
! p != pdl->end();
! ++p)
! {
! if ((*p)->is_section()
! && (*p)->output_section()->is_small_section())
! {
! pdl->insert(p, os);
! return;
! }
! }
! gold_unreachable();
! }
! // A small BSS section goes at the start of the BSS sections, after
! // other small BSS sections.
! if (os->type() == elfcpp::SHT_NOBITS && os->is_small_section())
! {
! for (Output_segment::Output_data_list::iterator p = pdl->begin();
! p != pdl->end();
! ++p)
! {
! if (!(*p)->is_section()
! || !(*p)->output_section()->is_small_section())
! {
! pdl->insert(p, os);
! return;
! }
! }
! }
! // A large BSS section goes at the end of the BSS sections, which
! // means that one that is not large must come before the first large
! // one.
! if (os->type() == elfcpp::SHT_NOBITS
! && !os->is_large_section()
! && !pdl->empty()
! && pdl->back()->is_section()
! && pdl->back()->output_section()->is_large_section())
{
! for (Output_segment::Output_data_list::iterator p = pdl->begin();
! p != pdl->end();
! ++p)
{
! if ((*p)->is_section()
! && (*p)->output_section()->is_large_section())
{
! pdl->insert(p, os);
return;
}
}
- gold_unreachable();
}
-
- // We do some further output section sorting in order to make the
- // generated program run more efficiently. We should only do this
- // when not using a linker script, so it is controled by the DO_SORT
- // parameter.
- if (do_sort)
- {
- // FreeBSD requires the .interp section to be in the first page
- // of the executable. That is a more efficient location anyhow
- // for any OS, since it means that the kernel will have the data
- // handy after it reads the program headers.
- if (os->is_interp() && !pdl->empty())
- {
- pdl->insert(pdl->begin(), os);
- return;
- }
-
- // Put loadable non-writable notes immediately after the .interp
- // sections, so that the PT_NOTE segment is on the first page of
- // the executable.
- if (os->type() == elfcpp::SHT_NOTE
- && (os->flags() & elfcpp::SHF_WRITE) == 0
- && !pdl->empty())
- {
- Output_segment::Output_data_list::iterator p = pdl->begin();
- if ((*p)->is_section() && (*p)->output_section()->is_interp())
- ++p;
- pdl->insert(p, os);
- return;
- }
-
- // If this section is used by the dynamic linker, and it is not
- // writable, then put it first, after the .interp section and
- // any loadable notes. This makes it more likely that the
- // dynamic linker will have to read less data from the disk.
- if (os->is_dynamic_linker_section()
- && !pdl->empty()
- && (os->flags() & elfcpp::SHF_WRITE) == 0)
- {
- bool is_reloc = (os->type() == elfcpp::SHT_REL
- || os->type() == elfcpp::SHT_RELA);
- Output_segment::Output_data_list::iterator p = pdl->begin();
- while (p != pdl->end()
- && (*p)->is_section()
- && ((*p)->output_section()->is_dynamic_linker_section()
- || (*p)->output_section()->type() == elfcpp::SHT_NOTE))
- {
- // Put reloc sections after the other ones. Putting the
- // dynamic reloc sections first confuses BFD, notably
- // objcopy and strip.
- if (!is_reloc
- && ((*p)->output_section()->type() == elfcpp::SHT_REL
- || (*p)->output_section()->type() == elfcpp::SHT_RELA))
- break;
- ++p;
- }
- pdl->insert(p, os);
- return;
- }
- }
-
- // If there were no constraints on the output section, just add it
- // to the end of the list.
- pdl->push_back(os);
- }
-
- // Remove an Output_section from this segment. It is an error if it
- // is not present.
-
- void
- Output_segment::remove_output_section(Output_section* os)
- {
- // We only need this for SHT_PROGBITS.
- gold_assert(os->type() == elfcpp::SHT_PROGBITS);
- for (Output_data_list::iterator p = this->output_data_.begin();
- p != this->output_data_.end();
- ++p)
- {
- if (*p == os)
- {
- this->output_data_.erase(p);
- return;
- }
- }
gold_unreachable();
}
--- 3424,3487 ----
this->flags_ = elfcpp::PF_R;
}
! // Add an Output_section to a PT_LOAD Output_segment.
void
! Output_segment::add_output_section_to_load(Layout* layout,
! Output_section* os,
! elfcpp::Elf_Word seg_flags)
{
+ gold_assert(this->type() == elfcpp::PT_LOAD);
gold_assert((os->flags() & elfcpp::SHF_ALLOC) != 0);
gold_assert(!this->is_max_align_known_);
gold_assert(os->is_large_data_section() == this->is_large_data_segment());
this->update_flags_for_output_section(seg_flags);
! // We don't want to change the ordering if we have a linker script
! // with a SECTIONS clause.
! Output_section_order order = os->order();
! if (layout->script_options()->saw_sections_clause())
! order = static_cast<Output_section_order>(0);
else
! gold_assert(order != ORDER_INVALID);
! this->output_lists_[order].push_back(os);
! }
! // Add an Output_section to a non-PT_LOAD Output_segment.
! void
! Output_segment::add_output_section_to_nonload(Output_section* os,
! elfcpp::Elf_Word seg_flags)
! {
! gold_assert(this->type() != elfcpp::PT_LOAD);
! gold_assert((os->flags() & elfcpp::SHF_ALLOC) != 0);
! gold_assert(!this->is_max_align_known_);
! this->update_flags_for_output_section(seg_flags);
! this->output_lists_[0].push_back(os);
! }
! // Remove an Output_section from this segment. It is an error if it
! // is not present.
! void
! Output_segment::remove_output_section(Output_section* os)
! {
! for (int i = 0; i < static_cast<int>(ORDER_MAX); ++i)
{
! Output_data_list* pdl = &this->output_lists_[i];
! for (Output_data_list::iterator p = pdl->begin(); p != pdl->end(); ++p)
{
! if (*p == os)
{
! pdl->erase(p);
return;
}
}
}
gold_unreachable();
}
*************** void
*** 3718,3724 ****
Output_segment::add_initial_output_data(Output_data* od)
{
gold_assert(!this->is_max_align_known_);
! this->output_data_.push_front(od);
}
// Return whether the first data section is a relro section.
--- 3492,3521 ----
Output_segment::add_initial_output_data(Output_data* od)
{
gold_assert(!this->is_max_align_known_);
! Output_data_list::iterator p = this->output_lists_[0].begin();
! this->output_lists_[0].insert(p, od);
! }
!
! // Return true if this segment has any sections which hold actual
! // data, rather than being a BSS section.
!
! bool
! Output_segment::has_any_data_sections() const
! {
! for (int i = 0; i < static_cast<int>(ORDER_MAX); ++i)
! {
! const Output_data_list* pdl = &this->output_lists_[i];
! for (Output_data_list::const_iterator p = pdl->begin();
! p != pdl->end();
! ++p)
! {
! if (!(*p)->is_section())
! return true;
! if ((*p)->output_section()->type() != elfcpp::SHT_NOBITS)
! return true;
! }
! }
! return false;
}
// Return whether the first data section is a relro section.
*************** Output_segment::add_initial_output_data(
*** 3726,3734 ****
bool
Output_segment::is_first_section_relro() const
{
! return (!this->output_data_.empty()
! && this->output_data_.front()->is_section()
! && this->output_data_.front()->output_section()->is_relro());
}
// Return the maximum alignment of the Output_data in Output_segment.
--- 3523,3538 ----
bool
Output_segment::is_first_section_relro() const
{
! for (int i = 0; i < static_cast<int>(ORDER_MAX); ++i)
! {
! const Output_data_list* pdl = &this->output_lists_[i];
! if (!pdl->empty())
! {
! Output_data* p = pdl->front();
! return p->is_section() && p->output_section()->is_relro();
! }
! }
! return false;
}
// Return the maximum alignment of the Output_data in Output_segment.
*************** Output_segment::maximum_alignment()
*** 3738,3753 ****
{
if (!this->is_max_align_known_)
{
! uint64_t addralign;
!
! addralign = Output_segment::maximum_alignment_list(&this->output_data_);
! if (addralign > this->max_align_)
! this->max_align_ = addralign;
!
! addralign = Output_segment::maximum_alignment_list(&this->output_bss_);
! if (addralign > this->max_align_)
! this->max_align_ = addralign;
!
this->is_max_align_known_ = true;
}
--- 3542,3554 ----
{
if (!this->is_max_align_known_)
{
! for (int i = 0; i < static_cast<int>(ORDER_MAX); ++i)
! {
! const Output_data_list* pdl = &this->output_lists_[i];
! uint64_t addralign = Output_segment::maximum_alignment_list(pdl);
! if (addralign > this->max_align_)
! this->max_align_ = addralign;
! }
this->is_max_align_known_ = true;
}
*************** Output_segment::maximum_alignment_list(c
*** 3771,3796 ****
return ret;
}
! // Return the number of dynamic relocs applied to this segment.
! unsigned int
! Output_segment::dynamic_reloc_count() const
{
! return (this->dynamic_reloc_count_list(&this->output_data_)
! + this->dynamic_reloc_count_list(&this->output_bss_));
}
! // Return the number of dynamic relocs applied to an Output_data_list.
! unsigned int
! Output_segment::dynamic_reloc_count_list(const Output_data_list* pdl) const
{
- unsigned int count = 0;
for (Output_data_list::const_iterator p = pdl->begin();
p != pdl->end();
++p)
! count += (*p)->dynamic_reloc_count();
! return count;
}
// Set the section addresses for an Output_segment. If RESET is true,
--- 3572,3599 ----
return ret;
}
! // Return whether this segment has any dynamic relocs.
! bool
! Output_segment::has_dynamic_reloc() const
{
! for (int i = 0; i < static_cast<int>(ORDER_MAX); ++i)
! if (this->has_dynamic_reloc_list(&this->output_lists_[i]))
! return true;
! return false;
}
! // Return whether this Output_data_list has any dynamic relocs.
! bool
! Output_segment::has_dynamic_reloc_list(const Output_data_list* pdl) const
{
for (Output_data_list::const_iterator p = pdl->begin();
p != pdl->end();
++p)
! if ((*p)->has_dynamic_reloc())
! return true;
! return false;
}
// Set the section addresses for an Output_segment. If RESET is true,
*************** Output_segment::set_section_addresses(co
*** 3818,3843 ****
{
uint64_t relro_size = 0;
off_t off = *poff;
! for (Output_data_list::iterator p = this->output_data_.begin();
! p != this->output_data_.end();
! ++p)
{
! if (!(*p)->is_section())
! break;
! Output_section* pos = (*p)->output_section();
! if (!pos->is_relro())
! break;
! gold_assert(!(*p)->is_section_flag_set(elfcpp::SHF_TLS));
! if ((*p)->is_address_valid())
! relro_size += (*p)->data_size();
! else
{
! // FIXME: This could be faster.
! (*p)->set_address_and_file_offset(addr + relro_size,
! off + relro_size);
! relro_size += (*p)->data_size();
! (*p)->reset_address_and_file_offset();
}
}
relro_size += increase_relro;
--- 3621,3650 ----
{
uint64_t relro_size = 0;
off_t off = *poff;
! for (int i = 0; i < static_cast<int>(ORDER_MAX); ++i)
{
! Output_data_list* pdl = &this->output_lists_[i];
! Output_data_list::iterator p;
! for (p = pdl->begin(); p != pdl->end(); ++p)
{
! if (!(*p)->is_section())
! break;
! Output_section* pos = (*p)->output_section();
! if (!pos->is_relro())
! break;
! if ((*p)->is_address_valid())
! relro_size += (*p)->data_size();
! else
! {
! // FIXME: This could be faster.
! (*p)->set_address_and_file_offset(addr + relro_size,
! off + relro_size);
! relro_size += (*p)->data_size();
! (*p)->reset_address_and_file_offset();
! }
}
+ if (p != pdl->end())
+ break;
}
relro_size += increase_relro;
*************** Output_segment::set_section_addresses(co
*** 3868,3883 ****
this->offset_ = orig_off;
! addr = this->set_section_list_addresses(layout, reset, &this->output_data_,
! addr, poff, pshndx, &in_tls);
! this->filesz_ = *poff - orig_off;
!
! off_t off = *poff;
!
! uint64_t ret = this->set_section_list_addresses(layout, reset,
! &this->output_bss_,
! addr, poff, pshndx,
! &in_tls);
// If the last section was a TLS section, align upward to the
// alignment of the TLS segment, so that the overall size of the TLS
--- 3675,3695 ----
this->offset_ = orig_off;
! off_t off = 0;
! uint64_t ret;
! for (int i = 0; i < static_cast<int>(ORDER_MAX); ++i)
! {
! addr = this->set_section_list_addresses(layout, reset,
! &this->output_lists_[i],
! addr, poff, pshndx, &in_tls);
! if (i < static_cast<int>(ORDER_SMALL_BSS))
! {
! this->filesz_ = *poff - orig_off;
! off = *poff;
! }
!
! ret = addr;
! }
// If the last section was a TLS section, align upward to the
// alignment of the TLS segment, so that the overall size of the TLS
*************** Output_segment::set_offset(unsigned int
*** 4020,4026 ****
gold_assert(!this->are_addresses_set_);
! if (this->output_data_.empty() && this->output_bss_.empty())
{
gold_assert(increase == 0);
this->vaddr_ = 0;
--- 3832,3842 ----
gold_assert(!this->are_addresses_set_);
! // A non-load section only uses output_lists_[0].
!
! Output_data_list* pdl = &this->output_lists_[0];
!
! if (pdl->empty())
{
gold_assert(increase == 0);
this->vaddr_ = 0;
*************** Output_segment::set_offset(unsigned int
*** 4033,4043 ****
return;
}
! const Output_data* first;
! if (this->output_data_.empty())
! first = this->output_bss_.front();
! else
! first = this->output_data_.front();
this->vaddr_ = first->address();
this->paddr_ = (first->has_load_address()
? first->load_address()
--- 3849,3880 ----
return;
}
! // Find the first and last section by address.
! const Output_data* first = NULL;
! const Output_data* last_data = NULL;
! const Output_data* last_bss = NULL;
! for (Output_data_list::const_iterator p = pdl->begin();
! p != pdl->end();
! ++p)
! {
! if (first == NULL
! || (*p)->address() < first->address()
! || ((*p)->address() == first->address()
! && (*p)->data_size() < first->data_size()))
! first = *p;
! const Output_data** plast;
! if ((*p)->is_section()
! && (*p)->output_section()->type() == elfcpp::SHT_NOBITS)
! plast = &last_bss;
! else
! plast = &last_data;
! if (*plast == NULL
! || (*p)->address() > (*plast)->address()
! || ((*p)->address() == (*plast)->address()
! && (*p)->data_size() > (*plast)->data_size()))
! *plast = *p;
! }
!
this->vaddr_ = first->address();
this->paddr_ = (first->has_load_address()
? first->load_address()
*************** Output_segment::set_offset(unsigned int
*** 4045,4065 ****
this->are_addresses_set_ = true;
this->offset_ = first->offset();
! if (this->output_data_.empty())
this->filesz_ = 0;
else
! {
! const Output_data* last_data = this->output_data_.back();
! this->filesz_ = (last_data->address()
! + last_data->data_size()
! - this->vaddr_);
! }
! const Output_data* last;
! if (this->output_bss_.empty())
! last = this->output_data_.back();
! else
! last = this->output_bss_.back();
this->memsz_ = (last->address()
+ last->data_size()
- this->vaddr_);
--- 3882,3895 ----
this->are_addresses_set_ = true;
this->offset_ = first->offset();
! if (last_data == NULL)
this->filesz_ = 0;
else
! this->filesz_ = (last_data->address()
! + last_data->data_size()
! - this->vaddr_);
! const Output_data* last = last_bss != NULL ? last_bss : last_data;
this->memsz_ = (last->address()
+ last->data_size()
- this->vaddr_);
*************** Output_segment::set_tls_offsets()
*** 4085,4118 ****
{
gold_assert(this->type_ == elfcpp::PT_TLS);
! for (Output_data_list::iterator p = this->output_data_.begin();
! p != this->output_data_.end();
! ++p)
! (*p)->set_tls_offset(this->vaddr_);
!
! for (Output_data_list::iterator p = this->output_bss_.begin();
! p != this->output_bss_.end();
++p)
(*p)->set_tls_offset(this->vaddr_);
}
! // Return the address of the first section.
uint64_t
Output_segment::first_section_load_address() const
{
! for (Output_data_list::const_iterator p = this->output_data_.begin();
! p != this->output_data_.end();
! ++p)
! if ((*p)->is_section())
! return (*p)->has_load_address() ? (*p)->load_address() : (*p)->address();
!
! for (Output_data_list::const_iterator p = this->output_bss_.begin();
! p != this->output_bss_.end();
! ++p)
! if ((*p)->is_section())
! return (*p)->has_load_address() ? (*p)->load_address() : (*p)->address();
!
gold_unreachable();
}
--- 3915,3944 ----
{
gold_assert(this->type_ == elfcpp::PT_TLS);
! for (Output_data_list::iterator p = this->output_lists_[0].begin();
! p != this->output_lists_[0].end();
++p)
(*p)->set_tls_offset(this->vaddr_);
}
! // Return the load address of the first section.
uint64_t
Output_segment::first_section_load_address() const
{
! for (int i = 0; i < static_cast<int>(ORDER_MAX); ++i)
! {
! const Output_data_list* pdl = &this->output_lists_[i];
! for (Output_data_list::const_iterator p = pdl->begin();
! p != pdl->end();
! ++p)
! {
! if ((*p)->is_section())
! return ((*p)->has_load_address()
! ? (*p)->load_address()
! : (*p)->address());
! }
! }
gold_unreachable();
}
*************** Output_segment::first_section_load_addre
*** 4121,4128 ****
unsigned int
Output_segment::output_section_count() const
{
! return (this->output_section_count_list(&this->output_data_)
! + this->output_section_count_list(&this->output_bss_));
}
// Return the number of Output_sections in an Output_data_list.
--- 3947,3956 ----
unsigned int
Output_segment::output_section_count() const
{
! unsigned int ret = 0;
! for (int i = 0; i < static_cast<int>(ORDER_MAX); ++i)
! ret += this->output_section_count_list(&this->output_lists_[i]);
! return ret;
}
// Return the number of Output_sections in an Output_data_list.
*************** Output_segment::section_with_lowest_load
*** 4150,4167 ****
{
Output_section* found = NULL;
uint64_t found_lma = 0;
! this->lowest_load_address_in_list(&this->output_data_, &found, &found_lma);
!
! Output_section* found_data = found;
! this->lowest_load_address_in_list(&this->output_bss_, &found, &found_lma);
! if (found != found_data && found_data != NULL)
! {
! gold_error(_("nobits section %s may not precede progbits section %s "
! "in same segment"),
! found->name(), found_data->name());
! return NULL;
! }
!
return found;
}
--- 3978,3986 ----
{
Output_section* found = NULL;
uint64_t found_lma = 0;
! for (int i = 0; i < static_cast<int>(ORDER_MAX); ++i)
! this->lowest_load_address_in_list(&this->output_lists_[i], &found,
! &found_lma);
return found;
}
*************** Output_segment::write_section_headers(co
*** 4221,4232 ****
if (this->type_ != elfcpp::PT_LOAD)
return v;
! v = this->write_section_headers_list<size, big_endian>(layout, secnamepool,
! &this->output_data_,
! v, pshndx);
! v = this->write_section_headers_list<size, big_endian>(layout, secnamepool,
! &this->output_bss_,
! v, pshndx);
return v;
}
--- 4040,4054 ----
if (this->type_ != elfcpp::PT_LOAD)
return v;
! for (int i = 0; i < static_cast<int>(ORDER_MAX); ++i)
! {
! const Output_data_list* pdl = &this->output_lists_[i];
! v = this->write_section_headers_list<size, big_endian>(layout,
! secnamepool,
! pdl,
! v, pshndx);
! }
!
return v;
}
*************** Output_segment::print_sections_to_mapfil
*** 4263,4270 ****
{
if (this->type() != elfcpp::PT_LOAD)
return;
! this->print_section_list_to_mapfile(mapfile, &this->output_data_);
! this->print_section_list_to_mapfile(mapfile, &this->output_bss_);
}
// Print an output section list to the map file.
--- 4085,4092 ----
{
if (this->type() != elfcpp::PT_LOAD)
return;
! for (int i = 0; i < static_cast<int>(ORDER_MAX); ++i)
! this->print_section_list_to_mapfile(mapfile, &this->output_lists_[i]);
}
// Print an output section list to the map file.
diff -rcp ../binutils-2.20.51.0.10.original/gold/output.h gold/output.h
*** ../binutils-2.20.51.0.10.original/gold/output.h 2010-08-10 15:11:28.000000000 +0100
--- gold/output.h 2010-08-10 15:14:03.000000000 +0100
*************** class Output_data
*** 56,62 ****
: address_(0), data_size_(0), offset_(-1),
is_address_valid_(false), is_data_size_valid_(false),
is_offset_valid_(false), is_data_size_fixed_(false),
! dynamic_reloc_count_(0)
{ }
virtual
--- 56,62 ----
: address_(0), data_size_(0), offset_(-1),
is_address_valid_(false), is_data_size_valid_(false),
is_offset_valid_(false), is_data_size_fixed_(false),
! has_dynamic_reloc_(false)
{ }
virtual
*************** class Output_data
*** 233,247 ****
is_layout_complete()
{ return Output_data::allocated_sizes_are_fixed; }
! // Count the number of dynamic relocations applied to this section.
void
add_dynamic_reloc()
! { ++this->dynamic_reloc_count_; }
! // Return the number of dynamic relocations applied to this section.
! unsigned int
! dynamic_reloc_count() const
! { return this->dynamic_reloc_count_; }
// Whether the address is valid.
bool
--- 233,247 ----
is_layout_complete()
{ return Output_data::allocated_sizes_are_fixed; }
! // Note that a dynamic reloc has been applied to this data.
void
add_dynamic_reloc()
! { this->has_dynamic_reloc_ = true; }
! // Return whether a dynamic reloc has been applied.
! bool
! has_dynamic_reloc() const
! { return this->has_dynamic_reloc_; }
// Whether the address is valid.
bool
*************** class Output_data
*** 424,438 ****
// File offset of contents in output file.
off_t offset_;
// Whether address_ is valid.
! bool is_address_valid_;
// Whether data_size_ is valid.
! bool is_data_size_valid_;
// Whether offset_ is valid.
! bool is_offset_valid_;
// Whether data size is fixed.
! bool is_data_size_fixed_;
! // Count of dynamic relocations applied to this section.
! unsigned int dynamic_reloc_count_;
};
// Output the section headers.
--- 424,438 ----
// File offset of contents in output file.
off_t offset_;
// Whether address_ is valid.
! bool is_address_valid_ : 1;
// Whether data_size_ is valid.
! bool is_data_size_valid_ : 1;
// Whether offset_ is valid.
! bool is_offset_valid_ : 1;
// Whether data size is fixed.
! bool is_data_size_fixed_ : 1;
! // Whether any dynamic relocs have been applied to this section.
! bool has_dynamic_reloc_ : 1;
};
// Output the section headers.
*************** class Output_section_lookup_maps
*** 2432,2438 ****
std::pair<Merge_section_properties, Output_merge_base*> value(msp, pomb);
std::pair<Merge_sections_by_properties::iterator, bool> result =
this->merge_sections_by_properties_.insert(value);
! gold_assert(value.second);
}
// Add a mapping from a merged input section in OBJECT with index SHNDX
--- 2432,2438 ----
std::pair<Merge_section_properties, Output_merge_base*> value(msp, pomb);
std::pair<Merge_sections_by_properties::iterator, bool> result =
this->merge_sections_by_properties_.insert(value);
! gold_assert(result.second);
}
// Add a mapping from a merged input section in OBJECT with index SHNDX
*************** class Output_section_lookup_maps
*** 2445,2451 ****
std::pair<Const_section_id, Output_merge_base*> value(csid, pomb);
std::pair<Merge_sections_by_id::iterator, bool> result =
this->merge_sections_by_id_.insert(value);
! gold_assert(value.second);
}
// Find a relaxed input section of OBJECT with index SHNDX.
--- 2445,2451 ----
std::pair<Const_section_id, Output_merge_base*> value(csid, pomb);
std::pair<Merge_sections_by_id::iterator, bool> result =
this->merge_sections_by_id_.insert(value);
! gold_assert(result.second);
}
// Find a relaxed input section of OBJECT with index SHNDX.
*************** class Output_section_lookup_maps
*** 2469,2475 ****
value(csid, poris);
std::pair<Relaxed_input_sections_by_id::iterator, bool> result =
this->relaxed_input_sections_by_id_.insert(value);
! gold_assert(value.second);
}
private:
--- 2469,2475 ----
value(csid, poris);
std::pair<Relaxed_input_sections_by_id::iterator, bool> result =
this->relaxed_input_sections_by_id_.insert(value);
! gold_assert(result.second);
}
private:
*************** class Output_section : public Output_dat
*** 2761,2766 ****
--- 2761,2777 ----
set_must_sort_attached_input_sections()
{ this->must_sort_attached_input_sections_ = true; }
+ // Get the order in which this section appears in the PT_LOAD output
+ // segment.
+ Output_section_order
+ order() const
+ { return this->order_; }
+
+ // Set the order for this section.
+ void
+ set_order(Output_section_order order)
+ { this->order_ = order; }
+
// Return whether this section holds relro data--data which has
// dynamic relocations but which may be marked read-only after the
// dynamic relocations have been completed.
*************** class Output_section : public Output_dat
*** 2778,2823 ****
clear_is_relro()
{ this->is_relro_ = false; }
- // True if this section holds relro local data--relro data for which
- // the dynamic relocations are all RELATIVE relocations.
- bool
- is_relro_local() const
- { return this->is_relro_local_; }
-
- // Record that this section holds relro local data.
- void
- set_is_relro_local()
- { this->is_relro_local_ = true; }
-
- // True if this must be the last relro section.
- bool
- is_last_relro() const
- { return this->is_last_relro_; }
-
- // Record that this must be the last relro section.
- void
- set_is_last_relro()
- {
- gold_assert(this->is_relro_);
- this->is_last_relro_ = true;
- }
-
- // True if this must be the first section following the relro sections.
- bool
- is_first_non_relro() const
- {
- gold_assert(!this->is_relro_);
- return this->is_first_non_relro_;
- }
-
- // Record that this must be the first non-relro section.
- void
- set_is_first_non_relro()
- {
- gold_assert(!this->is_relro_);
- this->is_first_non_relro_ = true;
- }
-
// True if this is a small section: a section which holds small
// variables.
bool
--- 2789,2794 ----
*************** class Output_section : public Output_dat
*** 2845,2871 ****
is_large_data_section()
{ return this->is_large_section_ && this->type_ != elfcpp::SHT_NOBITS; }
- // True if this is the .interp section which goes into the PT_INTERP
- // segment.
- bool
- is_interp() const
- { return this->is_interp_; }
-
- // Record that this is the interp section.
- void
- set_is_interp()
- { this->is_interp_ = true; }
-
- // True if this is a section used by the dynamic linker.
- bool
- is_dynamic_linker_section() const
- { return this->is_dynamic_linker_section_; }
-
- // Record that this is a section used by the dynamic linker.
- void
- set_is_dynamic_linker_section()
- { this->is_dynamic_linker_section_ = true; }
-
// Return whether this section should be written after all the input
// sections are complete.
bool
--- 2816,2821 ----
*************** class Output_section : public Output_dat
*** 3468,3473 ****
--- 3418,3436 ----
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
*************** class Output_section : public Output_dat
*** 3694,3699 ****
--- 3657,3664 ----
const elfcpp::Elf_Word type_;
// The section flags.
elfcpp::Elf_Xword flags_;
+ // The order of this section in the output segment.
+ Output_section_order order_;
// The section index.
unsigned int out_shndx_;
// If there is a STT_SECTION for this output section in the normal
*************** class Output_section : public Output_dat
*** 3761,3781 ****
bool attached_input_sections_are_sorted_ : 1;
// True if this section holds relro data.
bool is_relro_ : 1;
- // True if this section holds relro local data.
- bool is_relro_local_ : 1;
- // True if this must be the last relro section.
- bool is_last_relro_ : 1;
- // True if this must be the first section after the relro sections.
- bool is_first_non_relro_ : 1;
// True if this is a small section.
bool is_small_section_ : 1;
// True if this is a large section.
bool is_large_section_ : 1;
- // True if this is the .interp section going into the PT_INTERP
- // segment.
- bool is_interp_ : 1;
- // True if this is section is read by the dynamic linker.
- bool is_dynamic_linker_section_ : 1;
// Whether code-fills are generated at write.
bool generate_code_fills_at_write_ : 1;
// Whether the entry size field should be zero.
--- 3726,3735 ----
*************** class Output_section : public Output_dat
*** 3784,3789 ****
--- 3738,3745 ----
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_;
*************** class Output_segment
*** 3859,3870 ****
uint64_t
maximum_alignment();
! // Add the Output_section OS to this segment. SEG_FLAGS is the
! // segment flags to use. DO_SORT is true if we should sort the
! // placement of the input section for more efficient generated code.
void
! add_output_section(Output_section* os, elfcpp::Elf_Word seg_flags,
! bool do_sort);
// Remove an Output_section from this segment. It is an error if it
// is not present.
--- 3815,3831 ----
uint64_t
maximum_alignment();
! // Add the Output_section OS to this PT_LOAD segment. SEG_FLAGS is
! // the segment flags to use.
! void
! add_output_section_to_load(Layout* layout, Output_section* os,
! elfcpp::Elf_Word seg_flags);
!
! // Add the Output_section OS to this non-PT_LOAD segment. SEG_FLAGS
! // is the segment flags to use.
void
! add_output_section_to_nonload(Output_section* os,
! elfcpp::Elf_Word seg_flags);
// Remove an Output_section from this segment. It is an error if it
// is not present.
*************** class Output_segment
*** 3879,3890 ****
// Return true if this segment has any sections which hold actual
// data, rather than being a BSS section.
bool
! has_any_data_sections() const
! { return !this->output_data_.empty(); }
! // Return the number of dynamic relocations applied to this segment.
! unsigned int
! dynamic_reloc_count() const;
// Return the address of the first section.
uint64_t
--- 3840,3850 ----
// Return true if this segment has any sections which hold actual
// data, rather than being a BSS section.
bool
! has_any_data_sections() const;
! // Whether this segment has a dynamic relocs.
! bool
! has_dynamic_reloc() const;
// Return the address of the first section.
uint64_t
*************** class Output_segment
*** 3977,3983 ****
print_sections_to_mapfile(Mapfile*) const;
private:
! typedef std::list<Output_data*> Output_data_list;
// Find the maximum alignment in an Output_data_list.
static uint64_t
--- 3937,3943 ----
print_sections_to_mapfile(Mapfile*) const;
private:
! typedef std::vector<Output_data*> Output_data_list;
// Find the maximum alignment in an Output_data_list.
static uint64_t
*************** class Output_segment
*** 3997,4005 ****
unsigned int
output_section_count_list(const Output_data_list*) const;
! // Return the number of dynamic relocs in an Output_data_list.
! unsigned int
! dynamic_reloc_count_list(const Output_data_list*) const;
// Find the section with the lowest load address in an
// Output_data_list.
--- 3957,3965 ----
unsigned int
output_section_count_list(const Output_data_list*) const;
! // Return whether an Output_data_list has a dynamic reloc.
! bool
! has_dynamic_reloc_list(const Output_data_list*) const;
// Find the section with the lowest load address in an
// Output_data_list.
*************** class Output_segment
*** 4008,4013 ****
--- 3968,3979 ----
Output_section** found,
uint64_t* found_lma) const;
+ // Find the first and last entries by address.
+ void
+ find_first_and_last_list(const Output_data_list* pdl,
+ const Output_data** pfirst,
+ const Output_data** plast) const;
+
// Write the section headers in the list into V.
template<int size, bool big_endian>
unsigned char*
*************** class Output_segment
*** 4022,4031 ****
// NOTE: We want to use the copy constructor. Currently, shallow copy
// works for us so we do not need to write our own copy constructor.
! // The list of output data with contents attached to this segment.
! Output_data_list output_data_;
! // The list of output data without contents attached to this segment.
! Output_data_list output_bss_;
// The segment virtual address.
uint64_t vaddr_;
// The segment physical address.
--- 3988,3995 ----
// NOTE: We want to use the copy constructor. Currently, shallow copy
// works for us so we do not need to write our own copy constructor.
! // The list of output data attached to this segment.
! Output_data_list output_lists_[ORDER_MAX];
// The segment virtual address.
uint64_t vaddr_;
// The segment physical address.
diff -rcp ../binutils-2.20.51.0.10.original/gold/plugin.cc gold/plugin.cc
*** ../binutils-2.20.51.0.10.original/gold/plugin.cc 2010-08-10 15:11:28.000000000 +0100
--- gold/plugin.cc 2010-08-10 15:14:03.000000000 +0100
*************** Sized_pluginobj<size, big_endian>::do_ad
*** 705,730 ****
template<int size, bool big_endian>
Archive::Should_include
Sized_pluginobj<size, big_endian>::do_should_include_member(
! Symbol_table* symtab, Read_symbols_data*, std::string* why)
{
char* tmpbuf = NULL;
size_t tmpbuflen = 0;
! for (int i = 0; i < this->nsyms_; ++i) {
! const struct ld_plugin_symbol& sym = this->syms_[i];
! const char* name = sym.name;
! Symbol* symbol;
! Archive::Should_include t = Archive::should_include_member(symtab, name,
! &symbol, why,
! &tmpbuf,
! &tmpbuflen);
if (t == Archive::SHOULD_INCLUDE_YES)
{
if (tmpbuf != NULL)
free(tmpbuf);
return t;
}
! }
if (tmpbuf != NULL)
free(tmpbuf);
return Archive::SHOULD_INCLUDE_UNKNOWN;
--- 705,736 ----
template<int size, bool big_endian>
Archive::Should_include
Sized_pluginobj<size, big_endian>::do_should_include_member(
! Symbol_table* symtab,
! Layout* layout,
! Read_symbols_data*,
! std::string* why)
{
char* tmpbuf = NULL;
size_t tmpbuflen = 0;
! for (int i = 0; i < this->nsyms_; ++i)
! {
! const struct ld_plugin_symbol& sym = this->syms_[i];
! const char* name = sym.name;
! Symbol* symbol;
! Archive::Should_include t = Archive::should_include_member(symtab,
! layout,
! name,
! &symbol, why,
! &tmpbuf,
! &tmpbuflen);
if (t == Archive::SHOULD_INCLUDE_YES)
{
if (tmpbuf != NULL)
free(tmpbuf);
return t;
}
! }
if (tmpbuf != NULL)
free(tmpbuf);
return Archive::SHOULD_INCLUDE_UNKNOWN;
*************** Sized_pluginobj<size, big_endian>::do_ge
*** 862,868 ****
}
// Class Plugin_finish. This task runs after all replacement files have
! // been added. It calls each plugin's cleanup handler.
class Plugin_finish : public Task
{
--- 868,877 ----
}
// Class Plugin_finish. This task runs after all replacement files have
! // been added. For now, it's a placeholder for a possible plugin API
! // to allow the plugin to release most of its resources. The cleanup
! // handlers must be called later, because they can remove the temporary
! // object files that are needed until the end of the link.
class Plugin_finish : public Task
{
*************** class Plugin_finish : public Task
*** 892,900 ****
void
run(Workqueue*)
{
! Plugin_manager* plugins = parameters->options().plugins();
! gold_assert(plugins != NULL);
! plugins->cleanup();
}
std::string
--- 901,907 ----
void
run(Workqueue*)
{
! // We could call early cleanup handlers here.
}
std::string
diff -rcp ../binutils-2.20.51.0.10.original/gold/plugin.h gold/plugin.h
*** ../binutils-2.20.51.0.10.original/gold/plugin.h 2010-08-10 15:12:04.000000000 +0100
--- gold/plugin.h 2010-08-10 15:14:03.000000000 +0100
*************** class Sized_pluginobj : public Pluginobj
*** 376,382 ****
do_add_symbols(Symbol_table*, Read_symbols_data*, Layout*);
Archive::Should_include
! do_should_include_member(Symbol_table* symtab, Read_symbols_data*,
std::string* why);
// Get the size of a section.
--- 376,382 ----
do_add_symbols(Symbol_table*, Read_symbols_data*, Layout*);
Archive::Should_include
! do_should_include_member(Symbol_table* symtab, Layout*, Read_symbols_data*,
std::string* why);
// Get the size of a section.
diff -rcp ../binutils-2.20.51.0.10.original/gold/powerpc.cc gold/powerpc.cc
*** ../binutils-2.20.51.0.10.original/gold/powerpc.cc 2010-08-10 15:11:40.000000000 +0100
--- gold/powerpc.cc 2010-08-10 15:14:03.000000000 +0100
*************** Target_powerpc<size, big_endian>::got_se
*** 738,744 ****
layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE,
! this->got_, false, false, false, false);
// Create the GOT2 or TOC in the .got section.
if (size == 32)
--- 738,744 ----
layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
elfcpp::SHF_ALLOC | elfcpp::SHF_WRITE,
! this->got_, ORDER_DATA, false);
// Create the GOT2 or TOC in the .got section.
if (size == 32)
*************** Target_powerpc<size, big_endian>::got_se
*** 747,754 ****
layout->add_output_section_data(".got2", elfcpp::SHT_PROGBITS,
elfcpp::SHF_ALLOC
| elfcpp::SHF_WRITE,
! this->got2_, false, false, false,
! false);
}
else
{
--- 747,753 ----
layout->add_output_section_data(".got2", elfcpp::SHT_PROGBITS,
elfcpp::SHF_ALLOC
| elfcpp::SHF_WRITE,
! this->got2_, ORDER_DATA, false);
}
else
{
*************** Target_powerpc<size, big_endian>::got_se
*** 756,763 ****
layout->add_output_section_data(".toc", elfcpp::SHT_PROGBITS,
elfcpp::SHF_ALLOC
| elfcpp::SHF_WRITE,
! this->toc_, false, false, false,
! false);
}
// Define _GLOBAL_OFFSET_TABLE_ at the start of the .got section.
--- 755,761 ----
layout->add_output_section_data(".toc", elfcpp::SHT_PROGBITS,
elfcpp::SHF_ALLOC
| elfcpp::SHF_WRITE,
! this->toc_, ORDER_DATA, false);
}
// Define _GLOBAL_OFFSET_TABLE_ at the start of the .got section.
*************** Target_powerpc<size, big_endian>::rela_d
*** 784,791 ****
gold_assert(layout != NULL);
this->rela_dyn_ = new Reloc_section(parameters->options().combreloc());
layout->add_output_section_data(".rela.dyn", elfcpp::SHT_RELA,
! elfcpp::SHF_ALLOC, this->rela_dyn_, true,
! false, false, false);
}
return this->rela_dyn_;
}
--- 782,789 ----
gold_assert(layout != NULL);
this->rela_dyn_ = new Reloc_section(parameters->options().combreloc());
layout->add_output_section_data(".rela.dyn", elfcpp::SHT_RELA,
! elfcpp::SHF_ALLOC, this->rela_dyn_,
! ORDER_DYNAMIC_RELOCS, false);
}
return this->rela_dyn_;
}
*************** Output_data_plt_powerpc<size, big_endian
*** 845,852 ****
{
this->rel_ = new Reloc_section(false);
layout->add_output_section_data(".rela.plt", elfcpp::SHT_RELA,
! elfcpp::SHF_ALLOC, this->rel_, true, false,
! false, false);
}
template<int size, bool big_endian>
--- 843,850 ----
{
this->rel_ = new Reloc_section(false);
layout->add_output_section_data(".rela.plt", elfcpp::SHT_RELA,
! elfcpp::SHF_ALLOC, this->rel_,
! ORDER_DYNAMIC_PLT_RELOCS, false);
}
template<int size, bool big_endian>
*************** Target_powerpc<size, big_endian>::make_p
*** 980,986 ****
(elfcpp::SHF_ALLOC
| elfcpp::SHF_EXECINSTR
| elfcpp::SHF_WRITE),
! this->plt_, false, false, false, false);
// Define _PROCEDURE_LINKAGE_TABLE_ at the start of the .plt section.
symtab->define_in_output_data("_PROCEDURE_LINKAGE_TABLE_", NULL,
--- 978,984 ----
(elfcpp::SHF_ALLOC
| elfcpp::SHF_EXECINSTR
| elfcpp::SHF_WRITE),
! this->plt_, ORDER_PLT, false);
// Define _PROCEDURE_LINKAGE_TABLE_ at the start of the .plt section.
symtab->define_in_output_data("_PROCEDURE_LINKAGE_TABLE_", NULL,
*************** Target_powerpc<size, big_endian>::gc_pro
*** 1493,1499 ****
typedef Target_powerpc<size, big_endian> Powerpc;
typedef typename Target_powerpc<size, big_endian>::Scan Scan;
! gold::gc_process_relocs<size, big_endian, Powerpc, elfcpp::SHT_RELA, Scan>(
symtab,
layout,
this,
--- 1491,1498 ----
typedef Target_powerpc<size, big_endian> Powerpc;
typedef typename Target_powerpc<size, big_endian>::Scan Scan;
! gold::gc_process_relocs<size, big_endian, Powerpc, elfcpp::SHT_RELA, Scan,
! typename Target_powerpc::Relocatable_size_for_reloc>(
symtab,
layout,
this,
*************** Target_powerpc<size, big_endian>::scan_r
*** 1543,1550 ****
Output_section* os = layout->add_output_section_data(".sdata", 0,
elfcpp::SHF_ALLOC
| elfcpp::SHF_WRITE,
! sdata, false,
! false, false, false);
symtab->define_in_output_data("_SDA_BASE_", NULL,
Symbol_table::PREDEFINED,
os,
--- 1542,1550 ----
Output_section* os = layout->add_output_section_data(".sdata", 0,
elfcpp::SHF_ALLOC
| elfcpp::SHF_WRITE,
! sdata,
! ORDER_SMALL_DATA,
! false);
symtab->define_in_output_data("_SDA_BASE_", NULL,
Symbol_table::PREDEFINED,
os,
*************** Target_powerpc<size, big_endian>::Reloca
*** 1636,1642 ****
// Get the GOT offset if needed. Unlike i386 and x86_64, our GOT
// pointer points to the beginning, not the end, of the table.
// So we just use the plain offset.
- bool have_got_offset = false;
unsigned int got_offset = 0;
unsigned int got2_offset = 0;
switch (r_type)
--- 1636,1641 ----
*************** Target_powerpc<size, big_endian>::Reloca
*** 1668,1674 ****
gold_assert(object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD));
got_offset = object->local_got_offset(r_sym, GOT_TYPE_STANDARD);
}
- have_got_offset = true;
break;
// R_PPC_PLTREL24 is rather special. If non-zero,
--- 1667,1672 ----
*************** Target_powerpc<size, big_endian>::Reloca
*** 1681,1687 ****
got2_offset = got2->offset();
addend += got2_offset;
}
- have_got_offset = true;
break;
default:
--- 1679,1684 ----
diff -rcp ../binutils-2.20.51.0.10.original/gold/reloc.cc gold/reloc.cc
*** ../binutils-2.20.51.0.10.original/gold/reloc.cc 2010-08-10 15:11:28.000000000 +0100
--- gold/reloc.cc 2010-08-10 15:14:03.000000000 +0100
***************
*** 32,37 ****
--- 32,38 ----
#include "target-reloc.h"
#include "reloc.h"
#include "icf.h"
+ #include "compressed_output.h"
namespace gold
{
*************** Sized_relobj<size, big_endian>::write_se
*** 732,741 ****
--- 733,749 ----
off_t view_start;
section_size_type view_size;
+ bool must_decompress = false;
if (output_offset != invalid_address)
{
view_start = output_section_offset + output_offset;
view_size = convert_to_section_size_type(shdr.get_sh_size());
+ section_size_type uncompressed_size;
+ if (this->section_is_compressed(i, &uncompressed_size))
+ {
+ view_size = uncompressed_size;
+ must_decompress = true;
+ }
}
else
{
*************** Sized_relobj<size, big_endian>::write_se
*** 754,760 ****
{
unsigned char* buffer = os->postprocessing_buffer();
view = buffer + view_start;
! if (output_offset != invalid_address)
{
off_t sh_offset = shdr.get_sh_offset();
if (!rm.empty() && rm.back().file_offset > sh_offset)
--- 762,768 ----
{
unsigned char* buffer = os->postprocessing_buffer();
view = buffer + view_start;
! if (output_offset != invalid_address && !must_decompress)
{
off_t sh_offset = shdr.get_sh_offset();
if (!rm.empty() && rm.back().file_offset > sh_offset)
*************** Sized_relobj<size, big_endian>::write_se
*** 770,783 ****
else
{
view = of->get_output_view(view_start, view_size);
! off_t sh_offset = shdr.get_sh_offset();
! if (!rm.empty() && rm.back().file_offset > sh_offset)
! is_sorted = false;
! rm.push_back(File_read::Read_multiple_entry(sh_offset,
! view_size, view));
}
}
pvs->view = view;
pvs->address = os->address();
if (output_offset != invalid_address)
--- 778,804 ----
else
{
view = of->get_output_view(view_start, view_size);
! if (!must_decompress)
! {
! off_t sh_offset = shdr.get_sh_offset();
! if (!rm.empty() && rm.back().file_offset > sh_offset)
! is_sorted = false;
! rm.push_back(File_read::Read_multiple_entry(sh_offset,
! view_size, view));
! }
}
}
+ if (must_decompress)
+ {
+ // Read and decompress the section.
+ section_size_type len;
+ const unsigned char* p = this->section_contents(i, &len, false);
+ if (!decompress_input_section(p, len, view, view_size))
+ this->error(_("could not decompress section %s"),
+ this->section_name(i).c_str());
+ }
+
pvs->view = view;
pvs->address = os->address();
if (output_offset != invalid_address)
diff -rcp ../binutils-2.20.51.0.10.original/gold/resolve.cc gold/resolve.cc
*** ../binutils-2.20.51.0.10.original/gold/resolve.cc 2010-08-10 15:11:43.000000000 +0100
--- gold/resolve.cc 2010-08-10 15:14:03.000000000 +0100
*************** Symbol_table::resolve(Sized_symbol<size>
*** 335,352 ****
sym.get_st_type());
bool adjust_common_sizes;
typename Sized_symbol<size>::Size_type tosize = to->symsize();
if (Symbol_table::should_override(to, frombits, OBJECT, object,
! &adjust_common_sizes))
{
this->override(to, sym, st_shndx, is_ordinary, object, version);
if (adjust_common_sizes && tosize > to->symsize())
to->set_symsize(tosize);
}
else
{
if (adjust_common_sizes && sym.get_st_size() > tosize)
to->set_symsize(sym.get_st_size());
// The ELF ABI says that even for a reference to a symbol we
// merge the visibility.
to->override_visibility(sym.get_st_visibility());
--- 335,367 ----
sym.get_st_type());
bool adjust_common_sizes;
+ bool adjust_dyndef;
typename Sized_symbol<size>::Size_type tosize = to->symsize();
if (Symbol_table::should_override(to, frombits, OBJECT, object,
! &adjust_common_sizes,
! &adjust_dyndef))
{
+ elfcpp::STB tobinding = to->binding();
this->override(to, sym, st_shndx, is_ordinary, object, version);
if (adjust_common_sizes && tosize > to->symsize())
to->set_symsize(tosize);
+ if (adjust_dyndef)
+ {
+ // We are overriding an UNDEF or WEAK UNDEF with a DYN DEF.
+ // Remember which kind of UNDEF it was for future reference.
+ to->set_undef_binding(tobinding);
+ }
}
else
{
if (adjust_common_sizes && sym.get_st_size() > tosize)
to->set_symsize(sym.get_st_size());
+ if (adjust_dyndef)
+ {
+ // We are keeping a DYN DEF after seeing an UNDEF or WEAK UNDEF.
+ // Remember which kind of UNDEF it was.
+ to->set_undef_binding(sym.get_st_bind());
+ }
// The ELF ABI says that even for a reference to a symbol we
// merge the visibility.
to->override_visibility(sym.get_st_visibility());
*************** Symbol_table::resolve(Sized_symbol<size>
*** 381,389 ****
bool
Symbol_table::should_override(const Symbol* to, unsigned int frombits,
Defined defined, Object* object,
! bool* adjust_common_sizes)
{
*adjust_common_sizes = false;
unsigned int tobits;
if (to->source() == Symbol::IS_UNDEFINED)
--- 396,406 ----
bool
Symbol_table::should_override(const Symbol* to, unsigned int frombits,
Defined defined, Object* object,
! bool* adjust_common_sizes,
! bool* adjust_dyndef)
{
*adjust_common_sizes = false;
+ *adjust_dyndef = false;
unsigned int tobits;
if (to->source() == Symbol::IS_UNDEFINED)
*************** Symbol_table::should_override(const Symb
*** 531,542 ****
return false;
case UNDEF * 16 + DYN_DEF:
- case WEAK_UNDEF * 16 + DYN_DEF:
case DYN_UNDEF * 16 + DYN_DEF:
case DYN_WEAK_UNDEF * 16 + DYN_DEF:
// Use a dynamic definition if we have a reference.
return true;
case COMMON * 16 + DYN_DEF:
case WEAK_COMMON * 16 + DYN_DEF:
case DYN_COMMON * 16 + DYN_DEF:
--- 548,564 ----
return false;
case UNDEF * 16 + DYN_DEF:
case DYN_UNDEF * 16 + DYN_DEF:
case DYN_WEAK_UNDEF * 16 + DYN_DEF:
// Use a dynamic definition if we have a reference.
return true;
+ case WEAK_UNDEF * 16 + DYN_DEF:
+ // When overriding a weak undef by a dynamic definition,
+ // we need to remember that the original undef was weak.
+ *adjust_dyndef = true;
+ return true;
+
case COMMON * 16 + DYN_DEF:
case WEAK_COMMON * 16 + DYN_DEF:
case DYN_COMMON * 16 + DYN_DEF:
*************** Symbol_table::should_override(const Symb
*** 554,565 ****
return false;
case UNDEF * 16 + DYN_WEAK_DEF:
- case WEAK_UNDEF * 16 + DYN_WEAK_DEF:
case DYN_UNDEF * 16 + DYN_WEAK_DEF:
case DYN_WEAK_UNDEF * 16 + DYN_WEAK_DEF:
// Use a weak dynamic definition if we have a reference.
return true;
case COMMON * 16 + DYN_WEAK_DEF:
case WEAK_COMMON * 16 + DYN_WEAK_DEF:
case DYN_COMMON * 16 + DYN_WEAK_DEF:
--- 576,592 ----
return false;
case UNDEF * 16 + DYN_WEAK_DEF:
case DYN_UNDEF * 16 + DYN_WEAK_DEF:
case DYN_WEAK_UNDEF * 16 + DYN_WEAK_DEF:
// Use a weak dynamic definition if we have a reference.
return true;
+ case WEAK_UNDEF * 16 + DYN_WEAK_DEF:
+ // When overriding a weak undef by a dynamic definition,
+ // we need to remember that the original undef was weak.
+ *adjust_dyndef = true;
+ return true;
+
case COMMON * 16 + DYN_WEAK_DEF:
case WEAK_COMMON * 16 + DYN_WEAK_DEF:
case DYN_COMMON * 16 + DYN_WEAK_DEF:
*************** Symbol_table::should_override(const Symb
*** 570,581 ****
case DEF * 16 + UNDEF:
case WEAK_DEF * 16 + UNDEF:
- case DYN_DEF * 16 + UNDEF:
- case DYN_WEAK_DEF * 16 + UNDEF:
case UNDEF * 16 + UNDEF:
// A new undefined reference tells us nothing.
return false;
case WEAK_UNDEF * 16 + UNDEF:
case DYN_UNDEF * 16 + UNDEF:
case DYN_WEAK_UNDEF * 16 + UNDEF:
--- 597,612 ----
case DEF * 16 + UNDEF:
case WEAK_DEF * 16 + UNDEF:
case UNDEF * 16 + UNDEF:
// A new undefined reference tells us nothing.
return false;
+ case DYN_DEF * 16 + UNDEF:
+ case DYN_WEAK_DEF * 16 + UNDEF:
+ // For a dynamic def, we need to remember which kind of undef we see.
+ *adjust_dyndef = true;
+ return false;
+
case WEAK_UNDEF * 16 + UNDEF:
case DYN_UNDEF * 16 + UNDEF:
case DYN_WEAK_UNDEF * 16 + UNDEF:
*************** Symbol_table::should_override(const Symb
*** 591,598 ****
case DEF * 16 + WEAK_UNDEF:
case WEAK_DEF * 16 + WEAK_UNDEF:
- case DYN_DEF * 16 + WEAK_UNDEF:
- case DYN_WEAK_DEF * 16 + WEAK_UNDEF:
case UNDEF * 16 + WEAK_UNDEF:
case WEAK_UNDEF * 16 + WEAK_UNDEF:
case DYN_UNDEF * 16 + WEAK_UNDEF:
--- 622,627 ----
*************** Symbol_table::should_override(const Symb
*** 604,609 ****
--- 633,644 ----
// A new weak undefined reference tells us nothing.
return false;
+ case DYN_DEF * 16 + WEAK_UNDEF:
+ case DYN_WEAK_DEF * 16 + WEAK_UNDEF:
+ // For a dynamic def, we need to remember which kind of undef we see.
+ *adjust_dyndef = true;
+ return false;
+
case DEF * 16 + DYN_UNDEF:
case WEAK_DEF * 16 + DYN_UNDEF:
case DYN_DEF * 16 + DYN_UNDEF:
*************** bool
*** 811,820 ****
Symbol_table::should_override_with_special(const Symbol* to, Defined defined)
{
bool adjust_common_sizes;
unsigned int frombits = global_flag | regular_flag | def_flag;
bool ret = Symbol_table::should_override(to, frombits, defined, NULL,
! &adjust_common_sizes);
! gold_assert(!adjust_common_sizes);
return ret;
}
--- 846,857 ----
Symbol_table::should_override_with_special(const Symbol* to, Defined defined)
{
bool adjust_common_sizes;
+ bool adjust_dyn_def;
unsigned int frombits = global_flag | regular_flag | def_flag;
bool ret = Symbol_table::should_override(to, frombits, defined, NULL,
! &adjust_common_sizes,
! &adjust_dyn_def);
! gold_assert(!adjust_common_sizes && !adjust_dyn_def);
return ret;
}
diff -rcp ../binutils-2.20.51.0.10.original/gold/script.cc gold/script.cc
*** ../binutils-2.20.51.0.10.original/gold/script.cc 2010-08-10 15:11:40.000000000 +0100
--- gold/script.cc 2010-08-10 15:14:03.000000000 +0100
*************** Script_assertion::print(FILE* f) const
*** 1045,1052 ****
// Class Script_options.
Script_options::Script_options()
! : entry_(), symbol_assignments_(), version_script_info_(),
! script_sections_()
{
}
--- 1045,1052 ----
// Class Script_options.
Script_options::Script_options()
! : entry_(), symbol_assignments_(), symbol_definitions_(),
! symbol_references_(), version_script_info_(), script_sections_()
{
}
*************** Script_options::add_symbol_assignment(co
*** 1071,1076 ****
--- 1071,1083 ----
value, provide, hidden);
this->symbol_assignments_.push_back(p);
}
+
+ if (!provide)
+ {
+ std::string n(name, length);
+ this->symbol_definitions_.insert(n);
+ this->symbol_references_.erase(n);
+ }
}
else
{
*************** Script_options::add_symbol_assignment(co
*** 1084,1089 ****
--- 1091,1109 ----
}
}
+ // Add a reference to a symbol.
+
+ void
+ Script_options::add_symbol_reference(const char* name, size_t length)
+ {
+ if (length != 1 || name[0] != '.')
+ {
+ std::string n(name, length);
+ if (this->symbol_definitions_.find(n) == this->symbol_definitions_.end())
+ this->symbol_references_.insert(n);
+ }
+ }
+
// Add an assertion.
void
*************** script_set_common_allocation(void* closu
*** 2679,2684 ****
--- 2699,2715 ----
script_parse_option(closurev, arg, strlen(arg));
}
+ // Called by the bison parser to refer to a symbol.
+
+ extern "C" Expression*
+ script_symbol(void *closurev, const char* name, size_t length)
+ {
+ Parser_closure* closure = static_cast<Parser_closure*>(closurev);
+ if (length != 1 || name[0] != '.')
+ closure->script_options()->add_symbol_reference(name, length);
+ return script_exp_string(name, length);
+ }
+
// Called by the bison parser to define a symbol.
extern "C" void
diff -rcp ../binutils-2.20.51.0.10.original/gold/script-c.h gold/script-c.h
*** ../binutils-2.20.51.0.10.original/gold/script-c.h 2010-08-10 15:12:04.000000000 +0100
--- gold/script-c.h 2010-08-10 15:14:03.000000000 +0100
*************** script_push_lex_into_version_mode(void*
*** 303,308 ****
--- 303,316 ----
extern void
script_pop_lex_mode(void* closure);
+ /* Called by the bison parser to get the value of a symbol. This is
+ called for a reference to a symbol, but is not called for something
+ like "sym += 10". Uses of the special symbol "." can just call
+ script_exp_string. */
+
+ extern Expression_ptr
+ script_symbol(void* closure, const char*, size_t);
+
/* Called by the bison parser to set a symbol to a value. PROVIDE is
non-zero if the symbol should be provided--only defined if there is
an undefined reference. HIDDEN is non-zero if the symbol should be
diff -rcp ../binutils-2.20.51.0.10.original/gold/script.h gold/script.h
*** ../binutils-2.20.51.0.10.original/gold/script.h 2010-08-10 15:12:03.000000000 +0100
--- gold/script.h 2010-08-10 15:14:03.000000000 +0100
*************** class Script_options
*** 423,428 ****
--- 423,432 ----
add_symbol_assignment(const char* name, size_t length, bool is_defsym,
Expression* value, bool provide, bool hidden);
+ // Add a reference to a symbol.
+ void
+ add_symbol_reference(const char* name, size_t length);
+
// Add an assertion.
void
add_assertion(Expression* check, const char* message, size_t messagelen);
*************** class Script_options
*** 439,444 ****
--- 443,474 ----
void
add_symbols_to_table(Symbol_table*);
+ // Used to iterate over symbols which are referenced in expressions
+ // but not defined.
+ typedef Unordered_set<std::string>::const_iterator referenced_const_iterator;
+
+ referenced_const_iterator
+ referenced_begin() const
+ { return this->symbol_references_.begin(); }
+
+ referenced_const_iterator
+ referenced_end() const
+ { return this->symbol_references_.end(); }
+
+ // Return whether a symbol is referenced but not defined.
+ bool
+ is_referenced(const std::string& name) const
+ {
+ return (this->symbol_references_.find(name)
+ != this->symbol_references_.end());
+ }
+
+ // Return whether there are any symbols which were referenced but
+ // not defined.
+ bool
+ any_unreferenced() const
+ { return !this->symbol_references_.empty(); }
+
// Finalize the symbol values. Also check assertions.
void
finalize_symbols(Symbol_table*, const Layout*);
*************** class Script_options
*** 497,502 ****
--- 527,536 ----
std::string entry_;
// Symbols to set.
Symbol_assignments symbol_assignments_;
+ // Symbols defined in an expression, for faster lookup.
+ Unordered_set<std::string> symbol_definitions_;
+ // Symbols referenced in an expression.
+ Unordered_set<std::string> symbol_references_;
// Assertions to check.
Assertions assertions_;
// Version information parsed from a version script.
diff -rcp ../binutils-2.20.51.0.10.original/gold/script-sections.cc gold/script-sections.cc
*** ../binutils-2.20.51.0.10.original/gold/script-sections.cc 2010-08-10 15:12:03.000000000 +0100
--- gold/script-sections.cc 2010-08-10 15:14:03.000000000 +0100
*************** Script_sections::create_segments(Layout*
*** 3212,3218 ****
is_current_seg_readonly = true;
}
! current_seg->add_output_section(*p, seg_flags, false);
if (((*p)->flags() & elfcpp::SHF_WRITE) != 0)
is_current_seg_readonly = false;
--- 3212,3218 ----
is_current_seg_readonly = true;
}
! current_seg->add_output_section_to_load(layout, *p, seg_flags);
if (((*p)->flags() & elfcpp::SHF_WRITE) != 0)
is_current_seg_readonly = false;
*************** Script_sections::create_note_and_tls_seg
*** 3291,3297 ****
Layout::section_flags_to_segment((*p)->flags());
Output_segment* oseg = layout->make_output_segment(elfcpp::PT_NOTE,
seg_flags);
! oseg->add_output_section(*p, seg_flags, false);
// Incorporate any subsequent SHT_NOTE sections, in the
// hopes that the script is sensible.
--- 3291,3297 ----
Layout::section_flags_to_segment((*p)->flags());
Output_segment* oseg = layout->make_output_segment(elfcpp::PT_NOTE,
seg_flags);
! oseg->add_output_section_to_nonload(*p, seg_flags);
// Incorporate any subsequent SHT_NOTE sections, in the
// hopes that the script is sensible.
*************** Script_sections::create_note_and_tls_seg
*** 3300,3306 ****
&& (*pnext)->type() == elfcpp::SHT_NOTE)
{
seg_flags = Layout::section_flags_to_segment((*pnext)->flags());
! oseg->add_output_section(*pnext, seg_flags, false);
p = pnext;
++pnext;
}
--- 3300,3306 ----
&& (*pnext)->type() == elfcpp::SHT_NOTE)
{
seg_flags = Layout::section_flags_to_segment((*pnext)->flags());
! oseg->add_output_section_to_nonload(*pnext, seg_flags);
p = pnext;
++pnext;
}
*************** Script_sections::create_note_and_tls_seg
*** 3315,3328 ****
Layout::section_flags_to_segment((*p)->flags());
Output_segment* oseg = layout->make_output_segment(elfcpp::PT_TLS,
seg_flags);
! oseg->add_output_section(*p, seg_flags, false);
Layout::Section_list::const_iterator pnext = p + 1;
while (pnext != sections->end()
&& ((*pnext)->flags() & elfcpp::SHF_TLS) != 0)
{
seg_flags = Layout::section_flags_to_segment((*pnext)->flags());
! oseg->add_output_section(*pnext, seg_flags, false);
p = pnext;
++pnext;
}
--- 3315,3328 ----
Layout::section_flags_to_segment((*p)->flags());
Output_segment* oseg = layout->make_output_segment(elfcpp::PT_TLS,
seg_flags);
! oseg->add_output_section_to_nonload(*p, seg_flags);
Layout::Section_list::const_iterator pnext = p + 1;
while (pnext != sections->end()
&& ((*pnext)->flags() & elfcpp::SHF_TLS) != 0)
{
seg_flags = Layout::section_flags_to_segment((*pnext)->flags());
! oseg->add_output_section_to_nonload(*pnext, seg_flags);
p = pnext;
++pnext;
}
*************** Script_sections::attach_sections_using_p
*** 3477,3486 ****
elfcpp::Elf_Word seg_flags =
Layout::section_flags_to_segment(os->flags());
- r->second->add_output_section(os, seg_flags, false);
! if (r->second->type() == elfcpp::PT_LOAD)
{
if (in_load_segment)
gold_error(_("section in two PT_LOAD segments"));
in_load_segment = true;
--- 3477,3488 ----
elfcpp::Elf_Word seg_flags =
Layout::section_flags_to_segment(os->flags());
! if (r->second->type() != elfcpp::PT_LOAD)
! r->second->add_output_section_to_nonload(os, seg_flags);
! else
{
+ r->second->add_output_section_to_load(layout, os, seg_flags);
if (in_load_segment)
gold_error(_("section in two PT_LOAD segments"));
in_load_segment = true;
diff -rcp ../binutils-2.20.51.0.10.original/gold/sparc.cc gold/sparc.cc
*** ../binutils-2.20.51.0.10.original/gold/sparc.cc 2010-08-10 15:11:28.000000000 +0100
--- gold/sparc.cc 2010-08-10 15:14:03.000000000 +0100
*************** Target_sparc<size, big_endian>::got_sect
*** 1045,1056 ****
this->got_ = new Output_data_got<size, big_endian>();
! Output_section* os;
! os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
! (elfcpp::SHF_ALLOC
! | elfcpp::SHF_WRITE),
! this->got_, false, true, false,
! false);
// Define _GLOBAL_OFFSET_TABLE_ at the start of the .got section.
symtab->define_in_output_data("_GLOBAL_OFFSET_TABLE_", NULL,
--- 1045,1054 ----
this->got_ = new Output_data_got<size, big_endian>();
! layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
! (elfcpp::SHF_ALLOC
! | elfcpp::SHF_WRITE),
! this->got_, ORDER_RELRO, true);
// Define _GLOBAL_OFFSET_TABLE_ at the start of the .got section.
symtab->define_in_output_data("_GLOBAL_OFFSET_TABLE_", NULL,
*************** Target_sparc<size, big_endian>::rela_dyn
*** 1076,1083 ****
gold_assert(layout != NULL);
this->rela_dyn_ = new Reloc_section(parameters->options().combreloc());
layout->add_output_section_data(".rela.dyn", elfcpp::SHT_RELA,
! elfcpp::SHF_ALLOC, this->rela_dyn_, true,
! false, false, false);
}
return this->rela_dyn_;
}
--- 1074,1081 ----
gold_assert(layout != NULL);
this->rela_dyn_ = new Reloc_section(parameters->options().combreloc());
layout->add_output_section_data(".rela.dyn", elfcpp::SHT_RELA,
! elfcpp::SHF_ALLOC, this->rela_dyn_,
! ORDER_DYNAMIC_RELOCS, false);
}
return this->rela_dyn_;
}
*************** Output_data_plt_sparc<size, big_endian>:
*** 1179,1186 ****
{
this->rel_ = new Reloc_section(false);
layout->add_output_section_data(".rela.plt", elfcpp::SHT_RELA,
! elfcpp::SHF_ALLOC, this->rel_, true,
! false, false, false);
}
template<int size, bool big_endian>
--- 1177,1184 ----
{
this->rel_ = new Reloc_section(false);
layout->add_output_section_data(".rela.plt", elfcpp::SHT_RELA,
! elfcpp::SHF_ALLOC, this->rel_,
! ORDER_DYNAMIC_PLT_RELOCS, false);
}
template<int size, bool big_endian>
*************** Target_sparc<size, big_endian>::make_plt
*** 1402,1408 ****
(elfcpp::SHF_ALLOC
| elfcpp::SHF_EXECINSTR
| elfcpp::SHF_WRITE),
! this->plt_, false, false, false, false);
// Define _PROCEDURE_LINKAGE_TABLE_ at the start of the .plt section.
symtab->define_in_output_data("_PROCEDURE_LINKAGE_TABLE_", NULL,
--- 1400,1406 ----
(elfcpp::SHF_ALLOC
| elfcpp::SHF_EXECINSTR
| elfcpp::SHF_WRITE),
! this->plt_, ORDER_PLT, false);
// Define _PROCEDURE_LINKAGE_TABLE_ at the start of the .plt section.
symtab->define_in_output_data("_PROCEDURE_LINKAGE_TABLE_", NULL,
*************** Target_sparc<size, big_endian>::gc_proce
*** 2332,2338 ****
typedef Target_sparc<size, big_endian> Sparc;
typedef typename Target_sparc<size, big_endian>::Scan Scan;
! gold::gc_process_relocs<size, big_endian, Sparc, elfcpp::SHT_RELA, Scan>(
symtab,
layout,
this,
--- 2330,2337 ----
typedef Target_sparc<size, big_endian> Sparc;
typedef typename Target_sparc<size, big_endian>::Scan Scan;
! gold::gc_process_relocs<size, big_endian, Sparc, elfcpp::SHT_RELA, Scan,
! typename Target_sparc::Relocatable_size_for_reloc>(
symtab,
layout,
this,
*************** Target_sparc<size, big_endian>::Relocate
*** 2474,2480 ****
// Get the GOT offset if needed. Unlike i386 and x86_64, our GOT
// pointer points to the beginning, not the end, of the table.
// So we just use the plain offset.
- bool have_got_offset = false;
unsigned int got_offset = 0;
switch (r_type)
{
--- 2473,2478 ----
*************** Target_sparc<size, big_endian>::Relocate
*** 2495,2501 ****
gold_assert(object->local_has_got_offset(r_sym, GOT_TYPE_STANDARD));
got_offset = object->local_got_offset(r_sym, GOT_TYPE_STANDARD);
}
- have_got_offset = true;
break;
default:
--- 2493,2498 ----
diff -rcp ../binutils-2.20.51.0.10.original/gold/stringpool.cc gold/stringpool.cc
*** ../binutils-2.20.51.0.10.original/gold/stringpool.cc 2010-08-10 15:11:43.000000000 +0100
--- gold/stringpool.cc 2010-08-10 15:14:03.000000000 +0100
*************** Stringpool_template<Stringpool_char>::re
*** 87,114 ****
this->string_set_.swap(new_string_set);
}
- // Return the length of a string of arbitrary character type.
-
- template<typename Stringpool_char>
- size_t
- Stringpool_template<Stringpool_char>::string_length(const Stringpool_char* p)
- {
- size_t len = 0;
- for (; *p != 0; ++p)
- ++len;
- return len;
- }
-
- // Specialize string_length for char. Maybe we could just use
- // std::char_traits<>::length?
-
- template<>
- inline size_t
- Stringpool_template<char>::string_length(const char* p)
- {
- return strlen(p);
- }
-
// Compare two strings of arbitrary character type for equality.
template<typename Stringpool_char>
--- 87,92 ----
diff -rcp ../binutils-2.20.51.0.10.original/gold/stringpool.h gold/stringpool.h
*** ../binutils-2.20.51.0.10.original/gold/stringpool.h 2010-08-10 15:11:43.000000000 +0100
--- gold/stringpool.h 2010-08-10 15:14:03.000000000 +0100
*************** namespace gold
*** 32,37 ****
--- 32,59 ----
class Output_file;
+ // Return the length of a string in units of Char_type.
+
+ template<typename Char_type>
+ inline size_t
+ string_length(const Char_type* p)
+ {
+ size_t len = 0;
+ for (; *p != 0; ++p)
+ ++len;
+ return len;
+ }
+
+ // Specialize string_length for char. Maybe we could just use
+ // std::char_traits<>::length?
+
+ template<>
+ inline size_t
+ string_length(const char* p)
+ {
+ return strlen(p);
+ }
+
// A Stringpool is a pool of unique strings. It provides the
// following features:
*************** class Stringpool_template
*** 266,275 ****
Stringpool_template(const Stringpool_template&);
Stringpool_template& operator=(const Stringpool_template&);
- // Return the length of a string in units of Stringpool_char.
- static size_t
- string_length(const Stringpool_char*);
-
// Return whether two strings are equal.
static bool
string_equal(const Stringpool_char*, const Stringpool_char*);
--- 288,293 ----
diff -rcp ../binutils-2.20.51.0.10.original/gold/symtab.cc gold/symtab.cc
*** ../binutils-2.20.51.0.10.original/gold/symtab.cc 2010-08-10 15:12:04.000000000 +0100
--- gold/symtab.cc 2010-08-10 15:14:03.000000000 +0100
***************
*** 38,44 ****
#include "target.h"
#include "workqueue.h"
#include "symtab.h"
! #include "demangle.h" // needed for --dynamic-list-cpp-new
#include "plugin.h"
namespace gold
--- 38,44 ----
#include "target.h"
#include "workqueue.h"
#include "symtab.h"
! #include "script.h"
#include "plugin.h"
namespace gold
*************** Symbol::init_fields(const char* name, co
*** 76,81 ****
--- 76,83 ----
this->is_ordinary_shndx_ = false;
this->in_real_elf_ = false;
this->is_defined_in_discarded_section_ = false;
+ this->undef_binding_set_ = false;
+ this->undef_binding_weak_ = false;
}
// Return the demangled version of the symbol's name, but only
*************** Symbol_table::is_section_folded(Object*
*** 528,534 ****
// work list to avoid gc'ing them.
void
! Symbol_table::gc_mark_undef_symbols()
{
for (options::String_set::const_iterator p =
parameters->options().undefined_begin();
--- 530,536 ----
// work list to avoid gc'ing them.
void
! Symbol_table::gc_mark_undef_symbols(Layout* layout)
{
for (options::String_set::const_iterator p =
parameters->options().undefined_begin();
*************** Symbol_table::gc_mark_undef_symbols()
*** 551,556 ****
--- 553,579 ----
}
}
}
+
+ for (Script_options::referenced_const_iterator p =
+ layout->script_options()->referenced_begin();
+ p != layout->script_options()->referenced_end();
+ ++p)
+ {
+ Symbol* sym = this->lookup(p->c_str());
+ gold_assert(sym != NULL);
+ if (sym->source() == Symbol::FROM_OBJECT
+ && !sym->object()->is_dynamic())
+ {
+ Relobj* obj = static_cast<Relobj*>(sym->object());
+ bool is_ordinary;
+ unsigned int shndx = sym->shndx(&is_ordinary);
+ if (is_ordinary)
+ {
+ gold_assert(this->gc_ != NULL);
+ this->gc_->worklist().push(Section_id(obj, shndx));
+ }
+ }
+ }
}
void
*************** Symbol_table::get_copy_source(const Symb
*** 2161,2174 ****
// Add any undefined symbols named on the command line.
void
! Symbol_table::add_undefined_symbols_from_command_line()
{
! if (parameters->options().any_undefined())
{
if (parameters->target().get_size() == 32)
{
#if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_32_BIG)
! this->do_add_undefined_symbols_from_command_line<32>();
#else
gold_unreachable();
#endif
--- 2184,2198 ----
// Add any undefined symbols named on the command line.
void
! Symbol_table::add_undefined_symbols_from_command_line(Layout* layout)
{
! if (parameters->options().any_undefined()
! || layout->script_options()->any_unreferenced())
{
if (parameters->target().get_size() == 32)
{
#if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_32_BIG)
! this->do_add_undefined_symbols_from_command_line<32>(layout);
#else
gold_unreachable();
#endif
*************** Symbol_table::add_undefined_symbols_from
*** 2176,2182 ****
else if (parameters->target().get_size() == 64)
{
#if defined(HAVE_TARGET_64_LITTLE) || defined(HAVE_TARGET_64_BIG)
! this->do_add_undefined_symbols_from_command_line<64>();
#else
gold_unreachable();
#endif
--- 2200,2206 ----
else if (parameters->target().get_size() == 64)
{
#if defined(HAVE_TARGET_64_LITTLE) || defined(HAVE_TARGET_64_BIG)
! this->do_add_undefined_symbols_from_command_line<64>(layout);
#else
gold_unreachable();
#endif
*************** Symbol_table::add_undefined_symbols_from
*** 2188,2237 ****
template<int size>
void
! Symbol_table::do_add_undefined_symbols_from_command_line()
{
for (options::String_set::const_iterator p =
parameters->options().undefined_begin();
p != parameters->options().undefined_end();
++p)
! {
! const char* name = p->c_str();
! if (this->lookup(name) != NULL)
! continue;
! const char* version = NULL;
! Sized_symbol<size>* sym;
! Sized_symbol<size>* oldsym;
! bool resolve_oldsym;
! if (parameters->target().is_big_endian())
! {
#if defined(HAVE_TARGET_32_BIG) || defined(HAVE_TARGET_64_BIG)
! sym = this->define_special_symbol<size, true>(&name, &version,
! false, &oldsym,
! &resolve_oldsym);
#else
! gold_unreachable();
#endif
! }
! else
! {
#if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_64_LITTLE)
! sym = this->define_special_symbol<size, false>(&name, &version,
! false, &oldsym,
! &resolve_oldsym);
#else
! gold_unreachable();
#endif
! }
! gold_assert(oldsym == NULL);
! sym->init_undefined(name, version, elfcpp::STT_NOTYPE, elfcpp::STB_GLOBAL,
! elfcpp::STV_DEFAULT, 0);
! ++this->saw_undefined_;
! }
}
// Set the dynamic symbol indexes. INDEX is the index of the first
--- 2212,2270 ----
template<int size>
void
! Symbol_table::do_add_undefined_symbols_from_command_line(Layout* layout)
{
for (options::String_set::const_iterator p =
parameters->options().undefined_begin();
p != parameters->options().undefined_end();
++p)
! this->add_undefined_symbol_from_command_line<size>(p->c_str());
! for (Script_options::referenced_const_iterator p =
! layout->script_options()->referenced_begin();
! p != layout->script_options()->referenced_end();
! ++p)
! this->add_undefined_symbol_from_command_line<size>(p->c_str());
! }
!
! template<int size>
! void
! Symbol_table::add_undefined_symbol_from_command_line(const char* name)
! {
! if (this->lookup(name) != NULL)
! return;
! const char* version = NULL;
! Sized_symbol<size>* sym;
! Sized_symbol<size>* oldsym;
! bool resolve_oldsym;
! if (parameters->target().is_big_endian())
! {
#if defined(HAVE_TARGET_32_BIG) || defined(HAVE_TARGET_64_BIG)
! sym = this->define_special_symbol<size, true>(&name, &version,
! false, &oldsym,
! &resolve_oldsym);
#else
! gold_unreachable();
#endif
! }
! else
! {
#if defined(HAVE_TARGET_32_LITTLE) || defined(HAVE_TARGET_64_LITTLE)
! sym = this->define_special_symbol<size, false>(&name, &version,
! false, &oldsym,
! &resolve_oldsym);
#else
! gold_unreachable();
#endif
! }
! gold_assert(oldsym == NULL);
! sym->init_undefined(name, version, elfcpp::STT_NOTYPE, elfcpp::STB_GLOBAL,
! elfcpp::STV_DEFAULT, 0);
! ++this->saw_undefined_;
}
// Set the dynamic symbol indexes. INDEX is the index of the first
*************** Symbol_table::sized_write_globals(const
*** 2697,2702 ****
--- 2730,2736 ----
unsigned int shndx;
typename elfcpp::Elf_types<size>::Elf_Addr sym_value = sym->value();
typename elfcpp::Elf_types<size>::Elf_Addr dynsym_value = sym_value;
+ elfcpp::STB binding = sym->binding();
switch (sym->source())
{
case Symbol::FROM_OBJECT:
*************** Symbol_table::sized_write_globals(const
*** 2720,2725 ****
--- 2754,2761 ----
if (sym->needs_dynsym_value())
dynsym_value = target.dynsym_value(sym);
shndx = elfcpp::SHN_UNDEF;
+ if (sym->is_undef_binding_weak())
+ binding = elfcpp::STB_WEAK;
}
else if (symobj->pluginobj() != NULL)
shndx = elfcpp::SHN_UNDEF;
*************** Symbol_table::sized_write_globals(const
*** 2800,2806 ****
gold_assert(sym_index < output_count);
unsigned char* ps = psyms + (sym_index * sym_size);
this->sized_write_symbol<size, big_endian>(sym, sym_value, shndx,
! sympool, ps);
}
if (dynsym_index != -1U)
--- 2836,2842 ----
gold_assert(sym_index < output_count);
unsigned char* ps = psyms + (sym_index * sym_size);
this->sized_write_symbol<size, big_endian>(sym, sym_value, shndx,
! binding, sympool, ps);
}
if (dynsym_index != -1U)
*************** Symbol_table::sized_write_globals(const
*** 2809,2815 ****
gold_assert(dynsym_index < dynamic_count);
unsigned char* pd = dynamic_view + (dynsym_index * sym_size);
this->sized_write_symbol<size, big_endian>(sym, dynsym_value, shndx,
! dynpool, pd);
}
}
--- 2845,2851 ----
gold_assert(dynsym_index < dynamic_count);
unsigned char* pd = dynamic_view + (dynsym_index * sym_size);
this->sized_write_symbol<size, big_endian>(sym, dynsym_value, shndx,
! binding, dynpool, pd);
}
}
*************** Symbol_table::sized_write_symbol(
*** 2827,2832 ****
--- 2863,2869 ----
Sized_symbol<size>* sym,
typename elfcpp::Elf_types<size>::Elf_Addr value,
unsigned int shndx,
+ elfcpp::STB binding,
const Stringpool* pool,
unsigned char* p) const
{
*************** Symbol_table::sized_write_symbol(
*** 2847,2853 ****
if (sym->is_forced_local())
osym.put_st_info(elfcpp::elf_st_info(elfcpp::STB_LOCAL, type));
else
! osym.put_st_info(elfcpp::elf_st_info(sym->binding(), type));
osym.put_st_other(elfcpp::elf_st_other(sym->visibility(), sym->nonvis()));
osym.put_st_shndx(shndx);
}
--- 2884,2890 ----
if (sym->is_forced_local())
osym.put_st_info(elfcpp::elf_st_info(elfcpp::STB_LOCAL, type));
else
! osym.put_st_info(elfcpp::elf_st_info(binding, type));
osym.put_st_other(elfcpp::elf_st_other(sym->visibility(), sym->nonvis()));
osym.put_st_shndx(shndx);
}
diff -rcp ../binutils-2.20.51.0.10.original/gold/symtab.h gold/symtab.h
*** ../binutils-2.20.51.0.10.original/gold/symtab.h 2010-08-10 15:11:43.000000000 +0100
--- gold/symtab.h 2010-08-10 15:14:03.000000000 +0100
*************** class Symbol
*** 227,232 ****
--- 227,249 ----
void
override_visibility(elfcpp::STV);
+ // Set whether the symbol was originally a weak undef or a regular undef
+ // when resolved by a dynamic def.
+ inline void
+ set_undef_binding(elfcpp::STB bind)
+ {
+ if (!this->undef_binding_set_ || this->undef_binding_weak_)
+ {
+ this->undef_binding_weak_ = bind == elfcpp::STB_WEAK;
+ this->undef_binding_set_ = true;
+ }
+ }
+
+ // Return TRUE if a weak undef was resolved by a dynamic def.
+ inline bool
+ is_undef_binding_weak() const
+ { return this->undef_binding_weak_; }
+
// Return the non-visibility part of the st_other field.
unsigned char
nonvis() const
*************** class Symbol
*** 949,954 ****
--- 966,976 ----
// True if this symbol is defined in a section which was discarded
// (bit 31).
bool is_defined_in_discarded_section_ : 1;
+ // True if UNDEF_BINDING_WEAK_ has been set (bit 32).
+ bool undef_binding_set_ : 1;
+ // True if this symbol was a weak undef resolved by a dynamic def
+ // (bit 33).
+ bool undef_binding_weak_ : 1;
};
// The parts of a symbol which are size specific. Using a template
*************** class Symbol_table
*** 1247,1253 ****
// During garbage collection, this keeps undefined symbols.
void
! gc_mark_undef_symbols();
// During garbage collection, this ensures externally visible symbols
// are not treated as garbage while building shared objects.
--- 1269,1275 ----
// During garbage collection, this keeps undefined symbols.
void
! gc_mark_undef_symbols(Layout*);
// During garbage collection, this ensures externally visible symbols
// are not treated as garbage while building shared objects.
*************** class Symbol_table
*** 1397,1403 ****
// Add any undefined symbols named on the command line to the symbol
// table.
void
! add_undefined_symbols_from_command_line();
// SYM is defined using a COPY reloc. Return the dynamic object
// where the original definition was found.
--- 1419,1425 ----
// Add any undefined symbols named on the command line to the symbol
// table.
void
! add_undefined_symbols_from_command_line(Layout*);
// SYM is defined using a COPY reloc. Return the dynamic object
// where the original definition was found.
*************** class Symbol_table
*** 1536,1542 ****
// Whether we should override a symbol, based on flags in
// resolve.cc.
static bool
! should_override(const Symbol*, unsigned int, Defined, Object*, bool*);
// Report a problem in symbol resolution.
static void
--- 1558,1564 ----
// Whether we should override a symbol, based on flags in
// resolve.cc.
static bool
! should_override(const Symbol*, unsigned int, Defined, Object*, bool*, bool*);
// Report a problem in symbol resolution.
static void
*************** class Symbol_table
*** 1611,1617 ****
// table, sized version.
template<int size>
void
! do_add_undefined_symbols_from_command_line();
// Types of common symbols.
--- 1633,1644 ----
// table, sized version.
template<int size>
void
! do_add_undefined_symbols_from_command_line(Layout*);
!
! // Add one undefined symbol.
! template<int size>
! void
! add_undefined_symbol_from_command_line(const char* name);
// Types of common symbols.
*************** class Symbol_table
*** 1667,1673 ****
void
sized_write_symbol(Sized_symbol<size>*,
typename elfcpp::Elf_types<size>::Elf_Addr value,
! unsigned int shndx,
const Stringpool*, unsigned char* p) const;
// Possibly warn about an undefined symbol from a dynamic object.
--- 1694,1700 ----
void
sized_write_symbol(Sized_symbol<size>*,
typename elfcpp::Elf_types<size>::Elf_Addr value,
! unsigned int shndx, elfcpp::STB,
const Stringpool*, unsigned char* p) const;
// Possibly warn about an undefined symbol from a dynamic object.
diff -rcp ../binutils-2.20.51.0.10.original/gold/version.cc gold/version.cc
*** ../binutils-2.20.51.0.10.original/gold/version.cc 2010-08-10 15:11:43.000000000 +0100
--- gold/version.cc 2010-08-10 15:14:04.000000000 +0100
*************** namespace gold
*** 37,43 ****
// version number from configure.ac. But it's easier to just change
// this file for now.
! static const char* version_string = "1.9";
// Report version information.
--- 37,43 ----
// version number from configure.ac. But it's easier to just change
// this file for now.
! static const char* version_string = "1.10";
// Report version information.
diff -rcp ../binutils-2.20.51.0.10.original/gold/x86_64.cc gold/x86_64.cc
*** ../binutils-2.20.51.0.10.original/gold/x86_64.cc 2010-08-10 15:12:03.000000000 +0100
--- gold/x86_64.cc 2010-08-10 15:14:04.000000000 +0100
***************
*** 1,6 ****
// x86_64.cc -- x86_64 target support for gold.
! // Copyright 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
--- 1,6 ----
// x86_64.cc -- x86_64 target support for gold.
! // Copyright 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
// Written by Ian Lance Taylor <iant@google.com>.
// This file is part of gold.
*************** class Target_x86_64 : public Target_free
*** 64,71 ****
Target_x86_64()
: Target_freebsd<64, false>(&x86_64_info),
! got_(NULL), plt_(NULL), got_plt_(NULL), global_offset_table_(NULL),
! rela_dyn_(NULL), copy_relocs_(elfcpp::R_X86_64_COPY), dynbss_(NULL),
got_mod_index_offset_(-1U), tlsdesc_reloc_info_(),
tls_base_symbol_defined_(false)
{ }
--- 64,72 ----
Target_x86_64()
: Target_freebsd<64, false>(&x86_64_info),
! got_(NULL), plt_(NULL), got_plt_(NULL), got_tlsdesc_(NULL),
! global_offset_table_(NULL), rela_dyn_(NULL),
! copy_relocs_(elfcpp::R_X86_64_COPY), dynbss_(NULL),
got_mod_index_offset_(-1U), tlsdesc_reloc_info_(),
tls_base_symbol_defined_(false)
{ }
*************** class Target_x86_64 : public Target_free
*** 403,408 ****
--- 404,417 ----
return this->got_plt_;
}
+ // Get the GOT section for TLSDESC entries.
+ Output_data_got<64, false>*
+ got_tlsdesc_section() const
+ {
+ gold_assert(this->got_tlsdesc_ != NULL);
+ return this->got_tlsdesc_;
+ }
+
// Create the PLT section.
void
make_plt_section(Symbol_table* symtab, Layout* layout);
*************** class Target_x86_64 : public Target_free
*** 486,491 ****
--- 495,502 ----
Output_data_plt_x86_64* plt_;
// The GOT PLT section.
Output_data_space* got_plt_;
+ // The GOT section for TLSDESC relocations.
+ Output_data_got<64, false>* got_tlsdesc_;
// The _GLOBAL_OFFSET_TABLE_ symbol.
Symbol* global_offset_table_;
// The dynamic reloc section.
*************** Target_x86_64::got_section(Symbol_table*
*** 547,565 ****
this->got_ = new Output_data_got<64, false>();
! Output_section* os;
! os = layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
! (elfcpp::SHF_ALLOC
! | elfcpp::SHF_WRITE),
! this->got_, false, true, true,
! false);
this->got_plt_ = new Output_data_space(8, "** GOT PLT");
! os = layout->add_output_section_data(".got.plt", elfcpp::SHT_PROGBITS,
! (elfcpp::SHF_ALLOC
! | elfcpp::SHF_WRITE),
! this->got_plt_, false, false,
! false, true);
// The first three entries are reserved.
this->got_plt_->set_current_data_size(3 * 8);
--- 558,575 ----
this->got_ = new Output_data_got<64, false>();
! layout->add_output_section_data(".got", elfcpp::SHT_PROGBITS,
! (elfcpp::SHF_ALLOC
! | elfcpp::SHF_WRITE),
! this->got_, ORDER_RELRO_LAST,
! true);
this->got_plt_ = new Output_data_space(8, "** GOT PLT");
! layout->add_output_section_data(".got.plt", elfcpp::SHT_PROGBITS,
! (elfcpp::SHF_ALLOC
! | elfcpp::SHF_WRITE),
! this->got_plt_, ORDER_NON_RELRO_FIRST,
! false);
// The first three entries are reserved.
this->got_plt_->set_current_data_size(3 * 8);
*************** Target_x86_64::got_section(Symbol_table*
*** 576,581 ****
--- 586,600 ----
elfcpp::STB_LOCAL,
elfcpp::STV_HIDDEN, 0,
false, false);
+
+ // If there are any TLSDESC relocations, they get GOT entries in
+ // .got.plt after the jump slot entries.
+ this->got_tlsdesc_ = new Output_data_got<64, false>();
+ layout->add_output_section_data(".got.plt", elfcpp::SHT_PROGBITS,
+ (elfcpp::SHF_ALLOC
+ | elfcpp::SHF_WRITE),
+ this->got_tlsdesc_,
+ ORDER_NON_RELRO_FIRST, false);
}
return this->got_;
*************** Target_x86_64::rela_dyn_section(Layout*
*** 591,598 ****
gold_assert(layout != NULL);
this->rela_dyn_ = new Reloc_section(parameters->options().combreloc());
layout->add_output_section_data(".rela.dyn", elfcpp::SHT_RELA,
! elfcpp::SHF_ALLOC, this->rela_dyn_, true,
! false, false, false);
}
return this->rela_dyn_;
}
--- 610,617 ----
gold_assert(layout != NULL);
this->rela_dyn_ = new Reloc_section(parameters->options().combreloc());
layout->add_output_section_data(".rela.dyn", elfcpp::SHT_RELA,
! elfcpp::SHF_ALLOC, this->rela_dyn_,
! ORDER_DYNAMIC_RELOCS, false);
}
return this->rela_dyn_;
}
*************** Output_data_plt_x86_64::Output_data_plt_
*** 699,706 ****
{
this->rel_ = new Reloc_section(false);
layout->add_output_section_data(".rela.plt", elfcpp::SHT_RELA,
! elfcpp::SHF_ALLOC, this->rel_, true,
! false, false, false);
}
void
--- 718,725 ----
{
this->rel_ = new Reloc_section(false);
layout->add_output_section_data(".rela.plt", elfcpp::SHT_RELA,
! elfcpp::SHF_ALLOC, this->rel_,
! ORDER_DYNAMIC_PLT_RELOCS, false);
}
void
*************** Output_data_plt_x86_64::rela_tlsdesc(Lay
*** 750,756 ****
this->tlsdesc_rel_ = new Reloc_section(false);
layout->add_output_section_data(".rela.plt", elfcpp::SHT_RELA,
elfcpp::SHF_ALLOC, this->tlsdesc_rel_,
! true, false, false, false);
gold_assert(this->tlsdesc_rel_->output_section() ==
this->rel_->output_section());
}
--- 769,775 ----
this->tlsdesc_rel_ = new Reloc_section(false);
layout->add_output_section_data(".rela.plt", elfcpp::SHT_RELA,
elfcpp::SHF_ALLOC, this->tlsdesc_rel_,
! ORDER_DYNAMIC_PLT_RELOCS, false);
gold_assert(this->tlsdesc_rel_->output_section() ==
this->rel_->output_section());
}
*************** Target_x86_64::make_plt_section(Symbol_t
*** 914,920 ****
layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS,
(elfcpp::SHF_ALLOC
| elfcpp::SHF_EXECINSTR),
! this->plt_, false, false, false, false);
}
}
--- 933,939 ----
layout->add_output_section_data(".plt", elfcpp::SHT_PROGBITS,
(elfcpp::SHF_ALLOC
| elfcpp::SHF_EXECINSTR),
! this->plt_, ORDER_PLT, false);
}
}
*************** Target_x86_64::Scan::local(Symbol_table*
*** 1131,1138 ****
switch (r_type)
{
case elfcpp::R_X86_64_NONE:
! case elfcpp::R_386_GNU_VTINHERIT:
! case elfcpp::R_386_GNU_VTENTRY:
break;
case elfcpp::R_X86_64_64:
--- 1150,1157 ----
switch (r_type)
{
case elfcpp::R_X86_64_NONE:
! case elfcpp::R_X86_64_GNU_VTINHERIT:
! case elfcpp::R_X86_64_GNU_VTENTRY:
break;
case elfcpp::R_X86_64_64:
*************** Target_x86_64::Scan::local(Symbol_table*
*** 1308,1316 ****
// Create reserved PLT and GOT entries for the resolver.
target->reserve_tlsdesc_entries(symtab, layout);
! // Generate a double GOT entry with an R_X86_64_TLSDESC reloc.
! Output_data_got<64, false>* got
! = target->got_section(symtab, layout);
unsigned int r_sym = elfcpp::elf_r_sym<64>(reloc.get_r_info());
if (!object->local_has_got_offset(r_sym, GOT_TYPE_TLS_DESC))
{
--- 1327,1339 ----
// Create reserved PLT and GOT entries for the resolver.
target->reserve_tlsdesc_entries(symtab, layout);
! // Generate a double GOT entry with an
! // R_X86_64_TLSDESC reloc. The R_X86_64_TLSDESC reloc
! // is resolved lazily, so the GOT entry needs to be in
! // an area in .got.plt, not .got. Call got_section to
! // make sure the section has been created.
! target->got_section(symtab, layout);
! Output_data_got<64, false>* got = target->got_tlsdesc_section();
unsigned int r_sym = elfcpp::elf_r_sym<64>(reloc.get_r_info());
if (!object->local_has_got_offset(r_sym, GOT_TYPE_TLS_DESC))
{
*************** Target_x86_64::Scan::global(Symbol_table
*** 1485,1492 ****
switch (r_type)
{
case elfcpp::R_X86_64_NONE:
! case elfcpp::R_386_GNU_VTINHERIT:
! case elfcpp::R_386_GNU_VTENTRY:
break;
case elfcpp::R_X86_64_64:
--- 1508,1515 ----
switch (r_type)
{
case elfcpp::R_X86_64_NONE:
! case elfcpp::R_X86_64_GNU_VTINHERIT:
! case elfcpp::R_X86_64_GNU_VTENTRY:
break;
case elfcpp::R_X86_64_64:
*************** Target_x86_64::Scan::global(Symbol_table
*** 1689,1697 ****
// Create reserved PLT and GOT entries for the resolver.
target->reserve_tlsdesc_entries(symtab, layout);
! // Create a double GOT entry with an R_X86_64_TLSDESC reloc.
! Output_data_got<64, false>* got
! = target->got_section(symtab, layout);
Reloc_section *rt = target->rela_tlsdesc_section(layout);
got->add_global_pair_with_rela(gsym, GOT_TYPE_TLS_DESC, rt,
elfcpp::R_X86_64_TLSDESC, 0);
--- 1712,1724 ----
// Create reserved PLT and GOT entries for the resolver.
target->reserve_tlsdesc_entries(symtab, layout);
! // Create a double GOT entry with an R_X86_64_TLSDESC
! // reloc. The R_X86_64_TLSDESC reloc is resolved
! // lazily, so the GOT entry needs to be in an area in
! // .got.plt, not .got. Call got_section to make sure
! // the section has been created.
! target->got_section(symtab, layout);
! Output_data_got<64, false>* got = target->got_tlsdesc_section();
Reloc_section *rt = target->rela_tlsdesc_section(layout);
got->add_global_pair_with_rela(gsym, GOT_TYPE_TLS_DESC, rt,
elfcpp::R_X86_64_TLSDESC, 0);
*************** Target_x86_64::gc_process_relocs(Symbol_
*** 1783,1789 ****
}
gold::gc_process_relocs<64, false, Target_x86_64, elfcpp::SHT_RELA,
! Target_x86_64::Scan>(
symtab,
layout,
this,
--- 1810,1817 ----
}
gold::gc_process_relocs<64, false, Target_x86_64, elfcpp::SHT_RELA,
! Target_x86_64::Scan,
! Target_x86_64::Relocatable_size_for_reloc>(
symtab,
layout,
this,
*************** Target_x86_64::Relocate::relocate(const
*** 1964,1971 ****
switch (r_type)
{
case elfcpp::R_X86_64_NONE:
! case elfcpp::R_386_GNU_VTINHERIT:
! case elfcpp::R_386_GNU_VTENTRY:
break;
case elfcpp::R_X86_64_64:
--- 1992,1999 ----
switch (r_type)
{
case elfcpp::R_X86_64_NONE:
! case elfcpp::R_X86_64_GNU_VTINHERIT:
! case elfcpp::R_X86_64_GNU_VTENTRY:
break;
case elfcpp::R_X86_64_64:
*************** Target_x86_64::Relocate::relocate_tls(co
*** 2230,2247 ****
unsigned int got_type = (optimized_type == tls::TLSOPT_TO_IE
? GOT_TYPE_TLS_OFFSET
: GOT_TYPE_TLS_DESC);
! unsigned int got_offset;
if (gsym != NULL)
{
gold_assert(gsym->has_got_offset(got_type));
! got_offset = gsym->got_offset(got_type) - target->got_size();
}
else
{
unsigned int r_sym = elfcpp::elf_r_sym<64>(rela.get_r_info());
gold_assert(object->local_has_got_offset(r_sym, got_type));
! got_offset = (object->local_got_offset(r_sym, got_type)
! - target->got_size());
}
if (optimized_type == tls::TLSOPT_TO_IE)
{
--- 2258,2284 ----
unsigned int got_type = (optimized_type == tls::TLSOPT_TO_IE
? GOT_TYPE_TLS_OFFSET
: GOT_TYPE_TLS_DESC);
! unsigned int got_offset = 0;
! if (r_type == elfcpp::R_X86_64_GOTPC32_TLSDESC
! && optimized_type == tls::TLSOPT_NONE)
! {
! // We created GOT entries in the .got.tlsdesc portion of
! // the .got.plt section, but the offset stored in the
! // symbol is the offset within .got.tlsdesc.
! got_offset = (target->got_size()
! + target->got_plt_section()->data_size());
! }
if (gsym != NULL)
{
gold_assert(gsym->has_got_offset(got_type));
! got_offset += gsym->got_offset(got_type) - target->got_size();
}
else
{
unsigned int r_sym = elfcpp::elf_r_sym<64>(rela.get_r_info());
gold_assert(object->local_has_got_offset(r_sym, got_type));
! got_offset += (object->local_got_offset(r_sym, got_type)
! - target->got_size());
}
if (optimized_type == tls::TLSOPT_TO_IE)
{
*************** Target_x86_64::Relocatable_size_for_relo
*** 2643,2650 ****
switch (r_type)
{
case elfcpp::R_X86_64_NONE:
! case elfcpp::R_386_GNU_VTINHERIT:
! case elfcpp::R_386_GNU_VTENTRY:
case elfcpp::R_X86_64_TLSGD: // Global-dynamic
case elfcpp::R_X86_64_GOTPC32_TLSDESC: // Global-dynamic (from ~oliva url)
case elfcpp::R_X86_64_TLSDESC_CALL:
--- 2680,2687 ----
switch (r_type)
{
case elfcpp::R_X86_64_NONE:
! case elfcpp::R_X86_64_GNU_VTINHERIT:
! case elfcpp::R_X86_64_GNU_VTENTRY:
case elfcpp::R_X86_64_TLSGD: // Global-dynamic
case elfcpp::R_X86_64_GOTPC32_TLSDESC: // Global-dynamic (from ~oliva url)
case elfcpp::R_X86_64_TLSDESC_CALL:
diff -rcp ../binutils-2.20.51.0.10.original/gold/yyscript.y gold/yyscript.y
*** ../binutils-2.20.51.0.10.original/gold/yyscript.y 2010-08-10 15:11:40.000000000 +0100
--- gold/yyscript.y 2010-08-10 15:14:04.000000000 +0100
*************** exp:
*** 867,873 ****
| INTEGER
{ $$ = script_exp_integer($1); }
| string
! { $$ = script_exp_string($1.value, $1.length); }
| MAX_K '(' exp ',' exp ')'
{ $$ = script_exp_function_max($3, $5); }
| MIN_K '(' exp ',' exp ')'
--- 867,873 ----
| INTEGER
{ $$ = script_exp_integer($1); }
| string
! { $$ = script_symbol(closure, $1.value, $1.length); }
| MAX_K '(' exp ',' exp ')'
{ $$ = script_exp_function_max($3, $5); }
| MIN_K '(' exp ',' exp ')'