* expression.cc (Expression::Expression_eval_info): Add
authorIan Lance Taylor <ian@airs.com>
Fri, 23 Apr 2010 04:47:33 +0000 (04:47 +0000)
committerIan Lance Taylor <ian@airs.com>
Fri, 23 Apr 2010 04:47:33 +0000 (04:47 +0000)
result_alignment_pointer field.
(Expression::eval_with_dot): Add result_alignment_pointer
parameter.  Change all callers.
(Expression::eval_maybe_dot): Likewise.
(class Binary_expression): Add alignment_pointer parameter to
left_value and right_value.  Change all callers.
(BINARY_EXPRESSION): Set result alignment.
(class Trinary_expression): Add alignment_pointer parameter to
arg2_value and arg3_value.  Change all callers.
(Trinary_cond::value): Set result alignment.
(Max_expression::value, Min_expression::value): Likewise.
(Align_expression::value): Likewise.
* script-sections.cc (class Sections_element): Add dot_alignment
parameter to set_section_addresses virtual function.  Update
instantiations.
(class Output_section_element): Likewise.
(Script_sections::create_segments): Add dot_alignment parameter.
Change all callers.
(Script_sections::create_segments_from_phdrs_clause): Likewise.
(Script_sections::set_phdrs_clause_addresses): Likewise.
* script-sections.h: Update declarations.
* script.h: Update declarations.
* output.h (Output_segment::set_minimum_p_align): Don't decrease
min_p_align.
* testsuite/script_test_3.t: Set large alignment.
* testsuite/script_test_3.sh: Make sure that at least one LOAD
segment has expected alignment.

gold/ChangeLog
gold/expression.cc
gold/output.h
gold/script-sections.cc
gold/script-sections.h
gold/script.cc
gold/script.h
gold/testsuite/script_test_3.sh
gold/testsuite/script_test_3.t

index f3fabd00a6c1b3403a829b5360f82183e21d034b..54e775dd0dca76b678914c25025e1b13ef87bd7a 100644 (file)
@@ -1,3 +1,34 @@
+2010-04-22  Ian Lance Taylor  <iant@google.com>
+
+       * expression.cc (Expression::Expression_eval_info): Add
+       result_alignment_pointer field.
+       (Expression::eval_with_dot): Add result_alignment_pointer
+       parameter.  Change all callers.
+       (Expression::eval_maybe_dot): Likewise.
+       (class Binary_expression): Add alignment_pointer parameter to
+       left_value and right_value.  Change all callers.
+       (BINARY_EXPRESSION): Set result alignment.
+       (class Trinary_expression): Add alignment_pointer parameter to
+       arg2_value and arg3_value.  Change all callers.
+       (Trinary_cond::value): Set result alignment.
+       (Max_expression::value, Min_expression::value): Likewise.
+       (Align_expression::value): Likewise.
+       * script-sections.cc (class Sections_element): Add dot_alignment
+       parameter to set_section_addresses virtual function.  Update
+       instantiations.
+       (class Output_section_element): Likewise.
+       (Script_sections::create_segments): Add dot_alignment parameter.
+       Change all callers.
+       (Script_sections::create_segments_from_phdrs_clause): Likewise.
+       (Script_sections::set_phdrs_clause_addresses): Likewise.
+       * script-sections.h: Update declarations.
+       * script.h: Update declarations.
+       * output.h (Output_segment::set_minimum_p_align): Don't decrease
+       min_p_align.
+       * testsuite/script_test_3.t: Set large alignment.
+       * testsuite/script_test_3.sh: Make sure that at least one LOAD
+       segment has expected alignment.
+
 2010-04-22  Nick Clifton  <nickc@redhat.com>
 
        * po/gold.pot: Updated by the Translation project.
