Skip to content
Advertisement

Regarding gcov output in Linux kernel?

I am running gcov in Linux kernel tree , I am getting correct report but some summary that printed at every file header is coming incorrect like below :-

    -:    0:Graph:page_alloc.gcno
    -:    0:Data:page_alloc.gcda
    -:    0:Runs:0
    -:    0:Programs:0

Here we can see number of runs and programs runs are coming zero which is not correct. what could be reason of this bug ?

Advertisement

Answer

From here:

https://www.kernel.org/doc/Documentation/gcov.txt

And are you able to see all the following files in your system (mounted with debugfs on /sys/kernel/debug):

/sys/kernel/debug/gcov
/sys/kernel/debug/gcov/reset
/sys/kernel/debug/gcov/path/to/compile/dir/file.gcda
/sys/kernel/debug/gcov/path/to/compile/dir/file.gcno

The “/path/to/compile/dir” is depending on your kernel files.

Ans then you apply the gcov command:

# cd /tmp/linux-out
# gcov -o /sys/kernel/debug/gcov/tmp/linux-out/kernel spinlock.c

And the bugzilla.kernel.org does not seemed to have any bugs with gcov, except for one.

https://bugzilla.kernel.org/show_bug.cgi?id=57621

Most likely is your wrong setup or command line problems.

One more thing regarding about reading from /sys/kernel/debug: these are interfaces to read the internal counters inside the kernel. If you have not done anything at the userspace level, that will result in triggering the kernel functions you are interested in profiling, then the output will always remain zero. So just go ahead and do as many activities in userspace as possible (eg, “ls -alR /” to do a recursive read starting from root if you interested in filesystem API, or “ps -ef” or “netstat” if you are interested in procfs, or “wget/ping” commands if you want to profile networking APIs.)

For your case of tracing “page_alloc”, it is suggested to issue this command:

zip -r /tmp/my.zip /home/xxx

This will hopefully trigger a read of the files inside /home/xxx using dynamic memory and followed by zipping it up. Compression algorithm often require you to allocate the memory sufficient to contain all the data before compression can start. (this contrast with encryption algorithm, which may only need a fixed block of memory to do all the encryption, and thus will not show up a lot of “page_alloc” kernel calls).

For my case I just focused on one file: kernel/sched/core.c:

gcov -o /sys/kernel/debug/gcov/home/tthtlc/linux_latest/kernel/sched core.c

And then viewing the file core.c.gcov with vi:

  2396808:   98:void update_rq_clock(struct rq *rq)
        -:   99:{
        -:  100:    s64 delta;
        -:  101:
        -:  102:    lockdep_assert_held(&rq->lock);
        -:  103:
  2396808:  104:    if (rq->clock_skip_update & RQCF_ACT_SKIP)
        -:  105:        return;
        -:  106:
  1676266:  107:    delta = sched_clock_cpu(cpu_of(rq)) - rq->clock;
  1677622:  108:    if (delta < 0)
        -:  109:        return;
  1677556:  110:    rq->clock += delta;
        -:  111:    update_rq_clock_task(rq, delta);
        -:  112:}

So you can see that it has been executed lots of times.

And doing a grep for _alloc:

core.c.gcov:        -: 5325:static struct ctl_table *sd_alloc_ctl_entry(int n)
core.c.gcov:       16: 5376:sd_alloc_ctl_domain_table(struct sched_domain *sd)
core.c.gcov:        -: 5378:    struct ctl_table *table = sd_alloc_ctl_entry(14);
core.c.gcov:        8: 5416:static struct ctl_table *sd_alloc_ctl_cpu_table(int cpu)
core.c.gcov:        8: 5425:    entry = table = sd_alloc_ctl_entry(domain_num + 1);
core.c.gcov:       16: 5434:        entry->child = sd_alloc_ctl_domain_table(sd);
core.c.gcov:        1: 5445:    struct ctl_table *entry = sd_alloc_ctl_entry(cpu_num + 1);
core.c.gcov:        8: 5458:        entry->child = sd_alloc_ctl_cpu_table(i);
core.c.gcov:        -: 6086:enum s_alloc {
core.c.gcov:       28: 6217:        atomic_set(&(*sg)->sgc->ref, 1); /* for claim_allocations */
core.c.gcov:        -: 6346:static int __sdt_alloc(const struct cpumask *cpu_map);
core.c.gcov:        1: 6348:static void __free_domain_allocs(struct s_data *d, enum s_alloc what,
core.c.gcov:        1: 6364:static enum s_alloc __visit_domain_allocation_hell(struct s_data *d,
core.c.gcov:        1: 6369:    if (__sdt_alloc(cpu_map))
core.c.gcov:        -: 6382: * sched_group structure so that the subsequent __free_domain_allocs()
core.c.gcov:       16: 6385:static void claim_allocations(int cpu, struct sched_domain *sd)
core.c.gcov:        1: 6845:static int __sdt_alloc(const struct cpumask *cpu_map)
core.c.gcov:        -: 6971:    enum s_alloc alloc_state;
core.c.gcov:        1: 6976:    alloc_state = __visit_domain_allocation_hell(&d, cpu_map);
core.c.gcov:       16: 7016:            claim_allocations(i, sd);
core.c.gcov:        1: 7031:    __free_domain_allocs(&d, alloc_state, cpu_map);
core.c.gcov:        4: 8198:cpu_cgroup_css_alloc(struct cgroup_subsys_state *parent_css)
core.c.gcov:        -: 8595:    .css_alloc  = cpu_cgroup_css_alloc,

Perhaps it will help if you can elaborate your detailed setup and accessing the system using gcov.

User contributions licensed under: CC BY-SA
9 People found this is helpful
Advertisement