From 21f120f5227d635d6151668d12234a6fd32897b2 Mon Sep 17 00:00:00 2001 From: Ulrich Weigand Date: Sat, 19 Jun 2010 17:36:49 +0000 Subject: ChangeLog: * spu-multiarch.c (spu_xfer_partial): Wrap around local store limit on local store memory accesses. * spu-linux-nat.c (spu_xfer_partial): Likewise. * spu-tdep.c (spu_lslr): Remove. (spu_pointer_to_address): Do not truncate addresses. (spu_integer_to_address): Likewise. (spu_overlay_new_objfile): Use SPU_OVERLAY_LMA. * spu-tdep.h: Add comments. (SPUADDR_SPU): Respect SPU_OVERLAY_LMA bit. (SPU_OVERLAY_LMA): Define. gdbserver/ChangeLog: * spu-low.c (spu_read_memory): Wrap around local store limit. (spu_write_memory): Likewise. testsuite/ChangeLog: * gdb.arch/spu-ls.exp: New file. * gdb.arch/spu-ls.c: Likewise. --- gdb/ChangeLog | 13 +++++++++ gdb/gdbserver/ChangeLog | 5 ++++ gdb/gdbserver/spu-low.c | 38 ++++++++++++++++++++++-- gdb/spu-linux-nat.c | 22 ++++++++++++-- gdb/spu-multiarch.c | 27 +++++++++++++++-- gdb/spu-tdep.c | 27 +++-------------- gdb/spu-tdep.h | 61 +++++++++++++++++++++++++++++++++++++-- gdb/testsuite/ChangeLog | 5 ++++ gdb/testsuite/gdb.arch/spu-ls.c | 31 ++++++++++++++++++++ gdb/testsuite/gdb.arch/spu-ls.exp | 54 ++++++++++++++++++++++++++++++++++ 10 files changed, 251 insertions(+), 32 deletions(-) create mode 100644 gdb/testsuite/gdb.arch/spu-ls.c create mode 100644 gdb/testsuite/gdb.arch/spu-ls.exp diff --git a/gdb/ChangeLog b/gdb/ChangeLog index b8cd0f88606..48e62509ecf 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,16 @@ +2010-06-19 Ulrich Weigand + + * spu-multiarch.c (spu_xfer_partial): Wrap around local store + limit on local store memory accesses. + * spu-linux-nat.c (spu_xfer_partial): Likewise. + * spu-tdep.c (spu_lslr): Remove. + (spu_pointer_to_address): Do not truncate addresses. + (spu_integer_to_address): Likewise. + (spu_overlay_new_objfile): Use SPU_OVERLAY_LMA. + * spu-tdep.h: Add comments. + (SPUADDR_SPU): Respect SPU_OVERLAY_LMA bit. + (SPU_OVERLAY_LMA): Define. + 2010-06-18 Stan Shebs * osdata.c (get_osdata): Warn separately if target does not report diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog index 6b9f4935b0f..06c63430324 100644 --- a/gdb/gdbserver/ChangeLog +++ b/gdb/gdbserver/ChangeLog @@ -1,3 +1,8 @@ +2010-06-19 Ulrich Weigand + + * spu-low.c (spu_read_memory): Wrap around local store limit. + (spu_write_memory): Likewise. + 2010-06-15 Pedro Alves * linux-x86-low.c (amd64_emit_const, amd64_emit_void_call_2) diff --git a/gdb/gdbserver/spu-low.c b/gdb/gdbserver/spu-low.c index d9ac815d20f..2188d64ede7 100644 --- a/gdb/gdbserver/spu-low.c +++ b/gdb/gdbserver/spu-low.c @@ -561,7 +561,8 @@ spu_read_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len) { int fd, ret; CORE_ADDR addr; - char annex[32]; + char annex[32], lslr_annex[32], buf[32]; + CORE_ADDR lslr; /* We must be stopped on a spu_run system call. */ if (!parse_spufs_run (&fd, &addr)) @@ -570,6 +571,22 @@ spu_read_memory (CORE_ADDR memaddr, unsigned char *myaddr, int len) /* Use the "mem" spufs file to access SPU local store. */ sprintf (annex, "%d/mem", fd); ret = spu_proc_xfer_spu (annex, myaddr, NULL, memaddr, len); + if (ret > 0) + return ret == len ? 0 : EIO; + + /* SPU local store access wraps the address around at the + local store limit. We emulate this here. To avoid needing + an extra access to retrieve the LSLR, we only do that after + trying the original address first, and getting end-of-file. */ + sprintf (lslr_annex, "%d/lslr", fd); + memset (buf, 0, sizeof buf); + if (spu_proc_xfer_spu (lslr_annex, (unsigned char *)buf, NULL, + 0, sizeof buf) <= 0) + return ret; + + lslr = strtoul (buf, NULL, 16); + ret = spu_proc_xfer_spu (annex, myaddr, NULL, memaddr & lslr, len); + return ret == len ? 0 : EIO; } @@ -582,7 +599,8 @@ spu_write_memory (CORE_ADDR memaddr, const unsigned char *myaddr, int len) { int fd, ret; CORE_ADDR addr; - char annex[32]; + char annex[32], lslr_annex[32], buf[32]; + CORE_ADDR lslr; /* We must be stopped on a spu_run system call. */ if (!parse_spufs_run (&fd, &addr)) @@ -591,6 +609,22 @@ spu_write_memory (CORE_ADDR memaddr, const unsigned char *myaddr, int len) /* Use the "mem" spufs file to access SPU local store. */ sprintf (annex, "%d/mem", fd); ret = spu_proc_xfer_spu (annex, NULL, myaddr, memaddr, len); + if (ret > 0) + return ret == len ? 0 : EIO; + + /* SPU local store access wraps the address around at the + local store limit. We emulate this here. To avoid needing + an extra access to retrieve the LSLR, we only do that after + trying the original address first, and getting end-of-file. */ + sprintf (lslr_annex, "%d/lslr", fd); + memset (buf, 0, sizeof buf); + if (spu_proc_xfer_spu (lslr_annex, (unsigned char *)buf, NULL, + 0, sizeof buf) <= 0) + return ret; + + lslr = strtoul (buf, NULL, 16); + ret = spu_proc_xfer_spu (annex, NULL, myaddr, memaddr & lslr, len); + return ret == len ? 0 : EIO; } diff --git a/gdb/spu-linux-nat.c b/gdb/spu-linux-nat.c index 7c9e2c59d26..5adfe4baba7 100644 --- a/gdb/spu-linux-nat.c +++ b/gdb/spu-linux-nat.c @@ -562,7 +562,10 @@ spu_xfer_partial (struct target_ops *ops, { int fd; ULONGEST addr; - char mem_annex[32]; + char mem_annex[32], lslr_annex[32]; + gdb_byte buf[32]; + ULONGEST lslr; + LONGEST ret; /* We must be stopped on a spu_run system call. */ if (!parse_spufs_run (&fd, &addr)) @@ -570,7 +573,22 @@ spu_xfer_partial (struct target_ops *ops, /* Use the "mem" spufs file to access SPU local store. */ xsnprintf (mem_annex, sizeof mem_annex, "%d/mem", fd); - return spu_proc_xfer_spu (mem_annex, readbuf, writebuf, offset, len); + ret = spu_proc_xfer_spu (mem_annex, readbuf, writebuf, offset, len); + if (ret > 0) + return ret; + + /* SPU local store access wraps the address around at the + local store limit. We emulate this here. To avoid needing + an extra access to retrieve the LSLR, we only do that after + trying the original address first, and getting end-of-file. */ + xsnprintf (lslr_annex, sizeof lslr_annex, "%d/lslr", fd); + memset (buf, 0, sizeof buf); + if (spu_proc_xfer_spu (lslr_annex, buf, NULL, 0, sizeof buf) <= 0) + return ret; + + lslr = strtoulst (buf, NULL, 16); + return spu_proc_xfer_spu (mem_annex, readbuf, writebuf, + offset & lslr, len); } return -1; diff --git a/gdb/spu-multiarch.c b/gdb/spu-multiarch.c index d072032a510..450aa42fc53 100644 --- a/gdb/spu-multiarch.c +++ b/gdb/spu-multiarch.c @@ -259,14 +259,35 @@ spu_xfer_partial (struct target_ops *ops, enum target_object object, { int fd = SPUADDR_SPU (offset); CORE_ADDR addr = SPUADDR_ADDR (offset); - char mem_annex[32]; + char mem_annex[32], lslr_annex[32]; + gdb_byte buf[32]; + ULONGEST lslr; + LONGEST ret; - if (fd >= 0 && addr < SPU_LS_SIZE) + if (fd >= 0) { xsnprintf (mem_annex, sizeof mem_annex, "%d/mem", fd); + ret = ops_beneath->to_xfer_partial (ops_beneath, TARGET_OBJECT_SPU, + mem_annex, readbuf, writebuf, + addr, len); + if (ret > 0) + return ret; + + /* SPU local store access wraps the address around at the + local store limit. We emulate this here. To avoid needing + an extra access to retrieve the LSLR, we only do that after + trying the original address first, and getting end-of-file. */ + xsnprintf (lslr_annex, sizeof lslr_annex, "%d/lslr", fd); + memset (buf, 0, sizeof buf); + if (ops_beneath->to_xfer_partial (ops_beneath, TARGET_OBJECT_SPU, + lslr_annex, buf, NULL, + 0, sizeof buf) <= 0) + return ret; + + lslr = strtoulst (buf, NULL, 16); return ops_beneath->to_xfer_partial (ops_beneath, TARGET_OBJECT_SPU, mem_annex, readbuf, writebuf, - addr, len); + addr & lslr, len); } } diff --git a/gdb/spu-tdep.c b/gdb/spu-tdep.c index ae648418e9c..072ae8c7340 100644 --- a/gdb/spu-tdep.c +++ b/gdb/spu-tdep.c @@ -364,23 +364,6 @@ spu_gdbarch_id (struct gdbarch *gdbarch) return id; } -static ULONGEST -spu_lslr (int id) -{ - gdb_byte buf[32]; - char annex[32]; - - if (id == -1) - return SPU_LS_SIZE - 1; - - xsnprintf (annex, sizeof annex, "%d/lslr", id); - memset (buf, 0, sizeof buf); - target_read (¤t_target, TARGET_OBJECT_SPU, annex, - buf, 0, sizeof buf); - - return strtoulst (buf, NULL, 16); -} - static int spu_address_class_type_flags (int byte_size, int dwarf2_addr_class) { @@ -426,7 +409,6 @@ spu_pointer_to_address (struct gdbarch *gdbarch, struct type *type, const gdb_byte *buf) { int id = spu_gdbarch_id (gdbarch); - ULONGEST lslr = spu_lslr (id); enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); ULONGEST addr = extract_unsigned_integer (buf, TYPE_LENGTH (type), byte_order); @@ -435,7 +417,7 @@ spu_pointer_to_address (struct gdbarch *gdbarch, if (TYPE_ADDRESS_CLASS_1 (type)) return addr; - return addr? SPUADDR (id, addr & lslr) : 0; + return addr? SPUADDR (id, addr) : 0; } static CORE_ADDR @@ -443,10 +425,9 @@ spu_integer_to_address (struct gdbarch *gdbarch, struct type *type, const gdb_byte *buf) { int id = spu_gdbarch_id (gdbarch); - ULONGEST lslr = spu_lslr (id); ULONGEST addr = unpack_long (type, buf); - return SPUADDR (id, addr & lslr); + return SPUADDR (id, addr); } @@ -1777,7 +1758,7 @@ spu_overlay_update (struct obj_section *osect) /* Whenever a new objfile is loaded, read the target's _ovly_table. If there is one, go through all sections and make sure for non- overlay sections LMA equals VMA, while for overlay sections LMA - is larger than local store size. */ + is larger than SPU_OVERLAY_LMA. */ static void spu_overlay_new_objfile (struct objfile *objfile) { @@ -1807,7 +1788,7 @@ spu_overlay_new_objfile (struct objfile *objfile) if (ovly_table[ndx].mapped_ptr == 0) bfd_section_lma (obfd, bsect) = bfd_section_vma (obfd, bsect); else - bfd_section_lma (obfd, bsect) = bsect->filepos + SPU_LS_SIZE; + bfd_section_lma (obfd, bsect) = SPU_OVERLAY_LMA + bsect->filepos; } } diff --git a/gdb/spu-tdep.h b/gdb/spu-tdep.h index 9e70db9e248..4b83f7489ff 100644 --- a/gdb/spu-tdep.h +++ b/gdb/spu-tdep.h @@ -50,14 +50,71 @@ enum spu_regnum /* Local store. */ #define SPU_LS_SIZE 0x40000 -/* Address conversions. */ +/* Address conversions. + + In a combined PPU/SPU debugging session, we have to consider multiple + address spaces: the PPU 32- or 64-bit address space, and the 32-bit + local store address space for each SPU context. As it is currently + not yet possible to use the program_space / address_space mechanism + to represent this, we encode all those addresses into one single + 64-bit address for the whole process. For SPU programs using overlays, + this address space must also include separate ranges reserved for the + LMA of overlay sections. + + + The following combinations are supported for combined debugging: + + PPU address (this relies on the fact that PPC 64-bit user space + addresses can never have the highest-most bit set): + + +-+---------------------------------+ + |0| ADDR [63] | + +-+---------------------------------+ + + SPU address for SPU context with id SPU (this assumes that SPU + IDs, which are file descriptors, are never larger than 2^30): + + +-+-+--------------+----------------+ + |1|0| SPU [30] | ADDR [32] | + +-+-+--------------+----------------+ + + SPU overlay section LMA for SPU context with id SPU: + + +-+-+--------------+----------------+ + |1|1| SPU [30] | ADDR [32] | + +-+-+--------------+----------------+ + + + In SPU stand-alone debugging mode (using spu-linux-nat.c), + the following combinations are supported: + + SPU address: + + +-+-+--------------+----------------+ + |0|0| 0 | ADDR [32] | + +-+-+--------------+----------------+ + + SPU overlay section LMA: + + +-+-+--------------+----------------+ + |0|1| 0 | ADDR [32] | + +-+-+--------------+----------------+ + + + The following macros allow manipulation of addresses in the + above formats. */ + #define SPUADDR(spu, addr) \ ((spu) != -1? (ULONGEST)1 << 63 | (ULONGEST)(spu) << 32 | (addr) : (addr)) + #define SPUADDR_SPU(addr) \ (((addr) & (ULONGEST)1 << 63) \ - ? (int) ((ULONGEST)(addr) >> 32 & 0x7fffffff) \ + ? (int) ((ULONGEST)(addr) >> 32 & 0x3fffffff) \ : -1) + #define SPUADDR_ADDR(addr) \ (((addr) & (ULONGEST)1 << 63)? (ULONGEST)(addr) & 0xffffffff : (addr)) +#define SPU_OVERLAY_LMA ((ULONGEST)1 << 62) + #endif diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 3b61976f054..ca54ab73394 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2010-06-19 Ulrich Weigand + + * gdb.arch/spu-ls.exp: New file. + * gdb.arch/spu-ls.c: Likewise. + 2010-06-18 Stan Shebs * gdb.threads/thread-specific.exp: Add tests of $_thread. diff --git a/gdb/testsuite/gdb.arch/spu-ls.c b/gdb/testsuite/gdb.arch/spu-ls.c new file mode 100644 index 00000000000..4cb651f7e07 --- /dev/null +++ b/gdb/testsuite/gdb.arch/spu-ls.c @@ -0,0 +1,31 @@ +/* Copyright 2010 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + This file is part of the gdb testsuite. + + Contributed by Ulrich Weigand . + Tests for SPU local-store access. */ + +char *ptr = (char *)0x12345678; + +char array[256]; + +int +main (unsigned long long speid, unsigned long long argp, + unsigned long long envp) +{ + return 0; +} + diff --git a/gdb/testsuite/gdb.arch/spu-ls.exp b/gdb/testsuite/gdb.arch/spu-ls.exp new file mode 100644 index 00000000000..967d057bd23 --- /dev/null +++ b/gdb/testsuite/gdb.arch/spu-ls.exp @@ -0,0 +1,54 @@ +# Copyright 2010 Free Software Foundation, Inc. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . +# +# This file is part of the gdb testsuite. +# +# Contributed by Ulrich Weigand . +# Tests for SPU local-store access. + +if { ![istarget "spu-*-elf"] } then { + verbose "Skipping SPU-only testcase" + return +} + +set testfile "spu-ls" +set srcfile ${testfile}.c +set binfile ${objdir}/${subdir}/${testfile} +set sources ${srcdir}/${subdir}/${srcfile} + +if { [gdb_compile $sources ${binfile} executable { debug }] != "" } { + return -1 +} + +gdb_exit +gdb_start +gdb_reinitialize_dir $srcdir/$subdir +gdb_load ${binfile} + +if ![runto_main] then { + fail "Can't run to main" + return 0 +} + +gdb_test "print ptr" " = 0x12345678 \".*\"" "print ptr" +gdb_test_no_output "set ptr = array + \$lslr + 1" "set ptr = array + \$lslr + 1" +gdb_test_no_output "set array\[0\] = 1" "set array\[0\] = 1" +gdb_test "print *ptr" " = 1 '\\\\001'" "print *ptr" +gdb_test_no_output "set *ptr = 2" "set *ptr = 2" +gdb_test "print array\[0\]" " = 2 '\\\\002'" "print array\[0\]" + +gdb_exit + +return 0 -- cgit v1.2.1