index 853a698d187b1fc99a5a28ba5a49ba43eeafac8f..134b0fa2a22a4c10a1b283c63629a36b58357376 100644 (file)
@@ -66,6 +66,8 @@ struct Expression::Expression_eval_info
   Output_section* dot_section;
   // Points to where the section of the result should be stored.
   Output_section** result_section_pointer;
+  // Pointer to where the alignment of the result should be stored.
+  uint64_t* result_alignment_pointer;
 };
 
 // Evaluate an expression.
@@ -76,7 +78,7 @@ Expression::eval(const Symbol_table* symtab, const Layout* layout,
 {
   Output_section* dummy;
   return this->eval_maybe_dot(symtab, layout, check_assertions,
-                             false, 0, NULL, &dummy);
+                             false, 0, NULL, &dummy, NULL);
 }
 
 // Evaluate an expression which may refer to the dot symbol.
@@ -85,10 +87,12 @@ uint64_t
 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)
+                         Output_section** result_section_pointer,
+                         uint64_t* result_alignment_pointer)
 {
   return this->eval_maybe_dot(symtab, layout, check_assertions, true,
-                             dot_value, dot_section, result_section_pointer);
+                             dot_value, dot_section, result_section_pointer,
+                             result_alignment_pointer);
 }
 
 // Evaluate an expression which may or may not refer to the dot
@@ -98,7 +102,8 @@ uint64_t
 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)
+                          Output_section** result_section_pointer,
+                          uint64_t* result_alignment_pointer)
 {
   Expression_eval_info eei;
   eei.symtab = symtab;
@@ -113,6 +118,8 @@ Expression::eval_maybe_dot(const Symbol_table* symtab, const Layout* layout,
   *result_section_pointer = NULL;
   eei.result_section_pointer = result_section_pointer;
 
+  eei.result_alignment_pointer = result_alignment_pointer;
+
   return this->value(&eei);
 }
 
@@ -247,7 +254,8 @@ class Unary_expression : public Expression
                                      eei->is_dot_available,
                                      eei->dot_value,
                                      eei->dot_section,
-                                     arg_section_pointer);
+                                     arg_section_pointer,
+                                     eei->result_alignment_pointer);
   }
 
   void
@@ -317,26 +325,30 @@ class Binary_expression : public Expression
  protected:
   uint64_t
   left_value(const Expression_eval_info* eei,
-            Output_section** section_pointer) const
+            Output_section** section_pointer,
+            uint64_t* alignment_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,
-                                      section_pointer);
+                                      section_pointer,
+                                      alignment_pointer);
   }
 
   uint64_t
   right_value(const Expression_eval_info* eei,
-             Output_section** section_pointer) const
+             Output_section** section_pointer,
+             uint64_t* alignment_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,
-                                       section_pointer);
+                                       section_pointer,
+                                       alignment_pointer);
   }
 
   void
@@ -385,15 +397,27 @@ class Binary_expression : public Expression
     value(const Expression_eval_info* eei)                             \
     {                                                                  \
       Output_section* left_section;                                    \
-      uint64_t left = this->left_value(eei, &left_section);            \
+      uint64_t left_alignment;                                         \
+      uint64_t left = this->left_value(eei, &left_section,             \
+                                      &left_alignment);                \
       Output_section* right_section;                                   \
-      uint64_t right = this->right_value(eei, &right_section);         \
+      uint64_t right_alignment;                                                \
+      uint64_t right = this->right_value(eei, &right_section,          \
+                                        &right_alignment);             \
       if (KEEP_RIGHT && left_section == NULL && right_section != NULL) \
-       *eei->result_section_pointer = right_section;                   \
+       {                                                               \
+         *eei->result_section_pointer = right_section;                 \
+         if (eei->result_alignment_pointer != NULL)                    \
+           *eei->result_alignment_pointer = right_alignment;           \
+       }                                                               \
       else if (KEEP_LEFT                                               \
               && left_section != NULL                                  \
               && right_section == NULL)                                \
-       *eei->result_section_pointer = left_section;                    \
+       {                                                               \
+         *eei->result_section_pointer = left_section;                  \
+         if (eei->result_alignment_pointer != NULL)                    \
+           *eei->result_alignment_pointer = right_alignment;           \
+       }                                                               \
       else if ((WARN || left_section != right_section)                 \
               && (left_section != NULL || right_section != NULL)       \
               && parameters->options().relocatable())                  \
@@ -469,31 +493,36 @@ class Trinary_expression : public Expression
                                       eei->is_dot_available,
                                       eei->dot_value,
                                       eei->dot_section,
-                                      section_pointer);
+                                      section_pointer,
+                                      NULL);
   }
 
   uint64_t
   arg2_value(const Expression_eval_info* eei,
-            Output_section** section_pointer) const
+            Output_section** section_pointer,
+            uint64_t* alignment_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,
-                                      section_pointer);
+                                      section_pointer,
+                                      alignment_pointer);
   }
 
   uint64_t
   arg3_value(const Expression_eval_info* eei,
-            Output_section** section_pointer) const
+            Output_section** section_pointer,
+            uint64_t* alignment_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,
-                                      section_pointer);
+                                      section_pointer,
+                                      alignment_pointer);
   }
 
   void
@@ -529,8 +558,10 @@ class Trinary_cond : public Trinary_expression
     Output_section* arg1_section;
     uint64_t arg1 = this->arg1_value(eei, &arg1_section);
     return (arg1
-           ? this->arg2_value(eei, eei->result_section_pointer)
-           : this->arg3_value(eei, eei->result_section_pointer));
+           ? this->arg2_value(eei, eei->result_section_pointer,
+                              eei->result_alignment_pointer)
+           : this->arg3_value(eei, eei->result_section_pointer,
+                              eei->result_alignment_pointer));
   }
 
   void
@@ -565,14 +596,27 @@ class Max_expression : public Binary_expression
   value(const Expression_eval_info* eei)
   {
     Output_section* left_section;
-    uint64_t left = this->left_value(eei, &left_section);
+    uint64_t left_alignment;
+    uint64_t left = this->left_value(eei, &left_section, &left_alignment);
     Output_section* right_section;
-    uint64_t right = this->right_value(eei, &right_section);
+    uint64_t right_alignment;
+    uint64_t right = this->right_value(eei, &right_section, &right_alignment);
     if (left_section == right_section)
       *eei->result_section_pointer = left_section;
     else if ((left_section != NULL || right_section != NULL)
             && parameters->options().relocatable())
       gold_warning(_("max applied to section relative value"));
+    if (eei->result_alignment_pointer != NULL)
+      {
+       uint64_t ra = *eei->result_alignment_pointer;
+       if (left > right)
+         ra = std::max(ra, left_alignment);
+       else if (right > left)
+         ra = std::max(ra, right_alignment);
+       else
+         ra = std::max(ra, std::max(left_alignment, right_alignment));
+       *eei->result_alignment_pointer = ra;
+      }
     return std::max(left, right);
   }
 
@@ -600,14 +644,27 @@ class Min_expression : public Binary_expression
   value(const Expression_eval_info* eei)
   {
     Output_section* left_section;
-    uint64_t left = this->left_value(eei, &left_section);
+    uint64_t left_alignment;
+    uint64_t left = this->left_value(eei, &left_section, &left_alignment);
     Output_section* right_section;
-    uint64_t right = this->right_value(eei, &right_section);
+    uint64_t right_alignment;
+    uint64_t right = this->right_value(eei, &right_section, &right_alignment);
     if (left_section == right_section)
       *eei->result_section_pointer = left_section;
     else if ((left_section != NULL || right_section != NULL)
             && parameters->options().relocatable())
       gold_warning(_("min applied to section relative value"));
+    if (eei->result_alignment_pointer != NULL)
+      {
+       uint64_t ra = *eei->result_alignment_pointer;
+       if (left < right)
+         ra = std::max(ra, left_alignment);
+       else if (right < left)
+         ra = std::max(ra, right_alignment);
+       else
+         ra = std::max(ra, std::max(left_alignment, right_alignment));
+       *eei->result_alignment_pointer = ra;
+      }
     return std::min(left, right);
   }
 
