Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(458)

Unified Diff: gdb/amd64-tdep.c

Issue 11969036: Merge GDB 7.5.1 (Closed) Base URL: http://git.chromium.org/native_client/nacl-gdb.git@master
Patch Set: Created 7 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « gdb/amd64-tdep.h ('k') | gdb/amd64-windows-nat.c » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: gdb/amd64-tdep.c
diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c
index ea65d0d55bc8ba795f514d802b89e1eaf212cabe..8ae1142c47e35bde014af73938adc83aa6c12595 100644
--- a/gdb/amd64-tdep.c
+++ b/gdb/amd64-tdep.c
@@ -43,6 +43,8 @@
#include "features/i386/amd64.c"
#include "features/i386/amd64-avx.c"
+#include "features/i386/x32.c"
+#include "features/i386/x32-avx.c"
#include "ax.h"
#include "ax-gdb.h"
@@ -256,7 +258,8 @@ static const char *amd64_word_names[] =
static const char *amd64_dword_names[] =
{
"eax", "ebx", "ecx", "edx", "esi", "edi", "ebp", "esp",
- "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d"
+ "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d",
+ "eip"
};
/* Return the name of register REGNUM. */
@@ -592,7 +595,7 @@ amd64_classify (struct type *type, enum amd64_reg_class class[2])
}
static enum return_value_convention
-amd64_return_value (struct gdbarch *gdbarch, struct type *func_type,
+amd64_return_value (struct gdbarch *gdbarch, struct value *function,
struct type *type, struct regcache *regcache,
gdb_byte *readbuf, const gdb_byte *writebuf)
{
@@ -1258,7 +1261,7 @@ amd64_displaced_step_copy_insn (struct gdbarch *gdbarch,
struct regcache *regs)
{
int len = gdbarch_max_insn_length (gdbarch);
- /* Extra space for sentinels so fixup_{riprel,displaced_copy don't have to
+ /* Extra space for sentinels so fixup_{riprel,displaced_copy} don't have to
continually watch for running off the end of the buffer. */
int fixup_sentinel_space = len;
struct displaced_step_closure *dsc =
@@ -1858,6 +1861,188 @@ amd64_analyze_stack_align (CORE_ADDR pc, CORE_ADDR current_pc,
return min (pc + offset + 2, current_pc);
}
+/* Similar to amd64_analyze_stack_align for x32. */
+
+static CORE_ADDR
+amd64_x32_analyze_stack_align (CORE_ADDR pc, CORE_ADDR current_pc,
+ struct amd64_frame_cache *cache)
+{
+ /* There are 2 code sequences to re-align stack before the frame
+ gets set up:
+
+ 1. Use a caller-saved saved register:
+
+ leaq 8(%rsp), %reg
+ andq $-XXX, %rsp
+ pushq -8(%reg)
+
+ or
+
+ [addr32] leal 8(%rsp), %reg
+ andl $-XXX, %esp
+ [addr32] pushq -8(%reg)
+
+ 2. Use a callee-saved saved register:
+
+ pushq %reg
+ leaq 16(%rsp), %reg
+ andq $-XXX, %rsp
+ pushq -8(%reg)
+
+ or
+
+ pushq %reg
+ [addr32] leal 16(%rsp), %reg
+ andl $-XXX, %esp
+ [addr32] pushq -8(%reg)
+
+ "andq $-XXX, %rsp" can be either 4 bytes or 7 bytes:
+
+ 0x48 0x83 0xe4 0xf0 andq $-16, %rsp
+ 0x48 0x81 0xe4 0x00 0xff 0xff 0xff andq $-256, %rsp
+
+ "andl $-XXX, %esp" can be either 3 bytes or 6 bytes:
+
+ 0x83 0xe4 0xf0 andl $-16, %esp
+ 0x81 0xe4 0x00 0xff 0xff 0xff andl $-256, %esp
+ */
+
+ gdb_byte buf[19];
+ int reg, r;
+ int offset, offset_and;
+
+ if (target_read_memory (pc, buf, sizeof buf))
+ return pc;
+
+ /* Skip optional addr32 prefix. */
+ offset = buf[0] == 0x67 ? 1 : 0;
+
+ /* Check caller-saved saved register. The first instruction has
+ to be "leaq 8(%rsp), %reg" or "leal 8(%rsp), %reg". */
+ if (((buf[offset] & 0xfb) == 0x48 || (buf[offset] & 0xfb) == 0x40)
+ && buf[offset + 1] == 0x8d
+ && buf[offset + 3] == 0x24
+ && buf[offset + 4] == 0x8)
+ {
+ /* MOD must be binary 10 and R/M must be binary 100. */
+ if ((buf[offset + 2] & 0xc7) != 0x44)
+ return pc;
+
+ /* REG has register number. */
+ reg = (buf[offset + 2] >> 3) & 7;
+
+ /* Check the REX.R bit. */
+ if ((buf[offset] & 0x4) != 0)
+ reg += 8;
+
+ offset += 5;
+ }
+ else
+ {
+ /* Check callee-saved saved register. The first instruction
+ has to be "pushq %reg". */
+ reg = 0;
+ if ((buf[offset] & 0xf6) == 0x40
+ && (buf[offset + 1] & 0xf8) == 0x50)
+ {
+ /* Check the REX.B bit. */
+ if ((buf[offset] & 1) != 0)
+ reg = 8;
+
+ offset += 1;
+ }
+ else if ((buf[offset] & 0xf8) != 0x50)
+ return pc;
+
+ /* Get register. */
+ reg += buf[offset] & 0x7;
+
+ offset++;
+
+ /* Skip optional addr32 prefix. */
+ if (buf[offset] == 0x67)
+ offset++;
+
+ /* The next instruction has to be "leaq 16(%rsp), %reg" or
+ "leal 16(%rsp), %reg". */
+ if (((buf[offset] & 0xfb) != 0x48 && (buf[offset] & 0xfb) != 0x40)
+ || buf[offset + 1] != 0x8d
+ || buf[offset + 3] != 0x24
+ || buf[offset + 4] != 0x10)
+ return pc;
+
+ /* MOD must be binary 10 and R/M must be binary 100. */
+ if ((buf[offset + 2] & 0xc7) != 0x44)
+ return pc;
+
+ /* REG has register number. */
+ r = (buf[offset + 2] >> 3) & 7;
+
+ /* Check the REX.R bit. */
+ if ((buf[offset] & 0x4) != 0)
+ r += 8;
+
+ /* Registers in pushq and leaq have to be the same. */
+ if (reg != r)
+ return pc;
+
+ offset += 5;
+ }
+
+ /* Rigister can't be %rsp nor %rbp. */
+ if (reg == 4 || reg == 5)
+ return pc;
+
+ /* The next instruction may be "andq $-XXX, %rsp" or
+ "andl $-XXX, %esp". */
+ if (buf[offset] != 0x48)
+ offset--;
+
+ if (buf[offset + 2] != 0xe4
+ || (buf[offset + 1] != 0x81 && buf[offset + 1] != 0x83))
+ return pc;
+
+ offset_and = offset;
+ offset += buf[offset + 1] == 0x81 ? 7 : 4;
+
+ /* Skip optional addr32 prefix. */
+ if (buf[offset] == 0x67)
+ offset++;
+
+ /* The next instruction has to be "pushq -8(%reg)". */
+ r = 0;
+ if (buf[offset] == 0xff)
+ offset++;
+ else if ((buf[offset] & 0xf6) == 0x40
+ && buf[offset + 1] == 0xff)
+ {
+ /* Check the REX.B bit. */
+ if ((buf[offset] & 0x1) != 0)
+ r = 8;
+ offset += 2;
+ }
+ else
+ return pc;
+
+ /* 8bit -8 is 0xf8. REG must be binary 110 and MOD must be binary
+ 01. */
+ if (buf[offset + 1] != 0xf8
+ || (buf[offset] & 0xf8) != 0x70)
+ return pc;
+
+ /* R/M has register. */
+ r += buf[offset] & 7;
+
+ /* Registers in leaq and pushq have to be the same. */
+ if (reg != r)
+ return pc;
+
+ if (current_pc > pc + offset_and)
+ cache->saved_sp_reg = amd64_arch_reg_to_regnum (reg);
+
+ return min (pc + offset + 2, current_pc);
+}
+
/* Do a limited analysis of the prologue at PC and update CACHE
accordingly. Bail out early if CURRENT_PC is reached. Return the
address where the analysis stopped.
@@ -1865,10 +2050,16 @@ amd64_analyze_stack_align (CORE_ADDR pc, CORE_ADDR current_pc,
We will handle only functions beginning with:
pushq %rbp 0x55
- movq %rsp, %rbp 0x48 0x89 0xe5
+ movq %rsp, %rbp 0x48 0x89 0xe5 (or 0x48 0x8b 0xec)
+
+ or (for the X32 ABI):
- Any function that doesn't start with this sequence will be assumed
- to have no prologue and thus no valid frame pointer in %rbp. */
+ pushq %rbp 0x55
+ movl %esp, %ebp 0x89 0xe5 (or 0x8b 0xec)
+
+ Any function that doesn't start with one of these sequences will be
+ assumed to have no prologue and thus no valid frame pointer in
+ %rbp. */
static CORE_ADDR
amd64_analyze_prologue (struct gdbarch *gdbarch,
@@ -1876,14 +2067,23 @@ amd64_analyze_prologue (struct gdbarch *gdbarch,
struct amd64_frame_cache *cache)
{
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
- static gdb_byte proto[3] = { 0x48, 0x89, 0xe5 }; /* movq %rsp, %rbp */
+ /* There are two variations of movq %rsp, %rbp. */
+ static const gdb_byte mov_rsp_rbp_1[3] = { 0x48, 0x89, 0xe5 };
+ static const gdb_byte mov_rsp_rbp_2[3] = { 0x48, 0x8b, 0xec };
+ /* Ditto for movl %esp, %ebp. */
+ static const gdb_byte mov_esp_ebp_1[2] = { 0x89, 0xe5 };
+ static const gdb_byte mov_esp_ebp_2[2] = { 0x8b, 0xec };
+
gdb_byte buf[3];
gdb_byte op;
if (current_pc <= pc)
return current_pc;
- pc = amd64_analyze_stack_align (pc, current_pc, cache);
+ if (gdbarch_ptr_bit (gdbarch) == 32)
+ pc = amd64_x32_analyze_stack_align (pc, current_pc, cache);
+ else
+ pc = amd64_analyze_stack_align (pc, current_pc, cache);
op = read_memory_unsigned_integer (pc, 1, byte_order);
@@ -1898,14 +2098,30 @@ amd64_analyze_prologue (struct gdbarch *gdbarch,
if (current_pc <= pc + 1)
return current_pc;
- /* Check for `movq %rsp, %rbp'. */
read_memory (pc + 1, buf, 3);
- if (memcmp (buf, proto, 3) != 0)
- return pc + 1;
- /* OK, we actually have a frame. */
- cache->frameless_p = 0;
- return pc + 4;
+ /* Check for `movq %rsp, %rbp'. */
+ if (memcmp (buf, mov_rsp_rbp_1, 3) == 0
+ || memcmp (buf, mov_rsp_rbp_2, 3) == 0)
+ {
+ /* OK, we actually have a frame. */
+ cache->frameless_p = 0;
+ return pc + 4;
+ }
+
+ /* For X32, also check for `movq %esp, %ebp'. */
+ if (gdbarch_ptr_bit (gdbarch) == 32)
+ {
+ if (memcmp (buf, mov_esp_ebp_1, 2) == 0
+ || memcmp (buf, mov_esp_ebp_2, 2) == 0)
+ {
+ /* OK, we actually have a frame. */
+ cache->frameless_p = 0;
+ return pc + 3;
+ }
+ }
+
+ return pc + 1;
}
return pc;
@@ -2688,6 +2904,53 @@ amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
set_gdbarch_relocate_instruction (gdbarch, amd64_relocate_instruction);
set_gdbarch_gen_return_address (gdbarch, amd64_gen_return_address);
+
+ /* SystemTap variables and functions. */
+ set_gdbarch_stap_integer_prefix (gdbarch, "$");
+ set_gdbarch_stap_register_prefix (gdbarch, "%");
+ set_gdbarch_stap_register_indirection_prefix (gdbarch, "(");
+ set_gdbarch_stap_register_indirection_suffix (gdbarch, ")");
+ set_gdbarch_stap_is_single_operand (gdbarch,
+ i386_stap_is_single_operand);
+ set_gdbarch_stap_parse_special_token (gdbarch,
+ i386_stap_parse_special_token);
+}
+
+
+static struct type *
+amd64_x32_pseudo_register_type (struct gdbarch *gdbarch, int regnum)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+
+ switch (regnum - tdep->eax_regnum)
+ {
+ case AMD64_RBP_REGNUM: /* %ebp */
+ case AMD64_RSP_REGNUM: /* %esp */
+ return builtin_type (gdbarch)->builtin_data_ptr;
+ case AMD64_RIP_REGNUM: /* %eip */
+ return builtin_type (gdbarch)->builtin_func_ptr;
+ }
+
+ return i386_pseudo_register_type (gdbarch, regnum);
+}
+
+void
+amd64_x32_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ const struct target_desc *tdesc = info.target_desc;
+
+ amd64_init_abi (info, gdbarch);
+
+ if (! tdesc_has_registers (tdesc))
+ tdesc = tdesc_x32;
+ tdep->tdesc = tdesc;
+
+ tdep->num_dword_regs = 17;
+ set_tdesc_pseudo_register_type (gdbarch, amd64_x32_pseudo_register_type);
+
+ set_gdbarch_long_bit (gdbarch, 32);
+ set_gdbarch_ptr_bit (gdbarch, 32);
}
/* Provide a prototype to silence -Wmissing-prototypes. */
@@ -2698,6 +2961,8 @@ _initialize_amd64_tdep (void)
{
initialize_tdesc_amd64 ();
initialize_tdesc_amd64_avx ();
+ initialize_tdesc_x32 ();
+ initialize_tdesc_x32_avx ();
}
@@ -2722,7 +2987,8 @@ amd64_supply_fxsave (struct regcache *regcache, int regnum,
i387_supply_fxsave (regcache, regnum, fxsave);
- if (fxsave && gdbarch_ptr_bit (gdbarch) == 64)
+ if (fxsave
+ && gdbarch_bfd_arch_info (gdbarch)->bits_per_word == 64)
{
const gdb_byte *regs = fxsave;
@@ -2744,7 +3010,8 @@ amd64_supply_xsave (struct regcache *regcache, int regnum,
i387_supply_xsave (regcache, regnum, xsave);
- if (xsave && gdbarch_ptr_bit (gdbarch) == 64)
+ if (xsave
+ && gdbarch_bfd_arch_info (gdbarch)->bits_per_word == 64)
{
const gdb_byte *regs = xsave;
@@ -2772,7 +3039,7 @@ amd64_collect_fxsave (const struct regcache *regcache, int regnum,
i387_collect_fxsave (regcache, regnum, fxsave);
- if (gdbarch_ptr_bit (gdbarch) == 64)
+ if (gdbarch_bfd_arch_info (gdbarch)->bits_per_word == 64)
{
if (regnum == -1 || regnum == I387_FISEG_REGNUM (tdep))
regcache_raw_collect (regcache, I387_FISEG_REGNUM (tdep), regs + 12);
@@ -2793,7 +3060,7 @@ amd64_collect_xsave (const struct regcache *regcache, int regnum,
i387_collect_xsave (regcache, regnum, xsave, gcore);
- if (gdbarch_ptr_bit (gdbarch) == 64)
+ if (gdbarch_bfd_arch_info (gdbarch)->bits_per_word == 64)
{
if (regnum == -1 || regnum == I387_FISEG_REGNUM (tdep))
regcache_raw_collect (regcache, I387_FISEG_REGNUM (tdep),
« no previous file with comments | « gdb/amd64-tdep.h ('k') | gdb/amd64-windows-nat.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698