'How to covert the address from KCOV output to filename:lineno using addr2line?

I want to use KCOV (code coverage for fuzzing) in the Linux kernel to record the coverage of certain system calls. I have enabled the corresponding kernel configs started with the code example in the documentation:

#include <stdio.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <unistd.h>
#include <fcntl.h>
#include <linux/types.h>

#define KCOV_INIT_TRACE         _IOR('c', 1, unsigned long)
#define KCOV_ENABLE         _IO('c', 100)
#define KCOV_DISABLE            _IO('c', 101)
#define COVER_SIZE          (64<<10)

#define KCOV_TRACE_PC  0
#define KCOV_TRACE_CMP 1

int main(int argc, char **argv)
{
    int fd;
    unsigned long *cover, n, i;

    /* A single fd descriptor allows coverage collection on a single
        * thread.
        */
    fd = open("/sys/kernel/debug/kcov", O_RDWR);
    if (fd == -1)
        perror("open"), exit(1);
    /* Setup trace mode and trace size. */
    if (ioctl(fd, KCOV_INIT_TRACE, COVER_SIZE))
        perror("ioctl"), exit(1);
    /* Mmap buffer shared between kernel- and user-space. */
    cover = (unsigned long*)mmap(NULL, COVER_SIZE * sizeof(unsigned long),
                        PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
    if ((void*)cover == MAP_FAILED)
        perror("mmap"), exit(1);
    /* Enable coverage collection on the current thread. */
    if (ioctl(fd, KCOV_ENABLE, KCOV_TRACE_PC))
        perror("ioctl"), exit(1);
    /* Reset coverage from the tail of the ioctl() call. */
    __atomic_store_n(&cover[0], 0, __ATOMIC_RELAXED);
    /* That's the target syscal call. */
    read(-1, NULL, 0);
    /* Read number of PCs collected. */
    n = __atomic_load_n(&cover[0], __ATOMIC_RELAXED);
    for (i = 0; i < n; i++)
        printf("0x%lx\n", cover[i + 1]);
    /* Disable coverage collection for the current thread. After this call
        * coverage can be enabled for a different thread.
        */
    if (ioctl(fd, KCOV_DISABLE, 0))
        perror("ioctl"), exit(1);
    /* Free resources. */
    if (munmap(cover, COVER_SIZE * sizeof(unsigned long)))
        perror("munmap"), exit(1);
    if (close(fd))
        perror("close"), exit(1);
    return 0;
} 

The doc said After piping through addr2line output of the program looks as follows:: but I cannot get the same results.

I compiled it with gcc -g, and it would print the addresses if I ran the executable. Then I tried to use addr2line by addr2line -e a.out ${one_of_the_output_addresses}, it always returned ??:0. I searched some materials and some said I need to subtract the base VA to obtain the offset as the addr2line argument, but the program finishes immediately so I cannot get the value from /proc/<PID>/maps. I also tried to add a sleep function to the end to ensure I can get the base VA, but it still outputs ??:0 if I specify VA - base VA for addr2line. Any idea to reproduce the filename:lineno output from KCOV doc?



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source