File: kprobe_coverage.c

package info (click to toggle)
kcov 4-2
  • links: PTS
  • area: main
  • in suites: wheezy
  • size: 268 kB
  • sloc: ansic: 1,996; makefile: 7
file content (112 lines) | stat: -rw-r--r-- 2,482 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
/*
 * Copyright (C) 2010 Simon Kagstrom
 *
 * See COPYING for license details
 */
#define _GNU_SOURCE

#include <kc.h>
#include <stdio.h>
#include <utils.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>

static char debugfs_path[PATH_MAX];
static const char *kprobe_coverage_write_path;
static const char *kprobe_coverage_read_path;

/* From lttng */
static int lookup_debugfs(void)
{
	char mnt_dir[PATH_MAX];
	char mnt_type[PATH_MAX];
	int ret = -ENOENT;

	FILE *fp = fopen("/proc/mounts", "r");
	if (!fp)
		return -EINVAL;

	while (1) {
		if (fscanf(fp, "%*s %s %s %*s %*s %*s", mnt_dir, mnt_type) <= 0)
			panic("Debugfs does not seem to be mounted anywhere\n");

		if (!strcmp(mnt_type, "debugfs")) {
			strcpy(debugfs_path, mnt_dir);
			break;
		}
	}

	kprobe_coverage_write_path = dir_concat(debugfs_path, "kprobe-coverage/control");
	kprobe_coverage_read_path = dir_concat(debugfs_path, "kprobe-coverage/control");
	panic_if (!file_exists(kprobe_coverage_write_path),
			"kprobe-coverage/control not found in debugfs\n"
			"please load the kprobe_coverage module.\n");

	fclose(fp);

	return ret;
}

static int setup_breakpoints(struct kc *kc)
{
	GHashTableIter iter;
	unsigned long key;
	struct kc_addr *val;
	FILE *fp = fopen(kprobe_coverage_write_path, "w");

	panic_if(!fp, "Can't open kprobe coverage file %s for writing\n",
			kprobe_coverage_write_path);

	g_hash_table_iter_init(&iter, kc->addrs);
	while (g_hash_table_iter_next(&iter, (gpointer*)&key, (gpointer*)&val))
		fprintf(fp, "%s%s0x%lx\n",
				kc->module_name, strlen(kc->module_name) == 0 ? "" : ":",
				val->addr);

	fclose(fp);

	return 0;
}


void kprobe_coverage_run(struct kc *kc, const char *write_path,
		const char *read_path)
{
	FILE *fp;

	/* First lookup the path */
	if (write_path && read_path) {
		kprobe_coverage_write_path = xstrdup(write_path);
		kprobe_coverage_read_path = xstrdup(read_path);
	} else
		lookup_debugfs();
	setup_breakpoints(kc);

	fp = fopen(kprobe_coverage_read_path, "r");
	panic_if (!fp, "Can't open %s for reading\n",
			kprobe_coverage_write_path);

	while (!feof(fp)) {
		char *line = NULL;
		struct kc_addr *addr;
		unsigned long l_addr;
		char *endp;
		char *p;
		size_t sz = 0;

		if (getline(&line, &sz, fp) < 0)
			break;
		p = line;
		if (strchr(p, ':'))
			p = strchr(p, ':') + 1;
		l_addr = strtoul(p, &endp, 16);
		free(line);

		if (endp == p)
			continue;
		addr = kc_lookup_addr(kc, l_addr);
		if (addr)
			kc_addr_register_hit(addr);
	}
}