8000 lines
266 KiB
Diff
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(§ion_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 ')'
|