Bug Summary

File:obj-scan-build/../i386/i386/db_trace.c
Location:line 166, column 10
Description:Access to field 'pcb' results in a dereference of a null pointer (loaded from variable 'thread')

Annotated Source Code

1/*
2 * Mach Operating System
3 * Copyright (c) 1993,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#if MACH_KDB1
28
29#include <string.h>
30
31#include <mach/boolean.h>
32#include <vm/vm_map.h>
33#include <kern/thread.h>
34#include <kern/task.h>
35
36#include <machine/db_machdep.h>
37#include <machine/machspl.h>
38#include <machine/db_interface.h>
39#include <machine/db_trace.h>
40
41#include <ddb/db_access.h>
42#include <ddb/db_command.h>
43#include <ddb/db_output.h>
44#include <ddb/db_sym.h>
45#include <ddb/db_variables.h>
46#include <ddb/db_task_thread.h>
47
48#include "trap.h"
49
50/*
51 * Machine register set.
52 */
53struct db_variable db_regs[] = {
54 { "cs", (long *)&ddb_regs.cs, db_i386_reg_value },
55 { "ds", (long *)&ddb_regs.ds, db_i386_reg_value },
56 { "es", (long *)&ddb_regs.es, db_i386_reg_value },
57 { "fs", (long *)&ddb_regs.fs, db_i386_reg_value },
58 { "gs", (long *)&ddb_regs.gs, db_i386_reg_value },
59 { "ss", (long *)&ddb_regs.ss, db_i386_reg_value },
60 { "eax",(long *)&ddb_regs.eax, db_i386_reg_value },
61 { "ecx",(long *)&ddb_regs.ecx, db_i386_reg_value },
62 { "edx",(long *)&ddb_regs.edx, db_i386_reg_value },
63 { "ebx",(long *)&ddb_regs.ebx, db_i386_reg_value },
64 { "esp",(long *)&ddb_regs.uesp,db_i386_reg_value },
65 { "ebp",(long *)&ddb_regs.ebp, db_i386_reg_value },
66 { "esi",(long *)&ddb_regs.esi, db_i386_reg_value },
67 { "edi",(long *)&ddb_regs.edi, db_i386_reg_value },
68 { "eip",(long *)&ddb_regs.eip, db_i386_reg_value },
69 { "efl",(long *)&ddb_regs.efl, db_i386_reg_value },
70};
71struct db_variable *db_eregs = db_regs + sizeof(db_regs)/sizeof(db_regs[0]);
72
73/*
74 * Stack trace.
75 */
76#define INKERNEL(va)(((vm_offset_t)(va)) >= 0xC0000000UL) (((vm_offset_t)(va)) >= VM_MIN_KERNEL_ADDRESS0xC0000000UL)
77
78struct i386_frame {
79 struct i386_frame *f_frame;
80 long f_retaddr;
81 long f_arg0;
82};
83
84#define TRAP1 1
85#define INTERRUPT2 2
86#define SYSCALL3 3
87
88db_addr_t db_user_trap_symbol_value = 0;
89db_addr_t db_kernel_trap_symbol_value = 0;
90db_addr_t db_interrupt_symbol_value = 0;
91db_addr_t db_return_to_iret_symbol_value = 0;
92db_addr_t db_syscall_symbol_value = 0;
93boolean_t db_trace_symbols_found = FALSE((boolean_t) 0);
94
95struct i386_kregs {
96 char *name;
97 long offset;
98} i386_kregs[] = {
99 { "ebx", (long)(&((struct i386_kernel_state *)0)->k_ebx) },
100 { "esp", (long)(&((struct i386_kernel_state *)0)->k_esp) },
101 { "ebp", (long)(&((struct i386_kernel_state *)0)->k_ebp) },
102 { "edi", (long)(&((struct i386_kernel_state *)0)->k_edi) },
103 { "esi", (long)(&((struct i386_kernel_state *)0)->k_esi) },
104 { "eip", (long)(&((struct i386_kernel_state *)0)->k_eip) },
105 { 0 },
106};
107
108long *
109db_lookup_i386_kreg(
110 const char *name,
111 const long *kregp)
112{
113 struct i386_kregs *kp;
114
115 for (kp = i386_kregs; kp->name; kp++) {
116 if (strcmp(name, kp->name) == 0)
117 return (long *)((long)kregp + kp->offset);
118 }
119 return 0;
120}
121
122void
123db_i386_reg_value(
124 struct db_variable *vp,
125 db_expr_t *valuep,
126 int flag,
127 db_var_aux_param_t ap)
128{
129 long *dp = 0;
130 db_expr_t null_reg = 0;
131 thread_t thread = ap->thread;
1
Variable 'thread' initialized here
132 extern unsigned int_stack_high;
133
134 if (db_option(ap->modif, 'u')) {
2
Taking false branch
135 if (thread == THREAD_NULL((thread_t) 0)) {
136 if ((thread = current_thread()(active_threads[(0)])) == THREAD_NULL((thread_t) 0))
137 db_error("no user registers\n");
138 }
139 if (thread == current_thread()(active_threads[(0)])) {
140 if (ddb_regs.cs & 0x3)
141 dp = vp->valuep;
142 else if (ddb_regs.ebp < int_stack_high)
143 db_error("cannot get/set user registers in nested interrupt\n");
144 }
145 } else {
146 if (thread == THREAD_NULL((thread_t) 0) || thread == current_thread()(active_threads[(0)])) {
3
Assuming 'thread' is equal to null
147 dp = vp->valuep;
148 } else if ((thread->state & TH_SWAPPED0x0100) == 0 &&
149 thread->kernel_stack) {
150 dp = db_lookup_i386_kreg(vp->name,
151 (long *)(STACK_IKS(thread->kernel_stack)((struct i386_kernel_state *)((thread->kernel_stack) + (1*
4096)) - 1)
));
152 if (dp == 0)
153 dp = &null_reg;
154 } else if ((thread->state & TH_SWAPPED0x0100) &&
155 thread->swap_func != thread_exception_return) {
156/*.....this breaks t/t $taskN.0...*/
157 /* only EIP is valid */
158 if (vp->valuep == (long *) &ddb_regs.eip) {
159 dp = (long *)(&thread->swap_func);
160 } else {
161 dp = &null_reg;
162 }
163 }
164 }
165 if (dp == 0) {
4
Assuming 'dp' is equal to null
5
Taking true branch
166 if (thread->pcb == 0)
6
Access to field 'pcb' results in a dereference of a null pointer (loaded from variable 'thread')
167 db_error("no pcb\n");
168 dp = (long *)((long)(&thread->pcb->iss) +
169 ((long)vp->valuep - (long)&ddb_regs));
170 }
171 if (flag == DB_VAR_SET1)
172 *dp = *valuep;
173 else
174 *valuep = *dp;
175}
176
177void
178db_find_trace_symbols(void)
179{
180 db_expr_t value;
181#ifdef __ELF__1
182#define P
183#else
184#define P "_"
185#endif
186 if (db_value_of_name(P"user_trap", &value))
187 db_user_trap_symbol_value = (db_addr_t) value;
188 if (db_value_of_name(P"kernel_trap", &value))
189 db_kernel_trap_symbol_value = (db_addr_t) value;
190 if (db_value_of_name(P"interrupt", &value))
191 db_interrupt_symbol_value = (db_addr_t) value;
192 if (db_value_of_name(P"return_to_iret", &value))
193 db_return_to_iret_symbol_value = (db_addr_t) value;
194 if (db_value_of_name(P"syscall", &value))
195 db_syscall_symbol_value = (db_addr_t) value;
196#undef P
197 db_trace_symbols_found = TRUE((boolean_t) 1);
198}
199
200/*
201 * Figure out how many arguments were passed into the frame at "fp".
202 */
203const int db_numargs_default = 5;
204
205int
206db_numargs(
207 struct i386_frame *fp,
208 task_t task)
209{
210 long *argp;
211 long inst;
212 long args;
213 extern char etext[];
214
215 argp = (long *)db_get_task_value((long)&fp->f_retaddr, sizeof(long), FALSE((boolean_t) 0), task);
216 if (argp < (long *)VM_MIN_KERNEL_ADDRESS0xC0000000UL || argp > (long *)etext)
217 args = db_numargs_default;
218 else if (!DB_CHECK_ACCESS((long)argp, sizeof(long), task)db_check_access((long)argp,sizeof(long),task))
219 args = db_numargs_default;
220 else {
221 inst = db_get_task_value((long)argp, sizeof(long), FALSE((boolean_t) 0), task);
222 if ((inst & 0xff) == 0x59) /* popl %ecx */
223 args = 1;
224 else if ((inst & 0xffff) == 0xc483) /* addl %n, %esp */
225 args = ((inst >> 16) & 0xff) / 4;
226 else
227 args = db_numargs_default;
228 }
229 return args;
230}
231
232struct interrupt_frame {
233 struct i386_frame *if_frame; /* point to next frame */
234 long if_retaddr; /* return address to _interrupt */
235 long if_unit; /* unit number */
236 spl_t if_spl; /* saved spl */
237 long if_iretaddr; /* _return_to_{iret,iret_i} */
238 long if_edx; /* old sp(iret) or saved edx(iret_i) */
239 long if_ecx; /* saved ecx(iret_i) */
240 long if_eax; /* saved eax(iret_i) */
241 long if_eip; /* saved eip(iret_i) */
242 long if_cs; /* saved cs(iret_i) */
243 long if_efl; /* saved efl(iret_i) */
244};
245
246/*
247 * Figure out the next frame up in the call stack.
248 * For trap(), we print the address of the faulting instruction and
249 * proceed with the calling frame. We return the ip that faulted.
250 * If the trap was caused by jumping through a bogus pointer, then
251 * the next line in the backtrace will list some random function as
252 * being called. It should get the argument list correct, though.
253 * It might be possible to dig out from the next frame up the name
254 * of the function that faulted, but that could get hairy.
255 */
256void
257db_nextframe(
258 struct i386_frame **lfp, /* in/out */
259 struct i386_frame **fp, /* in/out */
260 db_addr_t *ip, /* out */
261 long frame_type, /* in */
262 const thread_t thread) /* in */
263{
264 struct i386_saved_state *saved_regs;
265 struct interrupt_frame *ifp;
266 task_t task = (thread != THREAD_NULL((thread_t) 0))? thread->task: TASK_NULL((task_t) 0);
267
268 switch(frame_type) {
269 case TRAP1:
270 /*
271 * We know that trap() has 1 argument and we know that
272 * it is an (struct i386_saved_state *).
273 */
274 saved_regs = (struct i386_saved_state *)
275 db_get_task_value((long)&((*fp)->f_arg0),sizeof(long),FALSE((boolean_t) 0),task);
276 db_printf(">>>>> %s (%d) at ",
277 trap_name(saved_regs->trapno), saved_regs->trapno);
278 db_task_printsym(saved_regs->eip, DB_STGY_PROC2, task);
279 db_printf(" <<<<<\n");
280 *fp = (struct i386_frame *)saved_regs->ebp;
281 *ip = (db_addr_t)saved_regs->eip;
282 break;
283 case INTERRUPT2:
284 if (*lfp == 0) {
285 db_printf(">>>>> interrupt <<<<<\n");
286 goto miss_frame;
287 }
288 db_printf(">>>>> interrupt at ");
289 ifp = (struct interrupt_frame *)(*lfp);
290 *fp = ifp->if_frame;
291 if (ifp->if_iretaddr == db_return_to_iret_symbol_value)
292 *ip = ((struct i386_interrupt_state *) ifp->if_edx)->eip;
293 else
294 *ip = (db_addr_t) ifp->if_eip;
295 db_task_printsym(*ip, DB_STGY_PROC2, task);
296 db_printf(" <<<<<\n");
297 break;
298 case SYSCALL3:
299 if (thread != THREAD_NULL((thread_t) 0) && thread->pcb) {
300 *ip = (db_addr_t) thread->pcb->iss.eip;
301 *fp = (struct i386_frame *) thread->pcb->iss.ebp;
302 break;
303 }
304 /* falling down for unknown case */
305 default:
306 miss_frame:
307 *ip = (db_addr_t)
308 db_get_task_value((long)&(*fp)->f_retaddr, sizeof(long), FALSE((boolean_t) 0), task);
309 *lfp = *fp;
310 *fp = (struct i386_frame *)
311 db_get_task_value((long)&(*fp)->f_frame, sizeof(long), FALSE((boolean_t) 0), task);
312 break;
313 }
314}
315
316#define F_USER_TRACE1 1
317#define F_TRACE_THREAD2 2
318
319void
320db_stack_trace_cmd(
321 db_expr_t addr,
322 boolean_t have_addr,
323 db_expr_t count,
324 const char *modif)
325{
326 boolean_t trace_thread = FALSE((boolean_t) 0);
327 struct i386_frame *frame;
328 db_addr_t callpc;
329 int flags = 0;
330 thread_t th;
331
332 {
333 const char *cp = modif;
334 char c;
335
336 while ((c = *cp++) != 0) {
337 if (c == 't')
338 trace_thread = TRUE((boolean_t) 1);
339 if (c == 'u')
340 flags |= F_USER_TRACE1;
341 }
342 }
343
344 if (!have_addr && !trace_thread) {
345 frame = (struct i386_frame *)ddb_regs.ebp;
346 callpc = (db_addr_t)ddb_regs.eip;
347 th = current_thread()(active_threads[(0)]);
348 } else if (trace_thread) {
349 if (have_addr) {
350 th = (thread_t) addr;
351 if (!db_check_thread_address_valid(th))
352 return;
353 } else {
354 th = db_default_thread;
355 if (th == THREAD_NULL((thread_t) 0))
356 th = current_thread()(active_threads[(0)]);
357 if (th == THREAD_NULL((thread_t) 0)) {
358 db_printf("no active thread\n");
359 return;
360 }
361 }
362 if (th == current_thread()(active_threads[(0)])) {
363 frame = (struct i386_frame *)ddb_regs.ebp;
364 callpc = (db_addr_t)ddb_regs.eip;
365 } else {
366 if (th->pcb == 0) {
367 db_printf("thread has no pcb\n");
368 return;
369 }
370 if ((th->state & TH_SWAPPED0x0100) || th->kernel_stack == 0) {
371 struct i386_saved_state *iss = &th->pcb->iss;
372
373 db_printf("Continuation ");
374 db_task_printsym((db_addr_t)th->swap_func,
375 DB_STGY_PROC2,
376 th->task);
377 db_printf("\n");
378
379 frame = (struct i386_frame *) (iss->ebp);
380 callpc = (db_addr_t) (iss->eip);
381 } else {
382 struct i386_kernel_state *iks;
383 iks = STACK_IKS(th->kernel_stack)((struct i386_kernel_state *)((th->kernel_stack) + (1*4096
)) - 1)
;
384 frame = (struct i386_frame *) (iks->k_ebp);
385 callpc = (db_addr_t) (iks->k_eip);
386 }
387 }
388 } else {
389 frame = (struct i386_frame *)addr;
390 th = (db_default_thread)? db_default_thread: current_thread()(active_threads[(0)]);
391 callpc = (db_addr_t)db_get_task_value((long)&frame->f_retaddr, sizeof(long),
392 FALSE((boolean_t) 0),
393 (th == THREAD_NULL((thread_t) 0)) ? TASK_NULL((task_t) 0) : th->task);
394 }
395
396 db_i386_stack_trace( th, frame, callpc, count, flags );
397}
398
399
400void
401db_i386_stack_trace(
402 const thread_t th,
403 struct i386_frame *frame,
404 db_addr_t callpc,
405 db_expr_t count,
406 int flags)
407{
408 task_t task;
409 boolean_t kernel_only;
410 long *argp;
411 long user_frame = 0;
412 struct i386_frame *lastframe;
413 int frame_type;
414 char *filename;
415 int linenum;
416 extern unsigned long db_maxoff;
417
418 if (count == -1)
419 count = 65535;
420
421 kernel_only = (flags & F_USER_TRACE1) == 0;
422
423 task = (th == THREAD_NULL((thread_t) 0)) ? TASK_NULL((task_t) 0) : th->task;
424
425 if (!db_trace_symbols_found)
426 db_find_trace_symbols();
427
428 if (!INKERNEL(callpc)(((vm_offset_t)(callpc)) >= 0xC0000000UL) && !INKERNEL(frame)(((vm_offset_t)(frame)) >= 0xC0000000UL)) {
429 db_printf(">>>>> user space <<<<<\n");
430 user_frame++;
431 }
432
433 lastframe = 0;
434 while (count-- && frame != 0) {
435 int narg;
436 char * name;
437 db_expr_t offset;
438
439 if (INKERNEL(callpc)(((vm_offset_t)(callpc)) >= 0xC0000000UL) && user_frame == 0) {
440 db_addr_t call_func = 0;
441
442 db_sym_t sym_tmp;
443 db_symbol_values(0,
444 sym_tmp = db_search_task_symbol(callpc,
445 DB_STGY_XTRN1,
446 (db_addr_t *)&offset,
447 TASK_NULL((task_t) 0)),
448 &name, (db_expr_t *)&call_func);
449 db_free_symbol(sym_tmp);
450 if ((db_user_trap_symbol_value && call_func == db_user_trap_symbol_value) ||
451 (db_kernel_trap_symbol_value && call_func == db_kernel_trap_symbol_value)) {
452 frame_type = TRAP1;
453 narg = 1;
454 } else if (db_interrupt_symbol_value && call_func == db_interrupt_symbol_value) {
455 frame_type = INTERRUPT2;
456 goto next_frame;
457 } else if (db_syscall_symbol_value && call_func == db_syscall_symbol_value) {
458 frame_type = SYSCALL3;
459 goto next_frame;
460 } else {
461 frame_type = 0;
462 narg = db_numargs(frame, task);
463 }
464 } else if (INKERNEL(callpc)(((vm_offset_t)(callpc)) >= 0xC0000000UL) ^ INKERNEL(frame)(((vm_offset_t)(frame)) >= 0xC0000000UL)) {
465 frame_type = 0;
466 narg = -1;
467 } else {
468 frame_type = 0;
469 narg = db_numargs(frame, task);
470 }
471
472 db_find_task_sym_and_offset(callpc, &name,do { db_sym_t s; db_symbol_values(0, s = db_search_task_symbol
(callpc,0 ,(db_addr_t *)&offset,task), &name, 0); db_free_symbol
(s); } while(0);
473 (db_addr_t *)&offset, task)do { db_sym_t s; db_symbol_values(0, s = db_search_task_symbol
(callpc,0 ,(db_addr_t *)&offset,task), &name, 0); db_free_symbol
(s); } while(0);
;
474 if (name == 0 || offset > db_maxoff) {
475 db_printf("0x%x(", callpc);
476 offset = 0;
477 } else
478 db_printf("%s(", name);
479
480 argp = &frame->f_arg0;
481 while (narg > 0) {
482 db_printf("%x", db_get_task_value((long)argp,sizeof(long),FALSE((boolean_t) 0),task));
483 argp++;
484 if (--narg != 0)
485 db_printf(",");
486 }
487 if (narg < 0)
488 db_printf("...");
489 db_printf(")");
490 if (offset) {
491 db_printf("+%x", offset);
492 }
493 if (db_line_at_pc(0, &filename, &linenum, callpc)) {
494 db_printf(" [%s", filename);
495 if (linenum > 0)
496 db_printf(":%d", linenum);
497 db_printf("]");
498 }
499 db_printf("\n");
500
501 next_frame:
502 db_nextframe(&lastframe, &frame, &callpc, frame_type, th);
503
504 if (frame == 0) {
505 /* end of chain */
506 break;
507 }
508 if (!INKERNEL(lastframe)(((vm_offset_t)(lastframe)) >= 0xC0000000UL) ||
509 (!INKERNEL(callpc)(((vm_offset_t)(callpc)) >= 0xC0000000UL) && !INKERNEL(frame)(((vm_offset_t)(frame)) >= 0xC0000000UL)))
510 user_frame++;
511 if (user_frame == 1) {
512 db_printf(">>>>> user space <<<<<\n");
513 if (kernel_only)
514 break;
515 }
516 if (frame <= lastframe) {
517 if (INKERNEL(lastframe)(((vm_offset_t)(lastframe)) >= 0xC0000000UL) && !INKERNEL(frame)(((vm_offset_t)(frame)) >= 0xC0000000UL))
518 continue;
519 db_printf("Bad frame pointer: 0x%x\n", frame);
520 break;
521 }
522 }
523}
524
525#define CTHREADS_SUPPORT1 1
526
527#if CTHREADS_SUPPORT1
528
529thread_t
530db_find_kthread(
531 vm_offset_t ustack_base,
532 vm_size_t ustack_top,
533 task_t task)
534{
535 thread_t thread;
536 if (task == TASK_NULL((task_t) 0))
537 task = db_current_task()(((active_threads[(0)]))? (active_threads[(0)])->task: ((task_t
) 0))
;
538
539 queue_iterate(&task->thread_list, thread, thread_t, thread_list)for ((thread) = (thread_t) ((&task->thread_list)->next
); !(((&task->thread_list)) == ((queue_entry_t)(thread
))); (thread) = (thread_t) ((&(thread)->thread_list)->
next))
{
540 vm_offset_t usp = thread->pcb->iss.uesp/*ebp works*/;
541 if (usp >= ustack_base && usp < ustack_top)
542 return thread;
543 }
544 return THREAD_NULL((thread_t) 0);
545}
546
547static void db_cproc_state(
548 int state,
549 char s[4])
550{
551 if (state == 0) {
552 *s++ = 'R';
553 } else {
554 if (state & 1) *s++ = 'S';
555 if (state & 2) *s++ = 'B';
556 if (state & 4) *s++ = 'C';
557 }
558 *s = 0;
559}
560
561/* offsets in a cproc structure */
562/* TODO: longs? */
563const int db_cproc_next_offset = 0 * 4;
564const int db_cproc_incarnation_offset = 1 * 4;
565const int db_cproc_list_offset = 2 * 4;
566const int db_cproc_wait_offset = 3 * 4;
567const int db_cproc_context_offset = 5 * 4;
568const int db_cproc_state_offset = 7 * 4;
569const int db_cproc_stack_base_offset = 10 * 4 + sizeof(mach_msg_header_t);
570const int db_cproc_stack_size_offset = 11 * 4 + sizeof(mach_msg_header_t);
571
572/* offsets in a cproc_switch context structure */
573const int db_cprocsw_framep_offset = 3 * 4;
574const int db_cprocsw_pc_offset = 4 * 4;
575
576#include <machine/setjmp.h>
577
578extern jmp_buf_t *db_recover;
579
580void db_trace_cproc(
581 vm_offset_t cproc,
582 thread_t thread)
583{
584 jmp_buf_t db_jmpbuf;
585 jmp_buf_t *prev = db_recover;
586 task_t task;
587 db_addr_t pc, fp;
588
589 task = (thread == THREAD_NULL((thread_t) 0))? TASK_NULL((task_t) 0): thread->task;
590
591 if (!_setjmp(db_recover = &db_jmpbuf)) {
592 char pstate[4];
593 unsigned int s, w, n, c, cth;
594
595 s = db_get_task_value(cproc + db_cproc_state_offset, 4, FALSE((boolean_t) 0), task);
596 w = db_get_task_value(cproc + db_cproc_wait_offset, 4, FALSE((boolean_t) 0), task);
597 n = db_get_task_value(cproc + db_cproc_next_offset, 4, FALSE((boolean_t) 0), task);
598 c = db_get_task_value(cproc + db_cproc_context_offset, 4, FALSE((boolean_t) 0), task);
599 cth = db_get_task_value(cproc + db_cproc_incarnation_offset, 4, FALSE((boolean_t) 0), task);
600
601 db_cproc_state(s, pstate);
602
603 db_printf("CThread %x (cproc %x) %s", cth, cproc, pstate);
604 if (w) db_printf(" awaits %x", w);
605 if (n) db_printf(" next %x", n);
606 db_printf("\n");
607
608 if ((s != 0) && (c != 0)) {
609 pc = db_get_task_value(c + db_cprocsw_pc_offset, 4, FALSE((boolean_t) 0), task);
610 fp = c + db_cprocsw_framep_offset;
611 } else {
612 db_addr_t sb;
613 vm_size_t ss;
614
615 sb = db_get_task_value(cproc + db_cproc_stack_base_offset, sizeof(db_expr_t), FALSE((boolean_t) 0), task);
616 ss = db_get_task_value(cproc + db_cproc_stack_size_offset, sizeof(db_expr_t), FALSE((boolean_t) 0), task);
617 db_printf(" Stack base: %x\n", sb);
618 /*
619 * Lessee now..
620 */
621 thread = db_find_kthread(sb, sb+ss, task);
622 if (thread != THREAD_NULL((thread_t) 0)) {
623 pc = thread->pcb->iss.eip;
624 fp = thread->pcb->iss.ebp;
625 } else
626 fp = -1;
627 }
628
629 if (fp != -1)
630 db_i386_stack_trace(thread, (struct i386_frame*)fp, pc,
631 -1, F_USER_TRACE1);
632 }
633
634 db_recover = prev;
635}
636
637void db_all_cprocs(
638 const task_t task,
639 db_expr_t cproc_list)
640{
641 jmp_buf_t db_jmpbuf;
642 jmp_buf_t *prev = db_recover;
643 thread_t thread;
644 db_expr_t cproc, next;
645
646
647 if (task != TASK_NULL((task_t) 0)) {
648 thread = (thread_t) queue_first(&task->thread_list)((&task->thread_list)->next);
649 } else
650 thread = current_thread()(active_threads[(0)]);
651
652 if (cproc_list != 0)
653 next = cproc_list;
654 else
655 if (!db_value_of_name("unix::cproc_list", &next)) {
656 db_printf("No cprocs.\n");
657 return;
658 }
659
660
661 while (next) {
662 if (_setjmp(db_recover = &db_jmpbuf))
663 break;
664
665 cproc = db_get_task_value(next, 4, FALSE((boolean_t) 0), TASK_NULL((task_t) 0));
666 if (cproc == 0) break;
667 next = cproc + db_cproc_list_offset;
668
669 db_trace_cproc(cproc, thread);
670 }
671
672 db_recover = prev;
673}
674
675#endif /* CTHREADS_SUPPORT */
676
677#endif /* MACH_KDB */