@@ -734,12 +791,21 @@ class Align_expression : public Binary_expression
   value(const Expression_eval_info* eei)
   {
     Output_section* align_section;
-    uint64_t align = this->right_value(eei, &align_section);
+    uint64_t align = this->right_value(eei, &align_section, NULL);
     if (align_section != NULL
        && parameters->options().relocatable())
       gold_warning(_("aligning to section relative value"));
 
-    uint64_t value = this->left_value(eei, eei->result_section_pointer);
+    if (eei->result_alignment_pointer != NULL
+       && align > *eei->result_alignment_pointer)
+      {
+       uint64_t a = align;
+       while ((a & (a - 1)) != 0)
+         a &= a - 1;
+       *eei->result_alignment_pointer = a;
+      }
+
+    uint64_t value = this->left_value(eei, eei->result_section_pointer, NULL);
     if (align <= 1)
       return value;
     return ((value + align - 1) / align) * align;
index 808856534928bf057e19333f319a5ba605908d21..410ec2c39e67f74e65bc82419dcad76fd77c5db5 100644 (file)
@@ -3833,7 +3833,10 @@ class Output_segment
   // upward based on the section alignments.
   void
   set_minimum_p_align(uint64_t align)
-  { this->min_p_align_ = align; }
+  {
+    if (align > this->min_p_align_)
+      this->min_p_align_ = align;
+  }
 
   // Set the offset of this segment based on the section.  This should
   // only be called for a non-PT_LOAD segment.
index 24b9103f9217d8c543c606704091902540836c53..b4cbb40114910131f2cf52efd13f8364d81b6911 100644 (file)
@@ -369,7 +369,8 @@ 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*, uint64_t*, uint64_t*)
+  set_section_addresses(Symbol_table*, Layout*, uint64_t*, uint64_t*,
+                       uint64_t*)
   { }
 
   // Check a constraint (ONLY_IF_RO, etc.) on an output section.  If
@@ -447,7 +448,7 @@ class Sections_element_assignment : public Sections_element
   // absolute symbols when setting dot.
   void
   set_section_addresses(Symbol_table* symtab, Layout* layout,
-                       uint64_t* dot_value, uint64_t*)
+                       uint64_t* dot_value, uint64_t*, uint64_t*)
   {
     this->assignment_.set_if_absolute(symtab, layout, true, *dot_value);
   }
@@ -484,17 +485,18 @@ class Sections_element_dot_assignment : public Sections_element
     // to be absolute.
     Output_section* dummy;
     *dot_value = this->val_->eval_with_dot(symtab, layout, true, *dot_value,
-                                          NULL, &dummy);
+                                          NULL, &dummy, NULL);
   }
 
   // Update the dot symbol while setting section addresses.
   void
   set_section_addresses(Symbol_table* symtab, Layout* layout,
-                       uint64_t* dot_value, uint64_t* load_address)
+                       uint64_t* dot_value, uint64_t* dot_alignment,
+                       uint64_t* load_address)
   {
     Output_section* dummy;
     *dot_value = this->val_->eval_with_dot(symtab, layout, false, *dot_value,
-                                          NULL, &dummy);
+                                          NULL, &dummy, dot_alignment);
     *load_address = *dot_value;
   }
 
@@ -577,7 +579,7 @@ class Output_section_element
   // the expression is an absolute value.
   virtual void
   set_section_addresses(Symbol_table*, Layout*, Output_section*, uint64_t,
-                       uint64_t*, Output_section**, std::string*,
+                       uint64_t*, uint64_t*, Output_section**, std::string*,
                        Input_section_list*)
   { }
 
