This is the mail archive of the systemtap@sourceware.org mailing list for the systemtap project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATH 1/3] User space probes-take3-RFC


prasanna,
I composed one example to test uprobe, it is in the attachment. And I compile uprobe.c with the command:
gcc --static -g -o uprobe uprobe.c
readelf --sections uprobe
And in kprobe-ex.c, some environment variant need modification.
#define PROBE_FILENAME "/root/test/uprobe"
/* program text segment start address */
#define TEXT_START 0x8048150
/* program text segment offset */
#define TEXT_OFFSET 0x150
/* probed instruction position */
#define PROBE_POS 0x8048304
And there are some problems about current uprobe patch
1) it influences some operations about probed inode. Because there is hook function like readpage(s), when kprobe-ex.ko module is inserted, if some operation like "cp uprobe uprobe1" is executed, file uprobe1 will include inserted "int3" instruction.


2) if probed instruction cause stack vma page fault, there will be some debug information like this:

void test_stack(){
   int i;
   int p[STACK_LIMIT];

/* set user probepoint here, and default there will
* be do_page_fault handler to expand stack
*/
p[0]=0;
i=0;
i++;
}
passed: prehandler executed
BUG: sleeping function called from invalid context at mm/rmap.c:84
in_atomic():0, irqs_disabled():1
<c014c72f> anon_vma_prepare+0x1b/0xbc <c011b885> release_console_sem+0x1a1/0x1a9
<c0148e1f> expand_stack+0x15/0xf1 <c02bb83c> do_page_fault+0x282/0x697
<c02bb5ba> do_page_fault+0x0/0x697 <c0103423> error_code+0x4f/0x54
<c01adbf6> __copy_to_user_ll+0xcf/0xda <c02ba977> uprobe_exceptions_notify+0x166/0x609
<c02bbc66> notifier_call_chain+0x15/0x25 <c02ba646> do_int3+0x3c/0x7b
<c02ba332> int3+0x1e/0x24
passed: post handler executed


3)if probed instruction cause heap vma page fault, the applicatin will hangup.
void test_heap(){
char *pchar;

pchar = (char*) malloc(HEAP_LIMIT);
pchar += (HEAP_LIMIT - 1);
*pchar = 'c'; //set probe point here
}
passed: prehandler executed
passed: page fault executed
passed: prehandler executed
BUG: scheduling while atomic: uprobe/0x00000002/7199
<c02b7dbf> schedule+0x43/0x73f <c011be4f> vprintk+0x2be/0x2f6
<c02b8e3f> __wait_on_bit_lock+0x4b/0x52 <c013b011> __lock_page+0x69/0x70
<c02b8673> io_schedule+0x26/0x30 <c013b094> sync_page+0x0/0x3b
<c013b0cc> sync_page+0x38/0x3b <c02b8e1e> __wait_on_bit_lock+0x2a/0x52
<c013b011> __lock_page+0x69/0x70 <c012bdf1> wake_bit_function+0x0/0x3c
<c02bab7c> uprobe_exceptions_notify+0x36b/0x609 <c02bbc66> notifier_call_chain+0x15/0x25
<c02ba646> do_int3+0x3c/0x7b <c02ba332> int3+0x1e/0x24
<c02b007b> __xfrm_policy_check+0x2a6/0x657
passed: page fault executed
BUG: spinlock wrong owner on CPU#1, syslog-ng/3683
lock: c0362664, .magic: dead4ead, .owner: uprobe/7199, .owner_cpu: 0
<c01ae774> _raw_spin_unlock+0x43/0x6c <c02ba14a> _spin_unlock_irqrestore+0x8/0xc
<c02badad> uprobe_exceptions_notify+0x59c/0x609 <c02bbc66> notifier_call_chain+0x15/0x25
<c02bb5ba> do_page_fault+0x0/0x697 <c02bb775> do_page_fault+0x1bb/0x697
<c015f786> sys_stat64+0x1e/0x23 <c01344ae> do_gettimeofday+0x31/0xda
<c02bb5ba> do_page_fault+0x0/0x697 <c0103423> error_code+0x4f/0x54


4) if probed instruction is int3, system will crash.
void test_trap3()
{
/* set probepoint at here */	
	asm volatile (".byte 0xcc");
}
system will crash.


thanks bibo,mao Prasanna S Panchamukhi wrote:
Hi,

Below is the take 3 of user space probes, which
seems to work for probes on applications and libraries.
Needs more testing and code review. This implementation
uses a spin lock to serialize the probe execution.

