Bug Summary

File:obj-scan-build/../ddb/db_sym.c
Location:line 415, column 2
Description:Access to field 'type' results in a dereference of a null pointer (loaded from variable 'stab')

Annotated Source Code

1/*
2 * Mach Operating System
3 * Copyright (c) 1992,1991,1990 Carnegie Mellon University
4 * All Rights Reserved.
5 *
6 * Permission to use, copy, modify and distribute this software and its
7 * documentation is hereby granted, provided that both the copyright
8 * notice and this permission notice appear in all copies of the
9 * software, derivative works or modified versions, and any portions
10 * thereof, and that both notices appear in supporting documentation.
11 *
12 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15 *
16 * Carnegie Mellon requests users of this software to return to
17 *
18 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
19 * School of Computer Science
20 * Carnegie Mellon University
21 * Pittsburgh PA 15213-3890
22 *
23 * any improvements or extensions that they make and grant Carnegie Mellon
24 * the rights to redistribute these changes.
25 */
26/*
27 * Author: David B. Golub, Carnegie Mellon University
28 * Date: 7/90
29 */
30
31#if MACH_KDB1
32
33#include <string.h>
34#include <mach/std_types.h>
35#include <machine/db_machdep.h>
36#include <ddb/db_command.h>
37#include <ddb/db_output.h>
38#include <ddb/db_sym.h>
39#include <ddb/db_task_thread.h>
40#include <ddb/db_aout.h>
41
42#include <vm/vm_map.h> /* vm_map_t */
43
44/*
45 * Multiple symbol tables
46 */
47#define MAXNOSYMTABS5 5 /* mach, bootstrap, ux, emulator, 1 spare */
48
49db_symtab_t db_symtabs[MAXNOSYMTABS5] = {{0,},};
50int db_nsymtab = 0;
51
52db_symtab_t *db_last_symtab;
53
54/*
55 * Add symbol table, with given name, to list of symbol tables.
56 */
57boolean_t
58db_add_symbol_table(
59 int type,
60 char *start,
61 char *end,
62 char *name,
63 char *ref,
64 char *map_pointer)
65{
66 db_symtab_t *st;
67 extern vm_map_t kernel_map;
68
69 if (db_nsymtab >= MAXNOSYMTABS5)
70 return (FALSE((boolean_t) 0));
71
72 st = &db_symtabs[db_nsymtab];
73 st->type = type;
74 st->start = start;
75 st->end = end;
76 st->private = ref;
77 st->map_pointer = (map_pointer == (char *)kernel_map)? 0: map_pointer;
78 strncpy(st->name, name, sizeof st->name - 1);
79 st->name[sizeof st->name - 1] = '\0';
80
81 db_nsymtab++;
82
83 return (TRUE((boolean_t) 1));
84}
85
86/*
87 * db_qualify("vm_map", "ux") returns "ux::vm_map".
88 *
89 * Note: return value points to static data whose content is
90 * overwritten by each call... but in practice this seems okay.
91 */
92static char * __attribute__ ((pure))
93db_qualify(symname, symtabname)
94 const char *symname;
95 const char *symtabname;
96{
97 static char tmp[256];
98 char *s;
99
100 s = tmp;
101 while ((*s++ = *symtabname++)) {
102 }
103 s[-1] = ':';
104 *s++ = ':';
105 while ((*s++ = *symname++)) {
106 }
107 return tmp;
108}
109
110
111boolean_t
112db_eqname( const char* src, const char* dst, char c )
113{
114 if (!strcmp(src, dst))
115 return (TRUE((boolean_t) 1));
116 if (src[0] == c)
117 return (!strcmp(src+1,dst));
118 return (FALSE((boolean_t) 0));
119}
120
121boolean_t
122db_value_of_name(
123 char *name,
124 db_expr_t *valuep)
125{
126 db_sym_t sym;
127
128 sym = db_lookup(name);
129 if (sym == DB_SYM_NULL((db_sym_t)0))
130 return (FALSE((boolean_t) 0));
131 db_symbol_values(0, sym, &name, valuep);
132
133 db_free_symbol(sym);
134 return (TRUE((boolean_t) 1));
135}
136
137/*
138 * Lookup a symbol.
139 * If the symbol has a qualifier (e.g., ux::vm_map),
140 * then only the specified symbol table will be searched;
141 * otherwise, all symbol tables will be searched.
142 */
143db_sym_t
144db_lookup(char *symstr)
145{
146 db_sym_t sp;
147 int i;
148 int symtab_start = 0;
149 int symtab_end = db_nsymtab;
150 char *cp;
151
152 /*
153 * Look for, remove, and remember any symbol table specifier.
154 */
155 for (cp = symstr; *cp; cp++) {
156 if (*cp == ':' && cp[1] == ':') {
157 *cp = '\0';
158 for (i = 0; i < db_nsymtab; i++) {
159 if (! strcmp(symstr, db_symtabs[i].name)) {
160 symtab_start = i;
161 symtab_end = i + 1;
162 break;
163 }
164 }
165 *cp = ':';
166 if (i == db_nsymtab)
167 db_error("Invalid symbol table name\n");
168 symstr = cp+2;
169 }
170 }
171
172 /*
173 * Look in the specified set of symbol tables.
174 * Return on first match.
175 */
176 for (i = symtab_start; i < symtab_end; i++) {
177 if ((sp = X_db_lookup(&db_symtabs[i], symstr)x_db[(&db_symtabs[i])->type].lookup(&db_symtabs[i]
,symstr)
)) {
178 db_last_symtab = &db_symtabs[i];
179 return sp;
180 }
181 db_free_symbol(sp);
182 }
183 return 0;
184}
185
186/*
187 * Common utility routine to parse a symbol string into a file
188 * name, a symbol name and line number.
189 * This routine is called from X_db_lookup if the object dependent
190 * handler supports qualified search with a file name or a line number.
191 * It parses the symbol string, and call an object dependent routine
192 * with parsed file name, symbol name and line number.
193 */
194db_sym_t
195db_sym_parse_and_lookup(
196 db_sym_t (*func)(),
197 db_symtab_t *symtab,
198 char *symstr)
199{
200 char *p;
201 int n;
202 int n_name;
203 int line_number;
204 char *file_name = 0;
205 char *sym_name = 0;
206 char *component[3];
207 db_sym_t found = DB_SYM_NULL((db_sym_t)0);
208
209 /*
210 * disassemble the symbol into components:
211 * [file_name:]symbol[:line_nubmer]
212 */
213 component[0] = symstr;
214 component[1] = component[2] = 0;
215 for (p = symstr, n = 1; *p; p++) {
216 if (*p == ':') {
217 if (n >= 3)
218 break;
219 *p = 0;
220 component[n++] = p+1;
221 }
222 }
223 if (*p != 0)
224 goto out;
225 line_number = 0;
226 n_name = n;
227 p = component[n-1];
228 if (*p >= '0' && *p <= '9') {
229 if (n == 1)
230 goto out;
231 for (line_number = 0; *p; p++) {
232 if (*p < '0' || *p > '9')
233 goto out;
234 line_number = line_number*10 + *p - '0';
235 }
236 n_name--;
237 } else if (n >= 3)
238 goto out;
239 if (n_name == 1) {
240 for (p = component[0]; *p && *p != '.'; p++);
241 if (*p == '.') {
242 file_name = component[0];
243 sym_name = 0;
244 } else {
245 file_name = 0;
246 sym_name = component[0];
247 }
248 } else {
249 file_name = component[0];
250 sym_name = component[1];
251 }
252 found = func(symtab, file_name, sym_name, line_number);
253
254out:
255 while (--n >= 1)
256 component[n][-1] = ':';
257 return(found);
258}
259
260/*
261 * Does this symbol name appear in more than one symbol table?
262 * Used by db_symbol_values to decide whether to qualify a symbol.
263 */
264boolean_t db_qualify_ambiguous_names = FALSE((boolean_t) 0);
265
266boolean_t
267db_name_is_ambiguous(char *sym_name)
268{
269 int i;
270 boolean_t found_once = FALSE((boolean_t) 0);
271
272 if (!db_qualify_ambiguous_names)
273 return FALSE((boolean_t) 0);
274
275 for (i = 0; i < db_nsymtab; i++) {
276 db_sym_t sp = X_db_lookup(&db_symtabs[i], sym_name)x_db[(&db_symtabs[i])->type].lookup(&db_symtabs[i]
,sym_name)
;
277 if (sp) {
278 if (found_once)
279 {
280 db_free_symbol(sp);
281 return TRUE((boolean_t) 1);
282 }
283 found_once = TRUE((boolean_t) 1);
284 }
285 db_free_symbol(sp);
286 }
287 return FALSE((boolean_t) 0);
288}
289
290/*
291 * Find the closest symbol to val, and return its name
292 * and the difference between val and the symbol found.
293 *
294 * Logic change. If the task argument is non NULL and a
295 * matching symbol is found in a symbol table which explictly
296 * specifies its map to be task->map, that symbol will have
297 * precedence over any symbol from a symbol table will a null
298 * map. This allows overlapping kernel/user maps to work correctly.
299 *
300 */
301db_sym_t
302db_search_task_symbol(
303 db_addr_t val,
304 db_strategy_t strategy,
305 db_addr_t *offp, /* better be unsigned */
306 task_t task)
307{
308 db_sym_t ret;
309
310 if (task != TASK_NULL((task_t) 0))
311 ret = db_search_in_task_symbol(val, strategy, offp, task);
312 else
313 {
314 ret = db_search_in_task_symbol(val, strategy, offp, task);
315 /*
316 db_search_in_task_symbol will return success with
317 a very large offset when it should have failed.
318 */
319 if (ret == DB_SYM_NULL((db_sym_t)0) || (*offp) > 0x1000000)
320 {
321 db_free_symbol(ret);
322 task = db_current_task()(((active_threads[(0)]))? (active_threads[(0)])->task: ((task_t
) 0))
;
323 ret = db_search_in_task_symbol(val, strategy, offp, task);
324 }
325 }
326
327 return ret;
328}
329
330db_sym_t
331db_search_in_task_symbol(
332 db_addr_t val,
333 db_strategy_t strategy,
334 db_addr_t *offp,
335 task_t task)
336{
337 vm_size_t diff;
338 vm_size_t newdiff;
339 int i;
340 db_symtab_t *sp;
341 db_sym_t ret = DB_SYM_NULL((db_sym_t)0), sym;
342 vm_map_t map_for_val;
343
344 map_for_val = (task == TASK_NULL((task_t) 0))? VM_MAP_NULL((vm_map_t) 0): task->map;
345 newdiff = diff = ~0;
346 db_last_symtab = (db_symtab_t *) 0;
347 for (sp = &db_symtabs[0], i = 0; i < db_nsymtab; sp++, i++)
348 {
349 newdiff = ~0;
350 if ((vm_map_t)sp->map_pointer == VM_MAP_NULL((vm_map_t) 0) ||
351 (vm_map_t)sp->map_pointer == map_for_val)
352 {
353 sym = X_db_search_symbol(sp, val, strategy, (db_expr_t*)&newdiff)x_db[(sp)->type].search_symbol(sp,val,strategy,(db_expr_t*
)&newdiff)
;
354 if (sym == DB_SYM_NULL((db_sym_t)0))
355 continue;
356 if (db_last_symtab == (db_symtab_t *) 0)
357 { /* first hit */
358 db_last_symtab = sp;
359 diff = newdiff;
360 db_free_symbol(ret);
361 ret = sym;
362 continue;
363 }
364 if ((vm_map_t) sp->map_pointer == VM_MAP_NULL((vm_map_t) 0) &&
365 (vm_map_t) db_last_symtab->map_pointer == VM_MAP_NULL((vm_map_t) 0) &&
366 newdiff < diff )
367 { /* closer null map match */
368 db_last_symtab = sp;
369 diff = newdiff;
370 db_free_symbol(ret);
371 ret = sym;
372 continue;
373 }
374 if ((vm_map_t) sp->map_pointer != VM_MAP_NULL((vm_map_t) 0) &&
375 (newdiff < 0x100000) &&
376 ((vm_map_t) db_last_symtab->map_pointer == VM_MAP_NULL((vm_map_t) 0) ||
377 newdiff < diff ))
378 { /* update if new is in matching map and symbol is "close",
379 and
380 old is VM_MAP_NULL or old in is matching map but is further away
381 */
382 db_last_symtab = sp;
383 diff = newdiff;
384 db_free_symbol(ret);
385 ret = sym;
386 continue;
387 }
388 }
389 }
390
391 *offp = diff;
392 return ret;
393}
394
395/*
396 * Return name and value of a symbol
397 */
398void
399db_symbol_values(
400 db_symtab_t *stab,
401 db_sym_t sym,
402 char **namep,
403 db_expr_t *valuep)
404{
405 db_expr_t value;
406 char *name;
407
408 if (sym == DB_SYM_NULL((db_sym_t)0)) {
4
Assuming 'sym' is not equal to null
5
Taking false branch
409 *namep = 0;
410 return;
411 }
412 if (stab == 0)
6
Taking true branch
413 stab = db_last_symtab;
414
415 X_db_symbol_values(stab, sym, &name, &value)x_db[(stab)->type].symbol_values(stab,sym,&name,&value
)
;
7
Within the expansion of the macro 'X_db_symbol_values':
a
Access to field 'type' results in a dereference of a null pointer (loaded from variable 'stab')
416
417 if (db_name_is_ambiguous(name))
418 *namep = db_qualify(name, db_last_symtab->name);
419 else
420 *namep = name;
421 if (valuep)
422 *valuep = value;
423}
424
425
426/*
427 * Print the closest symbol to value
428 *
429 * After matching the symbol according to the given strategy
430 * we print it in the name+offset format, provided the symbol's
431 * value is close enough (eg smaller than db_maxoff).
432 * We also attempt to print [filename:linenum] when applicable
433 * (eg for procedure names).
434 *
435 * If we could not find a reasonable name+offset representation,
436 * then we just print the value in hex. Small values might get
437 * bogus symbol associations, e.g. 3 might get some absolute
438 * value like _INCLUDE_VERSION or something, therefore we do
439 * not accept symbols whose value is zero (and use plain hex).
440 */
441
442unsigned long db_maxoff = 0x4000;
443
444void
445db_task_printsym(off, strategy, task)
446 db_addr_t off;
447 db_strategy_t strategy;
448 task_t task;
449{
450 db_addr_t d;
451 char *filename;
452 char *name;
453 db_expr_t value;
454 int linenum;
455 db_sym_t cursym;
456
457 cursym = db_search_task_symbol(off, strategy, &d, task);
458 db_symbol_values(0, cursym, &name, &value);
2
Passing null pointer value via 1st parameter 'stab'
3
Calling 'db_symbol_values'
459 if (name == 0 || d >= db_maxoff || value == 0 || *name == 0) {
460 db_printf("%#n", off);
461 db_free_symbol(cursym);
462 return;
463 }
464 db_printf("%s", name);
465 if (d)
466 db_printf("+0x%x", d);
467 if (strategy == DB_STGY_PROC2) {
468 if (db_line_at_pc(cursym, &filename, &linenum, off)) {
469 db_printf(" [%s", filename);
470 if (linenum > 0)
471 db_printf(":%d", linenum);
472 db_printf("]");
473 }
474 }
475 db_free_symbol(cursym);
476}
477
478void
479db_printsym(off, strategy)
480 db_expr_t off;
481 db_strategy_t strategy;
482{
483 db_task_printsym(off, strategy, TASK_NULL((task_t) 0));
1
Calling 'db_task_printsym'
484}
485
486boolean_t
487db_line_at_pc( sym, filename, linenum, pc)
488 db_sym_t sym;
489 char **filename;
490 int *linenum;
491 db_addr_t pc;
492{
493 return (db_last_symtab) ?
494 X_db_line_at_pc( db_last_symtab, sym, filename, linenum, pc)x_db[(db_last_symtab)->type].line_at_pc(db_last_symtab,sym
,filename,linenum,pc)
:
495 FALSE((boolean_t) 0);
496}
497
498void db_free_symbol(db_sym_t s)
499{
500 return (db_last_symtab) ?
501 X_db_free_symbol( db_last_symtab, s)x_db[(db_last_symtab)->type].free_symbol(s) :
502 FALSE((boolean_t) 0);
503}
504
505/*
506 * Switch into symbol-table specific routines
507 */
508
509void dummy_db_free_symbol(db_sym_t symbol) { }
510
511struct db_sym_switch x_db[] = {
512
513 /* BSD a.out format (really, sdb/dbx(1) symtabs) */
514#ifdef DB_NO_AOUT
515 { 0,},
516#else /* DB_NO_AOUT */
517 { aout_db_sym_init, aout_db_lookup, aout_db_search_symbol,
518 aout_db_line_at_pc, aout_db_symbol_values, dummy_db_free_symbol },
519#endif /* DB_NO_AOUT */
520
521 { 0,},
522
523 /* Machdep, not inited here */
524 { 0,}
525
526};
527
528#endif /* MACH_KDB */