public inbox for linux-ia64@vger.kernel.org
 help / color / mirror / Atom feed
* [Linux-ia64] One other question
@ 2001-04-18  5:11 Weihaw CHUANG
  2001-04-18  6:21 ` Stephane Eranian
  2001-04-18  7:05 ` David Mosberger
  0 siblings, 2 replies; 3+ messages in thread
From: Weihaw CHUANG @ 2001-04-18  5:11 UTC (permalink / raw)
  To: linux-ia64

In regards to my previous email.  

What I'm really trying to get at is, is there a method to single step
instructions with user level interrupts?

-Wei



^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [Linux-ia64] One other question
  2001-04-18  5:11 [Linux-ia64] One other question Weihaw CHUANG
@ 2001-04-18  6:21 ` Stephane Eranian
  2001-04-18  7:05 ` David Mosberger
  1 sibling, 0 replies; 3+ messages in thread
From: Stephane Eranian @ 2001-04-18  6:21 UTC (permalink / raw)
  To: linux-ia64

Hi,
On Tue, Apr 17, 2001 at 10:11:19PM -0700, Weihaw CHUANG wrote:
> In regards to my previous email.  
> 
> What I'm really trying to get at is, is there a method to single step
> instructions with user level interrupts?
> 

I believe you can simply do this using the ptrace() system call and
giving it the PTRACE_SINGLESTEP command. Look at arch/ia64/kernel/ptrace.c
for more details.

-- 
-Stephane


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [Linux-ia64] One other question
  2001-04-18  5:11 [Linux-ia64] One other question Weihaw CHUANG
  2001-04-18  6:21 ` Stephane Eranian
@ 2001-04-18  7:05 ` David Mosberger
  1 sibling, 0 replies; 3+ messages in thread
From: David Mosberger @ 2001-04-18  7:05 UTC (permalink / raw)
  To: linux-ia64

>>>>> On Tue, 17 Apr 2001 23:21:03 -0700, Stephane Eranian <eranian@frankl.hpl.hp.com> said:

  Stephane> Hi, On Tue, Apr 17, 2001 at 10:11:19PM -0700, Weihaw
  Stephane> CHUANG wrote:
  >> In regards to my previous email.
  >> 
  >> What I'm really trying to get at is, is there a method to single
  >> step instructions with user level interrupts?

  Stephane> I believe you can simply do this using the ptrace() system
  Stephane> call and giving it the PTRACE_SINGLESTEP command. Look at
  Stephane> arch/ia64/kernel/ptrace.c for more details.

That's correct.  I'm attaching a small test program I wrote a while
ago.  It shows how to single step individual instructions, basic
blocks, and system calls.

	--david

/*
    utrace -- micro tracing tool 
    Copyright (C) 1999-2001  Hewlett-Packard Company
    Contributed by David Mosberger-Tang <davidm@hpl.hp.com>

    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License as
    published by the Free Software Foundation; either version 2 of the
    License, or (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
    02111-1307 USA
*/

#include <errno.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

#include <sys/ptrace.h>
#include <sys/wait.h>

char *prog_name;

#if defined(__ia64__)

#include <asm/fpu.h>
#include <asm/ptrace.h>
#include <asm/ptrace_offsets.h>
#include <asm/rse.h>

int singlestep;

static inline double
fpreg_to_double (struct ia64_fpreg *fp)
{
  double result;

  asm ("ldf.fill %0=%1" : "=f"(result) : "m"(*fp));
  return result;
}

void
print_syscall (int child_pid, int state)
{
  long scnum, result, error, val;
#if 0
  struct ia64_fpreg fp;
#endif
  unsigned long bsp;
  int i;

  if (state = 0)
    return;

  errno = 0;
  scnum = ptrace (PTRACE_PEEKUSER, child_pid, PT_R15, 0);
  result = ptrace (PTRACE_PEEKUSER, child_pid, PT_R8, 0);
  error = ptrace (PTRACE_PEEKUSER, child_pid, PT_R10, 0);
  bsp = ptrace (PTRACE_PEEKUSER, child_pid, PT_AR_BSP, 0);

#if 0
  fp.u.bits[0] = ptrace (PTRACE_PEEKUSER, child_pid, PT_F32 + 0, 0);
  fp.u.bits[1] = ptrace (PTRACE_PEEKUSER, child_pid, PT_F32 + 8, 0);
  printf ("f32=%f\n", fpreg_to_double (&fp));
#endif

  if (errno)
    {
      printf ("%s: ptrace() failed, errno=%d\n", prog_name, errno);
      return;
    }
  printf ("<sc%04ld(", scnum);

  for (i = 0; i < 4; ++i)
    {
      val = ptrace (PTRACE_PEEKDATA, child_pid,
		    (long) ia64_rse_skip_regs ((long *) bsp, i), 0);
      printf ("%lx,", val);
    }

  if (error)
    printf ("...) -> errno=%ld\n", result);
  else
    printf ("...) -> %ld\n", result);
}

