home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: comp.unix.bsd
- Path: sparky!uunet!mcsun!sun4nl!eur.nl!pk
- From: pk@cs.few.eur.nl (Paul Kranenburg)
- Subject: Re: GDB under 386bsd 0.1
- Message-ID: <1992Sep4.153554.4387@cs.few.eur.nl>
- Keywords: gdb, ptrace
- Sender: news@cs.few.eur.nl
- Reply-To: pk@cs.eur.nl
- Organization: Erasmus University Rotterdam
- References: <1992Sep4.005417.3876@gumby.dsd.trw.com>
- Date: Fri, 4 Sep 1992 15:35:54 GMT
- Lines: 89
-
- In <1992Sep4.005417.3876@gumby.dsd.trw.com> gottloeb@eel.dsd.trw.com writes:
-
- >I have noticed a problem using gdb under 386bsd 0.1.
-
- >When at least one breakpoint has been set and the program terminates,
- >e.g. executes exit(), the breakpoint is not removed from the process's
- >text image. When the program is subsequently re-executed under gdb,
- >gdb remembers that a breakpoint is supposed to at the memory location
- >and puts one there again. However this time it shadows the breakpoint
- >instruction from the previous run rather than the original instruction.
- >When execution begins after reaching the breakpoint, various traps occur.
-
- >If the program is run after quitting gdb, a Trace/BPT trap occurs.
-
- >I think the problem is that gdb assumes that when ptrace modifies the
- >process's image the kernel either makes a private copy of the text image
- >or it will throw away the text image after the process terminates.
- >However, this is not the case - the kernel keeps the modified text image
- >around and executes it rather than a fresh copy from the original file.
-
- The 386 does not generate a page protection fault while it is executing
- in supervisor mode :-(, so copy on write handling never takes place when
- the kernel stuffs data into a process's text- or any other non-anonymous
- segment. So these cases must be explicitly checked for. Here's a patch
- for kern/sys_process.c:
-
-
- ------- sys_process.c -------
- *** /tmp/da05975 Fri Sep 4 16:51:50 1992
- --- sys_process.c Fri Sep 4 16:51:18 1992
- ***************
- *** 278,286 ****
- break;
-
- case PT_WRITE_I:
- ! case PT_WRITE_D:
- ! ipc.error = copyout((char *)&ipc.data, (char *)ipc.addr, sizeof(ipc.data));
- break;
-
- case PT_WRITE_U:
- if ((u_int)ipc.addr > UPAGES * NBPG - sizeof(int)) {
- --- 278,318 ----
- break;
-
- case PT_WRITE_I:
- ! case PT_WRITE_D: {
- ! vm_prot_t prot; /* current protection of region */
- ! int cow; /* ensure copy-on-write happens */
- !
- ! if (cow = (useracc(ipc.addr, sizeof(ipc.data), B_WRITE) == 0)) {
- ! vm_offset_t addr = (vm_offset_t)ipc.addr;
- ! vm_size_t size;
- ! vm_prot_t max_prot;
- ! vm_inherit_t inh;
- ! boolean_t shared;
- ! vm_object_t object;
- ! vm_offset_t objoff;
- !
- ! if (vm_region(&p->p_vmspace->vm_map, &addr, &size,
- ! &prot, &max_prot, &inh, &shared,
- ! &object, &objoff) != KERN_SUCCESS ||
- ! vm_protect(&p->p_vmspace->vm_map, ipc.addr,
- ! sizeof(ipc.data), FALSE,
- ! prot|VM_PROT_WRITE) != KERN_SUCCESS ||
- ! vm_fault(&p->p_vmspace->vm_map,trunc_page(ipc.addr),
- ! VM_PROT_WRITE, FALSE) != KERN_SUCCESS) {
- !
- ! ipc.error = EFAULT;
- ! break;
- ! }
- ! }
- ! ipc.error = copyout((char *)&ipc.data,
- ! (char *)ipc.addr, sizeof(ipc.data));
- ! if (cow)
- ! if (vm_protect(&p->p_vmspace->vm_map, ipc.addr,
- ! sizeof(ipc.data), FALSE,
- ! prot) != KERN_SUCCESS)
- ! printf("ptrace: oops\n");
- break;
- + }
-
- case PT_WRITE_U:
- if ((u_int)ipc.addr > UPAGES * NBPG - sizeof(int)) {
- ------------ EOP --------------------
-
- I am not entirely happy about the call to `vm_fault', but at this moment
- I don't see another way to enforce a copy on write.
-
- -pk
-