[BACK]Return to bsd-kvm.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / external / gpl3 / gdb / dist / gdb

Annotation of src/external/gpl3/gdb/dist/gdb/bsd-kvm.c, Revision 1.7

1.1       christos    1: /* BSD Kernel Data Access Library (libkvm) interface.
                      2:
1.7     ! christos    3:    Copyright (C) 2004-2015 Free Software Foundation, Inc.
1.1       christos    4:
                      5:    This file is part of GDB.
                      6:
                      7:    This program is free software; you can redistribute it and/or modify
                      8:    it under the terms of the GNU General Public License as published by
                      9:    the Free Software Foundation; either version 3 of the License, or
                     10:    (at your option) any later version.
                     11:
                     12:    This program is distributed in the hope that it will be useful,
                     13:    but WITHOUT ANY WARRANTY; without even the implied warranty of
                     14:    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     15:    GNU General Public License for more details.
                     16:
                     17:    You should have received a copy of the GNU General Public License
                     18:    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
                     19:
                     20: #include "defs.h"
                     21: #include "cli/cli-cmds.h"
                     22: #include "command.h"
                     23: #include "frame.h"
                     24: #include "regcache.h"
                     25: #include "target.h"
                     26: #include "value.h"
                     27: #include "gdbcore.h"           /* for get_exec_file */
                     28: #include "gdbthread.h"
                     29:
                     30: #include <fcntl.h>
                     31: #include <kvm.h>
                     32: #ifdef HAVE_NLIST_H
                     33: #include <nlist.h>
                     34: #endif
                     35: #include <paths.h>
                     36: #include "readline/readline.h"
                     37: #include <sys/param.h>
1.3       christos   38: #define _KMEMUSER
1.1       christos   39: #include <sys/proc.h>
                     40: #include <sys/user.h>
                     41:
                     42: #include "bsd-kvm.h"
                     43:
                     44: /* Kernel memory device file.  */
                     45: static const char *bsd_kvm_corefile;
                     46:
                     47: /* Kernel memory interface descriptor.  */
                     48: static kvm_t *core_kd;
                     49:
                     50: /* Address of process control block.  */
                     51: static struct pcb *bsd_kvm_paddr;
                     52:
                     53: /* Pointer to architecture-specific function that reconstructs the
                     54:    register state from PCB and supplies it to REGCACHE.  */
                     55: static int (*bsd_kvm_supply_pcb)(struct regcache *regcache, struct pcb *pcb);
                     56:
                     57: /* Target ops for libkvm interface.  */
                     58: static struct target_ops bsd_kvm_ops;
                     59:
                     60: /* This is the ptid we use while we're connected to kvm.  The kvm
                     61:    target currently doesn't export any view of the running processes,
                     62:    so this represents the kernel task.  */
                     63: static ptid_t bsd_kvm_ptid;
                     64:
                     65: static void
1.7     ! christos   66: bsd_kvm_open (const char *arg, int from_tty)
1.1       christos   67: {
                     68:   char errbuf[_POSIX2_LINE_MAX];
                     69:   char *execfile = NULL;
                     70:   kvm_t *temp_kd;
1.4       christos   71:   struct inferior *inf;
1.7     ! christos   72:   char *filename = NULL;
1.1       christos   73:
                     74:   target_preopen (from_tty);
                     75:
1.7     ! christos   76:   if (arg)
1.1       christos   77:     {
                     78:       char *temp;
                     79:
1.7     ! christos   80:       filename = tilde_expand (arg);
1.1       christos   81:       if (filename[0] != '/')
                     82:        {
                     83:          temp = concat (current_directory, "/", filename, (char *)NULL);
                     84:          xfree (filename);
                     85:          filename = temp;
                     86:        }
                     87:     }
                     88:
                     89:   execfile = get_exec_file (0);
                     90:   temp_kd = kvm_openfiles (execfile, filename, NULL,
                     91:                           write_files ? O_RDWR : O_RDONLY, errbuf);
                     92:   if (temp_kd == NULL)
                     93:     error (("%s"), errbuf);
                     94:
                     95:   bsd_kvm_corefile = filename;
                     96:   unpush_target (&bsd_kvm_ops);
                     97:   core_kd = temp_kd;
                     98:   push_target (&bsd_kvm_ops);
                     99:
1.6       christos  100:   inf = add_inferior_silent (ptid_get_pid(bsd_kvm_ptid));
1.4       christos  101:   inf->aspace = maybe_new_address_space ();
                    102:   inf->pspace = add_program_space (inf->aspace);
                    103:
1.1       christos  104:   add_thread_silent (bsd_kvm_ptid);
                    105:   inferior_ptid = bsd_kvm_ptid;
                    106:
                    107:   target_fetch_registers (get_current_regcache (), -1);
                    108:
                    109:   reinit_frame_cache ();
1.6       christos  110:   print_stack_frame (get_selected_frame (NULL), 0, SRC_AND_LOC, 1);
1.1       christos  111: }
                    112:
                    113: static void
1.7     ! christos  114: bsd_kvm_close (struct target_ops *self)
1.1       christos  115: {
                    116:   if (core_kd)
                    117:     {
                    118:       if (kvm_close (core_kd) == -1)
                    119:        warning (("%s"), kvm_geterr(core_kd));
                    120:       core_kd = NULL;
                    121:     }
                    122:
                    123:   inferior_ptid = null_ptid;
                    124:   delete_thread_silent (bsd_kvm_ptid);
                    125: }
                    126:
                    127: static LONGEST
                    128: bsd_kvm_xfer_memory (CORE_ADDR addr, ULONGEST len,
                    129:                     gdb_byte *readbuf, const gdb_byte *writebuf)
                    130: {
                    131:   ssize_t nbytes = len;
                    132:
                    133:   if (readbuf)
                    134:     nbytes = kvm_read (core_kd, addr, readbuf, nbytes);
                    135:   if (writebuf && nbytes > 0)
                    136:     nbytes = kvm_write (core_kd, addr, writebuf, nbytes);
                    137:   return nbytes;
                    138: }
                    139:
1.7     ! christos  140: static enum target_xfer_status
1.1       christos  141: bsd_kvm_xfer_partial (struct target_ops *ops, enum target_object object,
                    142:                      const char *annex, gdb_byte *readbuf,
                    143:                      const gdb_byte *writebuf,
1.7     ! christos  144:                      ULONGEST offset, ULONGEST len, ULONGEST *xfered_len)
1.1       christos  145: {
                    146:   switch (object)
                    147:     {
                    148:     case TARGET_OBJECT_MEMORY:
1.7     ! christos  149:       {
        !           150:        LONGEST ret = bsd_kvm_xfer_memory (offset, len, readbuf, writebuf);
        !           151:
        !           152:        if (ret < 0)
        !           153:          return TARGET_XFER_E_IO;
        !           154:        else if (ret == 0)
        !           155:          return TARGET_XFER_EOF;
        !           156:        else
        !           157:          {
        !           158:            *xfered_len = (ULONGEST) ret;
        !           159:            return TARGET_XFER_OK;
        !           160:          }
        !           161:       }
1.1       christos  162:
                    163:     default:
1.7     ! christos  164:       return TARGET_XFER_E_IO;
1.1       christos  165:     }
                    166: }
                    167:
                    168: static void
                    169: bsd_kvm_files_info (struct target_ops *ops)
                    170: {
                    171:   if (bsd_kvm_corefile && strcmp (bsd_kvm_corefile, _PATH_MEM) != 0)
                    172:     printf_filtered (_("\tUsing the kernel crash dump %s.\n"),
                    173:                     bsd_kvm_corefile);
                    174:   else
                    175:     printf_filtered (_("\tUsing the currently running kernel.\n"));
                    176: }
                    177:
                    178: /* Fetch process control block at address PADDR.  */
                    179:
                    180: static int
                    181: bsd_kvm_fetch_pcb (struct regcache *regcache, struct pcb *paddr)
                    182: {
                    183:   struct pcb pcb;
                    184:
                    185:   if (kvm_read (core_kd, (unsigned long) paddr, &pcb, sizeof pcb) == -1)
                    186:     error (("%s"), kvm_geterr (core_kd));
                    187:
                    188:   gdb_assert (bsd_kvm_supply_pcb);
                    189:   return bsd_kvm_supply_pcb (regcache, &pcb);
                    190: }
                    191:
                    192: static void
                    193: bsd_kvm_fetch_registers (struct target_ops *ops,
                    194:                         struct regcache *regcache, int regnum)
                    195: {
                    196:   struct nlist nl[2];
                    197:
                    198:   if (bsd_kvm_paddr)
                    199:     {
                    200:       bsd_kvm_fetch_pcb (regcache, bsd_kvm_paddr);
                    201:       return;
                    202:     }
                    203:
                    204:   /* On dumping core, BSD kernels store the faulting context (PCB)
                    205:      in the variable "dumppcb".  */
                    206:   memset (nl, 0, sizeof nl);
                    207:   nl[0].n_name = "_dumppcb";
                    208:
                    209:   if (kvm_nlist (core_kd, nl) == -1)
                    210:     error (("%s"), kvm_geterr (core_kd));
                    211:
                    212:   if (nl[0].n_value != 0)
                    213:     {
                    214:       /* Found dumppcb.  If it contains a valid context, return
                    215:         immediately.  */
                    216:       if (bsd_kvm_fetch_pcb (regcache, (struct pcb *) nl[0].n_value))
                    217:        return;
                    218:     }
                    219:
                    220:   /* Traditional BSD kernels have a process proc0 that should always
                    221:      be present.  The address of proc0's PCB is stored in the variable
                    222:      "proc0paddr".  */
                    223:
                    224:   memset (nl, 0, sizeof nl);
                    225:   nl[0].n_name = "_proc0paddr";
                    226:
                    227:   if (kvm_nlist (core_kd, nl) == -1)
                    228:     error (("%s"), kvm_geterr (core_kd));
                    229:
                    230:   if (nl[0].n_value != 0)
                    231:     {
                    232:       struct pcb *paddr;
                    233:
                    234:       /* Found proc0paddr.  */
                    235:       if (kvm_read (core_kd, nl[0].n_value, &paddr, sizeof paddr) == -1)
                    236:        error (("%s"), kvm_geterr (core_kd));
                    237:
                    238:       bsd_kvm_fetch_pcb (regcache, paddr);
                    239:       return;
                    240:     }
                    241:
1.2       christos  242: #if 1 /* TODO: HAVE_STRUCT_LWP_L_ADDR */
                    243:   memset (nl, 0, sizeof nl);
                    244:   nl[0].n_name = "_lwp0";
                    245:
                    246:   if (kvm_nlist (core_kd, nl) == -1)
                    247:     error (("%s"), kvm_geterr (core_kd));
                    248:
                    249:   if (nl[0].n_value != 0)
                    250:     {
                    251:       struct pcb *paddr;
                    252:
                    253:       /* Found lwp0.  */
                    254:       nl[0].n_value += offsetof (struct lwp, l_addr);
                    255:       if (kvm_read (core_kd, nl[0].n_value, &paddr, sizeof paddr) == -1)
                    256:        error (("%s"), kvm_geterr (core_kd));
                    257:
1.3       christos  258:       bsd_kvm_fetch_pcb (regcache, paddr);
1.2       christos  259:       return;
                    260:     }
                    261: #endif
                    262:
1.1       christos  263: #ifdef HAVE_STRUCT_THREAD_TD_PCB
                    264:   /* In FreeBSD kernels for 5.0-RELEASE and later, the PCB no longer
                    265:      lives in `struct proc' but in `struct thread'.  The `struct
                    266:      thread' for the initial thread for proc0 can be found in the
                    267:      variable "thread0".  */
                    268:
                    269:   memset (nl, 0, sizeof nl);
                    270:   nl[0].n_name = "_thread0";
                    271:
                    272:   if (kvm_nlist (core_kd, nl) == -1)
                    273:     error (("%s"), kvm_geterr (core_kd));
                    274:
                    275:   if (nl[0].n_value != 0)
                    276:     {
                    277:       struct pcb *paddr;
                    278:
                    279:       /* Found thread0.  */
                    280:       nl[0].n_value += offsetof (struct thread, td_pcb);
                    281:       if (kvm_read (core_kd, nl[0].n_value, &paddr, sizeof paddr) == -1)
                    282:        error (("%s"), kvm_geterr (core_kd));
                    283:
                    284:       bsd_kvm_fetch_pcb (regcache, paddr);
                    285:       return;
                    286:     }
                    287: #endif
                    288:
                    289:   /* i18n: PCB == "Process Control Block".  */
                    290:   error (_("Cannot find a valid PCB"));
                    291: }
                    292: 
                    293:
                    294: /* Kernel memory interface commands.  */
                    295: struct cmd_list_element *bsd_kvm_cmdlist;
                    296:
                    297: static void
                    298: bsd_kvm_cmd (char *arg, int fromtty)
                    299: {
                    300:   /* ??? Should this become an alias for "target kvm"?  */
                    301: }
                    302:
                    303: #ifndef HAVE_STRUCT_THREAD_TD_PCB
                    304:
                    305: static void
                    306: bsd_kvm_proc_cmd (char *arg, int fromtty)
                    307: {
                    308:   CORE_ADDR addr;
                    309:
                    310:   if (arg == NULL)
                    311:     error_no_arg (_("proc address"));
                    312:
                    313:   if (core_kd == NULL)
                    314:     error (_("No kernel memory image."));
                    315:
                    316:   addr = parse_and_eval_address (arg);
                    317: #ifdef HAVE_STRUCT_LWP
                    318:   addr += offsetof (struct lwp, l_addr);
                    319: #else
                    320:   addr += offsetof (struct proc, p_addr);
                    321: #endif
                    322:
                    323:   if (kvm_read (core_kd, addr, &bsd_kvm_paddr, sizeof bsd_kvm_paddr) == -1)
                    324:     error (("%s"), kvm_geterr (core_kd));
                    325:
                    326:   target_fetch_registers (get_current_regcache (), -1);
                    327:
                    328:   reinit_frame_cache ();
1.6       christos  329:   print_stack_frame (get_selected_frame (NULL), 0, SRC_AND_LOC, 1);
1.1       christos  330: }
                    331:
                    332: #endif
                    333:
                    334: static void
                    335: bsd_kvm_pcb_cmd (char *arg, int fromtty)
                    336: {
                    337:   if (arg == NULL)
                    338:     /* i18n: PCB == "Process Control Block".  */
                    339:     error_no_arg (_("pcb address"));
                    340:
                    341:   if (core_kd == NULL)
                    342:     error (_("No kernel memory image."));
                    343:
                    344:   bsd_kvm_paddr = (struct pcb *)(u_long) parse_and_eval_address (arg);
                    345:
                    346:   target_fetch_registers (get_current_regcache (), -1);
                    347:
                    348:   reinit_frame_cache ();
1.6       christos  349:   print_stack_frame (get_selected_frame (NULL), 0, SRC_AND_LOC, 1);
1.1       christos  350: }
                    351:
                    352: static int
                    353: bsd_kvm_thread_alive (struct target_ops *ops,
                    354:                      ptid_t ptid)
                    355: {
                    356:   return 1;
                    357: }
                    358:
                    359: static char *
                    360: bsd_kvm_pid_to_str (struct target_ops *ops, ptid_t ptid)
                    361: {
                    362:   static char buf[64];
                    363:   xsnprintf (buf, sizeof buf, "<kvm>");
                    364:   return buf;
                    365: }
                    366:
                    367: static int
                    368: bsd_kvm_return_one (struct target_ops *ops)
                    369: {
                    370:   return 1;
                    371: }
                    372:
                    373: /* Add the libkvm interface to the list of all possible targets and
                    374:    register CUPPLY_PCB as the architecture-specific process control
                    375:    block interpreter.  */
                    376:
                    377: void
                    378: bsd_kvm_add_target (int (*supply_pcb)(struct regcache *, struct pcb *))
                    379: {
                    380:   gdb_assert (bsd_kvm_supply_pcb == NULL);
                    381:   bsd_kvm_supply_pcb = supply_pcb;
                    382:
                    383:   bsd_kvm_ops.to_shortname = "kvm";
                    384:   bsd_kvm_ops.to_longname = _("Kernel memory interface");
                    385:   bsd_kvm_ops.to_doc = _("Use a kernel virtual memory image as a target.\n\
                    386: Optionally specify the filename of a core dump.");
                    387:   bsd_kvm_ops.to_open = bsd_kvm_open;
                    388:   bsd_kvm_ops.to_close = bsd_kvm_close;
                    389:   bsd_kvm_ops.to_fetch_registers = bsd_kvm_fetch_registers;
                    390:   bsd_kvm_ops.to_xfer_partial = bsd_kvm_xfer_partial;
                    391:   bsd_kvm_ops.to_files_info = bsd_kvm_files_info;
                    392:   bsd_kvm_ops.to_thread_alive = bsd_kvm_thread_alive;
                    393:   bsd_kvm_ops.to_pid_to_str = bsd_kvm_pid_to_str;
                    394:   bsd_kvm_ops.to_stratum = process_stratum;
                    395:   bsd_kvm_ops.to_has_memory = bsd_kvm_return_one;
                    396:   bsd_kvm_ops.to_has_stack = bsd_kvm_return_one;
                    397:   bsd_kvm_ops.to_has_registers = bsd_kvm_return_one;
                    398:   bsd_kvm_ops.to_magic = OPS_MAGIC;
                    399:
                    400:   add_target (&bsd_kvm_ops);
                    401:
                    402:   add_prefix_cmd ("kvm", class_obscure, bsd_kvm_cmd, _("\
                    403: Generic command for manipulating the kernel memory interface."),
                    404:                  &bsd_kvm_cmdlist, "kvm ", 0, &cmdlist);
                    405:
                    406: #ifndef HAVE_STRUCT_THREAD_TD_PCB
                    407:   add_cmd ("proc", class_obscure, bsd_kvm_proc_cmd,
                    408:           _("Set current context from proc address"), &bsd_kvm_cmdlist);
                    409: #endif
                    410:   add_cmd ("pcb", class_obscure, bsd_kvm_pcb_cmd,
                    411:           /* i18n: PCB == "Process Control Block".  */
                    412:           _("Set current context from pcb address"), &bsd_kvm_cmdlist);
                    413:
                    414:   /* Some notes on the ptid usage on this target.
                    415:
                    416:      The pid field represents the kvm inferior instance.  Currently,
                    417:      we don't support multiple kvm inferiors, but we start at 1
                    418:      anyway.  The lwp field is set to != 0, in case the core wants to
                    419:      refer to the whole kvm inferior with ptid(1,0,0).
                    420:
                    421:      If kvm is made to export running processes as gdb threads,
                    422:      the following form can be used:
                    423:      ptid (1, 1, 0) -> kvm inferior 1, in kernel
                    424:      ptid (1, 1, 1) -> kvm inferior 1, process 1
                    425:      ptid (1, 1, 2) -> kvm inferior 1, process 2
                    426:      ptid (1, 1, n) -> kvm inferior 1, process n  */
                    427:
                    428:   bsd_kvm_ptid = ptid_build (1, 1, 0);
                    429: }

CVSweb <webmaster@jp.NetBSD.org>