void
print_state (int child_pid, int with_slot)
{
  long ip, slot;

  ip = ptrace (PTRACE_PEEKUSER, child_pid, PT_CR_IIP, 0);
  if (with_slot)
    {
      slot = (ptrace (PTRACE_PEEKUSER, child_pid, PT_CR_IPSR, 0) >> 41) & 0x3;
      printf ("%016lx:%ld\n", ip, slot);
    }
  else
    printf ("%016lx\n", ip);
}

#elif defined(__i386__)

void
print_syscall (int child_pid, int state)
{
  int scnum, result;

  scnum = ptrace (PTRACE_PEEKUSER, child_pid, 11*4, 0);	/* read EAX */
  errno = 0;
  result = ptrace (PTRACE_PEEKUSER, child_pid, 6*4, 0);	/* read ORIG_EAX */

  if (result = -ENOSYS)
    return;

  if (errno)
    {
      printf ("%s: ptrace() failed, errno=%d\n", prog_name, errno);
      return;
    }
  printf ("<sc%03d>() -> %d\n", scnum, result);
}

#else
# error Sorry, you're architecture isn't supported.
#endif

int
main (int argc, char **argv, char **envp)
{
  int status, pid, child_pid, state = 1, arg;

  prog_name = argv[0];

  if (argc < 2 || strcmp (argv[1], "-h") = 0)
    {
      printf ("Usage: %s [-abB] command args...\n", prog_name);
      printf ("  -a: trace instruction execution\n");
      printf ("  -b: trace basic block execution\n");
      printf ("  -s: trace system call execution (default)\n");
      exit (-1);
    }

  arg = 1;
  if (strcmp (argv[arg], "-a") = 0)
    {
      singlestep = 1;
      ++arg;
    }
  if (strcmp (argv[arg], "-b") = 0)
    {
      singlestep = 2;
      ++arg;
    }
  if (strcmp (argv[arg], "-s") = 0)
    {
      singlestep = 0;
      ++arg;
    }

  child_pid = fork ();
  if (child_pid = 0)
    {
      ptrace (PTRACE_TRACEME, 0, 0, 0);
      execve (argv[arg], argv + arg, envp);
      printf ("%s: execve failed (errno=%d)\n", prog_name, errno);
      exit (-2);
    }

  while (1)
    {
      pid = wait4 (-1, &status, 0, 0);
      if (pid = -1)
	{
	  if (errno = EINTR)
	    continue;

	  printf ("%s: wait4() failed (errno=%d)\n", prog_name, errno);
	}
      if (WIFSIGNALED (status) || WIFEXITED (status)
	  || (WIFSTOPPED (status) && WSTOPSIG (status) != SIGTRAP))
	{
	  if (WIFEXITED (status))
	    {
	      printf ("%s: exit status %d\n", prog_name, WEXITSTATUS (status));
	      break;
	    }
	  else if (WIFSIGNALED (status))
	    {
	      printf ("%s: terminated by signal %d\n",
		      prog_name, WTERMSIG (status));
	    }
	  else
	    printf ("%s: got signal %d\n", prog_name, WSTOPSIG (status));
	}

      if (singlestep)
	{
	  /* single stepping through program: */
	  if (singlestep = 2)
	    {
	      print_state (child_pid, 0);
	      ptrace (PTRACE_SINGLEBLOCK, child_pid, 0, 0);
	    }
	  else
	    {
	      print_state (child_pid, 1);
	      ptrace (PTRACE_SINGLESTEP, child_pid, 0, 0);
	    }
	}
      else
	{
	  /* syscall tracing */
	  print_syscall (child_pid, state);
	  state = (state + 1) & 1;
	  ptrace (PTRACE_SYSCALL, child_pid, 0, 0);		/* continue */
	}
    }
  return 0;
}



^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2001-04-18  7:05 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2001-04-18  5:11 [Linux-ia64] One other question Weihaw CHUANG
2001-04-18  6:21 ` Stephane Eranian
2001-04-18  7:05 ` David Mosberger

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox