This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

gold patch committed (Was: Re: Help needed to track down bug: linking Linux kernel with gold creates unbootable kernel)


John Reiser <jreiser@bitwagon.com> writes:

>> Linux kernel linker scripts needs to align .rodata section to 2MB:
>>
>> . = ALIGN((1<<  21));
>>
>> Since gold can only align to 4K, gold can't be used on Linux
>> kernel.
>
> The linker script statement ". = ALIGN((1<<  21));" requires alignment
> to 2 MiB.  If gold "can only align to 4 KiB", then gold must emit an
> error message upon processing input that requires a larger alignment.
> It is a bug that current gold does not emit such a message for this case.

The problem is that the alignment requested by the linker script is
not reflected in the linker output.  That actually appears to be true
of the GNU linker as well.  Logically, an alignment requested in the
linker script should be reflected in the program segments.

I committed this patch to make an alignment requested in the linker
script be reflected in the p_align field of the generated program
headers.  I don't know if this actually fixes the problem, but it
seems like the right thing to do.

Ian


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.


Index: expression.cc
===================================================================
RCS file: /cvs/src/src/gold/expression.cc,v
retrieving revision 1.13
diff -p -u -r1.13 expression.cc
--- expression.cc	14 Dec 2009 19:53:04 -0000	1.13
+++ expression.cc	23 Apr 2010 04:37:09 -0000
@@ -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* sym
 {
   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_
   *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 Expressi
 				      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 Express
  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 Express
     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 Expres
 				       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_expr
     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_exp
   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_exp
   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_e
   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: output.h
===================================================================
RCS file: /cvs/src/src/gold/output.h,v
retrieving revision 1.103
diff -p -u -r1.103 output.h
--- output.h	9 Apr 2010 17:32:58 -0000	1.103
+++ output.h	23 Apr 2010 04:37:10 -0000
@@ -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: script-sections.cc
===================================================================
RCS file: /cvs/src/src/gold/script-sections.cc,v
retrieving revision 1.32
diff -p -u -r1.32 script-sections.cc
--- script-sections.cc	9 Apr 2010 17:32:58 -0000	1.32
+++ script-sections.cc	23 Apr 2010 04:37:11 -0000
@@ -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 : publ
   // 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 : 
     // 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 
   // 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_assignm
 		   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::s
     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_buff
   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 : publ
   // 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
     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 : publ
   // 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 : pub
   // 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_sectio
     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
   // 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_symb
 	  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_symb
 	  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_a
     {
       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_a
     {
       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_a
       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_a
       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_a
       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_a
        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 Sec
 
   // 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 Sec
 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(S
 
   // 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(S
 	    }
 	}
 
-      (*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(S
 	(*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(
 // 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*
     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*
 	  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(
 // 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_p
 // 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_addres
 	  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: script-sections.h
===================================================================
RCS file: /cvs/src/src/gold/script-sections.h,v
retrieving revision 1.11
diff -p -u -r1.11 script-sections.h
--- script-sections.h	9 Apr 2010 17:32:58 -0000	1.11
+++ script-sections.h	23 Apr 2010 04:37:11 -0000
@@ -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: script.cc
===================================================================
RCS file: /cvs/src/src/gold/script.cc,v
retrieving revision 1.70
diff -p -u -r1.70 script.cc
--- script.cc	9 Apr 2010 17:32:58 -0000	1.70
+++ script.cc	23 Apr 2010 04:37:11 -0000
@@ -955,7 +955,7 @@ Symbol_assignment::sized_finalize(Symbol
   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(Symbo
   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: script.h
===================================================================
RCS file: /cvs/src/src/gold/script.h,v
retrieving revision 1.32
diff -p -u -r1.32 script.h
--- script.h	12 Jan 2010 06:41:36 -0000	1.32
+++ script.h	23 Apr 2010 04:37:12 -0000
@@ -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: testsuite/script_test_3.sh
===================================================================
RCS file: /cvs/src/src/gold/testsuite/script_test_3.sh,v
retrieving revision 1.2
diff -p -u -r1.2 script_test_3.sh
--- testsuite/script_test_3.sh	10 Apr 2008 01:02:46 -0000	1.2
+++ testsuite/script_test_3.sh	23 Apr 2010 04:37:12 -0000
@@ -85,4 +85,18 @@ if test "$section_size" != "$segment_siz
   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: testsuite/script_test_3.t
===================================================================
RCS file: /cvs/src/src/gold/testsuite/script_test_3.t,v
retrieving revision 1.3
diff -p -u -r1.3 script_test_3.t
--- testsuite/script_test_3.t	24 Mar 2010 18:12:48 -0000	1.3
+++ testsuite/script_test_3.t	23 Apr 2010 04:37:12 -0000
@@ -35,7 +35,7 @@ SECTIONS
   .tdata : { *(.tdata*) } :data :tls
   .tbss : { *(.tbss*) } :data :tls
   . += 0x100000;
-  . = ALIGN(0x100);
+  . = ALIGN(0x100000);
   .bss : { *(.bss) } :bss
 }
 

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]