• Uncategorized

About c : Using-perfeventopen-to-get-sample-address-however-the-addr0

Question Detail

I tried to use perf_event_open() to track all the store instructions to get their access address. I found only when I set attr.precise_ip > 0, I can get the non-zero address. But when I ran the same process on vm instead of host, the error massage was “Operation not supported”, I can fix this problem by setting precise_ip = 0 on vm, but now I only get bunch of addresses equal to zero. I don’t understand why precise_ip is related to the sample addrress which is not pointed out on document, and I also don’t understand why I can’t set precise_ip = 1 on vm while I can do it on host. Is there anybody can help me??

FYI: I use - cpu host option when I start vm using qemu-system-x86_64

#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/fcntl.h>
#include <sys/syscall.h>
#include <linux/perf_event.h>

#define PERF_PAGES  (1 + (1 << 16))
struct perf_sample {
  struct perf_event_header header;
  __u64 ip;
  __u32 pid, tid;    /* if PERF_SAMPLE_TID */
  __u64 addr;        /* if PERF_SAMPLE_ADDR */
  __u64 weight;      /* if PERF_SAMPLE_WEIGHT */
  /* __u64 data_src;    /\* if PERF_SAMPLE_DATA_SRC *\/ */
  __u64 phy_addr;
};

int perf_event_open(struct perf_event_attr *attr,pid_t pid,int cpu,int group_fd,unsigned long flags)
{
    return syscall(__NR_perf_event_open,attr,pid,cpu,group_fd,flags);
}

void workload()
{
    int i,c=0;
    for(i=0;i<100000000;i++)
    {
        c+=i*i;
        c-=i*100;
        c+=i*i*i/100;
    }
}

int startup()
{
    struct perf_event_attr attr;
    memset(&attr,0,sizeof(struct perf_event_attr));

    attr.type = PERF_TYPE_RAW;
    attr.size = sizeof(struct perf_event_attr);
    attr.config = 0x82d0;
    attr.config1 = 0;
    attr.sample_period = 1000;
    attr.sample_type = PERF_SAMPLE_IP | PERF_SAMPLE_TID | PERF_SAMPLE_WEIGHT | PERF_SAMPLE_ADDR | PERF_SAMPLE_PHYS_ADDR ;
    attr.disabled = 0;
    //attr.inherit = 1;
    attr.exclude_kernel = 1;
    attr.exclude_hv = 1;
    attr.exclude_callchain_kernel = 1;
    attr.exclude_callchain_user = 1;
    attr.precise_ip = 1; // when i set attr.precise_ip = 0 , all the addr = 0;

    int fd=perf_event_open(&attr,0,-1,-1,0);
    if(fd<0)
    {
        perror("Cannot open perf fd!");
        return -1;
    }
    return fd;
}

void scan_thread(struct perf_event_mmap_page *p)
{
    char *pbuf = (char *)p + p->data_offset;
    __sync_synchronize();

    printf("%d,\n", p->data_size);
    if(p->data_head == p->data_tail) {
        return;
    }
    struct perf_event_header *ph = (void *)(pbuf + (p->data_tail % p->data_size));
    struct perf_sample* ps;
    switch(ph->type) {
        case PERF_RECORD_SAMPLE:
            ps = (struct perf_sample*)ph;
            // assert(ps != NULL);
            if(ps == NULL)
            {
                printf("null\n");
            }
            if(ps!= NULL &&  ps->addr != 0) {
                printf("ip %lx\n", ps->ip);
                printf("tid %d\n", ps->tid);
                printf("addr: %lx \n", ps->addr);
            }
            //printf("addr, %lx\n", ps->addr);
            //printf("phy addr, %lx\n", ps->phy_addr);
            break;
        default:
            printf("type %d\n", ph->type);
            break;
    }
}

int main()
{
    int fd = startup();
    size_t mmap_size = sysconf(_SC_PAGESIZE) * PERF_PAGES;
    struct perf_event_mmap_page *p = mmap(NULL, mmap_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    // start to perf
    ioctl(fd,PERF_EVENT_IOC_ENABLE,0);
    int a= 0;
    while(1)
    {
        // uint64_t instructions;
        // read(fd,&instructions,sizeof(instructions));
        // printf("instructions=%ld\n",instructions);
        // sleep(1);
        workload();
        scan_thread(p);
        sleep(1);
    }
}

Question Answer

No answer for now.

You may also like...

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.