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 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.
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.
{
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.
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
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;
*result_section_pointer = NULL;
eei.result_section_pointer = result_section_pointer;
+ eei.result_alignment_pointer = result_alignment_pointer;
+
return this->value(&eei);
}
eei->is_dot_available,
eei->dot_value,
eei->dot_section,
- arg_section_pointer);
+ arg_section_pointer,
+ eei->result_alignment_pointer);
}
void
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
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()) \
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
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
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);
}
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);
}
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;
// 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.
// 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
// 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);
}
// 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;
}
// 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*)
{ }
// 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);
}
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
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)
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);
// 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
Output_section* os,
uint64_t,
uint64_t* dot_value,
+ uint64_t*,
Output_section** dot_section,
std::string*,
Input_section_list*)
// 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.
// 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*);
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)
// 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,
Output_section* dummy;
address = this->address_->eval_with_dot(symtab, layout, true,
*dot_value, NULL,
- &dummy);
+ &dummy, NULL);
}
if (this->align_ != NULL)
{
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;
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;
{
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;
{
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());
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;
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());
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());
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());
// 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.
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;
// 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
}
}
- (*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)
(*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.
// 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_);
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(§ions);
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;
// 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
// 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();
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
// Create segments.
Output_segment*
- create_segments(Layout*);
+ create_segments(Layout*, uint64_t);
// Create PT_NOTE and PT_TLS segments.
void
// 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
// 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_;
uint64_t final_val = this->val_->eval_maybe_dot(symtab, layout, true,
is_dot_available,
dot_value, dot_section,
- §ion);
+ §ion, NULL);
Sized_symbol<size>* ssym = symtab->get_sized_symbol<size>(this->sym_);
ssym->set_value(final_val);
if (section != NULL)
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;
// 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
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
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
.tdata : { *(.tdata*) } :data :tls
.tbss : { *(.tbss*) } :data :tls
. += 0x100000;
- . = ALIGN(0x100);
+ . = ALIGN(0x100000);
.bss : { *(.bss) } :bss
}