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.
This commit is contained in:
parent
d5551862df
commit
a192ba0508
|
@ -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
|
||||
|
|
|
@ -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())
|
||||
{
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue