From 5bc2f5be52354dfebe40c35c519bf19e4332956a Mon Sep 17 00:00:00 2001 From: Cary Coutant Date: Mon, 18 Oct 2010 05:39:23 +0000 Subject: [PATCH] * output.h (Output_segment::set_section_addresses): Change function signature. Update all callers. * output.cc (Output_segment::is_first_section_relro): Ignore TLS sections. (Output_segment::set_section_addresses): Align after last TLS section. Add padding before last relro section instead of after. --- gold/ChangeLog | 9 +++++++++ gold/layout.cc | 4 ++-- gold/output.cc | 54 ++++++++++++++++++++++++++++++-------------------- gold/output.h | 2 +- 4 files changed, 45 insertions(+), 24 deletions(-) diff --git a/gold/ChangeLog b/gold/ChangeLog index b5ba411b7c3..a6e6ab6fbf0 100644 --- a/gold/ChangeLog +++ b/gold/ChangeLog @@ -1,3 +1,12 @@ +2010-10-17 Cary Coutant + + * output.h (Output_segment::set_section_addresses): Change function + signature. Update all callers. + * output.cc (Output_segment::is_first_section_relro): Ignore TLS + sections. + (Output_segment::set_section_addresses): Align after last TLS + section. Add padding before last relro section instead of after. + 2010-10-17 Doug Kwan * gold/arm.cc (Target_arm::got_section): Use correct order and set diff --git a/gold/layout.cc b/gold/layout.cc index 3df7d3d6fca..95f1de755a0 100644 --- a/gold/layout.cc +++ b/gold/layout.cc @@ -2658,7 +2658,7 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg, unsigned int shndx_hold = *pshndx; bool has_relro = false; uint64_t new_addr = (*p)->set_section_addresses(this, false, addr, - &increase_relro, + increase_relro, &has_relro, &off, pshndx); @@ -2688,7 +2688,7 @@ Layout::set_segment_offsets(const Target* target, Output_segment* load_seg, off = orig_off + ((addr - orig_addr) & (abi_pagesize - 1)); off = align_file_offset(off, addr, abi_pagesize); new_addr = (*p)->set_section_addresses(this, true, addr, - &increase_relro, + increase_relro, &has_relro, &off, pshndx); } diff --git a/gold/output.cc b/gold/output.cc index 4e7ad086757..1368c196b4f 100644 --- a/gold/output.cc +++ b/gold/output.cc @@ -3575,13 +3575,17 @@ Output_segment::has_any_data_sections() const return false; } -// Return whether the first data section is a relro section. +// Return whether the first data section (not counting TLS sections) +// is a relro section. bool Output_segment::is_first_section_relro() const { for (int i = 0; i < static_cast(ORDER_MAX); ++i) { + if (i == static_cast(ORDER_TLS_DATA) + || i == static_cast(ORDER_TLS_BSS)) + continue; const Output_data_list* pdl = &this->output_lists_[i]; if (!pdl->empty()) { @@ -3656,19 +3660,17 @@ Output_segment::has_dynamic_reloc_list(const Output_data_list* pdl) const // Set the section addresses for an Output_segment. If RESET is true, // reset the addresses first. ADDR is the address and *POFF is the // file offset. Set the section indexes starting with *PSHNDX. -// *PINCREASE_RELRO is the size of the portion of the first non-relro -// section that should be included in the PT_GNU_RELRO segment; if -// there is alignment padding between the last relro section and the -// next section, we add that padding to that size and return the -// updated value. If this segment has relro sections, and has been -// aligned for that purpose, set *HAS_RELRO to TRUE. -// Return the address of the immediately following segment. Update -// *PINCREASE_RELRO, *HAS_RELRO, *POFF, and *PSHNDX. +// INCREASE_RELRO is the size of the portion of the first non-relro +// section that should be included in the PT_GNU_RELRO segment. +// If this segment has relro sections, and has been aligned for +// that purpose, set *HAS_RELRO to TRUE. Return the address of +// the immediately following segment. Update *HAS_RELRO, *POFF, +// and *PSHNDX. uint64_t Output_segment::set_section_addresses(const Layout* layout, bool reset, uint64_t addr, - unsigned int* pincrease_relro, + unsigned int increase_relro, bool* has_relro, off_t* poff, unsigned int* pshndx) @@ -3678,6 +3680,8 @@ Output_segment::set_section_addresses(const Layout* layout, bool reset, uint64_t last_relro_pad = 0; off_t orig_off = *poff; + bool in_tls = false; + // If we have relro sections, we need to pad forward now so that the // relro sections plus INCREASE_RELRO end on a common page boundary. if (parameters->options().relro() @@ -3687,7 +3691,7 @@ Output_segment::set_section_addresses(const Layout* layout, bool reset, uint64_t relro_size = 0; off_t off = *poff; uint64_t max_align = 0; - for (int i = 0; i < static_cast(ORDER_MAX); ++i) + for (int i = 0; i <= static_cast(ORDER_RELRO_LAST); ++i) { Output_data_list* pdl = &this->output_lists_[i]; Output_data_list::iterator p; @@ -3695,13 +3699,23 @@ Output_segment::set_section_addresses(const Layout* layout, bool reset, { if (!(*p)->is_section()) break; - Output_section* pos = (*p)->output_section(); - if (!pos->is_relro()) - break; uint64_t align = (*p)->addralign(); if (align > max_align) max_align = align; + if ((*p)->is_section_flag_set(elfcpp::SHF_TLS)) + in_tls = true; + else if (in_tls) + { + // Align the first non-TLS section to the alignment + // of the TLS segment. + align = max_align; + in_tls = false; + } relro_size = align_address(relro_size, align); + // Ignore the size of the .tbss section. + if ((*p)->is_section_flag_set(elfcpp::SHF_TLS) + && (*p)->is_section_type(elfcpp::SHT_NOBITS)) + continue; if ((*p)->is_address_valid()) relro_size += (*p)->data_size(); else @@ -3716,14 +3730,12 @@ Output_segment::set_section_addresses(const Layout* layout, bool reset, if (p != pdl->end()) break; } - relro_size += *pincrease_relro; + relro_size += increase_relro; // Pad the total relro size to a multiple of the maximum // section alignment seen. uint64_t aligned_size = align_address(relro_size, max_align); // Note the amount of padding added after the last relro section. last_relro_pad = aligned_size - relro_size; - // Adjust *PINCREASE_RELRO to include the padding. - *pincrease_relro += last_relro_pad; *has_relro = true; uint64_t page_align = parameters->target().common_pagesize(); @@ -3749,7 +3761,7 @@ Output_segment::set_section_addresses(const Layout* layout, bool reset, this->are_addresses_set_ = true; } - bool in_tls = false; + in_tls = false; this->offset_ = orig_off; @@ -3757,14 +3769,14 @@ Output_segment::set_section_addresses(const Layout* layout, bool reset, 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_RELRO_LAST)) { *poff += last_relro_pad; addr += last_relro_pad; } + 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; diff --git a/gold/output.h b/gold/output.h index 52c69e9bd1e..d36d587ea19 100644 --- a/gold/output.h +++ b/gold/output.h @@ -3908,7 +3908,7 @@ class Output_segment // *PSHNDX. This should only be called for a PT_LOAD segment. uint64_t set_section_addresses(const Layout*, bool reset, uint64_t addr, - unsigned int* pincrease_relro, bool* has_relro, + unsigned int increase_relro, bool* has_relro, off_t* poff, unsigned int* pshndx); // Set the minimum alignment of this segment. This may be adjusted -- 2.30.2