* options.cc (General_options::parse_section_start): New function.
	(General_options::section_start): New function.
	(General_options::General_options): Initialize all members.
	* options.h: Include <map>
	(class General_options): Add --section-start.  Add section_starts_
	member.
	* layout.cc (Layout::attach_allocated_section_to_segment): If
	--section-start was used, set the address of the segment.  Remove
	local sort_sections.
	(Layout::relaxation_loop_body): If the address of the load segment
	has been set by --section-start, don't use it.
	* output.h (Output_segment::update_flags_for_output_section): New
	function.
	* output.cc (Output_segment::add_output_section): Call
	update_flags_for_output_section.
This commit is contained in:
Ian Lance Taylor 2010-01-06 22:37:18 +00:00
parent d5551862df
commit a192ba0508
6 changed files with 141 additions and 15 deletions

View File

@ -1,3 +1,22 @@
2010-01-06 Ian Lance Taylor <iant@google.com>
PR 10980
* options.cc (General_options::parse_section_start): New function.
(General_options::section_start): New function.
(General_options::General_options): Initialize all members.
* options.h: Include <map>
(class General_options): Add --section-start. Add section_starts_
member.
* layout.cc (Layout::attach_allocated_section_to_segment): If
--section-start was used, set the address of the segment. Remove
local sort_sections.
(Layout::relaxation_loop_body): If the address of the load segment
has been set by --section-start, don't use it.
* output.h (Output_segment::update_flags_for_output_section): New
function.
* output.cc (Output_segment::add_output_section): Call
update_flags_for_output_section.
2010-01-05 Ian Lance Taylor <iant@google.com>
PR 10980

View File

