[PATCH] Fix jit.exp on most 32-bit targets.

David Miller
2011-10-11T02:59:12Z

Outside of i386, most 32-bit targets align long long types on a 64-bit
boundary. But the JIT support code reading in the descriptor from the
target just assumes that the size field will come right after the
first three pointer sized fields.

This makes jit.exp fail.

Ok to commit?

2011-10-10 David S. Miller <davem@davemloft.net>

* gdbarch.sh: New field 'long_long_align_bit'.
* gdbarch.c, gdbarch.h: Regenerate.
* i386-tdep.c (i386_gdbarch_init): Set long_long_align_bit to 32.
* jit.c (jit_read_code_entry): Use it to determine correct size offset.

diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c
index 2b892b6..ea48fa7 100644
--- a/gdb/gdbarch.c
+++ b/gdb/gdbarch.c
@@ -145,6 +145,7 @@ struct gdbarch
int int_bit;
int long_bit;
int long_long_bit;
+ int long_long_align_bit;
int half_bit;
const struct floatformat ** half_format;
int float_bit;
@@ -299,6 +300,7 @@ struct gdbarch startup_gdbarch =
8 * sizeof (int), /* int_bit */
8 * sizeof (long), /* long_bit */
8 * sizeof (LONGEST), /* long_long_bit */
+ 8 * sizeof (LONGEST), /* long_long_align_bit */
16, /* half_bit */
0, /* half_format */
8 * sizeof (float), /* float_bit */
@@ -463,6 +465,7 @@ gdbarch_alloc (const struct gdbarch_info *info,
gdbarch->int_bit = 4*TARGET_CHAR_BIT;
gdbarch->long_bit = 4*TARGET_CHAR_BIT;
gdbarch->long_long_bit = 2*gdbarch->long_bit;
+ gdbarch->long_long_align_bit = 2*gdbarch->long_bit;
gdbarch->half_bit = 2*TARGET_CHAR_BIT;
gdbarch->float_bit = 4*TARGET_CHAR_BIT;
gdbarch->double_bit = 8*TARGET_CHAR_BIT;
@@ -576,6 +579,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
/* Skip verify of int_bit, invalid_p == 0 */
/* Skip verify of long_bit, invalid_p == 0 */
/* Skip verify of long_long_bit, invalid_p == 0 */
+ /* Skip verify of long_long_align_bit, invalid_p == 0 */
/* Skip verify of half_bit, invalid_p == 0 */
if (gdbarch->half_format == 0)
gdbarch->half_format = floatformats_ieee_half;
@@ -1020,6 +1024,9 @@ gdbarch_dump (struct gdbarch *gdbarch, struct ui_file *file)
"gdbarch_dump: long_double_format = %s\n",
pformat (gdbarch->long_double_format));
fprintf_unfiltered (file,
+ "gdbarch_dump: long_long_align_bit = %s\n",
+ plongest (gdbarch->long_long_align_bit));
+ fprintf_unfiltered (file,
"gdbarch_dump: long_long_bit = %s\n",
plongest (gdbarch->long_long_bit));
fprintf_unfiltered (file,
@@ -1424,6 +1431,23 @@ set_gdbarch_long_long_bit (struct gdbarch *gdbarch,
}

int
+gdbarch_long_long_align_bit (struct gdbarch *gdbarch)
+{
+ gdb_assert (gdbarch != NULL);
+ /* Skip verify of long_long_align_bit, invalid_p == 0 */
+ if (gdbarch_debug >= 2)
+ fprintf_unfiltered (gdb_stdlog, "gdbarch_long_long_align_bit called\n");
+ return gdbarch->long_long_align_bit;
+}
+
+void
+set_gdbarch_long_long_align_bit (struct gdbarch *gdbarch,
+ int long_long_align_bit)
+{
+ gdbarch->long_long_align_bit = long_long_align_bit;
+}
+
+int
gdbarch_half_bit (struct gdbarch *gdbarch)
{
gdb_assert (gdbarch != NULL);
diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h
index 0117322..d8420cc 100644
--- a/gdb/gdbarch.h
+++ b/gdb/gdbarch.h
@@ -120,6 +120,12 @@ extern void set_gdbarch_long_bit (struct gdbarch *gdbarch, int long_bit);
extern int gdbarch_long_long_bit (struct gdbarch *gdbarch);
extern void set_gdbarch_long_long_bit (struct gdbarch *gdbarch, int long_long_bit);

+/* Alignment of a long long or unsigned long long for the target
+ machine. */
+
+extern int gdbarch_long_long_align_bit (struct gdbarch *gdbarch);
+extern void set_gdbarch_long_long_align_bit (struct gdbarch *gdbarch, int long_long_align_bit);
+
/* The ABI default bit-size and format for "half", "float", "double", and
"long double". These bit/format pairs should eventually be combined
into a single object. For the moment, just initialize them as a pair.
@@ -586,7 +592,7 @@ extern void set_gdbarch_smash_text_address (struct gdbarch *gdbarch, gdbarch_sma
FIXME/cagney/2001-01-18: The logic is backwards. It should be asking if the
target can single step. If not, then implement single step using breakpoints.

- A return value of 1 means that the software_single_step breakpoints
+ A return value of 1 means that the software_single_step breakpoints
were inserted; 0 means they were not. */

extern int gdbarch_software_single_step_p (struct gdbarch *gdbarch);
diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh
index dcf0343..bf78173 100755
--- a/gdb/gdbarch.sh
+++ b/gdb/gdbarch.sh
@@ -362,6 +362,9 @@ v:int:long_bit:::8 * sizeof (long):4*TARGET_CHAR_BIT::0
# Number of bits in a long long or unsigned long long for the target
# machine.
v:int:long_long_bit:::8 * sizeof (LONGEST):2*gdbarch->long_bit::0
+# Alignment of a long long or unsigned long long for the target
+# machine.
+v:int:long_long_align_bit:::8 * sizeof (LONGEST):2*gdbarch->long_bit::0

# The ABI default bit-size and format for "half", "float", "double", and
# "long double". These bit/format pairs should eventually be combined
diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c
index 179bc45..2f0b6f5 100644
--- a/gdb/i386-tdep.c
+++ b/gdb/i386-tdep.c
@@ -7281,6 +7281,8 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)

tdep->record_regmap = i386_record_regmap;

+ set_gdbarch_long_long_align_bit (gdbarch, 32);
+
/* The format used for `long double' on almost all i386 targets is
the i387 extended floating-point format. In fact, of all targets
in the GCC 2.95 tree, only OSF/1 does it different, and insists
diff --git a/gdb/jit.c b/gdb/jit.c
index eb1bcc7..283ccdb 100644
--- a/gdb/jit.c
+++ b/gdb/jit.c
@@ -205,10 +205,11 @@ static void
jit_read_code_entry (struct gdbarch *gdbarch,
CORE_ADDR code_addr, struct jit_code_entry *code_entry)
{
- int err;
+ int err, off;
struct type *ptr_type;
int ptr_size;
int entry_size;
+ int align_bytes;
gdb_byte *entry_buf;
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);

@@ -230,8 +231,13 @@ jit_read_code_entry (struct gdbarch *gdbarch,
extract_typed_address (&entry_buf[ptr_size], ptr_type);
code_entry->symfile_addr =
extract_typed_address (&entry_buf[2 * ptr_size], ptr_type);
+
+ align_bytes = gdbarch_long_long_align_bit (gdbarch) / 8;
+ off = 3 * ptr_size;
+ off = (off + (align_bytes - 1)) & ~(align_bytes - 1);
+
code_entry->symfile_size =
- extract_unsigned_integer (&entry_buf[3 * ptr_size], 8, byte_order);
+ extract_unsigned_integer (&entry_buf[off], 8, byte_order);
}

/* This function registers code associated with a JIT code entry. It uses the