PR gold/13023
authorCary Coutant <ccoutant@google.com>
Mon, 31 Oct 2011 22:51:03 +0000 (22:51 +0000)
committerCary Coutant <ccoutant@google.com>
Mon, 31 Oct 2011 22:51:03 +0000 (22:51 +0000)
* expression.cc (Expression::eval_with_dot): Add
is_section_dot_assignment parameter.
(Expression::eval_maybe_dot): Likewise.  Adjust value when rhs is
absolute and assigning to dot within a section.
* script-sections.cc
(Output_section_element_assignment::set_section_addresses): Pass
dot_section to set_if_absolute.
(Output_section_element_dot_assignment::finalize_symbols): Pass TRUE
as is_section_dot_assignment flag to eval_with_dot.
(Output_section_element_dot_assignment::set_section_addresses):
Likewise.
* script.cc (Symbol_assignment::set_if_absolute): Add dot_section
parameter.  Also set value if relative to dot_section; set the
symbol's output_section.
* script.h (Expression::eval_with_dot): Add is_section_dot_assignment
parameter.  Adjust all callers.
(Expression::eval_maybe_dot): Likewise.
(Symbol_assignment::set_if_absolute): Add dot_section parameter.
Adjust all callers.
* testsuite/script_test_2.t: Test assignment of an absolute value
to dot within an output section element.

gold/ChangeLog
gold/expression.cc
gold/script-sections.cc
gold/script.cc
gold/script.h
gold/testsuite/script_test_2.t

index cc8aae0..a21b217 100644 (file)
@@ -1,5 +1,30 @@
 2011-10-31  Cary Coutant  <ccoutant@google.com>
 
+       PR gold/13023
+       * expression.cc (Expression::eval_with_dot): Add
+       is_section_dot_assignment parameter.
+       (Expression::eval_maybe_dot): Likewise.  Adjust value when rhs is
+       absolute and assigning to dot within a section.
+       * script-sections.cc
+       (Output_section_element_assignment::set_section_addresses): Pass
+       dot_section to set_if_absolute.
+       (Output_section_element_dot_assignment::finalize_symbols): Pass TRUE
+       as is_section_dot_assignment flag to eval_with_dot.
+       (Output_section_element_dot_assignment::set_section_addresses):
+       Likewise.
+       * script.cc (Symbol_assignment::set_if_absolute): Add dot_section
+       parameter.  Also set value if relative to dot_section; set the
+       symbol's output_section.
+       * script.h (Expression::eval_with_dot): Add is_section_dot_assignment
+       parameter.  Adjust all callers.
+       (Expression::eval_maybe_dot): Likewise.
+       (Symbol_assignment::set_if_absolute): Add dot_section parameter.
+       Adjust all callers.
+       * testsuite/script_test_2.t: Test assignment of an absolute value
+       to dot within an output section element.
+
+2011-10-31  Cary Coutant  <ccoutant@google.com>
+
        * options.h (class General_options): Add --[no-]gnu-unique options.
        * symtab.cc (Symbol_table::sized_write_globals): Convert
        STB_GNU_UNIQUE to STB_GLOBAL if --no-gnu-unique.
index e527b5e..b611a68 100644 (file)
@@ -77,7 +77,7 @@ Expression::eval(const Symbol_table* symtab, const Layout* layout,
                 bool check_assertions)
 {
   return this->eval_maybe_dot(symtab, layout, check_assertions,
-                             false, 0, NULL, NULL, NULL);
+                             false, 0, NULL, NULL, NULL, false);
 }
 
 // Evaluate an expression which may refer to the dot symbol.
@@ -87,11 +87,13 @@ Expression::eval_with_dot(const Symbol_table* symtab, const Layout* layout,
                          bool check_assertions, uint64_t dot_value,
                          Output_section* dot_section,
                          Output_section** result_section_pointer,
-                         uint64_t* result_alignment_pointer)
+                         uint64_t* result_alignment_pointer,
+                         bool is_section_dot_assignment)
 {
   return this->eval_maybe_dot(symtab, layout, check_assertions, true,
                              dot_value, dot_section, result_section_pointer,
-                             result_alignment_pointer);
+                             result_alignment_pointer,
+                             is_section_dot_assignment);
 }
 
 // Evaluate an expression which may or may not refer to the dot
