Bug Summary

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