diff --git a/gold/expression.cc b/gold/expression.cc index 25a19f9ae4..28d385b88d 100644 --- a/gold/expression.cc +++ b/gold/expression.cc @@ -54,6 +54,8 @@ struct Expression::Expression_eval_info 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; @@ -69,21 +71,24 @@ struct Expression::Expression_eval_info // 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 @@ -91,13 +96,14 @@ Expression::eval_with_dot(const Symbol_table* symtab, const Layout* layout, 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; @@ -237,6 +243,7 @@ class Unary_expression : public Expression 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, @@ -313,6 +320,7 @@ class Binary_expression : public Expression 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, @@ -324,6 +332,7 @@ class Binary_expression : public Expression 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, @@ -456,6 +465,7 @@ class Trinary_expression : public Expression 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, @@ -467,6 +477,7 @@ class Trinary_expression : public Expression 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, @@ -478,6 +489,7 @@ class Trinary_expression : public Expression 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, @@ -738,7 +750,7 @@ class Assert_expression : public Unary_expression 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; } diff --git a/gold/gold.cc b/gold/gold.cc index c79e87a0ee..f6437a811b 100644 --- a/gold/gold.cc +++ b/gold/gold.cc @@ -202,6 +202,9 @@ queue_middle_tasks(const General_options& options, // TODO: if this is too slow, do this as a task, rather than inline. symtab->detect_odr_violations(task, options.output_file_name()); + // Create any output sections required by any linker script. + layout->create_script_sections(); + // Define some sections and symbols needed for a dynamic link. This // handles some cases we want to see before we read the relocs. layout->create_initial_dynamic_sections(symtab); diff --git a/gold/layout.cc b/gold/layout.cc index c12501469b..b2fd9715fe 100644 --- a/gold/layout.cc +++ b/gold/layout.cc @@ -712,6 +712,18 @@ Layout::make_output_section(const char* name, elfcpp::Elf_Word type, return os; } +// Make an output section for a script. + +Output_section* +Layout::make_output_section_for_script(const char* name) +{ + name = this->namepool_.add(name, false, NULL); + Output_section* os = this->make_output_section(name, elfcpp::SHT_PROGBITS, + elfcpp::SHF_ALLOC); + os->set_found_in_sections_clause(); + return os; +} + // Return the number of segments we expect to see. size_t diff --git a/gold/layout.h b/gold/layout.h index 658eb1e02d..d1caa2cb37 100644 --- a/gold/layout.h +++ b/gold/layout.h @@ -168,6 +168,11 @@ class Layout void define_section_symbols(Symbol_table*); + // Create sections for linker scripts. + void + create_script_sections() + { this->script_options_->create_script_sections(this); } + // Define symbols from any linker script. void define_script_symbols(Symbol_table* symtab) @@ -314,6 +319,10 @@ class Layout void get_allocated_sections(Section_list*) const; + // Make a section for a linker script to hold data. + Output_section* + make_output_section_for_script(const char* name); + // Make a segment. This is used by the linker script code. Output_segment* make_output_segment(elfcpp::Elf_Word type, elfcpp::Elf_Word flags); diff --git a/gold/script-sections.cc b/gold/script-sections.cc index ff40ef542b..39aa9bd03d 100644 --- a/gold/script-sections.cc +++ b/gold/script-sections.cc @@ -54,6 +54,12 @@ class Sections_element 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*) @@ -175,7 +181,7 @@ class Sections_element_dot_assignment : public Sections_element // 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); } @@ -185,7 +191,7 @@ class Sections_element_dot_assignment : public Sections_element 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; } @@ -244,6 +250,11 @@ class Output_section_element 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*) @@ -354,7 +365,7 @@ class Output_section_element_dot_assignment : public Output_section_element 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); } @@ -390,8 +401,9 @@ Output_section_element_dot_assignment::set_section_addresses( 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) @@ -486,7 +498,7 @@ Output_data_expression::do_write_to_buffer(unsigned char* buf) { 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()) @@ -534,6 +546,11 @@ class Output_section_element_data : public Output_section_element : 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, @@ -631,7 +648,7 @@ class Output_section_element_fill : public Output_section_element 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) @@ -1195,6 +1212,10 @@ class Output_section_definition : public Sections_element 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); @@ -1365,6 +1386,27 @@ Output_section_definition::add_input_section(const Input_section_spec* spec, 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 @@ -1391,14 +1433,14 @@ Output_section_definition::finalize_symbols(Symbol_table* symtab, 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); @@ -1570,8 +1612,8 @@ Output_section_definition::set_section_addresses(Symbol_table* symtab, 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; @@ -1585,7 +1627,7 @@ Output_section_definition::set_section_addresses(Symbol_table* symtab, 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"), @@ -1610,7 +1652,7 @@ Output_section_definition::set_section_addresses(Symbol_table* symtab, { 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); } @@ -1621,8 +1663,9 @@ Output_section_definition::set_section_addresses(Symbol_table* symtab, 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()); @@ -1634,7 +1677,7 @@ Output_section_definition::set_section_addresses(Symbol_table* symtab, // 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); @@ -2002,7 +2045,8 @@ class Phdrs_element 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. @@ -2216,6 +2260,19 @@ Script_sections::add_input_section(const Input_section_spec* spec, bool keep) 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 @@ -2575,38 +2632,32 @@ Script_sections::create_segments(Layout* layout) // 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; } diff --git a/gold/script-sections.h b/gold/script-sections.h index 138f144c29..9043dfdda5 100644 --- a/gold/script-sections.h +++ b/gold/script-sections.h @@ -106,6 +106,10 @@ class Script_sections void add_input_section(const Input_section_spec* spec, bool keep); + // Create any required sections. + void + create_sections(Layout*); + // Add any symbols we are defining to the symbol table. void add_symbols_to_table(Symbol_table*); diff --git a/gold/script.cc b/gold/script.cc index ee54e9df56..42fb71ca7d 100644 --- a/gold/script.cc +++ b/gold/script.cc @@ -980,7 +980,7 @@ Symbol_assignment::sized_finalize(Symbol_table* symtab, const Layout* layout, Output_section* dot_section) { Output_section* section; - uint64_t final_val = this->val_->eval_maybe_dot(symtab, layout, + uint64_t final_val = this->val_->eval_maybe_dot(symtab, layout, true, is_dot_available, dot_value, dot_section, §ion); @@ -1000,8 +1000,9 @@ Symbol_assignment::set_if_absolute(Symbol_table* symtab, const Layout* layout, return; Output_section* val_section; - uint64_t val = this->val_->eval_maybe_dot(symtab, layout, is_dot_available, - dot_value, NULL, &val_section); + uint64_t val = this->val_->eval_maybe_dot(symtab, layout, false, + is_dot_available, dot_value, + NULL, &val_section); if (val_section != NULL) return; @@ -1055,7 +1056,7 @@ Symbol_assignment::print(FILE* f) const void Script_assertion::check(const Symbol_table* symtab, const Layout* layout) { - if (!this->check_->eval(symtab, layout)) + if (!this->check_->eval(symtab, layout, true)) gold_error("%s", this->message_.c_str()); } @@ -1122,6 +1123,15 @@ Script_options::add_assertion(Expression* check, const char* message, } } +// Create sections required by any linker scripts. + +void +Script_options::create_script_sections(Layout* layout) +{ + if (this->saw_sections_clause()) + this->script_sections_.create_sections(layout); +} + // Add any symbols we are defining to the symbol table. void diff --git a/gold/script.h b/gold/script.h index b2122271de..78d9ff019e 100644 --- a/gold/script.h +++ b/gold/script.h @@ -67,9 +67,10 @@ class Expression { } // 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 @@ -82,15 +83,17 @@ class Expression // 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. @@ -219,7 +222,7 @@ class Symbol_assignment // 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); @@ -307,6 +310,10 @@ class Script_options 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*);