diff options
author | rgrimes <rgrimes@FreeBSD.org> | 1993-06-12 14:58:17 +0000 |
---|---|---|
committer | rgrimes <rgrimes@FreeBSD.org> | 1993-06-12 14:58:17 +0000 |
commit | 25062ba061871945759b3baa833fe64969383e40 (patch) | |
tree | 2d1c31051ed0dbaad984013c9fe695b1a01e1c39 /sys/ddb | |
parent | f078b88a160c467761b3f3641f05dfd0aa3f7753 (diff) | |
download | FreeBSD-src-25062ba061871945759b3baa833fe64969383e40.zip FreeBSD-src-25062ba061871945759b3baa833fe64969383e40.tar.gz |
Initial import, 0.1 + pk 0.2.4-B1
Diffstat (limited to 'sys/ddb')
-rw-r--r-- | sys/ddb/db_access.c | 116 | ||||
-rw-r--r-- | sys/ddb/db_access.h | 55 | ||||
-rw-r--r-- | sys/ddb/db_aout.c | 309 | ||||
-rw-r--r-- | sys/ddb/db_break.c | 387 | ||||
-rw-r--r-- | sys/ddb/db_break.h | 84 | ||||
-rw-r--r-- | sys/ddb/db_command.c | 526 | ||||
-rw-r--r-- | sys/ddb/db_command.h | 67 | ||||
-rw-r--r-- | sys/ddb/db_examine.c | 364 | ||||
-rw-r--r-- | sys/ddb/db_expr.c | 248 | ||||
-rw-r--r-- | sys/ddb/db_input.c | 268 | ||||
-rw-r--r-- | sys/ddb/db_lex.c | 295 | ||||
-rw-r--r-- | sys/ddb/db_lex.h | 89 | ||||
-rw-r--r-- | sys/ddb/db_output.c | 389 | ||||
-rw-r--r-- | sys/ddb/db_output.h | 53 | ||||
-rw-r--r-- | sys/ddb/db_print.c | 104 | ||||
-rw-r--r-- | sys/ddb/db_run.c | 426 | ||||
-rw-r--r-- | sys/ddb/db_sym.c | 360 | ||||
-rw-r--r-- | sys/ddb/db_sym.h | 114 | ||||
-rw-r--r-- | sys/ddb/db_trap.c | 106 | ||||
-rw-r--r-- | sys/ddb/db_variables.c | 186 | ||||
-rw-r--r-- | sys/ddb/db_variables.h | 72 | ||||
-rw-r--r-- | sys/ddb/db_watch.c | 294 | ||||
-rw-r--r-- | sys/ddb/db_watch.h | 74 | ||||
-rw-r--r-- | sys/ddb/db_write_cmd.c | 120 |
24 files changed, 5106 insertions, 0 deletions
diff --git a/sys/ddb/db_access.c b/sys/ddb/db_access.c new file mode 100644 index 0000000..63368c0 --- /dev/null +++ b/sys/ddb/db_access.c @@ -0,0 +1,116 @@ +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ +/* + * HISTORY + * $Log: db_access.c,v $ + * Revision 1.1 1992/03/25 21:44:50 pace + * Initial revision + * + * Revision 2.3 91/02/05 17:05:44 mrt + * Changed to new Mach copyright + * [91/01/31 16:16:22 mrt] + * + * Revision 2.2 90/08/27 21:48:20 dbg + * Fix type declarations. + * [90/08/07 dbg] + * Created. + * [90/07/25 dbg] + * + */ +/* + * Author: David B. Golub, Carnegie Mellon University + * Date: 7/90 + */ +#include "param.h" +#include "proc.h" +#include <machine/db_machdep.h> /* type definitions */ + +/* + * Access unaligned data items on aligned (longword) + * boundaries. + */ + +extern void db_read_bytes(); /* machine-dependent */ +extern void db_write_bytes(); /* machine-dependent */ + +int db_extend[] = { /* table for sign-extending */ + 0, + 0xFFFFFF80, + 0xFFFF8000, + 0xFF800000 +}; + +db_expr_t +db_get_value(addr, size, is_signed) + db_addr_t addr; + register int size; + boolean_t is_signed; +{ + char data[sizeof(int)]; + register db_expr_t value; + register int i; + + db_read_bytes(addr, size, data); + + value = 0; +#if BYTE_MSF + for (i = 0; i < size; i++) +#else /* BYTE_LSF */ + for (i = size - 1; i >= 0; i--) +#endif + { + value = (value << 8) + (data[i] & 0xFF); + } + + if (size < 4) { + if (is_signed && (value & db_extend[size]) != 0) + value |= db_extend[size]; + } + return (value); +} + +void +db_put_value(addr, size, value) + db_addr_t addr; + register int size; + register db_expr_t value; +{ + char data[sizeof(int)]; + register int i; + +#if BYTE_MSF + for (i = size - 1; i >= 0; i--) +#else /* BYTE_LSF */ + for (i = 0; i < size; i++) +#endif + { + data[i] = value & 0xFF; + value >>= 8; + } + + db_write_bytes(addr, size, data); +} + diff --git a/sys/ddb/db_access.h b/sys/ddb/db_access.h new file mode 100644 index 0000000..ddc5349 --- /dev/null +++ b/sys/ddb/db_access.h @@ -0,0 +1,55 @@ +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ +/* + * HISTORY + * $Log: db_access.h,v $ + * Revision 1.1 1992/03/25 21:44:53 pace + * Initial revision + * + * Revision 2.3 91/02/05 17:05:49 mrt + * Changed to new Mach copyright + * [91/01/31 16:16:37 mrt] + * + * Revision 2.2 90/08/27 21:48:27 dbg + * Created. + * [90/08/07 dbg] + * + */ +/* + * Author: David B. Golub, Carnegie Mellon University + * Date: 7/90 + */ +/* + * Data access functions for debugger. + */ +#include <machine/db_machdep.h> /* expression types */ + +extern db_expr_t db_get_value(/* db_addr_t addr, + int size, + boolean_t is_signed */); +extern void db_put_value(/* db_addr_t addr, + int size, + db_expr_t value */); diff --git a/sys/ddb/db_aout.c b/sys/ddb/db_aout.c new file mode 100644 index 0000000..88f4b03 --- /dev/null +++ b/sys/ddb/db_aout.c @@ -0,0 +1,309 @@ +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ +/* + * HISTORY + * $Log: db_aout.c,v $ + * Revision 1.1 1992/03/25 21:44:55 pace + * Initial revision + * + * Revision 2.3 91/02/05 17:05:55 mrt + * Changed to new Mach copyright + * [91/01/31 16:16:44 mrt] + * + * Revision 2.2 90/08/27 21:48:35 dbg + * Created. + * [90/08/17 dbg] + * + */ +/* + * Author: David B. Golub, Carnegie Mellon University + * Date: 7/90 + */ +/* + * Symbol table routines for a.out format files. + */ + +#include "param.h" +#include "proc.h" +#include <machine/db_machdep.h> /* data types */ +#include <ddb/db_sym.h> + +#ifndef DB_NO_AOUT + +#define _AOUT_INCLUDE_ +#include "nlist.h" + +/* + * An a.out symbol table as loaded into the kernel debugger: + * + * symtab -> size of symbol entries, in bytes + * sp -> first symbol entry + * ... + * ep -> last symbol entry + 1 + * strtab == start of string table + * size of string table in bytes, + * including this word + * -> strings + */ + +/* + * Find pointers to the start and end of the symbol entries, + * given a pointer to the start of the symbol table. + */ +#define db_get_aout_symtab(symtab, sp, ep) \ + (sp = (struct nlist *)((symtab) + 1), \ + ep = (struct nlist *)((char *)sp + *(symtab))) + +#define SYMTAB_SPACE 63000 +int db_symtabsize = SYMTAB_SPACE; +char db_symtab[SYMTAB_SPACE] = { 1 }; + +X_db_sym_init(symtab, esymtab, name) + int * symtab; /* pointer to start of symbol table */ + char * esymtab; /* pointer to end of string table, + for checking - rounded up to integer + boundary */ + char * name; +{ + register struct nlist *sym_start, *sym_end; + register struct nlist *sp; + register char * strtab; + register int strlen; + + if (*symtab < 4) { + printf ("DDB: no symbols\n"); + return; + } + + db_get_aout_symtab(symtab, sym_start, sym_end); + + strtab = (char *)sym_end; + strlen = *(int *)strtab; + +#if 0 + if (strtab + ((strlen + sizeof(int) - 1) & ~(sizeof(int)-1)) + != esymtab) + { + db_printf("[ %s symbol table not valid ]\n", name); + return; + } + + db_printf("[ preserving %#x bytes of %s symbol table ]\n", + esymtab - (char *)symtab, name); +#endif + + for (sp = sym_start; sp < sym_end; sp++) { + register int strx; + strx = sp->n_un.n_strx; + if (strx != 0) { + if (strx > strlen) { + db_printf("Bad string table index (%#x)\n", strx); + sp->n_un.n_name = 0; + continue; + } + sp->n_un.n_name = strtab + strx; + } + } + + db_add_symbol_table(sym_start, sym_end, name, (char *)symtab); +} + +db_sym_t +X_db_lookup(stab, symstr) + db_symtab_t *stab; + char * symstr; +{ + register struct nlist *sp, *ep; + + sp = (struct nlist *)stab->start; + ep = (struct nlist *)stab->end; + + for (; sp < ep; sp++) { + if (sp->n_un.n_name == 0) + continue; + if ((sp->n_type & N_STAB) == 0 && + sp->n_un.n_name != 0 && + db_eqname(sp->n_un.n_name, symstr, '_')) + { + return ((db_sym_t)sp); + } + } + return ((db_sym_t)0); +} + +db_sym_t +X_db_search_symbol(symtab, off, strategy, diffp) + db_symtab_t * symtab; + register + db_addr_t off; + db_strategy_t strategy; + db_expr_t *diffp; /* in/out */ +{ + register unsigned int diff = *diffp; + register struct nlist *symp = 0; + register struct nlist *sp, *ep; + + sp = (struct nlist *)symtab->start; + ep = (struct nlist *)symtab->end; + + for (; sp < ep; sp++) { + if (sp->n_un.n_name == 0) + continue; + if ((sp->n_type & N_STAB) != 0) + continue; + if (off >= sp->n_value) { + if (off - sp->n_value < diff) { + diff = off - sp->n_value; + symp = sp; + if (diff == 0) + break; + } + else if (off - sp->n_value == diff) { + if (symp == 0) + symp = sp; + else if ((symp->n_type & N_EXT) == 0 && + (sp->n_type & N_EXT) != 0) + symp = sp; /* pick the external symbol */ + } + } + } + if (symp == 0) { + *diffp = off; + } + else { + *diffp = diff; + } + return ((db_sym_t)symp); +} + +/* + * Return the name and value for a symbol. + */ +void +X_db_symbol_values(sym, namep, valuep) + db_sym_t sym; + char **namep; + db_expr_t *valuep; +{ + register struct nlist *sp; + + sp = (struct nlist *)sym; + if (namep) + *namep = sp->n_un.n_name; + if (valuep) + *valuep = sp->n_value; +} + +boolean_t +X_db_line_at_pc() +{ + return (FALSE); +} + +/* + * Initialization routine for a.out files. + */ +kdb_init() +{ +#if 0 + extern char *esym; + extern int end; + + if (esym > (char *)&end) { + X_db_sym_init((int *)&end, esym, "mach"); + } +#endif + + X_db_sym_init (db_symtab, 0, "mach"); +} + +#if 0 +/* + * Read symbol table from file. + * (should be somewhere else) + */ +#include <boot_ufs/file_io.h> +#include <vm/vm_kern.h> + +read_symtab_from_file(fp, symtab_name) + struct file *fp; + char * symtab_name; +{ + vm_size_t resid; + kern_return_t result; + vm_offset_t symoff; + vm_size_t symsize; + vm_offset_t stroff; + vm_size_t strsize; + vm_size_t table_size; + vm_offset_t symtab; + + if (!get_symtab(fp, &symoff, &symsize)) { + boot_printf("[ error %d reading %s file header ]\n", + result, symtab_name); + return; + } + + stroff = symoff + symsize; + result = read_file(fp, (vm_offset_t)stroff, + (vm_offset_t)&strsize, sizeof(strsize), &resid); + if (result || resid) { + boot_printf("[ no valid symbol table present for %s ]\n", + symtab_name); + return; + } + + table_size = sizeof(int) + symsize + strsize; + table_size = (table_size + sizeof(int)-1) & ~(sizeof(int)-1); + + symtab = kmem_alloc_wired(kernel_map, table_size); + + *(int *)symtab = symsize; + + result = read_file(fp, symoff, + symtab + sizeof(int), symsize, &resid); + if (result || resid) { + boot_printf("[ error %d reading %s symbol table ]\n", + result, symtab_name); + return; + } + + result = read_file(fp, stroff, + symtab + sizeof(int) + symsize, strsize, &resid); + if (result || resid) { + boot_printf("[ error %d reading %s string table ]\n", + result, symtab_name); + return; + } + + X_db_sym_init((int *)symtab, + (char *)(symtab + table_size), + symtab_name); + +} +#endif + +#endif /* DB_NO_AOUT */ diff --git a/sys/ddb/db_break.c b/sys/ddb/db_break.c new file mode 100644 index 0000000..9db7a04 --- /dev/null +++ b/sys/ddb/db_break.c @@ -0,0 +1,387 @@ +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ +/* + * HISTORY + * $Log: db_break.c,v $ + * Revision 1.1 1992/03/25 21:44:57 pace + * Initial revision + * + * Revision 2.7 91/02/05 17:06:00 mrt + * Changed to new Mach copyright + * [91/01/31 16:17:01 mrt] + * + * Revision 2.6 91/01/08 15:09:03 rpd + * Added db_map_equal, db_map_current, db_map_addr. + * [90/11/10 rpd] + * + * Revision 2.5 90/11/05 14:26:32 rpd + * Initialize db_breakpoints_inserted to TRUE. + * [90/11/04 rpd] + * + * Revision 2.4 90/10/25 14:43:33 rwd + * Added map field to breakpoints. + * Added map argument to db_set_breakpoint, db_delete_breakpoint, + * db_find_breakpoint. Added db_find_breakpoint_here. + * [90/10/18 rpd] + * + * Revision 2.3 90/09/28 16:57:07 jsb + * Fixed db_breakpoint_free. + * [90/09/18 rpd] + * + * Revision 2.2 90/08/27 21:49:53 dbg + * Reflected changes in db_printsym()'s calling seq. + * [90/08/20 af] + * Clear breakpoints only if inserted. + * Reduce lint. + * [90/08/07 dbg] + * Created. + * [90/07/25 dbg] + * + */ +/* + * Author: David B. Golub, Carnegie Mellon University + * Date: 7/90 + */ +/* + * Breakpoints. + */ +#include "param.h" +#include "proc.h" +#include <machine/db_machdep.h> /* type definitions */ + +#include <ddb/db_lex.h> +#include <ddb/db_break.h> +#include <ddb/db_access.h> +#include <ddb/db_sym.h> +#include <ddb/db_break.h> + +extern boolean_t db_map_equal(); +extern boolean_t db_map_current(); +extern vm_map_t db_map_addr(); + +#define NBREAKPOINTS 100 +struct db_breakpoint db_break_table[NBREAKPOINTS]; +db_breakpoint_t db_next_free_breakpoint = &db_break_table[0]; +db_breakpoint_t db_free_breakpoints = 0; +db_breakpoint_t db_breakpoint_list = 0; + +db_breakpoint_t +db_breakpoint_alloc() +{ + register db_breakpoint_t bkpt; + + if ((bkpt = db_free_breakpoints) != 0) { + db_free_breakpoints = bkpt->link; + return (bkpt); + } + if (db_next_free_breakpoint == &db_break_table[NBREAKPOINTS]) { + db_printf("All breakpoints used.\n"); + return (0); + } + bkpt = db_next_free_breakpoint; + db_next_free_breakpoint++; + + return (bkpt); +} + +void +db_breakpoint_free(bkpt) + register db_breakpoint_t bkpt; +{ + bkpt->link = db_free_breakpoints; + db_free_breakpoints = bkpt; +} + +void +db_set_breakpoint(map, addr, count) + vm_map_t map; + db_addr_t addr; + int count; +{ + register db_breakpoint_t bkpt; + + if (db_find_breakpoint(map, addr)) { + db_printf("Already set.\n"); + return; + } + + bkpt = db_breakpoint_alloc(); + if (bkpt == 0) { + db_printf("Too many breakpoints.\n"); + return; + } + + bkpt->map = map; + bkpt->address = addr; + bkpt->flags = 0; + bkpt->init_count = count; + bkpt->count = count; + + bkpt->link = db_breakpoint_list; + db_breakpoint_list = bkpt; +} + +void +db_delete_breakpoint(map, addr) + vm_map_t map; + db_addr_t addr; +{ + register db_breakpoint_t bkpt; + register db_breakpoint_t *prev; + + for (prev = &db_breakpoint_list; + (bkpt = *prev) != 0; + prev = &bkpt->link) { + if (db_map_equal(bkpt->map, map) && + (bkpt->address == addr)) { + *prev = bkpt->link; + break; + } + } + if (bkpt == 0) { + db_printf("Not set.\n"); + return; + } + + db_breakpoint_free(bkpt); +} + +db_breakpoint_t +db_find_breakpoint(map, addr) + vm_map_t map; + db_addr_t addr; +{ + register db_breakpoint_t bkpt; + + for (bkpt = db_breakpoint_list; + bkpt != 0; + bkpt = bkpt->link) + { + if (db_map_equal(bkpt->map, map) && + (bkpt->address == addr)) + return (bkpt); + } + return (0); +} + +db_breakpoint_t +db_find_breakpoint_here(addr) + db_addr_t addr; +{ + return db_find_breakpoint(db_map_addr(addr), addr); +} + +boolean_t db_breakpoints_inserted = TRUE; + +void +db_set_breakpoints() +{ + register db_breakpoint_t bkpt; + + if (!db_breakpoints_inserted) { + + for (bkpt = db_breakpoint_list; + bkpt != 0; + bkpt = bkpt->link) + if (db_map_current(bkpt->map)) { + bkpt->bkpt_inst = db_get_value(bkpt->address, + BKPT_SIZE, + FALSE); + db_put_value(bkpt->address, + BKPT_SIZE, + BKPT_SET(bkpt->bkpt_inst)); + } + db_breakpoints_inserted = TRUE; + } +} + +void +db_clear_breakpoints() +{ + register db_breakpoint_t bkpt; + + if (db_breakpoints_inserted) { + + for (bkpt = db_breakpoint_list; + bkpt != 0; + bkpt = bkpt->link) + if (db_map_current(bkpt->map)) { + db_put_value(bkpt->address, BKPT_SIZE, bkpt->bkpt_inst); + } + db_breakpoints_inserted = FALSE; + } +} + +/* + * Set a temporary breakpoint. + * The instruction is changed immediately, + * so the breakpoint does not have to be on the breakpoint list. + */ +db_breakpoint_t +db_set_temp_breakpoint(addr) + db_addr_t addr; +{ + register db_breakpoint_t bkpt; + + bkpt = db_breakpoint_alloc(); + if (bkpt == 0) { + db_printf("Too many breakpoints.\n"); + return 0; + } + + bkpt->map = NULL; + bkpt->address = addr; + bkpt->flags = BKPT_TEMP; + bkpt->init_count = 1; + bkpt->count = 1; + + bkpt->bkpt_inst = db_get_value(bkpt->address, BKPT_SIZE, FALSE); + db_put_value(bkpt->address, BKPT_SIZE, BKPT_SET(bkpt->bkpt_inst)); + return bkpt; +} + +void +db_delete_temp_breakpoint(bkpt) + db_breakpoint_t bkpt; +{ + db_put_value(bkpt->address, BKPT_SIZE, bkpt->bkpt_inst); + db_breakpoint_free(bkpt); +} + +/* + * List breakpoints. + */ +void +db_list_breakpoints() +{ + register db_breakpoint_t bkpt; + + if (db_breakpoint_list == 0) { + db_printf("No breakpoints set\n"); + return; + } + + db_printf(" Map Count Address\n"); + for (bkpt = db_breakpoint_list; + bkpt != 0; + bkpt = bkpt->link) + { + db_printf("%s%8x %5d ", + db_map_current(bkpt->map) ? "*" : " ", + bkpt->map, bkpt->init_count); + db_printsym(bkpt->address, DB_STGY_PROC); + db_printf("\n"); + } +} + +/* Delete breakpoint */ +/*ARGSUSED*/ +void +db_delete_cmd(addr, have_addr, count, modif) + db_expr_t addr; + int have_addr; + db_expr_t count; + char * modif; +{ + db_delete_breakpoint(db_map_addr(addr), (db_addr_t)addr); +} + +/* Set breakpoint with skip count */ +/*ARGSUSED*/ +void +db_breakpoint_cmd(addr, have_addr, count, modif) + db_expr_t addr; + int have_addr; + db_expr_t count; + char * modif; +{ + if (count == -1) + count = 1; + + db_set_breakpoint(db_map_addr(addr), (db_addr_t)addr, count); +} + +/* list breakpoints */ +void +db_listbreak_cmd() +{ + db_list_breakpoints(); +} + +#include <vm/vm_kern.h> + +/* + * We want ddb to be usable before most of the kernel has been + * initialized. In particular, current_thread() or kernel_map + * (or both) may be null. + */ + +boolean_t +db_map_equal(map1, map2) + vm_map_t map1, map2; +{ + return ((map1 == map2) || + ((map1 == NULL) && (map2 == kernel_map)) || + ((map1 == kernel_map) && (map2 == NULL))); +} + +boolean_t +db_map_current(map) + vm_map_t map; +{ +#if 0 + thread_t thread; + + return ((map == NULL) || + (map == kernel_map) || + (((thread = current_thread()) != NULL) && + (map == thread->task->map))); +#else + return (1); +#endif +} + +vm_map_t +db_map_addr(addr) + vm_offset_t addr; +{ +#if 0 + thread_t thread; + + /* + * We want to return kernel_map for all + * non-user addresses, even when debugging + * kernel tasks with their own maps. + */ + + if ((VM_MIN_ADDRESS <= addr) && + (addr < VM_MAX_ADDRESS) && + ((thread = current_thread()) != NULL)) + return thread->task->map; + else +#endif + return kernel_map; +} diff --git a/sys/ddb/db_break.h b/sys/ddb/db_break.h new file mode 100644 index 0000000..874cbcb --- /dev/null +++ b/sys/ddb/db_break.h @@ -0,0 +1,84 @@ +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ +/* + * HISTORY + * $Log: db_break.h,v $ + * Revision 1.1 1992/03/25 21:44:59 pace + * Initial revision + * + * Revision 2.4 91/02/05 17:06:06 mrt + * Changed to new Mach copyright + * [91/01/31 16:17:10 mrt] + * + * Revision 2.3 90/10/25 14:43:40 rwd + * Added map field to breakpoints. + * [90/10/18 rpd] + * + * Revision 2.2 90/08/27 21:50:00 dbg + * Modularized typedef names. + * [90/08/20 af] + * Add external defintions. + * [90/08/07 dbg] + * Created. + * [90/07/25 dbg] + * + */ +/* + * Author: David B. Golub, Carnegie Mellon University + * Date: 7/90 + */ +#ifndef _DDB_DB_BREAK_H_ +#define _DDB_DB_BREAK_H_ + +#include <vm/vm_map.h> +#include <machine/db_machdep.h> + +/* + * Breakpoint. + */ + +struct db_breakpoint { + vm_map_t map; /* in this map */ + db_addr_t address; /* set here */ + int init_count; /* number of times to skip bkpt */ + int count; /* current count */ + int flags; /* flags: */ +#define BKPT_SINGLE_STEP 0x2 /* to simulate single step */ +#define BKPT_TEMP 0x4 /* temporary */ + int bkpt_inst; /* saved instruction at bkpt */ + struct db_breakpoint *link; /* link in in-use or free chain */ +}; +typedef struct db_breakpoint *db_breakpoint_t; + +extern db_breakpoint_t db_find_breakpoint(); +extern db_breakpoint_t db_find_breakpoint_here(); +extern void db_set_breakpoints(); +extern void db_clear_breakpoints(); + +extern db_breakpoint_t db_set_temp_breakpoint(/* db_addr_t addr */); +extern void db_delete_temp_breakpoint(/* db_breakpoint_t bkpt */); + +#endif _DDB_DB_BREAK_H_ diff --git a/sys/ddb/db_command.c b/sys/ddb/db_command.c new file mode 100644 index 0000000..e660e18 --- /dev/null +++ b/sys/ddb/db_command.c @@ -0,0 +1,526 @@ +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ +/* + * HISTORY + * $Log: db_command.c,v $ + * + * PATCHES MAGIC LEVEL PATCH THAT GOT US HERE + * -------------------- ----- ---------------------- + * CURRENT PATCH LEVEL: 1 00081 + * -------------------- ----- ---------------------- + * + * 01 Feb 93 Julian Elischer move strcmp to a more general + * part of the kernel. + * + * Revision 1.1 1992/03/25 21:45:02 pace + * Initial revision + * + * Revision 2.6 91/02/05 17:06:10 mrt + * Changed to new Mach copyright + * [91/01/31 16:17:18 mrt] + * + * Revision 2.5 91/01/08 17:31:54 rpd + * Forward reference for db_fncall(); + * [91/01/04 12:35:17 rvb] + * + * Add call as a synonym for ! and match for next + * [91/01/04 12:14:48 rvb] + * + * Revision 2.4 90/11/07 16:49:15 rpd + * Added search. + * [90/11/06 rpd] + * + * Revision 2.3 90/10/25 14:43:45 rwd + * Changed db_fncall to print the result unsigned. + * [90/10/19 rpd] + * + * Added CS_MORE to db_watchpoint_cmd. + * [90/10/17 rpd] + * Added watchpoint commands: watch, dwatch, show watches. + * [90/10/16 rpd] + * + * Revision 2.2 90/08/27 21:50:10 dbg + * Remove 'listbreaks' - use 'show breaks' instead. Change 'show + * threads' to 'show all threads' to avoid clash with 'show thread'. + * Set 'dot' here from db_prev or db_next, depending on 'db_ed_style' + * flag and syntax table. + * [90/08/22 dbg] + * Reduce lint. + * [90/08/07 dbg] + * Created. + * [90/07/25 dbg] + * + */ +/* + * Author: David B. Golub, Carnegie Mellon University + * Date: 7/90 + */ +/* + * Command dispatcher. + */ +#include "param.h" +#include "proc.h" +#include <machine/db_machdep.h> /* type definitions */ + +#include <ddb/db_lex.h> +#include <ddb/db_output.h> + +#include <setjmp.h> + +/* + * Exported global variables + */ +boolean_t db_cmd_loop_done; +jmp_buf db_jmpbuf; +db_addr_t db_dot; +db_addr_t db_last_addr; +db_addr_t db_prev; +db_addr_t db_next; + +/* + * if 'ed' style: 'dot' is set at start of last item printed, + * and '+' points to next line. + * Otherwise: 'dot' points to next item, '..' points to last. + */ +boolean_t db_ed_style = TRUE; + + +/* + * Utility routine - discard tokens through end-of-line. + */ +void +db_skip_to_eol() +{ + int t; + do { + t = db_read_token(); + } while (t != tEOL); +} + +/* + * Command table + */ +struct command { + char * name; /* command name */ + void (*fcn)(); /* function to call */ + int flag; /* extra info: */ +#define CS_OWN 0x1 /* non-standard syntax */ +#define CS_MORE 0x2 /* standard syntax, but may have other + words at end */ +#define CS_SET_DOT 0x100 /* set dot after command */ + struct command *more; /* another level of command */ +}; + +/* + * Results of command search. + */ +#define CMD_UNIQUE 0 +#define CMD_FOUND 1 +#define CMD_NONE 2 +#define CMD_AMBIGUOUS 3 +#define CMD_HELP 4 + +/* + * Search for command prefix. + */ +int +db_cmd_search(name, table, cmdp) + char * name; + struct command *table; + struct command **cmdp; /* out */ +{ + struct command *cmd; + int result = CMD_NONE; + + for (cmd = table; cmd->name != 0; cmd++) { + register char *lp; + register char *rp; + register int c; + + lp = name; + rp = cmd->name; + while ((c = *lp) == *rp) { + if (c == 0) { + /* complete match */ + *cmdp = cmd; + return (CMD_UNIQUE); + } + lp++; + rp++; + } + if (c == 0) { + /* end of name, not end of command - + partial match */ + if (result == CMD_FOUND) { + result = CMD_AMBIGUOUS; + /* but keep looking for a full match - + this lets us match single letters */ + } + else { + *cmdp = cmd; + result = CMD_FOUND; + } + } + } + if (result == CMD_NONE) { + /* check for 'help' */ + if (name[0] == 'h' && name[1] == 'e' + && name[2] == 'l' && name[3] == 'p') + result = CMD_HELP; + } + return (result); +} + +void +db_cmd_list(table) + struct command *table; +{ + register struct command *cmd; + + for (cmd = table; cmd->name != 0; cmd++) { + db_printf("%-12s", cmd->name); + db_end_line(); + } +} + +void +db_command(last_cmdp, cmd_table) + struct command **last_cmdp; /* IN_OUT */ + struct command *cmd_table; +{ + struct command *cmd; + int t; + char modif[TOK_STRING_SIZE]; + db_expr_t addr, count; + boolean_t have_addr; + int result; + + t = db_read_token(); + if (t == tEOL) { + /* empty line repeats last command, at 'next' */ + cmd = *last_cmdp; + addr = (db_expr_t)db_next; + have_addr = FALSE; + count = 1; + modif[0] = '\0'; + } + else if (t == tEXCL) { + void db_fncall(); + db_fncall(); + return; + } + else if (t != tIDENT) { + db_printf("?\n"); + db_flush_lex(); + return; + } + else { + /* + * Search for command + */ + while (cmd_table) { + result = db_cmd_search(db_tok_string, + cmd_table, + &cmd); + switch (result) { + case CMD_NONE: + db_printf("No such command\n"); + db_flush_lex(); + return; + case CMD_AMBIGUOUS: + db_printf("Ambiguous\n"); + db_flush_lex(); + return; + case CMD_HELP: + db_cmd_list(cmd_table); + db_flush_lex(); + return; + default: + break; + } + if ((cmd_table = cmd->more) != 0) { + t = db_read_token(); + if (t != tIDENT) { + db_cmd_list(cmd_table); + db_flush_lex(); + return; + } + } + } + + if ((cmd->flag & CS_OWN) == 0) { + /* + * Standard syntax: + * command [/modifier] [addr] [,count] + */ + t = db_read_token(); + if (t == tSLASH) { + t = db_read_token(); + if (t != tIDENT) { + db_printf("Bad modifier\n"); + db_flush_lex(); + return; + } + db_strcpy(modif, db_tok_string); + } + else { + db_unread_token(t); + modif[0] = '\0'; + } + + if (db_expression(&addr)) { + db_dot = (db_addr_t) addr; + db_last_addr = db_dot; + have_addr = TRUE; + } + else { + addr = (db_expr_t) db_dot; + have_addr = FALSE; + } + t = db_read_token(); + if (t == tCOMMA) { + if (!db_expression(&count)) { + db_printf("Count missing\n"); + db_flush_lex(); + return; + } + } + else { + db_unread_token(t); + count = -1; + } + if ((cmd->flag & CS_MORE) == 0) { + db_skip_to_eol(); + } + } + } + *last_cmdp = cmd; + if (cmd != 0) { + /* + * Execute the command. + */ + (*cmd->fcn)(addr, have_addr, count, modif); + + if (cmd->flag & CS_SET_DOT) { + /* + * If command changes dot, set dot to + * previous address displayed (if 'ed' style). + */ + if (db_ed_style) { + db_dot = db_prev; + } + else { + db_dot = db_next; + } + } + else { + /* + * If command does not change dot, + * set 'next' location to be the same. + */ + db_next = db_dot; + } + } +} + +/* + * 'show' commands + */ +extern void db_listbreak_cmd(); +extern void db_listwatch_cmd(); +extern void db_show_regs(), db_show_one_thread(), db_show_all_threads(); +extern void vm_map_print(), vm_object_print(), vm_page_print(); +extern void ipc_port_print(); +void db_show_help(); + +struct command db_show_all_cmds[] = { +#if 0 + { "threads", db_show_all_threads,0, 0 }, +#endif + { (char *)0 } +}; + +struct command db_show_cmds[] = { + { "all", 0, 0, db_show_all_cmds }, + { "registers", db_show_regs, 0, 0 }, + { "breaks", db_listbreak_cmd, 0, 0 }, + { "watches", db_listwatch_cmd, 0, 0 }, +#if 0 + { "thread", db_show_one_thread, 0, 0 }, +#endif + { "map", vm_map_print, 0, 0 }, + { "object", vm_object_print, 0, 0 }, +#if 0 + { "page", vm_page_print, 0, 0 }, +#endif +#if 0 + { "port", ipc_port_print, 0, 0 }, +#endif + { (char *)0, } +}; + +extern void db_print_cmd(), db_examine_cmd(), db_set_cmd(); +extern void db_search_cmd(); +extern void db_write_cmd(); +extern void db_delete_cmd(), db_breakpoint_cmd(); +extern void db_deletewatch_cmd(), db_watchpoint_cmd(); +extern void db_single_step_cmd(), db_trace_until_call_cmd(), + db_trace_until_matching_cmd(), db_continue_cmd(); +extern void db_stack_trace_cmd(); +void db_help_cmd(); +void db_fncall(); + +struct command db_command_table[] = { + { "print", db_print_cmd, 0, 0 }, + { "examine", db_examine_cmd, CS_SET_DOT, 0 }, + { "x", db_examine_cmd, CS_SET_DOT, 0 }, + { "search", db_search_cmd, CS_OWN|CS_SET_DOT, 0 }, + { "set", db_set_cmd, CS_OWN, 0 }, + { "write", db_write_cmd, CS_MORE|CS_SET_DOT, 0 }, + { "w", db_write_cmd, CS_MORE|CS_SET_DOT, 0 }, + { "delete", db_delete_cmd, 0, 0 }, + { "d", db_delete_cmd, 0, 0 }, + { "break", db_breakpoint_cmd, 0, 0 }, + { "dwatch", db_deletewatch_cmd, 0, 0 }, + { "watch", db_watchpoint_cmd, CS_MORE,0 }, + { "step", db_single_step_cmd, 0, 0 }, + { "s", db_single_step_cmd, 0, 0 }, + { "continue", db_continue_cmd, 0, 0 }, + { "c", db_continue_cmd, 0, 0 }, + { "until", db_trace_until_call_cmd,0, 0 }, + { "next", db_trace_until_matching_cmd,0, 0 }, + { "match", db_trace_until_matching_cmd,0, 0 }, + { "trace", db_stack_trace_cmd, 0, 0 }, + { "call", db_fncall, CS_OWN, 0 }, + { "show", 0, 0, db_show_cmds }, + { (char *)0, } +}; + +struct command *db_last_command = 0; + +void +db_help_cmd() +{ + struct command *cmd = db_command_table; + + while (cmd->name != 0) { + db_printf("%-12s", cmd->name); + db_end_line(); + cmd++; + } +} + +void +db_command_loop() +{ + /* + * Initialize 'prev' and 'next' to dot. + */ + db_prev = db_dot; + db_next = db_dot; + + db_cmd_loop_done = 0; + while (!db_cmd_loop_done) { + + (void) setjmp(db_jmpbuf); + if (db_print_position() != 0) + db_printf("\n"); + + db_printf("db> "); + (void) db_read_line(); + + db_command(&db_last_command, db_command_table); + } +} + +void +db_error(s) + char *s; +{ + if (s) + db_printf(s); + db_flush_lex(); + longjmp(db_jmpbuf, 1); +} + + +/* + * Call random function: + * !expr(arg,arg,arg) + */ +void +db_fncall() +{ + db_expr_t fn_addr; +#define MAXARGS 11 + db_expr_t args[MAXARGS]; + int nargs = 0; + db_expr_t retval; + db_expr_t (*func)(); + int t; + + if (!db_expression(&fn_addr)) { + db_printf("Bad function\n"); + db_flush_lex(); + return; + } + func = (db_expr_t (*) ()) fn_addr; + + t = db_read_token(); + if (t == tLPAREN) { + if (db_expression(&args[0])) { + nargs++; + while ((t = db_read_token()) == tCOMMA) { + if (nargs == MAXARGS) { + db_printf("Too many arguments\n"); + db_flush_lex(); + return; + } + if (!db_expression(&args[nargs])) { + db_printf("Argument missing\n"); + db_flush_lex(); + return; + } + nargs++; + } + db_unread_token(t); + } + if (db_read_token() != tRPAREN) { + db_printf("?\n"); + db_flush_lex(); + return; + } + } + db_skip_to_eol(); + + while (nargs < MAXARGS) { + args[nargs++] = 0; + } + + retval = (*func)(args[0], args[1], args[2], args[3], args[4], + args[5], args[6], args[7], args[8], args[9] ); + db_printf("%#n\n", retval); +} diff --git a/sys/ddb/db_command.h b/sys/ddb/db_command.h new file mode 100644 index 0000000..938a3d6 --- /dev/null +++ b/sys/ddb/db_command.h @@ -0,0 +1,67 @@ +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ +/* + * HISTORY + * $Log: db_command.h,v $ + * Revision 1.1 1992/03/25 21:45:05 pace + * Initial revision + * + * Revision 2.3 91/02/05 17:06:15 mrt + * Changed to new Mach copyright + * [91/01/31 16:17:28 mrt] + * + * Revision 2.2 90/08/27 21:50:19 dbg + * Replace db_last_address_examined with db_prev, db_next. + * [90/08/22 dbg] + * Created. + * [90/08/07 dbg] + * + */ +/* + * Author: David B. Golub, Carnegie Mellon University + * Date: 7/90 + */ +/* + * Command loop declarations. + */ + +#include "param.h" +#include "proc.h" +#include <machine/db_machdep.h> + +extern void db_command_loop(); +extern void db_skip_to_eol(); + +extern void db_error(/* char * */); /* report error */ + +extern db_addr_t db_dot; /* current location */ +extern db_addr_t db_last_addr; /* last explicit address typed */ +extern db_addr_t db_prev; /* last address examined + or written */ +extern db_addr_t db_next; /* next address to be examined + or written */ + + diff --git a/sys/ddb/db_examine.c b/sys/ddb/db_examine.c new file mode 100644 index 0000000..66f5f68 --- /dev/null +++ b/sys/ddb/db_examine.c @@ -0,0 +1,364 @@ +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ +/* + * HISTORY + * $Log: db_examine.c,v $ + * Revision 1.1 1992/03/25 21:45:07 pace + * Initial revision + * + * Revision 2.4 91/02/05 17:06:20 mrt + * Changed to new Mach copyright + * [91/01/31 16:17:37 mrt] + * + * Revision 2.3 90/11/07 16:49:23 rpd + * Added db_search_cmd, db_search. + * [90/11/06 rpd] + * + * Revision 2.2 90/08/27 21:50:38 dbg + * Add 'r', 'z' to print and examine formats. + * Change calling sequence of db_disasm. + * db_examine sets db_prev and db_next instead of explicitly + * advancing dot. + * [90/08/20 dbg] + * Reflected changes in db_printsym()'s calling seq. + * [90/08/20 af] + * Reduce lint. + * [90/08/07 dbg] + * Created. + * [90/07/25 dbg] + * + */ +/* + * Author: David B. Golub, Carnegie Mellon University + * Date: 7/90 + */ +#include "param.h" +#include "proc.h" +#include <machine/db_machdep.h> /* type definitions */ + +#include <ddb/db_lex.h> +#include <ddb/db_output.h> +#include <ddb/db_command.h> +#include <ddb/db_sym.h> + +char db_examine_format[TOK_STRING_SIZE] = "x"; + +extern db_addr_t db_disasm(/* db_addr_t, boolean_t */); + /* instruction disassembler */ + +/* + * Examine (print) data. + */ +/*ARGSUSED*/ +void +db_examine_cmd(addr, have_addr, count, modif) + db_expr_t addr; + int have_addr; + db_expr_t count; + char * modif; +{ + if (modif[0] != '\0') + db_strcpy(db_examine_format, modif); + + if (count == -1) + count = 1; + + db_examine((db_addr_t) addr, db_examine_format, count); +} + +db_examine(addr, fmt, count) + register + db_addr_t addr; + char * fmt; /* format string */ + int count; /* repeat count */ +{ + int c; + db_expr_t value; + int size; + int width; + char * fp; + + while (--count >= 0) { + fp = fmt; + size = 4; + width = 16; + while ((c = *fp++) != 0) { + switch (c) { + case 'b': + size = 1; + width = 4; + break; + case 'h': + size = 2; + width = 8; + break; + case 'l': + size = 4; + width = 16; + break; + case 'a': /* address */ + /* always forces a new line */ + if (db_print_position() != 0) + db_printf("\n"); + db_prev = addr; + db_printsym(addr, DB_STGY_ANY); + db_printf(":\t"); + break; + default: + if (db_print_position() == 0) { + /* If we hit a new symbol, print it */ + char * name; + db_expr_t off; + + db_find_sym_and_offset(addr, &name, &off); + if (off == 0) + db_printf("%s:\t", name); + else + db_printf("\t\t"); + + db_prev = addr; + } + + switch (c) { + case 'r': /* signed, current radix */ + value = db_get_value(addr, size, TRUE); + addr += size; + db_printf("%-*r", width, value); + break; + case 'x': /* unsigned hex */ + value = db_get_value(addr, size, FALSE); + addr += size; + db_printf("%-*x", width, value); + break; + case 'z': /* signed hex */ + value = db_get_value(addr, size, TRUE); + addr += size; + db_printf("%-*z", width, value); + break; + case 'd': /* signed decimal */ + value = db_get_value(addr, size, TRUE); + addr += size; + db_printf("%-*d", width, value); + break; + case 'u': /* unsigned decimal */ + value = db_get_value(addr, size, FALSE); + addr += size; + db_printf("%-*u", width, value); + break; + case 'o': /* unsigned octal */ + value = db_get_value(addr, size, FALSE); + addr += size; + db_printf("%-*o", width, value); + break; + case 'c': /* character */ + value = db_get_value(addr, 1, FALSE); + addr += 1; + if (value >= ' ' && value <= '~') + db_printf("%c", value); + else + db_printf("\\%03o", value); + break; + case 's': /* null-terminated string */ + for (;;) { + value = db_get_value(addr, 1, FALSE); + addr += 1; + if (value == 0) + break; + if (value >= ' ' && value <= '~') + db_printf("%c", value); + else + db_printf("\\%03o", value); + } + break; + case 'i': /* instruction */ + addr = db_disasm(addr, FALSE); + break; + case 'I': /* instruction, alternate form */ + addr = db_disasm(addr, TRUE); + break; + default: + break; + } + if (db_print_position() != 0) + db_end_line(); + break; + } + } + } + db_next = addr; +} + +/* + * Print value. + */ +char db_print_format = 'x'; + +/*ARGSUSED*/ +void +db_print_cmd(addr, have_addr, count, modif) + db_expr_t addr; + int have_addr; + db_expr_t count; + char * modif; +{ + db_expr_t value; + + if (modif[0] != '\0') + db_print_format = modif[0]; + + switch (db_print_format) { + case 'a': + db_printsym((db_addr_t)addr, DB_STGY_ANY); + break; + case 'r': + db_printf("%11r", addr); + break; + case 'x': + db_printf("%8x", addr); + break; + case 'z': + db_printf("%8z", addr); + break; + case 'd': + db_printf("%11d", addr); + break; + case 'u': + db_printf("%11u", addr); + break; + case 'o': + db_printf("%16o", addr); + break; + case 'c': + value = addr & 0xFF; + if (value >= ' ' && value <= '~') + db_printf("%c", value); + else + db_printf("\\%03o", value); + break; + } + db_printf("\n"); +} + +db_print_loc_and_inst(loc) + db_addr_t loc; +{ + db_printsym(loc, DB_STGY_PROC); + db_printf(":\t"); + (void) db_disasm(loc, TRUE); +} + +db_strcpy(dst, src) + register char *dst; + register char *src; +{ + while (*dst++ = *src++) + ; +} + +/* + * Search for a value in memory. + * Syntax: search [/bhl] addr value [mask] [,count] + */ +void +db_search_cmd() +{ + int t; + db_addr_t addr; + int size; + db_expr_t value; + db_expr_t mask; + unsigned int count; + + t = db_read_token(); + if (t == tSLASH) { + t = db_read_token(); + if (t != tIDENT) { + bad_modifier: + db_printf("Bad modifier\n"); + db_flush_lex(); + return; + } + + if (!strcmp(db_tok_string, "b")) + size = 1; + else if (!strcmp(db_tok_string, "h")) + size = 2; + else if (!strcmp(db_tok_string, "l")) + size = 4; + else + goto bad_modifier; + } else { + db_unread_token(t); + size = 4; + } + + if (!db_expression(&addr)) { + db_printf("Address missing\n"); + db_flush_lex(); + return; + } + + if (!db_expression(&value)) { + db_printf("Value missing\n"); + db_flush_lex(); + return; + } + + if (!db_expression(&mask)) + mask = 0xffffffff; + + t = db_read_token(); + if (t == tCOMMA) { + if (!db_expression(&count)) { + db_printf("Count missing\n"); + db_flush_lex(); + return; + } + } else { + db_unread_token(t); + count = -1; /* effectively forever */ + } + db_skip_to_eol(); + + db_search(addr, size, value, mask, count); +} + +db_search(addr, size, value, mask, count) + register + db_addr_t addr; + int size; + db_expr_t value; + db_expr_t mask; + unsigned int count; +{ + while (count-- != 0) { + db_prev = addr; + if ((db_get_value(addr, size, FALSE) & mask) == value) + break; + addr += size; + } + db_next = addr; +} diff --git a/sys/ddb/db_expr.c b/sys/ddb/db_expr.c new file mode 100644 index 0000000..062662c --- /dev/null +++ b/sys/ddb/db_expr.c @@ -0,0 +1,248 @@ +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ +/* + * HISTORY + * $Log: db_expr.c,v $ + * Revision 1.1 1992/03/25 21:45:09 pace + * Initial revision + * + * Revision 2.3 91/02/05 17:06:25 mrt + * Changed to new Mach copyright + * [91/01/31 16:17:46 mrt] + * + * Revision 2.2 90/08/27 21:50:57 dbg + * Use '..' instead of '$$' for db_prev. + * Use '+' for db_next. + * [90/08/22 dbg] + * + * Allow repeated unary operators. + * [90/08/20 dbg] + * + * Reflected back rename of db_symbol_value->db_value_of_name + * [90/08/20 af] + * Reduce lint. + * [90/08/07 dbg] + * Created. + * [90/07/25 dbg] + * + */ +/* + * Author: David B. Golub, Carnegie Mellon University + * Date: 7/90 + */ +#include "param.h" +#include "proc.h" +#include <machine/db_machdep.h> +#include <ddb/db_lex.h> +#include <ddb/db_access.h> +#include <ddb/db_command.h> + +boolean_t +db_term(valuep) + db_expr_t *valuep; +{ + int t; + + t = db_read_token(); + if (t == tIDENT) { + if (!db_value_of_name(db_tok_string, valuep)) { + db_error("Symbol not found\n"); + /*NOTREACHED*/ + } + return (TRUE); + } + if (t == tNUMBER) { + *valuep = (db_expr_t)db_tok_number; + return (TRUE); + } + if (t == tDOT) { + *valuep = (db_expr_t)db_dot; + return (TRUE); + } + if (t == tDOTDOT) { + *valuep = (db_expr_t)db_prev; + return (TRUE); + } + if (t == tPLUS) { + *valuep = (db_expr_t) db_next; + return (TRUE); + } + if (t == tDITTO) { + *valuep = (db_expr_t)db_last_addr; + return (TRUE); + } + if (t == tDOLLAR) { + if (!db_get_variable(valuep)) + return (FALSE); + return (TRUE); + } + if (t == tLPAREN) { + if (!db_expression(valuep)) { + db_error("Syntax error\n"); + /*NOTREACHED*/ + } + t = db_read_token(); + if (t != tRPAREN) { + db_error("Syntax error\n"); + /*NOTREACHED*/ + } + return (TRUE); + } + db_unread_token(t); + return (FALSE); +} + +boolean_t +db_unary(valuep) + db_expr_t *valuep; +{ + int t; + + t = db_read_token(); + if (t == tMINUS) { + if (!db_unary(valuep)) { + db_error("Syntax error\n"); + /*NOTREACHED*/ + } + *valuep = -*valuep; + return (TRUE); + } + if (t == tSTAR) { + /* indirection */ + if (!db_unary(valuep)) { + db_error("Syntax error\n"); + /*NOTREACHED*/ + } + *valuep = db_get_value((db_addr_t)*valuep, sizeof(int), FALSE); + return (TRUE); + } + db_unread_token(t); + return (db_term(valuep)); +} + +boolean_t +db_mult_expr(valuep) + db_expr_t *valuep; +{ + db_expr_t lhs, rhs; + int t; + + if (!db_unary(&lhs)) + return (FALSE); + + t = db_read_token(); + while (t == tSTAR || t == tSLASH || t == tPCT || t == tHASH) { + if (!db_term(&rhs)) { + db_error("Syntax error\n"); + /*NOTREACHED*/ + } + if (t == tSTAR) + lhs *= rhs; + else { + if (rhs == 0) { + db_error("Divide by 0\n"); + /*NOTREACHED*/ + } + if (t == tSLASH) + lhs /= rhs; + else if (t == tPCT) + lhs %= rhs; + else + lhs = ((lhs+rhs-1)/rhs)*rhs; + } + t = db_read_token(); + } + db_unread_token(t); + *valuep = lhs; + return (TRUE); +} + +boolean_t +db_add_expr(valuep) + db_expr_t *valuep; +{ + db_expr_t lhs, rhs; + int t; + + if (!db_mult_expr(&lhs)) + return (FALSE); + + t = db_read_token(); + while (t == tPLUS || t == tMINUS) { + if (!db_mult_expr(&rhs)) { + db_error("Syntax error\n"); + /*NOTREACHED*/ + } + if (t == tPLUS) + lhs += rhs; + else + lhs -= rhs; + t = db_read_token(); + } + db_unread_token(t); + *valuep = lhs; + return (TRUE); +} + +boolean_t +db_shift_expr(valuep) + db_expr_t *valuep; +{ + db_expr_t lhs, rhs; + int t; + + if (!db_add_expr(&lhs)) + return (FALSE); + + t = db_read_token(); + while (t == tSHIFT_L || t == tSHIFT_R) { + if (!db_add_expr(&rhs)) { + db_error("Syntax error\n"); + /*NOTREACHED*/ + } + if (rhs < 0) { + db_error("Negative shift amount\n"); + /*NOTREACHED*/ + } + if (t == tSHIFT_L) + lhs <<= rhs; + else { + /* Shift right is unsigned */ + lhs = (unsigned) lhs >> rhs; + } + t = db_read_token(); + } + db_unread_token(t); + *valuep = lhs; + return (TRUE); +} + +int +db_expression(valuep) + db_expr_t *valuep; +{ + return (db_shift_expr(valuep)); +} diff --git a/sys/ddb/db_input.c b/sys/ddb/db_input.c new file mode 100644 index 0000000..5ec7824 --- /dev/null +++ b/sys/ddb/db_input.c @@ -0,0 +1,268 @@ +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ +/* + * HISTORY + * $Log: db_input.c,v $ + * Revision 1.1 1992/03/25 21:45:10 pace + * Initial revision + * + * Revision 2.4 91/02/14 14:41:53 mrt + * Add input line editing. + * [90/11/11 dbg] + * + * Revision 2.3 91/02/05 17:06:32 mrt + * Changed to new Mach copyright + * [91/01/31 16:18:13 mrt] + * + * Revision 2.2 90/08/27 21:51:03 dbg + * Reduce lint. + * [90/08/07 dbg] + * Created. + * [90/07/25 dbg] + * + */ +/* + * Author: David B. Golub, Carnegie Mellon University + * Date: 7/90 + */ + +#include "param.h" +#include "proc.h" +#include <ddb/db_output.h> + +/* + * Character input and editing. + */ + +/* + * We don't track output position while editing input, + * since input always ends with a new-line. We just + * reset the line position at the end. + */ +char * db_lbuf_start; /* start of input line buffer */ +char * db_lbuf_end; /* end of input line buffer */ +char * db_lc; /* current character */ +char * db_le; /* one past last character */ + +#define CTRL(c) ((c) & 0x1f) +#define isspace(c) ((c) == ' ' || (c) == '\t') +#define BLANK ' ' +#define BACKUP '\b' + +void +db_putstring(s, count) + char *s; + int count; +{ + while (--count >= 0) + cnputc(*s++); +} + +void +db_putnchars(c, count) + int c; + int count; +{ + while (--count >= 0) + cnputc(c); +} + +/* + * Delete N characters, forward or backward + */ +#define DEL_FWD 0 +#define DEL_BWD 1 +void +db_delete(n, bwd) + int n; + int bwd; +{ + register char *p; + + if (bwd) { + db_lc -= n; + db_putnchars(BACKUP, n); + } + for (p = db_lc; p < db_le-n; p++) { + *p = *(p+n); + cnputc(*p); + } + db_putnchars(BLANK, n); + db_putnchars(BACKUP, db_le - db_lc); + db_le -= n; +} + +/* returns TRUE at end-of-line */ +int +db_inputchar(c) + int c; +{ + switch (c) { + case CTRL('b'): + /* back up one character */ + if (db_lc > db_lbuf_start) { + cnputc(BACKUP); + db_lc--; + } + break; + case CTRL('f'): + /* forward one character */ + if (db_lc < db_le) { + cnputc(*db_lc); + db_lc++; + } + break; + case CTRL('a'): + /* beginning of line */ + while (db_lc > db_lbuf_start) { + cnputc(BACKUP); + db_lc--; + } + break; + case CTRL('e'): + /* end of line */ + while (db_lc < db_le) { + cnputc(*db_lc); + db_lc++; + } + break; + case CTRL('h'): + case 0177: + /* erase previous character */ + if (db_lc > db_lbuf_start) + db_delete(1, DEL_BWD); + break; + case CTRL('d'): + /* erase next character */ + if (db_lc < db_le) + db_delete(1, DEL_FWD); + break; + case CTRL('k'): + /* delete to end of line */ + if (db_lc < db_le) + db_delete(db_le - db_lc, DEL_FWD); + break; + case CTRL('t'): + /* twiddle last 2 characters */ + if (db_lc >= db_lbuf_start + 2) { + c = db_lc[-2]; + db_lc[-2] = db_lc[-1]; + db_lc[-1] = c; + cnputc(BACKUP); + cnputc(BACKUP); + cnputc(db_lc[-2]); + cnputc(db_lc[-1]); + } + break; + case CTRL('r'): + db_putstring("^R\n", 3); + if (db_le > db_lbuf_start) { + db_putstring(db_lbuf_start, db_le - db_lbuf_start); + db_putnchars(BACKUP, db_le - db_lc); + } + break; + case '\n': + case '\r': + *db_le++ = c; + return (1); + default: + if (db_le == db_lbuf_end) { + cnputc('\007'); + } + else if (c >= ' ' && c <= '~') { + register char *p; + + for (p = db_le; p > db_lc; p--) + *p = *(p-1); + *db_lc++ = c; + db_le++; + cnputc(c); + db_putstring(db_lc, db_le - db_lc); + db_putnchars(BACKUP, db_le - db_lc); + } + break; + } + return (0); +} + +int +db_readline(lstart, lsize) + char * lstart; + int lsize; +{ + db_force_whitespace(); /* synch output position */ + + db_lbuf_start = lstart; + db_lbuf_end = lstart + lsize; + db_lc = lstart; + db_le = lstart; + + while (!db_inputchar(cngetc())) + continue; + + db_putchar('\n'); /* synch output position */ + + *db_le = 0; + return (db_le - db_lbuf_start); +} + +void +db_check_interrupt() +{ + register int c; + + c = cnmaygetc(); + switch (c) { + case -1: /* no character */ + return; + + case CTRL('c'): + db_error((char *)0); + /*NOTREACHED*/ + + case CTRL('s'): + do { + c = cnmaygetc(); + if (c == CTRL('c')) + db_error((char *)0); + } while (c != CTRL('q')); + break; + + default: + /* drop on floor */ + break; + } +} + +cnmaygetc () +{ + return (-1); +} + +/* called from kdb_trap in db_interface.c */ +cnpollc (flag) +{ +} diff --git a/sys/ddb/db_lex.c b/sys/ddb/db_lex.c new file mode 100644 index 0000000..dcfd900 --- /dev/null +++ b/sys/ddb/db_lex.c @@ -0,0 +1,295 @@ +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ +/* + * HISTORY + * $Log: db_lex.c,v $ + * Revision 1.1 1992/03/25 21:45:13 pace + * Initial revision + * + * Revision 2.3 91/02/05 17:06:36 mrt + * Changed to new Mach copyright + * [91/01/31 16:18:20 mrt] + * + * Revision 2.2 90/08/27 21:51:10 dbg + * Add 'dotdot' token. + * [90/08/22 dbg] + * + * Allow backslash to quote any character into an identifier. + * Allow colon in identifier for symbol table qualification. + * [90/08/16 dbg] + * Reduce lint. + * [90/08/07 dbg] + * Created. + * [90/07/25 dbg] + * + */ +/* + * Author: David B. Golub, Carnegie Mellon University + * Date: 7/90 + */ +/* + * Lexical analyzer. + */ +#include <ddb/db_lex.h> + +char db_line[120]; +char * db_lp, *db_endlp; + +int +db_read_line() +{ + int i; + + i = db_readline(db_line, sizeof(db_line)); + if (i == 0) + return (0); /* EOI */ + db_lp = db_line; + db_endlp = db_lp + i; + return (i); +} + +void +db_flush_line() +{ + db_lp = db_line; + db_endlp = db_line; +} + +int db_look_char = 0; + +int +db_read_char() +{ + int c; + + if (db_look_char != 0) { + c = db_look_char; + db_look_char = 0; + } + else if (db_lp >= db_endlp) + c = -1; + else + c = *db_lp++; + return (c); +} + +void +db_unread_char(c) +{ + db_look_char = c; +} + +int db_look_token = 0; + +void +db_unread_token(t) + int t; +{ + db_look_token = t; +} + +int +db_read_token() +{ + int t; + + if (db_look_token) { + t = db_look_token; + db_look_token = 0; + } + else + t = db_lex(); + return (t); +} + +int db_tok_number; +char db_tok_string[TOK_STRING_SIZE]; + +int db_radix = 16; + +void +db_flush_lex() +{ + db_flush_line(); + db_look_char = 0; + db_look_token = 0; +} + +int +db_lex() +{ + int c; + + c = db_read_char(); + while (c <= ' ' || c > '~') { + if (c == '\n' || c == -1) + return (tEOL); + c = db_read_char(); + } + + if (c >= '0' && c <= '9') { + /* number */ + int r, digit; + + if (c > '0') + r = db_radix; + else { + c = db_read_char(); + if (c == 'O' || c == 'o') + r = 8; + else if (c == 'T' || c == 't') + r = 10; + else if (c == 'X' || c == 'x') + r = 16; + else { + r = db_radix; + db_unread_char(c); + } + c = db_read_char(); + } + db_tok_number = 0; + for (;;) { + if (c >= '0' && c <= ((r == 8) ? '7' : '9')) + digit = c - '0'; + else if (r == 16 && ((c >= 'A' && c <= 'F') || + (c >= 'a' && c <= 'f'))) { + if (c >= 'a') + digit = c - 'a' + 10; + else if (c >= 'A') + digit = c - 'A' + 10; + } + else + break; + db_tok_number = db_tok_number * r + digit; + c = db_read_char(); + } + if ((c >= '0' && c <= '9') || + (c >= 'A' && c <= 'Z') || + (c >= 'a' && c <= 'z') || + (c == '_')) + { + db_error("Bad character in number\n"); + db_flush_lex(); + return (tEOF); + } + db_unread_char(c); + return (tNUMBER); + } + if ((c >= 'A' && c <= 'Z') || + (c >= 'a' && c <= 'z') || + c == '_' || c == '\\') + { + /* string */ + char *cp; + + cp = db_tok_string; + if (c == '\\') { + c = db_read_char(); + if (c == '\n' || c == -1) + db_error("Bad escape\n"); + } + *cp++ = c; + while (1) { + c = db_read_char(); + if ((c >= 'A' && c <= 'Z') || + (c >= 'a' && c <= 'z') || + (c >= '0' && c <= '9') || + c == '_' || c == '\\' || c == ':') + { + if (c == '\\') { + c = db_read_char(); + if (c == '\n' || c == -1) + db_error("Bad escape\n"); + } + *cp++ = c; + if (cp == db_tok_string+sizeof(db_tok_string)) { + db_error("String too long\n"); + db_flush_lex(); + return (tEOF); + } + continue; + } + else { + *cp = '\0'; + break; + } + } + db_unread_char(c); + return (tIDENT); + } + + switch (c) { + case '+': + return (tPLUS); + case '-': + return (tMINUS); + case '.': + c = db_read_char(); + if (c == '.') + return (tDOTDOT); + db_unread_char(c); + return (tDOT); + case '*': + return (tSTAR); + case '/': + return (tSLASH); + case '=': + return (tEQ); + case '%': + return (tPCT); + case '#': + return (tHASH); + case '(': + return (tLPAREN); + case ')': + return (tRPAREN); + case ',': + return (tCOMMA); + case '"': + return (tDITTO); + case '$': + return (tDOLLAR); + case '!': + return (tEXCL); + case '<': + c = db_read_char(); + if (c == '<') + return (tSHIFT_L); + db_unread_char(c); + break; + case '>': + c = db_read_char(); + if (c == '>') + return (tSHIFT_R); + db_unread_char(c); + break; + case -1: + return (tEOF); + } + db_printf("Bad character\n"); + db_flush_lex(); + return (tEOF); +} diff --git a/sys/ddb/db_lex.h b/sys/ddb/db_lex.h new file mode 100644 index 0000000..56c5569 --- /dev/null +++ b/sys/ddb/db_lex.h @@ -0,0 +1,89 @@ +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ +/* + * HISTORY + * $Log: db_lex.h,v $ + * Revision 1.1 1992/03/25 21:45:15 pace + * Initial revision + * + * Revision 2.3 91/02/05 17:06:41 mrt + * Changed to new Mach copyright + * [91/01/31 16:18:28 mrt] + * + * Revision 2.2 90/08/27 21:51:16 dbg + * Add 'dotdot' token. + * [90/08/22 dbg] + * Export db_flush_lex. + * [90/08/07 dbg] + * Created. + * [90/07/25 dbg] + * + */ +/* + * Author: David B. Golub, Carnegie Mellon University + * Date: 7/90 + */ +/* + * Lexical analyzer. + */ +extern int db_read_line(); +extern void db_flush_line(); +extern int db_read_char(); +extern void db_unread_char(/* char c */); +extern int db_read_token(); +extern void db_unread_token(/* int t */); +extern void db_flush_lex(); + +extern int db_tok_number; +#define TOK_STRING_SIZE 120 +extern char db_tok_string[TOK_STRING_SIZE]; +extern int db_radix; + +#define tEOF (-1) +#define tEOL 1 +#define tNUMBER 2 +#define tIDENT 3 +#define tPLUS 4 +#define tMINUS 5 +#define tDOT 6 +#define tSTAR 7 +#define tSLASH 8 +#define tEQ 9 +#define tLPAREN 10 +#define tRPAREN 11 +#define tPCT 12 +#define tHASH 13 +#define tCOMMA 14 +#define tDITTO 15 +#define tDOLLAR 16 +#define tEXCL 17 +#define tSHIFT_L 18 +#define tSHIFT_R 19 +#define tDOTDOT 20 + + + + diff --git a/sys/ddb/db_output.c b/sys/ddb/db_output.c new file mode 100644 index 0000000..fc8fca7 --- /dev/null +++ b/sys/ddb/db_output.c @@ -0,0 +1,389 @@ +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + * + * PATCHES MAGIC LEVEL PATCH THAT GOT US HERE + * -------------------- ----- ---------------------- + * CURRENT PATCH LEVEL: 4 00083 + * -------------------- ----- ---------------------- + * + * 14 Mar 93 Chris G. Demetriou Fixed so that tab is not output, + * use spaces instead. + */ +/* + * HISTORY + * $Log: db_output.c,v $ + * Revision 1.1 1992/03/25 21:45:18 pace + * Initial revision + * + * Revision 2.3 91/02/05 17:06:45 mrt + * Changed to new Mach copyright + * [91/01/31 16:18:41 mrt] + * + * Revision 2.2 90/08/27 21:51:25 dbg + * Put extra features of db_doprnt in _doprnt. + * [90/08/20 dbg] + * Reduce lint. + * [90/08/07 dbg] + * Created. + * [90/07/25 dbg] + * + */ +/* + * Author: David B. Golub, Carnegie Mellon University + * Date: 7/90 + */ + +/* + * Printf and character output for debugger. + */ + +#include "param.h" +#include <machine/stdarg.h> + +/* + * Character output - tracks position in line. + * To do this correctly, we should know how wide + * the output device is - then we could zero + * the line position when the output device wraps + * around to the start of the next line. + * + * Instead, we count the number of spaces printed + * since the last printing character so that we + * don't print trailing spaces. This avoids most + * of the wraparounds. + */ +int db_output_position = 0; /* output column */ +int db_last_non_space = 0; /* last non-space character */ +int db_tab_stop_width = 8; /* how wide are tab stops? */ +#define NEXT_TAB(i) \ + ((((i) + db_tab_stop_width) / db_tab_stop_width) * db_tab_stop_width) +int db_max_width = 80; /* output line width */ + +extern void db_check_interrupt(); + +/* + * Force pending whitespace. + */ +void +db_force_whitespace() +{ + register int last_print, next_tab; + + last_print = db_last_non_space; + while (last_print < db_output_position) { + next_tab = NEXT_TAB(last_print); + if (next_tab <= db_output_position) { + while (last_print < next_tab) { /* DON'T send a tab!!! */ + cnputc(' '); + last_print++; + } + } + else { + cnputc(' '); + last_print++; + } + } + db_last_non_space = db_output_position; +} + +/* + * Output character. Buffer whitespace. + */ +db_putchar(c) + int c; /* character to output */ +{ + if (c > ' ' && c <= '~') { + /* + * Printing character. + * If we have spaces to print, print them first. + * Use tabs if possible. + */ + db_force_whitespace(); + cnputc(c); + db_output_position++; + db_last_non_space = db_output_position; + } + else if (c == '\n') { + /* Return */ + cnputc(c); + db_output_position = 0; + db_last_non_space = 0; + db_check_interrupt(); + } + else if (c == '\t') { + /* assume tabs every 8 positions */ + db_output_position = NEXT_TAB(db_output_position); + } + else if (c == ' ') { + /* space */ + db_output_position++; + } + else if (c == '\007') { + /* bell */ + cnputc(c); + } + /* other characters are assumed non-printing */ +} + +/* + * Return output position + */ +int +db_print_position() +{ + return (db_output_position); +} + +/* + * End line if too long. + */ +void +db_end_line() +{ + if (db_output_position >= db_max_width) + db_printf("\n"); +} + +/* + * Printing + */ +extern int db_radix; + +/*VARARGS1*/ +db_printf(char *fmt, ...) +{ + va_list listp; + va_start(listp, fmt); + db_printf_guts (fmt, listp); + va_end(listp); +} + +/* alternate name */ + +/*VARARGS1*/ +kdbprintf(char *fmt, ...) +{ + va_list listp; + va_start(listp, fmt); + db_printf_guts (fmt, listp); + va_end(listp); +} + +/* + * Put a number (base <= 16) in a buffer in reverse order; return an + * optional length and a pointer to the NULL terminated (preceded?) + * buffer. + */ +static char * +db_ksprintn(ul, base, lenp) + register u_long ul; + register int base, *lenp; +{ /* A long in base 8, plus NULL. */ + static char buf[sizeof(long) * NBBY / 3 + 2]; + register char *p; + + p = buf; + do { + *++p = "0123456789abcdef"[ul % base]; + } while (ul /= base); + if (lenp) + *lenp = p - buf; + return (p); +} + +db_printf_guts(fmt, ap) + register const char *fmt; + va_list ap; +{ + register char *p; + register int ch, n; + u_long ul; + int base, lflag, tmp, width; + char padc; + int ladjust; + int sharpflag; + int neg; + + for (;;) { + padc = ' '; + width = 0; + while ((ch = *(u_char *)fmt++) != '%') { + if (ch == '\0') + return; + db_putchar(ch); + } + lflag = 0; + ladjust = 0; + sharpflag = 0; + neg = 0; +reswitch: switch (ch = *(u_char *)fmt++) { + case '0': + padc = '0'; + goto reswitch; + case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + for (width = 0;; ++fmt) { + width = width * 10 + ch - '0'; + ch = *fmt; + if (ch < '0' || ch > '9') + break; + } + goto reswitch; + case 'l': + lflag = 1; + goto reswitch; + case '-': + ladjust = 1; + goto reswitch; + case '#': + sharpflag = 1; + goto reswitch; + case 'b': + ul = va_arg(ap, int); + p = va_arg(ap, char *); + for (p = db_ksprintn(ul, *p++, NULL); ch = *p--;) + db_putchar(ch); + + if (!ul) + break; + + for (tmp = 0; n = *p++;) { + if (ul & (1 << (n - 1))) { + db_putchar(tmp ? ',' : '<'); + for (; (n = *p) > ' '; ++p) + db_putchar(n); + tmp = 1; + } else + for (; *p > ' '; ++p); + } + if (tmp) + db_putchar('>'); + break; + case '*': + width = va_arg (ap, int); + if (width < 0) { + ladjust = !ladjust; + width = -width; + } + goto reswitch; + case 'c': + db_putchar(va_arg(ap, int)); + break; + case 's': + p = va_arg(ap, char *); + width -= strlen (p); + if (!ladjust && width > 0) + while (width--) + db_putchar (padc); + while (ch = *p++) + db_putchar(ch); + if (ladjust && width > 0) + while (width--) + db_putchar (padc); + break; + case 'r': + ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); + if ((long)ul < 0) { + neg = 1; + ul = -(long)ul; + } + base = db_radix; + if (base < 8 || base > 16) + base = 10; + goto number; + case 'n': + ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); + base = db_radix; + if (base < 8 || base > 16) + base = 10; + goto number; + case 'd': + ul = lflag ? va_arg(ap, long) : va_arg(ap, int); + if ((long)ul < 0) { + neg = 1; + ul = -(long)ul; + } + base = 10; + goto number; + case 'o': + ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); + base = 8; + goto number; + case 'u': + ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); + base = 10; + goto number; + case 'z': + ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); + if ((long)ul < 0) { + neg = 1; + ul = -(long)ul; + } + base = 16; + goto number; + case 'x': + ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); + base = 16; +number: p = (char *)db_ksprintn(ul, base, &tmp); + if (sharpflag && ul != 0) { + if (base == 8) + tmp++; + else if (base == 16) + tmp += 2; + } + if (neg) + tmp++; + + if (!ladjust && width && (width -= tmp) > 0) + while (width--) + db_putchar(padc); + if (neg) + db_putchar ('-'); + if (sharpflag && ul != 0) { + if (base == 8) { + db_putchar ('0'); + } else if (base == 16) { + db_putchar ('0'); + db_putchar ('x'); + } + } + if (ladjust && width && (width -= tmp) > 0) + while (width--) + db_putchar(padc); + + while (ch = *p--) + db_putchar(ch); + break; + default: + db_putchar('%'); + if (lflag) + db_putchar('l'); + /* FALLTHROUGH */ + case '%': + db_putchar(ch); + } + } +} + diff --git a/sys/ddb/db_output.h b/sys/ddb/db_output.h new file mode 100644 index 0000000..3ad599d --- /dev/null +++ b/sys/ddb/db_output.h @@ -0,0 +1,53 @@ +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ +/* + * HISTORY + * $Log: db_output.h,v $ + * Revision 1.1 1992/03/25 21:45:20 pace + * Initial revision + * + * Revision 2.3 91/02/05 17:06:49 mrt + * Changed to new Mach copyright + * [91/01/31 16:18:48 mrt] + * + * Revision 2.2 90/08/27 21:51:32 dbg + * Created. + * [90/08/07 dbg] + * + */ +/* + * Author: David B. Golub, Carnegie Mellon University + * Date: 8/90 + */ + +/* + * Printing routines for kernel debugger. + */ + +extern void db_force_whitespace(); +extern int db_print_position(); +extern void db_end_line(); +extern int db_printf(); diff --git a/sys/ddb/db_print.c b/sys/ddb/db_print.c new file mode 100644 index 0000000..48eef38 --- /dev/null +++ b/sys/ddb/db_print.c @@ -0,0 +1,104 @@ +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ +/* + * HISTORY + * $Log: db_print.c,v $ + * Revision 1.1 1992/03/25 21:45:22 pace + * Initial revision + * + * Revision 2.5 91/02/05 17:06:53 mrt + * Changed to new Mach copyright + * [91/01/31 16:18:56 mrt] + * + * Revision 2.4 90/10/25 14:43:54 rwd + * Changed db_show_regs to print unsigned. + * [90/10/19 rpd] + * Generalized the watchpoint support. + * [90/10/16 rwd] + * + * Revision 2.3 90/09/09 23:19:52 rpd + * Avoid totally incorrect guesses of symbol names for small values. + * [90/08/30 17:39:08 af] + * + * Revision 2.2 90/08/27 21:51:49 dbg + * Insist that 'show thread' be called with an explicit address. + * [90/08/22 dbg] + * + * Fix type for db_maxoff. + * [90/08/20 dbg] + * + * Do not dereference the "valuep" field of a variable directly, + * call the new db_read/write_variable functions instead. + * Reflected changes in symbol lookup functions. + * [90/08/20 af] + * Reduce lint. + * [90/08/10 14:33:44 dbg] + * + * Created. + * [90/07/25 dbg] + * + */ +/* + * Author: David B. Golub, Carnegie Mellon University + * Date: 7/90 + */ + +/* + * Miscellaneous printing. + */ +#include "param.h" +#include "proc.h" + +#include <machine/db_machdep.h> + +#include <ddb/db_lex.h> +#include <ddb/db_variables.h> +#include <ddb/db_sym.h> + +extern unsigned int db_maxoff; + +void +db_show_regs() +{ + int (*func)(); + register struct db_variable *regp; + db_expr_t value, offset; + char * name; + + for (regp = db_regs; regp < db_eregs; regp++) { + db_read_variable(regp, &value); + db_printf("%-12s%#10n", regp->name, value); + db_find_xtrn_sym_and_offset((db_addr_t)value, &name, &offset); + if (name != 0 && offset <= db_maxoff && offset != value) { + db_printf("\t%s", name); + if (offset != 0) + db_printf("+%#r", offset); + } + db_printf("\n"); + } + db_print_loc_and_inst(PC_REGS(DDB_REGS)); +} + diff --git a/sys/ddb/db_run.c b/sys/ddb/db_run.c new file mode 100644 index 0000000..b8e33aa --- /dev/null +++ b/sys/ddb/db_run.c @@ -0,0 +1,426 @@ +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ +/* + * HISTORY + * $Log: db_run.c,v $ + * Revision 1.1 1992/03/25 21:45:24 pace + * Initial revision + * + * Revision 2.5 91/02/05 17:06:58 mrt + * Changed to new Mach copyright + * [91/01/31 16:19:05 mrt] + * + * Revision 2.4 91/01/08 15:09:10 rpd + * Fixed bug in db_restart_at_pc. + * [90/12/07 rpd] + * Added STEP_COUNT and count option to db_continue_cmd. + * Changed db_stop_at_pc to return (modified) is_breakpoint. + * Fixed db_stop_at_pc to print newlines in the right places. + * [90/11/27 rpd] + * + * Revision 2.3 90/10/25 14:43:59 rwd + * Changed db_find_breakpoint to db_find_breakpoint_here. + * [90/10/18 rpd] + * + * Fixed db_set_single_step to pass regs to branch_taken. + * Added watchpoint argument to db_restart_at_pc. + * [90/10/17 rpd] + * Generalized the watchpoint support. + * [90/10/16 rwd] + * Added watchpoint support. + * [90/10/16 rpd] + * + * Revision 2.2 90/08/27 21:51:59 dbg + * Fixed names for single-step functions. + * [90/08/20 af] + * Reduce lint. + * [90/08/07 dbg] + * Created. + * [90/07/25 dbg] + * + */ +/* + * Author: David B. Golub, Carnegie Mellon University + * Date: 7/90 + */ + +/* + * Commands to run process. + */ +#include "param.h" +#include "proc.h" +#include <machine/db_machdep.h> + +#include <ddb/db_lex.h> +#include <ddb/db_break.h> +#include <ddb/db_access.h> + +int db_run_mode; +#define STEP_NONE 0 +#define STEP_ONCE 1 +#define STEP_RETURN 2 +#define STEP_CALLT 3 +#define STEP_CONTINUE 4 +#define STEP_INVISIBLE 5 +#define STEP_COUNT 6 + +boolean_t db_sstep_print; +int db_loop_count; +int db_call_depth; + +int db_inst_count; +int db_load_count; +int db_store_count; + +#ifndef db_set_single_step +void db_set_single_step(/* db_regs_t *regs */); /* forward */ +#endif +#ifndef db_clear_single_step +void db_clear_single_step(/* db_regs_t *regs */); +#endif + +boolean_t +db_stop_at_pc(is_breakpoint) + boolean_t *is_breakpoint; +{ + register db_addr_t pc; + register db_breakpoint_t bkpt; + + db_clear_single_step(DDB_REGS); + db_clear_breakpoints(); + db_clear_watchpoints(); + pc = PC_REGS(DDB_REGS); + +#ifdef FIXUP_PC_AFTER_BREAK + if (*is_breakpoint) { + /* + * Breakpoint trap. Fix up the PC if the + * machine requires it. + */ + FIXUP_PC_AFTER_BREAK + pc = PC_REGS(DDB_REGS); + } +#endif + + /* + * Now check for a breakpoint at this address. + */ + bkpt = db_find_breakpoint_here(pc); + if (bkpt) { + if (--bkpt->count == 0) { + bkpt->count = bkpt->init_count; + *is_breakpoint = TRUE; + return (TRUE); /* stop here */ + } + } else if (*is_breakpoint) { + ddb_regs.tf_eip += 1; + } + + *is_breakpoint = FALSE; + + if (db_run_mode == STEP_INVISIBLE) { + db_run_mode = STEP_CONTINUE; + return (FALSE); /* continue */ + } + if (db_run_mode == STEP_COUNT) { + return (FALSE); /* continue */ + } + if (db_run_mode == STEP_ONCE) { + if (--db_loop_count > 0) { + if (db_sstep_print) { + db_printf("\t\t"); + db_print_loc_and_inst(pc); + db_printf("\n"); + } + return (FALSE); /* continue */ + } + } + if (db_run_mode == STEP_RETURN) { + db_expr_t ins = db_get_value(pc, sizeof(int), FALSE); + + /* continue until matching return */ + + if (!inst_trap_return(ins) && + (!inst_return(ins) || --db_call_depth != 0)) { + if (db_sstep_print) { + if (inst_call(ins) || inst_return(ins)) { + register int i; + + db_printf("[after %6d] ", db_inst_count); + for (i = db_call_depth; --i > 0; ) + db_printf(" "); + db_print_loc_and_inst(pc); + db_printf("\n"); + } + } + if (inst_call(ins)) + db_call_depth++; + return (FALSE); /* continue */ + } + } + if (db_run_mode == STEP_CALLT) { + db_expr_t ins = db_get_value(pc, sizeof(int), FALSE); + + /* continue until call or return */ + + if (!inst_call(ins) && + !inst_return(ins) && + !inst_trap_return(ins)) { + return (FALSE); /* continue */ + } + } + db_run_mode = STEP_NONE; + return (TRUE); +} + +void +db_restart_at_pc(watchpt) + boolean_t watchpt; +{ + register db_addr_t pc = PC_REGS(DDB_REGS); + + if ((db_run_mode == STEP_COUNT) || + (db_run_mode == STEP_RETURN) || + (db_run_mode == STEP_CALLT)) { + db_expr_t ins; + + /* + * We are about to execute this instruction, + * so count it now. + */ + + ins = db_get_value(pc, sizeof(int), FALSE); + db_inst_count++; + db_load_count += inst_load(ins); + db_store_count += inst_store(ins); +#ifdef SOFTWARE_SSTEP + /* XXX works on mips, but... */ + if (inst_branch(ins) || inst_call(ins)) { + ins = db_get_value(next_instr_address(pc,1), + sizeof(int), FALSE); + db_inst_count++; + db_load_count += inst_load(ins); + db_store_count += inst_store(ins); + } +#endif SOFTWARE_SSTEP + } + + if (db_run_mode == STEP_CONTINUE) { + if (watchpt || db_find_breakpoint_here(pc)) { + /* + * Step over breakpoint/watchpoint. + */ + db_run_mode = STEP_INVISIBLE; + db_set_single_step(DDB_REGS); + } else { + db_set_breakpoints(); + db_set_watchpoints(); + } + } else { + db_set_single_step(DDB_REGS); + } +} + +void +db_single_step(regs) + db_regs_t *regs; +{ + if (db_run_mode == STEP_CONTINUE) { + db_run_mode = STEP_INVISIBLE; + db_set_single_step(regs); + } +} + +#ifdef SOFTWARE_SSTEP +/* + * Software implementation of single-stepping. + * If your machine does not have a trace mode + * similar to the vax or sun ones you can use + * this implementation, done for the mips. + * Just define the above conditional and provide + * the functions/macros defined below. + * + * extern boolean_t + * inst_branch(), returns true if the instruction might branch + * extern unsigned + * branch_taken(), return the address the instruction might + * branch to + * db_getreg_val(); return the value of a user register, + * as indicated in the hardware instruction + * encoding, e.g. 8 for r8 + * + * next_instr_address(pc,bd) returns the address of the first + * instruction following the one at "pc", + * which is either in the taken path of + * the branch (bd==1) or not. This is + * for machines (mips) with branch delays. + * + * A single-step may involve at most 2 breakpoints - + * one for branch-not-taken and one for branch taken. + * If one of these addresses does not already have a breakpoint, + * we allocate a breakpoint and save it here. + * These breakpoints are deleted on return. + */ +db_breakpoint_t db_not_taken_bkpt = 0; +db_breakpoint_t db_taken_bkpt = 0; + +void +db_set_single_step(regs) + register db_regs_t *regs; +{ + db_addr_t pc = PC_REGS(regs); + register unsigned inst, brpc; + + /* + * User was stopped at pc, e.g. the instruction + * at pc was not executed. + */ + inst = db_get_value(pc, sizeof(int), FALSE); + if (inst_branch(inst) || inst_call(inst)) { + extern unsigned getreg_val(); + + brpc = branch_taken(inst, pc, getreg_val, regs); + if (brpc != pc) { /* self-branches are hopeless */ + db_taken_bkpt = db_set_temp_breakpoint(brpc); + } + pc = next_instr_address(pc,1); + } + pc = next_instr_address(pc,0); + db_not_taken_bkpt = db_set_temp_breakpoint(pc); +} + +void +db_clear_single_step(regs) + db_regs_t *regs; +{ + register db_breakpoint_t bkpt; + + if (db_taken_bkpt != 0) { + db_delete_temp_breakpoint(db_taken_bkpt); + db_taken_bkpt = 0; + } + if (db_not_taken_bkpt != 0) { + db_delete_temp_breakpoint(db_not_taken_bkpt); + db_not_taken_bkpt = 0; + } +} + +#endif SOFTWARE_SSTEP + +extern int db_cmd_loop_done; + +/* single-step */ +/*ARGSUSED*/ +void +db_single_step_cmd(addr, have_addr, count, modif) + db_expr_t addr; + int have_addr; + db_expr_t count; + char * modif; +{ + boolean_t print = FALSE; + + if (count == -1) + count = 1; + + if (modif[0] == 'p') + print = TRUE; + + db_run_mode = STEP_ONCE; + db_loop_count = count; + db_sstep_print = print; + db_inst_count = 0; + db_load_count = 0; + db_store_count = 0; + + db_cmd_loop_done = 1; +} + +/* trace and print until call/return */ +/*ARGSUSED*/ +void +db_trace_until_call_cmd(addr, have_addr, count, modif) + db_expr_t addr; + int have_addr; + db_expr_t count; + char * modif; +{ + boolean_t print = FALSE; + + if (modif[0] == 'p') + print = TRUE; + + db_run_mode = STEP_CALLT; + db_sstep_print = print; + db_inst_count = 0; + db_load_count = 0; + db_store_count = 0; + + db_cmd_loop_done = 1; +} + +/*ARGSUSED*/ +void +db_trace_until_matching_cmd(addr, have_addr, count, modif) + db_expr_t addr; + int have_addr; + db_expr_t count; + char * modif; +{ + boolean_t print = FALSE; + + if (modif[0] == 'p') + print = TRUE; + + db_run_mode = STEP_RETURN; + db_call_depth = 1; + db_sstep_print = print; + db_inst_count = 0; + db_load_count = 0; + db_store_count = 0; + + db_cmd_loop_done = 1; +} + +/* continue */ +/*ARGSUSED*/ +void +db_continue_cmd(addr, have_addr, count, modif) + db_expr_t addr; + int have_addr; + db_expr_t count; + char * modif; +{ + if (modif[0] == 'c') + db_run_mode = STEP_COUNT; + else + db_run_mode = STEP_CONTINUE; + db_inst_count = 0; + db_load_count = 0; + db_store_count = 0; + + db_cmd_loop_done = 1; +} diff --git a/sys/ddb/db_sym.c b/sys/ddb/db_sym.c new file mode 100644 index 0000000..0517c68 --- /dev/null +++ b/sys/ddb/db_sym.c @@ -0,0 +1,360 @@ +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ +/* + * HISTORY + * $Log: db_sym.c,v $ + * Revision 1.1 1992/03/25 21:45:27 pace + * Initial revision + * + * Revision 2.5 91/02/05 17:07:07 mrt + * Changed to new Mach copyright + * [91/01/31 16:19:17 mrt] + * + * Revision 2.4 90/10/25 14:44:05 rwd + * Changed db_printsym to print unsigned. + * [90/10/19 rpd] + * + * Revision 2.3 90/09/09 23:19:56 rpd + * Avoid totally incorrect guesses of symbol names for small values. + * [90/08/30 17:39:48 af] + * + * Revision 2.2 90/08/27 21:52:18 dbg + * Removed nlist.h. Fixed some type declarations. + * Qualifier character is ':'. + * [90/08/20 dbg] + * Modularized symtab info into a new db_symtab_t type. + * Modified db_add_symbol_table and others accordingly. + * Defined db_sym_t, a new (opaque) type used to represent + * symbols. This should support all sort of future symtable + * formats. Functions like db_qualify take a db_sym_t now. + * New db_symbol_values() function to explode the content + * of a db_sym_t. + * db_search_symbol() replaces db_find_sym_and_offset(), which is + * now a macro defined in our (new) header file. This new + * function accepts more restrictive searches, which are + * entirely delegated to the symtab-specific code. + * Accordingly, db_printsym() accepts a strategy parameter. + * New db_line_at_pc() function. + * Renamed misleading db_eqsym into db_eqname. + * [90/08/20 10:47:06 af] + * + * Created. + * [90/07/25 dbg] + * + * Revision 2.1 90/07/26 16:43:52 dbg + * Created. + * + */ +/* + * Author: David B. Golub, Carnegie Mellon University + * Date: 7/90 + */ +#include "param.h" +#include "proc.h" +#include <machine/db_machdep.h> +#include <ddb/db_sym.h> + +/* + * We import from the symbol-table dependent routines: + */ +extern db_sym_t X_db_lookup(); +extern db_sym_t X_db_search_symbol(); +extern boolean_t X_db_line_at_pc(); +extern void X_db_symbol_values(); + +/* + * Multiple symbol tables + */ +#define MAXNOSYMTABS 3 /* mach, ux, emulator */ + +db_symtab_t db_symtabs[MAXNOSYMTABS] = {{0,},}; +int db_nsymtab = 0; + +db_symtab_t *db_last_symtab; + +db_sym_t db_lookup(); /* forward */ + +/* + * Add symbol table, with given name, to list of symbol tables. + */ +void +db_add_symbol_table(start, end, name, ref) + char *start; + char *end; + char *name; + char *ref; +{ + if (db_nsymtab >= MAXNOSYMTABS) { + printf ("No slots left for %s symbol table", name); + panic ("db_sym.c: db_add_symbol_table"); + } + + db_symtabs[db_nsymtab].start = start; + db_symtabs[db_nsymtab].end = end; + db_symtabs[db_nsymtab].name = name; + db_symtabs[db_nsymtab].private = ref; + db_nsymtab++; +} + +/* + * db_qualify("vm_map", "ux") returns "unix:vm_map". + * + * Note: return value points to static data whose content is + * overwritten by each call... but in practice this seems okay. + */ +static char * +db_qualify(sym, symtabname) + db_sym_t sym; + register char *symtabname; +{ + char *symname; + static char tmp[256]; + register char *s; + + db_symbol_values(sym, &symname, 0); + s = tmp; + while (*s++ = *symtabname++) { + } + s[-1] = ':'; + while (*s++ = *symname++) { + } + return tmp; +} + + +boolean_t +db_eqname(src, dst, c) + char *src; + char *dst; + char c; +{ + if (!strcmp(src, dst)) + return (TRUE); + if (src[0] == c) + return (!strcmp(src+1,dst)); + return (FALSE); +} + +boolean_t +db_value_of_name(name, valuep) + char *name; + db_expr_t *valuep; +{ + db_sym_t sym; + + sym = db_lookup(name); + if (sym == DB_SYM_NULL) + return (FALSE); + db_symbol_values(sym, &name, valuep); + return (TRUE); +} + + +/* + * Lookup a symbol. + * If the symbol has a qualifier (e.g., ux:vm_map), + * then only the specified symbol table will be searched; + * otherwise, all symbol tables will be searched. + */ +db_sym_t +db_lookup(symstr) + char *symstr; +{ + db_sym_t sp; + register int i; + int symtab_start = 0; + int symtab_end = db_nsymtab; + register char *cp; + + /* + * Look for, remove, and remember any symbol table specifier. + */ + for (cp = symstr; *cp; cp++) { + if (*cp == ':') { + *cp = '\0'; + for (i = 0; i < db_nsymtab; i++) { + if (! strcmp(symstr, db_symtabs[i].name)) { + symtab_start = i; + symtab_end = i + 1; + break; + } + } + *cp = ':'; + if (i == db_nsymtab) { + db_error("invalid symbol table name"); + } + symstr = cp+1; + } + } + + /* + * Look in the specified set of symbol tables. + * Return on first match. + */ + for (i = symtab_start; i < symtab_end; i++) { + if (sp = X_db_lookup(&db_symtabs[i], symstr)) { + db_last_symtab = &db_symtabs[i]; + return sp; + } + } + return 0; +} + +/* + * Does this symbol name appear in more than one symbol table? + * Used by db_symbol_values to decide whether to qualify a symbol. + */ +boolean_t db_qualify_ambiguous_names = FALSE; + +boolean_t +db_symbol_is_ambiguous(sym) + db_sym_t sym; +{ + char *sym_name; + register int i; + register + boolean_t found_once = FALSE; + + if (!db_qualify_ambiguous_names) + return FALSE; + + db_symbol_values(sym, &sym_name, 0); + for (i = 0; i < db_nsymtab; i++) { + if (X_db_lookup(&db_symtabs[i], sym_name)) { + if (found_once) + return TRUE; + found_once = TRUE; + } + } + return FALSE; +} + +/* + * Find the closest symbol to val, and return its name + * and the difference between val and the symbol found. + */ +db_sym_t +db_search_symbol( val, strategy, offp) + register db_addr_t val; + db_strategy_t strategy; + db_expr_t *offp; +{ + register + unsigned int diff; + unsigned int newdiff; + register int i; + db_sym_t ret = DB_SYM_NULL, sym; + + newdiff = diff = ~0; + db_last_symtab = 0; + for (i = 0; i < db_nsymtab; i++) { + sym = X_db_search_symbol(&db_symtabs[i], val, strategy, &newdiff); + if (newdiff < diff) { + db_last_symtab = &db_symtabs[i]; + diff = newdiff; + ret = sym; + } + } + *offp = diff; + return ret; +} + +/* + * Return name and value of a symbol + */ +void +db_symbol_values(sym, namep, valuep) + db_sym_t sym; + char **namep; + db_expr_t *valuep; +{ + db_expr_t value; + + if (sym == DB_SYM_NULL) { + *namep = 0; + return; + } + + X_db_symbol_values(sym, namep, &value); + + if (db_symbol_is_ambiguous(sym)) + *namep = db_qualify(sym, db_last_symtab->name); + if (valuep) + *valuep = value; +} + + +/* + * Print a the closest symbol to value + * + * After matching the symbol according to the given strategy + * we print it in the name+offset format, provided the symbol's + * value is close enough (eg smaller than db_maxoff). + * We also attempt to print [filename:linenum] when applicable + * (eg for procedure names). + * + * If we could not find a reasonable name+offset representation, + * then we just print the value in hex. Small values might get + * bogus symbol associations, e.g. 3 might get some absolute + * value like _INCLUDE_VERSION or something, therefore we do + * not accept symbols whose value is zero (and use plain hex). + */ + +unsigned int db_maxoff = 0x10000000; + +void +db_printsym(off, strategy) + db_expr_t off; + db_strategy_t strategy; +{ + db_expr_t d; + char *filename; + char *name; + db_expr_t value; + int linenum; + db_sym_t cursym; + + cursym = db_search_symbol(off, strategy, &d); + db_symbol_values(cursym, &name, &value); + if (name == 0 || d >= db_maxoff || value == 0) { + db_printf("%#n", off); + return; + } + db_printf("%s", name); + if (d) + db_printf("+%#r", d); + if (strategy == DB_STGY_PROC) { + if (db_line_at_pc(cursym, &filename, &linenum, off)) + db_printf(" [%s:%d]", filename, linenum); + } +} + + +boolean_t +db_line_at_pc( sym, filename, linenum, pc) +{ + return X_db_line_at_pc( db_last_symtab, sym, filename, linenum, pc); +} diff --git a/sys/ddb/db_sym.h b/sys/ddb/db_sym.h new file mode 100644 index 0000000..663f1cd --- /dev/null +++ b/sys/ddb/db_sym.h @@ -0,0 +1,114 @@ +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ +/* + * HISTORY + * $Log: db_sym.h,v $ + * Revision 1.1 1992/03/25 21:45:29 pace + * Initial revision + * + * Revision 2.3 91/02/05 17:07:12 mrt + * Changed to new Mach copyright + * [91/01/31 16:19:27 mrt] + * + * Revision 2.2 90/08/27 21:52:39 dbg + * Changed type of db_sym_t to char * - it's a better type for an + * opaque pointer. + * [90/08/22 dbg] + * + * Created. + * [90/08/19 af] + * + */ +/* + * Author: Alessandro Forin, Carnegie Mellon University + * Date: 8/90 + */ + +/* + * This module can handle multiple symbol tables + */ +typedef struct { + char *name; /* symtab name */ + char *start; /* symtab location */ + char *end; + char *private; /* optional machdep pointer */ +} db_symtab_t; + +extern db_symtab_t *db_last_symtab; /* where last symbol was found */ + +/* + * Symbol representation is specific to the symtab style: + * BSD compilers use dbx' nlist, other compilers might use + * a different one + */ +typedef char * db_sym_t; /* opaque handle on symbols */ +#define DB_SYM_NULL ((db_sym_t)0) + +/* + * Non-stripped symbol tables will have duplicates, for instance + * the same string could match a parameter name, a local var, a + * global var, etc. + * We are most concern with the following matches. + */ +typedef int db_strategy_t; /* search strategy */ + +#define DB_STGY_ANY 0 /* anything goes */ +#define DB_STGY_XTRN 1 /* only external symbols */ +#define DB_STGY_PROC 2 /* only procedures */ + +extern boolean_t db_qualify_ambiguous_names; + /* if TRUE, check across symbol tables + * for multiple occurrences of a name. + * Might slow down quite a bit */ + +/* + * Functions exported by the symtable module + */ +extern void db_add_symbol_table(); + /* extend the list of symbol tables */ + +extern int db_value_of_name(/* char*, db_expr_t* */); + /* find symbol value given name */ + +extern db_sym_t db_search_symbol(/* db_expr_t, db_strategy_t, int* */); + /* find symbol given value */ + +extern void db_symbol_values(/* db_sym_t, char**, db_expr_t* */); + /* return name and value of symbol */ + +#define db_find_sym_and_offset(val,namep,offp) \ + db_symbol_values(db_search_symbol(val,DB_STGY_ANY,offp),namep,0) + /* find name&value given approx val */ + +#define db_find_xtrn_sym_and_offset(val,namep,offp) \ + db_symbol_values(db_search_symbol(val,DB_STGY_XTRN,offp),namep,0) + /* ditto, but no locals */ + +extern int db_eqname(/* char*, char*, char */); + /* strcmp, modulo leading char */ + +extern void db_printsym(/* db_expr_t, db_strategy_t */); + /* print closest symbol to a value */ diff --git a/sys/ddb/db_trap.c b/sys/ddb/db_trap.c new file mode 100644 index 0000000..099fab1 --- /dev/null +++ b/sys/ddb/db_trap.c @@ -0,0 +1,106 @@ +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ +/* + * HISTORY + * $Log: db_trap.c,v $ + * Revision 1.1 1992/03/25 21:45:31 pace + * Initial revision + * + * Revision 2.5 91/02/05 17:07:16 mrt + * Changed to new Mach copyright + * [91/01/31 16:19:35 mrt] + * + * Revision 2.4 91/01/08 15:09:17 rpd + * Changed db_stop_at_pc's arguments. + * Print db_inst_count, db_load_count, db_store_count. + * [90/11/27 rpd] + * + * Revision 2.3 90/10/25 14:44:11 rwd + * From rpd. + * [90/10/19 17:03:17 rwd] + * + * Generalized the watchpoint support. + * [90/10/16 rwd] + * Added watchpoint support. + * [90/10/16 rpd] + * + * Revision 2.2 90/08/27 21:52:52 dbg + * Assign to db_dot before calling the print function. + * [90/08/20 af] + * Reduce lint. + * [90/08/07 dbg] + * Created. + * [90/07/25 dbg] + * + */ +/* + * Author: David B. Golub, Carnegie Mellon University + * Date: 7/90 + */ + +/* + * Trap entry point to kernel debugger. + */ +#include "param.h" +#include "proc.h" +#include <ddb/db_command.h> +#include <ddb/db_break.h> + +extern void db_restart_at_pc(); +extern boolean_t db_stop_at_pc(); + +extern int db_inst_count; +extern int db_load_count; +extern int db_store_count; + +db_trap(type, code) + int type, code; +{ + boolean_t bkpt; + boolean_t watchpt; + + bkpt = IS_BREAKPOINT_TRAP(type, code); + watchpt = IS_WATCHPOINT_TRAP(type, code); + + if (db_stop_at_pc(&bkpt)) { + if (db_inst_count) { + db_printf("After %d instructions (%d loads, %d stores),\n", + db_inst_count, db_load_count, db_store_count); + } + if (bkpt) + db_printf("Breakpoint at\t"); + else if (watchpt) + db_printf("Watchpoint at\t"); + else + db_printf("Stopped at\t"); + db_dot = PC_REGS(DDB_REGS); + db_print_loc_and_inst(db_dot); + + db_command_loop(); + } + + db_restart_at_pc(watchpt); +} diff --git a/sys/ddb/db_variables.c b/sys/ddb/db_variables.c new file mode 100644 index 0000000..ed9512d --- /dev/null +++ b/sys/ddb/db_variables.c @@ -0,0 +1,186 @@ +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ +/* + * HISTORY + * $Log: db_variables.c,v $ + * Revision 1.1 1992/03/25 21:45:33 pace + * Initial revision + * + * Revision 2.3 91/02/05 17:07:19 mrt + * Changed to new Mach copyright + * [91/01/31 16:19:46 mrt] + * + * Revision 2.2 90/08/27 21:53:24 dbg + * New db_read/write_variable functions. Should be used instead + * of dereferencing valuep directly, which might not be a true + * pointer if there is an fcn() access function. + * [90/08/20 af] + * + * Fix declarations. + * Check for trailing garbage after last expression on command line. + * [90/08/10 14:34:54 dbg] + * + * Created. + * [90/07/25 dbg] + * + */ +/* + * Author: David B. Golub, Carnegie Mellon University + * Date: 7/90 + */ + +#include "param.h" +#include "proc.h" +#include <machine/db_machdep.h> + +#include <ddb/db_lex.h> +#include <ddb/db_variables.h> + +extern unsigned int db_maxoff; + +extern int db_radix; +extern int db_max_width; +extern int db_tab_stop_width; + +struct db_variable db_vars[] = { + { "radix", &db_radix, FCN_NULL }, + { "maxoff", (int *)&db_maxoff, FCN_NULL }, + { "maxwidth", &db_max_width, FCN_NULL }, + { "tabstops", &db_tab_stop_width, FCN_NULL }, +}; +struct db_variable *db_evars = db_vars + sizeof(db_vars)/sizeof(db_vars[0]); + +int +db_find_variable(varp) + struct db_variable **varp; +{ + int t; + struct db_variable *vp; + + t = db_read_token(); + if (t == tIDENT) { + for (vp = db_vars; vp < db_evars; vp++) { + if (!strcmp(db_tok_string, vp->name)) { + *varp = vp; + return (1); + } + } + for (vp = db_regs; vp < db_eregs; vp++) { + if (!strcmp(db_tok_string, vp->name)) { + *varp = vp; + return (1); + } + } + } + db_error("Unknown variable\n"); + return (0); +} + +int +db_get_variable(valuep) + db_expr_t *valuep; +{ + struct db_variable *vp; + + if (!db_find_variable(&vp)) + return (0); + + db_read_variable(vp, valuep); + + return (1); +} + +int +db_set_variable(value) + db_expr_t value; +{ + struct db_variable *vp; + + if (!db_find_variable(&vp)) + return (0); + + db_write_variable(vp, &value); + + return (1); +} + + +db_read_variable(vp, valuep) + struct db_variable *vp; + db_expr_t *valuep; +{ + int (*func)() = vp->fcn; + + if (func == FCN_NULL) + *valuep = *(vp->valuep); + else + (*func)(vp, valuep, DB_VAR_GET); +} + +db_write_variable(vp, valuep) + struct db_variable *vp; + db_expr_t *valuep; +{ + int (*func)() = vp->fcn; + + if (func == FCN_NULL) + *(vp->valuep) = *valuep; + else + (*func)(vp, valuep, DB_VAR_SET); +} + +void +db_set_cmd() +{ + db_expr_t value; + int (*func)(); + struct db_variable *vp; + int t; + + t = db_read_token(); + if (t != tDOLLAR) { + db_error("Unknown variable\n"); + return; + } + if (!db_find_variable(&vp)) { + db_error("Unknown variable\n"); + return; + } + + t = db_read_token(); + if (t != tEQ) + db_unread_token(t); + + if (!db_expression(&value)) { + db_error("No value\n"); + return; + } + if (db_read_token() != tEOL) { + db_error("?\n"); + } + + db_write_variable(vp, &value); +} diff --git a/sys/ddb/db_variables.h b/sys/ddb/db_variables.h new file mode 100644 index 0000000..f958d2c --- /dev/null +++ b/sys/ddb/db_variables.h @@ -0,0 +1,72 @@ +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ +/* + * HISTORY + * $Log: db_variables.h,v $ + * Revision 1.1 1992/03/25 21:45:35 pace + * Initial revision + * + * Revision 2.3 91/02/05 17:07:23 mrt + * Changed to new Mach copyright + * [91/01/31 16:19:54 mrt] + * + * Revision 2.2 90/08/27 21:53:40 dbg + * Modularized typedef name. Documented the calling sequence of + * the (optional) access function of a variable. Now the valuep + * field can be made opaque, eg be an offset that fcn() resolves. + * [90/08/20 af] + * + * Created. + * [90/07/25 dbg] + * + */ +/* + * Author: David B. Golub, Carnegie Mellon University + * Date: 7/90 + */ + +#ifndef _DB_VARIABLES_H_ +#define _DB_VARIABLES_H_ + +/* + * Debugger variables. + */ +struct db_variable { + char *name; /* Name of variable */ + int *valuep; /* value of variable */ + /* function to call when reading/writing */ + int (*fcn)(/* db_variable *vp, db_expr_t *valuep, int op */); +#define DB_VAR_GET 0 +#define DB_VAR_SET 1 +}; +#define FCN_NULL ((int (*)())0) + +extern struct db_variable db_vars[]; /* debugger variables */ +extern struct db_variable *db_evars; +extern struct db_variable db_regs[]; /* machine registers */ +extern struct db_variable *db_eregs; + +#endif /* _DB_VARIABLES_H_ */ diff --git a/sys/ddb/db_watch.c b/sys/ddb/db_watch.c new file mode 100644 index 0000000..e69d906d9 --- /dev/null +++ b/sys/ddb/db_watch.c @@ -0,0 +1,294 @@ +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ +/* + * HISTORY + * $Log: db_watch.c,v $ + * Revision 1.1 1992/03/25 21:45:37 pace + * Initial revision + * + * Revision 2.5 91/02/05 17:07:27 mrt + * Changed to new Mach copyright + * [91/01/31 16:20:02 mrt] + * + * Revision 2.4 91/01/08 15:09:24 rpd + * Use db_map_equal, db_map_current, db_map_addr. + * [90/11/10 rpd] + * + * Revision 2.3 90/11/05 14:26:39 rpd + * Initialize db_watchpoints_inserted to TRUE. + * [90/11/04 rpd] + * + * Revision 2.2 90/10/25 14:44:16 rwd + * Made db_watchpoint_cmd parse a size argument. + * [90/10/17 rpd] + * Generalized the watchpoint support. + * [90/10/16 rwd] + * Created. + * [90/10/16 rpd] + * + */ +/* + * Author: Richard P. Draves, Carnegie Mellon University + * Date: 10/90 + */ + +#include "param.h" +#include "proc.h" +#include <machine/db_machdep.h> + +#include <vm/vm_map.h> +#include <ddb/db_lex.h> +#include <ddb/db_watch.h> +#include <ddb/db_access.h> +#include <ddb/db_sym.h> +#include <machine/db_machdep.h> + +/* + * Watchpoints. + */ + +extern boolean_t db_map_equal(); +extern boolean_t db_map_current(); +extern vm_map_t db_map_addr(); + +boolean_t db_watchpoints_inserted = TRUE; + +#define NWATCHPOINTS 100 +struct db_watchpoint db_watch_table[NWATCHPOINTS]; +db_watchpoint_t db_next_free_watchpoint = &db_watch_table[0]; +db_watchpoint_t db_free_watchpoints = 0; +db_watchpoint_t db_watchpoint_list = 0; + +db_watchpoint_t +db_watchpoint_alloc() +{ + register db_watchpoint_t watch; + + if ((watch = db_free_watchpoints) != 0) { + db_free_watchpoints = watch->link; + return (watch); + } + if (db_next_free_watchpoint == &db_watch_table[NWATCHPOINTS]) { + db_printf("All watchpoints used.\n"); + return (0); + } + watch = db_next_free_watchpoint; + db_next_free_watchpoint++; + + return (watch); +} + +void +db_watchpoint_free(watch) + register db_watchpoint_t watch; +{ + watch->link = db_free_watchpoints; + db_free_watchpoints = watch; +} + +void +db_set_watchpoint(map, addr, size) + vm_map_t map; + db_addr_t addr; + vm_size_t size; +{ + register db_watchpoint_t watch; + + if (map == NULL) { + db_printf("No map.\n"); + return; + } + + /* + * Should we do anything fancy with overlapping regions? + */ + + for (watch = db_watchpoint_list; + watch != 0; + watch = watch->link) + if (db_map_equal(watch->map, map) && + (watch->loaddr == addr) && + (watch->hiaddr == addr+size)) { + db_printf("Already set.\n"); + return; + } + + watch = db_watchpoint_alloc(); + if (watch == 0) { + db_printf("Too many watchpoints.\n"); + return; + } + + watch->map = map; + watch->loaddr = addr; + watch->hiaddr = addr+size; + + watch->link = db_watchpoint_list; + db_watchpoint_list = watch; + + db_watchpoints_inserted = FALSE; +} + +void +db_delete_watchpoint(map, addr) + vm_map_t map; + db_addr_t addr; +{ + register db_watchpoint_t watch; + register db_watchpoint_t *prev; + + for (prev = &db_watchpoint_list; + (watch = *prev) != 0; + prev = &watch->link) + if (db_map_equal(watch->map, map) && + (watch->loaddr <= addr) && + (addr < watch->hiaddr)) { + *prev = watch->link; + db_watchpoint_free(watch); + return; + } + + db_printf("Not set.\n"); +} + +void +db_list_watchpoints() +{ + register db_watchpoint_t watch; + + if (db_watchpoint_list == 0) { + db_printf("No watchpoints set\n"); + return; + } + + db_printf(" Map Address Size\n"); + for (watch = db_watchpoint_list; + watch != 0; + watch = watch->link) + db_printf("%s%8x %8x %x\n", + db_map_current(watch->map) ? "*" : " ", + watch->map, watch->loaddr, + watch->hiaddr - watch->loaddr); +} + +/* Delete watchpoint */ +/*ARGSUSED*/ +void +db_deletewatch_cmd(addr, have_addr, count, modif) + db_expr_t addr; + int have_addr; + db_expr_t count; + char * modif; +{ + db_delete_watchpoint(db_map_addr(addr), addr); +} + +/* Set watchpoint */ +/*ARGSUSED*/ +void +db_watchpoint_cmd(addr, have_addr, count, modif) + db_expr_t addr; + int have_addr; + db_expr_t count; + char * modif; +{ + vm_size_t size; + db_expr_t value; + + if (db_expression(&value)) + size = (vm_size_t) value; + else + size = 4; + db_skip_to_eol(); + + db_set_watchpoint(db_map_addr(addr), addr, size); +} + +/* list watchpoints */ +void +db_listwatch_cmd() +{ + db_list_watchpoints(); +} + +void +db_set_watchpoints() +{ + register db_watchpoint_t watch; + + if (!db_watchpoints_inserted) { + for (watch = db_watchpoint_list; + watch != 0; + watch = watch->link) + pmap_protect(watch->map->pmap, + trunc_page(watch->loaddr), + round_page(watch->hiaddr), + VM_PROT_READ); + + db_watchpoints_inserted = TRUE; + } +} + +void +db_clear_watchpoints() +{ + db_watchpoints_inserted = FALSE; +} + +boolean_t +db_find_watchpoint(map, addr, regs) + vm_map_t map; + db_addr_t addr; + db_regs_t *regs; +{ + register db_watchpoint_t watch; + db_watchpoint_t found = 0; + + for (watch = db_watchpoint_list; + watch != 0; + watch = watch->link) + if (db_map_equal(watch->map, map)) { + if ((watch->loaddr <= addr) && + (addr < watch->hiaddr)) + return (TRUE); + else if ((trunc_page(watch->loaddr) <= addr) && + (addr < round_page(watch->hiaddr))) + found = watch; + } + + /* + * We didn't hit exactly on a watchpoint, but we are + * in a protected region. We want to single-step + * and then re-protect. + */ + + if (found) { + db_watchpoints_inserted = FALSE; + db_single_step(regs); + } + + return (FALSE); +} diff --git a/sys/ddb/db_watch.h b/sys/ddb/db_watch.h new file mode 100644 index 0000000..9795755 --- /dev/null +++ b/sys/ddb/db_watch.h @@ -0,0 +1,74 @@ +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ +/* + * HISTORY + * $Log: db_watch.h,v $ + * Revision 1.1 1992/03/25 21:45:40 pace + * Initial revision + * + * Revision 2.3 91/02/05 17:07:31 mrt + * Changed to new Mach copyright + * [91/01/31 16:20:09 mrt] + * + * Revision 2.2 90/10/25 14:44:21 rwd + * Generalized the watchpoint support. + * [90/10/16 rwd] + * Created. + * [90/10/16 rpd] + * + */ +/* + * Author: David B. Golub, Carnegie Mellon University + * Date: 10/90 + */ + +#ifndef _DDB_DB_WATCH_ +#define _DDB_DB_WATCH_ + +#include <vm/vm_map.h> +#include <machine/db_machdep.h> + +/* + * Watchpoint. + */ + +typedef struct db_watchpoint { + vm_map_t map; /* in this map */ + db_addr_t loaddr; /* from this address */ + db_addr_t hiaddr; /* to this address */ + struct db_watchpoint *link; /* link in in-use or free chain */ +} *db_watchpoint_t; + +extern boolean_t db_find_watchpoint(/* vm_map_t map, db_addr_t addr, + db_regs_t *regs */); +extern void db_set_watchpoints(); +extern void db_clear_watchpoints(); + +extern void db_set_watchpoint(/* vm_map_t map, db_addr_t addr, vm_size_t size */); +extern void db_delete_watchpoint(/* vm_map_t map, db_addr_t addr */); +extern void db_list_watchpoints(); + +#endif _DDB_DB_WATCH_ diff --git a/sys/ddb/db_write_cmd.c b/sys/ddb/db_write_cmd.c new file mode 100644 index 0000000..dce22a9 --- /dev/null +++ b/sys/ddb/db_write_cmd.c @@ -0,0 +1,120 @@ +/* + * Mach Operating System + * Copyright (c) 1991,1990 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie the + * rights to redistribute these changes. + */ +/* + * HISTORY + * $Log: db_write_cmd.c,v $ + * Revision 1.1 1992/03/25 21:45:42 pace + * Initial revision + * + * Revision 2.4 91/02/05 17:07:35 mrt + * Changed to new Mach copyright + * [91/01/31 16:20:19 mrt] + * + * Revision 2.3 90/10/25 14:44:26 rwd + * Changed db_write_cmd to print unsigned. + * [90/10/19 rpd] + * + * Revision 2.2 90/08/27 21:53:54 dbg + * Set db_prev and db_next instead of explicitly advancing dot. + * [90/08/22 dbg] + * Reflected changes in db_printsym()'s calling seq. + * [90/08/20 af] + * Warn user if nothing was written. + * [90/08/07 dbg] + * Created. + * [90/07/25 dbg] + * + */ +/* + * Author: David B. Golub, Carnegie Mellon University + * Date: 7/90 + */ + +#include "param.h" +#include "proc.h" +#include <machine/db_machdep.h> + +#include <ddb/db_lex.h> +#include <ddb/db_access.h> +#include <ddb/db_command.h> +#include <ddb/db_sym.h> + +/* + * Write to file. + */ +/*ARGSUSED*/ +void +db_write_cmd(address, have_addr, count, modif) + db_expr_t address; + boolean_t have_addr; + db_expr_t count; + char * modif; +{ + register + db_addr_t addr; + register + db_expr_t old_value; + db_expr_t new_value; + register int size; + boolean_t wrote_one = FALSE; + + addr = (db_addr_t) address; + + switch (modif[0]) { + case 'b': + size = 1; + break; + case 'h': + size = 2; + break; + case 'l': + case '\0': + size = 4; + break; + default: + db_error("Unknown size\n"); + return; + } + + while (db_expression(&new_value)) { + old_value = db_get_value(addr, size, FALSE); + db_printsym(addr, DB_STGY_ANY); + db_printf("\t\t%#8n\t=\t%#8n\n", old_value, new_value); + db_put_value(addr, size, new_value); + addr += size; + + wrote_one = TRUE; + } + + if (!wrote_one) + db_error("Nothing written.\n"); + + db_next = addr; + db_prev = addr - size; + + db_skip_to_eol(); +} + |