@@ -102,7 +104,8 @@ Expression::eval_maybe_dot(const Symbol_table* symtab, const Layout* layout,
                           bool check_assertions, bool is_dot_available,
                           uint64_t dot_value, Output_section* dot_section,
                           Output_section** result_section_pointer,
-                          uint64_t* result_alignment_pointer)
+                          uint64_t* result_alignment_pointer,
+                          bool is_section_dot_assignment)
 {
   Expression_eval_info eei;
   eei.symtab = symtab;
@@ -113,14 +116,24 @@ Expression::eval_maybe_dot(const Symbol_table* symtab, const Layout* layout,
   eei.dot_section = dot_section;
 
   // We assume the value is absolute, and only set this to a section
-  // if we find a section relative reference.
+  // if we find a section-relative reference.
   if (result_section_pointer != NULL)
     *result_section_pointer = NULL;
   eei.result_section_pointer = result_section_pointer;
 
   eei.result_alignment_pointer = result_alignment_pointer;
 
-  return this->value(&eei);
+  uint64_t val = this->value(&eei);
+
+  // If this is an assignment to dot within a section, and the value
+  // is absolute, treat it as a section-relative offset.
+  if (is_section_dot_assignment && *result_section_pointer == NULL)
+    {
+      gold_assert(dot_section != NULL);
+      val += dot_section->address();
+      *result_section_pointer = dot_section;
+    }
+  return val;
 }
 
 // A number.
@@ -257,7 +270,8 @@ class Unary_expression : public Expression
                                      eei->dot_value,
                                      eei->dot_section,
                                      arg_section_pointer,
-                                     eei->result_alignment_pointer);
+                                     eei->result_alignment_pointer,
+                                     false);
   }
 
   void
@@ -336,7 +350,8 @@ class Binary_expression : public Expression
                                       eei->dot_value,
                                       eei->dot_section,
                                       section_pointer,
-                                      alignment_pointer);
+                                      alignment_pointer,
+                                      false);
   }
 
   uint64_t
@@ -350,7 +365,8 @@ class Binary_expression : public Expression
                                        eei->dot_value,
                                        eei->dot_section,
                                        section_pointer,
-                                       alignment_pointer);
+                                       alignment_pointer,
+                                       false);
   }
 
   void
@@ -500,7 +516,8 @@ class Trinary_expression : public Expression
                                       eei->dot_value,
                                       eei->dot_section,
                                       section_pointer,
-                                      NULL);
+                                      NULL,
+                                      false);
   }
 
   uint64_t
@@ -514,7 +531,8 @@ class Trinary_expression : public Expression
                                       eei->dot_value,
                                       eei->dot_section,
                                       section_pointer,
-                                      alignment_pointer);
+                                      alignment_pointer,
+                                      false);
   }
 
   uint64_t
@@ -528,7 +546,8 @@ class Trinary_expression : public Expression
                                       eei->dot_value,
                                       eei->dot_section,
                                       section_pointer,
-                                      alignment_pointer);
+                                      alignment_pointer,
+                                      false);
   }
 
   void
index eba6b9d..f90c0b3 100644 (file)
@@ -680,7 +680,7 @@ class Sections_element_assignment : public Sections_element
   set_section_addresses(Symbol_table* symtab, Layout* layout,
                        uint64_t* dot_value, uint64_t*, uint64_t*)
   {
-    this->assignment_.set_if_absolute(symtab, layout, true, *dot_value);
+    this->assignment_.set_if_absolute(symtab, layout, true, *dot_value, NULL);
   }
 
   // Print for debugging.
@@ -714,7 +714,7 @@ class Sections_element_dot_assignment : public Sections_element
     // output section definition the dot symbol is always considered
     // to be absolute.
     *dot_value = this->val_->eval_with_dot(symtab, layout, true, *dot_value,
-                                          NULL, NULL, NULL);
+                                          NULL, NULL, NULL, false);
   }
 
   // Update the dot symbol while setting section addresses.
@@ -724,7 +724,7 @@ class Sections_element_dot_assignment : public Sections_element
                        uint64_t* load_address)
   {
     *dot_value = this->val_->eval_with_dot(symtab, layout, false, *dot_value,
-                                          NULL, NULL, dot_alignment);
+                                          NULL, NULL, dot_alignment, false);
     *load_address = *dot_value;
   }
 
@@ -866,9 +866,11 @@ class Output_section_element_assignment : public Output_section_element
   void
   set_section_addresses(Symbol_table* symtab, Layout* layout, Output_section*,
                        uint64_t, uint64_t* dot_value, uint64_t*,
-                       Output_section**, std::string*, Input_section_list*)
+                       Output_section** dot_section, std::string*,
+                       Input_section_list*)
   {
-    this->assignment_.set_if_absolute(symtab, layout, true, *dot_value);
+    this->assignment_.set_if_absolute(symtab, layout, true, *dot_value,
+                                     *dot_section);
   }
 
   // Print for debugging.
