perf symbols: Pass the mmap parameters instead of using mmap_event
[linux-2.6-block.git] / tools / perf / util / map.c
CommitLineData
66e274f3
FW
1#include "symbol.h"
2#include <stdlib.h>
3#include <string.h>
4#include <stdio.h>
e4204992 5#include "debug.h"
66e274f3 6
3846df2e
ACM
7const char *map_type__name[MAP__NR_TYPES] = {
8 [MAP__FUNCTION] = "Functions",
9 [MAP__VARIABLE] = "Variables",
10};
11
66e274f3
FW
12static inline int is_anon_memory(const char *filename)
13{
14 return strcmp(filename, "//anon") == 0;
15}
16
17static int strcommon(const char *pathname, char *cwd, int cwdlen)
18{
19 int n = 0;
20
21 while (n < cwdlen && pathname[n] == cwd[n])
22 ++n;
23
24 return n;
25}
26
3610583c
ACM
27void map__init(struct map *self, enum map_type type,
28 u64 start, u64 end, u64 pgoff, struct dso *dso)
afb7b4f0 29{
3610583c 30 self->type = type;
afb7b4f0
ACM
31 self->start = start;
32 self->end = end;
33 self->pgoff = pgoff;
34 self->dso = dso;
35 self->map_ip = map__map_ip;
36 self->unmap_ip = map__unmap_ip;
37 RB_CLEAR_NODE(&self->rb_node);
38}
39
b177f63f
ACM
40struct map *map__new(u64 start, u64 len, u64 pgoff, u32 pid, char *filename,
41 enum map_type type, char *cwd, int cwdlen)
66e274f3
FW
42{
43 struct map *self = malloc(sizeof(*self));
44
45 if (self != NULL) {
66e274f3 46 char newfilename[PATH_MAX];
afb7b4f0 47 struct dso *dso;
66e274f3
FW
48 int anon;
49
50 if (cwd) {
51 int n = strcommon(filename, cwd, cwdlen);
52
53 if (n == cwdlen) {
54 snprintf(newfilename, sizeof(newfilename),
55 ".%s", filename + n);
56 filename = newfilename;
57 }
58 }
59
60 anon = is_anon_memory(filename);
61
62 if (anon) {
b177f63f 63 snprintf(newfilename, sizeof(newfilename), "/tmp/perf-%d.map", pid);
66e274f3
FW
64 filename = newfilename;
65 }
66
00a192b3 67 dso = dsos__findnew(filename);
afb7b4f0 68 if (dso == NULL)
66e274f3
FW
69 goto out_delete;
70
b177f63f 71 map__init(self, type, start, start + len, pgoff, dso);
afb7b4f0 72
8d92c02a
ACM
73 if (anon) {
74set_identity:
ed52ce2e 75 self->map_ip = self->unmap_ip = identity__map_ip;
8d92c02a
ACM
76 } else if (strcmp(filename, "[vdso]") == 0) {
77 dso__set_loaded(dso, self->type);
78 goto set_identity;
79 }
66e274f3
FW
80 }
81 return self;
82out_delete:
83 free(self);
84 return NULL;
85}
86
c338aee8
ACM
87void map__delete(struct map *self)
88{
89 free(self);
90}
91
6a4694a4 92void map__fixup_start(struct map *self)
c338aee8 93{
6a4694a4 94 struct rb_root *symbols = &self->dso->symbols[self->type];
fcf1203a 95 struct rb_node *nd = rb_first(symbols);
c338aee8
ACM
96 if (nd != NULL) {
97 struct symbol *sym = rb_entry(nd, struct symbol, rb_node);
98 self->start = sym->start;
99 }
100}
101
6a4694a4 102void map__fixup_end(struct map *self)
c338aee8 103{
6a4694a4 104 struct rb_root *symbols = &self->dso->symbols[self->type];
fcf1203a 105 struct rb_node *nd = rb_last(symbols);
c338aee8
ACM
106 if (nd != NULL) {
107 struct symbol *sym = rb_entry(nd, struct symbol, rb_node);
108 self->end = sym->end;
109 }
110}
111
d70a5402
ACM
112#define DSO__DELETED "(deleted)"
113
9de89fe7 114int map__load(struct map *self, symbol_filter_t filter)
66bd8424 115{
79406cd7 116 const char *name = self->dso->long_name;
a128168d 117 int nr;
79406cd7 118
a128168d
MH
119 if (dso__loaded(self->dso, self->type))
120 return 0;
121
9de89fe7 122 nr = dso__load(self->dso, self, filter);
79406cd7
ACM
123 if (nr < 0) {
124 if (self->dso->has_build_id) {
125 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
126
127 build_id__sprintf(self->dso->build_id,
128 sizeof(self->dso->build_id),
129 sbuild_id);
130 pr_warning("%s with build id %s not found",
131 name, sbuild_id);
132 } else
133 pr_warning("Failed to open %s", name);
134
135 pr_warning(", continuing without symbols\n");
136 return -1;
137 } else if (nr == 0) {
138 const size_t len = strlen(name);
139 const size_t real_len = len - sizeof(DSO__DELETED);
140
141 if (len > sizeof(DSO__DELETED) &&
142 strcmp(name + real_len + 1, DSO__DELETED) == 0) {
143 pr_warning("%.*s was updated, restart the long "
144 "running apps that use it!\n",
145 (int)real_len, name);
146 } else {
147 pr_warning("no symbols found in %s, maybe install "
148 "a debug package?\n", name);
66bd8424 149 }
79406cd7
ACM
150
151 return -1;
66bd8424 152 }
9de89fe7
ACM
153 /*
154 * Only applies to the kernel, as its symtabs aren't relative like the
155 * module ones.
156 */
157 if (self->dso->kernel)
158 map__reloc_vmlinux(self);
66bd8424 159
79406cd7
ACM
160 return 0;
161}
162
9de89fe7
ACM
163struct symbol *map__find_symbol(struct map *self, u64 addr,
164 symbol_filter_t filter)
79406cd7 165{
9de89fe7 166 if (map__load(self, filter) < 0)
79406cd7
ACM
167 return NULL;
168
ea08d8cb 169 return dso__find_symbol(self->dso, self->type, addr);
66bd8424
ACM
170}
171
79406cd7
ACM
172struct symbol *map__find_symbol_by_name(struct map *self, const char *name,
173 symbol_filter_t filter)
174{
9de89fe7 175 if (map__load(self, filter) < 0)
79406cd7
ACM
176 return NULL;
177
178 if (!dso__sorted_by_name(self->dso, self->type))
179 dso__sort_by_name(self->dso, self->type);
180
181 return dso__find_symbol_by_name(self->dso, self->type, name);
182}
183
66e274f3
FW
184struct map *map__clone(struct map *self)
185{
186 struct map *map = malloc(sizeof(*self));
187
188 if (!map)
189 return NULL;
190
191 memcpy(map, self, sizeof(*self));
192
193 return map;
194}
195
196int map__overlap(struct map *l, struct map *r)
197{
198 if (l->start > r->start) {
199 struct map *t = l;
200 l = r;
201 r = t;
202 }
203
204 if (l->end > r->start)
205 return 1;
206
207 return 0;
208}
209
210size_t map__fprintf(struct map *self, FILE *fp)
211{
212 return fprintf(fp, " %Lx-%Lx %Lx %s\n",
213 self->start, self->end, self->pgoff, self->dso->name);
214}
7a2b6209
KS
215
216/*
217 * objdump wants/reports absolute IPs for ET_EXEC, and RIPs for ET_DYN.
218 * map->dso->adjust_symbols==1 for ET_EXEC-like cases.
219 */
220u64 map__rip_2objdump(struct map *map, u64 rip)
221{
222 u64 addr = map->dso->adjust_symbols ?
223 map->unmap_ip(map, rip) : /* RIP -> IP */
224 rip;
225 return addr;
226}
ee11b90b
KS
227
228u64 map__objdump_2ip(struct map *map, u64 addr)
229{
230 u64 ip = map->dso->adjust_symbols ?
231 addr :
232 map->unmap_ip(map, addr); /* RIP -> IP */
233 return ip;
234}