[PATCH] backends: Use ebl->class consistently in sparc backend.
by Mark Wielaard
sparc_init would check the ELF class to register to correct core_note
handler. But sparc_register_info would check the ELF machine to determine
whether the register set was 32 or 64 bits. This caused some confusion
and assertion failures in readelf when printing core notes where the
sparc machine and class didn't seem to match up. Check the ELF class
in both sparc_unit and sparc_register_info to give consistent results.
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
backends/ChangeLog | 4 ++++
backends/sparc_regs.c | 12 ++++++------
2 files changed, 10 insertions(+), 6 deletions(-)
diff --git a/backends/ChangeLog b/backends/ChangeLog
index c95e80f..4accedc 100644
--- a/backends/ChangeLog
+++ b/backends/ChangeLog
@@ -1,3 +1,7 @@
+2015-09-03 Mark Wielaard <mjw(a)redhat.com>
+
+ * sparc_regs.c (sparc_register_info): Use ebl->class not ebl->machine.
+
2015-06-26 Pino Toscano <toscano.pino(a)tiscali.it>
* i386_initreg.c: Reduce scope of some includes to match their usage.
diff --git a/backends/sparc_regs.c b/backends/sparc_regs.c
index f9709bb..2bddcf4 100644
--- a/backends/sparc_regs.c
+++ b/backends/sparc_regs.c
@@ -1,5 +1,5 @@
/* Register names and numbers for SPARC DWARF.
- Copyright (C) 2005, 2006 Red Hat, Inc.
+ Copyright (C) 2005, 2006, 2015 Red Hat, Inc.
This file is part of elfutils.
This file is free software; you can redistribute it and/or modify
@@ -42,8 +42,8 @@ sparc_register_info (Ebl *ebl,
const char **prefix, const char **setname,
int *bits, int *type)
{
- const int nfp = 32 + (ebl->machine == EM_SPARC ? 0 : 16);
- const int nspec = ebl->machine == EM_SPARC ? 8 : 6;
+ const int nfp = 32 + (ebl->class == ELFCLASS32 ? 0 : 16);
+ const int nspec = ebl->class == ELFCLASS32 ? 8 : 6;
if (name == NULL)
return 32 + nfp + nspec;
@@ -51,7 +51,7 @@ sparc_register_info (Ebl *ebl,
if (regno < 0 || regno >= 32 + nfp + nspec || namelen < 6)
return -1;
- *bits = ebl->machine == EM_SPARC ? 32 : 64;
+ *bits = ebl->class == ELFCLASS32 ? 32 : 64;
*type = DW_ATE_signed;
*prefix = "%";
@@ -66,9 +66,9 @@ sparc_register_info (Ebl *ebl,
};
*setname = "control";
*type = DW_ATE_unsigned;
- if ((ebl->machine != EM_SPARC ? 0 : 4) + 1 - (unsigned int) regno <= 1)
+ if ((ebl->class == ELFCLASS64 ? 0 : 4) + 1 - (unsigned int) regno <= 1)
*type = DW_ATE_address;
- return stpncpy (name, names[ebl->machine != EM_SPARC][regno],
+ return stpncpy (name, names[ebl->class == ELFCLASS64][regno],
namelen) + 1 - name;
}
--
2.4.3
8 years, 7 months
[PATCH] readelf: handle_core_item large right shift triggers undefined behaviour.
by Mark Wielaard
The problem is this:
int n = ffs (w);
w >>= n;
The intent is to shift away up to (and including) the first least
significant bit in w. But w is an unsigned int, so 32 bits. And the
least significant bit could be bit 32 (ffs counts from 1). Unfortunately
a right shift equal to (or larger than) the length in bits of the left
hand operand is undefined behaviour. We expect w to be zero afterwards.
Which would terminate the while loop in the function. But since it is
undefined behaviour anything can happen. In this case, what will actually
happen is that w is unchanged, causing an infinite loop...
gcc -fsanitize=undefined will catch and warn about this when w = 0x80000000
https://bugzilla.redhat.com/show_bug.cgi?id=1259259
Signed-off-by: Mark Wielaard <mjw(a)redhat.com>
---
src/ChangeLog | 4 ++++
src/readelf.c | 12 ++++++++++--
2 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/src/ChangeLog b/src/ChangeLog
index 5be1075..66f7ead 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,7 @@
+2015-09-03 Mark Wielaard <mjw(a)redhat.com>
+
+ * readelf.c (handle_core_item): Handle right shift >= 32 bits.
+
2015-08-11 Mark Wielaard <mjw(a)redhat.com>
* elflint.c (check_sections): When gnuld and a NOBITS section falls
diff --git a/src/readelf.c b/src/readelf.c
index d3c2b6b..aab8b5c 100644
--- a/src/readelf.c
+++ b/src/readelf.c
@@ -8474,8 +8474,16 @@ handle_core_item (Elf *core, const Ebl_Core_Item *item, const void *desc,
unsigned int w = negate ? ~*i : *i;
while (w != 0)
{
- int n = ffs (w);
- w >>= n;
+ /* Note that a right shift equal to (or greater than)
+ the number of bits of w is undefined behaviour. In
+ particular when the least significant bit is bit 32
+ (w = 0x8000000) then w >>= n is undefined. So
+ explicitly handle that case separately. */
+ unsigned int n = ffs (w);
+ if (n < sizeof (w) * 8)
+ w >>= n;
+ else
+ w = 0;
bit += n;
if (lastbit != 0 && lastbit + 1 == bit)
--
2.4.3
8 years, 7 months
i386_initreg.c
by Ben Gamari
Why does i386_initreg.c appear to have a x86_64 case as well, despite
the existence of x86_64_initreg.c?
Cheers,
- Ben
8 years, 7 months