@@ -904,14 +906,16 @@ class Output_section_element_dot_assignment : public Output_section_element
                   uint64_t* dot_value, Output_section** dot_section)
   {
     *dot_value = this->val_->eval_with_dot(symtab, layout, true, *dot_value,
-                                          *dot_section, dot_section, NULL);
+                                          *dot_section, dot_section, NULL,
+                                          true);
   }
 
   // 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, uint64_t*,
-                       Output_section**, std::string*, Input_section_list*);
+                       Output_section** dot_section, std::string*,
+                       Input_section_list*);
 
   // Print for debugging.
   void
@@ -942,7 +946,8 @@ Output_section_element_dot_assignment::set_section_addresses(
 {
   uint64_t next_dot = this->val_->eval_with_dot(symtab, layout, false,
                                                *dot_value, *dot_section,
-                                               dot_section, dot_alignment);
+                                               dot_section, dot_alignment,
+                                               true);
   if (next_dot < *dot_value)
     gold_error(_("dot may not move backward"));
   if (next_dot > *dot_value && output_section != NULL)
@@ -1043,7 +1048,8 @@ Output_data_expression::do_write_to_buffer(unsigned char* buf)
 {
   uint64_t val = this->val_->eval_with_dot(this->symtab_, this->layout_,
                                           true, this->dot_value_,
-                                          this->dot_section_, NULL, NULL);
+                                          this->dot_section_, NULL, NULL,
+                                          false);
 
   if (parameters->target().is_big_endian())
     this->endian_write_to_buffer<true>(val, buf);
@@ -1193,7 +1199,7 @@ class Output_section_element_fill : public Output_section_element
     Output_section* fill_section;
     uint64_t fill_val = this->val_->eval_with_dot(symtab, layout, false,
                                                  *dot_value, *dot_section,
-                                                 &fill_section, NULL);
+                                                 &fill_section, NULL, false);
     if (fill_section != NULL)
       gold_warning(_("fill value is not absolute"));
     // FIXME: The GNU linker supports fill values of arbitrary length.
@@ -2114,13 +2120,13 @@ Output_section_definition::finalize_symbols(Symbol_table* symtab,
        {
          address = this->address_->eval_with_dot(symtab, layout, true,
                                                  *dot_value, NULL,
-                                                 NULL, NULL);
+                                                 NULL, NULL, false);
        }
       if (this->align_ != NULL)
        {
          uint64_t align = this->align_->eval_with_dot(symtab, layout, true,
                                                       *dot_value, NULL,
-                                                      NULL, NULL);
+                                                      NULL, NULL, false);
          address = align_address(address, align);
        }
       *dot_value = address;
@@ -2309,7 +2315,7 @@ Output_section_definition::set_section_addresses(Symbol_table* symtab,
   else
     address = this->address_->eval_with_dot(symtab, layout, true,
                                            *dot_value, NULL, NULL,
-                                           dot_alignment);
+                                           dot_alignment, false);
   uint64_t align;
   if (this->align_ == NULL)
     {
@@ -2322,7 +2328,7 @@ Output_section_definition::set_section_addresses(Symbol_table* symtab,
     {
       Output_section* align_section;
       align = this->align_->eval_with_dot(symtab, layout, true, *dot_value,
-                                         NULL, &align_section, NULL);
+                                         NULL, &align_section, NULL, false);
       if (align_section != NULL)
        gold_warning(_("alignment of section %s is not absolute"),
                     this->name_.c_str());
@@ -2407,7 +2413,7 @@ Output_section_definition::set_section_addresses(Symbol_table* symtab,
       laddr = this->load_address_->eval_with_dot(symtab, layout, true,
                                                 *dot_value,
                                                 this->output_section_,
-                                                NULL, NULL);
+                                                NULL, NULL, false);
       if (this->output_section_ != NULL)
         this->output_section_->set_load_address(laddr);
     }
@@ -2422,7 +2428,8 @@ Output_section_definition::set_section_addresses(Symbol_table* symtab,
       Output_section* subalign_section;
       subalign = this->subalign_->eval_with_dot(symtab, layout, true,
                                                *dot_value, NULL,
-                                               &subalign_section, NULL);
+                                               &subalign_section, NULL,
+                                               false);
       if (subalign_section != NULL)
        gold_warning(_("subalign of section %s is not absolute"),
                     this->name_.c_str());
@@ -2437,7 +2444,7 @@ Output_section_definition::set_section_addresses(Symbol_table* symtab,
       uint64_t fill_val = this->fill_->eval_with_dot(symtab, layout, true,
                                                     *dot_value,
                                                     NULL, &fill_section,
-                                                    NULL);
+                                                    NULL, false);
       if (fill_section != NULL)
        gold_warning(_("fill of section %s is not absolute"),
                     this->name_.c_str());
index 7df0c9e..b471cf9 100644 (file)
@@ -983,18 +983,20 @@ Symbol_assignment::sized_finalize(Symbol_table* symtab, const Layout* layout,
   uint64_t final_val = this->val_->eval_maybe_dot(symtab, layout, true,
                                                  is_dot_available,
                                                  dot_value, dot_section,
-                                                 &section, NULL);
+                                                 &section, NULL, false);
   Sized_symbol<size>* ssym = symtab->get_sized_symbol<size>(this->sym_);
   ssym->set_value(final_val);
   if (section != NULL)
     ssym->set_output_section(section);
 }
 
