Free Software Foundation, Inc.
Written by Steve Chamberlain of Cygnus Support <sac@cygnus.com>.
-This file is part of GLD, the Gnu Linker.
+ This file is part of GLD, the Gnu Linker.
-GLD is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
+ GLD is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
-GLD is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
+ GLD is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
-You should have received a copy of the GNU General Public License
-along with GLD; see the file COPYING. If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA. */
+ You should have received a copy of the GNU General Public License
+ along with GLD; see the file COPYING. If not, write to the Free
+ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
+ 02111-1307, USA. */
/* This module is in charge of working out the contents of expressions.
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" },
+ { ORIGIN, "ORIGIN" },
+ { LENGTH, "LENGTH" },
+ { 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;
-
- result.value += dot & (maxpage - 1);
- 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:
}
break;
+ case LENGTH:
+ {
+ lang_memory_region_type *mem;
+
+ mem = lang_memory_region_lookup (tree->name.name, FALSE);
+ if (mem != NULL)
+ result = new_abs (mem->length);
+ else
+ einfo (_("%F%S: undefined MEMORY region `%s' referenced in expression\n"),
+ tree->name.name);
+ }
+ break;
+
+ case ORIGIN:
+ {
+ lang_memory_region_type *mem;
+
+ mem = lang_memory_region_lookup (tree->name.name, FALSE);
+ if (mem != NULL)
+ result = new_abs (mem->origin);
+ else
+ einfo (_("%F%S: undefined MEMORY region `%s' referenced in expression\n"),
+ tree->name.name);
+ }
+ break;
+
default:
FAIL ();
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;