@@ -635,8 +637,8 @@ 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, Output_section**,
-                       std::string*, Input_section_list*)
+                       uint64_t, uint64_t* dot_value, uint64_t*,
+                       Output_section**, std::string*, Input_section_list*)
   {
     this->assignment_.set_if_absolute(symtab, layout, true, *dot_value);
   }
@@ -668,14 +670,14 @@ 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);
+                                          *dot_section, dot_section, NULL);
   }
 
   // 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, Output_section**,
-                       std::string*, Input_section_list*);
+                       uint64_t, uint64_t* dot_value, uint64_t*,
+                       Output_section**, std::string*, Input_section_list*);
 
   // Print for debugging.
   void
@@ -699,13 +701,14 @@ Output_section_element_dot_assignment::set_section_addresses(
     Output_section* output_section,
     uint64_t,
     uint64_t* dot_value,
+    uint64_t* dot_alignment,
     Output_section** dot_section,
     std::string* fill,
     Input_section_list*)
 {
   uint64_t next_dot = this->val_->eval_with_dot(symtab, layout, false,
                                                *dot_value, *dot_section,
-                                               dot_section);
+                                               dot_section, dot_alignment);
   if (next_dot < *dot_value)
     gold_error(_("dot may not move backward"));
   if (next_dot > *dot_value && output_section != NULL)
@@ -807,7 +810,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_,
                                           true, this->dot_value_,
-                                          this->dot_section_, &dummy);
+                                          this->dot_section_, &dummy, NULL);
 
   if (parameters->target().is_big_endian())
     this->endian_write_to_buffer<true>(val, buf);
@@ -868,8 +871,8 @@ class Output_section_element_data : public Output_section_element
   // 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*);
+                       uint64_t* dot_value, uint64_t*, Output_section**,
+                       std::string*, Input_section_list*);
 
   // Print for debugging.
   void
@@ -893,6 +896,7 @@ Output_section_element_data::set_section_addresses(
     Output_section* os,
     uint64_t,
     uint64_t* dot_value,
+    uint64_t*,
     Output_section** dot_section,
     std::string*,
     Input_section_list*)
@@ -949,14 +953,14 @@ 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,
+                       uint64_t, uint64_t* dot_value, uint64_t*,
                        Output_section** dot_section,
                        std::string* fill, Input_section_list*)
   {
     Output_section* fill_section;
     uint64_t fill_val = this->val_->eval_with_dot(symtab, layout, false,
                                                  *dot_value, *dot_section,
-                                                 &fill_section);
+                                                 &fill_section, NULL);
     if (fill_section != NULL)
       gold_warning(_("fill value is not absolute"));
     // FIXME: The GNU linker supports fill values of arbitrary length.
@@ -1012,7 +1016,7 @@ class Output_section_element_input : public Output_section_element
   // Set the section address.
   void
   set_section_addresses(Symbol_table* symtab, Layout* layout, Output_section*,
-                       uint64_t subalign, uint64_t* dot_value,
+                       uint64_t subalign, uint64_t* dot_value, uint64_t*,
                        Output_section**, std::string* fill,
                        Input_section_list*);
 
@@ -1309,6 +1313,7 @@ Output_section_element_input::set_section_addresses(
     Output_section* output_section,
     uint64_t subalign,
     uint64_t* dot_value,
+    uint64_t*,
     Output_section** dot_section,
     std::string* fill,
     Input_section_list* input_sections)
@@ -1629,7 +1634,8 @@ class Output_section_definition : public Sections_element
   // Set the section address.
   void
   set_section_addresses(Symbol_table* symtab, Layout* layout,
-                       uint64_t* dot_value, uint64_t* load_address);
+                       uint64_t* dot_value, uint64_t*,
+                       uint64_t* load_address);
 
   // Check a constraint (ONLY_IF_RO, etc.) on an output section.  If
   // this section is constrained, and the input sections do not match,
