Don't check assertions until symbols are finalized. Create an output
authorIan Lance Taylor <iant@google.com>
Thu, 28 Feb 2008 04:45:47 +0000 (04:45 +0000)
committerIan Lance Taylor <iant@google.com>
Thu, 28 Feb 2008 04:45:47 +0000 (04:45 +0000)
section if the script uses a data statement with no input sections.
Don't create a loadable segment for the headers if there is no room.

gold/expression.cc
gold/gold.cc
gold/layout.cc
gold/layout.h
gold/script-sections.cc
gold/script-sections.h
gold/script.cc
gold/script.h

index 25a19f9ae495922d4c70eb32e27ad2e7d51c31b5..28d385b88d6f527fd9de0cf62ec1d0d35f170b9c 100644 (file)
@@ -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;
   }
index c79e87a0eeebb49fd43577249483bb191f4036a8..f6437a811bdc77e1c14b5d8aa202f08e3e0315d7 100644 (file)
@@ -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);
index c12501469b60202d18b2baba96f350c1f5893210..b2fd9715feca0ac0d377d713282393ee166cfa66 100644 (file)
@@ -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
index 658eb1e02d098ce477f35f96f5467d7423c0d9d5..d1caa2cb37305503c124e15f0a901dd8e14059e8 100644 (file)
@@ -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);
index ff40ef542bc2fb546cd806313e9704d14998081b..39aa9bd03dbaea66c5ef62fc16d522831add8058 100644 (file)
@@ -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;
 }
index 138f144c29d684034e9a84b96250d1d12dcba56c..9043dfdda56281aa4a922ef80b866532d6a81ac7 100644 (file)
@@ -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*);
index ee54e9df56d07467178c72dc665130977f1239a2..42fb71ca7d50d1da59b0a90b957671da4c8a9dc9 100644 (file)
@@ -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,
                                                  &section);
@@ -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
index b2122271de1da60d80af86a284980c3784cfd288..78d9ff019e7c685fa33ab5e268299d4b3bbd9d39 100644 (file)
@@ -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*);