public inbox for binutils@sourceware.org
 help / color / mirror / Atom feed
* [PATCH, ARM] Fix out-of-range immediate assembly errors on 64-bit  hosts
@ 2006-06-09 17:56 Julian Brown
  2006-06-12 11:45 ` Nick Clifton
  0 siblings, 1 reply; 7+ messages in thread
From: Julian Brown @ 2006-06-09 17:56 UTC (permalink / raw)
  To: binutils

[-- Attachment #1: Type: text/plain, Size: 733 bytes --]

Hi,

This patch fixes some immediate-out-of-range errors for VBIC, VORR etc. 
on 64-bit hosts. On such hosts, the X_add_number field of expressions 
will be 64 bits wide. INT_MIN and INT_MAX are used to signify that any 
immediate may be accepted for parse_immediate: unfortunately on a 64-bit 
host, 0xff000000 for instance is then interpreted as a positive integer 
outside that range. I've just made passing INT_MIN/INT_MAX disable the 
check instead, though I'm not very fond of that solution.

Tested with cross to arm-none-eabi from x86_64-unknown-linux-gnu.

OK to apply?

Cheers,

Julian

ChangeLog (gas):

     * config/tc-arm.c (parse_immediate): Handle 64-bit X_add_number
     case.
     (parse_big_immediate): Likewise.

[-- Attachment #2: neon-asm-64bit-host-1 --]
[-- Type: text/plain, Size: 1875 bytes --]

Index: config/tc-arm.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-arm.c,v
retrieving revision 1.274
diff -c -p -r1.274 tc-arm.c
*** config/tc-arm.c	7 Jun 2006 14:32:28 -0000	1.274
--- config/tc-arm.c	9 Jun 2006 16:41:36 -0000
*************** parse_immediate (char **str, int *val, i
*** 3887,3893 ****
        return FAIL;
      }
  
!   if (exp.X_add_number < min || exp.X_add_number > max)
      {
        inst.error = _("immediate value out of range");
        return FAIL;
--- 3887,3894 ----
        return FAIL;
      }
  
!   if ((min != INT_MIN || max != INT_MAX)
!       && (exp.X_add_number < min || exp.X_add_number > max))
      {
        inst.error = _("immediate value out of range");
        return FAIL;
*************** parse_big_immediate (char **str, int i)
*** 3910,3916 ****
    my_get_expression (&exp, &ptr, GE_OPT_PREFIX_BIG);
  
    if (exp.X_op == O_constant)
!     inst.operands[i].imm = exp.X_add_number;
    else if (exp.X_op == O_big
             && LITTLENUM_NUMBER_OF_BITS * exp.X_add_number > 32
             && LITTLENUM_NUMBER_OF_BITS * exp.X_add_number <= 64)
--- 3911,3928 ----
    my_get_expression (&exp, &ptr, GE_OPT_PREFIX_BIG);
  
    if (exp.X_op == O_constant)
!     {
!       inst.operands[i].imm = exp.X_add_number & 0xffffffff;
!       /* If we're on a 64-bit host, then a 64-bit number can be returned using
! 	 O_constant.  We have to be careful not to break compilation for
! 	 32-bit X_add_number, though.  */
!       if ((exp.X_add_number & ~0xffffffffl) != 0)
! 	{
!           inst.operands[i].reg = ((exp.X_add_number >> 16) >> 16) & 0xffffffff;
! 	  inst.operands[i].regisimm = 1;
! 	}
!     }
! 
    else if (exp.X_op == O_big
             && LITTLENUM_NUMBER_OF_BITS * exp.X_add_number > 32
             && LITTLENUM_NUMBER_OF_BITS * exp.X_add_number <= 64)

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH, ARM] Fix out-of-range immediate assembly errors on 64-bit   hosts
  2006-06-09 17:56 [PATCH, ARM] Fix out-of-range immediate assembly errors on 64-bit hosts Julian Brown
@ 2006-06-12 11:45 ` Nick Clifton
  2006-06-12 13:50   ` Julian Brown
  0 siblings, 1 reply; 7+ messages in thread
From: Nick Clifton @ 2006-06-12 11:45 UTC (permalink / raw)
  To: Julian Brown; +Cc: binutils

Hi Julian,


> This patch fixes some immediate-out-of-range errors for VBIC, VORR etc. 
> on 64-bit hosts. On such hosts, the X_add_number field of expressions 
> will be 64 bits wide. INT_MIN and INT_MAX are used to signify that any 
> immediate may be accepted for parse_immediate: unfortunately on a 64-bit 
> host, 0xff000000 for instance is then interpreted as a positive integer 
> outside that range.

Sorry - can you explain that last part again please ?  I get how INT_MIN 
and INT_MAX are being used to indicate "any integer value is acceptable" 
to parse_immediate(), but where does this 0xffff0000 value come from and 
why would it cause problems for parse_immediate() ?

> I've just made passing INT_MIN/INT_MAX disable the 
> check instead, though I'm not very fond of that solution.

There appears to be only once place where INT_MAX/INT_MIN are used, so 
maybe it would be cleaner to change that code to pass realistic minimum 
and maximum values ?

>     * config/tc-arm.c (parse_immediate): Handle 64-bit X_add_number
>     case.

That sentence is not quite true.  The change is to skip the range checks 
when the range is INT_MIN -> INT_MAX.


> !       /* If we're on a 64-bit host, then a 64-bit number can be returned using
> ! 	 O_constant.  We have to be careful not to break compilation for
> ! 	 32-bit X_add_number, though.  */
> !       if ((exp.X_add_number & ~0xffffffffl) != 0)
> ! 	{
> !           inst.operands[i].reg = ((exp.X_add_number >> 16) >> 16) & 0xffffffff;
> ! 	  inst.operands[i].regisimm = 1;
> ! 	}

I am a little bit confused here.  How is ((x >> 16) >> 16) different 
from (x >> 32) ?  If not, then why express it that way ?

Cheers
   Nick

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH, ARM] Fix out-of-range immediate assembly errors on 64-bit   hosts
  2006-06-12 11:45 ` Nick Clifton
