aboutsummaryrefslogtreecommitdiff
path: root/ld/ldexp.c
diff options
context:
space:
mode:
Diffstat (limited to 'ld/ldexp.c')
-rw-r--r--ld/ldexp.c90
1 files changed, 84 insertions, 6 deletions
diff --git a/ld/ldexp.c b/ld/ldexp.c
index 4023639..903374e 100644
--- a/ld/ldexp.c
+++ b/ld/ldexp.c
@@ -1,6 +1,6 @@
/* This module handles expression trees.
Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001
+ 2001, 2002
Free Software Foundation, Inc.
Written by Steve Chamberlain of Cygnus Support <sac@cygnus.com>.
@@ -39,6 +39,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
#include "ldgram.h"
#include "ldlang.h"
#include "libiberty.h"
+#include "safe-ctype.h"
static void exp_print_token PARAMS ((token_code_type code));
static void make_abs PARAMS ((etree_value_type *ptr));
@@ -46,7 +47,7 @@ static etree_value_type new_abs PARAMS ((bfd_vma value));
static void check PARAMS ((lang_output_section_statement_type *os,
const char *name, const char *op));
static etree_value_type new_rel
- PARAMS ((bfd_vma value, lang_output_section_statement_type *section));
+ PARAMS ((bfd_vma, char *, lang_output_section_statement_type *section));
static etree_value_type new_rel_from_section
PARAMS ((bfd_vma value, lang_output_section_statement_type *section));
static etree_value_type fold_binary
@@ -176,9 +177,22 @@ exp_intop (value)
etree_type *new = (etree_type *) stat_alloc (sizeof (new->value));
new->type.node_code = INT;
new->value.value = value;
+ new->value.str = NULL;
new->type.node_class = etree_value;
return new;
+}
+etree_type *
+exp_bigintop (value, str)
+ bfd_vma value;
+ char *str;
+{
+ etree_type *new = (etree_type *) stat_alloc (sizeof (new->value));
+ new->type.node_code = INT;
+ new->value.value = value;
+ new->value.str = str;
+ new->type.node_class = etree_value;
+ return new;
}
/* Build an expression representing an unnamed relocateable value. */
@@ -197,13 +211,15 @@ exp_relop (section, value)
}
static etree_value_type
-new_rel (value, section)
+new_rel (value, str, section)
bfd_vma value;
+ char *str;
lang_output_section_statement_type *section;
{
etree_value_type new;
new.valid_p = true;
new.value = value;
+ new.str = str;
new.section = section;
return new;
}
@@ -216,6 +232,7 @@ new_rel_from_section (value, section)
etree_value_type new;
new.valid_p = true;
new.value = value;
+ new.str = NULL;
new.section = section;
new.value -= section->bfd_section->vma;
@@ -450,6 +467,7 @@ fold_name (tree, current_section, allocation_done, dot)
being linked with -R? */
result = new_rel ((h->u.def.value
+ h->u.def.section->output_offset),
+ NULL,
os);
}
}
@@ -467,7 +485,7 @@ fold_name (tree, current_section, allocation_done, dot)
os = lang_output_section_find (tree->name.name);
check (os, tree->name.name, "ADDR");
- result = new_rel (0, os);
+ result = new_rel (0, NULL, os);
}
else
result = invalid ();
@@ -481,7 +499,7 @@ fold_name (tree, current_section, allocation_done, dot)
os = lang_output_section_find (tree->name.name);
check (os, tree->name.name, "LOADADDR");
if (os->load_base == NULL)
- result = new_rel (0, os);
+ result = new_rel (0, NULL, os);
else
result = exp_fold_tree_no_dot (os->load_base,
abs_output_section,
@@ -532,7 +550,7 @@ exp_fold_tree (tree, current_section, allocation_done, dot, dotp)
switch (tree->type.node_class)
{
case etree_value:
- result = new_rel (tree->value.value, current_section);
+ result = new_rel (tree->value.value, tree->value.str, current_section);
break;
case etree_rel:
@@ -542,6 +560,7 @@ exp_fold_tree (tree, current_section, allocation_done, dot, dotp)
result = new_rel ((tree->rel.value
+ tree->rel.section->output_section->vma
+ tree->rel.section->output_offset),
+ NULL,
current_section);
break;
@@ -1025,6 +1044,65 @@ exp_get_value_int (tree, def, name, allocation_done)
return (int) exp_get_vma (tree, (bfd_vma) def, name, allocation_done);
}
+fill_type *
+exp_get_fill (tree, def, name, allocation_done)
+ etree_type *tree;
+ fill_type *def;
+ char *name;
+ lang_phase_type allocation_done;
+{
+ fill_type *fill;
+ etree_value_type r;
+ size_t len;
+ unsigned int val;
+
+ if (tree == NULL)
+ return def;
+
+ r = exp_fold_tree_no_dot (tree, abs_output_section, allocation_done);
+ if (! r.valid_p && name != NULL)
+ einfo (_("%F%S nonconstant expression for %s\n"), name);
+
+ if (r.str != NULL && (len = strlen (r.str)) != 0)
+ {
+ unsigned char *dst;
+ unsigned char *s;
+ fill = (fill_type *) xmalloc ((len + 1) / 2 + sizeof (*fill) - 1);
+ fill->size = (len + 1) / 2;
+ dst = fill->data;
+ s = r.str;
+ val = 0;
+ do
+ {
+ unsigned int digit;
+
+ digit = *s++ - '0';
+ if (digit > 9)
+ digit = (digit - 'A' + '0' + 10) & 0xf;
+ val <<= 4;
+ val += digit;
+ --len;
+ if ((len & 1) == 0)
+ {
+ *dst++ = val;
+ val = 0;
+ }
+ }
+ while (len != 0);
+ }
+ else
+ {
+ fill = (fill_type *) xmalloc (4 + sizeof (*fill) - 1);
+ val = r.value;
+ fill->data[0] = (val >> 24) & 0xff;
+ fill->data[1] = (val >> 16) & 0xff;
+ fill->data[2] = (val >> 8) & 0xff;
+ fill->data[3] = (val >> 0) & 0xff;
+ fill->size = 4;
+ }
+ return fill;
+}
+
bfd_vma
exp_get_abs_int (tree, def, name, allocation_done)
etree_type *tree;