/***************************************************************************** * FILE: ptrace.c * * * * DESC: * * - ptrace handler * * * * Copyright (C) 1993,1994 * * Rainer Schnitker, Heeper Str. 283, 33607 Bielefeld * * email: rainer@mathematik.uni-bielefeld.de * * * *****************************************************************************/ #include "DPMI.H" #include "DPMI10.H" #include "PROCESS.H" #include "CDOSX32.H" #include "START32.H" #include "ADOSX32.H" #include "COPY32.H" #include "PTRACE.H" #include "DOSERRNO.H" #include "KDEB.H" #define FLAG_MASK 0x00000dd9L #define SINGLE_STEP 0x100 int do_ptrace(int request, int child_id, DWORD addr, DWORD data, DWORD * ret) { NEWPROCESS *child; #ifdef CONFIG_KDEB if (child_id == 1) return KDEB_ptrace(request, addr, data, ret); #endif if (!(child = find_process(child_id))) return EMX_ESRCH; if (child->pptr != npz || !(child->p_flags & PF_DEBUG)) return EMX_ESRCH; if (child->p_status != PS_STOP && child->p_status != PS_START) return EMX_ESRCH; *ret = 0; switch (request) { case PTRACE_TRACEME: case PTRACE_SESSION: return 0; case PTRACE_PEEKTEXT: case PTRACE_PEEKDATA: if (verify_illegal(child, addr, 4)) return EMX_EIO; *ret = read32(child->data32sel, addr); return 0; case PTRACE_POKETEXT: case PTRACE_POKEDATA: if (verify_illegal(child, addr, 4)) return EMX_EIO; if (dpmi10) { WORD page, pageorg; read32(child->data32sel, addr); /* page in */ if (GetPageAttributes(child->memhandle, addr & ~0xFFFL, 1, &pageorg)) return EMX_EIO; pageorg &= ~16; /* don't modify access/dirty */ page = pageorg | 8; /* read/write access */ if (ModifyPageAttributes(child->memhandle, addr & ~0xFFFL, 1, &page)) return EMX_EIO; store32(child->data32sel, addr, data); ModifyPageAttributes(child->memhandle, addr & ~0xFFFL, 1, &pageorg); } else store32(child->data32sel, addr, data); *ret = data; return 0; case PTRACE_EXIT: /* to do : switch to child -> do_signal(); */ child->p_flags |= PF_WAIT_WAIT; return 0; case PTRACE_PEEKUSER: if (addr == 0x30) { /* u_ar0 */ *ret = 0xE0000000 + ((DWORD) (UINT) & (child->regs)); return 0; } else { /* peek regs */ DWORD *peekat; peekat = (DWORD *) (UINT) (addr); if (peekat < &(child->regs.gs) || peekat > &(child->regs.ss)) return EMX_EIO; *ret = *peekat; return 0; } case PTRACE_POKEUSER: { /* poke regs */ DWORD *pokeat; pokeat = (DWORD *) (UINT) addr; if (pokeat < &(child->regs.gs) || pokeat > &(child->regs.ss)) return EMX_EIO; /* change data for critical regs */ if (pokeat == &(child->regs.eflags)) { data &= FLAG_MASK; data |= *pokeat & ~FLAG_MASK; } else if (pokeat <= &(child->regs.ds) || pokeat == &(child->regs.cs)) data = *pokeat; else if (pokeat == &(child->regs.esp)) { if (verify_illegal(child, data, 4)) return EMX_EIO; child->regs.esp = data; child->regs.esporg = data + 12L; } else if (pokeat == &(child->regs.esporg)) { if (verify_illegal(child, data, 4)) return EMX_EIO; child->regs.esporg = data; child->regs.esp = data - 12L; } else if (pokeat == &(child->regs.eip)) if (verify_illegal(child, data, 4)) return EMX_EIO; *pokeat = data; *ret = data; return 0; } case PTRACE_STEP: if ((int)data > 0 && (int)data <= MAX_SIGNALS) send_signal(child, (WORD) data); child->regs.eflags |= SINGLE_STEP; if (child->regs.esp == child->regs.esporg) child->regs.esp -= 12; npz->p_status = PS_STOP; switch_context(child); npz->p_status = PS_RUN; return 0; case PTRACE_RESUME: if ((int)data > 0 && (int)data <= MAX_SIGNALS) send_signal(child, (int) data); if (child->regs.esp == child->regs.esporg) child->regs.esp -= 12; npz->p_status = PS_STOP; switch_context(child); npz->p_status = PS_RUN; return 0; default: return EMX_EIO; } }