diff options
author | Ulrich Weigand <uweigand@de.ibm.com> | 2009-07-31 15:31:08 +0000 |
---|---|---|
committer | Ulrich Weigand <uweigand@de.ibm.com> | 2009-07-31 15:31:08 +0000 |
commit | cc5f0d615034abd00afe97bfaac585e433924685 (patch) | |
tree | e5bf9a5dd62fd60d2cfe4fba38463b6fd92ea88e /gdb/spu-tdep.c | |
parent | 0b9ff2c0a421194cbef8937954cdbbd624d066b0 (diff) | |
download | gdb-cc5f0d615034abd00afe97bfaac585e433924685.zip gdb-cc5f0d615034abd00afe97bfaac585e433924685.tar.gz gdb-cc5f0d615034abd00afe97bfaac585e433924685.tar.bz2 |
* ppc-linux-tdep.c: Include "solib.h", "solist.h", "exceptions.h",
"arch-utils.h", and "spu-tdep.h".
(spu_context_objfile, spe_context_lm_addr, spe_context_offset):
New static variables.
(spe_context_cache_ptid, spe_context_cache_address): Likewise.
(ppc_linux_spe_context_lookup): New function.
(ppc_linux_spe_context_inferior_created): Likewise.
(ppc_linux_spe_context_solib_loaded): Likewise.
(ppc_linux_spe_context_solib_unloaded): Likewise.
(ppc_linux_spe_context): Likewise.
(struct ppu2spu_cache, struct ppu2spu_data): New data types.
(ppu2spu_prev_arch, ppu2spu_this_id, ppu2spu_prev_register,
ppu2spu_unwind_register, ppu2spu_sniffer,
ppu2spu_dealloc_cache): New functions.
(ppu2spu_unwind): New static variable.
(ppc_linux_init_abi): Install cross-architecture unwinder.
(_initialize_ppc_linux_tdep): Attach to observers.
* spu-tdep.c (struct spu2ppu_cache): New data type.
(spu2ppu_prev_arch, spu2ppu_this_id, spu2ppu_prev_register,
spu2ppu_sniffer, spu2ppu_dealloc_cache): New functions.
(spu2ppu_unwind): New static variable.
(spu_gdbarch_init): Install cross-architecture unwinder.
Diffstat (limited to 'gdb/spu-tdep.c')
-rw-r--r-- | gdb/spu-tdep.c | 107 |
1 files changed, 107 insertions, 0 deletions
diff --git a/gdb/spu-tdep.c b/gdb/spu-tdep.c index aa456d7..5e70521 100644 --- a/gdb/spu-tdep.c +++ b/gdb/spu-tdep.c @@ -1088,6 +1088,110 @@ spu_write_pc (struct regcache *regcache, CORE_ADDR pc) } +/* Cell/B.E. cross-architecture unwinder support. */ + +struct spu2ppu_cache +{ + struct frame_id frame_id; + struct regcache *regcache; +}; + +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); +} + +static void +spu2ppu_this_id (struct frame_info *this_frame, + void **this_cache, struct frame_id *this_id) +{ + 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) +{ + struct spu2ppu_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); +} + +static int +spu2ppu_sniffer (const struct frame_unwind *self, + struct frame_info *this_frame, void **this_prologue_cache) +{ + struct gdbarch *gdbarch = get_frame_arch (this_frame); + enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + CORE_ADDR base, func, backchain; + gdb_byte buf[4]; + + if (gdbarch_bfd_arch_info (target_gdbarch)->arch == bfd_arch_spu) + return 0; + + 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, byte_order); + + if (!backchain) + { + struct frame_info *fi; + + struct spu2ppu_cache *cache + = FRAME_OBSTACK_CALLOC (1, struct spu2ppu_cache); + + cache->frame_id = frame_id_build (base + 16, func); + + 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; + + 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; + } + } + + return 0; +} + +static void +spu2ppu_dealloc_cache (struct frame_info *self, void *this_cache) +{ + struct spu2ppu_cache *cache = this_cache; + regcache_xfree (cache->regcache); +} + +static const struct frame_unwind spu2ppu_unwind = { + ARCH_FRAME, + spu2ppu_this_id, + spu2ppu_prev_register, + NULL, + spu2ppu_sniffer, + spu2ppu_dealloc_cache, + spu2ppu_prev_arch, +}; + + /* Function calling convention. */ static CORE_ADDR @@ -2310,6 +2414,9 @@ spu_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) 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); + /* Breakpoints. */ set_gdbarch_decr_pc_after_break (gdbarch, 4); set_gdbarch_breakpoint_from_pc (gdbarch, spu_breakpoint_from_pc); |