Bug Summary

File:obj-scan-build/../i386/i386/db_interface.c
Location:line 342, column 1
Description:Address of stack memory associated with local variable 'type' is still referred to by the global variable 'i386_last_kdb_sp' upon returning to the caller. This will be a dangling reference

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 * Interface to new debugger.
28 */
29
30#include <string.h>
31#include <sys/reboot.h>
32#include <vm/pmap.h>
33
34#include <i3861/thread.h>
35#include <i3861/db_machdep.h>
36#include <i3861/seg.h>
37#include <i3861/trap.h>
38#include <i3861/setjmp.h>
39#include <i3861/pmap.h>
40#include <i3861/proc_reg.h>
41#include <i3861/locore.h>
42#include "gdt.h"
43#include "trap.h"
44
45#include "vm_param.h"
46#include <vm/vm_map.h>
47#include <vm/vm_fault.h>
48#include <kern/cpu_number.h>
49#include <kern/printf.h>
50#include <kern/thread.h>
51#include <kern/task.h>
52#include <ddb/db_access.h>
53#include <ddb/db_command.h>
54#include <ddb/db_output.h>
55#include <ddb/db_run.h>
56#include <ddb/db_task_thread.h>
57#include <ddb/db_trap.h>
58#include <ddb/db_watch.h>
59#include <machine/db_interface.h>
60#include <machine/machspl.h>
61
62#if MACH_KDB1
63/* Whether the kernel uses any debugging register. */
64static boolean_t kernel_dr;
65#endif
66/* Whether the current debug registers are zero. */
67static boolean_t zero_dr;
68
69void db_load_context(pcb_t pcb)
70{
71#if MACH_KDB1
72 int s = splhigh();
73
74 if (kernel_dr) {
75 splx(s);
76 return;
77 }
78#endif
79 /* Else set user debug registers, if any */
80 unsigned int *dr = pcb->ims.ids.dr;
81 boolean_t will_zero_dr = !dr[0] && !dr[1] && !dr[2] && !dr[3] && !dr[7];
82
83 if (!(zero_dr && will_zero_dr))
84 {
85 set_dr0(dr[0])({ register unsigned long _temp__ = (dr[0]); asm volatile("movl %0,%%dr0"
: : "r" (_temp__)); })
;
86 set_dr1(dr[1])({ register unsigned long _temp__ = (dr[1]); asm volatile("movl %0,%%dr1"
: : "r" (_temp__)); })
;
87 set_dr2(dr[2])({ register unsigned long _temp__ = (dr[2]); asm volatile("movl %0,%%dr2"
: : "r" (_temp__)); })
;
88 set_dr3(dr[3])({ register unsigned long _temp__ = (dr[3]); asm volatile("movl %0,%%dr3"
: : "r" (_temp__)); })
;
89 set_dr7(dr[7])({ register unsigned long _temp__ = (dr[7]); asm volatile("movl %0,%%dr7"
: : "r" (_temp__)); })
;
90 zero_dr = will_zero_dr;
91 }
92
93#if MACH_KDB1
94 splx(s);
95#endif
96}
97
98void db_get_debug_state(
99 pcb_t pcb,
100 struct i386_debug_state *state)
101{
102 *state = pcb->ims.ids;
103}
104
105kern_return_t db_set_debug_state(
106 pcb_t pcb,
107 const struct i386_debug_state *state)
108{
109 int i;
110
111 for (i = 0; i <= 3; i++)
112 if (state->dr[i] < VM_MIN_ADDRESS(0)
113 || state->dr[i] >= VM_MAX_ADDRESS(0xc0000000UL))
114 return KERN_INVALID_ARGUMENT4;
115
116 pcb->ims.ids = *state;
117
118 if (pcb == current_thread()(active_threads[(0)])->pcb)
119 db_load_context(pcb);
120
121 return KERN_SUCCESS0;
122}
123
124#if MACH_KDB1
125
126struct i386_saved_state *i386_last_saved_statep;
127struct i386_saved_state i386_nested_saved_state;
128unsigned i386_last_kdb_sp;
129
130extern thread_t db_default_thread;
131
132static struct i386_debug_state ids;
133
134void db_dr (
135 int num,
136 vm_offset_t linear_addr,
137 int type,
138 int len,
139 int persistence)
140{
141 int s = splhigh();
142 unsigned long dr7;
143
144 if (!kernel_dr) {
145 if (!linear_addr) {
146 splx(s);
147 return;
148 }
149 kernel_dr = TRUE((boolean_t) 1);
150 /* Clear user debugging registers */
151 set_dr7(0)({ register unsigned long _temp__ = (0); asm volatile("movl %0,%%dr7"
: : "r" (_temp__)); })
;
152 set_dr0(0)({ register unsigned long _temp__ = (0); asm volatile("movl %0,%%dr0"
: : "r" (_temp__)); })
;
153 set_dr1(0)({ register unsigned long _temp__ = (0); asm volatile("movl %0,%%dr1"
: : "r" (_temp__)); })
;
154 set_dr2(0)({ register unsigned long _temp__ = (0); asm volatile("movl %0,%%dr2"
: : "r" (_temp__)); })
;
155 set_dr3(0)({ register unsigned long _temp__ = (0); asm volatile("movl %0,%%dr3"
: : "r" (_temp__)); })
;
156 }
157
158 ids.dr[num] = linear_addr;
159 switch (num) {
160 case 0: set_dr0(linear_addr)({ register unsigned long _temp__ = (linear_addr); asm volatile
("movl %0,%%dr0" : : "r" (_temp__)); })
; break;
161 case 1: set_dr1(linear_addr)({ register unsigned long _temp__ = (linear_addr); asm volatile
("movl %0,%%dr1" : : "r" (_temp__)); })
; break;
162 case 2: set_dr2(linear_addr)({ register unsigned long _temp__ = (linear_addr); asm volatile
("movl %0,%%dr2" : : "r" (_temp__)); })
; break;
163 case 3: set_dr3(linear_addr)({ register unsigned long _temp__ = (linear_addr); asm volatile
("movl %0,%%dr3" : : "r" (_temp__)); })
; break;
164 }
165
166 /* Replace type/len/persistence for DRnum in dr7 */
167 dr7 = get_dr7 ()({ register unsigned long _temp__; asm volatile("movl %%dr7, %0"
: "=r" (_temp__)); _temp__; })
;
168 dr7 &= ~(0xfUL << (4*num+16)) & ~(0x3UL << (2*num));
169 dr7 |= (((len << 2) | type) << (4*num+16)) | (persistence << (2*num));
170 set_dr7 (dr7)({ register unsigned long _temp__ = (dr7); asm volatile("movl %0,%%dr7"
: : "r" (_temp__)); })
;
171
172 if (kernel_dr) {
173 if (!ids.dr[0] && !ids.dr[1] && !ids.dr[2] && !ids.dr[3]) {
174 /* Not used any more, switch back to user debugging registers */
175 set_dr7 (0)({ register unsigned long _temp__ = (0); asm volatile("movl %0,%%dr7"
: : "r" (_temp__)); })
;
176 kernel_dr = FALSE((boolean_t) 0);
177 zero_dr = TRUE((boolean_t) 1);
178 db_load_context(current_thread()(active_threads[(0)])->pcb);
179 }
180 }
181 splx(s);
182}
183
184boolean_t
185db_set_hw_watchpoint(
186 const db_watchpoint_t watch,
187 unsigned num)
188{
189 vm_size_t size = watch->hiaddr - watch->loaddr;
190 db_addr_t addr = watch->loaddr;
191 vm_offset_t kern_addr;
192
193 if (num >= 4)
194 return FALSE((boolean_t) 0);
195 if (size != 1 && size != 2 && size != 4)
196 return FALSE((boolean_t) 0);
197
198 if (addr & (size-1))
199 /* Unaligned */
200 return FALSE((boolean_t) 0);
201
202 if (watch->task) {
203 if (db_user_to_kernel_address(watch->task, addr, &kern_addr, 1) < 0)
204 return FALSE((boolean_t) 0);
205 addr = kern_addr;
206 }
207 addr = kvtolin(addr)((vm_offset_t)(addr) - 0xC0000000UL + ((0xc0000000UL)));
208
209 db_dr (num, addr, I386_DB_TYPE_W1, size-1, I386_DB_LOCAL1|I386_DB_GLOBAL2);
210
211 db_printf("Hardware watchpoint %d set for %x\n", num, addr);
212 return TRUE((boolean_t) 1);
213}
214
215boolean_t
216db_clear_hw_watchpoint(
217 unsigned num)
218{
219 if (num >= 4)
220 return FALSE((boolean_t) 0);
221
222 db_dr (num, 0, 0, 0, 0);
223 return TRUE((boolean_t) 1);
224}
225
226/*
227 * Print trap reason.
228 */
229void
230kdbprinttrap(
231 int type,
232 int code)
233{
234 printf("kernel: %s (%d), code=%x\n",
235 trap_name(type), type, code);
236}
237
238/*
239 * kdb_trap - field a TRACE or BPT trap
240 */
241
242extern jmp_buf_t *db_recover;
243spl_t saved_ipl[NCPUS1]; /* just to know what was IPL before trap */
244
245boolean_t
246kdb_trap(
247 int type,
248 int code,
249 struct i386_saved_state *regs)
250{
251 spl_t s;
252
253 s = splhigh();
254 saved_ipl[cpu_number()(0)] = s;
255
256 switch (type) {
1
Control jumps to 'case -1:' at line 273
257 case T_DEBUG1: /* single_step */
258 {
259 int addr;
260 int status = get_dr6()({ register unsigned long _temp__; asm volatile("movl %%dr6, %0"
: "=r" (_temp__)); _temp__; })
;
261
262 if (status & 0xf) { /* hmm hdw break */
263 addr = status & 0x8 ? get_dr3()({ register unsigned long _temp__; asm volatile("movl %%dr3, %0"
: "=r" (_temp__)); _temp__; })
:
264 status & 0x4 ? get_dr2()({ register unsigned long _temp__; asm volatile("movl %%dr2, %0"
: "=r" (_temp__)); _temp__; })
:
265 status & 0x2 ? get_dr1()({ register unsigned long _temp__; asm volatile("movl %%dr1, %0"
: "=r" (_temp__)); _temp__; })
:
266 get_dr0()({ register unsigned long _temp__; asm volatile("movl %%dr0, %0"
: "=r" (_temp__)); _temp__; })
;
267 regs->efl |= EFL_RF0x00010000;
268 db_single_step_cmd(addr, 0, 1, "p");
269 }
270 }
271 case T_INT33: /* breakpoint */
272 case T_WATCHPOINT17: /* watchpoint */
273 case -1: /* keyboard interrupt */
274 break;
2
Execution continues on line 291
275
276 default:
277 if (db_recover) {
278 i386_nested_saved_state = *regs;
279 db_printf("Caught %s (%d), code = %x, pc = %x\n",
280 trap_name(type), type, code, regs->eip);
281 db_error("");
282 /*NOTREACHED*/
283 }
284 kdbprinttrap(type, code);
285 }
286
287#if NCPUS1 > 1
288 if (db_enter())
289#endif /* NCPUS > 1 */
290 {
291 i386_last_saved_statep = regs;
292 i386_last_kdb_sp = (unsigned) &type;
293
294 /* XXX Should switch to ddb`s own stack here. */
295
296 ddb_regs = *regs;
297 if ((regs->cs & 0x3) == KERNEL_RING0) {
3
Taking false branch
298 /*
299 * Kernel mode - esp and ss not saved
300 */
301 ddb_regs.uesp = (int)&regs->uesp; /* kernel stack pointer */
302 ddb_regs.ss = KERNEL_DS(0x10 | 0);
303 }
304
305 cnpollc(TRUE((boolean_t) 1));
306 db_task_trap(type, code, (regs->cs & 0x3) != 0);
307 cnpollc(FALSE((boolean_t) 0));
308
309 regs->eip = ddb_regs.eip;
310 regs->efl = ddb_regs.efl;
311 regs->eax = ddb_regs.eax;
312 regs->ecx = ddb_regs.ecx;
313 regs->edx = ddb_regs.edx;
314 regs->ebx = ddb_regs.ebx;
315 if ((regs->cs & 0x3) != KERNEL_RING0) {
4
Taking true branch
316 /*
317 * user mode - saved esp and ss valid
318 */
319 regs->uesp = ddb_regs.uesp; /* user stack pointer */
320 regs->ss = ddb_regs.ss & 0xffff; /* user stack segment */
321 }
322 regs->ebp = ddb_regs.ebp;
323 regs->esi = ddb_regs.esi;
324 regs->edi = ddb_regs.edi;
325 regs->es = ddb_regs.es & 0xffff;
326 regs->cs = ddb_regs.cs & 0xffff;
327 regs->ds = ddb_regs.ds & 0xffff;
328 regs->fs = ddb_regs.fs & 0xffff;
329 regs->gs = ddb_regs.gs & 0xffff;
330
331 if ((type == T_INT33) &&
332 (db_get_task_value(regs->eip, BKPT_SIZE(1), FALSE((boolean_t) 0), TASK_NULL((task_t) 0))
333 == BKPT_INST0xcc))
334 regs->eip += BKPT_SIZE(1);
335 }
336#if NCPUS1 > 1
337 db_leave();
338#endif /* NCPUS > 1 */
339
340 splx(s);
341 return 1;
342}
5
Address of stack memory associated with local variable 'type' is still referred to by the global variable 'i386_last_kdb_sp' upon returning to the caller. This will be a dangling reference
343
344/*
345 * Enter KDB through a keyboard trap.
346 * We show the registers as of the keyboard interrupt
347 * instead of those at its call to KDB.
348 */
349struct int_regs {
350 long edi;
351 long esi;
352 long ebp;
353 long ebx;
354 struct i386_interrupt_state *is;
355};
356
357void
358kdb_kentry(
359 struct int_regs *int_regs)
360{
361 struct i386_interrupt_state *is = int_regs->is;
362 spl_t s = splhigh();
363
364#if NCPUS1 > 1
365 if (db_enter())
366#endif /* NCPUS > 1 */
367 {
368 if ((is->cs & 0x3) != KERNEL_RING0) {
369 ddb_regs.uesp = ((int *)(is+1))[0];
370 ddb_regs.ss = ((int *)(is+1))[1];
371 }
372 else {
373 ddb_regs.ss = KERNEL_DS(0x10 | 0);
374 ddb_regs.uesp= (int)(is+1);
375 }
376 ddb_regs.efl = is->efl;
377 ddb_regs.cs = is->cs;
378 ddb_regs.eip = is->eip;
379 ddb_regs.eax = is->eax;
380 ddb_regs.ecx = is->ecx;
381 ddb_regs.edx = is->edx;
382 ddb_regs.ebx = int_regs->ebx;
383 ddb_regs.ebp = int_regs->ebp;
384 ddb_regs.esi = int_regs->esi;
385 ddb_regs.edi = int_regs->edi;
386 ddb_regs.ds = is->ds;
387 ddb_regs.es = is->es;
388 ddb_regs.fs = is->fs;
389 ddb_regs.gs = is->gs;
390
391 cnpollc(TRUE((boolean_t) 1));
392 db_task_trap(-1, 0, (ddb_regs.cs & 0x3) != 0);
393 cnpollc(FALSE((boolean_t) 0));
394
395 if ((ddb_regs.cs & 0x3) != KERNEL_RING0) {
396 ((int *)(is+1))[0] = ddb_regs.uesp;
397 ((int *)(is+1))[1] = ddb_regs.ss & 0xffff;
398 }
399 is->efl = ddb_regs.efl;
400 is->cs = ddb_regs.cs & 0xffff;
401 is->eip = ddb_regs.eip;
402 is->eax = ddb_regs.eax;
403 is->ecx = ddb_regs.ecx;
404 is->edx = ddb_regs.edx;
405 int_regs->ebx = ddb_regs.ebx;
406 int_regs->ebp = ddb_regs.ebp;
407 int_regs->esi = ddb_regs.esi;
408 int_regs->edi = ddb_regs.edi;
409 is->ds = ddb_regs.ds & 0xffff;
410 is->es = ddb_regs.es & 0xffff;
411 is->fs = ddb_regs.fs & 0xffff;
412 is->gs = ddb_regs.gs & 0xffff;
413 }
414#if NCPUS1 > 1
415 db_leave();
416#endif /* NCPUS > 1 */
417
418 (void) splx(s);
419}
420
421boolean_t db_no_vm_fault = TRUE((boolean_t) 1);
422
423int
424db_user_to_kernel_address(
425 const task_t task,
426 vm_offset_t addr,
427 vm_offset_t *kaddr,
428 int flag)
429{
430 pt_entry_t *ptp;
431 boolean_t faulted = FALSE((boolean_t) 0);
432
433 retry:
434 ptp = pmap_pte(task->map->pmap, addr);
435 if (ptp == PT_ENTRY_NULL((pt_entry_t *) 0) || (*ptp & INTEL_PTE_VALID0x00000001) == 0) {
436 if (!faulted && !db_no_vm_fault) {
437 kern_return_t err;
438
439 faulted = TRUE((boolean_t) 1);
440 err = vm_fault( task->map,
441 trunc_page(addr)((vm_offset_t)(((vm_offset_t)(addr)) & ~((1 << 12)-
1)))
,
442 VM_PROT_READ((vm_prot_t) 0x01),
443 FALSE((boolean_t) 0), FALSE((boolean_t) 0), 0);
444 if (err == KERN_SUCCESS0)
445 goto retry;
446 }
447 if (flag) {
448 db_printf("\nno memory is assigned to address %08x\n", addr);
449 db_error(0);
450 /* NOTREACHED */
451 }
452 return(-1);
453 }
454 *kaddr = ptetokv(*ptp)(((vm_offset_t)(((*ptp) & 0xfffff000)) + 0xC0000000UL)) + (addr & (INTEL_PGBYTES4096-1));
455 return(0);
456}
457
458/*
459 * Read bytes from kernel address space for debugger.
460 */
461
462void
463db_read_bytes(
464 vm_offset_t addr,
465 int size,
466 char *data,
467 task_t task)
468{
469 char *src;
470 int n;
471 vm_offset_t kern_addr;
472
473 src = (char *)addr;
474 if ((addr >= VM_MIN_KERNEL_ADDRESS0xC0000000UL && addr < VM_MAX_KERNEL_ADDRESS((0xffffffffUL) - ((0xc0000000UL)) + 0xC0000000UL)) || task == TASK_NULL((task_t) 0)) {
475 if (task == TASK_NULL((task_t) 0))
476 task = db_current_task()(((active_threads[(0)]))? (active_threads[(0)])->task: ((task_t
) 0))
;
477 while (--size >= 0) {
478 if (addr < VM_MIN_KERNEL_ADDRESS0xC0000000UL && task == TASK_NULL((task_t) 0)) {
479 db_printf("\nbad address %x\n", addr);
480 db_error(0);
481 /* NOTREACHED */
482 }
483 addr++;
484 *data++ = *src++;
485 }
486 return;
487 }
488 while (size > 0) {
489 if (db_user_to_kernel_address(task, addr, &kern_addr, 1) < 0)
490 return;
491 src = (char *)kern_addr;
492 n = intel_trunc_page(addr+INTEL_PGBYTES)(((unsigned long)(addr+4096)) & ~(4096 -1)) - addr;
493 if (n > size)
494 n = size;
495 size -= n;
496 addr += n;
497 while (--n >= 0)
498 *data++ = *src++;
499 }
500}
501
502/*
503 * Write bytes to kernel address space for debugger.
504 */
505void
506db_write_bytes(
507 vm_offset_t addr,
508 int size,
509 char *data,
510 task_t task)
511{
512 char *dst;
513
514 pt_entry_t *ptep0 = 0;
515 pt_entry_t oldmap0 = 0;
516 vm_offset_t addr1;
517 pt_entry_t *ptep1 = 0;
518 pt_entry_t oldmap1 = 0;
519 extern char etext;
520
521 if ((addr < VM_MIN_KERNEL_ADDRESS0xC0000000UL) ^
522 ((addr + size) <= VM_MIN_KERNEL_ADDRESS0xC0000000UL)) {
523 db_error("\ncannot write data into mixed space\n");
524 /* NOTREACHED */
525 }
526 if (addr < VM_MIN_KERNEL_ADDRESS0xC0000000UL) {
527 if (task) {
528 db_write_bytes_user_space(addr, size, data, task);
529 return;
530 } else if (db_current_task()(((active_threads[(0)]))? (active_threads[(0)])->task: ((task_t
) 0))
== TASK_NULL((task_t) 0)) {
531 db_printf("\nbad address %x\n", addr);
532 db_error(0);
533 /* NOTREACHED */
534 }
535 }
536
537 if (addr >= VM_MIN_KERNEL_ADDRESS0xC0000000UL &&
538 addr <= (vm_offset_t)&etext)
539 {
540 ptep0 = pmap_pte(kernel_pmap, addr);
541 oldmap0 = *ptep0;
542 *ptep0 |= INTEL_PTE_WRITE0x00000002;
543
544 addr1 = i386_trunc_page(addr + size - 1)(((unsigned long)(addr + size - 1)) & ~(4096 -1));
545 if (i386_trunc_page(addr)(((unsigned long)(addr)) & ~(4096 -1)) != addr1) {
546 /* data crosses a page boundary */
547
548 ptep1 = pmap_pte(kernel_pmap, addr1);
549 oldmap1 = *ptep1;
550 *ptep1 |= INTEL_PTE_WRITE0x00000002;
551 }
552 if (CPU_HAS_FEATURE(CPU_FEATURE_PGE)(cpu_features[(13) / 32] & (1 << ((13) % 32))))
553 set_cr4(get_cr4() & ~CR4_PGE)({ register unsigned long _temp__ = (({ register unsigned long
_temp__; asm volatile("mov %%cr4, %0" : "=r" (_temp__)); _temp__
; }) & ~0x0080); asm volatile("mov %0, %%cr4" : : "r" (_temp__
)); })
;
554 flush_tlb()({ register unsigned long _temp__ = (({ register unsigned long
_temp__; asm volatile("mov %%cr3, %0" : "=r" (_temp__)); _temp__
; })); asm volatile("mov %0, %%cr3" : : "r" (_temp__) : "memory"
); })
;
555 }
556
557 dst = (char *)addr;
558
559 while (--size >= 0)
560 *dst++ = *data++;
561
562 if (ptep0) {
563 *ptep0 = oldmap0;
564 if (ptep1) {
565 *ptep1 = oldmap1;
566 }
567 flush_tlb()({ register unsigned long _temp__ = (({ register unsigned long
_temp__; asm volatile("mov %%cr3, %0" : "=r" (_temp__)); _temp__
; })); asm volatile("mov %0, %%cr3" : : "r" (_temp__) : "memory"
); })
;
568 if (CPU_HAS_FEATURE(CPU_FEATURE_PGE)(cpu_features[(13) / 32] & (1 << ((13) % 32))))
569 set_cr4(get_cr4() | CR4_PGE)({ register unsigned long _temp__ = (({ register unsigned long
_temp__; asm volatile("mov %%cr4, %0" : "=r" (_temp__)); _temp__
; }) | 0x0080); asm volatile("mov %0, %%cr4" : : "r" (_temp__
)); })
;
570 }
571}
572
573void
574db_write_bytes_user_space(
575 vm_offset_t addr,
576 int size,
577 char *data,
578 task_t task)
579{
580 char *dst;
581 int n;
582 vm_offset_t kern_addr;
583
584 while (size > 0) {
585 if (db_user_to_kernel_address(task, addr, &kern_addr, 1) < 0)
586 return;
587 dst = (char *)kern_addr;
588 n = intel_trunc_page(addr+INTEL_PGBYTES)(((unsigned long)(addr+4096)) & ~(4096 -1)) - addr;
589 if (n > size)
590 n = size;
591 size -= n;
592 addr += n;
593 while (--n >= 0)
594 *dst++ = *data++;
595 }
596}
597
598boolean_t
599db_check_access(
600 vm_offset_t addr,
601 int size,
602 task_t task)
603{
604 int n;
605 vm_offset_t kern_addr;
606
607 if (addr >= VM_MIN_KERNEL_ADDRESS0xC0000000UL) {
608 if (kernel_task == TASK_NULL((task_t) 0))
609 return TRUE((boolean_t) 1);
610 task = kernel_task;
611 } else if (task == TASK_NULL((task_t) 0)) {
612 if (current_thread()(active_threads[(0)]) == THREAD_NULL((thread_t) 0))
613 return FALSE((boolean_t) 0);
614 task = current_thread()(active_threads[(0)])->task;
615 }
616 while (size > 0) {
617 if (db_user_to_kernel_address(task, addr, &kern_addr, 0) < 0)
618 return FALSE((boolean_t) 0);
619 n = intel_trunc_page(addr+INTEL_PGBYTES)(((unsigned long)(addr+4096)) & ~(4096 -1)) - addr;
620 if (n > size)
621 n = size;
622 size -= n;
623 addr += n;
624 }
625 return TRUE((boolean_t) 1);
626}
627
628boolean_t
629db_phys_eq(
630 task_t task1,
631 vm_offset_t addr1,
632 const task_t task2,
633 vm_offset_t addr2)
634{
635 vm_offset_t kern_addr1, kern_addr2;
636
637 if (addr1 >= VM_MIN_KERNEL_ADDRESS0xC0000000UL || addr2 >= VM_MIN_KERNEL_ADDRESS0xC0000000UL)
638 return FALSE((boolean_t) 0);
639 if ((addr1 & (INTEL_PGBYTES4096-1)) != (addr2 & (INTEL_PGBYTES4096-1)))
640 return FALSE((boolean_t) 0);
641 if (task1 == TASK_NULL((task_t) 0)) {
642 if (current_thread()(active_threads[(0)]) == THREAD_NULL((thread_t) 0))
643 return FALSE((boolean_t) 0);
644 task1 = current_thread()(active_threads[(0)])->task;
645 }
646 if (db_user_to_kernel_address(task1, addr1, &kern_addr1, 0) < 0
647 || db_user_to_kernel_address(task2, addr2, &kern_addr2, 0) < 0)
648 return FALSE((boolean_t) 0);
649 return(kern_addr1 == kern_addr2);
650}
651
652#define DB_USER_STACK_ADDR(0xC0000000UL) (VM_MIN_KERNEL_ADDRESS0xC0000000UL)
653#define DB_NAME_SEARCH_LIMIT((0xC0000000UL)-(4096*3)) (DB_USER_STACK_ADDR(0xC0000000UL)-(INTEL_PGBYTES4096*3))
654
655#define GNU
656
657#ifndef GNU
658static boolean_t
659db_search_null(
660 const task_t task,
661 vm_offset_t *svaddr,
662 vm_offset_t evaddr,
663 vm_offset_t *skaddr,
664 int flag)
665{
666 unsigned vaddr;
667 unsigned *kaddr;
668
669 kaddr = (unsigned *)*skaddr;
670 for (vaddr = *svaddr; vaddr > evaddr; ) {
671 if (vaddr % INTEL_PGBYTES4096 == 0) {
672 vaddr -= sizeof(unsigned);
673 if (db_user_to_kernel_address(task, vaddr, skaddr, 0) < 0)
674 return FALSE((boolean_t) 0);
675 kaddr = (vm_offset_t *)*skaddr;
676 } else {
677 vaddr -= sizeof(unsigned);
678 kaddr--;
679 }
680 if ((*kaddr == 0) ^ (flag == 0)) {
681 *svaddr = vaddr;
682 *skaddr = (unsigned)kaddr;
683 return TRUE((boolean_t) 1);
684 }
685 }
686 return FALSE((boolean_t) 0);
687}
688#endif /* GNU */
689
690#ifdef GNU
691static boolean_t
692looks_like_command(
693 const task_t task,
694 char* kaddr)
695{
696 char *c;
697
698 assert(!((vm_offset_t) kaddr & (INTEL_PGBYTES-1)))((!((vm_offset_t) kaddr & (4096 -1))) ? (void) (0) : Assert
("!((vm_offset_t) kaddr & (INTEL_PGBYTES-1))", "../i386/i386/db_interface.c"
, 698))
;
699
700 /*
701 * Must be the environment.
702 */
703 if (!memcmp(kaddr, "PATH=", 5) || !memcmp(kaddr, "TERM=", 5) || !memcmp(kaddr, "SHELL=", 6) || !memcmp(kaddr, "LOCAL_PART=", 11) || !memcmp(kaddr, "LC_ALL=", 7))
704 return FALSE((boolean_t) 0);
705
706 /*
707 * This is purely heuristical but works quite nicely.
708 * We know that it should look like words separated by \0, and
709 * eventually only \0s.
710 */
711 c = kaddr;
712 while (c < kaddr + INTEL_PGBYTES4096) {
713 if (!*c) {
714 if (c == kaddr)
715 /* Starts by \0. */
716 return FALSE((boolean_t) 0);
717 break;
718 }
719 while (c < kaddr + INTEL_PGBYTES4096 && *c)
720 c++;
721 if (c < kaddr + INTEL_PGBYTES4096)
722 c++; /* Skip \0 */
723 }
724 /*
725 * Check that the remainder is just \0s.
726 */
727 while (c < kaddr + INTEL_PGBYTES4096)
728 if (*c++)
729 return FALSE((boolean_t) 0);
730
731 return TRUE((boolean_t) 1);
732}
733#endif /* GNU */
734
735void
736db_task_name(
737 const task_t task)
738{
739 char *p;
740 int n;
741 vm_offset_t vaddr, kaddr;
742 unsigned sp;
743
744 if (task->name[0]) {
745 db_printf("%s", task->name);
746 return;
747 }
748
749#ifdef GNU
750 /*
751 * GNU Hurd-specific heuristics.
752 */
753
754 /* Heuristical address first. */
755 vaddr = 0x1026000;
756 if (db_user_to_kernel_address(task, vaddr, &kaddr, 0) >= 0 &&
757 looks_like_command(task, (char*) kaddr))
758 goto ok;
759
760 /* Try to catch SP of the main thread. */
761 thread_t thread;
762
763 task_lock(task);
764 thread = (thread_t) queue_first(&task->thread_list)((&task->thread_list)->next);
765 if (!thread) {
766 task_unlock(task)((void)(&(task)->lock));
767 db_printf(DB_NULL_TASK_NAME"? ");
768 return;
769 }
770 sp = thread->pcb->iss.uesp;
771 task_unlock(task)((void)(&(task)->lock));
772
773 vaddr = (sp & ~(INTEL_PGBYTES4096 - 1)) + INTEL_PGBYTES4096;
774 while (1) {
775 if (db_user_to_kernel_address(task, vaddr, &kaddr, 0) < 0)
776 return;
777 if (looks_like_command(task, (char*) kaddr))
778 break;
779 vaddr += INTEL_PGBYTES4096;
780 }
781#else /* GNU */
782 vaddr = DB_USER_STACK_ADDR(0xC0000000UL);
783 kaddr = 0;
784
785 /*
786 * skip nulls at the end
787 */
788 if (!db_search_null(task, &vaddr, DB_NAME_SEARCH_LIMIT((0xC0000000UL)-(4096*3)), &kaddr, 0)) {
789 db_printf(DB_NULL_TASK_NAME"? ");
790 return;
791 }
792 /*
793 * search start of args
794 */
795 if (!db_search_null(task, &vaddr, DB_NAME_SEARCH_LIMIT((0xC0000000UL)-(4096*3)), &kaddr, 1)) {
796 db_printf(DB_NULL_TASK_NAME"? ");
797 return;
798 }
799#endif /* GNU */
800
801ok:
802 n = DB_TASK_NAME_LEN23-1;
803#ifdef GNU
804 p = (char *)kaddr;
805 for (; n > 0; vaddr++, p++, n--) {
806#else /* GNU */
807 p = (char *)kaddr + sizeof(unsigned);
808 for (vaddr += sizeof(int); vaddr < DB_USER_STACK_ADDR(0xC0000000UL) && n > 0;
809 vaddr++, p++, n--) {
810#endif /* GNU */
811 if (vaddr % INTEL_PGBYTES4096 == 0) {
812 (void)db_user_to_kernel_address(task, vaddr, &kaddr, 0);
813 p = (char*)kaddr;
814 }
815 db_printf("%c", (*p < ' ' || *p > '~')? ' ': *p);
816 }
817 while (n-- >= 0) /* compare with >= 0 for one more space */
818 db_printf(" ");
819}
820
821#endif /* MACH_KDB */