aboutsummaryrefslogtreecommitdiff
path: root/gold/script-sections.cc
diff options
context:
space:
mode:
authorCary Coutant <ccoutant@gmail.com>2015-08-26 00:03:04 -0700
committerCary Coutant <ccoutant@gmail.com>2015-08-26 00:03:04 -0700
commit7c61d651fd0e42b8f68840a3735ed7e46d4fd083 (patch)
treed17fe965b2c4f27550fc720f54fb2b204d77f44f /gold/script-sections.cc
parent4bfacfd359a1f8d026d1a350f56f2f5d70b6cb65 (diff)
downloadgdb-7c61d651fd0e42b8f68840a3735ed7e46d4fd083.zip
gdb-7c61d651fd0e42b8f68840a3735ed7e46d4fd083.tar.gz
gdb-7c61d651fd0e42b8f68840a3735ed7e46d4fd083.tar.bz2
Fix problem where script specified both address and region for a section.
If a script specifies both address and region for an output section declaration, gold ignores the region specification. This can lead to bogus "moves backward" errors. This patch fixes gold so that if a section specifies both address and region, it will place the section at the specified address in the region, and update the location counter within the region. gold/ PR gold/18847 * script-sections.cc (Memory_region::set_address): New method. (Script_sections::find_memory_region): Add explicit_only parameter. (Output_section_definition::set_section_addresses): Handle case where script specifies both address and vma region. * script-sections.h (Script_sections::find_memory_region): Add explicit_only parameter.
Diffstat (limited to 'gold/script-sections.cc')
-rw-r--r--gold/script-sections.cc61
1 files changed, 43 insertions, 18 deletions
diff --git a/gold/script-sections.cc b/gold/script-sections.cc
index 3e377aa..261e8e3 100644
--- a/gold/script-sections.cc
+++ b/gold/script-sections.cc
@@ -93,7 +93,23 @@ class Memory_region
script_exp_binary_add(this->start_,
script_exp_integer(this->current_offset_));
}
-
+
+ void
+ set_address(uint64_t addr, const Symbol_table* symtab, const Layout* layout)
+ {
+ uint64_t start = this->start_->eval(symtab, layout, false);
+ uint64_t len = this->length_->eval(symtab, layout, false);
+ if (addr < start || addr >= start + len)
+ gold_error(_("address 0x%llx is not within region %s"),
+ static_cast<unsigned long long>(addr),
+ this->name_.c_str());
+ else if (addr < start + this->current_offset_)
+ gold_error(_("address 0x%llx moves dot backwards in region %s"),
+ static_cast<unsigned long long>(addr),
+ this->name_.c_str());
+ this->current_offset_ = addr - start;
+ }
+
void
increment_offset(std::string section_name, uint64_t amount,
const Symbol_table* symtab, const Layout* layout)
@@ -105,7 +121,7 @@ class Memory_region
gold_error(_("section %s overflows end of region %s"),
section_name.c_str(), this->name_.c_str());
}
-
+
// Returns true iff there is room left in this region
// for AMOUNT more bytes of data.
bool
@@ -120,7 +136,7 @@ class Memory_region
// are compatible with this region's attributes.
bool
attributes_compatible(elfcpp::Elf_Xword flags, elfcpp::Elf_Xword type) const;
-
+
void
add_section(Output_section_definition* sec, bool vma)
{
@@ -2237,6 +2253,7 @@ Memory_region*
Script_sections::find_memory_region(
Output_section_definition* section,
bool find_vma_region,
+ bool explicit_only,
Output_section_definition** previous_section_return)
{
if (previous_section_return != NULL)
@@ -2282,15 +2299,18 @@ Script_sections::find_memory_region(
}
}
- // Make a note of the first memory region whose attributes
- // are compatible with the section. If we do not find an
- // explicit region assignment, then we will return this region.
- Output_section* out_sec = section->get_output_section();
- if (first_match == NULL
- && out_sec != NULL
- && (*mr)->attributes_compatible(out_sec->flags(),
- out_sec->type()))
- first_match = *mr;
+ if (!explicit_only)
+ {
+ // Make a note of the first memory region whose attributes
+ // are compatible with the section. If we do not find an
+ // explicit region assignment, then we will return this region.
+ Output_section* out_sec = section->get_output_section();
+ if (first_match == NULL
+ && out_sec != NULL
+ && (*mr)->attributes_compatible(out_sec->flags(),
+ out_sec->type()))
+ first_match = *mr;
+ }
}
// With LMA computations, if an explicit region has not been specified then
@@ -2350,8 +2370,7 @@ Output_section_definition::set_section_addresses(Symbol_table* symtab,
;
else if (this->address_ == NULL)
{
- vma_region = script_sections->find_memory_region(this, true, NULL);
-
+ vma_region = script_sections->find_memory_region(this, true, false, NULL);
if (vma_region != NULL)
address = vma_region->get_current_address()->eval(symtab, layout,
false);
@@ -2359,9 +2378,15 @@ Output_section_definition::set_section_addresses(Symbol_table* symtab,
address = *dot_value;
}
else
- address = this->address_->eval_with_dot(symtab, layout, true,
- *dot_value, NULL, NULL,
- dot_alignment, false);
+ {
+ vma_region = script_sections->find_memory_region(this, true, true, NULL);
+ address = this->address_->eval_with_dot(symtab, layout, true,
+ *dot_value, NULL, NULL,
+ dot_alignment, false);
+ if (vma_region != NULL)
+ vma_region->set_address(address, symtab, layout);
+ }
+
uint64_t align;
if (this->align_ == NULL)
{
@@ -2405,7 +2430,7 @@ Output_section_definition::set_section_addresses(Symbol_table* symtab,
Output_section_definition* previous_section;
// Determine if an LMA region has been set for this section.
- lma_region = script_sections->find_memory_region(this, false,
+ lma_region = script_sections->find_memory_region(this, false, false,
&previous_section);
if (lma_region != NULL)