direct-io.hg
changeset 5907: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 +