@@ -1861,7 +1867,7 @@ Output_section_definition::finalize_symbols(Symbol_table* symtab,
          Output_section* dummy;
          address = this->address_->eval_with_dot(symtab, layout, true,
                                                  *dot_value, NULL,
-                                                 &dummy);
+                                                 &dummy, NULL);
        }
       if (this->align_ != NULL)
        {
@@ -1869,7 +1875,7 @@ Output_section_definition::finalize_symbols(Symbol_table* symtab,
          uint64_t align = this->align_->eval_with_dot(symtab, layout, true,
                                                       *dot_value,
                                                       NULL,
-                                                      &dummy);
+                                                      &dummy, NULL);
          address = align_address(address, align);
        }
       *dot_value = address;
@@ -1918,6 +1924,7 @@ void
 Output_section_definition::set_section_addresses(Symbol_table* symtab,
                                                 Layout* layout,
                                                 uint64_t* dot_value,
+                                                uint64_t* dot_alignment,
                                                  uint64_t* load_address)
 {
   uint64_t address;
@@ -1930,7 +1937,8 @@ Output_section_definition::set_section_addresses(Symbol_table* symtab,
     {
       Output_section* dummy;
       address = this->address_->eval_with_dot(symtab, layout, true,
-                                             *dot_value, NULL, &dummy);
+                                             *dot_value, NULL, &dummy,
+                                             dot_alignment);
     }
 
   uint64_t align;
@@ -1945,7 +1953,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, &align_section, NULL);
       if (align_section != NULL)
        gold_warning(_("alignment of section %s is not absolute"),
                     this->name_.c_str());
@@ -1976,7 +1984,8 @@ Output_section_definition::set_section_addresses(Symbol_table* symtab,
       Output_section* dummy;
       uint64_t laddr =
        this->load_address_->eval_with_dot(symtab, layout, true, *dot_value,
-                                          this->output_section_, &dummy);
+                                          this->output_section_, &dummy,
+                                          NULL);
       if (this->output_section_ != NULL)
         this->output_section_->set_load_address(laddr);
       this->evaluated_load_address_ = laddr;
@@ -1990,7 +1999,7 @@ 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);
+                                               &subalign_section, NULL);
       if (subalign_section != NULL)
        gold_warning(_("subalign of section %s is not absolute"),
                     this->name_.c_str());
@@ -2004,8 +2013,8 @@ Output_section_definition::set_section_addresses(Symbol_table* symtab,
       Output_section* fill_section;
       uint64_t fill_val = this->fill_->eval_with_dot(symtab, layout, true,
                                                     *dot_value,
-                                                    NULL,
-                                                    &fill_section);
+                                                    NULL, &fill_section,
+                                                    NULL);
       if (fill_section != NULL)
        gold_warning(_("fill of section %s is not absolute"),
                     this->name_.c_str());
@@ -2031,8 +2040,8 @@ Output_section_definition::set_section_addresses(Symbol_table* symtab,
        p != this->elements_.end();
        ++p)
     (*p)->set_section_addresses(symtab, layout, this->output_section_,
-                               subalign, dot_value, &dot_section, &fill,
-                               &input_sections);
+                               subalign, dot_value, dot_alignment,
+                               &dot_section, &fill, &input_sections);
 
   gold_assert(input_sections.empty());
 
@@ -2339,7 +2348,8 @@ class Orphan_output_section : public Sections_element
 
   // Set section addresses.
   void
-  set_section_addresses(Symbol_table*, Layout*, uint64_t*, uint64_t*);
+  set_section_addresses(Symbol_table*, Layout*, uint64_t*, uint64_t*,
+                       uint64_t*);
 
   // Get the list of segments to use for an allocated section when
   // using a PHDRS clause.
