2008-11-20 15:44:10 +00:00
|
|
|
|
--- gdb/Makefile.in
|
|
|
|
|
+++ gdb/Makefile.in
|
2008-11-07 14:07:25 +00:00
|
|
|
|
@@ -499,7 +499,7 @@ ALL_TARGET_OBS = \
|
|
|
|
|
sh64-tdep.o sh-linux-tdep.o shnbsd-tdep.o sh-tdep.o \
|
|
|
|
|
sparc-linux-tdep.o sparcnbsd-tdep.o sparcobsd-tdep.o \
|
|
|
|
|
sparc-sol2-tdep.o sparc-tdep.o \
|
|
|
|
|
- spu-tdep.o \
|
|
|
|
|
+ spu-tdep.o spu-multiarch.o solib-spu.o \
|
|
|
|
|
v850-tdep.o \
|
|
|
|
|
vaxnbsd-tdep.o vaxobsd-tdep.o vax-tdep.o \
|
|
|
|
|
xstormy16-tdep.o \
|
2009-01-19 00:46:30 +00:00
|
|
|
|
@@ -1338,7 +1338,7 @@ ALLDEPFILES = \
|
2008-11-07 14:07:25 +00:00
|
|
|
|
sparc64-tdep.c sparc64fbsd-nat.c sparc64fbsd-tdep.c \
|
|
|
|
|
sparc64nbsd-nat.c sparc64nbsd-tdep.c sparc64obsd-tdep.c \
|
|
|
|
|
sparcnbsd-nat.c sparcnbsd-tdep.c sparcobsd-tdep.c \
|
|
|
|
|
- spu-linux-nat.c spu-tdep.c \
|
|
|
|
|
+ spu-linux-nat.c spu-tdep.c spu-multiarch.c solib-spu.c \
|
|
|
|
|
v850-tdep.c \
|
|
|
|
|
vax-nat.c vax-tdep.c vaxbsd-nat.c vaxnbsd-tdep.c \
|
2009-01-19 00:46:30 +00:00
|
|
|
|
windows-nat.c windows-tdep.c \
|
2008-11-20 15:44:10 +00:00
|
|
|
|
--- gdb/arch-utils.c
|
|
|
|
|
+++ gdb/arch-utils.c
|
2008-11-07 14:07:25 +00:00
|
|
|
|
@@ -326,15 +326,24 @@ set_endian (char *ignore_args, int from_
|
2008-09-12 23:16:14 +00:00
|
|
|
|
}
|
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
/* Given SELECTED, a currently selected BFD architecture, and
|
|
|
|
|
- FROM_TARGET, a BFD architecture reported by the target description,
|
|
|
|
|
- return what architecture to use. Either may be NULL; if both are
|
|
|
|
|
- specified, we use the more specific. If the two are obviously
|
|
|
|
|
- incompatible, warn the user. */
|
|
|
|
|
+ TARGET_DESC, the current target description, return what
|
|
|
|
|
+ architecture to use.
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ SELECTED may be NULL, in which case we return the architecture
|
|
|
|
|
+ associated with TARGET_DESC. If SELECTED specifies a variant
|
|
|
|
|
+ of the architecture associtated with TARGET_DESC, return the
|
|
|
|
|
+ more specific of the two.
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ If SELECTED is a different architecture, but it is accepted as
|
|
|
|
|
+ compatible by the target, we can use the target architecture.
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ If SELECTED is obviously incompatible, warn the user. */
|
|
|
|
|
|
|
|
|
|
static const struct bfd_arch_info *
|
|
|
|
|
-choose_architecture_for_target (const struct bfd_arch_info *selected,
|
|
|
|
|
- const struct bfd_arch_info *from_target)
|
|
|
|
|
+choose_architecture_for_target (const struct target_desc *target_desc,
|
|
|
|
|
+ const struct bfd_arch_info *selected)
|
|
|
|
|
{
|
|
|
|
|
+ const struct bfd_arch_info *from_target = tdesc_architecture (target_desc);
|
|
|
|
|
const struct bfd_arch_info *compat1, *compat2;
|
|
|
|
|
|
|
|
|
|
if (selected == NULL)
|
|
|
|
|
@@ -364,6 +373,11 @@ choose_architecture_for_target (const st
|
|
|
|
|
|
|
|
|
|
if (compat1 == NULL && compat2 == NULL)
|
|
|
|
|
{
|
|
|
|
|
+ /* BFD considers the architectures incompatible. Check our target
|
|
|
|
|
+ description whether it accepts SELECTED as compatible anyway. */
|
|
|
|
|
+ if (tdesc_compatible_p (target_desc, selected))
|
|
|
|
|
+ return from_target;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
warning (_("Selected architecture %s is not compatible "
|
|
|
|
|
"with reported target architecture %s"),
|
|
|
|
|
selected->printable_name, from_target->printable_name);
|
|
|
|
|
@@ -692,7 +706,7 @@ gdbarch_info_fill (struct gdbarch_info *
|
|
|
|
|
/* From the target. */
|
|
|
|
|
if (info->target_desc != NULL)
|
|
|
|
|
info->bfd_arch_info = choose_architecture_for_target
|
|
|
|
|
- (info->bfd_arch_info, tdesc_architecture (info->target_desc));
|
|
|
|
|
+ (info->target_desc, info->bfd_arch_info);
|
|
|
|
|
/* From the default. */
|
|
|
|
|
if (info->bfd_arch_info == NULL)
|
|
|
|
|
info->bfd_arch_info = default_bfd_arch;
|
|
|
|
|
@@ -720,6 +734,27 @@ gdbarch_info_fill (struct gdbarch_info *
|
|
|
|
|
gdb_assert (info->bfd_arch_info != NULL);
|
|
|
|
|
}
|
|
|
|
|
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+/* restore_current_gdbarch() will be used by the cleanup machinery
|
|
|
|
|
+ to restore the current_gdbarch value saved in a call to
|
|
|
|
|
+ save_current_gdbarch(). */
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
|
|
|
|
+static void
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+restore_current_gdbarch (void *arg)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+{
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ current_gdbarch = arg;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+}
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+/* Save the value of current so that it may be restored by a
|
|
|
|
|
+ later call to do_cleanups(). Returns the struct cleanup pointer
|
|
|
|
|
+ needed for later doing the cleanup. */
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+struct cleanup *
|
|
|
|
|
+save_current_gdbarch (void)
|
|
|
|
|
+{
|
|
|
|
|
+ return make_cleanup (restore_current_gdbarch, current_gdbarch);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+}
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
/* */
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
extern initialize_file_ftype _initialize_gdbarch_utils; /* -Wmissing-prototypes */
|
2008-11-20 15:44:10 +00:00
|
|
|
|
--- gdb/arch-utils.h
|
|
|
|
|
+++ gdb/arch-utils.h
|
2008-11-07 14:07:25 +00:00
|
|
|
|
@@ -139,4 +139,9 @@ extern void gdbarch_info_fill (struct gd
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
extern struct gdbarch *gdbarch_from_bfd (bfd *abfd);
|
|
|
|
|
|
|
|
|
|
+/* Save value of current_gdbarch so that it may be restored by
|
|
|
|
|
+ a later call to do_cleanups(). Returns the struct cleanup
|
|
|
|
|
+ pointer needed for later doing the cleanup. */
|
|
|
|
|
+struct cleanup *save_current_gdbarch (void);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
#endif
|
2008-11-20 15:44:10 +00:00
|
|
|
|
--- gdb/avr-tdep.c
|
|
|
|
|
+++ gdb/avr-tdep.c
|
2008-11-07 14:07:25 +00:00
|
|
|
|
@@ -278,7 +278,8 @@ avr_convert_saddr_to_raw (CORE_ADDR x)
|
|
|
|
|
/* Convert from address to pointer and vice-versa. */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
-avr_address_to_pointer (struct type *type, gdb_byte *buf, CORE_ADDR addr)
|
|
|
|
|
+avr_address_to_pointer (struct gdbarch *gdbarch,
|
|
|
|
|
+ struct type *type, gdb_byte *buf, CORE_ADDR addr)
|
|
|
|
|
{
|
|
|
|
|
/* Is it a code address? */
|
|
|
|
|
if (TYPE_CODE (TYPE_TARGET_TYPE (type)) == TYPE_CODE_FUNC
|
|
|
|
|
@@ -296,7 +297,8 @@ avr_address_to_pointer (struct type *typ
|
2008-09-12 23:16:14 +00:00
|
|
|
|
}
|
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
static CORE_ADDR
|
|
|
|
|
-avr_pointer_to_address (struct type *type, const gdb_byte *buf)
|
|
|
|
|
+avr_pointer_to_address (struct gdbarch *gdbarch,
|
|
|
|
|
+ struct type *type, const gdb_byte *buf)
|
|
|
|
|
{
|
|
|
|
|
CORE_ADDR addr = extract_unsigned_integer (buf, TYPE_LENGTH (type));
|
|
|
|
|
|
2008-11-20 15:44:10 +00:00
|
|
|
|
--- gdb/breakpoint.c
|
|
|
|
|
+++ gdb/breakpoint.c
|
2009-01-19 00:46:30 +00:00
|
|
|
|
@@ -1134,7 +1134,7 @@ Note: automatically using hardware break
|
2008-11-07 14:07:25 +00:00
|
|
|
|
bpt->overlay_target_info = bpt->target_info;
|
|
|
|
|
bpt->overlay_target_info.placed_address = addr;
|
|
|
|
|
val = target_insert_breakpoint (&bpt->overlay_target_info);
|
|
|
|
|
- if (val != 0)
|
|
|
|
|
+ if (val > 0)
|
|
|
|
|
fprintf_unfiltered (tmp_error_stream,
|
|
|
|
|
"Overlay breakpoint %d failed: in ROM?",
|
|
|
|
|
bpt->owner->number);
|
2009-01-19 00:46:30 +00:00
|
|
|
|
@@ -1157,6 +1157,14 @@ Note: automatically using hardware break
|
2008-11-07 14:07:25 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+ if (val < 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ /* The target could not insert the breakpoint right away due
|
|
|
|
|
+ to a temporary issue. No error, but do not mark the bp
|
|
|
|
|
+ as 'inserted'. */
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ }
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
if (val)
|
|
|
|
|
{
|
|
|
|
|
/* Can't set the breakpoint. */
|
2009-01-19 00:46:30 +00:00
|
|
|
|
@@ -1626,6 +1634,14 @@ remove_breakpoint (struct bp_location *b
|
2008-11-07 14:07:25 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+ if (val < 0)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+ {
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* The target could not remove the breakpoint right away due
|
|
|
|
|
+ to a temporary issue. No error, but keep the bp marked
|
|
|
|
|
+ as 'inserted'. */
|
|
|
|
|
+ return 0;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+ }
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
/* In some cases, we might not be able to remove a breakpoint
|
|
|
|
|
in a shared library that has already been removed, but we
|
|
|
|
|
have not yet processed the shlib unload event. */
|
2009-01-19 00:46:30 +00:00
|
|
|
|
@@ -7552,6 +7568,37 @@ breakpoint_re_set (void)
|
2008-11-07 14:07:25 +00:00
|
|
|
|
|
|
|
|
|
create_overlay_event_breakpoint ("_ovly_debug_event");
|
|
|
|
|
}
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+/* Update breakpoint location list after an object file was relocated. */
|
|
|
|
|
+void
|
|
|
|
|
+breakpoint_relocate (struct objfile *objfile, struct section_offsets *delta)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+{
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ struct bp_location *b;
|
|
|
|
|
+ struct obj_section *s;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* Update the breakpoint addresses so that breakpoint_re_set has a chance
|
|
|
|
|
+ to identify the previous locations (to carry over enabled state). */
|
|
|
|
|
+ ALL_BP_LOCATIONS (b)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+ {
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ if (b->inserted || b->loc_type == bp_loc_other)
|
|
|
|
|
+ continue;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ ALL_OBJFILE_OSECTIONS (objfile, s)
|
|
|
|
|
+ {
|
|
|
|
|
+ CORE_ADDR offset = ANOFFSET (delta, s->the_bfd_section->index);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ if (b->address >= obj_section_addr (s) - offset
|
|
|
|
|
+ && b->address < obj_section_endaddr (s) - offset)
|
|
|
|
|
+ {
|
|
|
|
|
+ b->address += offset;
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+ }
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* Now reset all breakpoints. */
|
|
|
|
|
+ breakpoint_re_set ();
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+}
|
2008-11-07 14:07:25 +00:00
|
|
|
|
|
|
|
|
|
/* Reset the thread number of this breakpoint:
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-20 15:44:10 +00:00
|
|
|
|
--- gdb/breakpoint.h
|
|
|
|
|
+++ gdb/breakpoint.h
|
2009-01-19 00:46:30 +00:00
|
|
|
|
@@ -670,6 +670,8 @@ extern int breakpoint_thread_match (CORE
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
extern void until_break_command (char *, int, int);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+extern void breakpoint_relocate (struct objfile *, struct section_offsets *);
|
|
|
|
|
+
|
|
|
|
|
extern void breakpoint_re_set (void);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
extern void breakpoint_re_set_thread (struct breakpoint *);
|
2008-11-20 15:44:10 +00:00
|
|
|
|
--- gdb/cli/cli-dump.c
|
|
|
|
|
+++ gdb/cli/cli-dump.c
|
2008-11-07 14:07:25 +00:00
|
|
|
|
@@ -428,7 +428,7 @@ add_dump_command (char *name, void (*fun
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
/* Opaque data for restore_section_callback. */
|
|
|
|
|
struct callback_data {
|
|
|
|
|
- long load_offset;
|
|
|
|
|
+ CORE_ADDR load_offset;
|
|
|
|
|
CORE_ADDR load_start;
|
|
|
|
|
CORE_ADDR load_end;
|
|
|
|
|
};
|
|
|
|
|
@@ -533,8 +533,8 @@ restore_binary_file (char *filename, str
|
|
|
|
|
printf_filtered
|
|
|
|
|
("Restoring binary file %s into memory (0x%lx to 0x%lx)\n",
|
|
|
|
|
filename,
|
|
|
|
|
- (unsigned long) data->load_start + data->load_offset,
|
|
|
|
|
- (unsigned long) data->load_start + data->load_offset + len);
|
|
|
|
|
+ (unsigned long) (data->load_start + data->load_offset),
|
|
|
|
|
+ (unsigned long) (data->load_start + data->load_offset + len));
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
/* Now set the file pos to the requested load start pos. */
|
|
|
|
|
if (fseek (file, data->load_start, SEEK_SET) != 0)
|
|
|
|
|
@@ -584,7 +584,7 @@ restore_command (char *args, int from_tt
|
|
|
|
|
/* Parse offset (optional). */
|
|
|
|
|
if (args != NULL && *args != '\0')
|
|
|
|
|
data.load_offset =
|
|
|
|
|
- parse_and_eval_long (scan_expression_with_cleanup (&args, NULL));
|
|
|
|
|
+ parse_and_eval_address (scan_expression_with_cleanup (&args, NULL));
|
|
|
|
|
if (args != NULL && *args != '\0')
|
|
|
|
|
{
|
|
|
|
|
/* Parse start address (optional). */
|
2008-11-20 15:44:10 +00:00
|
|
|
|
--- gdb/configure.tgt
|
|
|
|
|
+++ gdb/configure.tgt
|
2009-01-19 00:46:30 +00:00
|
|
|
|
@@ -354,7 +354,8 @@ powerpc-*-aix* | rs6000-*-*)
|
2008-11-07 14:07:25 +00:00
|
|
|
|
powerpc-*-linux* | powerpc64-*-linux*)
|
|
|
|
|
# Target: PowerPC running Linux
|
|
|
|
|
gdb_target_obs="rs6000-tdep.o ppc-linux-tdep.o ppc-sysv-tdep.o \
|
|
|
|
|
- solib.o solib-svr4.o corelow.o symfile-mem.o"
|
|
|
|
|
+ solib.o solib-svr4.o solib-spu.o spu-multiarch.o \
|
|
|
|
|
+ corelow.o symfile-mem.o"
|
|
|
|
|
gdb_sim=../sim/ppc/libsim.a
|
|
|
|
|
build_gdbserver=yes
|
|
|
|
|
;;
|
2008-11-20 15:44:10 +00:00
|
|
|
|
--- gdb/corelow.c
|
|
|
|
|
+++ gdb/corelow.c
|
2008-11-07 14:07:25 +00:00
|
|
|
|
@@ -542,6 +542,33 @@ core_files_info (struct target_ops *t)
|
|
|
|
|
print_section_info (t, core_bfd);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+struct spuid_list
|
|
|
|
|
+{
|
|
|
|
|
+ gdb_byte *buf;
|
|
|
|
|
+ ULONGEST offset;
|
|
|
|
|
+ LONGEST len;
|
|
|
|
|
+ ULONGEST pos;
|
|
|
|
|
+ ULONGEST written;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+};
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+static void
|
|
|
|
|
+add_to_spuid_list (bfd *abfd, asection *asect, void *list_p)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+{
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ struct spuid_list *list = list_p;
|
|
|
|
|
+ int fd, pos = 0;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ sscanf (bfd_section_name (abfd, asect), "SPU/%d/regs%n", &fd, &pos);
|
|
|
|
|
+ if (pos == 0)
|
|
|
|
|
+ return;
|
|
|
|
|
+
|
|
|
|
|
+ if (list->pos >= list->offset && list->pos + 4 <= list->offset + list->len)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+ {
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ store_unsigned_integer (list->buf + list->pos - list->offset, 4, fd);
|
|
|
|
|
+ list->written += 4;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+ }
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ list->pos += 4;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+}
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
static LONGEST
|
|
|
|
|
core_xfer_partial (struct target_ops *ops, enum target_object object,
|
|
|
|
|
const char *annex, gdb_byte *readbuf,
|
|
|
|
|
@@ -634,6 +661,53 @@ core_xfer_partial (struct target_ops *op
|
|
|
|
|
}
|
|
|
|
|
/* FALL THROUGH */
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ case TARGET_OBJECT_SPU:
|
|
|
|
|
+ if (readbuf && annex)
|
|
|
|
|
+ {
|
|
|
|
|
+ /* When the SPU contexts are stored in core file, BFD
|
|
|
|
|
+ represents this with a fake section called "SPU/<annex>". */
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ struct bfd_section *section;
|
|
|
|
|
+ bfd_size_type size;
|
|
|
|
|
+ char *contents;
|
|
|
|
|
+
|
|
|
|
|
+ char sectionstr[100];
|
|
|
|
|
+ xsnprintf (sectionstr, sizeof sectionstr, "SPU/%s", annex);
|
|
|
|
|
+
|
|
|
|
|
+ section = bfd_get_section_by_name (core_bfd, sectionstr);
|
|
|
|
|
+ if (section == NULL)
|
|
|
|
|
+ return -1;
|
|
|
|
|
+
|
|
|
|
|
+ size = bfd_section_size (core_bfd, section);
|
|
|
|
|
+ if (offset >= size)
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ size -= offset;
|
|
|
|
|
+ if (size > len)
|
|
|
|
|
+ size = len;
|
|
|
|
|
+ if (size > 0
|
|
|
|
|
+ && !bfd_get_section_contents (core_bfd, section, readbuf,
|
|
|
|
|
+ (file_ptr) offset, size))
|
|
|
|
|
+ {
|
|
|
|
|
+ warning (_("Couldn't read SPU section in core file."));
|
|
|
|
|
+ return -1;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return size;
|
|
|
|
|
+ }
|
|
|
|
|
+ else if (readbuf)
|
|
|
|
|
+ {
|
|
|
|
|
+ /* NULL annex requests list of all present spuids. */
|
|
|
|
|
+ struct spuid_list list;
|
|
|
|
|
+ list.buf = readbuf;
|
|
|
|
|
+ list.offset = offset;
|
|
|
|
|
+ list.len = len;
|
|
|
|
|
+ list.pos = 0;
|
|
|
|
|
+ list.written = 0;
|
|
|
|
|
+ bfd_map_over_sections (core_bfd, add_to_spuid_list, &list);
|
|
|
|
|
+ return list.written;
|
|
|
|
|
+ }
|
|
|
|
|
+ return -1;
|
|
|
|
|
+
|
|
|
|
|
default:
|
|
|
|
|
if (ops->beneath != NULL)
|
|
|
|
|
return ops->beneath->to_xfer_partial (ops->beneath, object, annex,
|
|
|
|
|
@@ -673,8 +747,8 @@ core_file_thread_alive (ptid_t tid)
|
|
|
|
|
static const struct target_desc *
|
|
|
|
|
core_read_description (struct target_ops *target)
|
|
|
|
|
{
|
|
|
|
|
- if (gdbarch_core_read_description_p (current_gdbarch))
|
|
|
|
|
- return gdbarch_core_read_description (current_gdbarch, target, core_bfd);
|
|
|
|
|
+ if (core_gdbarch && gdbarch_core_read_description_p (core_gdbarch))
|
|
|
|
|
+ return gdbarch_core_read_description (core_gdbarch, target, core_bfd);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
return NULL;
|
|
|
|
|
}
|
2008-11-20 15:44:10 +00:00
|
|
|
|
--- gdb/doc/gdb.texinfo
|
|
|
|
|
+++ gdb/doc/gdb.texinfo
|
2009-01-19 00:46:30 +00:00
|
|
|
|
@@ -16834,6 +16834,33 @@ and local store addresses and transfer s
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
@end table
|
|
|
|
|
|
|
|
|
|
+When @value{GDBN} is debugging a combined PowerPC/SPU application
|
|
|
|
|
+on the Cell Broadband Engine, it provides in addition the following
|
|
|
|
|
+special commands:
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+@table @code
|
|
|
|
|
+@item set spu stop-on-load @var{arg}
|
|
|
|
|
+@kindex set spu
|
|
|
|
|
+Set whether to stop for new SPE threads. When set to @code{on}, @value{GDBN}
|
|
|
|
|
+will give control to the user when a new SPE thread enters its @code{main}
|
|
|
|
|
+function. The default is @code{off}.
|
|
|
|
|
+
|
|
|
|
|
+@item show spu stop-on-load
|
|
|
|
|
+@kindex show spu
|
|
|
|
|
+Show whether to stop for new SPE threads.
|
|
|
|
|
+
|
|
|
|
|
+@item set spu auto-flush-cache @var{arg}
|
|
|
|
|
+Set whether to automatically flush the software-managed cache. When set to
|
|
|
|
|
+@code{on}, @value{GDBN} will automatically cause the SPE software-managed
|
|
|
|
|
+cache to be flushed whenever SPE execution stops. This provides a consistent
|
|
|
|
|
+view of PowerPC memory that is accessed via the cache. If an application
|
|
|
|
|
+does not use the software-managed cache, this option has no effect.
|
|
|
|
|
+
|
|
|
|
|
+@item show spu auto-flush-cache
|
|
|
|
|
+Show whether to automatically flush the software-managed cache.
|
|
|
|
|
+
|
|
|
|
|
+@end table
|
|
|
|
|
+
|
|
|
|
|
@node PowerPC
|
|
|
|
|
@subsection PowerPC
|
|
|
|
|
@cindex PowerPC architecture
|
2009-01-19 00:46:30 +00:00
|
|
|
|
@@ -28801,6 +28828,7 @@ are explained further below.
|
2008-11-07 14:07:25 +00:00
|
|
|
|
<!DOCTYPE target SYSTEM "gdb-target.dtd">
|
|
|
|
|
<target version="1.0">
|
|
|
|
|
@r{[}@var{architecture}@r{]}
|
|
|
|
|
+ @r{[}@var{compatible}@dots{}@r{]}
|
|
|
|
|
@r{[}@var{feature}@dots{}@r{]}
|
|
|
|
|
</target>
|
|
|
|
|
@end smallexample
|
2009-01-19 00:46:30 +00:00
|
|
|
|
@@ -28852,9 +28880,33 @@ An @samp{<architecture>} element has thi
|
2008-11-07 14:07:25 +00:00
|
|
|
|
<architecture>@var{arch}</architecture>
|
|
|
|
|
@end smallexample
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
-@var{arch} is an architecture name from the same selection
|
|
|
|
|
-accepted by @code{set architecture} (@pxref{Targets, ,Specifying a
|
|
|
|
|
-Debugging Target}).
|
|
|
|
|
+@var{arch} is one of the architectures from the set accepted by
|
|
|
|
|
+@code{set architecture} (@pxref{Targets, ,Specifying a Debugging Target}).
|
|
|
|
|
+
|
|
|
|
|
+@subsection Compatible Architecture
|
|
|
|
|
+@cindex <compatible>
|
|
|
|
|
+
|
|
|
|
|
+A @samp{<compatible>} element has this form:
|
|
|
|
|
+
|
|
|
|
|
+@smallexample
|
|
|
|
|
+ <compatible>@var{arch}</compatible>
|
|
|
|
|
+@end smallexample
|
|
|
|
|
+
|
|
|
|
|
+@var{arch} is one of the architectures from the set accepted by
|
|
|
|
|
+@code{set architecture} (@pxref{Targets, ,Specifying a Debugging Target}).
|
|
|
|
|
+
|
|
|
|
|
+A @samp{<compatible>} element is used to specify that the target
|
|
|
|
|
+is able to run binaries in some other than the main target architecture
|
|
|
|
|
+given by the @samp{<architecture>} element. For example, on the
|
|
|
|
|
+Cell Broadband Engine, the main architecture is @code{powerpc:common}
|
|
|
|
|
+or @code{powerpc:common64}, but the system is able to run binaries
|
|
|
|
|
+in the @code{spu} architecture as well. The way to describe this
|
|
|
|
|
+capability with @samp{<compatible>} is as follows:
|
|
|
|
|
+
|
|
|
|
|
+@smallexample
|
|
|
|
|
+ <architecture>@code{powerpc:common}</architecture>
|
|
|
|
|
+ <compatible>@code{spu}</compatible>
|
|
|
|
|
+@end smallexample
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
@subsection Features
|
|
|
|
|
@cindex <feature>
|
2008-11-20 15:44:10 +00:00
|
|
|
|
--- gdb/features/Makefile
|
|
|
|
|
+++ gdb/features/Makefile
|
2008-11-07 14:07:25 +00:00
|
|
|
|
@@ -34,7 +34,7 @@
|
|
|
|
|
WHICH = arm-with-iwmmxt mips-linux mips64-linux \
|
|
|
|
|
rs6000/powerpc-32l rs6000/powerpc-altivec32l rs6000/powerpc-e500l \
|
|
|
|
|
rs6000/powerpc-64l rs6000/powerpc-altivec64l rs6000/powerpc-vsx32l \
|
|
|
|
|
- rs6000/powerpc-vsx64l
|
|
|
|
|
+ rs6000/powerpc-vsx64l rs6000/powerpc-cell32l rs6000/powerpc-cell64l
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
# Record which registers should be sent to GDB by default after stop.
|
|
|
|
|
arm-with-iwmmxt-expedite = r11,sp,pc
|
2008-11-20 15:44:10 +00:00
|
|
|
|
@@ -42,6 +42,7 @@ mips-linux-expedite = r29,pc
|
2008-11-07 14:07:25 +00:00
|
|
|
|
mips64-linux-expedite = r29,pc
|
|
|
|
|
rs6000/powerpc-32l-expedite = r1,pc
|
|
|
|
|
rs6000/powerpc-altivec32l-expedite = r1,pc
|
|
|
|
|
+rs6000/powerpc-cell32l-expedite = r1,pc,r0,orig_r3,r4
|
|
|
|
|
rs6000/powerpc-vsx32l-expedite = r1,pc
|
2008-11-20 15:44:10 +00:00
|
|
|
|
rs6000/powerpc-isa205-32l-expedite = r1,pc
|
|
|
|
|
rs6000/powerpc-isa205-altivec32l-expedite = r1,pc
|
|
|
|
|
@@ -49,6 +50,7 @@ rs6000/powerpc-isa205-vsx32l-expedite =
|
2008-11-07 14:07:25 +00:00
|
|
|
|
rs6000/powerpc-e500l-expedite = r1,pc
|
|
|
|
|
rs6000/powerpc-64l-expedite = r1,pc
|
|
|
|
|
rs6000/powerpc-altivec64l-expedite = r1,pc
|
|
|
|
|
+rs6000/powerpc-cell64l-expedite = r1,pc,r0,orig_r3,r4
|
|
|
|
|
rs6000/powerpc-vsx64l-expedite = r1,pc
|
2008-11-20 15:44:10 +00:00
|
|
|
|
rs6000/powerpc-isa205-64l-expedite = r1,pc
|
|
|
|
|
rs6000/powerpc-isa205-altivec64l-expedite = r1,pc
|
|
|
|
|
--- gdb/features/rs6000/powerpc-cell32l.c
|
|
|
|
|
+++ gdb/features/rs6000/powerpc-cell32l.c
|
2008-11-07 14:07:25 +00:00
|
|
|
|
@@ -0,0 +1,170 @@
|
|
|
|
|
+/* THIS FILE IS GENERATED. Original: powerpc-cell32l.xml */
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+#include "defs.h"
|
|
|
|
|
+#include "gdbtypes.h"
|
|
|
|
|
+#include "target-descriptions.h"
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+struct target_desc *tdesc_powerpc_cell32l;
|
|
|
|
|
+static void
|
|
|
|
|
+initialize_tdesc_powerpc_cell32l (void)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+{
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ struct target_desc *result = allocate_target_description ();
|
|
|
|
|
+ struct tdesc_feature *feature;
|
|
|
|
|
+ struct type *field_type, *type;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ set_tdesc_architecture (result, bfd_scan_arch ("powerpc:common"));
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ tdesc_add_compatible (result, bfd_scan_arch ("spu:256K"));
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ feature = tdesc_create_feature (result, "org.gnu.gdb.power.core");
|
|
|
|
|
+ tdesc_create_reg (feature, "r0", 0, 1, NULL, 32, "uint32");
|
|
|
|
|
+ tdesc_create_reg (feature, "r1", 1, 1, NULL, 32, "uint32");
|
|
|
|
|
+ tdesc_create_reg (feature, "r2", 2, 1, NULL, 32, "uint32");
|
|
|
|
|
+ tdesc_create_reg (feature, "r3", 3, 1, NULL, 32, "uint32");
|
|
|
|
|
+ tdesc_create_reg (feature, "r4", 4, 1, NULL, 32, "uint32");
|
|
|
|
|
+ tdesc_create_reg (feature, "r5", 5, 1, NULL, 32, "uint32");
|
|
|
|
|
+ tdesc_create_reg (feature, "r6", 6, 1, NULL, 32, "uint32");
|
|
|
|
|
+ tdesc_create_reg (feature, "r7", 7, 1, NULL, 32, "uint32");
|
|
|
|
|
+ tdesc_create_reg (feature, "r8", 8, 1, NULL, 32, "uint32");
|
|
|
|
|
+ tdesc_create_reg (feature, "r9", 9, 1, NULL, 32, "uint32");
|
|
|
|
|
+ tdesc_create_reg (feature, "r10", 10, 1, NULL, 32, "uint32");
|
|
|
|
|
+ tdesc_create_reg (feature, "r11", 11, 1, NULL, 32, "uint32");
|
|
|
|
|
+ tdesc_create_reg (feature, "r12", 12, 1, NULL, 32, "uint32");
|
|
|
|
|
+ tdesc_create_reg (feature, "r13", 13, 1, NULL, 32, "uint32");
|
|
|
|
|
+ tdesc_create_reg (feature, "r14", 14, 1, NULL, 32, "uint32");
|
|
|
|
|
+ tdesc_create_reg (feature, "r15", 15, 1, NULL, 32, "uint32");
|
|
|
|
|
+ tdesc_create_reg (feature, "r16", 16, 1, NULL, 32, "uint32");
|
|
|
|
|
+ tdesc_create_reg (feature, "r17", 17, 1, NULL, 32, "uint32");
|
|
|
|
|
+ tdesc_create_reg (feature, "r18", 18, 1, NULL, 32, "uint32");
|
|
|
|
|
+ tdesc_create_reg (feature, "r19", 19, 1, NULL, 32, "uint32");
|
|
|
|
|
+ tdesc_create_reg (feature, "r20", 20, 1, NULL, 32, "uint32");
|
|
|
|
|
+ tdesc_create_reg (feature, "r21", 21, 1, NULL, 32, "uint32");
|
|
|
|
|
+ tdesc_create_reg (feature, "r22", 22, 1, NULL, 32, "uint32");
|
|
|
|
|
+ tdesc_create_reg (feature, "r23", 23, 1, NULL, 32, "uint32");
|
|
|
|
|
+ tdesc_create_reg (feature, "r24", 24, 1, NULL, 32, "uint32");
|
|
|
|
|
+ tdesc_create_reg (feature, "r25", 25, 1, NULL, 32, "uint32");
|
|
|
|
|
+ tdesc_create_reg (feature, "r26", 26, 1, NULL, 32, "uint32");
|
|
|
|
|
+ tdesc_create_reg (feature, "r27", 27, 1, NULL, 32, "uint32");
|
|
|
|
|
+ tdesc_create_reg (feature, "r28", 28, 1, NULL, 32, "uint32");
|
|
|
|
|
+ tdesc_create_reg (feature, "r29", 29, 1, NULL, 32, "uint32");
|
|
|
|
|
+ tdesc_create_reg (feature, "r30", 30, 1, NULL, 32, "uint32");
|
|
|
|
|
+ tdesc_create_reg (feature, "r31", 31, 1, NULL, 32, "uint32");
|
|
|
|
|
+ tdesc_create_reg (feature, "pc", 64, 1, NULL, 32, "code_ptr");
|
|
|
|
|
+ tdesc_create_reg (feature, "msr", 65, 1, NULL, 32, "uint32");
|
|
|
|
|
+ tdesc_create_reg (feature, "cr", 66, 1, NULL, 32, "uint32");
|
|
|
|
|
+ tdesc_create_reg (feature, "lr", 67, 1, NULL, 32, "code_ptr");
|
|
|
|
|
+ tdesc_create_reg (feature, "ctr", 68, 1, NULL, 32, "uint32");
|
|
|
|
|
+ tdesc_create_reg (feature, "xer", 69, 1, NULL, 32, "uint32");
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ feature = tdesc_create_feature (result, "org.gnu.gdb.power.fpu");
|
|
|
|
|
+ tdesc_create_reg (feature, "f0", 32, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f1", 33, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f2", 34, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f3", 35, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f4", 36, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f5", 37, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f6", 38, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f7", 39, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f8", 40, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f9", 41, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f10", 42, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f11", 43, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f12", 44, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f13", 45, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f14", 46, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f15", 47, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f16", 48, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f17", 49, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f18", 50, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f19", 51, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f20", 52, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f21", 53, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f22", 54, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f23", 55, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f24", 56, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f25", 57, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f26", 58, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f27", 59, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f28", 60, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f29", 61, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f30", 62, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f31", 63, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "fpscr", 70, 1, "float", 32, "int");
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ feature = tdesc_create_feature (result, "org.gnu.gdb.power.linux");
|
|
|
|
|
+ tdesc_create_reg (feature, "orig_r3", 71, 1, NULL, 32, "int");
|
|
|
|
|
+ tdesc_create_reg (feature, "trap", 72, 1, NULL, 32, "int");
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ feature = tdesc_create_feature (result, "org.gnu.gdb.power.altivec");
|
|
|
|
|
+ field_type = tdesc_named_type (feature, "ieee_single");
|
|
|
|
|
+ type = init_vector_type (field_type, 4);
|
|
|
|
|
+ TYPE_NAME (type) = xstrdup ("v4f");
|
|
|
|
|
+ tdesc_record_type (feature, type);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ field_type = tdesc_named_type (feature, "int32");
|
|
|
|
|
+ type = init_vector_type (field_type, 4);
|
|
|
|
|
+ TYPE_NAME (type) = xstrdup ("v4i32");
|
|
|
|
|
+ tdesc_record_type (feature, type);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ field_type = tdesc_named_type (feature, "int16");
|
|
|
|
|
+ type = init_vector_type (field_type, 8);
|
|
|
|
|
+ TYPE_NAME (type) = xstrdup ("v8i16");
|
|
|
|
|
+ tdesc_record_type (feature, type);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ field_type = tdesc_named_type (feature, "int8");
|
|
|
|
|
+ type = init_vector_type (field_type, 16);
|
|
|
|
|
+ TYPE_NAME (type) = xstrdup ("v16i8");
|
|
|
|
|
+ tdesc_record_type (feature, type);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ type = init_composite_type (NULL, TYPE_CODE_UNION);
|
|
|
|
|
+ TYPE_NAME (type) = xstrdup ("vec128");
|
|
|
|
|
+ field_type = tdesc_named_type (feature, "uint128");
|
|
|
|
|
+ append_composite_type_field (type, xstrdup ("uint128"), field_type);
|
|
|
|
|
+ field_type = tdesc_named_type (feature, "v4f");
|
|
|
|
|
+ append_composite_type_field (type, xstrdup ("v4_float"), field_type);
|
|
|
|
|
+ field_type = tdesc_named_type (feature, "v4i32");
|
|
|
|
|
+ append_composite_type_field (type, xstrdup ("v4_int32"), field_type);
|
|
|
|
|
+ field_type = tdesc_named_type (feature, "v8i16");
|
|
|
|
|
+ append_composite_type_field (type, xstrdup ("v8_int16"), field_type);
|
|
|
|
|
+ field_type = tdesc_named_type (feature, "v16i8");
|
|
|
|
|
+ append_composite_type_field (type, xstrdup ("v16_int8"), field_type);
|
|
|
|
|
+ TYPE_VECTOR (type) = 1;
|
|
|
|
|
+ tdesc_record_type (feature, type);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ tdesc_create_reg (feature, "vr0", 73, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr1", 74, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr2", 75, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr3", 76, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr4", 77, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr5", 78, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr6", 79, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr7", 80, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr8", 81, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr9", 82, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr10", 83, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr11", 84, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr12", 85, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr13", 86, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr14", 87, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr15", 88, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr16", 89, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr17", 90, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr18", 91, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr19", 92, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr20", 93, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr21", 94, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr22", 95, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr23", 96, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr24", 97, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr25", 98, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr26", 99, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr27", 100, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr28", 101, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr29", 102, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr30", 103, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr31", 104, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vscr", 105, 1, "vector", 32, "int");
|
|
|
|
|
+ tdesc_create_reg (feature, "vrsave", 106, 1, "vector", 32, "int");
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ tdesc_powerpc_cell32l = result;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+}
|
2008-11-20 15:44:10 +00:00
|
|
|
|
--- gdb/features/rs6000/powerpc-cell32l.xml
|
|
|
|
|
+++ gdb/features/rs6000/powerpc-cell32l.xml
|
2008-11-07 14:07:25 +00:00
|
|
|
|
@@ -0,0 +1,19 @@
|
|
|
|
|
+<?xml version="1.0"?>
|
|
|
|
|
+<!-- Copyright (C) 2008 Free Software Foundation, Inc.
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ Copying and distribution of this file, with or without modification,
|
|
|
|
|
+ are permitted in any medium without royalty provided the copyright
|
|
|
|
|
+ notice and this notice are preserved. -->
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+<!-- Cell/B.E. architecture. Identical to the PowerPC 32-bit Linux UISA,
|
|
|
|
|
+ but adds support for the SPU as compatible architecture. -->
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+<!DOCTYPE target SYSTEM "gdb-target.dtd">
|
|
|
|
|
+<target>
|
|
|
|
|
+ <architecture>powerpc:common</architecture>
|
|
|
|
|
+ <compatible>spu</compatible>
|
|
|
|
|
+ <xi:include href="power-core.xml"/>
|
|
|
|
|
+ <xi:include href="power-fpu.xml"/>
|
|
|
|
|
+ <xi:include href="power-linux.xml"/>
|
|
|
|
|
+ <xi:include href="power-altivec.xml"/>
|
|
|
|
|
+</target>
|
2008-11-20 15:44:10 +00:00
|
|
|
|
--- gdb/features/rs6000/powerpc-cell64l.c
|
|
|
|
|
+++ gdb/features/rs6000/powerpc-cell64l.c
|
2008-11-07 14:07:25 +00:00
|
|
|
|
@@ -0,0 +1,170 @@
|
|
|
|
|
+/* THIS FILE IS GENERATED. Original: powerpc-cell64l.xml */
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+#include "defs.h"
|
|
|
|
|
+#include "gdbtypes.h"
|
|
|
|
|
+#include "target-descriptions.h"
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+struct target_desc *tdesc_powerpc_cell64l;
|
|
|
|
|
+static void
|
|
|
|
|
+initialize_tdesc_powerpc_cell64l (void)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+{
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ struct target_desc *result = allocate_target_description ();
|
|
|
|
|
+ struct tdesc_feature *feature;
|
|
|
|
|
+ struct type *field_type, *type;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ set_tdesc_architecture (result, bfd_scan_arch ("powerpc:common64"));
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ tdesc_add_compatible (result, bfd_scan_arch ("spu:256K"));
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ feature = tdesc_create_feature (result, "org.gnu.gdb.power.core");
|
|
|
|
|
+ tdesc_create_reg (feature, "r0", 0, 1, NULL, 64, "uint64");
|
|
|
|
|
+ tdesc_create_reg (feature, "r1", 1, 1, NULL, 64, "uint64");
|
|
|
|
|
+ tdesc_create_reg (feature, "r2", 2, 1, NULL, 64, "uint64");
|
|
|
|
|
+ tdesc_create_reg (feature, "r3", 3, 1, NULL, 64, "uint64");
|
|
|
|
|
+ tdesc_create_reg (feature, "r4", 4, 1, NULL, 64, "uint64");
|
|
|
|
|
+ tdesc_create_reg (feature, "r5", 5, 1, NULL, 64, "uint64");
|
|
|
|
|
+ tdesc_create_reg (feature, "r6", 6, 1, NULL, 64, "uint64");
|
|
|
|
|
+ tdesc_create_reg (feature, "r7", 7, 1, NULL, 64, "uint64");
|
|
|
|
|
+ tdesc_create_reg (feature, "r8", 8, 1, NULL, 64, "uint64");
|
|
|
|
|
+ tdesc_create_reg (feature, "r9", 9, 1, NULL, 64, "uint64");
|
|
|
|
|
+ tdesc_create_reg (feature, "r10", 10, 1, NULL, 64, "uint64");
|
|
|
|
|
+ tdesc_create_reg (feature, "r11", 11, 1, NULL, 64, "uint64");
|
|
|
|
|
+ tdesc_create_reg (feature, "r12", 12, 1, NULL, 64, "uint64");
|
|
|
|
|
+ tdesc_create_reg (feature, "r13", 13, 1, NULL, 64, "uint64");
|
|
|
|
|
+ tdesc_create_reg (feature, "r14", 14, 1, NULL, 64, "uint64");
|
|
|
|
|
+ tdesc_create_reg (feature, "r15", 15, 1, NULL, 64, "uint64");
|
|
|
|
|
+ tdesc_create_reg (feature, "r16", 16, 1, NULL, 64, "uint64");
|
|
|
|
|
+ tdesc_create_reg (feature, "r17", 17, 1, NULL, 64, "uint64");
|
|
|
|
|
+ tdesc_create_reg (feature, "r18", 18, 1, NULL, 64, "uint64");
|
|
|
|
|
+ tdesc_create_reg (feature, "r19", 19, 1, NULL, 64, "uint64");
|
|
|
|
|
+ tdesc_create_reg (feature, "r20", 20, 1, NULL, 64, "uint64");
|
|
|
|
|
+ tdesc_create_reg (feature, "r21", 21, 1, NULL, 64, "uint64");
|
|
|
|
|
+ tdesc_create_reg (feature, "r22", 22, 1, NULL, 64, "uint64");
|
|
|
|
|
+ tdesc_create_reg (feature, "r23", 23, 1, NULL, 64, "uint64");
|
|
|
|
|
+ tdesc_create_reg (feature, "r24", 24, 1, NULL, 64, "uint64");
|
|
|
|
|
+ tdesc_create_reg (feature, "r25", 25, 1, NULL, 64, "uint64");
|
|
|
|
|
+ tdesc_create_reg (feature, "r26", 26, 1, NULL, 64, "uint64");
|
|
|
|
|
+ tdesc_create_reg (feature, "r27", 27, 1, NULL, 64, "uint64");
|
|
|
|
|
+ tdesc_create_reg (feature, "r28", 28, 1, NULL, 64, "uint64");
|
|
|
|
|
+ tdesc_create_reg (feature, "r29", 29, 1, NULL, 64, "uint64");
|
|
|
|
|
+ tdesc_create_reg (feature, "r30", 30, 1, NULL, 64, "uint64");
|
|
|
|
|
+ tdesc_create_reg (feature, "r31", 31, 1, NULL, 64, "uint64");
|
|
|
|
|
+ tdesc_create_reg (feature, "pc", 64, 1, NULL, 64, "code_ptr");
|
|
|
|
|
+ tdesc_create_reg (feature, "msr", 65, 1, NULL, 64, "uint64");
|
|
|
|
|
+ tdesc_create_reg (feature, "cr", 66, 1, NULL, 32, "uint32");
|
|
|
|
|
+ tdesc_create_reg (feature, "lr", 67, 1, NULL, 64, "code_ptr");
|
|
|
|
|
+ tdesc_create_reg (feature, "ctr", 68, 1, NULL, 64, "uint64");
|
|
|
|
|
+ tdesc_create_reg (feature, "xer", 69, 1, NULL, 32, "uint32");
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ feature = tdesc_create_feature (result, "org.gnu.gdb.power.fpu");
|
|
|
|
|
+ tdesc_create_reg (feature, "f0", 32, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f1", 33, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f2", 34, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f3", 35, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f4", 36, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f5", 37, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f6", 38, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f7", 39, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f8", 40, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f9", 41, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f10", 42, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f11", 43, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f12", 44, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f13", 45, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f14", 46, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f15", 47, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f16", 48, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f17", 49, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f18", 50, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f19", 51, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f20", 52, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f21", 53, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f22", 54, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f23", 55, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f24", 56, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f25", 57, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f26", 58, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f27", 59, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f28", 60, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f29", 61, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f30", 62, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "f31", 63, 1, NULL, 64, "ieee_double");
|
|
|
|
|
+ tdesc_create_reg (feature, "fpscr", 70, 1, "float", 32, "int");
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ feature = tdesc_create_feature (result, "org.gnu.gdb.power.linux");
|
|
|
|
|
+ tdesc_create_reg (feature, "orig_r3", 71, 1, NULL, 64, "int");
|
|
|
|
|
+ tdesc_create_reg (feature, "trap", 72, 1, NULL, 64, "int");
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ feature = tdesc_create_feature (result, "org.gnu.gdb.power.altivec");
|
|
|
|
|
+ field_type = tdesc_named_type (feature, "ieee_single");
|
|
|
|
|
+ type = init_vector_type (field_type, 4);
|
|
|
|
|
+ TYPE_NAME (type) = xstrdup ("v4f");
|
|
|
|
|
+ tdesc_record_type (feature, type);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ field_type = tdesc_named_type (feature, "int32");
|
|
|
|
|
+ type = init_vector_type (field_type, 4);
|
|
|
|
|
+ TYPE_NAME (type) = xstrdup ("v4i32");
|
|
|
|
|
+ tdesc_record_type (feature, type);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ field_type = tdesc_named_type (feature, "int16");
|
|
|
|
|
+ type = init_vector_type (field_type, 8);
|
|
|
|
|
+ TYPE_NAME (type) = xstrdup ("v8i16");
|
|
|
|
|
+ tdesc_record_type (feature, type);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ field_type = tdesc_named_type (feature, "int8");
|
|
|
|
|
+ type = init_vector_type (field_type, 16);
|
|
|
|
|
+ TYPE_NAME (type) = xstrdup ("v16i8");
|
|
|
|
|
+ tdesc_record_type (feature, type);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ type = init_composite_type (NULL, TYPE_CODE_UNION);
|
|
|
|
|
+ TYPE_NAME (type) = xstrdup ("vec128");
|
|
|
|
|
+ field_type = tdesc_named_type (feature, "uint128");
|
|
|
|
|
+ append_composite_type_field (type, xstrdup ("uint128"), field_type);
|
|
|
|
|
+ field_type = tdesc_named_type (feature, "v4f");
|
|
|
|
|
+ append_composite_type_field (type, xstrdup ("v4_float"), field_type);
|
|
|
|
|
+ field_type = tdesc_named_type (feature, "v4i32");
|
|
|
|
|
+ append_composite_type_field (type, xstrdup ("v4_int32"), field_type);
|
|
|
|
|
+ field_type = tdesc_named_type (feature, "v8i16");
|
|
|
|
|
+ append_composite_type_field (type, xstrdup ("v8_int16"), field_type);
|
|
|
|
|
+ field_type = tdesc_named_type (feature, "v16i8");
|
|
|
|
|
+ append_composite_type_field (type, xstrdup ("v16_int8"), field_type);
|
|
|
|
|
+ TYPE_VECTOR (type) = 1;
|
|
|
|
|
+ tdesc_record_type (feature, type);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ tdesc_create_reg (feature, "vr0", 73, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr1", 74, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr2", 75, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr3", 76, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr4", 77, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr5", 78, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr6", 79, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr7", 80, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr8", 81, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr9", 82, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr10", 83, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr11", 84, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr12", 85, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr13", 86, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr14", 87, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr15", 88, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr16", 89, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr17", 90, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr18", 91, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr19", 92, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr20", 93, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr21", 94, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr22", 95, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr23", 96, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr24", 97, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr25", 98, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr26", 99, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr27", 100, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr28", 101, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr29", 102, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr30", 103, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vr31", 104, 1, NULL, 128, "vec128");
|
|
|
|
|
+ tdesc_create_reg (feature, "vscr", 105, 1, "vector", 32, "int");
|
|
|
|
|
+ tdesc_create_reg (feature, "vrsave", 106, 1, "vector", 32, "int");
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ tdesc_powerpc_cell64l = result;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+}
|
2008-11-20 15:44:10 +00:00
|
|
|
|
--- gdb/features/rs6000/powerpc-cell64l.xml
|
|
|
|
|
+++ gdb/features/rs6000/powerpc-cell64l.xml
|
2008-11-07 14:07:25 +00:00
|
|
|
|
@@ -0,0 +1,19 @@
|
|
|
|
|
+<?xml version="1.0"?>
|
|
|
|
|
+<!-- Copyright (C) 2008 Free Software Foundation, Inc.
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ Copying and distribution of this file, with or without modification,
|
|
|
|
|
+ are permitted in any medium without royalty provided the copyright
|
|
|
|
|
+ notice and this notice are preserved. -->
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+<!-- Cell/B.E. architecture. Identical to the PowerPC 64-bit Linux UISA,
|
|
|
|
|
+ but adds support for the SPU as compatible architecture. -->
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+<!DOCTYPE target SYSTEM "gdb-target.dtd">
|
|
|
|
|
+<target>
|
|
|
|
|
+ <architecture>powerpc:common64</architecture>
|
|
|
|
|
+ <compatible>spu</compatible>
|
|
|
|
|
+ <xi:include href="power64-core.xml"/>
|
|
|
|
|
+ <xi:include href="power-fpu.xml"/>
|
|
|
|
|
+ <xi:include href="power64-linux.xml"/>
|
|
|
|
|
+ <xi:include href="power-altivec.xml"/>
|
|
|
|
|
+</target>
|
2008-11-20 15:44:10 +00:00
|
|
|
|
--- gdb/findvar.c
|
|
|
|
|
+++ gdb/findvar.c
|
2009-01-19 00:46:30 +00:00
|
|
|
|
@@ -309,13 +309,15 @@ value_of_register_lazy (struct frame_inf
|
2008-11-07 14:07:25 +00:00
|
|
|
|
/* Given a pointer of type TYPE in target form in BUF, return the
|
|
|
|
|
address it represents. */
|
|
|
|
|
CORE_ADDR
|
|
|
|
|
-unsigned_pointer_to_address (struct type *type, const gdb_byte *buf)
|
|
|
|
|
+unsigned_pointer_to_address (struct gdbarch *gdbarch,
|
|
|
|
|
+ struct type *type, const gdb_byte *buf)
|
|
|
|
|
{
|
|
|
|
|
return extract_unsigned_integer (buf, TYPE_LENGTH (type));
|
|
|
|
|
}
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
CORE_ADDR
|
|
|
|
|
-signed_pointer_to_address (struct type *type, const gdb_byte *buf)
|
|
|
|
|
+signed_pointer_to_address (struct gdbarch *gdbarch,
|
|
|
|
|
+ struct type *type, const gdb_byte *buf)
|
|
|
|
|
{
|
|
|
|
|
return extract_signed_integer (buf, TYPE_LENGTH (type));
|
|
|
|
|
}
|
2009-01-19 00:46:30 +00:00
|
|
|
|
@@ -323,14 +325,15 @@ signed_pointer_to_address (struct type *
|
2008-11-07 14:07:25 +00:00
|
|
|
|
/* Given an address, store it as a pointer of type TYPE in target
|
|
|
|
|
format in BUF. */
|
|
|
|
|
void
|
|
|
|
|
-unsigned_address_to_pointer (struct type *type, gdb_byte *buf,
|
|
|
|
|
- CORE_ADDR addr)
|
|
|
|
|
+unsigned_address_to_pointer (struct gdbarch *gdbarch, struct type *type,
|
|
|
|
|
+ gdb_byte *buf, CORE_ADDR addr)
|
|
|
|
|
{
|
|
|
|
|
store_unsigned_integer (buf, TYPE_LENGTH (type), addr);
|
|
|
|
|
}
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
|
|
|
|
void
|
2008-11-07 14:07:25 +00:00
|
|
|
|
-address_to_signed_pointer (struct type *type, gdb_byte *buf, CORE_ADDR addr)
|
|
|
|
|
+address_to_signed_pointer (struct gdbarch *gdbarch, struct type *type,
|
|
|
|
|
+ gdb_byte *buf, CORE_ADDR addr)
|
|
|
|
|
{
|
|
|
|
|
store_signed_integer (buf, TYPE_LENGTH (type), addr);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
}
|
2008-11-20 15:44:10 +00:00
|
|
|
|
--- gdb/frame-unwind.c
|
|
|
|
|
+++ gdb/frame-unwind.c
|
2008-11-07 14:07:25 +00:00
|
|
|
|
@@ -126,7 +126,7 @@ default_frame_sniffer (const struct fram
|
|
|
|
|
struct value *
|
|
|
|
|
frame_unwind_got_optimized (struct frame_info *frame, int regnum)
|
|
|
|
|
{
|
|
|
|
|
- struct gdbarch *gdbarch = get_frame_arch (frame);
|
|
|
|
|
+ struct gdbarch *gdbarch = frame_arch_unwind (frame);
|
|
|
|
|
struct value *reg_val;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
reg_val = value_zero (register_type (gdbarch, regnum), not_lval);
|
|
|
|
|
@@ -149,7 +149,7 @@ frame_unwind_got_register (struct frame_
|
|
|
|
|
struct value *
|
|
|
|
|
frame_unwind_got_memory (struct frame_info *frame, int regnum, CORE_ADDR addr)
|
|
|
|
|
{
|
|
|
|
|
- struct gdbarch *gdbarch = get_frame_arch (frame);
|
|
|
|
|
+ struct gdbarch *gdbarch = frame_arch_unwind (frame);
|
|
|
|
|
|
|
|
|
|
return value_at_lazy (register_type (gdbarch, regnum), addr);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
}
|
2008-11-07 14:07:25 +00:00
|
|
|
|
@@ -161,7 +161,7 @@ struct value *
|
|
|
|
|
frame_unwind_got_constant (struct frame_info *frame, int regnum,
|
|
|
|
|
ULONGEST val)
|
|
|
|
|
{
|
|
|
|
|
- struct gdbarch *gdbarch = get_frame_arch (frame);
|
|
|
|
|
+ struct gdbarch *gdbarch = frame_arch_unwind (frame);
|
|
|
|
|
struct value *reg_val;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
reg_val = value_zero (register_type (gdbarch, regnum), not_lval);
|
|
|
|
|
@@ -173,7 +173,7 @@ frame_unwind_got_constant (struct frame_
|
|
|
|
|
struct value *
|
|
|
|
|
frame_unwind_got_bytes (struct frame_info *frame, int regnum, gdb_byte *buf)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
{
|
2008-11-07 14:07:25 +00:00
|
|
|
|
- struct gdbarch *gdbarch = get_frame_arch (frame);
|
|
|
|
|
+ struct gdbarch *gdbarch = frame_arch_unwind (frame);
|
|
|
|
|
struct value *reg_val;
|
|
|
|
|
|
|
|
|
|
reg_val = value_zero (register_type (gdbarch, regnum), not_lval);
|
|
|
|
|
@@ -189,7 +189,7 @@ struct value *
|
|
|
|
|
frame_unwind_got_address (struct frame_info *frame, int regnum,
|
|
|
|
|
CORE_ADDR addr)
|
|
|
|
|
{
|
|
|
|
|
- struct gdbarch *gdbarch = get_frame_arch (frame);
|
|
|
|
|
+ struct gdbarch *gdbarch = frame_arch_unwind (frame);
|
|
|
|
|
struct value *reg_val;
|
|
|
|
|
|
|
|
|
|
reg_val = value_zero (register_type (gdbarch, regnum), not_lval);
|
2008-11-20 15:44:10 +00:00
|
|
|
|
--- gdb/frame-unwind.h
|
|
|
|
|
+++ gdb/frame-unwind.h
|
2008-11-07 14:07:25 +00:00
|
|
|
|
@@ -121,6 +121,13 @@ typedef struct value * (frame_prev_regis
|
|
|
|
|
typedef void (frame_dealloc_cache_ftype) (struct frame_info *self,
|
|
|
|
|
void *this_cache);
|
|
|
|
|
|
|
|
|
|
+/* Assuming the frame chain: (outer) prev <-> this <-> next (inner);
|
|
|
|
|
+ use THIS frame, and implicitly the NEXT frame's register unwind
|
|
|
|
|
+ method, return PREV frame's architecture. */
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+typedef struct gdbarch *(frame_prev_arch_ftype) (struct frame_info *this_frame,
|
|
|
|
|
+ void **this_prologue_cache);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
struct frame_unwind
|
|
|
|
|
{
|
|
|
|
|
/* The frame's type. Should this instead be a collection of
|
|
|
|
|
@@ -133,6 +140,7 @@ struct frame_unwind
|
|
|
|
|
const struct frame_data *unwind_data;
|
|
|
|
|
frame_sniffer_ftype *sniffer;
|
|
|
|
|
frame_dealloc_cache_ftype *dealloc_cache;
|
|
|
|
|
+ frame_prev_arch_ftype *prev_arch;
|
|
|
|
|
};
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
/* Register a frame unwinder, _prepending_ it to the front of the
|
2008-11-20 15:44:10 +00:00
|
|
|
|
--- gdb/frame.c
|
|
|
|
|
+++ gdb/frame.c
|
2008-11-07 14:07:25 +00:00
|
|
|
|
@@ -41,6 +41,7 @@
|
|
|
|
|
#include "objfiles.h"
|
|
|
|
|
#include "exceptions.h"
|
|
|
|
|
#include "gdbthread.h"
|
|
|
|
|
+#include "arch-utils.h"
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
static struct frame_info *get_prev_frame_1 (struct frame_info *this_frame);
|
|
|
|
|
|
|
|
|
|
@@ -75,6 +76,13 @@ struct frame_info
|
|
|
|
|
void *prologue_cache;
|
|
|
|
|
const struct frame_unwind *unwind;
|
|
|
|
|
|
|
|
|
|
+ /* Cached copy of the previous frame's architecture. */
|
|
|
|
|
+ struct
|
|
|
|
|
+ {
|
|
|
|
|
+ int p;
|
|
|
|
|
+ struct gdbarch *arch;
|
|
|
|
|
+ } prev_arch;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
/* Cached copy of the previous frame's resume address. */
|
|
|
|
|
struct {
|
|
|
|
|
int p;
|
|
|
|
|
@@ -190,6 +198,9 @@ fprint_frame_type (struct ui_file *file,
|
|
|
|
|
case SIGTRAMP_FRAME:
|
|
|
|
|
fprintf_unfiltered (file, "SIGTRAMP_FRAME");
|
|
|
|
|
return;
|
|
|
|
|
+ case ARCH_FRAME:
|
|
|
|
|
+ fprintf_unfiltered (file, "ARCH_FRAME");
|
|
|
|
|
+ return;
|
|
|
|
|
default:
|
|
|
|
|
fprintf_unfiltered (file, "<unknown type>");
|
|
|
|
|
return;
|
|
|
|
|
@@ -251,6 +262,9 @@ get_frame_id (struct frame_info *fi)
|
|
|
|
|
}
|
|
|
|
|
if (!fi->this_id.p)
|
|
|
|
|
{
|
|
|
|
|
+ struct cleanup *old_chain = save_current_gdbarch ();
|
|
|
|
|
+ current_gdbarch = get_frame_arch (fi);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
if (frame_debug)
|
|
|
|
|
fprintf_unfiltered (gdb_stdlog, "{ get_frame_id (fi=%d) ",
|
|
|
|
|
fi->level);
|
|
|
|
|
@@ -266,6 +280,8 @@ get_frame_id (struct frame_info *fi)
|
|
|
|
|
fprint_frame_id (gdb_stdlog, fi->this_id.value);
|
|
|
|
|
fprintf_unfiltered (gdb_stdlog, " }\n");
|
|
|
|
|
}
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ do_cleanups (old_chain);
|
|
|
|
|
}
|
|
|
|
|
return fi->this_id.value;
|
|
|
|
|
}
|
|
|
|
|
@@ -459,7 +475,7 @@ frame_pc_unwind (struct frame_info *this
|
|
|
|
|
if (!this_frame->prev_pc.p)
|
|
|
|
|
{
|
|
|
|
|
CORE_ADDR pc;
|
|
|
|
|
- if (gdbarch_unwind_pc_p (get_frame_arch (this_frame)))
|
|
|
|
|
+ if (gdbarch_unwind_pc_p (frame_arch_unwind (this_frame)))
|
|
|
|
|
{
|
|
|
|
|
/* The right way. The `pure' way. The one true way. This
|
|
|
|
|
method depends solely on the register-unwind code to
|
|
|
|
|
@@ -477,7 +493,7 @@ frame_pc_unwind (struct frame_info *this
|
|
|
|
|
frame. This is all in stark contrast to the old
|
|
|
|
|
FRAME_SAVED_PC which would try to directly handle all the
|
|
|
|
|
different ways that a PC could be unwound. */
|
|
|
|
|
- pc = gdbarch_unwind_pc (get_frame_arch (this_frame), this_frame);
|
|
|
|
|
+ pc = gdbarch_unwind_pc (frame_arch_unwind (this_frame), this_frame);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
}
|
|
|
|
|
else
|
2008-11-07 14:07:25 +00:00
|
|
|
|
internal_error (__FILE__, __LINE__, _("No unwind_pc method"));
|
|
|
|
|
@@ -647,19 +663,24 @@ get_frame_register (struct frame_info *f
|
|
|
|
|
struct value *
|
|
|
|
|
frame_unwind_register_value (struct frame_info *frame, int regnum)
|
|
|
|
|
{
|
|
|
|
|
+ struct gdbarch *gdbarch;
|
|
|
|
|
struct value *value;
|
|
|
|
|
+ struct cleanup *old_chain;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
gdb_assert (frame != NULL);
|
|
|
|
|
+ gdbarch = frame_arch_unwind (frame);
|
|
|
|
|
|
|
|
|
|
if (frame_debug)
|
|
|
|
|
{
|
|
|
|
|
fprintf_unfiltered (gdb_stdlog, "\
|
|
|
|
|
{ frame_unwind_register_value (frame=%d,regnum=%d(%s),...) ",
|
|
|
|
|
frame->level, regnum,
|
|
|
|
|
- user_reg_map_regnum_to_name
|
|
|
|
|
- (get_frame_arch (frame), regnum));
|
|
|
|
|
+ user_reg_map_regnum_to_name (gdbarch, regnum));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+ old_chain = save_current_gdbarch ();
|
|
|
|
|
+ current_gdbarch = gdbarch;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
/* Find the unwinder. */
|
|
|
|
|
if (frame->unwind == NULL)
|
|
|
|
|
frame->unwind = frame_unwind_find_by_frame (frame, &frame->prologue_cache);
|
|
|
|
|
@@ -692,7 +713,7 @@ frame_unwind_register_value (struct fram
|
|
|
|
|
|
|
|
|
|
fprintf_unfiltered (gdb_stdlog, " bytes=");
|
|
|
|
|
fprintf_unfiltered (gdb_stdlog, "[");
|
|
|
|
|
- for (i = 0; i < register_size (get_frame_arch (frame), regnum); i++)
|
|
|
|
|
+ for (i = 0; i < register_size (gdbarch, regnum); i++)
|
|
|
|
|
fprintf_unfiltered (gdb_stdlog, "%02x", buf[i]);
|
|
|
|
|
fprintf_unfiltered (gdb_stdlog, "]");
|
|
|
|
|
}
|
|
|
|
|
@@ -701,6 +722,7 @@ frame_unwind_register_value (struct fram
|
|
|
|
|
fprintf_unfiltered (gdb_stdlog, " }\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+ do_cleanups (old_chain);
|
|
|
|
|
return value;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -715,7 +737,7 @@ frame_unwind_register_signed (struct fra
|
2008-09-12 23:16:14 +00:00
|
|
|
|
{
|
2008-11-07 14:07:25 +00:00
|
|
|
|
gdb_byte buf[MAX_REGISTER_SIZE];
|
|
|
|
|
frame_unwind_register (frame, regnum, buf);
|
|
|
|
|
- return extract_signed_integer (buf, register_size (get_frame_arch (frame),
|
|
|
|
|
+ return extract_signed_integer (buf, register_size (frame_arch_unwind (frame),
|
|
|
|
|
regnum));
|
|
|
|
|
}
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
@@ -730,7 +752,7 @@ frame_unwind_register_unsigned (struct f
|
|
|
|
|
{
|
|
|
|
|
gdb_byte buf[MAX_REGISTER_SIZE];
|
|
|
|
|
frame_unwind_register (frame, regnum, buf);
|
|
|
|
|
- return extract_unsigned_integer (buf, register_size (get_frame_arch (frame),
|
|
|
|
|
+ return extract_unsigned_integer (buf, register_size (frame_arch_unwind (frame),
|
|
|
|
|
regnum));
|
2008-09-12 23:16:14 +00:00
|
|
|
|
}
|
2008-11-07 14:07:25 +00:00
|
|
|
|
|
|
|
|
|
@@ -1067,6 +1089,8 @@ select_frame (struct frame_info *fi)
|
|
|
|
|
source language of this frame, and switch to it if desired. */
|
|
|
|
|
if (fi)
|
|
|
|
|
{
|
|
|
|
|
+ current_gdbarch = get_frame_arch (fi);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
/* We retrieve the frame's symtab by using the frame PC. However
|
|
|
|
|
we cannot use the frame PC as-is, because it usually points to
|
|
|
|
|
the instruction following the "call", which is sometimes the
|
2009-01-19 00:46:30 +00:00
|
|
|
|
@@ -1721,9 +1745,17 @@ enum frame_type
|
2008-11-07 14:07:25 +00:00
|
|
|
|
get_frame_type (struct frame_info *frame)
|
|
|
|
|
{
|
|
|
|
|
if (frame->unwind == NULL)
|
|
|
|
|
- /* Initialize the frame's unwinder because that's what
|
|
|
|
|
- provides the frame's type. */
|
|
|
|
|
- frame->unwind = frame_unwind_find_by_frame (frame, &frame->prologue_cache);
|
|
|
|
|
+ {
|
|
|
|
|
+ struct cleanup *old_chain = save_current_gdbarch ();
|
|
|
|
|
+ current_gdbarch = get_frame_arch (frame);
|
|
|
|
|
+
|
|
|
|
|
+ /* Initialize the frame's unwinder because that's what
|
|
|
|
|
+ provides the frame's type. */
|
|
|
|
|
+ frame->unwind = frame_unwind_find_by_frame (frame,
|
|
|
|
|
+ &frame->prologue_cache);
|
|
|
|
|
+ do_cleanups (old_chain);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
return frame->unwind->type;
|
|
|
|
|
}
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2009-01-19 00:46:30 +00:00
|
|
|
|
@@ -1790,17 +1822,48 @@ safe_frame_unwind_memory (struct frame_i
|
2008-11-07 14:07:25 +00:00
|
|
|
|
return !target_read_memory (addr, buf, len);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
}
|
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
-/* Architecture method. */
|
|
|
|
|
+/* Architecture methods. */
|
|
|
|
|
|
|
|
|
|
struct gdbarch *
|
|
|
|
|
get_frame_arch (struct frame_info *this_frame)
|
|
|
|
|
{
|
2009-01-19 00:46:30 +00:00
|
|
|
|
- /* In the future, this function will return a per-frame
|
|
|
|
|
- architecture instead of current_gdbarch. Calling the
|
|
|
|
|
- routine with a NULL value of this_frame is a bug! */
|
|
|
|
|
- gdb_assert (this_frame);
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ return frame_arch_unwind (this_frame->next);
|
|
|
|
|
+}
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+struct gdbarch *
|
|
|
|
|
+frame_arch_unwind (struct frame_info *next_frame)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+{
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ if (!next_frame->prev_arch.p)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+ {
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ struct gdbarch *arch;
|
|
|
|
|
+ struct cleanup *old_chain = save_current_gdbarch ();
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ if (next_frame->level >= 0)
|
|
|
|
|
+ current_gdbarch = get_frame_arch (next_frame);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ if (next_frame->unwind == NULL)
|
|
|
|
|
+ next_frame->unwind
|
|
|
|
|
+ = frame_unwind_find_by_frame (next_frame,
|
|
|
|
|
+ &next_frame->prologue_cache);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ if (next_frame->unwind->prev_arch != NULL)
|
|
|
|
|
+ arch = next_frame->unwind->prev_arch (next_frame,
|
|
|
|
|
+ &next_frame->prologue_cache);
|
|
|
|
|
+ else
|
|
|
|
|
+ arch = get_frame_arch (next_frame);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ next_frame->prev_arch.arch = arch;
|
|
|
|
|
+ next_frame->prev_arch.p = 1;
|
|
|
|
|
+ if (frame_debug)
|
|
|
|
|
+ fprintf_unfiltered (gdb_stdlog,
|
|
|
|
|
+ "{ frame_arch_unwind (next_frame=%d) -> %s }\n",
|
|
|
|
|
+ next_frame->level,
|
|
|
|
|
+ gdbarch_bfd_arch_info (arch)->printable_name);
|
|
|
|
|
+
|
|
|
|
|
+ do_cleanups (old_chain);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+ }
|
2009-01-19 00:46:30 +00:00
|
|
|
|
|
|
|
|
|
- return current_gdbarch;
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ return next_frame->prev_arch.arch;
|
|
|
|
|
}
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
/* Stack pointer methods. */
|
2008-11-20 15:44:10 +00:00
|
|
|
|
--- gdb/frame.h
|
|
|
|
|
+++ gdb/frame.h
|
2008-11-07 14:07:25 +00:00
|
|
|
|
@@ -180,6 +180,8 @@ enum frame_type
|
|
|
|
|
/* In a signal handler, various OSs handle this in various ways.
|
|
|
|
|
The main thing is that the frame may be far from normal. */
|
|
|
|
|
SIGTRAMP_FRAME,
|
|
|
|
|
+ /* Fake frame representing a cross-architecture call. */
|
|
|
|
|
+ ARCH_FRAME,
|
|
|
|
|
/* Sentinel or registers frame. This frame obtains register values
|
|
|
|
|
direct from the inferior's registers. */
|
|
|
|
|
SENTINEL_FRAME
|
|
|
|
|
@@ -518,6 +520,7 @@ extern int safe_frame_unwind_memory (str
|
|
|
|
|
/* Return this frame's architecture. */
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
extern struct gdbarch *get_frame_arch (struct frame_info *this_frame);
|
|
|
|
|
+extern struct gdbarch *frame_arch_unwind (struct frame_info *next_frame);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
/* Values for the source flag to be used in print_frame_info_base(). */
|
2008-11-20 15:44:10 +00:00
|
|
|
|
--- gdb/gcore.c
|
|
|
|
|
+++ gdb/gcore.c
|
2008-11-07 14:07:25 +00:00
|
|
|
|
@@ -35,7 +35,7 @@
|
|
|
|
|
generate-core-file for programs with large resident data. */
|
|
|
|
|
#define MAX_COPY_BYTES (1024 * 1024)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
-static char *default_gcore_target (void);
|
|
|
|
|
+static const char *default_gcore_target (void);
|
|
|
|
|
static enum bfd_architecture default_gcore_arch (void);
|
|
|
|
|
static unsigned long default_gcore_mach (void);
|
|
|
|
|
static int gcore_memory_sections (bfd *);
|
|
|
|
|
@@ -125,7 +125,7 @@ default_gcore_mach (void)
|
|
|
|
|
return 0;
|
|
|
|
|
#else
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
- const struct bfd_arch_info *bfdarch = gdbarch_bfd_arch_info (current_gdbarch);
|
|
|
|
|
+ const struct bfd_arch_info *bfdarch = gdbarch_bfd_arch_info (target_gdbarch);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
if (bfdarch != NULL)
|
|
|
|
|
return bfdarch->mach;
|
|
|
|
|
@@ -139,8 +139,7 @@ default_gcore_mach (void)
|
|
|
|
|
static enum bfd_architecture
|
|
|
|
|
default_gcore_arch (void)
|
|
|
|
|
{
|
|
|
|
|
- const struct bfd_arch_info * bfdarch = gdbarch_bfd_arch_info
|
|
|
|
|
- (current_gdbarch);
|
|
|
|
|
+ const struct bfd_arch_info *bfdarch = gdbarch_bfd_arch_info (target_gdbarch);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
if (bfdarch != NULL)
|
|
|
|
|
return bfdarch->arch;
|
|
|
|
|
@@ -150,10 +149,15 @@ default_gcore_arch (void)
|
|
|
|
|
return bfd_get_arch (exec_bfd);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
-static char *
|
|
|
|
|
+static const char *
|
|
|
|
|
default_gcore_target (void)
|
|
|
|
|
{
|
|
|
|
|
- /* FIXME: This may only work for ELF targets. */
|
|
|
|
|
+ /* The gdbarch may define a target to use for core files. */
|
|
|
|
|
+ if (gdbarch_gcore_bfd_target_p (target_gdbarch))
|
|
|
|
|
+ return gdbarch_gcore_bfd_target (target_gdbarch);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* Otherwise, try to fall back to the exec_bfd target. This will probably
|
|
|
|
|
+ not work for non-ELF targets. */
|
|
|
|
|
if (exec_bfd == NULL)
|
|
|
|
|
return NULL;
|
|
|
|
|
else
|
2008-11-20 15:44:10 +00:00
|
|
|
|
--- gdb/gdbarch.c
|
|
|
|
|
+++ gdb/gdbarch.c
|
2008-11-07 14:07:25 +00:00
|
|
|
|
@@ -225,6 +225,7 @@ struct gdbarch
|
|
|
|
|
gdbarch_regset_from_core_section_ftype *regset_from_core_section;
|
|
|
|
|
struct core_regset_section * core_regset_sections;
|
|
|
|
|
gdbarch_core_xfer_shared_libraries_ftype *core_xfer_shared_libraries;
|
|
|
|
|
+ const char * gcore_bfd_target;
|
|
|
|
|
int vtable_function_descriptors;
|
|
|
|
|
int vbit_in_delta;
|
|
|
|
|
gdbarch_skip_permanent_breakpoint_ftype *skip_permanent_breakpoint;
|
|
|
|
|
@@ -312,8 +313,8 @@ struct gdbarch startup_gdbarch =
|
|
|
|
|
0, /* register_to_value */
|
|
|
|
|
0, /* value_to_register */
|
|
|
|
|
0, /* value_from_register */
|
|
|
|
|
- 0, /* pointer_to_address */
|
|
|
|
|
- 0, /* address_to_pointer */
|
|
|
|
|
+ unsigned_pointer_to_address, /* pointer_to_address */
|
|
|
|
|
+ unsigned_address_to_pointer, /* address_to_pointer */
|
|
|
|
|
0, /* integer_to_address */
|
|
|
|
|
0, /* return_value */
|
|
|
|
|
0, /* skip_prologue */
|
|
|
|
|
@@ -357,6 +358,7 @@ struct gdbarch startup_gdbarch =
|
|
|
|
|
0, /* regset_from_core_section */
|
|
|
|
|
0, /* core_regset_sections */
|
|
|
|
|
0, /* core_xfer_shared_libraries */
|
|
|
|
|
+ 0, /* gcore_bfd_target */
|
|
|
|
|
0, /* vtable_function_descriptors */
|
|
|
|
|
0, /* vbit_in_delta */
|
|
|
|
|
0, /* skip_permanent_breakpoint */
|
|
|
|
|
@@ -608,6 +610,7 @@ verify_gdbarch (struct gdbarch *gdbarch)
|
|
|
|
|
/* Skip verify of fetch_pointer_argument, has predicate */
|
|
|
|
|
/* Skip verify of regset_from_core_section, has predicate */
|
|
|
|
|
/* Skip verify of core_xfer_shared_libraries, has predicate */
|
|
|
|
|
+ /* Skip verify of gcore_bfd_target, has predicate */
|
|
|
|
|
/* Skip verify of vtable_function_descriptors, invalid_p == 0 */
|
|
|
|
|
/* Skip verify of vbit_in_delta, invalid_p == 0 */
|
|
|
|
|
/* Skip verify of skip_permanent_breakpoint, has predicate */
|
|
|
|
|
@@ -829,6 +832,12 @@ gdbarch_dump (struct gdbarch *gdbarch, s
|
|
|
|
|
"gdbarch_dump: frame_red_zone_size = %s\n",
|
|
|
|
|
plongest (gdbarch->frame_red_zone_size));
|
|
|
|
|
fprintf_unfiltered (file,
|
|
|
|
|
+ "gdbarch_dump: gdbarch_gcore_bfd_target_p() = %d\n",
|
|
|
|
|
+ gdbarch_gcore_bfd_target_p (gdbarch));
|
|
|
|
|
+ fprintf_unfiltered (file,
|
|
|
|
|
+ "gdbarch_dump: gcore_bfd_target = %s\n",
|
|
|
|
|
+ gdbarch->gcore_bfd_target);
|
|
|
|
|
+ fprintf_unfiltered (file,
|
|
|
|
|
"gdbarch_dump: gdbarch_get_longjmp_target_p() = %d\n",
|
|
|
|
|
gdbarch_get_longjmp_target_p (gdbarch));
|
|
|
|
|
fprintf_unfiltered (file,
|
|
|
|
|
@@ -2055,7 +2064,7 @@ gdbarch_pointer_to_address (struct gdbar
|
|
|
|
|
gdb_assert (gdbarch->pointer_to_address != NULL);
|
|
|
|
|
if (gdbarch_debug >= 2)
|
|
|
|
|
fprintf_unfiltered (gdb_stdlog, "gdbarch_pointer_to_address called\n");
|
|
|
|
|
- return gdbarch->pointer_to_address (type, buf);
|
|
|
|
|
+ return gdbarch->pointer_to_address (gdbarch, type, buf);
|
|
|
|
|
}
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
void
|
|
|
|
|
@@ -2072,7 +2081,7 @@ gdbarch_address_to_pointer (struct gdbar
|
|
|
|
|
gdb_assert (gdbarch->address_to_pointer != NULL);
|
|
|
|
|
if (gdbarch_debug >= 2)
|
|
|
|
|
fprintf_unfiltered (gdb_stdlog, "gdbarch_address_to_pointer called\n");
|
|
|
|
|
- gdbarch->address_to_pointer (type, buf, addr);
|
|
|
|
|
+ gdbarch->address_to_pointer (gdbarch, type, buf, addr);
|
|
|
|
|
}
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
void
|
|
|
|
|
@@ -2931,6 +2940,31 @@ set_gdbarch_core_xfer_shared_libraries (
|
|
|
|
|
}
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
int
|
|
|
|
|
+gdbarch_gcore_bfd_target_p (struct gdbarch *gdbarch)
|
|
|
|
|
+{
|
|
|
|
|
+ gdb_assert (gdbarch != NULL);
|
|
|
|
|
+ return gdbarch->gcore_bfd_target != 0;
|
|
|
|
|
+}
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+const char *
|
|
|
|
|
+gdbarch_gcore_bfd_target (struct gdbarch *gdbarch)
|
|
|
|
|
+{
|
|
|
|
|
+ gdb_assert (gdbarch != NULL);
|
|
|
|
|
+ /* Check variable changed from pre-default. */
|
|
|
|
|
+ gdb_assert (gdbarch->gcore_bfd_target != 0);
|
|
|
|
|
+ if (gdbarch_debug >= 2)
|
|
|
|
|
+ fprintf_unfiltered (gdb_stdlog, "gdbarch_gcore_bfd_target called\n");
|
|
|
|
|
+ return gdbarch->gcore_bfd_target;
|
|
|
|
|
+}
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
|
|
|
|
+void
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+set_gdbarch_gcore_bfd_target (struct gdbarch *gdbarch,
|
|
|
|
|
+ const char * gcore_bfd_target)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+{
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ gdbarch->gcore_bfd_target = gcore_bfd_target;
|
|
|
|
|
+}
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+int
|
|
|
|
|
gdbarch_vtable_function_descriptors (struct gdbarch *gdbarch)
|
|
|
|
|
{
|
|
|
|
|
gdb_assert (gdbarch != NULL);
|
|
|
|
|
@@ -3367,10 +3401,15 @@ gdbarch_data (struct gdbarch *gdbarch, s
|
|
|
|
|
(as all fields are valid), but be careful to also detect
|
|
|
|
|
recursive references. */
|
|
|
|
|
{
|
|
|
|
|
+ struct cleanup *old_chain = save_current_gdbarch ();
|
|
|
|
|
+ current_gdbarch = gdbarch;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
gdb_assert (data->init_p);
|
|
|
|
|
data->init_p = 0;
|
|
|
|
|
gdbarch->data[data->index] = data->post_init (gdbarch);
|
|
|
|
|
data->init_p = 1;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ do_cleanups (old_chain);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
/* The architecture initialization hasn't completed - punt -
|
2008-11-20 15:44:10 +00:00
|
|
|
|
--- gdb/gdbarch.h
|
|
|
|
|
+++ gdb/gdbarch.h
|
2008-11-07 14:07:25 +00:00
|
|
|
|
@@ -348,11 +348,11 @@ typedef struct value * (gdbarch_value_fr
|
|
|
|
|
extern struct value * gdbarch_value_from_register (struct gdbarch *gdbarch, struct type *type, int regnum, struct frame_info *frame);
|
|
|
|
|
extern void set_gdbarch_value_from_register (struct gdbarch *gdbarch, gdbarch_value_from_register_ftype *value_from_register);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
-typedef CORE_ADDR (gdbarch_pointer_to_address_ftype) (struct type *type, const gdb_byte *buf);
|
|
|
|
|
+typedef CORE_ADDR (gdbarch_pointer_to_address_ftype) (struct gdbarch *gdbarch, struct type *type, const gdb_byte *buf);
|
|
|
|
|
extern CORE_ADDR gdbarch_pointer_to_address (struct gdbarch *gdbarch, struct type *type, const gdb_byte *buf);
|
|
|
|
|
extern void set_gdbarch_pointer_to_address (struct gdbarch *gdbarch, gdbarch_pointer_to_address_ftype *pointer_to_address);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
-typedef void (gdbarch_address_to_pointer_ftype) (struct type *type, gdb_byte *buf, CORE_ADDR addr);
|
|
|
|
|
+typedef void (gdbarch_address_to_pointer_ftype) (struct gdbarch *gdbarch, struct type *type, gdb_byte *buf, CORE_ADDR addr);
|
|
|
|
|
extern void gdbarch_address_to_pointer (struct gdbarch *gdbarch, struct type *type, gdb_byte *buf, CORE_ADDR addr);
|
|
|
|
|
extern void set_gdbarch_address_to_pointer (struct gdbarch *gdbarch, gdbarch_address_to_pointer_ftype *address_to_pointer);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
@@ -652,6 +652,13 @@ typedef LONGEST (gdbarch_core_xfer_share
|
|
|
|
|
extern LONGEST gdbarch_core_xfer_shared_libraries (struct gdbarch *gdbarch, gdb_byte *readbuf, ULONGEST offset, LONGEST len);
|
|
|
|
|
extern void set_gdbarch_core_xfer_shared_libraries (struct gdbarch *gdbarch, gdbarch_core_xfer_shared_libraries_ftype *core_xfer_shared_libraries);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+/* BFD target to use when generating a core file. */
|
|
|
|
|
+
|
|
|
|
|
+extern int gdbarch_gcore_bfd_target_p (struct gdbarch *gdbarch);
|
|
|
|
|
+
|
|
|
|
|
+extern const char * gdbarch_gcore_bfd_target (struct gdbarch *gdbarch);
|
|
|
|
|
+extern void set_gdbarch_gcore_bfd_target (struct gdbarch *gdbarch, const char * gcore_bfd_target);
|
|
|
|
|
+
|
|
|
|
|
/* If the elements of C++ vtables are in-place function descriptors rather
|
|
|
|
|
than normal function pointers (which may point to code or a descriptor),
|
|
|
|
|
set this to one. */
|
2008-11-20 15:44:10 +00:00
|
|
|
|
--- gdb/gdbarch.sh
|
|
|
|
|
+++ gdb/gdbarch.sh
|
2008-11-07 14:07:25 +00:00
|
|
|
|
@@ -466,8 +466,8 @@ f:void:value_to_register:struct frame_in
|
|
|
|
|
# (but not the value contents) filled in.
|
|
|
|
|
f:struct value *:value_from_register:struct type *type, int regnum, struct frame_info *frame:type, regnum, frame::default_value_from_register::0
|
|
|
|
|
#
|
|
|
|
|
-f:CORE_ADDR:pointer_to_address:struct type *type, const gdb_byte *buf:type, buf::unsigned_pointer_to_address::0
|
|
|
|
|
-f:void:address_to_pointer:struct type *type, gdb_byte *buf, CORE_ADDR addr:type, buf, addr::unsigned_address_to_pointer::0
|
|
|
|
|
+m:CORE_ADDR:pointer_to_address:struct type *type, const gdb_byte *buf:type, buf::unsigned_pointer_to_address::0
|
|
|
|
|
+m:void:address_to_pointer:struct type *type, gdb_byte *buf, CORE_ADDR addr:type, buf, addr::unsigned_address_to_pointer::0
|
|
|
|
|
M:CORE_ADDR:integer_to_address:struct type *type, const gdb_byte *buf:type, buf
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
# Return the return-value convention that will be used by FUNCTYPE
|
|
|
|
|
@@ -607,6 +607,9 @@ v:struct core_regset_section *:core_regs
|
|
|
|
|
# core file into buffer READBUF with length LEN.
|
|
|
|
|
M:LONGEST:core_xfer_shared_libraries:gdb_byte *readbuf, ULONGEST offset, LONGEST len:readbuf, offset, len
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+# BFD target to use when generating a core file.
|
|
|
|
|
+V:const char *:gcore_bfd_target:::0:0:::gdbarch->gcore_bfd_target
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
# If the elements of C++ vtables are in-place function descriptors rather
|
|
|
|
|
# than normal function pointers (which may point to code or a descriptor),
|
|
|
|
|
# set this to one.
|
2008-11-20 15:44:10 +00:00
|
|
|
|
@@ -1731,10 +1734,15 @@ gdbarch_data (struct gdbarch *gdbarch, s
|
2008-11-07 14:07:25 +00:00
|
|
|
|
(as all fields are valid), but be careful to also detect
|
|
|
|
|
recursive references. */
|
|
|
|
|
{
|
|
|
|
|
+ struct cleanup *old_chain = save_current_gdbarch ();
|
|
|
|
|
+ current_gdbarch = gdbarch;
|
|
|
|
|
+
|
|
|
|
|
gdb_assert (data->init_p);
|
|
|
|
|
data->init_p = 0;
|
|
|
|
|
gdbarch->data[data->index] = data->post_init (gdbarch);
|
|
|
|
|
data->init_p = 1;
|
|
|
|
|
+
|
|
|
|
|
+ do_cleanups (old_chain);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
/* The architecture initialization hasn't completed - punt -
|
2008-11-20 15:44:10 +00:00
|
|
|
|
--- gdb/gdbserver/Makefile.in
|
|
|
|
|
+++ gdb/gdbserver/Makefile.in
|
2009-01-19 00:46:30 +00:00
|
|
|
|
@@ -207,8 +207,8 @@ clean:
|
2008-11-07 14:07:25 +00:00
|
|
|
|
rm -f reg-cris.c reg-crisv32.c reg-x86-64-linux.c reg-xtensa.c
|
|
|
|
|
rm -f arm-with-iwmmxt.c mips-linux.c mips64-linux.c
|
|
|
|
|
rm -f powerpc-32l.c powerpc-64l.c powerpc-e500l.c
|
|
|
|
|
- rm -f powerpc-altivec32l.c powerpc-vsx32l.c powerpc-altivec64l.c
|
2008-11-20 15:44:10 +00:00
|
|
|
|
- rm -f powerpc-vsx64l.c
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ rm -f powerpc-altivec32l.c powerpc-cell32l.c powerpc-vsx32l.c
|
|
|
|
|
+ rm -f powerpc-altivec64l.c powerpc-cell64l.c powerpc-vsx64l.c
|
2008-11-20 15:44:10 +00:00
|
|
|
|
rm -f powerpc-isa205-32l.c powerpc-isa205-64l.c
|
|
|
|
|
rm -f powerpc-isa205-altivec32l.c powerpc-isa205-vsx32l.c powerpc-isa205-altivec64l.c
|
|
|
|
|
rm -f powerpc-isa205-vsx64l.c
|
2009-01-19 00:46:30 +00:00
|
|
|
|
@@ -356,6 +356,9 @@ powerpc-32l.c : $(srcdir)/../regformats/
|
2008-11-07 14:07:25 +00:00
|
|
|
|
powerpc-altivec32l.o : powerpc-altivec32l.c $(regdef_h)
|
|
|
|
|
powerpc-altivec32l.c : $(srcdir)/../regformats/rs6000/powerpc-altivec32l.dat $(regdat_sh)
|
|
|
|
|
$(SHELL) $(regdat_sh) $(srcdir)/../regformats/rs6000/powerpc-altivec32l.dat powerpc-altivec32l.c
|
|
|
|
|
+powerpc-cell32l.o : powerpc-cell32l.c $(regdef_h)
|
|
|
|
|
+powerpc-cell32l.c : $(srcdir)/../regformats/rs6000/powerpc-cell32l.dat $(regdat_sh)
|
|
|
|
|
+ $(SHELL) $(regdat_sh) $(srcdir)/../regformats/rs6000/powerpc-cell32l.dat powerpc-cell32l.c
|
|
|
|
|
powerpc-vsx32l.o : powerpc-vsx32l.c $(regdef_h)
|
|
|
|
|
powerpc-vsx32l.c : $(srcdir)/../regformats/rs6000/powerpc-vsx32l.dat $(regdat_sh)
|
|
|
|
|
$(SHELL) $(regdat_sh) $(srcdir)/../regformats/rs6000/powerpc-vsx32l.dat powerpc-vsx32l.c
|
2009-01-19 00:46:30 +00:00
|
|
|
|
@@ -377,6 +380,9 @@ powerpc-64l.c : $(srcdir)/../regformats/
|
2008-11-07 14:07:25 +00:00
|
|
|
|
powerpc-altivec64l.o : powerpc-altivec64l.c $(regdef_h)
|
|
|
|
|
powerpc-altivec64l.c : $(srcdir)/../regformats/rs6000/powerpc-altivec64l.dat $(regdat_sh)
|
|
|
|
|
$(SHELL) $(regdat_sh) $(srcdir)/../regformats/rs6000/powerpc-altivec64l.dat powerpc-altivec64l.c
|
|
|
|
|
+powerpc-cell64l.o : powerpc-cell64l.c $(regdef_h)
|
|
|
|
|
+powerpc-cell64l.c : $(srcdir)/../regformats/rs6000/powerpc-cell64l.dat $(regdat_sh)
|
|
|
|
|
+ $(SHELL) $(regdat_sh) $(srcdir)/../regformats/rs6000/powerpc-cell64l.dat powerpc-cell64l.c
|
|
|
|
|
powerpc-vsx64l.o : powerpc-vsx64l.c $(regdef_h)
|
|
|
|
|
powerpc-vsx64l.c : $(srcdir)/../regformats/rs6000/powerpc-vsx64l.dat $(regdat_sh)
|
|
|
|
|
$(SHELL) $(regdat_sh) $(srcdir)/../regformats/rs6000/powerpc-vsx64l.dat powerpc-vsx64l.c
|
2008-11-20 15:44:10 +00:00
|
|
|
|
--- gdb/gdbserver/configure.srv
|
|
|
|
|
+++ gdb/gdbserver/configure.srv
|
|
|
|
|
@@ -102,6 +102,7 @@ case "${target}" in
|
2008-11-07 14:07:25 +00:00
|
|
|
|
;;
|
|
|
|
|
powerpc*-*-linux*) srv_regobj="powerpc-32l.o"
|
|
|
|
|
srv_regobj="${srv_regobj} powerpc-altivec32l.o"
|
|
|
|
|
+ srv_regobj="${srv_regobj} powerpc-cell32l.o"
|
|
|
|
|
srv_regobj="${srv_regobj} powerpc-vsx32l.o"
|
2008-11-20 15:44:10 +00:00
|
|
|
|
srv_regobj="${srv_regobj} powerpc-isa205-32l.o"
|
|
|
|
|
srv_regobj="${srv_regobj} powerpc-isa205-altivec32l.o"
|
|
|
|
|
@@ -109,6 +110,7 @@ case "${target}" in
|
2008-11-07 14:07:25 +00:00
|
|
|
|
srv_regobj="${srv_regobj} powerpc-e500l.o"
|
|
|
|
|
srv_regobj="${srv_regobj} powerpc-64l.o"
|
|
|
|
|
srv_regobj="${srv_regobj} powerpc-altivec64l.o"
|
|
|
|
|
+ srv_regobj="${srv_regobj} powerpc-cell64l.o"
|
|
|
|
|
srv_regobj="${srv_regobj} powerpc-vsx64l.o"
|
2008-11-20 15:44:10 +00:00
|
|
|
|
srv_regobj="${srv_regobj} powerpc-isa205-64l.o"
|
|
|
|
|
srv_regobj="${srv_regobj} powerpc-isa205-altivec64l.o"
|
2009-02-03 21:49:21 +00:00
|
|
|
|
@@ -116,6 +118,7 @@ case "${target}" in
|
|
|
|
|
srv_tgtobj="linux-low.o linux-ppc-low.o"
|
|
|
|
|
srv_xmlfiles="rs6000/powerpc-32l.xml"
|
|
|
|
|
srv_xmlfiles="${srv_xmlfiles} rs6000/powerpc-altivec32l.xml"
|
|
|
|
|
+ srv_xmlfiles="${srv_xmlfiles} rs6000/powerpc-cell32l.xml"
|
|
|
|
|
srv_xmlfiles="${srv_xmlfiles} rs6000/powerpc-vsx32l.xml"
|
|
|
|
|
srv_xmlfiles="${srv_xmlfiles} rs6000/powerpc-isa205-32l.xml"
|
|
|
|
|
srv_xmlfiles="${srv_xmlfiles} rs6000/powerpc-isa205-altivec32l.xml"
|
|
|
|
|
@@ -130,6 +133,7 @@ case "${target}" in
|
2008-11-07 14:07:25 +00:00
|
|
|
|
srv_xmlfiles="${srv_xmlfiles} rs6000/power-spe.xml"
|
|
|
|
|
srv_xmlfiles="${srv_xmlfiles} rs6000/powerpc-64l.xml"
|
|
|
|
|
srv_xmlfiles="${srv_xmlfiles} rs6000/powerpc-altivec64l.xml"
|
|
|
|
|
+ srv_xmlfiles="${srv_xmlfiles} rs6000/powerpc-cell64l.xml"
|
|
|
|
|
srv_xmlfiles="${srv_xmlfiles} rs6000/powerpc-vsx64l.xml"
|
2008-11-20 15:44:10 +00:00
|
|
|
|
srv_xmlfiles="${srv_xmlfiles} rs6000/powerpc-isa205-64l.xml"
|
|
|
|
|
srv_xmlfiles="${srv_xmlfiles} rs6000/powerpc-isa205-altivec64l.xml"
|
|
|
|
|
--- gdb/gdbserver/linux-low.c
|
|
|
|
|
+++ gdb/gdbserver/linux-low.c
|
2009-01-19 00:46:30 +00:00
|
|
|
|
@@ -36,8 +36,14 @@
|
|
|
|
|
#include <ctype.h>
|
|
|
|
|
#include <pwd.h>
|
|
|
|
|
#include <sys/types.h>
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+#include <sys/stat.h>
|
|
|
|
|
+#include <sys/vfs.h>
|
2009-01-19 00:46:30 +00:00
|
|
|
|
#include <dirent.h>
|
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+#ifndef SPUFS_MAGIC
|
|
|
|
|
+#define SPUFS_MAGIC 0x23c9b64e
|
|
|
|
|
+#endif
|
2009-01-19 00:46:30 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
#ifndef PTRACE_GETSIGINFO
|
|
|
|
|
# define PTRACE_GETSIGINFO 0x4202
|
2009-01-19 00:46:30 +00:00
|
|
|
|
# define PTRACE_SETSIGINFO 0x4203
|
|
|
|
|
@@ -2180,6 +2186,102 @@ linux_qxfer_osdata (const char *annex,
|
|
|
|
|
return len;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+/* Enumerate spufs IDs for process PID. */
|
|
|
|
|
+static int
|
|
|
|
|
+spu_enumerate_spu_ids (long pid, unsigned char *buf, CORE_ADDR offset, int len)
|
|
|
|
|
+{
|
|
|
|
|
+ int pos = 0;
|
|
|
|
|
+ int written = 0;
|
|
|
|
|
+ char path[128];
|
|
|
|
|
+ DIR *dir;
|
|
|
|
|
+ struct dirent *entry;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ sprintf (path, "/proc/%ld/fd", pid);
|
|
|
|
|
+ dir = opendir (path);
|
|
|
|
|
+ if (!dir)
|
|
|
|
|
+ return -1;
|
|
|
|
|
+
|
|
|
|
|
+ rewinddir (dir);
|
|
|
|
|
+ while ((entry = readdir (dir)) != NULL)
|
|
|
|
|
+ {
|
|
|
|
|
+ struct stat st;
|
|
|
|
|
+ struct statfs stfs;
|
|
|
|
|
+ int fd;
|
|
|
|
|
+
|
|
|
|
|
+ fd = atoi (entry->d_name);
|
|
|
|
|
+ if (!fd)
|
|
|
|
|
+ continue;
|
|
|
|
|
+
|
|
|
|
|
+ sprintf (path, "/proc/%ld/fd/%d", pid, fd);
|
|
|
|
|
+ if (stat (path, &st) != 0)
|
|
|
|
|
+ continue;
|
|
|
|
|
+ if (!S_ISDIR (st.st_mode))
|
|
|
|
|
+ continue;
|
|
|
|
|
+
|
|
|
|
|
+ if (statfs (path, &stfs) != 0)
|
|
|
|
|
+ continue;
|
|
|
|
|
+ if (stfs.f_type != SPUFS_MAGIC)
|
|
|
|
|
+ continue;
|
|
|
|
|
+
|
|
|
|
|
+ if (pos >= offset && pos + 4 <= offset + len)
|
|
|
|
|
+ {
|
|
|
|
|
+ *(unsigned int *)(buf + pos - offset) = fd;
|
|
|
|
|
+ written += 4;
|
|
|
|
|
+ }
|
|
|
|
|
+ pos += 4;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ closedir (dir);
|
|
|
|
|
+ return written;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+}
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+/* Implements the to_xfer_partial interface for the TARGET_OBJECT_SPU
|
|
|
|
|
+ object type, using the /proc file system */
|
|
|
|
|
+static int
|
|
|
|
|
+linux_spu_qxfer_partial (const char *annex, unsigned char *readbuf,
|
|
|
|
|
+ unsigned const char *writebuf,
|
|
|
|
|
+ CORE_ADDR offset, int len)
|
|
|
|
|
+{
|
|
|
|
|
+ char buf[128];
|
|
|
|
|
+ int fd = 0;
|
|
|
|
|
+ int ret = 0;
|
|
|
|
|
+
|
|
|
|
|
+ if (!writebuf && !readbuf)
|
|
|
|
|
+ return -1;
|
|
|
|
|
+
|
|
|
|
|
+ if (!*annex)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (!readbuf)
|
|
|
|
|
+ return -1;
|
|
|
|
|
+ else
|
|
|
|
|
+ return spu_enumerate_spu_ids (inferior_pid, readbuf, offset, len);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ sprintf (buf, "/proc/%ld/fd/%s", inferior_pid, annex);
|
|
|
|
|
+ if (debug_threads)
|
|
|
|
|
+ printf ("access [%s] |offset [%lld] | len [%d]\n", buf, offset, len);
|
|
|
|
|
+
|
|
|
|
|
+ fd = open (buf, writebuf? O_WRONLY : O_RDONLY);
|
|
|
|
|
+ if (fd <= 0)
|
|
|
|
|
+ return -1;
|
|
|
|
|
+
|
|
|
|
|
+ if (offset != 0
|
|
|
|
|
+ && lseek (fd, (off_t) offset, SEEK_SET) != (off_t) offset)
|
|
|
|
|
+ {
|
|
|
|
|
+ close (fd);
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (writebuf)
|
|
|
|
|
+ ret = write (fd, writebuf, (size_t) len);
|
|
|
|
|
+ else
|
|
|
|
|
+ ret = read (fd, readbuf, (size_t) len);
|
|
|
|
|
+
|
|
|
|
|
+ close (fd);
|
|
|
|
|
+ return ret;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
static struct target_ops linux_target_ops = {
|
|
|
|
|
linux_create_inferior,
|
|
|
|
|
linux_attach,
|
2009-01-19 00:46:30 +00:00
|
|
|
|
@@ -2210,7 +2312,7 @@ static struct target_ops linux_target_op
|
2008-11-07 14:07:25 +00:00
|
|
|
|
#else
|
|
|
|
|
NULL,
|
|
|
|
|
#endif
|
|
|
|
|
- NULL,
|
|
|
|
|
+ linux_spu_qxfer_partial,
|
|
|
|
|
hostio_last_error_from_errno,
|
2009-01-19 00:46:30 +00:00
|
|
|
|
linux_qxfer_osdata,
|
2008-11-07 14:07:25 +00:00
|
|
|
|
};
|
2008-11-20 15:44:10 +00:00
|
|
|
|
--- gdb/gdbserver/linux-ppc-low.c
|
|
|
|
|
+++ gdb/gdbserver/linux-ppc-low.c
|
2008-11-07 14:07:25 +00:00
|
|
|
|
@@ -28,6 +28,7 @@
|
|
|
|
|
#define PPC_FEATURE_HAS_VSX 0x00000080
|
|
|
|
|
#define PPC_FEATURE_HAS_ALTIVEC 0x10000000
|
|
|
|
|
#define PPC_FEATURE_HAS_SPE 0x00800000
|
|
|
|
|
+#define PPC_FEATURE_CELL 0x00010000
|
2008-11-20 15:44:10 +00:00
|
|
|
|
#define PPC_FEATURE_ARCH_2_05 0x00001000
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
static unsigned long ppc_hwcap;
|
2008-11-20 15:44:10 +00:00
|
|
|
|
@@ -37,6 +38,8 @@ static unsigned long ppc_hwcap;
|
2008-11-07 14:07:25 +00:00
|
|
|
|
void init_registers_powerpc_32l (void);
|
|
|
|
|
/* Defined in auto-generated file powerpc-altivec32l.c. */
|
|
|
|
|
void init_registers_powerpc_altivec32l (void);
|
|
|
|
|
+/* Defined in auto-generated file powerpc-cell32l.c. */
|
|
|
|
|
+void init_registers_powerpc_cell32l (void);
|
|
|
|
|
/* Defined in auto-generated file powerpc-vsx32l.c. */
|
|
|
|
|
void init_registers_powerpc_vsx32l (void);
|
2008-11-20 15:44:10 +00:00
|
|
|
|
/* Defined in auto-generated file powerpc-isa205-32l.c. */
|
|
|
|
|
@@ -51,6 +54,8 @@ void init_registers_powerpc_e500l (void)
|
2008-11-07 14:07:25 +00:00
|
|
|
|
void init_registers_powerpc_64l (void);
|
|
|
|
|
/* Defined in auto-generated file powerpc-altivec64l.c. */
|
|
|
|
|
void init_registers_powerpc_altivec64l (void);
|
|
|
|
|
+/* Defined in auto-generated file powerpc-cell64l.c. */
|
|
|
|
|
+void init_registers_powerpc_cell64l (void);
|
|
|
|
|
/* Defined in auto-generated file powerpc-vsx64l.c. */
|
|
|
|
|
void init_registers_powerpc_vsx64l (void);
|
2008-11-20 15:44:10 +00:00
|
|
|
|
/* Defined in auto-generated file powerpc-isa205-64l.c. */
|
|
|
|
|
@@ -186,10 +191,72 @@ ppc_supply_ptrace_register (int regno, c
|
2008-11-07 14:07:25 +00:00
|
|
|
|
supply_register (regno, buf);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
}
|
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+
|
|
|
|
|
+#define INSTR_SC 0x44000002
|
|
|
|
|
+#define NR_spu_run 0x0116
|
|
|
|
|
+
|
|
|
|
|
+/* If the PPU thread is currently stopped on a spu_run system call,
|
|
|
|
|
+ return to FD and ADDR the file handle and NPC parameter address
|
|
|
|
|
+ used with the system call. Return non-zero if successful. */
|
|
|
|
|
+static int
|
|
|
|
|
+parse_spufs_run (int *fd, CORE_ADDR *addr)
|
|
|
|
|
+{
|
|
|
|
|
+ CORE_ADDR curr_pc;
|
|
|
|
|
+ int curr_insn;
|
|
|
|
|
+ int curr_r0;
|
|
|
|
|
+
|
|
|
|
|
+ if (register_size (0) == 4)
|
|
|
|
|
+ {
|
|
|
|
|
+ unsigned int pc, r0, r3, r4;
|
|
|
|
|
+ collect_register_by_name ("pc", &pc);
|
|
|
|
|
+ collect_register_by_name ("r0", &r0);
|
|
|
|
|
+ collect_register_by_name ("orig_r3", &r3);
|
|
|
|
|
+ collect_register_by_name ("r4", &r4);
|
|
|
|
|
+ curr_pc = (CORE_ADDR) pc;
|
|
|
|
|
+ curr_r0 = (int) r0;
|
|
|
|
|
+ *fd = (int) r3;
|
|
|
|
|
+ *addr = (CORE_ADDR) r4;
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ unsigned long pc, r0, r3, r4;
|
|
|
|
|
+ collect_register_by_name ("pc", &pc);
|
|
|
|
|
+ collect_register_by_name ("r0", &r0);
|
|
|
|
|
+ collect_register_by_name ("orig_r3", &r3);
|
|
|
|
|
+ collect_register_by_name ("r4", &r4);
|
|
|
|
|
+ curr_pc = (CORE_ADDR) pc;
|
|
|
|
|
+ curr_r0 = (int) r0;
|
|
|
|
|
+ *fd = (int) r3;
|
|
|
|
|
+ *addr = (CORE_ADDR) r4;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /* Fetch instruction preceding current NIP. */
|
|
|
|
|
+ if ((*the_target->read_memory) (curr_pc - 4,
|
|
|
|
|
+ (unsigned char *) &curr_insn, 4) != 0)
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ /* It should be a "sc" instruction. */
|
|
|
|
|
+ if (curr_insn != INSTR_SC)
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ /* System call number should be NR_spu_run. */
|
|
|
|
|
+ if (curr_r0 != NR_spu_run)
|
|
|
|
|
+ return 0;
|
|
|
|
|
+
|
|
|
|
|
+ return 1;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
static CORE_ADDR
|
|
|
|
|
ppc_get_pc (void)
|
|
|
|
|
{
|
|
|
|
|
- if (register_size (0) == 4)
|
|
|
|
|
+ CORE_ADDR addr;
|
|
|
|
|
+ int fd;
|
|
|
|
|
+
|
|
|
|
|
+ if (parse_spufs_run (&fd, &addr))
|
|
|
|
|
+ {
|
|
|
|
|
+ unsigned int pc;
|
|
|
|
|
+ (*the_target->read_memory) (addr, (unsigned char *) &pc, 4);
|
|
|
|
|
+ return ((CORE_ADDR)1 << 63) | ((CORE_ADDR)fd << 32) | (CORE_ADDR) (pc - 4);
|
|
|
|
|
+ }
|
|
|
|
|
+ else if (register_size (0) == 4)
|
|
|
|
|
{
|
|
|
|
|
unsigned int pc;
|
|
|
|
|
collect_register_by_name ("pc", &pc);
|
2008-11-20 15:44:10 +00:00
|
|
|
|
@@ -206,7 +273,15 @@ ppc_get_pc (void)
|
2008-11-07 14:07:25 +00:00
|
|
|
|
static void
|
|
|
|
|
ppc_set_pc (CORE_ADDR pc)
|
|
|
|
|
{
|
|
|
|
|
- if (register_size (0) == 4)
|
|
|
|
|
+ CORE_ADDR addr;
|
|
|
|
|
+ int fd;
|
|
|
|
|
+
|
|
|
|
|
+ if (parse_spufs_run (&fd, &addr))
|
|
|
|
|
+ {
|
|
|
|
|
+ unsigned int newpc = pc;
|
|
|
|
|
+ (*the_target->write_memory) (addr, (unsigned char *) &newpc, 4);
|
|
|
|
|
+ }
|
|
|
|
|
+ else if (register_size (0) == 4)
|
|
|
|
|
{
|
|
|
|
|
unsigned int newpc = pc;
|
|
|
|
|
supply_register_by_name ("pc", &newpc);
|
2008-11-20 15:44:10 +00:00
|
|
|
|
@@ -272,7 +347,9 @@ ppc_arch_setup (void)
|
2008-11-07 14:07:25 +00:00
|
|
|
|
if (msr < 0)
|
|
|
|
|
{
|
|
|
|
|
ppc_get_hwcap (&ppc_hwcap);
|
|
|
|
|
- if (ppc_hwcap & PPC_FEATURE_HAS_VSX)
|
|
|
|
|
+ if (ppc_hwcap & PPC_FEATURE_CELL)
|
|
|
|
|
+ init_registers_powerpc_cell64l ();
|
|
|
|
|
+ else if (ppc_hwcap & PPC_FEATURE_HAS_VSX)
|
2008-11-20 15:44:10 +00:00
|
|
|
|
{
|
|
|
|
|
if (ppc_hwcap & PPC_FEATURE_ARCH_2_05)
|
|
|
|
|
init_registers_powerpc_isa205_vsx64l ();
|
|
|
|
|
@@ -295,7 +372,9 @@ ppc_arch_setup (void)
|
2008-11-07 14:07:25 +00:00
|
|
|
|
init_registers_powerpc_32l ();
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
ppc_get_hwcap (&ppc_hwcap);
|
|
|
|
|
- if (ppc_hwcap & PPC_FEATURE_HAS_VSX)
|
|
|
|
|
+ if (ppc_hwcap & PPC_FEATURE_CELL)
|
|
|
|
|
+ init_registers_powerpc_cell32l ();
|
|
|
|
|
+ else if (ppc_hwcap & PPC_FEATURE_HAS_VSX)
|
2008-11-20 15:44:10 +00:00
|
|
|
|
{
|
|
|
|
|
if (ppc_hwcap & PPC_FEATURE_ARCH_2_05)
|
|
|
|
|
init_registers_powerpc_isa205_vsx32l ();
|
|
|
|
|
@@ -339,11 +418,24 @@ ppc_breakpoint_at (CORE_ADDR where)
|
2008-11-07 14:07:25 +00:00
|
|
|
|
{
|
|
|
|
|
unsigned int insn;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
- (*the_target->read_memory) (where, (unsigned char *) &insn, 4);
|
|
|
|
|
- if (insn == ppc_breakpoint)
|
|
|
|
|
- return 1;
|
|
|
|
|
- /* If necessary, recognize more trap instructions here. GDB only uses the
|
|
|
|
|
- one. */
|
|
|
|
|
+ if (where & ((CORE_ADDR)1 << 63))
|
|
|
|
|
+ {
|
|
|
|
|
+ char mem_annex[32];
|
|
|
|
|
+ sprintf (mem_annex, "%d/mem", (int)((where >> 32) & 0x7fffffff));
|
|
|
|
|
+ (*the_target->qxfer_spu) (mem_annex, (unsigned char *) &insn,
|
|
|
|
|
+ NULL, where & 0xffffffff, 4);
|
|
|
|
|
+ if (insn == 0x3fff)
|
|
|
|
|
+ return 1;
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ (*the_target->read_memory) (where, (unsigned char *) &insn, 4);
|
|
|
|
|
+ if (insn == ppc_breakpoint)
|
|
|
|
|
+ return 1;
|
|
|
|
|
+ /* If necessary, recognize more trap instructions here. GDB only uses
|
|
|
|
|
+ the one. */
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2009-01-22 17:17:17 +00:00
|
|
|
|
--- gdb/gdbserver/thread-db.c
|
|
|
|
|
+++ gdb/gdbserver/thread-db.c
|
|
|
|
|
@@ -386,6 +386,10 @@ thread_db_get_tls_address (struct thread
|
|
|
|
|
td_err_e err;
|
|
|
|
|
struct process_info *process;
|
|
|
|
|
|
|
|
|
|
+ /* If the thread layer is not (yet) initialized, fail. */
|
|
|
|
|
+ if (!all_symbols_looked_up)
|
|
|
|
|
+ return -1;
|
|
|
|
|
+
|
|
|
|
|
process = get_thread_process (thread);
|
|
|
|
|
if (!process->thread_known)
|
|
|
|
|
find_one_thread (process->lwpid);
|
2008-11-20 15:44:10 +00:00
|
|
|
|
--- gdb/i386-nat.c
|
|
|
|
|
+++ gdb/i386-nat.c
|
2009-01-19 00:46:30 +00:00
|
|
|
|
@@ -641,14 +641,14 @@ i386_insert_hw_breakpoint (struct bp_tar
|
2008-11-07 14:07:25 +00:00
|
|
|
|
}
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
/* Remove a hardware-assisted breakpoint at BP_TGT->placed_address.
|
|
|
|
|
- Return 0 on success, -1 on failure. */
|
|
|
|
|
+ Return 0 on success, EBUSY on failure. */
|
|
|
|
|
|
|
|
|
|
int
|
|
|
|
|
i386_remove_hw_breakpoint (struct bp_target_info *bp_tgt)
|
|
|
|
|
{
|
|
|
|
|
unsigned len_rw = i386_length_and_rw_bits (1, hw_execute);
|
|
|
|
|
CORE_ADDR addr = bp_tgt->placed_address;
|
|
|
|
|
- int retval = i386_remove_aligned_watchpoint (addr, len_rw);
|
|
|
|
|
+ int retval = i386_remove_aligned_watchpoint (addr, len_rw) ? EBUSY : 0;
|
|
|
|
|
|
|
|
|
|
if (maint_show_dr)
|
|
|
|
|
i386_show_dr ("remove_hwbp", addr, 1, hw_execute);
|
2008-11-20 15:44:10 +00:00
|
|
|
|
--- gdb/inferior.h
|
|
|
|
|
+++ gdb/inferior.h
|
2009-01-19 00:46:30 +00:00
|
|
|
|
@@ -142,13 +142,17 @@ extern CORE_ADDR read_pc (void);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
|
|
|
|
extern void write_pc (CORE_ADDR);
|
|
|
|
|
|
|
|
|
|
-extern CORE_ADDR unsigned_pointer_to_address (struct type *type,
|
|
|
|
|
+extern CORE_ADDR unsigned_pointer_to_address (struct gdbarch *gdbarch,
|
|
|
|
|
+ struct type *type,
|
|
|
|
|
const gdb_byte *buf);
|
|
|
|
|
-extern void unsigned_address_to_pointer (struct type *type, gdb_byte *buf,
|
|
|
|
|
+extern void unsigned_address_to_pointer (struct gdbarch *gdbarch,
|
|
|
|
|
+ struct type *type, gdb_byte *buf,
|
|
|
|
|
CORE_ADDR addr);
|
|
|
|
|
-extern CORE_ADDR signed_pointer_to_address (struct type *type,
|
|
|
|
|
+extern CORE_ADDR signed_pointer_to_address (struct gdbarch *gdbarch,
|
|
|
|
|
+ struct type *type,
|
|
|
|
|
const gdb_byte *buf);
|
|
|
|
|
-extern void address_to_signed_pointer (struct type *type, gdb_byte *buf,
|
|
|
|
|
+extern void address_to_signed_pointer (struct gdbarch *gdbarch,
|
|
|
|
|
+ struct type *type, gdb_byte *buf,
|
|
|
|
|
CORE_ADDR addr);
|
|
|
|
|
|
|
|
|
|
extern void wait_for_inferior (int treat_exec_as_sigtrap);
|
2008-11-20 15:44:10 +00:00
|
|
|
|
--- gdb/iq2000-tdep.c
|
|
|
|
|
+++ gdb/iq2000-tdep.c
|
2009-01-19 00:46:30 +00:00
|
|
|
|
@@ -87,7 +87,8 @@ insn_addr_from_ptr (CORE_ADDR ptr) /* ta
|
2008-09-12 23:16:14 +00:00
|
|
|
|
Convert a target pointer to an address in host (CORE_ADDR) format. */
|
|
|
|
|
|
|
|
|
|
static CORE_ADDR
|
|
|
|
|
-iq2000_pointer_to_address (struct type * type, const gdb_byte * buf)
|
|
|
|
|
+iq2000_pointer_to_address (struct gdbarch *gdbarch,
|
|
|
|
|
+ struct type * type, const gdb_byte * buf)
|
|
|
|
|
{
|
|
|
|
|
enum type_code target = TYPE_CODE (TYPE_TARGET_TYPE (type));
|
|
|
|
|
CORE_ADDR addr = extract_unsigned_integer (buf, TYPE_LENGTH (type));
|
2009-01-19 00:46:30 +00:00
|
|
|
|
@@ -104,7 +105,8 @@ iq2000_pointer_to_address (struct type *
|
2008-09-12 23:16:14 +00:00
|
|
|
|
Convert a host-format address (CORE_ADDR) into a target pointer. */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
-iq2000_address_to_pointer (struct type *type, gdb_byte *buf, CORE_ADDR addr)
|
|
|
|
|
+iq2000_address_to_pointer (struct gdbarch *gdbarch,
|
|
|
|
|
+ struct type *type, gdb_byte *buf, CORE_ADDR addr)
|
|
|
|
|
{
|
|
|
|
|
enum type_code target = TYPE_CODE (TYPE_TARGET_TYPE (type));
|
|
|
|
|
|
2008-11-20 15:44:10 +00:00
|
|
|
|
--- gdb/linux-nat.c
|
|
|
|
|
+++ gdb/linux-nat.c
|
2009-01-19 00:46:30 +00:00
|
|
|
|
@@ -53,6 +53,12 @@
|
|
|
|
|
#include <sys/types.h>
|
|
|
|
|
#include "gdb_dirent.h"
|
|
|
|
|
#include "xml-support.h"
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+#include <sys/vfs.h> /* for struct statfs */
|
|
|
|
|
+#include <dirent.h> /* for DIR etc. */
|
|
|
|
|
+
|
|
|
|
|
+#ifndef SPUFS_MAGIC
|
|
|
|
|
+#define SPUFS_MAGIC 0x23c9b64e
|
|
|
|
|
+#endif
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
#ifdef HAVE_PERSONALITY
|
|
|
|
|
# include <sys/personality.h>
|
2009-01-19 00:46:30 +00:00
|
|
|
|
@@ -3429,8 +3435,8 @@ linux_nat_do_thread_registers (bfd *obfd
|
2008-11-07 14:07:25 +00:00
|
|
|
|
gdb_gregset_t gregs;
|
|
|
|
|
gdb_fpregset_t fpregs;
|
|
|
|
|
unsigned long lwp = ptid_get_lwp (ptid);
|
|
|
|
|
- struct regcache *regcache = get_thread_regcache (ptid);
|
|
|
|
|
- struct gdbarch *gdbarch = get_regcache_arch (regcache);
|
|
|
|
|
+ struct gdbarch *gdbarch = target_gdbarch;
|
|
|
|
|
+ struct regcache *regcache = get_thread_arch_regcache (ptid, gdbarch);
|
|
|
|
|
const struct regset *regset;
|
|
|
|
|
int core_regset_p;
|
|
|
|
|
struct cleanup *old_chain;
|
2009-01-19 00:46:30 +00:00
|
|
|
|
@@ -3540,6 +3546,119 @@ linux_nat_corefile_thread_callback (stru
|
2008-11-07 14:07:25 +00:00
|
|
|
|
return 0;
|
|
|
|
|
}
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+/* Enumerate spufs IDs for process PID. */
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+static void
|
|
|
|
|
+iterate_over_spus (int pid, void (*callback) (void *, int), void *data)
|
|
|
|
|
+{
|
|
|
|
|
+ char path[128];
|
|
|
|
|
+ DIR *dir;
|
|
|
|
|
+ struct dirent *entry;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ xsnprintf (path, sizeof path, "/proc/%d/fd", pid);
|
|
|
|
|
+ dir = opendir (path);
|
|
|
|
|
+ if (!dir)
|
|
|
|
|
+ return;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ rewinddir (dir);
|
|
|
|
|
+ while ((entry = readdir (dir)) != NULL)
|
|
|
|
|
+ {
|
|
|
|
|
+ struct stat st;
|
|
|
|
|
+ struct statfs stfs;
|
|
|
|
|
+ int fd;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ fd = atoi (entry->d_name);
|
|
|
|
|
+ if (!fd)
|
|
|
|
|
+ continue;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ xsnprintf (path, sizeof path, "/proc/%d/fd/%d", pid, fd);
|
|
|
|
|
+ if (stat (path, &st) != 0)
|
|
|
|
|
+ continue;
|
|
|
|
|
+ if (!S_ISDIR (st.st_mode))
|
|
|
|
|
+ continue;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ if (statfs (path, &stfs) != 0)
|
|
|
|
|
+ continue;
|
|
|
|
|
+ if (stfs.f_type != SPUFS_MAGIC)
|
|
|
|
|
+ continue;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ callback (data, fd);
|
|
|
|
|
+ }
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ closedir (dir);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+}
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+/* Generate corefile notes for SPU contexts. */
|
|
|
|
|
+
|
|
|
|
|
+struct linux_spu_corefile_data
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+{
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ bfd *obfd;
|
|
|
|
|
+ char *note_data;
|
|
|
|
|
+ int *note_size;
|
|
|
|
|
+};
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+static void
|
|
|
|
|
+linux_spu_corefile_callback (void *data, int fd)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+{
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ struct linux_spu_corefile_data *args = data;
|
|
|
|
|
+ int i;
|
|
|
|
|
+
|
|
|
|
|
+ static const char *spu_files[] =
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+ {
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ "object-id",
|
|
|
|
|
+ "mem",
|
|
|
|
|
+ "regs",
|
|
|
|
|
+ "fpcr",
|
|
|
|
|
+ "lslr",
|
|
|
|
|
+ "decr",
|
|
|
|
|
+ "decr_status",
|
|
|
|
|
+ "signal1",
|
|
|
|
|
+ "signal1_type",
|
|
|
|
|
+ "signal2",
|
|
|
|
|
+ "signal2_type",
|
|
|
|
|
+ "event_mask",
|
|
|
|
|
+ "event_status",
|
|
|
|
|
+ "mbox_info",
|
|
|
|
|
+ "ibox_info",
|
|
|
|
|
+ "wbox_info",
|
|
|
|
|
+ "dma_info",
|
|
|
|
|
+ "proxydma_info",
|
|
|
|
|
+ };
|
|
|
|
|
+
|
|
|
|
|
+ for (i = 0; i < sizeof (spu_files) / sizeof (spu_files[0]); i++)
|
|
|
|
|
+ {
|
|
|
|
|
+ char annex[32], note_name[32];
|
|
|
|
|
+ gdb_byte *spu_data;
|
|
|
|
|
+ LONGEST spu_len;
|
|
|
|
|
+
|
|
|
|
|
+ xsnprintf (annex, sizeof annex, "%d/%s", fd, spu_files[i]);
|
|
|
|
|
+ spu_len = target_read_alloc (¤t_target, TARGET_OBJECT_SPU,
|
|
|
|
|
+ annex, &spu_data);
|
|
|
|
|
+ if (spu_len > 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ xsnprintf (note_name, sizeof note_name, "SPU/%s", annex);
|
|
|
|
|
+ args->note_data = elfcore_write_note (args->obfd, args->note_data,
|
|
|
|
|
+ args->note_size, note_name,
|
|
|
|
|
+ NT_SPU, spu_data, spu_len);
|
|
|
|
|
+ xfree (spu_data);
|
|
|
|
|
+ }
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+static char *
|
|
|
|
|
+linux_spu_make_corefile_notes (bfd *obfd, char *note_data, int *note_size)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+{
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ struct linux_spu_corefile_data args;
|
|
|
|
|
+ args.obfd = obfd;
|
|
|
|
|
+ args.note_data = note_data;
|
|
|
|
|
+ args.note_size = note_size;
|
|
|
|
|
+
|
|
|
|
|
+ iterate_over_spus (PIDGET (inferior_ptid),
|
|
|
|
|
+ linux_spu_corefile_callback, &args);
|
|
|
|
|
+
|
|
|
|
|
+ return args.note_data;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+}
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+
|
|
|
|
|
/* Fills the "to_make_corefile_note" target vector. Builds the note
|
|
|
|
|
section for a corefile, and returns it in a malloc buffer. */
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2009-01-19 00:46:30 +00:00
|
|
|
|
@@ -3600,6 +3719,8 @@ linux_nat_make_corefile_notes (bfd *obfd
|
2008-11-07 14:07:25 +00:00
|
|
|
|
xfree (auxv);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
}
|
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ note_data = linux_spu_make_corefile_notes (obfd, note_data, note_size);
|
|
|
|
|
+
|
|
|
|
|
make_cleanup (xfree, note_data);
|
|
|
|
|
return note_data;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
}
|
2009-01-19 00:46:30 +00:00
|
|
|
|
@@ -3931,6 +4052,99 @@ linux_proc_xfer_partial (struct target_o
|
2008-11-07 14:07:25 +00:00
|
|
|
|
return ret;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+/* Enumerate spufs IDs for process PID. */
|
|
|
|
|
+static LONGEST
|
|
|
|
|
+spu_enumerate_spu_ids (int pid, gdb_byte *buf, ULONGEST offset, LONGEST len)
|
|
|
|
|
+{
|
|
|
|
|
+ LONGEST pos = 0;
|
|
|
|
|
+ LONGEST written = 0;
|
|
|
|
|
+ char path[128];
|
|
|
|
|
+ DIR *dir;
|
|
|
|
|
+ struct dirent *entry;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ xsnprintf (path, sizeof path, "/proc/%d/fd", pid);
|
|
|
|
|
+ dir = opendir (path);
|
|
|
|
|
+ if (!dir)
|
|
|
|
|
+ return -1;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ rewinddir (dir);
|
|
|
|
|
+ while ((entry = readdir (dir)) != NULL)
|
|
|
|
|
+ {
|
|
|
|
|
+ struct stat st;
|
|
|
|
|
+ struct statfs stfs;
|
|
|
|
|
+ int fd;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ fd = atoi (entry->d_name);
|
|
|
|
|
+ if (!fd)
|
|
|
|
|
+ continue;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ xsnprintf (path, sizeof path, "/proc/%d/fd/%d", pid, fd);
|
|
|
|
|
+ if (stat (path, &st) != 0)
|
|
|
|
|
+ continue;
|
|
|
|
|
+ if (!S_ISDIR (st.st_mode))
|
|
|
|
|
+ continue;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ if (statfs (path, &stfs) != 0)
|
|
|
|
|
+ continue;
|
|
|
|
|
+ if (stfs.f_type != SPUFS_MAGIC)
|
|
|
|
|
+ continue;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ if (pos >= offset && pos + 4 <= offset + len)
|
|
|
|
|
+ {
|
|
|
|
|
+ store_unsigned_integer (buf + pos - offset, 4, fd);
|
|
|
|
|
+ written += 4;
|
|
|
|
|
+ }
|
|
|
|
|
+ pos += 4;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ closedir (dir);
|
|
|
|
|
+ return written;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+}
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+/* Implement the to_xfer_partial interface for the TARGET_OBJECT_SPU
|
|
|
|
|
+ object type, using the /proc file system. */
|
|
|
|
|
+static LONGEST
|
|
|
|
|
+linux_proc_xfer_spu (struct target_ops *ops, enum target_object object,
|
|
|
|
|
+ const char *annex, gdb_byte *readbuf,
|
|
|
|
|
+ const gdb_byte *writebuf,
|
|
|
|
|
+ ULONGEST offset, LONGEST len)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+{
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ char buf[128];
|
|
|
|
|
+ int fd = 0;
|
|
|
|
|
+ int ret = -1;
|
|
|
|
|
+ int pid = PIDGET (inferior_ptid);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ if (!annex)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+ {
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ if (!readbuf)
|
|
|
|
|
+ return -1;
|
|
|
|
|
+ else
|
|
|
|
|
+ return spu_enumerate_spu_ids (pid, readbuf, offset, len);
|
|
|
|
|
+ }
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ xsnprintf (buf, sizeof buf, "/proc/%d/fd/%s", pid, annex);
|
|
|
|
|
+ fd = open (buf, writebuf? O_WRONLY : O_RDONLY);
|
|
|
|
|
+ if (fd <= 0)
|
|
|
|
|
+ return -1;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ if (offset != 0
|
|
|
|
|
+ && lseek (fd, (off_t) offset, SEEK_SET) != (off_t) offset)
|
|
|
|
|
+ {
|
|
|
|
|
+ close (fd);
|
|
|
|
|
+ return 0;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+ }
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ if (writebuf)
|
|
|
|
|
+ ret = write (fd, writebuf, (size_t) len);
|
|
|
|
|
+ else if (readbuf)
|
|
|
|
|
+ ret = read (fd, readbuf, (size_t) len);
|
|
|
|
|
+
|
|
|
|
|
+ close (fd);
|
|
|
|
|
+ return ret;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
/* Parse LINE as a signal set and add its set bits to SIGS. */
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
static void
|
2009-01-19 00:46:30 +00:00
|
|
|
|
@@ -4136,6 +4350,10 @@ linux_xfer_partial (struct target_ops *o
|
|
|
|
|
return linux_nat_xfer_osdata (ops, object, annex, readbuf, writebuf,
|
|
|
|
|
offset, len);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ if (object == TARGET_OBJECT_SPU)
|
|
|
|
|
+ return linux_proc_xfer_spu (ops, object, annex, readbuf, writebuf,
|
|
|
|
|
+ offset, len);
|
|
|
|
|
+
|
|
|
|
|
xfer = linux_proc_xfer_partial (ops, object, annex, readbuf, writebuf,
|
|
|
|
|
offset, len);
|
|
|
|
|
if (xfer != 0)
|
2008-11-20 15:44:10 +00:00
|
|
|
|
--- gdb/m32c-tdep.c
|
|
|
|
|
+++ gdb/m32c-tdep.c
|
2009-01-19 00:46:30 +00:00
|
|
|
|
@@ -2401,7 +2401,8 @@ m32c_skip_trampoline_code (struct frame_
|
2008-11-07 14:07:25 +00:00
|
|
|
|
programmer! :) */
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
static void
|
|
|
|
|
-m32c_m16c_address_to_pointer (struct type *type, gdb_byte *buf, CORE_ADDR addr)
|
|
|
|
|
+m32c_m16c_address_to_pointer (struct gdbarch *gdbarch,
|
|
|
|
|
+ struct type *type, gdb_byte *buf, CORE_ADDR addr)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
{
|
2008-11-07 14:07:25 +00:00
|
|
|
|
enum type_code target_code;
|
|
|
|
|
gdb_assert (TYPE_CODE (type) == TYPE_CODE_PTR ||
|
2009-01-19 00:46:30 +00:00
|
|
|
|
@@ -2449,7 +2450,8 @@ m32c_m16c_address_to_pointer (struct typ
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
static CORE_ADDR
|
|
|
|
|
-m32c_m16c_pointer_to_address (struct type *type, const gdb_byte *buf)
|
|
|
|
|
+m32c_m16c_pointer_to_address (struct gdbarch *gdbarch,
|
|
|
|
|
+ struct type *type, const gdb_byte *buf)
|
|
|
|
|
{
|
|
|
|
|
CORE_ADDR ptr;
|
|
|
|
|
enum type_code target_code;
|
2008-11-20 15:44:10 +00:00
|
|
|
|
--- gdb/objfiles.c
|
|
|
|
|
+++ gdb/objfiles.c
|
2008-11-07 14:07:25 +00:00
|
|
|
|
@@ -672,7 +672,7 @@ objfile_relocate (struct objfile *objfil
|
2008-09-12 23:16:14 +00:00
|
|
|
|
}
|
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
/* Relocate breakpoints as necessary, after things are relocated. */
|
|
|
|
|
- breakpoint_re_set ();
|
|
|
|
|
+ breakpoint_relocate (objfile, delta);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
}
|
2008-11-07 14:07:25 +00:00
|
|
|
|
|
|
|
|
|
/* Many places in gdb want to test just to see if we have any partial
|
2008-11-20 15:44:10 +00:00
|
|
|
|
--- gdb/ppc-linux-nat.c
|
|
|
|
|
+++ gdb/ppc-linux-nat.c
|
|
|
|
|
@@ -60,6 +60,9 @@
|
|
|
|
|
If they aren't, we can provide them ourselves (their values are fixed
|
|
|
|
|
because they are part of the kernel ABI). They are used in the AT_HWCAP
|
|
|
|
|
entry of the AUXV. */
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+#ifndef PPC_FEATURE_CELL
|
|
|
|
|
+#define PPC_FEATURE_CELL 0x00010000
|
|
|
|
|
+#endif
|
|
|
|
|
#ifndef PPC_FEATURE_BOOKE
|
|
|
|
|
#define PPC_FEATURE_BOOKE 0x00008000
|
|
|
|
|
#endif
|
2009-01-22 17:17:17 +00:00
|
|
|
|
@@ -1238,12 +1241,58 @@ fill_fpregset (const struct regcache *re
|
|
|
|
|
fpregsetp, sizeof (*fpregsetp));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+static int
|
|
|
|
|
+ppc_linux_target_wordsize (void)
|
|
|
|
|
+{
|
|
|
|
|
+ int wordsize = 4;
|
|
|
|
|
+
|
|
|
|
|
+ /* Check for 64-bit inferior process. This is the case when the host is
|
|
|
|
|
+ 64-bit, and in addition the top bit of the MSR register is set. */
|
|
|
|
|
+#ifdef __powerpc64__
|
|
|
|
|
+ long msr;
|
|
|
|
|
+
|
|
|
|
|
+ int tid = TIDGET (inferior_ptid);
|
|
|
|
|
+ if (tid == 0)
|
|
|
|
|
+ tid = PIDGET (inferior_ptid);
|
|
|
|
|
+
|
|
|
|
|
+ errno = 0;
|
|
|
|
|
+ msr = (long) ptrace (PTRACE_PEEKUSER, tid, PT_MSR * 8, 0);
|
|
|
|
|
+ if (errno == 0 && msr < 0)
|
|
|
|
|
+ wordsize = 8;
|
|
|
|
|
+#endif
|
|
|
|
|
+
|
|
|
|
|
+ return wordsize;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static int
|
|
|
|
|
+ppc_linux_auxv_parse (struct target_ops *ops, gdb_byte **readptr,
|
|
|
|
|
+ gdb_byte *endptr, CORE_ADDR *typep, CORE_ADDR *valp)
|
|
|
|
|
+{
|
|
|
|
|
+ int sizeof_auxv_field = ppc_linux_target_wordsize ();
|
|
|
|
|
+ gdb_byte *ptr = *readptr;
|
|
|
|
|
+
|
|
|
|
|
+ if (endptr == ptr)
|
|
|
|
|
+ return 0;
|
|
|
|
|
+
|
|
|
|
|
+ if (endptr - ptr < sizeof_auxv_field * 2)
|
|
|
|
|
+ return -1;
|
|
|
|
|
+
|
|
|
|
|
+ *typep = extract_unsigned_integer (ptr, sizeof_auxv_field);
|
|
|
|
|
+ ptr += sizeof_auxv_field;
|
|
|
|
|
+ *valp = extract_unsigned_integer (ptr, sizeof_auxv_field);
|
|
|
|
|
+ ptr += sizeof_auxv_field;
|
|
|
|
|
+
|
|
|
|
|
+ *readptr = ptr;
|
|
|
|
|
+ return 1;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
static const struct target_desc *
|
|
|
|
|
ppc_linux_read_description (struct target_ops *ops)
|
|
|
|
|
{
|
2008-11-20 15:44:10 +00:00
|
|
|
|
int altivec = 0;
|
|
|
|
|
int vsx = 0;
|
|
|
|
|
int isa205 = 0;
|
|
|
|
|
+ int cell = 0;
|
|
|
|
|
|
|
|
|
|
int tid = TIDGET (inferior_ptid);
|
|
|
|
|
if (tid == 0)
|
2009-01-22 17:17:17 +00:00
|
|
|
|
@@ -1291,26 +1340,24 @@ ppc_linux_read_description (struct targe
|
2008-11-20 15:44:10 +00:00
|
|
|
|
if (ppc_linux_get_hwcap () & PPC_FEATURE_ARCH_2_05)
|
|
|
|
|
isa205 = 1;
|
|
|
|
|
|
2009-01-22 17:17:17 +00:00
|
|
|
|
- /* Check for 64-bit inferior process. This is the case when the host is
|
|
|
|
|
- 64-bit, and in addition the top bit of the MSR register is set. */
|
|
|
|
|
-#ifdef __powerpc64__
|
|
|
|
|
- {
|
|
|
|
|
- long msr;
|
|
|
|
|
- errno = 0;
|
|
|
|
|
- msr = (long) ptrace (PTRACE_PEEKUSER, tid, PT_MSR * 8, 0);
|
|
|
|
|
- if (errno == 0 && msr < 0)
|
|
|
|
|
- {
|
|
|
|
|
- if (vsx)
|
|
|
|
|
- return isa205? tdesc_powerpc_isa205_vsx64l : tdesc_powerpc_vsx64l;
|
|
|
|
|
- else if (altivec)
|
|
|
|
|
- return isa205? tdesc_powerpc_isa205_altivec64l : tdesc_powerpc_altivec64l;
|
2008-11-20 15:44:10 +00:00
|
|
|
|
+ if (ppc_linux_get_hwcap () & PPC_FEATURE_CELL)
|
|
|
|
|
+ cell = 1;
|
2009-01-22 17:17:17 +00:00
|
|
|
|
|
|
|
|
|
- return isa205? tdesc_powerpc_isa205_64l : tdesc_powerpc_64l;
|
|
|
|
|
- }
|
|
|
|
|
- }
|
|
|
|
|
-#endif
|
|
|
|
|
+ if (ppc_linux_target_wordsize () == 8)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (cell)
|
|
|
|
|
+ return tdesc_powerpc_cell64l;
|
|
|
|
|
+ else if (vsx)
|
|
|
|
|
+ return isa205? tdesc_powerpc_isa205_vsx64l : tdesc_powerpc_vsx64l;
|
|
|
|
|
+ else if (altivec)
|
|
|
|
|
+ return isa205? tdesc_powerpc_isa205_altivec64l : tdesc_powerpc_altivec64l;
|
2008-11-20 15:44:10 +00:00
|
|
|
|
+
|
2009-01-22 17:17:17 +00:00
|
|
|
|
+ return isa205? tdesc_powerpc_isa205_64l : tdesc_powerpc_64l;
|
|
|
|
|
+ }
|
2008-11-07 14:07:25 +00:00
|
|
|
|
|
|
|
|
|
- if (vsx)
|
2008-11-20 15:44:10 +00:00
|
|
|
|
+ if (cell)
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ return tdesc_powerpc_cell32l;
|
|
|
|
|
+ else if (vsx)
|
2008-11-20 15:44:10 +00:00
|
|
|
|
return isa205? tdesc_powerpc_isa205_vsx32l : tdesc_powerpc_vsx32l;
|
2008-11-07 14:07:25 +00:00
|
|
|
|
else if (altivec)
|
2008-11-20 15:44:10 +00:00
|
|
|
|
return isa205? tdesc_powerpc_isa205_altivec32l : tdesc_powerpc_altivec32l;
|
2009-01-22 17:17:17 +00:00
|
|
|
|
@@ -1342,6 +1389,7 @@ _initialize_ppc_linux_nat (void)
|
|
|
|
|
t->to_watchpoint_addr_within_range = ppc_linux_watchpoint_addr_within_range;
|
|
|
|
|
|
|
|
|
|
t->to_read_description = ppc_linux_read_description;
|
|
|
|
|
+ t->to_auxv_parse = ppc_linux_auxv_parse;
|
|
|
|
|
|
|
|
|
|
/* Register the target. */
|
|
|
|
|
linux_nat_add_target (t);
|
2008-11-20 15:44:10 +00:00
|
|
|
|
--- gdb/ppc-linux-tdep.c
|
|
|
|
|
+++ gdb/ppc-linux-tdep.c
|
2008-11-07 14:07:25 +00:00
|
|
|
|
@@ -38,12 +38,20 @@
|
|
|
|
|
#include "trad-frame.h"
|
|
|
|
|
#include "frame-unwind.h"
|
|
|
|
|
#include "tramp-frame.h"
|
|
|
|
|
+#include "observer.h"
|
|
|
|
|
+#include "auxv.h"
|
|
|
|
|
+#include "elf/common.h"
|
|
|
|
|
+#include "exceptions.h"
|
|
|
|
|
+#include "arch-utils.h"
|
|
|
|
|
+#include "spu-tdep.h"
|
|
|
|
|
|
|
|
|
|
#include "features/rs6000/powerpc-32l.c"
|
|
|
|
|
#include "features/rs6000/powerpc-altivec32l.c"
|
|
|
|
|
+#include "features/rs6000/powerpc-cell32l.c"
|
|
|
|
|
#include "features/rs6000/powerpc-vsx32l.c"
|
2008-11-20 15:44:10 +00:00
|
|
|
|
#include "features/rs6000/powerpc-isa205-32l.c"
|
|
|
|
|
#include "features/rs6000/powerpc-isa205-altivec32l.c"
|
|
|
|
|
+#include "features/rs6000/powerpc-cell64l.c"
|
|
|
|
|
#include "features/rs6000/powerpc-isa205-vsx32l.c"
|
2008-11-07 14:07:25 +00:00
|
|
|
|
#include "features/rs6000/powerpc-64l.c"
|
|
|
|
|
#include "features/rs6000/powerpc-altivec64l.c"
|
2008-11-20 15:44:10 +00:00
|
|
|
|
@@ -995,6 +1003,46 @@ static struct tramp_frame ppc64_linux_si
|
2008-11-07 14:07:25 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+/* Address to use for displaced stepping. When debugging a stand-alone
|
|
|
|
|
+ SPU executable, entry_point_address () will point to an SPU local-store
|
|
|
|
|
+ address and is thus not usable as displaced stepping location. We use
|
|
|
|
|
+ the auxiliary vector to determine the PowerPC-side entry point address
|
|
|
|
|
+ instead. */
|
|
|
|
|
+
|
|
|
|
|
+static CORE_ADDR ppc_linux_entry_point_addr = 0;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
|
|
|
|
+static void
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ppc_linux_inferior_created (struct target_ops *target, int from_tty)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+{
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ ppc_linux_entry_point_addr = 0;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+}
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+static CORE_ADDR
|
|
|
|
|
+ppc_linux_displaced_step_location (struct gdbarch *gdbarch)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+{
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ if (ppc_linux_entry_point_addr == 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ CORE_ADDR addr;
|
|
|
|
|
+
|
|
|
|
|
+ /* Determine entry point from target auxiliary vector. */
|
|
|
|
|
+ if (target_auxv_search (¤t_target, AT_ENTRY, &addr) <= 0)
|
|
|
|
|
+ error (_("Cannot find AT_ENTRY auxiliary vector entry."));
|
|
|
|
|
+
|
|
|
|
|
+ /* Make certain that the address points at real code, and not a
|
|
|
|
|
+ function descriptor. */
|
|
|
|
|
+ addr = gdbarch_convert_from_func_ptr_addr (gdbarch, addr,
|
|
|
|
|
+ ¤t_target);
|
|
|
|
|
+
|
|
|
|
|
+ /* Inferior calls also use the entry point as a breakpoint location.
|
|
|
|
|
+ We don't want displaced stepping to interfere with those
|
|
|
|
|
+ breakpoints, so leave space. */
|
|
|
|
|
+ ppc_linux_entry_point_addr = addr + 2 * PPC_INSN_SIZE;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return ppc_linux_entry_point_addr;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
/* Return 1 if PPC_ORIG_R3_REGNUM and PPC_TRAP_REGNUM are usable. */
|
|
|
|
|
int
|
|
|
|
|
ppc_linux_trap_reg_p (struct gdbarch *gdbarch)
|
2008-11-20 15:44:10 +00:00
|
|
|
|
@@ -1028,11 +1076,18 @@ ppc_linux_write_pc (struct regcache *reg
|
2008-11-07 14:07:25 +00:00
|
|
|
|
regcache_cooked_write_unsigned (regcache, PPC_TRAP_REGNUM, -1);
|
|
|
|
|
}
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+static int
|
|
|
|
|
+ppc_linux_spu_section (bfd *abfd, asection *asect, void *user_data)
|
|
|
|
|
+{
|
|
|
|
|
+ return strncmp (bfd_section_name (abfd, asect), "SPU/", 4) == 0;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
static const struct target_desc *
|
|
|
|
|
ppc_linux_core_read_description (struct gdbarch *gdbarch,
|
|
|
|
|
struct target_ops *target,
|
|
|
|
|
bfd *abfd)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
{
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ asection *cell = bfd_sections_find_if (abfd, ppc_linux_spu_section, NULL);
|
|
|
|
|
asection *altivec = bfd_get_section_by_name (abfd, ".reg-ppc-vmx");
|
|
|
|
|
asection *vsx = bfd_get_section_by_name (abfd, ".reg-ppc-vsx");
|
|
|
|
|
asection *section = bfd_get_section_by_name (abfd, ".reg");
|
2008-11-20 15:44:10 +00:00
|
|
|
|
@@ -1042,7 +1097,9 @@ ppc_linux_core_read_description (struct
|
2008-11-07 14:07:25 +00:00
|
|
|
|
switch (bfd_section_size (abfd, section))
|
|
|
|
|
{
|
|
|
|
|
case 48 * 4:
|
|
|
|
|
- if (vsx)
|
|
|
|
|
+ if (cell)
|
|
|
|
|
+ return tdesc_powerpc_cell32l;
|
|
|
|
|
+ else if (vsx)
|
|
|
|
|
return tdesc_powerpc_vsx32l;
|
|
|
|
|
else if (altivec)
|
|
|
|
|
return tdesc_powerpc_altivec32l;
|
2008-11-20 15:44:10 +00:00
|
|
|
|
@@ -1050,7 +1107,9 @@ ppc_linux_core_read_description (struct
|
2008-11-07 14:07:25 +00:00
|
|
|
|
return tdesc_powerpc_32l;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
case 48 * 8:
|
|
|
|
|
- if (vsx)
|
|
|
|
|
+ if (cell)
|
|
|
|
|
+ return tdesc_powerpc_cell64l;
|
|
|
|
|
+ else if (vsx)
|
|
|
|
|
return tdesc_powerpc_vsx64l;
|
|
|
|
|
else if (altivec)
|
|
|
|
|
return tdesc_powerpc_altivec64l;
|
2008-11-20 15:44:10 +00:00
|
|
|
|
@@ -1062,6 +1121,249 @@ ppc_linux_core_read_description (struct
|
2008-11-07 14:07:25 +00:00
|
|
|
|
}
|
2008-09-12 23:16:14 +00:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+/* Cell/B.E. active SPE context tracking support. */
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+static CORE_ADDR spe_context_lm_addr = 0;
|
|
|
|
|
+static CORE_ADDR spe_context_offset = 0;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+static ptid_t spe_context_cache_ptid;
|
|
|
|
|
+static CORE_ADDR spe_context_cache_address;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+/* Callback for new objfiles. We check whether we've loaded a version
|
|
|
|
|
+ of libspe2 that provides the __spe_current_active_context variable. */
|
|
|
|
|
+static void
|
|
|
|
|
+ppc_linux_new_objfile (struct objfile *objfile)
|
|
|
|
|
+{
|
|
|
|
|
+ struct minimal_symbol *sym;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ if (!objfile)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+ {
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ spe_context_lm_addr = 0;
|
|
|
|
|
+ spe_context_offset = 0;
|
|
|
|
|
+ spe_context_cache_ptid = minus_one_ptid;
|
|
|
|
|
+ spe_context_cache_address = 0;
|
|
|
|
|
+ return;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+ }
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ sym = lookup_minimal_symbol ("__spe_current_active_context", NULL, objfile);
|
|
|
|
|
+ if (sym)
|
|
|
|
|
+ {
|
|
|
|
|
+ spe_context_lm_addr = svr4_fetch_objfile_link_map (objfile);
|
|
|
|
|
+ spe_context_offset = SYMBOL_VALUE_ADDRESS (sym);
|
|
|
|
|
+ spe_context_cache_ptid = minus_one_ptid;
|
|
|
|
|
+ spe_context_cache_address = 0;
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+}
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+/* Retrieve contents of the N'th element in the current thread's
|
|
|
|
|
+ linked SPE context list into ID and NPC. Return the address of
|
|
|
|
|
+ said context element, or 0 if not found. */
|
|
|
|
|
+static CORE_ADDR
|
|
|
|
|
+ppc_linux_spe_context (int wordsize, int n, int *id, unsigned int *npc)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+{
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ CORE_ADDR spe_context = 0;
|
|
|
|
|
+ gdb_byte buf[16];
|
|
|
|
|
+ int i;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* Quick exit if we have not found __spe_current_active_context. */
|
|
|
|
|
+ if (!spe_context_lm_addr)
|
|
|
|
|
+ return 0;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* Look up cached address of thread-local variable. */
|
|
|
|
|
+ if (!ptid_equal (spe_context_cache_ptid, inferior_ptid))
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+ {
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ volatile struct gdb_exception ex;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ if (!target_get_thread_local_address_p ())
|
|
|
|
|
+ return 0;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ TRY_CATCH (ex, RETURN_MASK_ERROR)
|
|
|
|
|
+ {
|
|
|
|
|
+ spe_context_cache_address
|
|
|
|
|
+ = target_get_thread_local_address
|
|
|
|
|
+ (inferior_ptid, spe_context_lm_addr, spe_context_offset);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ spe_context_cache_ptid = inferior_ptid;
|
|
|
|
|
+ }
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ if (ex.reason < 0)
|
|
|
|
|
+ return 0;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+ }
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* Read variable value. */
|
|
|
|
|
+ if (target_read_memory (spe_context_cache_address, buf, wordsize) == 0)
|
|
|
|
|
+ spe_context = extract_unsigned_integer (buf, wordsize);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* Cyle through to N'th linked list element. */
|
|
|
|
|
+ for (i = 0; i < n && spe_context; i++)
|
|
|
|
|
+ if (target_read_memory (spe_context + align_up (12, wordsize),
|
|
|
|
|
+ buf, wordsize) == 0)
|
|
|
|
|
+ spe_context = extract_unsigned_integer (buf, wordsize);
|
|
|
|
|
+ else
|
|
|
|
|
+ spe_context = 0;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* Read current context. */
|
|
|
|
|
+ if (spe_context
|
|
|
|
|
+ && target_read_memory (spe_context, buf, 12) != 0)
|
|
|
|
|
+ spe_context = 0;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* Extract data elements. */
|
|
|
|
|
+ if (spe_context)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (id)
|
|
|
|
|
+ *id = extract_signed_integer (buf, 4);
|
|
|
|
|
+ if (npc)
|
|
|
|
|
+ *npc = extract_unsigned_integer (buf + 4, 4);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return spe_context;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+/* Cell/B.E. cross-architecture unwinder support. */
|
|
|
|
|
+
|
|
|
|
|
+struct ppu2spu_cache
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+{
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ struct frame_id frame_id;
|
|
|
|
|
+ struct regcache *regcache;
|
|
|
|
|
+};
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+static struct gdbarch *
|
|
|
|
|
+ppu2spu_prev_arch (struct frame_info *this_frame, void **this_cache)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+{
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ struct ppu2spu_cache *cache = *this_cache;
|
|
|
|
|
+ return get_regcache_arch (cache->regcache);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static void
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ppu2spu_this_id (struct frame_info *this_frame,
|
|
|
|
|
+ void **this_cache, struct frame_id *this_id)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+{
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ struct ppu2spu_cache *cache = *this_cache;
|
|
|
|
|
+ *this_id = cache->frame_id;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+}
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+static struct value *
|
|
|
|
|
+ppu2spu_prev_register (struct frame_info *this_frame,
|
|
|
|
|
+ void **this_cache, int regnum)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+{
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ struct ppu2spu_cache *cache = *this_cache;
|
|
|
|
|
+ struct gdbarch *gdbarch = get_regcache_arch (cache->regcache);
|
|
|
|
|
+ gdb_byte *buf;
|
|
|
|
|
+
|
|
|
|
|
+ buf = alloca (register_size (gdbarch, regnum));
|
|
|
|
|
+ regcache_cooked_read (cache->regcache, regnum, buf);
|
|
|
|
|
+ return frame_unwind_got_bytes (this_frame, regnum, buf);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+}
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+struct ppu2spu_data
|
|
|
|
|
+{
|
|
|
|
|
+ int id;
|
|
|
|
|
+ unsigned int npc;
|
|
|
|
|
+ gdb_byte gprs[128*16];
|
|
|
|
|
+};
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+static int
|
|
|
|
|
+ppu2spu_unwind_register (void *src, int regnum, gdb_byte *buf)
|
|
|
|
|
+{
|
|
|
|
|
+ struct ppu2spu_data *data = src;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ if (regnum >= 0 && regnum < SPU_NUM_GPRS)
|
|
|
|
|
+ memcpy (buf, data->gprs + 16*regnum, 16);
|
|
|
|
|
+ else if (regnum == SPU_ID_REGNUM)
|
|
|
|
|
+ store_unsigned_integer (buf, 4, data->id);
|
|
|
|
|
+ else if (regnum == SPU_PC_REGNUM)
|
|
|
|
|
+ store_unsigned_integer (buf, 4, data->npc);
|
|
|
|
|
+ else
|
|
|
|
|
+ return 0;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ return 1;
|
|
|
|
|
+}
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+static int
|
|
|
|
|
+ppu2spu_sniffer (const struct frame_unwind *self,
|
|
|
|
|
+ struct frame_info *this_frame, void **this_prologue_cache)
|
|
|
|
|
+{
|
|
|
|
|
+ struct gdbarch *gdbarch = get_frame_arch (this_frame);
|
|
|
|
|
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
|
|
|
|
|
+ struct ppu2spu_data data;
|
|
|
|
|
+ struct frame_info *fi;
|
|
|
|
|
+ CORE_ADDR base, func, backchain, spe_context;
|
|
|
|
|
+ gdb_byte buf[8];
|
|
|
|
|
+ int n = 0;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* Count the number of SPU contexts already in the frame chain. */
|
|
|
|
|
+ for (fi = get_next_frame (this_frame); fi; fi = get_next_frame (fi))
|
|
|
|
|
+ if (get_frame_type (fi) == ARCH_FRAME
|
|
|
|
|
+ && gdbarch_bfd_arch_info (get_frame_arch (fi))->arch == bfd_arch_spu)
|
|
|
|
|
+ n++;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ base = get_frame_sp (this_frame);
|
|
|
|
|
+ func = get_frame_pc (this_frame);
|
|
|
|
|
+ if (target_read_memory (base, buf, tdep->wordsize))
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ backchain = extract_unsigned_integer (buf, tdep->wordsize);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ spe_context = ppc_linux_spe_context (tdep->wordsize, n, &data.id, &data.npc);
|
|
|
|
|
+ if (spe_context && base <= spe_context && spe_context < backchain)
|
|
|
|
|
+ {
|
|
|
|
|
+ struct gdbarch *spu_gdbarch;
|
|
|
|
|
+ char annex[32];
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* Find gdbarch for SPU. */
|
|
|
|
|
+ struct gdbarch_info info;
|
|
|
|
|
+ gdbarch_info_init (&info);
|
|
|
|
|
+ info.bfd_arch_info = bfd_lookup_arch (bfd_arch_spu, bfd_mach_spu);
|
|
|
|
|
+ info.byte_order = BFD_ENDIAN_BIG;
|
|
|
|
|
+ info.osabi = GDB_OSABI_LINUX;
|
|
|
|
|
+ info.tdep_info = (void *) &data.id;
|
|
|
|
|
+ spu_gdbarch = gdbarch_find_by_info (info);
|
|
|
|
|
+ if (!spu_gdbarch)
|
|
|
|
|
+ return 0;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ xsnprintf (annex, sizeof annex, "%d/regs", data.id);
|
|
|
|
|
+ if (target_read (¤t_target, TARGET_OBJECT_SPU, annex,
|
|
|
|
|
+ data.gprs, 0, sizeof data.gprs)
|
|
|
|
|
+ == sizeof data.gprs)
|
|
|
|
|
+ {
|
|
|
|
|
+ struct ppu2spu_cache *cache
|
|
|
|
|
+ = FRAME_OBSTACK_CALLOC (1, struct ppu2spu_cache);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ struct regcache *regcache = regcache_xmalloc (spu_gdbarch);
|
|
|
|
|
+ struct cleanup *cleanups = make_cleanup_regcache_xfree (regcache);
|
|
|
|
|
+ regcache_save (regcache, ppu2spu_unwind_register, &data);
|
|
|
|
|
+ discard_cleanups (cleanups);
|
|
|
|
|
+
|
|
|
|
|
+ cache->frame_id = frame_id_build (base, func);
|
|
|
|
|
+ cache->regcache = regcache;
|
|
|
|
|
+ *this_prologue_cache = cache;
|
|
|
|
|
+ return 1;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
|
|
|
|
+static void
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ppu2spu_dealloc_cache (struct frame_info *self, void *this_cache)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+{
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ struct ppu2spu_cache *cache = this_cache;
|
|
|
|
|
+ regcache_xfree (cache->regcache);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+}
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+static const struct frame_unwind ppu2spu_unwind = {
|
|
|
|
|
+ ARCH_FRAME,
|
|
|
|
|
+ ppu2spu_this_id,
|
|
|
|
|
+ ppu2spu_prev_register,
|
|
|
|
|
+ NULL,
|
|
|
|
|
+ ppu2spu_sniffer,
|
|
|
|
|
+ ppu2spu_dealloc_cache,
|
|
|
|
|
+ ppu2spu_prev_arch,
|
|
|
|
|
+};
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
static void
|
|
|
|
|
ppc_linux_init_abi (struct gdbarch_info info,
|
|
|
|
|
struct gdbarch *gdbarch)
|
2008-11-20 15:44:10 +00:00
|
|
|
|
@@ -1102,6 +1404,12 @@ ppc_linux_init_abi (struct gdbarch_info
|
2008-11-07 14:07:25 +00:00
|
|
|
|
/* Trampolines. */
|
|
|
|
|
tramp_frame_prepend_unwinder (gdbarch, &ppc32_linux_sigaction_tramp_frame);
|
|
|
|
|
tramp_frame_prepend_unwinder (gdbarch, &ppc32_linux_sighandler_tramp_frame);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* BFD target for core files. */
|
|
|
|
|
+ if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_LITTLE)
|
|
|
|
|
+ set_gdbarch_gcore_bfd_target (gdbarch, "elf32-powerpcle");
|
|
|
|
|
+ else
|
|
|
|
|
+ set_gdbarch_gcore_bfd_target (gdbarch, "elf32-powerpc");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (tdep->wordsize == 8)
|
2008-11-20 15:44:10 +00:00
|
|
|
|
@@ -1119,6 +1427,12 @@ ppc_linux_init_abi (struct gdbarch_info
|
2008-11-07 14:07:25 +00:00
|
|
|
|
/* Trampolines. */
|
|
|
|
|
tramp_frame_prepend_unwinder (gdbarch, &ppc64_linux_sigaction_tramp_frame);
|
|
|
|
|
tramp_frame_prepend_unwinder (gdbarch, &ppc64_linux_sighandler_tramp_frame);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* BFD target for core files. */
|
|
|
|
|
+ if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_LITTLE)
|
|
|
|
|
+ set_gdbarch_gcore_bfd_target (gdbarch, "elf64-powerpcle");
|
|
|
|
|
+ else
|
|
|
|
|
+ set_gdbarch_gcore_bfd_target (gdbarch, "elf64-powerpc");
|
|
|
|
|
}
|
|
|
|
|
set_gdbarch_regset_from_core_section (gdbarch, ppc_linux_regset_from_core_section);
|
|
|
|
|
set_gdbarch_core_read_description (gdbarch, ppc_linux_core_read_description);
|
2008-11-20 15:44:10 +00:00
|
|
|
|
@@ -1158,6 +1472,22 @@ ppc_linux_init_abi (struct gdbarch_info
|
2008-11-07 14:07:25 +00:00
|
|
|
|
PPC_TRAP_REGNUM, "trap");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ /* Enable Cell/B.E. if supported by the target. */
|
|
|
|
|
+ if (tdesc_compatible_p (info.target_desc,
|
|
|
|
|
+ bfd_lookup_arch (bfd_arch_spu, bfd_mach_spu)))
|
|
|
|
|
+ {
|
|
|
|
|
+ /* Cell/B.E. multi-architecture support. */
|
|
|
|
|
+ set_spu_solib_ops (gdbarch);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* Cell/B.E. cross-architecture unwinder support. */
|
|
|
|
|
+ frame_unwind_prepend_unwinder (gdbarch, &ppu2spu_unwind);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* The default displaced_step_at_entry_point doesn't work for
|
|
|
|
|
+ SPU stand-alone executables. */
|
|
|
|
|
+ set_gdbarch_displaced_step_location (gdbarch,
|
|
|
|
|
+ ppc_linux_displaced_step_location);
|
|
|
|
|
+ }
|
2008-09-12 23:16:14 +00:00
|
|
|
|
}
|
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
void
|
2008-11-20 15:44:10 +00:00
|
|
|
|
@@ -1172,15 +1502,23 @@ _initialize_ppc_linux_tdep (void)
|
2008-11-07 14:07:25 +00:00
|
|
|
|
gdbarch_register_osabi (bfd_arch_rs6000, bfd_mach_rs6k, GDB_OSABI_LINUX,
|
|
|
|
|
ppc_linux_init_abi);
|
|
|
|
|
|
|
|
|
|
+ /* Attach to inferior_created observer. */
|
|
|
|
|
+ observer_attach_inferior_created (ppc_linux_inferior_created);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* Add ourselves to objfile event chain. */
|
|
|
|
|
+ observer_attach_new_objfile (ppc_linux_new_objfile);
|
|
|
|
|
+
|
|
|
|
|
/* Initialize the Linux target descriptions. */
|
|
|
|
|
initialize_tdesc_powerpc_32l ();
|
|
|
|
|
initialize_tdesc_powerpc_altivec32l ();
|
|
|
|
|
+ initialize_tdesc_powerpc_cell32l ();
|
|
|
|
|
initialize_tdesc_powerpc_vsx32l ();
|
2008-11-20 15:44:10 +00:00
|
|
|
|
initialize_tdesc_powerpc_isa205_32l ();
|
|
|
|
|
initialize_tdesc_powerpc_isa205_altivec32l ();
|
|
|
|
|
initialize_tdesc_powerpc_isa205_vsx32l ();
|
2008-11-07 14:07:25 +00:00
|
|
|
|
initialize_tdesc_powerpc_64l ();
|
|
|
|
|
initialize_tdesc_powerpc_altivec64l ();
|
|
|
|
|
+ initialize_tdesc_powerpc_cell64l ();
|
|
|
|
|
initialize_tdesc_powerpc_vsx64l ();
|
2008-11-20 15:44:10 +00:00
|
|
|
|
initialize_tdesc_powerpc_isa205_64l ();
|
|
|
|
|
initialize_tdesc_powerpc_isa205_altivec64l ();
|
|
|
|
|
--- gdb/ppc-linux-tdep.h
|
|
|
|
|
+++ gdb/ppc-linux-tdep.h
|
|
|
|
|
@@ -41,6 +41,7 @@ int ppc_linux_trap_reg_p (struct gdbarch
|
2008-11-07 14:07:25 +00:00
|
|
|
|
/* Linux target descriptions. */
|
|
|
|
|
extern struct target_desc *tdesc_powerpc_32l;
|
|
|
|
|
extern struct target_desc *tdesc_powerpc_altivec32l;
|
|
|
|
|
+extern struct target_desc *tdesc_powerpc_cell32l;
|
|
|
|
|
extern struct target_desc *tdesc_powerpc_vsx32l;
|
2008-11-20 15:44:10 +00:00
|
|
|
|
extern struct target_desc *tdesc_powerpc_isa205_32l;
|
|
|
|
|
extern struct target_desc *tdesc_powerpc_isa205_altivec32l;
|
|
|
|
|
@@ -48,6 +49,7 @@ extern struct target_desc *tdesc_powerpc
|
2008-11-07 14:07:25 +00:00
|
|
|
|
extern struct target_desc *tdesc_powerpc_e500l;
|
|
|
|
|
extern struct target_desc *tdesc_powerpc_64l;
|
|
|
|
|
extern struct target_desc *tdesc_powerpc_altivec64l;
|
|
|
|
|
+extern struct target_desc *tdesc_powerpc_cell64l;
|
|
|
|
|
extern struct target_desc *tdesc_powerpc_vsx64l;
|
2008-11-20 15:44:10 +00:00
|
|
|
|
extern struct target_desc *tdesc_powerpc_isa205_64l;
|
|
|
|
|
extern struct target_desc *tdesc_powerpc_isa205_altivec64l;
|
|
|
|
|
--- gdb/printcmd.c
|
|
|
|
|
+++ gdb/printcmd.c
|
2008-11-07 14:07:25 +00:00
|
|
|
|
@@ -386,7 +386,7 @@ print_scalar_formatted (const void *vala
|
|
|
|
|
/* If we are printing it as unsigned, truncate it in case it is actually
|
|
|
|
|
a negative signed value (e.g. "print/u (short)-1" should print 65535
|
|
|
|
|
(if shorts are 16 bits) instead of 4294967295). */
|
|
|
|
|
- if (options->format != 'd')
|
|
|
|
|
+ if (options->format != 'd' || TYPE_UNSIGNED (type))
|
2008-09-12 23:16:14 +00:00
|
|
|
|
{
|
2008-11-07 14:07:25 +00:00
|
|
|
|
if (len < sizeof (LONGEST))
|
|
|
|
|
val_long &= ((LONGEST) 1 << HOST_CHAR_BIT * len) - 1;
|
2008-11-20 15:44:10 +00:00
|
|
|
|
--- gdb/proc-service.c
|
|
|
|
|
+++ gdb/proc-service.c
|
2009-01-19 00:46:30 +00:00
|
|
|
|
@@ -258,7 +258,7 @@ ps_lgetregs (gdb_ps_prochandle_t ph, lwp
|
2008-11-07 14:07:25 +00:00
|
|
|
|
struct regcache *regcache;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
inferior_ptid = BUILD_LWP (lwpid, ph->pid);
|
|
|
|
|
- regcache = get_thread_regcache (inferior_ptid);
|
|
|
|
|
+ regcache = get_thread_arch_regcache (inferior_ptid, target_gdbarch);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
target_fetch_registers (regcache, -1);
|
|
|
|
|
fill_gregset (regcache, (gdb_gregset_t *) gregset, -1);
|
2009-01-19 00:46:30 +00:00
|
|
|
|
@@ -277,7 +277,7 @@ ps_lsetregs (gdb_ps_prochandle_t ph, lwp
|
2008-11-07 14:07:25 +00:00
|
|
|
|
struct regcache *regcache;
|
|
|
|
|
|
|
|
|
|
inferior_ptid = BUILD_LWP (lwpid, ph->pid);
|
|
|
|
|
- regcache = get_thread_regcache (inferior_ptid);
|
|
|
|
|
+ regcache = get_thread_arch_regcache (inferior_ptid, target_gdbarch);
|
|
|
|
|
|
|
|
|
|
supply_gregset (regcache, (const gdb_gregset_t *) gregset);
|
|
|
|
|
target_store_registers (regcache, -1);
|
2009-01-19 00:46:30 +00:00
|
|
|
|
@@ -297,7 +297,7 @@ ps_lgetfpregs (gdb_ps_prochandle_t ph, l
|
2008-11-07 14:07:25 +00:00
|
|
|
|
struct regcache *regcache;
|
|
|
|
|
|
|
|
|
|
inferior_ptid = BUILD_LWP (lwpid, ph->pid);
|
|
|
|
|
- regcache = get_thread_regcache (inferior_ptid);
|
|
|
|
|
+ regcache = get_thread_arch_regcache (inferior_ptid, target_gdbarch);
|
|
|
|
|
|
|
|
|
|
target_fetch_registers (regcache, -1);
|
|
|
|
|
fill_fpregset (regcache, (gdb_fpregset_t *) fpregset, -1);
|
2009-01-19 00:46:30 +00:00
|
|
|
|
@@ -317,7 +317,7 @@ ps_lsetfpregs (gdb_ps_prochandle_t ph, l
|
2008-11-07 14:07:25 +00:00
|
|
|
|
struct regcache *regcache;
|
|
|
|
|
|
|
|
|
|
inferior_ptid = BUILD_LWP (lwpid, ph->pid);
|
|
|
|
|
- regcache = get_thread_regcache (inferior_ptid);
|
|
|
|
|
+ regcache = get_thread_arch_regcache (inferior_ptid, target_gdbarch);
|
|
|
|
|
|
|
|
|
|
supply_fpregset (regcache, (const gdb_fpregset_t *) fpregset);
|
|
|
|
|
target_store_registers (regcache, -1);
|
2008-11-20 15:44:10 +00:00
|
|
|
|
--- gdb/regcache.c
|
|
|
|
|
+++ gdb/regcache.c
|
2008-11-07 14:07:25 +00:00
|
|
|
|
@@ -29,6 +29,7 @@
|
|
|
|
|
#include "gdb_string.h"
|
|
|
|
|
#include "gdbcmd.h" /* For maintenanceprintlist. */
|
|
|
|
|
#include "observer.h"
|
|
|
|
|
+#include "arch-utils.h"
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* DATA STRUCTURE
|
|
|
|
|
@@ -410,36 +411,60 @@ regcache_invalidate (struct regcache *re
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Global structure containing the current regcache. */
|
|
|
|
|
-/* FIXME: cagney/2002-05-11: The two global arrays registers[] and
|
|
|
|
|
- deprecated_register_valid[] currently point into this structure. */
|
|
|
|
|
-static struct regcache *current_regcache;
|
|
|
|
|
|
|
|
|
|
/* NOTE: this is a write-through cache. There is no "dirty" bit for
|
|
|
|
|
recording if the register values have been changed (eg. by the
|
|
|
|
|
user). Therefore all registers must be written back to the
|
|
|
|
|
target when appropriate. */
|
|
|
|
|
|
|
|
|
|
-struct regcache *get_thread_regcache (ptid_t ptid)
|
|
|
|
|
+struct regcache_list
|
|
|
|
|
{
|
|
|
|
|
- /* NOTE: uweigand/2007-05-05: We need to detect the thread's
|
|
|
|
|
- current architecture at this point. */
|
|
|
|
|
- struct gdbarch *thread_gdbarch = current_gdbarch;
|
|
|
|
|
+ struct regcache *regcache;
|
|
|
|
|
+ struct regcache_list *next;
|
|
|
|
|
+};
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+static struct regcache_list *current_regcache;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+struct regcache *
|
|
|
|
|
+get_thread_arch_regcache (ptid_t ptid, struct gdbarch *gdbarch)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+{
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ struct regcache_list *list;
|
|
|
|
|
+ struct regcache *new_regcache;
|
|
|
|
|
|
|
|
|
|
- if (current_regcache && ptid_equal (current_regcache->ptid, ptid)
|
|
|
|
|
- && get_regcache_arch (current_regcache) == thread_gdbarch)
|
|
|
|
|
- return current_regcache;
|
|
|
|
|
+ for (list = current_regcache; list; list = list->next)
|
|
|
|
|
+ if (ptid_equal (list->regcache->ptid, ptid)
|
|
|
|
|
+ && get_regcache_arch (list->regcache) == gdbarch)
|
|
|
|
|
+ return list->regcache;
|
|
|
|
|
|
|
|
|
|
- if (current_regcache)
|
|
|
|
|
- regcache_xfree (current_regcache);
|
|
|
|
|
+ new_regcache = regcache_xmalloc (gdbarch);
|
|
|
|
|
+ new_regcache->readonly_p = 0;
|
|
|
|
|
+ new_regcache->ptid = ptid;
|
|
|
|
|
|
|
|
|
|
- current_regcache = regcache_xmalloc (thread_gdbarch);
|
|
|
|
|
- current_regcache->readonly_p = 0;
|
|
|
|
|
- current_regcache->ptid = ptid;
|
|
|
|
|
+ list = xmalloc (sizeof (struct regcache_list));
|
|
|
|
|
+ list->regcache = new_regcache;
|
|
|
|
|
+ list->next = current_regcache;
|
|
|
|
|
+ current_regcache = list;
|
|
|
|
|
|
|
|
|
|
- return current_regcache;
|
|
|
|
|
+ return new_regcache;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
-struct regcache *get_current_regcache (void)
|
|
|
|
|
+static ptid_t current_thread_ptid;
|
|
|
|
|
+static struct gdbarch *current_thread_arch;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+struct regcache *
|
|
|
|
|
+get_thread_regcache (ptid_t ptid)
|
|
|
|
|
+{
|
|
|
|
|
+ if (!current_thread_arch || !ptid_equal (current_thread_ptid, ptid))
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+ {
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ current_thread_ptid = ptid;
|
|
|
|
|
+ current_thread_arch = target_thread_architecture (ptid);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+ }
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ return get_thread_arch_regcache (ptid, current_thread_arch);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+}
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+struct regcache *
|
|
|
|
|
+get_current_regcache (void)
|
|
|
|
|
{
|
|
|
|
|
return get_thread_regcache (inferior_ptid);
|
|
|
|
|
}
|
|
|
|
|
@@ -458,9 +483,11 @@ regcache_observer_target_changed (struct
|
|
|
|
|
static void
|
|
|
|
|
regcache_thread_ptid_changed (ptid_t old_ptid, ptid_t new_ptid)
|
|
|
|
|
{
|
|
|
|
|
- if (current_regcache != NULL
|
|
|
|
|
- && ptid_equal (current_regcache->ptid, old_ptid))
|
|
|
|
|
- current_regcache->ptid = new_ptid;
|
|
|
|
|
+ struct regcache_list *list;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ for (list = current_regcache; list; list = list->next)
|
|
|
|
|
+ if (ptid_equal (list->regcache->ptid, old_ptid))
|
|
|
|
|
+ list->regcache->ptid = new_ptid;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Low level examining and depositing of registers.
|
|
|
|
|
@@ -477,11 +504,20 @@ regcache_thread_ptid_changed (ptid_t old
|
|
|
|
|
void
|
|
|
|
|
registers_changed (void)
|
|
|
|
|
{
|
|
|
|
|
- int i;
|
|
|
|
|
+ struct regcache_list *list, *next;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ for (list = current_regcache; list; list = next)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+ {
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ next = list->next;
|
|
|
|
|
+ regcache_xfree (list->regcache);
|
|
|
|
|
+ xfree (list);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+ }
|
2008-11-07 14:07:25 +00:00
|
|
|
|
|
|
|
|
|
- regcache_xfree (current_regcache);
|
|
|
|
|
current_regcache = NULL;
|
|
|
|
|
|
|
|
|
|
+ current_thread_ptid = null_ptid;
|
|
|
|
|
+ current_thread_arch = NULL;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
/* Need to forget about any frames we have cached, too. */
|
|
|
|
|
reinit_frame_cache ();
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
@@ -509,6 +545,8 @@ regcache_raw_read (struct regcache *regc
|
|
|
|
|
{
|
|
|
|
|
struct cleanup *old_chain = save_inferior_ptid ();
|
|
|
|
|
inferior_ptid = regcache->ptid;
|
|
|
|
|
+ save_current_gdbarch ();
|
|
|
|
|
+ current_gdbarch = get_regcache_arch (regcache);
|
|
|
|
|
target_fetch_registers (regcache, regnum);
|
|
|
|
|
do_cleanups (old_chain);
|
|
|
|
|
}
|
|
|
|
|
@@ -667,6 +705,8 @@ regcache_raw_write (struct regcache *reg
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
old_chain = save_inferior_ptid ();
|
|
|
|
|
inferior_ptid = regcache->ptid;
|
|
|
|
|
+ save_current_gdbarch ();
|
|
|
|
|
+ current_gdbarch = get_regcache_arch (regcache);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
target_prepare_to_store (regcache);
|
|
|
|
|
memcpy (register_buffer (regcache, regnum), buf,
|
2008-11-20 15:44:10 +00:00
|
|
|
|
--- gdb/regcache.h
|
|
|
|
|
+++ gdb/regcache.h
|
2008-11-07 14:07:25 +00:00
|
|
|
|
@@ -26,6 +26,7 @@ struct gdbarch;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
extern struct regcache *get_current_regcache (void);
|
|
|
|
|
extern struct regcache *get_thread_regcache (ptid_t ptid);
|
|
|
|
|
+extern struct regcache *get_thread_arch_regcache (ptid_t, struct gdbarch *);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
void regcache_xfree (struct regcache *regcache);
|
|
|
|
|
struct cleanup *make_cleanup_regcache_xfree (struct regcache *regcache);
|
2008-11-20 15:44:10 +00:00
|
|
|
|
--- gdb/regformats/rs6000/powerpc-cell32l.dat
|
|
|
|
|
+++ gdb/regformats/rs6000/powerpc-cell32l.dat
|
2008-11-07 14:07:25 +00:00
|
|
|
|
@@ -0,0 +1,111 @@
|
|
|
|
|
+# DO NOT EDIT: generated from rs6000/powerpc-cell32l.xml
|
|
|
|
|
+name:powerpc_cell32l
|
|
|
|
|
+xmltarget:powerpc-cell32l.xml
|
|
|
|
|
+expedite:r1,pc,r0,orig_r3,r4
|
|
|
|
|
+32:r0
|
|
|
|
|
+32:r1
|
|
|
|
|
+32:r2
|
|
|
|
|
+32:r3
|
|
|
|
|
+32:r4
|
|
|
|
|
+32:r5
|
|
|
|
|
+32:r6
|
|
|
|
|
+32:r7
|
|
|
|
|
+32:r8
|
|
|
|
|
+32:r9
|
|
|
|
|
+32:r10
|
|
|
|
|
+32:r11
|
|
|
|
|
+32:r12
|
|
|
|
|
+32:r13
|
|
|
|
|
+32:r14
|
|
|
|
|
+32:r15
|
|
|
|
|
+32:r16
|
|
|
|
|
+32:r17
|
|
|
|
|
+32:r18
|
|
|
|
|
+32:r19
|
|
|
|
|
+32:r20
|
|
|
|
|
+32:r21
|
|
|
|
|
+32:r22
|
|
|
|
|
+32:r23
|
|
|
|
|
+32:r24
|
|
|
|
|
+32:r25
|
|
|
|
|
+32:r26
|
|
|
|
|
+32:r27
|
|
|
|
|
+32:r28
|
|
|
|
|
+32:r29
|
|
|
|
|
+32:r30
|
|
|
|
|
+32:r31
|
|
|
|
|
+64:f0
|
|
|
|
|
+64:f1
|
|
|
|
|
+64:f2
|
|
|
|
|
+64:f3
|
|
|
|
|
+64:f4
|
|
|
|
|
+64:f5
|
|
|
|
|
+64:f6
|
|
|
|
|
+64:f7
|
|
|
|
|
+64:f8
|
|
|
|
|
+64:f9
|
|
|
|
|
+64:f10
|
|
|
|
|
+64:f11
|
|
|
|
|
+64:f12
|
|
|
|
|
+64:f13
|
|
|
|
|
+64:f14
|
|
|
|
|
+64:f15
|
|
|
|
|
+64:f16
|
|
|
|
|
+64:f17
|
|
|
|
|
+64:f18
|
|
|
|
|
+64:f19
|
|
|
|
|
+64:f20
|
|
|
|
|
+64:f21
|
|
|
|
|
+64:f22
|
|
|
|
|
+64:f23
|
|
|
|
|
+64:f24
|
|
|
|
|
+64:f25
|
|
|
|
|
+64:f26
|
|
|
|
|
+64:f27
|
|
|
|
|
+64:f28
|
|
|
|
|
+64:f29
|
|
|
|
|
+64:f30
|
|
|
|
|
+64:f31
|
|
|
|
|
+32:pc
|
|
|
|
|
+32:msr
|
|
|
|
|
+32:cr
|
|
|
|
|
+32:lr
|
|
|
|
|
+32:ctr
|
|
|
|
|
+32:xer
|
|
|
|
|
+32:fpscr
|
|
|
|
|
+32:orig_r3
|
|
|
|
|
+32:trap
|
|
|
|
|
+128:vr0
|
|
|
|
|
+128:vr1
|
|
|
|
|
+128:vr2
|
|
|
|
|
+128:vr3
|
|
|
|
|
+128:vr4
|
|
|
|
|
+128:vr5
|
|
|
|
|
+128:vr6
|
|
|
|
|
+128:vr7
|
|
|
|
|
+128:vr8
|
|
|
|
|
+128:vr9
|
|
|
|
|
+128:vr10
|
|
|
|
|
+128:vr11
|
|
|
|
|
+128:vr12
|
|
|
|
|
+128:vr13
|
|
|
|
|
+128:vr14
|
|
|
|
|
+128:vr15
|
|
|
|
|
+128:vr16
|
|
|
|
|
+128:vr17
|
|
|
|
|
+128:vr18
|
|
|
|
|
+128:vr19
|
|
|
|
|
+128:vr20
|
|
|
|
|
+128:vr21
|
|
|
|
|
+128:vr22
|
|
|
|
|
+128:vr23
|
|
|
|
|
+128:vr24
|
|
|
|
|
+128:vr25
|
|
|
|
|
+128:vr26
|
|
|
|
|
+128:vr27
|
|
|
|
|
+128:vr28
|
|
|
|
|
+128:vr29
|
|
|
|
|
+128:vr30
|
|
|
|
|
+128:vr31
|
|
|
|
|
+32:vscr
|
|
|
|
|
+32:vrsave
|
2008-11-20 15:44:10 +00:00
|
|
|
|
--- gdb/regformats/rs6000/powerpc-cell64l.dat
|
|
|
|
|
+++ gdb/regformats/rs6000/powerpc-cell64l.dat
|
2008-11-07 14:07:25 +00:00
|
|
|
|
@@ -0,0 +1,111 @@
|
|
|
|
|
+# DO NOT EDIT: generated from rs6000/powerpc-cell64l.xml
|
|
|
|
|
+name:powerpc_cell64l
|
|
|
|
|
+xmltarget:powerpc-cell64l.xml
|
|
|
|
|
+expedite:r1,pc,r0,orig_r3,r4
|
|
|
|
|
+64:r0
|
|
|
|
|
+64:r1
|
|
|
|
|
+64:r2
|
|
|
|
|
+64:r3
|
|
|
|
|
+64:r4
|
|
|
|
|
+64:r5
|
|
|
|
|
+64:r6
|
|
|
|
|
+64:r7
|
|
|
|
|
+64:r8
|
|
|
|
|
+64:r9
|
|
|
|
|
+64:r10
|
|
|
|
|
+64:r11
|
|
|
|
|
+64:r12
|
|
|
|
|
+64:r13
|
|
|
|
|
+64:r14
|
|
|
|
|
+64:r15
|
|
|
|
|
+64:r16
|
|
|
|
|
+64:r17
|
|
|
|
|
+64:r18
|
|
|
|
|
+64:r19
|
|
|
|
|
+64:r20
|
|
|
|
|
+64:r21
|
|
|
|
|
+64:r22
|
|
|
|
|
+64:r23
|
|
|
|
|
+64:r24
|
|
|
|
|
+64:r25
|
|
|
|
|
+64:r26
|
|
|
|
|
+64:r27
|
|
|
|
|
+64:r28
|
|
|
|
|
+64:r29
|
|
|
|
|
+64:r30
|
|
|
|
|
+64:r31
|
|
|
|
|
+64:f0
|
|
|
|
|
+64:f1
|
|
|
|
|
+64:f2
|
|
|
|
|
+64:f3
|
|
|
|
|
+64:f4
|
|
|
|
|
+64:f5
|
|
|
|
|
+64:f6
|
|
|
|
|
+64:f7
|
|
|
|
|
+64:f8
|
|
|
|
|
+64:f9
|
|
|
|
|
+64:f10
|
|
|
|
|
+64:f11
|
|
|
|
|
+64:f12
|
|
|
|
|
+64:f13
|
|
|
|
|
+64:f14
|
|
|
|
|
+64:f15
|
|
|
|
|
+64:f16
|
|
|
|
|
+64:f17
|
|
|
|
|
+64:f18
|
|
|
|
|
+64:f19
|
|
|
|
|
+64:f20
|
|
|
|
|
+64:f21
|
|
|
|
|
+64:f22
|
|
|
|
|
+64:f23
|
|
|
|
|
+64:f24
|
|
|
|
|
+64:f25
|
|
|
|
|
+64:f26
|
|
|
|
|
+64:f27
|
|
|
|
|
+64:f28
|
|
|
|
|
+64:f29
|
|
|
|
|
+64:f30
|
|
|
|
|
+64:f31
|
|
|
|
|
+64:pc
|
|
|
|
|
+64:msr
|
|
|
|
|
+32:cr
|
|
|
|
|
+64:lr
|
|
|
|
|
+64:ctr
|
|
|
|
|
+32:xer
|
|
|
|
|
+32:fpscr
|
|
|
|
|
+64:orig_r3
|
|
|
|
|
+64:trap
|
|
|
|
|
+128:vr0
|
|
|
|
|
+128:vr1
|
|
|
|
|
+128:vr2
|
|
|
|
|
+128:vr3
|
|
|
|
|
+128:vr4
|
|
|
|
|
+128:vr5
|
|
|
|
|
+128:vr6
|
|
|
|
|
+128:vr7
|
|
|
|
|
+128:vr8
|
|
|
|
|
+128:vr9
|
|
|
|
|
+128:vr10
|
|
|
|
|
+128:vr11
|
|
|
|
|
+128:vr12
|
|
|
|
|
+128:vr13
|
|
|
|
|
+128:vr14
|
|
|
|
|
+128:vr15
|
|
|
|
|
+128:vr16
|
|
|
|
|
+128:vr17
|
|
|
|
|
+128:vr18
|
|
|
|
|
+128:vr19
|
|
|
|
|
+128:vr20
|
|
|
|
|
+128:vr21
|
|
|
|
|
+128:vr22
|
|
|
|
|
+128:vr23
|
|
|
|
|
+128:vr24
|
|
|
|
|
+128:vr25
|
|
|
|
|
+128:vr26
|
|
|
|
|
+128:vr27
|
|
|
|
|
+128:vr28
|
|
|
|
|
+128:vr29
|
|
|
|
|
+128:vr30
|
|
|
|
|
+128:vr31
|
|
|
|
|
+32:vscr
|
|
|
|
|
+32:vrsave
|
2008-11-20 15:44:10 +00:00
|
|
|
|
--- gdb/remote.c
|
|
|
|
|
+++ gdb/remote.c
|
2009-01-22 17:17:17 +00:00
|
|
|
|
@@ -4523,7 +4523,7 @@ process_stop_reply (struct stop_reply *s
|
|
|
|
|
for (ix = 0;
|
|
|
|
|
VEC_iterate(cached_reg_t, stop_reply->regcache, ix, reg);
|
|
|
|
|
ix++)
|
|
|
|
|
- regcache_raw_supply (get_thread_regcache (ptid),
|
|
|
|
|
+ regcache_raw_supply (get_thread_arch_regcache (ptid, target_gdbarch),
|
|
|
|
|
reg->num, reg->data);
|
|
|
|
|
VEC_free (cached_reg_t, stop_reply->regcache);
|
|
|
|
|
}
|
2009-01-19 00:46:30 +00:00
|
|
|
|
@@ -6781,7 +6781,7 @@ remote_insert_breakpoint (struct bp_targ
|
2008-11-07 14:07:25 +00:00
|
|
|
|
switch (packet_ok (rs->buf, &remote_protocol_packets[PACKET_Z0]))
|
|
|
|
|
{
|
|
|
|
|
case PACKET_ERROR:
|
|
|
|
|
- return -1;
|
|
|
|
|
+ return 1;
|
|
|
|
|
case PACKET_OK:
|
|
|
|
|
bp_tgt->placed_address = addr;
|
|
|
|
|
bp_tgt->placed_size = bpsize;
|
2009-01-19 00:46:30 +00:00
|
|
|
|
@@ -6968,7 +6968,7 @@ remote_insert_hw_breakpoint (struct bp_t
|
2008-11-07 14:07:25 +00:00
|
|
|
|
(target_gdbarch, &bp_tgt->placed_address, &bp_tgt->placed_size);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
if (remote_protocol_packets[PACKET_Z1].support == PACKET_DISABLE)
|
|
|
|
|
- return -1;
|
|
|
|
|
+ return 1;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
rs = get_remote_state ();
|
|
|
|
|
p = rs->buf;
|
2009-01-19 00:46:30 +00:00
|
|
|
|
@@ -6988,7 +6988,7 @@ remote_insert_hw_breakpoint (struct bp_t
|
2008-11-07 14:07:25 +00:00
|
|
|
|
{
|
|
|
|
|
case PACKET_ERROR:
|
|
|
|
|
case PACKET_UNKNOWN:
|
|
|
|
|
- return -1;
|
|
|
|
|
+ return 1;
|
|
|
|
|
case PACKET_OK:
|
|
|
|
|
return 0;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
}
|
2009-01-19 00:46:30 +00:00
|
|
|
|
@@ -7005,7 +7005,7 @@ remote_remove_hw_breakpoint (struct bp_t
|
2008-11-07 14:07:25 +00:00
|
|
|
|
char *p = rs->buf;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
if (remote_protocol_packets[PACKET_Z1].support == PACKET_DISABLE)
|
|
|
|
|
- return -1;
|
|
|
|
|
+ return 1;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
*(p++) = 'z';
|
|
|
|
|
*(p++) = '1';
|
2009-01-19 00:46:30 +00:00
|
|
|
|
@@ -7022,7 +7022,7 @@ remote_remove_hw_breakpoint (struct bp_t
|
2008-11-07 14:07:25 +00:00
|
|
|
|
{
|
|
|
|
|
case PACKET_ERROR:
|
|
|
|
|
case PACKET_UNKNOWN:
|
|
|
|
|
- return -1;
|
|
|
|
|
+ return 1;
|
|
|
|
|
case PACKET_OK:
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2009-01-22 17:17:17 +00:00
|
|
|
|
--- gdb/rs6000-tdep.c
|
|
|
|
|
+++ gdb/rs6000-tdep.c
|
|
|
|
|
@@ -3338,6 +3338,16 @@ rs6000_gdbarch_init (struct gdbarch_info
|
|
|
|
|
int num_pseudoregs = 0;
|
|
|
|
|
int cur_reg;
|
|
|
|
|
|
|
|
|
|
+ /* INFO may refer to a binary that is not of the PowerPC architecture,
|
|
|
|
|
+ e.g. when debugging a stand-alone SPE executable on a Cell/B.E. system.
|
|
|
|
|
+ In this case, we must not attempt to infer properties of the (PowerPC
|
|
|
|
|
+ side) of the target system from properties of that executable. Trust
|
|
|
|
|
+ the target description instead. */
|
|
|
|
|
+ if (info.abfd
|
|
|
|
|
+ && bfd_get_arch (info.abfd) != bfd_arch_powerpc
|
|
|
|
|
+ && bfd_get_arch (info.abfd) != bfd_arch_rs6000)
|
|
|
|
|
+ info.abfd = NULL;
|
|
|
|
|
+
|
|
|
|
|
from_xcoff_exec = info.abfd && info.abfd->format == bfd_object &&
|
|
|
|
|
bfd_get_flavour (info.abfd) == bfd_target_xcoff_flavour;
|
|
|
|
|
|
2008-11-20 15:44:10 +00:00
|
|
|
|
--- gdb/sentinel-frame.c
|
|
|
|
|
+++ gdb/sentinel-frame.c
|
2008-11-07 14:07:25 +00:00
|
|
|
|
@@ -76,11 +76,23 @@ sentinel_frame_this_id (struct frame_inf
|
|
|
|
|
internal_error (__FILE__, __LINE__, _("sentinel_frame_this_id called"));
|
2008-09-12 23:16:14 +00:00
|
|
|
|
}
|
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+static struct gdbarch *
|
|
|
|
|
+sentinel_frame_prev_arch (struct frame_info *this_frame,
|
|
|
|
|
+ void **this_prologue_cache)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+{
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ struct frame_unwind_cache *cache = *this_prologue_cache;
|
|
|
|
|
+ return get_regcache_arch (cache->regcache);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+}
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
const struct frame_unwind sentinel_frame_unwinder =
|
2008-09-12 23:16:14 +00:00
|
|
|
|
{
|
2008-11-07 14:07:25 +00:00
|
|
|
|
SENTINEL_FRAME,
|
|
|
|
|
sentinel_frame_this_id,
|
|
|
|
|
- sentinel_frame_prev_register
|
|
|
|
|
+ sentinel_frame_prev_register,
|
|
|
|
|
+ NULL,
|
|
|
|
|
+ NULL,
|
|
|
|
|
+ NULL,
|
|
|
|
|
+ sentinel_frame_prev_arch,
|
|
|
|
|
};
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
const struct frame_unwind *const sentinel_frame_unwind = &sentinel_frame_unwinder;
|
2008-11-20 15:44:10 +00:00
|
|
|
|
--- gdb/sol-thread.c
|
|
|
|
|
+++ gdb/sol-thread.c
|
2008-11-07 14:07:25 +00:00
|
|
|
|
@@ -1093,7 +1093,7 @@ ps_lgetregs (gdb_ps_prochandle_t ph, lwp
|
|
|
|
|
old_chain = save_inferior_ptid ();
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
inferior_ptid = BUILD_LWP (lwpid, PIDGET (inferior_ptid));
|
|
|
|
|
- regcache = get_thread_regcache (inferior_ptid);
|
|
|
|
|
+ regcache = get_thread_arch_regcache (inferior_ptid, target_gdbarch);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
if (target_has_execution)
|
|
|
|
|
procfs_ops.to_fetch_registers (regcache, -1);
|
|
|
|
|
@@ -1118,7 +1118,7 @@ ps_lsetregs (gdb_ps_prochandle_t ph, lwp
|
|
|
|
|
old_chain = save_inferior_ptid ();
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
inferior_ptid = BUILD_LWP (lwpid, PIDGET (inferior_ptid));
|
|
|
|
|
- regcache = get_thread_regcache (inferior_ptid);
|
|
|
|
|
+ regcache = get_thread_arch_regcache (inferior_ptid, target_gdbarch);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
supply_gregset (regcache, (const gdb_gregset_t *) gregset);
|
|
|
|
|
if (target_has_execution)
|
|
|
|
|
@@ -1229,7 +1229,7 @@ ps_lgetfpregs (gdb_ps_prochandle_t ph, l
|
|
|
|
|
old_chain = save_inferior_ptid ();
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
inferior_ptid = BUILD_LWP (lwpid, PIDGET (inferior_ptid));
|
|
|
|
|
- regcache = get_thread_regcache (inferior_ptid);
|
|
|
|
|
+ regcache = get_thread_arch_regcache (inferior_ptid, target_gdbarch);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
if (target_has_execution)
|
|
|
|
|
procfs_ops.to_fetch_registers (regcache, -1);
|
|
|
|
|
@@ -1254,7 +1254,7 @@ ps_lsetfpregs (gdb_ps_prochandle_t ph, l
|
|
|
|
|
old_chain = save_inferior_ptid ();
|
|
|
|
|
|
|
|
|
|
inferior_ptid = BUILD_LWP (lwpid, PIDGET (inferior_ptid));
|
|
|
|
|
- regcache = get_thread_regcache (inferior_ptid);
|
|
|
|
|
+ regcache = get_thread_arch_regcache (inferior_ptid, target_gdbarch);
|
|
|
|
|
|
|
|
|
|
supply_fpregset (regcache, (const gdb_fpregset_t *) fpregset);
|
|
|
|
|
if (target_has_execution)
|
2008-11-20 15:44:10 +00:00
|
|
|
|
--- gdb/solib-spu.c
|
|
|
|
|
+++ gdb/solib-spu.c
|
2009-01-22 17:17:17 +00:00
|
|
|
|
@@ -0,0 +1,482 @@
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+/* Cell SPU GNU/Linux support -- shared library handling.
|
|
|
|
|
+ Copyright (C) 2008 Free Software Foundation, Inc.
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ Contributed by Ulrich Weigand <uweigand@de.ibm.com>.
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ This file is part of GDB.
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ 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 2 of the License, or
|
|
|
|
|
+ (at your option) any later version.
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ 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.
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ You should have received a copy of the GNU General Public License
|
|
|
|
|
+ along with this program; if not, write to the Free Software
|
|
|
|
|
+ Foundation, Inc., 59 Temple Place - Suite 330,
|
|
|
|
|
+ Boston, MA 02111-1307, USA. */
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+#include "defs.h"
|
|
|
|
|
+#include "gdbcore.h"
|
|
|
|
|
+#include "gdb_string.h"
|
|
|
|
|
+#include "gdb_assert.h"
|
|
|
|
|
+#include "gdb_stat.h"
|
|
|
|
|
+#include "arch-utils.h"
|
|
|
|
|
+#include "bfd.h"
|
|
|
|
|
+#include "symtab.h"
|
|
|
|
|
+#include "solib.h"
|
|
|
|
|
+#include "solib-svr4.h"
|
|
|
|
|
+#include "solist.h"
|
|
|
|
|
+#include "inferior.h"
|
|
|
|
|
+#include "objfiles.h"
|
|
|
|
|
+#include "observer.h"
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+#include "spu-tdep.h"
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+/* Highest SPE id (file handle) the inferior may have. */
|
|
|
|
|
+#define MAX_SPE_FD 1024
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+/* Stand-alone SPE executable? */
|
|
|
|
|
+#define spu_standalone_p() \
|
|
|
|
|
+ (symfile_objfile && symfile_objfile->obfd \
|
|
|
|
|
+ && bfd_get_arch (symfile_objfile->obfd) == bfd_arch_spu)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+/* Relocate main SPE executable. */
|
|
|
|
|
+static void spu_relocate_main_executable (int spufs_fd)
|
|
|
|
|
+{
|
|
|
|
|
+ struct objfile *objfile;
|
|
|
|
|
+ struct cleanup *old_chain;
|
|
|
|
|
+ struct section_offsets *new_offsets;
|
|
|
|
|
+ int i;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ for (objfile = symfile_objfile;
|
|
|
|
|
+ objfile;
|
|
|
|
|
+ objfile = objfile->separate_debug_objfile)
|
|
|
|
|
+ {
|
|
|
|
|
+ new_offsets = xcalloc (objfile->num_sections,
|
|
|
|
|
+ sizeof (struct section_offsets));
|
|
|
|
|
+ old_chain = make_cleanup (xfree, new_offsets);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ for (i = 0; i < objfile->num_sections; i++)
|
|
|
|
|
+ new_offsets->offsets[i] = SPUADDR (spufs_fd, 0);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ objfile_relocate (objfile, new_offsets);
|
|
|
|
|
+ do_cleanups (old_chain);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* When running a stand-alone SPE executable, we need to skip one more
|
|
|
|
|
+ exec event on startup, to get past the binfmt_misc loader. */
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+static void
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+spu_skip_standalone_loader (void)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+{
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ if (target_has_execution)
|
|
|
|
|
+ {
|
|
|
|
|
+ struct cleanup *old_chain;
|
|
|
|
|
+ struct inferior *inferior = current_inferior ();
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* Suppress MI messages that are unexpected at this point. */
|
|
|
|
|
+ old_chain = make_cleanup_restore_integer (&suppress_resume_observer);
|
|
|
|
|
+ suppress_resume_observer = 1;
|
|
|
|
|
+ make_cleanup_restore_integer (&suppress_stop_observer);
|
|
|
|
|
+ suppress_stop_observer = 1;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2009-01-22 17:17:17 +00:00
|
|
|
|
+ /* Only some kernels report an extra SIGTRAP with the binfmt_misc
|
|
|
|
|
+ loader; others do not. In addition, if we have attached to an
|
|
|
|
|
+ already running inferior instead of starting a new one, we will
|
|
|
|
|
+ not see the extra SIGTRAP -- and we cannot readily distinguish
|
|
|
|
|
+ the two cases, in particular with the extended-remote target.
|
|
|
|
|
+
|
|
|
|
|
+ Thus we issue a single-step here. If no extra SIGTRAP was pending,
|
|
|
|
|
+ this will step past the first instruction of the stand-alone SPE
|
|
|
|
|
+ executable loader, but we don't care about that. */
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ inferior->stop_soon = STOP_QUIETLY;
|
2009-01-22 17:17:17 +00:00
|
|
|
|
+ resume (1, TARGET_SIGNAL_0);
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ wait_for_inferior (1);
|
|
|
|
|
+ inferior->stop_soon = NO_STOP_QUIETLY;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ do_cleanups (old_chain);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+/* Build a list of `struct so_list' objects describing the shared
|
|
|
|
|
+ objects currently loaded in the inferior. */
|
|
|
|
|
+static struct so_list *
|
|
|
|
|
+spu_current_sos (void)
|
|
|
|
|
+{
|
|
|
|
|
+ struct so_list *head;
|
|
|
|
|
+ struct so_list **link_ptr;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ char buf[MAX_SPE_FD * 4];
|
|
|
|
|
+ int i, size;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* First, retrieve the SVR4 shared library list. Switch to the
|
|
|
|
|
+ PPE architecture while doing so. This should not be strictly
|
|
|
|
|
+ necessary, but it is right now. */
|
|
|
|
|
+ struct cleanup *old_chain = save_current_gdbarch ();
|
|
|
|
|
+ current_gdbarch = target_gdbarch;
|
|
|
|
|
+ head = svr4_so_ops.current_sos ();
|
|
|
|
|
+ do_cleanups (old_chain);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* Append our libraries to the end of the list. */
|
|
|
|
|
+ for (link_ptr = &head; *link_ptr; link_ptr = &(*link_ptr)->next)
|
|
|
|
|
+ ;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* Determine list of SPU ids. */
|
|
|
|
|
+ size = target_read (¤t_target, TARGET_OBJECT_SPU, NULL,
|
|
|
|
|
+ buf, 0, sizeof buf);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* Do not add stand-alone SPE executable context as shared library,
|
|
|
|
|
+ but relocate main SPE executable objfile. */
|
|
|
|
|
+ if (spu_standalone_p ())
|
|
|
|
|
+ {
|
|
|
|
|
+ if (size == 4)
|
|
|
|
|
+ spu_relocate_main_executable (extract_unsigned_integer (buf, 4));
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ return head;
|
|
|
|
|
+ }
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* As soon as any SPE context exists in the inferior, we have to
|
|
|
|
|
+ enable SPU multi-architecture target support. */
|
|
|
|
|
+ if (size > 0)
|
|
|
|
|
+ spu_multiarch_enable ();
|
|
|
|
|
+ else
|
|
|
|
|
+ spu_multiarch_disable ();
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* Create an so_list entry for each SPU id. */
|
|
|
|
|
+ for (i = 0; i < size; i += 4)
|
|
|
|
|
+ {
|
|
|
|
|
+ int fd = extract_unsigned_integer (buf + i, 4);
|
|
|
|
|
+ struct so_list *new;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ unsigned long long addr;
|
|
|
|
|
+ char annex[32], id[100];
|
|
|
|
|
+ int len;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* Read object ID. There's a race window where the inferior may have
|
|
|
|
|
+ already created the SPE context, but not installed the object-id
|
|
|
|
|
+ yet. Skip such entries; we'll be back for them later. */
|
|
|
|
|
+ xsnprintf (annex, sizeof annex, "%d/object-id", fd);
|
|
|
|
|
+ len = target_read (¤t_target, TARGET_OBJECT_SPU, annex,
|
|
|
|
|
+ id, 0, sizeof id);
|
|
|
|
|
+ if (len <= 0 || len >= sizeof id)
|
|
|
|
|
+ continue;
|
|
|
|
|
+ id[len] = 0;
|
|
|
|
|
+ if (sscanf (id, "0x%llx", &addr) != 1 || !addr)
|
|
|
|
|
+ continue;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* Allocate so_list structure. */
|
|
|
|
|
+ new = XZALLOC (struct so_list);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* Encode FD and object ID in path name. Choose the name so as not
|
|
|
|
|
+ to conflict with any (normal) SVR4 library path name. */
|
|
|
|
|
+ xsnprintf (new->so_name, sizeof new->so_name, "@0x%llx <%d>", addr, fd);
|
|
|
|
|
+ strcpy (new->so_original_name, new->so_name);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ *link_ptr = new;
|
|
|
|
|
+ link_ptr = &new->next;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return head;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* Free so_list information. */
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+static void
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+spu_free_so (struct so_list *so)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+{
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ if (so->so_original_name[0] != '@')
|
|
|
|
|
+ svr4_so_ops.free_so (so);
|
|
|
|
|
+}
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+/* Relocate section addresses. */
|
|
|
|
|
+static void
|
|
|
|
|
+spu_relocate_section_addresses (struct so_list *so,
|
|
|
|
|
+ struct section_table *sec)
|
|
|
|
|
+{
|
|
|
|
|
+ if (so->so_original_name[0] != '@')
|
|
|
|
|
+ svr4_so_ops.relocate_section_addresses (so, sec);
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ unsigned long long addr;
|
|
|
|
|
+ int fd;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* Set addr_low/high to just LS offset for display. */
|
|
|
|
|
+ if (so->addr_low == 0 && so->addr_high == 0
|
|
|
|
|
+ && strcmp (sec->the_bfd_section->name, ".text") == 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ so->addr_low = sec->addr;
|
|
|
|
|
+ so->addr_high = sec->endaddr;
|
|
|
|
|
+ }
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* Decode object ID. */
|
|
|
|
|
+ if (sscanf (so->so_original_name, "@0x%llx <%d>", &addr, &fd) != 2)
|
|
|
|
|
+ internal_error (__FILE__, __LINE__, "bad object ID");
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ sec->addr = SPUADDR (fd, sec->addr);
|
|
|
|
|
+ sec->endaddr = SPUADDR (fd, sec->endaddr);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+/* Inferior memory should contain an SPE executable image at location ADDR.
|
|
|
|
|
+ Allocate a BFD representing that executable. Return NULL on error. */
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+static void *
|
|
|
|
|
+spu_bfd_iovec_open (bfd *nbfd, void *open_closure)
|
|
|
|
|
+{
|
|
|
|
|
+ return open_closure;
|
|
|
|
|
+}
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+static int
|
|
|
|
|
+spu_bfd_iovec_close (bfd *nbfd, void *stream)
|
|
|
|
|
+{
|
|
|
|
|
+ xfree (stream);
|
|
|
|
|
+ return 1;
|
|
|
|
|
+}
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+static file_ptr
|
|
|
|
|
+spu_bfd_iovec_pread (bfd *abfd, void *stream, void *buf,
|
|
|
|
|
+ file_ptr nbytes, file_ptr offset)
|
|
|
|
|
+{
|
|
|
|
|
+ CORE_ADDR addr = *(CORE_ADDR *)stream;
|
|
|
|
|
+ int ret;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* Switch to the PPE architecture while reading target memory.
|
|
|
|
|
+ This should not be necessary, but it is right now. */
|
|
|
|
|
+ struct cleanup *old_chain = save_current_gdbarch ();
|
|
|
|
|
+ current_gdbarch = target_gdbarch;
|
|
|
|
|
+ ret = target_read_memory (addr + offset, buf, nbytes);
|
|
|
|
|
+ do_cleanups (old_chain);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ if (ret != 0)
|
|
|
|
|
+ {
|
|
|
|
|
+ bfd_set_error (bfd_error_invalid_operation);
|
|
|
|
|
+ return -1;
|
|
|
|
|
+ }
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ return nbytes;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+}
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+static int
|
|
|
|
|
+spu_bfd_iovec_stat (bfd *abfd, void *stream, struct stat *sb)
|
|
|
|
|
+{
|
|
|
|
|
+ /* We don't have an easy way of finding the size of embedded spu
|
|
|
|
|
+ images. We could parse the in-memory ELF header and section
|
|
|
|
|
+ table to find the extent of the last section but that seems
|
|
|
|
|
+ pointless when the size is needed only for checks of other
|
|
|
|
|
+ parsed values in dbxread.c. */
|
|
|
|
|
+ sb->st_size = INT_MAX;
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+static bfd *
|
|
|
|
|
+spu_bfd_open (char *name, CORE_ADDR addr)
|
|
|
|
|
+{
|
|
|
|
|
+ bfd *nbfd;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ CORE_ADDR *open_closure = xmalloc (sizeof (CORE_ADDR));
|
|
|
|
|
+ *open_closure = addr;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ nbfd = bfd_openr_iovec (xstrdup (name), "elf32-spu",
|
|
|
|
|
+ spu_bfd_iovec_open, open_closure,
|
|
|
|
|
+ spu_bfd_iovec_pread, spu_bfd_iovec_close,
|
|
|
|
|
+ spu_bfd_iovec_stat);
|
|
|
|
|
+ if (!nbfd)
|
|
|
|
|
+ return NULL;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ if (!bfd_check_format (nbfd, bfd_object))
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+ {
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ bfd_close (nbfd);
|
|
|
|
|
+ return NULL;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+ }
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ return nbfd;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+}
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+/* Open shared library BFD. */
|
|
|
|
|
+static bfd *
|
|
|
|
|
+spu_open_bfd (char *pathname)
|
|
|
|
|
+{
|
|
|
|
|
+ char *original_name = strrchr (pathname, '@');
|
|
|
|
|
+ char name[64];
|
|
|
|
|
+ bfd *abfd;
|
|
|
|
|
+ asection *spu_name;
|
|
|
|
|
+ unsigned long long addr;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+ int fd;
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ if (!original_name)
|
|
|
|
|
+ return NULL;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* Decode object ID. */
|
|
|
|
|
+ if (sscanf (original_name, "@0x%llx <%d>", &addr, &fd) != 2)
|
|
|
|
|
+ internal_error (__FILE__, __LINE__, "bad object ID");
|
|
|
|
|
+
|
|
|
|
|
+ /* Open BFD representing SPE executable. */
|
|
|
|
|
+ abfd = spu_bfd_open (original_name, (CORE_ADDR) addr);
|
|
|
|
|
+ if (!abfd)
|
|
|
|
|
+ error (_("Cannot read SPE executable at %s"), original_name);
|
|
|
|
|
+
|
|
|
|
|
+ /* Retrieve SPU name note. */
|
|
|
|
|
+ spu_name = bfd_get_section_by_name (abfd, ".note.spu_name");
|
|
|
|
|
+ if (spu_name)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+ {
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ int sect_size = bfd_section_size (abfd, spu_name);
|
|
|
|
|
+ if (sect_size > 20)
|
|
|
|
|
+ {
|
|
|
|
|
+ char *buf = alloca (sect_size - 20 + strlen (original_name) + 1);
|
|
|
|
|
+ bfd_get_section_contents (abfd, spu_name, buf, 20, sect_size - 20);
|
|
|
|
|
+ buf[sect_size - 20] = '\0';
|
|
|
|
|
+
|
|
|
|
|
+ strcat (buf, original_name);
|
|
|
|
|
+
|
|
|
|
|
+ xfree ((char *)abfd->filename);
|
|
|
|
|
+ abfd->filename = xstrdup (buf);
|
|
|
|
|
+ }
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+ }
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+
|
|
|
|
|
+ return abfd;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* Lookup global symbol in a SPE executable. */
|
|
|
|
|
+static struct symbol *
|
|
|
|
|
+spu_lookup_lib_symbol (const struct objfile *objfile,
|
|
|
|
|
+ const char *name,
|
|
|
|
|
+ const char *linkage_name,
|
|
|
|
|
+ const domain_enum domain)
|
|
|
|
|
+{
|
|
|
|
|
+ if (bfd_get_arch (objfile->obfd) == bfd_arch_spu)
|
|
|
|
|
+ return lookup_global_symbol_from_objfile (objfile, name, linkage_name,
|
|
|
|
|
+ domain);
|
|
|
|
|
+
|
|
|
|
|
+ if (svr4_so_ops.lookup_lib_global_symbol != NULL)
|
|
|
|
|
+ return svr4_so_ops.lookup_lib_global_symbol (objfile, name, linkage_name,
|
|
|
|
|
+ domain);
|
|
|
|
|
+ return NULL;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* Enable shared library breakpoint. */
|
|
|
|
|
+static int
|
|
|
|
|
+spu_enable_break (struct objfile *objfile)
|
|
|
|
|
+{
|
|
|
|
|
+ struct minimal_symbol *spe_event_sym = NULL;
|
|
|
|
|
+
|
|
|
|
|
+ /* The libspe library will call __spe_context_update_event whenever any
|
|
|
|
|
+ SPE context is allocated or destroyed. */
|
|
|
|
|
+ spe_event_sym = lookup_minimal_symbol ("__spe_context_update_event",
|
|
|
|
|
+ NULL, objfile);
|
|
|
|
|
+
|
|
|
|
|
+ /* Place a solib_event breakpoint on the symbol. */
|
|
|
|
|
+ if (spe_event_sym)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+ {
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ CORE_ADDR addr = SYMBOL_VALUE_ADDRESS (spe_event_sym);
|
|
|
|
|
+ addr = gdbarch_convert_from_func_ptr_addr (target_gdbarch, addr,
|
|
|
|
|
+ ¤t_target);
|
|
|
|
|
+ create_solib_event_breakpoint (addr);
|
|
|
|
|
+ return 1;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+ }
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+/* Create inferior hook. */
|
|
|
|
|
+static void
|
|
|
|
|
+spu_solib_create_inferior_hook (void)
|
|
|
|
|
+{
|
|
|
|
|
+ /* Remove all previously installed solib breakpoints. Both the SVR4
|
|
|
|
|
+ code and us will re-install all required breakpoints. */
|
|
|
|
|
+ remove_solib_event_breakpoints ();
|
|
|
|
|
+
|
|
|
|
|
+ /* Handle SPE stand-alone executables. */
|
|
|
|
|
+ if (spu_standalone_p ())
|
|
|
|
|
+ {
|
|
|
|
|
+ /* After an SPE stand-alone executable was loaded, we'll receive
|
|
|
|
|
+ an additional trap due to the binfmt_misc handler. Make sure
|
|
|
|
|
+ to skip that trap. */
|
|
|
|
|
+ spu_skip_standalone_loader ();
|
|
|
|
|
+
|
|
|
|
|
+ /* At this point, the target is executing, so GDB expects to be
|
|
|
|
|
+ able to read/write target memory. For the stand-alone case,
|
|
|
|
|
+ "target memory" is actually the local store of the stand-alone
|
|
|
|
|
+ SPE context -- but at this point this context has not yet been
|
|
|
|
|
+ allocated. This is a problem in particular for breakpoints that
|
|
|
|
|
+ may already have been established.
|
|
|
|
|
+
|
|
|
|
|
+ We solve this by installing the multi-architecture handler
|
|
|
|
|
+ already at this point. This target will understand that
|
|
|
|
|
+ breakpoints falling the range of addresses covered by the
|
|
|
|
|
+ SPE local store need to be ignored.
|
|
|
|
|
+
|
|
|
|
|
+ (Note that this needs to be done here, before the solib code gets
|
|
|
|
|
+ active -- otherwise we'd fail on the first breakpoint_re_set call
|
|
|
|
|
+ triggered when new shared libraries are found.)
|
|
|
|
|
+
|
|
|
|
|
+ Once the actual stand-alone SPE context is installed, spu_current_sos
|
|
|
|
|
+ will detect this and relocate the main executable to its final (valid)
|
|
|
|
|
+ address range. Breakpoints will be automatically re-inserted at
|
|
|
|
|
+ that point. */
|
|
|
|
|
+ spu_multiarch_enable ();
|
|
|
|
|
+
|
|
|
|
|
+ /* A special case arises when re-starting an executable, because at
|
|
|
|
|
+ this point it still resides at the relocated address range that was
|
|
|
|
|
+ determined during its last execution. We need to undo the relocation
|
|
|
|
|
+ so that that multi-architecture target recognizes the stand-alone
|
|
|
|
|
+ initialization special case. */
|
|
|
|
|
+ spu_relocate_main_executable (-1);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /* Call SVR4 hook -- this will re-insert the SVR4 solib breakpoints. */
|
|
|
|
|
+ svr4_so_ops.solib_create_inferior_hook ();
|
|
|
|
|
+
|
|
|
|
|
+ /* If the inferior is statically linked against libspe, we need to install
|
|
|
|
|
+ our own solib breakpoint right now. Otherwise, it will be installed by
|
|
|
|
|
+ the solib_loaded observer below as soon as libspe is loaded. */
|
|
|
|
|
+ spu_enable_break (NULL);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* Install SPE "shared library" handling. This is called by -tdep code
|
|
|
|
|
+ that wants to support SPU as a secondary architecture. */
|
|
|
|
|
+void
|
|
|
|
|
+set_spu_solib_ops (struct gdbarch *gdbarch)
|
|
|
|
|
+{
|
|
|
|
|
+ static struct target_so_ops spu_so_ops;
|
|
|
|
|
+
|
|
|
|
|
+ /* Initialize this lazily, to avoid an initialization order
|
|
|
|
|
+ dependency on solib-svr4.c's _initialize routine. */
|
|
|
|
|
+ if (spu_so_ops.current_sos == NULL)
|
|
|
|
|
+ {
|
|
|
|
|
+ spu_so_ops = svr4_so_ops;
|
|
|
|
|
+ spu_so_ops.solib_create_inferior_hook = spu_solib_create_inferior_hook;
|
|
|
|
|
+ spu_so_ops.relocate_section_addresses = spu_relocate_section_addresses;
|
|
|
|
|
+ spu_so_ops.free_so = spu_free_so;
|
|
|
|
|
+ spu_so_ops.current_sos = spu_current_sos;
|
|
|
|
|
+ spu_so_ops.open_bfd = spu_open_bfd;
|
|
|
|
|
+ spu_so_ops.lookup_lib_global_symbol = spu_lookup_lib_symbol;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ set_solib_ops (gdbarch, &spu_so_ops);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* Observer for the solib_loaded event. Used to install our breakpoint
|
|
|
|
|
+ if libspe is a shared library. */
|
|
|
|
|
+static void
|
|
|
|
|
+spu_solib_loaded (struct so_list *so)
|
|
|
|
|
+{
|
|
|
|
|
+ if (strstr (so->so_original_name, "/libspe") != NULL)
|
|
|
|
|
+ {
|
|
|
|
|
+ solib_read_symbols (so, so->from_tty);
|
|
|
|
|
+ spu_enable_break (so->objfile);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+void
|
|
|
|
|
+_initialize_spu_solib (void)
|
|
|
|
|
+{
|
|
|
|
|
+ observer_attach_solib_loaded (spu_solib_loaded);
|
|
|
|
|
+}
|
|
|
|
|
+
|
2008-11-20 15:44:10 +00:00
|
|
|
|
--- gdb/solib.c
|
|
|
|
|
+++ gdb/solib.c
|
2009-01-19 00:46:30 +00:00
|
|
|
|
@@ -345,15 +345,22 @@ static int
|
2008-11-07 14:07:25 +00:00
|
|
|
|
solib_map_sections (void *arg)
|
|
|
|
|
{
|
|
|
|
|
struct so_list *so = (struct so_list *) arg; /* catch_errors bogon */
|
|
|
|
|
+ struct target_so_ops *ops = solib_ops (target_gdbarch);
|
|
|
|
|
char *filename;
|
|
|
|
|
struct section_table *p;
|
|
|
|
|
struct cleanup *old_chain;
|
|
|
|
|
- bfd *abfd;
|
|
|
|
|
+ bfd *abfd = NULL;
|
|
|
|
|
+
|
|
|
|
|
+ if (ops->open_bfd)
|
|
|
|
|
+ abfd = ops->open_bfd (so->so_name);
|
|
|
|
|
|
|
|
|
|
- filename = tilde_expand (so->so_name);
|
|
|
|
|
- old_chain = make_cleanup (xfree, filename);
|
|
|
|
|
- abfd = solib_bfd_open (filename);
|
|
|
|
|
- do_cleanups (old_chain);
|
|
|
|
|
+ if (!abfd)
|
|
|
|
|
+ {
|
|
|
|
|
+ filename = tilde_expand (so->so_name);
|
|
|
|
|
+ old_chain = make_cleanup (xfree, filename);
|
|
|
|
|
+ abfd = solib_bfd_open (filename);
|
|
|
|
|
+ do_cleanups (old_chain);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
|
|
/* Leave bfd open, core_xfer_memory and "info files" need it. */
|
|
|
|
|
so->abfd = abfd;
|
2009-01-19 00:46:30 +00:00
|
|
|
|
@@ -372,8 +379,6 @@ solib_map_sections (void *arg)
|
2008-11-07 14:07:25 +00:00
|
|
|
|
|
|
|
|
|
for (p = so->sections; p < so->sections_end; p++)
|
|
|
|
|
{
|
|
|
|
|
- struct target_so_ops *ops = solib_ops (target_gdbarch);
|
|
|
|
|
-
|
|
|
|
|
/* Relocate the section binding addresses as recorded in the shared
|
|
|
|
|
object's file by the base address to which the object was actually
|
|
|
|
|
mapped. */
|
2009-01-19 00:46:30 +00:00
|
|
|
|
@@ -454,7 +459,9 @@ static int
|
2008-11-07 14:07:25 +00:00
|
|
|
|
symbol_add_stub (void *arg)
|
|
|
|
|
{
|
|
|
|
|
struct so_list *so = (struct so_list *) arg; /* catch_errs bogon */
|
|
|
|
|
+ struct target_so_ops *ops = solib_ops (target_gdbarch);
|
|
|
|
|
struct section_addr_info *sap;
|
|
|
|
|
+ bfd *abfd = NULL;
|
|
|
|
|
|
|
|
|
|
/* Have we already loaded this shared object? */
|
|
|
|
|
ALL_OBJFILES (so->objfile)
|
2008-11-20 15:44:10 +00:00
|
|
|
|
--- gdb/solist.h
|
|
|
|
|
+++ gdb/solist.h
|
2009-01-19 00:46:30 +00:00
|
|
|
|
@@ -121,6 +121,10 @@ struct target_so_ops
|
2008-11-07 14:07:25 +00:00
|
|
|
|
and another from the list returned by current_sos, return 1
|
|
|
|
|
if they represent the same library. */
|
|
|
|
|
int (*same) (struct so_list *gdb, struct so_list *inferior);
|
|
|
|
|
+
|
|
|
|
|
+ /* Extra hook for opening a BFD for a solib. Can be used to
|
|
|
|
|
+ retrieve solibs from inferior memory instead of from files. */
|
|
|
|
|
+ bfd *(*open_bfd) (char *pathname);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
/* Free the memory associated with a (so_list *). */
|
2008-11-20 15:44:10 +00:00
|
|
|
|
--- gdb/spu-multiarch.c
|
|
|
|
|
+++ gdb/spu-multiarch.c
|
2009-01-22 17:17:17 +00:00
|
|
|
|
@@ -0,0 +1,461 @@
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+/* Cell SPU GNU/Linux multi-architecture debugging support.
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+ Copyright (C) 2008 Free Software Foundation, Inc.
|
|
|
|
|
+
|
|
|
|
|
+ Contributed by Ulrich Weigand <uweigand@de.ibm.com>.
|
|
|
|
|
+
|
|
|
|
|
+ This file is part of GDB.
|
|
|
|
|
+
|
|
|
|
|
+ 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 2 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.
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ You should have received a copy of the GNU General Public License
|
|
|
|
|
+ along with this program; if not, write to the Free Software
|
|
|
|
|
+ Foundation, Inc., 59 Temple Place - Suite 330,
|
|
|
|
|
+ Boston, MA 02111-1307, USA. */
|
|
|
|
|
+
|
|
|
|
|
+#include "defs.h"
|
|
|
|
|
+#include "gdbcore.h"
|
|
|
|
|
+#include "gdbcmd.h"
|
|
|
|
|
+#include "gdb_string.h"
|
|
|
|
|
+#include "gdb_assert.h"
|
|
|
|
|
+#include "arch-utils.h"
|
|
|
|
|
+#include "observer.h"
|
|
|
|
|
+#include "inferior.h"
|
|
|
|
|
+#include "regcache.h"
|
|
|
|
|
+#include "symfile.h"
|
|
|
|
|
+#include "objfiles.h"
|
|
|
|
|
+#include "block.h"
|
|
|
|
|
+#include "exec.h"
|
|
|
|
|
+#include "target-descriptions.h"
|
|
|
|
|
+
|
|
|
|
|
+#include "ppc-tdep.h"
|
|
|
|
|
+#include "ppc-linux-tdep.h"
|
|
|
|
|
+#include "spu-tdep.h"
|
|
|
|
|
+
|
|
|
|
|
+/* This module's target vector. */
|
|
|
|
|
+static struct target_ops spu_ops;
|
|
|
|
|
+
|
|
|
|
|
+/* Stand-alone SPE executable? */
|
|
|
|
|
+#define spu_standalone_p() \
|
|
|
|
|
+ (symfile_objfile && symfile_objfile->obfd \
|
|
|
|
|
+ && bfd_get_arch (symfile_objfile->obfd) == bfd_arch_spu)
|
|
|
|
|
+
|
|
|
|
|
+/* PPU side system calls. */
|
|
|
|
|
+#define INSTR_SC 0x44000002
|
|
|
|
|
+#define NR_spu_run 0x0116
|
|
|
|
|
+
|
|
|
|
|
+/* If the PPU thread is currently stopped on a spu_run system call,
|
|
|
|
|
+ return to FD and ADDR the file handle and NPC parameter address
|
|
|
|
|
+ used with the system call. Return non-zero if successful. */
|
|
|
|
|
+static int
|
|
|
|
|
+parse_spufs_run (ptid_t ptid, int *fd, CORE_ADDR *addr)
|
|
|
|
|
+{
|
|
|
|
|
+ struct gdbarch_tdep *tdep;
|
|
|
|
|
+ struct regcache *regcache;
|
|
|
|
|
+ char buf[4];
|
|
|
|
|
+ CORE_ADDR pc;
|
|
|
|
|
+ ULONGEST regval;
|
|
|
|
|
+
|
|
|
|
|
+ /* If we're not on PPU, there's nothing to detect. */
|
|
|
|
|
+ if (gdbarch_bfd_arch_info (target_gdbarch)->arch != bfd_arch_powerpc)
|
|
|
|
|
+ return 0;
|
|
|
|
|
+
|
|
|
|
|
+ /* Get PPU-side registers. */
|
|
|
|
|
+ regcache = get_thread_arch_regcache (ptid, target_gdbarch);
|
|
|
|
|
+ tdep = gdbarch_tdep (target_gdbarch);
|
|
|
|
|
+
|
|
|
|
|
+ /* Fetch instruction preceding current NIP. */
|
|
|
|
|
+ if (target_read_memory (regcache_read_pc (regcache) - 4, buf, 4) != 0)
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ /* It should be a "sc" instruction. */
|
|
|
|
|
+ if (extract_unsigned_integer (buf, 4) != INSTR_SC)
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ /* System call number should be NR_spu_run. */
|
|
|
|
|
+ regcache_cooked_read_unsigned (regcache, tdep->ppc_gp0_regnum, ®val);
|
|
|
|
|
+ if (regval != NR_spu_run)
|
|
|
|
|
+ return 0;
|
|
|
|
|
+
|
|
|
|
|
+ /* Register 3 contains fd, register 4 the NPC param pointer. */
|
|
|
|
|
+ regcache_cooked_read_unsigned (regcache, PPC_ORIG_R3_REGNUM, ®val);
|
|
|
|
|
+ *fd = (int) regval;
|
|
|
|
|
+ regcache_cooked_read_unsigned (regcache, tdep->ppc_gp0_regnum + 4, ®val);
|
|
|
|
|
+ *addr = (CORE_ADDR) regval;
|
|
|
|
|
+ return 1;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* Find gdbarch for SPU context SPUFS_FD. */
|
|
|
|
|
+static struct gdbarch *
|
|
|
|
|
+spu_gdbarch (int spufs_fd)
|
|
|
|
|
+{
|
|
|
|
|
+ struct gdbarch_info info;
|
|
|
|
|
+ gdbarch_info_init (&info);
|
|
|
|
|
+ info.bfd_arch_info = bfd_lookup_arch (bfd_arch_spu, bfd_mach_spu);
|
|
|
|
|
+ info.byte_order = BFD_ENDIAN_BIG;
|
|
|
|
|
+ info.osabi = GDB_OSABI_LINUX;
|
|
|
|
|
+ info.tdep_info = (void *) &spufs_fd;
|
|
|
|
|
+ return gdbarch_find_by_info (info);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* Override the to_thread_architecture routine. */
|
|
|
|
|
+static struct gdbarch *
|
|
|
|
|
+spu_thread_architecture (struct target_ops *ops, ptid_t ptid)
|
|
|
|
|
+{
|
|
|
|
|
+ int spufs_fd;
|
|
|
|
|
+ CORE_ADDR spufs_addr;
|
|
|
|
|
+
|
|
|
|
|
+ if (parse_spufs_run (ptid, &spufs_fd, &spufs_addr))
|
|
|
|
|
+ return spu_gdbarch (spufs_fd);
|
|
|
|
|
+
|
|
|
|
|
+ return target_gdbarch;
|
|
|
|
|
+}
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+/* Override the to_wait routine to detect current architecture. */
|
|
|
|
|
+static ptid_t
|
|
|
|
|
+spu_wait (ptid_t ptid, struct target_waitstatus *ourstatus)
|
|
|
|
|
+{
|
|
|
|
|
+ struct target_ops *ops_beneath = find_target_beneath (&spu_ops);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* Always switch to PPU while running the inferior. This allows
|
|
|
|
|
+ linux-thread-db.c code to work as expected. */
|
|
|
|
|
+ current_gdbarch = target_gdbarch;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* Run it. */
|
|
|
|
|
+ ptid = ops_beneath->to_wait (ptid, ourstatus);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* Detect and switch to current architecture. */
|
|
|
|
|
+ if (ourstatus->kind == TARGET_WAITKIND_STOPPED)
|
|
|
|
|
+ current_gdbarch = spu_thread_architecture (¤t_target, ptid);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ return ptid;
|
|
|
|
|
+}
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+
|
|
|
|
|
+/* Override the to_region_ok_for_hw_watchpoint routine. */
|
|
|
|
|
+static int
|
|
|
|
|
+spu_region_ok_for_hw_watchpoint (CORE_ADDR addr, int len)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+{
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ struct target_ops *ops_beneath = find_target_beneath (&spu_ops);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ while (ops_beneath && !ops_beneath->to_region_ok_for_hw_watchpoint)
|
|
|
|
|
+ ops_beneath = find_target_beneath (ops_beneath);
|
|
|
|
|
+ gdb_assert (ops_beneath);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* Ignore attempts to remove breakpoints in a stand-alone SPE
|
|
|
|
|
+ executable just after startup, before we know the FD. */
|
|
|
|
|
+ if (spu_standalone_p () && addr < SPU_LS_SIZE)
|
|
|
|
|
+ return -1;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* We cannot watch SPU local store. */
|
|
|
|
|
+ if (SPUADDR_SPU (addr) != -1)
|
|
|
|
|
+ return 0;
|
|
|
|
|
+
|
|
|
|
|
+ if (ops_beneath)
|
|
|
|
|
+ return ops_beneath->to_region_ok_for_hw_watchpoint (addr, len);
|
|
|
|
|
+
|
|
|
|
|
+ return 0;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+}
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+/* Override the to_insert_breakpoint routine. */
|
|
|
|
|
+static int
|
|
|
|
|
+spu_insert_breakpoint (struct bp_target_info *bp)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+{
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ struct target_ops *ops_beneath = find_target_beneath (&spu_ops);
|
|
|
|
|
+ CORE_ADDR addr = bp->placed_address;
|
|
|
|
|
+ struct cleanup *old_chain;
|
|
|
|
|
+ int ret;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ while (ops_beneath && !ops_beneath->to_insert_breakpoint)
|
|
|
|
|
+ ops_beneath = find_target_beneath (ops_beneath);
|
|
|
|
|
+ gdb_assert (ops_beneath);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* Ignore attempts to insert breakpoints in a stand-alone SPE
|
|
|
|
|
+ executable just after startup, before we know the FD. */
|
|
|
|
|
+ if (spu_standalone_p () && addr < SPU_LS_SIZE)
|
|
|
|
|
+ return -1;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ old_chain = save_current_gdbarch ();
|
|
|
|
|
+ if (SPUADDR_SPU (addr) != -1)
|
|
|
|
|
+ current_gdbarch = spu_gdbarch (SPUADDR_SPU (addr));
|
|
|
|
|
+ else
|
|
|
|
|
+ current_gdbarch = target_gdbarch;
|
|
|
|
|
+ ret = ops_beneath->to_insert_breakpoint (bp);
|
|
|
|
|
+ do_cleanups (old_chain);
|
|
|
|
|
+
|
2009-01-22 17:17:17 +00:00
|
|
|
|
+ /* Ignore failure to insert breakpoints in a stand-alone SPE
|
|
|
|
|
+ executable just before exit, when the FD is already gone. */
|
|
|
|
|
+ if (spu_standalone_p () && ret > 0)
|
|
|
|
|
+ ret = -1;
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ return ret;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+}
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+/* Override the to_remove_breakpoint routine. */
|
|
|
|
|
+static int
|
|
|
|
|
+spu_remove_breakpoint (struct bp_target_info *bp)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+{
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ struct target_ops *ops_beneath = find_target_beneath (&spu_ops);
|
|
|
|
|
+ CORE_ADDR addr = bp->placed_address;
|
|
|
|
|
+ struct cleanup *old_chain;
|
|
|
|
|
+ int ret;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ while (ops_beneath && !ops_beneath->to_remove_breakpoint)
|
|
|
|
|
+ ops_beneath = find_target_beneath (ops_beneath);
|
|
|
|
|
+ gdb_assert (ops_beneath);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* Ignore attempts to remove breakpoints in a stand-alone SPE
|
|
|
|
|
+ executable just after startup, before we know the FD. */
|
|
|
|
|
+ if (spu_standalone_p () && addr < SPU_LS_SIZE)
|
|
|
|
|
+ return -1;
|
|
|
|
|
+
|
|
|
|
|
+ old_chain = save_current_gdbarch ();
|
|
|
|
|
+ if (SPUADDR_SPU (addr) != -1)
|
|
|
|
|
+ current_gdbarch = spu_gdbarch (SPUADDR_SPU (addr));
|
|
|
|
|
+ else
|
|
|
|
|
+ current_gdbarch = target_gdbarch;
|
|
|
|
|
+ ret = ops_beneath->to_remove_breakpoint (bp);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+ do_cleanups (old_chain);
|
|
|
|
|
+
|
2009-01-22 17:17:17 +00:00
|
|
|
|
+ /* Ignore failure to remove breakpoints in a stand-alone SPE
|
|
|
|
|
+ executable just before exit, when the FD is already gone. */
|
|
|
|
|
+ if (spu_standalone_p () && ret > 0)
|
|
|
|
|
+ ret = -1;
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ return ret;
|
|
|
|
|
+}
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+/* Override the to_fetch_registers routine. */
|
|
|
|
|
+static void
|
|
|
|
|
+spu_fetch_registers (struct regcache *regcache, int regno)
|
|
|
|
|
+{
|
|
|
|
|
+ struct target_ops *ops_beneath = find_target_beneath (&spu_ops);
|
|
|
|
|
+ int spufs_fd;
|
|
|
|
|
+ CORE_ADDR spufs_addr;
|
|
|
|
|
+
|
|
|
|
|
+ /* This version applies only if we're currently in spu_run. */
|
|
|
|
|
+ if (gdbarch_bfd_arch_info (get_regcache_arch (regcache))->arch
|
|
|
|
|
+ != bfd_arch_spu)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+ {
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ while (ops_beneath && !ops_beneath->to_fetch_registers)
|
|
|
|
|
+ ops_beneath = find_target_beneath (ops_beneath);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ gdb_assert (ops_beneath);
|
|
|
|
|
+ ops_beneath->to_fetch_registers (regcache, regno);
|
|
|
|
|
+ return;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+ }
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* We must be stopped on a spu_run system call. */
|
|
|
|
|
+ if (!parse_spufs_run (inferior_ptid, &spufs_fd, &spufs_addr))
|
|
|
|
|
+ return;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* The ID register holds the spufs file handle. */
|
|
|
|
|
+ if (regno == -1 || regno == SPU_ID_REGNUM)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+ {
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ char buf[4];
|
|
|
|
|
+ store_unsigned_integer (buf, 4, spufs_fd);
|
|
|
|
|
+ regcache_raw_supply (regcache, SPU_ID_REGNUM, buf);
|
|
|
|
|
+ }
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* The NPC register is found in PPC memory at SPUFS_ADDR. */
|
|
|
|
|
+ if (regno == -1 || regno == SPU_PC_REGNUM)
|
|
|
|
|
+ {
|
|
|
|
|
+ struct cleanup *old_chain;
|
|
|
|
|
+ LONGEST ret;
|
|
|
|
|
+ char buf[4];
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* Switch to PPC arch while accessing target memory. */
|
|
|
|
|
+ old_chain = save_current_gdbarch ();
|
|
|
|
|
+ current_gdbarch = target_gdbarch;
|
|
|
|
|
+ ret = target_read (ops_beneath, TARGET_OBJECT_MEMORY, NULL,
|
|
|
|
|
+ buf, spufs_addr, sizeof buf);
|
|
|
|
|
+ do_cleanups (old_chain);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ if (ret == sizeof buf)
|
|
|
|
|
+ regcache_raw_supply (regcache, SPU_PC_REGNUM, buf);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+ }
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* The GPRs are found in the "regs" spufs file. */
|
|
|
|
|
+ if (regno == -1 || (regno >= 0 && regno < SPU_NUM_GPRS))
|
|
|
|
|
+ {
|
|
|
|
|
+ char buf[16 * SPU_NUM_GPRS], annex[32];
|
|
|
|
|
+ int i;
|
|
|
|
|
+
|
|
|
|
|
+ xsnprintf (annex, sizeof annex, "%d/regs", spufs_fd);
|
|
|
|
|
+ if (target_read (ops_beneath, TARGET_OBJECT_SPU, annex,
|
|
|
|
|
+ buf, 0, sizeof buf) == sizeof buf)
|
|
|
|
|
+ for (i = 0; i < SPU_NUM_GPRS; i++)
|
|
|
|
|
+ regcache_raw_supply (regcache, i, buf + i*16);
|
|
|
|
|
+ }
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+}
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+/* Override the to_store_registers routine. */
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+static void
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+spu_store_registers (struct regcache *regcache, int regno)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+{
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ struct target_ops *ops_beneath = find_target_beneath (&spu_ops);
|
|
|
|
|
+ int spufs_fd;
|
|
|
|
|
+ CORE_ADDR spufs_addr;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* This version applies only if we're currently in spu_run. */
|
|
|
|
|
+ if (gdbarch_bfd_arch_info (get_regcache_arch (regcache))->arch
|
|
|
|
|
+ != bfd_arch_spu)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+ {
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ while (ops_beneath && !ops_beneath->to_fetch_registers)
|
|
|
|
|
+ ops_beneath = find_target_beneath (ops_beneath);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ gdb_assert (ops_beneath);
|
|
|
|
|
+ ops_beneath->to_store_registers (regcache, regno);
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* We must be stopped on a spu_run system call. */
|
|
|
|
|
+ if (!parse_spufs_run (inferior_ptid, &spufs_fd, &spufs_addr))
|
|
|
|
|
+ return;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* The NPC register is found in PPC memory at SPUFS_ADDR. */
|
|
|
|
|
+ if (regno == -1 || regno == SPU_PC_REGNUM)
|
|
|
|
|
+ {
|
|
|
|
|
+ struct cleanup *old_chain;
|
|
|
|
|
+ char buf[4];
|
|
|
|
|
+ regcache_raw_collect (regcache, SPU_PC_REGNUM, buf);
|
|
|
|
|
+
|
|
|
|
|
+ /* Switch to PPC arch while accessing target memory. */
|
|
|
|
|
+ old_chain = save_current_gdbarch ();
|
|
|
|
|
+ current_gdbarch = target_gdbarch;
|
|
|
|
|
+ target_write (ops_beneath, TARGET_OBJECT_MEMORY, NULL,
|
|
|
|
|
+ buf, spufs_addr, sizeof buf);
|
|
|
|
|
+ do_cleanups (old_chain);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+ }
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* The GPRs are found in the "regs" spufs file. */
|
|
|
|
|
+ if (regno == -1 || (regno >= 0 && regno < SPU_NUM_GPRS))
|
|
|
|
|
+ {
|
|
|
|
|
+ char buf[16 * SPU_NUM_GPRS], annex[32];
|
|
|
|
|
+ int i;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ for (i = 0; i < SPU_NUM_GPRS; i++)
|
|
|
|
|
+ regcache_raw_collect (regcache, i, buf + i*16);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ xsnprintf (annex, sizeof annex, "%d/regs", spufs_fd);
|
|
|
|
|
+ target_write (ops_beneath, TARGET_OBJECT_SPU, annex,
|
|
|
|
|
+ buf, 0, sizeof buf);
|
|
|
|
|
+ }
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+/* Override the to_xfer_partial routine. */
|
|
|
|
|
+static LONGEST
|
|
|
|
|
+spu_xfer_partial (struct target_ops *ops, enum target_object object,
|
|
|
|
|
+ const char *annex, gdb_byte *readbuf,
|
|
|
|
|
+ const gdb_byte *writebuf, ULONGEST offset, LONGEST len)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+{
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ struct target_ops *ops_beneath = find_target_beneath (ops);
|
|
|
|
|
+
|
|
|
|
|
+ /* Use the "mem" spufs file to access SPU local store. */
|
|
|
|
|
+ if (object == TARGET_OBJECT_MEMORY)
|
|
|
|
|
+ {
|
|
|
|
|
+ int fd = SPUADDR_SPU (offset);
|
|
|
|
|
+ CORE_ADDR addr = SPUADDR_ADDR (offset);
|
|
|
|
|
+ char mem_annex[32];
|
|
|
|
|
+
|
|
|
|
|
+ if (fd >= 0 && addr < SPU_LS_SIZE)
|
|
|
|
|
+ {
|
|
|
|
|
+ xsnprintf (mem_annex, sizeof mem_annex, "%d/mem", fd);
|
|
|
|
|
+ return ops_beneath->to_xfer_partial (ops_beneath, TARGET_OBJECT_SPU,
|
|
|
|
|
+ mem_annex, readbuf, writebuf,
|
|
|
|
|
+ addr, len);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return ops_beneath->to_xfer_partial (ops_beneath, object, annex,
|
|
|
|
|
+ readbuf, writebuf, offset, len);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+}
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+/* Override the to_search_memory routine. */
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+static int
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+spu_search_memory (struct target_ops* ops,
|
|
|
|
|
+ CORE_ADDR start_addr, ULONGEST search_space_len,
|
|
|
|
|
+ const gdb_byte *pattern, ULONGEST pattern_len,
|
|
|
|
|
+ CORE_ADDR *found_addrp)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+{
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ struct target_ops *ops_beneath = find_target_beneath (ops);
|
|
|
|
|
+ while (ops_beneath && !ops_beneath->to_search_memory)
|
|
|
|
|
+ ops_beneath = find_target_beneath (ops_beneath);
|
|
|
|
|
+
|
|
|
|
|
+ /* For SPU local store, always fall back to the simple method. Likewise
|
|
|
|
|
+ if we do not have any target-specific special implementation. */
|
|
|
|
|
+ if (!ops_beneath || SPUADDR_SPU (start_addr) >= 0)
|
|
|
|
|
+ return simple_search_memory (ops,
|
|
|
|
|
+ start_addr, search_space_len,
|
|
|
|
|
+ pattern, pattern_len, found_addrp);
|
|
|
|
|
+
|
|
|
|
|
+ return ops_beneath->to_search_memory (ops_beneath,
|
|
|
|
|
+ start_addr, search_space_len,
|
|
|
|
|
+ pattern, pattern_len, found_addrp);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+/* Push and pop the SPU multi-architecture support target. */
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+void
|
|
|
|
|
+spu_multiarch_enable (void)
|
|
|
|
|
+{
|
|
|
|
|
+ /* If GDB was configured without SPU architecture support,
|
|
|
|
|
+ we cannot install SPU multi-architecture support either. */
|
|
|
|
|
+ if (spu_gdbarch (-1) == NULL)
|
|
|
|
|
+ return;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ push_target (&spu_ops);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+}
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+void
|
|
|
|
|
+spu_multiarch_disable (void)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+{
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ unpush_target (&spu_ops);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+}
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+static void
|
2008-11-17 15:51:24 +00:00
|
|
|
|
+spu_mourn_inferior (struct target_ops *ops)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+{
|
2009-01-22 17:17:17 +00:00
|
|
|
|
+ struct target_ops *ops_beneath = find_target_beneath (ops);
|
|
|
|
|
+ ops_beneath->to_mourn_inferior (ops_beneath);
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ spu_multiarch_disable ();
|
|
|
|
|
+}
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+/* Initialize the SPU multi-architecture support target. */
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+static void
|
|
|
|
|
+init_spu_ops (void)
|
|
|
|
|
+{
|
|
|
|
|
+ spu_ops.to_shortname = "spu";
|
|
|
|
|
+ spu_ops.to_longname = "SPU multi-architecture support.";
|
|
|
|
|
+ spu_ops.to_doc = "SPU multi-architecture support.";
|
|
|
|
|
+ spu_ops.to_mourn_inferior = spu_mourn_inferior;
|
|
|
|
|
+ spu_ops.to_fetch_registers = spu_fetch_registers;
|
|
|
|
|
+ spu_ops.to_store_registers = spu_store_registers;
|
|
|
|
|
+ spu_ops.to_xfer_partial = spu_xfer_partial;
|
|
|
|
|
+ spu_ops.to_search_memory = spu_search_memory;
|
|
|
|
|
+ spu_ops.to_insert_breakpoint = spu_insert_breakpoint;
|
|
|
|
|
+ spu_ops.to_remove_breakpoint = spu_remove_breakpoint;
|
|
|
|
|
+ spu_ops.to_region_ok_for_hw_watchpoint = spu_region_ok_for_hw_watchpoint;
|
|
|
|
|
+ spu_ops.to_wait = spu_wait;
|
|
|
|
|
+ spu_ops.to_thread_architecture = spu_thread_architecture;
|
|
|
|
|
+ spu_ops.to_stratum = arch_stratum;
|
|
|
|
|
+ spu_ops.to_magic = OPS_MAGIC;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+}
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+void
|
|
|
|
|
+_initialize_spu_multiarch (void)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+{
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* Install ourselves on the target stack. */
|
|
|
|
|
+ init_spu_ops ();
|
|
|
|
|
+ add_target (&spu_ops);
|
|
|
|
|
+}
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-20 15:44:10 +00:00
|
|
|
|
--- gdb/spu-tdep.c
|
|
|
|
|
+++ gdb/spu-tdep.c
|
2008-11-07 14:07:25 +00:00
|
|
|
|
@@ -40,14 +40,31 @@
|
|
|
|
|
#include "regcache.h"
|
|
|
|
|
#include "reggroups.h"
|
|
|
|
|
#include "floatformat.h"
|
|
|
|
|
+#include "block.h"
|
|
|
|
|
#include "observer.h"
|
|
|
|
|
+#include "infcall.h"
|
|
|
|
|
|
|
|
|
|
#include "spu-tdep.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+/* The list of available "set spu " and "show spu " commands. */
|
|
|
|
|
+static struct cmd_list_element *setspucmdlist = NULL;
|
|
|
|
|
+static struct cmd_list_element *showspucmdlist = NULL;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+/* Whether to stop for new SPE contexts. */
|
|
|
|
|
+static int spu_stop_on_load_p = 0;
|
|
|
|
|
+/* Whether to automatically flush the SW-managed cache. */
|
|
|
|
|
+static int spu_auto_flush_cache_p = 1;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
/* The tdep structure. */
|
|
|
|
|
struct gdbarch_tdep
|
|
|
|
|
{
|
|
|
|
|
+ /* The spufs ID identifying our address space. */
|
|
|
|
|
+ int id;
|
|
|
|
|
+ /* The size of this address space. */
|
|
|
|
|
+ CORE_ADDR lslr;
|
|
|
|
|
+
|
|
|
|
|
/* SPU-specific vector type. */
|
|
|
|
|
struct type *spu_builtin_type_vec128;
|
|
|
|
|
};
|
|
|
|
|
@@ -324,33 +341,87 @@ spu_register_reggroup_p (struct gdbarch
|
|
|
|
|
return default_register_reggroup_p (gdbarch, regnum, group);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
-/* Address conversion. */
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+/* Address handling. */
|
|
|
|
|
|
|
|
|
|
static CORE_ADDR
|
|
|
|
|
-spu_pointer_to_address (struct type *type, const gdb_byte *buf)
|
|
|
|
|
+spu_lslr (int id)
|
|
|
|
|
{
|
|
|
|
|
+ gdb_byte buf[16];
|
|
|
|
|
+ char annex[32];
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ xsnprintf (annex, sizeof annex, "%d/lslr", id);
|
|
|
|
|
+ memset (buf, 0, sizeof buf);
|
|
|
|
|
+ target_read (¤t_target, TARGET_OBJECT_SPU, annex,
|
|
|
|
|
+ buf, 0, sizeof buf);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ return strtoulst (buf, NULL, 16);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+}
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+static int
|
|
|
|
|
+spu_address_class_type_flags (int byte_size, int dwarf2_addr_class)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+{
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ if (dwarf2_addr_class == 1)
|
|
|
|
|
+ return TYPE_INSTANCE_FLAG_ADDRESS_CLASS_1;
|
|
|
|
|
+ else
|
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+static const char *
|
|
|
|
|
+spu_address_class_type_flags_to_name (struct gdbarch *gdbarch, int type_flags)
|
|
|
|
|
+{
|
|
|
|
|
+ if (type_flags & TYPE_INSTANCE_FLAG_ADDRESS_CLASS_1)
|
|
|
|
|
+ return "__ea";
|
|
|
|
|
+ else
|
|
|
|
|
+ return NULL;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static int
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+spu_address_class_name_to_type_flags (struct gdbarch *gdbarch,
|
|
|
|
|
+ const char *name, int *type_flags_ptr)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+{
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ if (strcmp (name, "__ea") == 0)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+ {
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ *type_flags_ptr = TYPE_INSTANCE_FLAG_ADDRESS_CLASS_1;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+ return 1;
|
|
|
|
|
+ }
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ else
|
|
|
|
|
+ return 0;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static void
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+spu_address_to_pointer (struct gdbarch *gdbarch,
|
|
|
|
|
+ struct type *type, gdb_byte *buf, CORE_ADDR addr)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+{
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ store_unsigned_integer (buf, TYPE_LENGTH (type), SPUADDR_ADDR (addr));
|
|
|
|
|
+}
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+static CORE_ADDR
|
|
|
|
|
+spu_pointer_to_address (struct gdbarch *gdbarch,
|
|
|
|
|
+ struct type *type, const gdb_byte *buf)
|
|
|
|
|
+{
|
|
|
|
|
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
|
|
|
|
|
ULONGEST addr = extract_unsigned_integer (buf, TYPE_LENGTH (type));
|
|
|
|
|
- ULONGEST lslr = SPU_LS_SIZE - 1; /* Hard-wired LS size. */
|
|
|
|
|
|
|
|
|
|
- if (target_has_registers && target_has_stack && target_has_memory)
|
|
|
|
|
- lslr = get_frame_register_unsigned (get_selected_frame (NULL),
|
|
|
|
|
- SPU_LSLR_REGNUM);
|
|
|
|
|
+ /* Do not convert __ea pointers. */
|
|
|
|
|
+ if (TYPE_ADDRESS_CLASS_1 (type))
|
|
|
|
|
+ return addr;
|
|
|
|
|
|
|
|
|
|
- return addr & lslr;
|
|
|
|
|
+ return addr? SPUADDR (tdep->id, addr & tdep->lslr) : 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static CORE_ADDR
|
|
|
|
|
spu_integer_to_address (struct gdbarch *gdbarch,
|
|
|
|
|
struct type *type, const gdb_byte *buf)
|
|
|
|
|
{
|
|
|
|
|
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
|
|
|
|
|
ULONGEST addr = unpack_long (type, buf);
|
|
|
|
|
- ULONGEST lslr = SPU_LS_SIZE - 1; /* Hard-wired LS size. */
|
|
|
|
|
|
|
|
|
|
- if (target_has_registers && target_has_stack && target_has_memory)
|
|
|
|
|
- lslr = get_frame_register_unsigned (get_selected_frame (NULL),
|
|
|
|
|
- SPU_LSLR_REGNUM);
|
|
|
|
|
+ /* Do not convert __ea pointers. */
|
|
|
|
|
+ if (TYPE_ADDRESS_CLASS_1 (type))
|
|
|
|
|
+ return addr;
|
|
|
|
|
|
|
|
|
|
- return addr & lslr;
|
|
|
|
|
+ return SPUADDR (tdep->id, addr & tdep->lslr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@@ -840,8 +911,11 @@ static struct spu_unwind_cache *
|
|
|
|
|
spu_frame_unwind_cache (struct frame_info *this_frame,
|
|
|
|
|
void **this_prologue_cache)
|
|
|
|
|
{
|
|
|
|
|
+ struct gdbarch *gdbarch = get_frame_arch (this_frame);
|
|
|
|
|
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
|
|
|
|
|
struct spu_unwind_cache *info;
|
|
|
|
|
struct spu_prologue_data data;
|
|
|
|
|
+ CORE_ADDR id = tdep->id;
|
|
|
|
|
gdb_byte buf[16];
|
|
|
|
|
|
|
|
|
|
if (*this_prologue_cache)
|
|
|
|
|
@@ -874,6 +948,7 @@ spu_frame_unwind_cache (struct frame_inf
|
|
|
|
|
/* Determine CFA via unwound CFA_REG plus CFA_OFFSET. */
|
|
|
|
|
get_frame_register (this_frame, data.cfa_reg, buf);
|
|
|
|
|
cfa = extract_unsigned_integer (buf, 4) + data.cfa_offset;
|
|
|
|
|
+ cfa = SPUADDR (id, cfa);
|
|
|
|
|
|
|
|
|
|
/* Call-saved register slots. */
|
|
|
|
|
for (i = 0; i < SPU_NUM_GPRS; i++)
|
|
|
|
|
@@ -896,7 +971,7 @@ spu_frame_unwind_cache (struct frame_inf
|
|
|
|
|
|
|
|
|
|
/* Get the backchain. */
|
|
|
|
|
reg = get_frame_register_unsigned (this_frame, SPU_SP_REGNUM);
|
|
|
|
|
- status = safe_read_memory_integer (reg, 4, &backchain);
|
|
|
|
|
+ status = safe_read_memory_integer (SPUADDR (id, reg), 4, &backchain);
|
|
|
|
|
|
|
|
|
|
/* A zero backchain terminates the frame chain. Also, sanity
|
|
|
|
|
check against the local store size limit. */
|
|
|
|
|
@@ -904,11 +979,11 @@ spu_frame_unwind_cache (struct frame_inf
|
|
|
|
|
{
|
|
|
|
|
/* Assume the link register is saved into its slot. */
|
|
|
|
|
if (backchain + 16 < SPU_LS_SIZE)
|
|
|
|
|
- info->saved_regs[SPU_LR_REGNUM].addr = backchain + 16;
|
|
|
|
|
+ info->saved_regs[SPU_LR_REGNUM].addr = SPUADDR (id, backchain + 16);
|
|
|
|
|
|
|
|
|
|
/* Frame bases. */
|
|
|
|
|
- info->frame_base = backchain;
|
|
|
|
|
- info->local_base = reg;
|
|
|
|
|
+ info->frame_base = SPUADDR (id, backchain);
|
|
|
|
|
+ info->local_base = SPUADDR (id, reg);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -917,7 +992,8 @@ spu_frame_unwind_cache (struct frame_inf
|
|
|
|
|
return info;
|
|
|
|
|
|
|
|
|
|
/* The previous SP is equal to the CFA. */
|
|
|
|
|
- trad_frame_set_value (info->saved_regs, SPU_SP_REGNUM, info->frame_base);
|
|
|
|
|
+ trad_frame_set_value (info->saved_regs, SPU_SP_REGNUM,
|
|
|
|
|
+ SPUADDR_ADDR (info->frame_base));
|
|
|
|
|
|
|
|
|
|
/* Read full contents of the unwound link register in order to
|
|
|
|
|
be able to determine the return address. */
|
|
|
|
|
@@ -995,24 +1071,28 @@ static const struct frame_base spu_frame
|
|
|
|
|
static CORE_ADDR
|
|
|
|
|
spu_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame)
|
|
|
|
|
{
|
|
|
|
|
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
|
|
|
|
|
CORE_ADDR pc = frame_unwind_register_unsigned (next_frame, SPU_PC_REGNUM);
|
|
|
|
|
/* Mask off interrupt enable bit. */
|
|
|
|
|
- return pc & -4;
|
|
|
|
|
+ return SPUADDR (tdep->id, pc & -4);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static CORE_ADDR
|
|
|
|
|
spu_unwind_sp (struct gdbarch *gdbarch, struct frame_info *next_frame)
|
|
|
|
|
{
|
|
|
|
|
- return frame_unwind_register_unsigned (next_frame, SPU_SP_REGNUM);
|
|
|
|
|
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
|
|
|
|
|
+ CORE_ADDR sp = frame_unwind_register_unsigned (next_frame, SPU_SP_REGNUM);
|
|
|
|
|
+ return SPUADDR (tdep->id, sp);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static CORE_ADDR
|
|
|
|
|
spu_read_pc (struct regcache *regcache)
|
|
|
|
|
{
|
|
|
|
|
+ struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache));
|
|
|
|
|
ULONGEST pc;
|
|
|
|
|
regcache_cooked_read_unsigned (regcache, SPU_PC_REGNUM, &pc);
|
|
|
|
|
/* Mask off interrupt enable bit. */
|
|
|
|
|
- return pc & -4;
|
|
|
|
|
+ return SPUADDR (tdep->id, pc & -4);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
@@ -1022,9 +1102,111 @@ spu_write_pc (struct regcache *regcache,
|
|
|
|
|
ULONGEST old_pc;
|
|
|
|
|
regcache_cooked_read_unsigned (regcache, SPU_PC_REGNUM, &old_pc);
|
|
|
|
|
regcache_cooked_write_unsigned (regcache, SPU_PC_REGNUM,
|
|
|
|
|
- (pc & -4) | (old_pc & 3));
|
|
|
|
|
+ (SPUADDR_ADDR (pc) & -4) | (old_pc & 3));
|
|
|
|
|
+}
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+/* Cell/B.E. cross-architecture unwinder support. */
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+struct spu2ppu_cache
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+{
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ struct frame_id frame_id;
|
|
|
|
|
+ struct regcache *regcache;
|
|
|
|
|
+};
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+static struct gdbarch *
|
|
|
|
|
+spu2ppu_prev_arch (struct frame_info *this_frame, void **this_cache)
|
|
|
|
|
+{
|
|
|
|
|
+ struct spu2ppu_cache *cache = *this_cache;
|
|
|
|
|
+ return get_regcache_arch (cache->regcache);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static void
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+spu2ppu_this_id (struct frame_info *this_frame,
|
|
|
|
|
+ void **this_cache, struct frame_id *this_id)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+{
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ struct spu2ppu_cache *cache = *this_cache;
|
|
|
|
|
+ *this_id = cache->frame_id;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+static struct value *
|
|
|
|
|
+spu2ppu_prev_register (struct frame_info *this_frame,
|
|
|
|
|
+ void **this_cache, int regnum)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+{
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ struct spu2ppu_cache *cache = *this_cache;
|
|
|
|
|
+ struct gdbarch *gdbarch = get_regcache_arch (cache->regcache);
|
|
|
|
|
+ gdb_byte *buf;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ buf = alloca (register_size (gdbarch, regnum));
|
|
|
|
|
+ regcache_cooked_read (cache->regcache, regnum, buf);
|
|
|
|
|
+ return frame_unwind_got_bytes (this_frame, regnum, buf);
|
|
|
|
|
+}
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+static int
|
|
|
|
|
+spu2ppu_sniffer (const struct frame_unwind *self,
|
|
|
|
|
+ struct frame_info *this_frame, void **this_prologue_cache)
|
|
|
|
|
+{
|
|
|
|
|
+ CORE_ADDR base, func, backchain;
|
|
|
|
|
+ gdb_byte buf[4];
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ if (gdbarch_bfd_arch_info (target_gdbarch)->arch == bfd_arch_spu)
|
|
|
|
|
+ return 0;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ base = get_frame_sp (this_frame);
|
|
|
|
|
+ func = get_frame_pc (this_frame);
|
|
|
|
|
+ if (target_read_memory (base, buf, 4))
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ backchain = extract_unsigned_integer (buf, 4);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ if (!backchain)
|
|
|
|
|
+ {
|
|
|
|
|
+ struct frame_info *fi;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ struct spu2ppu_cache *cache
|
|
|
|
|
+ = FRAME_OBSTACK_CALLOC (1, struct spu2ppu_cache);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ cache->frame_id = frame_id_build (base + 16, func);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ for (fi = get_next_frame (this_frame); fi; fi = get_next_frame (fi))
|
|
|
|
|
+ if (gdbarch_bfd_arch_info (get_frame_arch (fi))->arch != bfd_arch_spu)
|
|
|
|
|
+ break;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ if (fi)
|
|
|
|
|
+ {
|
|
|
|
|
+ cache->regcache = frame_save_as_regcache (fi);
|
|
|
|
|
+ *this_prologue_cache = cache;
|
|
|
|
|
+ return 1;
|
|
|
|
|
+ }
|
|
|
|
|
+ else
|
|
|
|
|
+ {
|
|
|
|
|
+ struct regcache *regcache;
|
|
|
|
|
+ regcache = get_thread_arch_regcache (inferior_ptid, target_gdbarch);
|
|
|
|
|
+ cache->regcache = regcache_dup (regcache);
|
|
|
|
|
+ *this_prologue_cache = cache;
|
|
|
|
|
+ return 1;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ return 0;
|
|
|
|
|
+}
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+static void
|
|
|
|
|
+spu2ppu_dealloc_cache (struct frame_info *self, void *this_cache)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+{
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ struct spu2ppu_cache *cache = this_cache;
|
|
|
|
|
+ regcache_xfree (cache->regcache);
|
|
|
|
|
+}
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+static const struct frame_unwind spu2ppu_unwind = {
|
|
|
|
|
+ ARCH_FRAME,
|
|
|
|
|
+ spu2ppu_this_id,
|
|
|
|
|
+ spu2ppu_prev_register,
|
|
|
|
|
+ NULL,
|
|
|
|
|
+ spu2ppu_sniffer,
|
|
|
|
|
+ spu2ppu_dealloc_cache,
|
|
|
|
|
+ spu2ppu_prev_arch,
|
|
|
|
|
+};
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
|
|
|
|
|
/* Function calling convention. */
|
|
|
|
|
|
|
|
|
|
@@ -1133,7 +1315,7 @@ spu_push_dummy_call (struct gdbarch *gdb
|
|
|
|
|
|
|
|
|
|
/* Set the return address. */
|
|
|
|
|
memset (buf, 0, sizeof buf);
|
|
|
|
|
- store_unsigned_integer (buf, 4, bp_addr);
|
|
|
|
|
+ store_unsigned_integer (buf, 4, SPUADDR_ADDR (bp_addr));
|
|
|
|
|
regcache_cooked_write (regcache, SPU_LR_REGNUM, buf);
|
|
|
|
|
|
|
|
|
|
/* If STRUCT_RETURN is true, then the struct return address (in
|
|
|
|
|
@@ -1142,7 +1324,7 @@ spu_push_dummy_call (struct gdbarch *gdb
|
|
|
|
|
if (struct_return)
|
|
|
|
|
{
|
|
|
|
|
memset (buf, 0, sizeof buf);
|
|
|
|
|
- store_unsigned_integer (buf, 4, struct_addr);
|
|
|
|
|
+ store_unsigned_integer (buf, 4, SPUADDR_ADDR (struct_addr));
|
|
|
|
|
regcache_cooked_write (regcache, regnum++, buf);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -1220,9 +1402,10 @@ spu_push_dummy_call (struct gdbarch *gdb
|
|
|
|
|
static struct frame_id
|
|
|
|
|
spu_dummy_id (struct gdbarch *gdbarch, struct frame_info *this_frame)
|
|
|
|
|
{
|
|
|
|
|
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
|
|
|
|
|
CORE_ADDR pc = get_frame_register_unsigned (this_frame, SPU_PC_REGNUM);
|
|
|
|
|
CORE_ADDR sp = get_frame_register_unsigned (this_frame, SPU_SP_REGNUM);
|
|
|
|
|
- return frame_id_build (sp, pc & -4);
|
|
|
|
|
+ return frame_id_build (SPUADDR (tdep->id, sp), SPUADDR (tdep->id, pc & -4));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Function return value access. */
|
|
|
|
|
@@ -1302,18 +1485,18 @@ spu_software_single_step (struct frame_i
|
|
|
|
|
instruction is a PPE-assisted call, in which case it is at PC + 8.
|
|
|
|
|
Wrap around LS limit to be on the safe side. */
|
|
|
|
|
if ((insn & 0xffffff00) == 0x00002100)
|
|
|
|
|
- next_pc = (pc + 8) & (SPU_LS_SIZE - 1);
|
|
|
|
|
+ next_pc = (SPUADDR_ADDR (pc) + 8) & (SPU_LS_SIZE - 1);
|
|
|
|
|
else
|
|
|
|
|
- next_pc = (pc + 4) & (SPU_LS_SIZE - 1);
|
|
|
|
|
+ next_pc = (SPUADDR_ADDR (pc) + 4) & (SPU_LS_SIZE - 1);
|
|
|
|
|
|
|
|
|
|
- insert_single_step_breakpoint (next_pc);
|
|
|
|
|
+ insert_single_step_breakpoint (SPUADDR (SPUADDR_SPU (pc), next_pc));
|
|
|
|
|
|
|
|
|
|
if (is_branch (insn, &offset, ®))
|
|
|
|
|
{
|
|
|
|
|
CORE_ADDR target = offset;
|
|
|
|
|
|
|
|
|
|
if (reg == SPU_PC_REGNUM)
|
|
|
|
|
- target += pc;
|
|
|
|
|
+ target += SPUADDR_ADDR (pc);
|
|
|
|
|
else if (reg != -1)
|
|
|
|
|
{
|
|
|
|
|
get_frame_register_bytes (frame, reg, 0, 4, buf);
|
|
|
|
|
@@ -1322,12 +1505,35 @@ spu_software_single_step (struct frame_i
|
|
|
|
|
|
|
|
|
|
target = target & (SPU_LS_SIZE - 1);
|
|
|
|
|
if (target != next_pc)
|
|
|
|
|
- insert_single_step_breakpoint (target);
|
|
|
|
|
+ insert_single_step_breakpoint (SPUADDR (SPUADDR_SPU (pc), target));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+/* Disassembler. */
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+static void
|
|
|
|
|
+spu_dis_asm_print_address (bfd_vma addr, struct disassemble_info *info)
|
|
|
|
|
+{
|
|
|
|
|
+ int id = *(int *)info->application_data;
|
|
|
|
|
+ CORE_ADDR spu_addr = SPUADDR (id, addr);
|
|
|
|
|
+ print_address (spu_addr, info->stream);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+}
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+static int
|
|
|
|
|
+gdb_print_insn_spu (bfd_vma memaddr, disassemble_info * info)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+{
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* The opcodes disassembler does 18-bit address arithmetic. Make sure the
|
|
|
|
|
+ SPU ID encoded in the high bits is added back when we call print_address. */
|
|
|
|
|
+ int id = SPUADDR_SPU (memaddr);
|
|
|
|
|
+ info->application_data = &id;
|
|
|
|
|
+ info->print_address_func = spu_dis_asm_print_address;
|
|
|
|
|
+ return print_insn_spu (memaddr, info);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+}
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+
|
|
|
|
|
/* Target overlays for the SPU overlay manager.
|
|
|
|
|
|
|
|
|
|
See the documentation of simple_overlay_update for how the
|
|
|
|
|
@@ -1444,7 +1650,7 @@ static void
|
|
|
|
|
spu_overlay_update_osect (struct obj_section *osect)
|
|
|
|
|
{
|
|
|
|
|
struct spu_overlay_table *ovly_table;
|
|
|
|
|
- CORE_ADDR val;
|
|
|
|
|
+ CORE_ADDR id, val;
|
|
|
|
|
|
|
|
|
|
ovly_table = spu_get_overlay_table (osect->objfile);
|
|
|
|
|
if (!ovly_table)
|
|
|
|
|
@@ -1454,7 +1660,8 @@ spu_overlay_update_osect (struct obj_sec
|
|
|
|
|
if (ovly_table->mapped_ptr == 0)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
- val = read_memory_unsigned_integer (ovly_table->mapped_ptr, 4);
|
|
|
|
|
+ id = SPUADDR_SPU (obj_section_addr (osect));
|
|
|
|
|
+ val = read_memory_unsigned_integer (SPUADDR (id, ovly_table->mapped_ptr), 4);
|
|
|
|
|
osect->ovly_mapped = (val == ovly_table->mapped_val);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -1516,6 +1723,131 @@ spu_overlay_new_objfile (struct objfile
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+/* Insert temporary breakpoint on "main" function of newly loaded
|
|
|
|
|
+ SPE context OBJFILE. */
|
|
|
|
|
+static void
|
|
|
|
|
+spu_catch_start (struct objfile *objfile)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+{
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ struct minimal_symbol *minsym;
|
|
|
|
|
+ struct symtab *symtab;
|
|
|
|
|
+ CORE_ADDR pc;
|
|
|
|
|
+ char buf[32];
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* Do this only if requested by "set spu stop-on-load on". */
|
|
|
|
|
+ if (!spu_stop_on_load_p)
|
|
|
|
|
+ return;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* Consider only SPU objfiles. */
|
|
|
|
|
+ if (!objfile || bfd_get_arch (objfile->obfd) != bfd_arch_spu)
|
|
|
|
|
+ return;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* The main objfile is handled differently. */
|
|
|
|
|
+ if (objfile == symfile_objfile)
|
|
|
|
|
+ return;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* There can be multiple symbols named "main". Search for the
|
|
|
|
|
+ "main" in *this* objfile. */
|
|
|
|
|
+ minsym = lookup_minimal_symbol ("main", NULL, objfile);
|
|
|
|
|
+ if (!minsym)
|
|
|
|
|
+ return;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* If we have debugging information, try to use it -- this
|
|
|
|
|
+ will allow us to properly skip the prologue. */
|
|
|
|
|
+ pc = SYMBOL_VALUE_ADDRESS (minsym);
|
|
|
|
|
+ symtab = find_pc_sect_symtab (pc, SYMBOL_OBJ_SECTION (minsym));
|
|
|
|
|
+ if (symtab != NULL)
|
|
|
|
|
+ {
|
|
|
|
|
+ struct blockvector *bv = BLOCKVECTOR (symtab);
|
|
|
|
|
+ struct block *block = BLOCKVECTOR_BLOCK (bv, GLOBAL_BLOCK);
|
|
|
|
|
+ struct symbol *sym;
|
|
|
|
|
+ struct symtab_and_line sal;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ sym = lookup_block_symbol (block, "main", NULL, VAR_DOMAIN);
|
|
|
|
|
+ if (sym)
|
|
|
|
|
+ {
|
|
|
|
|
+ fixup_symbol_section (sym, objfile);
|
|
|
|
|
+ sal = find_function_start_sal (sym, 1);
|
|
|
|
|
+ pc = sal.pc;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* Use a numerical address for the tbreak command to avoid having
|
|
|
|
|
+ the breakpoint re-set incorrectly. */
|
|
|
|
|
+ xsnprintf (buf, sizeof buf, "*%s", core_addr_to_string (pc));
|
|
|
|
|
+ tbreak_command (buf, 0);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+}
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+/* Lookup OBJFILE corresponding to the current SPU context. */
|
|
|
|
|
+static struct objfile *
|
|
|
|
|
+spu_objfile_from_context (void)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+{
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ struct frame_info *frame = get_current_frame ();
|
|
|
|
|
+ struct gdbarch *gdbarch = get_frame_arch (frame);
|
|
|
|
|
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
|
|
|
|
|
+ struct objfile *obj;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ if (gdbarch_bfd_arch_info (gdbarch)->arch != bfd_arch_spu)
|
|
|
|
|
+ return NULL;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ ALL_OBJFILES (obj)
|
|
|
|
|
+ {
|
|
|
|
|
+ if (obj->sections != obj->sections_end
|
|
|
|
|
+ && SPUADDR_SPU (obj_section_addr (obj->sections)) == tdep->id)
|
|
|
|
|
+ return obj;
|
|
|
|
|
+ }
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ return NULL;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+}
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+/* Flush cache for ea pointer access if available and return 1. Return 0 if
|
|
|
|
|
+ inferior call was not executed. */
|
|
|
|
|
+static void
|
|
|
|
|
+flush_ea_cache (void)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+{
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ struct value *ea_flush_fn = NULL;
|
|
|
|
|
+ struct minimal_symbol *msymbol;
|
|
|
|
|
+ struct objfile *obj;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ obj = spu_objfile_from_context ();
|
|
|
|
|
+ if (obj == NULL)
|
|
|
|
|
+ return;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* Lookup inferior function __cache_flush. */
|
|
|
|
|
+ msymbol = lookup_minimal_symbol ("__cache_flush", NULL, obj);
|
|
|
|
|
+ if (msymbol != NULL)
|
|
|
|
|
+ {
|
|
|
|
|
+ struct type *type;
|
|
|
|
|
+ CORE_ADDR addr;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ type = builtin_type_void;
|
|
|
|
|
+ type = lookup_function_type (type);
|
|
|
|
|
+ type = lookup_pointer_type (type);
|
|
|
|
|
+ addr = SYMBOL_VALUE_ADDRESS (msymbol);
|
|
|
|
|
+ ea_flush_fn = value_from_pointer (type, addr);
|
|
|
|
|
+ }
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ if (ea_flush_fn)
|
|
|
|
|
+ call_function_by_hand (ea_flush_fn, 0, NULL);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+}
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+/* This handler is called when the inferior has stopped. If it is stopped in
|
|
|
|
|
+ SPU architecture then flush the ea cache if used. */
|
|
|
|
|
+static void
|
|
|
|
|
+spu_attach_normal_stop (struct bpstats *bs)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+{
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ if (!spu_auto_flush_cache_p)
|
|
|
|
|
+ return;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ if (!target_has_registers || !target_has_stack || !target_has_memory)
|
|
|
|
|
+ return;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* Temporarily reset the spu_auto_flush_cache_p to avoid recursively
|
|
|
|
|
+ re-entering this function when __cache_flush stops. */
|
|
|
|
|
+ spu_auto_flush_cache_p = 0;
|
|
|
|
|
+ flush_ea_cache ();
|
|
|
|
|
+ spu_auto_flush_cache_p = 1;
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
/* "info spu" commands. */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
@@ -2065,6 +2397,37 @@ info_spu_command (char *args, int from_t
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
+/* Root of all "set spu "/"show spu " commands. */
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+static void
|
|
|
|
|
+show_spu_command (char *args, int from_tty)
|
|
|
|
|
+{
|
|
|
|
|
+ help_list (showspucmdlist, "show spu ", all_commands, gdb_stdout);
|
|
|
|
|
+}
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+static void
|
|
|
|
|
+set_spu_command (char *args, int from_tty)
|
|
|
|
|
+{
|
|
|
|
|
+ help_list (setspucmdlist, "set spu ", all_commands, gdb_stdout);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+}
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+static void
|
|
|
|
|
+show_spu_stop_on_load (struct ui_file *file, int from_tty,
|
|
|
|
|
+ struct cmd_list_element *c, const char *value)
|
|
|
|
|
+{
|
|
|
|
|
+ fprintf_filtered (file, _("Stopping for new SPE threads is %s.\n"),
|
|
|
|
|
+ value);
|
|
|
|
|
+}
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
|
|
|
|
+static void
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+show_spu_auto_flush_cache (struct ui_file *file, int from_tty,
|
|
|
|
|
+ struct cmd_list_element *c, const char *value)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+{
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ fprintf_filtered (file, _("Automatic software-cache flush is %s.\n"),
|
|
|
|
|
+ value);
|
|
|
|
|
+}
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
/* Set up gdbarch struct. */
|
|
|
|
|
|
|
|
|
|
static struct gdbarch *
|
|
|
|
|
@@ -2072,22 +2435,30 @@ spu_gdbarch_init (struct gdbarch_info in
|
|
|
|
|
{
|
|
|
|
|
struct gdbarch *gdbarch;
|
|
|
|
|
struct gdbarch_tdep *tdep;
|
|
|
|
|
+ int id = -1;
|
|
|
|
|
|
|
|
|
|
- /* Find a candidate among the list of pre-declared architectures. */
|
|
|
|
|
- arches = gdbarch_list_lookup_by_info (arches, &info);
|
|
|
|
|
- if (arches != NULL)
|
|
|
|
|
- return arches->gdbarch;
|
|
|
|
|
+ /* Which spufs ID was requested as address space? */
|
|
|
|
|
+ if (info.tdep_info)
|
|
|
|
|
+ id = *(int *)info.tdep_info;
|
|
|
|
|
|
|
|
|
|
- /* Is is for us? */
|
|
|
|
|
- if (info.bfd_arch_info->mach != bfd_mach_spu)
|
|
|
|
|
- return NULL;
|
|
|
|
|
+ /* Find a candidate among extant architectures. */
|
|
|
|
|
+ for (arches = gdbarch_list_lookup_by_info (arches, &info);
|
|
|
|
|
+ arches != NULL;
|
|
|
|
|
+ arches = gdbarch_list_lookup_by_info (arches->next, &info))
|
|
|
|
|
+ {
|
|
|
|
|
+ tdep = gdbarch_tdep (arches->gdbarch);
|
|
|
|
|
+ if (tdep && tdep->id == id)
|
|
|
|
|
+ return arches->gdbarch;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+ }
|
2008-11-07 14:07:25 +00:00
|
|
|
|
|
|
|
|
|
- /* Yes, create a new architecture. */
|
|
|
|
|
+ /* None found, so create a new architecture. */
|
|
|
|
|
tdep = XCALLOC (1, struct gdbarch_tdep);
|
|
|
|
|
+ tdep->id = id;
|
|
|
|
|
+ tdep->lslr = id != -1? spu_lslr (id) : SPU_LS_SIZE - 1;
|
|
|
|
|
gdbarch = gdbarch_alloc (&info, tdep);
|
|
|
|
|
|
|
|
|
|
/* Disassembler. */
|
|
|
|
|
- set_gdbarch_print_insn (gdbarch, print_insn_spu);
|
|
|
|
|
+ set_gdbarch_print_insn (gdbarch, gdb_print_insn_spu);
|
|
|
|
|
|
|
|
|
|
/* Registers. */
|
|
|
|
|
set_gdbarch_num_regs (gdbarch, SPU_NUM_REGS);
|
|
|
|
|
@@ -2118,9 +2489,16 @@ spu_gdbarch_init (struct gdbarch_info in
|
|
|
|
|
set_gdbarch_double_format (gdbarch, floatformats_ieee_double);
|
|
|
|
|
set_gdbarch_long_double_format (gdbarch, floatformats_ieee_double);
|
|
|
|
|
|
|
|
|
|
- /* Address conversion. */
|
|
|
|
|
+ /* Address handling. */
|
|
|
|
|
+ set_gdbarch_address_to_pointer (gdbarch, spu_address_to_pointer);
|
|
|
|
|
set_gdbarch_pointer_to_address (gdbarch, spu_pointer_to_address);
|
|
|
|
|
set_gdbarch_integer_to_address (gdbarch, spu_integer_to_address);
|
|
|
|
|
+ set_gdbarch_address_class_type_flags (gdbarch, spu_address_class_type_flags);
|
|
|
|
|
+ set_gdbarch_address_class_type_flags_to_name
|
|
|
|
|
+ (gdbarch, spu_address_class_type_flags_to_name);
|
|
|
|
|
+ set_gdbarch_address_class_name_to_type_flags
|
|
|
|
|
+ (gdbarch, spu_address_class_name_to_type_flags);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
|
|
|
|
|
/* Inferior function calls. */
|
|
|
|
|
set_gdbarch_call_dummy_location (gdbarch, ON_STACK);
|
|
|
|
|
@@ -2142,6 +2520,9 @@ spu_gdbarch_init (struct gdbarch_info in
|
|
|
|
|
set_gdbarch_skip_prologue (gdbarch, spu_skip_prologue);
|
|
|
|
|
set_gdbarch_in_function_epilogue_p (gdbarch, spu_in_function_epilogue_p);
|
|
|
|
|
|
|
|
|
|
+ /* Cell/B.E. cross-architecture unwinder support. */
|
|
|
|
|
+ frame_unwind_prepend_unwinder (gdbarch, &spu2ppu_unwind);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
/* Breakpoints. */
|
|
|
|
|
set_gdbarch_decr_pc_after_break (gdbarch, 4);
|
|
|
|
|
set_gdbarch_breakpoint_from_pc (gdbarch, spu_breakpoint_from_pc);
|
|
|
|
|
@@ -2163,6 +2544,50 @@ _initialize_spu_tdep (void)
|
|
|
|
|
observer_attach_new_objfile (spu_overlay_new_objfile);
|
|
|
|
|
spu_overlay_data = register_objfile_data ();
|
|
|
|
|
|
|
|
|
|
+ /* Install spu stop-on-load handler. */
|
|
|
|
|
+ observer_attach_new_objfile (spu_catch_start);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* Add ourselves to normal_stop event chain. */
|
|
|
|
|
+ observer_attach_normal_stop (spu_attach_normal_stop);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* Add root prefix command for all "set spu"/"show spu" commands. */
|
|
|
|
|
+ add_prefix_cmd ("spu", no_class, set_spu_command,
|
|
|
|
|
+ _("Various SPU specific commands."),
|
|
|
|
|
+ &setspucmdlist, "set spu ", 0, &setlist);
|
|
|
|
|
+ add_prefix_cmd ("spu", no_class, show_spu_command,
|
|
|
|
|
+ _("Various SPU specific commands."),
|
|
|
|
|
+ &showspucmdlist, "show spu ", 0, &showlist);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* Toggle whether or not to add a temporary breakpoint at the "main"
|
|
|
|
|
+ function of new SPE contexts. */
|
|
|
|
|
+ add_setshow_boolean_cmd ("stop-on-load", class_support,
|
|
|
|
|
+ &spu_stop_on_load_p, _("\
|
|
|
|
|
+Set whether to stop for new SPE threads."),
|
|
|
|
|
+ _("\
|
|
|
|
|
+Show whether to stop for new SPE threads."),
|
|
|
|
|
+ _("\
|
|
|
|
|
+Use \"on\" to give control to the user when a new SPE thread\n\
|
|
|
|
|
+enters its \"main\" function.\n\
|
|
|
|
|
+Use \"off\" to disable stopping for new SPE threads."),
|
|
|
|
|
+ NULL,
|
|
|
|
|
+ show_spu_stop_on_load,
|
|
|
|
|
+ &setspucmdlist, &showspucmdlist);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* Toggle whether or not to automatically flush the software-managed
|
|
|
|
|
+ cache whenever SPE execution stops. */
|
|
|
|
|
+ add_setshow_boolean_cmd ("auto-flush-cache", class_support,
|
|
|
|
|
+ &spu_auto_flush_cache_p, _("\
|
|
|
|
|
+Set whether to automatically flush the software-managed cache."),
|
|
|
|
|
+ _("\
|
|
|
|
|
+Show whether to automatically flush the software-managed cache."),
|
|
|
|
|
+ _("\
|
|
|
|
|
+Use \"on\" to automatically flush the software-managed cache\n\
|
|
|
|
|
+whenever SPE execution stops.\n\
|
|
|
|
|
+Use \"off\" to never automatically flush the software-managed cache."),
|
|
|
|
|
+ NULL,
|
|
|
|
|
+ show_spu_auto_flush_cache,
|
|
|
|
|
+ &setspucmdlist, &showspucmdlist);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
/* Add root prefix command for all "info spu" commands. */
|
|
|
|
|
add_prefix_cmd ("spu", class_info, info_spu_command,
|
|
|
|
|
_("Various SPU specific commands."),
|
2008-11-20 15:44:10 +00:00
|
|
|
|
--- gdb/spu-tdep.h
|
|
|
|
|
+++ gdb/spu-tdep.h
|
2008-11-07 14:07:25 +00:00
|
|
|
|
@@ -50,4 +50,17 @@ enum spu_regnum
|
|
|
|
|
/* Local store. */
|
|
|
|
|
#define SPU_LS_SIZE 0x40000
|
|
|
|
|
|
|
|
|
|
+/* Address conversions. */
|
|
|
|
|
+#define SPUADDR(spu, addr) \
|
|
|
|
|
+ ((spu) != -1? (ULONGEST)1 << 63 | (ULONGEST)(spu) << 32 | (addr) : (addr))
|
|
|
|
|
+#define SPUADDR_SPU(addr) \
|
|
|
|
|
+ (((addr) & (ULONGEST)1 << 63)? (ULONGEST)(addr) >> 32 & 0x7fffffff : -1)
|
|
|
|
|
+#define SPUADDR_ADDR(addr) \
|
|
|
|
|
+ (((addr) & (ULONGEST)1 << 63)? (ULONGEST)(addr) & 0xffffffff : (addr))
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+/* SPU multi-architecture support. */
|
|
|
|
|
+extern void set_spu_solib_ops (struct gdbarch *gdbarch);
|
|
|
|
|
+extern void spu_multiarch_enable (void);
|
|
|
|
|
+extern void spu_multiarch_disable (void);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
#endif
|
2008-11-20 15:44:10 +00:00
|
|
|
|
--- gdb/stack.c
|
|
|
|
|
+++ gdb/stack.c
|
2008-11-07 14:07:25 +00:00
|
|
|
|
@@ -45,6 +45,7 @@
|
|
|
|
|
#include "valprint.h"
|
|
|
|
|
#include "gdbthread.h"
|
|
|
|
|
#include "cp-support.h"
|
|
|
|
|
+#include "arch-utils.h"
|
|
|
|
|
|
|
|
|
|
#include "gdb_assert.h"
|
|
|
|
|
#include <ctype.h>
|
|
|
|
|
@@ -109,6 +110,8 @@ print_stack_frame (struct frame_info *fr
|
|
|
|
|
enum print_what print_what)
|
|
|
|
|
{
|
|
|
|
|
struct print_stack_frame_args args;
|
|
|
|
|
+ struct cleanup *old_chain = save_current_gdbarch ();
|
|
|
|
|
+ current_gdbarch = get_frame_arch (frame);
|
|
|
|
|
|
|
|
|
|
args.frame = frame;
|
|
|
|
|
args.print_level = print_level;
|
|
|
|
|
@@ -118,6 +121,7 @@ print_stack_frame (struct frame_info *fr
|
|
|
|
|
args.print_args = 1;
|
|
|
|
|
|
|
|
|
|
catch_errors (print_stack_frame_stub, &args, "", RETURN_MASK_ERROR);
|
|
|
|
|
+ do_cleanups (old_chain);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct print_args_args
|
|
|
|
|
@@ -223,6 +227,9 @@ print_frame_args (struct symbol *func, s
|
|
|
|
|
stb = ui_out_stream_new (uiout);
|
|
|
|
|
old_chain = make_cleanup_ui_out_stream_delete (stb);
|
|
|
|
|
|
|
|
|
|
+ save_current_gdbarch ();
|
|
|
|
|
+ current_gdbarch = get_frame_arch (frame);
|
|
|
|
|
+
|
|
|
|
|
if (func)
|
|
|
|
|
{
|
|
|
|
|
struct block *b = SYMBOL_BLOCK_VALUE (func);
|
|
|
|
|
@@ -474,9 +481,11 @@ print_frame_info (struct frame_info *fra
|
|
|
|
|
struct symtab_and_line sal;
|
|
|
|
|
int source_print;
|
|
|
|
|
int location_print;
|
|
|
|
|
+ struct cleanup *old_chain;
|
|
|
|
|
|
|
|
|
|
if (get_frame_type (frame) == DUMMY_FRAME
|
|
|
|
|
- || get_frame_type (frame) == SIGTRAMP_FRAME)
|
|
|
|
|
+ || get_frame_type (frame) == SIGTRAMP_FRAME
|
|
|
|
|
+ || get_frame_type (frame) == ARCH_FRAME)
|
|
|
|
|
{
|
|
|
|
|
struct cleanup *uiout_cleanup
|
|
|
|
|
= make_cleanup_ui_out_tuple_begin_end (uiout, "frame");
|
|
|
|
|
@@ -509,6 +518,10 @@ print_frame_info (struct frame_info *fra
|
|
|
|
|
annotate_signal_handler_caller ();
|
|
|
|
|
ui_out_field_string (uiout, "func", "<signal handler called>");
|
|
|
|
|
}
|
|
|
|
|
+ else if (get_frame_type (frame) == ARCH_FRAME)
|
|
|
|
|
+ {
|
|
|
|
|
+ ui_out_field_string (uiout, "func", "<cross-architecture call>");
|
|
|
|
|
+ }
|
|
|
|
|
ui_out_text (uiout, "\n");
|
|
|
|
|
annotate_frame_end ();
|
|
|
|
|
|
|
|
|
|
@@ -522,6 +535,10 @@ print_frame_info (struct frame_info *fra
|
|
|
|
|
the next frame is a SIGTRAMP_FRAME or a DUMMY_FRAME, then the
|
|
|
|
|
next frame was not entered as the result of a call, and we want
|
|
|
|
|
to get the line containing FRAME->pc. */
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ old_chain = save_current_gdbarch ();
|
|
|
|
|
+ current_gdbarch = get_frame_arch (frame);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
find_frame_sal (frame, &sal);
|
|
|
|
|
|
|
|
|
|
location_print = (print_what == LOCATION
|
|
|
|
|
@@ -577,6 +594,7 @@ print_frame_info (struct frame_info *fra
|
|
|
|
|
annotate_frame_end ();
|
|
|
|
|
|
|
|
|
|
gdb_flush (gdb_stdout);
|
|
|
|
|
+ do_cleanups (old_chain);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
2009-01-19 00:46:30 +00:00
|
|
|
|
@@ -1435,6 +1453,7 @@ static void
|
2008-11-07 14:07:25 +00:00
|
|
|
|
print_frame_local_vars (struct frame_info *frame, int num_tabs,
|
|
|
|
|
struct ui_file *stream)
|
|
|
|
|
{
|
|
|
|
|
+ struct cleanup *old_chain;
|
|
|
|
|
struct block *block = get_frame_block (frame, 0);
|
|
|
|
|
int values_printed = 0;
|
|
|
|
|
|
2009-01-19 00:46:30 +00:00
|
|
|
|
@@ -1444,6 +1463,9 @@ print_frame_local_vars (struct frame_inf
|
2008-11-07 14:07:25 +00:00
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+ old_chain = save_current_gdbarch ();
|
|
|
|
|
+ current_gdbarch = get_frame_arch (frame);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
while (block)
|
|
|
|
|
{
|
|
|
|
|
if (print_block_frame_locals (block, frame, num_tabs, stream))
|
2009-01-19 00:46:30 +00:00
|
|
|
|
@@ -1457,6 +1479,8 @@ print_frame_local_vars (struct frame_inf
|
2008-11-07 14:07:25 +00:00
|
|
|
|
|
|
|
|
|
if (!values_printed)
|
|
|
|
|
fprintf_filtered (stream, _("No locals.\n"));
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ do_cleanups (old_chain);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Same, but print labels. */
|
2008-11-20 15:44:10 +00:00
|
|
|
|
--- gdb/target-descriptions.c
|
|
|
|
|
+++ gdb/target-descriptions.c
|
2008-11-07 14:07:25 +00:00
|
|
|
|
@@ -104,6 +104,10 @@ typedef struct tdesc_feature
|
|
|
|
|
} *tdesc_feature_p;
|
|
|
|
|
DEF_VEC_P(tdesc_feature_p);
|
|
|
|
|
|
|
|
|
|
+/* A compatible architecture from a target description. */
|
|
|
|
|
+typedef const struct bfd_arch_info *arch_p;
|
|
|
|
|
+DEF_VEC_P(arch_p);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
/* A target description. */
|
|
|
|
|
|
|
|
|
|
struct target_desc
|
|
|
|
|
@@ -111,6 +115,9 @@ struct target_desc
|
|
|
|
|
/* The architecture reported by the target, if any. */
|
|
|
|
|
const struct bfd_arch_info *arch;
|
|
|
|
|
|
|
|
|
|
+ /* The list of compatible architectures reported by the target. */
|
|
|
|
|
+ VEC(arch_p) *compatible;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
/* Any architecture-specific properties specified by the target. */
|
|
|
|
|
VEC(property_s) *properties;
|
|
|
|
|
|
|
|
|
|
@@ -290,6 +297,28 @@ tdesc_architecture (const struct target_
|
|
|
|
|
{
|
|
|
|
|
return target_desc->arch;
|
|
|
|
|
}
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+/* Return non-zero if this target description is compatible
|
|
|
|
|
+ with the given BFD architecture. */
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+int
|
|
|
|
|
+tdesc_compatible_p (const struct target_desc *target_desc,
|
|
|
|
|
+ const struct bfd_arch_info *arch)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+{
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ const struct bfd_arch_info *compat;
|
|
|
|
|
+ int ix;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ for (ix = 0; VEC_iterate (arch_p, target_desc->compatible, ix, compat);
|
|
|
|
|
+ ix++)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+ {
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ if (compat == arch
|
|
|
|
|
+ || arch->compatible (arch, compat)
|
|
|
|
|
+ || compat->compatible (compat, arch))
|
|
|
|
|
+ return 1;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+ }
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ return 0;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+}
|
2008-11-07 14:07:25 +00:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Return 1 if this target description includes any registers. */
|
|
|
|
|
@@ -885,6 +914,8 @@ free_target_description (void *arg)
|
|
|
|
|
}
|
|
|
|
|
VEC_free (property_s, target_desc->properties);
|
|
|
|
|
|
|
|
|
|
+ VEC_free (arch_p, target_desc->compatible);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
xfree (target_desc);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@@ -895,6 +926,30 @@ make_cleanup_free_target_description (st
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void
|
|
|
|
|
+tdesc_add_compatible (struct target_desc *target_desc,
|
|
|
|
|
+ const struct bfd_arch_info *compatible)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+{
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ const struct bfd_arch_info *compat;
|
|
|
|
|
+ int ix;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ /* If this instance of GDB is compiled without BFD support for the
|
|
|
|
|
+ compatible architecture, simply ignore it -- we would not be able
|
|
|
|
|
+ to handle it anyway. */
|
|
|
|
|
+ if (compatible == NULL)
|
|
|
|
|
+ return;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ for (ix = 0; VEC_iterate (arch_p, target_desc->compatible, ix, compat);
|
|
|
|
|
+ ix++)
|
|
|
|
|
+ if (compat == compatible)
|
|
|
|
|
+ internal_error (__FILE__, __LINE__,
|
|
|
|
|
+ _("Attempted to add duplicate "
|
|
|
|
|
+ "compatible architecture \"%s\""),
|
|
|
|
|
+ compatible->printable_name);
|
|
|
|
|
+
|
|
|
|
|
+ VEC_safe_push (arch_p, target_desc->compatible, compatible);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+}
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+void
|
|
|
|
|
set_tdesc_property (struct target_desc *target_desc,
|
|
|
|
|
const char *key, const char *value)
|
|
|
|
|
{
|
|
|
|
|
@@ -993,6 +1048,7 @@ static void
|
|
|
|
|
maint_print_c_tdesc_cmd (char *args, int from_tty)
|
|
|
|
|
{
|
|
|
|
|
const struct target_desc *tdesc;
|
|
|
|
|
+ const struct bfd_arch_info *compatible;
|
|
|
|
|
const char *filename, *inp;
|
|
|
|
|
char *function, *outp;
|
|
|
|
|
struct property *prop;
|
|
|
|
|
@@ -1049,6 +1105,16 @@ maint_print_c_tdesc_cmd (char *args, int
|
|
|
|
|
printf_unfiltered ("\n");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+ for (ix = 0; VEC_iterate (arch_p, tdesc->compatible, ix, compatible);
|
|
|
|
|
+ ix++)
|
|
|
|
|
+ {
|
|
|
|
|
+ printf_unfiltered
|
|
|
|
|
+ (" tdesc_add_compatible (result, bfd_scan_arch (\"%s\"));\n",
|
|
|
|
|
+ compatible->printable_name);
|
|
|
|
|
+ }
|
|
|
|
|
+ if (ix)
|
|
|
|
|
+ printf_unfiltered ("\n");
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
for (ix = 0; VEC_iterate (property_s, tdesc->properties, ix, prop);
|
|
|
|
|
ix++)
|
|
|
|
|
{
|
2008-11-20 15:44:10 +00:00
|
|
|
|
--- gdb/target-descriptions.h
|
|
|
|
|
+++ gdb/target-descriptions.h
|
2008-11-07 14:07:25 +00:00
|
|
|
|
@@ -123,6 +123,12 @@ int tdesc_numbered_register_choices (con
|
|
|
|
|
const struct bfd_arch_info *tdesc_architecture
|
|
|
|
|
(const struct target_desc *);
|
|
|
|
|
|
|
|
|
|
+/* Return non-zero if this target description is compatible
|
|
|
|
|
+ with the given BFD architecture. */
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+int tdesc_compatible_p (const struct target_desc *,
|
|
|
|
|
+ const struct bfd_arch_info *);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
/* Return the string value of a property named KEY, or NULL if the
|
|
|
|
|
property was not specified. */
|
|
|
|
|
|
|
|
|
|
@@ -169,6 +175,8 @@ void set_tdesc_architecture (struct targ
|
|
|
|
|
const struct bfd_arch_info *);
|
|
|
|
|
void set_tdesc_property (struct target_desc *,
|
|
|
|
|
const char *key, const char *value);
|
|
|
|
|
+void tdesc_add_compatible (struct target_desc *,
|
|
|
|
|
+ const struct bfd_arch_info *);
|
|
|
|
|
|
|
|
|
|
struct tdesc_feature *tdesc_create_feature (struct target_desc *tdesc,
|
|
|
|
|
const char *name);
|
2008-11-20 15:44:10 +00:00
|
|
|
|
--- gdb/target.c
|
|
|
|
|
+++ gdb/target.c
|
2008-11-07 14:07:25 +00:00
|
|
|
|
@@ -91,6 +91,9 @@ static LONGEST target_xfer_partial (stru
|
|
|
|
|
void *readbuf, const void *writebuf,
|
|
|
|
|
ULONGEST offset, LONGEST len);
|
|
|
|
|
|
|
|
|
|
+static struct gdbarch *default_thread_architecture (struct target_ops *ops,
|
|
|
|
|
+ ptid_t ptid);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
static void init_dummy_target (void);
|
|
|
|
|
|
|
|
|
|
static struct target_ops debug_target;
|
2008-11-20 15:44:10 +00:00
|
|
|
|
@@ -485,6 +488,7 @@ update_current_target (void)
|
2008-11-07 14:07:25 +00:00
|
|
|
|
INHERIT (to_find_memory_regions, t);
|
|
|
|
|
INHERIT (to_make_corefile_notes, t);
|
|
|
|
|
INHERIT (to_get_thread_local_address, t);
|
|
|
|
|
+ INHERIT (to_thread_architecture, t);
|
|
|
|
|
INHERIT (to_can_execute_reverse, t);
|
|
|
|
|
/* Do not inherit to_read_description. */
|
|
|
|
|
INHERIT (to_get_ada_task_ptid, t);
|
2008-11-20 15:44:10 +00:00
|
|
|
|
@@ -647,6 +651,8 @@ update_current_target (void)
|
2008-11-07 14:07:25 +00:00
|
|
|
|
de_fault (to_async_mask,
|
|
|
|
|
(int (*) (int))
|
|
|
|
|
return_one);
|
|
|
|
|
+ de_fault (to_thread_architecture,
|
|
|
|
|
+ default_thread_architecture);
|
|
|
|
|
current_target.to_read_description = NULL;
|
|
|
|
|
de_fault (to_get_ada_task_ptid,
|
|
|
|
|
(ptid_t (*) (long, long))
|
2009-01-19 00:46:30 +00:00
|
|
|
|
@@ -2099,7 +2105,8 @@ target_require_runnable (void)
|
2008-11-07 14:07:25 +00:00
|
|
|
|
/* Do not worry about thread_stratum targets that can not
|
|
|
|
|
create inferiors. Assume they will be pushed again if
|
|
|
|
|
necessary, and continue to the process_stratum. */
|
|
|
|
|
- if (t->to_stratum == thread_stratum)
|
|
|
|
|
+ if (t->to_stratum == thread_stratum
|
|
|
|
|
+ || t->to_stratum == arch_stratum)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
error (_("\
|
2009-01-19 00:46:30 +00:00
|
|
|
|
@@ -2259,6 +2266,12 @@ default_watchpoint_addr_within_range (st
|
2008-11-07 14:07:25 +00:00
|
|
|
|
return addr >= start && addr < start + length;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+static struct gdbarch *
|
|
|
|
|
+default_thread_architecture (struct target_ops *ops, ptid_t ptid)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+{
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ return target_gdbarch;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+}
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
static int
|
|
|
|
|
return_zero (void)
|
|
|
|
|
{
|
2009-01-19 00:46:30 +00:00
|
|
|
|
@@ -3148,6 +3161,19 @@ debug_to_find_new_threads (void)
|
2008-11-07 14:07:25 +00:00
|
|
|
|
fputs_unfiltered ("target_find_new_threads ()\n", gdb_stdlog);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+static struct gdbarch *
|
|
|
|
|
+debug_to_thread_architecture (struct target_ops *ops, ptid_t ptid)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+{
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ struct gdbarch *retval;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ retval = debug_target.to_thread_architecture (ops, ptid);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+ fprintf_unfiltered (gdb_stdlog, "target_thread_architecture (%s) = %p [%s]\n",
|
|
|
|
|
+ target_pid_to_str (ptid), retval,
|
|
|
|
|
+ gdbarch_bfd_arch_info (retval)->printable_name);
|
|
|
|
|
+ return retval;
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+}
|
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
static void
|
|
|
|
|
debug_to_stop (ptid_t ptid)
|
|
|
|
|
{
|
2009-01-19 00:46:30 +00:00
|
|
|
|
@@ -3233,6 +3259,7 @@ setup_target_debug (void)
|
2008-11-07 14:07:25 +00:00
|
|
|
|
current_target.to_stop = debug_to_stop;
|
|
|
|
|
current_target.to_rcmd = debug_to_rcmd;
|
|
|
|
|
current_target.to_pid_to_exec_file = debug_to_pid_to_exec_file;
|
|
|
|
|
+ current_target.to_thread_architecture = debug_to_thread_architecture;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2008-11-20 15:44:10 +00:00
|
|
|
|
--- gdb/target.h
|
|
|
|
|
+++ gdb/target.h
|
2008-11-07 14:07:25 +00:00
|
|
|
|
@@ -62,7 +62,8 @@ enum strata
|
|
|
|
|
file_stratum, /* Executable files, etc */
|
|
|
|
|
core_stratum, /* Core dump files */
|
|
|
|
|
process_stratum, /* Executing processes */
|
|
|
|
|
- thread_stratum /* Executing threads */
|
|
|
|
|
+ thread_stratum, /* Executing threads */
|
|
|
|
|
+ arch_stratum /* Architecture overrides */
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
enum thread_control_capabilities
|
2009-01-19 00:46:30 +00:00
|
|
|
|
@@ -535,6 +536,9 @@ struct target_ops
|
2008-11-07 14:07:25 +00:00
|
|
|
|
simultaneously? */
|
|
|
|
|
int (*to_supports_multi_process) (void);
|
|
|
|
|
|
|
|
|
|
+ /* Determine current architecture of thread PTID. */
|
|
|
|
|
+ struct gdbarch *(*to_thread_architecture) (struct target_ops *, ptid_t);
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
int to_magic;
|
|
|
|
|
/* Need sub-structure for target machine related rather than comm related?
|
|
|
|
|
*/
|
2009-01-19 00:46:30 +00:00
|
|
|
|
@@ -1040,6 +1044,11 @@ extern char *normal_pid_to_str (ptid_t p
|
2008-11-07 14:07:25 +00:00
|
|
|
|
#define target_pid_to_exec_file(pid) \
|
|
|
|
|
(current_target.to_pid_to_exec_file) (pid)
|
2008-09-12 23:16:14 +00:00
|
|
|
|
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+/* Determine current architecture of thread PTID. */
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
+#define target_thread_architecture(ptid) \
|
|
|
|
|
+ (current_target.to_thread_architecture (¤t_target, ptid))
|
2008-09-12 23:16:14 +00:00
|
|
|
|
+
|
2008-11-07 14:07:25 +00:00
|
|
|
|
/*
|
|
|
|
|
* Iterator function for target memory regions.
|
|
|
|
|
* Calls a callback function once for each memory region 'mapped'
|
2008-11-20 15:44:10 +00:00
|
|
|
|
--- gdb/testsuite/gdb.base/dump.exp
|
|
|
|
|
+++ gdb/testsuite/gdb.base/dump.exp
|
2008-11-07 14:07:25 +00:00
|
|
|
|
@@ -42,6 +42,12 @@ if {[istarget "ia64*-*-*"] || [istarget
|
|
|
|
|
set is64bitonly "yes"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+if {[istarget "spu*-*-*"]} then {
|
|
|
|
|
+ # The internal address format used for the combined Cell/B.E.
|
|
|
|
|
+ # debugger required 64-bit.
|
|
|
|
|
+ set is64bitonly "yes"
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
if { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable ${options}] != "" } {
|
|
|
|
|
untested dump.exp
|
|
|
|
|
return -1
|
2008-11-20 15:44:10 +00:00
|
|
|
|
--- gdb/testsuite/gdb.xml/tdesc-regs.exp
|
|
|
|
|
+++ gdb/testsuite/gdb.xml/tdesc-regs.exp
|
2008-09-12 23:16:14 +00:00
|
|
|
|
@@ -39,6 +39,16 @@ switch -glob -- [istarget] {
|
|
|
|
|
set regdir "rs6000/"
|
|
|
|
|
set core-regs {power-core.xml}
|
|
|
|
|
}
|
|
|
|
|
+ "spu*-*-*" {
|
|
|
|
|
+ # This may be either the spu-linux-nat target, or the Cell/B.E.
|
|
|
|
|
+ # multi-architecture debugger in SPU standalone executable mode.
|
|
|
|
|
+ # We do not support XML register sets on SPU in either case.
|
|
|
|
|
+ # However, the multi-arch debugger will accept XML registers sets
|
|
|
|
|
+ # (on the PowerPC side), hence the test below would fail.
|
|
|
|
|
+ # Simply return unconditionally here.
|
|
|
|
|
+ unsupported "register tests"
|
|
|
|
|
+ return 0
|
|
|
|
|
+ }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# If no core registers were specified, assume this target does not
|
2008-11-20 15:44:10 +00:00
|
|
|
|
--- gdb/thread.c
|
|
|
|
|
+++ gdb/thread.c
|
2009-01-19 00:46:30 +00:00
|
|
|
|
@@ -767,6 +767,7 @@ switch_to_thread (ptid_t ptid)
|
2008-11-07 14:07:25 +00:00
|
|
|
|
inferior_ptid = ptid;
|
|
|
|
|
reinit_frame_cache ();
|
|
|
|
|
registers_changed ();
|
|
|
|
|
+ current_gdbarch = get_regcache_arch (get_current_regcache ());
|
|
|
|
|
|
|
|
|
|
/* We don't check for is_stopped, because we're called at times
|
|
|
|
|
while in the TARGET_RUNNING state, e.g., while handling an
|
2008-11-20 15:44:10 +00:00
|
|
|
|
--- gdb/utils.c
|
|
|
|
|
+++ gdb/utils.c
|
2009-01-19 00:46:30 +00:00
|
|
|
|
@@ -3022,7 +3022,6 @@ core_addr_to_string_nz (const CORE_ADDR
|
2008-11-07 14:07:25 +00:00
|
|
|
|
CORE_ADDR
|
|
|
|
|
string_to_core_addr (const char *my_string)
|
|
|
|
|
{
|
|
|
|
|
- int addr_bit = gdbarch_addr_bit (current_gdbarch);
|
|
|
|
|
CORE_ADDR addr = 0;
|
|
|
|
|
|
|
|
|
|
if (my_string[0] == '0' && tolower (my_string[1]) == 'x')
|
2009-01-19 00:46:30 +00:00
|
|
|
|
@@ -3038,17 +3037,6 @@ string_to_core_addr (const char *my_stri
|
2008-11-07 14:07:25 +00:00
|
|
|
|
else
|
|
|
|
|
error (_("invalid hex \"%s\""), my_string);
|
|
|
|
|
}
|
|
|
|
|
-
|
|
|
|
|
- /* Not very modular, but if the executable format expects
|
|
|
|
|
- addresses to be sign-extended, then do so if the address was
|
|
|
|
|
- specified with only 32 significant bits. Really this should
|
|
|
|
|
- be determined by the target architecture, not by the object
|
|
|
|
|
- file. */
|
|
|
|
|
- if (i - 2 == addr_bit / 4
|
|
|
|
|
- && exec_bfd
|
|
|
|
|
- && bfd_get_sign_extend_vma (exec_bfd))
|
|
|
|
|
- addr = (addr ^ ((CORE_ADDR) 1 << (addr_bit - 1)))
|
|
|
|
|
- - ((CORE_ADDR) 1 << (addr_bit - 1));
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2008-11-20 15:44:10 +00:00
|
|
|
|
--- gdb/varobj.c
|
|
|
|
|
+++ gdb/varobj.c
|
2008-11-07 14:07:25 +00:00
|
|
|
|
@@ -427,6 +427,8 @@ static struct frame_info *
|
|
|
|
|
find_frame_addr_in_frame_chain (CORE_ADDR frame_addr)
|
|
|
|
|
{
|
|
|
|
|
struct frame_info *frame = NULL;
|
|
|
|
|
+ CORE_ADDR frame_base;
|
|
|
|
|
+ int addr_bit;
|
|
|
|
|
|
|
|
|
|
if (frame_addr == (CORE_ADDR) 0)
|
|
|
|
|
return NULL;
|
|
|
|
|
@@ -436,7 +438,17 @@ find_frame_addr_in_frame_chain (CORE_ADD
|
|
|
|
|
frame = get_prev_frame (frame);
|
|
|
|
|
if (frame == NULL)
|
|
|
|
|
return NULL;
|
|
|
|
|
- if (get_frame_base_address (frame) == frame_addr)
|
|
|
|
|
+
|
|
|
|
|
+ /* The CORE_ADDR we get as argument was parsed from a string GDB
|
|
|
|
|
+ output as $fp. This output got truncated to gdbarch_addr_bit.
|
|
|
|
|
+ Truncate the frame base address in the same manner before
|
|
|
|
|
+ comparing it against our argument. */
|
|
|
|
|
+ frame_base = get_frame_base_address (frame);
|
|
|
|
|
+ addr_bit = gdbarch_addr_bit (get_frame_arch (frame));
|
|
|
|
|
+ if (addr_bit < (sizeof (CORE_ADDR) * HOST_CHAR_BIT))
|
|
|
|
|
+ frame_base &= ((CORE_ADDR) 1 << addr_bit) - 1;
|
|
|
|
|
+
|
|
|
|
|
+ if (frame_base == frame_addr)
|
|
|
|
|
return frame;
|
|
|
|
|
}
|
|
|
|
|
}
|
2008-11-20 15:44:10 +00:00
|
|
|
|
--- gdb/xml-tdesc.c
|
|
|
|
|
+++ gdb/xml-tdesc.c
|
2008-11-07 14:07:25 +00:00
|
|
|
|
@@ -106,6 +106,20 @@ tdesc_end_arch (struct gdb_xml_parser *p
|
|
|
|
|
set_tdesc_architecture (data->tdesc, arch);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
+/* Handle the end of a <compatible> element and its value. */
|
|
|
|
|
+
|
|
|
|
|
+static void
|
|
|
|
|
+tdesc_end_compatible (struct gdb_xml_parser *parser,
|
|
|
|
|
+ const struct gdb_xml_element *element,
|
|
|
|
|
+ void *user_data, const char *body_text)
|
|
|
|
|
+{
|
|
|
|
|
+ struct tdesc_parsing_data *data = user_data;
|
|
|
|
|
+ const struct bfd_arch_info *arch;
|
|
|
|
|
+
|
|
|
|
|
+ arch = bfd_scan_arch (body_text);
|
|
|
|
|
+ tdesc_add_compatible (data->tdesc, arch);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
/* Handle the start of a <target> element. */
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
@@ -345,6 +359,8 @@ static const struct gdb_xml_attribute ta
|
|
|
|
|
static const struct gdb_xml_element target_children[] = {
|
|
|
|
|
{ "architecture", NULL, NULL, GDB_XML_EF_OPTIONAL,
|
|
|
|
|
NULL, tdesc_end_arch },
|
|
|
|
|
+ { "compatible", NULL, NULL, GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
|
|
|
|
|
+ NULL, tdesc_end_compatible },
|
|
|
|
|
{ "feature", feature_attributes, feature_children,
|
|
|
|
|
GDB_XML_EF_OPTIONAL | GDB_XML_EF_REPEATABLE,
|
|
|
|
|
tdesc_start_feature, NULL },
|
2008-11-20 15:44:10 +00:00
|
|
|
|
--- gdb/xstormy16-tdep.c
|
|
|
|
|
+++ gdb/xstormy16-tdep.c
|
2008-11-07 14:07:25 +00:00
|
|
|
|
@@ -592,7 +592,8 @@ xstormy16_skip_trampoline_code (struct f
|
|
|
|
|
and vice versa. */
|
|
|
|
|
|
|
|
|
|
static CORE_ADDR
|
|
|
|
|
-xstormy16_pointer_to_address (struct type *type, const gdb_byte *buf)
|
|
|
|
|
+xstormy16_pointer_to_address (struct gdbarch *gdbarch,
|
|
|
|
|
+ struct type *type, const gdb_byte *buf)
|
|
|
|
|
{
|
|
|
|
|
enum type_code target = TYPE_CODE (TYPE_TARGET_TYPE (type));
|
|
|
|
|
CORE_ADDR addr = extract_unsigned_integer (buf, TYPE_LENGTH (type));
|
|
|
|
|
@@ -608,7 +609,8 @@ xstormy16_pointer_to_address (struct typ
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
-xstormy16_address_to_pointer (struct type *type, gdb_byte *buf, CORE_ADDR addr)
|
|
|
|
|
+xstormy16_address_to_pointer (struct gdbarch *gdbarch,
|
|
|
|
|
+ struct type *type, gdb_byte *buf, CORE_ADDR addr)
|
|
|
|
|
{
|
|
|
|
|
enum type_code target = TYPE_CODE (TYPE_TARGET_TYPE (type));
|
|
|
|
|
|