@ 2006-06-12 13:50   ` Julian Brown
  2006-06-15  9:54     ` Nick Clifton
  0 siblings, 1 reply; 7+ messages in thread
From: Julian Brown @ 2006-06-12 13:50 UTC (permalink / raw)
  To: Nick Clifton; +Cc: binutils

Nick Clifton wrote:
> Hi Julian,
> 
> 
>> This patch fixes some immediate-out-of-range errors for VBIC, VORR 
>> etc. on 64-bit hosts. On such hosts, the X_add_number field of 
>> expressions will be 64 bits wide. INT_MIN and INT_MAX are used to 
>> signify that any immediate may be accepted for parse_immediate: 
>> unfortunately on a 64-bit host, 0xff000000 for instance is then 
>> interpreted as a positive integer outside that range.
> 
> 
> Sorry - can you explain that last part again please ?  I get how INT_MIN 
> and INT_MAX are being used to indicate "any integer value is acceptable" 
> to parse_immediate(), but where does this 0xffff0000 value come from and 
> why would it cause problems for parse_immediate() ?

0xffff0000 is parsed as a positive integer when 
sizeof(exp.X_add_number)==8, and a negative integer when it equals 4. 
For VORR, VBIC, etc. a large range of values is acceptable for the 
immediate, so validation is done properly later on in assembling the 
instruction rather than here.

>> I've just made passing INT_MIN/INT_MAX disable the check instead, 
>> though I'm not very fond of that solution.
> 
> 
> There appears to be only once place where INT_MAX/INT_MIN are used, so 
> maybe it would be cleaner to change that code to pass realistic minimum 
> and maximum values ?

There's a design flaw in here somewhere with respect to binutils mostly 
using the word size of the host not the target, and this patch probably 
exascerbates the situation by not really being well thought-out enough, 
sorry. :-/

I don't know why it didn't occur to me to use LONG_MIN, LONG_MAX at the 
caller instead, but that seems a bit wrong too somehow. I think it'd 
probably work, but maybe it'd be better to add a 
bounds-checked/non-bounds-checked argument to parse_immediate() or write 
a non-bounds-checking version of the function instead?

