diff options
Diffstat (limited to 'gold/script-sections.cc')
-rw-r--r-- | gold/script-sections.cc | 360 |
1 files changed, 197 insertions, 163 deletions
diff --git a/gold/script-sections.cc b/gold/script-sections.cc index 7f51e8b..341599c 100644 --- a/gold/script-sections.cc +++ b/gold/script-sections.cc @@ -61,7 +61,7 @@ class Sections_element // Finalize symbols and check assertions. virtual void - finalize_symbols(Symbol_table*, const Layout*, bool*, uint64_t*) + finalize_symbols(Symbol_table*, const Layout*, uint64_t*) { } // Return the output section name to use for an input file name and @@ -80,7 +80,7 @@ class Sections_element // Set section addresses. This includes applying assignments if the // the expression is an absolute value. virtual void - set_section_addresses(Symbol_table*, Layout*, bool*, uint64_t*) + set_section_addresses(Symbol_table*, Layout*, uint64_t*) { } // Check a constraint (ONLY_IF_RO, etc.) on an output section. If @@ -129,10 +129,9 @@ class Sections_element_assignment : public Sections_element // Finalize the symbol. void finalize_symbols(Symbol_table* symtab, const Layout* layout, - bool* dot_has_value, uint64_t* dot_value) + uint64_t* dot_value) { - this->assignment_.finalize_with_dot(symtab, layout, *dot_has_value, - *dot_value); + this->assignment_.finalize_with_dot(symtab, layout, *dot_value, NULL); } // Set the section address. There is no section here, but if the @@ -140,10 +139,9 @@ class Sections_element_assignment : public Sections_element // absolute symbols when setting dot. void set_section_addresses(Symbol_table* symtab, Layout* layout, - bool* dot_has_value, uint64_t* dot_value) + uint64_t* dot_value) { - this->assignment_.set_if_absolute(symtab, layout, true, *dot_has_value, - *dot_value); + this->assignment_.set_if_absolute(symtab, layout, true, *dot_value); } // Print for debugging. @@ -171,25 +169,24 @@ class Sections_element_dot_assignment : public Sections_element // Finalize the symbol. void finalize_symbols(Symbol_table* symtab, const Layout* layout, - bool* dot_has_value, uint64_t* dot_value) + uint64_t* dot_value) { - bool dummy; - *dot_value = this->val_->eval_with_dot(symtab, layout, *dot_has_value, - *dot_value, &dummy); - *dot_has_value = true; + // We ignore the section of the result because outside of an + // 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, + NULL, &dummy); } // Update the dot symbol while setting section addresses. void set_section_addresses(Symbol_table* symtab, Layout* layout, - bool* dot_has_value, uint64_t* dot_value) + uint64_t* dot_value) { - bool is_absolute; - *dot_value = this->val_->eval_with_dot(symtab, layout, *dot_has_value, - *dot_value, &is_absolute); - if (!is_absolute) - gold_error(_("dot set to non-absolute value")); - *dot_has_value = true; + Output_section* dummy; + *dot_value = this->val_->eval_with_dot(symtab, layout, *dot_value, + NULL, &dummy); } // Print for debugging. @@ -217,8 +214,7 @@ class Sections_element_assertion : public Sections_element // Check the assertion. void - finalize_symbols(Symbol_table* symtab, const Layout* layout, bool*, - uint64_t*) + finalize_symbols(Symbol_table* symtab, const Layout* layout, uint64_t*) { this->assertion_.check(symtab, layout); } // Print for debugging. @@ -254,7 +250,7 @@ class Output_section_element // Finalize symbols and check assertions. virtual void - finalize_symbols(Symbol_table*, const Layout*, bool*, uint64_t*) + finalize_symbols(Symbol_table*, const Layout*, uint64_t*, Output_section**) { } // Return whether this element matches FILE_NAME and SECTION_NAME. @@ -267,7 +263,8 @@ class Output_section_element // the expression is an absolute value. virtual void set_section_addresses(Symbol_table*, Layout*, Output_section*, uint64_t, - uint64_t*, std::string*, Input_section_list*) + uint64_t*, Output_section**, std::string*, + Input_section_list*) { } // Print the element for debugging purposes. @@ -313,10 +310,10 @@ class Output_section_element_assignment : public Output_section_element // Finalize the symbol. void finalize_symbols(Symbol_table* symtab, const Layout* layout, - bool* dot_has_value, uint64_t* dot_value) + uint64_t* dot_value, Output_section** dot_section) { - this->assignment_.finalize_with_dot(symtab, layout, *dot_has_value, - *dot_value); + this->assignment_.finalize_with_dot(symtab, layout, *dot_value, + *dot_section); } // Set the section address. There is no section here, but if the @@ -324,10 +321,10 @@ class Output_section_element_assignment : public Output_section_element // absolute symbols when setting dot. void set_section_addresses(Symbol_table* symtab, Layout* layout, Output_section*, - uint64_t, uint64_t* dot_value, std::string*, - Input_section_list*) + uint64_t, uint64_t* dot_value, Output_section**, + std::string*, Input_section_list*) { - this->assignment_.set_if_absolute(symtab, layout, true, true, *dot_value); + this->assignment_.set_if_absolute(symtab, layout, true, *dot_value); } // Print for debugging. @@ -354,19 +351,17 @@ class Output_section_element_dot_assignment : public Output_section_element // Finalize the symbol. void finalize_symbols(Symbol_table* symtab, const Layout* layout, - bool* dot_has_value, uint64_t* dot_value) + uint64_t* dot_value, Output_section** dot_section) { - bool dummy; - *dot_value = this->val_->eval_with_dot(symtab, layout, *dot_has_value, - *dot_value, &dummy); - *dot_has_value = true; + *dot_value = this->val_->eval_with_dot(symtab, layout, *dot_value, + *dot_section, dot_section); } // Update the dot symbol while setting section addresses. void set_section_addresses(Symbol_table* symtab, Layout* layout, Output_section*, - uint64_t, uint64_t* dot_value, std::string*, - Input_section_list*); + uint64_t, uint64_t* dot_value, Output_section**, + std::string*, Input_section_list*); // Print for debugging. void @@ -390,14 +385,12 @@ Output_section_element_dot_assignment::set_section_addresses( Output_section* output_section, uint64_t, uint64_t* dot_value, + Output_section** dot_section, std::string* fill, Input_section_list*) { - bool is_absolute; - uint64_t next_dot = this->val_->eval_with_dot(symtab, layout, true, - *dot_value, &is_absolute); - if (!is_absolute) - gold_error(_("dot set to non-absolute value")); + uint64_t next_dot = this->val_->eval_with_dot(symtab, layout, *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) @@ -438,94 +431,84 @@ class Output_section_element_assertion : public Output_section_element Script_assertion assertion_; }; -// A data item in an output section. +// We use a special instance of Output_section_data to handle BYTE, +// SHORT, etc. This permits forward references to symbols in the +// expressions. -class Output_section_element_data : public Output_section_element +class Output_data_expression : public Output_section_data { public: - Output_section_element_data(int size, bool is_signed, Expression* val) - : size_(size), is_signed_(is_signed), val_(val) + Output_data_expression(int size, bool is_signed, Expression* val, + const Symbol_table* symtab, const Layout* layout, + uint64_t dot_value, Output_section* dot_section) + : Output_section_data(size, 0), + is_signed_(is_signed), val_(val), symtab_(symtab), + layout_(layout), dot_value_(dot_value), dot_section_(dot_section) { } - // Finalize symbols--we just need to update dot. - void - finalize_symbols(Symbol_table*, const Layout*, bool*, uint64_t* dot_value) - { *dot_value += this->size_; } - - // Store the value in the section. + protected: + // Write the data to the output file. void - set_section_addresses(Symbol_table*, Layout*, Output_section*, uint64_t, - uint64_t* dot_value, std::string*, - Input_section_list*); + do_write(Output_file*); - // Print for debugging. + // Write the data to a buffer. void - print(FILE*) const; + do_write_to_buffer(unsigned char*); private: template<bool big_endian> - std::string - set_fill_string(uint64_t); + void + endian_write_to_buffer(uint64_t, unsigned char*); - // The size in bytes. - int size_; - // Whether the value is signed. bool is_signed_; - // The value. Expression* val_; + const Symbol_table* symtab_; + const Layout* layout_; + uint64_t dot_value_; + Output_section* dot_section_; }; -// Store the value in the section. +// Write the data element to the output file. void -Output_section_element_data::set_section_addresses(Symbol_table* symtab, - Layout* layout, - Output_section* os, - uint64_t, - uint64_t* dot_value, - std::string*, - Input_section_list*) +Output_data_expression::do_write(Output_file* of) { - gold_assert(os != NULL); + unsigned char* view = of->get_output_view(this->offset(), this->data_size()); + this->write_to_buffer(view); + of->write_output_view(this->offset(), this->data_size(), view); +} - bool is_absolute; - uint64_t val = this->val_->eval_with_dot(symtab, layout, true, *dot_value, - &is_absolute); - if (!is_absolute) - gold_error(_("data directive with non-absolute value")); +// Write the data element to a buffer. + +void +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_, + this->dot_section_, &dummy); - std::string fill; if (parameters->is_big_endian()) - fill = this->set_fill_string<true>(val); + this->endian_write_to_buffer<true>(val, buf); else - fill = this->set_fill_string<false>(val); - - os->add_output_section_data(new Output_data_const(fill, 0)); - - *dot_value += this->size_; + this->endian_write_to_buffer<false>(val, buf); } -// Get the value to store in a std::string. - template<bool big_endian> -std::string - Output_section_element_data::set_fill_string(uint64_t val) +void +Output_data_expression::endian_write_to_buffer(uint64_t val, + unsigned char* buf) { - std::string ret; - unsigned char buf[8]; - switch (this->size_) + switch (this->data_size()) { case 1: elfcpp::Swap_unaligned<8, big_endian>::writeval(buf, val); - ret.assign(reinterpret_cast<char*>(buf), 1); break; case 2: elfcpp::Swap_unaligned<16, big_endian>::writeval(buf, val); - ret.assign(reinterpret_cast<char*>(buf), 2); break; case 4: elfcpp::Swap_unaligned<32, big_endian>::writeval(buf, val); - ret.assign(reinterpret_cast<char*>(buf), 4); break; case 8: if (parameters->get_size() == 32) @@ -535,12 +518,68 @@ std::string val |= 0xffffffff00000000LL; } elfcpp::Swap_unaligned<64, big_endian>::writeval(buf, val); - ret.assign(reinterpret_cast<char*>(buf), 8); break; default: gold_unreachable(); } - return ret; +} + +// A data item in an output section. + +class Output_section_element_data : public Output_section_element +{ + public: + Output_section_element_data(int size, bool is_signed, Expression* val) + : size_(size), is_signed_(is_signed), val_(val) + { } + + // Finalize symbols--we just need to update dot. + void + finalize_symbols(Symbol_table*, const Layout*, uint64_t* dot_value, + Output_section**) + { *dot_value += this->size_; } + + // Store the value in the section. + void + set_section_addresses(Symbol_table*, Layout*, Output_section*, uint64_t, + uint64_t* dot_value, Output_section**, std::string*, + Input_section_list*); + + // Print for debugging. + void + print(FILE*) const; + + private: + // The size in bytes. + int size_; + // Whether the value is signed. + bool is_signed_; + // The value. + Expression* val_; +}; + +// Store the value in the section. + +void +Output_section_element_data::set_section_addresses( + Symbol_table* symtab, + Layout* layout, + Output_section* os, + uint64_t, + uint64_t* dot_value, + Output_section** dot_section, + std::string*, + Input_section_list*) +{ + gold_assert(os != NULL); + os->add_output_section_data(new Output_data_expression(this->size_, + this->is_signed_, + this->val_, + symtab, + layout, + *dot_value, + *dot_section)); + *dot_value += this->size_; } // Print for debugging. @@ -586,15 +625,16 @@ class Output_section_element_fill : public Output_section_element // Update the fill value while setting section addresses. void set_section_addresses(Symbol_table* symtab, Layout* layout, Output_section*, - uint64_t, uint64_t* dot_value, std::string* fill, - Input_section_list*) + uint64_t, uint64_t* dot_value, + Output_section** dot_section, + std::string* fill, Input_section_list*) { - bool is_absolute; - uint64_t fill_val = this->val_->eval_with_dot(symtab, layout, true, - *dot_value, - &is_absolute); - if (!is_absolute) - gold_error(_("fill set to non-absolute value")); + Output_section* fill_section; + uint64_t fill_val = this->val_->eval_with_dot(symtab, layout, + *dot_value, *dot_section, + &fill_section); + if (fill_section != NULL) + gold_warning(_("fill value is not absolute")); // FIXME: The GNU linker supports fill values of arbitrary length. unsigned char fill_buff[4]; elfcpp::Swap_unaligned<32, true>::writeval(fill_buff, fill_val); @@ -633,11 +673,11 @@ class Output_section_element_input : public Output_section_element // Finalize symbols--just update the value of the dot symbol. void - finalize_symbols(Symbol_table*, const Layout*, bool* dot_has_value, - uint64_t* dot_value) + finalize_symbols(Symbol_table*, const Layout*, uint64_t* dot_value, + Output_section** dot_section) { *dot_value = this->final_dot_value_; - *dot_has_value = true; + *dot_section = this->final_dot_section_; } // See whether we match FILE_NAME and SECTION_NAME as an input @@ -649,7 +689,8 @@ class Output_section_element_input : public Output_section_element void set_section_addresses(Symbol_table* symtab, Layout* layout, Output_section*, uint64_t subalign, uint64_t* dot_value, - std::string* fill, Input_section_list*); + Output_section**, std::string* fill, + Input_section_list*); // Print for debugging. void @@ -707,6 +748,9 @@ class Output_section_element_input : public Output_section_element bool keep_; // The value of dot after including all matching sections. uint64_t final_dot_value_; + // The section where dot is defined after including all matching + // sections. + Output_section* final_dot_section_; }; // Construct Output_section_element_input. The parser records strings @@ -722,7 +766,8 @@ Output_section_element_input::Output_section_element_input( filename_exclusions_(), input_section_patterns_(), keep_(keep), - final_dot_value_(0) + final_dot_value_(0), + final_dot_section_(NULL) { // The filename pattern "*" is common, and matches all files. Turn // it into the empty string. @@ -885,6 +930,7 @@ Output_section_element_input::set_section_addresses( Output_section* output_section, uint64_t subalign, uint64_t* dot_value, + Output_section** dot_section, std::string* fill, Input_section_list* input_sections) { @@ -1001,6 +1047,7 @@ Output_section_element_input::set_section_addresses( } this->final_dot_value_ = *dot_value; + this->final_dot_section_ = *dot_section; } // Print for debugging. @@ -1153,7 +1200,7 @@ class Output_section_definition : public Sections_element // Finalize symbols and check assertions. void - finalize_symbols(Symbol_table*, const Layout*, bool*, uint64_t*); + finalize_symbols(Symbol_table*, const Layout*, uint64_t*); // Return the output section name to use for an input file name and // section name. @@ -1168,7 +1215,7 @@ class Output_section_definition : public Sections_element // Set the section address. void set_section_addresses(Symbol_table* symtab, Layout* layout, - bool* dot_has_value, uint64_t* dot_value); + uint64_t* dot_value); // Check a constraint (ONLY_IF_RO, etc.) on an output section. If // this section is constrained, and the input sections do not match, @@ -1333,7 +1380,6 @@ Output_section_definition::add_symbols_to_table(Symbol_table* symtab) void Output_section_definition::finalize_symbols(Symbol_table* symtab, const Layout* layout, - bool* dot_has_value, uint64_t* dot_value) { if (this->output_section_ != NULL) @@ -1343,28 +1389,28 @@ Output_section_definition::finalize_symbols(Symbol_table* symtab, uint64_t address = *dot_value; if (this->address_ != NULL) { - bool dummy; + Output_section* dummy; address = this->address_->eval_with_dot(symtab, layout, - *dot_has_value, *dot_value, + *dot_value, NULL, &dummy); } if (this->align_ != NULL) { - bool dummy; + Output_section* dummy; uint64_t align = this->align_->eval_with_dot(symtab, layout, - *dot_has_value, *dot_value, + NULL, &dummy); address = align_address(address, align); } *dot_value = address; } - *dot_has_value = true; + Output_section* dot_section = this->output_section_; for (Output_section_elements::iterator p = this->elements_.begin(); p != this->elements_.end(); ++p) - (*p)->finalize_symbols(symtab, layout, dot_has_value, dot_value); + (*p)->finalize_symbols(symtab, layout, dot_value, &dot_section); } // Return the output section name to use for an input section name. @@ -1514,25 +1560,16 @@ Output_section_definition::place_orphan_here(const Output_section *os, void Output_section_definition::set_section_addresses(Symbol_table* symtab, Layout* layout, - bool* dot_has_value, uint64_t* dot_value) { - bool is_absolute; uint64_t address; - if (this->address_ != NULL) - { - address = this->address_->eval_with_dot(symtab, layout, *dot_has_value, - *dot_value, &is_absolute); - if (!is_absolute) - gold_error(_("address of section %s is not absolute"), - this->name_.c_str()); - } + if (this->address_ == NULL) + address = *dot_value; else { - if (!*dot_has_value) - gold_error(_("no address given for section %s"), - this->name_.c_str()); - address = *dot_value; + Output_section* dummy; + address = this->address_->eval_with_dot(symtab, layout, *dot_value, + NULL, &dummy); } uint64_t align; @@ -1545,11 +1582,12 @@ Output_section_definition::set_section_addresses(Symbol_table* symtab, } else { - align = this->align_->eval_with_dot(symtab, layout, *dot_has_value, - *dot_value, &is_absolute); - if (!is_absolute) - gold_error(_("alignment of section %s is not absolute"), - this->name_.c_str()); + Output_section* align_section; + align = this->align_->eval_with_dot(symtab, layout, *dot_value, + NULL, &align_section); + if (align_section != NULL) + gold_warning(_("alignment of section %s is not absolute"), + this->name_.c_str()); if (this->output_section_ != NULL) this->output_section_->set_addralign(align); } @@ -1557,7 +1595,6 @@ Output_section_definition::set_section_addresses(Symbol_table* symtab, address = align_address(address, align); *dot_value = address; - *dot_has_value = true; // The address of non-SHF_ALLOC sections is forced to zero, // regardless of what the linker script wants. @@ -1567,12 +1604,10 @@ Output_section_definition::set_section_addresses(Symbol_table* symtab, if (this->load_address_ != NULL && this->output_section_ != NULL) { + Output_section* dummy; uint64_t load_address = - this->load_address_->eval_with_dot(symtab, layout, *dot_has_value, - *dot_value, &is_absolute); - if (!is_absolute) - gold_error(_("load address of section %s is not absolute"), - this->name_.c_str()); + this->load_address_->eval_with_dot(symtab, layout, *dot_value, + this->output_section_, &dummy); this->output_section_->set_load_address(load_address); } @@ -1581,11 +1616,12 @@ Output_section_definition::set_section_addresses(Symbol_table* symtab, subalign = 0; else { - subalign = this->subalign_->eval_with_dot(symtab, layout, *dot_has_value, - *dot_value, &is_absolute); - if (!is_absolute) - gold_error(_("subalign of section %s is not absolute"), - this->name_.c_str()); + Output_section* subalign_section; + subalign = this->subalign_->eval_with_dot(symtab, layout, *dot_value, + NULL, &subalign_section); + if (subalign_section != NULL) + gold_warning(_("subalign of section %s is not absolute"), + this->name_.c_str()); } std::string fill; @@ -1593,13 +1629,14 @@ 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, - *dot_has_value, *dot_value, - &is_absolute); - if (!is_absolute) - gold_error(_("fill of section %s is not absolute"), - this->name_.c_str()); + NULL, + &fill_section); + if (fill_section != NULL) + gold_warning(_("fill of section %s is not absolute"), + this->name_.c_str()); unsigned char fill_buff[4]; elfcpp::Swap_unaligned<32, true>::writeval(fill_buff, fill_val); fill.assign(reinterpret_cast<char*>(fill_buff), 4); @@ -1617,11 +1654,13 @@ Output_section_definition::set_section_addresses(Symbol_table* symtab, *dot_value = address; } + Output_section* dot_section = this->output_section_; for (Output_section_elements::iterator p = this->elements_.begin(); p != this->elements_.end(); ++p) (*p)->set_section_addresses(symtab, layout, this->output_section_, - subalign, dot_value, &fill, &input_sections); + subalign, dot_value, &dot_section, &fill, + &input_sections); gold_assert(input_sections.empty()); } @@ -1806,7 +1845,7 @@ class Orphan_output_section : public Sections_element // Set section addresses. void - set_section_addresses(Symbol_table*, Layout*, bool*, uint64_t*); + set_section_addresses(Symbol_table*, Layout*, uint64_t*); // Get the list of segments to use for an allocated section when // using a PHDRS clause. If this is an allocated section, return @@ -1845,14 +1884,10 @@ Orphan_output_section::place_orphan_here(const Output_section* os, void Orphan_output_section::set_section_addresses(Symbol_table*, Layout*, - bool* dot_has_value, uint64_t* dot_value) { typedef std::list<std::pair<Relobj*, unsigned int> > Input_section_list; - if (!*dot_has_value) - gold_error(_("no address for orphan section %s"), this->os_->name()); - uint64_t address = *dot_value; address = align_address(address, this->os_->addralign()); @@ -2177,12 +2212,11 @@ Script_sections::finalize_symbols(Symbol_table* symtab, const Layout* layout) { if (!this->saw_sections_clause_) return; - bool dot_has_value = false; uint64_t dot_value = 0; for (Sections_elements::iterator p = this->sections_elements_->begin(); p != this->sections_elements_->end(); ++p) - (*p)->finalize_symbols(symtab, layout, &dot_has_value, &dot_value); + (*p)->finalize_symbols(symtab, layout, &dot_value); } // Return the name of the output section to use for an input file name @@ -2290,12 +2324,12 @@ Script_sections::set_section_addresses(Symbol_table* symtab, Layout* layout) } } - bool dot_has_value = false; + // For a relocatable link, we implicitly set dot to zero. uint64_t dot_value = 0; for (Sections_elements::iterator p = this->sections_elements_->begin(); p != this->sections_elements_->end(); ++p) - (*p)->set_section_addresses(symtab, layout, &dot_has_value, &dot_value); + (*p)->set_section_addresses(symtab, layout, &dot_value); if (this->phdrs_elements_ != NULL) { |