perf tools: Move dso_* related functions into dso object
[deliverable/linux.git] / tools / perf / util / dso.c
CommitLineData
cdd059d7
JO
1#include "symbol.h"
2#include "dso.h"
3#include "util.h"
4#include "debug.h"
5
6char dso__symtab_origin(const struct dso *dso)
7{
8 static const char origin[] = {
9 [DSO_BINARY_TYPE__KALLSYMS] = 'k',
10 [DSO_BINARY_TYPE__VMLINUX] = 'v',
11 [DSO_BINARY_TYPE__JAVA_JIT] = 'j',
12 [DSO_BINARY_TYPE__DEBUGLINK] = 'l',
13 [DSO_BINARY_TYPE__BUILD_ID_CACHE] = 'B',
14 [DSO_BINARY_TYPE__FEDORA_DEBUGINFO] = 'f',
15 [DSO_BINARY_TYPE__UBUNTU_DEBUGINFO] = 'u',
16 [DSO_BINARY_TYPE__BUILDID_DEBUGINFO] = 'b',
17 [DSO_BINARY_TYPE__SYSTEM_PATH_DSO] = 'd',
18 [DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE] = 'K',
19 [DSO_BINARY_TYPE__GUEST_KALLSYMS] = 'g',
20 [DSO_BINARY_TYPE__GUEST_KMODULE] = 'G',
21 [DSO_BINARY_TYPE__GUEST_VMLINUX] = 'V',
22 };
23
24 if (dso == NULL || dso->symtab_type == DSO_BINARY_TYPE__NOT_FOUND)
25 return '!';
26 return origin[dso->symtab_type];
27}
28
29int dso__binary_type_file(struct dso *dso, enum dso_binary_type type,
30 char *root_dir, char *file, size_t size)
31{
32 char build_id_hex[BUILD_ID_SIZE * 2 + 1];
33 int ret = 0;
34
35 switch (type) {
36 case DSO_BINARY_TYPE__DEBUGLINK: {
37 char *debuglink;
38
39 strncpy(file, dso->long_name, size);
40 debuglink = file + dso->long_name_len;
41 while (debuglink != file && *debuglink != '/')
42 debuglink--;
43 if (*debuglink == '/')
44 debuglink++;
45 filename__read_debuglink(dso->long_name, debuglink,
46 size - (debuglink - file));
47 }
48 break;
49 case DSO_BINARY_TYPE__BUILD_ID_CACHE:
50 /* skip the locally configured cache if a symfs is given */
51 if (symbol_conf.symfs[0] ||
52 (dso__build_id_filename(dso, file, size) == NULL))
53 ret = -1;
54 break;
55
56 case DSO_BINARY_TYPE__FEDORA_DEBUGINFO:
57 snprintf(file, size, "%s/usr/lib/debug%s.debug",
58 symbol_conf.symfs, dso->long_name);
59 break;
60
61 case DSO_BINARY_TYPE__UBUNTU_DEBUGINFO:
62 snprintf(file, size, "%s/usr/lib/debug%s",
63 symbol_conf.symfs, dso->long_name);
64 break;
65
66 case DSO_BINARY_TYPE__BUILDID_DEBUGINFO:
67 if (!dso->has_build_id) {
68 ret = -1;
69 break;
70 }
71
72 build_id__sprintf(dso->build_id,
73 sizeof(dso->build_id),
74 build_id_hex);
75 snprintf(file, size,
76 "%s/usr/lib/debug/.build-id/%.2s/%s.debug",
77 symbol_conf.symfs, build_id_hex, build_id_hex + 2);
78 break;
79
80 case DSO_BINARY_TYPE__SYSTEM_PATH_DSO:
81 snprintf(file, size, "%s%s",
82 symbol_conf.symfs, dso->long_name);
83 break;
84
85 case DSO_BINARY_TYPE__GUEST_KMODULE:
86 snprintf(file, size, "%s%s%s", symbol_conf.symfs,
87 root_dir, dso->long_name);
88 break;
89
90 case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE:
91 snprintf(file, size, "%s%s", symbol_conf.symfs,
92 dso->long_name);
93 break;
94
95 default:
96 case DSO_BINARY_TYPE__KALLSYMS:
97 case DSO_BINARY_TYPE__VMLINUX:
98 case DSO_BINARY_TYPE__GUEST_KALLSYMS:
99 case DSO_BINARY_TYPE__GUEST_VMLINUX:
100 case DSO_BINARY_TYPE__JAVA_JIT:
101 case DSO_BINARY_TYPE__NOT_FOUND:
102 ret = -1;
103 break;
104 }
105
106 return ret;
107}
108
109static int open_dso(struct dso *dso, struct machine *machine)
110{
111 char *root_dir = (char *) "";
112 char *name;
113 int fd;
114
115 name = malloc(PATH_MAX);
116 if (!name)
117 return -ENOMEM;
118
119 if (machine)
120 root_dir = machine->root_dir;
121
122 if (dso__binary_type_file(dso, dso->data_type,
123 root_dir, name, PATH_MAX)) {
124 free(name);
125 return -EINVAL;
126 }
127
128 fd = open(name, O_RDONLY);
129 free(name);
130 return fd;
131}
132
133int dso__data_fd(struct dso *dso, struct machine *machine)
134{
135 static enum dso_binary_type binary_type_data[] = {
136 DSO_BINARY_TYPE__BUILD_ID_CACHE,
137 DSO_BINARY_TYPE__SYSTEM_PATH_DSO,
138 DSO_BINARY_TYPE__NOT_FOUND,
139 };
140 int i = 0;
141
142 if (dso->data_type != DSO_BINARY_TYPE__NOT_FOUND)
143 return open_dso(dso, machine);
144
145 do {
146 int fd;
147
148 dso->data_type = binary_type_data[i++];
149
150 fd = open_dso(dso, machine);
151 if (fd >= 0)
152 return fd;
153
154 } while (dso->data_type != DSO_BINARY_TYPE__NOT_FOUND);
155
156 return -EINVAL;
157}
158
159static void
160dso_cache__free(struct rb_root *root)
161{
162 struct rb_node *next = rb_first(root);
163
164 while (next) {
165 struct dso_cache *cache;
166
167 cache = rb_entry(next, struct dso_cache, rb_node);
168 next = rb_next(&cache->rb_node);
169 rb_erase(&cache->rb_node, root);
170 free(cache);
171 }
172}
173
174static struct dso_cache*
175dso_cache__find(struct rb_root *root, u64 offset)
176{
177 struct rb_node **p = &root->rb_node;
178 struct rb_node *parent = NULL;
179 struct dso_cache *cache;
180
181 while (*p != NULL) {
182 u64 end;
183
184 parent = *p;
185 cache = rb_entry(parent, struct dso_cache, rb_node);
186 end = cache->offset + DSO__DATA_CACHE_SIZE;
187
188 if (offset < cache->offset)
189 p = &(*p)->rb_left;
190 else if (offset >= end)
191 p = &(*p)->rb_right;
192 else
193 return cache;
194 }
195 return NULL;
196}
197
198static void
199dso_cache__insert(struct rb_root *root, struct dso_cache *new)
200{
201 struct rb_node **p = &root->rb_node;
202 struct rb_node *parent = NULL;
203 struct dso_cache *cache;
204 u64 offset = new->offset;
205
206 while (*p != NULL) {
207 u64 end;
208
209 parent = *p;
210 cache = rb_entry(parent, struct dso_cache, rb_node);
211 end = cache->offset + DSO__DATA_CACHE_SIZE;
212
213 if (offset < cache->offset)
214 p = &(*p)->rb_left;
215 else if (offset >= end)
216 p = &(*p)->rb_right;
217 }
218
219 rb_link_node(&new->rb_node, parent, p);
220 rb_insert_color(&new->rb_node, root);
221}
222
223static ssize_t
224dso_cache__memcpy(struct dso_cache *cache, u64 offset,
225 u8 *data, u64 size)
226{
227 u64 cache_offset = offset - cache->offset;
228 u64 cache_size = min(cache->size - cache_offset, size);
229
230 memcpy(data, cache->data + cache_offset, cache_size);
231 return cache_size;
232}
233
234static ssize_t
235dso_cache__read(struct dso *dso, struct machine *machine,
236 u64 offset, u8 *data, ssize_t size)
237{
238 struct dso_cache *cache;
239 ssize_t ret;
240 int fd;
241
242 fd = dso__data_fd(dso, machine);
243 if (fd < 0)
244 return -1;
245
246 do {
247 u64 cache_offset;
248
249 ret = -ENOMEM;
250
251 cache = zalloc(sizeof(*cache) + DSO__DATA_CACHE_SIZE);
252 if (!cache)
253 break;
254
255 cache_offset = offset & DSO__DATA_CACHE_MASK;
256 ret = -EINVAL;
257
258 if (-1 == lseek(fd, cache_offset, SEEK_SET))
259 break;
260
261 ret = read(fd, cache->data, DSO__DATA_CACHE_SIZE);
262 if (ret <= 0)
263 break;
264
265 cache->offset = cache_offset;
266 cache->size = ret;
267 dso_cache__insert(&dso->cache, cache);
268
269 ret = dso_cache__memcpy(cache, offset, data, size);
270
271 } while (0);
272
273 if (ret <= 0)
274 free(cache);
275
276 close(fd);
277 return ret;
278}
279
280static ssize_t dso_cache_read(struct dso *dso, struct machine *machine,
281 u64 offset, u8 *data, ssize_t size)
282{
283 struct dso_cache *cache;
284
285 cache = dso_cache__find(&dso->cache, offset);
286 if (cache)
287 return dso_cache__memcpy(cache, offset, data, size);
288 else
289 return dso_cache__read(dso, machine, offset, data, size);
290}
291
292ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine,
293 u64 offset, u8 *data, ssize_t size)
294{
295 ssize_t r = 0;
296 u8 *p = data;
297
298 do {
299 ssize_t ret;
300
301 ret = dso_cache_read(dso, machine, offset, p, size);
302 if (ret < 0)
303 return ret;
304
305 /* Reached EOF, return what we have. */
306 if (!ret)
307 break;
308
309 BUG_ON(ret > size);
310
311 r += ret;
312 p += ret;
313 offset += ret;
314 size -= ret;
315
316 } while (size);
317
318 return r;
319}
320
321ssize_t dso__data_read_addr(struct dso *dso, struct map *map,
322 struct machine *machine, u64 addr,
323 u8 *data, ssize_t size)
324{
325 u64 offset = map->map_ip(map, addr);
326 return dso__data_read_offset(dso, machine, offset, data, size);
327}
328
329struct map *dso__new_map(const char *name)
330{
331 struct map *map = NULL;
332 struct dso *dso = dso__new(name);
333
334 if (dso)
335 map = map__new2(0, dso, MAP__FUNCTION);
336
337 return map;
338}
339
340struct dso *dso__kernel_findnew(struct machine *machine, const char *name,
341 const char *short_name, int dso_type)
342{
343 /*
344 * The kernel dso could be created by build_id processing.
345 */
346 struct dso *dso = __dsos__findnew(&machine->kernel_dsos, name);
347
348 /*
349 * We need to run this in all cases, since during the build_id
350 * processing we had no idea this was the kernel dso.
351 */
352 if (dso != NULL) {
353 dso__set_short_name(dso, short_name);
354 dso->kernel = dso_type;
355 }
356
357 return dso;
358}
359
360void dso__set_long_name(struct dso *dso, char *name)
361{
362 if (name == NULL)
363 return;
364 dso->long_name = name;
365 dso->long_name_len = strlen(name);
366}
367
368void dso__set_short_name(struct dso *dso, const char *name)
369{
370 if (name == NULL)
371 return;
372 dso->short_name = name;
373 dso->short_name_len = strlen(name);
374}
375
376static void dso__set_basename(struct dso *dso)
377{
378 dso__set_short_name(dso, basename(dso->long_name));
379}
380
381int dso__name_len(const struct dso *dso)
382{
383 if (!dso)
384 return strlen("[unknown]");
385 if (verbose)
386 return dso->long_name_len;
387
388 return dso->short_name_len;
389}
390
391bool dso__loaded(const struct dso *dso, enum map_type type)
392{
393 return dso->loaded & (1 << type);
394}
395
396bool dso__sorted_by_name(const struct dso *dso, enum map_type type)
397{
398 return dso->sorted_by_name & (1 << type);
399}
400
401void dso__set_sorted_by_name(struct dso *dso, enum map_type type)
402{
403 dso->sorted_by_name |= (1 << type);
404}
405
406struct dso *dso__new(const char *name)
407{
408 struct dso *dso = calloc(1, sizeof(*dso) + strlen(name) + 1);
409
410 if (dso != NULL) {
411 int i;
412 strcpy(dso->name, name);
413 dso__set_long_name(dso, dso->name);
414 dso__set_short_name(dso, dso->name);
415 for (i = 0; i < MAP__NR_TYPES; ++i)
416 dso->symbols[i] = dso->symbol_names[i] = RB_ROOT;
417 dso->cache = RB_ROOT;
418 dso->symtab_type = DSO_BINARY_TYPE__NOT_FOUND;
419 dso->data_type = DSO_BINARY_TYPE__NOT_FOUND;
420 dso->loaded = 0;
421 dso->sorted_by_name = 0;
422 dso->has_build_id = 0;
423 dso->kernel = DSO_TYPE_USER;
424 dso->needs_swap = DSO_SWAP__UNSET;
425 INIT_LIST_HEAD(&dso->node);
426 }
427
428 return dso;
429}
430
431void dso__delete(struct dso *dso)
432{
433 int i;
434 for (i = 0; i < MAP__NR_TYPES; ++i)
435 symbols__delete(&dso->symbols[i]);
436 if (dso->sname_alloc)
437 free((char *)dso->short_name);
438 if (dso->lname_alloc)
439 free(dso->long_name);
440 dso_cache__free(&dso->cache);
441 free(dso);
442}
443
444void dso__set_build_id(struct dso *dso, void *build_id)
445{
446 memcpy(dso->build_id, build_id, sizeof(dso->build_id));
447 dso->has_build_id = 1;
448}
449
450bool dso__build_id_equal(const struct dso *dso, u8 *build_id)
451{
452 return memcmp(dso->build_id, build_id, sizeof(dso->build_id)) == 0;
453}
454
455void dso__read_running_kernel_build_id(struct dso *dso, struct machine *machine)
456{
457 char path[PATH_MAX];
458
459 if (machine__is_default_guest(machine))
460 return;
461 sprintf(path, "%s/sys/kernel/notes", machine->root_dir);
462 if (sysfs__read_build_id(path, dso->build_id,
463 sizeof(dso->build_id)) == 0)
464 dso->has_build_id = true;
465}
466
467int dso__kernel_module_get_build_id(struct dso *dso,
468 const char *root_dir)
469{
470 char filename[PATH_MAX];
471 /*
472 * kernel module short names are of the form "[module]" and
473 * we need just "module" here.
474 */
475 const char *name = dso->short_name + 1;
476
477 snprintf(filename, sizeof(filename),
478 "%s/sys/module/%.*s/notes/.note.gnu.build-id",
479 root_dir, (int)strlen(name) - 1, name);
480
481 if (sysfs__read_build_id(filename, dso->build_id,
482 sizeof(dso->build_id)) == 0)
483 dso->has_build_id = true;
484
485 return 0;
486}
487
488bool __dsos__read_build_ids(struct list_head *head, bool with_hits)
489{
490 bool have_build_id = false;
491 struct dso *pos;
492
493 list_for_each_entry(pos, head, node) {
494 if (with_hits && !pos->hit)
495 continue;
496 if (pos->has_build_id) {
497 have_build_id = true;
498 continue;
499 }
500 if (filename__read_build_id(pos->long_name, pos->build_id,
501 sizeof(pos->build_id)) > 0) {
502 have_build_id = true;
503 pos->has_build_id = true;
504 }
505 }
506
507 return have_build_id;
508}
509
510void dsos__add(struct list_head *head, struct dso *dso)
511{
512 list_add_tail(&dso->node, head);
513}
514
515struct dso *dsos__find(struct list_head *head, const char *name)
516{
517 struct dso *pos;
518
519 list_for_each_entry(pos, head, node)
520 if (strcmp(pos->long_name, name) == 0)
521 return pos;
522 return NULL;
523}
524
525struct dso *__dsos__findnew(struct list_head *head, const char *name)
526{
527 struct dso *dso = dsos__find(head, name);
528
529 if (!dso) {
530 dso = dso__new(name);
531 if (dso != NULL) {
532 dsos__add(head, dso);
533 dso__set_basename(dso);
534 }
535 }
536
537 return dso;
538}
539
540size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp,
541 bool with_hits)
542{
543 struct dso *pos;
544 size_t ret = 0;
545
546 list_for_each_entry(pos, head, node) {
547 if (with_hits && !pos->hit)
548 continue;
549 ret += dso__fprintf_buildid(pos, fp);
550 ret += fprintf(fp, " %s\n", pos->long_name);
551 }
552 return ret;
553}
554
555size_t __dsos__fprintf(struct list_head *head, FILE *fp)
556{
557 struct dso *pos;
558 size_t ret = 0;
559
560 list_for_each_entry(pos, head, node) {
561 int i;
562 for (i = 0; i < MAP__NR_TYPES; ++i)
563 ret += dso__fprintf(pos, i, fp);
564 }
565
566 return ret;
567}
568
569size_t dso__fprintf_buildid(struct dso *dso, FILE *fp)
570{
571 char sbuild_id[BUILD_ID_SIZE * 2 + 1];
572
573 build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
574 return fprintf(fp, "%s", sbuild_id);
575}
576
577size_t dso__fprintf(struct dso *dso, enum map_type type, FILE *fp)
578{
579 struct rb_node *nd;
580 size_t ret = fprintf(fp, "dso: %s (", dso->short_name);
581
582 if (dso->short_name != dso->long_name)
583 ret += fprintf(fp, "%s, ", dso->long_name);
584 ret += fprintf(fp, "%s, %sloaded, ", map_type__name[type],
585 dso->loaded ? "" : "NOT ");
586 ret += dso__fprintf_buildid(dso, fp);
587 ret += fprintf(fp, ")\n");
588 for (nd = rb_first(&dso->symbols[type]); nd; nd = rb_next(nd)) {
589 struct symbol *pos = rb_entry(nd, struct symbol, rb_node);
590 ret += symbol__fprintf(pos, fp);
591 }
592
593 return ret;
594}
This page took 0.068213 seconds and 5 git commands to generate.