>> !       /* If we're on a 64-bit host, then a 64-bit number can be 
>> returned using
>> !      O_constant.  We have to be careful not to break compilation for
>> !      32-bit X_add_number, though.  */
>> !       if ((exp.X_add_number & ~0xffffffffl) != 0)
>> !     {
>> !           inst.operands[i].reg = ((exp.X_add_number >> 16) >> 16) & 
>> 0xffffffff;
>> !       inst.operands[i].regisimm = 1;
>> !     }
> 
> 
> I am a little bit confused here.  How is ((x >> 16) >> 16) different 
> from (x >> 32) ?  If not, then why express it that way ?

If sizeof(exp.X_add_number)==4 (i.e. on 32-bit hosts), then I think that 
writing (x >> 32) is invalid C (which isn't very nice, even if that code 
would never be executed). Is there a less weird way of writing the same 
thing?

Cheers,

Julian

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH, ARM] Fix out-of-range immediate assembly errors on 64-bit   hosts
  2006-06-12 13:50   ` Julian Brown
@ 2006-06-15  9:54     ` Nick Clifton
  2006-06-15 14:58       ` Daniel Jacobowitz
  2006-09-06 13:27       ` Julian Brown
  0 siblings, 2 replies; 7+ messages in thread
From: Nick Clifton @ 2006-06-15  9:54 UTC (permalink / raw)
  To: Julian Brown; +Cc: binutils

Hi Julian,

>> Sorry - can you explain that last part again please ?  I get how 
>> INT_MIN and INT_MAX are being used to indicate "any integer value is 
>> acceptable" to parse_immediate(), but where does this 0xffff0000 value 
>> come from and why would it cause problems for parse_immediate() ?
> 
> 0xffff0000 is parsed as a positive integer when 
> sizeof(exp.X_add_number)==8, and a negative integer when it equals 4. 

And you are saying that "0xffff0000 > INT_MAX" for a 64-bit host ? 
(This was the bit that I had not caught, sorry).

> I don't know why it didn't occur to me to use LONG_MIN, LONG_MAX at the 
> caller instead, but that seems a bit wrong too somehow.

Yes, although it might be a simpler change.

> I think it'd 
> probably work, but maybe it'd be better to add a 
> bounds-checked/non-bounds-checked argument to parse_immediate() or write 
> a non-bounds-checking version of the function instead?

I think that this would be the best solution.  It makes the meaning of 
the arguments passed to parse_immediate more obvious.


>> I am a little bit confused here.  How is ((x >> 16) >> 16) different 
>> from (x >> 32) ?  If not, then why express it that way ?
> 
> If sizeof(exp.X_add_number)==4 (i.e. on 32-bit hosts), then I think that 
> writing (x >> 32) is invalid C (which isn't very nice, even if that code 
> would never be executed).

Ah, yes, I had not considered that.

> Is there a less weird way of writing the same thing?

Not really.  You use a macro I guess.  eg:

   /* Do not use ">> 32" as this will trigger a warning on hosts
      where sizeof (typeof (a)) == 4.  */
   #define get_top_32_bits(a)  (((a) >> 16) >> 16) & 0xffffffff)

Or just have the comment in the code.  (Hmm, do we need to worry about 
compiling on 16-bit hosts where ">> 16" would trigger a warning ?)

