This is the mail archive of the binutils@sourceware.org mailing list for the binutils project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

PATCH: fix sleb128 for 64 vs 32 host


Hello,

we recently hit a misunderstanding between gcc and gas on sleb128.
According to the bfd configuration (whether bfd_vma is 32 or 64 bits), we have:

   1              		.data
   2 0000 FFFFFFFF 		.sleb128 281474976710655
   2      FFFF3F

or

   1              		.data
   2 0000 7F       		.sleb128 281474976710655


But as gcc doesnât know how gas is configured and as it has its own
idea of the length of leb128 data, the output may be incorrect.

On 64 bit host, the value (0xffff_ffff_ffff) is considered as a
constant and the output is handled by output_leb128, for which
the value is positive.

But on a 32 bit host, the value is considered as bignum (O_big)
with 3 16 bit digits and the output is handled by output_big_sleb128.
But the latter begins by stripping sign extension digits, thus
the wrong result.

Is it really worth stripping leading digits in output_big_?leb128 ?
The only operation performed on bignum is the negation.

So I propose the following patch.  Is it ok for trunk ?
No regression for i386-linux target.

Tristan.

2015-11-16  Tristan Gingold  <gingold@adacore.com>

	* read.c (output_big_uleb128): Do not strip leading digit.
	(output_big_sleb128): Ditto.


diff --git a/gas/ChangeLog b/gas/ChangeLog
index 5420973..05a6255 100644
--- a/gas/ChangeLog
+++ b/gas/ChangeLog
@@ -1,3 +1,8 @@
+2015-11-16  Tristan Gingold  <gingold@adacore.com>
+
+	* read.c (output_big_uleb128): Do not strip leading digit.
+	(output_big_sleb128): Ditto.
+
 2015-09-29  Dominik Vogt  <vogt@linux.vnet.ibm.com>
 
 	* doc/c-s390.texi: Add documentation.
diff --git a/gas/read.c b/gas/read.c
index a3e83c3..d7c9158 100644
--- a/gas/read.c
+++ b/gas/read.c
@@ -5054,11 +5054,8 @@ output_big_sleb128 (char *p, LITTLENUM_TYPE *bignum, int size)
   int loaded = 0;
   unsigned byte;
 
-  /* Strip leading sign extensions off the bignum.  */
-  while (size > 1
-	 && bignum[size - 1] == LITTLENUM_MASK
-	 && bignum[size - 2] > LITTLENUM_MASK / 2)
-    size--;
+  /* Do not strip leading sign extensions off the bignum, so that
+     the output is predictible.  */
 
   do
     {
@@ -5109,11 +5106,6 @@ output_big_uleb128 (char *p, LITTLENUM_TYPE *bignum, int size)
   int loaded = 0;
   unsigned byte;
 
-  /* Strip leading zeros off the bignum.  */
-  /* XXX: Is this needed?  */
-  while (size > 0 && bignum[size - 1] == 0)
-    size--;
-
   do
     {
       if (loaded < 7 && size > 0)






Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]