Use the address mask with addresses for SREC, etc.

Maciej W. Rozycki
2007-07-24T17:35:35Z

Hello,

Some binary formats, such as SREC, only support 32-bit addresses and do
not sign-extend them properly for targets that require it. This causes a
problem with the MIPS target when KSEG addresses are used as they have bit
31 set which should be propagated through the high 32 bits to suit 64-bit
BFD. It is seen with the gdb.base/dump.exp set of tests.

Here is a change that fixes the problem. It has been successfully tested
for mipsisa32-sde-elf, with the mips-sim-sde32/-EB,
mips-sim-sde32/-mips16/-EB, mips-sim-sde32/-EL and
mips-sim-sde32/-mips16/-EL target boards, removing all the 15 failures
like below seen there:

(gdb) file intarr1.srec
Load new symbol table from ".../gdb/testsuite.mips-sim-sde32.-EL/intarr1.srec"? (y or n) y
Reading symbols from .../gdb/testsuite.mips-sim-sde32.-EL/intarr1.srec...done.
(gdb) print intarray
Cannot access memory at address 0x800220a8
(gdb) PASS: gdb.base/dump.exp: reload array as value, srec; capture intarray
FAIL: gdb.base/dump.exp: reload array as value, srec; value restored ok

2007-07-24 Nigel Stephens <nigel@mips.com>
Chris Dearman <chris@mips.com>
Maciej W. Rozycki <macro@mips.com>

* cli/cli-dump.c (restore_section_callback): Use the address mask
when comparing addresses.
* exec.c (xfer_memory): Likewise.

OK to apply?

Maciej

12100-3.diff
Index: binutils-quilt/src/gdb/exec.c
===================================================================
--- binutils-quilt.orig/src/gdb/exec.c 2007-07-23 18:59:51.000000000 +0100
+++ binutils-quilt/src/gdb/exec.c 2007-07-23 19:00:23.000000000 +0100
@@ -463,6 +463,8 @@
struct section_table *p;
CORE_ADDR nextsectaddr, memend;
asection *section = NULL;
+ int addr_bit = gdbarch_addr_bit (current_gdbarch);
+ CORE_ADDR addr_mask;

if (len <= 0)
internal_error (__FILE__, __LINE__, _("failed internal consistency check"));
@@ -474,30 +476,46 @@
memaddr = overlay_mapped_address (memaddr, section);
}

+ /* Only match address bits which are significant
+ for the current architecture. */
+ if (addr_bit < sizeof (CORE_ADDR) * HOST_CHAR_BIT)
+ {
+ addr_mask = ((CORE_ADDR)1 << addr_bit) - 1;
+ memaddr &= addr_mask;
+ }
+ else
+ addr_mask = ~(CORE_ADDR)0;
+
memend = memaddr + len;
nextsectaddr = memend;

for (p = target->to_sections; p < target->to_sections_end; p++)
{
+ CORE_ADDR p_addr;
+
if (overlay_debugging && section && p->the_bfd_section &&
strcmp (section->name, p->the_bfd_section->name) != 0)
continue; /* not the section we need */
- if (memaddr >= p->addr)
+
+ p_addr = p->addr & addr_mask;
+ if (memaddr >= p_addr)
{
- if (memend <= p->endaddr)
+ CORE_ADDR p_endaddr = p->endaddr & addr_mask;
+
+ if (memend <= p_endaddr)
{
/* Entire transfer is within this section. */
if (write)
res = bfd_set_section_contents (p->bfd, p->the_bfd_section,
- myaddr, memaddr - p->addr,
+ myaddr, memaddr - p_addr,
len);
else
res = bfd_get_section_contents (p->bfd, p->the_bfd_section,
- myaddr, memaddr - p->addr,
+ myaddr, memaddr - p_addr,
len);
return (res != 0) ? len : 0;
}
- else if (memaddr >= p->endaddr)
+ else if (memaddr >= p_endaddr)
{
/* This section ends before the transfer starts. */
continue;
@@ -505,20 +523,20 @@
else
{
/* This section overlaps the transfer. Just do half. */
- len = p->endaddr - memaddr;
+ len = p_endaddr - memaddr;
if (write)
res = bfd_set_section_contents (p->bfd, p->the_bfd_section,
- myaddr, memaddr - p->addr,
+ myaddr, memaddr - p_addr,
len);
else
res = bfd_get_section_contents (p->bfd, p->the_bfd_section,
- myaddr, memaddr - p->addr,
+ myaddr, memaddr - p_addr,
len);
return (res != 0) ? len : 0;
}
}
else
- nextsectaddr = min (nextsectaddr, p->addr);
+ nextsectaddr = min (nextsectaddr, p_addr);
}

if (nextsectaddr >= memend)
Index: binutils-quilt/src/gdb/cli/cli-dump.c
===================================================================
--- binutils-quilt.orig/src/gdb/cli/cli-dump.c 2007-07-23 18:59:51.000000000 +0100
+++ binutils-quilt/src/gdb/cli/cli-dump.c 2007-07-23 19:00:34.000000000 +0100
@@ -462,6 +462,8 @@
bfd_vma sec_end = sec_start + size;
bfd_size_type sec_offset = 0;
bfd_size_type sec_load_count = size;
+ int addr_bit = gdbarch_addr_bit (current_gdbarch);
+ CORE_ADDR addr_mask;
struct cleanup *old_chain;
gdb_byte *buf;
int ret;
@@ -470,9 +472,17 @@
if (!(bfd_get_section_flags (ibfd, isec) & SEC_LOAD))
return;

- /* Does the section overlap with the desired restore range? */
- if (sec_end <= data->load_start
- || (data->load_end > 0 && sec_start >= data->load_end))
+ /* Only match address bits which are significant
+ for the current architecture. */
+ if (addr_bit < sizeof (CORE_ADDR) * HOST_CHAR_BIT)
+ addr_mask = ((CORE_ADDR) 1 << addr_bit) - 1;
+ else
+ addr_mask = ~(CORE_ADDR) 0;
+
+ /* Does the section overlap with the desired restore range? */
+ if (sec_end <= (data->load_start & addr_mask)
+ || ((data->load_end & addr_mask) > 0
+ && sec_start >= (data->load_end & addr_mask)))
{
/* No, no useable data in this section. */
printf_filtered (_("skipping section %s...\n"),
@@ -483,11 +493,11 @@
/* Compare section address range with user-requested
address range (if any). Compute where the actual
transfer should start and end. */
- if (sec_start < data->load_start)
+ if (sec_start < (data->load_start & addr_mask))
sec_offset = data->load_start - sec_start;
/* Size of a partial transfer: */
sec_load_count -= sec_offset;
- if (data->load_end > 0 && sec_end > data->load_end)
+ if (data->load_end > 0 && sec_end > (data->load_end & addr_mask))
sec_load_count -= sec_end - data->load_end;

/* Get the data. */