Cheers
   Nick

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH, ARM] Fix out-of-range immediate assembly errors on 64-bit   hosts
  2006-06-15  9:54     ` Nick Clifton
@ 2006-06-15 14:58       ` Daniel Jacobowitz
  2006-09-06 13:27       ` Julian Brown
  1 sibling, 0 replies; 7+ messages in thread
From: Daniel Jacobowitz @ 2006-06-15 14:58 UTC (permalink / raw)
  To: Nick Clifton; +Cc: Julian Brown, binutils

On Thu, Jun 15, 2006 at 09:10:01AM +0100, Nick Clifton wrote:
> Or just have the comment in the code.  (Hmm, do we need to worry about 
> compiling on 16-bit hosts where ">> 16" would trigger a warning ?)

No, we do not.  It's standard for GNU tools to only support 32-bit
hosts, even when they support 16-bit targets.

-- 
Daniel Jacobowitz
CodeSourcery

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH, ARM] Fix out-of-range immediate assembly errors on 64-bit   hosts
  2006-06-15  9:54     ` Nick Clifton
  2006-06-15 14:58       ` Daniel Jacobowitz
@ 2006-09-06 13:27       ` Julian Brown
  2006-11-14 12:42         ` Nick Clifton
  1 sibling, 1 reply; 7+ messages in thread
From: Julian Brown @ 2006-09-06 13:27 UTC (permalink / raw)
  To: Nick Clifton; +Cc: binutils, Paul Brook

[-- Attachment #1: Type: text/plain, Size: 1819 bytes --]

Hi,

Nick Clifton wrote:
> Hi Julian,
> 
>> I think it'd probably work, but maybe it'd be better to add a 
>> bounds-checked/non-bounds-checked argument to parse_immediate() or 
>> write a non-bounds-checking version of the function instead?
> 
> I think that this would be the best solution.  It makes the meaning of 
> the arguments passed to parse_immediate more obvious.
[...]
> 
>>> I am a little bit confused here.  How is ((x >> 16) >> 16) different 
>>> from (x >> 32) ?  If not, then why express it that way ?
>>
>> If sizeof(exp.X_add_number)==4 (i.e. on 32-bit hosts), then I think 
>> that writing (x >> 32) is invalid C (which isn't very nice, even if 
>> that code would never be executed).

> [...] Or just have the comment in the code.

Here's a (rather belated) new version of the patch which adds 
bounds-checking and non-bounds-checking forms to parse_immediate, 
avoiding the previous nastiness with INT_MIN/INT_MAX.

Tested with "make check" on x86 and x86_64 with cross to arm-none-eabi.

OK? (for mainline? CSL branch?)

Cheers,

Julian

ChangeLog

     gas/
     * config/tc-arm.c (parse_immediate): Add BOUNDED parameter, rename
     to...
     (parse_immediate_maybe_bounded): This. Only bounds-check if BOUNDED
     is true.
     (parse_immediate_bounded): New function, with same arguments and
     semantics as previous parse_immediate.
     (parse_immediate_unbounded): New function. Parse an unbounded
     integer (with sizeof (exp.X_add_number)).
     (parse_big_immediate): Allow for 64-bit exp.X_add_number when
     parsing 64-bit immediates.
     (parse_address_main): Use parse_immediate_bounded not
     parse_immediate.
     (parse_ror): Likewise.
     (parse_operands): Likewise. For Neon immediates, use
     parse_immediate_unbounded. Add new local po_imm_unb_or_fail macro.


[-- Attachment #2: neon-asm-64bit-host-3 --]
[-- Type: text/plain, Size: 6347 bytes --]

? gas/config/~tc-arm.c
Index: gas/config/tc-arm.c
===================================================================
RCS file: /cvs/src/src/gas/config/tc-arm.c,v
retrieving revision 1.250.2.29
diff -c -p -r1.250.2.29 tc-arm.c
*** gas/config/tc-arm.c	5 Sep 2006 20:23:46 -0000	1.250.2.29
--- gas/config/tc-arm.c	6 Sep 2006 12:59:19 -0000
*************** const pseudo_typeS md_pseudo_table[] =
*** 3943,3955 ****
  
  /* Generic immediate-value read function for use in insn parsing.
     STR points to the beginning of the immediate (the leading #);
!    VAL receives the value; if the value is outside [MIN, MAX]
!    issue an error.  PREFIX_OPT is true if the immediate prefix is
     optional.  */
  
  static int
! parse_immediate (char **str, int *val, int min, int max,
! 		 bfd_boolean prefix_opt)
  {
    expressionS exp;
    my_get_expression (&exp, str, prefix_opt ? GE_OPT_PREFIX : GE_IMM_PREFIX);
--- 3943,3955 ----
  
  /* Generic immediate-value read function for use in insn parsing.
     STR points to the beginning of the immediate (the leading #);
!    VAL receives the value; if the value is outside [MIN, MAX] and BOUNDED is
!    true, it issue an error.  PREFIX_OPT is true if the immediate prefix is
     optional.  */
  
  static int
! parse_immediate_maybe_bounded (char **str, int *val, bfd_boolean bounded,
! 			       int min, int max, bfd_boolean prefix_opt)
  {
    expressionS exp;
    my_get_expression (&exp, str, prefix_opt ? GE_OPT_PREFIX : GE_IMM_PREFIX);
*************** parse_immediate (char **str, int *val, i
*** 3959,3965 ****
        return FAIL;
      }
  
!   if (exp.X_add_number < min || exp.X_add_number > max)
      {
        inst.error = _("immediate value out of range");
        return FAIL;
--- 3959,3965 ----
        return FAIL;
      }
  
!   if (bounded && (exp.X_add_number < min || exp.X_add_number > max))
      {
        inst.error = _("immediate value out of range");
        return FAIL;
*************** parse_immediate (char **str, int *val, i
*** 3969,3974 ****
--- 3969,3987 ----
    return SUCCESS;
  }
  
+ static int
+ parse_immediate_bounded (char **str, int *val, int min, int max,
+ 			 bfd_boolean prefix_opt)
+ {
+   return parse_immediate_maybe_bounded (str, val, TRUE, min, max, prefix_opt);
+ }
+ 
+ static int
+ parse_immediate_unbounded (char **str, int *val, bfd_boolean prefix_opt)
+ {
+   return parse_immediate_maybe_bounded (str, val, FALSE, 0, 0, prefix_opt);
+ }
+ 
  /* Less-generic immediate-value read function with the possibility of loading a
     big (64-bit) immediate, as required by Neon VMOV and VMVN immediate
     instructions. Puts the result directly in inst.operands[i].  */
*************** parse_big_immediate (char **str, int i)
*** 3982,3988 ****
    my_get_expression (&exp, &ptr, GE_OPT_PREFIX_BIG);
  
    if (exp.X_op == O_constant)
!     inst.operands[i].imm = exp.X_add_number;
    else if (exp.X_op == O_big
             && LITTLENUM_NUMBER_OF_BITS * exp.X_add_number > 32
             && LITTLENUM_NUMBER_OF_BITS * exp.X_add_number <= 64)
--- 3995,4012 ----
    my_get_expression (&exp, &ptr, GE_OPT_PREFIX_BIG);
  
    if (exp.X_op == O_constant)
!     {
!       inst.operands[i].imm = exp.X_add_number & 0xffffffff;
!       /* If we're on a 64-bit host, then a 64-bit number can be returned using
! 	 O_constant.  We have to be careful not to break compilation for
! 	 32-bit X_add_number, though.  */
!       if ((exp.X_add_number & ~0xffffffffl) != 0)
! 	{
!           /* X >> 32 is illegal if sizeof (exp.X_add_number) == 4.  */
! 	  inst.operands[i].reg = ((exp.X_add_number >> 16) >> 16) & 0xffffffff;
! 	  inst.operands[i].regisimm = 1;
! 	}
!     }
    else if (exp.X_op == O_big
             && LITTLENUM_NUMBER_OF_BITS * exp.X_add_number > 32
             && LITTLENUM_NUMBER_OF_BITS * exp.X_add_number <= 64)
*************** parse_address_main (char **str, int i, i
*** 4700,4707 ****
        if (skip_past_char (&p, '{') == SUCCESS)
  	{
  	  /* [Rn], {expr} - unindexed, with option */
! 	  if (parse_immediate (&p, &inst.operands[i].imm,
! 			       0, 255, TRUE) == FAIL)
  	    return PARSE_OPERAND_FAIL;
  
  	  if (skip_past_char (&p, '}') == FAIL)
--- 4724,4731 ----
        if (skip_past_char (&p, '{') == SUCCESS)
  	{
  	  /* [Rn], {expr} - unindexed, with option */
! 	  if (parse_immediate_bounded (&p, &inst.operands[i].imm,
! 				       0, 255, TRUE) == FAIL)
  	    return PARSE_OPERAND_FAIL;
  
  	  if (skip_past_char (&p, '}') == FAIL)
*************** parse_ror (char **str)
*** 4972,4978 ****
        return FAIL;
      }
  
!   if (parse_immediate (&s, &rot, 0, 24, FALSE) == FAIL)
      return FAIL;
  
    switch (rot)
--- 4996,5002 ----
        return FAIL;
      }
  
!   if (parse_immediate_bounded (&s, &rot, 0, 24, FALSE) == FAIL)
      return FAIL;
  
    switch (rot)
*************** parse_operands (char *str, const unsigne
*** 5479,5485 ****
  } while (0)
  
  #define po_imm_or_fail(min, max, popt) do {			\
!   if (parse_immediate (&str, &val, min, max, popt) == FAIL)	\
      goto failure;						\
    inst.operands[i].imm = val;					\
  } while (0)
--- 5503,5515 ----
  } while (0)
  
  #define po_imm_or_fail(min, max, popt) do {			\
!   if (parse_immediate_bounded (&str, &val, min, max, popt) == FAIL) \
!     goto failure;						\
!   inst.operands[i].imm = val;					\
! } while (0)
! 
! #define po_imm_unb_or_fail(popt) do {				\
!   if (parse_immediate_unbounded (&str, &val, popt) == FAIL)	\
      goto failure;						\
    inst.operands[i].imm = val;					\
  } while (0)
*************** parse_operands (char *str, const unsigne
*** 5578,5584 ****
              break;
              try_imm:
              /* Immediate gets verified properly later, so accept any now.  */
!             po_imm_or_fail (INT_MIN, INT_MAX, TRUE);
            }
            break;
  
--- 5608,5614 ----
              break;
              try_imm:
              /* Immediate gets verified properly later, so accept any now.  */
!             po_imm_unb_or_fail (TRUE);
            }
            break;
  
*************** parse_operands (char *str, const unsigne
*** 6027,6032 ****
--- 6057,6063 ----
  #undef po_reg_or_fail
  #undef po_reg_or_goto
  #undef po_imm_or_fail
+ #undef po_imm_unb_or_fail
  #undef po_scalar_or_fail
  \f
  /* Shorthand macro for instruction encoding functions issuing errors.  */

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH, ARM] Fix out-of-range immediate assembly errors on 64-bit   hosts
  2006-09-06 13:27       ` Julian Brown