@ -1025,7 +1025,9 @@ Layout::attach_allocated_section_to_segment(Output_section* os)
elfcpp::Elf_Word seg_flags = Layout::section_flags_to_segment(flags);
bool sort_sections = !this->script_options_->saw_sections_clause();
// Check for --section-start.
uint64_t addr;
bool is_address_set = parameters->options().section_start(os->name(), &addr);
// In general the only thing we really care about for PT_LOAD
// segments is whether or not they are writable, so that is how we
@ -1054,7 +1056,18 @@ Layout::attach_allocated_section_to_segment(Output_section* os)
if (os->is_large_data_section() && !(*p)->is_large_data_segment())
continue;
(*p)->add_output_section(os, seg_flags, sort_sections);
if (is_address_set)
{
if ((*p)->are_addresses_set())
continue;
(*p)->add_initial_output_data(os);
(*p)->update_flags_for_output_section(seg_flags);
(*p)->set_addresses(addr, addr);
break;
}
(*p)->add_output_section(os, seg_flags, true);
break;
}
@ -1064,7 +1077,9 @@ Layout::attach_allocated_section_to_segment(Output_section* os)
seg_flags);
if (os->is_large_data_section())
oseg->set_is_large_data_segment();
oseg->add_output_section(os, seg_flags, sort_sections);
oseg->add_output_section(os, seg_flags, true);
if (is_address_set)
oseg->set_addresses(addr, addr);
}
// If we see a loadable SHT_NOTE section, we create a PT_NOTE
@ -1492,6 +1507,14 @@ Layout::relaxation_loop_body(
|| load_seg != NULL
|| 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())
{

View File

@ -398,6 +398,63 @@ General_options::parse_just_symbols(const char*, const char* arg,
cmdline->inputs().add_file(file);
}
// Handle --section-start.
void
General_options::parse_section_start(const char*, const char* arg,
Command_line*)
{
const char* eq = strchr(arg, '=');
if (eq == NULL)
{
gold_error(_("invalid argument to --section-start; "
"must be SECTION=ADDRESS"));
return;
}
std::string section_name(arg, eq - arg);
++eq;
const char* val_start = eq;
if (eq[0] == '0' && (eq[1] == 'x' || eq[1] == 'X'))
eq += 2;
if (*eq == '\0')
{
gold_error(_("--section-start address missing"));
return;
}
uint64_t addr = 0;
hex_init();
for (; *eq != '\0'; ++eq)
{
if (!hex_p(*eq))
{
gold_error(_("--section-start argument %s is not a valid hex number"),
val_start);
return;
}
addr <<= 4;
addr += hex_value(*eq);
}
this->section_starts_[section_name] = addr;
}
// Look up a --section-start value.
bool
General_options::section_start(const char* secname, uint64_t* paddr) const
{
if (this->section_starts_.empty())
return false;
std::map<std::string, uint64_t>::const_iterator p =
this->section_starts_.find(secname);
if (p == this->section_starts_.end())
return false;
*paddr = p->second;
return true;
}
void
General_options::parse_static(const char*, const char*, Command_line*)
{
@ -749,9 +806,17 @@ namespace gold
General_options::General_options()
: printed_version_(false),
execstack_status_(General_options::EXECSTACK_FROM_INPUT), static_(false),
do_demangle_(false), plugins_(),
incremental_disposition_(INCREMENTAL_CHECK), implicit_incremental_(false)
execstack_status_(EXECSTACK_FROM_INPUT),
icf_status_(ICF_NONE),
static_(false),
do_demangle_(false),
plugins_(NULL),
dynamic_list_(),
incremental_disposition_(INCREMENTAL_CHECK),
implicit_incremental_(false),
excluded_libs_(),
symbols_to_retain_(),
section_starts_()
{
// Turn off option registration once construction is complete.
gold::options::ready_to_register = false;

View File

@ -39,6 +39,7 @@
#include <cstdlib>
#include <cstring>
#include <list>
#include <map>
#include <string>
#include <vector>
@ -845,6 +846,9 @@ class General_options
N_("Add DIR to link time shared library search path"),
N_("DIR"));
DEFINE_special(section_start, options::TWO_DASHES, '\0',
N_("Set address of section"), N_("SECTION=ADDRESS"));
DEFINE_optional_string(sort_common, options::TWO_DASHES, '\0', NULL,
N_("Sort common symbols by alignment"),
N_("[={ascending,descending}]"));
@ -1174,6 +1178,12 @@ class General_options
bool
check_excluded_libs (const std::string &s) const;
// If an explicit start address was given for section SECNAME with
// the --section-start option, return true and set *PADDR to the
// address. Otherwise return false.
bool
section_start(const char* secname, uint64_t* paddr) const;
private:
// Don't copy this structure.
General_options(const General_options&);
@ -1261,6 +1271,8 @@ class General_options
Unordered_set<std::string> excluded_libs_;
// List of symbol-names to keep, via -retain-symbol-info.
Unordered_set<std::string> symbols_to_retain_;
// Map from section name to address from --section-start.
std::map<std::string, uint64_t> section_starts_;
};
// The position-dependent options. We use this to store the state of

View File

@ -3081,11 +3081,7 @@ Output_segment::add_output_section(Output_section* os,
gold_assert(os->is_large_data_section() == this->is_large_data_segment());
gold_assert(this->type() == elfcpp::PT_LOAD || !do_sort);
// Update the segment flags. The ELF ABI specifies that a PT_TLS
// segment should always have PF_R as the flags, regardless of the
// associated sections.
if (this->type() != elfcpp::PT_TLS)
this->flags_ |= seg_flags;
this->update_flags_for_output_section(seg_flags);
Output_segment::Output_data_list* pdl;
if (os->type() == elfcpp::SHT_NOBITS)
@ -3363,8 +3359,8 @@ Output_segment::remove_output_section(Output_section* os)
gold_unreachable();
}
// Add an Output_data (which is not an Output_section) to the start of
// a segment.
// Add an Output_data (which need not be an Output_section) to the
// start of a segment.
void
Output_segment::add_initial_output_data(Output_data* od)

View File

@ -3483,8 +3483,8 @@ class Output_segment
void
remove_output_section(Output_section* os);
// Add an Output_data (which is not an Output_section) to the start
// of this segment.
// Add an Output_data (which need not be an Output_section) to the
// start of this segment.
void
add_initial_output_data(Output_data*);
@ -3516,6 +3516,17 @@ class Output_segment
this->are_addresses_set_ = true;
}
// Update the flags for the flags of an output section added to this
// segment.
void
update_flags_for_output_section(elfcpp::Elf_Xword flags)
{
// The ELF ABI specifies that a PT_TLS segment should always have
// PF_R as the flags.
if (this->type() != elfcpp::PT_TLS)
this->flags_ |= flags;
}
// Set the segment flags. This is only used if we have a PHDRS
// clause which explicitly specifies the flags.
void