GDB (API)
/home/stan/gdb/src/gdb/i386-cygwin-tdep.c
Go to the documentation of this file.
00001 /* Target-dependent code for Cygwin running on i386's, for GDB.
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 "osabi.h"
00022 #include "gdb_string.h"
00023 #include "i386-tdep.h"
00024 #include "windows-tdep.h"
00025 #include "regset.h"
00026 #include "gdb_obstack.h"
00027 #include "xml-support.h"
00028 #include "gdbcore.h"
00029 #include "inferior.h"
00030 
00031 /* Core file support.  */
00032 
00033 /* This vector maps GDB's idea of a register's number into an address
00034    in the windows exception context vector.  */
00035 
00036 static int i386_windows_gregset_reg_offset[] =
00037 {
00038   176, /* eax */
00039   172, /* ecx */
00040   168, /* edx */
00041   164, /* ebx */
00042 
00043   196, /* esp */
00044   180, /* ebp */
00045   160, /* esi */
00046   156, /* edi */
00047 
00048   184, /* eip */
00049   192, /* eflags */
00050   188, /* cs */
00051   200, /* ss */
00052 
00053   152, /* ds */
00054   148, /* es */
00055   144, /* fs */
00056   140, /* gs */
00057 
00058   56, /* FloatSave.RegisterArea[0 * 10] */
00059   66, /* FloatSave.RegisterArea[1 * 10] */
00060   76, /* FloatSave.RegisterArea[2 * 10] */
00061   86, /* FloatSave.RegisterArea[3 * 10] */
00062   96, /* FloatSave.RegisterArea[4 * 10] */
00063   106, /* FloatSave.RegisterArea[5 * 10] */
00064   116, /* FloatSave.RegisterArea[6 * 10] */
00065   126, /* FloatSave.RegisterArea[7 * 10] */
00066 
00067   28, /* FloatSave.ControlWord */
00068   32, /* FloatSave.StatusWord */
00069   36, /* FloatSave.TagWord */
00070   44, /* FloatSave.ErrorSelector */
00071   40, /* FloatSave.ErrorOffset */
00072   52, /* FloatSave.DataSelector */
00073   48, /* FloatSave.DataOffset */
00074   44, /* FloatSave.ErrorSelector */
00075 
00076   /* XMM0-7 */
00077   364, /* ExtendedRegisters[10*16] */
00078   380, /* ExtendedRegisters[11*16] */
00079   396, /* ExtendedRegisters[12*16] */
00080   412, /* ExtendedRegisters[13*16] */
00081   428, /* ExtendedRegisters[14*16] */
00082   444, /* ExtendedRegisters[15*16] */
00083   460, /* ExtendedRegisters[16*16] */
00084   476, /* ExtendedRegisters[17*16] */
00085 
00086   /* MXCSR */
00087   228 /* ExtendedRegisters[24] */
00088 };
00089 
00090 #define I386_WINDOWS_SIZEOF_GREGSET 716
00091 
00092 /* Return the appropriate register set for the core section identified
00093    by SECT_NAME and SECT_SIZE.  */
00094 
00095 static const struct regset *
00096 i386_windows_regset_from_core_section (struct gdbarch *gdbarch,
00097                                      const char *sect_name, size_t sect_size)
00098 {
00099   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
00100 
00101   if (strcmp (sect_name, ".reg") == 0
00102       && sect_size == I386_WINDOWS_SIZEOF_GREGSET)
00103     {
00104       if (tdep->gregset == NULL)
00105         tdep->gregset = regset_alloc (gdbarch, i386_supply_gregset,
00106                                       i386_collect_gregset);
00107       return tdep->gregset;
00108     }
00109 
00110   return NULL;
00111 }
00112 
00113 struct cpms_data
00114 {
00115   struct gdbarch *gdbarch;
00116   struct obstack *obstack;
00117   int module_count;
00118 };
00119 
00120 static void
00121 core_process_module_section (bfd *abfd, asection *sect, void *obj)
00122 {
00123   struct cpms_data *data = obj;
00124   enum bfd_endian byte_order = gdbarch_byte_order (data->gdbarch);
00125 
00126   char *module_name;
00127   size_t module_name_size;
00128   CORE_ADDR base_addr;
00129 
00130   gdb_byte *buf = NULL;
00131 
00132   if (strncmp (sect->name, ".module", 7) != 0)
00133     return;
00134 
00135   buf = xmalloc (bfd_get_section_size (sect) + 1);
00136   if (!buf)
00137     {
00138       printf_unfiltered ("memory allocation failed for %s\n", sect->name);
00139       goto out;
00140     }
00141   if (!bfd_get_section_contents (abfd, sect,
00142                                  buf, 0, bfd_get_section_size (sect)))
00143     goto out;
00144 
00145 
00146 
00147   /* A DWORD (data_type) followed by struct windows_core_module_info.  */
00148 
00149   base_addr =
00150     extract_unsigned_integer (buf + 4, 4, byte_order);
00151 
00152   module_name_size =
00153     extract_unsigned_integer (buf + 8, 4, byte_order);
00154 
00155   if (12 + module_name_size > bfd_get_section_size (sect))
00156     goto out;
00157   module_name = (char *) buf + 12;
00158 
00159   /* The first module is the .exe itself.  */
00160   if (data->module_count != 0)
00161     windows_xfer_shared_library (module_name, base_addr,
00162                                  data->gdbarch, data->obstack);
00163   data->module_count++;
00164 
00165 out:
00166   if (buf)
00167     xfree (buf);
00168   return;
00169 }
00170 
00171 static LONGEST
00172 windows_core_xfer_shared_libraries (struct gdbarch *gdbarch,
00173                                   gdb_byte *readbuf,
00174                                   ULONGEST offset, LONGEST len)
00175 {
00176   struct obstack obstack;
00177   const char *buf;
00178   LONGEST len_avail;
00179   struct cpms_data data = { gdbarch, &obstack, 0 };
00180 
00181   obstack_init (&obstack);
00182   obstack_grow_str (&obstack, "<library-list>\n");
00183   bfd_map_over_sections (core_bfd,
00184                          core_process_module_section,
00185                          &data);
00186   obstack_grow_str0 (&obstack, "</library-list>\n");
00187 
00188   buf = obstack_finish (&obstack);
00189   len_avail = strlen (buf);
00190   if (offset >= len_avail)
00191     return 0;
00192 
00193   if (len > len_avail - offset)
00194     len = len_avail - offset;
00195   memcpy (readbuf, buf + offset, len);
00196 
00197   obstack_free (&obstack, NULL);
00198   return len;
00199 }
00200 
00201 /* This is how we want PTIDs from core files to be printed.  */
00202 
00203 static char *
00204 i386_windows_core_pid_to_str (struct gdbarch *gdbarch, ptid_t ptid)
00205 {
00206   static char buf[80];
00207 
00208   if (ptid_get_lwp (ptid) != 0)
00209     {
00210       snprintf (buf, sizeof (buf), "Thread 0x%lx", ptid_get_lwp (ptid));
00211       return buf;
00212     }
00213 
00214   return normal_pid_to_str (ptid);
00215 }
00216 
00217 static CORE_ADDR
00218 i386_cygwin_skip_trampoline_code (struct frame_info *frame, CORE_ADDR pc)
00219 {
00220   return i386_pe_skip_trampoline_code (frame, pc, NULL);
00221 }
00222 
00223 static const char *
00224 i386_cygwin_auto_wide_charset (void)
00225 {
00226   return "UTF-16";
00227 }
00228 
00229 static void
00230 i386_cygwin_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
00231 {
00232   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
00233 
00234   windows_init_abi (info, gdbarch);
00235 
00236   set_gdbarch_skip_trampoline_code (gdbarch, i386_cygwin_skip_trampoline_code);
00237 
00238   set_gdbarch_skip_main_prologue (gdbarch, i386_skip_main_prologue);
00239 
00240   tdep->struct_return = reg_struct_return;
00241 
00242   tdep->gregset_reg_offset = i386_windows_gregset_reg_offset;
00243   tdep->gregset_num_regs = ARRAY_SIZE (i386_windows_gregset_reg_offset);
00244   tdep->sizeof_gregset = I386_WINDOWS_SIZEOF_GREGSET;
00245 
00246   /* Core file support.  */
00247   set_gdbarch_regset_from_core_section
00248     (gdbarch, i386_windows_regset_from_core_section);
00249   set_gdbarch_core_xfer_shared_libraries
00250     (gdbarch, windows_core_xfer_shared_libraries);
00251   set_gdbarch_core_pid_to_str (gdbarch, i386_windows_core_pid_to_str);
00252 
00253   set_gdbarch_auto_wide_charset (gdbarch, i386_cygwin_auto_wide_charset);
00254 }
00255 
00256 static enum gdb_osabi
00257 i386_cygwin_osabi_sniffer (bfd *abfd)
00258 {
00259   char *target_name = bfd_get_target (abfd);
00260 
00261   if (strcmp (target_name, "pei-i386") == 0)
00262     return GDB_OSABI_CYGWIN;
00263 
00264   /* Cygwin uses elf core dumps.  Do not claim all ELF executables,
00265      check whether there is a .reg section of proper size.  */
00266   if (strcmp (target_name, "elf32-i386") == 0)
00267     {
00268       asection *section = bfd_get_section_by_name (abfd, ".reg");
00269       if (section
00270           && bfd_section_size (abfd, section) == I386_WINDOWS_SIZEOF_GREGSET)
00271         return GDB_OSABI_CYGWIN;
00272     }
00273 
00274   return GDB_OSABI_UNKNOWN;
00275 }
00276 
00277 /* Provide a prototype to silence -Wmissing-prototypes.  */
00278 void _initialize_i386_cygwin_tdep (void);
00279 
00280 void
00281 _initialize_i386_cygwin_tdep (void)
00282 {
00283   gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_coff_flavour,
00284                                   i386_cygwin_osabi_sniffer);
00285 
00286   /* Cygwin uses elf core dumps.  */
00287   gdbarch_register_osabi_sniffer (bfd_arch_i386, bfd_target_elf_flavour,
00288                                   i386_cygwin_osabi_sniffer);
00289 
00290   gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_CYGWIN,
00291                           i386_cygwin_init_abi);
00292 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines