The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/ddb/db_main.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: MIT-CMU
    3  *
    4  * Mach Operating System
    5  * Copyright (c) 1991,1990 Carnegie Mellon University
    6  * All Rights Reserved.
    7  *
    8  * Permission to use, copy, modify and distribute this software and its
    9  * documentation is hereby granted, provided that both the copyright
   10  * notice and this permission notice appear in all copies of the
   11  * software, derivative works or modified versions, and any portions
   12  * thereof, and that both notices appear in supporting documentation.
   13  *
   14  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
   15  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
   16  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
   17  *
   18  * Carnegie Mellon requests users of this software to return to
   19  *
   20  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
   21  *  School of Computer Science
   22  *  Carnegie Mellon University
   23  *  Pittsburgh PA 15213-3890
   24  *
   25  * any improvements or extensions that they make and grant Carnegie the
   26  * rights to redistribute these changes.
   27  */
   28 
   29 #include <sys/cdefs.h>
   30 __FBSDID("$FreeBSD$");
   31 
   32 #include <sys/param.h>
   33 #include <sys/systm.h>
   34 #include <sys/cons.h>
   35 #include <sys/linker.h>
   36 #include <sys/kdb.h>
   37 #include <sys/kernel.h>
   38 #include <sys/pcpu.h>
   39 #include <sys/proc.h>
   40 #include <sys/reboot.h>
   41 #include <sys/sysctl.h>
   42 
   43 #include <machine/kdb.h>
   44 #include <machine/pcb.h>
   45 #include <machine/setjmp.h>
   46 
   47 #include <ddb/ddb.h>
   48 #include <ddb/db_command.h>
   49 #include <ddb/db_sym.h>
   50 
   51 struct db_private {
   52         char*           strtab;
   53         vm_offset_t     relbase;
   54 };
   55 typedef struct db_private *db_private_t;
   56 
   57 #define DB_PRIVATE(x) ((db_private_t)(x->private))
   58 
   59 SYSCTL_NODE(_debug, OID_AUTO, ddb, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
   60     "DDB settings");
   61 
   62 static dbbe_init_f db_init;
   63 static dbbe_trap_f db_trap;
   64 static dbbe_trace_f db_trace_self_wrapper;
   65 static dbbe_trace_thread_f db_trace_thread_wrapper;
   66 
   67 KDB_BACKEND(ddb, db_init, db_trace_self_wrapper, db_trace_thread_wrapper,
   68     db_trap);
   69 
   70 /*
   71  * Symbols can be loaded by specifying the exact addresses of
   72  * the symtab and strtab in memory. This is used when loaded from
   73  * boot loaders different than the native one (like Xen).
   74  */
   75 vm_offset_t ksymtab, kstrtab, ksymtab_size, ksymtab_relbase;
   76 static struct db_private ksymtab_private;
   77 
   78 bool
   79 X_db_line_at_pc(db_symtab_t *symtab, c_db_sym_t sym, char **file, int *line,
   80     db_expr_t off)
   81 {
   82         return (false);
   83 }
   84 
   85 c_db_sym_t
   86 X_db_lookup(db_symtab_t *symtab, const char *symbol)
   87 {
   88         c_linker_sym_t lsym;
   89         Elf_Sym *sym;
   90 
   91         if (symtab->private == NULL) {
   92                 return ((c_db_sym_t)((!linker_ddb_lookup(symbol, &lsym))
   93                         ? lsym : NULL));
   94         } else {
   95                 sym = (Elf_Sym *)symtab->start;
   96                 while ((char *)sym < symtab->end) {
   97                         if (sym->st_name != 0 &&
   98                             !strcmp(DB_PRIVATE(symtab)->strtab +
   99                             sym->st_name, symbol))
  100                                 return ((c_db_sym_t)sym);
  101                         sym++;
  102                 }
  103         }
  104         return (NULL);
  105 }
  106 
  107 c_db_sym_t
  108 X_db_search_symbol(db_symtab_t *symtab, db_addr_t off, db_strategy_t strat,
  109     db_expr_t *diffp)
  110 {
  111         c_linker_sym_t lsym;
  112         Elf_Sym *sym, *match;
  113         unsigned long diff;
  114         db_addr_t stoffs = off;
  115 
  116         if (symtab->private == NULL) {
  117                 if (!linker_ddb_search_symbol((caddr_t)off, &lsym, &diff)) {
  118                         *diffp = (db_expr_t)diff;
  119                         return ((c_db_sym_t)lsym);
  120                 }
  121                 return (NULL);
  122         }
  123         else
  124                 stoffs -= DB_PRIVATE(symtab)->relbase;
  125 
  126         diff = ~0UL;
  127         match = NULL;
  128         for (sym = (Elf_Sym*)symtab->start; (char*)sym < symtab->end; sym++) {
  129                 if (sym->st_name == 0 || sym->st_shndx == SHN_UNDEF)
  130                         continue;
  131                 if (stoffs < sym->st_value)
  132                         continue;
  133                 if (ELF_ST_TYPE(sym->st_info) != STT_OBJECT &&
  134                     ELF_ST_TYPE(sym->st_info) != STT_FUNC &&
  135                     ELF_ST_TYPE(sym->st_info) != STT_NOTYPE)
  136                         continue;
  137                 if ((stoffs - sym->st_value) > diff)
  138                         continue;
  139                 if ((stoffs - sym->st_value) < diff) {
  140                         diff = stoffs - sym->st_value;
  141                         match = sym;
  142                 } else {
  143                         if (match == NULL)
  144                                 match = sym;
  145                         else if (ELF_ST_BIND(match->st_info) == STB_LOCAL &&
  146                             ELF_ST_BIND(sym->st_info) != STB_LOCAL)
  147                                 match = sym;
  148                 }
  149                 if (diff == 0) {
  150                         if (strat == DB_STGY_PROC &&
  151                             ELF_ST_TYPE(sym->st_info) == STT_FUNC &&
  152                             ELF_ST_BIND(sym->st_info) != STB_LOCAL)
  153                                 break;
  154                         if (strat == DB_STGY_ANY &&
  155                             ELF_ST_BIND(sym->st_info) != STB_LOCAL)
  156                                 break;
  157                 }
  158         }
  159 
  160         *diffp = (match == NULL) ? off : diff;
  161         return ((c_db_sym_t)match);
  162 }
  163 
  164 bool
  165 X_db_sym_numargs(db_symtab_t *symtab, c_db_sym_t sym, int *nargp,
  166     char **argp)
  167 {
  168         return (false);
  169 }
  170 
  171 void
  172 X_db_symbol_values(db_symtab_t *symtab, c_db_sym_t sym, const char **namep,
  173     db_expr_t *valp)
  174 {
  175         linker_symval_t lval;
  176 
  177         if (symtab->private == NULL) {
  178                 linker_ddb_symbol_values((c_linker_sym_t)sym, &lval);
  179                 if (namep != NULL)
  180                         *namep = (const char*)lval.name;
  181                 if (valp != NULL)
  182                         *valp = (db_expr_t)lval.value;
  183         } else {
  184                 if (namep != NULL)
  185                         *namep = (const char *)DB_PRIVATE(symtab)->strtab +
  186                             ((const Elf_Sym *)sym)->st_name;
  187                 if (valp != NULL)
  188                         *valp = (db_expr_t)((const Elf_Sym *)sym)->st_value +
  189                             DB_PRIVATE(symtab)->relbase;
  190         }
  191 }
  192 
  193 int
  194 db_fetch_ksymtab(vm_offset_t ksym_start, vm_offset_t ksym_end,
  195     vm_offset_t relbase)
  196 {
  197         Elf_Size strsz;
  198 
  199         if (ksym_end > ksym_start && ksym_start != 0) {
  200                 ksymtab = ksym_start;
  201                 ksymtab_size = *(Elf_Size*)ksymtab;
  202                 ksymtab += sizeof(Elf_Size);
  203                 kstrtab = ksymtab + ksymtab_size;
  204                 strsz = *(Elf_Size*)kstrtab;
  205                 kstrtab += sizeof(Elf_Size);
  206                 ksymtab_relbase = relbase;
  207                 if (kstrtab + strsz > ksym_end) {
  208                         /* Sizes doesn't match, unset everything. */
  209                         ksymtab = ksymtab_size = kstrtab = ksymtab_relbase
  210                             = 0;
  211                 }
  212         }
  213 
  214         if (ksymtab == 0 || ksymtab_size == 0 || kstrtab == 0)
  215                 return (-1);
  216 
  217         return (0);
  218 }
  219 
  220 static int
  221 db_init(void)
  222 {
  223 
  224         db_command_init();
  225 
  226         if (ksymtab != 0 && kstrtab != 0 && ksymtab_size != 0) {
  227                 ksymtab_private.strtab = (char *)kstrtab;
  228                 ksymtab_private.relbase = ksymtab_relbase;
  229                 db_add_symbol_table((char *)ksymtab,
  230                     (char *)(ksymtab + ksymtab_size), "elf", (char *)&ksymtab_private);
  231         }
  232         db_add_symbol_table(NULL, NULL, "kld", NULL);
  233         return (1);     /* We're the default debugger. */
  234 }
  235 
  236 static int
  237 db_trap(int type, int code)
  238 {
  239         jmp_buf jb;
  240         void *prev_jb;
  241         bool bkpt, watchpt;
  242         const char *why;
  243 
  244         /*
  245          * Don't handle the trap if the console is unavailable (i.e. it
  246          * is in graphics mode).
  247          */
  248         if (cnunavailable())
  249                 return (0);
  250 
  251         if (db_stop_at_pc(type, code, &bkpt, &watchpt)) {
  252                 if (db_inst_count) {
  253                         db_printf("After %d instructions (%d loads, %d stores),\n",
  254                             db_inst_count, db_load_count, db_store_count);
  255                 }
  256                 prev_jb = kdb_jmpbuf(jb);
  257                 if (setjmp(jb) == 0) {
  258                         db_dot = PC_REGS();
  259                         db_print_thread();
  260                         if (bkpt)
  261                                 db_printf("Breakpoint at\t");
  262                         else if (watchpt)
  263                                 db_printf("Watchpoint at\t");
  264                         else
  265                                 db_printf("Stopped at\t");
  266                         db_print_loc_and_inst(db_dot);
  267                 }
  268                 why = kdb_why;
  269                 db_script_kdbenter(why != KDB_WHY_UNSET ? why : "unknown");
  270                 db_command_loop();
  271                 (void)kdb_jmpbuf(prev_jb);
  272         }
  273 
  274         db_restart_at_pc(watchpt);
  275 
  276         return (1);
  277 }
  278 
  279 static void
  280 db_trace_self_wrapper(void)
  281 {
  282         jmp_buf jb;
  283         void *prev_jb;
  284 
  285         prev_jb = kdb_jmpbuf(jb);
  286         if (setjmp(jb) == 0)
  287                 db_trace_self();
  288         (void)kdb_jmpbuf(prev_jb);
  289 }
  290 
  291 static void
  292 db_trace_thread_wrapper(struct thread *td)
  293 {
  294         jmp_buf jb;
  295         void *prev_jb;
  296 
  297         prev_jb = kdb_jmpbuf(jb);
  298         if (setjmp(jb) == 0)
  299                 db_trace_thread(td, -1);
  300         (void)kdb_jmpbuf(prev_jb);
  301 }

Cache object: 0bd4c934b4234e59f5db3a300d5455ea


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.