diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 31a9b70374..ce3f532a63 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,10 @@ +2008-04-25 Pedro Alves + + * amd64-tdep.c (amd64_get_longjmp_target): New. + (amd64_init_abi): Register amd64_get_longjmp_target as + gdbarch_get_longjmp_target callback. + * i386-tdep.c (i386_get_longjmp_target): Remove 64-bit handling. + 2008-04-25 Pedro Alves * breakpoint.h (enum bpstat_what_main_action): Delete diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c index a9a29b3720..33338b69dc 100644 --- a/gdb/amd64-tdep.c +++ b/gdb/amd64-tdep.c @@ -1101,6 +1101,36 @@ amd64_regset_from_core_section (struct gdbarch *gdbarch, } +/* Figure out where the longjmp will land. Slurp the jmp_buf out of + %rdi. We expect its value to be a pointer to the jmp_buf structure + from which we extract the address that we will land at. This + address is copied into PC. This routine returns non-zero on + success. */ + +static int +amd64_get_longjmp_target (struct frame_info *frame, CORE_ADDR *pc) +{ + gdb_byte buf[8]; + CORE_ADDR jb_addr; + struct gdbarch *gdbarch = get_frame_arch (frame); + int jb_pc_offset = gdbarch_tdep (gdbarch)->jb_pc_offset; + int len = TYPE_LENGTH (builtin_type_void_func_ptr); + + /* If JB_PC_OFFSET is -1, we have no way to find out where the + longjmp will land. */ + if (jb_pc_offset == -1) + return 0; + + get_frame_register (frame, AMD64_RDI_REGNUM, buf); + jb_addr = extract_typed_address (buf, builtin_type_void_data_ptr); + if (target_read_memory (jb_addr + jb_pc_offset, buf, len)) + return 0; + + *pc = extract_typed_address (buf, builtin_type_void_func_ptr); + + return 1; +} + void amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) { @@ -1174,6 +1204,8 @@ amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) if (tdep->gregset_reg_offset) set_gdbarch_regset_from_core_section (gdbarch, amd64_regset_from_core_section); + + set_gdbarch_get_longjmp_target (gdbarch, amd64_get_longjmp_target); } diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c index ee7ed515d1..765f1ca494 100644 --- a/gdb/i386-tdep.c +++ b/gdb/i386-tdep.c @@ -1295,36 +1295,31 @@ i386_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame) stack. We expect the first arg to be a pointer to the jmp_buf structure from which we extract the address that we will land at. This address is copied into PC. This routine returns non-zero on - success. - - This function is 64-bit safe. */ + success. */ static int i386_get_longjmp_target (struct frame_info *frame, CORE_ADDR *pc) { - gdb_byte buf[8]; + gdb_byte buf[4]; CORE_ADDR sp, jb_addr; struct gdbarch *gdbarch = get_frame_arch (frame); int jb_pc_offset = gdbarch_tdep (gdbarch)->jb_pc_offset; - int len = TYPE_LENGTH (builtin_type_void_func_ptr); /* If JB_PC_OFFSET is -1, we have no way to find out where the longjmp will land. */ if (jb_pc_offset == -1) return 0; - /* Don't use I386_ESP_REGNUM here, since this function is also used - for AMD64. */ - get_frame_register (frame, gdbarch_sp_regnum (gdbarch), buf); - sp = extract_typed_address (buf, builtin_type_void_data_ptr); - if (target_read_memory (sp + len, buf, len)) + get_frame_register (frame, I386_ESP_REGNUM, buf); + sp = extract_unsigned_integer (buf, 4); + if (target_read_memory (sp + 4, buf, 4)) return 0; - jb_addr = extract_typed_address (buf, builtin_type_void_data_ptr); - if (target_read_memory (jb_addr + jb_pc_offset, buf, len)) + jb_addr = extract_unsigned_integer (buf, 4); + if (target_read_memory (jb_addr + jb_pc_offset, buf, 4)) return 0; - *pc = extract_typed_address (buf, builtin_type_void_func_ptr); + *pc = extract_unsigned_integer (buf, 4); return 1; }