kgdb - Fix kernel trapframe backtraces for i386
authorMatthew Dillon <dillon@apollo.backplane.com>
Mon, 28 Dec 2009 02:19:59 +0000 (18:19 -0800)
committerMatthew Dillon <dillon@apollo.backplane.com>
Mon, 28 Dec 2009 02:19:59 +0000 (18:19 -0800)
* A recent gdb update removed our stack frame sniffer hooks,
  add them back in for i386.

* I got trapframe to work properly for i386.  I dunno about
  interrupt frames.

gnu/usr.bin/gdb/kgdb/kgdb.c
gnu/usr.bin/gdb/kgdb/kgdb.h
gnu/usr.bin/gdb/kgdb/trgt.c
gnu/usr.bin/gdb/kgdb/trgt_i386.c

index d38525f..77ad5c5 100644 (file)
@@ -64,6 +64,7 @@
 #include <gdbcore.h>
 #include <wrapper.h>
 #include <observer.h>
+#include <arch-utils.h>
 
 #include "kgdb.h"
 
index 4b72303..40aa95a 100644 (file)
@@ -54,6 +54,8 @@ void kgdb_trgt_fetch_registers(struct target_ops *, struct regcache *, int);
 void kld_init(void);
 void kld_new_objfile(struct objfile *);
 
+extern const struct frame_unwind kgdb_trgt_trapframe_unwind;
+
 struct kthr *kgdb_thr_first(void);
 struct kthr *kgdb_thr_init(void);
 struct kthr *kgdb_thr_lookup_tid(int);
index a884005..4ccff73 100644 (file)
@@ -136,6 +136,8 @@ kgdb_trgt_open(char *filename, int from_tty)
        if (curkthr != 0)
                inferior_ptid = ptid_build(curkthr->pid, 0, curkthr->tid);
 
+       frame_unwind_prepend_unwinder(get_frame_arch(get_current_frame()), &kgdb_trgt_trapframe_unwind);
+
        if (ontop) {
                /* XXX: fetch registers? */
                kld_init();
index f9dd0af..8932266 100644 (file)
@@ -239,6 +239,7 @@ struct kgdb_frame_cache {
 #define        FT_INTRFRAME            2
 /*#define      FT_INTRTRAPFRAME        3*/
 #define        FT_TIMERFRAME           4
+#define        FT_CALLTRAP             5
 
 static int kgdb_trgt_frame_offset[15] = {
        offsetof(struct trapframe, tf_eax),
@@ -261,8 +262,6 @@ static int kgdb_trgt_frame_offset[15] = {
 static struct kgdb_frame_cache *
 kgdb_trgt_frame_cache(struct frame_info *next_frame, void **this_cache)
 {
-       enum bfd_endian byte_order = gdbarch_byte_order(get_frame_arch(next_frame));
-       char buf[MAX_REGISTER_SIZE];
        struct kgdb_frame_cache *cache;
        char *pname;
 
@@ -271,9 +270,12 @@ kgdb_trgt_frame_cache(struct frame_info *next_frame, void **this_cache)
                cache = FRAME_OBSTACK_ZALLOC(struct kgdb_frame_cache);
                *this_cache = cache;
                cache->pc = get_frame_address_in_block(next_frame);
+               cache->sp = get_frame_sp(next_frame);
                find_pc_partial_function(cache->pc, &pname, NULL, NULL);
 
-               if (pname[0] != 'X')
+               if (strcmp(pname, "calltrap") == 0)
+                       cache->frame_type = FT_CALLTRAP;
+               else if (pname[0] != 'X')
                        cache->frame_type = FT_NORMAL;
                else if (strcmp(pname, "Xtimerint") == 0)
                        cache->frame_type = FT_TIMERFRAME;
@@ -285,11 +287,6 @@ kgdb_trgt_frame_cache(struct frame_info *next_frame, void **this_cache)
                        */
                else
                        cache->frame_type = FT_INTRFRAME;
-
-               frame_unwind_register(next_frame, I386_ESP_REGNUM, buf);
-               cache->sp = extract_unsigned_integer(buf,
-                   register_size(get_frame_arch(next_frame), I386_ESP_REGNUM),
-                   byte_order);
        }
        return (cache);
 }
@@ -318,6 +315,7 @@ kgdb_trgt_trapframe_prev_register(struct frame_info *next_frame,
        ofs = kgdb_trgt_frame_offset[regnum] + 4;
 
        cache = kgdb_trgt_frame_cache(next_frame, this_cache);
+
        switch (cache->frame_type) {
        case FT_NORMAL:
                break;
@@ -331,6 +329,9 @@ kgdb_trgt_trapframe_prev_register(struct frame_info *next_frame,
                ofs -= ofs_fix;
                break;
                */
+       case FT_CALLTRAP:
+               ofs += 0;
+               break;
        default:
                fprintf_unfiltered(gdb_stderr, "Correct FT_XXX frame offsets "
                   "for %d\n", cache->frame_type);