X-Git-Url: http://git.efficios.com/?a=blobdiff_plain;f=gdb%2Famd64-tdep.c;h=9ff7dfc5134f123b1924623356b40e3bb3e57905;hb=f65e204425b5b46a5927d9501c42f25d98a866ce;hp=a62efde5e4a06cc1e7e32277e86055a14b0d34c5;hpb=62e5fd57bcdfb58eadd08ec430c4dfd742027d8e;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c index a62efde5e4..9ff7dfc513 100644 --- a/gdb/amd64-tdep.c +++ b/gdb/amd64-tdep.c @@ -1,6 +1,6 @@ /* Target-dependent code for AMD64. - Copyright (C) 2001-2016 Free Software Foundation, Inc. + Copyright (C) 2001-2017 Free Software Foundation, Inc. Contributed by Jiri Smid, SuSE Labs. @@ -40,15 +40,18 @@ #include "amd64-tdep.h" #include "i387-tdep.h" #include "x86-xstate.h" +#include #include "features/i386/amd64.c" #include "features/i386/amd64-avx.c" #include "features/i386/amd64-mpx.c" -#include "features/i386/amd64-avx512.c" +#include "features/i386/amd64-avx-mpx.c" +#include "features/i386/amd64-avx-avx512.c" +#include "features/i386/amd64-avx-mpx-avx512-pku.c" #include "features/i386/x32.c" #include "features/i386/x32-avx.c" -#include "features/i386/x32-avx512.c" +#include "features/i386/x32-avx-avx512.c" #include "ax.h" #include "ax-gdb.h" @@ -154,6 +157,10 @@ static const char *amd64_xmm_avx512_names[] = { "xmm28", "xmm29", "xmm30", "xmm31" }; +static const char *amd64_pkeys_names[] = { + "pkru" +}; + /* DWARF Register Number Mapping as defined in the System V psABI, section 3.6. */ @@ -351,7 +358,7 @@ amd64_pseudo_register_read_value (struct gdbarch *gdbarch, struct regcache *regcache, int regnum) { - gdb_byte raw_buf[MAX_REGISTER_SIZE]; + gdb_byte *raw_buf = (gdb_byte *) alloca (register_size (gdbarch, regnum)); struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); enum register_status status; struct value *result_value; @@ -412,7 +419,7 @@ amd64_pseudo_register_write (struct gdbarch *gdbarch, struct regcache *regcache, int regnum, const gdb_byte *buf) { - gdb_byte raw_buf[MAX_REGISTER_SIZE]; + gdb_byte *raw_buf = (gdb_byte *) alloca (register_size (gdbarch, regnum)); struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); if (i386_byte_regnum_p (gdbarch, regnum)) @@ -672,7 +679,7 @@ amd64_classify (struct type *type, enum amd64_reg_class theclass[2]) if ((code == TYPE_CODE_INT || code == TYPE_CODE_ENUM || code == TYPE_CODE_BOOL || code == TYPE_CODE_RANGE || code == TYPE_CODE_CHAR - || code == TYPE_CODE_PTR || code == TYPE_CODE_REF) + || code == TYPE_CODE_PTR || TYPE_IS_REFERENCE (type)) && (len == 1 || len == 2 || len == 4 || len == 8)) theclass[0] = AMD64_INTEGER; @@ -845,10 +852,10 @@ amd64_return_value (struct gdbarch *gdbarch, struct value *function, gdb_assert (regnum != -1); if (readbuf) - regcache_raw_read_part (regcache, regnum, offset, min (len, 8), + regcache_raw_read_part (regcache, regnum, offset, std::min (len, 8), readbuf + i * 8); if (writebuf) - regcache_raw_write_part (regcache, regnum, offset, min (len, 8), + regcache_raw_write_part (regcache, regnum, offset, std::min (len, 8), writebuf + i * 8); } @@ -956,7 +963,7 @@ amd64_push_arguments (struct regcache *regcache, int nargs, gdb_assert (regnum != -1); memset (buf, 0, sizeof buf); - memcpy (buf, valbuf + j * 8, min (len, 8)); + memcpy (buf, valbuf + j * 8, std::min (len, 8)); regcache_raw_write_part (regcache, regnum, offset, 8, buf); } } @@ -997,6 +1004,13 @@ amd64_push_dummy_call (struct gdbarch *gdbarch, struct value *function, enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); gdb_byte buf[8]; + /* BND registers can be in arbitrary values at the moment of the + inferior call. This can cause boundary violations that are not + due to a real bug or even desired by the user. The best to be done + is set the BND registers to allow access to the whole memory, INIT + state, before pushing the inferior call. */ + i387_reset_bnd_regs (gdbarch, regcache); + /* Pass arguments. */ sp = amd64_push_arguments (regcache, nargs, args, sp, struct_return); @@ -1301,12 +1315,10 @@ static void fixup_riprel (struct gdbarch *gdbarch, struct displaced_step_closure *dsc, CORE_ADDR from, CORE_ADDR to, struct regcache *regs) { - enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); const struct amd64_insn *insn_details = &dsc->insn_details; int modrm_offset = insn_details->modrm_offset; gdb_byte *insn = insn_details->raw_insn + modrm_offset; CORE_ADDR rip_base; - int32_t disp; int insn_length; int arch_tmp_regno, tmp_regno; ULONGEST orig_value; @@ -1315,7 +1327,6 @@ fixup_riprel (struct gdbarch *gdbarch, struct displaced_step_closure *dsc, ++insn; /* Compute the rip-relative address. */ - disp = extract_signed_integer (insn, sizeof (int32_t), byte_order); insn_length = gdb_buffered_insn_length (gdbarch, dsc->insn_buf, dsc->max_len, from); rip_base = from + insn_length; @@ -1766,15 +1777,47 @@ amd64_relocate_instruction (struct gdbarch *gdbarch, the user program would return to. */ if (insn[0] == 0xe8) { - gdb_byte push_buf[16]; - unsigned int ret_addr; + gdb_byte push_buf[32]; + CORE_ADDR ret_addr; + int i = 0; /* Where "ret" in the original code will return to. */ ret_addr = oldloc + insn_length; - push_buf[0] = 0x68; /* pushq $... */ - store_unsigned_integer (&push_buf[1], 4, byte_order, ret_addr); + + /* If pushing an address higher than or equal to 0x80000000, + avoid 'pushq', as that sign extends its 32-bit operand, which + would be incorrect. */ + if (ret_addr <= 0x7fffffff) + { + push_buf[0] = 0x68; /* pushq $... */ + store_unsigned_integer (&push_buf[1], 4, byte_order, ret_addr); + i = 5; + } + else + { + push_buf[i++] = 0x48; /* sub $0x8,%rsp */ + push_buf[i++] = 0x83; + push_buf[i++] = 0xec; + push_buf[i++] = 0x08; + + push_buf[i++] = 0xc7; /* movl $imm,(%rsp) */ + push_buf[i++] = 0x04; + push_buf[i++] = 0x24; + store_unsigned_integer (&push_buf[i], 4, byte_order, + ret_addr & 0xffffffff); + i += 4; + + push_buf[i++] = 0xc7; /* movl $imm,4(%rsp) */ + push_buf[i++] = 0x44; + push_buf[i++] = 0x24; + push_buf[i++] = 0x04; + store_unsigned_integer (&push_buf[i], 4, byte_order, + ret_addr >> 32); + i += 4; + } + gdb_assert (i <= sizeof (push_buf)); /* Push the push. */ - append_insns (to, 5, push_buf); + append_insns (to, i, push_buf); /* Convert the relative call to a relative jump. */ insn[0] = 0xe9; @@ -2037,7 +2080,7 @@ amd64_analyze_stack_align (CORE_ADDR pc, CORE_ADDR current_pc, if (current_pc > pc + offset_and) cache->saved_sp_reg = amd64_arch_reg_to_regnum (reg); - return min (pc + offset + 2, current_pc); + return std::min (pc + offset + 2, current_pc); } /* Similar to amd64_analyze_stack_align for x32. */ @@ -2219,7 +2262,7 @@ amd64_x32_analyze_stack_align (CORE_ADDR pc, CORE_ADDR current_pc, if (current_pc > pc + offset_and) cache->saved_sp_reg = amd64_arch_reg_to_regnum (reg); - return min (pc + offset + 2, current_pc); + return std::min (pc + offset + 2, current_pc); } /* Do a limited analysis of the prologue at PC and update CACHE @@ -2408,7 +2451,7 @@ amd64_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc) && (cust != NULL && COMPUNIT_PRODUCER (cust) != NULL && startswith (COMPUNIT_PRODUCER (cust), "clang "))) - return max (start_pc, post_prologue_pc); + return std::max (start_pc, post_prologue_pc); } amd64_init_frame_cache (&cache); @@ -3016,6 +3059,26 @@ amd64_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) tdep->bnd0r_regnum = AMD64_BND0R_REGNUM; } + if (tdesc_find_feature (tdesc, "org.gnu.gdb.i386.segments") != NULL) + { + const struct tdesc_feature *feature = + tdesc_find_feature (tdesc, "org.gnu.gdb.i386.segments"); + struct tdesc_arch_data *tdesc_data_segments = + (struct tdesc_arch_data *) info.tdep_info; + + tdesc_numbered_register (feature, tdesc_data_segments, + AMD64_FSBASE_REGNUM, "fs_base"); + tdesc_numbered_register (feature, tdesc_data_segments, + AMD64_GSBASE_REGNUM, "gs_base"); + } + + if (tdesc_find_feature (tdesc, "org.gnu.gdb.i386.pkeys") != NULL) + { + tdep->pkeys_register_names = amd64_pkeys_names; + tdep->pkru_regnum = AMD64_PKRU_REGNUM; + tdep->num_pkeys_regs = 1; + } + tdep->num_byte_regs = 20; tdep->num_word_regs = 16; tdep->num_dword_regs = 16; @@ -3158,11 +3221,14 @@ amd64_target_description (uint64_t xcr0) { switch (xcr0 & X86_XSTATE_ALL_MASK) { - case X86_XSTATE_MPX_AVX512_MASK: - case X86_XSTATE_AVX512_MASK: - return tdesc_amd64_avx512; + case X86_XSTATE_AVX_MPX_AVX512_PKU_MASK: + return tdesc_amd64_avx_mpx_avx512_pku; + case X86_XSTATE_AVX_AVX512_MASK: + return tdesc_amd64_avx_avx512; case X86_XSTATE_MPX_MASK: return tdesc_amd64_mpx; + case X86_XSTATE_AVX_MPX_MASK: + return tdesc_amd64_avx_mpx; case X86_XSTATE_AVX_MASK: return tdesc_amd64_avx; default: @@ -3179,11 +3245,13 @@ _initialize_amd64_tdep (void) initialize_tdesc_amd64 (); initialize_tdesc_amd64_avx (); initialize_tdesc_amd64_mpx (); - initialize_tdesc_amd64_avx512 (); + initialize_tdesc_amd64_avx_mpx (); + initialize_tdesc_amd64_avx_avx512 (); + initialize_tdesc_amd64_avx_mpx_avx512_pku (); initialize_tdesc_x32 (); initialize_tdesc_x32_avx (); - initialize_tdesc_x32_avx512 (); + initialize_tdesc_x32_avx_avx512 (); }