This is the mail archive of the
binutils@sourceware.org
mailing list for the binutils project.
PATCH: fix sleb128 for 64 vs 32 host
- From: Tristan Gingold <gingold at adacore dot com>
- To: Binutils <binutils at sourceware dot org>
- Date: Mon, 16 Nov 2015 12:44:48 +0100
- Subject: PATCH: fix sleb128 for 64 vs 32 host
- Authentication-results: sourceware.org; auth=none
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)