1e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <sys/types.h>
2e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <stdlib.h>
3e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <unistd.h>
4e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <stdio.h>
5e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <inttypes.h>
6e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <ctype.h>
7e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include <string.h>
8e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
9e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "parse-events.h"
10e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "evlist.h"
11e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "evsel.h"
12e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "thread_map.h"
13e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "cpumap.h"
14e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "machine.h"
15e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "event.h"
16e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "thread.h"
17e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
18e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#include "tests.h"
19e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
20e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#define BUFSZ	1024
21e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng#define READLEN	128
22e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
23e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstruct state {
24e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	u64 done[1024];
25e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	size_t done_cnt;
26e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng};
27e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
28e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic unsigned int hex(char c)
29e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
30e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (c >= '0' && c <= '9')
31e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return c - '0';
32e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (c >= 'a' && c <= 'f')
33e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return c - 'a' + 10;
34e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return c - 'A' + 10;
35e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
36e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
37e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void read_objdump_line(const char *line, size_t line_len, void **buf,
38e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			      size_t *len)
39e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
40e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	const char *p;
41e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	size_t i;
42e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
43e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	/* Skip to a colon */
44e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	p = strchr(line, ':');
45e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (!p)
46e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return;
47e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	i = p + 1 - line;
48e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
49e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	/* Read bytes */
50e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	while (*len) {
51e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		char c1, c2;
52e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
53e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		/* Skip spaces */
54e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		for (; i < line_len; i++) {
55e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			if (!isspace(line[i]))
56e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				break;
57e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		}
58e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		/* Get 2 hex digits */
59e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (i >= line_len || !isxdigit(line[i]))
60e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			break;
61e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		c1 = line[i++];
62e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (i >= line_len || !isxdigit(line[i]))
63e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			break;
64e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		c2 = line[i++];
65e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		/* Followed by a space */
66e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (i < line_len && line[i] && !isspace(line[i]))
67e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			break;
68e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		/* Store byte */
69e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		*(unsigned char *)*buf = (hex(c1) << 4) | hex(c2);
70e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		*buf += 1;
71e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		*len -= 1;
72e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
73e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
74e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
75e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int read_objdump_output(FILE *f, void **buf, size_t *len)
76e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
77e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	char *line = NULL;
78e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	size_t line_len;
79e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	ssize_t ret;
80e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int err = 0;
81e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
82e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	while (1) {
83e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		ret = getline(&line, &line_len, f);
84e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (feof(f))
85e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			break;
86e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (ret < 0) {
87e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			pr_debug("getline failed\n");
88e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			err = -1;
89e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			break;
90e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		}
91e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		read_objdump_line(line, ret, buf, len);
92e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
93e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
94e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	free(line);
95e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
96e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return err;
97e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
98e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
99e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int read_via_objdump(const char *filename, u64 addr, void *buf,
100e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			    size_t len)
101e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
102e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	char cmd[PATH_MAX * 2];
103e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	const char *fmt;
104e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	FILE *f;
105e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int ret;
106e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
107e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	fmt = "%s -d --start-address=0x%"PRIx64" --stop-address=0x%"PRIx64" %s";
108e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	ret = snprintf(cmd, sizeof(cmd), fmt, "objdump", addr, addr + len,
109e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		       filename);
110e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (ret <= 0 || (size_t)ret >= sizeof(cmd))
111e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return -1;
112e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
113e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	pr_debug("Objdump command is: %s\n", cmd);
114e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
115e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	/* Ignore objdump errors */
116e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	strcat(cmd, " 2>/dev/null");
117e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
118e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	f = popen(cmd, "r");
119e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (!f) {
120e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		pr_debug("popen failed\n");
121e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return -1;
122e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
123e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
124e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	ret = read_objdump_output(f, &buf, &len);
125e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (len) {
126e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		pr_debug("objdump read too few bytes\n");
127e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (!ret)
128e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			ret = len;
129e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
130e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
131e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	pclose(f);
132e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
133e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return ret;
134e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
135e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
136e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int read_object_code(u64 addr, size_t len, u8 cpumode,
137e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			    struct thread *thread, struct machine *machine,
138e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			    struct state *state)
139e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
140e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct addr_location al;
141e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	unsigned char buf1[BUFSZ];
142e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	unsigned char buf2[BUFSZ];
143e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	size_t ret_len;
144e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	u64 objdump_addr;
145e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int ret;
146e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
147e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	pr_debug("Reading object code for memory address: %#"PRIx64"\n", addr);
148e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
149e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION, addr,
150e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			      &al);
151e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (!al.map || !al.map->dso) {
152e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		pr_debug("thread__find_addr_map failed\n");
153e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return -1;
154e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
155e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
156e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	pr_debug("File is: %s\n", al.map->dso->long_name);
157e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
158e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (al.map->dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS &&
159e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	    !dso__is_kcore(al.map->dso)) {
160e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		pr_debug("Unexpected kernel address - skipping\n");
161e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return 0;
162e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
163e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
164e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	pr_debug("On file address is: %#"PRIx64"\n", al.addr);
165e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
166e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (len > BUFSZ)
167e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		len = BUFSZ;
168e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
169e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	/* Do not go off the map */
170e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (addr + len > al.map->end)
171e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		len = al.map->end - addr;
172e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
173e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	/* Read the object code using perf */
174e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	ret_len = dso__data_read_offset(al.map->dso, machine, al.addr, buf1,
175e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng					len);
176e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (ret_len != len) {
177e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		pr_debug("dso__data_read_offset failed\n");
178e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return -1;
179e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
180e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
181e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	/*
182e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	 * Converting addresses for use by objdump requires more information.
183e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	 * map__load() does that.  See map__rip_2objdump() for details.
184e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	 */
185e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (map__load(al.map, NULL))
186e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return -1;
187e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
188e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	/* objdump struggles with kcore - try each map only once */
189e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (dso__is_kcore(al.map->dso)) {
190e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		size_t d;
191e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
192e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		for (d = 0; d < state->done_cnt; d++) {
193e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			if (state->done[d] == al.map->start) {
194e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				pr_debug("kcore map tested already");
195e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				pr_debug(" - skipping\n");
196e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				return 0;
197e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			}
198e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		}
199e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (state->done_cnt >= ARRAY_SIZE(state->done)) {
200e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			pr_debug("Too many kcore maps - skipping\n");
201e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			return 0;
202e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		}
203e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		state->done[state->done_cnt++] = al.map->start;
204e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
205e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
206e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	/* Read the object code using objdump */
207e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	objdump_addr = map__rip_2objdump(al.map, al.addr);
208e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	ret = read_via_objdump(al.map->dso->long_name, objdump_addr, buf2, len);
209e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (ret > 0) {
210e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		/*
211e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		 * The kernel maps are inaccurate - assume objdump is right in
212e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		 * that case.
213e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		 */
214e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (cpumode == PERF_RECORD_MISC_KERNEL ||
215e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		    cpumode == PERF_RECORD_MISC_GUEST_KERNEL) {
216e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			len -= ret;
217e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			if (len) {
218e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				pr_debug("Reducing len to %zu\n", len);
219e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			} else if (dso__is_kcore(al.map->dso)) {
220e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				/*
221e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				 * objdump cannot handle very large segments
222e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				 * that may be found in kcore.
223e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				 */
224e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				pr_debug("objdump failed for kcore");
225e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				pr_debug(" - skipping\n");
226e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				return 0;
227e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			} else {
228e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				return -1;
229e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			}
230e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		}
231e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
232e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (ret < 0) {
233e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		pr_debug("read_via_objdump failed\n");
234e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return -1;
235e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
236e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
237e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	/* The results should be identical */
238e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (memcmp(buf1, buf2, len)) {
239e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		pr_debug("Bytes read differ from those read by objdump\n");
240e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return -1;
241e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
242e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	pr_debug("Bytes read match those read by objdump\n");
243e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
244e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return 0;
245e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
246e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
247e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int process_sample_event(struct machine *machine,
248e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				struct perf_evlist *evlist,
249e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				union perf_event *event, struct state *state)
250e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
251e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct perf_sample sample;
252e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct thread *thread;
253e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	u8 cpumode;
254e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
255e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (perf_evlist__parse_sample(evlist, event, &sample)) {
256e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		pr_debug("perf_evlist__parse_sample failed\n");
257e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return -1;
258e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
259e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
260e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	thread = machine__findnew_thread(machine, sample.pid, sample.pid);
261e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (!thread) {
262e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		pr_debug("machine__findnew_thread failed\n");
263e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return -1;
264e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
265e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
266e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
267e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
268e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return read_object_code(sample.ip, READLEN, cpumode, thread, machine,
269e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				state);
270e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
271e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
272e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int process_event(struct machine *machine, struct perf_evlist *evlist,
273e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			 union perf_event *event, struct state *state)
274e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
275e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (event->header.type == PERF_RECORD_SAMPLE)
276e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return process_sample_event(machine, evlist, event, state);
277e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
278e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (event->header.type < PERF_RECORD_MAX)
279e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return machine__process_event(machine, event);
280e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
281e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return 0;
282e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
283e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
284e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int process_events(struct machine *machine, struct perf_evlist *evlist,
285e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			  struct state *state)
286e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
287e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	union perf_event *event;
288e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int i, ret;
289e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
290e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	for (i = 0; i < evlist->nr_mmaps; i++) {
291e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		while ((event = perf_evlist__mmap_read(evlist, i)) != NULL) {
292e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			ret = process_event(machine, evlist, event, state);
293e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			perf_evlist__mmap_consume(evlist, i);
294e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			if (ret < 0)
295e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				return ret;
296e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		}
297e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
298e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return 0;
299e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
300e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
301e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int comp(const void *a, const void *b)
302e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
303e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return *(int *)a - *(int *)b;
304e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
305e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
306e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void do_sort_something(void)
307e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
308e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int buf[40960], i;
309e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
310e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	for (i = 0; i < (int)ARRAY_SIZE(buf); i++)
311e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		buf[i] = ARRAY_SIZE(buf) - i - 1;
312e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
313e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	qsort(buf, ARRAY_SIZE(buf), sizeof(int), comp);
314e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
315e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	for (i = 0; i < (int)ARRAY_SIZE(buf); i++) {
316e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (buf[i] != i) {
317e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			pr_debug("qsort failed\n");
318e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			break;
319e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		}
320e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
321e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
322e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
323e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void sort_something(void)
324e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
325e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int i;
326e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
327e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	for (i = 0; i < 10; i++)
328e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		do_sort_something();
329e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
330e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
331e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void syscall_something(void)
332e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
333e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int pipefd[2];
334e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int i;
335e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
336e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	for (i = 0; i < 1000; i++) {
337e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (pipe(pipefd) < 0) {
338e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			pr_debug("pipe failed\n");
339e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			break;
340e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		}
341e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		close(pipefd[1]);
342e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		close(pipefd[0]);
343e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
344e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
345e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
346e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void fs_something(void)
347e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
348e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	const char *test_file_name = "temp-perf-code-reading-test-file--";
349e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	FILE *f;
350e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int i;
351e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
352e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	for (i = 0; i < 1000; i++) {
353e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		f = fopen(test_file_name, "w+");
354e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (f) {
355e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			fclose(f);
356e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			unlink(test_file_name);
357e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		}
358e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
359e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
360e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
361e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic void do_something(void)
362e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
363e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	fs_something();
364e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
365e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	sort_something();
366e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
367e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	syscall_something();
368e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
369e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
370e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengenum {
371e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	TEST_CODE_READING_OK,
372e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	TEST_CODE_READING_NO_VMLINUX,
373e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	TEST_CODE_READING_NO_KCORE,
374e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	TEST_CODE_READING_NO_ACCESS,
375e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	TEST_CODE_READING_NO_KERNEL_OBJ,
376e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng};
377e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
378e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengstatic int do_test_code_reading(bool try_kcore)
379e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
380e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct machines machines;
381e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct machine *machine;
382e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct thread *thread;
383e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct perf_record_opts opts = {
384e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		.mmap_pages	     = UINT_MAX,
385e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		.user_freq	     = UINT_MAX,
386e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		.user_interval	     = ULLONG_MAX,
387e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		.freq		     = 4000,
388e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		.target		     = {
389e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			.uses_mmap   = true,
390e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		},
391e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	};
392e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct state state = {
393e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		.done_cnt = 0,
394e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	};
395e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct thread_map *threads = NULL;
396e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct cpu_map *cpus = NULL;
397e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct perf_evlist *evlist = NULL;
398e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct perf_evsel *evsel = NULL;
399e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int err = -1, ret;
400e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	pid_t pid;
401e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	struct map *map;
402e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	bool have_vmlinux, have_kcore, excl_kernel = false;
403e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
404e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	pid = getpid();
405e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
406e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	machines__init(&machines);
407e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	machine = &machines.host;
408e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
409e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	ret = machine__create_kernel_maps(machine);
410e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (ret < 0) {
411e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		pr_debug("machine__create_kernel_maps failed\n");
412e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		goto out_err;
413e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
414e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
415e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	/* Force the use of kallsyms instead of vmlinux to try kcore */
416e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (try_kcore)
417e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		symbol_conf.kallsyms_name = "/proc/kallsyms";
418e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
419e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	/* Load kernel map */
420e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	map = machine->vmlinux_maps[MAP__FUNCTION];
421e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	ret = map__load(map, NULL);
422e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (ret < 0) {
423e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		pr_debug("map__load failed\n");
424e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		goto out_err;
425e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
426e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	have_vmlinux = dso__is_vmlinux(map->dso);
427e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	have_kcore = dso__is_kcore(map->dso);
428e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
429e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	/* 2nd time through we just try kcore */
430e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (try_kcore && !have_kcore)
431e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return TEST_CODE_READING_NO_KCORE;
432e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
433e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	/* No point getting kernel events if there is no kernel object */
434e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (!have_vmlinux && !have_kcore)
435e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		excl_kernel = true;
436e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
437e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	threads = thread_map__new_by_tid(pid);
438e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (!threads) {
439e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		pr_debug("thread_map__new_by_tid failed\n");
440e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		goto out_err;
441e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
442e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
443e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	ret = perf_event__synthesize_thread_map(NULL, threads,
444e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng						perf_event__process, machine);
445e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (ret < 0) {
446e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		pr_debug("perf_event__synthesize_thread_map failed\n");
447e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		goto out_err;
448e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
449e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
450e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	thread = machine__findnew_thread(machine, pid, pid);
451e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (!thread) {
452e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		pr_debug("machine__findnew_thread failed\n");
453e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		goto out_err;
454e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
455e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
456e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	cpus = cpu_map__new(NULL);
457e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (!cpus) {
458e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		pr_debug("cpu_map__new failed\n");
459e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		goto out_err;
460e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
461e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
462e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	while (1) {
463e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		const char *str;
464e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
465e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		evlist = perf_evlist__new();
466e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (!evlist) {
467e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			pr_debug("perf_evlist__new failed\n");
468e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			goto out_err;
469e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		}
470e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
471e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		perf_evlist__set_maps(evlist, cpus, threads);
472e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
473e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (excl_kernel)
474e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			str = "cycles:u";
475e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		else
476e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			str = "cycles";
477e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		pr_debug("Parsing event '%s'\n", str);
478e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		ret = parse_events(evlist, str);
479e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (ret < 0) {
480e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			pr_debug("parse_events failed\n");
481e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			goto out_err;
482e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		}
483e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
484e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		perf_evlist__config(evlist, &opts);
485e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
486e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		evsel = perf_evlist__first(evlist);
487e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
488e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		evsel->attr.comm = 1;
489e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		evsel->attr.disabled = 1;
490e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		evsel->attr.enable_on_exec = 0;
491e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
492e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		ret = perf_evlist__open(evlist);
493e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		if (ret < 0) {
494e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			if (!excl_kernel) {
495e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				excl_kernel = true;
496e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				perf_evlist__delete(evlist);
497e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				evlist = NULL;
498e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng				continue;
499e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			}
500e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			pr_debug("perf_evlist__open failed\n");
501e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng			goto out_err;
502e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		}
503e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		break;
504e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
505e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
506e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	ret = perf_evlist__mmap(evlist, UINT_MAX, false);
507e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (ret < 0) {
508e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		pr_debug("perf_evlist__mmap failed\n");
509e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		goto out_err;
510e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
511e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
512e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	perf_evlist__enable(evlist);
513e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
514e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	do_something();
515e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
516e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	perf_evlist__disable(evlist);
517e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
518e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	ret = process_events(machine, evlist, &state);
519e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (ret < 0)
520e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		goto out_err;
521e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
522e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (!have_vmlinux && !have_kcore && !try_kcore)
523e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		err = TEST_CODE_READING_NO_KERNEL_OBJ;
524e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	else if (!have_vmlinux && !try_kcore)
525e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		err = TEST_CODE_READING_NO_VMLINUX;
526e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	else if (excl_kernel)
527e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		err = TEST_CODE_READING_NO_ACCESS;
528e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	else
529e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		err = TEST_CODE_READING_OK;
530e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengout_err:
531e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (evlist) {
532e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		perf_evlist__munmap(evlist);
533e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		perf_evlist__close(evlist);
534e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		perf_evlist__delete(evlist);
535e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	}
536e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (cpus)
537e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		cpu_map__delete(cpus);
538e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (threads)
539e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		thread_map__delete(threads);
540e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	machines__destroy_kernel_maps(&machines);
541e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	machine__delete_threads(machine);
542e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	machines__exit(&machines);
543e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
544e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	return err;
545e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
546e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
547e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Chengint test__code_reading(void)
548e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng{
549e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	int ret;
550e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
551e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	ret = do_test_code_reading(false);
552e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	if (!ret)
553e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		ret = do_test_code_reading(true);
554e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng
555e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	switch (ret) {
556e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	case TEST_CODE_READING_OK:
557e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return 0;
558e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	case TEST_CODE_READING_NO_VMLINUX:
559e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		fprintf(stderr, " (no vmlinux)");
560e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return 0;
561e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	case TEST_CODE_READING_NO_KCORE:
562e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		fprintf(stderr, " (no kcore)");
563e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return 0;
564e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	case TEST_CODE_READING_NO_ACCESS:
565e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		fprintf(stderr, " (no access)");
566e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return 0;
567e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	case TEST_CODE_READING_NO_KERNEL_OBJ:
568e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		fprintf(stderr, " (no kernel obj)");
569e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return 0;
570e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	default:
571e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng		return -1;
572e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng	};
573e6e8a0bd7cffcc9ae2e0e75546fb12a19213d4aeBen Cheng}
574