From baed091b2b498c9cd74af81c6891ad13c312ee47 Mon Sep 17 00:00:00 2001 From: Michal Ludvig Date: Thu, 24 Oct 2002 01:27:43 +0000 Subject: [PATCH] 2002-10-24 Michal Ludvig * dwarf2cfi.c (struct context) (struct context_reg): Moved to dwarf2cfi.h (context_alloc, frame_state_alloc, context_cpy): Made extern instead of static, removed prototypes. * dwarf2cfi.h (struct context) (struct context_reg): New, moved from dwarf2cfi.c (context_alloc, frame_state_alloc, context_cpy): New prototypes. * x86-64-linux-tdep.c (x86_64_linux_sigtramp_saved_pc): Changed from static to extern. (LINUX_SIGINFO_SIZE, LINUX_SIGCONTEXT_PC_OFFSET) (LINUX_SIGCONTEXT_FP_OFFSET) (LINUX_UCONTEXT_SIGCONTEXT_OFFSET): Adjusted. (x86_64_linux_in_sigtramp, x86_64_linux_frame_chain) (x86_64_init_frame_pc, x86_64_init_extra_frame_info): New. * x86-64-tdep.c (x86_64_gdbarch_init): Several set_gdbarch_*() calls now use x86-64 specific functions instead of DWARF2 CFI ones. * x86-64-tdep.h (x86_64_linux_in_sigtramp) (x86_64_linux_frame_chain, x86_64_init_frame_pc) (x86_64_init_extra_frame_info): New prototypes. --- gdb/ChangeLog | 24 ++++++++++++ gdb/dwarf2cfi.c | 40 ++------------------ gdb/dwarf2cfi.h | 34 +++++++++++++++++ gdb/x86-64-linux-tdep.c | 83 ++++++++++++++++++++++++++++++++++++----- gdb/x86-64-tdep.c | 11 +++--- gdb/x86-64-tdep.h | 6 ++- 6 files changed, 145 insertions(+), 53 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 985d12176b6..daa56c480f3 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,27 @@ +2002-10-24 Michal Ludvig + + * dwarf2cfi.c (struct context) + (struct context_reg): Moved to dwarf2cfi.h + (context_alloc, frame_state_alloc, context_cpy): + Made extern instead of static, removed prototypes. + * dwarf2cfi.h (struct context) + (struct context_reg): New, moved from dwarf2cfi.c + (context_alloc, frame_state_alloc, context_cpy): + New prototypes. + * x86-64-linux-tdep.c (x86_64_linux_sigtramp_saved_pc): + Changed from static to extern. + (LINUX_SIGINFO_SIZE, LINUX_SIGCONTEXT_PC_OFFSET) + (LINUX_SIGCONTEXT_FP_OFFSET) + (LINUX_UCONTEXT_SIGCONTEXT_OFFSET): Adjusted. + (x86_64_linux_in_sigtramp, x86_64_linux_frame_chain) + (x86_64_init_frame_pc, x86_64_init_extra_frame_info): New. + * x86-64-tdep.c (x86_64_gdbarch_init): Several + set_gdbarch_*() calls now use x86-64 specific functions + instead of DWARF2 CFI ones. + * x86-64-tdep.h (x86_64_linux_in_sigtramp) + (x86_64_linux_frame_chain, x86_64_init_frame_pc) + (x86_64_init_extra_frame_info): New prototypes. + 2002-10-23 David Carlton * linespec.c: #include "parser-defs.h". diff --git a/gdb/dwarf2cfi.c b/gdb/dwarf2cfi.c index 18782b16dc8..41e645b8866 100644 --- a/gdb/dwarf2cfi.c +++ b/gdb/dwarf2cfi.c @@ -90,37 +90,6 @@ struct fde_array int array_size; }; -struct context_reg -{ - union - { - unsigned int reg; - long offset; - CORE_ADDR addr; - } - loc; - enum - { - REG_CTX_UNSAVED, - REG_CTX_SAVED_OFFSET, - REG_CTX_SAVED_REG, - REG_CTX_SAVED_ADDR, - REG_CTX_VALUE, - } - how; -}; - -/* This is the register and unwind state for a particular frame. */ -struct context -{ - struct context_reg *reg; - - CORE_ADDR cfa; - CORE_ADDR ra; - void *lsda; - int args_size; -}; - struct frame_state_reg { union @@ -208,11 +177,8 @@ static struct fde_unit *fde_unit_alloc (void); static struct cie_unit *cie_unit_alloc (void); static void fde_chunks_need_space (); -static struct context *context_alloc (); -static struct frame_state *frame_state_alloc (); static void unwind_tmp_obstack_init (); static void unwind_tmp_obstack_free (); -static void context_cpy (struct context *dst, struct context *src); static unsigned int read_1u (bfd * abfd, char **p); static int read_1s (bfd * abfd, char **p); @@ -286,7 +252,7 @@ fde_chunks_need_space (void) } /* Alocate a new `struct context' on temporary obstack. */ -static struct context * +struct context * context_alloc (void) { struct context *context; @@ -303,7 +269,7 @@ context_alloc (void) } /* Alocate a new `struct frame_state' on temporary obstack. */ -static struct frame_state * +struct frame_state * frame_state_alloc (void) { struct frame_state *fs; @@ -332,7 +298,7 @@ unwind_tmp_obstack_free (void) unwind_tmp_obstack_init (); } -static void +void context_cpy (struct context *dst, struct context *src) { int regs_size = sizeof (struct context_reg) * NUM_REGS; diff --git a/gdb/dwarf2cfi.h b/gdb/dwarf2cfi.h index f4c675aca7b..b6abbdeebe6 100644 --- a/gdb/dwarf2cfi.h +++ b/gdb/dwarf2cfi.h @@ -22,6 +22,37 @@ #ifndef DWARF2CFI_H #define DWARF2CFI_H +struct context_reg +{ + union + { + unsigned int reg; + long offset; + CORE_ADDR addr; + } + loc; + enum + { + REG_CTX_UNSAVED, + REG_CTX_SAVED_OFFSET, + REG_CTX_SAVED_REG, + REG_CTX_SAVED_ADDR, + REG_CTX_VALUE, + } + how; +}; + +/* This is the register and unwind state for a particular frame. */ +struct context +{ + struct context_reg *reg; + + CORE_ADDR cfa; + CORE_ADDR ra; + void *lsda; + int args_size; +}; + /* Return the frame address. */ CORE_ADDR cfi_read_fp (); @@ -63,4 +94,7 @@ void cfi_get_saved_register (char *raw_buffer, void cfi_virtual_frame_pointer (CORE_ADDR pc, int *frame_regnum, LONGEST * frame_offset); +struct context *context_alloc (); +void context_cpy (struct context *dst, struct context *src); +struct frame_state *frame_state_alloc (); #endif diff --git a/gdb/x86-64-linux-tdep.c b/gdb/x86-64-linux-tdep.c index ac41daa8849..71e3276c8a2 100644 --- a/gdb/x86-64-linux-tdep.c +++ b/gdb/x86-64-linux-tdep.c @@ -35,8 +35,10 @@ #define LINUX_SIGTRAMP_OFFSET1 (7) static const unsigned char linux_sigtramp_code[] = { - LINUX_SIGTRAMP_INSN0, 0xc7, 0xc0, 0x89, 0x00, 0x00, 0x00, /* mov $0x89,%rax */ - LINUX_SIGTRAMP_INSN1, 0x05 /* syscall */ + /* mov $__NR_rt_sigreturn,%rax */ + LINUX_SIGTRAMP_INSN0, 0xc7, 0xc0, 0x0f, 0x00, 0x00, 0x00, + /* syscall */ + LINUX_SIGTRAMP_INSN1, 0x05 }; #define LINUX_SIGTRAMP_LEN (sizeof linux_sigtramp_code) @@ -68,17 +70,22 @@ x86_64_linux_sigtramp_start (CORE_ADDR pc) return pc; } -#define LINUX_SIGINFO_SIZE 128 +#define LINUX_SIGINFO_SIZE 0 /* Offset to struct sigcontext in ucontext, from . */ -#define LINUX_UCONTEXT_SIGCONTEXT_OFFSET (36) +#define LINUX_UCONTEXT_SIGCONTEXT_OFFSET 40 + +/* Offset to saved PC in sigcontext, from . */ +#define LINUX_SIGCONTEXT_PC_OFFSET 128 +#define LINUX_SIGCONTEXT_FP_OFFSET 120 /* Assuming FRAME is for a GNU/Linux sigtramp routine, return the address of the associated sigcontext structure. */ -CORE_ADDR +static CORE_ADDR x86_64_linux_sigcontext_addr (struct frame_info *frame) { CORE_ADDR pc; + ULONGEST rsp; pc = x86_64_linux_sigtramp_start (frame->pc); if (pc) @@ -92,7 +99,8 @@ x86_64_linux_sigcontext_addr (struct frame_info *frame) /* This is the top frame. */ - return read_register (SP_REGNUM) + LINUX_SIGINFO_SIZE + + rsp = read_register (SP_REGNUM); + return rsp + LINUX_SIGINFO_SIZE + LINUX_UCONTEXT_SIGCONTEXT_OFFSET; } @@ -101,13 +109,10 @@ x86_64_linux_sigcontext_addr (struct frame_info *frame) return 0; } -/* Offset to saved PC in sigcontext, from . */ -#define LINUX_SIGCONTEXT_PC_OFFSET (136) - /* Assuming FRAME is for a GNU/Linux sigtramp routine, return the saved program counter. */ -CORE_ADDR +static CORE_ADDR x86_64_linux_sigtramp_saved_pc (struct frame_info *frame) { CORE_ADDR addr; @@ -135,3 +140,61 @@ x86_64_linux_frame_saved_pc (struct frame_info *frame) return x86_64_linux_sigtramp_saved_pc (frame); return cfi_get_ra (frame); } + +/* Return whether PC is in a GNU/Linux sigtramp routine. */ + +int +x86_64_linux_in_sigtramp (CORE_ADDR pc, char *name) +{ + if (name) + return STREQ ("__restore_rt", name); + + return (x86_64_linux_sigtramp_start (pc) != 0); +} + +CORE_ADDR +x86_64_linux_frame_chain (struct frame_info *fi) +{ + ULONGEST addr; + CORE_ADDR fp, pc; + + if (! fi->signal_handler_caller) + { + fp = cfi_frame_chain (fi); + if(fp) + return fp; + else + addr = fi->frame; + } + else + addr = fi->next->frame; + + addr += LINUX_SIGINFO_SIZE + LINUX_UCONTEXT_SIGCONTEXT_OFFSET; + + fp = read_memory_integer (addr + LINUX_SIGCONTEXT_FP_OFFSET, 8)+8; + + return fp; +} + +void +x86_64_init_frame_pc (int fromleaf, struct frame_info *fi) +{ + CORE_ADDR addr; + + if(fi->next && fi->next->signal_handler_caller) + { + addr = fi->next->next->frame + + LINUX_SIGINFO_SIZE + + LINUX_UCONTEXT_SIGCONTEXT_OFFSET; + fi->pc = read_memory_integer (addr + + LINUX_SIGCONTEXT_PC_OFFSET, 8); + } + else + cfi_init_frame_pc (fromleaf, fi); +} + +void +x86_64_init_extra_frame_info (int fromleaf, struct frame_info *fi) +{ + cfi_init_extra_frame_info (fromleaf, fi); +} diff --git a/gdb/x86-64-tdep.c b/gdb/x86-64-tdep.c index 31f32f189cd..5d92a99b140 100644 --- a/gdb/x86-64-tdep.c +++ b/gdb/x86-64-tdep.c @@ -1026,7 +1026,7 @@ x86_64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) /* FRAME_CHAIN takes a frame's nominal address and produces the frame's chain-pointer. */ - set_gdbarch_frame_chain (gdbarch, cfi_frame_chain); + set_gdbarch_frame_chain (gdbarch, x86_64_linux_frame_chain); set_gdbarch_frameless_function_invocation (gdbarch, x86_64_frameless_function_invocation); @@ -1041,10 +1041,10 @@ x86_64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_frame_init_saved_regs (gdbarch, x86_64_frame_init_saved_regs); /* Frame pc initialization is handled by unwind informations. */ - set_gdbarch_init_frame_pc (gdbarch, cfi_init_frame_pc); + set_gdbarch_init_frame_pc (gdbarch, x86_64_init_frame_pc); /* Initialization of unwind informations. */ - set_gdbarch_init_extra_frame_info (gdbarch, cfi_init_extra_frame_info); + set_gdbarch_init_extra_frame_info (gdbarch, x86_64_init_extra_frame_info); /* Getting saved registers is handled by unwind informations. */ set_gdbarch_get_saved_register (gdbarch, cfi_get_saved_register); @@ -1054,8 +1054,7 @@ x86_64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) /* Cons up virtual frame pointer for trace */ set_gdbarch_virtual_frame_pointer (gdbarch, cfi_virtual_frame_pointer); - - set_gdbarch_frame_chain_valid (gdbarch, generic_file_frame_chain_valid); + set_gdbarch_frame_chain_valid (gdbarch, file_frame_chain_valid); set_gdbarch_use_generic_dummy_frames (gdbarch, 1); set_gdbarch_call_dummy_location (gdbarch, AT_ENTRY_POINT); @@ -1122,6 +1121,8 @@ x86_64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_dwarf2_build_frame_info (gdbarch, dwarf2_build_frame_info); set_gdbarch_dwarf2_reg_to_regnum (gdbarch, x86_64_dwarf2_reg_to_regnum); + set_gdbarch_pc_in_sigtramp (gdbarch, x86_64_linux_in_sigtramp); + return gdbarch; } diff --git a/gdb/x86-64-tdep.h b/gdb/x86-64-tdep.h index 711486077fb..fd23a7a7f31 100644 --- a/gdb/x86-64-tdep.h +++ b/gdb/x86-64-tdep.h @@ -31,8 +31,12 @@ extern int x86_64_num_gregs; int x86_64_register_number (const char *name); const char *x86_64_register_name (int reg_nr); - gdbarch_frame_saved_pc_ftype x86_64_linux_frame_saved_pc; gdbarch_saved_pc_after_call_ftype x86_64_linux_saved_pc_after_call; +gdbarch_pc_in_sigtramp_ftype x86_64_linux_in_sigtramp; +CORE_ADDR x86_64_linux_frame_chain (struct frame_info *fi); +void x86_64_init_frame_pc (int fromleaf, struct frame_info *fi); +void x86_64_init_extra_frame_info (int fromleaf, struct frame_info *fi); + #endif -- 2.30.2