URL
https://opencores.org/ocsvn/openrisc/openrisc/trunk
Subversion Repositories openrisc
Compare Revisions
- This comparison shows the changes necessary to convert path
/openrisc/trunk/rtos/rtems/c/src/librdbg/src
- from Rev 30 to Rev 173
- ↔ Reverse comparison
Rev 30 → Rev 173
/powerpc/rdbg_f.c
0,0 → 1,156
/* |
************************************************************************** |
* |
* Component = |
* |
* Synopsis = rdbg/powerpc/rdbg_f.c |
* |
* $Id: rdbg_f.c,v 1.2 2001-09-27 12:02:02 chris Exp $ |
* |
************************************************************************** |
*/ |
|
#include <assert.h> |
#include <errno.h> |
#include <rdbg/reg.h> |
#include <rdbg/remdeb.h> |
#include <rdbg/rdbg.h> |
#include <rtems/score/cpu.h> |
#include <rtems/score/thread.h> |
#include <libcpu/cpu.h> |
|
void |
CtxToRegs (const CPU_Exception_frame* ctx, xdr_regs* regs) |
{ |
* ((CPU_Exception_frame*) regs) = *ctx; |
} |
|
|
void |
RegsToCtx (const xdr_regs* regs, CPU_Exception_frame* ctx) |
{ |
*ctx = * ((CPU_Exception_frame*) regs); |
} |
|
void |
get_ctx_thread( Thread_Control *thread, CPU_Exception_frame* ctx) |
{ |
unsigned int *ptr; |
unsigned int i; |
|
ctx->EXC_SRR0 = thread->Registers.pc; |
ctx->EXC_SRR1 = thread->Registers.msr; |
ctx->_EXC_number = 0xdeadbeef; |
|
ctx->GPR1 = thread->Registers.gpr1; |
ctx->GPR2 = thread->Registers.gpr2; |
/* |
* Fill with dummy values... |
*/ |
ptr = &ctx->GPR3; |
for (i = 0; i < 10; i++) |
ptr [i] = 0xdeadbeef; |
|
ctx->GPR13 = thread->Registers.gpr13; |
ctx->GPR14 = thread->Registers.gpr14; |
ctx->GPR15 = thread->Registers.gpr15; |
ctx->GPR16 = thread->Registers.gpr16; |
ctx->GPR17 = thread->Registers.gpr17; |
ctx->GPR18 = thread->Registers.gpr18; |
ctx->GPR19 = thread->Registers.gpr19; |
ctx->GPR20 = thread->Registers.gpr20; |
ctx->GPR21 = thread->Registers.gpr21; |
ctx->GPR22 = thread->Registers.gpr22; |
ctx->GPR23 = thread->Registers.gpr23; |
ctx->GPR24 = thread->Registers.gpr24; |
ctx->GPR25 = thread->Registers.gpr25; |
ctx->GPR26 = thread->Registers.gpr26; |
ctx->GPR27 = thread->Registers.gpr27; |
ctx->GPR28 = thread->Registers.gpr28; |
ctx->GPR29 = thread->Registers.gpr29; |
ctx->GPR30 = thread->Registers.gpr30; |
ctx->GPR31 = thread->Registers.gpr31; |
ctx->EXC_CR = thread->Registers.cr; |
ctx->EXC_CTR = 0xdeadbeef; |
ctx->EXC_XER = 0xdeadbeef; |
ctx->EXC_LR = 0xdeadbeef; |
ctx->EXC_MSR = 0xdeadbeef; |
ctx->EXC_DAR = 0xdeadbeef; |
} |
|
void |
set_ctx_thread( Thread_Control *thread, CPU_Exception_frame* ctx) |
{ |
thread->Registers.gpr1 = ctx->GPR1; |
thread->Registers.gpr2 = ctx->GPR2; |
|
thread->Registers.gpr13 = ctx->GPR13; |
thread->Registers.gpr14 = ctx->GPR14; |
thread->Registers.gpr15 = ctx->GPR15; |
thread->Registers.gpr16 = ctx->GPR16; |
thread->Registers.gpr17 = ctx->GPR17; |
thread->Registers.gpr18 = ctx->GPR18; |
thread->Registers.gpr19 = ctx->GPR19; |
thread->Registers.gpr20 = ctx->GPR20; |
thread->Registers.gpr21 = ctx->GPR21; |
thread->Registers.gpr22 = ctx->GPR22; |
thread->Registers.gpr23 = ctx->GPR23; |
thread->Registers.gpr24 = ctx->GPR24; |
thread->Registers.gpr25 = ctx->GPR25; |
thread->Registers.gpr26 = ctx->GPR26; |
thread->Registers.gpr27 = ctx->GPR27; |
thread->Registers.gpr28 = ctx->GPR28; |
thread->Registers.gpr29 = ctx->GPR29; |
thread->Registers.gpr30 = ctx->GPR30; |
thread->Registers.gpr31 = ctx->GPR31; |
thread->Registers.cr = ctx->EXC_CR; |
thread->Registers.pc = ctx->EXC_SRR0; |
thread->Registers.msr = ctx->EXC_SRR1; |
} |
|
|
|
int |
Single_Step(CPU_Exception_frame* ctx) |
{ |
if ((ctx->EXC_SRR1 & MSR_SE) != 0 || ExitForSingleStep != 0) { |
/* Check coherency */ |
assert ((ctx->EXC_SRR1 & MSR_SE) != 0); |
assert (ExitForSingleStep != 0); |
return 0; |
} |
ctx->EXC_SRR1 |= MSR_SE; |
++ExitForSingleStep; |
return 0; |
} |
|
int |
CheckForSingleStep (CPU_Exception_frame* ctx) |
{ |
if (ExitForSingleStep) { |
/* |
* This functions can be called both from |
* INT1 and INT3 handlers. In case it is |
* called from INT3, need to clear TF. |
*/ |
ctx->EXC_SRR1 &= ~MSR_SE; |
ExitForSingleStep = 0; |
return 1; |
} |
return 0; |
} |
|
void |
CancelSingleStep (CPU_Exception_frame* ctx) |
{ |
/* Cancel scheduled SS */ |
ctx->EXC_SRR1 &= ~MSR_SE; |
ExitForSingleStep-- ; |
} |
cpuExcHandlerType oldExcHandler; |
|
void connect_rdbg_exception() |
{ |
oldExcHandler = globalExceptHdl; |
globalExceptHdl = BreakPointExcHdl ; |
} |
/powerpc/rdbg_cpu_asm.S
0,0 → 1,84
/* cpu_asm.s |
* |
* This file contains all assembly code for the Intel i386 implementation |
* of RDBG. |
* |
* $Id: rdbg_cpu_asm.S,v 1.2 2001-09-27 12:02:02 chris Exp $ |
* |
*/ |
|
#include <libcpu/cpu.h> |
#include <libcpu/io.h> |
#include <rtems/score/targopts.h> |
#include <asm.h> |
|
BEGIN_CODE |
|
/* |
* void copyback_data_cache_and_invalidate_instr_cache(addr, size) |
* |
* This routine performs a copy of the data cache |
* and invalidate the instruction cache |
*/ |
|
.p2align 5 |
PUBLIC_VAR (copyback_data_cache_and_invalidate_instr_cache) |
|
SYM (copyback_data_cache_and_invalidate_instr_cache): |
/* make sure the data changed is in the cache */ |
sync |
/* r3 address to handle, r4 length in bytes */ |
addi r6, r0, PPC_CACHE_ALIGNMENT |
/* r5 = last address to handle */ |
add r5,r3,r4 |
/* r3 = cache_align(r3, PPC_CACHE_ALIGNMENT) */ |
subi r0,r6,1 |
andc r3,r3,r0 |
/* R4 = R3 = copy of first address */ |
mr r4,r3 |
/* |
* Copyback data cache |
*/ |
1: cmplw r4,r5 /* r4 >= r5 then done */ |
dcbst 0,r4 /* flush (data cache bloc store) */ |
add r4,r4,r6 /* r4 = next cache line addr */ |
blt 1b /* end r4 >= r5 then done */ |
sync /* Wait for all dcbst to complete on bus */ |
/* |
* invalidate instruction cache |
*/ |
/* R4 = fisrt address */ |
mr r4,r3 |
2: cmplw r4,r5 /* r4 >= r5 then done */ |
icbi 0,r4 /* invalidate (instruction cache bloc invalidate) */ |
add r4,r4,r6 /* r4 = next cache line addr */ |
blt 2b /* end r4 >= r5 then done */ |
sync /* Wait for all icbi to complete on bus */ |
isync |
blr |
|
|
/* |
* void enterRdbg(void) |
* |
* This function perform a call to the exception SYSTEM call |
* It is used : |
* 1 - in the user code, to simulate a Breakpoint. |
* (with justSaveContext = 0) |
* 2 - in the RDBG code, to push a ctx in the list. |
* (with justSaveContext = 1) |
* |
* In most of case, it will be use as described in 1. |
* The 2nd possibility will be used by RDBG to obtain |
* its own ctx |
*/ |
|
PUBLIC_VAR (enterRdbg) |
|
SYM (enterRdbg): |
sc |
blr |
|
END_CODE |
|
END |
/powerpc/Makefile.am
0,0 → 1,12
## |
## $Id: Makefile.am,v 1.2 2001-09-27 12:02:02 chris Exp $ |
## |
|
AUTOMAKE_OPTIONS = foreign 1.4 |
|
SUBDIRS = mcp750 |
|
EXTRA_DIST = excep_f.c rdbg_cpu_asm.S rdbg_f.c |
|
include $(top_srcdir)/../../../automake/subdirs.am |
include $(top_srcdir)/../../../automake/local.am |
/powerpc/excep_f.c
0,0 → 1,167
/* |
************************************************************************** |
* |
* Component = |
* |
* Synopsis = rdbg/powerpc/excep_f.c |
* |
* $Id: excep_f.c,v 1.2 2001-09-27 12:02:02 chris Exp $ |
* |
************************************************************************** |
*/ |
|
#include <rtems.h> |
#include <rtems/error.h> |
#include <assert.h> |
#include <errno.h> |
#include <rdbg/rdbg.h> |
#include <rdbg/servrpc.h> |
|
int |
ExcepToSig (Exception_context *ctx) |
{ |
int excep = getExcNum (ctx); |
|
switch (excep) { |
case ASM_FLOAT_VECTOR : return SIGFPE; |
|
case ASM_TRACE_VECTOR : |
case ASM_PROG_VECTOR : |
case ASM_SYS_VECTOR : return SIGTRAP; |
|
case ASM_ISI_VECTOR : return SIGSEGV; |
|
case ASM_RESET_VECTOR : |
case ASM_MACH_VECTOR : |
case ASM_EXT_VECTOR : |
case ASM_ALIGN_VECTOR : return SIGILL; |
|
default: |
break; |
} |
return SIGKILL; |
} |
|
|
/*----- Breakpoint Exception management -----*/ |
|
/* |
* Handler for Breakpoint Exceptions : |
* software breakpoints. |
*/ |
|
void |
BreakPointExcHdl(CPU_Exception_frame *ctx) |
{ |
rtems_status_code status; |
rtems_id continueSemId; |
|
if ( (justSaveContext) && (ctx->_EXC_number == ASM_SYS_VECTOR) ) { |
PushSavedExceptCtx (_Thread_Executing->Object.id, ctx); |
justSaveContext = 0; |
} |
else { |
if (ctx->_EXC_number != ASM_TRACE_VECTOR){ |
NbSerializedCtx++; |
rtems_semaphore_obtain(serializeSemId, RTEMS_WAIT, RTEMS_NO_TIMEOUT); |
NbSerializedCtx--; |
} |
|
currentTargetThread = _Thread_Executing->Object.id; |
|
#ifdef DDEBUG |
printk("----------------------------------------------------------\n"); |
printk("Exception %d caught at PC %x by thread %d\n", |
ctx->_EXC_number, |
ctx->EXC_SRR0, |
_Thread_Executing->Object.id); |
printk("----------------------------------------------------------\n"); |
printk("Processor execution context at time of the fault was :\n"); |
printk("----------------------------------------------------------\n"); |
printk("\t R0 = %x\n", ctx->GPR0); |
printk("\t R1 = %x\n", ctx->GPR1); |
printk("\t R2 = %x\n", ctx->GPR2); |
printk("\t R3 = %x\n", ctx->GPR3); |
printk("\t R4 = %x\n", ctx->GPR4); |
printk("\t R5 = %x\n", ctx->GPR5); |
printk("\t R6 = %x\n", ctx->GPR6); |
printk("\t R7 = %x\n", ctx->GPR7); |
printk("\t R8 = %x\n", ctx->GPR8); |
printk("\t R9 = %x\n", ctx->GPR9); |
printk("\t R10 = %x\n", ctx->GPR10); |
printk("\t R11 = %x\n", ctx->GPR11); |
printk("\t R12 = %x\n", ctx->GPR12); |
printk("\t R13 = %x\n", ctx->GPR13); |
printk("\t R14 = %x\n", ctx->GPR14); |
printk("\t R15 = %x\n", ctx->GPR15); |
printk("\t R16 = %x\n", ctx->GPR16); |
printk("\t R17 = %x\n", ctx->GPR17); |
printk("\t R18 = %x\n", ctx->GPR18); |
printk("\t R19 = %x\n", ctx->GPR19); |
printk("\t R20 = %x\n", ctx->GPR20); |
printk("\t R21 = %x\n", ctx->GPR21); |
printk("\t R22 = %x\n", ctx->GPR22); |
printk("\t R23 = %x\n", ctx->GPR23); |
printk("\t R24 = %x\n", ctx->GPR24); |
printk("\t R25 = %x\n", ctx->GPR25); |
printk("\t R26 = %x\n", ctx->GPR26); |
printk("\t R27 = %x\n", ctx->GPR27); |
printk("\t R28 = %x\n", ctx->GPR28); |
printk("\t R29 = %x\n", ctx->GPR29); |
printk("\t R30 = %x\n", ctx->GPR30); |
printk("\t R31 = %x\n", ctx->GPR31); |
printk("\t CR = %x\n", ctx->EXC_CR); |
printk("\t CTR = %x\n", ctx->EXC_CTR); |
printk("\t XER = %x\n", ctx->EXC_XER); |
printk("\t LR = %x\n", ctx->EXC_LR); |
printk("\t MSR = %x\n", ctx->EXC_MSR); |
#endif |
|
status = rtems_semaphore_create (rtems_build_name('D', 'B', 'G', 'c'), |
0, |
RTEMS_FIFO | |
RTEMS_COUNTING_SEMAPHORE | |
RTEMS_NO_INHERIT_PRIORITY | |
RTEMS_NO_PRIORITY_CEILING | |
RTEMS_LOCAL, |
0, |
&continueSemId); |
if (status != RTEMS_SUCCESSFUL) |
rtems_panic ("Can't create continue semaphore: `%s'\n",rtems_status_text(status)); |
|
PushExceptCtx (_Thread_Executing->Object.id, continueSemId, ctx); |
|
switch (ctx->_EXC_number){ |
case ASM_TRACE_VECTOR : |
DPRINTF((" TRACE EXCEPTION !!!\n")); |
ctx->EXC_SRR1 &= ~MSR_SE; |
ExitForSingleStep-- ; |
rtems_semaphore_release( wakeupEventSemId ); |
break; |
|
case ASM_PROG_VECTOR : |
DPRINTF((" BREAKPOINT EXCEPTION !!!\n")); |
rtems_semaphore_release( wakeupEventSemId ); |
break; |
|
case ASM_SYS_VECTOR : |
DPRINTF((" ENTER RDBG !!!\n")); |
rtems_semaphore_release( wakeupEventSemId ); |
break; |
|
default: |
DPRINTF((" OTHER EXCEPTION !!!\n")); |
rtems_semaphore_release( wakeupEventSemId ); |
break; |
} |
|
rtems_semaphore_obtain(continueSemId, RTEMS_WAIT, RTEMS_NO_TIMEOUT); |
|
PopExceptCtx (_Thread_Executing->Object.id); |
rtems_semaphore_delete(continueSemId); |
} |
|
} |
|
|
|
/powerpc/mcp750/remdeb.h
0,0 → 1,581
/* |
* Please do not edit this file. |
* It was generated using rpcgen. |
*/ |
|
#ifndef _REMDEB_H_RPCGEN |
#define _REMDEB_H_RPCGEN |
|
#include <rpc/rpc.h> |
|
|
#ifdef __cplusplus |
extern "C" { |
#endif |
|
#define RTEMS_PORT 2071 |
#define RTEMS_BACK_PORT 2073 |
#ifndef REMDEB_H |
#define RPCGENSRVNAME(a) a |
|
enum rpc_type { |
SUNRPC = 0, |
BADRPCTYPE = 25, |
}; |
typedef enum rpc_type rpc_type; |
#define NET_SAFE 1400 |
|
struct UDP_MSG { |
u_char type; |
u_char msg_num; |
u_short spec; |
long pid; |
u_long context; |
}; |
typedef struct UDP_MSG UDP_MSG; |
/* |
* Sun request values for the remote ptrace system call |
*/ |
|
|
enum ptracereq { |
RPT_TRACEME = 0, |
RPT_CHILDDONE = 0, |
RPT_PEEKTEXT = 0 + 1, |
RPT_PEEKDATA = 0 + 2, |
RPT_PEEKUSER = 0 + 3, |
RPT_POKETEXT = 0 + 4, |
RPT_POKEDATA = 0 + 5, |
RPT_POKEUSER = 0 + 6, |
RPT_CONT = 0 + 7, |
RPT_KILL = 0 + 8, |
RPT_SINGLESTEP = 0 + 9, |
RPT_ATTACH = 0 + 10, |
RPT_DETACH = 0 + 11, |
RPT_GETREGS = 0 + 12, |
RPT_SETREGS = 0 + 13, |
RPT_GETFPREGS = 0 + 14, |
RPT_SETFPREGS = 0 + 15, |
RPT_READDATA = 0 + 16, |
RPT_WRITEDATA = 0 + 17, |
RPT_READTEXT = 0 + 18, |
RPT_WRITETEXT = 0 + 19, |
RPT_GETFPAREGS = 0 + 20, |
RPT_SETFPAREGS = 0 + 21, |
RPT_22 = 0 + 22, |
RPT_23 = 0 + 23, |
RPT_SYSCALL = 0 + 24, |
RPT_DUMPCORE = 0 + 25, |
RPT_26 = 0 + 26, |
RPT_27 = 0 + 27, |
RPT_28 = 0 + 28, |
RPT_GETUCODE = 0 + 29, |
RPT_GETTARGETTHREAD = 50, |
RPT_SETTARGETTHREAD = 51, |
RPT_THREADSUSPEND = 52, |
RPT_THREADRESUME = 53, |
RPT_THREADLIST = 54, |
RPT_GETTHREADNAME = 55, |
RPT_SETTHREADNAME = 56, |
RPT_SETTHREADREGS = 57, |
RPT_GETTHREADREGS = 58, |
RPT_STEPRANGE = 75, |
RPT_CONTTO = 76, |
RPT_SETBREAK = 77, |
RPT_CLRBREAK = 78, |
RPT_GETBREAK = 79, |
RPT_GETNAME = 80, |
RPT_STOP = 81, |
RPT_PGETREGS = 82, |
RPT_PSETREGS = 83, |
RPT_PSETTHREADREGS = 84, |
RPT_PGETTHREADREGS = 85, |
}; |
typedef enum ptracereq ptracereq; |
|
struct xdr_regs { |
u_int tabreg[40]; |
}; |
typedef struct xdr_regs xdr_regs; |
/* now define register macros to apply to xdr_regs struct */ |
|
#define R_PC 0 |
#define R_MSR 1 |
#define R_EXCEPNB 2 |
#define R_R0 3 |
#define R_R1 (R_R0 + 1) |
#define R_R2 (R_R0 + 2) |
#define R_R3 (R_R0 + 3) |
#define R_R4 (R_R0 + 4) |
#define R_R5 (R_R0 + 5) |
#define R_R6 (R_R0 + 6) |
#define R_R7 (R_R0 + 7) |
#define R_R8 (R_R0 + 8) |
#define R_R9 (R_R0 + 9) |
#define R_R10 (R_R0 + 10) |
#define R_R11 (R_R0 + 11) |
#define R_R12 (R_R0 + 12) |
#define R_R13 (R_R0 + 13) |
#define R_R14 (R_R0 + 14) |
#define R_R15 (R_R0 + 15) |
#define R_R16 (R_R0 + 16) |
#define R_R17 (R_R0 + 17) |
#define R_R18 (R_R0 + 18) |
#define R_R19 (R_R0 + 19) |
#define R_R20 (R_R0 + 20) |
#define R_R21 (R_R0 + 21) |
#define R_R22 (R_R0 + 22) |
#define R_R23 (R_R0 + 23) |
#define R_R24 (R_R0 + 24) |
#define R_R25 (R_R0 + 25) |
#define R_R26 (R_R0 + 26) |
#define R_R27 (R_R0 + 27) |
#define R_R28 (R_R0 + 28) |
#define R_R29 (R_R0 + 29) |
#define R_R30 (R_R0 + 30) |
#define R_R31 (R_R0 + 31) |
#define R_CR 35 |
#define R_CTR 36 |
#define R_XER 37 |
#define R_LR 38 |
#define R_MQ 39 |
|
#include <libcpu/raw_exception.h> |
|
#define REG_PC tabreg[R_PC] /* PC register offset */ |
#define REG_SP tabreg[R_R1] /* SP register offset */ |
#define REG_FP tabreg[R_R1] /* SP register offset (no FP on PPC) */ |
#define BREAK_SIZE 4 /* Breakpoint occupies 4 bytes */ |
#define BREAK_ADJ 0 /* Nothing to subtract from address after bp */ |
#define IS_BREAK(l) ((l) == 0x7d8d6808) |
#define SET_BREAK(l) (0x7d8d6808) |
#define ORG_BREAK(c,p) (p) |
#define IS_STEP(regs) (regs.tabreg[R_EXCEPNB] == ASM_TRACE_VECTOR) /* Was step and not break */ |
#define TARGET_PROC_TYPE 3 |
#define MAXDEBUGGEE 150 |
#define NAMEMAX 17 |
/* |
* Memory data for read/write text or data. The size is in data. The target |
* addr is in the addr field. |
* Be careful before modifying because this value goes into internal |
* pipes and is allocated on stack too. Pipes and/or the stack could |
* become too small if this value gets incremented. |
*/ |
#define MEM_DATA_MAX 256 |
|
struct xdr_mem { |
u_long addr; |
u_int dataNb; |
u_char data[MEM_DATA_MAX]; |
}; |
typedef struct xdr_mem xdr_mem; |
|
enum break_type { |
BRKT_NONE = 0, |
BRKT_INSTR = 1, |
BRKT_READ = 2, |
BRKT_WRITE = 3, |
BRKT_ACCESS = 4, |
BRKT_EXEC = 5, |
BRKT_OS_CALL = 6, |
BRKT_OS_SWITCH = 7, |
BRKT_STEPEMUL = 8, |
}; |
typedef enum break_type break_type; |
#define MAX_THRD_BRK 4 |
|
struct xdr_break { |
u_char type; |
u_char thread_spec; |
u_short handle; |
u_long ee_loc; |
u_long ee_type; |
u_short length; |
u_char pass_count; |
u_char curr_pass; |
u_long thread_list[MAX_THRD_BRK]; |
}; |
typedef struct xdr_break xdr_break; |
#define UTHREAD_MAX 64 |
#define THREADNAMEMAX 16 |
|
typedef char *thread_name; |
|
struct KernThread { |
u_int threadLi; |
}; |
typedef struct KernThread KernThread; |
typedef KernThread *ptThreadList; |
|
struct thread_list { |
u_int nbThread; |
ptThreadList threads; |
}; |
typedef struct thread_list thread_list; |
|
struct ptrace_addr_data_in { |
ptracereq req; |
union { |
xdr_regs regs; |
struct { |
u_int pregs_len; |
u_int *pregs_val; |
} pregs; |
thread_name name; |
xdr_mem mem; |
xdr_break breakp; |
u_int address; |
} ptrace_addr_data_in_u; |
}; |
typedef struct ptrace_addr_data_in ptrace_addr_data_in; |
|
struct ptrace_addr_data_out { |
ptracereq req; |
union { |
xdr_regs regs; |
struct { |
u_int pregs_len; |
u_int *pregs_val; |
} pregs; |
thread_list threads; |
thread_name name; |
xdr_mem mem; |
xdr_break breakp; |
u_int addr; |
} ptrace_addr_data_out_u; |
}; |
typedef struct ptrace_addr_data_out ptrace_addr_data_out; |
|
typedef struct { |
u_int CHAR_DATA_len; |
char *CHAR_DATA_val; |
} CHAR_DATA; |
#define XRY_MAX_INST_BUFF 128 |
#define XRY_MAX_INSTANCES 16 |
#ifndef XRY_MAX_CMD_STR |
#define XRY_MAX_CMD_STR 320 |
#endif /* REMDEB_H */ |
|
struct xry_inst { |
u_char flags; |
u_char type; |
u_char sub_type; |
u_char res_type; |
u_long value; |
u_long value2; |
}; |
typedef struct xry_inst xry_inst; |
|
struct instance { |
struct xry_inst instances[XRY_MAX_INSTANCES]; |
u_char buffer[XRY_MAX_INST_BUFF]; |
}; |
typedef struct instance instance; |
|
struct instance_union { |
bool_t instances; |
union { |
instance inst; |
char *buffer; |
} instance_union_u; |
}; |
typedef struct instance_union instance_union; |
|
typedef char *one_arg; |
#define XRY_MAX_OBJ_NAME 32 |
/* now open_connex() routine which establishes a connection to server */ |
|
enum debug_type { |
DEBTYP_PROCESS = 0, |
DEBTYP_C_ACTOR = 1, |
DEBTYP_KERNEL = 2, |
DEBTYP_OTHER = 3, |
}; |
typedef enum debug_type debug_type; |
#define DEBUGGER_IS_GDB 0x2 /* */ |
|
struct open_in { |
u_char back_port[16]; |
u_short debug_type; |
u_short flags; |
u_char destination[16]; |
one_arg user_name; |
}; |
typedef struct open_in open_in; |
|
struct open_out { |
u_long port; |
u_int pad[4]; |
u_int fp; |
u_char cmd_table_num; |
u_char cmd_table_vers; |
u_short server_vers; |
}; |
typedef struct open_out open_out; |
/* now close_connex() routine which detaches from server */ |
|
enum close_control { |
CLOSE_IGNORE = 0, |
CLOSE_KILL = 1, |
CLOSE_DETACH = 2, |
}; |
typedef enum close_control close_control; |
|
struct close_in { |
close_control control; |
}; |
typedef struct close_in close_in; |
/* now send_signal() routine which sends signals to processes like kill(2) */ |
|
struct signal_in { |
int pid; |
int sig; |
}; |
typedef struct signal_in signal_in; |
|
struct signal_out { |
int kill_return; |
int errNo; |
}; |
typedef struct signal_out signal_out; |
/* now wait_info() routine which returns results of polling the wait status |
of a process/actor. It may return 0 if running, else pid or -1 */ |
|
enum stop_code { |
STOP_ERROR = 0, |
STOP_NONE = 1, |
STOP_UNKNOWN = 2, |
STOP_BREAK = 3, |
STOP_STEP = 4, |
STOP_SIGNAL = 5, |
STOP_TERM_EXIT = 6, |
STOP_TERM_SIG = 7, |
STOP_DETACHED = 8, |
STOP_KILLED = 9, |
STOP_SPAWN_FAILED = 10, |
}; |
typedef enum stop_code stop_code; |
|
struct wait_in { |
int pid; |
}; |
typedef struct wait_in wait_in; |
|
struct wait_out { |
int wait_return; |
int errNo; |
int status; |
stop_code reason; |
int handle; |
u_long PC; |
u_long SP; |
u_long FP; |
u_long thread; |
}; |
typedef struct wait_out wait_out; |
/* now ptrace() routine. This matches the Sun UNIX ptrace as well as |
some additions */ |
#define PTRFLG_FORCE 1 |
#define PTRFLG_NON_OWNER 2 |
#define PTRFLG_FREE 4 |
#define PTRDET_UNOWN 0x100 |
|
struct ptrace_in { |
int pid; |
ptrace_addr_data_in addr; |
u_int data; |
u_int flags; |
}; |
typedef struct ptrace_in ptrace_in; |
|
struct ptrace_out { |
ptrace_addr_data_out addr; |
int result; |
int errNo; |
}; |
typedef struct ptrace_out ptrace_out; |
|
struct one_symbol { |
char *symbolName; |
long symbolValue; |
}; |
typedef struct one_symbol one_symbol; |
|
typedef struct { |
u_int all_symbols_len; |
one_symbol *all_symbols_val; |
} all_symbols; |
|
struct get_global_symbols_out { |
all_symbols symbols; |
}; |
typedef struct get_global_symbols_out get_global_symbols_out; |
|
struct get_text_data_in { |
int pid; |
char *actorName; |
}; |
typedef struct get_text_data_in get_text_data_in; |
|
struct get_text_data_out { |
int result; |
int errNo; |
u_long textStart; |
u_long textSize; |
u_long dataStart; |
u_long dataSize; |
}; |
typedef struct get_text_data_out get_text_data_out; |
|
struct one_signal { |
u_int number; |
char *name; |
}; |
typedef struct one_signal one_signal; |
|
typedef struct { |
u_int all_signals_len; |
one_signal *all_signals_val; |
} all_signals; |
|
struct get_signal_names_out { |
all_signals signals; |
}; |
typedef struct get_signal_names_out get_signal_names_out; |
/* now define the actual calls we support */ |
#define REMDEB_H |
#endif |
|
#define REMOTEDEB 0x20000fff |
#define REMOTEVERS 2 |
|
#if defined(__STDC__) || defined(__cplusplus) |
#define OPEN_CONNEX 1 |
extern open_out * open_connex_2(open_in *, CLIENT *); |
extern open_out * open_connex_2_svc(open_in *, struct svc_req *); |
#define SEND_SIGNAL 2 |
extern signal_out * send_signal_2(signal_in *, CLIENT *); |
extern signal_out * send_signal_2_svc(signal_in *, struct svc_req *); |
#define CLOSE_CONNEX 10 |
extern void * close_connex_2(close_in *, CLIENT *); |
extern void * close_connex_2_svc(close_in *, struct svc_req *); |
#define PTRACE 11 |
extern ptrace_out * ptrace_2(ptrace_in *, CLIENT *); |
extern ptrace_out * ptrace_2_svc(ptrace_in *, struct svc_req *); |
#define WAIT_INFO 13 |
extern wait_out * wait_info_2(wait_in *, CLIENT *); |
extern wait_out * wait_info_2_svc(wait_in *, struct svc_req *); |
#define GET_SIGNAL_NAMES 17 |
extern get_signal_names_out * get_signal_names_2(void *, CLIENT *); |
extern get_signal_names_out * get_signal_names_2_svc(void *, struct svc_req *); |
extern int remotedeb_2_freeresult (SVCXPRT *, xdrproc_t, caddr_t); |
|
#else /* K&R C */ |
#define OPEN_CONNEX 1 |
extern open_out * open_connex_2(); |
extern open_out * open_connex_2_svc(); |
#define SEND_SIGNAL 2 |
extern signal_out * send_signal_2(); |
extern signal_out * send_signal_2_svc(); |
#define CLOSE_CONNEX 10 |
extern void * close_connex_2(); |
extern void * close_connex_2_svc(); |
#define PTRACE 11 |
extern ptrace_out * ptrace_2(); |
extern ptrace_out * ptrace_2_svc(); |
#define WAIT_INFO 13 |
extern wait_out * wait_info_2(); |
extern wait_out * wait_info_2_svc(); |
#define GET_SIGNAL_NAMES 17 |
extern get_signal_names_out * get_signal_names_2(); |
extern get_signal_names_out * get_signal_names_2_svc(); |
extern int remotedeb_2_freeresult (); |
#endif /* K&R C */ |
|
/* the xdr functions */ |
|
#if defined(__STDC__) || defined(__cplusplus) |
extern bool_t xdr_rpc_type (XDR *, rpc_type*); |
extern bool_t xdr_UDP_MSG (XDR *, UDP_MSG*); |
extern bool_t xdr_ptracereq (XDR *, ptracereq*); |
extern bool_t xdr_xdr_regs (XDR *, xdr_regs*); |
extern bool_t xdr_xdr_mem (XDR *, xdr_mem*); |
extern bool_t xdr_break_type (XDR *, break_type*); |
extern bool_t xdr_xdr_break (XDR *, xdr_break*); |
extern bool_t xdr_thread_name (XDR *, thread_name*); |
extern bool_t xdr_KernThread (XDR *, KernThread*); |
extern bool_t xdr_thread_list (XDR *, thread_list*); |
extern bool_t xdr_ptrace_addr_data_in (XDR *, ptrace_addr_data_in*); |
extern bool_t xdr_ptrace_addr_data_out (XDR *, ptrace_addr_data_out*); |
extern bool_t xdr_CHAR_DATA (XDR *, CHAR_DATA*); |
extern bool_t xdr_xry_inst (XDR *, xry_inst*); |
extern bool_t xdr_instance (XDR *, instance*); |
extern bool_t xdr_instance_union (XDR *, instance_union*); |
extern bool_t xdr_one_arg (XDR *, one_arg*); |
extern bool_t xdr_debug_type (XDR *, debug_type*); |
extern bool_t xdr_open_in (XDR *, open_in*); |
extern bool_t xdr_open_out (XDR *, open_out*); |
extern bool_t xdr_close_control (XDR *, close_control*); |
extern bool_t xdr_close_in (XDR *, close_in*); |
extern bool_t xdr_signal_in (XDR *, signal_in*); |
extern bool_t xdr_signal_out (XDR *, signal_out*); |
extern bool_t xdr_stop_code (XDR *, stop_code*); |
extern bool_t xdr_wait_in (XDR *, wait_in*); |
extern bool_t xdr_wait_out (XDR *, wait_out*); |
extern bool_t xdr_ptrace_in (XDR *, ptrace_in*); |
extern bool_t xdr_ptrace_out (XDR *, ptrace_out*); |
extern bool_t xdr_one_symbol (XDR *, one_symbol*); |
extern bool_t xdr_all_symbols (XDR *, all_symbols*); |
extern bool_t xdr_get_global_symbols_out (XDR *, get_global_symbols_out*); |
extern bool_t xdr_get_text_data_in (XDR *, get_text_data_in*); |
extern bool_t xdr_get_text_data_out (XDR *, get_text_data_out*); |
extern bool_t xdr_one_signal (XDR *, one_signal*); |
extern bool_t xdr_all_signals (XDR *, all_signals*); |
extern bool_t xdr_get_signal_names_out (XDR *, get_signal_names_out*); |
|
#else /* K&R C */ |
extern bool_t xdr_rpc_type (); |
extern bool_t xdr_UDP_MSG (); |
extern bool_t xdr_ptracereq (); |
extern bool_t xdr_xdr_regs (); |
extern bool_t xdr_xdr_mem (); |
extern bool_t xdr_break_type (); |
extern bool_t xdr_xdr_break (); |
extern bool_t xdr_thread_name (); |
extern bool_t xdr_KernThread (); |
extern bool_t xdr_thread_list (); |
extern bool_t xdr_ptrace_addr_data_in (); |
extern bool_t xdr_ptrace_addr_data_out (); |
extern bool_t xdr_CHAR_DATA (); |
extern bool_t xdr_xry_inst (); |
extern bool_t xdr_instance (); |
extern bool_t xdr_instance_union (); |
extern bool_t xdr_one_arg (); |
extern bool_t xdr_debug_type (); |
extern bool_t xdr_open_in (); |
extern bool_t xdr_open_out (); |
extern bool_t xdr_close_control (); |
extern bool_t xdr_close_in (); |
extern bool_t xdr_signal_in (); |
extern bool_t xdr_signal_out (); |
extern bool_t xdr_stop_code (); |
extern bool_t xdr_wait_in (); |
extern bool_t xdr_wait_out (); |
extern bool_t xdr_ptrace_in (); |
extern bool_t xdr_ptrace_out (); |
extern bool_t xdr_one_symbol (); |
extern bool_t xdr_all_symbols (); |
extern bool_t xdr_get_global_symbols_out (); |
extern bool_t xdr_get_text_data_in (); |
extern bool_t xdr_get_text_data_out (); |
extern bool_t xdr_one_signal (); |
extern bool_t xdr_all_signals (); |
extern bool_t xdr_get_signal_names_out (); |
|
#endif /* K&R C */ |
|
#ifdef __cplusplus |
} |
#endif |
|
#endif /* !_REMDEB_H_RPCGEN */ |
/powerpc/mcp750/Makefile.am
0,0 → 1,90
## |
## $Id: Makefile.am,v 1.2 2001-09-27 12:02:02 chris Exp $ |
## |
|
AUTOMAKE_OPTIONS = foreign 1.4 |
|
VPATH = @srcdir@:@srcdir@/..:@srcdir@/../.. |
|
LIBNAME = librdbg |
LIB = ${ARCH}/${LIBNAME}.a |
|
# C and C++ source names |
C_FILES = rdbg.c servcon.c servbkpt.c servrpc.c excep.c excep_f.c servtgt.c \ |
servtsp.c servutil.c _servtgt.c rdbg_f.c ptrace.c |
C_O_FILES = $(C_FILES:%.c=${ARCH}/%.o) |
|
# Asm source names |
S_FILES = rdbg_cpu_asm.S |
S_O_FILES = $(S_FILES:%.S=${ARCH}/%.o) |
|
# Generated C source names |
GEN_C_FILES = remdeb_xdr.c remdeb_svc.c |
GEN_C_O_FILES = $(GEN_C_FILES:%.c=${ARCH}/%.o) |
|
# H source names |
H_FILES = remdeb.h |
|
# X source names |
X_FILES = remdeb.x remdeb_f.x |
|
OBJS = $(GEN_C_O_FILES) $(C_O_FILES) $(S_O_FILES) |
|
include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg |
include $(top_srcdir)/../../../automake/lib.am |
|
# |
# Add local stuff here using += |
# |
|
MAINTAINERCLEANFILES += $(H_FILES) $(GEN_C_FILES) |
|
FRONTEND = \"$(RTEMS_CPU)/mcp750/remdeb_f.x\" |
|
$(PROJECT_RELEASE)/lib/$(LIBNAME)$(LIB_VARIANT).a: $(LIB) |
$(INSTALL_DATA) $< $@ |
|
$(LIB): ${OBJS} |
$(make-library) |
|
$(srcdir)/remdeb.h: $(X_FILES) |
if RPCTOOLS |
@rm -f $@ |
( cd $(top_srcdir)/src; \ |
$(RPCGEN) -h -DFRONTEND=$(FRONTEND) \ |
-o powerpc/mcp750/remdeb.h remdeb.x ) |
endif |
$(srcdir)/remdeb_xdr.c: $(X_FILES) |
if RPCTOOLS |
@rm -f $@ |
( cd $(top_srcdir)/src; \ |
$(RPCGEN) -c -DFRONTEND=$(FRONTEND) \ |
-o powerpc/mcp750/remdeb_xdr.c remdeb.x ) |
endif |
|
$(srcdir)/remdeb_svc.c: $(X_FILES) |
if RPCTOOLS |
@rm -f $@ tmpSvc.c |
( cd $(top_srcdir)/src; \ |
$(RPCGEN) -m -DFRONTEND=$(FRONTEND) \ |
-o powerpc/mcp750/tmpSvc.c remdeb.x; \ |
$(AWK) -f ./awk.svc THEPROG="remdeb.h" powerpc/mcp750/tmpSvc.c \ |
> powerpc/mcp750/remdeb_svc.c; \ |
rm -f powerpc/mcp750/tmpSvc.c ) |
endif |
|
$(PROJECT_INCLUDE)/rdbg/remdeb.h: $(srcdir)/remdeb.h |
$(INSTALL_DATA) $< $@ |
|
$(PROJECT_INCLUDE)/rdbg: |
@$(mkinstalldirs) $@ |
|
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rdbg $(PROJECT_INCLUDE)/rdbg/remdeb.h |
|
TMPINSTALL_FILES += $(PROJECT_RELEASE)/lib/$(LIBNAME)$(LIB_VARIANT).a |
|
all-local: ${ARCH} $(PREINSTALL_FILES) $(TMPINSTALL_FILES) |
|
EXTRA_DIST = remdeb_f.x $(GEN_C_FILES) |
|
include $(top_srcdir)/../../../automake/local.am |
/powerpc/mcp750/remdeb_f.x
0,0 → 1,76
/* |
************************************************************************** |
* |
* Component = rdblib |
* Synopsis = remdeb_f.x |
* |
************************************************************************** |
* $Id: remdeb_f.x,v 1.2 2001-09-27 12:02:02 chris Exp $ |
************************************************************************** |
*/ |
|
struct xdr_regs |
{ |
unsigned int tabreg[40]; |
}; |
|
#ifdef RPC_HDR |
|
%/* now define register macros to apply to xdr_regs struct */ |
% |
%#define R_PC 0 |
%#define R_MSR 1 |
%#define R_EXCEPNB 2 |
%#define R_R0 3 |
%#define R_R1 (R_R0 + 1) |
%#define R_R2 (R_R0 + 2) |
%#define R_R3 (R_R0 + 3) |
%#define R_R4 (R_R0 + 4) |
%#define R_R5 (R_R0 + 5) |
%#define R_R6 (R_R0 + 6) |
%#define R_R7 (R_R0 + 7) |
%#define R_R8 (R_R0 + 8) |
%#define R_R9 (R_R0 + 9) |
%#define R_R10 (R_R0 + 10) |
%#define R_R11 (R_R0 + 11) |
%#define R_R12 (R_R0 + 12) |
%#define R_R13 (R_R0 + 13) |
%#define R_R14 (R_R0 + 14) |
%#define R_R15 (R_R0 + 15) |
%#define R_R16 (R_R0 + 16) |
%#define R_R17 (R_R0 + 17) |
%#define R_R18 (R_R0 + 18) |
%#define R_R19 (R_R0 + 19) |
%#define R_R20 (R_R0 + 20) |
%#define R_R21 (R_R0 + 21) |
%#define R_R22 (R_R0 + 22) |
%#define R_R23 (R_R0 + 23) |
%#define R_R24 (R_R0 + 24) |
%#define R_R25 (R_R0 + 25) |
%#define R_R26 (R_R0 + 26) |
%#define R_R27 (R_R0 + 27) |
%#define R_R28 (R_R0 + 28) |
%#define R_R29 (R_R0 + 29) |
%#define R_R30 (R_R0 + 30) |
%#define R_R31 (R_R0 + 31) |
%#define R_CR 35 |
%#define R_CTR 36 |
%#define R_XER 37 |
%#define R_LR 38 |
%#define R_MQ 39 |
% |
%#include <libcpu/raw_exception.h> |
% |
%#define REG_PC tabreg[R_PC] /* PC register offset */ |
%#define REG_SP tabreg[R_R1] /* SP register offset */ |
%#define REG_FP tabreg[R_R1] /* SP register offset (no FP on PPC) */ |
%#define BREAK_SIZE 4 /* Breakpoint occupies 4 bytes */ |
%#define BREAK_ADJ 0 /* Nothing to subtract from address after bp */ |
%#define IS_BREAK(l) ((l) == 0x7d8d6808) |
%#define SET_BREAK(l) (0x7d8d6808) |
%#define ORG_BREAK(c,p) (p) |
%#define IS_STEP(regs) (regs.tabreg[R_EXCEPNB] == ASM_TRACE_VECTOR) /* Was step and not break */ |
%#define TARGET_PROC_TYPE 3 |
|
#endif |
|
/powerpc/mcp750/remdeb_svc.c
0,0 → 1,122
#include <rpc/types.h> |
#include <rpc/rpc.h> |
#include <stdio.h> |
#include <stdlib.h> |
#include <string.h> |
#include <bsp.h> |
#include <rdbg/servrpc.h> |
#include <rdbg/remdeb.h> |
#define fprintf(a,b) printf(b) |
/*HEADER_START*/ |
#define RTEMS_PORT 2071 |
#define RTEMS_BACK_PORT 2073 |
/* |
* Sun request values for the remote ptrace system call |
*/ |
|
/* |
* Memory data for read/write text or data. The size is in data. The target |
* addr is in the addr field. |
* Be careful before modifying because this value goes into internal |
* pipes and is allocated on stack too. Pipes and/or the stack could |
* become too small if this value gets incremented. |
*/ |
#ifndef XRY_MAX_CMD_STR |
#endif /* REMDEB_H */ |
/* now open_connex() routine which establishes a connection to server */ |
#define DEBUGGER_IS_GDB 0x2 /* */ |
/* now close_connex() routine which detaches from server */ |
/* now send_signal() routine which sends signals to processes like kill(2) */ |
/* now wait_info() routine which returns results of polling the wait status |
of a process/actor. It may return 0 if running, else pid or -1 */ |
/* now ptrace() routine. This matches the Sun UNIX ptrace as well as |
some additions */ |
/* now define the actual calls we support */ |
const char* names [] = { |
"NULLPROC", "OPEN_CONNEX", "SEND_SIGNAL", "name3", |
"name4", "name5", "name6", "name7", |
"name8", "name9", "CLOSE_CONNEX", "PTRACE", |
"name12", "WAIT_INFO", "name14", "name15", |
"name16", "GET_SIGNAL_NAMES", "name18" |
}; |
|
void |
remotedeb_2(struct svc_req *rqstp, register SVCXPRT *transp) |
{ |
union { |
open_in open_connex_2_arg; |
signal_in send_signal_2_arg; |
close_in close_connex_2_arg; |
ptrace_in ptrace_2_arg; |
wait_in wait_info_2_arg; |
} argument; |
char *result; |
xdrproc_t _xdr_argument, _xdr_result; |
char *(*local)(char *, struct svc_req *); |
|
DPRINTF (("remotedeb_2: %s (%d)\n", |
(unsigned) rqstp->rq_proc < |
(unsigned) (sizeof names / sizeof names[0]) ? |
names [rqstp->rq_proc] : "???", |
(int) rqstp->rq_proc)); |
|
switch (rqstp->rq_proc) { |
case NULLPROC: |
(void) svc_sendreply (transp, (xdrproc_t) xdr_void, (char *)NULL); |
return; |
|
case OPEN_CONNEX: |
_xdr_argument = (xdrproc_t) xdr_open_in; |
_xdr_result = (xdrproc_t) xdr_open_out; |
local = (char *(*)(char *, struct svc_req *)) open_connex_2_svc; |
break; |
|
case SEND_SIGNAL: |
_xdr_argument = (xdrproc_t) xdr_signal_in; |
_xdr_result = (xdrproc_t) xdr_signal_out; |
local = (char *(*)(char *, struct svc_req *)) send_signal_2_svc; |
break; |
|
case CLOSE_CONNEX: |
_xdr_argument = (xdrproc_t) xdr_close_in; |
_xdr_result = (xdrproc_t) xdr_void; |
local = (char *(*)(char *, struct svc_req *)) close_connex_2_svc; |
break; |
|
case PTRACE: |
_xdr_argument = (xdrproc_t) xdr_ptrace_in; |
_xdr_result = (xdrproc_t) xdr_ptrace_out; |
local = (char *(*)(char *, struct svc_req *)) ptrace_2_svc; |
break; |
|
case WAIT_INFO: |
_xdr_argument = (xdrproc_t) xdr_wait_in; |
_xdr_result = (xdrproc_t) xdr_wait_out; |
local = (char *(*)(char *, struct svc_req *)) wait_info_2_svc; |
break; |
|
case GET_SIGNAL_NAMES: |
_xdr_argument = (xdrproc_t) xdr_void; |
_xdr_result = (xdrproc_t) xdr_get_signal_names_out; |
local = (char *(*)(char *, struct svc_req *)) get_signal_names_2_svc; |
break; |
|
default: |
svcerr_noproc (transp); |
return; |
} |
memset ((char *)&argument, 0, sizeof (argument)); |
if (!svc_getargs (transp, _xdr_argument, (caddr_t) &argument)) { |
svcerr_decode (transp); |
return; |
} |
result = (*local)((char *)&argument, rqstp); |
if (result != NULL && !svc_sendreply(transp, _xdr_result, result)) { |
svcerr_systemerr (transp); |
} |
if (!svc_freeargs (transp, _xdr_argument, (caddr_t) &argument)) { |
fprintf (stderr, "unable to free arguments"); |
exit (1); |
} |
return; |
} |
/powerpc/mcp750/remdeb_xdr.c
0,0 → 1,928
/* |
* Please do not edit this file. |
* It was generated using rpcgen. |
*/ |
|
#include "remdeb.h" |
#define RTEMS_PORT 2071 |
#define RTEMS_BACK_PORT 2073 |
|
bool_t |
xdr_rpc_type (XDR *xdrs, rpc_type *objp) |
{ |
register int32_t *buf; |
|
if (!xdr_enum (xdrs, (enum_t *) objp)) |
return FALSE; |
return TRUE; |
} |
|
bool_t |
xdr_UDP_MSG (XDR *xdrs, UDP_MSG *objp) |
{ |
register int32_t *buf; |
|
if (!xdr_u_char (xdrs, &objp->type)) |
return FALSE; |
if (!xdr_u_char (xdrs, &objp->msg_num)) |
return FALSE; |
if (!xdr_u_short (xdrs, &objp->spec)) |
return FALSE; |
if (!xdr_long (xdrs, &objp->pid)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->context)) |
return FALSE; |
return TRUE; |
} |
/* |
* Sun request values for the remote ptrace system call |
*/ |
|
|
bool_t |
xdr_ptracereq (XDR *xdrs, ptracereq *objp) |
{ |
register int32_t *buf; |
|
if (!xdr_enum (xdrs, (enum_t *) objp)) |
return FALSE; |
return TRUE; |
} |
|
bool_t |
xdr_xdr_regs (XDR *xdrs, xdr_regs *objp) |
{ |
register int32_t *buf; |
|
int i; |
|
if (xdrs->x_op == XDR_ENCODE) { |
buf = XDR_INLINE(xdrs, 40 * BYTES_PER_XDR_UNIT); |
if (buf == NULL) { |
if (!xdr_vector (xdrs, (char *)objp->tabreg, 40, |
sizeof (u_int), (xdrproc_t) xdr_u_int)) |
return FALSE; |
} else { |
{ |
register u_int *genp; |
|
for (i = 0, genp = objp->tabreg; |
i < 40; ++i) { |
IXDR_PUT_U_LONG(buf, *genp++); |
} |
} |
} |
return TRUE; |
} else if (xdrs->x_op == XDR_DECODE) { |
buf = XDR_INLINE(xdrs, 40 * BYTES_PER_XDR_UNIT); |
if (buf == NULL) { |
if (!xdr_vector (xdrs, (char *)objp->tabreg, 40, |
sizeof (u_int), (xdrproc_t) xdr_u_int)) |
return FALSE; |
} else { |
{ |
register u_int *genp; |
|
for (i = 0, genp = objp->tabreg; |
i < 40; ++i) { |
*genp++ = IXDR_GET_U_LONG(buf); |
} |
} |
} |
return TRUE; |
} |
|
if (!xdr_vector (xdrs, (char *)objp->tabreg, 40, |
sizeof (u_int), (xdrproc_t) xdr_u_int)) |
return FALSE; |
return TRUE; |
} |
/* |
* Memory data for read/write text or data. The size is in data. The target |
* addr is in the addr field. |
* Be careful before modifying because this value goes into internal |
* pipes and is allocated on stack too. Pipes and/or the stack could |
* become too small if this value gets incremented. |
*/ |
bool_t xdr_xdr_mem(xdrs, objp) |
XDR *xdrs; |
struct xdr_mem *objp; |
{ |
if (!xdr_u_long(xdrs, &objp->addr)) { |
return (FALSE); |
} |
if (!xdr_u_int(xdrs, &objp->dataNb)) { |
return(FALSE); |
} |
return (xdr_opaque(xdrs, objp->data, objp->dataNb)); |
} |
|
bool_t |
xdr_break_type (XDR *xdrs, break_type *objp) |
{ |
register int32_t *buf; |
|
if (!xdr_enum (xdrs, (enum_t *) objp)) |
return FALSE; |
return TRUE; |
} |
|
bool_t |
xdr_xdr_break (XDR *xdrs, xdr_break *objp) |
{ |
register int32_t *buf; |
|
int i; |
|
if (xdrs->x_op == XDR_ENCODE) { |
if (!xdr_u_char (xdrs, &objp->type)) |
return FALSE; |
if (!xdr_u_char (xdrs, &objp->thread_spec)) |
return FALSE; |
buf = XDR_INLINE (xdrs, 4 * BYTES_PER_XDR_UNIT); |
if (buf == NULL) { |
if (!xdr_u_short (xdrs, &objp->handle)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->ee_loc)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->ee_type)) |
return FALSE; |
if (!xdr_u_short (xdrs, &objp->length)) |
return FALSE; |
|
} else { |
IXDR_PUT_U_SHORT(buf, objp->handle); |
IXDR_PUT_U_LONG(buf, objp->ee_loc); |
IXDR_PUT_U_LONG(buf, objp->ee_type); |
IXDR_PUT_U_SHORT(buf, objp->length); |
} |
if (!xdr_u_char (xdrs, &objp->pass_count)) |
return FALSE; |
if (!xdr_u_char (xdrs, &objp->curr_pass)) |
return FALSE; |
buf = XDR_INLINE(xdrs, MAX_THRD_BRK * BYTES_PER_XDR_UNIT); |
if (buf == NULL) { |
if (!xdr_vector (xdrs, (char *)objp->thread_list, MAX_THRD_BRK, |
sizeof (u_long), (xdrproc_t) xdr_u_long)) |
return FALSE; |
} else { |
{ |
register u_long *genp; |
|
for (i = 0, genp = objp->thread_list; |
i < MAX_THRD_BRK; ++i) { |
IXDR_PUT_U_LONG(buf, *genp++); |
} |
} |
} |
return TRUE; |
} else if (xdrs->x_op == XDR_DECODE) { |
if (!xdr_u_char (xdrs, &objp->type)) |
return FALSE; |
if (!xdr_u_char (xdrs, &objp->thread_spec)) |
return FALSE; |
buf = XDR_INLINE (xdrs, 4 * BYTES_PER_XDR_UNIT); |
if (buf == NULL) { |
if (!xdr_u_short (xdrs, &objp->handle)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->ee_loc)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->ee_type)) |
return FALSE; |
if (!xdr_u_short (xdrs, &objp->length)) |
return FALSE; |
|
} else { |
objp->handle = IXDR_GET_U_SHORT(buf); |
objp->ee_loc = IXDR_GET_U_LONG(buf); |
objp->ee_type = IXDR_GET_U_LONG(buf); |
objp->length = IXDR_GET_U_SHORT(buf); |
} |
if (!xdr_u_char (xdrs, &objp->pass_count)) |
return FALSE; |
if (!xdr_u_char (xdrs, &objp->curr_pass)) |
return FALSE; |
buf = XDR_INLINE(xdrs, MAX_THRD_BRK * BYTES_PER_XDR_UNIT); |
if (buf == NULL) { |
if (!xdr_vector (xdrs, (char *)objp->thread_list, MAX_THRD_BRK, |
sizeof (u_long), (xdrproc_t) xdr_u_long)) |
return FALSE; |
} else { |
{ |
register u_long *genp; |
|
for (i = 0, genp = objp->thread_list; |
i < MAX_THRD_BRK; ++i) { |
*genp++ = IXDR_GET_U_LONG(buf); |
} |
} |
} |
return TRUE; |
} |
|
if (!xdr_u_char (xdrs, &objp->type)) |
return FALSE; |
if (!xdr_u_char (xdrs, &objp->thread_spec)) |
return FALSE; |
if (!xdr_u_short (xdrs, &objp->handle)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->ee_loc)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->ee_type)) |
return FALSE; |
if (!xdr_u_short (xdrs, &objp->length)) |
return FALSE; |
if (!xdr_u_char (xdrs, &objp->pass_count)) |
return FALSE; |
if (!xdr_u_char (xdrs, &objp->curr_pass)) |
return FALSE; |
if (!xdr_vector (xdrs, (char *)objp->thread_list, MAX_THRD_BRK, |
sizeof (u_long), (xdrproc_t) xdr_u_long)) |
return FALSE; |
return TRUE; |
} |
|
bool_t |
xdr_thread_name (XDR *xdrs, thread_name *objp) |
{ |
register int32_t *buf; |
|
if (!xdr_string (xdrs, objp, THREADNAMEMAX)) |
return FALSE; |
return TRUE; |
} |
|
bool_t |
xdr_KernThread (XDR *xdrs, KernThread *objp) |
{ |
register int32_t *buf; |
|
if (!xdr_u_int (xdrs, &objp->threadLi)) |
return FALSE; |
return TRUE; |
} |
bool_t xdr_thread_list(xdrs, objp) |
XDR *xdrs; |
struct thread_list *objp; |
{ |
return (xdr_array(xdrs, (char**)&objp->threads, &objp->nbThread, |
UTHREAD_MAX, sizeof(KernThread), xdr_KernThread)); |
} |
|
bool_t |
xdr_ptrace_addr_data_in (XDR *xdrs, ptrace_addr_data_in *objp) |
{ |
register int32_t *buf; |
|
if (!xdr_ptracereq (xdrs, &objp->req)) |
return FALSE; |
switch (objp->req) { |
case RPT_SETTHREADREGS: |
if (!xdr_xdr_regs (xdrs, &objp->ptrace_addr_data_in_u.regs)) |
return FALSE; |
break; |
case RPT_SETREGS: |
if (!xdr_xdr_regs (xdrs, &objp->ptrace_addr_data_in_u.regs)) |
return FALSE; |
break; |
case RPT_PSETTHREADREGS: |
if (!xdr_array (xdrs, (char **)&objp->ptrace_addr_data_in_u.pregs.pregs_val, (u_int *) &objp->ptrace_addr_data_in_u.pregs.pregs_len, ~0, |
sizeof (u_int), (xdrproc_t) xdr_u_int)) |
return FALSE; |
break; |
case RPT_PSETREGS: |
if (!xdr_array (xdrs, (char **)&objp->ptrace_addr_data_in_u.pregs.pregs_val, (u_int *) &objp->ptrace_addr_data_in_u.pregs.pregs_len, ~0, |
sizeof (u_int), (xdrproc_t) xdr_u_int)) |
return FALSE; |
break; |
case RPT_SETTHREADNAME: |
if (!xdr_thread_name (xdrs, &objp->ptrace_addr_data_in_u.name)) |
return FALSE; |
break; |
case RPT_WRITETEXT: |
if (!xdr_xdr_mem (xdrs, &objp->ptrace_addr_data_in_u.mem)) |
return FALSE; |
break; |
case RPT_WRITEDATA: |
if (!xdr_xdr_mem (xdrs, &objp->ptrace_addr_data_in_u.mem)) |
return FALSE; |
break; |
case RPT_SETBREAK: |
if (!xdr_xdr_break (xdrs, &objp->ptrace_addr_data_in_u.breakp)) |
return FALSE; |
break; |
default: |
if (!xdr_u_int (xdrs, &objp->ptrace_addr_data_in_u.address)) |
return FALSE; |
break; |
} |
return TRUE; |
} |
|
bool_t |
xdr_ptrace_addr_data_out (XDR *xdrs, ptrace_addr_data_out *objp) |
{ |
register int32_t *buf; |
|
if (!xdr_ptracereq (xdrs, &objp->req)) |
return FALSE; |
switch (objp->req) { |
case RPT_GETREGS: |
if (!xdr_xdr_regs (xdrs, &objp->ptrace_addr_data_out_u.regs)) |
return FALSE; |
break; |
case RPT_GETTHREADREGS: |
if (!xdr_xdr_regs (xdrs, &objp->ptrace_addr_data_out_u.regs)) |
return FALSE; |
break; |
case RPT_PGETREGS: |
if (!xdr_array (xdrs, (char **)&objp->ptrace_addr_data_out_u.pregs.pregs_val, (u_int *) &objp->ptrace_addr_data_out_u.pregs.pregs_len, ~0, |
sizeof (u_int), (xdrproc_t) xdr_u_int)) |
return FALSE; |
break; |
case RPT_PGETTHREADREGS: |
if (!xdr_array (xdrs, (char **)&objp->ptrace_addr_data_out_u.pregs.pregs_val, (u_int *) &objp->ptrace_addr_data_out_u.pregs.pregs_len, ~0, |
sizeof (u_int), (xdrproc_t) xdr_u_int)) |
return FALSE; |
break; |
case RPT_THREADLIST: |
if (!xdr_thread_list (xdrs, &objp->ptrace_addr_data_out_u.threads)) |
return FALSE; |
break; |
case RPT_GETTHREADNAME: |
if (!xdr_thread_name (xdrs, &objp->ptrace_addr_data_out_u.name)) |
return FALSE; |
break; |
case RPT_READTEXT: |
if (!xdr_xdr_mem (xdrs, &objp->ptrace_addr_data_out_u.mem)) |
return FALSE; |
break; |
case RPT_GETNAME: |
if (!xdr_xdr_mem (xdrs, &objp->ptrace_addr_data_out_u.mem)) |
return FALSE; |
break; |
case RPT_READDATA: |
if (!xdr_xdr_mem (xdrs, &objp->ptrace_addr_data_out_u.mem)) |
return FALSE; |
break; |
case RPT_GETBREAK: |
if (!xdr_xdr_break (xdrs, &objp->ptrace_addr_data_out_u.breakp)) |
return FALSE; |
break; |
default: |
if (!xdr_u_int (xdrs, &objp->ptrace_addr_data_out_u.addr)) |
return FALSE; |
break; |
} |
return TRUE; |
} |
|
bool_t |
xdr_CHAR_DATA (XDR *xdrs, CHAR_DATA *objp) |
{ |
register int32_t *buf; |
|
if (!xdr_bytes (xdrs, (char **)&objp->CHAR_DATA_val, (u_int *) &objp->CHAR_DATA_len, NET_SAFE)) |
return FALSE; |
return TRUE; |
} |
#ifndef XRY_MAX_CMD_STR |
#endif /* REMDEB_H */ |
|
bool_t |
xdr_xry_inst (XDR *xdrs, xry_inst *objp) |
{ |
register int32_t *buf; |
|
if (!xdr_u_char (xdrs, &objp->flags)) |
return FALSE; |
if (!xdr_u_char (xdrs, &objp->type)) |
return FALSE; |
if (!xdr_u_char (xdrs, &objp->sub_type)) |
return FALSE; |
if (!xdr_u_char (xdrs, &objp->res_type)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->value)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->value2)) |
return FALSE; |
return TRUE; |
} |
|
bool_t |
xdr_instance (XDR *xdrs, instance *objp) |
{ |
register int32_t *buf; |
|
int i; |
if (!xdr_vector (xdrs, (char *)objp->instances, XRY_MAX_INSTANCES, |
sizeof (xry_inst), (xdrproc_t) xdr_xry_inst)) |
return FALSE; |
if (!xdr_vector (xdrs, (char *)objp->buffer, XRY_MAX_INST_BUFF, |
sizeof (u_char), (xdrproc_t) xdr_u_char)) |
return FALSE; |
return TRUE; |
} |
|
bool_t |
xdr_instance_union (XDR *xdrs, instance_union *objp) |
{ |
register int32_t *buf; |
|
if (!xdr_bool (xdrs, &objp->instances)) |
return FALSE; |
switch (objp->instances) { |
case TRUE: |
if (!xdr_instance (xdrs, &objp->instance_union_u.inst)) |
return FALSE; |
break; |
case FALSE: |
if (!xdr_string (xdrs, &objp->instance_union_u.buffer, XRY_MAX_CMD_STR)) |
return FALSE; |
break; |
default: |
return FALSE; |
} |
return TRUE; |
} |
|
bool_t |
xdr_one_arg (XDR *xdrs, one_arg *objp) |
{ |
register int32_t *buf; |
|
if (!xdr_string (xdrs, objp, NET_SAFE)) |
return FALSE; |
return TRUE; |
} |
/* now open_connex() routine which establishes a connection to server */ |
|
bool_t |
xdr_debug_type (XDR *xdrs, debug_type *objp) |
{ |
register int32_t *buf; |
|
if (!xdr_enum (xdrs, (enum_t *) objp)) |
return FALSE; |
return TRUE; |
} |
#define DEBUGGER_IS_GDB 0x2 /* */ |
|
bool_t |
xdr_open_in (XDR *xdrs, open_in *objp) |
{ |
register int32_t *buf; |
|
int i; |
if (!xdr_vector (xdrs, (char *)objp->back_port, 16, |
sizeof (u_char), (xdrproc_t) xdr_u_char)) |
return FALSE; |
if (!xdr_u_short (xdrs, &objp->debug_type)) |
return FALSE; |
if (!xdr_u_short (xdrs, &objp->flags)) |
return FALSE; |
if (!xdr_vector (xdrs, (char *)objp->destination, 16, |
sizeof (u_char), (xdrproc_t) xdr_u_char)) |
return FALSE; |
if (!xdr_one_arg (xdrs, &objp->user_name)) |
return FALSE; |
return TRUE; |
} |
|
bool_t |
xdr_open_out (XDR *xdrs, open_out *objp) |
{ |
register int32_t *buf; |
|
int i; |
|
if (xdrs->x_op == XDR_ENCODE) { |
buf = XDR_INLINE(xdrs, (2 + ( 4 )) * BYTES_PER_XDR_UNIT); |
if (buf == NULL) { |
if (!xdr_u_long (xdrs, &objp->port)) |
return FALSE; |
if (!xdr_vector (xdrs, (char *)objp->pad, 4, |
sizeof (u_int), (xdrproc_t) xdr_u_int)) |
return FALSE; |
if (!xdr_u_int (xdrs, &objp->fp)) |
return FALSE; |
|
} else { |
IXDR_PUT_U_LONG(buf, objp->port); |
{ |
register u_int *genp; |
|
for (i = 0, genp = objp->pad; |
i < 4; ++i) { |
IXDR_PUT_U_LONG(buf, *genp++); |
} |
} |
IXDR_PUT_U_LONG(buf, objp->fp); |
} |
if (!xdr_u_char (xdrs, &objp->cmd_table_num)) |
return FALSE; |
if (!xdr_u_char (xdrs, &objp->cmd_table_vers)) |
return FALSE; |
if (!xdr_u_short (xdrs, &objp->server_vers)) |
return FALSE; |
return TRUE; |
} else if (xdrs->x_op == XDR_DECODE) { |
buf = XDR_INLINE(xdrs, (2 + ( 4 )) * BYTES_PER_XDR_UNIT); |
if (buf == NULL) { |
if (!xdr_u_long (xdrs, &objp->port)) |
return FALSE; |
if (!xdr_vector (xdrs, (char *)objp->pad, 4, |
sizeof (u_int), (xdrproc_t) xdr_u_int)) |
return FALSE; |
if (!xdr_u_int (xdrs, &objp->fp)) |
return FALSE; |
|
} else { |
objp->port = IXDR_GET_U_LONG(buf); |
{ |
register u_int *genp; |
|
for (i = 0, genp = objp->pad; |
i < 4; ++i) { |
*genp++ = IXDR_GET_U_LONG(buf); |
} |
} |
objp->fp = IXDR_GET_U_LONG(buf); |
} |
if (!xdr_u_char (xdrs, &objp->cmd_table_num)) |
return FALSE; |
if (!xdr_u_char (xdrs, &objp->cmd_table_vers)) |
return FALSE; |
if (!xdr_u_short (xdrs, &objp->server_vers)) |
return FALSE; |
return TRUE; |
} |
|
if (!xdr_u_long (xdrs, &objp->port)) |
return FALSE; |
if (!xdr_vector (xdrs, (char *)objp->pad, 4, |
sizeof (u_int), (xdrproc_t) xdr_u_int)) |
return FALSE; |
if (!xdr_u_int (xdrs, &objp->fp)) |
return FALSE; |
if (!xdr_u_char (xdrs, &objp->cmd_table_num)) |
return FALSE; |
if (!xdr_u_char (xdrs, &objp->cmd_table_vers)) |
return FALSE; |
if (!xdr_u_short (xdrs, &objp->server_vers)) |
return FALSE; |
return TRUE; |
} |
/* now close_connex() routine which detaches from server */ |
|
bool_t |
xdr_close_control (XDR *xdrs, close_control *objp) |
{ |
register int32_t *buf; |
|
if (!xdr_enum (xdrs, (enum_t *) objp)) |
return FALSE; |
return TRUE; |
} |
|
bool_t |
xdr_close_in (XDR *xdrs, close_in *objp) |
{ |
register int32_t *buf; |
|
if (!xdr_close_control (xdrs, &objp->control)) |
return FALSE; |
return TRUE; |
} |
/* now send_signal() routine which sends signals to processes like kill(2) */ |
|
bool_t |
xdr_signal_in (XDR *xdrs, signal_in *objp) |
{ |
register int32_t *buf; |
|
if (!xdr_int (xdrs, &objp->pid)) |
return FALSE; |
if (!xdr_int (xdrs, &objp->sig)) |
return FALSE; |
return TRUE; |
} |
|
bool_t |
xdr_signal_out (XDR *xdrs, signal_out *objp) |
{ |
register int32_t *buf; |
|
if (!xdr_int (xdrs, &objp->kill_return)) |
return FALSE; |
if (!xdr_int (xdrs, &objp->errNo)) |
return FALSE; |
return TRUE; |
} |
/* now wait_info() routine which returns results of polling the wait status |
of a process/actor. It may return 0 if running, else pid or -1 */ |
|
bool_t |
xdr_stop_code (XDR *xdrs, stop_code *objp) |
{ |
register int32_t *buf; |
|
if (!xdr_enum (xdrs, (enum_t *) objp)) |
return FALSE; |
return TRUE; |
} |
|
bool_t |
xdr_wait_in (XDR *xdrs, wait_in *objp) |
{ |
register int32_t *buf; |
|
if (!xdr_int (xdrs, &objp->pid)) |
return FALSE; |
return TRUE; |
} |
|
bool_t |
xdr_wait_out (XDR *xdrs, wait_out *objp) |
{ |
register int32_t *buf; |
|
|
if (xdrs->x_op == XDR_ENCODE) { |
buf = XDR_INLINE (xdrs, 3 * BYTES_PER_XDR_UNIT); |
if (buf == NULL) { |
if (!xdr_int (xdrs, &objp->wait_return)) |
return FALSE; |
if (!xdr_int (xdrs, &objp->errNo)) |
return FALSE; |
if (!xdr_int (xdrs, &objp->status)) |
return FALSE; |
|
} else { |
IXDR_PUT_LONG(buf, objp->wait_return); |
IXDR_PUT_LONG(buf, objp->errNo); |
IXDR_PUT_LONG(buf, objp->status); |
} |
if (!xdr_stop_code (xdrs, &objp->reason)) |
return FALSE; |
buf = XDR_INLINE(xdrs,5 * BYTES_PER_XDR_UNIT); |
if (buf == NULL) { |
if (!xdr_int (xdrs, &objp->handle)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->PC)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->SP)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->FP)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->thread)) |
return FALSE; |
} else { |
IXDR_PUT_LONG(buf, objp->handle); |
IXDR_PUT_U_LONG(buf, objp->PC); |
IXDR_PUT_U_LONG(buf, objp->SP); |
IXDR_PUT_U_LONG(buf, objp->FP); |
IXDR_PUT_U_LONG(buf, objp->thread); |
} |
return TRUE; |
} else if (xdrs->x_op == XDR_DECODE) { |
buf = XDR_INLINE (xdrs, 3 * BYTES_PER_XDR_UNIT); |
if (buf == NULL) { |
if (!xdr_int (xdrs, &objp->wait_return)) |
return FALSE; |
if (!xdr_int (xdrs, &objp->errNo)) |
return FALSE; |
if (!xdr_int (xdrs, &objp->status)) |
return FALSE; |
|
} else { |
objp->wait_return = IXDR_GET_LONG(buf); |
objp->errNo = IXDR_GET_LONG(buf); |
objp->status = IXDR_GET_LONG(buf); |
} |
if (!xdr_stop_code (xdrs, &objp->reason)) |
return FALSE; |
buf = XDR_INLINE(xdrs,5 * BYTES_PER_XDR_UNIT); |
if (buf == NULL) { |
if (!xdr_int (xdrs, &objp->handle)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->PC)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->SP)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->FP)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->thread)) |
return FALSE; |
} else { |
objp->handle = IXDR_GET_LONG(buf); |
objp->PC = IXDR_GET_U_LONG(buf); |
objp->SP = IXDR_GET_U_LONG(buf); |
objp->FP = IXDR_GET_U_LONG(buf); |
objp->thread = IXDR_GET_U_LONG(buf); |
} |
return TRUE; |
} |
|
if (!xdr_int (xdrs, &objp->wait_return)) |
return FALSE; |
if (!xdr_int (xdrs, &objp->errNo)) |
return FALSE; |
if (!xdr_int (xdrs, &objp->status)) |
return FALSE; |
if (!xdr_stop_code (xdrs, &objp->reason)) |
return FALSE; |
if (!xdr_int (xdrs, &objp->handle)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->PC)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->SP)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->FP)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->thread)) |
return FALSE; |
return TRUE; |
} |
/* now ptrace() routine. This matches the Sun UNIX ptrace as well as |
some additions */ |
|
bool_t |
xdr_ptrace_in (XDR *xdrs, ptrace_in *objp) |
{ |
register int32_t *buf; |
|
if (!xdr_int (xdrs, &objp->pid)) |
return FALSE; |
if (!xdr_ptrace_addr_data_in (xdrs, &objp->addr)) |
return FALSE; |
if (!xdr_u_int (xdrs, &objp->data)) |
return FALSE; |
if (!xdr_u_int (xdrs, &objp->flags)) |
return FALSE; |
return TRUE; |
} |
|
bool_t |
xdr_ptrace_out (XDR *xdrs, ptrace_out *objp) |
{ |
register int32_t *buf; |
|
if (!xdr_ptrace_addr_data_out (xdrs, &objp->addr)) |
return FALSE; |
if (!xdr_int (xdrs, &objp->result)) |
return FALSE; |
if (!xdr_int (xdrs, &objp->errNo)) |
return FALSE; |
return TRUE; |
} |
|
bool_t |
xdr_one_symbol (XDR *xdrs, one_symbol *objp) |
{ |
register int32_t *buf; |
|
if (!xdr_string (xdrs, &objp->symbolName, ~0)) |
return FALSE; |
if (!xdr_long (xdrs, &objp->symbolValue)) |
return FALSE; |
return TRUE; |
} |
|
bool_t |
xdr_all_symbols (XDR *xdrs, all_symbols *objp) |
{ |
register int32_t *buf; |
|
if (!xdr_array (xdrs, (char **)&objp->all_symbols_val, (u_int *) &objp->all_symbols_len, ~0, |
sizeof (one_symbol), (xdrproc_t) xdr_one_symbol)) |
return FALSE; |
return TRUE; |
} |
|
bool_t |
xdr_get_global_symbols_out (XDR *xdrs, get_global_symbols_out *objp) |
{ |
register int32_t *buf; |
|
if (!xdr_all_symbols (xdrs, &objp->symbols)) |
return FALSE; |
return TRUE; |
} |
|
bool_t |
xdr_get_text_data_in (XDR *xdrs, get_text_data_in *objp) |
{ |
register int32_t *buf; |
|
if (!xdr_int (xdrs, &objp->pid)) |
return FALSE; |
if (!xdr_string (xdrs, &objp->actorName, 16)) |
return FALSE; |
return TRUE; |
} |
|
bool_t |
xdr_get_text_data_out (XDR *xdrs, get_text_data_out *objp) |
{ |
register int32_t *buf; |
|
|
if (xdrs->x_op == XDR_ENCODE) { |
buf = XDR_INLINE(xdrs,6 * BYTES_PER_XDR_UNIT); |
if (buf == NULL) { |
if (!xdr_int (xdrs, &objp->result)) |
return FALSE; |
if (!xdr_int (xdrs, &objp->errNo)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->textStart)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->textSize)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->dataStart)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->dataSize)) |
return FALSE; |
} else { |
IXDR_PUT_LONG(buf, objp->result); |
IXDR_PUT_LONG(buf, objp->errNo); |
IXDR_PUT_U_LONG(buf, objp->textStart); |
IXDR_PUT_U_LONG(buf, objp->textSize); |
IXDR_PUT_U_LONG(buf, objp->dataStart); |
IXDR_PUT_U_LONG(buf, objp->dataSize); |
} |
return TRUE; |
} else if (xdrs->x_op == XDR_DECODE) { |
buf = XDR_INLINE(xdrs,6 * BYTES_PER_XDR_UNIT); |
if (buf == NULL) { |
if (!xdr_int (xdrs, &objp->result)) |
return FALSE; |
if (!xdr_int (xdrs, &objp->errNo)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->textStart)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->textSize)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->dataStart)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->dataSize)) |
return FALSE; |
} else { |
objp->result = IXDR_GET_LONG(buf); |
objp->errNo = IXDR_GET_LONG(buf); |
objp->textStart = IXDR_GET_U_LONG(buf); |
objp->textSize = IXDR_GET_U_LONG(buf); |
objp->dataStart = IXDR_GET_U_LONG(buf); |
objp->dataSize = IXDR_GET_U_LONG(buf); |
} |
return TRUE; |
} |
|
if (!xdr_int (xdrs, &objp->result)) |
return FALSE; |
if (!xdr_int (xdrs, &objp->errNo)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->textStart)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->textSize)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->dataStart)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->dataSize)) |
return FALSE; |
return TRUE; |
} |
|
bool_t |
xdr_one_signal (XDR *xdrs, one_signal *objp) |
{ |
register int32_t *buf; |
|
if (!xdr_u_int (xdrs, &objp->number)) |
return FALSE; |
if (!xdr_string (xdrs, &objp->name, ~0)) |
return FALSE; |
return TRUE; |
} |
|
bool_t |
xdr_all_signals (XDR *xdrs, all_signals *objp) |
{ |
register int32_t *buf; |
|
if (!xdr_array (xdrs, (char **)&objp->all_signals_val, (u_int *) &objp->all_signals_len, ~0, |
sizeof (one_signal), (xdrproc_t) xdr_one_signal)) |
return FALSE; |
return TRUE; |
} |
|
bool_t |
xdr_get_signal_names_out (XDR *xdrs, get_signal_names_out *objp) |
{ |
register int32_t *buf; |
|
if (!xdr_all_signals (xdrs, &objp->signals)) |
return FALSE; |
return TRUE; |
} |
/* now define the actual calls we support */ |
/ptrace.c
0,0 → 1,333
/* |
************************************************************************** |
* |
* Component = |
* |
* Synopsis = rkdb/rkdb.c |
* |
* $Id: ptrace.c,v 1.2 2001-09-27 12:02:01 chris Exp $ |
* |
************************************************************************** |
*/ |
|
#include <assert.h> |
#include <errno.h> |
#include <rdbg/rdbg.h> |
#include <rdbg/rdbg_f.h> |
#include <rdbg/servrpc.h> |
|
extern rtems_id serializeSemId; |
extern rtems_id wakeupEventSemId; |
extern rtems_id eventTaskId; |
extern Exception_context *FirstCtx; |
extern Exception_context *LastCtx; |
extern CPU_Exception_frame SavedContext; |
extern unsigned int NbExceptCtx; |
extern unsigned int NbSerializedCtx; |
|
|
|
/* -------------------------------------------------------------------- |
return a pointer to the Thread Control structure of the specified |
Id |
-------------------------------------------------------------------- */ |
|
Thread_Control *Thread_Get_RDBG ( |
Objects_Id Id |
) |
{ |
unsigned index; |
|
if ( Id <_Objects_Information_table[OBJECTS_RTEMS_TASKS]->maximum_id && |
Id >_Objects_Information_table[OBJECTS_RTEMS_TASKS]->minimum_id) { |
|
index = Id - _Objects_Information_table[OBJECTS_RTEMS_TASKS]->minimum_id; |
if ( _Objects_Information_table[OBJECTS_RTEMS_TASKS]->local_table[1+index] != NULL) { |
return (Thread_Control *)(_Objects_Information_table[OBJECTS_RTEMS_TASKS]->local_table[1+index]); |
} |
} |
|
if ( Id <_Objects_Information_table[OBJECTS_POSIX_THREADS]->maximum_id && |
Id >_Objects_Information_table[OBJECTS_POSIX_THREADS]->minimum_id) { |
|
index = Id - _Objects_Information_table[OBJECTS_POSIX_THREADS]->minimum_id; |
if ( _Objects_Information_table[OBJECTS_POSIX_THREADS]->local_table[1+index] != NULL) |
return (Thread_Control *)(_Objects_Information_table[OBJECTS_POSIX_THREADS]->local_table[1+index]); |
} |
|
return 0; |
|
} |
|
|
/* -------------------------------------------------------------------- |
Memory read |
-------------------------------------------------------------------- */ |
|
int |
safeMemRead(void *src, void *dest, int nbBytes){ |
|
/* |
* safe because if it generates an exception, |
* it must return normally |
* TBD |
*/ |
|
memcpy(dest, src, nbBytes); |
return 0; |
} |
|
/* -------------------------------------------------------------------- |
Memory write |
-------------------------------------------------------------------- */ |
int |
safeMemWrite(void *src, void * dest, int nbBytes){ |
|
/* |
* safe because if it generates an exception, |
* it must return normally |
* TBD |
*/ |
|
memcpy(dest, src, nbBytes); |
return 0; |
} |
|
/* -------------------------------------------------------------------- |
Ptrace |
-------------------------------------------------------------------- */ |
|
int |
ptrace (int request, int pid, char* addr, int data, char* addr2) |
{ |
int diag; |
errno = 0 ; |
if (pid != 1) { |
errno = ESRCH; |
return -1; |
} |
switch (request) { |
|
case RPT_SINGLESTEP:{ |
Exception_context *ctx; |
|
if (CannotRestart == 1){ |
setErrno(EIO); |
return -1; |
} |
|
if ((ctx = GetExceptCtx (currentTargetThread)) != NULL) { |
Single_Step(ctx->ctx); |
rtems_semaphore_release( ctx->semaphoreId ); |
return 0; |
} |
break; |
} |
|
case RPT_PEEKTEXT: |
case RPT_PEEKDATA: { |
diag = safeMemRead(addr, &data, sizeof data); |
if (diag == 0) return data; |
mem_error: |
return -1; |
} |
|
case RPT_POKETEXT: { |
diag = safeMemWrite(&data, addr, sizeof data); |
|
/* |
* We must flush the INSTR and DATA cache to be sure the |
* opcode modification is taken into account, because |
* the breakpoint opcode is written via the data cache |
* while execution code is fetched via the instruction |
* cache |
*/ |
|
if (diag == 0) { |
copyback_data_cache_and_invalidate_instr_cache(addr, sizeof data); |
return 0; |
} |
goto mem_error; |
} |
case RPT_POKEDATA: { |
diag = safeMemWrite(&data, addr, sizeof data); |
if (diag == 0) return 0; |
goto mem_error; |
} |
case RPT_CONT: { |
Exception_context *ctx; |
|
if (CannotRestart == 1){ |
setErrno (EIO); |
return -1; |
} |
|
ctx = GetExceptCtx (currentTargetThread); |
|
if (!isRdbgException(ctx)) { |
CannotRestart = 1; |
setErrno (EIO); |
return -1; |
} |
|
assert (data == 0); |
assert (ExitForSingleStep == 0); |
|
rtems_semaphore_release( serializeSemId ); |
|
if ((ctx = GetExceptCtx (currentTargetThread)) != NULL) { |
rtems_semaphore_release( ctx->semaphoreId ); |
} |
return 0; |
} |
|
case RPT_ATTACH: |
return 0; |
|
case RPT_DETACH:{ |
Exception_context *ctx; |
|
if (NbExceptCtx || NbSerializedCtx) { |
ctx = FirstCtx; |
rtems_task_delete(eventTaskId); |
rtems_semaphore_delete(serializeSemId); |
rtems_semaphore_delete(wakeupEventSemId); |
} |
return 0; |
} |
|
case RPT_GETREGS:{ |
Exception_context *ctx; |
|
if ((ctx = GetExceptCtx (currentTargetThread)) != NULL) { |
CtxToRegs (ctx->ctx, (xdr_regs*) addr); |
return 0; |
} |
break; |
} |
|
case RPT_SETREGS:{ |
Exception_context *ctx; |
|
if ((ctx = GetExceptCtx (currentTargetThread)) != NULL) { |
RegsToCtx ((xdr_regs*) addr, ctx->ctx); |
return 0; |
} |
break; |
} |
|
case RPT_READTEXT: |
case RPT_READDATA: { |
diag = safeMemRead(addr, addr2, data); |
if (diag == 0) return 0; |
goto mem_error; |
} |
case RPT_WRITETEXT: |
case RPT_WRITEDATA: { |
diag = safeMemWrite(addr2, addr, data); |
if (diag == 0) return 0; |
goto mem_error; |
} |
|
case RPT_GETTARGETTHREAD: |
if (!NbExceptCtx) { |
errno = EBUSY; |
return -1; |
} |
return currentTargetThread; |
|
case RPT_SETTARGETTHREAD: |
if (!NbExceptCtx) { |
errno = EBUSY; |
return -1; |
} |
currentTargetThread = data; |
return 0; |
|
case RPT_GETTHREADNAME: { |
return TgtGetThreadName (NULL, (unsigned)(data), (char *) addr); |
} |
|
case RPT_THREADLIST: { |
int count = TgtThreadList (NULL, (unsigned*) addr, UTHREAD_MAX |
* sizeof (unsigned)); |
if (count < 0) { |
errno = EINVAL; |
return -1; |
} |
return count; |
} |
|
case RPT_SETTHREADREGS: { |
Exception_context *ctx; |
CPU_Exception_frame Ectx; |
Thread_Control *thread; |
rtems_id id; |
|
rtems_task_ident(RTEMS_SELF, RTEMS_SEARCH_ALL_NODES, &id); |
if (data == (unsigned)id) |
break; |
|
if ((ctx = GetExceptCtx (data)) != NULL) { |
RegsToCtx ((xdr_regs*) addr, ctx->ctx); |
return 0; |
} |
thread = Thread_Get_RDBG ((Objects_Id)(data)); |
if (thread != NULL) { |
RegsToCtx ((xdr_regs*) addr, &Ectx); |
set_ctx_thread (thread, &Ectx); |
return 0; |
} |
break; |
} |
|
case RPT_GETTHREADREGS: { |
Exception_context *ctx; |
CPU_Exception_frame Ectx; |
Thread_Control *thread; |
rtems_id id; |
|
rtems_task_ident(RTEMS_SELF, RTEMS_SEARCH_ALL_NODES, &id); |
if (data == (unsigned)id){ |
justSaveContext = 1; |
enterRdbg(); |
CtxToRegs (&(SavedContext), (xdr_regs*) addr); |
return 0; |
} |
|
if ((ctx = GetExceptCtx (data)) != NULL) { |
CtxToRegs (ctx->ctx, (xdr_regs*) addr); |
return 0; |
} |
thread = Thread_Get_RDBG ((Objects_Id)(data)); |
if (thread != NULL) { |
get_ctx_thread (thread, &Ectx); |
CtxToRegs (&Ectx, (xdr_regs*) addr); |
return 0; |
} |
break; |
} |
|
case RPT_KILL: |
TotalReboot = 1; |
return 0; |
|
case RPT_TRACEME: |
case RPT_PEEKUSER: |
case RPT_POKEUSER: |
case RPT_GETFPREGS: |
case RPT_SETFPREGS: |
case RPT_GETFPAREGS: |
case RPT_SETFPAREGS: |
case RPT_SYSCALL: |
case RPT_DUMPCORE: |
case RPT_GETUCODE: |
case RPT_THREADSUSPEND: |
case RPT_THREADRESUME: |
case RPT_SETTHREADNAME: |
default: |
break; |
} |
errno = EINVAL; |
return -1; |
} |
/rdbg.c
0,0 → 1,143
/* |
************************************************************************** |
* |
* Component = |
* |
* Synopsis = rkdb/rkdb.c |
* |
* $Id: rdbg.c,v 1.2 2001-09-27 12:02:01 chris Exp $ |
* |
************************************************************************** |
*/ |
|
#include <assert.h> |
#include <errno.h> |
#include <rtems.h> |
#include <rtems/error.h> |
#include <rdbg/rdbg.h> |
#include <rdbg/servrpc.h> |
#include <rtems/rtems_bsdnet.h> |
#include <rpc/pmap_clnt.h> |
#include <sys/socket.h> |
#include <netinet/in.h> |
|
u_short rtemsPort = RTEMS_PORT; |
int BackPort = RTEMS_BACK_PORT; |
int rtemsActive = 0; |
SVCXPRT* rtemsXprt; |
int rtemsSock; |
char ActName[] = "RTEMS"; |
volatile int ExitForSingleStep = 0 ; |
volatile int Continue; |
volatile int justSaveContext; |
volatile Objects_Id currentTargetThread; |
volatile int CannotRestart = 0; |
volatile int TotalReboot = 0; |
int CONN_LIST_INC = 3; |
int PID_LIST_INC = 1; |
int TSP_RETRIES = 10; |
|
|
int |
getId() |
{ |
rtems_id id; |
|
rtems_task_ident(RTEMS_SELF, RTEMS_SEARCH_ALL_NODES, &id); |
return (int)(id) ; |
} |
|
static int |
rdbgInit (void) |
{ |
int sock; |
struct sockaddr_in addr; |
|
sock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); |
if (sock == -1) { |
printf("%s: rkdbInit: cannot allocate socket\n", ActName); |
return -1; |
} |
|
bzero( (void *)&addr, sizeof(struct sockaddr_in)); |
addr.sin_port = htons(rtemsPort); |
if ((bind(sock, (struct sockaddr*) &addr, sizeof(addr))) == -1) { |
printf("%s: rkdbInit: cannot bind socket\n", ActName); |
return -2; |
} |
rtemsXprt = svcudp_create(sock); |
if (svcudp_enablecache(rtemsXprt, 1) == 0) { |
printf("%s: rkdbInit: cannot enable rpc cache\n", ActName); |
return -3; |
} |
rtemsSock = sock; |
if (!svc_register(rtemsXprt, REMOTEDEB, REMOTEVERS, remotedeb_2, 0)) { |
printf(stderr, "unable to register (REMOTEDEB, REMOTEVERS, udp)."); |
return -4; |
} |
|
return 0; |
} |
|
rtems_task |
rdbgDaemon (rtems_task_argument argument) |
{ |
svc_run(); |
} |
|
void |
rtems_rdbg_initialize (void) |
{ |
rtems_name task_name; |
rtems_id tid; |
rtems_status_code status; |
|
#ifdef DDEBUG |
rdb_debug = 1; /* DPRINTF now will display */ |
#endif |
|
DPRINTF (("%s init starting\n", ActName)); |
|
/* Print version string */ |
#ifdef DDEBUG |
printk ("RDBG v.%d built on [%s %s]\n", SERVER_VERS, __DATE__, __TIME__); |
#else |
printk ("RDBG v.%d\n", SERVER_VERS); |
#endif |
|
/* Create socket and init UDP RPC server */ |
if (rdbgInit() != 0) goto error; |
|
Continue = 1; |
justSaveContext = 0; |
currentTargetThread = 0; |
|
task_name = rtems_build_name( 'R', 'D', 'B', 'G' ); |
if ((status = rtems_task_create( task_name, 5, 24576, |
RTEMS_INTERRUPT_LEVEL(0), |
RTEMS_DEFAULT_ATTRIBUTES | RTEMS_SYSTEM_TASK |
, &tid )) |
!= RTEMS_SUCCESSFUL){ |
printf("status = %d\n",status); |
rtems_panic ("Can't create task.\n"); |
} |
|
status = rtems_task_start(tid, rdbgDaemon, 0); |
|
return; |
|
error: |
printf ("initialization failed.\n"); |
} |
|
void |
setErrno (int error) |
{ |
errno = error; |
} |
|
int |
getErrno() |
{ |
return errno; |
} |
/servtgt.c
0,0 → 1,552
/* |
************************************************************************** |
* |
* Component: RDB servers |
* Module: servtgt.c |
* |
* $Id: servtgt.c,v 1.2 2001-09-27 12:02:01 chris Exp $ |
* |
************************************************************************** |
*/ |
|
|
#include <string.h> |
#include <sys/errno.h> |
#include <rdbg/rdbg.h> |
#include <rdbg/servrpc.h> |
#include <sys/socket.h> |
#include <assert.h> |
|
#ifdef DDEBUG |
#define Ptrace TgtDbgPtrace |
#else |
#define Ptrace TgtRealPtrace |
#endif |
|
/* ---------------------------------------------------------------- |
TgtBreakRestoreOrig - Restore original instruction at "addr" |
just before single-stepping it. |
---------------------------------------------------------------- */ |
|
int TgtBreakRestoreOrig (int pid, void *addr, void *addr2) |
/* Process identifier */ |
/* Breakpoint address */ |
/* Original instruction or bkpt number */ |
{ |
int ret; |
int l; |
|
l = (long)Ptrace(RPT_PEEKTEXT, pid, addr, 0, NULL); /* assume ok */ |
ret = ORG_BREAK (l, (UINT32) addr2); /* reconstruct old instr */ |
ret = Ptrace(RPT_POKETEXT, pid, addr, ret, NULL); /* poke back old */ |
return ret; |
} |
|
/* ----------------------------------------------------------------------- |
TgtBreakCancelStep - Restore the breakpoint at "addr" if the single-step |
has failed at the ptrace level. |
----------------------------------------------------------------------- */ |
|
#define BKPT0(plst) ((BASE_BREAK*)(plst)->break_list) |
|
void TgtBreakCancelStep (PID_LIST* plst) |
{ |
assert (plst->break_list); |
assert (BKPT0 (plst)->clr_step); |
|
if (plst->break_list && BKPT0 (plst)->clr_step) { |
int idx = BKPT0 (plst)->last_break; |
int data; |
|
data = Ptrace (RPT_PEEKTEXT, plst->pid, |
(char *)plst->break_list [idx].ee_loc, 0, NULL); |
assert (! IS_BREAK (data)); |
Ptrace (RPT_POKETEXT, plst->pid, |
(char *)plst->break_list[idx].ee_loc, |
(int) SET_BREAK (data), NULL); |
} |
} |
|
/* ----------------------------------------------------------------------- |
TgtCreateNew - add a new process into the process management lists. |
----------------------------------------------------------------------- */ |
|
void |
TgtCreateNew(PID pid, int conn, INT32 child, char *name, Boolean spawn) |
{ |
int idx; |
|
for (idx = 0; idx < pid_list_cnt; idx++) |
if (!pid_list[idx].pid) |
break; /* find empty */ |
|
if (idx >= pid_list_cnt) |
{ /* no empties, add more */ |
PID_LIST *tmp_pid_list = pid_list; |
|
pid_list_cnt += PID_LIST_INC; |
pid_list = (PID_LIST*) Realloc(pid_list, /* get new or extend */ |
pid_list_cnt * sizeof(PID_LIST)); |
if (!pid_list) |
{ /* out of memory */ |
pid_list_cnt -= PID_LIST_INC; |
if (pid_list_cnt) |
{ /* realloc failed - malloc again */ |
pid_list = tmp_pid_list; |
/* above relies on old pointer being valid after failed realloc */ |
} |
return; /* failed */ |
} |
/* now clear newly added space */ |
memset(pid_list+pid_list_cnt-PID_LIST_INC, 0, |
PID_LIST_INC * sizeof(PID_LIST)); |
idx = pid_list_cnt - PID_LIST_INC; |
} |
else /* clear entry we found */ |
memset(&pid_list[idx], 0, sizeof(PID_LIST)); |
|
/* now fill in empty entry */ |
pid_list[idx].pid = pid; |
pid_list[idx].running = 1; /* we have not called wait yet */ |
pid_list[idx].primary_conn = (UCHAR)conn; /* primary owner */ |
if (conn != -1) |
{ /* found caller */ |
pid_list[idx].owners = 1; |
PIDMAP_SET (conn, idx); /* mask in */ |
} |
pid_list[idx].thread = (UINT32)-1; /* no thread for now */ |
pid_list[idx].last_start = LAST_START; /* handle MiX bug */ |
|
pid_list[idx].name = name ? (char *)StrDup(name) : (char *)NULL; |
|
} |
|
/* ----------------------------------------------------------------------- |
TgtNotifyWaitChange - send event to clients indicating child changed state. |
----------------------------------------------------------------------- */ |
|
void |
TgtNotifyWaitChange( PID pid, int status, Boolean exclude) |
{ |
int conn, idx; |
|
idx = FindPidEntry (pid); /* locate the pid that changed */ |
if (idx < 0) |
{ |
DPRINTF(("TgtNotifyWaitChange: pid %d not in our list\n", |
(int) pid)); |
return; /* not in our list */ |
} |
pid_list[idx].running = 0; /* not running */ |
pid_list[idx].state = status; /* save status of stop/term */ |
if (!pid_list[idx].owners && !STS_SIGNALLED(status)) |
TgtDelete(&pid_list[idx], -1, 0); /* terminated and no owners */ |
else |
{ /* normal cases */ |
for (conn = 0; conn < conn_list_cnt; conn++) |
{ /* now find all interested clients */ |
if (!conn_list[conn].in_use /* free entry */ |
|| ! PIDMAP_TEST (conn, idx)) |
continue; /* not using this pid */ |
if (conn == exclude) |
continue; /* do not do this one */ |
TspSendWaitChange(conn, BMSG_WAIT, 1, pid, 0, False);/* notify of change */ |
} |
} |
} |
|
/* ----------------------------------------------------------------------- |
TgtNotifyAll - send a message to all clients interested in process. |
----------------------------------------------------------------------- */ |
|
void |
TgtNotifyAll( int pid_idx, BACK_MSG msg, UINT16 spec, |
UINT32 context, int exclude, Boolean force) |
{ |
int conn; |
|
DPRINTF(("TgtNotifyAll: msg %d (%s) for pid_idx=%d (%d,%d)\n", |
msg, BmsgNames [msg], pid_idx, exclude, force)); |
for (conn = 0; conn < conn_list_cnt; conn++) |
if (conn_list[conn].in_use /* not free */ |
&& PIDMAP_TEST (conn, pid_idx)) |
{ |
if (conn != exclude) |
TspSendWaitChange(conn, msg, spec, pid_list[pid_idx].pid, context, |
force); |
} |
} |
|
/* ----------------------------------------------------------------------- |
TgtDelete - mark process as now uncontrolled. |
|
Notes: |
- this function removes a process from the process list. |
- the notify argument indicates a message to send if needed. |
----------------------------------------------------------------------- */ |
|
void TgtDelete(PID_LIST *plst, int conn_idx, BACK_MSG notify) |
{ |
int idx = plst - pid_list, cnt, conn; |
|
/* found */ |
cnt = pid_list[idx].owners; |
if (cnt) |
{ /* some connections to break */ |
for (conn = 0; cnt && conn < conn_list_cnt; conn++) |
if (conn_list[conn].in_use /* not free */ |
&& PIDMAP_TEST (conn, idx)) |
{ /* found one that uses it */ |
PIDMAP_CLEAR (conn, idx); |
if (notify && conn != conn_idx) |
TspSendWaitChange(conn, notify, 0, plst->pid, 0, True); |
if (!--cnt) |
break; |
} |
} |
if (pid_list[idx].name) |
Free(pid_list[idx].name); /* free string name back */ |
/* Free breakpoint list */ |
if (pid_list [idx].break_list != NULL) { |
Free (pid_list [idx].break_list); |
} |
pid_list[idx].pid = 0; /* gone */ |
} |
|
|
/* ----------------------------------------------------------------------- |
TgtKillAndDelete - kill or detach process and remove entry. |
----------------------------------------------------------------------- */ |
|
int |
TgtKillAndDelete( PID_LIST *plst, struct svc_req *rqstp, Boolean term) |
{ |
ptrace_in pin; /* used for ptrace call */ |
ptrace_out *pout; |
|
/* Remove breakpoints */ |
if (plst->break_alloc > 0) { |
pin.pid = plst->pid; |
pin.addr.req = RPT_CLRBREAK; |
pin.data = 0; /* clear all */ |
pin.flags = PTRFLG_NON_OWNER; |
pout = RPCGENSRVNAME(ptrace_2_svc) (&pin, rqstp); |
if (pout->result < 0) { |
DPRINTF (("TgtKillAndDelete: RPT_CLRBREAK failed %d\n", |
getErrno())); |
return -1; |
} |
} |
|
if (term) |
{ /* kill */ |
pin.addr.ptrace_addr_data_in_u.address = 0; |
pin.data = -1; /* Don't want notification from slave */ |
pin.addr.req = RPT_KILL; |
} |
else |
{ /* detach */ |
pin.addr.ptrace_addr_data_in_u.address = 1; |
pin.data = 0; |
pin.addr.req = RPT_DETACH; |
} |
pin.pid = plst->pid; |
pin.flags = PTRFLG_FREE | PTRFLG_NON_OWNER; |
|
DPRINTF (("TgtKillAndDelete: ptrace_2_svc (%s (%d), %d)\n", |
PtraceName (pin.addr.req), pin.addr.req, pin.pid)); |
|
pout = RPCGENSRVNAME(ptrace_2_svc) (&pin, rqstp);/* start it */ |
if (pout->errNo == ESRCH && plst->pid) |
TgtDelete(plst, -1, BMSG_KILLED); /* only entry remains */ |
return 0; |
} |
|
/* ----------------------------------------------------------------------- |
TgtDetachCon - detach a connection's ownership of a process. |
----------------------------------------------------------------------- */ |
|
void |
TgtDetachCon( int conn_idx, int pid_idx, Boolean delete) |
{ |
if ((unsigned) pid_idx >= pid_list_cnt |
|| !pid_list[pid_idx].pid) |
return; /* not valid */ |
if (PIDMAP_TEST (conn_idx, pid_idx)) |
{ /* if an owner, release control */ |
PIDMAP_CLEAR (conn_idx, pid_idx); |
|
if (pid_list[pid_idx].owners) |
pid_list[pid_idx].owners--; |
if (pid_list[pid_idx].primary_conn == conn_idx) |
pid_list[pid_idx].primary_conn = NO_PRIMARY; |
if (delete |
&& !pid_list[pid_idx].owners |
&& PROC_TERMINATED (pid_list + pid_idx)) |
TgtDelete(&pid_list[pid_idx], -1, 0); /* remove entry */ |
} |
} |
|
/* ----------------------------------------------------------------------- |
TgtHandleChildChange - decide what action to take after wait() returns. |
Used in the master only. |
----------------------------------------------------------------------- */ |
|
#ifdef DDEBUG |
static char* LastStartNames[] = { |
"NONE", "STEP", "CONT", "RANGE", |
"STEPOFF", "KILLED", "DETACHED" |
}; |
|
char* GetLastStartName (int last_start) |
{ |
static char buf [32]; |
|
strcpy (buf, LastStartNames [last_start & ~LAST_START]); |
if (last_start & LAST_START) { |
strcat (buf, "+START"); |
} |
return buf; |
} |
#endif |
|
Boolean TgtHandleChildChange(PID pid, int* status, int *unexp, |
CPU_Exception_frame* ctx) |
{ /* return False if continue, else stop */ |
int idx, sig; |
int bidx = 0; |
PID_LIST *plst; |
unsigned long PC; |
BASE_BREAK *base = NULL; /* break_list[0] is really BASE_BREAK */ |
int hadStepEmul; |
int origHadStepEmul; |
int stopWanted; |
|
DPRINTF (("TgtHandleChildChange: pid %d status %x cap\n", |
(int) pid, *status)); |
if (unexp) |
*unexp = 0; /* initialize to ok */ |
|
/* first, find pid in question */ |
idx = FindPidEntry (pid); |
if (idx < 0) |
{ /* cannot locate this process */ |
DPRINTF (("TgtHandleChildChange: unknown process (%s pid)\n", |
FindPidEntry (pid) >= 0 ? "stale" : "unknown")); |
if (unexp) |
*unexp = 1; /* Unexpected change */ |
return(False); /* unknown: ignore (used to stop and notify) */ |
} |
|
/* found */ |
plst = &pid_list[idx]; /* pointer to entry */ |
/* first we see if just stopped */ |
|
/* copy ctxt */ |
CtxToRegs(ctx, &(plst->regs)); |
|
stopWanted = plst->stop_wanted; |
plst->stop_wanted = 0; /* For the next time */ |
|
hadStepEmul = BreakClear (plst, -1, -1) > 0; |
origHadStepEmul = hadStepEmul; /* hadStepEmul is cleared if real bkpt met */ |
|
if (STS_SIGNALLED (*status)) |
{ /* stopped, not terminated */ |
sig = STS_GETSIG (*status); /* signal that stopped us */ |
|
/* now, we read the registers and see what to do next */ |
if (TgtPtrace(RPT_GETREGS, pid, (void *)&plst->regs, 0, NULL) < 0) { |
memset (&plst->regs, 0, sizeof plst->regs); |
} |
|
/* Get current thread */ |
plst->thread = TgtPtrace(RPT_GETTARGETTHREAD, pid, NULL, 0, NULL); |
|
if (sig == SIGTRAP) |
{ /* stopped from break/step */ |
PC = plst->regs.REG_PC; |
/* Must check PC to see whether in situations where we had |
step emulation we are on a breakpoint or just |
have returned from an emulated single-step */ |
if (BreakIdentify (plst, 0 /*no adjust*/, -1 /*no thread*/) > 0) { |
hadStepEmul = 0; |
} |
plst->is_step = hadStepEmul || IS_STEP(plst->regs) |
|| plst->last_start == LAST_START; |
DPRINTF (("TgtHandleChildChange: %s last_start %s\n", plst->is_step |
? "step": "break", GetLastStartName (plst->last_start))); |
|
if ((plst->is_step || origHadStepEmul || stopWanted) |
&& (plst->last_start == LAST_STEP |
|| plst->last_start == LAST_STEPOFF |
|| plst->last_start == LAST_RANGE)) |
{ |
DPRINTF (("TgtHandleChildChange: restoring stepped-off bkpt\n")); |
BreakSteppedOff (plst); |
} |
|
if (plst->last_start == LAST_STEPOFF && (plst->is_step||origHadStepEmul)) |
{ /* stepped off break and now need cont */ |
DPRINTF (("TgtHandleChildChange: auto-resuming after step-off\n")); |
plst->last_start = LAST_CONT; /* convert to normal cont */ |
if (!stopWanted) { |
if (TgtPtrace(RPT_CONT, pid, (char *)1, 0, NULL)) |
return True; /* tell people */ |
return(False); /* wait for change */ |
} |
DPRINTF (("TgtHandleChildChange: stop_wanted %d in step-off\n", |
stopWanted)); |
*status = STS_MAKESIG (stopWanted); |
return True; /* Stop and notify */ |
} |
|
base = plst->break_list ? ((BASE_BREAK*)plst->break_list) : |
((BASE_BREAK*)NULL); |
/* now see if step in range */ |
|
if (plst->last_start == LAST_RANGE /* step in range */ |
&& (plst->is_step || origHadStepEmul) /* not a breakpoint */ |
&& PC >= base->range_start |
&& PC <= base->range_end) |
{ /* still in range, keep going */ |
if (stopWanted) { |
DPRINTF (("TgtHandleChildChange: stop_wanted %d in step-range\n", |
stopWanted)); |
} else { |
DPRINTF (("TgtHandleChildChange: Reservation at %x\n", |
plst->regs.REG_PC)); |
} |
} |
if (!plst->is_step) /* was break */ |
{ |
bidx = BreakIdentify (plst, 1 /*adjust*/, plst->thread); |
if (bidx == 0) { |
DPRINTF (("TgtHandleChildChange: forwarding bkpt to kernel\n")); |
if (unexp) { |
*unexp = 1; |
} |
return False; |
} |
if (bidx < 0) { /* Unwanted breakpoint, must step it off */ |
ptrace_in pin; |
ptrace_out* out; |
if (origHadStepEmul) |
{ |
DPRINTF (("TgtHandleChildChange: bkpt %x becomes step\n", |
plst->regs.REG_PC)); |
bidx = -bidx; |
plst->is_step = 1; |
base->clr_step = plst->break_list [bidx].type == BRKT_INSTR; |
base->last_break = bidx; |
return True; |
} |
if (stopWanted) { |
DPRINTF (("TgtHandleChildChange: stop_wanted %d at bkpt %x\n", |
stopWanted, plst->regs.REG_PC)); |
/* The PC has already been adjusted by BreakIdentify */ |
*status = STS_MAKESIG (stopWanted); |
return True; |
} |
/* All the handling is done in ptrace_2_svc() so call it */ |
bidx = -bidx; |
DPRINTF (("TgtHandleChildChange: last %d (%s) restarting bkpt %d\n", |
plst->last_start, GetLastStartName (plst->last_start), bidx)); |
base->clr_step = 1; |
base->last_break = bidx; /* remember which one */ |
plst->running = 0; /* So that ptrace is accepted */ |
pin.pid = plst->pid; |
|
if (plst->last_start == LAST_STEP) { |
pin.addr.req = RPT_SINGLESTEP; |
} else { |
pin.addr.req = RPT_CONT; |
} |
pin.addr.ptrace_addr_data_in_u.address = 1; |
pin.data = 0; |
pin.flags = PTRFLG_NON_OWNER; |
out = RPCGENSRVNAME(ptrace_2_svc) (&pin, NULL); |
if (out->result == 0) return False; /* Continue waiting */ |
DPRINTF(("TgtHandleChildChange: failed to restart bkpt!\n")); |
/* If something went wrong, just stop on breakpoint */ |
} |
} |
} /* else sig != SIGTRAP */ |
|
/* finally, fill in stop info in break point array base */ |
if (bidx > 0) |
{ /* store break info */ |
/* will need to get off the break for SW breakpoints only */ |
base->clr_step = plst->break_list [bidx].type == BRKT_INSTR; |
base->last_break = bidx; /* remember which one */ |
} |
else if (base) |
{ /* clear break info */ |
base->clr_step = False; /* not stopped on break */ |
base->last_break = 0; |
} |
/* decision to notify owner based on last_start */ |
} /* stopped */ |
else /* terminated */ |
{ |
if (plst->last_start == LAST_START) |
{ /* spawn failed */ |
TgtNotifyAll(idx, BMSG_EXEC_FAIL, 0, 0, -1, True); |
plst->running = False; /* not running - dead */ |
plst->state = *status; /* contains errno in high word */ |
return(False); |
} |
|
else if ((UCHAR)(plst->last_start & ~LAST_START) < (UCHAR)LAST_KILLED) |
plst->last_start = LAST_NONE; /* doesn't matter anymore */ |
else |
return(False); /* killed and detach already notified */ |
} |
return(True); /* stop and notify */ |
} |
|
#ifdef DDEBUG |
|
/* ----------------------------------------------------------------------- |
TgtDbgPtrace - debug version of ptrace. |
----------------------------------------------------------------------- */ |
|
int TgtDbgPtrace(int request, PID pid, char *addr, int data, void *addr2) |
{ |
int diag; |
|
DPRINTF (("TgtDbgPtrace: entered (%s (%d), %d, %x, %d, %x)\n", |
PtraceName (request), request, pid, (int) addr, data, |
(int) addr2)); |
|
if (request == RPT_WRITETEXT || request == RPT_WRITEDATA) { |
int i; |
|
DPRINTF (("TgtDbgPtrace:")); |
if (rdb_debug) { |
for (i = 0; i < data && i < 16; ++i) { |
printf (" %02x", ((char*) addr2) [i] & 0xFF); |
} |
printf ("\n"); |
} |
} |
|
diag = TgtRealPtrace (request, pid, addr, data, addr2); |
|
DPRINTF (("TgtDbgPtrace: returned %d (%x) errno %d\n", |
diag, diag, getErrno())); |
|
if (request == RPT_GETREGS || request == RPT_GETTHREADREGS |
|| request == RPT_SETREGS || request == RPT_SETTHREADREGS) |
{ |
/* Use DPRINTF() so as to have the id prefix */ |
DPRINTF (("TgtDbgPtrace: (%s) PC = %x, SP = %x, FP = %x\n", |
PtraceName (request), |
((xdr_regs*)addr)->REG_PC, |
((xdr_regs*)addr)->REG_SP, |
((xdr_regs*)addr)->REG_FP)); |
} |
|
return(diag); |
} |
#endif /* DDEBUG */ |
/servcon.c
0,0 → 1,138
/* |
************************************************************************** |
* |
* Component: RDBG |
* Module: servcon.c |
* |
* Synopsis: Management of RPC client connections. |
* |
* $Id: servcon.c,v 1.2 2001-09-27 12:02:01 chris Exp $ |
* |
************************************************************************** |
*/ |
|
#include <sys/errno.h> |
#include <rdbg/rdbg.h> |
#include <rdbg/servrpc.h> |
|
/* |
* ConnCreate - create a new connection entry for a client. |
* |
* This function finds an empty entry in the connection array |
* or makes space. It fills in the fields that are passed to it. |
* It does not do any validation on net addresses nor does it |
* start a validation cycle on other clients. This is done by |
* the caller. |
*/ |
|
int |
ConnCreate (struct svc_req* rqstp, open_in* in) |
{ |
NET_OPAQUE sender; |
int idx; |
CONN_LIST* clst; |
|
setErrno (0); |
|
/* Convert to valid Net address */ |
if (! TspTranslateRpcAddr (rqstp, &sender)) { |
DPRINTF (("ConnCreate: TspTranslateRpcAddr failed\n")); |
return -1; |
} |
if (! TspValidateAddr ((NET_OPAQUE*) in->back_port, &sender)) { |
DPRINTF (("ConnCreate: TspValidateAddr failed\n")); |
return -1; /* errno now setup with error */ |
} |
|
/* look for an empty connection entry */ |
for (idx = 0; idx < conn_list_cnt; idx++) { |
if (!conn_list[idx].in_use) |
break; /* an empty one found */ |
} |
|
if (idx >= conn_list_cnt) { /* no empties, create space */ |
CONN_LIST* tmp_conn_list = conn_list; |
|
conn_list_cnt += CONN_LIST_INC; |
if (conn_list) { |
conn_list = (CONN_LIST *) Realloc (conn_list, /* extend */ |
conn_list_cnt * sizeof (CONN_LIST)); |
} else { |
conn_list = (CONN_LIST *)Malloc(conn_list_cnt * sizeof(CONN_LIST)); |
} |
|
if (!conn_list) { /* unable to get space */ |
if ((conn_list_cnt -= CONN_LIST_INC)) { |
/* was realloc, restore space */ |
conn_list = tmp_conn_list; |
} |
return -1; /* errno set by failed alloc */ |
} |
/* clear newly created memory */ |
memset (conn_list + idx, 0, CONN_LIST_INC * sizeof (CONN_LIST)); |
} else { /* clear new entry */ |
memset (conn_list + idx, 0, sizeof (CONN_LIST)); |
} |
clst = conn_list + idx; |
|
clst->in_use = True; /* now in use */ |
clst->sender = sender; |
memcpy (&clst->back_port, &in->back_port, sizeof (NET_OPAQUE)); |
memcpy (&clst->route, &in->destination, sizeof (NET_OPAQUE)); |
clst->debug_type = (UCHAR) in->debug_type; |
clst->flags = in->flags; |
strncpy (clst->user_name, in->user_name, NAMEMAX-1); |
clst->user_name [NAMEMAX-1] = 0; |
|
return idx; |
} |
|
/* |
* ConnDelete - remove connection entry when shutdown. |
* |
*/ |
|
void |
ConnDelete (int conn, struct svc_req* rqstp, close_control control) |
{ |
CONN_LIST* clst = conn_list + conn; |
int idx; |
Boolean prim; |
|
if (! clst->in_use) return; /* not active */ |
|
for (idx = 0; idx < pid_list_cnt; idx++) { |
PID_LIST* plst = pid_list + idx; |
|
if (! PIDMAP_TEST (conn, idx)) continue; |
|
/* found a controlled pid */ |
prim = (plst->primary_conn == conn) ? True : False; |
TgtDetachCon (conn, idx, True); |
|
/* if still running or alive, we use close control on it */ |
if (! plst->pid) |
continue; /* entry gone */ |
|
if (prim && control == CLOSE_KILL) { |
/* kill off process */ |
TgtKillAndDelete (plst, rqstp, True); |
} else if (! plst->owners) { |
/* no owners left */ |
if (control == CLOSE_DETACH) { |
TgtKillAndDelete (plst, rqstp, False); |
} |
if (control == CLOSE_DETACH || PROC_TERMINATED (plst)) { |
TgtDelete (plst, conn, (control==CLOSE_DETACH) ? |
BMSG_DETACH : 0); |
} |
} |
} |
if (clst->list) { |
Free (clst->list); /* free allocated memory */ |
} |
DPRINTF (("ConnDelete: Connection closed for port %u\n", |
HL_W(*((UINT16*) &clst->back_port.c[2])))); |
|
clst->in_use = False; /* free it back */ |
} |
/servbkpt.c
0,0 → 1,589
/* |
********************************************************************** |
* |
* Component: RDB servers |
* Module: servbkpt.c |
* |
* Synopsis: Management of breakpoints |
* |
* $Id: servbkpt.c,v 1.2 2001-09-27 12:02:01 chris Exp $ |
* |
********************************************************************** |
*/ |
|
#include <sys/errno.h> |
#include <assert.h> |
#include <rdbg/rdbg.h> |
#include <rdbg/servrpc.h> |
|
/*----- Macros -----*/ |
|
#define BKPT0(plst) ((BASE_BREAK*)(plst)->break_list) |
#define BKPT_INCR 5 /* how many bkpt slots alloc at a time */ |
|
#define BKPT_OVER(plst,idx,addr,size) \ |
((plst)->break_list[idx].ee_loc + BREAK_SIZE > (UINT32) (addr) \ |
&& (plst)->break_list[idx].ee_loc < (UINT32) (addr) + (size)) |
|
#define BKPT_SLOTS \ |
(sizeof ((xdr_break*) 0)->thread_list / \ |
sizeof ((xdr_break*) 0)->thread_list [0]) |
|
|
/* |
* BreakAlloc - alloc a breakpoint entry. |
* |
* This is a generic routine to insert an entry in the |
* breakpoint list. It returns the number of entry just |
* created. It returns -1 if failed. |
*/ |
|
static int |
BreakAlloc (PID_LIST* plst, Boolean normal) |
{ |
int idx, len; |
xdr_break* blst; |
|
if (!normal) { /* want 0 entry */ |
if (plst->break_list) { |
return(0); /* already there */ |
} |
idx = 1; /* force alloc below */ |
} else { |
for (idx = 1; idx < (int)plst->break_alloc; idx++) { |
if (plst->break_list[idx].type == BRKT_NONE) { |
/* got a free one */ |
memset(&plst->break_list[idx], 0, sizeof(xdr_break)); |
return(idx); /* found one */ |
} |
} |
} |
/* idx is the requested entry */ |
|
if (idx >= (int)plst->break_alloc) { /* need more space */ |
len = plst->break_alloc + BKPT_INCR; |
blst = (xdr_break*)Realloc(plst->break_list, len*sizeof(xdr_break)); |
if (!blst) { |
return(-1); /* failed, no space */ |
} |
plst->break_alloc = len; /* got more */ |
plst->break_list = blst; |
|
/* Clear new space */ |
memset(blst + len - BKPT_INCR, 0, BKPT_INCR * sizeof(xdr_break)); |
idx = len - BKPT_INCR; /* next available */ |
if (!idx) { |
idx = 1; /* for normal cases */ |
} |
} |
return(normal ? idx : 0); /* return it */ |
} |
|
/* |
* BreakSet - set a breakpoint in process |
* |
* Returns the number or -1/errno. |
*/ |
|
#ifdef DDEBUG |
static const char* BreakTypes[] = { |
"NONE", "INSTR", "READ", "WRITE", |
"ACCESS", "EXEC", "OS_CALL", "OS_SWITCH", |
"STEPEMUL" |
}; |
|
#define BN_MAX (sizeof BreakTypes / sizeof BreakTypes[0]) |
#define BREAK_NAME(t) ((unsigned) (t) < BN_MAX ? BreakTypes[t] : "???") |
#endif |
|
int |
BreakSet (PID_LIST* plst, int conn_idx, xdr_break* bkpt) |
{ |
int pid = plst->pid; |
int type = bkpt->type; |
void* addr = (void *) bkpt->ee_loc; |
int idx; |
int data; |
|
DPRINTF(("BreakSet: type %d (%s) at 0x%x th %d ee_type %d len %d " |
"pass %d curr %d list %d %d %d %d\n", type, BREAK_NAME(type), |
(int) addr, |
bkpt->thread_spec, bkpt->ee_type, bkpt->length, bkpt->pass_count, |
bkpt->curr_pass, bkpt->thread_list [0], bkpt->thread_list [1], |
bkpt->thread_list [2], bkpt->thread_list [3])); |
|
idx = BreakAlloc(plst, True); /* get entry */ |
if (idx < 0) { /* no memory */ |
setErrno(ENOMEM); /* set for safety */ |
return -1; /* return the error */ |
} |
|
data = TgtPtrace(RPT_PEEKTEXT, pid, addr, 0, NULL); /* current */ |
if (getErrno()) { |
return -1; /* failed, return the error */ |
} |
if (IS_BREAK(data)) { /* There is already a break here */ |
DPRINTF(("BreakSet: already have soft bkpt at %x\n", addr)); |
if (type == BRKT_STEPEMUL) { |
++BKPT0 (plst)->pad1; |
return 1; /* Any non-error value is OK */ |
} |
setErrno(EBUSY); |
return -1; |
} |
|
TgtPtrace(RPT_POKETEXT, pid, addr, SET_BREAK(data), NULL); |
|
if (getErrno()) { |
return -1; |
} |
|
plst->break_list[idx] = *bkpt; |
plst->break_list[idx].ee_type = data; /* saved data */ |
|
/* Inform other owners */ |
if (type != BRKT_STEPEMUL) { |
TgtNotifyAll (plst - pid_list, BMSG_BREAK, 1 /*added*/, idx, |
conn_idx, False); |
} else { |
++BKPT0 (plst)->pad1; |
} |
/* Return the number */ |
setErrno(0); /* Just in case */ |
return idx; |
} |
|
int |
BreakSetAt (PID_LIST* plst, int conn_idx, unsigned long addr, break_type type) |
{ |
xdr_break xb; |
|
memset (&xb, 0, sizeof xb); |
xb.type = type; |
xb.ee_loc = addr; |
return BreakSet (plst, conn_idx, &xb); |
} |
|
/*----- Find a breakpoint by address -----*/ |
|
int |
BreakGetIndex(PID_LIST* plst, void* addr) |
{ |
int idx; |
int data = -1; |
|
if (!plst->break_alloc) { |
setErrno(EFAULT); |
return -1; |
} |
for (idx = 1; idx < (int)plst->break_alloc; idx++) { |
if ((u_long) addr == plst->break_list [idx].ee_loc) { |
data = idx; |
break; |
} |
} |
return data; |
} |
|
/*----- Getting information about breakpoint -----*/ |
|
/* |
* If data > 0, fill "bkpt" with information about breakpoint |
* and return the number of the next one. |
* If data == 0, return the count of breakpoints. |
*/ |
|
int |
BreakGet (const PID_LIST* plst, int data, xdr_break* bkpt) |
{ |
int idx; |
|
if (!data) { /* just count them */ |
for (idx = 1; idx < (int)plst->break_alloc; idx++) { |
if (plst->break_list[idx].type != BRKT_NONE) { |
data++; |
} |
} |
return data; /* count */ |
} |
if ((unsigned) data >= plst->break_alloc) { |
/* out of range */ |
setErrno(EFAULT); /* closest match */ |
return -1; |
} |
/* get it and say which is next */ |
*bkpt = plst->break_list[data]; |
for (idx = (int)data+1; idx < (int)plst->break_alloc; idx++) { |
if (plst->break_list[idx].type != BRKT_NONE) { |
return idx; |
} |
} |
return 0; /* otherwise returns 0 for no more */ |
} |
|
/*----- Clearing bkpts -----*/ |
|
/* |
* BreakClear - clear one (if data != 0) or all breakpoints |
* (if data == 0). Return the number of bkpts cleared. |
* If (data == -1), remove step-emulation breakpoints. |
*/ |
|
int |
BreakClear (PID_LIST* plst, int conn_idx, int data) |
{ |
int pid_idx = plst - pid_list; |
int idx; |
int cleared = 0; |
int clearStepEmul = 0; |
int terminated = PROC_TERMINATED (plst); |
int stepEmulCount = 0; |
|
/* break handle in data */ |
if (!plst->break_alloc) { /* there are no breaks */ |
DPRINTF (("BreakClear: no bkpts defined.\n")); |
setErrno(EFAULT); /* closest match */ |
return -1; /* return error */ |
} |
if (!data) { /* clear all */ |
idx = 1; |
data = plst->break_alloc-1; |
|
/* Inform other owners */ |
DPRINTF (("BreakClear: clearing all bkpts.\n")); |
TgtNotifyAll (pid_idx, BMSG_BREAK, 0 /*clr*/, 0, conn_idx, False); |
|
} else if (data == -1) { /* clear all step-emul bkpts */ |
DPRINTF(("BreakClear: removing %d step-emul bkpts\n", |
BKPT0 (plst)->pad1)); |
|
stepEmulCount = BKPT0 (plst)->pad1; |
BKPT0 (plst)->pad1 = 0; |
|
clearStepEmul = 1; |
idx = 1; |
data = plst->break_alloc-1; |
} else if ((unsigned) data >= plst->break_alloc |
|| plst->break_list[data].type == BRKT_NONE) { |
|
/* out of range */ |
DPRINTF (("BreakClear: invalid bkpt %d\n", data)); |
setErrno(EFAULT); /* closest match */ |
return -1; /* return error */ |
} else { |
idx = data; |
/* Inform other owners */ |
TgtNotifyAll (pid_idx, BMSG_BREAK, 0 /*clr*/, idx, conn_idx, False); |
DPRINTF (("BreakClear: clearing bkpt %d\n", data)); |
} |
|
for (; idx <= data; idx++) { /* clear each one */ |
int type = plst->break_list[idx].type; |
|
if (clearStepEmul && type != BRKT_STEPEMUL) continue; |
|
if (type == BRKT_INSTR || (clearStepEmul && type == BRKT_STEPEMUL)) { |
/* just patch back */ |
char* addr = (char *)plst->break_list[idx].ee_loc; |
int val; |
|
if (BKPT0 (plst)->clr_step && BKPT0 (plst)->last_break == idx) { |
BKPT0 (plst)->clr_step = 0; /* not needed */ |
} |
/* Neighboring bytes can have breakpoints too... */ |
if (! terminated) { |
setErrno (0); |
val = TgtPtrace(RPT_PEEKTEXT, plst->pid, addr, 0, NULL); |
if (getErrno()) { |
DPRINTF (("BreakClear: addr %x not readable!\n", addr)); |
setErrno (0); /* Forget bkpt */ |
} else { |
assert (IS_BREAK (val)); |
val = ORG_BREAK (val, (int)plst->break_list[idx].ee_type); |
TgtPtrace(RPT_POKETEXT, plst->pid, addr, val, NULL); |
if (getErrno()) { |
DPRINTF (("BreakClear: addr %x not writable!\n", addr)); |
setErrno (0); |
} |
} |
} |
++cleared; /* indicate cleared */ |
} |
memset(&plst->break_list[idx], 0, sizeof(xdr_break)); |
} |
assert (!clearStepEmul || cleared <= stepEmulCount); |
if (stepEmulCount && cleared == 0) { |
DPRINTF (("BreakClear: all STEPEMUL bkpts were shared\n")); |
return 1; |
} |
return cleared; |
} |
|
/*----- Hiding of breakpoints -----*/ |
|
/* |
* PatchBreak - patch original data from break into data buffer. |
* |
* Notes: |
* - this routine patches the original data under a break into the data |
* buffer from a ptrace read/peek. |
*/ |
|
static void |
PatchBreak (char* buff, UINT32 bstart, int bsize, UINT32 dstart, char* dvalue) |
{ |
int size = BREAK_SIZE; /* default size */ |
|
/* Must deal with all sorts of unalignments |
* (3 full overlaps, 3 unaligns) |
*/ |
if (bsize < BREAK_SIZE) { |
/* case where buffer is smaller than data */ |
memcpy(buff, dvalue+(bstart-dstart), bsize); /* copy over */ |
return; |
} |
/* buffer larger than data. |
* we need to see where break fits in buffer and whether |
* we have part of it off the end. We set bstart to be the |
* buffer offset, dtart to be the break data offset, and |
* size to be the amount to copy |
*/ |
if (dstart < bstart) { |
/* break before actual buffer */ |
dstart = bstart-dstart; /* offset in data */ |
size -= dstart; /* amount to copy */ |
bstart = 0; /* offset in buffer */ |
|
} else if (dstart + size > bstart + bsize) { |
/* off end */ |
bstart += bsize; /* end of buffer */ |
size -= (dstart + size) - bstart; |
bstart = bsize - size; /* come back into buffer enough */ |
dstart = 0; /* start of data */ |
|
} else { /* normal case */ |
bstart = dstart - bstart; /* offset in buffer */ |
dstart = 0; |
} |
memcpy(buff+bstart, dvalue+dstart, size); |
} |
|
void |
BreakHide (const PID_LIST* plst, void* addr, int data, void* addr2) |
{ |
int idx; |
|
if (!plst->break_list) /* no breaks exist, so skip this */ |
return; |
|
/* if breakpoints, replace */ |
|
for (idx = 1; idx < (int)plst->break_alloc; idx++) { |
int type = plst->break_list[idx].type; |
|
if (type != BRKT_INSTR && type != BRKT_STEPEMUL) { |
continue; |
} |
/* break, see if overlaps */ |
if (BKPT_OVER (plst, idx, addr, data)) { |
|
/* overlaps, patch in old value */ |
PatchBreak((char *)addr2, (UINT32)addr, data, |
plst->break_list[idx].ee_loc, |
(char *)&plst->break_list[idx].ee_type); |
} |
} |
} |
|
/*----- Checking of breakpoint overwrites -----*/ |
|
/* |
* BreakOverwrite - check if memory write does not involve addresses |
* having software breakpoints. |
*/ |
|
int |
BreakOverwrite (const PID_LIST* plst, const char* addr, unsigned int size) |
{ |
int idx; |
|
if (!plst->break_list) { /* No breaks exist */ |
return 0; |
} |
|
for (idx = 1; idx < (int)plst->break_alloc; idx++) { |
int type = plst->break_list[idx].type; |
|
/* Consider only breakpoints involving modified memory */ |
if (type != BRKT_INSTR && type != BRKT_STEPEMUL) { |
continue; |
} |
if (BKPT_OVER (plst, idx, addr, size)) { |
return -1; /* overlaps */ |
} |
} |
return 0; |
} |
|
/*----- Execution support -----*/ |
|
/* |
* BreakStepRange - Start stepping in a range. |
* |
* Range is saved in breakpoint 0. |
*/ |
|
int |
BreakStepRange (PID_LIST* plst, void* addr, int len) |
{ |
if (!plst->break_list) { |
/* get list */ |
if (BreakAlloc (plst, False) == -1) { /* must not be any memory */ |
setErrno(ENOMEM); /* to be safe */ |
return -1; /* fails */ |
} |
} |
BKPT0 (plst)->range_start = (UINT32)addr; |
BKPT0 (plst)->range_end = (UINT32)addr+(len-1); |
return 0; |
} |
|
/* |
* If the Program Counter is changed, consider that the |
* current breakpoint has not been reached yet. |
*/ |
|
void |
BreakPcChanged (PID_LIST* plst) |
{ |
if (plst->break_list) { |
/* clear break stuff */ |
BKPT0 (plst)->clr_step = False; |
} |
} |
|
/* |
* BreakStepOff - prepare stepping off a breakpoint. |
*/ |
|
int |
BreakStepOff (const PID_LIST* plst, void** paddr2) |
{ |
if (plst->break_list && BKPT0 (plst)->clr_step) { |
|
/* need clear then step off break */ |
int last = BKPT0 (plst)->last_break; |
|
/* clear break, step, then do exec */ |
|
*paddr2 = (void*) plst->break_list[last].ee_type; |
|
/* Need to clr_step after TgtPtrace() when wait() returns */ |
return 1; |
} |
return 0; |
} |
|
/* |
* BreakSteppedOff - check if just stepped off a breakpoint |
* and re-insert it into the code. |
*/ |
|
void |
BreakSteppedOff (PID_LIST* plst) |
{ |
if (plst->break_list && BKPT0 (plst)->clr_step) { |
int idx = BKPT0 (plst)->last_break; |
int data; |
|
BKPT0 (plst)->clr_step = 0; |
|
/* |
* Re-insert the breakpoint. |
*/ |
data = TgtPtrace (RPT_PEEKTEXT, plst->pid, |
(char *)plst->break_list [idx].ee_loc, 0, NULL); |
assert (! IS_BREAK (data)); |
TgtPtrace (RPT_POKETEXT, plst->pid, |
(char *)plst->break_list[idx].ee_loc, |
(int) SET_BREAK (data), NULL); |
} |
} |
|
|
/* |
* Returns whether a thread matches a breakpoint. |
*/ |
|
static int |
BreakThreadMatch (xdr_break* xb, int thread) |
{ |
int slot; |
|
if (thread < 0) return 1; /* Break existence check only */ |
|
if (xb->thread_list [0] == 0) return 1; /* Universal break */ |
|
for (slot = 0; slot < BKPT_SLOTS; ++slot) { |
if (xb->thread_list [slot] == 0) return 0; /* End of list */ |
if (xb->thread_list [slot] == thread) return 1; /* Match */ |
} |
return 0; /* No matches found */ |
} |
|
|
int |
BreakAdjustPC (PID_LIST* plst) |
{ |
/* |
* BREAK_ADJ is the value by which the Program Counter |
* has to be decremented after a software breakpoint |
* is hit. It must be defined and can be zero. |
*/ |
#if BREAK_ADJ |
/* subtract back if necessary */ |
plst->regs.REG_PC -= BREAK_ADJ; /* now write back */ |
TgtPtrace(RPT_SETREGS, plst->pid, (char *)&plst->regs, 0, NULL); |
#else |
(void) plst; |
#endif |
return 0; |
} |
|
|
/* |
* Identify the current breakpoint. The process just stopped. |
*/ |
|
int |
BreakIdentify (PID_LIST* plst, int adjust, int thread) |
{ |
int foreignBkpt = 0; |
int bidx; |
|
for (bidx = 1; bidx < (int) plst->break_alloc; bidx++) { |
int type = plst->break_list[bidx].type; |
|
if ((type == BRKT_INSTR || type == BRKT_STEPEMUL) |
&& plst->regs.REG_PC - BREAK_ADJ |
== plst->break_list[bidx].ee_loc) { /* found matching */ |
if (!BreakThreadMatch (&plst->break_list[bidx], thread)) { |
if (foreignBkpt == 0) { |
foreignBkpt = bidx; |
} |
continue; |
} |
if (adjust) { |
BreakAdjustPC (plst); |
} |
return bidx; |
} |
} |
if (foreignBkpt) { |
if (adjust) { |
BreakAdjustPC (plst); |
} |
return -foreignBkpt; |
} |
return 0; |
} |
/remdeb.x
0,0 → 1,546
/* |
********************************************************************** |
* |
* Component: RDBG servers |
* Module: remdeb.x |
* |
* Synopsis: XDR definitions for remote debug server RPC calls. |
* XDR definitions for RPCGEN to build remote debug server. |
* |
* $Id: remdeb.x,v 1.2 2001-09-27 12:02:01 chris Exp $ |
* |
********************************************************************** |
*/ |
|
#ifdef RPC_SVC |
%/*HEADER_START*/ |
#endif |
|
%#define RTEMS_PORT 2071 |
%#define RTEMS_BACK_PORT 2073 |
|
#ifdef RPC_HDR |
%#ifndef REMDEB_H |
%#define RPCGENSRVNAME(a) a |
#endif |
|
enum rpc_type { |
SUNRPC = 0, |
BADRPCTYPE = 25 |
}; |
|
|
const NET_SAFE = 1400; /* this is safe for UDP messages */ |
|
struct UDP_MSG |
{ /* format of UDP messages (should be in .h) */ |
unsigned char type; /* type of message (BMSG_xx) */ |
unsigned char msg_num; /* ringed number for resend detect */ |
unsigned short spec; /* specific information for type */ |
long pid; /* process this affects */ |
unsigned long context; /* specific information to request */ |
}; |
|
/* First we support the overhead structures and types needed for RPC |
requests. Then, we have all RPC routines input/output args. */ |
|
%/* |
% * Sun request values for the remote ptrace system call |
% */ |
% |
enum ptracereq |
{ /* these match PTRACE_xxx numbers */ |
RPT_TRACEME = 0, /* 0, by tracee to begin tracing */ |
RPT_CHILDDONE = 0, /* 0, tracee is done with his half */ |
RPT_PEEKTEXT, /* 1, read word from text segment */ |
RPT_PEEKDATA, /* 2, read word from data segment */ |
RPT_PEEKUSER, /* 3, read word from user struct */ |
RPT_POKETEXT, /* 4, write word into text segment */ |
RPT_POKEDATA, /* 5, write word into data segment */ |
RPT_POKEUSER, /* 6, write word into user struct */ |
RPT_CONT, /* 7, continue process */ |
RPT_KILL, /* 8, terminate process */ |
RPT_SINGLESTEP, /* 9, single step process */ |
RPT_ATTACH, /* 10, attach to an existing process (returns 2 if not primary)*/ |
RPT_DETACH, /* 11, detach from a process */ |
RPT_GETREGS, /* 12, get all registers */ |
RPT_SETREGS, /* 13, set all registers */ |
RPT_GETFPREGS, /* 14, get all floating point regs */ |
RPT_SETFPREGS, /* 15, set all floating point regs */ |
RPT_READDATA, /* 16, read data segment */ |
RPT_WRITEDATA, /* 17, write data segment */ |
RPT_READTEXT, /* 18, read text segment */ |
RPT_WRITETEXT, /* 19, write text segment */ |
RPT_GETFPAREGS, /* 20, get all fpa regs */ |
RPT_SETFPAREGS, /* 21, set all fpa regs */ |
RPT_22, /* 22, filler */ |
RPT_23, /* 23, filler */ |
RPT_SYSCALL, /* 24, trap next sys call */ |
RPT_DUMPCORE, /* 25, dump process core */ |
RPT_26, /* 26, filler */ |
RPT_27, /* 27, filler */ |
RPT_28, /* 28, filler */ |
RPT_GETUCODE, /* 29, get u.u_code */ |
/* Begin specific ptrace options */ |
RPT_GETTARGETTHREAD = 50, /* get PM target thread identifier */ |
RPT_SETTARGETTHREAD = 51, /* set PM target thread identifier */ |
RPT_THREADSUSPEND = 52, /* suspend a thread */ |
RPT_THREADRESUME = 53, /* resume a thread */ |
RPT_THREADLIST = 54, /* get list of process's threads */ |
RPT_GETTHREADNAME = 55, /* get the name of the thread */ |
RPT_SETTHREADNAME = 56, /* set the name of the thread */ |
RPT_SETTHREADREGS = 57, /* set all registers for a specific thread*/ |
RPT_GETTHREADREGS = 58, /* get all registers for a specific thread*/ |
/* Begin extended ptrace options for remote debug server */ |
RPT_STEPRANGE = 75, /* step while in range (addr=start, data=len) */ |
RPT_CONTTO = 76, /* cont from PC to temp break in addr */ |
RPT_SETBREAK = 77, /* set a breakpoint (addr=break) */ |
RPT_CLRBREAK = 78, /* clear a breakpoint (data=handle or 0 for all) */ |
RPT_GETBREAK = 79, /* get breakpoint (data=handle, addr=buffer to |
fill). Returns next break. If data=0, |
returns number of breaks. */ |
RPT_GETNAME = 80, /* get name of process (data 0=name, 1=path |
as started, 2=fullpath). Return in addr |
as mem) */ |
RPT_STOP = 81, /* (C-actors) Stop the C-actor */ |
RPT_PGETREGS = 82, /* portable version */ |
RPT_PSETREGS = 83, /* portable version */ |
RPT_PSETTHREADREGS = 84, /* portable version */ |
RPT_PGETTHREADREGS = 85 /* portable version */ |
}; |
|
#include FRONTEND |
|
const MAXDEBUGGEE= 150; |
const NAMEMAX = 17; |
|
% /* |
% * Memory data for read/write text or data. The size is in data. The target |
% * addr is in the addr field. |
% * Be careful before modifying because this value goes into internal |
% * pipes and is allocated on stack too. Pipes and/or the stack could |
% * become too small if this value gets incremented. |
% */ |
|
const MEM_DATA_MAX = 256; |
|
#ifndef RPC_XDR |
|
struct xdr_mem { |
u_long addr; |
u_int dataNb; |
unsigned char data[MEM_DATA_MAX]; |
}; |
|
#else |
/* manually define best XDR function for this */ |
%bool_t xdr_xdr_mem(xdrs, objp) |
% XDR *xdrs; |
% struct xdr_mem *objp; |
%{ |
% if (!xdr_u_long(xdrs, &objp->addr)) { |
% return (FALSE); |
% } |
% if (!xdr_u_int(xdrs, &objp->dataNb)) { |
% return(FALSE); |
% } |
% return (xdr_opaque(xdrs, objp->data, objp->dataNb)); |
%} |
|
#endif |
|
/* Breakpoint structure maps to same structure on host. Do not change one |
without changing the other. */ |
|
enum break_type |
{ /* types of breakpoints */ |
BRKT_NONE, /* unused entry */ |
BRKT_INSTR, /* general instruction break */ |
BRKT_READ, /* read break */ |
BRKT_WRITE, /* write breakpoint */ |
BRKT_ACCESS, /* read-or-write break */ |
BRKT_EXEC, /* execution HW breakpoint */ |
BRKT_OS_CALL, /* break on OS call, addr is call number */ |
BRKT_OS_SWITCH, /* dispatch breakpoint */ |
BRKT_STEPEMUL /* emulate hardware single-step */ |
}; |
const MAX_THRD_BRK = 4; /* enough for 128 threads per process */ |
struct xdr_break |
{ /* one per process local breakpoint */ |
u_char type; /* BRKT_xxx type of break */ |
u_char thread_spec; /* 0=all, else count of threads it affects */ |
u_short handle; /* handle of breakpoint returned */ |
u_long ee_loc; /* address of start */ |
u_long ee_type; /* type/method of address */ |
u_short length; /* length of break if range, else 0 */ |
u_char pass_count; /* pass count to initialize to (0=none) */ |
u_char curr_pass; /* pass count current value */ |
u_long thread_list[MAX_THRD_BRK]; /* bit map for thread list */ |
}; /* 20 bytes+4 per thread_list (4x4=16) = 36 */ |
|
const UTHREAD_MAX = 64; |
|
const THREADNAMEMAX = 16; |
typedef string thread_name <THREADNAMEMAX>; |
|
struct KernThread { |
unsigned int threadLi; |
}; |
|
#ifndef RPC_XDR |
|
#ifdef RPC_HDR |
%typedef KernThread *ptThreadList; |
#endif |
|
struct thread_list { |
unsigned int nbThread; |
ptThreadList threads; |
}; |
|
#else /* RPC_XDR */ |
|
/* must write this function by hand */ |
|
%bool_t xdr_thread_list(xdrs, objp) |
% XDR *xdrs; |
% struct thread_list *objp; |
%{ |
% return (xdr_array(xdrs, (char**)&objp->threads, &objp->nbThread, |
% UTHREAD_MAX, sizeof(KernThread), xdr_KernThread)); |
%} |
|
#endif /* not RPC_XDR */ |
|
|
union ptrace_addr_data_in switch (ptracereq req) { |
/* |
* due to rpcgen poor features, we cannot put RPC_SETREGS |
* AND RPC_SETTHREADREGS in the case list. So we use a hack (FIX rpcgen). |
*/ |
#ifndef RPC_HDR |
case RPT_SETTHREADREGS : |
xdr_regs regs; |
#endif |
case RPT_SETREGS: |
|
xdr_regs regs; |
|
#ifndef RPC_HDR |
case RPT_PSETTHREADREGS: |
u_int pregs<>; |
#endif |
case RPT_PSETREGS: |
u_int pregs<>; |
|
#ifdef LATER |
case RPT_SETFPREGS: |
xdr_fp_status fpregs; |
#endif |
case RPT_SETTHREADNAME: |
thread_name name; |
#ifndef RPC_HDR |
case RPT_WRITETEXT: |
xdr_mem mem; |
#endif |
case RPT_WRITEDATA: |
xdr_mem mem; |
case RPT_SETBREAK: |
xdr_break breakp; |
default: |
u_int address; |
}; |
|
union ptrace_addr_data_out switch (ptracereq req) { |
case RPT_GETREGS: |
xdr_regs regs; |
#ifndef RPC_HDR |
case RPT_GETTHREADREGS: |
xdr_regs regs; |
#endif |
|
case RPT_PGETREGS: |
u_int pregs<>; |
|
#ifndef RPC_HDR |
case RPT_PGETTHREADREGS: |
u_int pregs<>; |
#endif |
|
#ifdef LATER |
case RPT_GETFPREGS: |
xdr_fp_status fpregs; |
#endif |
case RPT_THREADLIST: |
thread_list threads; |
case RPT_GETTHREADNAME: |
thread_name name; |
#ifndef RPC_HDR |
case RPT_READTEXT: |
xdr_mem mem; |
case RPT_GETNAME: |
xdr_mem mem; |
#endif |
case RPT_READDATA: |
xdr_mem mem; |
case RPT_GETBREAK: |
xdr_break breakp; |
default: |
u_int addr; |
}; |
|
typedef opaque CHAR_DATA <NET_SAFE>; /* variable sized data */ |
|
const XRY_MAX_INST_BUFF = 128; |
const XRY_MAX_INSTANCES = 16; |
%#ifndef XRY_MAX_CMD_STR |
const XRY_MAX_CMD_STR = 320; /* XRY_MAX_INST_BUFF+(XRY_MAX_INSTANCES*12) */ |
%#endif /* REMDEB_H */ |
|
|
struct xry_inst |
{ |
unsigned char flags; /* value2 interp, etc. INFL_xxx */ |
unsigned char type; /* base type of data (str, val, etc) INST_xxx */ |
unsigned char sub_type; /* specific type (task, res, etc). This is |
set and defined by the user defined instance |
processor and not the auto-processor */ |
unsigned char res_type; |
u_long value; /* pointer to value or value itself */ |
u_long value2; /* second value (optional - based on flags) */ |
}; |
|
struct instance |
{ |
struct xry_inst instances[XRY_MAX_INSTANCES]; |
unsigned char buffer[XRY_MAX_INST_BUFF]; |
}; |
|
union instance_union switch (bool instances) |
{ |
case TRUE: |
instance inst; |
case FALSE: |
string buffer <XRY_MAX_CMD_STR>; |
}; |
|
typedef string one_arg <NET_SAFE>; |
|
const XRY_MAX_OBJ_NAME = 32; /* objname in some commands */ |
|
% /* now open_connex() routine which establishes a connection to server */ |
|
enum debug_type |
{ /* type of connection requested */ |
DEBTYP_PROCESS = 0, /* process connection */ |
DEBTYP_C_ACTOR = 1, /* C-Actor connection */ |
DEBTYP_KERNEL = 2, /* kernel debug connection */ |
DEBTYP_OTHER = 3 /* other subsystem */ |
}; |
|
%#define DEBUGGER_IS_GDB 0x2 /* */ |
|
struct open_in |
{ /* input args to open a connection */ |
u_char back_port[16]; /* opaque NET address format */ |
u_short debug_type; /* type of process DEBTYP_xxx */ |
u_short flags; /* connection information OPNFLG_xxx */ |
u_char destination[16];/* opaque address if to router */ |
one_arg user_name; /* name of user on host */ |
}; |
|
struct open_out |
{ /* return from open_connex */ |
u_long port; /* connection number to server or -1 if error */ |
u_int pad[4]; /* Planned to be KnIpcDest. Never used */ |
u_int fp; /* True if floating point processor. If error, |
set to errno for open error. */ |
u_char cmd_table_num; /* command table used */ |
u_char cmd_table_vers; /* version of command table */ |
u_short server_vers; /* version number of server itself */ |
}; |
|
% /* now close_connex() routine which detaches from server */ |
|
enum close_control |
{ /* choice of how to handle owned processes */ |
CLOSE_IGNORE = 0, /* ignore all controlled pids on close */ |
CLOSE_KILL = 1, /* kill all controlled pids on close */ |
CLOSE_DETACH = 2 /* detach free running all controlled pids */ |
}; |
|
struct close_in |
{ /* arg to close connection */ |
close_control control; /* shutdown of owned processes control */ |
}; |
|
% /* now send_signal() routine which sends signals to processes like kill(2) */ |
|
struct signal_in |
{ /* input to send_signal */ |
int pid; /* process/actor to send signal to */ |
int sig; /* signal to send (from /usr/include/signal.h) */ |
}; |
|
struct signal_out |
{ /* return from send_signal */ |
int kill_return; /* return code from kill(2) call */ |
int errNo; /* error code if failed */ |
}; |
|
|
% /* now wait_info() routine which returns results of polling the wait status |
% of a process/actor. It may return 0 if running, else pid or -1 */ |
|
enum stop_code |
{ /* stop code information */ |
STOP_ERROR = 0, /* error, errno set */ |
STOP_NONE = 1, /* not stopped */ |
STOP_UNKNOWN = 2, /* unknown stop reason */ |
STOP_BREAK = 3, /* stopped on breakpoint */ |
STOP_STEP = 4, /* stopped on step */ |
STOP_SIGNAL = 5, /* stopped on signal receieve */ |
STOP_TERM_EXIT = 6, /* terminated normally */ |
STOP_TERM_SIG = 7, /* terminated by signal */ |
STOP_DETACHED = 8, /* detached from server */ |
STOP_KILLED = 9, /* killed by ptrace KILL */ |
STOP_SPAWN_FAILED = 10 /* spawn failed in exec part, handle=errno */ |
}; |
|
struct wait_in |
{ /* input arg to wait is process */ |
int pid; /* process/actor id */ |
}; |
|
struct wait_out |
{ /* result of wait_info call */ |
int wait_return; /* -1=error,0=running,pid=stopped */ |
int errNo; /* error code if error */ |
int status; /* wait(2) status if stopped */ |
stop_code reason; /* reason in more abstracted terms */ |
int handle; /* handle of break if stopped on break, |
or signal number or exit code */ |
u_long PC; /* program counter if stopped */ |
u_long SP; /* stack pointer if stopped */ |
u_long FP; /* frame pointer if stopped */ |
u_long thread; /* thread that stopped if applies (else -1) */ |
}; |
|
% /* now ptrace() routine. This matches the Sun UNIX ptrace as well as |
% some additions */ |
|
const PTRFLG_FORCE = 1; /* when set and process running, forces process |
to stop, make the request, then start again. |
This is used for breakpoints and the like */ |
const PTRFLG_NON_OWNER = 2; /* do request even if not primary owner (will |
notify all owners including caller if owns) */ |
const PTRFLG_FREE = 4; /* free pid_list after KILL/DETACH */ |
|
const PTRDET_UNOWN = 0x100; /* data value in RPT_DETACH just disconnects |
caller as an owner of process. */ |
|
struct ptrace_in |
{ /* input args matches ptrace but for XDR */ |
int pid; /* process to act on */ |
ptrace_addr_data_in addr; /* mappings for addr and addr2 */ |
u_int data; /* simple data arg of ptrace */ |
u_int flags; /* mask of PTRFLG_xxx flags. */ |
}; |
|
struct ptrace_out |
{ /* return information from ptrace */ |
ptrace_addr_data_out addr; /* return through addr/addr2 */ |
int result; /* result of ptrace call (return value) */ |
int errNo; /* error code if error */ |
}; |
|
/* Data for GET_GLOBAL_SYMBOLS */ |
struct one_symbol { /* Must match common/src/lib/ctx/ctx.h */ |
string symbolName<>; |
long symbolValue; |
}; |
|
typedef one_symbol all_symbols<>; |
|
struct get_global_symbols_out { |
all_symbols symbols; |
}; |
|
/* Data for GET_TEXT_DATA */ |
struct get_text_data_in { |
int pid; /* process/actor id if non-zero */ |
string actorName<16>; /* actor name for system mode */ |
}; |
|
struct get_text_data_out { |
int result; |
int errNo; |
u_long textStart; |
u_long textSize; |
u_long dataStart; |
u_long dataSize; |
}; |
|
/* Data for GET_SIGNAL_NAMES */ |
struct one_signal { |
u_int number; |
string name<>; |
}; |
|
typedef one_signal all_signals<>; |
|
struct get_signal_names_out { |
all_signals signals; |
}; |
|
% /* now define the actual calls we support */ |
|
program REMOTEDEB { |
version REMOTEVERS { |
|
/* open a connection to server or router */ |
open_out |
OPEN_CONNEX(open_in) = 1; |
|
/* send a signal to a process */ |
signal_out |
SEND_SIGNAL(signal_in) = 2; |
|
/* all routines below require a connection first */ |
|
/* close the connection to the server */ |
void |
CLOSE_CONNEX(close_in) = 10; |
|
/* process ptrace request */ |
ptrace_out |
PTRACE(ptrace_in) = 11; |
|
/* poll for status of process */ |
wait_out |
WAIT_INFO(wait_in) = 13; |
|
get_signal_names_out |
GET_SIGNAL_NAMES(void) = 17; |
|
} = 2; /* now version 2 */ |
} = 0x20000fff; |
|
#ifdef RPC_HDR |
%#define REMDEB_H |
%#endif |
#endif |
|
#ifdef RPC_SVC |
|
%const char* names [] = { |
% "NULLPROC", "OPEN_CONNEX", "SEND_SIGNAL", "name3", |
% "name4", "name5", "name6", "name7", |
% "name8", "name9", "CLOSE_CONNEX", "PTRACE", |
% "name12", "WAIT_INFO", "name14", "name15", |
% "name16", "GET_SIGNAL_NAMES", "name18" |
%}; |
% |
|
%/*HEADER_END*/ |
#endif |
/excep.c
0,0 → 1,136
/* |
************************************************************************** |
* |
* Component = |
* |
* Synopsis = rdbgexcep.c |
* |
* $Id: excep.c,v 1.2 2001-09-27 12:02:01 chris Exp $ |
* |
************************************************************************** |
*/ |
|
#include <rtems.h> |
#include <rtems/error.h> |
#include <assert.h> |
#include <errno.h> |
#include <rdbg/rdbg.h> |
#include <rdbg/servrpc.h> |
|
unsigned int NbExceptCtx; |
volatile unsigned int NbSerializedCtx; |
Exception_context *FirstCtx = NULL; |
Exception_context *LastCtx = NULL; |
|
CPU_Exception_frame SavedContext; |
|
|
/********* Save an exception context at the end of a list *****/ |
|
int PushExceptCtx ( Objects_Id Id, Objects_Id semId, CPU_Exception_frame *ctx ) { |
|
Exception_context *SaveCtx; |
|
SaveCtx = (Exception_context *)malloc(sizeof(Exception_context)); |
if (SaveCtx == NULL) |
rtems_panic("Can't allocate memory to save Exception context"); |
|
SaveCtx->id = Id; |
SaveCtx->ctx = ctx; |
SaveCtx->semaphoreId = semId; |
SaveCtx->previous = NULL; |
SaveCtx->next = NULL; |
|
if (FirstCtx == NULL){ /* initialization */ |
FirstCtx = SaveCtx; |
LastCtx = SaveCtx; |
NbExceptCtx = 1; |
} |
else { |
NbExceptCtx ++; |
LastCtx->next = SaveCtx; |
SaveCtx->previous = LastCtx; |
LastCtx = SaveCtx; |
} |
return 0; |
} |
|
/********* Save an temporary exception context in a ******/ |
/********* global variable ******/ |
|
int PushSavedExceptCtx ( Objects_Id Id, CPU_Exception_frame *ctx ) { |
|
memcpy (&(SavedContext), ctx, sizeof(CPU_Exception_frame)); |
return 0; |
} |
|
|
/****** Remove the context of the specified Id thread *********/ |
/****** If Id = -1, then return the first context *********/ |
|
|
int PopExceptCtx ( Objects_Id Id ) { |
|
Exception_context *ExtractCtx; |
|
if (FirstCtx == NULL) return -1; |
|
if (Id == -1) { |
ExtractCtx = LastCtx; |
LastCtx = LastCtx->previous; |
free(ExtractCtx); |
NbExceptCtx --; |
return 0; |
} |
|
ExtractCtx = LastCtx; |
|
while (ExtractCtx->id != Id && ExtractCtx != NULL) { |
ExtractCtx = ExtractCtx->previous; |
} |
|
if (ExtractCtx == NULL) |
return -1; |
|
if ( ExtractCtx->previous != NULL) |
(ExtractCtx->previous)->next = ExtractCtx->next; |
|
if ( ExtractCtx->next != NULL) |
(ExtractCtx->next)->previous = ExtractCtx->previous; |
|
if (ExtractCtx == FirstCtx) |
FirstCtx = FirstCtx->next; |
else |
if (ExtractCtx == LastCtx) |
LastCtx = LastCtx->previous; |
|
free(ExtractCtx); |
NbExceptCtx --; |
return 0; |
} |
|
/****** Return the context of the specified Id thread *********/ |
/****** If Id = -1, then return the first context *********/ |
|
|
Exception_context *GetExceptCtx ( Objects_Id Id ) { |
|
Exception_context *ExtractCtx; |
|
if (FirstCtx == NULL) return NULL; |
|
if (Id == -1) { |
return LastCtx; |
} |
|
ExtractCtx = LastCtx; |
|
while (ExtractCtx->id != Id && ExtractCtx != NULL) { |
ExtractCtx = ExtractCtx->previous; |
} |
|
if (ExtractCtx == NULL) |
return NULL; |
|
return ExtractCtx; |
} |
/servrpc.c
0,0 → 1,722
/* |
********************************************************************** |
* |
* Component: RDBG |
* Module: servrpc.c |
* |
* Synopsis: support routines for RPC dispatch for remote debug server. |
* Main server dispatch routines from RPC to support remote debug. |
* |
* $Id: servrpc.c,v 1.2 2001-09-27 12:02:01 chris Exp $ |
* |
********************************************************************** |
*/ |
|
#include <string.h> |
#include <sys/errno.h> |
#include <rdbg/rdbg.h> |
#include <rdbg/remdeb.h> |
#include <rdbg/servrpc.h> |
|
/************************************************************************/ |
|
/* ----------------------------------------------------------------------- |
open_connex_2_svc - setup a new connection from a client. |
|
Notes: |
- this function creates a new connection to a client. It allocates |
an entry in the connection structure and fills in the information |
sent and implied by the message. |
- a client connection entry is needed for all further messages to work |
properly. |
----------------------------------------------------------------------- */ |
|
open_out* RPCGENSRVNAME(open_connex_2_svc) (open_in *in, struct svc_req *rqstp) |
{ |
static open_out out; /* output response. This could be heap local */ |
int idx; |
static int one_time = 0; /* we do one-time setup on back port */ |
|
/* need to support in->debug_type, in->flags, and in->destination!!! */ |
|
if (!one_time) |
{ /* only setup one backport socket */ |
/* now setup signals and the like for handling process changes */ |
setErrno(0); |
TspInit(rqstp->rq_xprt->xp_sock); /* init transport system */ |
if (getErrno()) |
{ /* failed in setup */ |
out.port = (u_long)-1; |
out.fp = getErrno(); /* error causing to fail */ |
return(&out); /* fail */ |
} |
one_time = True; /* disable doing this again */ |
} |
|
DPRINTF(("open_connex_2_svc: Opening connection from '%s'\n", |
in->user_name)); |
|
/* now setup a validation of all other connections */ |
for (idx = 0; idx < conn_list_cnt; idx++) |
if (conn_list[idx].in_use) |
{ /* setup retry timer */ |
DPRINTF(("open_connex_2_svc: Still have connection %d with port %d\n", |
idx, HL_W(*((UINT16*)&conn_list[idx].back_port.c[2])))); |
} |
|
idx = ConnCreate(rqstp, in); /* setup the connection */ |
out.port = idx; /* connection number */ |
if (idx == -1) |
out.fp = getErrno(); /* error causing to fail */ |
else |
out.fp = TARGET_PROC_TYPE; |
|
out.server_vers = SERVER_VERS; |
return(&out); |
} |
|
/* ----------------------------------------------------------------------- |
send_signal_2_svc - send a kill/signal to the specified process. |
|
Notes: |
- this function sends a signal to the process specified. This process |
does not have to be under debug nor attached by this server. The kill |
may be refused on other grounds though. |
- kill(pid, 0) can be used to validate the process still exists if |
needed. |
----------------------------------------------------------------------- */ |
|
signal_out *RPCGENSRVNAME(send_signal_2_svc) (signal_in *in, struct svc_req *rqstp) |
{ |
static signal_out out; /* return code from kill */ |
|
/* we do not care if connected */ |
setErrno(0); |
out.kill_return = 0; |
out.errNo = 0; |
TotalReboot = 1; |
return(&out); |
} |
|
/* ----------------------------------------------------------------------- |
close_connex_2_svc - close a connection from a client. |
----------------------------------------------------------------------- */ |
|
void *RPCGENSRVNAME(close_connex_2_svc) (close_in *in, struct svc_req *rqstp) |
{ |
int conn_idx = TspConnGetIndex(rqstp); |
|
if (conn_idx != -1) /* found it, clear out */ |
ConnDelete(conn_idx, rqstp, in->control); |
|
return (void*) ""; /* need to return something */ |
} |
|
/* ----------------------------------------------------------------------- |
ptrace_2_svc - control process under debug. |
----------------------------------------------------------------------- */ |
|
#define REG_COUNT \ |
(sizeof (xdr_regs) / sizeof (int)) |
|
ptrace_out *RPCGENSRVNAME(ptrace_2_svc) (ptrace_in *in, struct svc_req *rqstp) |
{ |
int conn_idx = rqstp ? TspConnGetIndex(rqstp) : -1; |
static ptrace_out out; /* outut response (error or data) */ |
void *addr, *addr2; /* used for actual ptrace call */ |
unsigned int data; |
int req, pid, ret, pid_idx, idx; |
static union |
{ /* local buffer for returned data */ |
Objects_Id t_list[UTHREAD_MAX]; /* thread_list return */ |
char t_name[THREADNAMEMAX]; /* thread name return */ |
} local_buff; /* for return handling of strings and the like */ |
PID_LIST *plst = NULL; /* current pid_list entry */ |
|
DPRINTF (("ptrace_2_svc: entered (%s (%d), %d, XXXX, %d, XXXX)\n", |
PtraceName (in->addr.req), in->addr.req, in->pid, |
in->data)); |
|
out.addr.ptrace_addr_data_out_u.addr = 0; |
|
/* validate the connection */ |
if (conn_idx == -1 && rqstp != NULL) |
{ /* no connection, error */ |
DPRINTF(("ptrace_2_svc: msg from unknown debugger!\n")); |
out.result = -1; |
out.errNo = ECHILD; /* closest error */ |
out.addr.req = 0; /* to avoid copies that should not occur */ |
return(&out); |
} |
/* Consider that the last back-message is acknowledged */ |
if (conn_idx >= 0 && conn_list[conn_idx].retry) { |
TspMessageReceive(conn_idx, in->pid); |
} |
|
req = in->addr.req; |
out.addr.req = req; /* needed for RPC */ |
pid = in->pid; |
addr = addr2 = NULL; |
data = in->data; |
setErrno(0); /* assume works */ |
out.result = 0; /* assume worked ok */ |
out.errNo = 0; |
|
/* lookup process to make sure we have under control */ |
pid_idx = FindPidEntry (in->pid); |
if (pid_idx >= 0) /* found it */ |
{ |
plst = &pid_list[pid_idx]; |
if (conn_idx < 0) |
conn_idx = plst->primary_conn; |
} |
|
/* now we handle the special case of ATTACH to a pid we already control */ |
if (req == RPT_ATTACH) |
{ /* look it up first */ |
if (plst) |
{ /* we have controlled , so return ok+show conn */ |
ret = 2; /* normally secondary connection */ |
if (! PIDMAP_TEST (conn_idx, pid_idx)) |
{ /* mark as an owner if not already */ |
plst->owners++; |
PIDMAP_SET (conn_idx, pid_idx); /* mask in */ |
} |
else if (plst->primary_conn != NO_PRIMARY) |
{ /* regrab makes primary */ |
/* Only if not primary already */ |
if (plst->primary_conn != conn_idx) { |
TspSendWaitChange(plst->primary_conn, BMSG_NOT_PRIM, |
conn_idx, plst->pid, 0, False); /* tell old owner */ |
} |
plst->primary_conn = NO_PRIMARY; |
} |
|
if (plst->primary_conn == NO_PRIMARY) |
{ /* none now, so take over */ |
plst->primary_conn = conn_idx; /* new primary */ |
ret = 1; /* primary */ |
} |
out.result = ret; /* primary or secondary owner */ |
return(&out); |
} |
/* else attach process using target code */ |
setErrno(ESRCH); /* assume the worst */ |
if (!TgtAttach(conn_idx, pid)) |
{ /* failed */ |
out.errNo = getErrno(); |
out.result = 0; |
} |
return(&out); |
} |
else if (req == RPT_DETACH) |
{ /* see which kind of detach */ |
if (data == PTRDET_UNOWN) |
{ /* only want to disconnect from */ |
TgtDetachCon(conn_idx, pid_idx, True); /* remove from control */ |
return(&out); /* done */ |
} |
} |
else if (plst && (req == RPT_GETNAME || req == RPT_GETBREAK)) |
{ |
/* do nothing */ |
} |
|
else if (plst && req == RPT_CLRBREAK) { |
/* To be able to remove breakpoints from a "running" system */ |
DPRINTF (("ptrace_2_svc: allowing RPT_CLRBREAK %d\n", data)); |
/* do nothing */ |
} |
|
else if (plst && plst->running) |
{ /* error, process is running and not detach */ |
out.result = -1; |
out.errNo = ETXTBSY; /* closest error */ |
DPRINTF (("ptrace_2_svc: failed, still running.\n")); |
return(&out); |
} |
if (plst == NULL) { |
out.result = -1; |
out.errNo = ESRCH; |
DPRINTF (("ptrace_2_svc: No such process.\n")); |
return (&out); |
} |
|
/* now make sure secondary owner is not trying to modify */ |
if (!(in->flags & PTRFLG_NON_OWNER)) /* if not overriden */ |
if (conn_idx != plst->primary_conn |
&& ( (req >= RPT_POKETEXT && req <= RPT_SINGLESTEP) |
|| (req >= RPT_SETREGS && req <= RPT_SETFPAREGS && (req & 1)) |
|| (req >= RPT_SYSCALL && req <= RPT_DUMPCORE) |
|| (req >= RPT_SETTARGETTHREAD && req <= RPT_THREADRESUME) |
|| (req >= RPT_SETTHREADNAME && req <= RPT_SETTHREADREGS) |
|| (req >= RPT_STEPRANGE && req <= RPT_CLRBREAK) |
|| (req == RPT_STOP) |
|| (req >= RPT_PSETREGS && req <= RPT_PSETTHREADREGS))) |
{ /* not owner */ |
out.result = -1; |
out.errNo = EPERM; /* cannot alter as not primary */ |
DPRINTF (("ptrace_2_svc: refused, not owner, flags %d conn_idx %d primary_conn %d\n", in->flags, conn_idx, |
plst->primary_conn)); |
return(&out); |
} |
|
addr = (void *)in->addr.ptrace_addr_data_in_u.address; /* default */ |
/* now setup normal ptrace request by unpacking. May execute here. */ |
switch (req) |
{ /* handle unpacking or setup for real call */ |
/* first the ones where addr points to input data */ |
case RPT_SETREGS: |
case RPT_SETTHREADREGS: |
addr = (void *)&in->addr.ptrace_addr_data_in_u.regs; /* reg list */ |
break; |
|
case RPT_PSETREGS: |
case RPT_PSETTHREADREGS: |
if (in->addr.ptrace_addr_data_in_u.pregs.pregs_len != REG_COUNT) { |
DPRINTF(("ptrace_2_svc: pid %d got %d expected %d\n", pid, |
in->addr.ptrace_addr_data_in_u.pregs.pregs_len, REG_COUNT)); |
setErrno(EINVAL); |
break; |
} |
req = req == RPT_PSETREGS ? RPT_SETREGS : RPT_SETTHREADREGS; |
addr = (void *) in->addr.ptrace_addr_data_in_u.pregs.pregs_val; |
break; |
|
case RPT_SETTHREADNAME: |
addr = (void *)in->addr.ptrace_addr_data_in_u.name; |
break; |
case RPT_WRITETEXT: |
case RPT_WRITEDATA: |
if ((int) data < 0) { |
setErrno(EINVAL); |
break; |
} |
addr = (void *)in->addr.ptrace_addr_data_in_u.mem.addr; /* targ addr */ |
addr2 = (void *)in->addr.ptrace_addr_data_in_u.mem.data; /* buff */ |
|
/* Forbid writing over breakpoints */ |
if (BreakOverwrite (plst, addr, data)) { |
setErrno(EBUSY); |
} |
break; |
|
case RPT_POKETEXT: |
case RPT_POKEDATA: |
/* Forbid writing over breakpoints */ |
if (BreakOverwrite (plst, addr, sizeof (int))) { |
setErrno(EBUSY); |
} |
break; |
|
/* now ones where we handle locally */ |
case RPT_GETTARGETTHREAD: |
out.result = plst->thread; |
req = 0; /* force exit */ |
break; |
|
case RPT_PGETREGS: /* return from our buffer */ |
out.addr.ptrace_addr_data_out_u.pregs.pregs_len = REG_COUNT; |
out.addr.ptrace_addr_data_out_u.pregs.pregs_val = (u_int*) &plst->regs; |
req = 0; /* force exit */ |
break; |
|
case RPT_GETREGS: |
/* return directly from our buffer */ |
/* this buffer is refreshed when changing target thread */ |
out.addr.ptrace_addr_data_out_u.regs = plst->regs; |
req = 0; /* force exit */ |
break; |
|
case RPT_SETBREAK: |
idx = BreakSet (plst, conn_idx, &in->addr.ptrace_addr_data_in_u.breakp); |
if (idx < 0) break; |
req = 0; /* force exit */ |
out.result = idx; /* return break index (>0) */ |
break; |
|
case RPT_CLRBREAK: |
if (conn_list[conn_idx].flags & DEBUGGER_IS_GDB) { |
data = BreakGetIndex (plst, addr); |
} |
out.result = BreakClear (plst, conn_idx, data); |
/* if errored, errno will still be set */ |
req = 0; |
break; |
|
case RPT_GETBREAK: |
/* data=handle, addr=in_buffer, returns next break. Data=0, returns cnt */ |
out.result = BreakGet (plst, data, &out.addr. |
ptrace_addr_data_out_u.breakp); |
req = 0; /* handle locally */ |
break; |
|
case RPT_GETNAME: /* get the name of the process */ |
if (!plst->name) |
out.addr.ptrace_addr_data_out_u.mem.dataNb = 0; |
else |
{ |
int maxLen = sizeof out.addr.ptrace_addr_data_out_u.mem.data - 1; |
data = strlen(plst->name); |
if (data > maxLen) |
data = maxLen; |
out.addr.ptrace_addr_data_out_u.mem.dataNb = data+1; |
memcpy(out.addr.ptrace_addr_data_out_u.mem.data, plst->name, data+1); |
out.addr.ptrace_addr_data_out_u.mem.data [maxLen] = '\0'; |
} |
req = 0; |
break; |
|
case RPT_CONTTO: |
if (BreakSetAt (plst, conn_idx, (u_long) addr, BRKT_STEPEMUL) < 0) |
{ |
DPRINTF(("ptrace_2_svc: BreakSet failed at %x", addr)); |
break; |
} |
req = RPT_CONT; |
/* data can contain a signal number, addr2 is unused */ |
goto case_RPT_CONT; |
|
case RPT_STEPRANGE: |
/* convert to step */ |
if (!data) |
data = 1; /* should we give an error?? */ |
BreakStepRange (plst, addr, data); |
if (getErrno()) break; |
|
req = RPT_SINGLESTEP; /* do by stepping */ |
addr = (void*) 1; /* start from current PC */ |
data = -2; /* want non-atomic stepping */ |
/* fall through to other exec cases */ |
|
case RPT_CONT: |
case_RPT_CONT: |
case RPT_SINGLESTEP: |
|
if (BreakStepOff (plst, &addr2)) |
{ /* need clear then step off break */ |
/* clear break, step, then do exec */ |
if (addr == (void*) 1) |
addr = (void*) plst->regs.REG_PC;/* need for patch */ |
|
/* data is always 0, so atomic single-step */ |
} else if (req == RPT_SINGLESTEP) { |
data = -2; /* want non-atomic stepping */ |
} |
break; |
|
/* now ones where addr points to an output area */ |
case RPT_PGETTHREADREGS: |
addr = (void*) out.addr.ptrace_addr_data_out_u.mem.data; |
if (sizeof out.addr.ptrace_addr_data_out_u.mem.data < |
REG_COUNT * sizeof(int)) { |
setErrno(EINVAL); |
break; |
} |
if (data == plst->thread) { |
out.addr.ptrace_addr_data_out_u.pregs.pregs_len = REG_COUNT; |
out.addr.ptrace_addr_data_out_u.pregs.pregs_val = (u_int*) &plst->regs; |
req = 0; /* force exit */ |
break; |
} |
req = RPT_GETTHREADREGS; |
break; |
|
case RPT_GETTHREADREGS: |
addr = (void*) &out.addr.ptrace_addr_data_out_u.regs; |
break; |
case RPT_GETTHREADNAME: |
out.addr.ptrace_addr_data_out_u.name = local_buff.t_name; |
addr = (void*) out.addr.ptrace_addr_data_out_u.name; |
break; |
case RPT_THREADLIST: |
out.addr.ptrace_addr_data_out_u.threads.threads =(ptThreadList) local_buff.t_list; |
addr = (void*) out.addr.ptrace_addr_data_out_u.threads.threads; |
break; |
case RPT_READTEXT: |
case RPT_READDATA: |
if ((int) data < 0) { |
setErrno(EINVAL); |
break; |
} |
addr = (void *)in->addr.ptrace_addr_data_in_u.address; |
addr2 = (void *)out.addr.ptrace_addr_data_out_u.mem.data; |
out.addr.ptrace_addr_data_out_u.mem.dataNb = data; |
break; |
case RPT_DETACH: |
/* Do not allow detaching if breakpoints still there */ |
if (BreakGet (plst, 0, NULL)) |
{ /* some bkpts still set */ |
setErrno(EINVAL); /* cannot detach safely */ |
break; |
} |
/* fall through */ |
case RPT_KILL: |
/* in the event they are trying to detach or kill a terminated process, |
we just delete the entry. */ |
if (PROC_TERMINATED (plst)) |
{ |
TgtDelete(plst, -1, BMSG_KILLED); /* just blow off */ |
req = 0; /* now exit */ |
} |
break; |
} |
|
if (getErrno()) |
{ /* failed in code above */ |
out.result = -1; |
out.errNo = getErrno(); |
DPRINTF(("ptrace_2_svc: result %d errNo %d\n", out.result, out.errNo)); |
return(&out); |
} |
else if (!req) |
{ /* bail out now */ |
DPRINTF(("ptrace_2_svc: result %d errNo %d\n", out.result, out.errNo)); |
return(&out); |
} |
|
/* OK, make the call */ |
out.result = TgtPtrace(req, pid, addr, data, addr2); |
out.errNo = getErrno(); |
|
/* if no error, cleanup afterwards */ |
if (getErrno()) |
{ |
/* Remove step-emul breakpoints if any */ |
if (req == RPT_SINGLESTEP || req == RPT_CONT) { |
BreakClear (plst, -1, -1); |
} |
DPRINTF(("ptrace_2_svc: result %d errNo %d\n", out.result, out.errNo)); |
return(&out); /* return error */ |
} |
|
switch (in->addr.req) |
{ /* handle some special calls that affect state */ |
case RPT_CONT: |
case RPT_STEPRANGE: |
/* change to running */ |
if (in->addr.req == RPT_STEPRANGE) |
plst->last_start = LAST_RANGE; /* so range steps */ |
else if (addr2) |
plst->last_start = LAST_STEPOFF; /* now continue after wait */ |
else |
plst->last_start = LAST_CONT; |
plst->running = 1; /* mark as running */ |
if (!rqstp) /* Called internally to restart bkpt, no msg to anybody */ |
break; |
TgtNotifyAll(pid_idx, BMSG_WAIT, 0, 0, (in->flags & PTRFLG_NON_OWNER) |
? -1 : conn_idx, True); |
break; |
case RPT_SINGLESTEP: |
/* mark as step */ |
plst->last_start = LAST_STEP; /* so we know how started */ |
plst->running = 1; /* mark as running (wait should catch fast) */ |
break; |
case RPT_DETACH: /* mark as disconnected */ |
case RPT_KILL: /* mark as killed */ |
if (in->flags & PTRFLG_FREE) /* notify and delete entry */ |
TgtDelete(plst, -1, (in->addr.req==RPT_KILL) ? BMSG_KILLED : BMSG_DETACH); |
else |
{ /* notify and mark */ |
plst->last_start = (in->addr.req==RPT_KILL) ? |
LAST_KILLED : LAST_DETACHED; |
plst->state = -1; |
plst->running = False; |
TgtNotifyAll(pid_idx, (in->addr.req==RPT_KILL) ? |
BMSG_KILLED : BMSG_DETACH, 0, 0, -1, True); |
} |
break; |
case RPT_SETTHREADREGS: |
case RPT_PSETTHREADREGS: |
if (data != plst->thread) |
break; |
DPRINTF(("ptrace_2_svc: pid %d target thread regs changed!\n", pid)); |
|
case RPT_SETREGS: |
case RPT_PSETREGS: |
/* change our buffer as well */ |
if (plst->regs.REG_PC != ((xdr_regs*)addr)->REG_PC) |
BreakPcChanged (plst); |
plst->regs = *(xdr_regs*) addr; /* copy in */ |
break; |
|
/* case RPT_PGETREGS has been handled locally above */ |
case RPT_PGETTHREADREGS: |
/* We need to update pointer so that XDR works on return */ |
out.addr.ptrace_addr_data_out_u.pregs.pregs_len = REG_COUNT; |
out.addr.ptrace_addr_data_out_u.pregs.pregs_val = |
(void*) out.addr.ptrace_addr_data_out_u.mem.data; |
break; |
|
case RPT_PEEKTEXT: |
case RPT_PEEKDATA: |
case RPT_READDATA: |
case RPT_READTEXT: |
if (req < RPT_READDATA) |
{ /* peek */ |
/* addr is start */ |
data = sizeof(int); |
addr2 = &out.result; /* data buffer */ |
/* Like read: addr is start, data is length, addr2 is buffer */ |
} |
BreakHide (plst, addr, data, addr2); |
break; |
|
case RPT_SETTARGETTHREAD: |
DPRINTF(("ptrace_2_svc: pid %d new target thread %d\n", pid, data)); |
TgtPtrace (RPT_GETREGS, pid, (char*) &plst->regs, 0, NULL); |
plst->thread = data; |
if (plst->break_list) { /* Forget we had to step off breakpoint */ |
BASE_BREAK* base = (BASE_BREAK*) plst->break_list; |
DPRINTF(("ptrace_2_svc: clr_step %d last_break %d\n", base->clr_step, |
base->last_break)); |
base->clr_step = 0; /* Not stopped on break */ |
base->last_break = 0; |
} |
break; |
|
case RPT_THREADLIST: |
out.addr.ptrace_addr_data_out_u.threads.nbThread = out.result; |
break; |
|
default: |
break; |
} /* end switch */ |
DPRINTF(("ptrace_2_svc 2: result %d errNo %d\n", out.result, out.errNo)); |
return(&out); |
} |
|
/* ----------------------------------------------------------------------- |
wait_info_2_svc - non-blocking wait request to check status. |
----------------------------------------------------------------------- */ |
|
wait_out *RPCGENSRVNAME(wait_info_2_svc) (in, rqstp) |
wait_in *in; |
struct svc_req *rqstp; /* server info */ |
{ |
int conn_idx = TspConnGetIndex(rqstp); |
static wait_out out; /* output of pid and status */ |
int idx; |
PID_LIST *plst; |
|
memset(&out, 0, sizeof(out)); /* zero for safety */ |
out.reason = STOP_ERROR; /* assume the worst */ |
|
if (conn_idx == -1) |
{ /* no connection, error */ |
DPRINTF(("wait_info_2_svc: msg from unknown debugger!\n")); |
out.wait_return = -1; |
out.errNo = ECHILD; /* closest error */ |
return(&out); |
} |
else |
{ /* see if confirming message received */ |
if (conn_list[conn_idx].retry) |
TspMessageReceive(conn_idx, in->pid); |
} |
|
if (!in->pid) |
{ /* warm test verify only */ |
/* this call (pid==0) is made to confirm that that connection is still |
active. */ |
/* we let it fall through as an error since any use other than connection |
reset would be an error (there is no pid0). */ |
} |
else |
{ /* normal request */ |
idx = FindPidEntry (in->pid); |
if (idx >= 0) |
{ /* found process they requested on */ |
plst = &pid_list[idx]; |
out.wait_return = plst->running ? 0 : in->pid; |
/* return: 0 is running, pid is stopped/term */ |
out.errNo = 0; |
out.status = plst->state; /* last stopped reason if stopped */ |
out.thread = plst->thread;/* current thread (or -1 if none) from stop */ |
if (!out.wait_return) |
out.reason = STOP_NONE; /* running, no action */ |
else if (STS_SIGNALLED (out.status)) |
{ /* stopped on signal */ |
out.handle = STS_GETSIG (out.status); /* signal number */ |
if (out.handle == SIGTRAP) |
if (plst->is_step) |
{ /* single step with hitting a break */ |
out.reason = STOP_STEP; |
out.handle = 0; /* no information */ |
} |
else |
{ /* stopped on break */ |
out.reason = STOP_BREAK; |
if (plst->break_list) |
out.handle = ((BASE_BREAK*)plst->break_list)->last_break; |
else |
out.handle = 0; /* no break */ |
} |
else |
out.reason = STOP_SIGNAL; |
out.PC = plst->regs.REG_PC; /* copy standard regs */ |
out.SP = plst->regs.REG_SP; |
out.FP = plst->regs.REG_FP; |
} |
else |
{ /* terminated, so lower use count */ |
if (plst->last_start == LAST_KILLED) |
out.reason = STOP_KILLED; |
else if (plst->last_start == LAST_DETACHED) |
out.reason = STOP_DETACHED; |
else if (plst->last_start == LAST_START) |
{ /* failed in exec */ |
out.reason = STOP_SPAWN_FAILED; |
out.handle = STS_GETCODE (out.status); /* errno reason */ |
} |
else if (STS_TERMONSIG (out.status)) |
{ /* terminated on signal */ |
out.reason = STOP_TERM_SIG; |
/* mask off the core-dumped bit 7 */ |
out.handle = (int)(unsigned)(u_char) STS_TERMGETSIG (out.status); |
} |
else |
{ /* exit(2)ed */ |
out.reason = STOP_TERM_EXIT; |
out.handle = STS_GETCODE (out.status); /* code */ |
} |
} |
DPRINTF(("wait_info_2_svc: pid %d return %d status %x errNo %d" |
" reason %d handle %d pc %x sp %x fp %x thread %d\n", |
in->pid, out.wait_return, out.status, out.errNo, out.reason, |
out.handle, out.PC, out.SP, out.FP, out.thread)); |
return(&out); |
} |
} |
/* if not found in list, we return error: no such process */ |
out.wait_return = -1; |
out.errNo = ESRCH; /* no process */ |
out.status = 0; |
return(&out); |
} |
|
/* ----------------------------------------------------------------------- |
get_signal_names_2_svc - return names for signals |
----------------------------------------------------------------------- */ |
|
static one_signal SignalNames[] = { |
{SIGILL, "SIGILL/EVT_ILL"}, |
{SIGTRAP, "SIGTRAP/EVT_BKPT"}, |
{SIGFPE, "SIGFPE/EVT_FPE"}, |
{SIGKILL, "SIGKILL/EVT_AKILL"}, |
{SIGSEGV, "SIGSEGV/EVT_SEGV"}, |
{17, "SIGSTOP"}, |
{23, "SIGSTOP"} |
}; |
|
get_signal_names_out* RPCGENSRVNAME(get_signal_names_2_svc) (in, rqstp) |
void* in; |
struct svc_req *rqstp; /* server info */ |
{ |
static get_signal_names_out out; |
|
out.signals.all_signals_len = sizeof SignalNames / sizeof SignalNames[0]; |
out.signals.all_signals_val = SignalNames; |
|
return(&out); |
} |
/servtsp.c
0,0 → 1,331
/* |
************************************************************************** |
* |
* Component: RDBG |
* Module: servtsp.c |
* |
* Synopsis: Transport management for remote debug server. |
* |
* $Id: servtsp.c,v 1.2 2001-09-27 12:02:01 chris Exp $ |
* |
************************************************************************** |
*/ |
|
#include <sys/errno.h> |
#include <rdbg/rdbg.h> |
#include <rdbg/servrpc.h> |
#include <signal.h> |
#include <rpc/rpc.h> |
#include <rpc/svc.h> |
#include <netinet/in.h> |
#include <sys/socket.h> |
|
static int out_sock; |
static int warm_test; |
|
static void TimeTestHandler(); |
|
/* |
* TspInit - Initialize the transport system. |
* |
*/ |
|
void |
TspInit (int id) |
{ |
struct sigaction sa; |
|
/* setup a socket to send event messages back through */ |
out_sock = socket (PF_INET, SOCK_DGRAM, 0); |
if (out_sock < 0) { |
DPRINTF (("TspInit: socket() failed %d errno %d\n", |
out_sock, getErrno())); |
return; /* failed to open socket, let caller deal with */ |
} |
{ |
struct sockaddr_in addr; |
|
bzero ((void *)(&addr), sizeof addr); |
addr.sin_family = AF_INET; |
addr.sin_port = htons (BackPort); |
if (bind (out_sock, (struct sockaddr*) &addr, sizeof addr) < 0) { |
DPRINTF (("TspInit: bind() failed\n")); |
} |
} |
/* setup alarm timer for warm testing */ |
memset (&sa, 0, sizeof (sa)); |
sa.sa_handler = TimeTestHandler; |
sigaction (SIGALRM, &sa, 0); |
} |
|
/* |
* TspTranslateRpcAddr - translate from an RPC handle to an |
* opaque address. |
* |
* Converts the sender's address into the opaque data structure |
* used for network addresses. This is used to look up the sender |
* on each call. |
*/ |
|
Boolean |
TspTranslateRpcAddr (struct svc_req* rqstp, NET_OPAQUE* opaque) |
{ |
struct sockaddr_in* addr; /* used as template to extract net info */ |
unsigned char* up; |
|
memset (opaque, 0, sizeof (NET_OPAQUE)); |
/* |
* We interpret the remote address as a standard netbuf name. |
* The format is 2 bytes of address family (normally AF_INET) |
* and then a length (5) and then the IP address. |
*/ |
if (rqstp->rq_xprt->xp_addrlen != 16) |
{ |
DPRINTF (("TspTranslateRpcAddr: Unknown remote address!!!\n")); |
setErrno (EPROTONOSUPPORT); |
return False; /* invalid, so fails */ |
} |
/* addr = &rqstp->rq_xprt->xp_raddr; */ |
addr = svc_getcaller (rqstp->rq_xprt); |
/* verify it is AF_INET */ |
if (addr->sin_family != AF_INET) { /* no, error */ |
DPRINTF (("TspTranslateRpcAddr: Not an internet address!!\n")); |
setErrno (EAFNOSUPPORT);/* invalid addr family */ |
return False; |
} |
/* good address type */ |
up = (unsigned char *) &addr->sin_addr.s_addr; |
DPRINTF (("TspTranslateRpcAddr: Sent by %u.%u.%u.%u port #%u\n", |
up[0], up[1], up[2], up[3], htons (addr->sin_port))); |
memcpy (opaque, addr, sizeof (struct sockaddr_in)); |
return True; |
} |
|
/* |
* TspValidateAddr - validate a passed in opaque address. |
* |
* Checks that the passed in address is in the format |
* expected. |
*/ |
|
Boolean |
TspValidateAddr (NET_OPAQUE* opaque, NET_OPAQUE* sender) |
{ |
struct sockaddr_in* addr; /* used as template to extract net info */ |
|
addr = (struct sockaddr_in*) opaque; |
/* Verify it is AF_INET. Should check against sender IP address too */ |
if (addr->sin_family != AF_INET) { |
DPRINTF (("TspValidateAddr: Back port invalid: %d\n", |
htons (addr->sin_port))); |
return False; /* not valid */ |
} |
/* otherwise, we copy in the IP address, since client may not know it */ |
addr->sin_addr.s_addr = ((struct sockaddr_in*) sender)->sin_addr.s_addr; |
DPRINTF (("TspValidateAddr: Back port is %d\n", htons (addr->sin_port))); |
return True; |
} |
|
/* |
* TspConnGetIndex - lookup an rpc caller's address as a connection entry. |
* |
* Looks up an ip address of a caller to locate the |
* connection index in our connection array. |
*/ |
|
int |
TspConnGetIndex (struct svc_req* rqstp) |
{ |
int conn; |
/* &rqstp->rq_xprt->xp_raddr; */ |
struct sockaddr_in *addr = svc_getcaller (rqstp->rq_xprt); |
|
for (conn = 0; conn < conn_list_cnt; conn++) { |
if (!conn_list[conn].in_use) |
continue; /* not used */ |
|
if (addr->sin_addr.s_addr == ((struct sockaddr_in *) |
&conn_list [conn].sender)->sin_addr.s_addr |
&& addr->sin_port == ((struct sockaddr_in *) |
&conn_list[conn].sender)->sin_port) { |
return conn; |
} |
} |
return -1; |
} |
|
|
/* |
* TspSendWaitChange - send wait-change message to clients to |
* notify change. |
*/ |
|
void |
TspSendWaitChange( |
int conn, /* connection to send to */ |
BACK_MSG msg, /* BMSG type */ |
UINT16 spec, /* special information */ |
PID pid, /* pid it refers to */ |
UINT32 context, /* additional context for message */ |
Boolean force) /* force into being only message */ |
{ |
int idx; |
struct SEND_LIST* snd_ptr; |
|
if (force) { |
/* force to top, which means others gone */ |
idx = 0; |
conn_list [conn].send_idx = 1; |
conn_list[conn].retry = 0; |
} else { |
for (idx = 0; idx < (int) conn_list[conn].send_idx; idx++) { |
if (conn_list[conn].send_list[idx].send_type == msg |
&& conn_list[conn].send_list[idx].pid == pid) |
return; /* already pended for this pid */ |
} |
idx = conn_list[conn].send_idx; |
if (idx+1 > MAX_SEND) |
return; /* we lose it, what should we do??? */ |
conn_list[conn].send_idx++; |
} |
snd_ptr = &conn_list[conn].send_list[idx]; |
snd_ptr->send_type = msg; /* message to send */ |
snd_ptr->retry = TSP_RETRIES; /* about 1 minute of retries */ |
snd_ptr->spec = htons ((u_short) spec); |
snd_ptr->pid = htonl (pid); |
snd_ptr->context = htonl (context); |
TspSendMessage (conn, False); /* now do the send */ |
} |
|
/* |
* TspSendMessage - send message at top of send list for connection. |
*/ |
|
void |
TspSendMessage( int conn, Boolean resend) |
{ |
struct sockaddr_in addr; |
struct UDP_MSG msg; |
int cnt; |
|
if (!resend && conn_list[conn].retry) |
return; /* already waiting for reply */ |
|
/* |
* Note on above: if no back port we can't remove unless |
* someone blows off. |
*/ |
if (!resend) { |
/* first time, setup. Set retry count: */ |
conn_list[conn].retry = conn_list[conn].send_list[0].retry; |
conn_list[conn].last_msg_num++; /* new sequence number */ |
if (!warm_test++) { /* starting, so enable timer */ |
alarm (2); /* resend every 2 seconds as needed */ |
} |
} |
|
msg.type = conn_list[conn].send_list[0].send_type; |
msg.msg_num = conn_list[conn].last_msg_num; |
msg.spec = conn_list[conn].send_list[0].spec; |
msg.pid = conn_list[conn].send_list[0].pid; |
msg.context = conn_list[conn].send_list[0].context; |
|
memset (&addr, 0, sizeof addr); |
addr.sin_family = AF_INET; |
addr.sin_port = ((struct sockaddr_in*)&conn_list[conn].back_port)->sin_port; |
addr.sin_addr.s_addr = |
((struct sockaddr_in*)&conn_list[conn].back_port)->sin_addr.s_addr; |
|
DPRINTF (("TspSendMessage: Sending msg %d (%s) to port %d\n", |
msg.type, BmsgNames [msg.type], HL_W (addr.sin_port))); |
|
cnt = sendto (out_sock, &msg, sizeof msg, 0, (struct sockaddr*) &addr, |
sizeof addr); |
if (cnt != sizeof msg) { /* failed on send */ |
printf ("%s: Failed to send msg %d to conn %d (%d vs. %d)\n", |
ActName, msg.type, conn, cnt, sizeof msg); |
} |
} |
|
/* |
* TspMessageReceive - confirmation received, now send next if any. |
* |
* - since UDP is connectionless, we batch up the sends and use |
* one at a time until we get a message indicating ready for |
* next (from ack). |
*/ |
|
void |
TspMessageReceive (int conn, PID pid) |
{ |
/* We remove the send list entry and use next if any */ |
conn_list[conn].retry = 0; /* reset */ |
if (!warm_test || !--warm_test) { |
alarm (0); /* reset timer if not used */ |
} |
#ifdef DDEBUG |
if (conn_list[conn].send_list[0].send_type == BMSG_WARM) { |
DPRINTF (("TspMessageReceive: Connection reset for conn %d\n", conn)); |
} |
#endif |
/* Move up by one if needed */ |
if (!--conn_list[conn].send_idx) |
return; /* no more to do */ |
|
memcpy (conn_list[conn].send_list, conn_list[conn].send_list+1, |
conn_list[conn].send_idx * sizeof(struct SEND_LIST)); /* copy down */ |
TspSendMessage (conn, 0); |
} |
|
/* |
* TspGetHostName - return client's host name. |
* |
* - this routine returns the name of the client's host or the net |
* number of unknown. |
*/ |
|
char* |
TspGetHostName (conn_idx) |
int conn_idx; /* client connection number */ |
{ |
static char buff [30]; /* largest net num */ |
unsigned char* cp; |
|
cp = conn_list[conn_idx].sender.c+4; |
sprintf (buff, "%u.%u.%u.%u", cp[0], cp[1], cp[2], cp[3]); |
return buff; |
} |
|
/* |
* TimeTestHandler - alarm timer handler to resend warm/wait test. |
*/ |
|
static void |
TimeTestHandler() |
{ |
int conn; |
|
if (!warm_test) |
return; /* no longer enabled */ |
|
for (conn = 0; conn < conn_list_cnt; conn++) { |
/* locate all that are using this */ |
if (!conn_list[conn].in_use) |
continue; /* not used */ |
|
if (!conn_list[conn].retry) continue; |
/* found one that we are testing */ |
if (!--conn_list[conn].retry) { |
/* |
* Counted down the retries: blow off. |
* Need to have connection flag to indicate not blowing |
* off for cases where client is stopped due to being |
* debugged. |
*/ |
ConnDelete (conn, NULL, CLOSE_IGNORE); |
continue; |
} |
TspSendMessage (conn, True); /* send another message */ |
} |
alarm (2); /* setup for 2 seconds from now */ |
} |
/Makefile.am
0,0 → 1,13
## |
## $Id: Makefile.am,v 1.2 2001-09-27 12:02:01 chris Exp $ |
## |
|
AUTOMAKE_OPTIONS = foreign 1.4 |
|
SUBDIRS = $(RTEMS_CPU) |
|
EXTRA_DIST = _servtgt.c awk.svc excep.c ptrace.c rdbg.c remdeb.x servbkpt.c \ |
servcon.c servrpc.c servtgt.c servtsp.c servutil.c |
|
include $(top_srcdir)/../../../automake/subdirs.am |
include $(top_srcdir)/../../../automake/local.am |
/i386/rdbg_f.c
0,0 → 1,155
/* |
************************************************************************** |
* |
* Component = |
* |
* Synopsis = rdbg/i386/rdbg_f.c |
* |
* $Id: rdbg_f.c,v 1.2 2001-09-27 12:02:01 chris Exp $ |
* |
************************************************************************** |
*/ |
|
#include <assert.h> |
#include <errno.h> |
#include <rdbg/reg.h> |
#include <rdbg/remdeb.h> |
#include <rdbg/rdbg.h> |
#include <rtems/score/cpu.h> |
#include <rtems/score/thread.h> |
|
|
void |
CtxToRegs (const CPU_Exception_frame* ctx, xdr_regs* regs) |
{ |
regs->tabreg [GS] = 0; |
regs->tabreg [FS] = 0; |
regs->tabreg [ES] = 0; |
regs->tabreg [DS] = 0; |
regs->tabreg [EDI] = ctx->edi; |
regs->tabreg [ESI] = ctx->esi; |
regs->tabreg [EBP] = ctx->ebp; |
regs->tabreg [ESP] = ctx->esp0; |
regs->tabreg [EBX] = ctx->ebx; |
regs->tabreg [EDX] = ctx->edx; |
regs->tabreg [ECX] = ctx->ecx; |
regs->tabreg [EAX] = ctx->eax; |
regs->tabreg [TRAPNO] = ctx->idtIndex; |
regs->tabreg [ERR] = ctx->faultCode; |
regs->tabreg [EIP] = ctx->eip; |
regs->tabreg [CS] = ctx->cs & 0xFFFF; |
regs->tabreg [EFL] = ctx->eflags; |
} |
|
|
void |
RegsToCtx (const xdr_regs* regs, CPU_Exception_frame* ctx) |
{ |
ctx->edi = regs->tabreg [EDI]; |
ctx->esi = regs->tabreg [ESI]; |
ctx->ebp = regs->tabreg [EBP]; |
ctx->esp0 = regs->tabreg [ESP]; |
ctx->ebx = regs->tabreg [EBX]; |
ctx->edx = regs->tabreg [EDX]; |
ctx->ecx = regs->tabreg [ECX]; |
ctx->eax = regs->tabreg [EAX]; |
ctx->idtIndex = regs->tabreg [TRAPNO]; |
ctx->faultCode = regs->tabreg [ERR]; |
ctx->eip = regs->tabreg [EIP]; |
ctx->cs = regs->tabreg [CS]; |
ctx->eflags = regs->tabreg [EFL]; |
} |
|
void |
get_ctx_thread( Thread_Control *thread, CPU_Exception_frame* ctx) |
{ |
ctx->edi = thread->Registers.edi; |
ctx->esi = thread->Registers.esi; |
ctx->ebp = (unsigned32)(thread->Registers.ebp); |
ctx->esp0 = (unsigned32)(thread->Registers.esp); |
ctx->ebx = thread->Registers.ebx; |
ctx->edx = 0; |
ctx->ecx = 0; |
ctx->eax = 0; |
ctx->idtIndex = 0; |
ctx->faultCode = 0; |
ctx->eip = *(unsigned int*)(thread->Registers.esp); |
ctx->cs = 0; |
ctx->eflags = thread->Registers.eflags; |
} |
|
void |
set_ctx_thread( Thread_Control *thread, CPU_Exception_frame* ctx) |
{ |
thread->Registers.edi = ctx->edi; |
thread->Registers.esi = ctx->esi; |
thread->Registers.ebp = (void*)(ctx->ebp); |
thread->Registers.esp = (void*)(ctx->esp0); |
thread->Registers.ebx = ctx->ebx; |
thread->Registers.eflags = ctx->eflags; |
} |
|
|
|
int |
Single_Step(CPU_Exception_frame* ctx) |
{ |
/* Check if not already set */ |
if ((ctx->eflags & EFLAGS_TF) != 0 || ExitForSingleStep != 0) { |
/* Check coherency */ |
assert ((ctx->eflags & EFLAGS_TF) != 0); |
assert (ExitForSingleStep != 0); |
return 0; |
} |
ctx->eflags |= EFLAGS_TF; /* eflags */ |
++ExitForSingleStep; |
|
return 0; |
} |
|
int |
CheckForSingleStep (CPU_Exception_frame* ctx) |
{ |
if (ExitForSingleStep) { |
/* |
* This functions can be called both from |
* INT1 and INT3 handlers. In case it is |
* called from INT3, need to clear TF. |
*/ |
ctx->eflags &= ~EFLAGS_TF; |
ExitForSingleStep = 0; |
return 1; |
} |
return 0; |
} |
|
void |
CancelSingleStep (CPU_Exception_frame* ctx) |
{ |
/* Cancel scheduled SS */ |
ctx->eflags &= ~EFLAGS_TF; |
ExitForSingleStep-- ; |
} |
|
cpuExcHandlerType old_currentExcHandler; |
extern void rtems_exception_prologue_50(); |
|
void connect_rdbg_exception() |
{ |
interrupt_gate_descriptor *currentIdtEntry; |
unsigned limit; |
unsigned level; |
|
/* |
* Connect the Exception used to debug |
*/ |
i386_get_info_from_IDTR (¤tIdtEntry, &limit); |
|
_CPU_ISR_Disable(level); |
create_interrupt_gate_descriptor (¤tIdtEntry[50], rtems_exception_prologue_50); |
_CPU_ISR_Enable(level); |
|
old_currentExcHandler = _currentExcHandler; |
_currentExcHandler = BreakPointExcHdl ; |
|
} |
/i386/rdbg_cpu_asm.S
0,0 → 1,72
/* cpu_asm.s |
* |
* This file contains all assembly code for the Intel i386 implementation |
* of RDBG. |
* |
* $Id: rdbg_cpu_asm.S,v 1.2 2001-09-27 12:02:01 chris Exp $ |
* |
*/ |
|
#include <asm.h> |
|
BEGIN_CODE |
|
/* |
* void copyback_data_cache_and_invalidate_instr_cache(addr, size) |
* |
* This routine performs a copy of the data cache |
* and invalidate the instruction cache |
*/ |
|
.p2align 1 |
PUBLIC (copyback_data_cache_and_invalidate_instr_cache) |
|
SYM (copyback_data_cache_and_invalidate_instr_cache): |
wbinvd |
ret |
|
|
|
/* |
* void enterRdbg(void) |
* |
* This function perform a call to the exception 19 |
* It is used : |
* 1 - in the user code, to simulate a Breakpoint. |
* (with justSaveContext = 0) |
* 2 - in the RDBG code, to push a ctx in the list. |
* (with justSaveContext = 1) |
* |
* In most of case, it will be use as described in 1. |
* The 2nd possibility will be used by RDBG to obtain |
* its own ctx |
*/ |
|
PUBLIC (enterRdbg) |
|
SYM (enterRdbg): |
int $50 |
ret |
|
|
/* |
* void rtems_exception_prologue_50(void) |
* |
* Exception 50 is used to enter Rdbg |
* |
*/ |
|
.p2align 4 |
|
PUBLIC (rtems_exception_prologue_50) |
PUBLIC (_Exception_Handler) |
|
SYM (rtems_exception_prologue_50): |
pushl $ 0 |
pushl $ 50 |
jmp SYM(_Exception_Handler) ; |
|
|
END_CODE |
|
END |
/i386/any/remdeb.h
0,0 → 1,559
/* |
* Please do not edit this file. |
* It was generated using rpcgen. |
*/ |
|
#ifndef _REMDEB_H_RPCGEN |
#define _REMDEB_H_RPCGEN |
|
#include <rpc/rpc.h> |
|
|
#ifdef __cplusplus |
extern "C" { |
#endif |
|
#define RTEMS_PORT 2071 |
#define RTEMS_BACK_PORT 2073 |
#ifndef REMDEB_H |
#define RPCGENSRVNAME(a) a |
|
enum rpc_type { |
SUNRPC = 0, |
BADRPCTYPE = 25, |
}; |
typedef enum rpc_type rpc_type; |
#define NET_SAFE 1400 |
|
struct UDP_MSG { |
u_char type; |
u_char msg_num; |
u_short spec; |
long pid; |
u_long context; |
}; |
typedef struct UDP_MSG UDP_MSG; |
/* |
* Sun request values for the remote ptrace system call |
*/ |
|
|
enum ptracereq { |
RPT_TRACEME = 0, |
RPT_CHILDDONE = 0, |
RPT_PEEKTEXT = 0 + 1, |
RPT_PEEKDATA = 0 + 2, |
RPT_PEEKUSER = 0 + 3, |
RPT_POKETEXT = 0 + 4, |
RPT_POKEDATA = 0 + 5, |
RPT_POKEUSER = 0 + 6, |
RPT_CONT = 0 + 7, |
RPT_KILL = 0 + 8, |
RPT_SINGLESTEP = 0 + 9, |
RPT_ATTACH = 0 + 10, |
RPT_DETACH = 0 + 11, |
RPT_GETREGS = 0 + 12, |
RPT_SETREGS = 0 + 13, |
RPT_GETFPREGS = 0 + 14, |
RPT_SETFPREGS = 0 + 15, |
RPT_READDATA = 0 + 16, |
RPT_WRITEDATA = 0 + 17, |
RPT_READTEXT = 0 + 18, |
RPT_WRITETEXT = 0 + 19, |
RPT_GETFPAREGS = 0 + 20, |
RPT_SETFPAREGS = 0 + 21, |
RPT_22 = 0 + 22, |
RPT_23 = 0 + 23, |
RPT_SYSCALL = 0 + 24, |
RPT_DUMPCORE = 0 + 25, |
RPT_26 = 0 + 26, |
RPT_27 = 0 + 27, |
RPT_28 = 0 + 28, |
RPT_GETUCODE = 0 + 29, |
RPT_GETTARGETTHREAD = 50, |
RPT_SETTARGETTHREAD = 51, |
RPT_THREADSUSPEND = 52, |
RPT_THREADRESUME = 53, |
RPT_THREADLIST = 54, |
RPT_GETTHREADNAME = 55, |
RPT_SETTHREADNAME = 56, |
RPT_SETTHREADREGS = 57, |
RPT_GETTHREADREGS = 58, |
RPT_STEPRANGE = 75, |
RPT_CONTTO = 76, |
RPT_SETBREAK = 77, |
RPT_CLRBREAK = 78, |
RPT_GETBREAK = 79, |
RPT_GETNAME = 80, |
RPT_STOP = 81, |
RPT_PGETREGS = 82, |
RPT_PSETREGS = 83, |
RPT_PSETTHREADREGS = 84, |
RPT_PGETTHREADREGS = 85, |
}; |
typedef enum ptracereq ptracereq; |
|
struct xdr_regs { |
u_int tabreg[19]; |
}; |
typedef struct xdr_regs xdr_regs; |
/* now define register macros to apply to xdr_reg struct */ |
|
#define GS 0 |
#define FS 1 |
#define ES 2 |
#define DS 3 |
#define EDI 4 |
#define ESI 5 |
#define EBP 6 |
#define ESP 7 |
#define EBX 8 |
#define EDX 9 |
#define ECX 10 |
#define EAX 11 |
#define TRAPNO 12 |
#define ERR 13 |
#define EIP 14 |
#define CS 15 |
#define EFL 16 |
#define UESP 17 |
#define SS 18 |
|
#define REG_PC tabreg[EIP] /* PC (eip) register offset */ |
#define REG_SP tabreg[UESP] /* SP (uesp) register offset */ |
#define REG_FP tabreg[EBP] /* FP (ebp) register offset */ |
/* now define the BREAKPOINT mask technique to a long word */ |
#define SET_BREAK(l) ((l&0xFFFFFF00) | 0xCC) |
#define IS_BREAK(l) (((l) & 0xFF) == 0xCC) |
#define ORG_BREAK(c,p) (((c) & 0xFFFFFF00) | ((p) & 0xFF)) |
#define IS_STEP(regs) (regs.tabreg[TRAPNO] == 1) /* was step and not break */ |
#define BREAK_ADJ 1 /* must subtract one from address after bp */ |
#define BREAK_SIZE 1 /* Breakpoint occupies one byte */ |
#define TARGET_PROC_TYPE 0 |
#define MAXDEBUGGEE 150 |
#define NAMEMAX 17 |
/* |
* Memory data for read/write text or data. The size is in data. The target |
* addr is in the addr field. |
* Be careful before modifying because this value goes into internal |
* pipes and is allocated on stack too. Pipes and/or the stack could |
* become too small if this value gets incremented. |
*/ |
#define MEM_DATA_MAX 256 |
|
struct xdr_mem { |
u_long addr; |
u_int dataNb; |
u_char data[MEM_DATA_MAX]; |
}; |
typedef struct xdr_mem xdr_mem; |
|
enum break_type { |
BRKT_NONE = 0, |
BRKT_INSTR = 1, |
BRKT_READ = 2, |
BRKT_WRITE = 3, |
BRKT_ACCESS = 4, |
BRKT_EXEC = 5, |
BRKT_OS_CALL = 6, |
BRKT_OS_SWITCH = 7, |
BRKT_STEPEMUL = 8, |
}; |
typedef enum break_type break_type; |
#define MAX_THRD_BRK 4 |
|
struct xdr_break { |
u_char type; |
u_char thread_spec; |
u_short handle; |
u_long ee_loc; |
u_long ee_type; |
u_short length; |
u_char pass_count; |
u_char curr_pass; |
u_long thread_list[MAX_THRD_BRK]; |
}; |
typedef struct xdr_break xdr_break; |
#define UTHREAD_MAX 64 |
#define THREADNAMEMAX 16 |
|
typedef char *thread_name; |
|
struct KernThread { |
u_int threadLi; |
}; |
typedef struct KernThread KernThread; |
typedef KernThread *ptThreadList; |
|
struct thread_list { |
u_int nbThread; |
ptThreadList threads; |
}; |
typedef struct thread_list thread_list; |
|
struct ptrace_addr_data_in { |
ptracereq req; |
union { |
xdr_regs regs; |
struct { |
u_int pregs_len; |
u_int *pregs_val; |
} pregs; |
thread_name name; |
xdr_mem mem; |
xdr_break breakp; |
u_int address; |
} ptrace_addr_data_in_u; |
}; |
typedef struct ptrace_addr_data_in ptrace_addr_data_in; |
|
struct ptrace_addr_data_out { |
ptracereq req; |
union { |
xdr_regs regs; |
struct { |
u_int pregs_len; |
u_int *pregs_val; |
} pregs; |
thread_list threads; |
thread_name name; |
xdr_mem mem; |
xdr_break breakp; |
u_int addr; |
} ptrace_addr_data_out_u; |
}; |
typedef struct ptrace_addr_data_out ptrace_addr_data_out; |
|
typedef struct { |
u_int CHAR_DATA_len; |
char *CHAR_DATA_val; |
} CHAR_DATA; |
#define XRY_MAX_INST_BUFF 128 |
#define XRY_MAX_INSTANCES 16 |
#ifndef XRY_MAX_CMD_STR |
#define XRY_MAX_CMD_STR 320 |
#endif /* REMDEB_H */ |
|
struct xry_inst { |
u_char flags; |
u_char type; |
u_char sub_type; |
u_char res_type; |
u_long value; |
u_long value2; |
}; |
typedef struct xry_inst xry_inst; |
|
struct instance { |
struct xry_inst instances[XRY_MAX_INSTANCES]; |
u_char buffer[XRY_MAX_INST_BUFF]; |
}; |
typedef struct instance instance; |
|
struct instance_union { |
bool_t instances; |
union { |
instance inst; |
char *buffer; |
} instance_union_u; |
}; |
typedef struct instance_union instance_union; |
|
typedef char *one_arg; |
#define XRY_MAX_OBJ_NAME 32 |
/* now open_connex() routine which establishes a connection to server */ |
|
enum debug_type { |
DEBTYP_PROCESS = 0, |
DEBTYP_C_ACTOR = 1, |
DEBTYP_KERNEL = 2, |
DEBTYP_OTHER = 3, |
}; |
typedef enum debug_type debug_type; |
#define DEBUGGER_IS_GDB 0x2 /* */ |
|
struct open_in { |
u_char back_port[16]; |
u_short debug_type; |
u_short flags; |
u_char destination[16]; |
one_arg user_name; |
}; |
typedef struct open_in open_in; |
|
struct open_out { |
u_long port; |
u_int pad[4]; |
u_int fp; |
u_char cmd_table_num; |
u_char cmd_table_vers; |
u_short server_vers; |
}; |
typedef struct open_out open_out; |
/* now close_connex() routine which detaches from server */ |
|
enum close_control { |
CLOSE_IGNORE = 0, |
CLOSE_KILL = 1, |
CLOSE_DETACH = 2, |
}; |
typedef enum close_control close_control; |
|
struct close_in { |
close_control control; |
}; |
typedef struct close_in close_in; |
/* now send_signal() routine which sends signals to processes like kill(2) */ |
|
struct signal_in { |
int pid; |
int sig; |
}; |
typedef struct signal_in signal_in; |
|
struct signal_out { |
int kill_return; |
int errNo; |
}; |
typedef struct signal_out signal_out; |
/* now wait_info() routine which returns results of polling the wait status |
of a process/actor. It may return 0 if running, else pid or -1 */ |
|
enum stop_code { |
STOP_ERROR = 0, |
STOP_NONE = 1, |
STOP_UNKNOWN = 2, |
STOP_BREAK = 3, |
STOP_STEP = 4, |
STOP_SIGNAL = 5, |
STOP_TERM_EXIT = 6, |
STOP_TERM_SIG = 7, |
STOP_DETACHED = 8, |
STOP_KILLED = 9, |
STOP_SPAWN_FAILED = 10, |
}; |
typedef enum stop_code stop_code; |
|
struct wait_in { |
int pid; |
}; |
typedef struct wait_in wait_in; |
|
struct wait_out { |
int wait_return; |
int errNo; |
int status; |
stop_code reason; |
int handle; |
u_long PC; |
u_long SP; |
u_long FP; |
u_long thread; |
}; |
typedef struct wait_out wait_out; |
/* now ptrace() routine. This matches the Sun UNIX ptrace as well as |
some additions */ |
#define PTRFLG_FORCE 1 |
#define PTRFLG_NON_OWNER 2 |
#define PTRFLG_FREE 4 |
#define PTRDET_UNOWN 0x100 |
|
struct ptrace_in { |
int pid; |
ptrace_addr_data_in addr; |
u_int data; |
u_int flags; |
}; |
typedef struct ptrace_in ptrace_in; |
|
struct ptrace_out { |
ptrace_addr_data_out addr; |
int result; |
int errNo; |
}; |
typedef struct ptrace_out ptrace_out; |
|
struct one_symbol { |
char *symbolName; |
long symbolValue; |
}; |
typedef struct one_symbol one_symbol; |
|
typedef struct { |
u_int all_symbols_len; |
one_symbol *all_symbols_val; |
} all_symbols; |
|
struct get_global_symbols_out { |
all_symbols symbols; |
}; |
typedef struct get_global_symbols_out get_global_symbols_out; |
|
struct get_text_data_in { |
int pid; |
char *actorName; |
}; |
typedef struct get_text_data_in get_text_data_in; |
|
struct get_text_data_out { |
int result; |
int errNo; |
u_long textStart; |
u_long textSize; |
u_long dataStart; |
u_long dataSize; |
}; |
typedef struct get_text_data_out get_text_data_out; |
|
struct one_signal { |
u_int number; |
char *name; |
}; |
typedef struct one_signal one_signal; |
|
typedef struct { |
u_int all_signals_len; |
one_signal *all_signals_val; |
} all_signals; |
|
struct get_signal_names_out { |
all_signals signals; |
}; |
typedef struct get_signal_names_out get_signal_names_out; |
/* now define the actual calls we support */ |
#define REMDEB_H |
#endif |
|
#define REMOTEDEB 0x20000fff |
#define REMOTEVERS 2 |
|
#if defined(__STDC__) || defined(__cplusplus) |
#define OPEN_CONNEX 1 |
extern open_out * open_connex_2(open_in *, CLIENT *); |
extern open_out * open_connex_2_svc(open_in *, struct svc_req *); |
#define SEND_SIGNAL 2 |
extern signal_out * send_signal_2(signal_in *, CLIENT *); |
extern signal_out * send_signal_2_svc(signal_in *, struct svc_req *); |
#define CLOSE_CONNEX 10 |
extern void * close_connex_2(close_in *, CLIENT *); |
extern void * close_connex_2_svc(close_in *, struct svc_req *); |
#define PTRACE 11 |
extern ptrace_out * ptrace_2(ptrace_in *, CLIENT *); |
extern ptrace_out * ptrace_2_svc(ptrace_in *, struct svc_req *); |
#define WAIT_INFO 13 |
extern wait_out * wait_info_2(wait_in *, CLIENT *); |
extern wait_out * wait_info_2_svc(wait_in *, struct svc_req *); |
#define GET_SIGNAL_NAMES 17 |
extern get_signal_names_out * get_signal_names_2(void *, CLIENT *); |
extern get_signal_names_out * get_signal_names_2_svc(void *, struct svc_req *); |
extern int remotedeb_2_freeresult (SVCXPRT *, xdrproc_t, caddr_t); |
|
#else /* K&R C */ |
#define OPEN_CONNEX 1 |
extern open_out * open_connex_2(); |
extern open_out * open_connex_2_svc(); |
#define SEND_SIGNAL 2 |
extern signal_out * send_signal_2(); |
extern signal_out * send_signal_2_svc(); |
#define CLOSE_CONNEX 10 |
extern void * close_connex_2(); |
extern void * close_connex_2_svc(); |
#define PTRACE 11 |
extern ptrace_out * ptrace_2(); |
extern ptrace_out * ptrace_2_svc(); |
#define WAIT_INFO 13 |
extern wait_out * wait_info_2(); |
extern wait_out * wait_info_2_svc(); |
#define GET_SIGNAL_NAMES 17 |
extern get_signal_names_out * get_signal_names_2(); |
extern get_signal_names_out * get_signal_names_2_svc(); |
extern int remotedeb_2_freeresult (); |
#endif /* K&R C */ |
|
/* the xdr functions */ |
|
#if defined(__STDC__) || defined(__cplusplus) |
extern bool_t xdr_rpc_type (XDR *, rpc_type*); |
extern bool_t xdr_UDP_MSG (XDR *, UDP_MSG*); |
extern bool_t xdr_ptracereq (XDR *, ptracereq*); |
extern bool_t xdr_xdr_regs (XDR *, xdr_regs*); |
extern bool_t xdr_xdr_mem (XDR *, xdr_mem*); |
extern bool_t xdr_break_type (XDR *, break_type*); |
extern bool_t xdr_xdr_break (XDR *, xdr_break*); |
extern bool_t xdr_thread_name (XDR *, thread_name*); |
extern bool_t xdr_KernThread (XDR *, KernThread*); |
extern bool_t xdr_thread_list (XDR *, thread_list*); |
extern bool_t xdr_ptrace_addr_data_in (XDR *, ptrace_addr_data_in*); |
extern bool_t xdr_ptrace_addr_data_out (XDR *, ptrace_addr_data_out*); |
extern bool_t xdr_CHAR_DATA (XDR *, CHAR_DATA*); |
extern bool_t xdr_xry_inst (XDR *, xry_inst*); |
extern bool_t xdr_instance (XDR *, instance*); |
extern bool_t xdr_instance_union (XDR *, instance_union*); |
extern bool_t xdr_one_arg (XDR *, one_arg*); |
extern bool_t xdr_debug_type (XDR *, debug_type*); |
extern bool_t xdr_open_in (XDR *, open_in*); |
extern bool_t xdr_open_out (XDR *, open_out*); |
extern bool_t xdr_close_control (XDR *, close_control*); |
extern bool_t xdr_close_in (XDR *, close_in*); |
extern bool_t xdr_signal_in (XDR *, signal_in*); |
extern bool_t xdr_signal_out (XDR *, signal_out*); |
extern bool_t xdr_stop_code (XDR *, stop_code*); |
extern bool_t xdr_wait_in (XDR *, wait_in*); |
extern bool_t xdr_wait_out (XDR *, wait_out*); |
extern bool_t xdr_ptrace_in (XDR *, ptrace_in*); |
extern bool_t xdr_ptrace_out (XDR *, ptrace_out*); |
extern bool_t xdr_one_symbol (XDR *, one_symbol*); |
extern bool_t xdr_all_symbols (XDR *, all_symbols*); |
extern bool_t xdr_get_global_symbols_out (XDR *, get_global_symbols_out*); |
extern bool_t xdr_get_text_data_in (XDR *, get_text_data_in*); |
extern bool_t xdr_get_text_data_out (XDR *, get_text_data_out*); |
extern bool_t xdr_one_signal (XDR *, one_signal*); |
extern bool_t xdr_all_signals (XDR *, all_signals*); |
extern bool_t xdr_get_signal_names_out (XDR *, get_signal_names_out*); |
|
#else /* K&R C */ |
extern bool_t xdr_rpc_type (); |
extern bool_t xdr_UDP_MSG (); |
extern bool_t xdr_ptracereq (); |
extern bool_t xdr_xdr_regs (); |
extern bool_t xdr_xdr_mem (); |
extern bool_t xdr_break_type (); |
extern bool_t xdr_xdr_break (); |
extern bool_t xdr_thread_name (); |
extern bool_t xdr_KernThread (); |
extern bool_t xdr_thread_list (); |
extern bool_t xdr_ptrace_addr_data_in (); |
extern bool_t xdr_ptrace_addr_data_out (); |
extern bool_t xdr_CHAR_DATA (); |
extern bool_t xdr_xry_inst (); |
extern bool_t xdr_instance (); |
extern bool_t xdr_instance_union (); |
extern bool_t xdr_one_arg (); |
extern bool_t xdr_debug_type (); |
extern bool_t xdr_open_in (); |
extern bool_t xdr_open_out (); |
extern bool_t xdr_close_control (); |
extern bool_t xdr_close_in (); |
extern bool_t xdr_signal_in (); |
extern bool_t xdr_signal_out (); |
extern bool_t xdr_stop_code (); |
extern bool_t xdr_wait_in (); |
extern bool_t xdr_wait_out (); |
extern bool_t xdr_ptrace_in (); |
extern bool_t xdr_ptrace_out (); |
extern bool_t xdr_one_symbol (); |
extern bool_t xdr_all_symbols (); |
extern bool_t xdr_get_global_symbols_out (); |
extern bool_t xdr_get_text_data_in (); |
extern bool_t xdr_get_text_data_out (); |
extern bool_t xdr_one_signal (); |
extern bool_t xdr_all_signals (); |
extern bool_t xdr_get_signal_names_out (); |
|
#endif /* K&R C */ |
|
#ifdef __cplusplus |
} |
#endif |
|
#endif /* !_REMDEB_H_RPCGEN */ |
/i386/any/Makefile.am
0,0 → 1,90
## |
## $Id: Makefile.am,v 1.2 2001-09-27 12:02:01 chris Exp $ |
## |
|
AUTOMAKE_OPTIONS = foreign 1.4 |
|
VPATH = @srcdir@:@srcdir@/..:@srcdir@/../.. |
|
LIBNAME = librdbg |
LIB = ${ARCH}/${LIBNAME}.a |
|
# C and C++ source names |
C_FILES = rdbg.c servcon.c servbkpt.c servrpc.c excep.c excep_f.c servtgt.c \ |
servtsp.c servutil.c _servtgt.c rdbg_f.c ptrace.c |
C_O_FILES = $(C_FILES:%.c=${ARCH}/%.o) |
|
# Asm source names |
S_FILES = rdbg_cpu_asm.S |
S_O_FILES = $(S_FILES:%.S=${ARCH}/%.o) |
|
# Generated C source names |
GEN_C_FILES = remdeb_xdr.c remdeb_svc.c |
GEN_C_O_FILES = $(GEN_C_FILES:%.c=${ARCH}/%.o) |
|
# H source names |
H_FILES = remdeb.h |
|
# X source names |
X_FILES = remdeb.x remdeb_f.x |
|
OBJS = $(GEN_C_O_FILES) $(C_O_FILES) $(S_O_FILES) |
|
include $(RTEMS_ROOT)/make/custom/@RTEMS_BSP@.cfg |
include $(top_srcdir)/../../../automake/lib.am |
|
# |
# Add local stuff here using += |
# |
|
MAINTAINERCLEANFILES += $(H_FILES) $(GEN_C_FILES) |
|
FRONTEND = \"$(RTEMS_CPU)/any/remdeb_f.x\" |
|
$(PROJECT_RELEASE)/lib/$(LIBNAME)$(LIB_VARIANT).a: $(LIB) |
$(INSTALL_DATA) $< $@ |
|
$(LIB): ${OBJS} |
$(make-library) |
|
$(srcdir)/remdeb.h: $(X_FILES) |
if RPCTOOLS |
@rm -f $@ |
( cd $(top_srcdir)/src; \ |
$(RPCGEN) -h -DFRONTEND=$(FRONTEND) \ |
-o i386/any/remdeb.h remdeb.x ) |
endif |
$(srcdir)/remdeb_xdr.c: $(X_FILES) |
if RPCTOOLS |
@rm -f $@ |
( cd $(top_srcdir)/src; \ |
$(RPCGEN) -c -DFRONTEND=$(FRONTEND) \ |
-o i386/any/remdeb_xdr.c remdeb.x ) |
endif |
|
$(srcdir)/remdeb_svc.c: $(X_FILES) |
if RPCTOOLS |
@rm -f $@ tmpSvc.c |
( cd $(top_srcdir)/src; \ |
$(RPCGEN) -m -DFRONTEND=$(FRONTEND) \ |
-o i386/any/tmpSvc.c remdeb.x; \ |
$(AWK) -f ./awk.svc THEPROG="remdeb.h" i386/any/tmpSvc.c \ |
> i386/any/remdeb_svc.c; \ |
rm -f i386/any/tmpSvc.c ) |
endif |
|
$(PROJECT_INCLUDE)/rdbg/remdeb.h: $(srcdir)/remdeb.h |
$(INSTALL_DATA) $< $@ |
|
$(PROJECT_INCLUDE)/rdbg: |
@$(mkinstalldirs) $@ |
|
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rdbg $(PROJECT_INCLUDE)/rdbg/remdeb.h |
|
TMPINSTALL_FILES += $(PROJECT_RELEASE)/lib/$(LIBNAME)$(LIB_VARIANT).a |
|
all-local: ${ARCH} $(PREINSTALL_FILES) $(TMPINSTALL_FILES) |
|
EXTRA_DIST = remdeb_f.x $(GEN_C_FILES) |
|
include $(top_srcdir)/../../../automake/local.am |
/i386/any/remdeb_f.x
0,0 → 1,59
/* |
************************************************************************** |
* |
* Component = rdblib |
* |
* Synopsis = remdeb_f.x |
* |
* $Id: remdeb_f.x,v 1.2 2001-09-27 12:02:01 chris Exp $ |
* |
************************************************************************** |
*/ |
|
struct xdr_regs |
{ |
unsigned int tabreg[19]; |
}; |
|
#ifdef RPC_HDR |
|
%/* now define register macros to apply to xdr_reg struct */ |
% |
%#define GS 0 |
%#define FS 1 |
%#define ES 2 |
%#define DS 3 |
%#define EDI 4 |
%#define ESI 5 |
%#define EBP 6 |
%#define ESP 7 |
%#define EBX 8 |
%#define EDX 9 |
%#define ECX 10 |
%#define EAX 11 |
%#define TRAPNO 12 |
%#define ERR 13 |
%#define EIP 14 |
%#define CS 15 |
%#define EFL 16 |
%#define UESP 17 |
%#define SS 18 |
% |
%#define REG_PC tabreg[EIP] /* PC (eip) register offset */ |
%#define REG_SP tabreg[UESP] /* SP (uesp) register offset */ |
%#define REG_FP tabreg[EBP] /* FP (ebp) register offset */ |
|
%/* now define the BREAKPOINT mask technique to a long word */ |
%#define SET_BREAK(l) ((l&0xFFFFFF00) | 0xCC) |
%#define IS_BREAK(l) (((l) & 0xFF) == 0xCC) |
%#define ORG_BREAK(c,p) (((c) & 0xFFFFFF00) | ((p) & 0xFF)) |
%#define IS_STEP(regs) (regs.tabreg[TRAPNO] == 1) /* was step and not break */ |
%#define BREAK_ADJ 1 /* must subtract one from address after bp */ |
%#define BREAK_SIZE 1 /* Breakpoint occupies one byte */ |
|
%#define TARGET_PROC_TYPE 0 |
|
#endif |
|
|
|
/i386/any/remdeb_svc.c
0,0 → 1,122
#include <rpc/types.h> |
#include <rpc/rpc.h> |
#include <stdio.h> |
#include <stdlib.h> |
#include <string.h> |
#include <bsp.h> |
#include <rdbg/servrpc.h> |
#include <rdbg/remdeb.h> |
#define fprintf(a,b) printf(b) |
/*HEADER_START*/ |
#define RTEMS_PORT 2071 |
#define RTEMS_BACK_PORT 2073 |
/* |
* Sun request values for the remote ptrace system call |
*/ |
|
/* |
* Memory data for read/write text or data. The size is in data. The target |
* addr is in the addr field. |
* Be careful before modifying because this value goes into internal |
* pipes and is allocated on stack too. Pipes and/or the stack could |
* become too small if this value gets incremented. |
*/ |
#ifndef XRY_MAX_CMD_STR |
#endif /* REMDEB_H */ |
/* now open_connex() routine which establishes a connection to server */ |
#define DEBUGGER_IS_GDB 0x2 /* */ |
/* now close_connex() routine which detaches from server */ |
/* now send_signal() routine which sends signals to processes like kill(2) */ |
/* now wait_info() routine which returns results of polling the wait status |
of a process/actor. It may return 0 if running, else pid or -1 */ |
/* now ptrace() routine. This matches the Sun UNIX ptrace as well as |
some additions */ |
/* now define the actual calls we support */ |
const char* names [] = { |
"NULLPROC", "OPEN_CONNEX", "SEND_SIGNAL", "name3", |
"name4", "name5", "name6", "name7", |
"name8", "name9", "CLOSE_CONNEX", "PTRACE", |
"name12", "WAIT_INFO", "name14", "name15", |
"name16", "GET_SIGNAL_NAMES", "name18" |
}; |
|
void |
remotedeb_2(struct svc_req *rqstp, register SVCXPRT *transp) |
{ |
union { |
open_in open_connex_2_arg; |
signal_in send_signal_2_arg; |
close_in close_connex_2_arg; |
ptrace_in ptrace_2_arg; |
wait_in wait_info_2_arg; |
} argument; |
char *result; |
xdrproc_t _xdr_argument, _xdr_result; |
char *(*local)(char *, struct svc_req *); |
|
DPRINTF (("remotedeb_2: %s (%d)\n", |
(unsigned) rqstp->rq_proc < |
(unsigned) (sizeof names / sizeof names[0]) ? |
names [rqstp->rq_proc] : "???", |
(int) rqstp->rq_proc)); |
|
switch (rqstp->rq_proc) { |
case NULLPROC: |
(void) svc_sendreply (transp, (xdrproc_t) xdr_void, (char *)NULL); |
return; |
|
case OPEN_CONNEX: |
_xdr_argument = (xdrproc_t) xdr_open_in; |
_xdr_result = (xdrproc_t) xdr_open_out; |
local = (char *(*)(char *, struct svc_req *)) open_connex_2_svc; |
break; |
|
case SEND_SIGNAL: |
_xdr_argument = (xdrproc_t) xdr_signal_in; |
_xdr_result = (xdrproc_t) xdr_signal_out; |
local = (char *(*)(char *, struct svc_req *)) send_signal_2_svc; |
break; |
|
case CLOSE_CONNEX: |
_xdr_argument = (xdrproc_t) xdr_close_in; |
_xdr_result = (xdrproc_t) xdr_void; |
local = (char *(*)(char *, struct svc_req *)) close_connex_2_svc; |
break; |
|
case PTRACE: |
_xdr_argument = (xdrproc_t) xdr_ptrace_in; |
_xdr_result = (xdrproc_t) xdr_ptrace_out; |
local = (char *(*)(char *, struct svc_req *)) ptrace_2_svc; |
break; |
|
case WAIT_INFO: |
_xdr_argument = (xdrproc_t) xdr_wait_in; |
_xdr_result = (xdrproc_t) xdr_wait_out; |
local = (char *(*)(char *, struct svc_req *)) wait_info_2_svc; |
break; |
|
case GET_SIGNAL_NAMES: |
_xdr_argument = (xdrproc_t) xdr_void; |
_xdr_result = (xdrproc_t) xdr_get_signal_names_out; |
local = (char *(*)(char *, struct svc_req *)) get_signal_names_2_svc; |
break; |
|
default: |
svcerr_noproc (transp); |
return; |
} |
memset ((char *)&argument, 0, sizeof (argument)); |
if (!svc_getargs (transp, _xdr_argument, (caddr_t) &argument)) { |
svcerr_decode (transp); |
return; |
} |
result = (*local)((char *)&argument, rqstp); |
if (result != NULL && !svc_sendreply(transp, _xdr_result, result)) { |
svcerr_systemerr (transp); |
} |
if (!svc_freeargs (transp, _xdr_argument, (caddr_t) &argument)) { |
fprintf (stderr, "unable to free arguments"); |
exit (1); |
} |
return; |
} |
/i386/any/remdeb_xdr.c
0,0 → 1,928
/* |
* Please do not edit this file. |
* It was generated using rpcgen. |
*/ |
|
#include "remdeb.h" |
#define RTEMS_PORT 2071 |
#define RTEMS_BACK_PORT 2073 |
|
bool_t |
xdr_rpc_type (XDR *xdrs, rpc_type *objp) |
{ |
register int32_t *buf; |
|
if (!xdr_enum (xdrs, (enum_t *) objp)) |
return FALSE; |
return TRUE; |
} |
|
bool_t |
xdr_UDP_MSG (XDR *xdrs, UDP_MSG *objp) |
{ |
register int32_t *buf; |
|
if (!xdr_u_char (xdrs, &objp->type)) |
return FALSE; |
if (!xdr_u_char (xdrs, &objp->msg_num)) |
return FALSE; |
if (!xdr_u_short (xdrs, &objp->spec)) |
return FALSE; |
if (!xdr_long (xdrs, &objp->pid)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->context)) |
return FALSE; |
return TRUE; |
} |
/* |
* Sun request values for the remote ptrace system call |
*/ |
|
|
bool_t |
xdr_ptracereq (XDR *xdrs, ptracereq *objp) |
{ |
register int32_t *buf; |
|
if (!xdr_enum (xdrs, (enum_t *) objp)) |
return FALSE; |
return TRUE; |
} |
|
bool_t |
xdr_xdr_regs (XDR *xdrs, xdr_regs *objp) |
{ |
register int32_t *buf; |
|
int i; |
|
if (xdrs->x_op == XDR_ENCODE) { |
buf = XDR_INLINE(xdrs, 19 * BYTES_PER_XDR_UNIT); |
if (buf == NULL) { |
if (!xdr_vector (xdrs, (char *)objp->tabreg, 19, |
sizeof (u_int), (xdrproc_t) xdr_u_int)) |
return FALSE; |
} else { |
{ |
register u_int *genp; |
|
for (i = 0, genp = objp->tabreg; |
i < 19; ++i) { |
IXDR_PUT_U_LONG(buf, *genp++); |
} |
} |
} |
return TRUE; |
} else if (xdrs->x_op == XDR_DECODE) { |
buf = XDR_INLINE(xdrs, 19 * BYTES_PER_XDR_UNIT); |
if (buf == NULL) { |
if (!xdr_vector (xdrs, (char *)objp->tabreg, 19, |
sizeof (u_int), (xdrproc_t) xdr_u_int)) |
return FALSE; |
} else { |
{ |
register u_int *genp; |
|
for (i = 0, genp = objp->tabreg; |
i < 19; ++i) { |
*genp++ = IXDR_GET_U_LONG(buf); |
} |
} |
} |
return TRUE; |
} |
|
if (!xdr_vector (xdrs, (char *)objp->tabreg, 19, |
sizeof (u_int), (xdrproc_t) xdr_u_int)) |
return FALSE; |
return TRUE; |
} |
/* |
* Memory data for read/write text or data. The size is in data. The target |
* addr is in the addr field. |
* Be careful before modifying because this value goes into internal |
* pipes and is allocated on stack too. Pipes and/or the stack could |
* become too small if this value gets incremented. |
*/ |
bool_t xdr_xdr_mem(xdrs, objp) |
XDR *xdrs; |
struct xdr_mem *objp; |
{ |
if (!xdr_u_long(xdrs, &objp->addr)) { |
return (FALSE); |
} |
if (!xdr_u_int(xdrs, &objp->dataNb)) { |
return(FALSE); |
} |
return (xdr_opaque(xdrs, objp->data, objp->dataNb)); |
} |
|
bool_t |
xdr_break_type (XDR *xdrs, break_type *objp) |
{ |
register int32_t *buf; |
|
if (!xdr_enum (xdrs, (enum_t *) objp)) |
return FALSE; |
return TRUE; |
} |
|
bool_t |
xdr_xdr_break (XDR *xdrs, xdr_break *objp) |
{ |
register int32_t *buf; |
|
int i; |
|
if (xdrs->x_op == XDR_ENCODE) { |
if (!xdr_u_char (xdrs, &objp->type)) |
return FALSE; |
if (!xdr_u_char (xdrs, &objp->thread_spec)) |
return FALSE; |
buf = XDR_INLINE (xdrs, 4 * BYTES_PER_XDR_UNIT); |
if (buf == NULL) { |
if (!xdr_u_short (xdrs, &objp->handle)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->ee_loc)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->ee_type)) |
return FALSE; |
if (!xdr_u_short (xdrs, &objp->length)) |
return FALSE; |
|
} else { |
IXDR_PUT_U_SHORT(buf, objp->handle); |
IXDR_PUT_U_LONG(buf, objp->ee_loc); |
IXDR_PUT_U_LONG(buf, objp->ee_type); |
IXDR_PUT_U_SHORT(buf, objp->length); |
} |
if (!xdr_u_char (xdrs, &objp->pass_count)) |
return FALSE; |
if (!xdr_u_char (xdrs, &objp->curr_pass)) |
return FALSE; |
buf = XDR_INLINE(xdrs, MAX_THRD_BRK * BYTES_PER_XDR_UNIT); |
if (buf == NULL) { |
if (!xdr_vector (xdrs, (char *)objp->thread_list, MAX_THRD_BRK, |
sizeof (u_long), (xdrproc_t) xdr_u_long)) |
return FALSE; |
} else { |
{ |
register u_long *genp; |
|
for (i = 0, genp = objp->thread_list; |
i < MAX_THRD_BRK; ++i) { |
IXDR_PUT_U_LONG(buf, *genp++); |
} |
} |
} |
return TRUE; |
} else if (xdrs->x_op == XDR_DECODE) { |
if (!xdr_u_char (xdrs, &objp->type)) |
return FALSE; |
if (!xdr_u_char (xdrs, &objp->thread_spec)) |
return FALSE; |
buf = XDR_INLINE (xdrs, 4 * BYTES_PER_XDR_UNIT); |
if (buf == NULL) { |
if (!xdr_u_short (xdrs, &objp->handle)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->ee_loc)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->ee_type)) |
return FALSE; |
if (!xdr_u_short (xdrs, &objp->length)) |
return FALSE; |
|
} else { |
objp->handle = IXDR_GET_U_SHORT(buf); |
objp->ee_loc = IXDR_GET_U_LONG(buf); |
objp->ee_type = IXDR_GET_U_LONG(buf); |
objp->length = IXDR_GET_U_SHORT(buf); |
} |
if (!xdr_u_char (xdrs, &objp->pass_count)) |
return FALSE; |
if (!xdr_u_char (xdrs, &objp->curr_pass)) |
return FALSE; |
buf = XDR_INLINE(xdrs, MAX_THRD_BRK * BYTES_PER_XDR_UNIT); |
if (buf == NULL) { |
if (!xdr_vector (xdrs, (char *)objp->thread_list, MAX_THRD_BRK, |
sizeof (u_long), (xdrproc_t) xdr_u_long)) |
return FALSE; |
} else { |
{ |
register u_long *genp; |
|
for (i = 0, genp = objp->thread_list; |
i < MAX_THRD_BRK; ++i) { |
*genp++ = IXDR_GET_U_LONG(buf); |
} |
} |
} |
return TRUE; |
} |
|
if (!xdr_u_char (xdrs, &objp->type)) |
return FALSE; |
if (!xdr_u_char (xdrs, &objp->thread_spec)) |
return FALSE; |
if (!xdr_u_short (xdrs, &objp->handle)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->ee_loc)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->ee_type)) |
return FALSE; |
if (!xdr_u_short (xdrs, &objp->length)) |
return FALSE; |
if (!xdr_u_char (xdrs, &objp->pass_count)) |
return FALSE; |
if (!xdr_u_char (xdrs, &objp->curr_pass)) |
return FALSE; |
if (!xdr_vector (xdrs, (char *)objp->thread_list, MAX_THRD_BRK, |
sizeof (u_long), (xdrproc_t) xdr_u_long)) |
return FALSE; |
return TRUE; |
} |
|
bool_t |
xdr_thread_name (XDR *xdrs, thread_name *objp) |
{ |
register int32_t *buf; |
|
if (!xdr_string (xdrs, objp, THREADNAMEMAX)) |
return FALSE; |
return TRUE; |
} |
|
bool_t |
xdr_KernThread (XDR *xdrs, KernThread *objp) |
{ |
register int32_t *buf; |
|
if (!xdr_u_int (xdrs, &objp->threadLi)) |
return FALSE; |
return TRUE; |
} |
bool_t xdr_thread_list(xdrs, objp) |
XDR *xdrs; |
struct thread_list *objp; |
{ |
return (xdr_array(xdrs, (char**)&objp->threads, &objp->nbThread, |
UTHREAD_MAX, sizeof(KernThread), xdr_KernThread)); |
} |
|
bool_t |
xdr_ptrace_addr_data_in (XDR *xdrs, ptrace_addr_data_in *objp) |
{ |
register int32_t *buf; |
|
if (!xdr_ptracereq (xdrs, &objp->req)) |
return FALSE; |
switch (objp->req) { |
case RPT_SETTHREADREGS: |
if (!xdr_xdr_regs (xdrs, &objp->ptrace_addr_data_in_u.regs)) |
return FALSE; |
break; |
case RPT_SETREGS: |
if (!xdr_xdr_regs (xdrs, &objp->ptrace_addr_data_in_u.regs)) |
return FALSE; |
break; |
case RPT_PSETTHREADREGS: |
if (!xdr_array (xdrs, (char **)&objp->ptrace_addr_data_in_u.pregs.pregs_val, (u_int *) &objp->ptrace_addr_data_in_u.pregs.pregs_len, ~0, |
sizeof (u_int), (xdrproc_t) xdr_u_int)) |
return FALSE; |
break; |
case RPT_PSETREGS: |
if (!xdr_array (xdrs, (char **)&objp->ptrace_addr_data_in_u.pregs.pregs_val, (u_int *) &objp->ptrace_addr_data_in_u.pregs.pregs_len, ~0, |
sizeof (u_int), (xdrproc_t) xdr_u_int)) |
return FALSE; |
break; |
case RPT_SETTHREADNAME: |
if (!xdr_thread_name (xdrs, &objp->ptrace_addr_data_in_u.name)) |
return FALSE; |
break; |
case RPT_WRITETEXT: |
if (!xdr_xdr_mem (xdrs, &objp->ptrace_addr_data_in_u.mem)) |
return FALSE; |
break; |
case RPT_WRITEDATA: |
if (!xdr_xdr_mem (xdrs, &objp->ptrace_addr_data_in_u.mem)) |
return FALSE; |
break; |
case RPT_SETBREAK: |
if (!xdr_xdr_break (xdrs, &objp->ptrace_addr_data_in_u.breakp)) |
return FALSE; |
break; |
default: |
if (!xdr_u_int (xdrs, &objp->ptrace_addr_data_in_u.address)) |
return FALSE; |
break; |
} |
return TRUE; |
} |
|
bool_t |
xdr_ptrace_addr_data_out (XDR *xdrs, ptrace_addr_data_out *objp) |
{ |
register int32_t *buf; |
|
if (!xdr_ptracereq (xdrs, &objp->req)) |
return FALSE; |
switch (objp->req) { |
case RPT_GETREGS: |
if (!xdr_xdr_regs (xdrs, &objp->ptrace_addr_data_out_u.regs)) |
return FALSE; |
break; |
case RPT_GETTHREADREGS: |
if (!xdr_xdr_regs (xdrs, &objp->ptrace_addr_data_out_u.regs)) |
return FALSE; |
break; |
case RPT_PGETREGS: |
if (!xdr_array (xdrs, (char **)&objp->ptrace_addr_data_out_u.pregs.pregs_val, (u_int *) &objp->ptrace_addr_data_out_u.pregs.pregs_len, ~0, |
sizeof (u_int), (xdrproc_t) xdr_u_int)) |
return FALSE; |
break; |
case RPT_PGETTHREADREGS: |
if (!xdr_array (xdrs, (char **)&objp->ptrace_addr_data_out_u.pregs.pregs_val, (u_int *) &objp->ptrace_addr_data_out_u.pregs.pregs_len, ~0, |
sizeof (u_int), (xdrproc_t) xdr_u_int)) |
return FALSE; |
break; |
case RPT_THREADLIST: |
if (!xdr_thread_list (xdrs, &objp->ptrace_addr_data_out_u.threads)) |
return FALSE; |
break; |
case RPT_GETTHREADNAME: |
if (!xdr_thread_name (xdrs, &objp->ptrace_addr_data_out_u.name)) |
return FALSE; |
break; |
case RPT_READTEXT: |
if (!xdr_xdr_mem (xdrs, &objp->ptrace_addr_data_out_u.mem)) |
return FALSE; |
break; |
case RPT_GETNAME: |
if (!xdr_xdr_mem (xdrs, &objp->ptrace_addr_data_out_u.mem)) |
return FALSE; |
break; |
case RPT_READDATA: |
if (!xdr_xdr_mem (xdrs, &objp->ptrace_addr_data_out_u.mem)) |
return FALSE; |
break; |
case RPT_GETBREAK: |
if (!xdr_xdr_break (xdrs, &objp->ptrace_addr_data_out_u.breakp)) |
return FALSE; |
break; |
default: |
if (!xdr_u_int (xdrs, &objp->ptrace_addr_data_out_u.addr)) |
return FALSE; |
break; |
} |
return TRUE; |
} |
|
bool_t |
xdr_CHAR_DATA (XDR *xdrs, CHAR_DATA *objp) |
{ |
register int32_t *buf; |
|
if (!xdr_bytes (xdrs, (char **)&objp->CHAR_DATA_val, (u_int *) &objp->CHAR_DATA_len, NET_SAFE)) |
return FALSE; |
return TRUE; |
} |
#ifndef XRY_MAX_CMD_STR |
#endif /* REMDEB_H */ |
|
bool_t |
xdr_xry_inst (XDR *xdrs, xry_inst *objp) |
{ |
register int32_t *buf; |
|
if (!xdr_u_char (xdrs, &objp->flags)) |
return FALSE; |
if (!xdr_u_char (xdrs, &objp->type)) |
return FALSE; |
if (!xdr_u_char (xdrs, &objp->sub_type)) |
return FALSE; |
if (!xdr_u_char (xdrs, &objp->res_type)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->value)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->value2)) |
return FALSE; |
return TRUE; |
} |
|
bool_t |
xdr_instance (XDR *xdrs, instance *objp) |
{ |
register int32_t *buf; |
|
int i; |
if (!xdr_vector (xdrs, (char *)objp->instances, XRY_MAX_INSTANCES, |
sizeof (xry_inst), (xdrproc_t) xdr_xry_inst)) |
return FALSE; |
if (!xdr_vector (xdrs, (char *)objp->buffer, XRY_MAX_INST_BUFF, |
sizeof (u_char), (xdrproc_t) xdr_u_char)) |
return FALSE; |
return TRUE; |
} |
|
bool_t |
xdr_instance_union (XDR *xdrs, instance_union *objp) |
{ |
register int32_t *buf; |
|
if (!xdr_bool (xdrs, &objp->instances)) |
return FALSE; |
switch (objp->instances) { |
case TRUE: |
if (!xdr_instance (xdrs, &objp->instance_union_u.inst)) |
return FALSE; |
break; |
case FALSE: |
if (!xdr_string (xdrs, &objp->instance_union_u.buffer, XRY_MAX_CMD_STR)) |
return FALSE; |
break; |
default: |
return FALSE; |
} |
return TRUE; |
} |
|
bool_t |
xdr_one_arg (XDR *xdrs, one_arg *objp) |
{ |
register int32_t *buf; |
|
if (!xdr_string (xdrs, objp, NET_SAFE)) |
return FALSE; |
return TRUE; |
} |
/* now open_connex() routine which establishes a connection to server */ |
|
bool_t |
xdr_debug_type (XDR *xdrs, debug_type *objp) |
{ |
register int32_t *buf; |
|
if (!xdr_enum (xdrs, (enum_t *) objp)) |
return FALSE; |
return TRUE; |
} |
#define DEBUGGER_IS_GDB 0x2 /* */ |
|
bool_t |
xdr_open_in (XDR *xdrs, open_in *objp) |
{ |
register int32_t *buf; |
|
int i; |
if (!xdr_vector (xdrs, (char *)objp->back_port, 16, |
sizeof (u_char), (xdrproc_t) xdr_u_char)) |
return FALSE; |
if (!xdr_u_short (xdrs, &objp->debug_type)) |
return FALSE; |
if (!xdr_u_short (xdrs, &objp->flags)) |
return FALSE; |
if (!xdr_vector (xdrs, (char *)objp->destination, 16, |
sizeof (u_char), (xdrproc_t) xdr_u_char)) |
return FALSE; |
if (!xdr_one_arg (xdrs, &objp->user_name)) |
return FALSE; |
return TRUE; |
} |
|
bool_t |
xdr_open_out (XDR *xdrs, open_out *objp) |
{ |
register int32_t *buf; |
|
int i; |
|
if (xdrs->x_op == XDR_ENCODE) { |
buf = XDR_INLINE(xdrs, (2 + ( 4 )) * BYTES_PER_XDR_UNIT); |
if (buf == NULL) { |
if (!xdr_u_long (xdrs, &objp->port)) |
return FALSE; |
if (!xdr_vector (xdrs, (char *)objp->pad, 4, |
sizeof (u_int), (xdrproc_t) xdr_u_int)) |
return FALSE; |
if (!xdr_u_int (xdrs, &objp->fp)) |
return FALSE; |
|
} else { |
IXDR_PUT_U_LONG(buf, objp->port); |
{ |
register u_int *genp; |
|
for (i = 0, genp = objp->pad; |
i < 4; ++i) { |
IXDR_PUT_U_LONG(buf, *genp++); |
} |
} |
IXDR_PUT_U_LONG(buf, objp->fp); |
} |
if (!xdr_u_char (xdrs, &objp->cmd_table_num)) |
return FALSE; |
if (!xdr_u_char (xdrs, &objp->cmd_table_vers)) |
return FALSE; |
if (!xdr_u_short (xdrs, &objp->server_vers)) |
return FALSE; |
return TRUE; |
} else if (xdrs->x_op == XDR_DECODE) { |
buf = XDR_INLINE(xdrs, (2 + ( 4 )) * BYTES_PER_XDR_UNIT); |
if (buf == NULL) { |
if (!xdr_u_long (xdrs, &objp->port)) |
return FALSE; |
if (!xdr_vector (xdrs, (char *)objp->pad, 4, |
sizeof (u_int), (xdrproc_t) xdr_u_int)) |
return FALSE; |
if (!xdr_u_int (xdrs, &objp->fp)) |
return FALSE; |
|
} else { |
objp->port = IXDR_GET_U_LONG(buf); |
{ |
register u_int *genp; |
|
for (i = 0, genp = objp->pad; |
i < 4; ++i) { |
*genp++ = IXDR_GET_U_LONG(buf); |
} |
} |
objp->fp = IXDR_GET_U_LONG(buf); |
} |
if (!xdr_u_char (xdrs, &objp->cmd_table_num)) |
return FALSE; |
if (!xdr_u_char (xdrs, &objp->cmd_table_vers)) |
return FALSE; |
if (!xdr_u_short (xdrs, &objp->server_vers)) |
return FALSE; |
return TRUE; |
} |
|
if (!xdr_u_long (xdrs, &objp->port)) |
return FALSE; |
if (!xdr_vector (xdrs, (char *)objp->pad, 4, |
sizeof (u_int), (xdrproc_t) xdr_u_int)) |
return FALSE; |
if (!xdr_u_int (xdrs, &objp->fp)) |
return FALSE; |
if (!xdr_u_char (xdrs, &objp->cmd_table_num)) |
return FALSE; |
if (!xdr_u_char (xdrs, &objp->cmd_table_vers)) |
return FALSE; |
if (!xdr_u_short (xdrs, &objp->server_vers)) |
return FALSE; |
return TRUE; |
} |
/* now close_connex() routine which detaches from server */ |
|
bool_t |
xdr_close_control (XDR *xdrs, close_control *objp) |
{ |
register int32_t *buf; |
|
if (!xdr_enum (xdrs, (enum_t *) objp)) |
return FALSE; |
return TRUE; |
} |
|
bool_t |
xdr_close_in (XDR *xdrs, close_in *objp) |
{ |
register int32_t *buf; |
|
if (!xdr_close_control (xdrs, &objp->control)) |
return FALSE; |
return TRUE; |
} |
/* now send_signal() routine which sends signals to processes like kill(2) */ |
|
bool_t |
xdr_signal_in (XDR *xdrs, signal_in *objp) |
{ |
register int32_t *buf; |
|
if (!xdr_int (xdrs, &objp->pid)) |
return FALSE; |
if (!xdr_int (xdrs, &objp->sig)) |
return FALSE; |
return TRUE; |
} |
|
bool_t |
xdr_signal_out (XDR *xdrs, signal_out *objp) |
{ |
register int32_t *buf; |
|
if (!xdr_int (xdrs, &objp->kill_return)) |
return FALSE; |
if (!xdr_int (xdrs, &objp->errNo)) |
return FALSE; |
return TRUE; |
} |
/* now wait_info() routine which returns results of polling the wait status |
of a process/actor. It may return 0 if running, else pid or -1 */ |
|
bool_t |
xdr_stop_code (XDR *xdrs, stop_code *objp) |
{ |
register int32_t *buf; |
|
if (!xdr_enum (xdrs, (enum_t *) objp)) |
return FALSE; |
return TRUE; |
} |
|
bool_t |
xdr_wait_in (XDR *xdrs, wait_in *objp) |
{ |
register int32_t *buf; |
|
if (!xdr_int (xdrs, &objp->pid)) |
return FALSE; |
return TRUE; |
} |
|
bool_t |
xdr_wait_out (XDR *xdrs, wait_out *objp) |
{ |
register int32_t *buf; |
|
|
if (xdrs->x_op == XDR_ENCODE) { |
buf = XDR_INLINE (xdrs, 3 * BYTES_PER_XDR_UNIT); |
if (buf == NULL) { |
if (!xdr_int (xdrs, &objp->wait_return)) |
return FALSE; |
if (!xdr_int (xdrs, &objp->errNo)) |
return FALSE; |
if (!xdr_int (xdrs, &objp->status)) |
return FALSE; |
|
} else { |
IXDR_PUT_LONG(buf, objp->wait_return); |
IXDR_PUT_LONG(buf, objp->errNo); |
IXDR_PUT_LONG(buf, objp->status); |
} |
if (!xdr_stop_code (xdrs, &objp->reason)) |
return FALSE; |
buf = XDR_INLINE(xdrs,5 * BYTES_PER_XDR_UNIT); |
if (buf == NULL) { |
if (!xdr_int (xdrs, &objp->handle)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->PC)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->SP)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->FP)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->thread)) |
return FALSE; |
} else { |
IXDR_PUT_LONG(buf, objp->handle); |
IXDR_PUT_U_LONG(buf, objp->PC); |
IXDR_PUT_U_LONG(buf, objp->SP); |
IXDR_PUT_U_LONG(buf, objp->FP); |
IXDR_PUT_U_LONG(buf, objp->thread); |
} |
return TRUE; |
} else if (xdrs->x_op == XDR_DECODE) { |
buf = XDR_INLINE (xdrs, 3 * BYTES_PER_XDR_UNIT); |
if (buf == NULL) { |
if (!xdr_int (xdrs, &objp->wait_return)) |
return FALSE; |
if (!xdr_int (xdrs, &objp->errNo)) |
return FALSE; |
if (!xdr_int (xdrs, &objp->status)) |
return FALSE; |
|
} else { |
objp->wait_return = IXDR_GET_LONG(buf); |
objp->errNo = IXDR_GET_LONG(buf); |
objp->status = IXDR_GET_LONG(buf); |
} |
if (!xdr_stop_code (xdrs, &objp->reason)) |
return FALSE; |
buf = XDR_INLINE(xdrs,5 * BYTES_PER_XDR_UNIT); |
if (buf == NULL) { |
if (!xdr_int (xdrs, &objp->handle)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->PC)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->SP)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->FP)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->thread)) |
return FALSE; |
} else { |
objp->handle = IXDR_GET_LONG(buf); |
objp->PC = IXDR_GET_U_LONG(buf); |
objp->SP = IXDR_GET_U_LONG(buf); |
objp->FP = IXDR_GET_U_LONG(buf); |
objp->thread = IXDR_GET_U_LONG(buf); |
} |
return TRUE; |
} |
|
if (!xdr_int (xdrs, &objp->wait_return)) |
return FALSE; |
if (!xdr_int (xdrs, &objp->errNo)) |
return FALSE; |
if (!xdr_int (xdrs, &objp->status)) |
return FALSE; |
if (!xdr_stop_code (xdrs, &objp->reason)) |
return FALSE; |
if (!xdr_int (xdrs, &objp->handle)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->PC)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->SP)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->FP)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->thread)) |
return FALSE; |
return TRUE; |
} |
/* now ptrace() routine. This matches the Sun UNIX ptrace as well as |
some additions */ |
|
bool_t |
xdr_ptrace_in (XDR *xdrs, ptrace_in *objp) |
{ |
register int32_t *buf; |
|
if (!xdr_int (xdrs, &objp->pid)) |
return FALSE; |
if (!xdr_ptrace_addr_data_in (xdrs, &objp->addr)) |
return FALSE; |
if (!xdr_u_int (xdrs, &objp->data)) |
return FALSE; |
if (!xdr_u_int (xdrs, &objp->flags)) |
return FALSE; |
return TRUE; |
} |
|
bool_t |
xdr_ptrace_out (XDR *xdrs, ptrace_out *objp) |
{ |
register int32_t *buf; |
|
if (!xdr_ptrace_addr_data_out (xdrs, &objp->addr)) |
return FALSE; |
if (!xdr_int (xdrs, &objp->result)) |
return FALSE; |
if (!xdr_int (xdrs, &objp->errNo)) |
return FALSE; |
return TRUE; |
} |
|
bool_t |
xdr_one_symbol (XDR *xdrs, one_symbol *objp) |
{ |
register int32_t *buf; |
|
if (!xdr_string (xdrs, &objp->symbolName, ~0)) |
return FALSE; |
if (!xdr_long (xdrs, &objp->symbolValue)) |
return FALSE; |
return TRUE; |
} |
|
bool_t |
xdr_all_symbols (XDR *xdrs, all_symbols *objp) |
{ |
register int32_t *buf; |
|
if (!xdr_array (xdrs, (char **)&objp->all_symbols_val, (u_int *) &objp->all_symbols_len, ~0, |
sizeof (one_symbol), (xdrproc_t) xdr_one_symbol)) |
return FALSE; |
return TRUE; |
} |
|
bool_t |
xdr_get_global_symbols_out (XDR *xdrs, get_global_symbols_out *objp) |
{ |
register int32_t *buf; |
|
if (!xdr_all_symbols (xdrs, &objp->symbols)) |
return FALSE; |
return TRUE; |
} |
|
bool_t |
xdr_get_text_data_in (XDR *xdrs, get_text_data_in *objp) |
{ |
register int32_t *buf; |
|
if (!xdr_int (xdrs, &objp->pid)) |
return FALSE; |
if (!xdr_string (xdrs, &objp->actorName, 16)) |
return FALSE; |
return TRUE; |
} |
|
bool_t |
xdr_get_text_data_out (XDR *xdrs, get_text_data_out *objp) |
{ |
register int32_t *buf; |
|
|
if (xdrs->x_op == XDR_ENCODE) { |
buf = XDR_INLINE(xdrs,6 * BYTES_PER_XDR_UNIT); |
if (buf == NULL) { |
if (!xdr_int (xdrs, &objp->result)) |
return FALSE; |
if (!xdr_int (xdrs, &objp->errNo)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->textStart)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->textSize)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->dataStart)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->dataSize)) |
return FALSE; |
} else { |
IXDR_PUT_LONG(buf, objp->result); |
IXDR_PUT_LONG(buf, objp->errNo); |
IXDR_PUT_U_LONG(buf, objp->textStart); |
IXDR_PUT_U_LONG(buf, objp->textSize); |
IXDR_PUT_U_LONG(buf, objp->dataStart); |
IXDR_PUT_U_LONG(buf, objp->dataSize); |
} |
return TRUE; |
} else if (xdrs->x_op == XDR_DECODE) { |
buf = XDR_INLINE(xdrs,6 * BYTES_PER_XDR_UNIT); |
if (buf == NULL) { |
if (!xdr_int (xdrs, &objp->result)) |
return FALSE; |
if (!xdr_int (xdrs, &objp->errNo)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->textStart)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->textSize)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->dataStart)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->dataSize)) |
return FALSE; |
} else { |
objp->result = IXDR_GET_LONG(buf); |
objp->errNo = IXDR_GET_LONG(buf); |
objp->textStart = IXDR_GET_U_LONG(buf); |
objp->textSize = IXDR_GET_U_LONG(buf); |
objp->dataStart = IXDR_GET_U_LONG(buf); |
objp->dataSize = IXDR_GET_U_LONG(buf); |
} |
return TRUE; |
} |
|
if (!xdr_int (xdrs, &objp->result)) |
return FALSE; |
if (!xdr_int (xdrs, &objp->errNo)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->textStart)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->textSize)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->dataStart)) |
return FALSE; |
if (!xdr_u_long (xdrs, &objp->dataSize)) |
return FALSE; |
return TRUE; |
} |
|
bool_t |
xdr_one_signal (XDR *xdrs, one_signal *objp) |
{ |
register int32_t *buf; |
|
if (!xdr_u_int (xdrs, &objp->number)) |
return FALSE; |
if (!xdr_string (xdrs, &objp->name, ~0)) |
return FALSE; |
return TRUE; |
} |
|
bool_t |
xdr_all_signals (XDR *xdrs, all_signals *objp) |
{ |
register int32_t *buf; |
|
if (!xdr_array (xdrs, (char **)&objp->all_signals_val, (u_int *) &objp->all_signals_len, ~0, |
sizeof (one_signal), (xdrproc_t) xdr_one_signal)) |
return FALSE; |
return TRUE; |
} |
|
bool_t |
xdr_get_signal_names_out (XDR *xdrs, get_signal_names_out *objp) |
{ |
register int32_t *buf; |
|
if (!xdr_all_signals (xdrs, &objp->signals)) |
return FALSE; |
return TRUE; |
} |
/* now define the actual calls we support */ |
/i386/Makefile.am
0,0 → 1,12
## |
## $Id: Makefile.am,v 1.2 2001-09-27 12:02:01 chris Exp $ |
## |
|
AUTOMAKE_OPTIONS = foreign 1.4 |
|
SUBDIRS = any |
|
EXTRA_DIST = excep_f.c rdbg_cpu_asm.S rdbg_f.c |
|
include $(top_srcdir)/../../../automake/subdirs.am |
include $(top_srcdir)/../../../automake/local.am |
/i386/excep_f.c
0,0 → 1,153
/* |
************************************************************************** |
* |
* Component = |
* |
* Synopsis = rdbg/i386/excep.c |
* |
* $Id: excep_f.c,v 1.2 2001-09-27 12:02:01 chris Exp $ |
* |
************************************************************************** |
*/ |
|
#include <rtems.h> |
#include <rtems/error.h> |
#include <assert.h> |
#include <errno.h> |
#include <rdbg/rdbg.h> |
#include <rdbg/servrpc.h> |
|
/* ----------------------------------------------------------------- |
Maping of hardware exceptions into Unix-like signal numbers. |
It is identical to the one used by the PM and the AM. |
----------------------------------------------------------------- */ |
|
int |
ExcepToSig (Exception_context *ctx) |
{ |
int excep = getExcNum (ctx); |
|
|
switch (excep) { |
|
case I386_EXCEPTION_MATH_COPROC_UNAVAIL: |
case I386_EXCEPTION_I386_COPROC_SEG_ERR: |
case I386_EXCEPTION_FLOAT_ERROR: |
case I386_EXCEPTION_BOUND: |
return SIGFPE; |
|
case I386_EXCEPTION_DEBUG: |
case I386_EXCEPTION_BREAKPOINT: |
case I386_EXCEPTION_ENTER_RDBG: |
return SIGTRAP; |
|
case I386_EXCEPTION_OVERFLOW: |
case I386_EXCEPTION_DIVIDE_BY_ZERO: |
case I386_EXCEPTION_ILLEGAL_INSTR: |
return SIGILL; |
|
case I386_EXCEPTION_SEGMENT_NOT_PRESENT: |
case I386_EXCEPTION_STACK_SEGMENT_FAULT: |
case I386_EXCEPTION_GENERAL_PROT_ERR: |
case I386_EXCEPTION_PAGE_FAULT: |
return SIGSEGV; |
|
default: |
break; |
} |
return SIGKILL; |
} |
|
|
/*----- Breakpoint Exception management -----*/ |
|
/* |
* Handler for Breakpoint Exceptions : |
* software breakpoints. |
*/ |
|
void |
BreakPointExcHdl(CPU_Exception_frame *ctx) |
{ |
rtems_status_code status; |
rtems_id continueSemId; |
|
if ( (justSaveContext) && (ctx->idtIndex == I386_EXCEPTION_ENTER_RDBG) ) { |
PushSavedExceptCtx (_Thread_Executing->Object.id, ctx); |
justSaveContext = 0; |
} |
else { |
if (ctx->idtIndex != I386_EXCEPTION_DEBUG){ |
NbSerializedCtx++; |
rtems_semaphore_obtain(serializeSemId, RTEMS_WAIT, RTEMS_NO_TIMEOUT); |
NbSerializedCtx--; |
} |
|
currentTargetThread = _Thread_Executing->Object.id; |
|
#ifdef DDEBUG |
printk("----------------------------------------------------------\n"); |
printk("Exception %d caught at PC %x by thread %d\n", |
ctx->idtIndex, |
ctx->eip, |
_Thread_Executing->Object.id); |
printk("----------------------------------------------------------\n"); |
printk("Processor execution context at time of the fault was :\n"); |
printk("----------------------------------------------------------\n"); |
printk(" EAX = %x EBX = %x ECX = %x EDX = %x\n", |
ctx->eax, ctx->ebx, ctx->ecx, ctx->edx); |
printk(" ESI = %x EDI = %x EBP = %x ESP = %x\n", |
ctx->esi, ctx->edi, ctx->ebp, ctx->esp0); |
printk("----------------------------------------------------------\n"); |
printk("Error code pushed by processor itself (if not 0) = %x\n", |
ctx->faultCode); |
printk("----------------------------------------------------------\n\n"); |
#endif |
|
status = rtems_semaphore_create (rtems_build_name('D', 'B', 'G', 'c'), |
0, |
RTEMS_FIFO | |
RTEMS_COUNTING_SEMAPHORE | |
RTEMS_NO_INHERIT_PRIORITY | |
RTEMS_NO_PRIORITY_CEILING | |
RTEMS_LOCAL, |
0, |
&continueSemId); |
if (status != RTEMS_SUCCESSFUL) |
rtems_panic ("Can't create continue semaphore: `%s'\n",rtems_status_text(status)); |
|
PushExceptCtx (_Thread_Executing->Object.id, continueSemId, ctx); |
|
switch (ctx->idtIndex){ |
case I386_EXCEPTION_DEBUG: |
DPRINTF((" DEBUG EXCEPTION !!!\n")); |
ctx->eflags &= ~EFLAGS_TF; |
ExitForSingleStep-- ; |
rtems_semaphore_release( wakeupEventSemId ); |
break; |
|
case I386_EXCEPTION_BREAKPOINT: |
DPRINTF((" BREAKPOINT EXCEPTION !!!\n")); |
rtems_semaphore_release( wakeupEventSemId ); |
break; |
|
case I386_EXCEPTION_ENTER_RDBG: |
DPRINTF((" ENTER RDBG !!!\n")); |
rtems_semaphore_release( wakeupEventSemId ); |
break; |
|
default: |
DPRINTF((" OTHER EXCEPTION !!!\n")); |
rtems_semaphore_release( wakeupEventSemId ); |
break; |
} |
|
rtems_semaphore_obtain(continueSemId, RTEMS_WAIT, RTEMS_NO_TIMEOUT); |
|
PopExceptCtx (_Thread_Executing->Object.id); |
rtems_semaphore_delete(continueSemId); |
} |
} |
|
|
|
/awk.svc
0,0 → 1,65
######################################################################### |
# |
# Component: RDBG |
# Module: awk.svc |
# |
# Synopsis: AWK script which transforms the server skeleton produced |
# by rpcgen(1) into something suitable for RDB servers. |
# |
######################################################################### |
# |
# $Id: awk.svc,v 1.2 2001-09-27 12:02:01 chris Exp $ |
# |
BEGIN { |
headerstarted = 0 |
withinproc = 0 |
brack = 0 |
} |
|
$1 ~ /^\/\*HEADER_START\*\/$/ { |
headerstarted = 1 |
printf("#include <rpc/types.h>\n"); |
printf("#include <rpc/rpc.h>\n"); |
printf("#include <stdio.h>\n"); |
printf("#include <stdlib.h>\n"); |
printf("#include <string.h>\n"); |
printf("#include <bsp.h>\n"); |
printf("#include <rdbg/servrpc.h>\n"); |
printf("#include <rdbg/%s>\n", THEPROG); |
printf("#define fprintf(a,b) printf(b)\n"); |
} |
|
$1 ~ /^\/\*HEADER_END\*\/$/ { |
headerstarted = 0 |
} |
|
{ |
if (headerstarted == 1) { |
print $0 |
} else if ($1 ~ /.*_2.*/) { |
withinproc = 1 |
printf("void\n"); |
print $0 |
} else if (withinproc == 1) { |
if ($1 == "switch") { |
print "\tDPRINTF ((\"remotedeb_2: %s (%d)\\n\", " |
print "\t\t(unsigned) rqstp->rq_proc < " |
print "\t\t(unsigned) (sizeof names / sizeof names[0]) ?" |
print "\t\tnames [rqstp->rq_proc] : \"???\", " |
print "\t\t(int) rqstp->rq_proc));\n" |
} |
for (i = 1; i <= NF; i++) { |
if ($i == "{") { |
brack++; |
} else if ($i == "}") { |
brack--; |
if (brack == 0) { |
withinproc = 0; |
} |
} |
} |
if ($1 != "_rpcsvcdirty" ) { |
print $0 |
} |
} |
} |
/_servtgt.c
0,0 → 1,305
/* |
============================================================================ |
_SERVTGT |
$Id: _servtgt.c,v 1.2 2001-09-27 12:02:01 chris Exp $ |
============================================================================ |
*/ |
|
|
#include <string.h> |
#include <rtems.h> |
#include <rtems/error.h> |
|
#include <rdbg/rdbg.h> |
#include <rdbg/rdbg_f.h> |
#include <rdbg/servrpc.h> |
#include <errno.h> |
#include <sys/socket.h> |
#include <assert.h> |
#include <rtems/score/cpu.h> |
|
#ifdef DDEBUG |
#define Ptrace TgtDbgPtrace |
#else |
#define Ptrace TgtRealPtrace |
#endif |
|
extern int errno; |
|
rtems_id eventTaskId; |
rtems_id serializeSemId; |
rtems_id wakeupEventSemId; |
|
CPU_Exception_frame Idle_frame; |
|
/* ----------------------------------------------------------------- |
TgtRealPtrace - lowest level ptrace() wrapper |
----------------------------------------------------------------- */ |
|
int |
TgtRealPtrace(int req, PID aid, char* addr, int d, void* addr2) |
{ |
return ptrace(req, aid, addr, d, addr2); |
} |
|
|
|
/* ----------------------------------------------------------------------- |
TgtChange() is called when the system stops. |
It informs the generic layers must be informed of |
that fact. |
----------------------------------------------------------------------- */ |
|
static int |
TgtChange (PID pid, CPU_Exception_frame* ctx, int status) |
{ |
|
if (TgtHandleChildChange (pid, &status, NULL, ctx)) { |
TgtNotifyWaitChange (pid, status, -1); |
} |
|
return 0; |
} |
|
/* ----------------------------------------------------------------------- |
eventTask |
----------------------------------------------------------------------- */ |
|
rtems_task eventTask( rtems_task_argument pid) |
{ |
Exception_context *ctx; |
|
DPRINTF (("event task: pid %d\n", pid)); |
|
|
/* |
* we spend all our time waiting for a semaphore. |
* If wait change, we send info |
*/ |
|
for (;;){ |
DPRINTF (("Event Task: wait event\n")); |
rtems_semaphore_obtain(wakeupEventSemId, RTEMS_WAIT, RTEMS_NO_TIMEOUT); |
DPRINTF (("Event Task: wake up !!!!!!!!!!!!!\n")); |
|
errno = 0; |
ctx = GetExceptCtx(currentTargetThread); |
|
CheckForSingleStep(ctx->ctx); |
|
TgtChange(pid, ctx->ctx,STS_MAKESIG(ExcepToSig(ctx))); |
|
} |
} |
|
/* ------------------------------------------------------------------- |
MyThreadIdle - |
|
This task is used to initiate the exception mechanism: |
It calls the enterDebug function with justSaveContext=1 |
only to push a first valid context in the list |
---------------------------------------------------------------------*/ |
|
rtems_task MyThreadIdle(rtems_task_argument argument) |
{ |
enterRdbg(); |
rtems_task_delete( RTEMS_SELF ); |
} |
|
/* ----------------------------------------------------------------------- |
TgtAttach - attach to a process that is running without control. |
|
Notes: |
- this function performs a ptrace ATTACH equivalent (attaching to a |
process that we do not control now). |
----------------------------------------------------------------------- */ |
|
Boolean TgtAttach( |
int conn_idx, /* client that is requesting */ |
PID pid) /* process to attach to */ |
{ |
rtems_name task_name; |
rtems_status_code status; |
rtems_id debugId; |
|
errno = 0; |
|
DPRINTF (("TgtAttach pid=%d\n",pid)); |
|
Ptrace(RPT_ATTACH, pid, NULL, 0, NULL); |
if (errno) |
return(False); /* failed */ |
|
TgtCreateNew(pid, conn_idx, 0, NULL, False); |
|
|
connect_rdbg_exception(); |
|
/* |
* Create the attach debuger task |
*/ |
task_name = rtems_build_name( 'E', 'v', 'n', 't' ); |
if ((status = rtems_task_create( task_name, 10, 24576, |
RTEMS_INTERRUPT_LEVEL(0), |
RTEMS_DEFAULT_ATTRIBUTES | RTEMS_SYSTEM_TASK, |
&eventTaskId )) |
!= RTEMS_SUCCESSFUL){ |
printf("status = %d\n",status); |
rtems_panic ("Can't create task.\n"); |
} |
|
status = rtems_task_start(eventTaskId, eventTask, pid); |
|
status = rtems_semaphore_create (rtems_build_name('D', 'B', 'G', 's'), |
1, |
RTEMS_FIFO | |
RTEMS_COUNTING_SEMAPHORE | |
RTEMS_NO_INHERIT_PRIORITY | |
RTEMS_NO_PRIORITY_CEILING | |
RTEMS_LOCAL, |
0, |
&serializeSemId); |
if (status != RTEMS_SUCCESSFUL) |
rtems_panic ("Can't create serialize semaphore: `%s'\n",rtems_status_text(status)); |
|
status = rtems_semaphore_create (rtems_build_name('D', 'B', 'G', 'w'), |
0, |
RTEMS_FIFO | |
RTEMS_COUNTING_SEMAPHORE | |
RTEMS_NO_INHERIT_PRIORITY | |
RTEMS_NO_PRIORITY_CEILING | |
RTEMS_LOCAL, |
0, |
&wakeupEventSemId); |
if (status != RTEMS_SUCCESSFUL) |
rtems_panic ("Can't create wakeup semaphore: `%s'\n",rtems_status_text(status)); |
|
/* |
* Create the MyThreadIdle task to init Exception mechanism |
*/ |
task_name = rtems_build_name( 'R', 'i', 'n', 'i' ); |
if ((status = rtems_task_create( task_name, 10, 24576, |
RTEMS_INTERRUPT_LEVEL(0), |
RTEMS_DEFAULT_ATTRIBUTES, |
&debugId )) |
!= RTEMS_SUCCESSFUL){ |
printf("status = %d\n",status); |
rtems_panic ("Can't create task.\n"); |
} |
|
status = rtems_task_start(debugId, MyThreadIdle, pid); |
|
return(True); |
} |
|
/* ----------------------------------------------------------------------- |
TgtPtrace - handle ptrace requests for server. |
----------------------------------------------------------------------- */ |
|
int TgtPtrace( |
int req, |
PID pid, |
char *addr, |
int data, |
void *addr2) |
{ |
if ((req == RPT_SINGLESTEP || req == RPT_CONT) |
&& addr2) /* clear then step */ |
{ /* addr2 is the old value */ |
int ret; |
|
errno = 0; |
TgtBreakRestoreOrig (pid, addr, addr2); |
ret = Ptrace(RPT_SINGLESTEP, pid, addr, data, NULL); /* step over */ |
if (ret) /* error, cannot single-step */ |
{ |
int pid_idx = FindPidEntry (pid); |
TgtBreakCancelStep (&pid_list [pid_idx]); |
} |
return(ret); /* failed or done */ |
} |
else |
return(Ptrace(req, pid, addr, data, addr2)); /* normal call */ |
} |
|
/* ----------------------------------------------------------------- |
TgtGetThreadName - get thread name |
--------------------------------------------------------------- */ |
|
int TgtGetThreadName ( |
PID_LIST *plst, /* Process entry */ |
unsigned Id, /* Thread ID */ |
char *ThrName) /* Thread name */ |
{ |
int index; |
unsigned name; |
|
if ( Id <_Objects_Information_table[OBJECTS_RTEMS_TASKS]->maximum_id && |
Id >_Objects_Information_table[OBJECTS_RTEMS_TASKS]->minimum_id) { |
|
index = Id - _Objects_Information_table[OBJECTS_RTEMS_TASKS]->minimum_id; |
name = *(unsigned*)(_Objects_Information_table[OBJECTS_RTEMS_TASKS]->local_table[1+index]->name); |
ThrName[0] = (char)((name >> 24) & 0xFF ); |
ThrName[1] = (char)((name >> 16) & 0xFF ); |
ThrName[2] = (char)((name >> 8) & 0xFF ); |
ThrName[3] = (char)( name & 0xFF ); |
ThrName[4] = 0x0; |
return 0; |
} |
|
if ( Id <_Objects_Information_table[OBJECTS_POSIX_THREADS]->maximum_id && |
Id >_Objects_Information_table[OBJECTS_POSIX_THREADS]->minimum_id) { |
|
index = Id - _Objects_Information_table[OBJECTS_POSIX_THREADS]->minimum_id; |
name = *(unsigned*)(_Objects_Information_table[OBJECTS_POSIX_THREADS]->local_table[1+index]->name); |
ThrName[0] = (char)((name >> 24) & 0xFF ); |
ThrName[1] = (char)((name >> 16) & 0xFF ); |
ThrName[2] = (char)((name >> 8) & 0xFF ); |
ThrName[3] = (char)( name & 0xFF ); |
ThrName[4] = 0x0; |
return 0; |
} |
|
|
return -1; |
|
} |
|
/* ----------------------------------------------------------------- |
TgtThreadList - return all the threads in the system |
----------------------------------------------------------------- */ |
|
int |
TgtThreadList ( |
PID_LIST* plst, /* Process entry */ |
unsigned* threads, /* Output buffer */ |
unsigned size) /* Output buffer size */ |
{ |
int curr = 0; |
Objects_Id id; |
unsigned index; |
|
id = _Objects_Information_table[OBJECTS_RTEMS_TASKS]->minimum_id; |
|
while (id < _Objects_Information_table[OBJECTS_RTEMS_TASKS]->maximum_id){ |
index = id - _Objects_Information_table[OBJECTS_RTEMS_TASKS]->minimum_id; |
if ( _Objects_Information_table[OBJECTS_RTEMS_TASKS]->local_table[1+index] != NULL){ |
threads[curr] = (unsigned) id; |
curr++; |
} |
id ++; |
} |
|
id = _Objects_Information_table[OBJECTS_POSIX_THREADS]->minimum_id; |
|
while (id < _Objects_Information_table[OBJECTS_POSIX_THREADS]->maximum_id){ |
index = id - _Objects_Information_table[OBJECTS_POSIX_THREADS]->minimum_id; |
if ( _Objects_Information_table[OBJECTS_POSIX_THREADS]->local_table[1+index] != NULL){ |
threads[curr] = (unsigned) id; |
curr++; |
} |
id ++; |
} |
|
return curr; |
} |
/servutil.c
0,0 → 1,132
/* |
********************************************************************** |
* |
* Component: RDB |
* Module: servutil.c |
* |
* Synopsis: Various utility routines |
* |
* $Id: servutil.c,v 1.2 2001-09-27 12:02:01 chris Exp $ |
* |
********************************************************************** |
*/ |
|
#include <string.h> |
#include <rdbg/rdbg.h> |
#include <rdbg/servrpc.h> |
|
/*----- Management of per-process list ----*/ |
|
/* |
* ListAlloc - build up list entry. |
* |
* Notes: |
* - this is a generic routine to build up entries in the per-connection |
* list. The fields list, list_sz and list_alloc are affected. |
*/ |
|
Boolean |
ListAlloc(buff, clst) |
char *buff; |
CONN_LIST *clst; /* place to copy it */ |
{ |
int tmp; |
char* name; |
int new_len; |
int len; |
|
tmp = strlen(buff); |
new_len = (int)clst->list_sz + 1 + tmp; |
if (clst->list_alloc < (unsigned)new_len) { |
/* need more space */ |
name = (char *)Realloc(clst->list, len = new_len + MAX_FILENAME); |
if (name == NULL) { |
return(False); /* failed, no space */ |
} |
clst->list_alloc = len; |
clst->list = name; |
} |
strcpy(clst->list + clst->list_sz, buff); |
clst->list_sz += tmp; |
return(True); |
} |
|
/*----- Management of processes -----*/ |
|
/* |
* FindPidEntry - locate pid_list entry from pid |
*/ |
|
int |
FindPidEntry (pid) |
int pid; /* process identifier */ |
{ |
int idx; |
|
/* pid 0 is invalid, and signals a free slot */ |
if (pid_list == NULL || pid == 0) { |
return -1; |
} |
for (idx = 0; idx < pid_list_cnt; idx++) { |
if (pid_list [idx].pid == pid ) |
return idx; |
} |
return -1; |
} |
|
/*----- Debug suport -----*/ |
|
#ifdef DDEBUG |
|
/* |
* Names of debug primitives |
*/ |
|
const char* PtraceNames [] = { |
|
"RPT_TRACEME", "RPT_PEEKTEXT", "RPT_PEEKDATA", "RPT_PEEKUSER", |
"RPT_POKETEXT", "RPT_POKEDATA", "RPT_POKEUSER", "RPT_CONT", |
"RPT_KILL", "RPT_SINGLESTEP", "RPT_ATTACH", "RPT_DETACH", |
"RPT_GETREGS", "RPT_SETREGS", "RPT_GETFPREGS", "RPT_SETFPREGS", |
"RPT_READDATA", "RPT_WRITEDATA", "RPT_READTEXT", "RPT_WRITETEXT", |
"RPT_GETFPAREGS", "RPT_SETFPAREGS", "RPT_22", "RPT_23", |
"RPT_SYSCALL", "RPT_DUMPCORE", "RPT_26", "RPT_27", |
"RPT_28", "RPT_GETUCODE", "RPT_30", "RPT_31", |
"RPT_32", "RPT_33", "RPT_34", "RPT_35", |
"RPT_36", "RPT_37", "RPT_38", "RPT_39", |
"RPT_40", "RPT_41", "RPT_42", "RPT_43", |
"RPT_44", "RPT_45", "RPT_46", "RPT_47", |
"RPT_48", "RPT_49", "RPT_GETTARGETTHREAD", "RPT_SETTARGETTHREAD", |
"RPT_THREADSUSPEND", "RPT_THREADRESUME", "RPT_THREADLIST", "RPT_GETTHREADNAME", |
"RPT_SETTHREADNAME", "RPT_SETTHREADREGS", "RPT_GETTHREADREGS", |
"RPT_59", |
"RPT_60", "RPT_61", "RPT_62", "RPT_63", |
"RPT_64", "RPT_65", "RPT_66", "RPT_67", |
"RPT_68", "RPT_69", "RPT_70", "RPT_71", |
"RPT_72", "RPT_73", "RPT_74", "RPT_STEPRANGE", |
"RPT_CONTTO", "RPT_SETBREAK", "RPT_CLRBREAK", "RPT_GETBREAK", |
"RPT_GETNAME", "RPT_STOP", |
"RPT_PGETREGS", "RPT_PSETREGS", |
"RPT_PSETTHREADREGS", "RPT_PGETTHREADREGS" |
}; |
|
const char* |
PtraceName(req) |
int req; |
{ |
static char bufret[40]; |
|
if ((req < 0) || (req >= sizeof(PtraceNames)/sizeof(char*))) { |
sprintf(bufret, "BAD_REQ_%d", req); |
return bufret; |
} |
return PtraceNames[req]; |
} |
|
const char* BmsgNames [] = { |
"?", "WARM", "WAIT", "BREAK", |
"EXEC_FAIL", "DETACH", "KILLED", "NOT_PRIM", |
"NEW_PID" |
}; |
|
#endif /* DDEBUG */ |