Index: gold/script-sections.cc =================================================================== RCS file: /cvs/src/src/gold/script-sections.cc,v retrieving revision 1.22 diff -u -p -r1.22 script-sections.cc --- gold/script-sections.cc 9 Oct 2009 23:18:19 -0000 1.22 +++ gold/script-sections.cc 15 Oct 2009 08:46:55 -0000 @@ -2827,10 +2827,69 @@ Script_sections::set_section_addresses(S // For a relocatable link, we implicitly set dot to zero. uint64_t dot_value = 0; uint64_t load_address = 0; + + bool any_T_segment_address_set = + (parameters->options().user_set_Ttext() + || parameters->options().user_set_Tdata() + || parameters->options().user_set_Tbss()); + bool first_read_only_section_seen = false; + bool first_writable_section_seen = false; + bool first_nobits_section_seen = false; for (Sections_elements::iterator p = this->sections_elements_->begin(); p != this->sections_elements_->end(); ++p) - (*p)->set_section_addresses(symtab, layout, &dot_value, &load_address); + { + Output_section* os = (*p)->get_output_section(); + + // Handle -Ttext, -Tdata and -Tbss options. We do this by looking for + // the first section of the appropriate type for each of these segments + // and do a dot assignment right before that. + if (any_T_segment_address_set + && os != NULL + && (os->flags() & elfcpp::SHF_ALLOC) != 0) + { + uint64_t new_dot_value = dot_value; + + if (!first_read_only_section_seen + && (os->flags() & elfcpp::SHF_WRITE) == 0) + { + // We assume the segment containing the first read-only + // section to be the text segment. + if (parameters->options().user_set_Ttext()) + new_dot_value = parameters->options().Ttext(); + first_read_only_section_seen = true; + } + else if (!first_writable_section_seen + && (os->flags() & elfcpp::SHF_WRITE) != 0) + { + // We assume the segment containing the first writable + // section to be the data segment. + if (parameters->options().user_set_Tdata()) + new_dot_value = parameters->options().Tdata(); + first_writable_section_seen = true; + } + else if (!first_nobits_section_seen + && os->type() == elfcpp::SHT_NOBITS) + { + // We assume the segment containing the first NOBITS section to + // be the bss segment. + if (parameters->options().user_set_Tbss()) + new_dot_value = parameters->options().Tbss(); + first_nobits_section_seen = true; + } + + // Update dot and load address if necessary. + if (new_dot_value < dot_value) + gold_error(_("dot may not move backward")); + else if (new_dot_value != dot_value) + { + dot_value = new_dot_value; + load_address = new_dot_value; + } + } + + (*p)->set_section_addresses(symtab, layout, &dot_value, &load_address); + } if (this->phdrs_elements_ != NULL) { @@ -2995,6 +3054,14 @@ Script_sections::create_segments(Layout* // skipping a page. need_new_segment = true; } + else if (parameters->options().user_set_Tbss() + && !is_bss_section(*plast) + && is_bss_section(*p)) + { + // If -Tbss is specified, we need to separate the data and BSS + // segments. + need_new_segment = true; + } else if (is_bss_section(*plast) && !is_bss_section(*p)) { // A non-BSS section can not follow a BSS section in the