GDB (API)
/home/stan/gdb/src/gdb/i386obsd-tdep.c
Go to the documentation of this file.
00001 /* Target-dependent code for OpenBSD/i386.
00002 
00003    Copyright (C) 1988-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 "arch-utils.h"
00022 #include "frame.h"
00023 #include "frame-unwind.h"
00024 #include "gdbcore.h"
00025 #include "regcache.h"
00026 #include "regset.h"
00027 #include "symtab.h"
00028 #include "objfiles.h"
00029 #include "osabi.h"
00030 #include "target.h"
00031 #include "trad-frame.h"
00032 
00033 #include "gdb_assert.h"
00034 #include "gdb_string.h"
00035 
00036 #include "i386-tdep.h"
00037 #include "i387-tdep.h"
00038 #include "solib-svr4.h"
00039 #include "bsd-uthread.h"
00040 
00041 /* Support for signal handlers.  */
00042 
00043 /* Since OpenBSD 3.2, the sigtramp routine is mapped at a random page
00044    in virtual memory.  The randomness makes it somewhat tricky to
00045    detect it, but fortunately we can rely on the fact that the start
00046    of the sigtramp routine is page-aligned.  We recognize the
00047    trampoline by looking for the code that invokes the sigreturn
00048    system call.  The offset where we can find that code varies from
00049    release to release.
00050 
00051    By the way, the mapping mentioned above is read-only, so you cannot
00052    place a breakpoint in the signal trampoline.  */
00053 
00054 /* Default page size.  */
00055 static const int i386obsd_page_size = 4096;
00056 
00057 /* Offset for sigreturn(2).  */
00058 static const int i386obsd_sigreturn_offset[] = {
00059   0x0a,                         /* OpenBSD 3.2 */
00060   0x14,                         /* OpenBSD 3.6 */
00061   0x3a,                         /* OpenBSD 3.8 */
00062   -1
00063 };
00064 
00065 /* Return whether THIS_FRAME corresponds to an OpenBSD sigtramp
00066    routine.  */
00067 
00068 static int
00069 i386obsd_sigtramp_p (struct frame_info *this_frame)
00070 {
00071   CORE_ADDR pc = get_frame_pc (this_frame);
00072   CORE_ADDR start_pc = (pc & ~(i386obsd_page_size - 1));
00073   /* The call sequence invoking sigreturn(2).  */
00074   const gdb_byte sigreturn[] =
00075   {
00076     0xb8,
00077     0x67, 0x00, 0x00, 0x00,     /* movl $SYS_sigreturn, %eax */
00078     0xcd, 0x80                  /* int $0x80 */
00079   };
00080   size_t buflen = sizeof sigreturn;
00081   const int *offset;
00082   gdb_byte *buf;
00083   const char *name;
00084 
00085   /* If the function has a valid symbol name, it isn't a
00086      trampoline.  */
00087   find_pc_partial_function (pc, &name, NULL, NULL);
00088   if (name != NULL)
00089     return 0;
00090 
00091   /* If the function lives in a valid section (even without a starting
00092      point) it isn't a trampoline.  */
00093   if (find_pc_section (pc) != NULL)
00094     return 0;
00095 
00096   /* Allocate buffer.  */
00097   buf = alloca (buflen);
00098 
00099   /* Loop over all offsets.  */
00100   for (offset = i386obsd_sigreturn_offset; *offset != -1; offset++)
00101     {
00102       /* If we can't read the instructions, return zero.  */
00103       if (!safe_frame_unwind_memory (this_frame, start_pc + *offset,
00104                                      buf, buflen))
00105         return 0;
00106 
00107       /* Check for sigreturn(2).  */
00108       if (memcmp (buf, sigreturn, buflen) == 0)
00109         return 1;
00110     }
00111 
00112   return 0;
00113 }
00114 
00115 /* Mapping between the general-purpose registers in `struct reg'
00116    format and GDB's register cache layout.  */
00117 
00118 /* From <machine/reg.h>.  */
00119 static int i386obsd_r_reg_offset[] =
00120 {
00121   0 * 4,                        /* %eax */
00122   1 * 4,                        /* %ecx */
00123   2 * 4,                        /* %edx */
00124   3 * 4,                        /* %ebx */
00125   4 * 4,                        /* %esp */
00126   5 * 4,                        /* %ebp */
00127   6 * 4,                        /* %esi */
00128   7 * 4,                        /* %edi */
00129   8 * 4,                        /* %eip */
00130   9 * 4,                        /* %eflags */
00131   10 * 4,                       /* %cs */
00132   11 * 4,                       /* %ss */
00133   12 * 4,                       /* %ds */
00134   13 * 4,                       /* %es */
00135   14 * 4,                       /* %fs */
00136   15 * 4                        /* %gs */
00137 };
00138 
00139 static void
00140 i386obsd_aout_supply_regset (const struct regset *regset,
00141                              struct regcache *regcache, int regnum,
00142                              const void *regs, size_t len)
00143 {
00144   const struct gdbarch_tdep *tdep = gdbarch_tdep (regset->arch);
00145   const gdb_byte *gregs = regs;
00146 
00147   gdb_assert (len >= tdep->sizeof_gregset + I387_SIZEOF_FSAVE);
00148 
00149   i386_supply_gregset (regset, regcache, regnum, regs, tdep->sizeof_gregset);
00150   i387_supply_fsave (regcache, regnum, gregs + tdep->sizeof_gregset);
00151 }
00152 
00153 static const struct regset *
00154 i386obsd_aout_regset_from_core_section (struct gdbarch *gdbarch,
00155                                         const char *sect_name,
00156                                         size_t sect_size)
00157 {
00158   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
00159 
00160   /* OpenBSD a.out core dumps don't use seperate register sets for the
00161      general-purpose and floating-point registers.  */
00162 
00163   if (strcmp (sect_name, ".reg") == 0
00164       && sect_size >= tdep->sizeof_gregset + I387_SIZEOF_FSAVE)
00165     {
00166       if (tdep->gregset == NULL)
00167         tdep->gregset =
00168           regset_alloc (gdbarch, i386obsd_aout_supply_regset, NULL);
00169       return tdep->gregset;
00170     }
00171 
00172   return NULL;
00173 }
00174 
00175 
00176 /* Sigtramp routine location for OpenBSD 3.1 and earlier releases.  */
00177 CORE_ADDR i386obsd_sigtramp_start_addr = 0xbfbfdf20;
00178 CORE_ADDR i386obsd_sigtramp_end_addr = 0xbfbfdff0;
00179 
00180 /* From <machine/signal.h>.  */
00181 int i386obsd_sc_reg_offset[I386_NUM_GREGS] =
00182 {
00183   10 * 4,                       /* %eax */
00184   9 * 4,                        /* %ecx */
00185   8 * 4,                        /* %edx */
00186   7 * 4,                        /* %ebx */
00187   14 * 4,                       /* %esp */
00188   6 * 4,                        /* %ebp */
00189   5 * 4,                        /* %esi */
00190   4 * 4,                        /* %edi */
00191   11 * 4,                       /* %eip */
00192   13 * 4,                       /* %eflags */
00193   12 * 4,                       /* %cs */
00194   15 * 4,                       /* %ss */
00195   3 * 4,                        /* %ds */
00196   2 * 4,                        /* %es */
00197   1 * 4,                        /* %fs */
00198   0 * 4                         /* %gs */
00199 };
00200 
00201 /* From /usr/src/lib/libpthread/arch/i386/uthread_machdep.c.  */
00202 static int i386obsd_uthread_reg_offset[] =
00203 {
00204   11 * 4,                       /* %eax */
00205   10 * 4,                       /* %ecx */
00206   9 * 4,                        /* %edx */
00207   8 * 4,                        /* %ebx */
00208   -1,                           /* %esp */
00209   6 * 4,                        /* %ebp */
00210   5 * 4,                        /* %esi */
00211   4 * 4,                        /* %edi */
00212   12 * 4,                       /* %eip */
00213   -1,                           /* %eflags */
00214   13 * 4,                       /* %cs */
00215   -1,                           /* %ss */
00216   3 * 4,                        /* %ds */
00217   2 * 4,                        /* %es */
00218   1 * 4,                        /* %fs */
00219   0 * 4                         /* %gs */
00220 };
00221 
00222 /* Offset within the thread structure where we can find the saved
00223    stack pointer (%esp).  */
00224 #define I386OBSD_UTHREAD_ESP_OFFSET     176
00225 
00226 static void
00227 i386obsd_supply_uthread (struct regcache *regcache,
00228                          int regnum, CORE_ADDR addr)
00229 {
00230   struct gdbarch *gdbarch = get_regcache_arch (regcache);
00231   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
00232   CORE_ADDR sp_addr = addr + I386OBSD_UTHREAD_ESP_OFFSET;
00233   CORE_ADDR sp = 0;
00234   gdb_byte buf[4];
00235   int i;
00236 
00237   gdb_assert (regnum >= -1);
00238 
00239   if (regnum == -1 || regnum == I386_ESP_REGNUM)
00240     {
00241       int offset;
00242 
00243       /* Fetch stack pointer from thread structure.  */
00244       sp = read_memory_unsigned_integer (sp_addr, 4, byte_order);
00245 
00246       /* Adjust the stack pointer such that it looks as if we just
00247          returned from _thread_machdep_switch.  */
00248       offset = i386obsd_uthread_reg_offset[I386_EIP_REGNUM] + 4;
00249       store_unsigned_integer (buf, 4, byte_order, sp + offset);
00250       regcache_raw_supply (regcache, I386_ESP_REGNUM, buf);
00251     }
00252 
00253   for (i = 0; i < ARRAY_SIZE (i386obsd_uthread_reg_offset); i++)
00254     {
00255       if (i386obsd_uthread_reg_offset[i] != -1
00256           && (regnum == -1 || regnum == i))
00257         {
00258           /* Fetch stack pointer from thread structure (if we didn't
00259              do so already).  */
00260           if (sp == 0)
00261             sp = read_memory_unsigned_integer (sp_addr, 4, byte_order);
00262 
00263           /* Read the saved register from the stack frame.  */
00264           read_memory (sp + i386obsd_uthread_reg_offset[i], buf, 4);
00265           regcache_raw_supply (regcache, i, buf);
00266         }
00267     }
00268 }
00269 
00270 static void
00271 i386obsd_collect_uthread (const struct regcache *regcache,
00272                           int regnum, CORE_ADDR addr)
00273 {
00274   struct gdbarch *gdbarch = get_regcache_arch (regcache);
00275   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
00276   CORE_ADDR sp_addr = addr + I386OBSD_UTHREAD_ESP_OFFSET;
00277   CORE_ADDR sp = 0;
00278   gdb_byte buf[4];
00279   int i;
00280 
00281   gdb_assert (regnum >= -1);
00282 
00283   if (regnum == -1 || regnum == I386_ESP_REGNUM)
00284     {
00285       int offset;
00286 
00287       /* Calculate the stack pointer (frame pointer) that will be
00288          stored into the thread structure.  */
00289       offset = i386obsd_uthread_reg_offset[I386_EIP_REGNUM] + 4;
00290       regcache_raw_collect (regcache, I386_ESP_REGNUM, buf);
00291       sp = extract_unsigned_integer (buf, 4, byte_order) - offset;
00292 
00293       /* Store the stack pointer.  */
00294       write_memory_unsigned_integer (sp_addr, 4, byte_order, sp);
00295 
00296       /* The stack pointer was (potentially) modified.  Make sure we
00297          build a proper stack frame.  */
00298       regnum = -1;
00299     }
00300 
00301   for (i = 0; i < ARRAY_SIZE (i386obsd_uthread_reg_offset); i++)
00302     {
00303       if (i386obsd_uthread_reg_offset[i] != -1
00304           && (regnum == -1 || regnum == i))
00305         {
00306           /* Fetch stack pointer from thread structure (if we didn't
00307              calculate it already).  */
00308           if (sp == 0)
00309             sp = read_memory_unsigned_integer (sp_addr, 4, byte_order);
00310 
00311           /* Write the register into the stack frame.  */
00312           regcache_raw_collect (regcache, i, buf);
00313           write_memory (sp + i386obsd_uthread_reg_offset[i], buf, 4);
00314         }
00315     }
00316 }
00317 
00318 /* Kernel debugging support.  */
00319 
00320 /* From <machine/frame.h>.  Note that %esp and %ess are only saved in
00321    a trap frame when entering the kernel from user space.  */
00322 static int i386obsd_tf_reg_offset[] =
00323 {
00324   10 * 4,                       /* %eax */
00325   9 * 4,                        /* %ecx */
00326   8 * 4,                        /* %edx */
00327   7 * 4,                        /* %ebx */
00328   -1,                           /* %esp */
00329   6 * 4,                        /* %ebp */
00330   5 * 4,                        /* %esi */
00331   4 * 4,                        /* %edi */
00332   13 * 4,                       /* %eip */
00333   15 * 4,                       /* %eflags */
00334   14 * 4,                       /* %cs */
00335   -1,                           /* %ss */
00336   3 * 4,                        /* %ds */
00337   2 * 4,                        /* %es */
00338   0 * 4,                        /* %fs */
00339   1 * 4                         /* %gs */
00340 };
00341 
00342 static struct trad_frame_cache *
00343 i386obsd_trapframe_cache (struct frame_info *this_frame, void **this_cache)
00344 {
00345   struct gdbarch *gdbarch = get_frame_arch (this_frame);
00346   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
00347   struct trad_frame_cache *cache;
00348   CORE_ADDR func, sp, addr;
00349   ULONGEST cs;
00350   const char *name;
00351   int i;
00352 
00353   if (*this_cache)
00354     return *this_cache;
00355 
00356   cache = trad_frame_cache_zalloc (this_frame);
00357   *this_cache = cache;
00358 
00359   func = get_frame_func (this_frame);
00360   sp = get_frame_register_unsigned (this_frame, I386_ESP_REGNUM);
00361 
00362   find_pc_partial_function (func, &name, NULL, NULL);
00363   if (name && strncmp (name, "Xintr", 5) == 0)
00364     addr = sp + 8;              /* It's an interrupt frame.  */
00365   else
00366     addr = sp;
00367 
00368   for (i = 0; i < ARRAY_SIZE (i386obsd_tf_reg_offset); i++)
00369     if (i386obsd_tf_reg_offset[i] != -1)
00370       trad_frame_set_reg_addr (cache, i, addr + i386obsd_tf_reg_offset[i]);
00371 
00372   /* Read %cs from trap frame.  */
00373   addr += i386obsd_tf_reg_offset[I386_CS_REGNUM];
00374   cs = read_memory_unsigned_integer (addr, 4, byte_order);
00375   if ((cs & I386_SEL_RPL) == I386_SEL_UPL)
00376     {
00377       /* Trap from user space; terminate backtrace.  */
00378       trad_frame_set_id (cache, outer_frame_id);
00379     }
00380   else
00381     {
00382       /* Construct the frame ID using the function start.  */
00383       trad_frame_set_id (cache, frame_id_build (sp + 8, func));
00384     }
00385 
00386   return cache;
00387 }
00388 
00389 static void
00390 i386obsd_trapframe_this_id (struct frame_info *this_frame,
00391                             void **this_cache, struct frame_id *this_id)
00392 {
00393   struct trad_frame_cache *cache =
00394     i386obsd_trapframe_cache (this_frame, this_cache);
00395   
00396   trad_frame_get_id (cache, this_id);
00397 }
00398 
00399 static struct value *
00400 i386obsd_trapframe_prev_register (struct frame_info *this_frame,
00401                                   void **this_cache, int regnum)
00402 {
00403   struct trad_frame_cache *cache =
00404     i386obsd_trapframe_cache (this_frame, this_cache);
00405 
00406   return trad_frame_get_register (cache, this_frame, regnum);
00407 }
00408 
00409 static int
00410 i386obsd_trapframe_sniffer (const struct frame_unwind *self,
00411                             struct frame_info *this_frame,
00412                             void **this_prologue_cache)
00413 {
00414   ULONGEST cs;
00415   const char *name;
00416 
00417   /* Check Current Privilege Level and bail out if we're not executing
00418      in kernel space.  */
00419   cs = get_frame_register_unsigned (this_frame, I386_CS_REGNUM);
00420   if ((cs & I386_SEL_RPL) == I386_SEL_UPL)
00421     return 0;
00422 
00423   find_pc_partial_function (get_frame_pc (this_frame), &name, NULL, NULL);
00424   return (name && (strcmp (name, "calltrap") == 0
00425                    || strcmp (name, "syscall1") == 0
00426                    || strncmp (name, "Xintr", 5) == 0
00427                    || strncmp (name, "Xsoft", 5) == 0));
00428 }
00429 
00430 static const struct frame_unwind i386obsd_trapframe_unwind = {
00431   /* FIXME: kettenis/20051219: This really is more like an interrupt
00432      frame, but SIGTRAMP_FRAME would print <signal handler called>,
00433      which really is not what we want here.  */
00434   NORMAL_FRAME,
00435   default_frame_unwind_stop_reason,
00436   i386obsd_trapframe_this_id,
00437   i386obsd_trapframe_prev_register,
00438   NULL,
00439   i386obsd_trapframe_sniffer
00440 };
00441 
00442 
00443 static void 
00444 i386obsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
00445 {
00446   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
00447 
00448   /* Obviously OpenBSD is BSD-based.  */
00449   i386bsd_init_abi (info, gdbarch);
00450 
00451   /* OpenBSD has a different `struct reg'.  */
00452   tdep->gregset_reg_offset = i386obsd_r_reg_offset;
00453   tdep->gregset_num_regs = ARRAY_SIZE (i386obsd_r_reg_offset);
00454   tdep->sizeof_gregset = 16 * 4;
00455 
00456   /* OpenBSD uses -freg-struct-return by default.  */
00457   tdep->struct_return = reg_struct_return;
00458 
00459   /* OpenBSD uses a different memory layout.  */
00460   tdep->sigtramp_start = i386obsd_sigtramp_start_addr;
00461   tdep->sigtramp_end = i386obsd_sigtramp_end_addr;
00462   tdep->sigtramp_p = i386obsd_sigtramp_p;
00463 
00464   /* OpenBSD has a `struct sigcontext' that's different from the
00465      original 4.3 BSD.  */
00466   tdep->sc_reg_offset = i386obsd_sc_reg_offset;
00467   tdep->sc_num_regs = ARRAY_SIZE (i386obsd_sc_reg_offset);
00468 
00469   /* OpenBSD provides a user-level threads implementation.  */
00470   bsd_uthread_set_supply_uthread (gdbarch, i386obsd_supply_uthread);
00471   bsd_uthread_set_collect_uthread (gdbarch, i386obsd_collect_uthread);
00472 
00473   /* Unwind kernel trap frames correctly.  */
00474   frame_unwind_prepend_unwinder (gdbarch, &i386obsd_trapframe_unwind);
00475 }
00476 
00477 /* OpenBSD a.out.  */
00478 
00479 static void
00480 i386obsd_aout_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
00481 {
00482   i386obsd_init_abi (info, gdbarch);
00483 
00484   /* OpenBSD a.out has a single register set.  */
00485   set_gdbarch_regset_from_core_section
00486     (gdbarch, i386obsd_aout_regset_from_core_section);
00487 }
00488 
00489 /* OpenBSD ELF.  */
00490 
00491 static void
00492 i386obsd_elf_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
00493 {
00494   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
00495 
00496   /* It's still OpenBSD.  */
00497   i386obsd_init_abi (info, gdbarch);
00498 
00499   /* But ELF-based.  */
00500   i386_elf_init_abi (info, gdbarch);
00501 
00502   /* OpenBSD ELF uses SVR4-style shared libraries.  */
00503   set_solib_svr4_fetch_link_map_offsets
00504     (gdbarch, svr4_ilp32_fetch_link_map_offsets);
00505 }
00506 
00507 
00508 /* Provide a prototype to silence -Wmissing-prototypes.  */
00509 void _initialize_i386obsd_tdep (void);
00510 
00511 void
00512 _initialize_i386obsd_tdep (void)
00513 {
00514   /* FIXME: kettenis/20021020: Since OpenBSD/i386 binaries are
00515      indistingushable from NetBSD/i386 a.out binaries, building a GDB
00516      that should support both these targets will probably not work as
00517      expected.  */
00518 #define GDB_OSABI_OPENBSD_AOUT GDB_OSABI_NETBSD_AOUT
00519 
00520   gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_OPENBSD_AOUT,
00521                           i386obsd_aout_init_abi);
00522   gdbarch_register_osabi (bfd_arch_i386, 0, GDB_OSABI_OPENBSD_ELF,
00523                           i386obsd_elf_init_abi);
00524 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Defines