diff --git a/binutils-2.20.51.0.10-copy-osabi.patch b/binutils-2.20.51.0.10-copy-osabi.patch new file mode 100644 index 0000000..86cb447 --- /dev/null +++ b/binutils-2.20.51.0.10-copy-osabi.patch @@ -0,0 +1,19 @@ +*** ../binutils-2.20.51.0.10.original/bfd/elf.c 2010-08-10 15:04:55.000000000 +0100 +--- bfd/elf.c 2010-08-10 15:05:42.000000000 +0100 +*************** _bfd_elf_copy_private_bfd_data (bfd *ibf +*** 1074,1079 **** +--- 1074,1087 ---- + + /* Copy object attributes. */ + _bfd_elf_copy_obj_attributes (ibfd, obfd); ++ ++ /* If the input BFD has the OSABI field set and the ++ output BFD does not, then copy the value. */ ++ if (elf_elfheader (ibfd)->e_ident [EI_OSABI] != ELFOSABI_NONE ++ && elf_elfheader (obfd)->e_ident [EI_OSABI] == ELFOSABI_NONE) ++ elf_elfheader (obfd)->e_ident [EI_OSABI] = ++ elf_elfheader (ibfd)->e_ident [EI_OSABI]; ++ + return TRUE; + } + diff --git a/binutils-2.20.51.0.10-ppc64-pie.patch b/binutils-2.20.51.0.10-ppc64-pie.patch new file mode 100644 index 0000000..f68b329 --- /dev/null +++ b/binutils-2.20.51.0.10-ppc64-pie.patch @@ -0,0 +1,24 @@ +*** ../binutils-2.20.51.0.10.original/bfd/elf64-ppc.c 2010-08-10 14:58:09.000000000 +0100 +--- bfd/elf64-ppc.c 2010-08-10 15:03:16.000000000 +0100 +*************** ppc64_elf_relocate_section (bfd *output_ +*** 12757,12763 **** + else if (!SYMBOL_CALLS_LOCAL (info, &h->elf) + && !is_opd + && r_type != R_PPC64_TOC) +! outrel.r_info = ELF64_R_INFO (h->elf.dynindx, r_type); + else + { + /* This symbol is local, or marked to become local, +--- 12757,12768 ---- + else if (!SYMBOL_CALLS_LOCAL (info, &h->elf) + && !is_opd + && r_type != R_PPC64_TOC) +! { +! outrel.r_info = ELF64_R_INFO (h->elf.dynindx, r_type); +! if (h->elf.dynindx == -1 +! && h->elf.root.type == bfd_link_hash_undefweak) +! memset (&outrel, 0, sizeof outrel); +! } + else + { + /* This symbol is local, or marked to become local, diff --git a/binutils-2.20.51.0.10-update-gold.patch b/binutils-2.20.51.0.10-update-gold.patch new file mode 100644 index 0000000..d8f8962 --- /dev/null +++ b/binutils-2.20.51.0.10-update-gold.patch @@ -0,0 +1,7999 @@ +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 . + + // 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 . + + // 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 . + + // 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 . + + // 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 . + + // 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 . + + // 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* 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*, 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*, Symbol_table*); + + // Functors for STL set. + struct output_section_address_less_than +*************** Target_arm::got_section(Symb +*** 4116,4137 **** + + this->got_ = new Arm_output_data_got(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(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::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::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::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::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* arm_relobj = + Arm_relobj::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* arm_relobj = + Arm_relobj::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::fix_exid +*** 5846,5851 **** +--- 5883,5910 ---- + this->set_section_offsets_need_adjustment(); + } + ++ // Link EXIDX output sections to text output sections. ++ ++ template ++ void ++ Arm_output_section::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* arm_relobj = ++ Arm_relobj::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::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::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::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::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::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 +--- 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 +*************** Target_arm::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::gc_process_reloc +*** 8124,8130 **** + typedef Target_arm Arm; + typedef typename Target_arm::Scan Scan; + +! gold::gc_process_relocs<32, big_endian, Arm, elfcpp::SHT_REL, Scan>( + symtab, + layout, + this, +--- 8213,8220 ---- + typedef Target_arm Arm; + typedef typename Target_arm::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::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::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* os = ++ Arm_output_section::as_arm_output_section(*p); ++ os->set_exidx_section_link(); ++ } + } + + // Return whether a direct absolute static relocation needs to be applied. +*************** Target_arm::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* exidx_output_section = +! Arm_output_section::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* 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::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 +*** 11427,11432 **** +--- 11544,11550 ---- + void + Target_arm::fix_exidx_coverage( + Layout* layout, ++ const Input_objects* input_objects, + Arm_output_section* exidx_section, + Symbol_table* symtab) + { +*************** Target_arm::fix_exidx_covera +*** 11439,11453 **** + typedef std::set + Sorted_output_section_list; + Sorted_output_section_list sorted_output_sections; +! Layout::Section_list section_list; +! layout->get_allocated_sections(§ion_list); +! for (Layout::Section_list::const_iterator p = section_list.begin(); +! p != section_list.end(); + ++p) + { +! // We only care about output sections that contain executable code. +! if (((*p)->flags() & elfcpp::SHF_EXECINSTR) != 0) +! sorted_output_sections.insert(*p); + } + + // Go over the output sections in ascending order of output addresses. +--- 11557,11586 ---- + typedef std::set + 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* arm_relobj = +! Arm_relobj::as_arm_relobj(*p); +! std::vector 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 . + + // 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 . + + // 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(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(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(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 . + + // 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 . + + // 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:: +*** 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: +*** 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::do_add_s +*** 753,760 **** + + template + Archive::Should_include +! Sized_dynobj::do_should_include_member( +! Symbol_table*, Read_symbols_data*, std::string*) + { + return Archive::SHOULD_INCLUDE_YES; + } +--- 753,762 ---- + + template + Archive::Should_include +! Sized_dynobj::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 ++ 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 + inline void + gc_process_relocs( + Symbol_table* symtab, +--- 172,178 ---- + // folding (--icf). + + template + 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(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(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 . + + // 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 . + + // 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(*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_info; + typedef std::vector > Addend_info; + typedef std::vector Offset_info; ++ typedef std::vector Reloc_addend_size_info; + typedef Unordered_map 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_mapinsert(destination->end(), buffer, buffer + valsize / 8); + } + ++ // Read a possibly unaligned integer of SIZE from SOURCE. ++ ++ template ++ typename elfcpp::Valtype_base::Valtype ++ read_from_pointer(const unsigned char* source) ++ { ++ typename elfcpp::Valtype_base::Valtype return_value; ++ if (parameters->target().is_big_endian()) ++ return_value = elfcpp::Swap_unaligned::readval(source); ++ else ++ return_value = elfcpp::Swap_unaligned::readval(source); ++ return return_value; ++ } ++ + // Read a possibly unaligned integer of SIZE. Update SOURCE after read. + + template +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_relobjnamepool_.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_relobjoptions().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_relobjchoose_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_relobjoptions().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_relobjmake_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 . + + // 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 . + + // This file is part of gold. +*************** +*** 26,31 **** +--- 26,32 ---- + #include + + #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::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(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(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::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::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_strings; + + // As we see the strings, we add them to a Stringpool. + Stringpool_template 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_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_lists; ++ + // As we see the strings, we add them to a Stringpool. + Stringpool_template 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::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::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 ++ Compressed_section_map* ++ build_compressed_section_map( ++ const unsigned char* pshdrs, ++ unsigned int shnum, ++ const char* names, ++ section_size_type names_size, ++ Sized_relobj* obj) ++ { ++ Compressed_section_map* uncompressed_sizes = new Compressed_section_map(); ++ const unsigned int shdr_size = elfcpp::Elf_sizes::shdr_size; ++ const unsigned char* p = pshdrs + shdr_size; ++ for (unsigned int i = 1; i < shnum; ++i, p += shdr_size) ++ { ++ typename elfcpp::Shdr 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(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 +*************** Sized_relobj::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::do_add_s +*** 1562,1567 **** +--- 1614,1620 ---- + template + Archive::Should_include + Sized_relobj::do_should_include_member(Symbol_table* symtab, ++ Layout* layout, + Read_symbols_data* sd, + std::string* why) + { +*************** Sized_relobj::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 vec_; + }; + ++ // Type for mapping section index to uncompressed size. ++ ++ typedef std::map Compressed_section_map; ++ + // A regular object file. This is size and endian specific. + + template +*************** 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 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 This; +*************** class Sized_relobj : public Relobj +*** 2024,2029 **** +--- 2060,2067 ---- + std::vector deferred_layout_; + // The list of relocation sections whose layout was deferred. + std::vector 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(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(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(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(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(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(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(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(ORDER_MAX); ++i) +! { +! addr = this->set_section_list_addresses(layout, reset, +! &this->output_lists_[i], +! addr, poff, pshndx, &in_tls); +! if (i < static_cast(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(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(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(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(layout, secnamepool, +! &this->output_data_, +! v, pshndx); +! v = this->write_section_headers_list(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(ORDER_MAX); ++i) +! { +! const Output_data_list* pdl = &this->output_lists_[i]; +! v = this->write_section_headers_list(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(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 value(msp, pomb); + std::pair 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 value(msp, pomb); + std::pair 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 value(csid, pomb); + std::pair 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 value(csid, pomb); + std::pair 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 result = + this->relaxed_input_sections_by_id_.insert(value); +! gold_assert(value.second); + } + + private: +--- 2469,2475 ---- + value(csid, poris); + std::pair 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_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_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 + 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::do_ad +*** 705,730 **** + template + Archive::Should_include + Sized_pluginobj::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 + Archive::Should_include + Sized_pluginobj::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::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::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::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::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::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_powerpcrel_ = new Reloc_section(false); + layout->add_output_section_data(".rela.plt", elfcpp::SHT_RELA, +! elfcpp::SHF_ALLOC, this->rel_, true, false, +! false, false); + } + + template +--- 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 +*************** Target_powerpc::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::gc_pro +*** 1493,1499 **** + typedef Target_powerpc Powerpc; + typedef typename Target_powerpc::Scan Scan; + +! gold::gc_process_relocs( + symtab, + layout, + this, +--- 1491,1498 ---- + typedef Target_powerpc Powerpc; + typedef typename Target_powerpc::Scan Scan; + +! gold::gc_process_relocs( + symtab, + layout, + this, +*************** Target_powerpc::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::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::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::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::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::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::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 +*** 335,352 **** + sym.get_st_type()); + + bool adjust_common_sizes; + typename Sized_symbol::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_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 +*** 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(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::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 symbol_definitions_; ++ // Symbols referenced in an expression. ++ Unordered_set 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::got_sect +*** 1045,1056 **** + + this->got_ = new Output_data_got(); + +! 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(); + +! 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::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: +*** 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 +--- 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 +*************** Target_sparc::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::gc_proce +*** 2332,2338 **** + typedef Target_sparc Sparc; + typedef typename Target_sparc::Scan Scan; + +! gold::gc_process_relocs( + symtab, + layout, + this, +--- 2330,2337 ---- + typedef Target_sparc Sparc; + typedef typename Target_sparc::Scan Scan; + +! gold::gc_process_relocs( + symtab, + layout, + this, +*************** Target_sparc::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::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::re +*** 87,114 **** + this->string_set_.swap(new_string_set); + } + +- // Return the length of a string of arbitrary character type. +- +- template +- size_t +- Stringpool_template::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::string_length(const char* p) +- { +- return strlen(p); +- } +- + // Compare two strings of arbitrary character type for equality. + + template +--- 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 ++ 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(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 + 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* sym; +! Sized_symbol* 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(&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(&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 + 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(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(p->c_str()); +! } +! +! template +! void +! Symbol_table::add_undefined_symbol_from_command_line(const char* name) +! { +! if (this->lookup(name) != NULL) +! return; + +! const char* version = NULL; + +! Sized_symbol* sym; +! Sized_symbol* 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(&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(&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::Elf_Addr sym_value = sym->value(); + typename elfcpp::Elf_types::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(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(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(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(sym, dynsym_value, shndx, +! binding, dynpool, pd); + } + } + +*************** Symbol_table::sized_write_symbol( +*** 2827,2832 **** +--- 2863,2869 ---- + Sized_symbol* sym, + typename elfcpp::Elf_types::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 + void +! do_add_undefined_symbols_from_command_line(); + + // Types of common symbols. + +--- 1633,1644 ---- + // table, sized version. + template + void +! do_add_undefined_symbols_from_command_line(Layout*); +! +! // Add one undefined symbol. +! template +! 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*, + typename elfcpp::Elf_types::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*, + typename elfcpp::Elf_types::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 . + + // 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 . + + // 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 ')' diff --git a/binutils.spec b/binutils.spec index 92a41c0..8fdeb1a 100644 --- a/binutils.spec +++ b/binutils.spec @@ -16,25 +16,22 @@ Summary: A GNU collection of binary utilities Name: %{?cross}binutils%{?_with_debug:-debug} -Version: 2.20.51.0.7 -Release: 5%{?dist} +Version: 2.20.51.0.10 +Release: 1%{?dist} License: GPLv3+ Group: Development/Tools URL: http://sources.redhat.com/binutils Source: ftp://ftp.kernel.org/pub/linux/devel/binutils/binutils-%{version}.tar.bz2 Source2: binutils-2.19.50.0.1-output-format.sed Patch01: binutils-2.20.51.0.2-libtool-lib64.patch -Patch02: binutils-2.20.51.0.2-ppc64-pie.patch +Patch02: binutils-2.20.51.0.10-ppc64-pie.patch Patch03: binutils-2.20.51.0.2-ia64-lib64.patch Patch04: binutils-2.20.51.0.2-envvar-revert.patch Patch05: binutils-2.20.51.0.2-version.patch Patch06: binutils-2.20.51.0.2-set-long-long.patch Patch07: binutils-2.20.51.0.2-build-id.patch -Patch08: binutils-2.20.51.0.2-copy-osabi.patch -Patch09: binutils-2.20.51.0.7-do-not-bind-unique-symbols-locally.patch -Patch10: binutils-2.20.51.0.7-dwarf4.patch -Patch11: binutils-2.20.51.0.7-unique-archive-symbols.patch -Patch12: binutils-2.20.51.0.7-gold-INPUT.patch +Patch08: binutils-2.20.51.0.10-copy-osabi.patch +Patch09: binutils-2.20.51.0.10-update-gold.patch %define gold_arches %ix86 x86_64 @@ -133,10 +130,7 @@ using libelf instead of BFD. %patch06 -p0 -b .set-long-long~ %patch07 -p0 -b .build-id~ %patch08 -p0 -b .copy-osabi~ -%patch09 -p0 -b .do-not-bind-unique~ -%patch10 -p0 -b .dwarf4~ -%patch11 -p0 -b .unique~ -%patch12 -p0 -b .gold-input~ +%patch09 -p0 -b .update-gold~ # We cannot run autotools as there is an exact requirement of autoconf-2.59. @@ -419,6 +413,10 @@ exit 0 %endif # %{isnative} %changelog +* Tue Aug 10 2010 Nick Clifton - 2.20.51.0.10-1 +- Rebase on 2.20.51.0.10 tarball. +- Import GOLD sources from binutils mainline as of 10 Aug 2010. + * Wed Jun 30 2010 Nick Clifton - 2.20.51.0.7-5 - Rename the binutils-static package to binutils-devel in line with the Fedora packaging guidelines. diff --git a/sources b/sources index 6baea8c..07f1d6c 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -8b2608344fc9750afe1ff37121681504 binutils-2.20.51.0.7.tar.bz2 +e7dfcff0aeb3e590f1403a761271103f binutils-2.20.51.0.10.tar.bz2