X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fi386-tdep.c;h=b2b74121a678598073191843126b7ed01f61da66;hb=a773502202241bcd099845c5a17d6c566eabeaef;hp=6052f959b92648d058437f074d0942241b0b79e1;hpb=e866c49707d6b97b6763baddaa2773e4ee893102;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c index 6052f959b9..b2b74121a6 100644 --- a/gdb/i386-tdep.c +++ b/gdb/i386-tdep.c @@ -2,7 +2,7 @@ Copyright (C) 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, - 2010 Free Software Foundation, Inc. + 2010, 2011 Free Software Foundation, Inc. This file is part of GDB. @@ -45,7 +45,7 @@ #include "dis-asm.h" #include "disasm.h" #include "remote.h" - +#include "exceptions.h" #include "gdb_assert.h" #include "gdb_string.h" @@ -445,17 +445,17 @@ i386_skip_prefixes (gdb_byte *insn, size_t max_len) static int i386_absolute_jmp_p (const gdb_byte *insn) { - /* jmp far (absolute address in operand) */ + /* jmp far (absolute address in operand). */ if (insn[0] == 0xea) return 1; if (insn[0] == 0xff) { - /* jump near, absolute indirect (/4) */ + /* jump near, absolute indirect (/4). */ if ((insn[1] & 0x38) == 0x20) return 1; - /* jump far, absolute indirect (/5) */ + /* jump far, absolute indirect (/5). */ if ((insn[1] & 0x38) == 0x28) return 1; } @@ -466,17 +466,17 @@ i386_absolute_jmp_p (const gdb_byte *insn) static int i386_absolute_call_p (const gdb_byte *insn) { - /* call far, absolute */ + /* call far, absolute. */ if (insn[0] == 0x9a) return 1; if (insn[0] == 0xff) { - /* Call near, absolute indirect (/2) */ + /* Call near, absolute indirect (/2). */ if ((insn[1] & 0x38) == 0x10) return 1; - /* Call far, absolute indirect (/3) */ + /* Call far, absolute indirect (/3). */ if ((insn[1] & 0x38) == 0x18) return 1; } @@ -489,9 +489,9 @@ i386_ret_p (const gdb_byte *insn) { switch (insn[0]) { - case 0xc2: /* ret near, pop N bytes */ + case 0xc2: /* ret near, pop N bytes. */ case 0xc3: /* ret near */ - case 0xca: /* ret far, pop N bytes */ + case 0xca: /* ret far, pop N bytes. */ case 0xcb: /* ret far */ case 0xcf: /* iret */ return 1; @@ -507,7 +507,7 @@ i386_call_p (const gdb_byte *insn) if (i386_absolute_call_p (insn)) return 1; - /* call near, relative */ + /* call near, relative. */ if (insn[0] == 0xe8) return 1; @@ -736,7 +736,7 @@ i386_relocate_instruction (struct gdbarch *gdbarch, /* Where "ret" in the original code will return to. */ ret_addr = oldloc + insn_length; - push_buf[0] = 0x68; /* pushq $... */ + push_buf[0] = 0x68; /* pushq $... */ memcpy (&push_buf[1], &ret_addr, 4); /* Push the push. */ append_insns (to, 5, push_buf); @@ -747,7 +747,14 @@ i386_relocate_instruction (struct gdbarch *gdbarch, /* Adjust the destination offset. */ rel32 = extract_signed_integer (insn + 1, 4, byte_order); newrel = (oldloc - *to) + rel32; - store_signed_integer (insn + 1, 4, newrel, byte_order); + store_signed_integer (insn + 1, 4, byte_order, newrel); + + if (debug_displaced) + fprintf_unfiltered (gdb_stdlog, + "Adjusted insn rel32=%s at %s to" + " rel32=%s at %s\n", + hex_string (rel32), paddress (gdbarch, oldloc), + hex_string (newrel), paddress (gdbarch, *to)); /* Write the adjusted jump into its displaced location. */ append_insns (to, 5, insn); @@ -766,11 +773,11 @@ i386_relocate_instruction (struct gdbarch *gdbarch, { rel32 = extract_signed_integer (insn + offset, 4, byte_order); newrel = (oldloc - *to) + rel32; - store_signed_integer (insn + offset, 4, newrel, byte_order); + store_signed_integer (insn + offset, 4, byte_order, newrel); if (debug_displaced) fprintf_unfiltered (gdb_stdlog, - "Adjusted insn rel32=0x%s at 0x%s to" - " rel32=0x%s at 0x%s\n", + "Adjusted insn rel32=%s at %s to" + " rel32=%s at %s\n", hex_string (rel32), paddress (gdbarch, oldloc), hex_string (newrel), paddress (gdbarch, *to)); } @@ -797,6 +804,7 @@ struct i386_frame_cache { /* Base address. */ CORE_ADDR base; + int base_p; LONGEST sp_offset; CORE_ADDR pc; @@ -821,6 +829,7 @@ i386_alloc_frame_cache (void) cache = FRAME_OBSTACK_ZALLOC (struct i386_frame_cache); /* Base address. */ + cache->base_p = 0; cache->base = 0; cache->sp_offset = -4; cache->pc = 0; @@ -850,7 +859,9 @@ i386_follow_jump (struct gdbarch *gdbarch, CORE_ADDR pc) long delta = 0; int data16 = 0; - target_read_memory (pc, &op, 1); + if (target_read_memory (pc, &op, 1)) + return pc; + if (op == 0x66) { data16 = 1; @@ -916,12 +927,15 @@ i386_analyze_struct_return (CORE_ADDR pc, CORE_ADDR current_pc, if (current_pc <= pc) return pc; - target_read_memory (pc, &op, 1); + if (target_read_memory (pc, &op, 1)) + return pc; if (op != 0x58) /* popl %eax */ return pc; - target_read_memory (pc + 1, buf, 4); + if (target_read_memory (pc + 1, buf, 4)) + return pc; + if (memcmp (buf, proto1, 3) != 0 && memcmp (buf, proto2, 4) != 0) return pc; @@ -960,7 +974,8 @@ i386_skip_probe (CORE_ADDR pc) gdb_byte buf[8]; gdb_byte op; - target_read_memory (pc, &op, 1); + if (target_read_memory (pc, &op, 1)) + return pc; if (op == 0x68 || op == 0x6a) { @@ -1111,42 +1126,91 @@ struct i386_insn gdb_byte mask[I386_MAX_MATCHED_INSN_LEN]; }; -/* Search for the instruction at PC in the list SKIP_INSNS. Return +/* Return whether instruction at PC matches PATTERN. */ + +static int +i386_match_pattern (CORE_ADDR pc, struct i386_insn pattern) +{ + gdb_byte op; + + if (target_read_memory (pc, &op, 1)) + return 0; + + if ((op & pattern.mask[0]) == pattern.insn[0]) + { + gdb_byte buf[I386_MAX_MATCHED_INSN_LEN - 1]; + int insn_matched = 1; + size_t i; + + gdb_assert (pattern.len > 1); + gdb_assert (pattern.len <= I386_MAX_MATCHED_INSN_LEN); + + if (target_read_memory (pc + 1, buf, pattern.len - 1)) + return 0; + + for (i = 1; i < pattern.len; i++) + { + if ((buf[i - 1] & pattern.mask[i]) != pattern.insn[i]) + insn_matched = 0; + } + return insn_matched; + } + return 0; +} + +/* Search for the instruction at PC in the list INSN_PATTERNS. Return the first instruction description that matches. Otherwise, return NULL. */ static struct i386_insn * -i386_match_insn (CORE_ADDR pc, struct i386_insn *skip_insns) +i386_match_insn (CORE_ADDR pc, struct i386_insn *insn_patterns) { - struct i386_insn *insn; + struct i386_insn *pattern; + + for (pattern = insn_patterns; pattern->len > 0; pattern++) + { + if (i386_match_pattern (pc, *pattern)) + return pattern; + } + + return NULL; +} + +/* Return whether PC points inside a sequence of instructions that + matches INSN_PATTERNS. */ + +static int +i386_match_insn_block (CORE_ADDR pc, struct i386_insn *insn_patterns) +{ + CORE_ADDR current_pc; + int ix, i; gdb_byte op; + struct i386_insn *insn; - target_read_memory (pc, &op, 1); + insn = i386_match_insn (pc, insn_patterns); + if (insn == NULL) + return 0; - for (insn = skip_insns; insn->len > 0; insn++) + current_pc = pc - insn->len; + ix = insn - insn_patterns; + for (i = ix - 1; i >= 0; i--) { - if ((op & insn->mask[0]) == insn->insn[0]) - { - gdb_byte buf[I386_MAX_MATCHED_INSN_LEN - 1]; - int insn_matched = 1; - size_t i; + if (!i386_match_pattern (current_pc, insn_patterns[i])) + return 0; - gdb_assert (insn->len > 1); - gdb_assert (insn->len <= I386_MAX_MATCHED_INSN_LEN); + current_pc -= insn_patterns[i].len; + } - target_read_memory (pc + 1, buf, insn->len - 1); - for (i = 1; i < insn->len; i++) - { - if ((buf[i - 1] & insn->mask[i]) != insn->insn[i]) - insn_matched = 0; - } + current_pc = pc + insn->len; + for (insn = insn_patterns + ix + 1; insn->len > 0; insn++) + { + if (!i386_match_pattern (current_pc, *insn)) + return 0; - if (insn_matched) - return insn; - } + current_pc += insn->len; } - return NULL; + return 1; } /* Some special instructions that might be migrated by GCC into the @@ -1157,7 +1221,7 @@ i386_match_insn (CORE_ADDR pc, struct i386_insn *skip_insns) struct i386_insn i386_frame_setup_skip_insns[] = { - /* Check for `movb imm8, r' and `movl imm32, r'. + /* Check for `movb imm8, r' and `movl imm32, r'. ??? Should we handle 16-bit operand-sizes here? */ @@ -1212,7 +1276,8 @@ i386_skip_noop (CORE_ADDR pc) gdb_byte op; int check = 1; - target_read_memory (pc, &op, 1); + if (target_read_memory (pc, &op, 1)) + return pc; while (check) { @@ -1221,7 +1286,8 @@ i386_skip_noop (CORE_ADDR pc) if (op == 0x90) { pc += 1; - target_read_memory (pc, &op, 1); + if (target_read_memory (pc, &op, 1)) + return pc; check = 1; } /* Ignore no-op instruction `mov %edi, %edi'. @@ -1237,11 +1303,15 @@ i386_skip_noop (CORE_ADDR pc) else if (op == 0x8b) { - target_read_memory (pc + 1, &op, 1); + if (target_read_memory (pc + 1, &op, 1)) + return pc; + if (op == 0xff) { pc += 2; - target_read_memory (pc, &op, 1); + if (target_read_memory (pc, &op, 1)) + return pc; + check = 1; } } @@ -1267,7 +1337,8 @@ i386_analyze_frame_setup (struct gdbarch *gdbarch, if (limit <= pc) return limit; - target_read_memory (pc, &op, 1); + if (target_read_memory (pc, &op, 1)) + return pc; if (op == 0x55) /* pushl %ebp */ { @@ -1302,7 +1373,8 @@ i386_analyze_frame_setup (struct gdbarch *gdbarch, if (limit <= pc + skip) return limit; - target_read_memory (pc + skip, &op, 1); + if (target_read_memory (pc + skip, &op, 1)) + return pc + skip; /* Check for `movl %esp, %ebp' -- can be written in two ways. */ switch (op) @@ -1338,7 +1410,8 @@ i386_analyze_frame_setup (struct gdbarch *gdbarch, NOTE: You can't subtract a 16-bit immediate from a 32-bit reg, so we don't have to worry about a data16 prefix. */ - target_read_memory (pc, &op, 1); + if (target_read_memory (pc, &op, 1)) + return pc; if (op == 0x83) { /* `subl' with 8-bit immediate. */ @@ -1394,7 +1467,8 @@ i386_analyze_register_saves (CORE_ADDR pc, CORE_ADDR current_pc, offset -= cache->locals; for (i = 0; i < 8 && pc < current_pc; i++) { - target_read_memory (pc, &op, 1); + if (target_read_memory (pc, &op, 1)) + return pc; if (op < 0x50 || op > 0x57) break; @@ -1487,7 +1561,9 @@ i386_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc) for (i = 0; i < 6; i++) { - target_read_memory (pc + i, &op, 1); + if (target_read_memory (pc + i, &op, 1)) + return pc; + if (pic_pat[i] != op) break; } @@ -1495,7 +1571,8 @@ i386_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc) { int delta = 6; - target_read_memory (pc + delta, &op, 1); + if (target_read_memory (pc + delta, &op, 1)) + return pc; if (op == 0x89) /* movl %ebx, x(%ebp) */ { @@ -1508,7 +1585,8 @@ i386_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc) else /* Unexpected instruction. */ delta = 0; - target_read_memory (pc + delta, &op, 1); + if (target_read_memory (pc + delta, &op, 1)) + return pc; } /* addl y,%ebx */ @@ -1538,7 +1616,8 @@ i386_skip_main_prologue (struct gdbarch *gdbarch, CORE_ADDR pc) enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); gdb_byte op; - target_read_memory (pc, &op, 1); + if (target_read_memory (pc, &op, 1)) + return pc; if (op == 0xe8) { gdb_byte buf[4]; @@ -1577,20 +1656,16 @@ i386_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame) /* Normal frames. */ -static struct i386_frame_cache * -i386_frame_cache (struct frame_info *this_frame, void **this_cache) +static void +i386_frame_cache_1 (struct frame_info *this_frame, + struct i386_frame_cache *cache) { struct gdbarch *gdbarch = get_frame_arch (this_frame); enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); - struct i386_frame_cache *cache; gdb_byte buf[4]; int i; - if (*this_cache) - return *this_cache; - - cache = i386_alloc_frame_cache (); - *this_cache = cache; + cache->pc = get_frame_func (this_frame); /* In principle, for normal frames, %ebp holds the frame pointer, which holds the base address for the current stack frame. @@ -1604,23 +1679,15 @@ i386_frame_cache (struct frame_info *this_frame, void **this_cache) get_frame_register (this_frame, I386_EBP_REGNUM, buf); cache->base = extract_unsigned_integer (buf, 4, byte_order); if (cache->base == 0) - return cache; + return; /* For normal frames, %eip is stored at 4(%ebp). */ cache->saved_regs[I386_EIP_REGNUM] = 4; - cache->pc = get_frame_func (this_frame); if (cache->pc != 0) i386_analyze_prologue (gdbarch, cache->pc, get_frame_pc (this_frame), cache); - if (cache->saved_sp_reg != -1) - { - /* Saved stack pointer has been saved. */ - get_frame_register (this_frame, cache->saved_sp_reg, buf); - cache->saved_sp = extract_unsigned_integer (buf, 4, byte_order); - } - if (cache->locals < 0) { /* We didn't find a valid frame, which means that CACHE->base @@ -1633,6 +1700,10 @@ i386_frame_cache (struct frame_info *this_frame, void **this_cache) if (cache->saved_sp_reg != -1) { + /* Saved stack pointer has been saved. */ + get_frame_register (this_frame, cache->saved_sp_reg, buf); + cache->saved_sp = extract_unsigned_integer (buf, 4, byte_order); + /* We're halfway aligning the stack. */ cache->base = ((cache->saved_sp - 4) & 0xfffffff0) - 4; cache->saved_regs[I386_EIP_REGNUM] = cache->saved_sp - 4; @@ -1660,9 +1731,17 @@ i386_frame_cache (struct frame_info *this_frame, void **this_cache) cache->saved_regs[I386_EBP_REGNUM] = 0; } + if (cache->saved_sp_reg != -1) + { + /* Saved stack pointer has been saved (but the SAVED_SP_REG + register may be unavailable). */ + if (cache->saved_sp == 0 + && frame_register_read (this_frame, cache->saved_sp_reg, buf)) + cache->saved_sp = extract_unsigned_integer (buf, 4, byte_order); + } /* Now that we have the base address for the stack frame we can calculate the value of %esp in the calling frame. */ - if (cache->saved_sp == 0) + else if (cache->saved_sp == 0) cache->saved_sp = cache->base + 8; /* Adjust all the saved registers such that they contain addresses @@ -1671,6 +1750,28 @@ i386_frame_cache (struct frame_info *this_frame, void **this_cache) if (cache->saved_regs[i] != -1) cache->saved_regs[i] += cache->base; + cache->base_p = 1; +} + +static struct i386_frame_cache * +i386_frame_cache (struct frame_info *this_frame, void **this_cache) +{ + volatile struct gdb_exception ex; + struct i386_frame_cache *cache; + + if (*this_cache) + return *this_cache; + + cache = i386_alloc_frame_cache (); + *this_cache = cache; + + TRY_CATCH (ex, RETURN_MASK_ERROR) + { + i386_frame_cache_1 (this_frame, cache); + } + if (ex.reason < 0 && ex.error != NOT_AVAILABLE_ERROR) + throw_exception (ex); + return cache; } @@ -1688,6 +1789,22 @@ i386_frame_this_id (struct frame_info *this_frame, void **this_cache, (*this_id) = frame_id_build (cache->base + 8, cache->pc); } +static enum unwind_stop_reason +i386_frame_unwind_stop_reason (struct frame_info *this_frame, + void **this_cache) +{ + struct i386_frame_cache *cache = i386_frame_cache (this_frame, this_cache); + + if (!cache->base_p) + return UNWIND_UNAVAILABLE; + + /* This marks the outermost frame. */ + if (cache->base == 0) + return UNWIND_OUTERMOST; + + return UNWIND_NO_REASON; +} + static struct value * i386_frame_prev_register (struct frame_info *this_frame, void **this_cache, int regnum) @@ -1727,8 +1844,19 @@ i386_frame_prev_register (struct frame_info *this_frame, void **this_cache, if (regnum == I386_EIP_REGNUM && cache->pc_in_eax) return frame_unwind_got_register (this_frame, regnum, I386_EAX_REGNUM); - if (regnum == I386_ESP_REGNUM && cache->saved_sp) - return frame_unwind_got_constant (this_frame, regnum, cache->saved_sp); + if (regnum == I386_ESP_REGNUM + && (cache->saved_sp != 0 || cache->saved_sp_reg != -1)) + { + /* If the SP has been saved, but we don't know where, then this + means that SAVED_SP_REG register was found unavailable back + when we built the cache. */ + if (cache->saved_sp == 0) + return frame_unwind_got_register (this_frame, regnum, + cache->saved_sp_reg); + else + return frame_unwind_got_constant (this_frame, regnum, + cache->saved_sp); + } if (regnum < I386_NUM_SAVED_REGS && cache->saved_regs[regnum] != -1) return frame_unwind_got_memory (this_frame, regnum, @@ -1740,6 +1868,7 @@ i386_frame_prev_register (struct frame_info *this_frame, void **this_cache, static const struct frame_unwind i386_frame_unwind = { NORMAL_FRAME, + i386_frame_unwind_stop_reason, i386_frame_this_id, i386_frame_prev_register, NULL, @@ -1783,6 +1912,7 @@ i386_epilogue_frame_cache (struct frame_info *this_frame, void **this_cache) { struct gdbarch *gdbarch = get_frame_arch (this_frame); enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + volatile struct gdb_exception ex; struct i386_frame_cache *cache; gdb_byte buf[4]; @@ -1792,23 +1922,43 @@ i386_epilogue_frame_cache (struct frame_info *this_frame, void **this_cache) cache = i386_alloc_frame_cache (); *this_cache = cache; - /* Cache base will be %esp plus cache->sp_offset (-4). */ - get_frame_register (this_frame, I386_ESP_REGNUM, buf); - cache->base = extract_unsigned_integer (buf, 4, - byte_order) + cache->sp_offset; + TRY_CATCH (ex, RETURN_MASK_ERROR) + { + /* Cache base will be %esp plus cache->sp_offset (-4). */ + get_frame_register (this_frame, I386_ESP_REGNUM, buf); + cache->base = extract_unsigned_integer (buf, 4, + byte_order) + cache->sp_offset; + + /* Cache pc will be the frame func. */ + cache->pc = get_frame_pc (this_frame); - /* Cache pc will be the frame func. */ - cache->pc = get_frame_pc (this_frame); + /* The saved %esp will be at cache->base plus 8. */ + cache->saved_sp = cache->base + 8; - /* The saved %esp will be at cache->base plus 8. */ - cache->saved_sp = cache->base + 8; + /* The saved %eip will be at cache->base plus 4. */ + cache->saved_regs[I386_EIP_REGNUM] = cache->base + 4; - /* The saved %eip will be at cache->base plus 4. */ - cache->saved_regs[I386_EIP_REGNUM] = cache->base + 4; + cache->base_p = 1; + } + if (ex.reason < 0 && ex.error != NOT_AVAILABLE_ERROR) + throw_exception (ex); return cache; } +static enum unwind_stop_reason +i386_epilogue_frame_unwind_stop_reason (struct frame_info *this_frame, + void **this_cache) +{ + struct i386_frame_cache *cache + = i386_epilogue_frame_cache (this_frame, this_cache); + + if (!cache->base_p) + return UNWIND_UNAVAILABLE; + + return UNWIND_NO_REASON; +} + static void i386_epilogue_frame_this_id (struct frame_info *this_frame, void **this_cache, @@ -1817,12 +1967,16 @@ i386_epilogue_frame_this_id (struct frame_info *this_frame, struct i386_frame_cache *cache = i386_epilogue_frame_cache (this_frame, this_cache); + if (!cache->base_p) + return; + (*this_id) = frame_id_build (cache->base + 8, cache->pc); } static const struct frame_unwind i386_epilogue_frame_unwind = { NORMAL_FRAME, + i386_epilogue_frame_unwind_stop_reason, i386_epilogue_frame_this_id, i386_frame_prev_register, NULL, @@ -1830,6 +1984,88 @@ static const struct frame_unwind i386_epilogue_frame_unwind = }; +/* Stack-based trampolines. */ + +/* These trampolines are used on cross x86 targets, when taking the + address of a nested function. When executing these trampolines, + no stack frame is set up, so we are in a similar situation as in + epilogues and i386_epilogue_frame_this_id can be re-used. */ + +/* Static chain passed in register. */ + +struct i386_insn i386_tramp_chain_in_reg_insns[] = +{ + /* `movl imm32, %eax' and `movl imm32, %ecx' */ + { 5, { 0xb8 }, { 0xfe } }, + + /* `jmp imm32' */ + { 5, { 0xe9 }, { 0xff } }, + + {0} +}; + +/* Static chain passed on stack (when regparm=3). */ + +struct i386_insn i386_tramp_chain_on_stack_insns[] = +{ + /* `push imm32' */ + { 5, { 0x68 }, { 0xff } }, + + /* `jmp imm32' */ + { 5, { 0xe9 }, { 0xff } }, + + {0} +}; + +/* Return whether PC points inside a stack trampoline. */ + +static int +i386_in_stack_tramp_p (struct gdbarch *gdbarch, CORE_ADDR pc) +{ + gdb_byte insn; + char *name; + + /* A stack trampoline is detected if no name is associated + to the current pc and if it points inside a trampoline + sequence. */ + + find_pc_partial_function (pc, &name, NULL, NULL); + if (name) + return 0; + + if (target_read_memory (pc, &insn, 1)) + return 0; + + if (!i386_match_insn_block (pc, i386_tramp_chain_in_reg_insns) + && !i386_match_insn_block (pc, i386_tramp_chain_on_stack_insns)) + return 0; + + return 1; +} + +static int +i386_stack_tramp_frame_sniffer (const struct frame_unwind *self, + struct frame_info *this_frame, + void **this_prologue_cache) +{ + if (frame_relative_level (this_frame) == 0) + return i386_in_stack_tramp_p (get_frame_arch (this_frame), + get_frame_pc (this_frame)); + else + return 0; +} + +static const struct frame_unwind i386_stack_tramp_frame_unwind = +{ + NORMAL_FRAME, + i386_epilogue_frame_unwind_stop_reason, + i386_epilogue_frame_this_id, + i386_frame_prev_register, + NULL, + i386_stack_tramp_frame_sniffer +}; + + /* Signal trampolines. */ static struct i386_frame_cache * @@ -1838,6 +2074,7 @@ i386_sigtramp_frame_cache (struct frame_info *this_frame, void **this_cache) struct gdbarch *gdbarch = get_frame_arch (this_frame); struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); + volatile struct gdb_exception ex; struct i386_frame_cache *cache; CORE_ADDR addr; gdb_byte buf[4]; @@ -1847,30 +2084,50 @@ i386_sigtramp_frame_cache (struct frame_info *this_frame, void **this_cache) cache = i386_alloc_frame_cache (); - get_frame_register (this_frame, I386_ESP_REGNUM, buf); - cache->base = extract_unsigned_integer (buf, 4, byte_order) - 4; - - addr = tdep->sigcontext_addr (this_frame); - if (tdep->sc_reg_offset) + TRY_CATCH (ex, RETURN_MASK_ERROR) { - int i; + get_frame_register (this_frame, I386_ESP_REGNUM, buf); + cache->base = extract_unsigned_integer (buf, 4, byte_order) - 4; - gdb_assert (tdep->sc_num_regs <= I386_NUM_SAVED_REGS); + addr = tdep->sigcontext_addr (this_frame); + if (tdep->sc_reg_offset) + { + int i; - for (i = 0; i < tdep->sc_num_regs; i++) - if (tdep->sc_reg_offset[i] != -1) - cache->saved_regs[i] = addr + tdep->sc_reg_offset[i]; - } - else - { - cache->saved_regs[I386_EIP_REGNUM] = addr + tdep->sc_pc_offset; - cache->saved_regs[I386_ESP_REGNUM] = addr + tdep->sc_sp_offset; + gdb_assert (tdep->sc_num_regs <= I386_NUM_SAVED_REGS); + + for (i = 0; i < tdep->sc_num_regs; i++) + if (tdep->sc_reg_offset[i] != -1) + cache->saved_regs[i] = addr + tdep->sc_reg_offset[i]; + } + else + { + cache->saved_regs[I386_EIP_REGNUM] = addr + tdep->sc_pc_offset; + cache->saved_regs[I386_ESP_REGNUM] = addr + tdep->sc_sp_offset; + } + + cache->base_p = 1; } + if (ex.reason < 0 && ex.error != NOT_AVAILABLE_ERROR) + throw_exception (ex); *this_cache = cache; return cache; } +static enum unwind_stop_reason +i386_sigtramp_frame_unwind_stop_reason (struct frame_info *this_frame, + void **this_cache) +{ + struct i386_frame_cache *cache = + i386_sigtramp_frame_cache (this_frame, this_cache); + + if (!cache->base_p) + return UNWIND_UNAVAILABLE; + + return UNWIND_NO_REASON; +} + static void i386_sigtramp_frame_this_id (struct frame_info *this_frame, void **this_cache, struct frame_id *this_id) @@ -1878,6 +2135,9 @@ i386_sigtramp_frame_this_id (struct frame_info *this_frame, void **this_cache, struct i386_frame_cache *cache = i386_sigtramp_frame_cache (this_frame, this_cache); + if (!cache->base_p) + return; + /* See the end of i386_push_dummy_call. */ (*this_id) = frame_id_build (cache->base + 8, get_frame_pc (this_frame)); } @@ -1925,6 +2185,7 @@ i386_sigtramp_frame_sniffer (const struct frame_unwind *self, static const struct frame_unwind i386_sigtramp_frame_unwind = { SIGTRAMP_FRAME, + i386_sigtramp_frame_unwind_stop_reason, i386_sigtramp_frame_this_id, i386_sigtramp_frame_prev_register, NULL, @@ -2171,7 +2432,8 @@ i386_extract_return_value (struct gdbarch *gdbarch, struct type *type, } else internal_error (__FILE__, __LINE__, - _("Cannot extract return value of %d bytes long."), len); + _("Cannot extract return value of %d bytes long."), + len); } } @@ -2417,7 +2679,7 @@ i386_ymm_type (struct gdbarch *gdbarch) init_vector_type (bt->builtin_int128, 2)); TYPE_VECTOR (t) = 1; - TYPE_NAME (t) = "builtin_type_vec128i"; + TYPE_NAME (t) = "builtin_type_vec256i"; tdep->i386_ymm_type = t; } @@ -2467,7 +2729,7 @@ i386_mmx_type (struct gdbarch *gdbarch) } /* Return the GDB type object for the "standard" data type of data in - register REGNUM. */ + register REGNUM. */ static struct type * i386_pseudo_register_type (struct gdbarch *gdbarch, int regnum) @@ -2509,18 +2771,21 @@ i386_mmx_regnum_to_fp_regnum (struct regcache *regcache, int regnum) return (I387_ST0_REGNUM (tdep) + fpreg); } -void +enum register_status i386_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache, int regnum, gdb_byte *buf) { gdb_byte raw_buf[MAX_REGISTER_SIZE]; + enum register_status status; if (i386_mmx_regnum_p (gdbarch, regnum)) { int fpnum = i386_mmx_regnum_to_fp_regnum (regcache, regnum); /* Extract (always little endian). */ - regcache_raw_read (regcache, fpnum, raw_buf); + status = regcache_raw_read (regcache, fpnum, raw_buf); + if (status != REG_VALID) + return status; memcpy (buf, raw_buf, register_size (gdbarch, regnum)); } else @@ -2531,15 +2796,19 @@ i386_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache, { regnum -= tdep->ymm0_regnum; - /* Extract (always little endian). Read lower 128bits. */ - regcache_raw_read (regcache, - I387_XMM0_REGNUM (tdep) + regnum, - raw_buf); + /* Extract (always little endian). Read lower 128bits. */ + status = regcache_raw_read (regcache, + I387_XMM0_REGNUM (tdep) + regnum, + raw_buf); + if (status != REG_VALID) + return status; memcpy (buf, raw_buf, 16); /* Read upper 128bits. */ - regcache_raw_read (regcache, - tdep->ymm0h_regnum + regnum, - raw_buf); + status = regcache_raw_read (regcache, + tdep->ymm0h_regnum + regnum, + raw_buf); + if (status != REG_VALID) + return status; memcpy (buf + 16, raw_buf, 16); } else if (i386_word_regnum_p (gdbarch, regnum)) @@ -2547,7 +2816,9 @@ i386_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache, int gpnum = regnum - tdep->ax_regnum; /* Extract (always little endian). */ - regcache_raw_read (regcache, gpnum, raw_buf); + status = regcache_raw_read (regcache, gpnum, raw_buf); + if (status != REG_VALID) + return status; memcpy (buf, raw_buf, 2); } else if (i386_byte_regnum_p (gdbarch, regnum)) @@ -2559,7 +2830,9 @@ i386_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache, /* Extract (always little endian). We read both lower and upper registers. */ - regcache_raw_read (regcache, gpnum % 4, raw_buf); + status = regcache_raw_read (regcache, gpnum % 4, raw_buf); + if (status != REG_VALID) + return status; if (gpnum >= 4) memcpy (buf, raw_buf + 1, 1); else @@ -2568,6 +2841,8 @@ i386_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache, else internal_error (__FILE__, __LINE__, _("invalid regnum")); } + + return REG_VALID; } void @@ -2671,7 +2946,8 @@ i386_next_regnum (int regnum) needs any special handling. */ static int -i386_convert_register_p (struct gdbarch *gdbarch, int regnum, struct type *type) +i386_convert_register_p (struct gdbarch *gdbarch, + int regnum, struct type *type) { int len = TYPE_LENGTH (type); @@ -2700,21 +2976,17 @@ i386_convert_register_p (struct gdbarch *gdbarch, int regnum, struct type *type) /* Read a value of type TYPE from register REGNUM in frame FRAME, and return its contents in TO. */ -static void +static int i386_register_to_value (struct frame_info *frame, int regnum, - struct type *type, gdb_byte *to) + struct type *type, gdb_byte *to, + int *optimizedp, int *unavailablep) { struct gdbarch *gdbarch = get_frame_arch (frame); int len = TYPE_LENGTH (type); - /* FIXME: kettenis/20030609: What should we do if REGNUM isn't - available in FRAME (i.e. if it wasn't saved)? */ - if (i386_fp_regnum_p (gdbarch, regnum)) - { - i387_register_to_value (frame, regnum, type, to); - return; - } + return i387_register_to_value (frame, regnum, type, to, + optimizedp, unavailablep); /* Read a value spread across multiple registers. */ @@ -2725,11 +2997,18 @@ i386_register_to_value (struct frame_info *frame, int regnum, gdb_assert (regnum != -1); gdb_assert (register_size (gdbarch, regnum) == 4); - get_frame_register (frame, regnum, to); + if (!get_frame_register_bytes (frame, regnum, 0, + register_size (gdbarch, regnum), + to, optimizedp, unavailablep)) + return 0; + regnum = i386_next_regnum (regnum); len -= 4; to += 4; } + + *optimizedp = *unavailablep = 0; + return 1; } /* Write the contents FROM of a value of type TYPE into register @@ -3235,7 +3514,7 @@ struct i386_record_s }; /* Parse "modrm" part in current memory address that irp->addr point to - Return -1 if something wrong. */ + Return -1 if something wrong. */ static int i386_record_modrm (struct i386_record_s *irp) @@ -3260,7 +3539,7 @@ i386_record_modrm (struct i386_record_s *irp) /* Get the memory address that current instruction write to and set it to the argument "addr". - Return -1 if something wrong. */ + Return -1 if something wrong. */ static int i386_record_lea_modrm_addr (struct i386_record_s *irp, uint64_t *addr) @@ -3493,7 +3772,7 @@ i386_record_lea_modrm_addr (struct i386_record_s *irp, uint64_t *addr) /* Record the value of the memory that willbe changed in current instruction to "record_arch_list". - Return -1 if something wrong. */ + Return -1 if something wrong. */ static int i386_record_lea_modrm (struct i386_record_s *irp) @@ -3531,7 +3810,7 @@ Do you want to stop the program?"), } /* Record the push operation to "record_arch_list". - Return -1 if something wrong. */ + Return -1 if something wrong. */ static int i386_record_push (struct i386_record_s *irp, int size) @@ -3556,9 +3835,9 @@ i386_record_push (struct i386_record_s *irp, int size) #define I386_SAVE_FPU_ENV 0xfffe #define I386_SAVE_FPU_ENV_REG_STACK 0xffff -/* Record the value of floating point registers which will be changed by the - current instruction to "record_arch_list". Return -1 if something is wrong. -*/ +/* Record the value of floating point registers which will be changed + by the current instruction to "record_arch_list". Return -1 if + something is wrong. */ static int i386_record_floats (struct gdbarch *gdbarch, struct i386_record_s *ir, @@ -3620,7 +3899,7 @@ static int i386_record_floats (struct gdbarch *gdbarch, /* Parse the current instruction and record the values of the registers and memory that will be changed in current instruction to "record_arch_list". - Return -1 if something wrong. */ + Return -1 if something wrong. */ #define I386_RECORD_ARCH_LIST_ADD_REG(regnum) \ record_arch_list_add_reg (ir.regcache, ir.regmap[(regnum)]) @@ -3753,7 +4032,7 @@ i386_process_record (struct gdbarch *gdbarch, struct regcache *regcache, else if (ir.regmap[X86_RECORD_R8_REGNUM]) ir.aflag = 2; - /* now check op code */ + /* Now check op code. */ opcode = (uint32_t) opcode8; reswitch: switch (opcode) @@ -4541,6 +4820,7 @@ Do you want to stop the program?"), ir.addr -= 1; goto no_support; } + /* FALLTHROUGH */ case 0x0fb2: /* lss Gv */ case 0x0fb4: /* lfs Gv */ case 0x0fb5: /* lgs Gv */ @@ -4636,7 +4916,7 @@ Do you want to stop the program?"), ir.reg |= ((opcode & 7) << 3); if (ir.mod != 3) { - /* Memory. */ + /* Memory. */ uint64_t addr64; if (i386_record_lea_modrm_addr (&ir, &addr64)) @@ -5320,6 +5600,7 @@ Do you want to stop the program?"), ir.addr -= 1; goto no_support; } + /* FALLTHROUGH */ case 0xf5: /* cmc */ case 0xf8: /* clc */ case 0xf9: /* stc */ @@ -6254,7 +6535,7 @@ reswitch_prefix_add: case 0x660f3804: /* pmaddubsw */ case 0x660f3805: /* phsubw */ case 0x660f3806: /* phsubd */ - case 0x660f3807: /* phaddsw */ + case 0x660f3807: /* phsubsw */ case 0x660f3808: /* psignb */ case 0x660f3809: /* psignw */ case 0x660f380a: /* psignd */ @@ -6345,7 +6626,7 @@ reswitch_prefix_add: case 0x660f63: /* packsswb */ case 0x660f64: /* pcmpgtb */ case 0x660f65: /* pcmpgtw */ - case 0x660f66: /* pcmpgtl */ + case 0x660f66: /* pcmpgtd */ case 0x660f67: /* packuswb */ case 0x660f68: /* punpckhbw */ case 0x660f69: /* punpckhwd */ @@ -6361,7 +6642,7 @@ reswitch_prefix_add: case 0xf30f70: /* pshufhw */ case 0x660f74: /* pcmpeqb */ case 0x660f75: /* pcmpeqw */ - case 0x660f76: /* pcmpeql */ + case 0x660f76: /* pcmpeqd */ case 0x660f7c: /* haddpd */ case 0xf20f7c: /* haddps */ case 0x660f7d: /* hsubpd */ @@ -6407,7 +6688,7 @@ reswitch_prefix_add: case 0x660fed: /* paddsw */ case 0x660fee: /* pmaxsw */ case 0x660fef: /* pxor */ - case 0x660ff0: /* lddqu */ + case 0xf20ff0: /* lddqu */ case 0x660ff1: /* psllw */ case 0x660ff2: /* pslld */ case 0x660ff3: /* psllq */ @@ -6416,11 +6697,11 @@ reswitch_prefix_add: case 0x660ff6: /* psadbw */ case 0x660ff8: /* psubb */ case 0x660ff9: /* psubw */ - case 0x660ffa: /* psubl */ + case 0x660ffa: /* psubd */ case 0x660ffb: /* psubq */ case 0x660ffc: /* paddb */ case 0x660ffd: /* paddw */ - case 0x660ffe: /* paddl */ + case 0x660ffe: /* paddd */ if (i386_record_modrm (&ir)) return -1; ir.reg |= rex_r; @@ -6456,7 +6737,8 @@ reswitch_prefix_add: || opcode == 0x0f17 || opcode == 0x660f17) goto no_support; ir.rm |= ir.rex_b; - if (!i386_xmm_regnum_p (gdbarch, I387_XMM0_REGNUM (tdep) + ir.rm)) + if (!i386_xmm_regnum_p (gdbarch, + I387_XMM0_REGNUM (tdep) + ir.rm)) goto no_support; record_arch_list_add_reg (ir.regcache, I387_XMM0_REGNUM (tdep) + ir.rm); @@ -6522,7 +6804,7 @@ reswitch_prefix_add: case 0x0f3804: /* pmaddubsw */ case 0x0f3805: /* phsubw */ case 0x0f3806: /* phsubd */ - case 0x0f3807: /* phaddsw */ + case 0x0f3807: /* phsubsw */ case 0x0f3808: /* psignb */ case 0x0f3809: /* psignw */ case 0x0f380a: /* psignd */ @@ -6555,7 +6837,7 @@ reswitch_prefix_add: case 0x0f63: /* packsswb */ case 0x0f64: /* pcmpgtb */ case 0x0f65: /* pcmpgtw */ - case 0x0f66: /* pcmpgtl */ + case 0x0f66: /* pcmpgtd */ case 0x0f67: /* packuswb */ case 0x0f68: /* punpckhbw */ case 0x0f69: /* punpckhwd */ @@ -6566,7 +6848,7 @@ reswitch_prefix_add: case 0x0f70: /* pshufw */ case 0x0f74: /* pcmpeqb */ case 0x0f75: /* pcmpeqw */ - case 0x0f76: /* pcmpeql */ + case 0x0f76: /* pcmpeqd */ case 0x0fc4: /* pinsrw */ case 0x0fd1: /* psrlw */ case 0x0fd2: /* psrld */ @@ -6604,11 +6886,11 @@ reswitch_prefix_add: case 0x0ff6: /* psadbw */ case 0x0ff8: /* psubb */ case 0x0ff9: /* psubw */ - case 0x0ffa: /* psubl */ + case 0x0ffa: /* psubd */ case 0x0ffb: /* psubq */ case 0x0ffc: /* paddb */ case 0x0ffd: /* paddw */ - case 0x0ffe: /* paddl */ + case 0x0ffe: /* paddd */ if (i386_record_modrm (&ir)) return -1; if (!i386_mmx_regnum_p (gdbarch, I387_MM0_REGNUM (tdep) + ir.reg)) @@ -6688,7 +6970,8 @@ reswitch_prefix_add: if (ir.mod == 3) { ir.rm |= ir.rex_b; - if (!i386_xmm_regnum_p (gdbarch, I387_XMM0_REGNUM (tdep) + ir.rm)) + if (!i386_xmm_regnum_p (gdbarch, + I387_XMM0_REGNUM (tdep) + ir.rm)) goto no_support; record_arch_list_add_reg (ir.regcache, I387_XMM0_REGNUM (tdep) + ir.rm); @@ -6791,7 +7074,8 @@ i386_fast_tracepoint_valid_at (struct gdbarch *gdbarch, /* Return a bit of target-specific detail to add to the caller's generic failure message. */ if (msg) - *msg = xstrprintf (_("; instruction is only %d bytes long, need at least %d bytes for the jump"), + *msg = xstrprintf (_("; instruction is only %d bytes long, " + "need at least %d bytes for the jump"), len, jumplen); return 0; } @@ -7113,7 +7397,7 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) ymm0_regnum = tdep->ax_regnum + tdep->num_word_regs; if (tdep->num_dword_regs) { - /* Support dword pseudo-registesr if it hasn't been disabled. */ + /* Support dword pseudo-register if it hasn't been disabled. */ tdep->eax_regnum = ymm0_regnum; ymm0_regnum += tdep->num_dword_regs; } @@ -7123,7 +7407,7 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) mm0_regnum = ymm0_regnum; if (tdep->num_ymm_regs) { - /* Support YMM pseudo-registesr if it is available. */ + /* Support YMM pseudo-register if it is available. */ tdep->ymm0_regnum = ymm0_regnum; mm0_regnum += tdep->num_ymm_regs; } @@ -7132,13 +7416,14 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) if (tdep->num_mmx_regs != 0) { - /* Support MMX pseudo-registesr if MMX hasn't been disabled. */ + /* Support MMX pseudo-register if MMX hasn't been disabled. */ tdep->mm0_regnum = mm0_regnum; } else tdep->mm0_regnum = -1; /* Hook in the legacy prologue-based unwinders last (fallback). */ + frame_unwind_append_unwinder (gdbarch, &i386_stack_tramp_frame_unwind); frame_unwind_append_unwinder (gdbarch, &i386_sigtramp_frame_unwind); frame_unwind_append_unwinder (gdbarch, &i386_frame_unwind);