From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 7879 invoked by alias); 9 Jul 2011 06:35:38 -0000 Received: (qmail 7215 invoked by uid 22791); 9 Jul 2011 06:35:36 -0000 X-SWARE-Spam-Status: No, hits=-2.2 required=5.0 tests=AWL,BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,SPF_HELO_PASS,TW_VD,TW_VN,T_RP_MATCHES_RCVD,T_TVD_MIME_NO_HEADERS X-Spam-Check-By: sourceware.org Received: from smtp-out.google.com (HELO smtp-out.google.com) (216.239.44.51) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Sat, 09 Jul 2011 06:35:21 +0000 Received: from kpbe11.cbf.corp.google.com (kpbe11.cbf.corp.google.com [172.25.105.75]) by smtp-out.google.com with ESMTP id p696ZKD1024805 for ; Fri, 8 Jul 2011 23:35:20 -0700 Received: from pwi3 (pwi3.prod.google.com [10.241.219.3]) by kpbe11.cbf.corp.google.com with ESMTP id p696ZJko018228 (version=TLSv1/SSLv3 cipher=RC4-SHA bits=128 verify=NOT) for ; Fri, 8 Jul 2011 23:35:19 -0700 Received: by pwi3 with SMTP id 3so2553315pwi.22 for ; Fri, 08 Jul 2011 23:35:19 -0700 (PDT) Received: by 10.68.50.40 with SMTP id z8mr4355292pbn.204.1310193318854; Fri, 08 Jul 2011 23:35:18 -0700 (PDT) Received: from coign.google.com ([216.239.45.130]) by mx.google.com with ESMTPS id b4sm3913588pba.75.2011.07.08.23.35.17 (version=TLSv1/SSLv3 cipher=OTHER); Fri, 08 Jul 2011 23:35:18 -0700 (PDT) From: Ian Lance Taylor To: binutils@sourceware.org Subject: gold patch committed: Don't crash with weird linker script Date: Sat, 09 Jul 2011 10:53:00 -0000 Message-ID: User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/23.1 (gnu/linux) MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" X-System-Of-Record: true X-IsSubscribed: yes Mailing-List: contact binutils-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: binutils-owner@sourceware.org X-SW-Source: 2011-07/txt/msg00102.txt.bz2 --=-=-= Content-length: 824 In PR 11985 Nick asks what gold should do when using a weird linker script which discards key sections. I suppose I think that the general goal should be to honor the linker script as much as possible. That is what this patch does: if the linker script discards sections like .dynamic or .interp, gold just carries on and does the best it can. Committed to mainline. Ian 2011-07-08 Ian Lance Taylor PR gold/11985 * layout.cc (Layout::create_initial_dynamic_sections): Don't crash if linker script discards key sections. (Layout::create_dynamic_symtab): Likewise. (Layout::assign_local_dynsym_offsets): Likewise. (Layout::sized_create_version_sections): Likewise. (Layout::create_interp): Likewise. (Layout::finish_dynamic_section): Likewise. (Layout::set_dynamic_symbol_size): Likewise. --=-=-= Content-Type: text/x-diff Content-Disposition: inline; filename=foo.patch Content-Description: patch Content-length: 12664 Index: layout.cc =================================================================== RCS file: /cvs/src/src/gold/layout.cc,v retrieving revision 1.213 diff -p -u -r1.213 layout.cc --- layout.cc 8 Jul 2011 22:48:08 -0000 1.213 +++ layout.cc 9 Jul 2011 06:30:56 -0000 @@ -1786,15 +1786,20 @@ Layout::create_initial_dynamic_sections( false, ORDER_RELRO, true); - this->dynamic_symbol_ = - symtab->define_in_output_data("_DYNAMIC", NULL, Symbol_table::PREDEFINED, - this->dynamic_section_, 0, 0, - elfcpp::STT_OBJECT, elfcpp::STB_LOCAL, - elfcpp::STV_HIDDEN, 0, false, false); + // A linker script may discard .dynamic, so check for NULL. + if (this->dynamic_section_ != NULL) + { + this->dynamic_symbol_ = + symtab->define_in_output_data("_DYNAMIC", NULL, + Symbol_table::PREDEFINED, + this->dynamic_section_, 0, 0, + elfcpp::STT_OBJECT, elfcpp::STB_LOCAL, + elfcpp::STV_HIDDEN, 0, false, false); - this->dynamic_data_ = new Output_data_dynamic(&this->dynpool_); + this->dynamic_data_ = new Output_data_dynamic(&this->dynpool_); - this->dynamic_section_->add_output_section_data(this->dynamic_data_); + this->dynamic_section_->add_output_section_data(this->dynamic_data_); + } } // For each output section whose name can be represented as C symbol, @@ -3708,20 +3713,27 @@ Layout::create_dynamic_symtab(const Inpu ORDER_DYNAMIC_LINKER, false); - Output_section_data* odata = new Output_data_fixed_space(index * symsize, - align, - "** dynsym"); - dynsym->add_output_section_data(odata); - - dynsym->set_info(local_symcount); - dynsym->set_entsize(symsize); - dynsym->set_addralign(align); + // Check for NULL as a linker script may discard .dynsym. + if (dynsym != NULL) + { + Output_section_data* odata = new Output_data_fixed_space(index * symsize, + align, + "** dynsym"); + dynsym->add_output_section_data(odata); + + dynsym->set_info(local_symcount); + dynsym->set_entsize(symsize); + dynsym->set_addralign(align); - this->dynsym_section_ = dynsym; + this->dynsym_section_ = dynsym; + } Output_data_dynamic* const odyn = this->dynamic_data_; - odyn->add_section_address(elfcpp::DT_SYMTAB, dynsym); - odyn->add_constant(elfcpp::DT_SYMENT, symsize); + if (odyn != NULL) + { + odyn->add_section_address(elfcpp::DT_SYMTAB, dynsym); + odyn->add_constant(elfcpp::DT_SYMENT, symsize); + } // If there are more than SHN_LORESERVE allocated sections, we // create a .dynsym_shndx section. It is possible that we don't @@ -3738,20 +3750,23 @@ Layout::create_dynamic_symtab(const Inpu elfcpp::SHF_ALLOC, false, ORDER_DYNAMIC_LINKER, false); - this->dynsym_xindex_ = new Output_symtab_xindex(index); + if (dynsym_xindex != NULL) + { + this->dynsym_xindex_ = new Output_symtab_xindex(index); - dynsym_xindex->add_output_section_data(this->dynsym_xindex_); + dynsym_xindex->add_output_section_data(this->dynsym_xindex_); - dynsym_xindex->set_link_section(dynsym); - dynsym_xindex->set_addralign(4); - dynsym_xindex->set_entsize(4); + dynsym_xindex->set_link_section(dynsym); + dynsym_xindex->set_addralign(4); + dynsym_xindex->set_entsize(4); - dynsym_xindex->set_after_input_sections(); + dynsym_xindex->set_after_input_sections(); - // This tells the driver code to wait until the symbol table has - // written out before writing out the postprocessing sections, - // including the .dynsym_shndx section. - this->any_postprocessing_sections_ = true; + // This tells the driver code to wait until the symbol table + // has written out before writing out the postprocessing + // sections, including the .dynsym_shndx section. + this->any_postprocessing_sections_ = true; + } } // Create the dynamic string table section. @@ -3763,16 +3778,24 @@ Layout::create_dynamic_symtab(const Inpu ORDER_DYNAMIC_LINKER, false); - Output_section_data* strdata = new Output_data_strtab(&this->dynpool_); - dynstr->add_output_section_data(strdata); + if (dynstr != NULL) + { + Output_section_data* strdata = new Output_data_strtab(&this->dynpool_); + dynstr->add_output_section_data(strdata); - dynsym->set_link_section(dynstr); - this->dynamic_section_->set_link_section(dynstr); + if (dynsym != NULL) + dynsym->set_link_section(dynstr); + if (this->dynamic_section_ != NULL) + this->dynamic_section_->set_link_section(dynstr); - odyn->add_section_address(elfcpp::DT_STRTAB, dynstr); - odyn->add_section_size(elfcpp::DT_STRSZ, dynstr); + if (odyn != NULL) + { + odyn->add_section_address(elfcpp::DT_STRTAB, dynstr); + odyn->add_section_size(elfcpp::DT_STRSZ, dynstr); + } - *pdynstr = dynstr; + *pdynstr = dynstr; + } // Create the hash tables. @@ -3793,12 +3816,18 @@ Layout::create_dynamic_symtab(const Inpu hashlen, align, "** hash"); - hashsec->add_output_section_data(hashdata); + if (hashsec != NULL && hashdata != NULL) + hashsec->add_output_section_data(hashdata); - hashsec->set_link_section(dynsym); - hashsec->set_entsize(4); + if (hashsec != NULL) + { + if (dynsym != NULL) + hashsec->set_link_section(dynsym); + hashsec->set_entsize(4); + } - odyn->add_section_address(elfcpp::DT_HASH, hashsec); + if (odyn != NULL) + odyn->add_section_address(elfcpp::DT_HASH, hashsec); } if (strcmp(parameters->options().hash_style(), "gnu") == 0 @@ -3818,17 +3847,23 @@ Layout::create_dynamic_symtab(const Inpu hashlen, align, "** hash"); - hashsec->add_output_section_data(hashdata); + if (hashsec != NULL && hashdata != NULL) + hashsec->add_output_section_data(hashdata); - hashsec->set_link_section(dynsym); + if (hashsec != NULL) + { + if (dynsym != NULL) + hashsec->set_link_section(dynsym); - // For a 64-bit target, the entries in .gnu.hash do not have a - // uniform size, so we only set the entry size for a 32-bit - // target. - if (parameters->target().get_size() == 32) - hashsec->set_entsize(4); + // For a 64-bit target, the entries in .gnu.hash do not have + // a uniform size, so we only set the entry size for a + // 32-bit target. + if (parameters->target().get_size() == 32) + hashsec->set_entsize(4); - odyn->add_section_address(elfcpp::DT_GNU_HASH, hashsec); + if (odyn != NULL) + odyn->add_section_address(elfcpp::DT_GNU_HASH, hashsec); + } } } @@ -3838,7 +3873,8 @@ void Layout::assign_local_dynsym_offsets(const Input_objects* input_objects) { Output_section* dynsym = this->dynsym_section_; - gold_assert(dynsym != NULL); + if (dynsym == NULL) + return; off_t off = dynsym->offset(); @@ -3919,46 +3955,59 @@ Layout::sized_create_version_sections( ORDER_DYNAMIC_LINKER, false); - unsigned char* vbuf; - unsigned int vsize; - versions->symbol_section_contents(symtab, &this->dynpool_, - local_symcount, - dynamic_symbols, - &vbuf, &vsize); - - Output_section_data* vdata = new Output_data_const_buffer(vbuf, vsize, 2, - "** versions"); - - vsec->add_output_section_data(vdata); - vsec->set_entsize(2); - vsec->set_link_section(this->dynsym_section_); + // Check for NULL since a linker script may discard this section. + if (vsec != NULL) + { + unsigned char* vbuf; + unsigned int vsize; + versions->symbol_section_contents(symtab, + &this->dynpool_, + local_symcount, + dynamic_symbols, + &vbuf, &vsize); + + Output_section_data* vdata = new Output_data_const_buffer(vbuf, vsize, 2, + "** versions"); + + vsec->add_output_section_data(vdata); + vsec->set_entsize(2); + vsec->set_link_section(this->dynsym_section_); + } Output_data_dynamic* const odyn = this->dynamic_data_; - odyn->add_section_address(elfcpp::DT_VERSYM, vsec); + if (odyn != NULL && vsec != NULL) + odyn->add_section_address(elfcpp::DT_VERSYM, vsec); if (versions->any_defs()) { Output_section* vdsec; - 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; - unsigned int vdentries; - versions->def_section_contents(&this->dynpool_, &vdbuf, - &vdsize, &vdentries); - - Output_section_data* vddata = - new Output_data_const_buffer(vdbuf, vdsize, 4, "** version defs"); - - vdsec->add_output_section_data(vddata); - vdsec->set_link_section(dynstr); - vdsec->set_info(vdentries); + vdsec = this->choose_output_section(NULL, ".gnu.version_d", + elfcpp::SHT_GNU_verdef, + elfcpp::SHF_ALLOC, + false, ORDER_DYNAMIC_LINKER, false); - odyn->add_section_address(elfcpp::DT_VERDEF, vdsec); - odyn->add_constant(elfcpp::DT_VERDEFNUM, vdentries); + if (vdsec != NULL) + { + unsigned char* vdbuf; + unsigned int vdsize; + unsigned int vdentries; + versions->def_section_contents(&this->dynpool_, + &vdbuf, &vdsize, + &vdentries); + + Output_section_data* vddata = + new Output_data_const_buffer(vdbuf, vdsize, 4, "** version defs"); + + vdsec->add_output_section_data(vddata); + vdsec->set_link_section(dynstr); + vdsec->set_info(vdentries); + + if (odyn != NULL) + { + odyn->add_section_address(elfcpp::DT_VERDEF, vdsec); + odyn->add_constant(elfcpp::DT_VERDEFNUM, vdentries); + } + } } if (versions->any_needs()) @@ -3969,22 +4018,28 @@ Layout::sized_create_version_sections( elfcpp::SHF_ALLOC, false, ORDER_DYNAMIC_LINKER, false); - unsigned char* vnbuf; - unsigned int vnsize; - unsigned int vnentries; - versions->need_section_contents(&this->dynpool_, - &vnbuf, &vnsize, - &vnentries); - - Output_section_data* vndata = - new Output_data_const_buffer(vnbuf, vnsize, 4, "** version refs"); - - vnsec->add_output_section_data(vndata); - vnsec->set_link_section(dynstr); - vnsec->set_info(vnentries); + if (vnsec != NULL) + { + unsigned char* vnbuf; + unsigned int vnsize; + unsigned int vnentries; + versions->need_section_contents(&this->dynpool_, + &vnbuf, &vnsize, + &vnentries); + + Output_section_data* vndata = + new Output_data_const_buffer(vnbuf, vnsize, 4, "** version refs"); + + vnsec->add_output_section_data(vndata); + vnsec->set_link_section(dynstr); + vnsec->set_info(vnentries); - odyn->add_section_address(elfcpp::DT_VERNEED, vnsec); - odyn->add_constant(elfcpp::DT_VERNEEDNUM, vnentries); + if (odyn != NULL) + { + odyn->add_section_address(elfcpp::DT_VERNEED, vnsec); + odyn->add_constant(elfcpp::DT_VERNEEDNUM, vnentries); + } + } } } @@ -4011,7 +4066,8 @@ Layout::create_interp(const Target* targ elfcpp::SHF_ALLOC, false, ORDER_INTERP, false); - osec->add_output_section_data(odata); + if (osec != NULL) + osec->add_output_section_data(odata); } // Add dynamic tags for the PLT and the dynamic relocs. This is @@ -4117,7 +4173,8 @@ void Layout::finish_dynamic_section(const Input_objects* input_objects, const Symbol_table* symtab) { - if (!this->script_options_->saw_phdrs_clause()) + if (!this->script_options_->saw_phdrs_clause() + && this->dynamic_section_ != NULL) { Output_segment* oseg = this->make_output_segment(elfcpp::PT_DYNAMIC, (elfcpp::PF_R @@ -4127,6 +4184,8 @@ Layout::finish_dynamic_section(const Inp } Output_data_dynamic* const odyn = this->dynamic_data_; + if (odyn == NULL) + return; for (Input_objects::Dynobj_iterator p = input_objects->dynobj_begin(); p != input_objects->dynobj_end(); @@ -4322,7 +4381,11 @@ void Layout::set_dynamic_symbol_size(const Symbol_table* symtab) { Output_data_dynamic* const odyn = this->dynamic_data_; + if (odyn == NULL) + return; odyn->finalize_data_size(); + if (this->dynamic_symbol_ == NULL) + return; off_t data_size = odyn->data_size(); const int size = parameters->target().get_size(); if (size == 32) --=-=-=--