aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf/util/session.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/perf/util/session.c')
-rw-r--r--tools/perf/util/session.c84
1 files changed, 77 insertions, 7 deletions
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 707ce1cb1621..ce3a6c8abe76 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -4,6 +4,7 @@
4#include <sys/types.h> 4#include <sys/types.h>
5 5
6#include "session.h" 6#include "session.h"
7#include "sort.h"
7#include "util.h" 8#include "util.h"
8 9
9static int perf_session__open(struct perf_session *self, bool force) 10static int perf_session__open(struct perf_session *self, bool force)
@@ -50,31 +51,100 @@ out_close:
50 51
51struct perf_session *perf_session__new(const char *filename, int mode, bool force) 52struct perf_session *perf_session__new(const char *filename, int mode, bool force)
52{ 53{
53 size_t len = strlen(filename) + 1; 54 size_t len = filename ? strlen(filename) + 1 : 0;
54 struct perf_session *self = zalloc(sizeof(*self) + len); 55 struct perf_session *self = zalloc(sizeof(*self) + len);
55 56
56 if (self == NULL) 57 if (self == NULL)
57 goto out; 58 goto out;
58 59
59 if (perf_header__init(&self->header) < 0) 60 if (perf_header__init(&self->header) < 0)
60 goto out_delete; 61 goto out_free;
61 62
62 memcpy(self->filename, filename, len); 63 memcpy(self->filename, filename, len);
64 self->threads = RB_ROOT;
65 self->last_match = NULL;
66 self->mmap_window = 32;
67 self->cwd = NULL;
68 self->cwdlen = 0;
69 map_groups__init(&self->kmaps);
70
71 if (perf_session__create_kernel_maps(self) < 0)
72 goto out_delete;
63 73
64 if (mode == O_RDONLY && perf_session__open(self, force) < 0) { 74 if (mode == O_RDONLY && perf_session__open(self, force) < 0)
65 perf_session__delete(self); 75 goto out_delete;
66 self = NULL;
67 }
68out: 76out:
69 return self; 77 return self;
70out_delete: 78out_free:
71 free(self); 79 free(self);
72 return NULL; 80 return NULL;
81out_delete:
82 perf_session__delete(self);
83 return NULL;
73} 84}
74 85
75void perf_session__delete(struct perf_session *self) 86void perf_session__delete(struct perf_session *self)
76{ 87{
77 perf_header__exit(&self->header); 88 perf_header__exit(&self->header);
78 close(self->fd); 89 close(self->fd);
90 free(self->cwd);
79 free(self); 91 free(self);
80} 92}
93
94static bool symbol__match_parent_regex(struct symbol *sym)
95{
96 if (sym->name && !regexec(&parent_regex, sym->name, 0, NULL, 0))
97 return 1;
98
99 return 0;
100}
101
102struct symbol **perf_session__resolve_callchain(struct perf_session *self,
103 struct thread *thread,
104 struct ip_callchain *chain,
105 struct symbol **parent)
106{
107 u8 cpumode = PERF_RECORD_MISC_USER;
108 struct symbol **syms = NULL;
109 unsigned int i;
110
111 if (symbol_conf.use_callchain) {
112 syms = calloc(chain->nr, sizeof(*syms));
113 if (!syms) {
114 fprintf(stderr, "Can't allocate memory for symbols\n");
115 exit(-1);
116 }
117 }
118
119 for (i = 0; i < chain->nr; i++) {
120 u64 ip = chain->ips[i];
121 struct addr_location al;
122
123 if (ip >= PERF_CONTEXT_MAX) {
124 switch (ip) {
125 case PERF_CONTEXT_HV:
126 cpumode = PERF_RECORD_MISC_HYPERVISOR; break;
127 case PERF_CONTEXT_KERNEL:
128 cpumode = PERF_RECORD_MISC_KERNEL; break;
129 case PERF_CONTEXT_USER:
130 cpumode = PERF_RECORD_MISC_USER; break;
131 default:
132 break;
133 }
134 continue;
135 }
136
137 thread__find_addr_location(thread, self, cpumode,
138 MAP__FUNCTION, ip, &al, NULL);
139 if (al.sym != NULL) {
140 if (sort__has_parent && !*parent &&
141 symbol__match_parent_regex(al.sym))
142 *parent = al.sym;
143 if (!symbol_conf.use_callchain)
144 break;
145 syms[i] = al.sym;
146 }
147 }
148
149 return syms;
150}