diff --git a/share/man/man4/ddb.4 b/share/man/man4/ddb.4 index f880ec4294b7..d96a3e4f74be 100644 --- a/share/man/man4/ddb.4 +++ b/share/man/man4/ddb.4 @@ -1,4 +1,4 @@ -.\" $NetBSD: ddb.4,v 1.45 2000/05/22 11:46:07 jhawk Exp $ +.\" $NetBSD: ddb.4,v 1.46 2000/05/22 14:49:11 jhawk Exp $ .\" .\" Copyright (c) 1997, 1998 The NetBSD Foundation, Inc. .\" All rights reserved. @@ -587,6 +587,42 @@ If not supported, incorrect information will be displayed. .It Ic "show watches" Display all watchpoints. .It Xo +.Ic sifting Ns Op Cm /F +.Ar string +.Xc +Search the symbol tables for all symbols of which +.Ar string +is a substring, and display them. If +.Cm /F +is specified, a character is displayed immediately after each symbol +name indicating the type of symbol. +.Pp +For +.Ns Xr a.out 5 -format +symbol tables, +absolute symbols display +.Sy @ , +text segment symbols display +.Sy * , +data segment symbols display +.Sy + , +.Tn BSS +segment symbols display +.Sy - , +and filename symbols display +.Sy / . +For +.Tn ELF Ns -format +symbol tables, +object symbols display +.Sy + , +function symbols display +.Sy * , +section symbols display +.Sy & , +and file symbols display +.Sy / . +.It Xo .Ic step Ns Op Cm /p .Op Cm , Ns Ar count .Xc diff --git a/sys/ddb/db_aout.c b/sys/ddb/db_aout.c index 63cb682ec518..77cea6bb9d53 100644 --- a/sys/ddb/db_aout.c +++ b/sys/ddb/db_aout.c @@ -1,4 +1,4 @@ -/* $NetBSD: db_aout.c,v 1.27 2000/03/30 11:31:26 augustss Exp $ */ +/* $NetBSD: db_aout.c,v 1.28 2000/05/22 14:49:10 jhawk Exp $ */ /* * Mach Operating System @@ -51,6 +51,8 @@ boolean_t db_aout_line_at_pc __P((db_symtab_t *, db_sym_t, char **, int *, db_expr_t)); boolean_t db_aout_sym_numargs __P((db_symtab_t *, db_sym_t, int *, char **)); +void db_aout_forall __P((db_symtab_t *, + db_forall_func_t db_forall_func, void *)); db_symformat_t db_symformat_aout = { "a.out", @@ -60,6 +62,7 @@ db_symformat_t db_symformat_aout = { db_aout_symbol_values, db_aout_line_at_pc, db_aout_sym_numargs, + db_aout_forall }; /* @@ -346,4 +349,49 @@ db_aout_sym_numargs(symtab, cursym, nargp, argnamep) } return FALSE; } + +void +db_aout_forall(stab, db_forall_func, arg) + db_symtab_t *stab; + db_forall_func_t db_forall_func; + void *arg; +{ + static char suffix[2]; + 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) { + suffix[1] = '\0'; + switch(sp->n_type & N_TYPE) { + case N_ABS: + suffix[0] = '@'; + break; + case N_TEXT: + suffix[0] = '*'; + break; + case N_DATA: + suffix[0] = '+'; + break; + case N_BSS: + suffix[0] = '-'; + break; + case N_FN: + suffix[0] = '/'; + break; + default: + suffix[0] = '\0'; + } + (*db_forall_func)(stab, (db_sym_t)sp, sp->n_un.n_name, + suffix, '_', arg); + } + } + return; +} + + #endif /* DB_AOUT_SYMBOLS */ diff --git a/sys/ddb/db_command.c b/sys/ddb/db_command.c index 24a0c7d5e90c..93d62f65898d 100644 --- a/sys/ddb/db_command.c +++ b/sys/ddb/db_command.c @@ -1,4 +1,4 @@ -/* $NetBSD: db_command.c,v 1.40 2000/05/20 03:08:41 jhawk Exp $ */ +/* $NetBSD: db_command.c,v 1.41 2000/05/22 14:49:10 jhawk Exp $ */ /* * Mach Operating System @@ -481,6 +481,7 @@ struct db_command db_command_table[] = { { "search", db_search_cmd, CS_OWN|CS_SET_DOT, NULL }, { "set", db_set_cmd, CS_OWN, NULL }, { "show", NULL, 0, db_show_cmds }, + { "sifting", db_sifting_cmd, CS_OWN, NULL }, { "step", db_single_step_cmd, 0, NULL }, { "sync", db_sync_cmd, CS_OWN, NULL }, { "trace", db_stack_trace_cmd, 0, NULL }, @@ -645,6 +646,40 @@ db_reboot_cmd(addr, have_addr, count, modif) cpu_reboot((int)bootflags, NULL); } +void +db_sifting_cmd(addr, have_addr, count, omodif) + db_expr_t addr; + int have_addr; + db_expr_t count; + char * omodif; +{ + int mode, t; + + 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, "F")) + mode = 'F'; + else + goto bad_modifier; + t = db_read_token(); + } else + mode = 0; + + if (t==tIDENT) + db_sifting(db_tok_string, mode); + else { + db_printf("Bad argument (non-string)\n"); + db_flush_lex(); + } +} + void db_sync_cmd(addr, have_addr, count, modif) db_expr_t addr; diff --git a/sys/ddb/db_command.h b/sys/ddb/db_command.h index 39e1e2dd58c6..870b964a937f 100644 --- a/sys/ddb/db_command.h +++ b/sys/ddb/db_command.h @@ -1,4 +1,4 @@ -/* $NetBSD: db_command.h,v 1.15 2000/04/10 02:22:13 chs Exp $ */ +/* $NetBSD: db_command.h,v 1.16 2000/05/22 14:49:10 jhawk Exp $ */ /* * Mach Operating System @@ -48,6 +48,7 @@ void db_command_loop __P((void)); void db_error __P((char *)); void db_fncall __P((db_expr_t, int, db_expr_t, char *)); void db_reboot_cmd __P((db_expr_t, int, db_expr_t, char *)); +void db_sifting_cmd __P((db_expr_t, int, db_expr_t, char *)); void db_sync_cmd __P((db_expr_t, int, db_expr_t, char *)); db_addr_t db_dot; /* current location */ diff --git a/sys/ddb/db_elf.c b/sys/ddb/db_elf.c index 8fe1603e2bf1..77aaf6de38a4 100644 --- a/sys/ddb/db_elf.c +++ b/sys/ddb/db_elf.c @@ -1,4 +1,4 @@ -/* $NetBSD: db_elf.c,v 1.10 1999/10/25 13:55:06 kleink Exp $ */ +/* $NetBSD: db_elf.c,v 1.11 2000/05/22 14:49:10 jhawk Exp $ */ /*- * Copyright (c) 1997 The NetBSD Foundation, Inc. @@ -75,6 +75,8 @@ boolean_t db_elf_line_at_pc __P((db_symtab_t *, db_sym_t, char **, int *, db_expr_t)); boolean_t db_elf_sym_numargs __P((db_symtab_t *, db_sym_t, int *, char **)); +void db_elf_forall __P((db_symtab_t *, + db_forall_func_t db_forall_func, void *)); db_symformat_t db_symformat_elf = { "ELF", @@ -84,6 +86,7 @@ db_symformat_t db_symformat_elf = { db_elf_symbol_values, db_elf_line_at_pc, db_elf_sym_numargs, + db_elf_forall }; /* @@ -397,4 +400,46 @@ db_elf_sym_numargs(symtab, cursym, nargp, argnamep) */ return (FALSE); } + +void +db_elf_forall(stab, db_forall_func, arg) + db_symtab_t *stab; + db_forall_func_t db_forall_func; + void *arg; +{ + char *strtab; + static char suffix[2]; + Elf_Sym *symp, *symtab_start, *symtab_end; + + symtab_start = STAB_TO_SYMSTART(stab); + symtab_end = STAB_TO_SYMEND(stab); + + strtab = db_elf_find_strtab(stab); + if (strtab == NULL) + return; + + for (symp = symtab_start; symp < symtab_end; symp++) + if (symp->st_name != 0) { + suffix[1] = '\0'; + switch (ELFDEFNNAME(ST_TYPE)(symp->st_info)) { + case STT_OBJECT: + suffix[0] = '+'; + break; + case STT_FUNC: + suffix[0] = '*'; + break; + case STT_SECTION: + suffix[0] = '&'; + break; + case STT_FILE: + suffix[0] = '/'; + break; + default: + suffix[0] = '\0'; + } + (*db_forall_func)(stab, (db_sym_t)symp, + strtab + symp->st_name, suffix, 0, arg); + } + return; +} #endif /* DB_ELF_SYMBOLS */ diff --git a/sys/ddb/db_sym.c b/sys/ddb/db_sym.c index 7b0eda1fba2a..7cbae04c6e9c 100644 --- a/sys/ddb/db_sym.c +++ b/sys/ddb/db_sym.c @@ -1,4 +1,4 @@ -/* $NetBSD: db_sym.c,v 1.19 2000/03/30 11:31:27 augustss Exp $ */ +/* $NetBSD: db_sym.c,v 1.20 2000/05/22 14:49:10 jhawk Exp $ */ /* * Mach Operating System @@ -32,6 +32,7 @@ #include +#include #include #include #include @@ -53,6 +54,7 @@ db_symtab_t db_symtabs[MAXNOSYMTABS] = {{0,},}; db_symtab_t *db_last_symtab; static char *db_qualify __P((db_sym_t, const char *)); +static db_forall_func_t db_sift; /* * Put the most picky symbol table formats at the top! @@ -79,6 +81,8 @@ boolean_t X_db_line_at_pc __P((db_symtab_t *, db_sym_t, char **, int *, db_expr_t)); int X_db_sym_numargs __P((db_symtab_t *, db_sym_t, int *, char **)); +void X_db_forall __P((db_symtab_t *, + db_forall_func_t db_forall_func, void *)); /* * Initialize the kernel debugger by initializing the master symbol @@ -279,6 +283,113 @@ db_lookup(symstr) return 0; } +/* Private structure for passing args to db_sift() from db_sifting(). */ +struct db_sift_args { + char *symstr; + int mode; +}; + +/* + * Does the work of db_sifting(), called once for each + * symbol via X_db_forall(), prints out symbols matching + * criteria. + */ +static void +db_sift(stab, sym, name, suffix, prefix, arg) + db_symtab_t *stab; + db_sym_t sym; + char *name; + char *suffix; + int prefix; + void *arg; +{ + char c, sc; + char *find, *p; + size_t len; + struct db_sift_args *dsa; + + dsa = (struct db_sift_args*)arg; + + find = dsa->symstr; /* String we're looking for. */ + p = name; /* String we're searching within. */ + + /* Matching algorithm cribbed from strstr(), which is not + in the kernel. */ + if ((c = *find++) != 0) { + len = strlen(find); + do { + do { + if ((sc = *p++) == 0) + return; + } while (sc != c); + } while (strncmp(p, find, len) != 0); + } + if (dsa->mode=='F') /* ala ls -F */ + db_printf("%s%s ", name, suffix); + else + db_printf("%s ", name); +} + +/* + * "Sift" for a partial symbol. + * Named for the Sun OpenPROM command ("sifting"). + * 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.. + * + * "mode" is how-to-display, set from modifiers. + */ +void +db_sifting(symstr, mode) + char *symstr; + int mode; +{ + char *cp; + int i; + int symtab_start = 0; + int symtab_end = MAXNOSYMTABS; + struct db_sift_args dsa; + + /* + * Look for, remove, and remember any symbol table specifier. + */ + for (cp = symstr; *cp; cp++) { + if (*cp == ':') { + *cp = '\0'; + for (i = 0; i < MAXNOSYMTABS; i++) { + if (db_symtabs[i].name && + ! strcmp(symstr, db_symtabs[i].name)) { + symtab_start = i; + symtab_end = i + 1; + break; + } + } + *cp = ':'; + if (i == MAXNOSYMTABS) { + db_error("invalid symbol table name"); + /*NOTREACHED*/ + } + symstr = cp+1; + } + } + + /* Pass args to db_sift(). */ + dsa.symstr = symstr; + dsa.mode = mode; + + /* + * Look in the specified set of symbol tables. + */ + for (i = symtab_start; i < symtab_end; i++) + if (db_symtabs[i].name) { + db_printf("Sifting table %s:\n", db_symtabs[i].name); + X_db_forall(&db_symtabs[i], db_sift, &dsa); + } + + return; +} + + /* * Does this symbol name appear in more than one symbol table? * Used by db_symbol_values to decide whether to qualify a symbol. @@ -514,3 +625,13 @@ X_db_sym_numargs(stab, cursym, nargp, argnamep) argnamep)); return (FALSE); } + +void +X_db_forall(stab, db_forall_func, arg) + db_symtab_t *stab; + db_forall_func_t db_forall_func; + void *arg; +{ + if (db_symformat != NULL) + (*db_symformat->sym_forall)(stab, db_forall_func, arg); +} diff --git a/sys/ddb/db_sym.h b/sys/ddb/db_sym.h index 46ce0b468c71..936000f561d4 100644 --- a/sys/ddb/db_sym.h +++ b/sys/ddb/db_sym.h @@ -1,4 +1,4 @@ -/* $NetBSD: db_sym.h,v 1.11 1999/04/12 20:38:21 pk Exp $ */ +/* $NetBSD: db_sym.h,v 1.12 2000/05/22 14:49:10 jhawk Exp $ */ /* * Mach Operating System @@ -61,6 +61,20 @@ typedef int db_strategy_t; /* search strategy */ #define DB_STGY_XTRN 1 /* only external symbols */ #define DB_STGY_PROC 2 /* only procedures */ + +/* + * Internal db_forall function calling convention: + * + * (*db_forall_func)(stab, sym, name, suffix, prefix, arg); + * + * stab is the symbol table, symbol the (opaque) symbol pointer, + * name the name of the symbol, suffix a string representing + * the type, prefix an initial ignorable function prefix (e.g. "_" + * in a.out), and arg an opaque argument to be passed in. + */ +typedef void (db_forall_func_t) + __P((db_symtab_t *, db_sym_t, char *, char *, int, void *)); + /* * A symbol table may be in one of many formats. All symbol tables * must be of the same format as the master kernel symbol table. @@ -77,6 +91,8 @@ typedef struct { char **, int *, db_expr_t)); boolean_t (*sym_numargs) __P((db_symtab_t *, db_sym_t, int *, char **)); + void (*sym_forall) __P((db_symtab_t *, + db_forall_func_t *db_forall_func, void *)); } db_symformat_t; extern boolean_t db_qualify_ambiguous_names; @@ -102,6 +118,9 @@ int db_value_of_name __P((char *, db_expr_t *)); db_sym_t db_lookup __P((char *)); +void db_sifting __P((char *, int)); + /* print partially matching symbol names */ + boolean_t db_symbol_is_ambiguous __P((db_sym_t)); db_sym_t db_search_symbol __P((db_addr_t, db_strategy_t, db_expr_t *));