aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDJ Delorie <dj@redhat.com>2014-01-21 15:12:19 -0500
committerDJ Delorie <dj@redhat.com>2014-01-21 15:12:19 -0500
commitc9d665580ec705dab16bdf27147e584b44f70ed5 (patch)
tree3738321caec9c0fe53181c20f2b3e5c609a4eff5
parent4869db5e97b2062a3adf81158577171990248ef3 (diff)
downloadgdb-c9d665580ec705dab16bdf27147e584b44f70ed5.zip
gdb-c9d665580ec705dab16bdf27147e584b44f70ed5.tar.gz
gdb-c9d665580ec705dab16bdf27147e584b44f70ed5.tar.bz2
Ensure that %func() expressions are outermost terms
This is to avoid expressions like: %hi(foo) + 1, which will not do what you expect. The complex relocations can handle it, but the internal fixups can't.
-rw-r--r--gas/ChangeLog7
-rw-r--r--gas/config/tc-rl78.c36
2 files changed, 42 insertions, 1 deletions
diff --git a/gas/ChangeLog b/gas/ChangeLog
index 15fe29c..259c014 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,10 @@
+2014-01-21 DJ Delorie <dj@redhat.com>
+
+ * config/tc-rl78.c (require_end_of_expr): New.
+ (md_operand): Call it.
+ (rl78_cons_fix_new): Mark LO16, HI16, ahd HI8 internal relocations
+ as not overflowing.
+
2014-01-17 Will Newton <will.newton@linaro.org>
* config/tc-arm.c (do_vfp_nsyn_cvt_fpv8): Set OP to 1
diff --git a/gas/config/tc-rl78.c b/gas/config/tc-rl78.c
index 651f3f6..2f59af8 100644
--- a/gas/config/tc-rl78.c
+++ b/gas/config/tc-rl78.c
@@ -347,6 +347,23 @@ md_number_to_chars (char * buf, valueT val, int n)
number_to_chars_littleendian (buf, val, n);
}
+static void
+require_end_of_expr (char *fname)
+{
+ while (* input_line_pointer == ' '
+ || * input_line_pointer == '\t')
+ input_line_pointer ++;
+
+ if (! * input_line_pointer
+ || strchr ("\n\r,", * input_line_pointer)
+ || strchr (comment_chars, * input_line_pointer)
+ || strchr (line_comment_chars, * input_line_pointer)
+ || strchr (line_separator_chars, * input_line_pointer))
+ return;
+
+ as_bad (_("%%%s() must be outermost term in expression"), fname);
+}
+
static struct
{
char * fname;
@@ -388,6 +405,8 @@ md_operand (expressionS * exp ATTRIBUTE_UNUSED)
input_line_pointer ++;
exp->X_md = reloc;
+
+ require_end_of_expr (reloc_functions[i].fname);
}
void
@@ -552,6 +571,7 @@ rl78_cons_fix_new (fragS * frag,
expressionS * exp)
{
bfd_reloc_code_real_type type;
+ fixS *fixP;
switch (size)
{
@@ -601,7 +621,21 @@ rl78_cons_fix_new (fragS * frag,
type = BFD_RELOC_RL78_DIFF;
}
- fix_new_exp (frag, where, (int) size, exp, 0, type);
+ fixP = fix_new_exp (frag, where, (int) size, exp, 0, type);
+ switch (exp->X_md)
+ {
+ /* These are intended to have values larger than the container,
+ since the backend puts only the portion we need in it.
+ However, we don't have a backend-specific reloc for them as
+ they're handled with complex relocations. */
+ case BFD_RELOC_RL78_LO16:
+ case BFD_RELOC_RL78_HI16:
+ case BFD_RELOC_RL78_HI8:
+ fixP->fx_no_overflow = 1;
+ break;
+ default:
+ break;
+ }
}
/* No relaxation just yet */