const Symbol_table* symtab;
// The layout--we use this to get section information.
const Layout* layout;
+ // Whether to check assertions.
+ bool check_assertions;
// Whether expressions can refer to the dot symbol. The dot symbol
// is only available within a SECTIONS clause.
bool is_dot_available;
// Evaluate an expression.
uint64_t
-Expression::eval(const Symbol_table* symtab, const Layout* layout)
+Expression::eval(const Symbol_table* symtab, const Layout* layout,
+ bool check_assertions)
{
Output_section* dummy;
- return this->eval_maybe_dot(symtab, layout, false, 0, NULL, &dummy);
+ return this->eval_maybe_dot(symtab, layout, check_assertions,
+ false, 0, NULL, &dummy);
}
// Evaluate an expression which may refer to the dot symbol.
uint64_t
Expression::eval_with_dot(const Symbol_table* symtab, const Layout* layout,
- uint64_t dot_value, Output_section* dot_section,
+ bool check_assertions, uint64_t dot_value,
+ Output_section* dot_section,
Output_section** result_section_pointer)
{
- return this->eval_maybe_dot(symtab, layout, true, dot_value, dot_section,
- result_section_pointer);
+ return this->eval_maybe_dot(symtab, layout, check_assertions, true,
+ dot_value, dot_section, result_section_pointer);
}
// Evaluate an expression which may or may not refer to the dot
uint64_t
Expression::eval_maybe_dot(const Symbol_table* symtab, const Layout* layout,
- bool is_dot_available, uint64_t dot_value,
- Output_section* dot_section,
+ bool check_assertions, bool is_dot_available,
+ uint64_t dot_value, Output_section* dot_section,
Output_section** result_section_pointer)
{
Expression_eval_info eei;
eei.symtab = symtab;
eei.layout = layout;
+ eei.check_assertions = check_assertions;
eei.is_dot_available = is_dot_available;
eei.dot_value = dot_value;
eei.dot_section = dot_section;
Output_section** arg_section_pointer) const
{
return this->arg_->eval_maybe_dot(eei->symtab, eei->layout,
+ eei->check_assertions,
eei->is_dot_available,
eei->dot_value,
eei->dot_section,
Output_section** section_pointer) const
{
return this->left_->eval_maybe_dot(eei->symtab, eei->layout,
+ eei->check_assertions,
eei->is_dot_available,
eei->dot_value,
eei->dot_section,
Output_section** section_pointer) const
{
return this->right_->eval_maybe_dot(eei->symtab, eei->layout,
+ eei->check_assertions,
eei->is_dot_available,
eei->dot_value,
eei->dot_section,
Output_section** section_pointer) const
{
return this->arg1_->eval_maybe_dot(eei->symtab, eei->layout,
+ eei->check_assertions,
eei->is_dot_available,
eei->dot_value,
eei->dot_section,
Output_section** section_pointer) const
{
return this->arg1_->eval_maybe_dot(eei->symtab, eei->layout,
+ eei->check_assertions,
eei->is_dot_available,
eei->dot_value,
eei->dot_section,
Output_section** section_pointer) const
{
return this->arg1_->eval_maybe_dot(eei->symtab, eei->layout,
+ eei->check_assertions,
eei->is_dot_available,
eei->dot_value,
eei->dot_section,
value(const Expression_eval_info* eei)
{
uint64_t value = this->arg_value(eei, eei->result_section_pointer);
- if (!value)
+ if (!value && eei->check_assertions)
gold_error("%s", this->message_.c_str());
return value;
}
virtual ~Sections_element()
{ }
+ // Create any required output sections. The only real
+ // implementation is in Output_section_definition.
+ virtual void
+ create_sections(Layout*)
+ { }
+
// Add any symbol being defined to the symbol table.
virtual void
add_symbols_to_table(Symbol_table*)
// output section definition the dot symbol is always considered
// to be absolute.
Output_section* dummy;
- *dot_value = this->val_->eval_with_dot(symtab, layout, *dot_value,
+ *dot_value = this->val_->eval_with_dot(symtab, layout, true, *dot_value,
NULL, &dummy);
}
uint64_t* dot_value, uint64_t* load_address)
{
Output_section* dummy;
- *dot_value = this->val_->eval_with_dot(symtab, layout, *dot_value,
+ *dot_value = this->val_->eval_with_dot(symtab, layout, false, *dot_value,
NULL, &dummy);
*load_address = *dot_value;
}
virtual ~Output_section_element()
{ }
+ // Return whether this element requires an output section to exist.
+ virtual bool
+ needs_output_section() const
+ { return false; }
+
// Add any symbol being defined to the symbol table.
virtual void
add_symbols_to_table(Symbol_table*)
finalize_symbols(Symbol_table* symtab, const Layout* layout,
uint64_t* dot_value, Output_section** dot_section)
{
- *dot_value = this->val_->eval_with_dot(symtab, layout, *dot_value,
+ *dot_value = this->val_->eval_with_dot(symtab, layout, true, *dot_value,
*dot_section, dot_section);
}
std::string* fill,
Input_section_list*)
{
- uint64_t next_dot = this->val_->eval_with_dot(symtab, layout, *dot_value,
- *dot_section, dot_section);
+ uint64_t next_dot = this->val_->eval_with_dot(symtab, layout, false,
+ *dot_value, *dot_section,
+ dot_section);
if (next_dot < *dot_value)
gold_error(_("dot may not move backward"));
if (next_dot > *dot_value && output_section != NULL)
{
Output_section* dummy;
uint64_t val = this->val_->eval_with_dot(this->symtab_, this->layout_,
- this->dot_value_,
+ true, this->dot_value_,
this->dot_section_, &dummy);
if (parameters->target().is_big_endian())
: size_(size), is_signed_(is_signed), val_(val)
{ }
+ // If there is a data item, then we must create an output section.
+ bool
+ needs_output_section() const
+ { return true; }
+
// Finalize symbols--we just need to update dot.
void
finalize_symbols(Symbol_table*, const Layout*, uint64_t* dot_value,
std::string* fill, Input_section_list*)
{
Output_section* fill_section;
- uint64_t fill_val = this->val_->eval_with_dot(symtab, layout,
+ uint64_t fill_val = this->val_->eval_with_dot(symtab, layout, false,
*dot_value, *dot_section,
&fill_section);
if (fill_section != NULL)
void
add_input_section(const Input_section_spec* spec, bool keep);
+ // Create any required output sections.
+ void
+ create_sections(Layout*);
+
// Add any symbols being defined to the symbol table.
void
add_symbols_to_table(Symbol_table* symtab);
this->elements_.push_back(p);
}
+// Create any required output sections. We need an output section if
+// there is a data statement here.
+
+void
+Output_section_definition::create_sections(Layout* layout)
+{
+ if (this->output_section_ != NULL)
+ return;
+ for (Output_section_elements::const_iterator p = this->elements_.begin();
+ p != this->elements_.end();
+ ++p)
+ {
+ if ((*p)->needs_output_section())
+ {
+ const char* name = this->name_.c_str();
+ this->output_section_ = layout->make_output_section_for_script(name);
+ return;
+ }
+ }
+}
+
// Add any symbols being defined to the symbol table.
void
if (this->address_ != NULL)
{
Output_section* dummy;
- address = this->address_->eval_with_dot(symtab, layout,
+ address = this->address_->eval_with_dot(symtab, layout, true,
*dot_value, NULL,
&dummy);
}
if (this->align_ != NULL)
{
Output_section* dummy;
- uint64_t align = this->align_->eval_with_dot(symtab, layout,
+ uint64_t align = this->align_->eval_with_dot(symtab, layout, true,
*dot_value,
NULL,
&dummy);
else
{
Output_section* dummy;
- address = this->address_->eval_with_dot(symtab, layout, *dot_value,
- NULL, &dummy);
+ address = this->address_->eval_with_dot(symtab, layout, true,
+ *dot_value, NULL, &dummy);
}
uint64_t align;
else
{
Output_section* align_section;
- align = this->align_->eval_with_dot(symtab, layout, *dot_value,
+ align = this->align_->eval_with_dot(symtab, layout, true, *dot_value,
NULL, &align_section);
if (align_section != NULL)
gold_warning(_("alignment of section %s is not absolute"),
{
Output_section* dummy;
uint64_t load_address =
- this->load_address_->eval_with_dot(symtab, layout, *dot_value,
+ this->load_address_->eval_with_dot(symtab, layout, true, *dot_value,
this->output_section_, &dummy);
this->output_section_->set_load_address(load_address);
}
else
{
Output_section* subalign_section;
- subalign = this->subalign_->eval_with_dot(symtab, layout, *dot_value,
- NULL, &subalign_section);
+ subalign = this->subalign_->eval_with_dot(symtab, layout, true,
+ *dot_value, NULL,
+ &subalign_section);
if (subalign_section != NULL)
gold_warning(_("subalign of section %s is not absolute"),
this->name_.c_str());
// FIXME: The GNU linker supports fill values of arbitrary
// length.
Output_section* fill_section;
- uint64_t fill_val = this->fill_->eval_with_dot(symtab, layout,
+ uint64_t fill_val = this->fill_->eval_with_dot(symtab, layout, true,
*dot_value,
NULL,
&fill_section);
eval_load_address(Symbol_table* symtab, Layout* layout)
{
if (this->load_address_ != NULL)
- this->load_address_value_ = this->load_address_->eval(symtab, layout);
+ this->load_address_value_ = this->load_address_->eval(symtab, layout,
+ true);
}
// Return the load address.
this->output_section_->add_input_section(spec, keep);
}
+// Create any required sections.
+
+void
+Script_sections::create_sections(Layout* layout)
+{
+ if (!this->saw_sections_clause_)
+ return;
+ for (Sections_elements::iterator p = this->sections_elements_->begin();
+ p != this->sections_elements_->end();
+ ++p)
+ (*p)->create_sections(layout);
+}
+
// Add any symbols we are defining to the symbol table.
void
// efficient in any case. We try to use the first PT_LOAD segment
// if we can, otherwise we make a new one.
+ if (first_seg == NULL)
+ return NULL;
+
size_t sizeof_headers = this->total_header_size(layout);
- if (first_seg != NULL
- && (first_seg->paddr() & (abi_pagesize - 1)) >= sizeof_headers)
+ if ((first_seg->paddr() & (abi_pagesize - 1)) >= sizeof_headers)
{
first_seg->set_addresses(first_seg->vaddr() - sizeof_headers,
first_seg->paddr() - sizeof_headers);
return first_seg;
}
+ uint64_t vma = first_seg->vaddr();
+ uint64_t lma = first_seg->paddr();
+
+ uint64_t subtract = this->header_size_adjustment(lma, sizeof_headers);
+
+ // If there is no room to squeeze in the headers, then punt. The
+ // resulting executable probably won't run on GNU/Linux, but we
+ // trust that the user knows what they are doing.
+ if (lma < subtract || vma < subtract)
+ return NULL;
+
Output_segment* load_seg = layout->make_output_segment(elfcpp::PT_LOAD,
elfcpp::PF_R);
- if (first_seg == NULL)
- load_seg->set_addresses(0, 0);
- else
- {
- uint64_t vma = first_seg->vaddr();
- uint64_t lma = first_seg->paddr();
-
- uint64_t subtract = this->header_size_adjustment(lma, sizeof_headers);
- if (lma >= subtract && vma >= subtract)
- load_seg->set_addresses(vma - subtract, lma - subtract);
- else
- {
- // We could handle this case by create the file header
- // outside of any PT_LOAD segment, and creating a new
- // PT_LOAD segment after the others to hold the segment
- // headers.
- gold_error(_("sections loaded on first page without room for "
- "file and program headers are not supported"));
- }
- }
+ load_seg->set_addresses(vma - subtract, lma - subtract);
return load_seg;
}
{ }
// Return the value of the expression which is not permitted to
- // refer to the dot symbol.
+ // refer to the dot symbol. CHECK_ASSERTIONS is true if we should
+ // check whether assertions are true.
uint64_t
- eval(const Symbol_table*, const Layout*);
+ eval(const Symbol_table*, const Layout*, bool check_assertions);
// Return the value of an expression which is permitted to refer to
// the dot symbol. DOT_VALUE is the absolute value of the dot
// value; to get a section relative value the caller must subtract
// the section address.
uint64_t
- eval_with_dot(const Symbol_table*, const Layout*, uint64_t dot_value,
- Output_section* dot_section, Output_section** result_section);
+ eval_with_dot(const Symbol_table*, const Layout*, bool check_assertions,
+ uint64_t dot_value, Output_section* dot_section,
+ Output_section** result_section);
// Return the value of an expression which may or may not be
// permitted to refer to the dot symbol, depending on
// is_dot_available.
uint64_t
- eval_maybe_dot(const Symbol_table*, const Layout*, bool is_dot_available,
- uint64_t dot_value, Output_section* dot_section,
+ eval_maybe_dot(const Symbol_table*, const Layout*, bool check_assertions,
+ bool is_dot_available, uint64_t dot_value,
+ Output_section* dot_section,
Output_section** result_section);
// Print the expression to the FILE. This is for debugging.
// Set the symbol value, but only if the value is absolute. This is
// used while processing a SECTIONS clause. We assume that dot is
- // an absolute value here.
+ // an absolute value here. We do not check assertions.
void
set_if_absolute(Symbol_table*, const Layout*, bool is_dot_available,
uint64_t dot_value);
bool
define_symbol(const char* definition);
+ // Create sections required by any linker scripts.
+ void
+ create_script_sections(Layout*);
+
// Add all symbol definitions to the symbol table.
void
add_symbols_to_table(Symbol_table*);