All of lore.kernel.org
 help / color / mirror / Atom feed
From: Masami Hiramatsu <mhiramat@redhat.com>
To: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>,
	Ananth N Mavinakayanahalli <ananth@in.ibm.com>,
	Steven Rostedt <rostedt@goodmis.org>,
	Andrew Morton <akpm@linux-foundation.org>,
	Andi Kleen <andi@firstfloor.org>,
	Arnaldo Carvalho de Melo <acme@redhat.com>,
	Jim Keniston <jkenisto@us.ibm.com>,
	systemtap-ml <systemtap@sources.redhat.com>,
	LKML <linux-kernel@vger.kernel.org>,
	kvm@vger.kernel.org
Subject: Re: [PATCH -tip 2/6 V4] x86: add arch-dep register and stack	access API to ptrace
Date: Thu, 02 Apr 2009 20:45:21 -0400	[thread overview]
Message-ID: <49D55C21.2060706@redhat.com> (raw)
In-Reply-To: <20090402234835.GA6112@nowhere>

Frederic Weisbecker wrote:
> On Thu, Apr 02, 2009 at 01:24:47PM -0400, Masami Hiramatsu wrote:
>> Add following APIs for accessing registers and stack entries from pt_regs.
>> - query_register_offset(const char *name)
>>    Query the offset of "name" register.
>>
>> - query_register_name(unsigned offset)
>>    Query the name of register by its offset.
>>
>> - get_register(struct pt_regs *regs, unsigned offset)
>>    Get the value of a register by its offset.
>>
>> - valid_stack_address(struct pt_regs *regs, unsigned long addr)
>>    Check the address is in the stack.
>>
>> - get_stack_nth(struct pt_regs *reg, unsigned nth)
>>    Get Nth entry of the stack. (N >= 0)
>>
>> - get_argument_nth(struct pt_regs *reg, unsigned nth)
>>    Get Nth argument at function call. (N >= 0)
>>
>> Signed-off-by: Masami Hiramatsu <mhiramat@redhat.com>
>> Cc: Steven Rostedt <rostedt@goodmis.org>
>> Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
>> Cc: Ingo Molnar <mingo@elte.hu>
>> Cc: Frederic Weisbecker <fweisbec@gmail.com>
>> ---
>>
>>  arch/x86/include/asm/ptrace.h |   66 +++++++++++++++++++++++++++++++++++++++++
>>  arch/x86/kernel/ptrace.c      |   59 +++++++++++++++++++++++++++++++++++++
>>  2 files changed, 125 insertions(+), 0 deletions(-)
>>
>>
>> diff --git a/arch/x86/include/asm/ptrace.h b/arch/x86/include/asm/ptrace.h
>> index aed0894..44773b8 100644
>> --- a/arch/x86/include/asm/ptrace.h
>> +++ b/arch/x86/include/asm/ptrace.h
>> @@ -7,6 +7,7 @@
>>
>>  #ifdef __KERNEL__
>>  #include <asm/segment.h>
>> +#include <asm/page_types.h>
>>  #endif
>>
>>  #ifndef __ASSEMBLY__
>> @@ -215,6 +216,71 @@ static inline unsigned long user_stack_pointer(struct pt_regs *regs)
>>  	return regs->sp;
>>  }
>>
>> +/* Query offset/name of register from its name/offset */
>> +extern int query_register_offset(const char *name);
>> +extern const char *query_register_name(unsigned offset);
>> +#define MAX_REG_OFFSET (offsetof(struct pt_regs, sp))
>> +
>> +/* Get register value from its offset */
>> +static inline unsigned long get_register(struct pt_regs *regs, unsigned offset)
>> +{
>> +	if (unlikely(offset > MAX_REG_OFFSET))
>> +		return 0;
>> +	return *(unsigned long *)((unsigned long)regs + offset);
>> +}
>> +
>> +/* Check the address in the stack */
>> +static inline int valid_stack_address(struct pt_regs *regs, unsigned long addr)
>> +{
>> +	return ((addr & ~(THREAD_SIZE - 1))  ==
>> +		(kernel_trap_sp(regs) & ~(THREAD_SIZE - 1)));
>> +}
>> +
>> +/* Get Nth entry of the stack */
>> +static inline unsigned long get_stack_nth(struct pt_regs *regs, unsigned n)
>> +{
>> +	unsigned long *addr = (unsigned long *)kernel_trap_sp(regs);
>> +	addr += n;
>> +	if (valid_stack_address(regs, (unsigned long)addr))
>> +		return *addr;
>> +	else
>> +		return 0;
>> +}
>> +
>> +/* Get Nth argument at function call */
>> +static inline unsigned long get_argument_nth(struct pt_regs *regs, unsigned n)
>> +{
>> +#ifdef CONFIG_X86_32
>> +#define NR_REGPARMS 3
>> +	if (n < NR_REGPARMS) {
>> +		switch (n) {
>> +		case 0: return regs->ax;
>> +		case 1: return regs->dx;
>> +		case 2: return regs->cx;
>> +		}
>> +		return 0;
>> +#else /* CONFIG_X86_64 */
>> +#define NR_REGPARMS 6
>> +	if (n < NR_REGPARMS) {
>> +		switch (n) {
>> +		case 0: return regs->di;
>> +		case 1: return regs->si;
>> +		case 2: return regs->dx;
>> +		case 3: return regs->cx;
>> +		case 4: return regs->r8;
>> +		case 5: return regs->r9;
>> +		}
>> +		return 0;
>> +#endif
>> +	} else {
>> +		/*
>> +		 * The typical case: arg n is on the stack.
>> +		 * (Note: stack[0] = return address, so skip it)
>> +		 */
>> +		return get_stack_nth(regs, 1 + n - NR_REGPARMS);
>> +	}
>> +}
>> +
>>  /*
>>   * These are defined as per linux/ptrace.h, which see.
>>   */
>> diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c
>> index 5c6e463..8d65dcb 100644
>> --- a/arch/x86/kernel/ptrace.c
>> +++ b/arch/x86/kernel/ptrace.c
>> @@ -46,6 +46,65 @@ enum x86_regset {
>>  	REGSET_IOPERM32,
>>  };
>>
>> +struct pt_regs_offset {
>> +	const char *name;
>> +	int offset;
>> +};
>> +
>> +#define REG_OFFSET(r) offsetof(struct pt_regs, r)
>> +#define REG_OFFSET_NAME(r) {.name = #r, .offset = REG_OFFSET(r)}
>> +#define REG_OFFSET_END {.name = NULL, .offset = 0}
>> +
>> +static struct pt_regs_offset regoffset_table[] = {
>> +#ifdef CONFIG_X86_64
>> +	REG_OFFSET_NAME(r15),
>> +	REG_OFFSET_NAME(r14),
>> +	REG_OFFSET_NAME(r13),
>> +	REG_OFFSET_NAME(r12),
>> +	REG_OFFSET_NAME(r11),
>> +	REG_OFFSET_NAME(r10),
>> +	REG_OFFSET_NAME(r9),
>> +	REG_OFFSET_NAME(r8),
>> +#endif
>> +	REG_OFFSET_NAME(bx),
>> +	REG_OFFSET_NAME(cx),
>> +	REG_OFFSET_NAME(dx),
>> +	REG_OFFSET_NAME(si),
>> +	REG_OFFSET_NAME(di),
>> +	REG_OFFSET_NAME(bp),
>> +	REG_OFFSET_NAME(ax),
>> +#ifdef CONFIG_X86_32
>> +	REG_OFFSET_NAME(ds),
>> +	REG_OFFSET_NAME(es),
>> +	REG_OFFSET_NAME(fs),
>> +	REG_OFFSET_NAME(gs),
>> +#endif
>> +	REG_OFFSET_NAME(orig_ax),
>> +	REG_OFFSET_NAME(ip),
>> +	REG_OFFSET_NAME(cs),
> 
> 
> 
> You seem to have also forgotten ss here.

Oh, I forgot it because ss usually ignored in the kernel...
Anyway, it should be supported.


>> +	REG_OFFSET_NAME(flags),
>> +	REG_OFFSET_NAME(sp),
>> +	REG_OFFSET_END,
>> +};
>> +
>> +int query_register_offset(const char *name)
>> +{
>> +	struct pt_regs_offset *roff = regoffset_table;
>> +	for (roff = regoffset_table; roff->name != NULL; roff++)
>> +		if (!strcmp(roff->name, name))
>> +			return (unsigned)roff->offset;
> 
> 
> 
> Tiny thing here: could you set the full (unsigned int) cast?

or, I don't need to cast it...

>> +	return -EINVAL;
>> +}
>> +
>> +const char *query_register_name(unsigned offset)
>> +{
>> +	struct pt_regs_offset *roff = regoffset_table;
>> +	for (roff = regoffset_table; roff->name != NULL; roff++)
>> +		if (roff->offset == offset)
>> +			return roff->name;
>> +	return NULL;
>> +}
>> +
>>  /*
>>   * does not yet catch signals sent when the child dies.
>>   * in exit.c or in signal.c.
> 
> 
> All in one it looks good!

Thanks!

-- 
Masami Hiramatsu

Software Engineer
Hitachi Computer Products (America) Inc.
Software Solutions Division

e-mail: mhiramat@redhat.com


WARNING: multiple messages have this Message-ID (diff)
From: Masami Hiramatsu <mhiramat@redhat.com>
To: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@elte.hu>,
	        Ananth N Mavinakayanahalli <ananth@in.ibm.com>,
	        Steven Rostedt <rostedt@goodmis.org>,
	        Andrew Morton <akpm@linux-foundation.org>,
	        Andi Kleen <andi@firstfloor.org>,
	        Arnaldo Carvalho de Melo <acme@redhat.com>,
	        Jim Keniston <jkenisto@us.ibm.com>,
	        systemtap-ml <systemtap@sources.redhat.com>,
	        LKML <linux-kernel@vger.kernel.org>,
	kvm@vger.kernel.org
Subject: Re: [PATCH -tip 2/6 V4] x86: add arch-dep register and stack	access  API to ptrace
Date: Thu, 02 Apr 2009 20:45:21 -0400	[thread overview]
Message-ID: <49D55C21.2060706@redhat.com> (raw)
In-Reply-To: <20090402234835.GA6112@nowhere>

Frederic Weisbecker wrote:
> On Thu, Apr 02, 2009 at 01:24:47PM -0400, Masami Hiramatsu wrote:
>> Add following APIs for accessing registers and stack entries from pt_regs.
>> - query_register_offset(const char *name)
>>    Query the offset of "name" register.
>>
>> - query_register_name(unsigned offset)
>>    Query the name of register by its offset.
>>
>> - get_register(struct pt_regs *regs, unsigned offset)
>>    Get the value of a register by its offset.
>>
>> - valid_stack_address(struct pt_regs *regs, unsigned long addr)
>>    Check the address is in the stack.
>>
>> - get_stack_nth(struct pt_regs *reg, unsigned nth)
>>    Get Nth entry of the stack. (N >= 0)
>>
>> - get_argument_nth(struct pt_regs *reg, unsigned nth)
>>    Get Nth argument at function call. (N >= 0)
>>
>> Signed-off-by: Masami Hiramatsu <mhiramat@redhat.com>
>> Cc: Steven Rostedt <rostedt@goodmis.org>
>> Cc: Ananth N Mavinakayanahalli <ananth@in.ibm.com>
>> Cc: Ingo Molnar <mingo@elte.hu>
>> Cc: Frederic Weisbecker <fweisbec@gmail.com>
>> ---
>>
>>  arch/x86/include/asm/ptrace.h |   66 +++++++++++++++++++++++++++++++++++++++++
>>  arch/x86/kernel/ptrace.c      |   59 +++++++++++++++++++++++++++++++++++++
>>  2 files changed, 125 insertions(+), 0 deletions(-)
>>
>>
>> diff --git a/arch/x86/include/asm/ptrace.h b/arch/x86/include/asm/ptrace.h
>> index aed0894..44773b8 100644
>> --- a/arch/x86/include/asm/ptrace.h
>> +++ b/arch/x86/include/asm/ptrace.h
>> @@ -7,6 +7,7 @@
>>
>>  #ifdef __KERNEL__
>>  #include <asm/segment.h>
>> +#include <asm/page_types.h>
>>  #endif
>>
>>  #ifndef __ASSEMBLY__
>> @@ -215,6 +216,71 @@ static inline unsigned long user_stack_pointer(struct pt_regs *regs)
>>  	return regs->sp;
>>  }
>>
>> +/* Query offset/name of register from its name/offset */
>> +extern int query_register_offset(const char *name);
>> +extern const char *query_register_name(unsigned offset);
>> +#define MAX_REG_OFFSET (offsetof(struct pt_regs, sp))
>> +
>> +/* Get register value from its offset */
>> +static inline unsigned long get_register(struct pt_regs *regs, unsigned offset)
>> +{
>> +	if (unlikely(offset > MAX_REG_OFFSET))
>> +		return 0;
>> +	return *(unsigned long *)((unsigned long)regs + offset);
>> +}
>> +
>> +/* Check the address in the stack */
>> +static inline int valid_stack_address(struct pt_regs *regs, unsigned long addr)
>> +{
>> +	return ((addr & ~(THREAD_SIZE - 1))  ==
>> +		(kernel_trap_sp(regs) & ~(THREAD_SIZE - 1)));
>> +}
>> +
>> +/* Get Nth entry of the stack */
>> +static inline unsigned long get_stack_nth(struct pt_regs *regs, unsigned n)
>> +{
>> +	unsigned long *addr = (unsigned long *)kernel_trap_sp(regs);
>> +	addr += n;
>> +	if (valid_stack_address(regs, (unsigned long)addr))
>> +		return *addr;
>> +	else
>> +		return 0;
>> +}
>> +
>> +/* Get Nth argument at function call */
>> +static inline unsigned long get_argument_nth(struct pt_regs *regs, unsigned n)
>> +{
>> +#ifdef CONFIG_X86_32
>> +#define NR_REGPARMS 3
>> +	if (n < NR_REGPARMS) {
>> +		switch (n) {
>> +		case 0: return regs->ax;
>> +		case 1: return regs->dx;
>> +		case 2: return regs->cx;
>> +		}
>> +		return 0;
>> +#else /* CONFIG_X86_64 */
>> +#define NR_REGPARMS 6
>> +	if (n < NR_REGPARMS) {
>> +		switch (n) {
>> +		case 0: return regs->di;
>> +		case 1: return regs->si;
>> +		case 2: return regs->dx;
>> +		case 3: return regs->cx;
>> +		case 4: return regs->r8;
>> +		case 5: return regs->r9;
>> +		}
>> +		return 0;
>> +#endif
>> +	} else {
>> +		/*
>> +		 * The typical case: arg n is on the stack.
>> +		 * (Note: stack[0] = return address, so skip it)
>> +		 */
>> +		return get_stack_nth(regs, 1 + n - NR_REGPARMS);
>> +	}
>> +}
>> +
>>  /*
>>   * These are defined as per linux/ptrace.h, which see.
>>   */
>> diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c
>> index 5c6e463..8d65dcb 100644
>> --- a/arch/x86/kernel/ptrace.c
>> +++ b/arch/x86/kernel/ptrace.c
>> @@ -46,6 +46,65 @@ enum x86_regset {
>>  	REGSET_IOPERM32,
>>  };
>>
>> +struct pt_regs_offset {
>> +	const char *name;
>> +	int offset;
>> +};
>> +
>> +#define REG_OFFSET(r) offsetof(struct pt_regs, r)
>> +#define REG_OFFSET_NAME(r) {.name = #r, .offset = REG_OFFSET(r)}
>> +#define REG_OFFSET_END {.name = NULL, .offset = 0}
>> +
>> +static struct pt_regs_offset regoffset_table[] = {
>> +#ifdef CONFIG_X86_64
>> +	REG_OFFSET_NAME(r15),
>> +	REG_OFFSET_NAME(r14),
>> +	REG_OFFSET_NAME(r13),
>> +	REG_OFFSET_NAME(r12),
>> +	REG_OFFSET_NAME(r11),
>> +	REG_OFFSET_NAME(r10),
>> +	REG_OFFSET_NAME(r9),
>> +	REG_OFFSET_NAME(r8),
>> +#endif
>> +	REG_OFFSET_NAME(bx),
>> +	REG_OFFSET_NAME(cx),
>> +	REG_OFFSET_NAME(dx),
>> +	REG_OFFSET_NAME(si),
>> +	REG_OFFSET_NAME(di),
>> +	REG_OFFSET_NAME(bp),
>> +	REG_OFFSET_NAME(ax),
>> +#ifdef CONFIG_X86_32
>> +	REG_OFFSET_NAME(ds),
>> +	REG_OFFSET_NAME(es),
>> +	REG_OFFSET_NAME(fs),
>> +	REG_OFFSET_NAME(gs),
>> +#endif
>> +	REG_OFFSET_NAME(orig_ax),
>> +	REG_OFFSET_NAME(ip),
>> +	REG_OFFSET_NAME(cs),
> 
> 
> 
> You seem to have also forgotten ss here.

Oh, I forgot it because ss usually ignored in the kernel...
Anyway, it should be supported.


>> +	REG_OFFSET_NAME(flags),
>> +	REG_OFFSET_NAME(sp),
>> +	REG_OFFSET_END,
>> +};
>> +
>> +int query_register_offset(const char *name)
>> +{
>> +	struct pt_regs_offset *roff = regoffset_table;
>> +	for (roff = regoffset_table; roff->name != NULL; roff++)
>> +		if (!strcmp(roff->name, name))
>> +			return (unsigned)roff->offset;
> 
> 
> 
> Tiny thing here: could you set the full (unsigned int) cast?

or, I don't need to cast it...

>> +	return -EINVAL;
>> +}
>> +
>> +const char *query_register_name(unsigned offset)
>> +{
>> +	struct pt_regs_offset *roff = regoffset_table;
>> +	for (roff = regoffset_table; roff->name != NULL; roff++)
>> +		if (roff->offset == offset)
>> +			return roff->name;
>> +	return NULL;
>> +}
>> +
>>  /*
>>   * does not yet catch signals sent when the child dies.
>>   * in exit.c or in signal.c.
> 
> 
> All in one it looks good!

Thanks!

-- 
Masami Hiramatsu

Software Engineer
Hitachi Computer Products (America) Inc.
Software Solutions Division

e-mail: mhiramat@redhat.com

  reply	other threads:[~2009-04-03  0:46 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2009-04-02 17:24 [PATCH -tip 2/6 V4] x86: add arch-dep register and stack access API to ptrace Masami Hiramatsu
2009-04-02 17:24 ` Masami Hiramatsu
2009-04-02 23:48 ` Frederic Weisbecker
2009-04-02 23:48   ` Frederic Weisbecker
2009-04-03  0:45   ` Masami Hiramatsu [this message]
2009-04-03  0:45     ` Masami Hiramatsu
2009-04-03 16:02   ` [PATCH -tip 2/6 V4.1] " Masami Hiramatsu
2009-04-03 16:02     ` Masami Hiramatsu
2009-04-03 20:20     ` Roland McGrath
2009-04-03 21:34       ` Masami Hiramatsu
2009-04-03 21:34         ` Masami Hiramatsu
2009-04-03 23:29         ` [PATCH -tip 2/6 V4.2] " Masami Hiramatsu
2009-04-03 23:29           ` Masami Hiramatsu
2009-04-06 19:22           ` Roland McGrath
2009-04-06 19:22             ` Roland McGrath
2009-04-06 19:57             ` Masami Hiramatsu
2009-04-06 19:57               ` Masami Hiramatsu

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=49D55C21.2060706@redhat.com \
    --to=mhiramat@redhat.com \
    --cc=acme@redhat.com \
    --cc=akpm@linux-foundation.org \
    --cc=ananth@in.ibm.com \
    --cc=andi@firstfloor.org \
    --cc=fweisbec@gmail.com \
    --cc=jkenisto@us.ibm.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@elte.hu \
    --cc=rostedt@goodmis.org \
    --cc=systemtap@sources.redhat.com \
    /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.