Please provide your review comments on these patchs.
Thanks to Yanmin, Anil and Jim for their review commoments.

Thanks
Prasanna

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

#define TRAP_FLAG 0x100
# define ENTER_KERNEL   "int $0x80\n\t"
#define STACK_LIMIT	90000
#define HEAP_LIMIT	0x200000

void test_libfunction(const char *ori)
{
   int result;

/* set probepoint at strcmp function, when program is
 * loaded to run, it will load first few page into page,
 * and then load page on demand
 */	
	result = strcmp(ori,"1234");	
}

void test_stack(){
   int i;
   int p[STACK_LIMIT];

/* set user probepoint here, and default there will
 * be do_page_fault handler to expand stack
 */
	p[0]=0;	
	i=0;
	i++;
}

void test_heap(){
   char *pchar;
	
	pchar = (char*) malloc(HEAP_LIMIT);
	pchar += (HEAP_LIMIT - 1); 
	*pchar = 'c';  //set probe point here

}

int test_dummy(int i)
{
	return i+1;
}

void test_functioncall()
{
    int i;
	i=0;
/* set probepoint at function call point */
	test_dummy(i);	
}

void test_functionreturn()
{
   int i;
	i=0;
/* set probepoint at function return point */
	return;	
}

void test_trap3()
{
/* set probepoint at here */	
	asm volatile (".byte 0xcc");
}

void test_syscall()
{
/* set probepoint at int 0x80 point */
	asm volatile (ENTER_KERNEL : : "a" (20) /* getpid() */);
}

void my_trap(int sig)
{
  printf("trap1 : PASS\n");
}

void test_fork(){
   int pid, status;
   char *pchar;

	pchar = (char*) malloc(HEAP_LIMIT);
	pchar += (HEAP_LIMIT - 1);
	pid= fork();
	if (pid == 0){
	/* here it will generate COW, and set probepoint here */
		*pchar = 'c';
		exit(0);
	}
	else{
		wait(&status);
	}
   
}

int main()
{
  int result,pid;
  int status;
  int i;
  char *pchar;

  	signal(SIGTRAP, my_trap);

/* set probepoint at i=i+1 point */
  	i=i+1;
	pchar = "12345";
	test_libfunction(pchar);

	test_stack();

	test_heap();

	test_functioncall();

	test_functionreturn();

	test_trap3();

	test_syscall();
	
	test_fork();	
	printf("finished\n");
	return 0;
}

/*kprobe_example.c*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/kprobes.h>
#include <linux/kallsyms.h>
#include <linux/sched.h>

#define PROBE_FILENAME	"/root/test/uprobe"
#define TEXT_START 	0x8048150
#define TEXT_OFFSET 	0x150
#define PROBE_POS	0x8048304
/*For each probe you need to allocate a kprobe structure*/
struct uprobe  uprobe_ex;

/*kprobe pre_handler: called just before the probed instruction is executed*/
int handler_pre(struct kprobe *p, struct pt_regs *regs)
{
        printk("passed: prehandler executed \n");

        return 0;
}

/*kprobe post_handler: called after the probed instruction is executed*/
void handler_post(struct kprobe *p, struct pt_regs *regs, unsigned long flags)
{
	printk("passed: post handler executed \n");
}

/* fault_handler: this is called if an exception is generated for any
 * instruction within the pre- or post-handler, or when Kprobes
 * single-steps the probed instruction.
 */
int handler_fault(struct kprobe *p, struct pt_regs *regs, int trapnr)
{
        printk("passed: page fault executed \n");
        return 0;
}

int init_module(void)
{
        int ret;
	char *pname = PROBE_FILENAME;

	uprobe_ex.kp.pre_handler = handler_pre;
        uprobe_ex.kp.post_handler = handler_post;
        uprobe_ex.kp.fault_handler = handler_fault;
	//uprobe_ex.kp.opcode = 0;

        uprobe_ex.kp.addr = (kprobe_opcode_t*)PROBE_POS;
	uprobe_ex.offset = (PROBE_POS - TEXT_START + TEXT_OFFSET);
	uprobe_ex.pathname = pname;

        if ((ret = register_uprobe(&uprobe_ex) < 0)) {
                printk("register_uprobe failed, returned %d\n", ret);
                return -1;
        }
        printk("uprobe registered\n");
        return 0;
}

void cleanup_module(void)
{
        unregister_uprobe(&uprobe_ex);
        printk("uprobe unregistered\n");
}

MODULE_LICENSE("GPL");


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]