struct exp_data_seg exp_data_seg;
+segment_type *segments;
+
/* Print the string representation of the given token. Surround it
with spaces if INFIX_P is TRUE. */
{ REL, "relocatable" },
{ DATA_SEGMENT_ALIGN, "DATA_SEGMENT_ALIGN" },
{ DATA_SEGMENT_RELRO_END, "DATA_SEGMENT_RELRO_END" },
- { DATA_SEGMENT_END, "DATA_SEGMENT_END" }
+ { DATA_SEGMENT_END, "DATA_SEGMENT_END" },
+ { SEGMENT_START, "SEGMENT_START" }
};
unsigned int idx;
result.valid_p = FALSE;
break;
- case DATA_SEGMENT_RELRO_END:
- if (allocation_done != lang_first_phase_enum
- && (exp_data_seg.phase == exp_dataseg_align_seen
- || exp_data_seg.phase == exp_dataseg_adjust
- || exp_data_seg.phase == exp_dataseg_relro_adjust
- || allocation_done != lang_allocating_phase_enum))
- {
- if (exp_data_seg.phase == exp_dataseg_align_seen
- || exp_data_seg.phase == exp_dataseg_relro_adjust)
- exp_data_seg.relro_end
- = result.value + current_section->bfd_section->vma;
- if (exp_data_seg.phase == exp_dataseg_align_seen)
- exp_data_seg.phase = exp_dataseg_relro_seen;
- result.value = dot - current_section->bfd_section->vma;
- }
- else
- result.valid_p = FALSE;
- break;
-
case DATA_SEGMENT_END:
if (allocation_done != lang_first_phase_enum
&& current_section == abs_output_section
result = exp_fold_tree (tree->binary.lhs, current_section,
allocation_done, dot, dotp);
- if (result.valid_p)
+
+ /* The SEGMENT_START operator is special because its first
+ operand is a string, not the name of a symbol. */
+ if (result.valid_p && tree->type.node_code == SEGMENT_START)
+ {
+ const char *segment_name;
+ segment_type *seg;
+ /* Check to see if the user has overridden the default
+ value. */
+ segment_name = tree->binary.rhs->name.name;
+ for (seg = segments; seg; seg = seg->next)
+ if (strcmp (seg->name, segment_name) == 0)
+ {
+ seg->used = TRUE;
+ result.value = seg->value;
+ result.str = NULL;
+ result.section = NULL;
+ break;
+ }
+ }
+ else if (result.valid_p)
{
etree_value_type other;
case ALIGN_K:
result.value = align_n (result.value, other.value);
break;
-
+
case DATA_SEGMENT_ALIGN:
if (allocation_done != lang_first_phase_enum
&& current_section == abs_output_section
result.value = align_n (dot, maxpage);
if (exp_data_seg.phase == exp_dataseg_relro_adjust)
- {
- /* Attempt to align DATA_SEGMENT_RELRO_END at
- a common page boundary. */
- bfd_vma relro;
-
- relro = exp_data_seg.relro_end - exp_data_seg.base;
- result.value += -relro & (other.value - 1);
- exp_data_seg.base = result.value;
- }
+ result.value = exp_data_seg.base;
else if (exp_data_seg.phase != exp_dataseg_adjust)
{
result.value += dot & (maxpage - 1);
result.valid_p = FALSE;
break;
+ case DATA_SEGMENT_RELRO_END:
+ if (allocation_done != lang_first_phase_enum
+ && (exp_data_seg.phase == exp_dataseg_align_seen
+ || exp_data_seg.phase == exp_dataseg_adjust
+ || exp_data_seg.phase == exp_dataseg_relro_adjust
+ || allocation_done != lang_allocating_phase_enum))
+ {
+ if (exp_data_seg.phase == exp_dataseg_align_seen
+ || exp_data_seg.phase == exp_dataseg_relro_adjust)
+ exp_data_seg.relro_end
+ = result.value + other.value;
+ if (exp_data_seg.phase == exp_dataseg_relro_adjust
+ && (exp_data_seg.relro_end
+ & (exp_data_seg.pagesize - 1)))
+ {
+ exp_data_seg.relro_end += exp_data_seg.pagesize - 1;
+ exp_data_seg.relro_end &= ~(exp_data_seg.pagesize - 1);
+ result.value = exp_data_seg.relro_end - other.value;
+ }
+ if (exp_data_seg.phase == exp_dataseg_align_seen)
+ exp_data_seg.phase = exp_dataseg_relro_seen;
+ }
+ else
+ result.valid_p = FALSE;
+ break;
+
default:
FAIL ();
}
etree_value_type result;
result.valid_p = FALSE;
-
+
switch (tree->type.node_code)
{
case SIZEOF_HEADERS:
{
h->type = bfd_link_hash_undefined;
h->u.undef.abfd = NULL;
- bfd_link_add_undef (link_info.hash, h);
+ if (h->u.undef.next == NULL)
+ bfd_link_add_undef (link_info.hash, h);
}
}
break;
os = lang_output_section_find (tree->name.name);
if (os && os->processed > 0)
- result = new_abs (os->bfd_section->_raw_size / opb);
+ result = new_abs (os->bfd_section->size / opb);
}
break;
if (result.valid_p)
{
if (! result.value)
- einfo ("%F%P: %s\n", tree->assert_s.message);
+ einfo ("%X%P: %s\n", tree->assert_s.message);
return result;
}
break;