1dd3cb568SWarner Losh /*-
2796df753SPedro F. Giffuni * SPDX-License-Identifier: MIT-CMU
3796df753SPedro F. Giffuni *
45b81b6b3SRodney W. Grimes * Mach Operating System
55b81b6b3SRodney W. Grimes * Copyright (c) 1991,1990 Carnegie Mellon University
65b81b6b3SRodney W. Grimes * All Rights Reserved.
75b81b6b3SRodney W. Grimes *
85b81b6b3SRodney W. Grimes * Permission to use, copy, modify and distribute this software and its
95b81b6b3SRodney W. Grimes * documentation is hereby granted, provided that both the copyright
105b81b6b3SRodney W. Grimes * notice and this permission notice appear in all copies of the
115b81b6b3SRodney W. Grimes * software, derivative works or modified versions, and any portions
125b81b6b3SRodney W. Grimes * thereof, and that both notices appear in supporting documentation.
135b81b6b3SRodney W. Grimes *
145b81b6b3SRodney W. Grimes * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS
155b81b6b3SRodney W. Grimes * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
165b81b6b3SRodney W. Grimes * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
175b81b6b3SRodney W. Grimes *
185b81b6b3SRodney W. Grimes * Carnegie Mellon requests users of this software to return to
195b81b6b3SRodney W. Grimes *
205b81b6b3SRodney W. Grimes * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
215b81b6b3SRodney W. Grimes * School of Computer Science
225b81b6b3SRodney W. Grimes * Carnegie Mellon University
235b81b6b3SRodney W. Grimes * Pittsburgh PA 15213-3890
245b81b6b3SRodney W. Grimes *
255b81b6b3SRodney W. Grimes * any improvements or extensions that they make and grant Carnegie the
265b81b6b3SRodney W. Grimes * rights to redistribute these changes.
275b81b6b3SRodney W. Grimes */
285b81b6b3SRodney W. Grimes /*
295b81b6b3SRodney W. Grimes * Author: David B. Golub, Carnegie Mellon University
305b81b6b3SRodney W. Grimes * Date: 7/90
315b81b6b3SRodney W. Grimes */
32753960f7SDavid E. O'Brien
33753960f7SDavid E. O'Brien #include <sys/cdefs.h>
34721555e7SZbigniew Bodek #include "opt_kstack_pages.h"
35721555e7SZbigniew Bodek
36f540b106SGarrett Wollman #include <sys/param.h>
376f8a182bSMitchell Horne #include <sys/systm.h>
38530c0060SRobert Watson #include <sys/pcpu.h>
3989e5ef89SHans Petter Selasky #include <sys/proc.h>
40eddfbb76SRobert Watson #include <sys/smp.h>
41754cb545SMitchell Horne #include <sys/sysent.h>
42eddfbb76SRobert Watson
43eddfbb76SRobert Watson #include <net/vnet.h>
445ccbc3ccSBruce Evans
45f540b106SGarrett Wollman #include <ddb/ddb.h>
465b81b6b3SRodney W. Grimes #include <ddb/db_sym.h>
47eddfbb76SRobert Watson #include <ddb/db_variables.h>
485b81b6b3SRodney W. Grimes
494e38d895SWarner Losh #include "opt_ddb.h"
509aece96fSPoul-Henning Kamp
515b81b6b3SRodney W. Grimes /*
525b81b6b3SRodney W. Grimes * Multiple symbol tables
535b81b6b3SRodney W. Grimes */
54f7d75744SDavid Greenman #ifndef MAXNOSYMTABS
555b81b6b3SRodney W. Grimes #define MAXNOSYMTABS 3 /* mach, ux, emulator */
56f7d75744SDavid Greenman #endif
575b81b6b3SRodney W. Grimes
58f73a856dSPoul-Henning Kamp static db_symtab_t db_symtabs[MAXNOSYMTABS] = {{0,},};
59f73a856dSPoul-Henning Kamp static int db_nsymtab = 0;
605b81b6b3SRodney W. Grimes
6194e24bf0SBruce Evans static db_symtab_t *db_last_symtab; /* where last symbol was found */
625b81b6b3SRodney W. Grimes
6314e10f99SAlfred Perlstein static c_db_sym_t db_lookup( const char *symstr);
6414e10f99SAlfred Perlstein static char *db_qualify(c_db_sym_t sym, char *symtabname);
65cd508278SPedro F. Giffuni static bool db_symbol_is_ambiguous(c_db_sym_t sym);
66cd508278SPedro F. Giffuni static bool db_line_at_pc(c_db_sym_t, char **, int *, db_expr_t);
675b81b6b3SRodney W. Grimes
68eddfbb76SRobert Watson static int db_cpu = -1;
69eddfbb76SRobert Watson
70eddfbb76SRobert Watson #ifdef VIMAGE
71eddfbb76SRobert Watson static void *db_vnet = NULL;
72eddfbb76SRobert Watson #endif
73eddfbb76SRobert Watson
74eddfbb76SRobert Watson /*
75eddfbb76SRobert Watson * Validate the CPU number used to interpret per-CPU variables so we can
76eddfbb76SRobert Watson * avoid later confusion if an invalid CPU is requested.
77eddfbb76SRobert Watson */
78eddfbb76SRobert Watson int
db_var_db_cpu(struct db_variable * vp,db_expr_t * valuep,int op)79eddfbb76SRobert Watson db_var_db_cpu(struct db_variable *vp, db_expr_t *valuep, int op)
80eddfbb76SRobert Watson {
81eddfbb76SRobert Watson
82eddfbb76SRobert Watson switch (op) {
83eddfbb76SRobert Watson case DB_VAR_GET:
84eddfbb76SRobert Watson *valuep = db_cpu;
85eddfbb76SRobert Watson return (1);
86eddfbb76SRobert Watson
87eddfbb76SRobert Watson case DB_VAR_SET:
886e1c5d18SAndriy Gapon if (*(int *)valuep < -1 || *(int *)valuep > mp_maxid) {
896e1c5d18SAndriy Gapon db_printf("Invalid value: %d\n", *(int*)valuep);
90eddfbb76SRobert Watson return (0);
91eddfbb76SRobert Watson }
92eddfbb76SRobert Watson db_cpu = *(int *)valuep;
93eddfbb76SRobert Watson return (1);
94eddfbb76SRobert Watson
95eddfbb76SRobert Watson default:
96eddfbb76SRobert Watson db_printf("db_var_db_cpu: unknown operation\n");
97eddfbb76SRobert Watson return (0);
98eddfbb76SRobert Watson }
99eddfbb76SRobert Watson }
100eddfbb76SRobert Watson
101eddfbb76SRobert Watson /*
102eddfbb76SRobert Watson * Read-only variable reporting the current CPU, which is what we use when
103eddfbb76SRobert Watson * db_cpu is set to -1.
104eddfbb76SRobert Watson */
105eddfbb76SRobert Watson int
db_var_curcpu(struct db_variable * vp,db_expr_t * valuep,int op)106eddfbb76SRobert Watson db_var_curcpu(struct db_variable *vp, db_expr_t *valuep, int op)
107eddfbb76SRobert Watson {
108eddfbb76SRobert Watson
109eddfbb76SRobert Watson switch (op) {
110eddfbb76SRobert Watson case DB_VAR_GET:
111eddfbb76SRobert Watson *valuep = curcpu;
112eddfbb76SRobert Watson return (1);
113eddfbb76SRobert Watson
114eddfbb76SRobert Watson case DB_VAR_SET:
115eddfbb76SRobert Watson db_printf("Read-only variable.\n");
116eddfbb76SRobert Watson return (0);
117eddfbb76SRobert Watson
118eddfbb76SRobert Watson default:
119eddfbb76SRobert Watson db_printf("db_var_curcpu: unknown operation\n");
120eddfbb76SRobert Watson return (0);
121eddfbb76SRobert Watson }
122eddfbb76SRobert Watson }
123eddfbb76SRobert Watson
124eddfbb76SRobert Watson #ifdef VIMAGE
125eddfbb76SRobert Watson /*
126eddfbb76SRobert Watson * Validate the virtual network pointer used to interpret per-vnet global
127eddfbb76SRobert Watson * variable expansion. Right now we don't do much here, really we should
128eddfbb76SRobert Watson * walk the global vnet list to check it's an OK pointer.
129eddfbb76SRobert Watson */
130eddfbb76SRobert Watson int
db_var_db_vnet(struct db_variable * vp,db_expr_t * valuep,int op)131eddfbb76SRobert Watson db_var_db_vnet(struct db_variable *vp, db_expr_t *valuep, int op)
132eddfbb76SRobert Watson {
133eddfbb76SRobert Watson
134eddfbb76SRobert Watson switch (op) {
135eddfbb76SRobert Watson case DB_VAR_GET:
136eddfbb76SRobert Watson *valuep = (db_expr_t)db_vnet;
137eddfbb76SRobert Watson return (1);
138eddfbb76SRobert Watson
139eddfbb76SRobert Watson case DB_VAR_SET:
140eddfbb76SRobert Watson db_vnet = *(void **)valuep;
141eddfbb76SRobert Watson return (1);
142eddfbb76SRobert Watson
143eddfbb76SRobert Watson default:
144eddfbb76SRobert Watson db_printf("db_var_db_vnet: unknown operation\n");
145eddfbb76SRobert Watson return (0);
146eddfbb76SRobert Watson }
147eddfbb76SRobert Watson }
148eddfbb76SRobert Watson
149eddfbb76SRobert Watson /*
150eddfbb76SRobert Watson * Read-only variable reporting the current vnet, which is what we use when
151eddfbb76SRobert Watson * db_vnet is set to NULL.
152eddfbb76SRobert Watson */
153eddfbb76SRobert Watson int
db_var_curvnet(struct db_variable * vp,db_expr_t * valuep,int op)154eddfbb76SRobert Watson db_var_curvnet(struct db_variable *vp, db_expr_t *valuep, int op)
155eddfbb76SRobert Watson {
156eddfbb76SRobert Watson
157eddfbb76SRobert Watson switch (op) {
158eddfbb76SRobert Watson case DB_VAR_GET:
159eddfbb76SRobert Watson *valuep = (db_expr_t)curvnet;
160eddfbb76SRobert Watson return (1);
161eddfbb76SRobert Watson
162eddfbb76SRobert Watson case DB_VAR_SET:
163eddfbb76SRobert Watson db_printf("Read-only variable.\n");
164eddfbb76SRobert Watson return (0);
165eddfbb76SRobert Watson
166eddfbb76SRobert Watson default:
1678fe344faSBjoern A. Zeeb db_printf("db_var_curvnet: unknown operation\n");
168eddfbb76SRobert Watson return (0);
169eddfbb76SRobert Watson }
170eddfbb76SRobert Watson }
171eddfbb76SRobert Watson #endif
172eddfbb76SRobert Watson
1735b81b6b3SRodney W. Grimes /*
1745b81b6b3SRodney W. Grimes * Add symbol table, with given name, to list of symbol tables.
1755b81b6b3SRodney W. Grimes */
1765b81b6b3SRodney W. Grimes void
db_add_symbol_table(char * start,char * end,char * name,char * ref)177a41dd031SPedro F. Giffuni db_add_symbol_table(char *start, char *end, char *name, char *ref)
1785b81b6b3SRodney W. Grimes {
1795b81b6b3SRodney W. Grimes if (db_nsymtab >= MAXNOSYMTABS) {
1805b81b6b3SRodney W. Grimes printf ("No slots left for %s symbol table", name);
1815b81b6b3SRodney W. Grimes panic ("db_sym.c: db_add_symbol_table");
1825b81b6b3SRodney W. Grimes }
1835b81b6b3SRodney W. Grimes
1845b81b6b3SRodney W. Grimes db_symtabs[db_nsymtab].start = start;
1855b81b6b3SRodney W. Grimes db_symtabs[db_nsymtab].end = end;
1865b81b6b3SRodney W. Grimes db_symtabs[db_nsymtab].name = name;
1875b81b6b3SRodney W. Grimes db_symtabs[db_nsymtab].private = ref;
1885b81b6b3SRodney W. Grimes db_nsymtab++;
1895b81b6b3SRodney W. Grimes }
1905b81b6b3SRodney W. Grimes
1915b81b6b3SRodney W. Grimes /*
1925b81b6b3SRodney W. Grimes * db_qualify("vm_map", "ux") returns "unix:vm_map".
1935b81b6b3SRodney W. Grimes *
1945b81b6b3SRodney W. Grimes * Note: return value points to static data whose content is
1955b81b6b3SRodney W. Grimes * overwritten by each call... but in practice this seems okay.
1965b81b6b3SRodney W. Grimes */
1975b81b6b3SRodney W. Grimes static char *
db_qualify(c_db_sym_t sym,char * symtabname)198a41dd031SPedro F. Giffuni db_qualify(c_db_sym_t sym, char *symtabname)
1995b81b6b3SRodney W. Grimes {
200a1c1e16aSMatthew Dillon const char *symname;
2015b81b6b3SRodney W. Grimes static char tmp[256];
2025b81b6b3SRodney W. Grimes
2035b81b6b3SRodney W. Grimes db_symbol_values(sym, &symname, 0);
2042127f260SArchie Cobbs snprintf(tmp, sizeof(tmp), "%s:%s", symtabname, symname);
2055b81b6b3SRodney W. Grimes return tmp;
2065b81b6b3SRodney W. Grimes }
2075b81b6b3SRodney W. Grimes
208cd508278SPedro F. Giffuni bool
db_eqname(const char * src,const char * dst,int c)209a41dd031SPedro F. Giffuni db_eqname(const char *src, const char *dst, int c)
2105b81b6b3SRodney W. Grimes {
2115b81b6b3SRodney W. Grimes if (!strcmp(src, dst))
2122b490bc7SPedro F. Giffuni return (true);
2135b81b6b3SRodney W. Grimes if (src[0] == c)
2145b81b6b3SRodney W. Grimes return (!strcmp(src+1,dst));
2152b490bc7SPedro F. Giffuni return (false);
2165b81b6b3SRodney W. Grimes }
2175b81b6b3SRodney W. Grimes
218cd508278SPedro F. Giffuni bool
db_value_of_name(const char * name,db_expr_t * valuep)219a41dd031SPedro F. Giffuni db_value_of_name(const char *name, db_expr_t *valuep)
2205b81b6b3SRodney W. Grimes {
221fe08c21aSMatthew Dillon c_db_sym_t sym;
2225b81b6b3SRodney W. Grimes
2235b81b6b3SRodney W. Grimes sym = db_lookup(name);
224fe08c21aSMatthew Dillon if (sym == C_DB_SYM_NULL)
2252b490bc7SPedro F. Giffuni return (false);
2265b81b6b3SRodney W. Grimes db_symbol_values(sym, &name, valuep);
2272b490bc7SPedro F. Giffuni return (true);
2285b81b6b3SRodney W. Grimes }
2295b81b6b3SRodney W. Grimes
230cd508278SPedro F. Giffuni bool
db_value_of_name_pcpu(const char * name,db_expr_t * valuep)231a41dd031SPedro F. Giffuni db_value_of_name_pcpu(const char *name, db_expr_t *valuep)
232eddfbb76SRobert Watson {
233eddfbb76SRobert Watson static char tmp[256];
234eddfbb76SRobert Watson db_expr_t value;
235eddfbb76SRobert Watson c_db_sym_t sym;
236eddfbb76SRobert Watson int cpu;
237eddfbb76SRobert Watson
238eddfbb76SRobert Watson if (db_cpu != -1)
239eddfbb76SRobert Watson cpu = db_cpu;
240eddfbb76SRobert Watson else
241eddfbb76SRobert Watson cpu = curcpu;
242eddfbb76SRobert Watson snprintf(tmp, sizeof(tmp), "pcpu_entry_%s", name);
243eddfbb76SRobert Watson sym = db_lookup(tmp);
244eddfbb76SRobert Watson if (sym == C_DB_SYM_NULL)
2452b490bc7SPedro F. Giffuni return (false);
246eddfbb76SRobert Watson db_symbol_values(sym, &name, &value);
247eddfbb76SRobert Watson if (value < DPCPU_START || value >= DPCPU_STOP)
2482b490bc7SPedro F. Giffuni return (false);
249eddfbb76SRobert Watson *valuep = (db_expr_t)((uintptr_t)value + dpcpu_off[cpu]);
2502b490bc7SPedro F. Giffuni return (true);
251eddfbb76SRobert Watson }
252eddfbb76SRobert Watson
253cd508278SPedro F. Giffuni bool
db_value_of_name_vnet(const char * name,db_expr_t * valuep)254a41dd031SPedro F. Giffuni db_value_of_name_vnet(const char *name, db_expr_t *valuep)
255eddfbb76SRobert Watson {
256eddfbb76SRobert Watson #ifdef VIMAGE
257eddfbb76SRobert Watson static char tmp[256];
258eddfbb76SRobert Watson db_expr_t value;
259eddfbb76SRobert Watson c_db_sym_t sym;
260eddfbb76SRobert Watson struct vnet *vnet;
261eddfbb76SRobert Watson
262eddfbb76SRobert Watson if (db_vnet != NULL)
263eddfbb76SRobert Watson vnet = db_vnet;
264eddfbb76SRobert Watson else
265eddfbb76SRobert Watson vnet = curvnet;
266eddfbb76SRobert Watson snprintf(tmp, sizeof(tmp), "vnet_entry_%s", name);
267eddfbb76SRobert Watson sym = db_lookup(tmp);
268eddfbb76SRobert Watson if (sym == C_DB_SYM_NULL)
2692b490bc7SPedro F. Giffuni return (false);
270eddfbb76SRobert Watson db_symbol_values(sym, &name, &value);
271eddfbb76SRobert Watson if (value < VNET_START || value >= VNET_STOP)
2722b490bc7SPedro F. Giffuni return (false);
273eddfbb76SRobert Watson *valuep = (db_expr_t)((uintptr_t)value + vnet->vnet_data_base);
2742b490bc7SPedro F. Giffuni return (true);
275eddfbb76SRobert Watson #else
2762b490bc7SPedro F. Giffuni return (false);
277eddfbb76SRobert Watson #endif
278eddfbb76SRobert Watson }
2795b81b6b3SRodney W. Grimes
2805b81b6b3SRodney W. Grimes /*
2815b81b6b3SRodney W. Grimes * Lookup a symbol.
2825b81b6b3SRodney W. Grimes * If the symbol has a qualifier (e.g., ux:vm_map),
2835b81b6b3SRodney W. Grimes * then only the specified symbol table will be searched;
2845b81b6b3SRodney W. Grimes * otherwise, all symbol tables will be searched.
2855b81b6b3SRodney W. Grimes */
286fe08c21aSMatthew Dillon static c_db_sym_t
db_lookup(const char * symstr)287a41dd031SPedro F. Giffuni db_lookup(const char *symstr)
2885b81b6b3SRodney W. Grimes {
289fe08c21aSMatthew Dillon c_db_sym_t sp;
2903e85b721SEd Maste int i;
2915b81b6b3SRodney W. Grimes int symtab_start = 0;
2925b81b6b3SRodney W. Grimes int symtab_end = db_nsymtab;
2933e85b721SEd Maste const char *cp;
2945b81b6b3SRodney W. Grimes
2955b81b6b3SRodney W. Grimes /*
2965b81b6b3SRodney W. Grimes * Look for, remove, and remember any symbol table specifier.
2975b81b6b3SRodney W. Grimes */
2985b81b6b3SRodney W. Grimes for (cp = symstr; *cp; cp++) {
2995b81b6b3SRodney W. Grimes if (*cp == ':') {
3005b81b6b3SRodney W. Grimes for (i = 0; i < db_nsymtab; i++) {
301a1c1e16aSMatthew Dillon int n = strlen(db_symtabs[i].name);
302a1c1e16aSMatthew Dillon
303a1c1e16aSMatthew Dillon if (
304a1c1e16aSMatthew Dillon n == (cp - symstr) &&
305a1c1e16aSMatthew Dillon strncmp(symstr, db_symtabs[i].name, n) == 0
306a1c1e16aSMatthew Dillon ) {
3075b81b6b3SRodney W. Grimes symtab_start = i;
3085b81b6b3SRodney W. Grimes symtab_end = i + 1;
3095b81b6b3SRodney W. Grimes break;
3105b81b6b3SRodney W. Grimes }
3115b81b6b3SRodney W. Grimes }
3125b81b6b3SRodney W. Grimes if (i == db_nsymtab) {
3135b81b6b3SRodney W. Grimes db_error("invalid symbol table name");
3145b81b6b3SRodney W. Grimes }
3155b81b6b3SRodney W. Grimes symstr = cp+1;
3165b81b6b3SRodney W. Grimes }
3175b81b6b3SRodney W. Grimes }
3185b81b6b3SRodney W. Grimes
3195b81b6b3SRodney W. Grimes /*
3205b81b6b3SRodney W. Grimes * Look in the specified set of symbol tables.
3215b81b6b3SRodney W. Grimes * Return on first match.
3225b81b6b3SRodney W. Grimes */
3235b81b6b3SRodney W. Grimes for (i = symtab_start; i < symtab_end; i++) {
324169cd910SPoul-Henning Kamp sp = X_db_lookup(&db_symtabs[i], symstr);
325169cd910SPoul-Henning Kamp if (sp) {
3265b81b6b3SRodney W. Grimes db_last_symtab = &db_symtabs[i];
3275b81b6b3SRodney W. Grimes return sp;
3285b81b6b3SRodney W. Grimes }
3295b81b6b3SRodney W. Grimes }
3305b81b6b3SRodney W. Grimes return 0;
3315b81b6b3SRodney W. Grimes }
3325b81b6b3SRodney W. Grimes
3335b81b6b3SRodney W. Grimes /*
3342b490bc7SPedro F. Giffuni * If true, check across symbol tables for multiple occurrences
33594e24bf0SBruce Evans * of a name. Might slow things down quite a bit.
33694e24bf0SBruce Evans */
337cd508278SPedro F. Giffuni static volatile bool db_qualify_ambiguous_names = false;
33894e24bf0SBruce Evans
33994e24bf0SBruce Evans /*
3405b81b6b3SRodney W. Grimes * Does this symbol name appear in more than one symbol table?
3415b81b6b3SRodney W. Grimes * Used by db_symbol_values to decide whether to qualify a symbol.
3425b81b6b3SRodney W. Grimes */
343cd508278SPedro F. Giffuni static bool
db_symbol_is_ambiguous(c_db_sym_t sym)344a41dd031SPedro F. Giffuni db_symbol_is_ambiguous(c_db_sym_t sym)
3455b81b6b3SRodney W. Grimes {
346a1c1e16aSMatthew Dillon const char *sym_name;
3473e85b721SEd Maste int i;
3483e85b721SEd Maste bool found_once = false;
3495b81b6b3SRodney W. Grimes
3505b81b6b3SRodney W. Grimes if (!db_qualify_ambiguous_names)
3512b490bc7SPedro F. Giffuni return (false);
3525b81b6b3SRodney W. Grimes
3535b81b6b3SRodney W. Grimes db_symbol_values(sym, &sym_name, 0);
3545b81b6b3SRodney W. Grimes for (i = 0; i < db_nsymtab; i++) {
3555b81b6b3SRodney W. Grimes if (X_db_lookup(&db_symtabs[i], sym_name)) {
3565b81b6b3SRodney W. Grimes if (found_once)
357cd508278SPedro F. Giffuni return (true);
3582b490bc7SPedro F. Giffuni found_once = true;
3595b81b6b3SRodney W. Grimes }
3605b81b6b3SRodney W. Grimes }
3612b490bc7SPedro F. Giffuni return (false);
3625b81b6b3SRodney W. Grimes }
3635b81b6b3SRodney W. Grimes
3645b81b6b3SRodney W. Grimes /*
3655b81b6b3SRodney W. Grimes * Find the closest symbol to val, and return its name
3665b81b6b3SRodney W. Grimes * and the difference between val and the symbol found.
3675b81b6b3SRodney W. Grimes */
368fe08c21aSMatthew Dillon c_db_sym_t
db_search_symbol(db_addr_t val,db_strategy_t strategy,db_expr_t * offp)369a41dd031SPedro F. Giffuni db_search_symbol(db_addr_t val, db_strategy_t strategy, db_expr_t *offp)
3705b81b6b3SRodney W. Grimes {
3715b81b6b3SRodney W. Grimes unsigned int diff;
372ecbb00a2SDoug Rabson size_t newdiff;
3733e85b721SEd Maste int i;
3748310609fSEric van Gyzen c_db_sym_t ret, sym;
3755b81b6b3SRodney W. Grimes
3768310609fSEric van Gyzen /*
3778310609fSEric van Gyzen * The kernel will never map the first page, so any symbols in that
3788310609fSEric van Gyzen * range cannot refer to addresses. Some third-party assembly files
3798310609fSEric van Gyzen * define internal constants which appear in their symbol table.
3808310609fSEric van Gyzen * Avoiding the lookup for those symbols avoids replacing small offsets
3818310609fSEric van Gyzen * with those symbols during disassembly.
3828310609fSEric van Gyzen */
3838310609fSEric van Gyzen if (val < PAGE_SIZE) {
3848310609fSEric van Gyzen *offp = 0;
3858310609fSEric van Gyzen return (C_DB_SYM_NULL);
3868310609fSEric van Gyzen }
3878310609fSEric van Gyzen
3888310609fSEric van Gyzen ret = C_DB_SYM_NULL;
389ecb65f66SJohn Baldwin newdiff = diff = val;
3905b81b6b3SRodney W. Grimes for (i = 0; i < db_nsymtab; i++) {
3915b81b6b3SRodney W. Grimes sym = X_db_search_symbol(&db_symtabs[i], val, strategy, &newdiff);
392ecb65f66SJohn Baldwin if ((uintmax_t)newdiff < (uintmax_t)diff) {
3935b81b6b3SRodney W. Grimes db_last_symtab = &db_symtabs[i];
3945b81b6b3SRodney W. Grimes diff = newdiff;
3955b81b6b3SRodney W. Grimes ret = sym;
3965b81b6b3SRodney W. Grimes }
3975b81b6b3SRodney W. Grimes }
3985b81b6b3SRodney W. Grimes *offp = diff;
3995b81b6b3SRodney W. Grimes return ret;
4005b81b6b3SRodney W. Grimes }
4015b81b6b3SRodney W. Grimes
4025b81b6b3SRodney W. Grimes /*
4035b81b6b3SRodney W. Grimes * Return name and value of a symbol
4045b81b6b3SRodney W. Grimes */
4055b81b6b3SRodney W. Grimes void
db_symbol_values(c_db_sym_t sym,const char ** namep,db_expr_t * valuep)406a41dd031SPedro F. Giffuni db_symbol_values(c_db_sym_t sym, const char **namep, db_expr_t *valuep)
4075b81b6b3SRodney W. Grimes {
4085b81b6b3SRodney W. Grimes db_expr_t value;
4095b81b6b3SRodney W. Grimes
4105b81b6b3SRodney W. Grimes if (sym == DB_SYM_NULL) {
4119f915a92SPedro F. Giffuni *namep = NULL;
4125b81b6b3SRodney W. Grimes return;
4135b81b6b3SRodney W. Grimes }
4145b81b6b3SRodney W. Grimes
4156edf3d91SDoug Rabson X_db_symbol_values(db_last_symtab, sym, namep, &value);
4165b81b6b3SRodney W. Grimes
4175b81b6b3SRodney W. Grimes if (db_symbol_is_ambiguous(sym))
4185b81b6b3SRodney W. Grimes *namep = db_qualify(sym, db_last_symtab->name);
4195b81b6b3SRodney W. Grimes if (valuep)
4205b81b6b3SRodney W. Grimes *valuep = value;
4215b81b6b3SRodney W. Grimes }
4225b81b6b3SRodney W. Grimes
4235b81b6b3SRodney W. Grimes /*
4245b81b6b3SRodney W. Grimes * Print a the closest symbol to value
4255b81b6b3SRodney W. Grimes *
4265b81b6b3SRodney W. Grimes * After matching the symbol according to the given strategy
4275b81b6b3SRodney W. Grimes * we print it in the name+offset format, provided the symbol's
4285b81b6b3SRodney W. Grimes * value is close enough (eg smaller than db_maxoff).
4295b81b6b3SRodney W. Grimes * We also attempt to print [filename:linenum] when applicable
4305b81b6b3SRodney W. Grimes * (eg for procedure names).
4315b81b6b3SRodney W. Grimes *
4325b81b6b3SRodney W. Grimes * If we could not find a reasonable name+offset representation,
4335b81b6b3SRodney W. Grimes * then we just print the value in hex. Small values might get
4345b81b6b3SRodney W. Grimes * bogus symbol associations, e.g. 3 might get some absolute
4355b81b6b3SRodney W. Grimes * value like _INCLUDE_VERSION or something, therefore we do
4367d350e72SBruce Evans * not accept symbols whose value is "small" (and use plain hex).
4375b81b6b3SRodney W. Grimes */
4385b81b6b3SRodney W. Grimes
4393da6ef3cSBruce Evans db_expr_t db_maxoff = 0x10000;
4405b81b6b3SRodney W. Grimes
4415b81b6b3SRodney W. Grimes void
db_printsym(db_expr_t off,db_strategy_t strategy)442a41dd031SPedro F. Giffuni db_printsym(db_expr_t off, db_strategy_t strategy)
4435b81b6b3SRodney W. Grimes {
4445b81b6b3SRodney W. Grimes db_expr_t d;
4455b81b6b3SRodney W. Grimes char *filename;
446a1c1e16aSMatthew Dillon const char *name;
4475b81b6b3SRodney W. Grimes int linenum;
448fe08c21aSMatthew Dillon c_db_sym_t cursym;
4495b81b6b3SRodney W. Grimes
450f434f351SBruce Evans if (off < 0 && off >= -db_maxoff) {
451596dfc04SBruce Evans db_printf("%+#lr", (long)off);
4527d350e72SBruce Evans return;
4537d350e72SBruce Evans }
454f434f351SBruce Evans cursym = db_search_symbol(off, strategy, &d);
455f434f351SBruce Evans db_symbol_values(cursym, &name, NULL);
456f434f351SBruce Evans if (name == NULL || d >= (db_addr_t)db_maxoff) {
457596dfc04SBruce Evans db_printf("%#lr", (unsigned long)off);
4585b81b6b3SRodney W. Grimes return;
4595b81b6b3SRodney W. Grimes }
4609aece96fSPoul-Henning Kamp #ifdef DDB_NUMSYM
4619aece96fSPoul-Henning Kamp db_printf("%#lr = %s", (unsigned long)off, name);
4629aece96fSPoul-Henning Kamp #else
4635b81b6b3SRodney W. Grimes db_printf("%s", name);
4649aece96fSPoul-Henning Kamp #endif
4655b81b6b3SRodney W. Grimes if (d)
4661c6989faSPeter Wemm db_printf("+%+#lr", (long)d);
4675b81b6b3SRodney W. Grimes if (strategy == DB_STGY_PROC) {
4685b81b6b3SRodney W. Grimes if (db_line_at_pc(cursym, &filename, &linenum, off))
4695b81b6b3SRodney W. Grimes db_printf(" [%s:%d]", filename, linenum);
4705b81b6b3SRodney W. Grimes }
4715b81b6b3SRodney W. Grimes }
4725b81b6b3SRodney W. Grimes
473cd508278SPedro F. Giffuni static bool
db_line_at_pc(c_db_sym_t sym,char ** filename,int * linenum,db_expr_t pc)474a41dd031SPedro F. Giffuni db_line_at_pc(c_db_sym_t sym, char **filename, int *linenum, db_expr_t pc)
4755b81b6b3SRodney W. Grimes {
476cd508278SPedro F. Giffuni return (X_db_line_at_pc(db_last_symtab, sym, filename, linenum, pc));
4775b81b6b3SRodney W. Grimes }
478f7d75744SDavid Greenman
479cd508278SPedro F. Giffuni bool
db_sym_numargs(c_db_sym_t sym,int * nargp,char ** argnames)480a41dd031SPedro F. Giffuni db_sym_numargs(c_db_sym_t sym, int *nargp, char **argnames)
481f7d75744SDavid Greenman {
482cd508278SPedro F. Giffuni return (X_db_sym_numargs(db_last_symtab, sym, nargp, argnames));
483f7d75744SDavid Greenman }
484754cb545SMitchell Horne
485754cb545SMitchell Horne void
db_decode_syscall(struct thread * td,u_int number)486*aba921bdSMitchell Horne db_decode_syscall(struct thread *td, u_int number)
487754cb545SMitchell Horne {
488754cb545SMitchell Horne struct proc *p;
489754cb545SMitchell Horne
490*aba921bdSMitchell Horne db_printf(" (%u", number);
491754cb545SMitchell Horne p = (td != NULL) ? td->td_proc : NULL;
492*aba921bdSMitchell Horne if (p != NULL) {
493*aba921bdSMitchell Horne db_printf(", %s, %s", p->p_sysent->sv_name,
494*aba921bdSMitchell Horne syscallname(p, number));
495754cb545SMitchell Horne }
496754cb545SMitchell Horne db_printf(")");
497754cb545SMitchell Horne }
498