-// Set the symbol value if the expression yields an absolute value.
+// Set the symbol value if the expression yields an absolute value or
+// a value relative to DOT_SECTION.
 
 void
 Symbol_assignment::set_if_absolute(Symbol_table* symtab, const Layout* layout,
-                                  bool is_dot_available, uint64_t dot_value)
+                                  bool is_dot_available, uint64_t dot_value,
+                                  Output_section* dot_section)
 {
   if (this->sym_ == NULL)
     return;
@@ -1002,8 +1004,9 @@ Symbol_assignment::set_if_absolute(Symbol_table* symtab, const Layout* layout,
   Output_section* val_section;
   uint64_t val = this->val_->eval_maybe_dot(symtab, layout, false,
                                            is_dot_available, dot_value,
-                                           NULL, &val_section, NULL);
-  if (val_section != NULL)
+                                           dot_section, &val_section, NULL,
+                                           false);
+  if (val_section != NULL && val_section != dot_section)
     return;
 
   if (parameters->target().get_size() == 32)
@@ -1026,6 +1029,8 @@ Symbol_assignment::set_if_absolute(Symbol_table* symtab, const Layout* layout,
     }
   else
     gold_unreachable();
+  if (val_section != NULL)
+    this->sym_->set_output_section(val_section);
 }
 
 // Print for debugging.
@@ -1215,7 +1220,7 @@ Script_options::set_section_addresses(Symbol_table* symtab, Layout* layout)
   for (Symbol_assignments::iterator p = this->symbol_assignments_.begin();
        p != this->symbol_assignments_.end();
        ++p)
-    (*p)->set_if_absolute(symtab, layout, false, 0);
+    (*p)->set_if_absolute(symtab, layout, false, 0, NULL);
 
   return this->script_sections_.set_section_addresses(symtab, layout);
 }
index 73079a4..f41f438 100644 (file)
@@ -90,20 +90,28 @@ class Expression
   // the section address.  If RESULT_ALIGNMENT is not NULL, this sets
   // *RESULT_ALIGNMENT to the alignment of the value of that alignment
   // is larger than *RESULT_ALIGNMENT; this will only be non-zero if
-  // this is an ALIGN expression.
+  // this is an ALIGN expression.  If IS_SECTION_DOT_ASSIGMENT is true,
+  // we are evaluating an assignment to dot within an output section,
+  // and an absolute value should be interpreted as an offset within
+  // the section.
   uint64_t
   eval_with_dot(const Symbol_table*, const Layout*, bool check_assertions,
                uint64_t dot_value, Output_section* dot_section,
-               Output_section** result_section, uint64_t* result_alignment);
+               Output_section** result_section, uint64_t* result_alignment,
+               bool is_section_dot_assignment);
 
   // Return the value of an expression which may or may not be
   // permitted to refer to the dot symbol, depending on
-  // is_dot_available.
+  // is_dot_available.  If IS_SECTION_DOT_ASSIGMENT is true,
+  // we are evaluating an assignment to dot within an output section,
+  // and an absolute value should be interpreted as an offset within
+  // the section.
   uint64_t
   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, uint64_t* result_alignment);
+                Output_section** result_section, uint64_t* result_alignment,
+                bool is_section_dot_assignment);
 
   // Print the expression to the FILE.  This is for debugging.
   virtual void
@@ -339,12 +347,12 @@ class Symbol_assignment
   finalize_with_dot(Symbol_table*, const Layout*, uint64_t dot_value,
                    Output_section* dot_section);
 
-  // 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.  We do not check assertions.
+  // Set the symbol value, but only if the value is absolute or relative to
+  // DOT_SECTION.  This is used while processing a SECTIONS clause.
+  // We assume that dot is 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);
+                 uint64_t dot_value, Output_section* dot_section);
 
   const std::string&
   name() const
index 73d39df..6a0188f 100644 (file)
@@ -49,7 +49,7 @@ SECTIONS
     /* This should match the remaining sections.  */
     *(.gold_test)
 
-    . = . + 4;
+    . = 60;
     start_data = .;
     BYTE(1)
     SHORT(2)