ia64/xen-unstable

changeset 5923:dd1c092a7ee2

PDB: add some additional files
author ach61@arcadians.cl.cam.ac.uk
date Thu Jul 28 21:32:13 2005 +0000 (2005-07-28)
parents 577d1c7b47a9
children 0474ffc52ba7
files linux-2.6-xen-sparse/kernel/ptrace.c tools/debugger/pdb/linux-2.6-module/pdb_debug.h
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/linux-2.6-xen-sparse/kernel/ptrace.c	Thu Jul 28 21:32:13 2005 +0000
     1.3 @@ -0,0 +1,391 @@
     1.4 +/*
     1.5 + * linux/kernel/ptrace.c
     1.6 + *
     1.7 + * (C) Copyright 1999 Linus Torvalds
     1.8 + *
     1.9 + * Common interfaces for "ptrace()" which we do not want
    1.10 + * to continually duplicate across every architecture.
    1.11 + */
    1.12 +
    1.13 +#include <linux/module.h>
    1.14 +#include <linux/sched.h>
    1.15 +#include <linux/errno.h>
    1.16 +#include <linux/mm.h>
    1.17 +#include <linux/highmem.h>
    1.18 +#include <linux/pagemap.h>
    1.19 +#include <linux/smp_lock.h>
    1.20 +#include <linux/ptrace.h>
    1.21 +#include <linux/security.h>
    1.22 +#include <linux/signal.h>
    1.23 +
    1.24 +#include <asm/pgtable.h>
    1.25 +#include <asm/uaccess.h>
    1.26 +
    1.27 +/*
    1.28 + * ptrace a task: make the debugger its new parent and
    1.29 + * move it to the ptrace list.
    1.30 + *
    1.31 + * Must be called with the tasklist lock write-held.
    1.32 + */
    1.33 +void __ptrace_link(task_t *child, task_t *new_parent)
    1.34 +{
    1.35 +	if (!list_empty(&child->ptrace_list))
    1.36 +		BUG();
    1.37 +	if (child->parent == new_parent)
    1.38 +		return;
    1.39 +	list_add(&child->ptrace_list, &child->parent->ptrace_children);
    1.40 +	REMOVE_LINKS(child);
    1.41 +	child->parent = new_parent;
    1.42 +	SET_LINKS(child);
    1.43 +}
    1.44 + 
    1.45 +/*
    1.46 + * Turn a tracing stop into a normal stop now, since with no tracer there
    1.47 + * would be no way to wake it up with SIGCONT or SIGKILL.  If there was a
    1.48 + * signal sent that would resume the child, but didn't because it was in
    1.49 + * TASK_TRACED, resume it now.
    1.50 + * Requires that irqs be disabled.
    1.51 + */
    1.52 +void ptrace_untrace(task_t *child)
    1.53 +{
    1.54 +	spin_lock(&child->sighand->siglock);
    1.55 +	if (child->state == TASK_TRACED) {
    1.56 +		if (child->signal->flags & SIGNAL_STOP_STOPPED) {
    1.57 +			child->state = TASK_STOPPED;
    1.58 +		} else {
    1.59 +			signal_wake_up(child, 1);
    1.60 +		}
    1.61 +	}
    1.62 +	spin_unlock(&child->sighand->siglock);
    1.63 +}
    1.64 +
    1.65 +/*
    1.66 + * unptrace a task: move it back to its original parent and
    1.67 + * remove it from the ptrace list.
    1.68 + *
    1.69 + * Must be called with the tasklist lock write-held.
    1.70 + */
    1.71 +void __ptrace_unlink(task_t *child)
    1.72 +{
    1.73 +	if (!child->ptrace)
    1.74 +		BUG();
    1.75 +	child->ptrace = 0;
    1.76 +	if (!list_empty(&child->ptrace_list)) {
    1.77 +		list_del_init(&child->ptrace_list);
    1.78 +		REMOVE_LINKS(child);
    1.79 +		child->parent = child->real_parent;
    1.80 +		SET_LINKS(child);
    1.81 +	}
    1.82 +
    1.83 +	if (child->state == TASK_TRACED)
    1.84 +		ptrace_untrace(child);
    1.85 +}
    1.86 +
    1.87 +/*
    1.88 + * Check that we have indeed attached to the thing..
    1.89 + */
    1.90 +int ptrace_check_attach(struct task_struct *child, int kill)
    1.91 +{
    1.92 +	int ret = -ESRCH;
    1.93 +
    1.94 +	/*
    1.95 +	 * We take the read lock around doing both checks to close a
    1.96 +	 * possible race where someone else was tracing our child and
    1.97 +	 * detached between these two checks.  After this locked check,
    1.98 +	 * we are sure that this is our traced child and that can only
    1.99 +	 * be changed by us so it's not changing right after this.
   1.100 +	 */
   1.101 +	read_lock(&tasklist_lock);
   1.102 +	if ((child->ptrace & PT_PTRACED) && child->parent == current &&
   1.103 +	    (!(child->ptrace & PT_ATTACHED) || child->real_parent != current)
   1.104 +	    && child->signal != NULL) {
   1.105 +		ret = 0;
   1.106 +		spin_lock_irq(&child->sighand->siglock);
   1.107 +		if (child->state == TASK_STOPPED) {
   1.108 +			child->state = TASK_TRACED;
   1.109 +		} else if (child->state != TASK_TRACED && !kill) {
   1.110 +			ret = -ESRCH;
   1.111 +		}
   1.112 +		spin_unlock_irq(&child->sighand->siglock);
   1.113 +	}
   1.114 +	read_unlock(&tasklist_lock);
   1.115 +
   1.116 +	if (!ret && !kill) {
   1.117 +		wait_task_inactive(child);
   1.118 +	}
   1.119 +
   1.120 +	/* All systems go.. */
   1.121 +	return ret;
   1.122 +}
   1.123 +
   1.124 +int ptrace_attach(struct task_struct *task)
   1.125 +{
   1.126 +	int retval;
   1.127 +	task_lock(task);
   1.128 +	retval = -EPERM;
   1.129 +	if (task->pid <= 1)
   1.130 +		goto bad;
   1.131 +	if (task == current)
   1.132 +		goto bad;
   1.133 +	if (!task->mm)
   1.134 +		goto bad;
   1.135 +	if(((current->uid != task->euid) ||
   1.136 +	    (current->uid != task->suid) ||
   1.137 +	    (current->uid != task->uid) ||
   1.138 + 	    (current->gid != task->egid) ||
   1.139 + 	    (current->gid != task->sgid) ||
   1.140 + 	    (current->gid != task->gid)) && !capable(CAP_SYS_PTRACE))
   1.141 +		goto bad;
   1.142 +	smp_rmb();
   1.143 +	if (!task->mm->dumpable && !capable(CAP_SYS_PTRACE))
   1.144 +		goto bad;
   1.145 +	/* the same process cannot be attached many times */
   1.146 +	if (task->ptrace & PT_PTRACED)
   1.147 +		goto bad;
   1.148 +	retval = security_ptrace(current, task);
   1.149 +	if (retval)
   1.150 +		goto bad;
   1.151 +
   1.152 +	/* Go */
   1.153 +	task->ptrace |= PT_PTRACED | ((task->real_parent != current)
   1.154 +				      ? PT_ATTACHED : 0);
   1.155 +	if (capable(CAP_SYS_PTRACE))
   1.156 +		task->ptrace |= PT_PTRACE_CAP;
   1.157 +	task_unlock(task);
   1.158 +
   1.159 +	write_lock_irq(&tasklist_lock);
   1.160 +	__ptrace_link(task, current);
   1.161 +	write_unlock_irq(&tasklist_lock);
   1.162 +
   1.163 +	force_sig_specific(SIGSTOP, task);
   1.164 +	return 0;
   1.165 +
   1.166 +bad:
   1.167 +	task_unlock(task);
   1.168 +	return retval;
   1.169 +}
   1.170 +
   1.171 +int ptrace_detach(struct task_struct *child, unsigned int data)
   1.172 +{
   1.173 +	if (!valid_signal(data))
   1.174 +		return	-EIO;
   1.175 +
   1.176 +	/* Architecture-specific hardware disable .. */
   1.177 +	ptrace_disable(child);
   1.178 +
   1.179 +	/* .. re-parent .. */
   1.180 +	child->exit_code = data;
   1.181 +
   1.182 +	write_lock_irq(&tasklist_lock);
   1.183 +	__ptrace_unlink(child);
   1.184 +	/* .. and wake it up. */
   1.185 +	if (child->exit_state != EXIT_ZOMBIE)
   1.186 +		wake_up_process(child);
   1.187 +	write_unlock_irq(&tasklist_lock);
   1.188 +
   1.189 +	return 0;
   1.190 +}
   1.191 +
   1.192 +/*
   1.193 + * Access another process' address space.
   1.194 + * Source/target buffer must be kernel space, 
   1.195 + * Do not walk the page table directly, use get_user_pages
   1.196 + */
   1.197 +
   1.198 +int access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write)
   1.199 +{
   1.200 +	struct mm_struct *mm;
   1.201 +	struct vm_area_struct *vma;
   1.202 +	struct page *page;
   1.203 +	void *old_buf = buf;
   1.204 +
   1.205 +	mm = get_task_mm(tsk);
   1.206 +	if (!mm)
   1.207 +		return 0;
   1.208 +
   1.209 +	down_read(&mm->mmap_sem);
   1.210 +	/* ignore errors, just check how much was sucessfully transfered */
   1.211 +	while (len) {
   1.212 +		int bytes, ret, offset;
   1.213 +		void *maddr;
   1.214 +
   1.215 +		ret = get_user_pages(tsk, mm, addr, 1,
   1.216 +				write, 1, &page, &vma);
   1.217 +		if (ret <= 0)
   1.218 +			break;
   1.219 +
   1.220 +		bytes = len;
   1.221 +		offset = addr & (PAGE_SIZE-1);
   1.222 +		if (bytes > PAGE_SIZE-offset)
   1.223 +			bytes = PAGE_SIZE-offset;
   1.224 +
   1.225 +		maddr = kmap(page);
   1.226 +		if (write) {
   1.227 +			copy_to_user_page(vma, page, addr,
   1.228 +					  maddr + offset, buf, bytes);
   1.229 +			set_page_dirty_lock(page);
   1.230 +		} else {
   1.231 +			copy_from_user_page(vma, page, addr,
   1.232 +					    buf, maddr + offset, bytes);
   1.233 +		}
   1.234 +		kunmap(page);
   1.235 +		page_cache_release(page);
   1.236 +		len -= bytes;
   1.237 +		buf += bytes;
   1.238 +		addr += bytes;
   1.239 +	}
   1.240 +	up_read(&mm->mmap_sem);
   1.241 +	mmput(mm);
   1.242 +	
   1.243 +	return buf - old_buf;
   1.244 +}
   1.245 +EXPORT_SYMBOL(access_process_vm);
   1.246 +
   1.247 +int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len)
   1.248 +{
   1.249 +	int copied = 0;
   1.250 +
   1.251 +	while (len > 0) {
   1.252 +		char buf[128];
   1.253 +		int this_len, retval;
   1.254 +
   1.255 +		this_len = (len > sizeof(buf)) ? sizeof(buf) : len;
   1.256 +		retval = access_process_vm(tsk, src, buf, this_len, 0);
   1.257 +		if (!retval) {
   1.258 +			if (copied)
   1.259 +				break;
   1.260 +			return -EIO;
   1.261 +		}
   1.262 +		if (copy_to_user(dst, buf, retval))
   1.263 +			return -EFAULT;
   1.264 +		copied += retval;
   1.265 +		src += retval;
   1.266 +		dst += retval;
   1.267 +		len -= retval;			
   1.268 +	}
   1.269 +	return copied;
   1.270 +}
   1.271 +
   1.272 +int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len)
   1.273 +{
   1.274 +	int copied = 0;
   1.275 +
   1.276 +	while (len > 0) {
   1.277 +		char buf[128];
   1.278 +		int this_len, retval;
   1.279 +
   1.280 +		this_len = (len > sizeof(buf)) ? sizeof(buf) : len;
   1.281 +		if (copy_from_user(buf, src, this_len))
   1.282 +			return -EFAULT;
   1.283 +		retval = access_process_vm(tsk, dst, buf, this_len, 1);
   1.284 +		if (!retval) {
   1.285 +			if (copied)
   1.286 +				break;
   1.287 +			return -EIO;
   1.288 +		}
   1.289 +		copied += retval;
   1.290 +		src += retval;
   1.291 +		dst += retval;
   1.292 +		len -= retval;			
   1.293 +	}
   1.294 +	return copied;
   1.295 +}
   1.296 +
   1.297 +static int ptrace_setoptions(struct task_struct *child, long data)
   1.298 +{
   1.299 +	child->ptrace &= ~PT_TRACE_MASK;
   1.300 +
   1.301 +	if (data & PTRACE_O_TRACESYSGOOD)
   1.302 +		child->ptrace |= PT_TRACESYSGOOD;
   1.303 +
   1.304 +	if (data & PTRACE_O_TRACEFORK)
   1.305 +		child->ptrace |= PT_TRACE_FORK;
   1.306 +
   1.307 +	if (data & PTRACE_O_TRACEVFORK)
   1.308 +		child->ptrace |= PT_TRACE_VFORK;
   1.309 +
   1.310 +	if (data & PTRACE_O_TRACECLONE)
   1.311 +		child->ptrace |= PT_TRACE_CLONE;
   1.312 +
   1.313 +	if (data & PTRACE_O_TRACEEXEC)
   1.314 +		child->ptrace |= PT_TRACE_EXEC;
   1.315 +
   1.316 +	if (data & PTRACE_O_TRACEVFORKDONE)
   1.317 +		child->ptrace |= PT_TRACE_VFORK_DONE;
   1.318 +
   1.319 +	if (data & PTRACE_O_TRACEEXIT)
   1.320 +		child->ptrace |= PT_TRACE_EXIT;
   1.321 +
   1.322 +	return (data & ~PTRACE_O_MASK) ? -EINVAL : 0;
   1.323 +}
   1.324 +
   1.325 +static int ptrace_getsiginfo(struct task_struct *child, siginfo_t __user * data)
   1.326 +{
   1.327 +	siginfo_t lastinfo;
   1.328 +	int error = -ESRCH;
   1.329 +
   1.330 +	read_lock(&tasklist_lock);
   1.331 +	if (likely(child->sighand != NULL)) {
   1.332 +		error = -EINVAL;
   1.333 +		spin_lock_irq(&child->sighand->siglock);
   1.334 +		if (likely(child->last_siginfo != NULL)) {
   1.335 +			lastinfo = *child->last_siginfo;
   1.336 +			error = 0;
   1.337 +		}
   1.338 +		spin_unlock_irq(&child->sighand->siglock);
   1.339 +	}
   1.340 +	read_unlock(&tasklist_lock);
   1.341 +	if (!error)
   1.342 +		return copy_siginfo_to_user(data, &lastinfo);
   1.343 +	return error;
   1.344 +}
   1.345 +
   1.346 +static int ptrace_setsiginfo(struct task_struct *child, siginfo_t __user * data)
   1.347 +{
   1.348 +	siginfo_t newinfo;
   1.349 +	int error = -ESRCH;
   1.350 +
   1.351 +	if (copy_from_user(&newinfo, data, sizeof (siginfo_t)))
   1.352 +		return -EFAULT;
   1.353 +
   1.354 +	read_lock(&tasklist_lock);
   1.355 +	if (likely(child->sighand != NULL)) {
   1.356 +		error = -EINVAL;
   1.357 +		spin_lock_irq(&child->sighand->siglock);
   1.358 +		if (likely(child->last_siginfo != NULL)) {
   1.359 +			*child->last_siginfo = newinfo;
   1.360 +			error = 0;
   1.361 +		}
   1.362 +		spin_unlock_irq(&child->sighand->siglock);
   1.363 +	}
   1.364 +	read_unlock(&tasklist_lock);
   1.365 +	return error;
   1.366 +}
   1.367 +
   1.368 +int ptrace_request(struct task_struct *child, long request,
   1.369 +		   long addr, long data)
   1.370 +{
   1.371 +	int ret = -EIO;
   1.372 +
   1.373 +	switch (request) {
   1.374 +#ifdef PTRACE_OLDSETOPTIONS
   1.375 +	case PTRACE_OLDSETOPTIONS:
   1.376 +#endif
   1.377 +	case PTRACE_SETOPTIONS:
   1.378 +		ret = ptrace_setoptions(child, data);
   1.379 +		break;
   1.380 +	case PTRACE_GETEVENTMSG:
   1.381 +		ret = put_user(child->ptrace_message, (unsigned long __user *) data);
   1.382 +		break;
   1.383 +	case PTRACE_GETSIGINFO:
   1.384 +		ret = ptrace_getsiginfo(child, (siginfo_t __user *) data);
   1.385 +		break;
   1.386 +	case PTRACE_SETSIGINFO:
   1.387 +		ret = ptrace_setsiginfo(child, (siginfo_t __user *) data);
   1.388 +		break;
   1.389 +	default:
   1.390 +		break;
   1.391 +	}
   1.392 +
   1.393 +	return ret;
   1.394 +}
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/tools/debugger/pdb/linux-2.6-module/pdb_debug.h	Thu Jul 28 21:32:13 2005 +0000
     2.3 @@ -0,0 +1,46 @@
     2.4 +
     2.5 +#ifndef __PDB_DEBUG_H_
     2.6 +#define __PDB_DEBUG_H_
     2.7 +
     2.8 +/* debugger.c */
     2.9 +void pdb_initialize_bwcpoint (void);
    2.10 +int pdb_suspend (struct task_struct *target);
    2.11 +int pdb_resume (struct task_struct *target);
    2.12 +int pdb_read_registers (struct task_struct *target, pdb_op_rd_regs_p op);
    2.13 +int pdb_write_register (struct task_struct *target, pdb_op_wr_reg_p op);
    2.14 +int pdb_read_memory (struct task_struct *target, pdb_op_rd_mem_req_p req, 
    2.15 +                     pdb_op_rd_mem_resp_p resp);
    2.16 +int pdb_write_memory (struct task_struct *target, pdb_op_wr_mem_p op);
    2.17 +int pdb_access_memory (struct task_struct *target, unsigned long address, 
    2.18 +                       void *buffer, int length, int write);
    2.19 +int pdb_continue (struct task_struct *target);
    2.20 +int pdb_step (struct task_struct *target);
    2.21 +
    2.22 +int pdb_insert_memory_breakpoint (struct task_struct *target, 
    2.23 +                                  memory_t address, u32 length);
    2.24 +int pdb_remove_memory_breakpoint (struct task_struct *target,
    2.25 +                                  memory_t address, u32 length);
    2.26 +
    2.27 +int pdb_exceptions_notify (struct notifier_block *self, unsigned long val,
    2.28 +                           void *data);
    2.29 +
    2.30 +int pdb_debug_fn (struct pt_regs *regs, long error_code,
    2.31 +                  unsigned int condition);
    2.32 +int pdb_int3_fn (struct pt_regs *regs, long error_code);
    2.33 +
    2.34 +/* module.c */
    2.35 +void pdb_send_response (pdb_response_t *response);
    2.36 +
    2.37 +#endif
    2.38 +
    2.39 +
    2.40 +/*
    2.41 + * Local variables:
    2.42 + * mode: C
    2.43 + * c-set-style: "BSD"
    2.44 + * c-basic-offset: 4
    2.45 + * tab-width: 4
    2.46 + * indent-tabs-mode: nil
    2.47 + * End:
    2.48 + */
    2.49 +