GDB (API)
/home/stan/gdb/src/gdb/amd64-nat.c
Go to the documentation of this file.
00001 /* Native-dependent code for AMD64.
00002 
00003    Copyright (C) 2003-2013 Free Software Foundation, Inc.
00004 
00005    This file is part of GDB.
00006 
00007    This program is free software; you can redistribute it and/or modify
00008    it under the terms of the GNU General Public License as published by
00009    the Free Software Foundation; either version 3 of the License, or
00010    (at your option) any later version.
00011 
00012    This program is distributed in the hope that it will be useful,
00013    but WITHOUT ANY WARRANTY; without even the implied warranty of
00014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015    GNU General Public License for more details.
00016 
00017    You should have received a copy of the GNU General Public License
00018    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
00019 
00020 #include "defs.h"
00021 #include "gdbarch.h"
00022 #include "regcache.h"
00023 
00024 #include "gdb_assert.h"
00025 #include "gdb_string.h"
00026 
00027 #include "i386-tdep.h"
00028 #include "amd64-tdep.h"
00029 #include "amd64-nat.h"
00030 
00031 /* The following bits of code help with implementing debugging 32-bit
00032    code natively on AMD64.  The idea is to define two mappings between
00033    the register number as used by GDB and the register set used by the
00034    host to represent the general-purpose registers; one for 32-bit
00035    code and one for 64-bit code.  The mappings are specified by the
00036    follwing variables and consist of an array of offsets within the
00037    register set indexed by register number, and the number of
00038    registers supported by the mapping.  We don't need mappings for the
00039    floating-point and SSE registers, since the difference between
00040    64-bit and 32-bit variants are negligable.  The difference in the
00041    number of SSE registers is already handled by the target code.  */
00042 
00043 /* General-purpose register mapping for native 32-bit code.  */
00044 int *amd64_native_gregset32_reg_offset;
00045 int amd64_native_gregset32_num_regs = I386_NUM_GREGS;
00046 
00047 /* General-purpose register mapping for native 64-bit code.  */
00048 int *amd64_native_gregset64_reg_offset;
00049 int amd64_native_gregset64_num_regs = AMD64_NUM_GREGS;
00050 
00051 /* Return the offset of REGNUM within the appropriate native
00052    general-purpose register set.  */
00053 
00054 static int
00055 amd64_native_gregset_reg_offset (struct gdbarch *gdbarch, int regnum)
00056 {
00057   int *reg_offset = amd64_native_gregset64_reg_offset;
00058   int num_regs = amd64_native_gregset64_num_regs;
00059 
00060   gdb_assert (regnum >= 0);
00061 
00062   if (gdbarch_bfd_arch_info (gdbarch)->bits_per_word == 32)
00063     {
00064       reg_offset = amd64_native_gregset32_reg_offset;
00065       num_regs = amd64_native_gregset32_num_regs;
00066     }
00067 
00068   if (num_regs > gdbarch_num_regs (gdbarch))
00069     num_regs = gdbarch_num_regs (gdbarch);
00070 
00071   if (regnum < num_regs && regnum < gdbarch_num_regs (gdbarch))
00072     return reg_offset[regnum];
00073 
00074   return -1;
00075 }
00076 
00077 /* Return whether the native general-purpose register set supplies
00078    register REGNUM.  */
00079 
00080 int
00081 amd64_native_gregset_supplies_p (struct gdbarch *gdbarch, int regnum)
00082 {
00083   return (amd64_native_gregset_reg_offset (gdbarch, regnum) != -1);
00084 }
00085 
00086 
00087 /* Supply register REGNUM, whose contents are stored in GREGS, to
00088    REGCACHE.  If REGNUM is -1, supply all appropriate registers.  */
00089 
00090 void
00091 amd64_supply_native_gregset (struct regcache *regcache,
00092                              const void *gregs, int regnum)
00093 {
00094   const char *regs = gregs;
00095   struct gdbarch *gdbarch = get_regcache_arch (regcache);
00096   int num_regs = amd64_native_gregset64_num_regs;
00097   int i;
00098 
00099   if (gdbarch_bfd_arch_info (gdbarch)->bits_per_word == 32)
00100     num_regs = amd64_native_gregset32_num_regs;
00101 
00102   if (num_regs > gdbarch_num_regs (gdbarch))
00103     num_regs = gdbarch_num_regs (gdbarch);
00104 
00105   for (i = 0; i < num_regs; i++)
00106     {
00107       if (regnum == -1 || regnum == i)
00108         {
00109           int offset = amd64_native_gregset_reg_offset (gdbarch, i);
00110 
00111           if (offset != -1)
00112             regcache_raw_supply (regcache, i, regs + offset);
00113         }
00114     }
00115 }
00116 
00117 /* Collect register REGNUM from REGCACHE and store its contents in
00118    GREGS.  If REGNUM is -1, collect and store all appropriate
00119    registers.  */
00120 
00121 void
00122 amd64_collect_native_gregset (const struct regcache *regcache,
00123                               void *gregs, int regnum)
00124 {
00125   char *regs = gregs;
00126   struct gdbarch *gdbarch = get_regcache_arch (regcache);
00127   int num_regs = amd64_native_gregset64_num_regs;
00128   int i;
00129 
00130   if (gdbarch_bfd_arch_info (gdbarch)->bits_per_word == 32)
00131     {
00132       num_regs = amd64_native_gregset32_num_regs;
00133 
00134       /* Make sure %eax, %ebx, %ecx, %edx, %esi, %edi, %ebp, %esp and
00135          %eip get zero-extended to 64 bits.  */
00136       for (i = 0; i <= I386_EIP_REGNUM; i++)
00137         {
00138           if (regnum == -1 || regnum == i)
00139             memset (regs + amd64_native_gregset_reg_offset (gdbarch, i), 0, 8);
00140         }
00141       /* Ditto for %cs, %ss, %ds, %es, %fs, and %gs.  */
00142       for (i = I386_CS_REGNUM; i <= I386_GS_REGNUM; i++)
00143         {
00144           if (regnum == -1 || regnum == i)
00145             memset (regs + amd64_native_gregset_reg_offset (gdbarch, i), 0, 8);
00146         }
00147     }
00148 
00149   if (num_regs > gdbarch_num_regs (gdbarch))
00150     num_regs = gdbarch_num_regs (gdbarch);
00151 
00152   for (i = 0; i < num_regs; i++)
00153     {
00154       if (regnum == -1 || regnum == i)
00155         {
00156           int offset = amd64_native_gregset_reg_offset (gdbarch, i);
00157 
00158           if (offset != -1)
00159             regcache_raw_collect (regcache, i, regs + offset);
00160         }
00161     }
00162 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines