---------------------------------------------------------------------- PATCH FOR UPS Generated Tue Oct 6 17:14:36 BST 1998 on FreeBSD 2.2.6-STABLE In ups-3.33 Apply with : patch -c -p -s < this_file This is 3.33-02 with cx_libfuncs.h change removed because it got into ups-3.33.tar.gz. ---------------------------------------------------------------------- *** ./lib/libmtrprog/ifdefs.h.ups Thu Oct 1 10:57:09 1998 --- ./lib/libmtrprog/ifdefs.h Thu Oct 1 14:17:04 1998 *************** *** 149,167 **** /* Obsolete Sun386i systems. */ #if defined(__i386__) #define ARCH_SUN386 1 ! #define THIS_ARCH "sunos-sun386i" #endif #if defined(__mc68020__) #define ARCH_SUN3 1 ! #define THIS_ARCH "sunos-sun3" #define IS_BIG_ENDIAN 1 #endif #if defined(__sparc__) #define ARCH_SUN4 1 #define ARCH_SPARC 1 ! #define THIS_ARCH "sunos-sparc" #define IS_BIG_ENDIAN 1 #endif --- 149,167 ---- /* Obsolete Sun386i systems. */ #if defined(__i386__) #define ARCH_SUN386 1 ! #define THIS_ARCH "386-sun-sunos" #endif #if defined(__mc68020__) #define ARCH_SUN3 1 ! #define THIS_ARCH "m68k-sun-sunos" #define IS_BIG_ENDIAN 1 #endif #if defined(__sparc__) #define ARCH_SUN4 1 #define ARCH_SPARC 1 ! #define THIS_ARCH "sparc-sun-sunos" #define IS_BIG_ENDIAN 1 #endif *************** *** 192,204 **** #if defined(__sparc__) #define ARCH_SUN4 1 #define ARCH_SPARC 1 ! #define THIS_ARCH "solaris-sparc" #define IS_BIG_ENDIAN 1 #endif #if defined(__i386__) #define ARCH_386 1 ! #define THIS_ARCH "solaris-386" #endif #endif --- 192,204 ---- #if defined(__sparc__) #define ARCH_SUN4 1 #define ARCH_SPARC 1 ! #define THIS_ARCH "sparc-sun-solaris2" #define IS_BIG_ENDIAN 1 #endif #if defined(__i386__) #define ARCH_386 1 ! #define THIS_ARCH "386-sun-solaris" #endif #endif *************** *** 216,222 **** #if defined(__i386__) #define ARCH_386 1 #define ARCH_BSDI386 1 ! #define THIS_ARCH "bsdi-386" #endif #endif --- 216,222 ---- #if defined(__i386__) #define ARCH_386 1 #define ARCH_BSDI386 1 ! #define THIS_ARCH "386-unknown-bsdi" #endif #endif *************** *** 231,237 **** #define OS_BSD 1 #define ARCH_CLIPPER 1 ! #define THIS_ARCH "clipper" #endif --- 231,237 ---- #define OS_BSD 1 #define ARCH_CLIPPER 1 ! #define THIS_ARCH "clipper-unknown-bsd" #endif *************** *** 262,273 **** #define ARCH_386 1 #define ARCH_BSDI386 1 ! #define THIS_ARCH "bsdi-386" #if (OS_FREEBSD >= 2) #define ARCH_FREEBSD386 1 #undef THIS_ARCH ! #define THIS_ARCH "freebsd-386" #endif #endif /* __i386__ */ --- 262,273 ---- #define ARCH_386 1 #define ARCH_BSDI386 1 ! #define THIS_ARCH "386-unknown-freebsd" #if (OS_FREEBSD >= 2) #define ARCH_FREEBSD386 1 #undef THIS_ARCH ! #define THIS_ARCH "386-unknown-freebsd2" #endif #endif /* __i386__ */ *************** *** 288,294 **** #if defined(__i386__) #define ARCH_386 1 #define ARCH_LINUX386 1 ! #define THIS_ARCH "linux-386" #endif #endif --- 288,294 ---- #if defined(__i386__) #define ARCH_386 1 #define ARCH_LINUX386 1 ! #define THIS_ARCH "386-unknown-linux" #endif #endif *************** *** 307,313 **** #if defined(__i386__) #define ARCH_386 1 #define ARCH_BSDI386 1 ! #define THIS_ARCH "bsd-386" #endif #endif --- 307,313 ---- #if defined(__i386__) #define ARCH_386 1 #define ARCH_BSDI386 1 ! #define THIS_ARCH "386-unknown-???bsd" #endif #endif *************** *** 327,333 **** #if defined(__mips__) #define ARCH_MIPS 1 #define ARCH_MIPS_MIPS 1 ! #define THIS_ARCH "mips-mips" #define IS_BIG_ENDIAN 1 #endif --- 327,337 ---- #if defined(__mips__) #define ARCH_MIPS 1 #define ARCH_MIPS_MIPS 1 ! #if defined(__newsos__) ! #define THIS_ARCH "mips-sony-newsos" ! #else ! #define THIS_ARCH "mips-mips-riscos" ! #endif #define IS_BIG_ENDIAN 1 #endif *************** *** 346,358 **** #if defined(__mips__) #define ARCH_MIPS 1 #define ARCH_ULTRIX_MIPS 1 ! #define THIS_ARCH "ultrix-mips" #endif #if defined(__vax__) #define ARCH_VAX 1 #define ARCH_ULTRIX_VAX 1 ! #define THIS_ARCH "ultrix-vax" #endif #endif --- 350,362 ---- #if defined(__mips__) #define ARCH_MIPS 1 #define ARCH_ULTRIX_MIPS 1 ! #define THIS_ARCH "mips-dec-ultrix" #endif #if defined(__vax__) #define ARCH_VAX 1 #define ARCH_ULTRIX_VAX 1 ! #define THIS_ARCH "vax-dec-ultrix" #endif #endif *************** *** 369,387 **** #if defined(__i386__) #define ARCH_386 1 ! #define THIS_ARCH "unknown-386" #endif #if defined(__sparc__) #define ARCH_SUN4 1 #define ARCH_SPARC 1 ! #define THIS_ARCH "unknown-sparc" #define IS_BIG_ENDIAN 1 #endif #if defined(__vax__) #define ARCH_VAX 1 ! #define THIS_ARCH "unknown-vax" #endif #endif --- 373,391 ---- #if defined(__i386__) #define ARCH_386 1 ! #define THIS_ARCH "386-uknown-unknown" #endif #if defined(__sparc__) #define ARCH_SUN4 1 #define ARCH_SPARC 1 ! #define THIS_ARCH "sparc-unknown-unknown" #define IS_BIG_ENDIAN 1 #endif #if defined(__vax__) #define ARCH_VAX 1 ! #define THIS_ARCH "vax-unknown-unknown" #endif #endif *** ./ups/Makefile.ups Tue Jun 16 01:41:48 1998 --- ./ups/Makefile Mon Oct 5 23:20:16 1998 *************** *** 76,87 **** ASOBJS = $Das_vax.o $Das_68020.o $Das_mips.o $Das_clipper.o $Das_sparc.o ASSRCS = as_vax.c as_68020.c as_mips.c as_clipper.c as_sparc.c ! AOOBJS = $Dao_target.o $Dao_procfs.o $Dao_ptrace.o $Dao_core.o \ $Dao_symread.o $Dao_shlib.o $Dao_symload.o $Dao_symparse.o \ $Dao_symscan.o $Dao_symcb.o $Dao_aout.o $Dao_elfcore.o \ $Dao_elfread.o $Dao_elfsym.o $Dao_elflib.o $Dao_aflist.o \ $Dao_te.o $Dao_text.o $Dao_stack.o ${ASOBJS} ! AOSRCS = ao_target.c ao_procfs.c ao_ptrace.c ao_core.c \ ao_symread.c ao_shlib.c ao_symload.c ao_symparse.c \ ao_symscan.c ao_symcb.c ao_aout.c ao_elfcore.c \ ao_elfread.c ao_elfsym.c ao_elflib.c ao_aflist.c \ --- 76,89 ---- ASOBJS = $Das_vax.o $Das_68020.o $Das_mips.o $Das_clipper.o $Das_sparc.o ASSRCS = as_vax.c as_68020.c as_mips.c as_clipper.c as_sparc.c ! AOOBJS = $Dao_target.o $Dao_procfs.o $Dao_core.o \ ! $Dao_ptrace.o $Dao_pt_regs.o $Dao_pt_uarea.o \ $Dao_symread.o $Dao_shlib.o $Dao_symload.o $Dao_symparse.o \ $Dao_symscan.o $Dao_symcb.o $Dao_aout.o $Dao_elfcore.o \ $Dao_elfread.o $Dao_elfsym.o $Dao_elflib.o $Dao_aflist.o \ $Dao_te.o $Dao_text.o $Dao_stack.o ${ASOBJS} ! AOSRCS = ao_target.c ao_procfs.c ao_core.c \ ! ao_ptrace.c ao_pt_regs.c ao_pt_uarea.c \ ao_symread.c ao_shlib.c ao_symload.c ao_symparse.c \ ao_symscan.c ao_symcb.c ao_aout.c ao_elfcore.c \ ao_elfread.c ao_elfsym.c ao_elflib.c ao_aflist.c \ *************** *** 422,429 **** $Dao_procfs.o: ao_procfs.c ao_ifdefs.h ups.h target.h ao_core.h ao_target.h ao_procfs.h \ ao_elflib.h ao_elfcore.h breakpoint.h obj_bpt.h debug.h ui.h ${CCLINE}ao_procfs.c ! $Dao_ptrace.o: ao_ptrace.c ao_ifdefs.h ${CCLINE}ao_ptrace.c $Dao_core.o: ao_core.c ao_ifdefs.h ups.h target.h data.h ao_core.h ao_elfcore.h \ ao_aout.h ${CCLINE}ao_core.c --- 424,438 ---- $Dao_procfs.o: ao_procfs.c ao_ifdefs.h ups.h target.h ao_core.h ao_target.h ao_procfs.h \ ao_elflib.h ao_elfcore.h breakpoint.h obj_bpt.h debug.h ui.h ${CCLINE}ao_procfs.c ! $Dao_ptrace.o: ao_ptrace.c ao_ifdefs.h ups.h ui.h target.h ao_target.h \ ! ao_ptrace.h debug.h ${CCLINE}ao_ptrace.c + $Dao_pt_regs.o: ao_pt_regs.c ao_ifdefs.h ups.h ui.h target.h ao_target.h \ + ao_ptrace.h debug.h + ${CCLINE}ao_pt_regs.c + $Dao_pt_uarea.o: ao_pt_uarea.c ao_ifdefs.h ups.h ui.h target.h ao_target.h \ + ao_ptrace.h debug.h + ${CCLINE}ao_pt_uarea.c $Dao_core.o: ao_core.c ao_ifdefs.h ups.h target.h data.h ao_core.h ao_elfcore.h \ ao_aout.h ${CCLINE}ao_core.c *** ./ups/ao_ptrace.c.ups Thu Oct 1 10:45:10 1998 --- ./ups/ao_ptrace.c Tue Oct 6 01:48:39 1998 *************** *** 12,243 **** #include #include "ao_ifdefs.h" #ifdef AO_USE_PTRACE - #include #include - #include - #include #include #include #include - #include - #ifdef OS_ULTRIX - #include /* needed for user.h */ - #endif - - #ifdef __STDC__ - #include - #endif - - #if defined(OS_ULTRIX) || defined(ARCH_MIPS) - /* The Ultrix system header files and clash - * over the #defines for some symbols, so we #undef them. Hmmm ... - */ - #undef JB_S0 - #undef JB_S1 - #undef JB_S2 - #undef JB_S3 - #undef JB_S4 - #undef JB_S5 - #undef JB_S6 - #undef JB_S7 - #undef JB_S8 - #undef JB_SP - #undef JB_PC - #undef NJBREGS - #endif - - #include #include ! #include /* VAX needs this for user.h */ ! #include ! #ifndef OS_LINUX /* RGA linux merge */ ! #include ! #endif ! #include ! ! #ifdef ARCH_VAX ! #include ! #endif #include #include #include - #ifdef ARCH_MIPS - #include "mips_frame.h" - #endif #include "ups.h" #include "ui.h" - #include "ci.h" - #include "target.h" - #include "breakpoint.h" - #include "obj_bpt.h" /* BUG: need this for recalculate_bpt_addrs */ #include "mreg.h" ! #include "dx.h" ! #include "as.h" ! #include "ao.h" ! #include "ao_asm.h" ! #include "ao_text.h" ! #include "ao_shlib.h" ! #include "ao_core.h" ! #include "ao_stack.h" #include "ao_target.h" #include "ao_ptrace.h" - #include "ao_aout.h" #include "debug.h" - #include "tdr.h" - #include "state.h" - - #if defined(OS_ULTRIX) && defined(ARCH_MIPS) - #define MIPS_ULTRIX - #endif - - #ifdef ARCH_SUN4 - #define NO_SINGLE_STEP - #include - - #ifdef CPU_ARCH - static int sparc_u_offset PROTO((void)); - int gethostid PROTO((void)); - #endif - #endif ! #if defined(OS_SUNOS) || defined(MIPS_ULTRIX) || defined(OS_RISCOS) || defined(OS_BSD44) ! #include ! #endif ! #ifndef OS_SUNOS ! /* Word size (and alignment) for ptrace read/write data requests. ! * ! * Used in ao_read_data and ao_write_data. ! */ #define WORDSIZE 4 - - #if defined(OS_LINUX) - /* Request values for the ptrace system call - */ - #define PTRACE_PEEKUSER PTRACE_PEEKUSR - #define PTRACE_POKEUSER PTRACE_POKEUSR - typedef int ptracereq_t; - - #elif defined (OS_BSD44) - /* Request values for the ptrace system call - */ - #define PTRACE_TRACEME PT_TRACE_ME /* by tracee to begin tracing */ - #define PTRACE_PEEKTEXT PT_READ_I /* read word from text segment */ - #define PTRACE_PEEKDATA PT_READ_D /* read word from data segment */ - #define PTRACE_PEEKUSER PT_READ_U /* read word from user struct */ - #define PTRACE_POKETEXT PT_WRITE_I /* write word into text segment */ - #define PTRACE_POKEDATA PT_WRITE_D /* write word into data segment */ - #define PTRACE_POKEUSER PT_WRITE_U /* write word into user struct */ - #define PTRACE_CONT PT_CONTINUE /* continue process */ - #define PTRACE_KILL PT_KILL /* terminate process */ - #define PTRACE_SINGLESTEP PT_STEP /* single step process */ - #if defined(PT_ATTACH) && defined(PT_DETACH) - #define PTRACE_ATTACH PT_ATTACH - #define PTRACE_DETACH PT_DETACH - #else - #define PTRACE_ATTACH 10 - #define PTRACE_DETACH 11 - #endif - typedef int ptracereq_t; - - #elif defined(ARCH_MIPS) && (defined(OS_ULTRIX) || defined(OS_RISCOS)) - /* Request values for the ptrace system call - */ - enum ptracereq { - PTRACE_TRACEME = PT_TRACE_ME, /* by tracee to begin tracing */ - PTRACE_PEEKTEXT = PT_READ_I, /* read word from text segment */ - PTRACE_PEEKDATA = PT_READ_D, /* read word from data segment */ - PTRACE_PEEKUSER = PT_READ_U, /* read word from user struct */ - PTRACE_POKETEXT = PT_WRITE_I, /* write word into text segment */ - PTRACE_POKEDATA = PT_WRITE_D, /* write word into data segment */ - PTRACE_POKEUSER = PT_WRITE_U, /* write word into user struct */ - PTRACE_CONT = PT_CONTINUE, /* continue process */ - PTRACE_KILL = PT_KILL, /* terminate process */ - PTRACE_SINGLESTEP = PT_STEP, /* single step process */ - }; - typedef enum ptracereq ptracereq_t; - - #else - /* Request values for the ptrace system call - */ - enum ptracereq { - PTRACE_TRACEME = 0, /* by tracee to begin tracing */ - PTRACE_CHILDDONE = 0, /* tracee is done with his half */ - PTRACE_PEEKTEXT = 1, /* read word from text segment */ - PTRACE_PEEKDATA = 2, /* read word from data segment */ - PTRACE_PEEKUSER = 3, /* read word from user struct */ - PTRACE_POKETEXT = 4, /* write word into text segment */ - PTRACE_POKEDATA = 5, /* write word into data segment */ - PTRACE_POKEUSER = 6, /* write word into user struct */ - PTRACE_CONT = 7, /* continue process */ - PTRACE_KILL = 8, /* terminate process */ - PTRACE_SINGLESTEP = 9 /* single step process */ - }; - typedef enum ptracereq ptracereq_t; - - #endif - #else /* !OS_SUNOS */ - typedef enum ptracereq ptracereq_t; - #endif - - #ifndef WSTOPSIG - #define WSTOPSIG(w) ((w).w_stopsig) - #endif - - #ifdef PTRACE_DEBUG - static int ptrace_debug PROTO((int request, int pid, int addr, int data)); - #define ptrace ptrace_debug - #endif - - #if defined(OS_SUNOS) - int ptrace PROTO((ptracereq_t req, int pid, char *addr, int data, char *addr2)); - #define std_ptrace(req, pid, addr, data) ptrace(req, pid, addr, data, (char *)NULL) - #elif defined(OS_BSD44) - #define std_ptrace(req, pid, addr, data) ptrace(req, pid, addr, data) - #elif defined(OS_LINUX) - #define std_ptrace(req, pid, addr, data) ptrace(req, pid, (int)addr, data) - #else - int ptrace PROTO((ptracereq_t req, int pid, char *addr, int data)); - #define std_ptrace(req, pid, addr, data) ptrace(req, pid, addr, data) - #endif - - /* Return the offset into the u area of member. - * Used when doing PEEKUSER ptrace requests. - */ - #ifdef ARCH_MIPS - #define U_OFFSET(member) ((char *)((int)&((struct user *)NULL)->member / 4)) - #else - #define U_OFFSET(member) ((char *)&((struct user *)NULL)->member) - #endif - - #ifdef OS_SUNOS_4 - #define u_tsize u_procp->p_tsize - #define u_dsize u_procp->p_dsize - #define u_ssize u_procp->p_ssize - #endif /* OS_SUNOS_4 */ - - /* Macros for getting/setting registers in a Sun regs structure. - */ - #ifdef ARCH_SUN3 - #define IS_FLOAT_REG(regno) ((regno) >= 16) - #define FRAME_REG(sr) ((sr)->sr_regs.r_areg[6]) - #define INTEGER_REG(sr, regno) ((sr)->sr_regs.r_dreg[regno]) - #endif - - #ifdef ARCH_SUN386 - #define FRAME_REG(sr) ((sr)->sr_regs.r_reg[EBP]) - #define INTEGER_REG(sr, regno) ((sr)->sr_regs.r_reg[regno]) - #endif - - #ifdef ARCH_SUN4 - #define IS_FLOAT_REG(regno) ((regno) >= 32 && (regno) < 64) - #define FLOAT_REG_OFFSET 32 - #define FRAME_REG(sr) ((sr)->sr_rwindow.rw_fp) - #define INTEGER_REG(sr, regno) ((&(sr)->sr_regs.r_y)[regno]) #endif #if defined(OS_SUNOS) || defined(OS_BSD44) || defined(OS_LINUX) --- 12,53 ---- #include #include "ao_ifdefs.h" + /* + * This file contains general routines concerned with using the 'ptrace()' + * system call to debug processes. The gory detail is in "ao_ptuarea.c". + * + * Look in "ao_ifdefs.h" for the definitions of AO_... symbols. + * + */ + #ifdef AO_USE_PTRACE #include #include #include #include #include ! #include #include #include #include + #include #include "ups.h" #include "ui.h" #include "mreg.h" ! #include "target.h" #include "ao_target.h" #include "ao_ptrace.h" #include "debug.h" ! /* Definitions. */ ! /* ------------ */ ! #ifndef AO_HAS_PTRACE_RANGE ! /* Word size (and alignment) for ptrace read/write data requests. */ #define WORDSIZE 4 #endif #if defined(OS_SUNOS) || defined(OS_BSD44) || defined(OS_LINUX) *************** *** 247,1319 **** typedef union wait wait_arg_t; #endif ! static void init_pid PROTO((iproc_t *ip, int pid, bool attached)); ! static int e_ptrace PROTO((ptracereq_t req, int pid, char *addr, int data)); ! static int update_regs PROTO((target_t *xp)); ! static void stop_target PROTO((void)); ! static void wait_for_target PROTO((target_t *xp)); ! ! #ifdef UAREA_REGS ! int get_uarea_reg PROTO((iproc_t *ip, int ri, taddr_t *p_value)); ! int set_uarea_reg PROTO((iproc_t *ip, int ri, taddr_t value)); ! int reg_to_uarea_index PROTO((int regno)); ! #ifdef ARCH_BSDI386 ! typedef int (*get_uarea_word_func_t)PROTO((int arg, int offset)); ! void set_uarea_reg_offsets PROTO((ureg_t *ur, ! get_uarea_word_func_t get_uarea_word_func, ! int arg)); ! #else ! void set_uarea_reg_offsets PROTO((ureg_t *ur)); ! #endif #endif ! #ifdef OS_SUNOS ! static int set_sun_regval PROTO((sunregs_t *sr, int pid, ! int regno, taddr_t val)); #endif - #ifdef ARCH_CLIPPER - int get_clipper_fp_reg PROTO((iproc_t *ip, int regno, taddr_t *p_val)); - #endif ! #ifdef ARCH_SUN3 ! static void convert_68881_reg PROTO((unsigned *rwords, bool is_double, ! fpval_t *p_val)); ! #endif ! #ifndef OS_SUNOS static int get_words PROTO((int pid, ptracereq_t ptrace_req, taddr_t addr, char *buf, size_t nbytes)); - #endif ! static int wait_with_intr PROTO((wait_arg_t *p_status)); ! static char *get_restart_pc PROTO((iproc_t *ip)); ! #ifdef ARCH_BSDI386 ! static int get_uarea_word_with_ptrace PROTO((int pid, int offset)); ! #endif ! #ifdef ARCH_SUN3 ! # define BPT_PC_OFFSET 2 ! #else ! # ifdef ARCH_386 ! # define BPT_PC_OFFSET 1 ! # else ! # define BPT_PC_OFFSET 0 ! # endif ! #endif ! /* Special value for ptrace restart requests meaning restart the target ! * from where it stopped. */ ! #define RESTART_FROM_WHERE_STOPPED ((taddr_t)1) ! ! struct Ptrace_info { ! #ifdef ARCH_CLIPPER ! taddr_t fpreg_sp; ! ureg_t fp_uregs[16]; ! #endif ! #ifdef OS_SUNOS_4 ! sunregs_t sunregs; ! #endif ! #ifdef UAREA_REGS /* Currently VAX and MIPS under Ultrix */ ! ureg_t uregs[N_UREGS]; ! #endif ! }; ! ! /* Used for reattaching to same target */ ! static int Last_attach_pid; ! ! #ifdef PTRACE_DEBUG ! #undef ptrace - static int - ptrace_debug(request, pid, addr, data) - int request, pid, addr, data; - { - static char *reqnames[] = { - "TRACEME", "PEEKTEXT", "PEEKDATA", "PEEKUSER", "POKETEXT", - "POKEDATA", "POKEUSER", "CONT", "KILL", "SINGLESTEP" - }; - char buf[50], ebeforebuf[20], eafterbuf[20], *reqname, *ebefore, *eafter; - int errno_before, errno_after, res; - static bool first_call = TRUE, no_debug; ! if ((Debug_flags & DBFLAG_PTRACE) == 0) ! return ptrace(request, pid, addr, data); ! if (request < 0 || request > 9) { ! sprintf(buf, "", request); ! reqname = buf; } - else - reqname = reqnames[request]; ! errno_before = errno; ! res = ptrace(request, pid, addr, data); ! errno_after = errno; ! if (errno_before != 0) { ! sprintf(ebeforebuf, "[errno=%d]", errno_before); ! ebefore = ebeforebuf; ! } ! else ! ebefore = ""; ! if (errno_after != 0) { ! sprintf(eafterbuf, "[errno=%d]", errno_after); ! eafter = eafterbuf; } - else - eafter = ""; - - fprintf(stderr, "\tproc %d%s: ptrace(%s, %d, 0x%x, 0x%x)", - getpid(), ebefore, - reqname, pid, addr, data); - if (res != 0 || errno_after != 0) - fprintf(stderr, " -> 0x%x%s", res, eafter); - fputc('\n', stderr); ! fflush(stderr); ! errno = errno_after; ! return res; } ! #define ptrace ptrace_debug - #endif /* PTRACE_DEBUG */ ! /* Call ptrace(2), but abort if errno gets set. ! */ ! static int ! e_ptrace(req, pid, addr, data) ! ptracereq_t req; ! int pid; ! char *addr; ! int data; { ! int res; ! ! #ifdef ARCH_LINUX386 ! if (req == PTRACE_CONT || req == PTRACE_SINGLESTEP) { ! if (addr != (char *) 1) { ! std_ptrace(PTRACE_POKEUSER, pid, 4*EIP, addr); ! addr = (char *) 1; ! } ! } #endif ! errno = 0; ! res = std_ptrace(req, pid, addr, data); ! if (errno != 0) ! panic("ptrace failed in e_ptrace"); ! return res; ! } - #ifdef UAREA_REGS ! #ifdef ARCH_LINUX386 ! static ! int ! do_register_translation(regno) ! int regno; { ! static int regmap[] = { ! EAX, ECX, EDX, EBX, UESP, EBP, ESI, EDI, ! EIP, EFL, CS, SS, DS, ES, FS, GS, ORIG_EAX ! }; ! return regmap[regno]; } - #endif ! #ifndef ARCH_BSDI386 ! /* Set the offsets into the u area for the registers. ! * Called once on startup. ! * Not static because we also need this information set up for core ! * files - thus we are called from core.c ! */ ! void ! set_uarea_reg_offsets(ur) ! ureg_t *ur; { ! #ifdef ARCH_VAX ! #define RUADDR(rno) (ctob(UPAGES) + (rno * 4)) ! static taddr_t rmap[] = { ! RUADDR(R0), RUADDR(R1), RUADDR(R2), RUADDR(R3), ! RUADDR(R4), RUADDR(R5), RUADDR(R6), RUADDR(R7), ! RUADDR(R8), RUADDR(R9), RUADDR(R10), RUADDR(R11), ! RUADDR(AP), RUADDR(FP), RUADDR(SP), RUADDR(PC), ! RUADDR(PS), ! }; ! #undef RUADDR ! taddr_t *rptr; ! ! rptr = rmap; ! while (rptr < rmap + N_UREGS) ! ur++->ur_uaddr = *rptr++; ! #endif /* ARCH_VAX */ ! #ifdef ARCH_MIPS ! int i; ! ! for (i = 0; i < NGP_REGS + NFP_REGS; ++i) ! ur[i].ur_uaddr = i; ! ! if (i != UR_FP) ! panic("regno botch in suro"); ! ! /* This ureg is the frame pointer `register'. We evaluate this ! * on the demand, so there is no u area address. For safety, ! * make sure that any attempt to use it causes an error. ! */ ! ur[UR_FP].ur_uaddr = 20000; ! ! ur[UR_PC].ur_uaddr = PC; ! #endif /* ARCH_MIPS */ ! #ifdef ARCH_CLIPPER ! int i; ! ! for (i = 0; i < 16; ++i) ! ur[i].ur_uaddr = (int)U_OFFSET(u_pcb.pcb_regs[i]); ! ur[UR_PC].ur_uaddr = (int)U_OFFSET(u_pcb.pcb_cxt.cxt_pc); ! #endif ! #ifdef ARCH_LINUX386 ! ! /* RGA seems like we should use a regmap translation here ! * so that ur[i].ur_uaddr = 4*regmap[i];. However this causes ! * wait_for_target() to return SR_SSTEP instead of SR_BPT ! * on startup, so working around this by doing the register ! * transtation in do_register_translation() defined above. ! * This is called from reg_to_uarea_index. ! */ ! ! int i; ! ! for (i = 0; i <= 16; i++) ! ur[i].ur_uaddr = 4*i; ! #endif ! } ! #endif /* !ARCH_BSDI386 */ ! ! /* Set *p_val to the current value of u area register ri. ! * ri is a general purpose register number, or one of UR_PC, UR_AP, UR_FP ! * and UR_SP. See mreg.h ! */ ! int ! get_uarea_reg(ip, ri, p_val) ! iproc_t *ip; ! int ri; ! taddr_t *p_val; ! { ! ureg_t *ur; ! ! ur = ip->ip_ptrace_info->uregs + ri; ! if (!ur->ur_is_current) { ! errno = 0; ! #ifdef ARCH_MIPS ! if (ri == UR_FP) { ! taddr_t sp, pc; ! ! if (get_uarea_reg(ip, UR_SP, &sp) != 0) ! return -1; ! if (get_uarea_reg(ip, UR_PC, &pc) != 0) ! return -1; ! ur->ur_value = sp + get_frame_size(pc); ! } ! else { ! ur->ur_value = std_ptrace(PTRACE_PEEKUSER, ip->ip_pid, ! (char *)ur->ur_uaddr, 0); ! } ! #else ! ur->ur_value = std_ptrace(PTRACE_PEEKUSER, ip->ip_pid, ! (char *)ur->ur_uaddr, 0); ! #endif ! if (errno != 0) ! return -1; ! ur->ur_is_current = TRUE; ! } ! *p_val = ur->ur_value; ! return 0; ! } ! ! int ! set_uarea_reg(ip, ri, value) ! iproc_t *ip; ! int ri; ! taddr_t value; ! { ! ureg_t *ur; ! ! ur = ip->ip_ptrace_info->uregs + ri; ! errno = 0; ! e_ptrace(PTRACE_POKEUSER, ip->ip_pid, (char *)ur->ur_uaddr, (int)value); ! ur->ur_is_current = FALSE; ! return (errno == 0) ? 0 : -1; ! } ! ! /* Convert machine independent register number regno to u area register number. ! */ ! int ! reg_to_uarea_index(regno) ! int regno; ! { ! switch(regno) { ! case UPSREG_PC: ! return UR_PC; ! case UPSREG_SP: ! return UR_SP; ! case UPSREG_AP: ! #ifdef ARCH_VAX ! return UR_AP; ! case UPSREG_CONDITION_CODES: ! return UR_PSL; ! #endif ! case UPSREG_FP: ! return UR_FP; ! default: ! if (regno < 0 || regno >= N_UAREA_GREGS) ! panic("bad regno in xp_getreg"); ! #ifdef ARCH_LINUX386 ! return do_register_translation(regno); ! #else ! return regno; ! #endif ! } ! /* NOTREACHED */ ! } ! #endif /* UAREA_REGS */ ! ! #ifdef ARCH_CLIPPER ! int ! get_clipper_fp_reg(xp, regno, p_val) ! target_t *xp; ! int regno; ! taddr_t *p_val; ! { ! ureg_t *ur; ! ! if (ip->ip_ptrace_info->fpreg_sp == 0) { ! static unsigned short text[] = { ! 0xb420, /* saved0 */ ! 0x0000, /* second word of saved0 */ ! 0x0900, /* BPT */ ! 0x0000, /* nop */ ! }; ! taddr_t pc, saved_restart_pc, saved_sp, sp, new_sp, word1, word2; ! int errno1, errno2, i; ! ! saved_sp = sp = xp_getreg(xp, UPSREG_SP); ! ! /* Back off to a word aligned place at least four halfwords ! * before the current pc. ! */ ! saved_restart_pc = ip->ip_restart_pc; ! pc = (ip->ip_restart_pc - 8) & ~3; ! ! word1 = std_ptrace(PTRACE_PEEKTEXT, ip->ip_pid, (char *)pc, 0); ! errno1 = errno; ! word2 = std_ptrace(PTRACE_PEEKTEXT, ip->ip_pid, (char *)(pc + 4), 0); ! errno2 = errno; ! ! std_ptrace(PTRACE_POKETEXT, ip->ip_pid, (char *)pc, *(int *)text); ! ! /* At this point we can still back out. Beyond this point ! * we have trodden on the text, so any errors are fatal. ! */ ! if (errno != 0 || errno1 != 0 || errno2 != 0) { ! errf("Can't insert fp register grabbing code (%m)"); ! return -1; ! } ! ! e_ptrace(PTRACE_POKETEXT, ip->ip_pid, ! (char *)(pc + 4), *(int *)&text[2]); ! ! /* Ensure that the stack pointer is eight byte aligned ! */ ! if (sp & 7) { ! sp &= ~7; ! if (ao_setreg(xp, UPSREG_SP, sp) != 0) ! panic("can't set sp in gifr"); ! } ! ! e_ptrace(PTRACE_CONT, ip->ip_pid, (char *)pc, 0); ! wait_for_target(ip); ! ! new_sp = xp_getreg(xp, UPSREG_SP); ! ! /* Make sure we've hit the breakpoint, and that the sp ! * has been moved by the saved0. ! */ ! if (ip->ip_stopres != SR_BPT && ip->ip_stopres != SR_SSTEP) ! panic("ws botch in gcfr"); ! ! e_ptrace(PTRACE_POKETEXT, ip->ip_pid, (char *)pc, word1); ! e_ptrace(PTRACE_POKETEXT, ip->ip_pid, (char *)(pc + 4), word2); ! ! /* Sometimes the pc doesn't advance. I don't know why. ! */ ! if (ip->ip_restart_pc == pc) { ! errf("Error running fp regno grabbing code"); ! ip->ip_restart_pc = saved_restart_pc; ! return -1; ! } ! ! if (ip->ip_restart_pc != pc + 4) ! panic("pc botch in gcfr"); ! if (new_sp != sp - 4 * 16) ! panic("sp botch in gcfr"); ! ! ip->ip_restart_pc = saved_restart_pc; ! ! ip->ip_ptrace_info->fpreg_sp = sp - 8 * 8; /* 8 eight byte doubles */ ! ao_setreg(xp, UPSREG_SP, saved_sp); ! ! for (i = 0; i < 16; ++i) ! ip->ip_ptrace_info->fp_uregs[i].ur_is_current = FALSE; ! } ! ! ur = &ip->ip_ptrace_info->fp_uregs[regno]; ! if (!ur->ur_is_current) { ! if (ao_read_data(xp, ip->ip_ptrace_info->fpreg_sp + regno * 4, ! (char *)&ur->ur_value, 4) != 0) { ! errf("Can't read fp register value from the stack (%m)"); ! return -1; ! } ! ur->ur_is_current = TRUE; ! } ! ! *p_val = ur->ur_value; ! return 0; ! } ! #endif /* ARCH_CLIPPER */ ! ! #ifdef OS_SUNOS ! /* Return the current value of Sun register regno. ! * regno is a machine independent register number. ! */ ! taddr_t ! get_sun_regval(sr, pid, reg) ! sunregs_t *sr; ! int pid, reg; ! { ! switch(reg) { ! case UPSREG_PC: ! return sr->sr_regs.r_pc; ! case UPSREG_SP: ! return sr->sr_regs.r_sp; ! case UPSREG_FP: ! case UPSREG_AP: ! return FRAME_REG(sr); ! #ifdef ARCH_SUN4 ! case UPSREG_CONDITION_CODES: ! return sr->sr_regs.r_psr; ! #endif ! default: ! #ifdef ARCH_SUN4 ! if (reg == UPSREG_FP_CONDITION_CODES || (reg >= 32 && reg < 64)) { ! if (sr->sr_need_fpu) { ! e_ptrace(PTRACE_GETFPREGS, pid, ! (char *)&sr->sr_fpu, 0); ! sr->sr_need_fpu = FALSE; ! } ! if (reg == UPSREG_FP_CONDITION_CODES) ! return sr->sr_fpu.fpu_fsr; ! return sr->sr_fpu.fpu_regs[reg - FLOAT_REG_OFFSET]; ! } ! #endif ! if (reg < 0 || reg >= N_SUN_GREGS) ! panic("bad reg in gsr"); ! #ifdef ARCH_SUN4 ! if (reg == 0) ! return 0; ! #endif ! return INTEGER_REG(sr, reg); ! } ! } ! ! static int ! set_sun_regval(sr, pid, regno, val) ! sunregs_t *sr; ! int pid, regno; ! taddr_t val; ! { ! #ifdef ARCH_SUN3 ! /* BUG */ ! if (regno >= 14) { ! errf("\bCan't handle 68881/fpa register floats yet"); ! return -1; ! } ! #endif ! ! switch(regno) { ! case UPSREG_PC: ! sr->sr_regs.r_pc = val; ! break; ! case UPSREG_FP: ! case UPSREG_AP: ! FRAME_REG(sr) = val; ! break; ! case UPSREG_SP: ! sr->sr_regs.r_sp = val; ! break; ! default: ! #ifdef ARCH_SUN4 ! if (IS_FLOAT_REG(regno)) { ! if (sr->sr_need_fpu) { ! e_ptrace(PTRACE_GETFPREGS, pid, ! (char *)&sr->sr_fpu, 0); ! sr->sr_need_fpu = FALSE; ! } ! sr->sr_fpu.fpu_regs[regno - FLOAT_REG_OFFSET] = val; ! ! if (std_ptrace(PTRACE_SETFPREGS, pid, ! (char *)&sr->sr_fpu, 0) != 0) { ! sr->sr_need_fpu = TRUE; ! return -1; ! } ! return 0; ! } ! #endif ! if (regno < 0 || regno >= N_SUN_GREGS) ! panic("bad regno in ssr"); ! INTEGER_REG(sr, regno) = val; ! break; ! } ! ! errno = 0; ! e_ptrace(PTRACE_SETREGS, pid, (char *)sr, 0); ! if (errno != 0) ! return -1; ! ! #ifdef ARCH_SUN4 ! if (ptrace(PTRACE_WRITEDATA, pid, (char *)sr->sr_regs.r_sp, ! sizeof(sr->sr_rwindow), (char *)&sr->sr_rwindow) != 0) ! return -1; ! #endif ! ! return 0; ! } ! ! #endif /* OS_SUNOS */ ! ! #ifdef ARCH_BSDI386 ! static int ! get_uarea_word_with_ptrace(pid, offset) ! int pid, offset; ! { ! return e_ptrace(PTRACE_PEEKUSER, pid, (char *)offset, 0); ! } ! ! void ! set_uarea_reg_offsets(ur, get_uarea_word, arg) ! ureg_t *ur; ! get_uarea_word_func_t get_uarea_word; ! int arg; ! { ! static int trapregs[N_UREGS] = { ! tEAX, tECX, tEDX, tEBX, tESP, tEBP, tESI, tEDI, tEIP ! }; ! #ifdef bsdi ! static int syscallregs[N_UREGS] = { ! sEAX, sECX, sEDX, sEBX, sESP, sEBP, sESI, sEDI, sEIP ! }; ! #endif ! taddr_t addr; ! int flags, offset, i, *regmap; ! ! flags = (*get_uarea_word)(arg, (int)U_OFFSET(u_pcb.pcb_flags)); ! #ifdef bsdi ! regmap = ((flags & FM_TRAP) != 0) ? trapregs : syscallregs; ! addr = (*get_uarea_word)(arg, (int)U_OFFSET(u_kproc.kp_proc.p_regs)); ! #else ! regmap = trapregs; ! addr = (*get_uarea_word)(arg, (int)U_OFFSET(u_kproc.kp_proc.p_md.md_regs)); ! #endif ! ! offset = addr - USRSTACK; ! ! for (i = 0; i < N_UREGS; ++i) ! ur[i].ur_uaddr = offset + 4 * regmap[i]; ! } ! #endif /* ARCH_BSDI386 */ ! ! /* Update the stored machine register values. This is called after the ! * target has been run and has thus changed the register values. ! * For the VAX, we just mark our cached values as invalid. ! * ! * The pc is a special case, as when we hit a breakpoint some machines ! * report the pc as pointing after the trap opcode. Thus if we are at ! * a breakpoint we adjust the pc value. The VAX kernel seems to do ! * this for us. ! * ! * Return TRUE if the target stopped because it hit a breakpoint. ! */ ! static int ! update_regs(xp) ! target_t *xp; ! { ! taddr_t pc; ! breakpoint_t *bp; ! iproc_t *ip; ! #ifdef UAREA_REGS ! ureg_t *ur; ! #endif ! #ifdef OS_SUNOS ! sunregs_t *sr; ! #endif ! ! ip = GET_IPROC(xp); ! ! #ifdef UAREA_REGS ! for (ur = ip->ip_ptrace_info->uregs + N_UREGS; ur >= ip->ip_ptrace_info->uregs; --ur) ! ur->ur_is_current = FALSE; ! ! #ifdef ARCH_BSDI386 ! set_uarea_reg_offsets(ip->ip_ptrace_info->uregs, ! get_uarea_word_with_ptrace, ip->ip_pid); ! #endif ! ! #ifdef ARCH_CLIPPER ! ip->ip_ptrace_info->fpreg_sp = 0; ! #endif ! ! if (get_uarea_reg(ip, UR_PC, &pc) != 0) ! panic("can't get pc in ur"); ! bp = get_breakpoint_at_addr(xp, pc - BPT_PC_OFFSET); ! if (bp != NULL) { ! pc -= BPT_PC_OFFSET; ! ip->ip_ptrace_info->uregs[UR_PC].ur_value = pc; ! } ! #endif /* UAREA_REGS */ ! ! #ifdef OS_SUNOS ! sr = &ip->ip_ptrace_info->sunregs; ! e_ptrace(PTRACE_GETREGS, ip->ip_pid, (char *)&sr->sr_regs, 0); ! #ifdef ARCH_SUN4 ! if (ptrace(PTRACE_READDATA, ip->ip_pid, (char *)sr->sr_regs.r_sp, ! sizeof(sr->sr_rwindow), (char *)&sr->sr_rwindow) != 0) { ! panic("rwindow read botch in ur"); ! } ! #endif ! pc = (taddr_t)sr->sr_regs.r_pc; ! bp = get_breakpoint_at_addr(xp, pc - BPT_PC_OFFSET); ! if (bp != NULL) { ! pc -= BPT_PC_OFFSET; ! sr->sr_regs.r_pc = pc; ! } ! #if defined(ARCH_SUN3) || defined(ARCH_SUN4) ! sr->sr_need_fpu = TRUE; ! #endif ! #endif /* OS_SUNOS */ ! ip->ip_restart_pc = pc; ! return bp != NULL; ! } ! ! int ! ptrace_setreg(ip, regno, value) ! iproc_t *ip; ! int regno; ! taddr_t value; ! { ! #ifdef OS_SUNOS ! return set_sun_regval(&ip->ip_ptrace_info->sunregs, ! ip->ip_pid, regno, value); ! #else ! #ifdef UAREA_REGS ! return set_uarea_reg(ip, reg_to_uarea_index(regno), value); ! #else ! panic("don't know how to get a register value for this machine"); ! return 0; /* to satisfy gcc */ ! #endif /* !UAREA_REGS */ ! #endif /* !ARCH_SUN3 */ ! } ! ! #ifdef OS_SUNOS ! void ! ptrace_get_regtab(ip, sr) ! iproc_t *ip; ! sunregs_t *sr; ! { ! *sr = ip->ip_ptrace_info->sunregs; ! } ! ! bool ! ptrace_set_all_regs(ip, sr) ! iproc_t *ip; ! sunregs_t *sr; ! { ! if (std_ptrace(PTRACE_SETREGS, ip->ip_pid, ! (char *)&sr->sr_regs, 0) != 0) { ! return FALSE; ! } ! ! ip->ip_ptrace_info->sunregs = *sr; ! return TRUE; ! } ! #endif ! ! jmp_buf Longjmp_env; ! ! /* A pointer to this is passed to wn_set_abort_func() by wait_for_target(). ! */ ! static void ! stop_target() ! { ! longjmp(Longjmp_env, 1); ! } ! ! static int ! wait_with_intr(p_status) ! wait_arg_t *p_status; ! { ! if (setjmp(Longjmp_env) == 1) ! return 0; #ifdef OS_LINUX return wait3(p_status, WNOHANG, NULL); #else ! return wait(p_status); ! #endif ! } ! ! /* Wait for process xp to stop. If the process didn't die, update the ! * stored register values. Set ip_stopres to the reason why the ! * process stopped, and ip_restart_pc to the address the process ! * should be restarted from. ! */ ! static void ! wait_for_target(xp) ! target_t *xp; ! { ! static int want_errors = -1; ! iproc_t *ip; ! stopres_t stopres; ! int pid, at_bpt; ! bool user_stopped_target; ! wait_arg_t status; ! ! ip = GET_IPROC(xp); ! ! if (want_errors == -1) ! want_errors = getenv("WANT_ERRORS") != NULL; ! ! user_stopped_target = FALSE; ! for (;;) { ! abort_func_t oldfunc; ! ! if ((Debug_flags & DBFLAG_NO_STOP) != 0) ! pid = wait(&status); ! else { ! oldfunc = set_user_abort_func(stop_target); ! pid = wait_with_intr(&status); ! (void) set_user_abort_func(oldfunc); ! } ! ! if (pid == 0) { ! if (user_wants_stop(FALSE)) { ! kill(ip->ip_pid, SIGTRAP); ! user_stopped_target = TRUE; ! } ! continue; ! } ! else ! if (user_wants_stop(FALSE)) /* RGA so Stop button breaks */ ! user_stopped_target = TRUE; /* out of a Step */ ! if (pid == ip->ip_pid) ! break; ! else if (pid == -1) { ! if (errno != EINTR) ! errf("Wait returned -1: %s", get_errno_str()); ! } ! else { ! if (want_errors) ! errf("Wait returned bad pid %d (expected %d)", ! pid, ip->ip_pid); ! } ! } ! ! if (WIFSTOPPED(status)) { ! ip->ip_lastsig = 0; ! at_bpt = update_regs(xp); ! if (WSTOPSIG(status) != SIGTRAP) { ! stopres = SR_SIG; ! ip->ip_lastsig = WSTOPSIG(status); ! } ! else if (user_stopped_target) ! stopres = SR_USER; ! else if (at_bpt) ! stopres = SR_BPT; ! else ! stopres = SR_SSTEP; ! } ! else { ! ip->ip_lastsig = -1; ! ip->ip_restart_pc = 0; ! stopres = SR_DIED; ! mark_breakpoints_as_uninstalled(xp); ! } ! ip->ip_stopres = stopres; ! ! if (stopres == SR_DIED) { ! ip->ip_pid = 0; ! #ifndef OS_LINUX ! #if defined(OS_SUNOS_4) || defined(OS_BSD44) ! unload_shared_library_symtabs(xp); ! #endif ! #endif ! } ! } ! ! static char * ! get_restart_pc(ip) ! iproc_t *ip; ! { ! #ifdef ARCH_CLIPPER ! if (ip->ip_ptrace_info->fpreg_sp != 0) ! return (char *)ip->ip_restart_pc; ! #endif ! if (ip->ip_stopres != SR_BPT) ! return (char *)1; ! ! return (char *)ip->ip_restart_pc; ! } ! ! static void ! init_pid(ip, pid, attached) ! iproc_t *ip; ! int pid; ! bool attached; ! { ! if (ip->ip_ptrace_info == NULL) { ! ip->ip_ptrace_info = ! (Ptrace_info *)e_malloc(sizeof(Ptrace_info)); ! } ! ! ip->ip_core = NULL; ! ip->ip_pid = pid; ! ip->ip_attached = attached; ! ! #if defined(UAREA_REGS) && !defined(ARCH_BSDI386) ! set_uarea_reg_offsets(ip->ip_ptrace_info->uregs); ! #endif ! ! #ifdef ARCH_CLIPPER ! ip->ip_ptrace_info->fpreg_sp = 0; ! #endif ! ! #ifdef ARCH_SUN3 ! ip->ip_ptrace_info->sunregs.sr_fptype = FPT_68881; /* BUG: just for testing */ ! #endif ! ! #ifdef OS_SUNOS ! /* Purify doesn't seem to know that PTRACE_GETREGS sets ! * all of a regs structure. ! */ ! memset((char *)&ip->ip_ptrace_info->sunregs, '\0', sizeof(ip->ip_ptrace_info->sunregs)); ! #endif ! } ! ! int ! ptrace_create_child(xp, argv, envp, rdlist, p_stopres) ! target_t *xp; ! const char **argv, **envp; ! long rdlist; ! stopres_t *p_stopres; ! { ! iproc_t *ip; ! int pid; ! taddr_t main_addr, main_min_bpt_addr; ! ! ip = GET_IPROC(xp); ! ! fflush(stdout); ! fflush(stderr); ! ! if ((pid = vfork()) == 0) { ! arg_do_redirs_in_child(rdlist); ! if (std_ptrace(PTRACE_TRACEME, 0, (char *)NULL, 0) != 0) ! panic("ptrace TRACEME request failed in child"); ! execve(xp->xp_textpath, (char **)argv, (char **)envp); ! perror(xp->xp_textpath); ! _exit(1); ! } ! ! arg_tidy_redirs_in_parent(rdlist); ! if (pid == -1) { ! failmesg("Can't fork to run", "", xp->xp_textpath); ! *p_stopres = SR_DIED; ! return -1; ! } ! ! #ifndef OS_LINUX ! if (ip->ip_core != NULL) ! unload_shared_library_symtabs(xp); ! #endif ! ! init_pid(ip, pid, FALSE); ! ! wait_for_target(xp); ! ! if (ip->ip_stopres == SR_DIED) { ! errf("Can't start %s", xp->xp_textpath); ! *p_stopres = SR_DIED; ! return -1; ! } ! ! *p_stopres = ip->ip_stopres; ! if (!target_process_exists(xp)) ! return -1; ! ! if (get_startup_stop_addrs(xp, &main_addr, &main_min_bpt_addr) != 0) ! return -1; ! ! /* We want the target stopped at the start of main so we can ! * get the minimum sp value (xp_set_base_sp) - this is used ! * to decide when we have stepped off the end of main. ! * ! * Under SunOS we also need to load shared library information ! * after the target has started and the runtime linking has been ! * done. In this case (OS_SUNOS_4) we have to first stop right ! * at the start of main, then set another breakpoint after the ! * stack setup code (the usual place) and continue the target to ! * that. The reason for this is that run-time linking invoked ! * from [start] will overwrite the first user instruction in main ! * if it refers to a shared library global, blowing away any ! * breakpoint that has been written there. We assume that the ! * stack setup code will not contain such an instruction. ! */ ! if (*p_stopres == SR_SSTEP) { ! #ifdef OS_SUNOS_4 ! *p_stopres = xp_execto(xp, main_addr); ! if (*p_stopres == SR_BPT && main_addr != main_min_bpt_addr) ! *p_stopres = xp_execto(xp, main_min_bpt_addr); ! #else ! *p_stopres = xp_execto(xp, main_min_bpt_addr); ! #ifdef AO_ELF ! xp->xp_new_dynamic_libs = ! elf_get_dynamic_solibs(xp->xp_apool, xp->xp_textpath, ! NULL, &ip->ip_solibs, FALSE); ! #endif ! #endif ! } ! ! return 0; ! } ! ! int ! ptrace_attach_to_process(xp, pid) ! target_t *xp; ! int pid; ! { ! #if defined(OS_SUNOS) || defined(OS_LINUX) || defined(OS_BSD44) ! iproc_t *ip; ! int reattach; ! ! if (pid == 0) ! pid = Last_attach_pid; ! else ! Last_attach_pid = pid; ! ! ip = GET_IPROC(xp); ! ! #if defined(OS_BSD44) ! { ! int fd; ! char *procfs_file; ! procfs_file = strf ("/proc/%d/ctl", pid); ! if (((fd = open (procfs_file, O_WRONLY, 0)) < 0) ! || (write (fd, "attach", 7) != 7)) { ! errf("Can't attach to %s (%s)", procfs_file, get_errno_str()); ! return -1; ! } ! close (fd); ! } ! #else ! if (std_ptrace(PTRACE_ATTACH, pid, (char *)NULL, 0) != 0) { ! errf("Can't attach to process %d (%s)", pid, get_errno_str()); ! return -1; ! } ! #endif ! init_pid(ip, pid, TRUE); ! wait_for_target(xp); ! ! if (ip->ip_stopres == SR_DIED) { ! errf("Process %d died on being attached to!", pid); ! ip->ip_pid = 0; ! return -1; ! } ! ! #if defined(OS_SUNOS_4) || defined(OS_BSD44) ! reattach = ptrace_get_last_attach_pid() != 0; ! if (reattach) ! { ! free_library_load_list(); ! if (td_init_from()) ! { ! bool eof; ! int res; ! ! res = td_load_loop(&eof); ! ! if (res != 0) ! fprintf(stderr, "Error in init file\n"); ! td_restore_replay_fp(); ! } ! } ! load_shared_library_symtabs(xp, FALSE); ! #endif ! ! return 0; ! #else ! errf("This machine does not support attaching to running processes"); ! return -1; ! #endif /* OS_SUNOS || OS_LINUX */ } ! /* Kill off the target process */ void ! ptrace_kill(xp) target_t *xp; { ! wait_arg_t status; iproc_t *ip; ip = GET_IPROC(xp); ! std_ptrace(PTRACE_KILL, ip->ip_pid, (char *)NULL, 0); ! if (ip->ip_attached) { ! /* wait() hangs on a PTRACE_ATTACH process which ! * has been killed, so fake the status. ! */ ! #ifdef WAIT_STATUS_IS_INT ! status = SIGKILL; ! #else ! status.w_T.w_Termsig = SIGKILL; ! status.w_T.w_Retcode = 0; ! #endif } ! #ifndef OS_LINUX ! #if defined(OS_SUNOS_4) || defined(OS_BSD44) ! mark_breakpoints_as_uninstalled(xp); ! unload_shared_library_symtabs(xp); ! #endif ! #endif ! /* RGA commenting out per Ian Edwards : ! wait_for_target() only called ! unload_shared_library_symtabs() if stopres == SR_DIED, on FreeBSD ! stopres was SR_SIG so it was not called. Also need to mark ! breakpoints as uninstalled as they get reloaded. else { ! wait_for_target(xp); ! }*/ ip->ip_pid = 0; } void ptrace_stop(xp) target_t *xp; --- 57,277 ---- typedef union wait wait_arg_t; #endif ! #ifdef ARCH_SUN4 ! #define NO_SINGLE_STEP #endif ! #ifndef WSTOPSIG ! #define WSTOPSIG(w) ((w).w_stopsig) #endif ! /* Used for reattaching to same target */ ! static int Last_attach_pid; ! ! /* Used by 'stop_target()'. */ ! static jmp_buf Longjmp_env; ! ! static void stop_target PROTO((void)); ! static char *get_restart_pc PROTO((iproc_t *ip)); ! static int wait_with_intr PROTO((wait_arg_t *p_status)); static int get_words PROTO((int pid, ptracereq_t ptrace_req, taddr_t addr, char *buf, size_t nbytes)); ! #ifndef AO_HAS_PTRACE_RANGE ! static int ! get_words(pid, ptrace_req, addr, buf, nbytes) ! int pid; ! ptracereq_t ptrace_req; ! taddr_t addr; ! char *buf; ! size_t nbytes; ! { ! char *optr; ! int word, trailing_nbytes; ! taddr_t lim; ! optr = buf; ! /* Round down the address to a four byte alignment */ ! if ((addr & (WORDSIZE - 1)) != 0) { ! taddr_t aligned; ! int offset, count; ! offset = addr & (WORDSIZE - 1); ! aligned = addr - offset; ! errno = 0; ! word = std_ptrace(ptrace_req, pid, (char *)aligned, 0); ! if (errno != 0) ! return -1; ! count = WORDSIZE - offset; ! if (count > nbytes) ! count = nbytes; ! memcpy(buf, (char *)&word + offset, count); ! optr += count; ! addr += count; ! nbytes -= count; } ! /* At this point addr is on a 32 bit word boundary. ! */ ! trailing_nbytes = nbytes & 03; ! nbytes -= trailing_nbytes; ! lim = addr + nbytes; ! errno = 0; ! /* Copy the whole words into the buffer. We still have to use ! * memcpy because optr might not be four byte aligned (in our ! * address space) and some machines (e.g. MIPS) would object. ! */ ! while (addr < lim) { ! word = std_ptrace(ptrace_req, pid, (char *)addr, 0); ! memcpy(optr, (char *)&word, WORDSIZE); ! addr += WORDSIZE; ! optr += WORDSIZE; } ! if (trailing_nbytes != 0) { ! word = std_ptrace(ptrace_req, pid, (char *)addr, 0); ! memcpy(optr, (char *)&word, trailing_nbytes); ! } ! return errno != 0 ? -1 : 0; } ! #endif ! static char * ! get_restart_pc(ip) ! iproc_t *ip; { ! #ifdef ARCH_CLIPPER ! if (ip->ip_ptrace_info->fpreg_sp != 0) ! return (char *)ip->ip_restart_pc; #endif ! if (ip->ip_stopres != SR_BPT) ! return (char *)1; + return (char *)ip->ip_restart_pc; + } ! /* A pointer to this is passed to wn_set_abort_func() by ptrace_wait_for_target(). ! */ ! static void ! stop_target() { ! longjmp(Longjmp_env, 1); } ! static int ! wait_with_intr(p_status) ! wait_arg_t *p_status; { ! if (setjmp(Longjmp_env) == 1) ! return 0; #ifdef OS_LINUX return wait3(p_status, WNOHANG, NULL); #else ! return wait(p_status); ! #endif } ! ! /* Wait for process xp to stop. If the process didn't die, update the ! * stored register values. Set ip_stopres to the reason why the ! * process stopped, and ip_restart_pc to the address the process ! * should be restarted from. */ void ! ptrace_wait_for_target(xp) target_t *xp; { ! static int want_errors = -1; iproc_t *ip; + stopres_t stopres; + int pid, at_bpt; + bool user_stopped_target; + wait_arg_t status; ip = GET_IPROC(xp); ! if (want_errors == -1) ! want_errors = getenv("WANT_ERRORS") != NULL; ! user_stopped_target = FALSE; ! for (;;) { ! abort_func_t oldfunc; ! ! if ((Debug_flags & DBFLAG_NO_STOP) != 0) ! pid = wait(&status); ! else { ! oldfunc = set_user_abort_func(stop_target); ! pid = wait_with_intr(&status); ! (void) set_user_abort_func(oldfunc); } ! if (pid == 0) { ! if (user_wants_stop(FALSE)) { ! kill(ip->ip_pid, SIGTRAP); ! user_stopped_target = TRUE; ! } ! continue; ! } ! else ! if (user_wants_stop(FALSE)) /* RGA so Stop button breaks */ ! user_stopped_target = TRUE; /* out of a Step */ ! if (pid == ip->ip_pid) ! break; ! else if (pid == -1) { ! if (errno != EINTR) ! errf("Wait returned -1: %s", get_errno_str()); ! } ! else { ! if (want_errors) ! errf("Wait returned bad pid %d (expected %d)", ! pid, ip->ip_pid); ! } ! } + if (WIFSTOPPED(status)) { + ip->ip_lastsig = 0; + at_bpt = ptrace_update_regs(xp); + if (WSTOPSIG(status) != SIGTRAP) { + stopres = SR_SIG; + ip->ip_lastsig = WSTOPSIG(status); + } + else if (user_stopped_target) + stopres = SR_USER; + else if (at_bpt) + stopres = SR_BPT; + else + stopres = SR_SSTEP; + } else { ! ip->ip_lastsig = -1; ! ip->ip_restart_pc = 0; ! stopres = SR_DIED; ! mark_breakpoints_as_uninstalled(xp); ! } ! ip->ip_stopres = stopres; ! ! if (stopres == SR_DIED) { ip->ip_pid = 0; + unload_shared_library_symtabs(xp); + } } + void ptrace_stop(xp) target_t *xp; *************** *** 1327,1374 **** } } - int - ptrace_get_last_attach_pid() - { - return Last_attach_pid; - } - - /* Detach from a process which we earlier attached to. - * Leave the process running. - */ - void - ptrace_detach_from_process(xp) - target_t *xp; - { - iproc_t *ip; - - ip = GET_IPROC(xp); - - #if defined(OS_BSD44) - { - int fd; - char *procfs_file; - procfs_file = strf ("/proc/%d/ctl", ip->ip_pid); - if (((fd = open (procfs_file, O_WRONLY, 0)) < 0) - || (write (fd, "detach", 7) != 7)) { - errf("Can't detach from %s (%s)", procfs_file, get_errno_str()); - } - close (fd); - } - #endif - #ifdef OS_SUNOS - (void) e_ptrace(PTRACE_DETACH, ip->ip_pid, - get_restart_pc(ip), ip->ip_lastsig); - #endif /* OS_SUNOS */ - - #ifndef OS_LINUX - #if defined(OS_SUNOS_4) || defined(OS_BSD44) - unload_shared_library_symtabs(xp); - #endif - #endif - ip->ip_pid = 0; - ip->ip_attached = FALSE; /* RGA added */ - } stopres_t ptrace_continue(xp, addr, sig) --- 285,290 ---- *************** *** 1385,1394 **** (addr != 0) ? (char *)addr : get_restart_pc(ip), sig); ! wait_for_target(xp); return ip->ip_stopres; } stopres_t ptrace_single_step(xp, sig) target_t *xp; --- 301,311 ---- (addr != 0) ? (char *)addr : get_restart_pc(ip), sig); ! ptrace_wait_for_target(xp); return ip->ip_stopres; } + stopres_t ptrace_single_step(xp, sig) target_t *xp; *************** *** 1418,1424 **** panic("can't install bp in sst"); e_ptrace(PTRACE_CONT, ip->ip_pid, get_restart_pc(ip), sig); ! wait_for_target(xp); if (ip->ip_stopres != SR_DIED) { if (must_uninstall_bp && uninstall_breakpoint(bp) != 0) --- 335,341 ---- panic("can't install bp in sst"); e_ptrace(PTRACE_CONT, ip->ip_pid, get_restart_pc(ip), sig); ! ptrace_wait_for_target(xp); if (ip->ip_stopres != SR_DIED) { if (must_uninstall_bp && uninstall_breakpoint(bp) != 0) *************** *** 1431,1691 **** #else (void) e_ptrace(PTRACE_SINGLESTEP, ip->ip_pid, get_restart_pc(ip), sig); ! wait_for_target(xp); #endif /* !NO_SINGLE_STEP */ return ip->ip_stopres; } ! ! int ! ptrace_readreg(ip, regno, p_val) ! iproc_t *ip; ! int regno; ! taddr_t *p_val; { ! if (ip->ip_pid == 0) { ! #ifdef ARCH_CLIPPER ! if (regno >= 16 && regno < 32) { ! errf("Sorry, can't get fp registers from core files on the Clipper"); ! return -1; ! } ! #endif ! #ifdef OS_LINUX ! errf("Sorry, getting fp registers from core files on this machine not implemented"); ! *p_val = 0; ! return 0; ! #else ! return aout_get_core_reg(ip->ip_core, regno, p_val); ! #endif ! } ! #ifdef OS_SUNOS ! *p_val = get_sun_regval(&ip->ip_ptrace_info->sunregs, ! ip->ip_pid, regno); ! return 0; ! #else ! #ifdef UAREA_REGS ! #ifdef ARCH_CLIPPER ! if (regno >= 16 && regno < 32) ! return get_clipper_fp_reg(ip, regno - 16, p_val); ! #endif ! return get_uarea_reg(ip, reg_to_uarea_index(regno), p_val); ! #else ! panic("don't know how to get a register value for this machine"); ! return -1; /* to satisfy gcc */ ! #endif /* !UAREA_REGS */ ! #endif /* !ARCH_SUN3 */ ! } ! int ! ptrace_read_fpreg(ip, regno, num_bytes, p_val) ! iproc_t *ip; ! int regno; ! int num_bytes; ! fpval_t *p_val; ! { ! #ifdef ARCH_SUN3 ! sunregs_t *sr; ! /* The f68881 has eight registers, which are numbered 18..25 in ! * the symbol table. */ ! regno -= 18; ! if (regno < 0 || regno >= 8) ! panic("bad regno in rf"); ! ! ip = GET_IPROC(xp); ! sr = &ip->ip_ptrace_info->sunregs; ! if (sr->sr_need_fpu) { ! e_ptrace(PTRACE_GETFPREGS, ip->ip_pid, (char *)&sr->sr_fpu, 0); ! sr->sr_need_fpu = FALSE; ! } ! ! convert_68881_reg((unsigned *)sr->sr_fpu.f_fpstatus.fps_regs[regno].fp, ! (num_bytes == sizeof(double), p_val); ! return 0; #else ! switch (num_bytes) { ! case sizeof(float): ! if (ptrace_readreg(ip, regno, (taddr_t *)&p_val->f) != 0) ! return -1; ! break; ! case sizeof(double): ! { ! int regno2; ! taddr_t *buf = (taddr_t *)&p_val->d; ! ! regno2 = regno + 1; ! #ifdef ARCH_BSDI386 ! if (regno == 3) ! regno2 = 6; #endif - if (ptrace_readreg(ip, regno, buf) != 0 || - ptrace_readreg(ip, regno2, buf + 1) != 0) - return -1; } ! break; ! #if (defined(__GNUC__) && !defined (OS_SUNOS_4)) || defined(HAVE_LONG_DOUBLE) ! case sizeof(long double): ! panic("cannot do long double from register"); ! break; ! #endif } ! return 0; ! #endif } ! #if defined(ARCH_SUN4) && defined(CPU_ARCH) ! /* The Sun 4m CPU has an extra 1024 byte field at the start of the ! * u area. This means we have to add or subtract this amount if we ! * are running on a different CPU architecture than the one we were ! * compiled on. ! */ ! static int ! sparc_u_offset() { ! static int offset; ! static bool need_offset = TRUE; ! if (need_offset) { ! int cputype; ! cputype = (gethostid() >> 24) & CPU_ARCH; ! #ifdef SUN4M_ARCH ! offset = (cputype == SUN4M_ARCH) ? 0 : -1024; ! #else ! offset = (cputype == 0x70) ? 1024 : 0; #endif ! if ((Debug_flags & DBFLAG_MISC) != 0) ! printf("sparc_u_offset = %d\n", offset); ! need_offset = FALSE; } ! return offset; ! } ! #endif ! /* Return the current state of signal handling for signal sig in process ! * xp. Returns SGH_CAUGHT, SGH_IGNORED or SGH_DEFAULT. * ! * You might think we could return the address of the signal handler for ! * caught signals, but on the Suns at least the returned address is that ! * of a library routine which handles all caught signals. */ ! sigstate_t ! ptrace_get_sigstate(ip, signo) ! iproc_t *ip; ! int signo; ! { ! caddr_t uaddr; ! taddr_t handler; ! sigstate_t res; ! ! if (signo < 1 || signo >= NSIG) ! panic("signo botch in gss"); ! ! #ifdef ARCH_MIPS ! uaddr = (char *)(SIG_BASE + signo); ! #else ! #ifdef ARCH_BSDI386 ! uaddr = U_OFFSET(u_sigacts.ps_sigact[signo]); ! #else ! #if defined(ARCH_SUN4) && defined(CPU_ARCH) ! uaddr = U_OFFSET(u_signal[signo]) + sparc_u_offset(); ! #else ! #ifdef ARCH_LINUX386 ! uaddr = 0; /* XXX */ #else ! uaddr = U_OFFSET(u_signal[signo]); ! #endif ! #endif #endif #endif ! errno = 0; ! handler = e_ptrace(PTRACE_PEEKUSER, ip->ip_pid, (char *)uaddr, 0); - if (handler == (taddr_t)SIG_IGN) - res = SGH_IGNORED; - else if (handler == (taddr_t)SIG_DFL) - res = SGH_DEFAULT; - else - res = SGH_CAUGHT; ! return res; } ! #ifndef OS_SUNOS ! static int ! get_words(pid, ptrace_req, addr, buf, nbytes) int pid; - ptracereq_t ptrace_req; - taddr_t addr; - char *buf; - size_t nbytes; { ! char *optr; ! int word, trailing_nbytes; ! taddr_t lim; ! optr = buf; ! /* Round down the address to a four byte alignment ! */ ! if ((addr & (WORDSIZE - 1)) != 0) { ! taddr_t aligned; ! int offset, count; ! offset = addr & (WORDSIZE - 1); ! aligned = addr - offset; ! errno = 0; ! word = std_ptrace(ptrace_req, pid, (char *)aligned, 0); ! if (errno != 0) return -1; ! count = WORDSIZE - offset; ! if (count > nbytes) ! count = nbytes; ! memcpy(buf, (char *)&word + offset, count); ! optr += count; ! addr += count; ! nbytes -= count; } ! /* At this point addr is on a 32 bit word boundary. ! */ ! ! trailing_nbytes = nbytes & 03; ! nbytes -= trailing_nbytes; ! lim = addr + nbytes; ! errno = 0; ! /* Copy the whole words into the buffer. We still have to use ! * memcpy because optr might not be four byte aligned (in our ! * address space) and some machines (e.g. MIPS) would object. ! */ ! while (addr < lim) { ! word = std_ptrace(ptrace_req, pid, (char *)addr, 0); ! memcpy(optr, (char *)&word, WORDSIZE); ! addr += WORDSIZE; ! optr += WORDSIZE; } - - if (trailing_nbytes != 0) { - word = std_ptrace(ptrace_req, pid, (char *)addr, 0); - memcpy(optr, (char *)&word, trailing_nbytes); } ! return errno != 0 ? -1 : 0; } #endif int ptrace_write_text(ip, addr, buf, nbytes) --- 348,591 ---- #else (void) e_ptrace(PTRACE_SINGLESTEP, ip->ip_pid, get_restart_pc(ip), sig); ! ptrace_wait_for_target(xp); #endif /* !NO_SINGLE_STEP */ return ip->ip_stopres; } ! /* Kill off the target process ! */ ! void ! ptrace_kill(xp) ! target_t *xp; { ! wait_arg_t status; ! iproc_t *ip; ! ip = GET_IPROC(xp); ! std_ptrace(PTRACE_KILL, ip->ip_pid, (char *)NULL, 0); ! if (ip->ip_attached) { ! /* wait() hangs on a PTRACE_ATTACH process which ! * has been killed, so fake the status. */ ! #ifdef WAIT_STATUS_IS_INT ! status = SIGKILL; #else ! status.w_T.w_Termsig = SIGKILL; ! status.w_T.w_Retcode = 0; #endif } ! else { ! ptrace_wait_for_target(xp); } ! mark_breakpoints_as_uninstalled(xp); ! unload_shared_library_symtabs(xp); ! ip->ip_pid = 0; } ! ! int ! ptrace_create_child(xp, argv, envp, rdlist, p_stopres) ! target_t *xp; ! const char **argv, **envp; ! long rdlist; ! stopres_t *p_stopres; { ! iproc_t *ip; ! int pid; ! taddr_t main_addr, main_min_bpt_addr; ! ip = GET_IPROC(xp); ! fflush(stdout); ! fflush(stderr); ! if ((pid = vfork()) == 0) { ! arg_do_redirs_in_child(rdlist); ! if (std_ptrace(PTRACE_TRACEME, 0, (char *)NULL, 0) != 0) ! panic("ptrace TRACEME request failed in child"); ! execve(xp->xp_textpath, (char **)argv, (char **)envp); ! perror(xp->xp_textpath); ! _exit(1); ! } ! ! arg_tidy_redirs_in_parent(rdlist); ! if (pid == -1) { ! failmesg("Can't fork to run", "", xp->xp_textpath); ! *p_stopres = SR_DIED; ! return -1; ! } ! ! #ifndef OS_LINUX ! if (ip->ip_core != NULL) ! unload_shared_library_symtabs(xp); #endif ! ptrace_init_pid(ip, pid, FALSE); ! ! ptrace_wait_for_target(xp); ! if (ip->ip_stopres == SR_DIED) { ! errf("Can't start %s", xp->xp_textpath); ! *p_stopres = SR_DIED; ! return -1; } ! *p_stopres = ip->ip_stopres; ! if (!target_process_exists(xp)) ! return -1; ! ! if (get_startup_stop_addrs(xp, &main_addr, &main_min_bpt_addr) != 0) ! return -1; ! /* We want the target stopped at the start of main so we can ! * get the minimum sp value (xp_set_base_sp) - this is used ! * to decide when we have stepped off the end of main. * ! * Under SunOS we also need to load shared library information ! * after the target has started and the runtime linking has been ! * done. In this case (OS_SUNOS_4) we have to first stop right ! * at the start of main, then set another breakpoint after the ! * stack setup code (the usual place) and continue the target to ! * that. The reason for this is that run-time linking invoked ! * from [start] will overwrite the first user instruction in main ! * if it refers to a shared library global, blowing away any ! * breakpoint that has been written there. We assume that the ! * stack setup code will not contain such an instruction. */ ! if (*p_stopres == SR_SSTEP) { ! #ifdef OS_SUNOS_4 ! *p_stopres = xp_execto(xp, main_addr); ! if (*p_stopres == SR_BPT && main_addr != main_min_bpt_addr) ! *p_stopres = xp_execto(xp, main_min_bpt_addr); #else ! *p_stopres = xp_execto(xp, main_min_bpt_addr); ! #ifdef AO_ELF ! xp->xp_new_dynamic_libs = ! elf_get_dynamic_solibs(xp->xp_apool, xp->xp_textpath, ! NULL, &ip->ip_solibs, FALSE); #endif #endif + } ! return 0; ! } ! int ! ptrace_get_last_attach_pid() ! { ! return Last_attach_pid; } ! ! int ! ptrace_attach_to_process(xp, pid) ! target_t *xp; int pid; { ! #if defined(AO_HAS_PTRACE_ATTACH) || defined(AO_USE_PROCFS_ATTACH) ! iproc_t *ip; ! int reattach; ! if (pid == 0) ! pid = Last_attach_pid; ! else ! Last_attach_pid = pid; ! ip = GET_IPROC(xp); ! #if defined(AO_USE_PROCFS_ATTACH) ! { ! int fd; ! char *procfs_file; ! procfs_file = strf ("/proc/%d/ctl", pid); ! if (((fd = open (procfs_file, O_WRONLY, 0)) < 0) ! || (write (fd, "attach", 7) != 7)) { ! errf("Can't attach to %s (%s)", procfs_file, get_errno_str()); ! return -1; ! } ! close (fd); ! } ! #else ! if (std_ptrace(PTRACE_ATTACH, pid, (char *)NULL, 0) != 0) { ! errf("Can't attach to process %d (%s)", pid, get_errno_str()); return -1; + } + #endif + ptrace_init_pid(ip, pid, TRUE); ! ptrace_wait_for_target(xp); ! if (ip->ip_stopres == SR_DIED) { ! errf("Process %d died on being attached to!", pid); ! ip->ip_pid = 0; ! return -1; } ! reattach = ptrace_get_last_attach_pid() != 0; ! if (reattach) ! { ! free_library_load_list(); ! if (td_init_from()) ! { ! bool eof; ! int res; ! res = td_load_loop(&eof); ! if (res != 0) ! fprintf(stderr, "Error in init file\n"); ! td_restore_replay_fp(); } } + load_shared_library_symtabs(xp, FALSE); ! return 0; ! #else ! errf("This machine does not support attaching to running processes"); ! return -1; ! #endif } + + + /* Detach from a process which we earlier attached to. + * Leave the process running. + */ + void + ptrace_detach_from_process(xp) + target_t *xp; + { + iproc_t *ip; + + ip = GET_IPROC(xp); + + #if defined(AO_HAS_PTRACE_ATTACH) || defined(AO_USE_PROCFS_ATTACH) + #if defined(AO_USE_PROCFS_ATTACH) + { + int fd; + char *procfs_file; + procfs_file = strf ("/proc/%d/ctl", ip->ip_pid); + if (((fd = open (procfs_file, O_WRONLY, 0)) < 0) + || (write (fd, "detach", 7) != 7)) { + errf("Can't detach from %s (%s)", procfs_file, get_errno_str()); + } + close (fd); + } + #else + (void) e_ptrace(PTRACE_DETACH, ip->ip_pid, + get_restart_pc(ip), ip->ip_lastsig); #endif + #endif + unload_shared_library_symtabs(xp); + ip->ip_pid = 0; + ip->ip_attached = FALSE; /* RGA added */ + } + int ptrace_write_text(ip, addr, buf, nbytes) *************** *** 1694,1700 **** const char *buf; size_t nbytes; { ! #ifdef OS_SUNOS if (ptrace(PTRACE_WRITETEXT, ip->ip_pid, (char *)addr, (int)nbytes, (char *)buf) != 0) return -1; --- 594,600 ---- const char *buf; size_t nbytes; { ! #ifdef AO_HAS_PTRACE_RANGE if (ptrace(PTRACE_WRITETEXT, ip->ip_pid, (char *)addr, (int)nbytes, (char *)buf) != 0) return -1; *************** *** 1714,1719 **** --- 614,620 ---- #endif } + /* Read nbytes bytes into buf starting at address addr in the text area * of process xp. The byte count is returned or -1 case of error. */ *************** *** 1731,1745 **** if (pid == 0) panic("ao_read_text_from_process with no proc"); ! #ifdef OS_SUNOS if (ptrace(PTRACE_READTEXT, pid, (char *)addr, (int)nbytes, buf) != 0) return -1; return 0; #else return get_words(pid, PTRACE_PEEKTEXT, addr, buf, nbytes); ! #endif /* !OS_SUNOS */ } /* Read nbytes of data into buf from process xp, starting at target * address addr. * Return the number of bytes read, or -1 if there was an error. --- 632,647 ---- if (pid == 0) panic("ao_read_text_from_process with no proc"); ! #ifdef AO_HAS_PTRACE_RANGE if (ptrace(PTRACE_READTEXT, pid, (char *)addr, (int)nbytes, buf) != 0) return -1; return 0; #else return get_words(pid, PTRACE_PEEKTEXT, addr, buf, nbytes); ! #endif } + /* Read nbytes of data into buf from process xp, starting at target * address addr. * Return the number of bytes read, or -1 if there was an error. *************** *** 1760,1766 **** */ memset(buf, '\0', nbytes); #endif ! #ifdef OS_SUNOS if (ptrace(PTRACE_READDATA, ip->ip_pid, (char *)addr, (int)nbytes, buf) == 0) return 0; --- 662,668 ---- */ memset(buf, '\0', nbytes); #endif ! #ifdef AO_HAS_PTRACE_RANGE if (ptrace(PTRACE_READDATA, ip->ip_pid, (char *)addr, (int)nbytes, buf) == 0) return 0; *************** *** 1768,1776 **** return -1; #else return get_words(ip->ip_pid, PTRACE_PEEKDATA, addr, buf, nbytes); ! #endif /* !OS_SUNOS */ } int ptrace_write_data(ip, addr, buf, nbytes) iproc_t *ip; --- 670,679 ---- return -1; #else return get_words(ip->ip_pid, PTRACE_PEEKDATA, addr, buf, nbytes); ! #endif } + int ptrace_write_data(ip, addr, buf, nbytes) iproc_t *ip; *************** *** 1778,1798 **** const char *buf; size_t nbytes; { ! #ifndef OS_SUNOS const char *iptr; taddr_t lim; int word, trailing_nbytes; - #endif int pid; pid = ip->ip_pid; - #ifdef OS_SUNOS - if (ptrace(PTRACE_WRITEDATA, pid, (char *)addr, (int)nbytes, - (char *)buf) == 0) - return 0; - else - return -1; - #else iptr = buf; /* Round down the address to a four byte alignment --- 681,699 ---- const char *buf; size_t nbytes; { ! #ifdef AO_HAS_PTRACE_RANGE ! if (ptrace(PTRACE_WRITEDATA, ip->ip_pid, (char *)addr, (int)nbytes, ! (char *)buf) == 0) ! return 0; ! else ! return -1; ! #else const char *iptr; taddr_t lim; int word, trailing_nbytes; int pid; pid = ip->ip_pid; iptr = buf; /* Round down the address to a four byte alignment *************** *** 1823,1829 **** addr += count; nbytes -= count; } - /* At this point addr is on a 32 bit word boundary. */ --- 724,729 ---- *************** *** 1851,1873 **** } return errno != 0 ? -1 : 0; ! #endif /* !OS_SUNOS */ } int ptrace_write_corefile(ip, name) iproc_t *ip; const char *name; { ! #ifdef OS_SUNOS if (std_ptrace(PTRACE_DUMPCORE, ip->ip_pid, (char *)name, 0) == 0) return 0; failmesg("Can't dump core file to", "file", name); #else errf("Sorry, this machine/OS does not support core snapshots"); - #endif return -1; } #endif /* AO_USE_PTRACE */ --- 751,863 ---- } return errno != 0 ? -1 : 0; ! #endif } + int ptrace_write_corefile(ip, name) iproc_t *ip; const char *name; { ! #ifdef AO_HAS_PTRACE_DUMPCORE if (std_ptrace(PTRACE_DUMPCORE, ip->ip_pid, (char *)name, 0) == 0) return 0; failmesg("Can't dump core file to", "file", name); + return -1; #else errf("Sorry, this machine/OS does not support core snapshots"); return -1; + #endif + } + + + /* Call ptrace(2), but abort if errno gets set. + */ + int + e_ptrace(req, pid, addr, data) + ptracereq_t req; + int pid; + char *addr; + int data; + { + int res; + + #ifdef ARCH_LINUX386 + if (req == PTRACE_CONT || req == PTRACE_SINGLESTEP) { + if (addr != (char *) 1) { + std_ptrace(PTRACE_POKEUSER, pid, 4*EIP, addr); + addr = (char *) 1; + } + } + #endif + errno = 0; + res = std_ptrace(req, pid, addr, data); + if (errno != 0) + panic("ptrace failed in e_ptrace"); + return res; + } + + + /* + * This routine *MUST* be the last in the file. + */ + #ifdef PTRACE_DEBUG + #undef ptrace + + int + ptrace_debug(request, pid, addr, data) + int request, pid, addr, data; + { + static char *reqnames[] = { + "TRACEME", "PEEKTEXT", "PEEKDATA", "PEEKUSER", "POKETEXT", + "POKEDATA", "POKEUSER", "CONT", "KILL", "SINGLESTEP" + }; + char buf[50], ebeforebuf[20], eafterbuf[20], *reqname, *ebefore, *eafter; + int errno_before, errno_after, res; + static bool first_call = TRUE, no_debug; + + if ((Debug_flags & DBFLAG_PTRACE) == 0) + return ptrace(request, pid, addr, data); + + if (request < 0 || request > 9) { + sprintf(buf, "", request); + reqname = buf; + } + else + reqname = reqnames[request]; + + errno_before = errno; + res = ptrace(request, pid, addr, data); + errno_after = errno; + if (errno_before != 0) { + sprintf(ebeforebuf, "[errno=%d]", errno_before); + ebefore = ebeforebuf; + } + else + ebefore = ""; + + if (errno_after != 0) { + sprintf(eafterbuf, "[errno=%d]", errno_after); + eafter = eafterbuf; + } + else + eafter = ""; + + fprintf(stderr, "\tproc %d%s: ptrace(%s, %d, 0x%x, 0x%x)", + getpid(), ebefore, + reqname, pid, addr, data); + if (res != 0 || errno_after != 0) + fprintf(stderr, " -> 0x%x%s", res, eafter); + fputc('\n', stderr); + + fflush(stderr); + + errno = errno_after; + return res; } + + #endif /* PTRACE_DEBUG */ #endif /* AO_USE_PTRACE */ *** ./ups/ao_ptrace.h.ups Thu Nov 6 18:30:50 1997 --- ./ups/ao_ptrace.h Tue Oct 6 15:41:54 1998 *************** *** 9,14 **** --- 9,117 ---- /* @(#)ao_ptrace.h 1.1 24/5/95 (UKC) */ + /* Cope with 'ptrace()' variations across systems. */ + /* ----------------------------------------------- */ + + #include + + #if defined(OS_SUNOS) + typedef enum ptracereq ptracereq_t; + #endif + + #if defined(OS_LINUX) + /* + * Request values for the ptrace system call + */ + #define PTRACE_PEEKUSER PTRACE_PEEKUSR + #define PTRACE_POKEUSER PTRACE_POKEUSR + typedef int ptracereq_t; + #endif + + #if defined (OS_BSD44) + /* + * Request values for the ptrace system call + */ + #define PTRACE_TRACEME PT_TRACE_ME /* by tracee to begin tracing */ + #define PTRACE_PEEKTEXT PT_READ_I /* read word from text segment */ + #define PTRACE_PEEKDATA PT_READ_D /* read word from data segment */ + #define PTRACE_PEEKUSER PT_READ_U /* read word from user struct */ + #define PTRACE_POKETEXT PT_WRITE_I /* write word into text segment */ + #define PTRACE_POKEDATA PT_WRITE_D /* write word into data segment */ + #define PTRACE_POKEUSER PT_WRITE_U /* write word into user struct */ + #define PTRACE_CONT PT_CONTINUE /* continue process */ + #define PTRACE_KILL PT_KILL /* terminate process */ + #define PTRACE_SINGLESTEP PT_STEP /* single step process */ + + #if defined(PT_ATTACH) && defined(PT_DETACH) + #define PTRACE_ATTACH PT_ATTACH + #define PTRACE_DETACH PT_DETACH + #else + #define PTRACE_ATTACH 10 + #define PTRACE_DETACH 11 + #endif + + #if defined(PT_GETREGS) && defined(PT_SETREGS) + #define PTRACE_GETREGS PT_GETREGS + #define PTRACE_SETREGS PT_SETREGS + #endif + + typedef int ptracereq_t; + #endif + + #if defined(ARCH_MIPS) && (defined(OS_ULTRIX) || defined(OS_RISCOS)) + /* + * Request values for the ptrace system call + */ + enum ptracereq { + PTRACE_TRACEME = PT_TRACE_ME, /* by tracee to begin tracing */ + PTRACE_PEEKTEXT = PT_READ_I, /* read word from text segment */ + PTRACE_PEEKDATA = PT_READ_D, /* read word from data segment */ + PTRACE_PEEKUSER = PT_READ_U, /* read word from user struct */ + PTRACE_POKETEXT = PT_WRITE_I, /* write word into text segment */ + PTRACE_POKEDATA = PT_WRITE_D, /* write word into data segment */ + PTRACE_POKEUSER = PT_WRITE_U, /* write word into user struct */ + PTRACE_CONT = PT_CONTINUE, /* continue process */ + PTRACE_KILL = PT_KILL, /* terminate process */ + PTRACE_SINGLESTEP = PT_STEP, /* single step process */ + }; + typedef enum ptracereq ptracereq_t; + #endif + + + /* + * Structure to hold registers got via 'ptrace()'. + */ + struct Ptrace_info { + #if defined(ARCH_CLIPPER) + taddr_t fpreg_sp; + ureg_t fp_uregs[16]; + #elif defined(OS_SUNOS_4) + sunregs_t sunregs; + #elif defined(AO_HAS_PTRACE_REGS) + ptrace_regs_t ptrace_regs; + #elif defined(UAREA_REGS) + ureg_t uregs[N_UREGS]; + #endif + }; + + + /* + * + */ + #ifdef ARCH_SUN3 + #define BPT_PC_OFFSET 2 + #else + #ifdef ARCH_386 + #define BPT_PC_OFFSET 1 + #else + #define BPT_PC_OFFSET 0 + #endif + #endif + + + /* + * Routine declarations. + */ int ptrace_setreg PROTO((iproc_t *ip, int regno, taddr_t value)); int ptrace_create_child PROTO((target_t *xp, const char **argv, const char **envp, *************** *** 35,42 **** --- 138,170 ---- size_t nbytes)); int ptrace_write_corefile PROTO((iproc_t *ip, const char *name)); + void ptrace_init_pid PROTO((iproc_t *ip, int pid, bool attached)); + void ptrace_wait_for_target PROTO((target_t *xp)); + int ptrace_update_regs PROTO((target_t *xp)); + int e_ptrace PROTO((ptracereq_t req, int pid, char *addr, int data)); + + #ifdef OS_SUNOS_4 int ptrace_set_all_regs PROTO((iproc_t *ip, sunregs_t *regtab)); void ptrace_get_regtab PROTO((iproc_t *ip, sunregs_t *regtab)); #endif int ptrace_get_last_attach_pid PROTO((void)); + + #ifdef PTRACE_DEBUG + int ptrace_debug PROTO((int request, int pid, int addr, int data)); + #define ptrace ptrace_debug + #endif + + #if defined(OS_SUNOS) + int ptrace PROTO((ptracereq_t req, int pid, char *addr, int data, char *addr2)); + #define std_ptrace(req, pid, addr, data) ptrace(req, pid, addr, data, (char *)NULL) + #elif defined(OS_BSD44) + #define std_ptrace(req, pid, addr, data) ptrace(req, pid, addr, data) + #elif defined(OS_LINUX) + #define std_ptrace(req, pid, addr, data) ptrace(req, pid, (int)addr, data) + #else + int ptrace PROTO((ptracereq_t req, int pid, char *addr, int data)); + #define std_ptrace(req, pid, addr, data) ptrace(req, pid, addr, data) + #endif + + *** ./ups/ao_target.c.ups Thu Oct 1 10:45:10 1998 --- ./ups/ao_target.c Tue Oct 6 02:07:53 1998 *************** *** 48,56 **** #include "obj_signal.h" #include "state.h" - #ifdef OS_LINUX - #include - #endif static int ao_initialise PROTO((ebuf_t *usage_eb, char **argv)); static void ao_show_target_driver_info PROTO((bool name_only)); --- 48,53 ---- *************** *** 846,856 **** #endif #ifdef OS_SUNOS #ifdef AO_USE_PROCFS ! static int *regs = NULL, *origregs; static size_t regbytes; #else ! sunregs_t sunregs, origsunregs; ! sunregs_t *regs, *origregs; #endif #endif #ifdef ARCH_SUN4 --- 843,853 ---- #endif #ifdef OS_SUNOS #ifdef AO_USE_PROCFS ! static int *regs = NULL, *orig_regs; static size_t regbytes; #else ! sunregs_t sunregs, orig_sunregs; ! sunregs_t *regs, *orig_regs; #endif #endif #ifdef ARCH_SUN4 *************** *** 864,871 **** --- 861,873 ---- taddr_t saved_sp, saved_regs[N_REG_ARGS]; #endif #if defined(ARCH_BSDI386) || defined(ARCH_LINUX386) + #ifdef AO_HAS_PTRACE_REGS + ptrace_regs_t ptrace_regs, orig_ptrace_regs; + ptrace_regs_t *regs, *orig_regs; + #else taddr_t saved_regs[N_UREGS]; #endif + #endif breakpoint_t *bp; taddr_t realargs[40]; *************** *** 953,969 **** if (regs == NULL) { regbytes = sizeof(int) * procfs_get_reg_index(PROCFS_REG_NREGS); regs = e_malloc(regbytes); ! origregs = e_malloc(regbytes); } procfs_get_regtab(ip, regs); ! memcpy(origregs, regs, regbytes); sp = regs[procfs_get_reg_index(PROCFS_REG_SP)]; #else ptrace_get_regtab(ip, &sunregs); ! origsunregs = sunregs; regs = &sunregs; ! origregs = &origsunregs; sp = sunregs.sr_regs.r_sp; #endif #endif --- 955,971 ---- if (regs == NULL) { regbytes = sizeof(int) * procfs_get_reg_index(PROCFS_REG_NREGS); regs = e_malloc(regbytes); ! orig_regs = e_malloc(regbytes); } procfs_get_regtab(ip, regs); ! memcpy(orig_regs, regs, regbytes); sp = regs[procfs_get_reg_index(PROCFS_REG_SP)]; #else ptrace_get_regtab(ip, &sunregs); ! orig_sunregs = sunregs; regs = &sunregs; ! orig_regs = &orig_sunregs; sp = sunregs.sr_regs.r_sp; #endif #endif *************** *** 973,983 **** --- 975,993 ---- sp = saved_sp = xp_getreg(xp, UPSREG_SP); #endif #if defined(ARCH_BSDI386) || defined(ARCH_LINUX386) + #ifdef AO_HAS_PTRACE_REGS + ptrace_get_regtab(ip, &ptrace_regs); + orig_ptrace_regs = ptrace_regs; + regs = &ptrace_regs; + orig_regs = &orig_ptrace_regs; + sp = ptrace_regs.regs.r_eip; + #else for (i = 0; i < N_UREGS; ++i) if (get_uarea_reg(ip, i, &saved_regs[i]) != 0) panic("can't get reg in pcf"); sp = xp_getreg(xp, UPSREG_SP); #endif + #endif retpc = saved_restart_pc = ip->ip_restart_pc; *************** *** 1165,1171 **** *p_mesg = "Can't set registers for target function call"; return -1; } ! #endif /* Jump to the start of the function. */ --- 1175,1181 ---- *p_mesg = "Can't set registers for target function call"; return -1; } ! #endif /* ARCH_SUN4 */ /* Jump to the start of the function. */ *************** *** 1195,1210 **** /* Restore the registers we saved. */ ! #ifdef ARCH_VAX ps_setreg(ip, UPSREG_PC, saved_restart_pc); ps_setreg(ip, UPSREG_SP, saved_sp); ps_setreg(ip, 0, saved_r0); ps_setreg(ip, 1, saved_r1); ! #endif ! #ifdef OS_SUNOS ! ps_set_all_regs(ip, origregs); ! #endif ! #ifdef ARCH_MIPS if (saveregs) { for (i = 1; i < 16; ++i) { if (ps_setreg(ip, i, regtab[i]) != 0) --- 1205,1218 ---- /* Restore the registers we saved. */ ! #if defined(ARCH_VAX) ps_setreg(ip, UPSREG_PC, saved_restart_pc); ps_setreg(ip, UPSREG_SP, saved_sp); ps_setreg(ip, 0, saved_r0); ps_setreg(ip, 1, saved_r1); ! #elif defined(AO_HAS_PTRACE_REGS) ! ps_set_all_regs(ip, orig_regs); ! #elif defined(ARCH_MIPS) if (saveregs) { for (i = 1; i < 16; ++i) { if (ps_setreg(ip, i, regtab[i]) != 0) *************** *** 1215,1238 **** panic("can't restore registers in cf"); } } ! #endif ! #ifdef ARCH_CLIPPER for (i = 0; i < N_REG_ARGS; ++i) { if (ps_setreg(ip, i, saved_regs[i]) != 0) panic("can't restore regs in cf"); } if (ps_setreg(ip, UPSREG_SP, saved_sp) != 0) panic("can't restore sp in cf"); ! #endif ! #ifdef ARCH_BSDI386 for (i = 0; i < N_UREGS; ++i) if (set_uarea_reg(ip, i, saved_regs[i]) != 0) panic("can't restore regs in cf"); ! #endif ! #ifdef ARCH_LINUX386 for (i = 0; i < N_UREGS; ++i) if (i != ORIG_EAX && set_uarea_reg(ip, i, saved_regs[i]) != 0) panic("can't restore regs in cf"); #endif /* Wait for target will have set ip_restart_pc to retpc, because --- 1223,1245 ---- panic("can't restore registers in cf"); } } ! #elif defined(ARCH_CLIPPER) for (i = 0; i < N_REG_ARGS; ++i) { if (ps_setreg(ip, i, saved_regs[i]) != 0) panic("can't restore regs in cf"); } if (ps_setreg(ip, UPSREG_SP, saved_sp) != 0) panic("can't restore sp in cf"); ! #elif defined(ARCH_BSDI386) for (i = 0; i < N_UREGS; ++i) if (set_uarea_reg(ip, i, saved_regs[i]) != 0) panic("can't restore regs in cf"); ! #elif defined(ARCH_LINUX386) for (i = 0; i < N_UREGS; ++i) if (i != ORIG_EAX && set_uarea_reg(ip, i, saved_regs[i]) != 0) panic("can't restore regs in cf"); + #else + ps_set_all_regs(ip, orig_regs); #endif /* Wait for target will have set ip_restart_pc to retpc, because *************** *** 1242,1245 **** --- 1249,1253 ---- return 0; } + #endif /* AO_TARGET */ *** ./ups/mreg.h.ups Mon Sep 29 20:18:07 1997 --- ./ups/mreg.h Tue Oct 6 01:37:07 1998 *************** *** 95,100 **** --- 95,112 ---- } ureg_t; #endif /* UAREA_REGS */ + + #ifdef AO_HAS_PTRACE_REGS + #undef UAREA_REGS + #include + typedef struct ptraceregst { + struct reg regs; + struct fpreg fpregs; + bool need_fpregs; + } ptrace_regs_t; + #endif + + #ifdef OS_SUNOS_4 typedef struct sunregsst { struct regs sr_regs; *************** *** 111,114 **** } sunregs_t; taddr_t get_sun_regval PROTO((sunregs_t *sr, int pid, int reg)); ! #endif --- 123,127 ---- } sunregs_t; taddr_t get_sun_regval PROTO((sunregs_t *sr, int pid, int reg)); ! #endif /* OS_SUN_4 */ ! *** ./ups/obj_bpt.c.ups Thu Oct 1 11:01:36 1998 --- ./ups/obj_bpt.c Thu Oct 1 14:17:05 1998 *************** *** 1901,1908 **** bool junk; read_config_file(get_temp_bpt_filename(), TRUE, TRUE, TRUE, FALSE, &junk); ! /* if (unlink(get_temp_bpt_filename()) != 0)*/ ! /* errf("Can't unlink `%s'", get_temp_bpt_filename());*/ } /* Add the breakpoint header to the display. Called on startup from main(). --- 1901,1908 ---- bool junk; read_config_file(get_temp_bpt_filename(), TRUE, TRUE, TRUE, FALSE, &junk); ! if (unlink(get_temp_bpt_filename()) != 0) ! errf("Can't unlink `%s'", get_temp_bpt_filename()); } /* Add the breakpoint header to the display. Called on startup from main(). *** ./ups/ao_pt_uarea.c.ups Mon Oct 5 19:16:08 1998 --- ./ups/ao_pt_uarea.c Tue Oct 6 16:04:22 1998 *************** *** 0 **** --- 1,644 ---- + /* ao_pt_uarea.c - process manipulation for a.out files using ptrace (part 3) */ + + /* Copyright 1993 Mark Russell, University of Kent at Canterbury. + * + * You can do what you like with this source code as long as + * you don't try to make money out of it and you include an + * unaltered copy of this message (including the copyright). + */ + + char ups_ao_pt_uarea_c_sccsid[] = "@(#)ao_pt2.c 1.2 04 Jun 1995 (UKC)"; + + #include + #include "ao_ifdefs.h" + + #ifdef AO_USE_PTRACE + + #include + #include + #include + #include + #include + #include + #include /* needed for user.h */ + + #ifdef __STDC__ + #include + #endif + + #if defined(OS_ULTRIX) || defined(ARCH_MIPS) + /* The Ultrix system header files and clash + * over the #defines for some symbols, so we #undef them. Hmmm ... + */ + #undef JB_S0 + #undef JB_S1 + #undef JB_S2 + #undef JB_S3 + #undef JB_S4 + #undef JB_S5 + #undef JB_S6 + #undef JB_S7 + #undef JB_S8 + #undef JB_SP + #undef JB_PC + #undef NJBREGS + #endif + + #include + #include + #ifdef OS_ULTRIX + #include /* VAX needs this for user.h */ + #endif + #include + #ifndef OS_LINUX /* RGA linux merge */ + #include + #endif + #include + + #ifdef ARCH_VAX + #include + #endif + #include + #include + #include + + #ifdef ARCH_MIPS + #include "mips_frame.h" + #endif + #include "ups.h" + #include "ui.h" + #include "ci.h" + #include "target.h" + #include "breakpoint.h" + #include "obj_bpt.h" /* BUG: need this for recalculate_bpt_addrs */ + #include "mreg.h" + #include "dx.h" + #include "as.h" + #include "ao.h" + #include "ao_asm.h" + #include "ao_text.h" + #include "ao_shlib.h" + #include "ao_core.h" + #include "ao_stack.h" + #include "ao_target.h" + #include "ao_ptrace.h" + #include "ao_aout.h" + #include "debug.h" + #include "tdr.h" + #include "state.h" + + #if defined(OS_ULTRIX) && defined(ARCH_MIPS) + #define MIPS_ULTRIX + #endif + + #ifdef ARCH_SUN4 + #include + + #ifdef CPU_ARCH + static int sparc_u_offset PROTO((void)); + int gethostid PROTO((void)); + #endif + + #endif + + + /* Return the offset into the u area of member. + * Used when doing PEEKUSER ptrace requests. + */ + #ifdef ARCH_MIPS + #define U_OFFSET(member) ((char *)((int)&((struct user *)NULL)->member / 4)) + #else + #define U_OFFSET(member) ((char *)&((struct user *)NULL)->member) + #endif + + #ifdef OS_SUNOS_4 + #define u_tsize u_procp->p_tsize + #define u_dsize u_procp->p_dsize + #define u_ssize u_procp->p_ssize + #endif /* OS_SUNOS_4 */ + + + #ifdef UAREA_REGS + int get_uarea_reg PROTO((iproc_t *ip, int ri, taddr_t *p_value)); + int set_uarea_reg PROTO((iproc_t *ip, int ri, taddr_t value)); + #endif + + + #if defined(UAREA_REGS) || defined(USERCORE) + int reg_to_uarea_index PROTO((int regno)); + #ifdef ARCH_BSDI386 + typedef int (*get_uarea_word_func_t)PROTO((int arg, int offset)); + void set_uarea_reg_offsets PROTO((ureg_t *ur, + get_uarea_word_func_t get_uarea_word_func, + int arg)); + #else + void set_uarea_reg_offsets PROTO((ureg_t *ur)); + #endif + #endif /* UAREA_REGS or USERCORE */ + + + #ifdef ARCH_CLIPPER + int get_clipper_fp_reg PROTO((iproc_t *ip, int regno, taddr_t *p_val)); + #endif + + #ifdef ARCH_SUN3 + static void convert_68881_reg PROTO((unsigned *rwords, bool is_double, + fpval_t *p_val)); + #endif + + #ifdef ARCH_BSDI386 + static int get_uarea_word_with_ptrace PROTO((int pid, int offset)); + #endif + + + #if defined(UAREA_REGS) || defined(USERCORE) + + #ifdef ARCH_LINUX386 + static + int + do_register_translation(regno) + int regno; + { + static int regmap[] = { + EAX, ECX, EDX, EBX, UESP, EBP, ESI, EDI, + EIP, EFL, CS, SS, DS, ES, FS, GS, ORIG_EAX + }; + return regmap[regno]; + } + #endif + + + /* + * Convert machine independent register number regno to u area register number. + */ + int + reg_to_uarea_index(regno) + int regno; + { + switch(regno) { + case UPSREG_PC: + return UR_PC; + case UPSREG_SP: + return UR_SP; + case UPSREG_AP: + #ifdef ARCH_VAX + return UR_AP; + case UPSREG_CONDITION_CODES: + return UR_PSL; + #endif + case UPSREG_FP: + return UR_FP; + default: + if (regno < 0 || regno >= N_UAREA_GREGS) + panic("bad regno in xp_getreg"); + #ifdef ARCH_LINUX386 + return do_register_translation(regno); + #else + return regno; + #endif + } + /* NOTREACHED */ + } + + #ifdef ARCH_BSDI386 + void + set_uarea_reg_offsets(ur, get_uarea_word, arg) + ureg_t *ur; + get_uarea_word_func_t get_uarea_word; + int arg; + { + static int trapregs[N_UREGS] = { + tEAX, tECX, tEDX, tEBX, tESP, tEBP, tESI, tEDI, tEIP + }; + #ifdef bsdi + static int syscallregs[N_UREGS] = { + sEAX, sECX, sEDX, sEBX, sESP, sEBP, sESI, sEDI, sEIP + }; + #endif + taddr_t addr; + int flags, offset, i, *regmap; + + flags = (*get_uarea_word)(arg, (int)U_OFFSET(u_pcb.pcb_flags)); + #ifdef bsdi + regmap = ((flags & FM_TRAP) != 0) ? trapregs : syscallregs; + addr = (*get_uarea_word)(arg, (int)U_OFFSET(u_kproc.kp_proc.p_regs)); + #else + regmap = trapregs; + addr = (*get_uarea_word)(arg, (int)U_OFFSET(u_kproc.kp_proc.p_md.md_regs)); + #endif + + offset = addr - USRSTACK; + + for (i = 0; i < N_UREGS; ++i) + ur[i].ur_uaddr = offset + 4 * regmap[i]; + } + #endif /* ARCH_BSDI386 */ + #endif /* UAREA_REGS or USERCORE */ + + + #ifdef UAREA_REGS + + #ifndef ARCH_BSDI386 + /* Set the offsets into the u area for the registers. + * Called once on startup. + * Not static because we also need this information set up for core + * files - thus we are called from core.c + */ + void + set_uarea_reg_offsets(ur) + ureg_t *ur; + { + #ifdef ARCH_VAX + #define RUADDR(rno) (ctob(UPAGES) + (rno * 4)) + static taddr_t rmap[] = { + RUADDR(R0), RUADDR(R1), RUADDR(R2), RUADDR(R3), + RUADDR(R4), RUADDR(R5), RUADDR(R6), RUADDR(R7), + RUADDR(R8), RUADDR(R9), RUADDR(R10), RUADDR(R11), + RUADDR(AP), RUADDR(FP), RUADDR(SP), RUADDR(PC), + RUADDR(PS), + }; + #undef RUADDR + taddr_t *rptr; + + rptr = rmap; + while (rptr < rmap + N_UREGS) + ur++->ur_uaddr = *rptr++; + #endif /* ARCH_VAX */ + #ifdef ARCH_MIPS + int i; + + for (i = 0; i < NGP_REGS + NFP_REGS; ++i) + ur[i].ur_uaddr = i; + + if (i != UR_FP) + panic("regno botch in suro"); + + /* This ureg is the frame pointer `register'. We evaluate this + * on the demand, so there is no u area address. For safety, + * make sure that any attempt to use it causes an error. + */ + ur[UR_FP].ur_uaddr = 20000; + + ur[UR_PC].ur_uaddr = PC; + #endif /* ARCH_MIPS */ + #ifdef ARCH_CLIPPER + int i; + + for (i = 0; i < 16; ++i) + ur[i].ur_uaddr = (int)U_OFFSET(u_pcb.pcb_regs[i]); + ur[UR_PC].ur_uaddr = (int)U_OFFSET(u_pcb.pcb_cxt.cxt_pc); + #endif + #ifdef ARCH_LINUX386 + + /* RGA seems like we should use a regmap translation here + * so that ur[i].ur_uaddr = 4*regmap[i];. However this causes + * ptrace_wait_for_target() to return SR_SSTEP instead of SR_BPT + * on startup, so working around this by doing the register + * translation in do_register_translation() defined above. + * This is called from reg_to_uarea_index. + */ + + int i; + + for (i = 0; i <= 16; i++) + ur[i].ur_uaddr = 4*i; + #endif + } + #endif /* !ARCH_BSDI386 */ + + + /* Set *p_val to the current value of u area register ri. + * ri is a general purpose register number, or one of UR_PC, UR_AP, UR_FP + * and UR_SP. See mreg.h + */ + int + get_uarea_reg(ip, ri, p_val) + iproc_t *ip; + int ri; + taddr_t *p_val; + { + ureg_t *ur; + + ur = ip->ip_ptrace_info->uregs + ri; + if (!ur->ur_is_current) { + errno = 0; + #ifdef ARCH_MIPS + if (ri == UR_FP) { + taddr_t sp, pc; + + if (get_uarea_reg(ip, UR_SP, &sp) != 0) + return -1; + if (get_uarea_reg(ip, UR_PC, &pc) != 0) + return -1; + ur->ur_value = sp + get_frame_size(pc); + } + else { + ur->ur_value = std_ptrace(PTRACE_PEEKUSER, ip->ip_pid, + (char *)ur->ur_uaddr, 0); + } + #else + ur->ur_value = std_ptrace(PTRACE_PEEKUSER, ip->ip_pid, + (char *)ur->ur_uaddr, 0); + #endif + if (errno != 0) + return -1; + ur->ur_is_current = TRUE; + } + *p_val = ur->ur_value; + return 0; + } + + int + set_uarea_reg(ip, ri, value) + iproc_t *ip; + int ri; + taddr_t value; + { + ureg_t *ur; + + ur = ip->ip_ptrace_info->uregs + ri; + errno = 0; + e_ptrace(PTRACE_POKEUSER, ip->ip_pid, (char *)ur->ur_uaddr, (int)value); + ur->ur_is_current = FALSE; + return (errno == 0) ? 0 : -1; + } + + + #ifdef ARCH_CLIPPER + int + get_clipper_fp_reg(xp, regno, p_val) + target_t *xp; + int regno; + taddr_t *p_val; + { + ureg_t *ur; + + if (ip->ip_ptrace_info->fpreg_sp == 0) { + static unsigned short text[] = { + 0xb420, /* saved0 */ + 0x0000, /* second word of saved0 */ + 0x0900, /* BPT */ + 0x0000, /* nop */ + }; + taddr_t pc, saved_restart_pc, saved_sp, sp, new_sp, word1, word2; + int errno1, errno2, i; + + saved_sp = sp = xp_getreg(xp, UPSREG_SP); + + /* Back off to a word aligned place at least four halfwords + * before the current pc. + */ + saved_restart_pc = ip->ip_restart_pc; + pc = (ip->ip_restart_pc - 8) & ~3; + + word1 = std_ptrace(PTRACE_PEEKTEXT, ip->ip_pid, (char *)pc, 0); + errno1 = errno; + word2 = std_ptrace(PTRACE_PEEKTEXT, ip->ip_pid, (char *)(pc + 4), 0); + errno2 = errno; + + std_ptrace(PTRACE_POKETEXT, ip->ip_pid, (char *)pc, *(int *)text); + + /* At this point we can still back out. Beyond this point + * we have trodden on the text, so any errors are fatal. + */ + if (errno != 0 || errno1 != 0 || errno2 != 0) { + errf("Can't insert fp register grabbing code (%m)"); + return -1; + } + + e_ptrace(PTRACE_POKETEXT, ip->ip_pid, + (char *)(pc + 4), *(int *)&text[2]); + + /* Ensure that the stack pointer is eight byte aligned + */ + if (sp & 7) { + sp &= ~7; + if (ao_setreg(xp, UPSREG_SP, sp) != 0) + panic("can't set sp in gifr"); + } + + e_ptrace(PTRACE_CONT, ip->ip_pid, (char *)pc, 0); + ptrace_wait_for_target(ip); + + new_sp = xp_getreg(xp, UPSREG_SP); + + /* Make sure we've hit the breakpoint, and that the sp + * has been moved by the saved0. + */ + if (ip->ip_stopres != SR_BPT && ip->ip_stopres != SR_SSTEP) + panic("ws botch in gcfr"); + + e_ptrace(PTRACE_POKETEXT, ip->ip_pid, (char *)pc, word1); + e_ptrace(PTRACE_POKETEXT, ip->ip_pid, (char *)(pc + 4), word2); + + /* Sometimes the pc doesn't advance. I don't know why. + */ + if (ip->ip_restart_pc == pc) { + errf("Error running fp regno grabbing code"); + ip->ip_restart_pc = saved_restart_pc; + return -1; + } + + if (ip->ip_restart_pc != pc + 4) + panic("pc botch in gcfr"); + if (new_sp != sp - 4 * 16) + panic("sp botch in gcfr"); + + ip->ip_restart_pc = saved_restart_pc; + + ip->ip_ptrace_info->fpreg_sp = sp - 8 * 8; /* 8 eight byte doubles */ + ao_setreg(xp, UPSREG_SP, saved_sp); + + for (i = 0; i < 16; ++i) + ip->ip_ptrace_info->fp_uregs[i].ur_is_current = FALSE; + } + + ur = &ip->ip_ptrace_info->fp_uregs[regno]; + if (!ur->ur_is_current) { + if (ao_read_data(xp, ip->ip_ptrace_info->fpreg_sp + regno * 4, + (char *)&ur->ur_value, 4) != 0) { + errf("Can't read fp register value from the stack (%m)"); + return -1; + } + ur->ur_is_current = TRUE; + } + + *p_val = ur->ur_value; + return 0; + } + #endif /* ARCH_CLIPPER */ + + + #ifdef ARCH_BSDI386 + static int + get_uarea_word_with_ptrace(pid, offset) + int pid, offset; + { + return e_ptrace(PTRACE_PEEKUSER, pid, (char *)offset, 0); + } + #endif /* ARCH_BSDI386 */ + + + /* Update the stored machine register values. This is called after the + * target has been run and has thus changed the register values. + * For the VAX, we just mark our cached values as invalid. + * + * The pc is a special case, as when we hit a breakpoint some machines + * report the pc as pointing after the trap opcode. Thus if we are at + * a breakpoint we adjust the pc value. The VAX kernel seems to do + * this for us. + * + * Return TRUE if the target stopped because it hit a breakpoint. + */ + int + ptrace_update_ua_regs(xp) + target_t *xp; + { + taddr_t pc; + breakpoint_t *bp; + iproc_t *ip; + ureg_t *ur; + + ip = GET_IPROC(xp); + + for (ur = ip->ip_ptrace_info->uregs + N_UREGS; ur >= ip->ip_ptrace_info->uregs; --ur) + ur->ur_is_current = FALSE; + + #ifdef ARCH_BSDI386 + set_uarea_reg_offsets(ip->ip_ptrace_info->uregs, + get_uarea_word_with_ptrace, ip->ip_pid); + #endif + + #ifdef ARCH_CLIPPER + ip->ip_ptrace_info->fpreg_sp = 0; + #endif + + if (get_uarea_reg(ip, UR_PC, &pc) != 0) + panic("can't get pc in ur"); + bp = get_breakpoint_at_addr(xp, pc - BPT_PC_OFFSET); + if (bp != NULL) { + pc -= BPT_PC_OFFSET; + ip->ip_ptrace_info->uregs[UR_PC].ur_value = pc; + } + + ip->ip_restart_pc = pc; + return bp != NULL; + } + #endif /* UAREA_REGS */ + + + void + ptrace_init_pid(ip, pid, attached) + iproc_t *ip; + int pid; + bool attached; + { + if (ip->ip_ptrace_info == NULL) { + ip->ip_ptrace_info = + (Ptrace_info *)e_malloc(sizeof(Ptrace_info)); + } + + ip->ip_core = NULL; + ip->ip_pid = pid; + ip->ip_attached = attached; + + #if defined(UAREA_REGS) && !defined(ARCH_BSDI386) + set_uarea_reg_offsets(ip->ip_ptrace_info->uregs); + #endif + + #ifdef ARCH_CLIPPER + ip->ip_ptrace_info->fpreg_sp = 0; + #endif + + #ifdef ARCH_SUN3 + ip->ip_ptrace_info->sunregs.sr_fptype = FPT_68881; /* BUG: just for testing */ + #endif + + #ifdef OS_SUNOS + /* Purify doesn't seem to know that PTRACE_GETREGS sets + * all of a regs structure. + */ + memset((char *)&ip->ip_ptrace_info->sunregs, '\0', sizeof(ip->ip_ptrace_info->sunregs)); + #endif + } + + + #if defined(ARCH_SUN4) && defined(CPU_ARCH) + /* The Sun 4m CPU has an extra 1024 byte field at the start of the + * u area. This means we have to add or subtract this amount if we + * are running on a different CPU architecture than the one we were + * compiled on. + */ + static int + sparc_u_offset() + { + static int offset; + static bool need_offset = TRUE; + + if (need_offset) { + int cputype; + + cputype = (gethostid() >> 24) & CPU_ARCH; + + #ifdef SUN4M_ARCH + offset = (cputype == SUN4M_ARCH) ? 0 : -1024; + #else + offset = (cputype == 0x70) ? 1024 : 0; + #endif + + if ((Debug_flags & DBFLAG_MISC) != 0) + printf("sparc_u_offset = %d\n", offset); + + need_offset = FALSE; + } + + return offset; + } + #endif + + + /* Return the current state of signal handling for signal sig in process + * xp. Returns SGH_CAUGHT, SGH_IGNORED or SGH_DEFAULT. + * + * You might think we could return the address of the signal handler for + * caught signals, but on the Suns at least the returned address is that + * of a library routine which handles all caught signals. + */ + sigstate_t + ptrace_get_sigstate(ip, signo) + iproc_t *ip; + int signo; + { + caddr_t uaddr; + taddr_t handler; + sigstate_t res; + + if (signo < 1 || signo >= NSIG) + panic("signo botch in gss"); + + #if defined(ARCH_MIPS) + uaddr = (char *)(SIG_BASE + signo); + #elif defined(ARCH_BSDI386) + uaddr = U_OFFSET(u_sigacts.ps_sigact[signo]); + #elif defined(ARCH_SUN4) && defined(CPU_ARCH) + uaddr = U_OFFSET(u_signal[signo]) + sparc_u_offset(); + #elif defined(ARCH_LINUX386) + uaddr = 0; /* XXX */ + #else + uaddr = U_OFFSET(u_signal[signo]); + #endif + + errno = 0; + handler = e_ptrace(PTRACE_PEEKUSER, ip->ip_pid, (char *)uaddr, 0); + + if (handler == (taddr_t)SIG_IGN) + res = SGH_IGNORED; + else if (handler == (taddr_t)SIG_DFL) + res = SGH_DEFAULT; + else + res = SGH_CAUGHT; + + return res; + } + + #endif /* AO_USE_PTRACE */ *** ./ups/ao_ifdefs.h.ups Thu Oct 1 10:57:10 1998 --- ./ups/ao_ifdefs.h Tue Oct 6 15:38:41 1998 *************** *** 9,15 **** /* @(#)ao_ifdefs.h 1.1 24/5/95 (UKC) */ ! /* Define AO_TARGET for the hosts that we have native a.out back ends for. * Other machines have the gdb based back end only. */ --- 9,16 ---- /* @(#)ao_ifdefs.h 1.1 24/5/95 (UKC) */ ! /* ! * Define AO_TARGET for the hosts that we have native a.out back ends for. * Other machines have the gdb based back end only. */ *************** *** 33,40 **** #define AO_TARGET #endif ! /* If we do have native support, should we use ptrace() or /proc? */ #ifdef AO_TARGET #ifdef OS_SUNOS_5 #define AO_ELF --- 34,45 ---- #define AO_TARGET #endif ! ! /* ! * If we do have native support, should we use 'ptrace()' or /proc ? ! * Is the executable format ELF or "classic" 'a.out' ? */ + #ifdef AO_TARGET #ifdef OS_SUNOS_5 #define AO_ELF *************** *** 47,63 **** #endif #endif ! #ifdef AO_USE_PTRACE ! #if defined(OS_SUNOS) ! #define AO_PTRACE_SUN ! #elif defined(OS_LINUX) ! #define AO_PTRACE_LINUX ! #elif defined(OS_ULTRIX) ! #define AO_PTRACE_OTHER #elif defined(OS_BSD44) ! #define AO_PTRACE_BSD ! #else ! #define AO_PTRACE_OTHER #endif #endif --- 52,91 ---- #endif #endif ! ! /* ! * Does the core file on this system have a copy of the u-area ? ! * Also implies register values in core files come out of the u-area. ! * As usual SunOS has its own code. ! */ ! ! #ifdef AO_TARGET ! #if !defined(OS_SUNOS) ! #define USERCORE ! #endif ! #endif ! ! ! /* ! * What are the capabilities/limitations of 'ptrace()' on the system ? ! * ! * Note - SunOS has its own routines for get/set registers via 'ptrace()'. ! */ ! ! #ifdef OS_SUNOS ! #define AO_HAS_PTRACE_RANGE 1 /* Can read/write n bytes at a time. */ ! #define AO_HAS_PTRACE_DUMPCORE 1 /* Can dump core with 'ptrace()'. */ ! #define AO_HAS_PTRACE_REGS 1 /* 'ptrace()' can get/set registers. */ ! #endif ! ! #if defined(OS_SUNOS) || defined(OS_LINUX) ! #define AO_HAS_PTRACE_ATTACH 1 #elif defined(OS_BSD44) ! #define AO_USE_PROCFS_ATTACH 1 /* Attach via 'ptrace()' is broken. */ #endif + + #if defined (OS_BSD44) + #define AO_HAS_PTRACE_REGS 1 /* 'ptrace()' can get/set registers. */ #endif + *** ./ups/ao_pt_regs.c.ups Mon Oct 5 23:20:32 1998 --- ./ups/ao_pt_regs.c Tue Oct 6 16:58:38 1998 *************** *** 0 **** --- 1,525 ---- + /* ao_pt_regs.c - use ptrace to get/set registers directly, not via u-area */ + + /* Copyright 1993 Mark Russell, University of Kent at Canterbury. + * + * You can do what you like with this source code as long as + * you don't try to make money out of it and you include an + * unaltered copy of this message (including the copyright). + */ + + char ups_ao_pt_regs_c_sccsid[] = "@(#)ao_pt2.c 1.2 04 Jun 1995 (UKC)"; + + #include + #include "ao_ifdefs.h" + + #if defined(AO_USE_PTRACE) + + #include + #include + #include + #include + #include + #include + + #ifdef __STDC__ + #include + #endif + + #include + #include + + #include + #include + #include + + #include "ups.h" + #include "ui.h" + #include "ci.h" + #include "target.h" + #include "breakpoint.h" + #include "mreg.h" + #include "dx.h" + #include "as.h" + #include "ao.h" + #include "ao_asm.h" + #include "ao_text.h" + #include "ao_shlib.h" + #include "ao_core.h" + #include "ao_stack.h" + #include "ao_target.h" + #include "ao_ptrace.h" + #include "ao_aout.h" + #include "debug.h" + #include "tdr.h" + #include "state.h" + + + /* + * Macros for getting/setting registers in a Sun regs structure. + */ + #ifdef ARCH_SUN3 + #define IS_FLOAT_REG(regno) ((regno) >= 16) + #define PC_REG(sr) ((sr)->sr_regs.r_pc) + #define SP_REG(sr) ((sr)->sr_regs.r_sp) + #define FRAME_REG(sr) ((sr)->sr_regs.r_areg[6]) + #define INTEGER_REG(sr, regno) ((sr)->sr_regs.r_dreg[regno]) + #endif + + #ifdef ARCH_SUN386 + #define FRAME_REG(sr) ((sr)->sr_regs.r_reg[EBP]) + #define INTEGER_REG(sr, regno) ((sr)->sr_regs.r_reg[regno]) + #endif + + #ifdef ARCH_SUN4 + #define IS_FLOAT_REG(regno) ((regno) >= 32 && (regno) < 64) + #define FLOAT_REG_OFFSET 32 + #define PC_REG(sr) ((sr)->sr_regs.r_pc) + #define SP_REG(sr) ((sr)->sr_regs.r_sp) + #define FRAME_REG(sr) ((sr)->sr_rwindow.rw_fp) + #define INTEGER_REG(sr, regno) ((&(sr)->sr_regs.r_y)[regno]) + #endif + + #ifdef ARCH_BSDI386 + #define PC_REG(pr) ((pr)->regs.r_eip) + #define SP_REG(pr) ((pr)->regs.r_esp) + #define FRAME_REG(pr) ((pr)->regs.r_ebp) + #define INTEGER_REG(pr, regno) ((&(pr)->regs.r_es)[regno]) + #endif + + + #ifdef OS_SUNOS + static int set_sun_regval PROTO((sunregs_t *sr, int pid, + int regno, taddr_t val)); + #endif + + #ifdef ARCH_SUN3 + static void convert_68881_reg PROTO((unsigned *rwords, bool is_double, + fpval_t *p_val)); + #endif + + + #if defined(AO_HAS_PTRACE_REGS) + + #ifdef OS_SUNOS + /* Return the current value of Sun register regno. + * regno is a machine independent register number. + */ + taddr_t + get_sun_regval(sr, pid, reg) + sunregs_t *sr; + int pid, reg; + { + switch(reg) { + case UPSREG_PC: + return PC_REG(sr); + case UPSREG_SP: + return SP_REG(sr); + case UPSREG_FP: + case UPSREG_AP: + return FRAME_REG(sr); + #ifdef ARCH_SUN4 + case UPSREG_CONDITION_CODES: + return sr->sr_regs.r_psr; + #endif + default: + #ifdef ARCH_SUN4 + if (reg == UPSREG_FP_CONDITION_CODES || (reg >= 32 && reg < 64)) { + if (sr->sr_need_fpu) { + e_ptrace(PTRACE_GETFPREGS, pid, + (char *)&sr->sr_fpu, 0); + sr->sr_need_fpu = FALSE; + } + if (reg == UPSREG_FP_CONDITION_CODES) + return sr->sr_fpu.fpu_fsr; + return sr->sr_fpu.fpu_regs[reg - FLOAT_REG_OFFSET]; + } + #endif + if (reg < 0 || reg >= N_SUN_GREGS) + panic("bad reg in gsr"); + #ifdef ARCH_SUN4 + if (reg == 0) + return 0; + #endif + return INTEGER_REG(sr, reg); + } + } + + + static int + set_sun_regval(sr, pid, regno, val) + sunregs_t *sr; + int pid, regno; + taddr_t val; + { + #ifdef ARCH_SUN3 + /* BUG */ + if (regno >= 14) { + errf("\bCan't handle 68881/fpa register floats yet"); + return -1; + } + #endif + + switch(regno) { + case UPSREG_PC: + PC_REG(sr) = val; + break; + case UPSREG_FP: + case UPSREG_AP: + FRAME_REG(sr) = val; + break; + case UPSREG_SP: + SP_REG(sr) = val; + break; + default: + #ifdef ARCH_SUN4 + if (IS_FLOAT_REG(regno)) { + if (sr->sr_need_fpu) { + e_ptrace(PTRACE_GETFPREGS, pid, + (char *)&sr->sr_fpu, 0); + sr->sr_need_fpu = FALSE; + } + sr->sr_fpu.fpu_regs[regno - FLOAT_REG_OFFSET] = val; + + if (std_ptrace(PTRACE_SETFPREGS, pid, + (char *)&sr->sr_fpu, 0) != 0) { + sr->sr_need_fpu = TRUE; + return -1; + } + return 0; + } + #endif + if (regno < 0 || regno >= N_SUN_GREGS) + panic("bad regno in ssr"); + INTEGER_REG(sr, regno) = val; + break; + } + + errno = 0; + e_ptrace(PTRACE_SETREGS, pid, (char *)sr, 0); + if (errno != 0) + return -1; + + #ifdef ARCH_SUN4 + if (ptrace(PTRACE_WRITEDATA, pid, (char *)SP_REG(sr), + sizeof(sr->sr_rwindow), (char *)&sr->sr_rwindow) != 0) + return -1; + #endif + + return 0; + } + #endif /* OS_SUNOS */ + + + /* + * Return the current value of ptrace'd register 'regno', which is a + * machine independent register number. + */ + taddr_t + get_ptrace_reg(pr, pid, regno) + ptrace_regs_t *pr; + int pid, regno; + { + switch(regno) { + case UPSREG_PC: + return PC_REG(pr); + case UPSREG_SP: + return SP_REG(pr); + case UPSREG_FP: + case UPSREG_AP: + return FRAME_REG(pr); + default: + if (regno < 0 || regno >= sizeof(pr->regs)/sizeof(PC_REG(pr))) + panic("bad regno in gpr"); + return INTEGER_REG(pr, regno); + } + } + + + static int + set_ptrace_reg(pr, pid, regno, val) + ptrace_regs_t *pr; + int pid, regno; + taddr_t val; + { + switch(regno) { + case UPSREG_PC: + PC_REG(pr) = val; + break; + case UPSREG_FP: + case UPSREG_AP: + FRAME_REG(pr) = val; + break; + case UPSREG_SP: + SP_REG(pr) = val; + break; + default: + if (regno < 0 || regno >= sizeof(pr->regs)/sizeof(PC_REG(pr))) + panic("bad regno in spr"); + INTEGER_REG(pr, regno) = val; + break; + } + + errno = 0; + e_ptrace(PTRACE_SETREGS, pid, (char *)pr, 0); + if (errno != 0) + return -1; + + return 0; + } + + + /* Update the stored machine register values. This is called after the + * target has been run and has thus changed the register values. + * + * The pc is a special case, as when we hit a breakpoint some machines + * report the pc as pointing after the trap opcode. Thus if we are at + * a breakpoint we adjust the pc value. + * + * Return TRUE if the target stopped because it hit a breakpoint. + */ + static int + ptrace_update_pt_regs(xp) + target_t *xp; + { + taddr_t pc; + breakpoint_t *bp; + iproc_t *ip; + #ifdef OS_SUNOS + sunregs_t *sr; + #else + ptrace_regs_t *pr; + #endif + + ip = GET_IPROC(xp); + + #ifdef OS_SUNOS + sr = &ip->ip_ptrace_info->sunregs; + e_ptrace(PTRACE_GETREGS, ip->ip_pid, (char *)&sr->sr_regs, 0); + #ifdef ARCH_SUN4 + if (ptrace(PTRACE_READDATA, ip->ip_pid, (char *)SP_REG(sr), + sizeof(sr->sr_rwindow), (char *)&sr->sr_rwindow) != 0) { + panic("rwindow read botch in pur"); + } + #endif + pc = (taddr_t)PC_REG(sr); + bp = get_breakpoint_at_addr(xp, pc - BPT_PC_OFFSET); + if (bp != NULL) { + pc -= BPT_PC_OFFSET; + PC_REG(sr) = pc; + } + #if defined(ARCH_SUN3) || defined(ARCH_SUN4) + sr->sr_need_fpu = TRUE; + #endif + + #else /* not OS_SUNOS */ + + pr = &ip->ip_ptrace_info->ptrace_regs; + e_ptrace(PTRACE_GETREGS, ip->ip_pid, (char *)&pr->regs, 0); + pc = (taddr_t)PC_REG(pr); + bp = get_breakpoint_at_addr(xp, pc - BPT_PC_OFFSET); + if (bp != NULL) { + pc -= BPT_PC_OFFSET; + PC_REG(pr) = pc; + } + pr->need_fpregs = TRUE; + #endif + ip->ip_restart_pc = pc; + return bp != NULL; + } + + #if defined(OS_SUNOS) + void + ptrace_get_regtab(ip, sr) + iproc_t *ip; + sunregs_t *sr; + { + *sr = ip->ip_ptrace_info->sunregs; + } + + bool + ptrace_set_all_regs(ip, sr) + iproc_t *ip; + sunregs_t *sr; + { + if (std_ptrace(PTRACE_SETREGS, ip->ip_pid, + (char *)&sr->sr_regs, 0) != 0) { + return FALSE; + } + + ip->ip_ptrace_info->sunregs = *sr; + return TRUE; + } + + #else + + void + ptrace_get_regtab(ip, pr) + iproc_t *ip; + ptrace_regs_t *pr; + { + *pr = ip->ip_ptrace_info->ptrace_regs; + } + + bool + ptrace_set_all_regs(ip, pr) + iproc_t *ip; + ptrace_regs_t *pr; + { + if (std_ptrace(PTRACE_SETREGS, ip->ip_pid, + (char *)&pr->regs, 0) != 0) { + return FALSE; + } + + ip->ip_ptrace_info->ptrace_regs = *pr; + return TRUE; + } + #endif + + + #endif /* AO_HAS_PTRACE_REGS */ + + + /* + * ptrace_update_regs + */ + int + ptrace_update_regs(xp) + target_t *xp; + { + #if defined(AO_HAS_PTRACE_REGS) + return ptrace_update_pt_regs (xp); + #elif defined(UAREA_REGS) + return ptrace_update_ua_regs (xp); + #else + panic ("don't know how to update register values for this machine"); + return 0; + #endif + } + + + /* + * ptrace_setreg + */ + int + ptrace_setreg(ip, regno, value) + iproc_t *ip; + int regno; + taddr_t value; + { + #if defined(OS_SUNOS) + return set_sun_regval (&ip->ip_ptrace_info->sunregs, + ip->ip_pid, regno, value); + #elif defined(AO_HAS_PTRACE_REGS) + return set_ptrace_reg (&ip->ip_ptrace_info->ptrace_regs, + ip->ip_pid, regno, value); + #elif defined(UAREA_REGS) + return set_uarea_reg(ip, reg_to_uarea_index(regno), value); + #else + panic ("don't know how to set a register value for this machine"); + return 0; + #endif + } + + + /* + * ptrace_readreg + */ + int + ptrace_readreg(ip, regno, p_val) + iproc_t *ip; + int regno; + taddr_t *p_val; + { + /* If pid == 0 then reading a core file. */ + if (ip->ip_pid == 0) { + #ifdef ARCH_CLIPPER + if (regno >= 16 && regno < 32) { + errf("Sorry, can't get fp registers from core files on the Clipper"); + return -1; + } + #endif + return aout_get_core_reg(ip->ip_core, regno, p_val); + } + + #if defined(OS_SUNOS) + *p_val = get_sun_regval (&ip->ip_ptrace_info->sunregs, + ip->ip_pid, regno); + return 0; + #elif defined(AO_HAS_PTRACE_REGS) + *p_val = get_ptrace_reg (&ip->ip_ptrace_info->ptrace_regs, + ip->ip_pid, regno); + return 0; + #elif defined(UAREA_REGS) + #ifdef ARCH_CLIPPER + if (regno >= 16 && regno < 32) + return get_clipper_fp_reg (ip, regno - 16, p_val); + #endif + return get_uarea_reg (ip, reg_to_uarea_index(regno), p_val); + #else + panic ("don't know how to get a register value for this machine"); + return 0; + #endif + } + + + /* + * ptrace_read_fpreg + */ + int + ptrace_read_fpreg(ip, regno, num_bytes, p_val) + iproc_t *ip; + int regno; + int num_bytes; + fpval_t *p_val; + { + #ifdef ARCH_SUN3 + sunregs_t *sr; + + /* The f68881 has eight registers, which are numbered 18..25 in + * the symbol table. + */ + regno -= 18; + if (regno < 0 || regno >= 8) + panic("bad regno in rf"); + + ip = GET_IPROC(xp); + sr = &ip->ip_ptrace_info->sunregs; + if (sr->sr_need_fpu) { + e_ptrace(PTRACE_GETFPREGS, ip->ip_pid, (char *)&sr->sr_fpu, 0); + sr->sr_need_fpu = FALSE; + } + + convert_68881_reg((unsigned *)sr->sr_fpu.f_fpstatus.fps_regs[regno].fp, + (num_bytes == sizeof(double), p_val); + return 0; + #else + switch (num_bytes) { + case sizeof(float): + if (ptrace_readreg(ip, regno, (taddr_t *)&p_val->f) != 0) + return -1; + break; + case sizeof(double): + { + int regno2; + taddr_t *buf = (taddr_t *)&p_val->d; + + regno2 = regno + 1; + #ifdef ARCH_BSDI386 + if (regno == 3) + regno2 = 6; + #endif + if (ptrace_readreg(ip, regno, buf) != 0 || + ptrace_readreg(ip, regno2, buf+1) != 0) + return -1; + } + break; + default: + panic("cannot get this size floating point from register"); + break; + } + return 0; + #endif + } + + + #endif /* AO_USE_PTRACE */ *** ./ups/ao_aout.c.ups Thu Oct 1 10:45:09 1998 --- ./ups/ao_aout.c Tue Oct 6 15:32:38 1998 *************** *** 98,108 **** #endif #endif ! #undef USERCORE ! #if defined(OS_BSD44) || defined(OS_ULTRIX) || defined(ARCH_CLIPPER) || \ ! defined(ARCH_VAX) || defined(OS_RISCOS) || defined(OS_NEWSOS) || \ ! defined(OS_LINUX) ! #define USERCORE struct core { union c_header { struct user cu_u; --- 98,104 ---- #endif #endif ! #ifdef USERCORE struct core { union c_header { struct user cu_u; *************** *** 120,125 **** --- 116,122 ---- sunregs_t *sr)); #endif + #ifdef USERCORE #undef DATADDR *************** *** 344,360 **** return TRUE; } int aout_get_core_reg(co, regno, p_val) Coredesc *co; int regno; taddr_t *p_val; { ! #ifdef OS_SUNOS *p_val = get_sun_regval((sunregs_t *)core_getregs(co), 0, regno); return 0; ! #else /* !OS_SUNOS */ ! #ifdef USERCORE ureg_t *uregs; taddr_t addr; #ifdef ARCH_MIPS --- 341,364 ---- return TRUE; } + /* + * Get a register value from a core file. + * SunOS has the same structure (sunregs_t) in co->regs as when running + * an executable. + * The rest have to go through the u-area so have an array of ureg_t in + * co->regs. NOTE - used by systems that would not go through the u-area + * to get at the registers when running an executable. + */ int aout_get_core_reg(co, regno, p_val) Coredesc *co; int regno; taddr_t *p_val; { ! #if defined(OS_SUNOS) *p_val = get_sun_regval((sunregs_t *)core_getregs(co), 0, regno); return 0; ! #elif defined(USERCORE) ureg_t *uregs; taddr_t addr; #ifdef ARCH_MIPS *************** *** 382,390 **** uregs = (ureg_t *)core_getregs(co); addr = uregs[reg_to_uarea_index(regno)].ur_uaddr; #endif /* !ARCH_MIPS */ - /* if (!core_dread(co, addr, (char *)p_val, 4)) return -1; */ - /* Cannot use 'core_dread()' because "addr" IS the offset into - the core file. */ if (!core_read(co, (off_t)addr, (char *)p_val, 4)) return -1; return 0; --- 386,391 ---- *************** *** 392,398 **** panic("core_getreg NYI"); return 0; /* to satisfy gcc */ #endif /* !USERCORE*/ - #endif /* !OS_SUNOS */ } #ifdef OS_SUNOS --- 393,398 ---- *************** *** 462,470 **** size_t data_size, stack_size; int signo; char *regs; - #ifdef OS_SUNOS_4 struct core core; if (read(fd, (char *)&core, sizeof(core)) != sizeof(core)) { if (want_messages) failmesg("Can't read", "core file", corepath); --- 462,473 ---- size_t data_size, stack_size; int signo; char *regs; struct core core; + #ifdef USERCORE + struct user *u; + #endif + #if defined(OS_SUNOS_4) if (read(fd, (char *)&core, sizeof(core)) != sizeof(core)) { if (want_messages) failmesg("Can't read", "core file", corepath); *************** *** 484,536 **** data_size = core.c_dsize; stack_size = core.c_ssize; signo = core.c_signo; ! #endif /* OS_SUNOS_4 */ ! #ifdef USERCORE ! struct core core; ! struct user *u; ! if (read(fd, (char *)&core, sizeof(core)) != sizeof(core)) { if (want_messages) errf("Can't read", "core file", corepath); return -1; } u = &(core.c_un.cu_u); regs = e_malloc(sizeof(ureg_t) * N_UREGS); - #ifdef OS_BSD44 - cmdname = u->u_kproc.kp_proc.p_comm; set_uarea_reg_offsets((ureg_t *)regs, get_uword, (int)&core); signo = u->u_sig; data_offset = sizeof(struct core); #else cmdname = u->u_comm; - set_uarea_reg_offsets((ureg_t *)regs); signo = 0; data_offset = sizeof(struct user); #endif ! data_size = ctob(u->u_dsize); ! stack_size = ctob(u->u_ssize); #endif /* USERCORE */ ! #ifdef ARCH_CLIPPER dataseg.base = data_addr; ! #else ! #ifdef OS_SUNOS_4 dataseg.base = (taddr_t)N_DATADDR(core.c_aouthdr); ! #else ! #ifdef USERCORE ! #ifdef ARCH_MIPS dataseg.base = USRDATA; ! #else ! #if defined(ARCH_386) && defined(OS_BSD44) dataseg.base = (taddr_t)u->u_kproc.kp_eproc.e_vm.vm_daddr; ! #else dataseg.base = ctob((u)->u_tsize); ! #endif /* !BSDI_386 */ ! #endif /* !MIPS */ ! #endif /* !USERCORE */ ! #endif /* !SunOS */ ! #endif /* !Clipper */ dataseg.lim = dataseg.base + data_size; dataseg.file_offset = data_offset; --- 487,533 ---- data_size = core.c_dsize; stack_size = core.c_ssize; signo = core.c_signo; ! #elif defined(USERCORE) if (read(fd, (char *)&core, sizeof(core)) != sizeof(core)) { if (want_messages) errf("Can't read", "core file", corepath); return -1; } u = &(core.c_un.cu_u); + data_size = ctob(u->u_dsize); + stack_size = ctob(u->u_ssize); + #if defined(OS_BSD44) regs = e_malloc(sizeof(ureg_t) * N_UREGS); set_uarea_reg_offsets((ureg_t *)regs, get_uword, (int)&core); + #else + regs = e_malloc(sizeof(ureg_t) * N_UREGS); + set_uarea_reg_offsets((ureg_t *)regs); + #endif + + #if defined(OS_BSD44) + cmdname = u->u_kproc.kp_proc.p_comm; signo = u->u_sig; data_offset = sizeof(struct core); #else cmdname = u->u_comm; signo = 0; data_offset = sizeof(struct user); #endif ! #endif /* USERCORE */ ! #if defined(ARCH_CLIPPER) dataseg.base = data_addr; ! #elif defined(OS_SUNOS_4) dataseg.base = (taddr_t)N_DATADDR(core.c_aouthdr); ! #elif defined(ARCH_MIPS) dataseg.base = USRDATA; ! #elif defined(ARCH_386) && defined(OS_BSD44) dataseg.base = (taddr_t)u->u_kproc.kp_eproc.e_vm.vm_daddr; ! #elif defined(USERCORE) dataseg.base = ctob((u)->u_tsize); ! #endif dataseg.lim = dataseg.base + data_size; dataseg.file_offset = data_offset; *************** *** 574,579 **** --- 571,577 ---- return *(int *)&cp->c_un.cu_dummy[offset]; } #endif + /* Attempt to get the argv array of the target from the stack so * we can put the arguments in the command line. If we succeed,