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