X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Fi386-tdep.c;h=dd19e2499d01e0e64a1aa6083ba38696ed535306;hb=a89aa300140bab0f0a12c652367635c8291cad9c;hp=a639b174c70d19ac8977f0904dadcfccc9936557;hpb=3b3850e8522c6002cf38ecd573a4a83ac818a9bb;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c index a639b174c7..dd19e2499d 100644 --- a/gdb/i386-tdep.c +++ b/gdb/i386-tdep.c @@ -41,7 +41,7 @@ #include "symtab.h" #include "target.h" #include "value.h" -#include "trad-frame.h" +#include "dis-asm.h" #include "gdb_assert.h" #include "gdb_string.h" @@ -249,10 +249,8 @@ struct i386_frame_cache CORE_ADDR sp_offset; CORE_ADDR pc; - /* Saved registers. While trad-frame allocates space for the full - NUM_REGS + NUM_PSEUDOREGS, some of the code below cheats and - allocates space for only I386_NUM_SAVED_REGS. */ - struct trad_frame_saved_reg *saved_regs; + /* Saved registers. */ + CORE_ADDR saved_regs[I386_NUM_SAVED_REGS]; CORE_ADDR saved_sp; int pc_in_eax; @@ -263,7 +261,7 @@ struct i386_frame_cache /* Allocate and initialize a frame cache. */ static struct i386_frame_cache * -i386_alloc_frame_cache (struct frame_info *next_frame) +i386_alloc_frame_cache (void) { struct i386_frame_cache *cache; int i; @@ -275,7 +273,10 @@ i386_alloc_frame_cache (struct frame_info *next_frame) cache->sp_offset = -4; cache->pc = 0; - cache->saved_regs = trad_frame_alloc_saved_regs (next_frame); + /* Saved registers. We initialize these to -1 since zero is a valid + offset (that's where %ebp is supposed to be stored). */ + for (i = 0; i < I386_NUM_SAVED_REGS; i++) + cache->saved_regs[i] = -1; cache->saved_sp = 0; cache->pc_in_eax = 0; @@ -439,6 +440,7 @@ i386_analyze_frame_setup (CORE_ADDR pc, CORE_ADDR current_pc, struct i386_frame_cache *cache) { unsigned char op; + int skip = 0; if (current_pc <= pc) return current_pc; @@ -449,32 +451,68 @@ i386_analyze_frame_setup (CORE_ADDR pc, CORE_ADDR current_pc, { /* Take into account that we've executed the `pushl %ebp' that starts this instruction sequence. */ - cache->saved_regs[I386_EBP_REGNUM].addr = 0; + cache->saved_regs[I386_EBP_REGNUM] = 0; cache->sp_offset += 4; /* If that's all, return now. */ if (current_pc <= pc + 1) return current_pc; - /* Check for `movl %esp, %ebp' -- can be written in two ways. */ op = read_memory_unsigned_integer (pc + 1, 1); + + /* Check for some special instructions that might be migrated + by GCC into the prologue. We check for + + xorl %ebx, %ebx + xorl %ecx, %ecx + xorl %edx, %edx + + and the equivalent + + subl %ebx, %ebx + subl %ecx, %ecx + subl %edx, %edx + + Make sure we only skip these instructions if we later see the + `movl %esp, %ebp' that actually sets up the frame. */ + while (op == 0x29 || op == 0x31) + { + op = read_memory_unsigned_integer (pc + skip + 2, 1); + switch (op) + { + case 0xdb: /* %ebx */ + case 0xc9: /* %ecx */ + case 0xd2: /* %edx */ + skip += 2; + break; + default: + return pc + 1; + } + + op = read_memory_unsigned_integer (pc + skip + 1, 1); + } + + /* Check for `movl %esp, %ebp' -- can be written in two ways. */ switch (op) { case 0x8b: - if (read_memory_unsigned_integer (pc + 2, 1) != 0xec) + if (read_memory_unsigned_integer (pc + skip + 2, 1) != 0xec) return pc + 1; break; case 0x89: - if (read_memory_unsigned_integer (pc + 2, 1) != 0xe5) + if (read_memory_unsigned_integer (pc + skip + 2, 1) != 0xe5) return pc + 1; break; default: return pc + 1; } - /* OK, we actually have a frame. We just don't know how large it is - yet. Set its size to zero. We'll adjust it if necessary. */ + /* OK, we actually have a frame. We just don't know how large + it is yet. Set its size to zero. We'll adjust it if + necessary. We also now commit to skipping the special + instructions mentioned before. */ cache->locals = 0; + pc += skip; /* If that's all, return now. */ if (current_pc <= pc + 3) @@ -534,23 +572,22 @@ static CORE_ADDR i386_analyze_register_saves (CORE_ADDR pc, CORE_ADDR current_pc, struct i386_frame_cache *cache) { - if (cache->locals >= 0) - { - CORE_ADDR offset; - unsigned char op; - int i; + CORE_ADDR offset = 0; + unsigned char op; + int i; - offset = - 4 - cache->locals; - for (i = 0; i < 8 && pc < current_pc; i++) - { - op = read_memory_unsigned_integer (pc, 1); - if (op < 0x50 || op > 0x57) - break; + if (cache->locals > 0) + offset -= cache->locals; + for (i = 0; i < 8 && pc < current_pc; i++) + { + op = read_memory_unsigned_integer (pc, 1); + if (op < 0x50 || op > 0x57) + break; - cache->saved_regs[op - 0x50].addr = offset; - offset -= 4; - pc++; - } + offset -= 4; + cache->saved_regs[op - 0x50] = offset; + cache->sp_offset += 4; + pc++; } return pc; @@ -609,11 +646,6 @@ i386_skip_prologue (CORE_ADDR start_pc) unsigned char op; int i; - /* Allocate space for the maximum number of saved registers. This - should include all registers mentioned above, and %eip. */ - cache.saved_regs = alloca (I386_NUM_SAVED_REGS - * sizeof (cache.saved_regs[0])); - cache.locals = -1; pc = i386_analyze_prologue (start_pc, 0xffffffff, &cache); if (cache.locals < 0) @@ -695,7 +727,7 @@ i386_frame_cache (struct frame_info *next_frame, void **this_cache) if (*this_cache) return *this_cache; - cache = i386_alloc_frame_cache (next_frame); + cache = i386_alloc_frame_cache (); *this_cache = cache; /* In principle, for normal frames, %ebp holds the frame pointer, @@ -713,7 +745,7 @@ i386_frame_cache (struct frame_info *next_frame, void **this_cache) return cache; /* For normal frames, %eip is stored at 4(%ebp). */ - cache->saved_regs[I386_EIP_REGNUM].addr = 4; + cache->saved_regs[I386_EIP_REGNUM] = 4; cache->pc = frame_func_unwind (next_frame); if (cache->pc != 0) @@ -740,9 +772,8 @@ i386_frame_cache (struct frame_info *next_frame, void **this_cache) /* Adjust all the saved registers such that they contain addresses instead of offsets. */ for (i = 0; i < I386_NUM_SAVED_REGS; i++) - if (cache->saved_regs[i].realnum >= 0 - && cache->saved_regs[i].addr != -1) - cache->saved_regs[i].addr += cache->base; + if (cache->saved_regs[i] != -1) + cache->saved_regs[i] += cache->base; return cache; } @@ -801,7 +832,8 @@ i386_frame_prev_register (struct frame_info *next_frame, void **this_cache, ULONGEST val; /* Clear the direction flag. */ - frame_unwind_unsigned_register (next_frame, PS_REGNUM, &val); + val = frame_unwind_register_unsigned (next_frame, + I386_EFLAGS_REGNUM); val &= ~(1 << 10); store_unsigned_integer (valuep, 4, val); } @@ -830,8 +862,23 @@ i386_frame_prev_register (struct frame_info *next_frame, void **this_cache, return; } - trad_frame_prev_register (next_frame, cache->saved_regs, regnum, - optimizedp, lvalp, addrp, realnump, valuep); + if (regnum < I386_NUM_SAVED_REGS && cache->saved_regs[regnum] != -1) + { + *optimizedp = 0; + *lvalp = lval_memory; + *addrp = cache->saved_regs[regnum]; + *realnump = -1; + if (valuep) + { + /* Read the value in from memory. */ + read_memory (*addrp, valuep, + register_size (current_gdbarch, regnum)); + } + return; + } + + frame_register_unwind (next_frame, regnum, + optimizedp, lvalp, addrp, realnump, valuep); } static const struct frame_unwind i386_frame_unwind = @@ -842,7 +889,7 @@ static const struct frame_unwind i386_frame_unwind = }; static const struct frame_unwind * -i386_frame_p (CORE_ADDR pc) +i386_frame_sniffer (struct frame_info *next_frame) { return &i386_frame_unwind; } @@ -861,7 +908,7 @@ i386_sigtramp_frame_cache (struct frame_info *next_frame, void **this_cache) if (*this_cache) return *this_cache; - cache = i386_alloc_frame_cache (next_frame); + cache = i386_alloc_frame_cache (); frame_unwind_register (next_frame, I386_ESP_REGNUM, buf); cache->base = extract_unsigned_integer (buf, 4) - 4; @@ -875,12 +922,12 @@ i386_sigtramp_frame_cache (struct frame_info *next_frame, void **this_cache) for (i = 0; i < tdep->sc_num_regs; i++) if (tdep->sc_reg_offset[i] != -1) - cache->saved_regs[i].addr = addr + tdep->sc_reg_offset[i]; + cache->saved_regs[i] = addr + tdep->sc_reg_offset[i]; } else { - cache->saved_regs[I386_EIP_REGNUM].addr = addr + tdep->sc_pc_offset; - cache->saved_regs[I386_ESP_REGNUM].addr = addr + tdep->sc_sp_offset; + cache->saved_regs[I386_EIP_REGNUM] = addr + tdep->sc_pc_offset; + cache->saved_regs[I386_ESP_REGNUM] = addr + tdep->sc_sp_offset; } *this_cache = cache; @@ -920,8 +967,9 @@ static const struct frame_unwind i386_sigtramp_frame_unwind = }; static const struct frame_unwind * -i386_sigtramp_frame_p (CORE_ADDR pc) +i386_sigtramp_frame_sniffer (struct frame_info *next_frame) { + CORE_ADDR pc = frame_pc_unwind (next_frame); char *name; /* We shouldn't even bother to try if the OSABI didn't register @@ -988,11 +1036,14 @@ i386_get_longjmp_target (CORE_ADDR *pc) if (jb_pc_offset == -1) return 0; - sp = read_register (SP_REGNUM); + /* Don't use I386_ESP_REGNUM here, since this function is also used + for AMD64. */ + regcache_cooked_read (current_regcache, SP_REGNUM, buf); + sp = extract_typed_address (buf, builtin_type_void_data_ptr); if (target_read_memory (sp + len, buf, len)) return 0; - jb_addr = extract_typed_address (buf, builtin_type_void_func_ptr); + jb_addr = extract_typed_address (buf, builtin_type_void_data_ptr); if (target_read_memory (jb_addr + jb_pc_offset, buf, len)) return 0; @@ -1101,8 +1152,8 @@ i386_extract_return_value (struct type *type, struct regcache *regcache, } else { - int low_size = REGISTER_RAW_SIZE (LOW_RETURN_REGNUM); - int high_size = REGISTER_RAW_SIZE (HIGH_RETURN_REGNUM); + int low_size = register_size (current_gdbarch, LOW_RETURN_REGNUM); + int high_size = register_size (current_gdbarch, HIGH_RETURN_REGNUM); if (len <= low_size) { @@ -1175,8 +1226,8 @@ i386_store_return_value (struct type *type, struct regcache *regcache, } else { - int low_size = REGISTER_RAW_SIZE (LOW_RETURN_REGNUM); - int high_size = REGISTER_RAW_SIZE (HIGH_RETURN_REGNUM); + int low_size = register_size (current_gdbarch, LOW_RETURN_REGNUM); + int high_size = register_size (current_gdbarch, HIGH_RETURN_REGNUM); if (len <= low_size) regcache_raw_write_part (regcache, LOW_RETURN_REGNUM, 0, len, valbuf); @@ -1290,7 +1341,7 @@ i386_pseudo_register_read (struct gdbarch *gdbarch, struct regcache *regcache, /* Extract (always little endian). */ regcache_raw_read (regcache, fpnum, mmx_buf); - memcpy (buf, mmx_buf, REGISTER_RAW_SIZE (regnum)); + memcpy (buf, mmx_buf, register_size (gdbarch, regnum)); } else regcache_raw_read (regcache, regnum, buf); @@ -1308,7 +1359,7 @@ i386_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache, /* Read ... */ regcache_raw_read (regcache, fpnum, mmx_buf); /* ... Modify ... (always little endian). */ - memcpy (mmx_buf, buf, REGISTER_RAW_SIZE (regnum)); + memcpy (mmx_buf, buf, register_size (gdbarch, regnum)); /* ... Write. */ regcache_raw_write (regcache, fpnum, mmx_buf); } @@ -1412,7 +1463,7 @@ i386_register_to_value (struct frame_info *frame, int regnum, gdb_assert (regnum != -1); gdb_assert (register_size (current_gdbarch, regnum) == 4); - frame_read_register (frame, regnum, buf); + get_frame_register (frame, regnum, buf); regnum = i386_next_regnum (regnum); len -= 4; buf += 4; @@ -1516,7 +1567,7 @@ i386_pc_in_sigtramp (CORE_ADDR pc, char *name) deals with switching between those. */ static int -i386_print_insn (bfd_vma pc, disassemble_info *info) +i386_print_insn (bfd_vma pc, struct disassemble_info *info) { gdb_assert (disassembly_flavor == att_flavor || disassembly_flavor == intel_flavor); @@ -1680,14 +1731,14 @@ i386_register_reggroup_p (struct gdbarch *gdbarch, int regnum, } -/* Get the ith function argument for the current function. */ +/* Get the ARGIth function argument for the current function. */ + static CORE_ADDR i386_fetch_pointer_argument (struct frame_info *frame, int argi, struct type *type) { - CORE_ADDR stack; - frame_read_register (frame, SP_REGNUM, &stack); - return read_memory_unsigned_integer (stack + (4 * (argi + 1)), 4); + CORE_ADDR sp = get_frame_register_unsigned (frame, I386_ESP_REGNUM); + return read_memory_unsigned_integer (sp + (4 * (argi + 1)), 4); } @@ -1706,10 +1757,23 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) tdep = XMALLOC (struct gdbarch_tdep); gdbarch = gdbarch_alloc (&info, tdep); - /* The i386 default settings don't include the SSE registers. + /* The i386 default settings now include the SSE registers. + I386_NUM_XREGS includes mxcsr, and we don't want to count + this as one of the xmm regs -- which is why we subtract one. + + Note: kevinb/2003-07-14: Whatever Mark's concerns are about the + FPU registers in the FIXME below apply to the SSE registers as well. + The only problem that I see is that these registers will show up + in "info all-registers" even on CPUs where they don't exist. IMO, + however, if it's a choice between printing them always (even when + they don't exist) or never showing them to the user (even when they + do exist), I prefer the former over the latter. Ideally, of course, + we'd somehow autodetect that we have them (or not) and display them + when we have them and suppress them when we don't. + FIXME: kettenis/20020614: They do include the FPU registers for now, which probably is not quite right. */ - tdep->num_xmm_regs = 0; + tdep->num_xmm_regs = I386_NUM_XREGS - 1; tdep->jb_pc_offset = -1; tdep->struct_return = pcc_struct_return; @@ -1731,9 +1795,9 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) alignment. */ set_gdbarch_long_double_bit (gdbarch, 96); - /* The default ABI includes general-purpose registers and - floating-point registers. */ - set_gdbarch_num_regs (gdbarch, I386_NUM_GREGS + I386_NUM_FREGS); + /* The default ABI includes general-purpose registers, + floating-point registers, and the SSE registers. */ + set_gdbarch_num_regs (gdbarch, I386_SSE_NUM_REGS); set_gdbarch_register_name (gdbarch, i386_register_name); set_gdbarch_register_type (gdbarch, i386_register_type); @@ -1802,16 +1866,15 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_fetch_pointer_argument (gdbarch, i386_fetch_pointer_argument); /* Hook in the DWARF CFI frame unwinder. */ - frame_unwind_append_predicate (gdbarch, dwarf2_frame_p); - set_gdbarch_dwarf2_build_frame_info (gdbarch, dwarf2_build_frame_info); + frame_unwind_append_sniffer (gdbarch, dwarf2_frame_sniffer); frame_base_set_default (gdbarch, &i386_frame_base); /* Hook in ABI-specific overrides, if they have been registered. */ gdbarch_init_osabi (info, gdbarch); - frame_unwind_append_predicate (gdbarch, i386_sigtramp_frame_p); - frame_unwind_append_predicate (gdbarch, i386_frame_p); + frame_unwind_append_sniffer (gdbarch, i386_sigtramp_frame_sniffer); + frame_unwind_append_sniffer (gdbarch, i386_frame_sniffer); return gdbarch; }