3 #include <linux/kernel.h> 4 #include <linux/types.h> 10 #include <sys/param.h> 33 static unsigned int hex(
char c)
35 if (c >=
'0' && c <=
'9')
37 if (c >=
'a' && c <=
'f')
45 size_t bytes_read = 0;
46 unsigned char *chunk_start = *buf;
49 while (*buf_len > 0) {
61 **buf = (
hex(c1) << 4) |
hex(c2);
80 unsigned char *chunk_end = chunk_start + bytes_read - 1;
83 while (chunk_start < chunk_end) {
85 *chunk_start = *chunk_end;
99 size_t ret, bytes_read = 0;
102 p = strchr(line,
':');
127 size_t line_len, off_last = 0;
130 u64 addr, last_addr = start_addr;
132 while (off_last < *len) {
133 size_t off, read_bytes, written_bytes;
134 unsigned char tmp[
BUFSZ];
136 ret = getline(&line, &line_len, f);
150 if (sscanf(line,
"%"PRIx64, &addr) != 1)
152 if (addr < last_addr) {
153 pr_debug(
"addr going backwards, read beyond section?\n");
160 off = addr - start_addr;
163 written_bytes = MIN(read_bytes, *len - off);
164 memcpy(buf + off, tmp, written_bytes);
165 off_last = off + written_bytes;
184 fmt =
"%s -z -d --start-address=0x%"PRIx64
" --stop-address=0x%"PRIx64
" %s";
185 ret = snprintf(cmd,
sizeof(cmd), fmt,
"objdump", addr, addr + len,
187 if (ret <= 0 || (
size_t)ret >=
sizeof(cmd))
190 pr_debug(
"Objdump command is: %s\n", cmd);
193 strcat(cmd,
" 2>/dev/null");
203 pr_debug(
"objdump read too few bytes: %zd\n", len);
213 static void dump_buf(
unsigned char *buf,
size_t len)
217 for (i = 0; i < len; i++) {
229 unsigned char buf1[
BUFSZ];
230 unsigned char buf2[
BUFSZ];
233 const char *objdump_name;
237 pr_debug(
"Reading object code for memory address: %#"PRIx64
"\n", addr);
240 if (cpumode == PERF_RECORD_MISC_HYPERVISOR) {
241 pr_debug(
"Hypervisor address can not be resolved - skipping\n");
245 pr_debug(
"thread__find_map failed\n");
253 pr_debug(
"Unexpected kernel address - skipping\n");
263 if (addr + len > al.
map->
end)
269 if (ret_len != len) {
270 pr_debug(
"dso__data_read_offset failed\n");
285 for (d = 0; d < state->
done_cnt; d++) {
287 pr_debug(
"kcore map tested already");
293 pr_debug(
"Too many kcore maps - skipping\n");
303 sizeof(decomp_name)) < 0) {
308 objdump_name = decomp_name;
316 unlink(objdump_name);
323 if (cpumode == PERF_RECORD_MISC_KERNEL ||
324 cpumode == PERF_RECORD_MISC_GUEST_KERNEL) {
327 pr_debug(
"Reducing len to %zu\n", len);
333 pr_debug(
"objdump failed for kcore");
342 pr_debug(
"read_via_objdump failed\n");
347 if (memcmp(buf1, buf2, len)) {
348 pr_debug(
"Bytes read differ from those read by objdump\n");
355 pr_debug(
"Bytes read match those read by objdump\n");
369 pr_debug(
"perf_evlist__parse_sample failed\n");
375 pr_debug(
"machine__findnew_thread failed\n");
387 if (event->
header.type == PERF_RECORD_SAMPLE)
390 if (event->
header.type == PERF_RECORD_THROTTLE ||
391 event->
header.type == PERF_RECORD_UNTHROTTLE)
394 if (event->
header.type < PERF_RECORD_MAX) {
399 pr_debug(
"machine__process_event failed, event type %u\n",
414 for (i = 0; i < evlist->
nr_mmaps; i++) {
415 md = &evlist->
mmap[i];
430 static int comp(
const void *a,
const void *b)
432 return *(
int *)a - *(
int *)b;
439 for (i = 0; i < (int)ARRAY_SIZE(buf); i++)
440 buf[i] = ARRAY_SIZE(buf) - i - 1;
442 qsort(buf, ARRAY_SIZE(buf),
sizeof(
int),
comp);
444 for (i = 0; i < (int)ARRAY_SIZE(buf); i++) {
456 for (i = 0; i < 10; i++)
465 for (i = 0; i < 1000; i++) {
466 if (pipe(pipefd) < 0) {
477 const char *test_file_name =
"temp-perf-code-reading-test-file--";
481 for (i = 0; i < 1000; i++) {
482 f = fopen(test_file_name,
"w+");
485 unlink(test_file_name);
492 const char *
event = excl_kernel ?
"cycles:u" :
"cycles";
495 char cpuid[128], model[16], model_c[16], cpum_cf_v[16];
501 ret = sscanf(cpuid,
"%*[^,],%u,%[^,],%[^,],%[^,],%x", &family, model_c,
502 model, cpum_cf_v, &cpum_cf_a);
505 if (excl_kernel && (cpum_cf_a & 4))
507 if (!excl_kernel && (cpum_cf_a & 2))
512 event = excl_kernel ?
"cpu-clock:u" :
"cpu-clock";
541 .user_freq = UINT_MAX,
542 .user_interval = ULLONG_MAX,
548 struct state state = {
558 bool have_vmlinux, have_kcore, excl_kernel =
false;
567 pr_debug(
"machine__create_kernel_maps failed\n");
586 if (try_kcore && !have_kcore)
590 if (!have_vmlinux && !have_kcore)
595 pr_debug(
"thread_map__new_by_tid failed\n");
602 pr_debug(
"perf_event__synthesize_thread_map failed\n");
608 pr_debug(
"machine__findnew_thread failed\n");
623 pr_debug(
"perf_evlist__new failed\n");
630 pr_debug(
"Parsing event '%s'\n", str);
641 evsel->
attr.comm = 1;
642 evsel->
attr.disabled = 1;
643 evsel->
attr.enable_on_exec = 0;
665 pr_debug(
"perf_evlist__open() failed!\n%s\n", errbuf);
675 pr_debug(
"perf_evlist__mmap failed\n");
689 if (!have_vmlinux && !have_kcore && !try_kcore)
691 else if (!have_vmlinux && !try_kcore)
693 else if (excl_kernel)
void perf_evlist__set_maps(struct perf_evlist *evlist, struct cpu_map *cpus, struct thread_map *threads)
static size_t read_objdump_chunk(const char **line, unsigned char **buf, size_t *buf_len)
void perf_mmap__consume(struct perf_mmap *map)
static bool dso__is_vmlinux(struct dso *dso)
static unsigned int hex(char c)
static void sort_something(void)
void perf_evlist__enable(struct perf_evlist *evlist)
int machine__create_kernel_maps(struct machine *machine)
struct thread_map * thread_map__get(struct thread_map *map)
struct map * thread__find_map(struct thread *thread, u8 cpumode, u64 addr, struct addr_location *al)
void perf_evlist__delete(struct perf_evlist *evlist)
static void do_sort_something(void)
struct thread_map * thread_map__new_by_tid(pid_t tid)
int dso__decompress_kmodule_path(struct dso *dso, const char *name, char *pathname, size_t len)
int machine__process_event(struct machine *machine, union perf_event *event, struct perf_sample *sample)
int parse_events(struct perf_evlist *evlist, const char *str, struct parse_events_error *err)
static struct map * machine__kernel_map(struct machine *machine)
void cpu_map__put(struct cpu_map *map)
int perf_mmap__read_init(struct perf_mmap *map)
int perf_event__process(struct perf_tool *tool __maybe_unused, union perf_event *event, struct perf_sample *sample, struct machine *machine)
#define pr_debug(fmt,...)
static int read_via_objdump(const char *filename, u64 addr, void *buf, size_t len)
static int process_event(struct machine *machine, struct perf_evlist *evlist, union perf_event *event, struct state *state)
int perf_evlist__open(struct perf_evlist *evlist)
static const char * do_determine_event(bool excl_kernel)
bool dso__needs_decompress(struct dso *dso)
int perf_evlist__parse_sample(struct perf_evlist *evlist, union perf_event *event, struct perf_sample *sample)
static int str(yyscan_t scanner, int token)
static void do_something(void)
static int process_events(struct machine *machine, struct perf_evlist *evlist, struct state *state)
static int read_object_code(u64 addr, size_t len, u8 cpumode, struct thread *thread, struct state *state)
static bool dso__is_kcore(struct dso *dso)
void perf_evlist__config(struct perf_evlist *evlist, struct record_opts *opts, struct callchain_param *callchain)
static int read_objdump_output(FILE *f, void *buf, size_t *len, u64 start_addr)
int perf_evlist__mmap(struct perf_evlist *evlist, unsigned int pages)
x86 movsq based memcpy() in arch/x86/lib/memcpy_64.S") MEMCPY_FN(memcpy_erms
u64 map__rip_2objdump(struct map *map, u64 rip)
void perf_mmap__read_done(struct perf_mmap *map)
struct perf_event_header header
int test__code_reading(struct test *test __maybe_unused, int subtest __maybe_unused)
static struct perf_evsel * perf_evlist__first(struct perf_evlist *evlist)
const char * kallsyms_name
union perf_event * perf_mmap__read_event(struct perf_mmap *map)
void thread__put(struct thread *thread)
void perf_evlist__disable(struct perf_evlist *evlist)
void machine__delete(struct machine *machine)
int perf_event__synthesize_thread_map(struct perf_tool *tool, struct thread_map *threads, perf_event__handler_t process, struct machine *machine, bool mmap_data, unsigned int proc_map_timeout)
struct machine * machine__new_host(void)
enum dso_binary_type symtab_type
static int process_sample_event(struct machine *machine, struct perf_evlist *evlist, union perf_event *event, struct state *state)
static size_t read_objdump_line(const char *line, unsigned char *buf, size_t buf_len)
void thread_map__put(struct thread_map *map)
ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine, u64 offset, u8 *data, ssize_t size)
int perf_evlist__strerror_open(struct perf_evlist *evlist, int err, char *buf, size_t size)
struct cpu_map * cpu_map__new(const char *cpu_list)
int map__load(struct map *map)
void machine__delete_threads(struct machine *machine)
static void fs_something(void)
static int do_test_code_reading(bool try_kcore)
static void syscall_something(void)
static void dump_buf(unsigned char *buf, size_t len)
static int comp(const void *a, const void *b)
struct thread * machine__findnew_thread(struct machine *machine, pid_t pid, pid_t tid)
struct perf_evlist * perf_evlist__new(void)
struct perf_event_attr attr
struct cpu_map * cpu_map__get(struct cpu_map *map)