@ 2006-11-14 12:42         ` Nick Clifton
  0 siblings, 0 replies; 7+ messages in thread
From: Nick Clifton @ 2006-11-14 12:42 UTC (permalink / raw)
  To: Julian Brown; +Cc: binutils, Paul Brook

Hi Julian,

   Going through my email backlogs and I found this:

>     gas/
>     * config/tc-arm.c (parse_immediate): Add BOUNDED parameter, rename
>     to...
>     (parse_immediate_maybe_bounded): This. Only bounds-check if BOUNDED
>     is true.
>     (parse_immediate_bounded): New function, with same arguments and
>     semantics as previous parse_immediate.
>     (parse_immediate_unbounded): New function. Parse an unbounded
>     integer (with sizeof (exp.X_add_number)).
>     (parse_big_immediate): Allow for 64-bit exp.X_add_number when
>     parsing 64-bit immediates.
>     (parse_address_main): Use parse_immediate_bounded not
>     parse_immediate.
>     (parse_ror): Likewise.
>     (parse_operands): Likewise. For Neon immediates, use
>     parse_immediate_unbounded. Add new local po_imm_unb_or_fail macro.

Are you still waiting for approval for this patch ?  If so, please 
consider it approved.

Cheers
   Nick

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2006-11-14 12:42 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-06-09 17:56 [PATCH, ARM] Fix out-of-range immediate assembly errors on 64-bit hosts Julian Brown
2006-06-12 11:45 ` Nick Clifton
2006-06-12 13:50   ` Julian Brown
2006-06-15  9:54     ` Nick Clifton
2006-06-15 14:58       ` Daniel Jacobowitz
2006-09-06 13:27       ` Julian Brown
2006-11-14 12:42         ` Nick Clifton

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).