All of lore.kernel.org
 help / color / mirror / Atom feed
From: David Mosberger <davidm@hpl.hp.com>
To: linux-ia64@vger.kernel.org
Subject: Re: [Linux-ia64] One other question
Date: Wed, 18 Apr 2001 07:05:03 +0000	[thread overview]
Message-ID: <marc-linux-ia64-105590693005421@msgid-missing> (raw)
In-Reply-To: <marc-linux-ia64-105590693005419@msgid-missing>

>>>>> 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;
}



      parent reply	other threads:[~2001-04-18  7:05 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
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 message]

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=marc-linux-ia64-105590693005421@msgid-missing \
    --to=davidm@hpl.hp.com \
    --cc=linux-ia64@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.