@@ -2368,6 +2378,7 @@ class Orphan_output_section : public Sections_element
 void
 Orphan_output_section::set_section_addresses(Symbol_table*, Layout*,
                                             uint64_t* dot_value,
+                                            uint64_t*,
                                              uint64_t* load_address)
 {
   typedef std::list<Output_section::Simple_input_section> Input_section_list;
@@ -2950,6 +2961,7 @@ Script_sections::set_section_addresses(Symbol_table* symtab, Layout* layout)
 
   // For a relocatable link, we implicitly set dot to zero.
   uint64_t dot_value = 0;
+  uint64_t dot_alignment = 0;
   uint64_t load_address = 0;
 
   // Check to see if we want to use any of -Ttext, -Tdata and -Tbss options
@@ -2995,7 +3007,8 @@ Script_sections::set_section_addresses(Symbol_table* symtab, Layout* layout)
            }
        }
 
-      (*p)->set_section_addresses(symtab, layout, &dot_value, &load_address);
+      (*p)->set_section_addresses(symtab, layout, &dot_value, &dot_alignment,
+                                 &load_address);
     } 
 
   if (this->phdrs_elements_ != NULL)
@@ -3006,7 +3019,7 @@ Script_sections::set_section_addresses(Symbol_table* symtab, Layout* layout)
        (*p)->eval_load_address(symtab, layout);
     }
 
-  return this->create_segments(layout);
+  return this->create_segments(layout, dot_alignment);
 }
 
 // Sort the sections in order to put them into segments.
@@ -3114,7 +3127,7 @@ Script_sections::header_size_adjustment(uint64_t lma,
 // if any.
 
 Output_segment*
-Script_sections::create_segments(Layout* layout)
+Script_sections::create_segments(Layout* layout, uint64_t dot_alignment)
 {
   gold_assert(this->saw_sections_clause_);
 
@@ -3122,7 +3135,7 @@ Script_sections::create_segments(Layout* layout)
     return NULL;
 
   if (this->saw_phdrs_clause())
-    return create_segments_from_phdrs_clause(layout);
+    return create_segments_from_phdrs_clause(layout, dot_alignment);
 
   Layout::Section_list sections;
   layout->get_allocated_sections(&sections);
@@ -3195,6 +3208,7 @@ Script_sections::create_segments(Layout* layout)
          current_seg = layout->make_output_segment(elfcpp::PT_LOAD,
                                                    seg_flags);
          current_seg->set_addresses(vma, lma);
+         current_seg->set_minimum_p_align(dot_alignment);
          if (first_seg == NULL)
            first_seg = current_seg;
          is_current_seg_readonly = true;
@@ -3388,10 +3402,11 @@ Script_sections::expected_segment_count(const Layout* layout) const
 // should hold the file header and program headers, if any.
 
 Output_segment*
-Script_sections::create_segments_from_phdrs_clause(Layout* layout)
+Script_sections::create_segments_from_phdrs_clause(Layout* layout,
+                                                  uint64_t dot_alignment)
 {
   this->attach_sections_using_phdrs_clause(layout);
-  return this->set_phdrs_clause_addresses(layout);
+  return this->set_phdrs_clause_addresses(layout, dot_alignment);
 }
 
 // Create the segments from the PHDRS clause, and put the output
@@ -3485,7 +3500,8 @@ Script_sections::attach_sections_using_phdrs_clause(Layout* layout)
 // if any.
 
 Output_segment*
-Script_sections::set_phdrs_clause_addresses(Layout* layout)
+Script_sections::set_phdrs_clause_addresses(Layout* layout,
+                                           uint64_t dot_alignment)
 {
   Output_segment* load_seg = NULL;
   for (Phdrs_elements::const_iterator p = this->phdrs_elements_->begin();
@@ -3508,6 +3524,8 @@ Script_sections::set_phdrs_clause_addresses(Layout* layout)
          continue;
        }
 
+      oseg->set_minimum_p_align(dot_alignment);
+
       // The output sections should have addresses from the SECTIONS
       // clause.  The addresses don't have to be in order, so find the
       // one with the lowest load address.  Use that to set the
index 725d1a2ecca753409b4b1a2ec38599fa5f3156f4..f18b06c7d13a1f2625c56f6ac59dc3ff330c38e4 100644 (file)
@@ -232,7 +232,7 @@ class Script_sections
 
   // Create segments.
   Output_segment*
-  create_segments(Layout*);
+  create_segments(Layout*, uint64_t);
 
   // Create PT_NOTE and PT_TLS segments.
   void
@@ -253,7 +253,7 @@ class Script_sections
 
   // Create the segments from a PHDRS clause.
   Output_segment*
-  create_segments_from_phdrs_clause(Layout* layout);
+  create_segments_from_phdrs_clause(Layout* layout, uint64_t);
 
   // Attach sections to segments from a PHDRS clause.
   void
@@ -261,7 +261,7 @@ class Script_sections
 
   // Set addresses of segments from a PHDRS clause.
   Output_segment*
-  set_phdrs_clause_addresses(Layout*);
+  set_phdrs_clause_addresses(Layout*, uint64_t);
 
   // True if we ever saw a SECTIONS clause.
   bool saw_sections_clause_;
index 11e4612905c4ba837d63a92418163d82c6a251ff..a68fb3865a02b0f6bd1207bbe2daf02412e53049 100644 (file)
@@ -955,7 +955,7 @@ 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);
+                                                 &section, NULL);
   Sized_symbol<size>* ssym = symtab->get_sized_symbol<size>(this->sym_);
   ssym->set_value(final_val);
   if (section != NULL)
@@ -974,7 +974,7 @@ 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, &val_section, NULL);
   if (val_section != NULL)
     return;
 
index f4c3f22620be86b1025f4756d882fb0d550b91d9..3b8cb92f1c8462a18b651bb45640f02a36c224b9 100644 (file)
@@ -86,11 +86,14 @@ class Expression
   // value is defined.  If the value is absolute *RESULT_SECTION will
   // be NULL.  Note that the returned value is still an absolute
   // value; to get a section relative value the caller must subtract
-  // the section address.
+  // 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.
   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);
+               Output_section** result_section, uint64_t* result_alignment);
 
   // Return the value of an expression which may or may not be
   // permitted to refer to the dot symbol, depending on
@@ -99,7 +102,7 @@ class Expression
   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);
+                Output_section** result_section, uint64_t* result_alignment);
 
   // Print the expression to the FILE.  This is for debugging.
   virtual void
index cddb69accfdc5f90c8c1d4364554bce24ef5ecac..d114edd1807015e1d45009f0596147ae9362e7fe 100755 (executable)
@@ -85,4 +85,18 @@ if test "$section_size" != "$segment_size"; then
   exit 1
 fi
 
+# At least one PT_LOAD segment should have an alignment >= 0x100000.
+found=no
+for a in `grep LOAD script_test_3.stdout | sed -e 's/^.* 0x/0x/'`; do
+  script="BEGIN { if ($a >= 0x100000) { print \"true\" } else { print \"false\" } }"
+  x=`awk "$script" < /dev/null`
+  if test "$x" = "true"; then
+    found=yes
+  fi
+done
+if test "$found" = "no"; then
+  echo "no LOAD segment has required alignment"
+  exit 1
+fi
+
 exit 0
index a6a655f7e72434c333cac0c9e5d7ce897ad44ae8..75d8130510189bdd32c3d166c5a52a86bf30d90d 100644 (file)
@@ -35,7 +35,7 @@ SECTIONS
   .tdata : { *(.tdata*) } :data :tls
   .tbss : { *(.tbss*) } :data :tls
   . += 0x100000;
-  . = ALIGN(0x100);
+  . = ALIGN(0x100000);
   .bss : { *(.bss) } :bss
 }