]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - tools/perf/util/dso.c
perf tools: Move extra string util functions to util/string2.h
[mirror_ubuntu-artful-kernel.git] / tools / perf / util / dso.c
CommitLineData
bda6ee4a 1#include <asm/bug.h>
877a7a11 2#include <linux/kernel.h>
c6580451
JO
3#include <sys/time.h>
4#include <sys/resource.h>
cdd059d7
JO
5#include "symbol.h"
6#include "dso.h"
69d2591a 7#include "machine.h"
cfe9174f 8#include "auxtrace.h"
cdd059d7
JO
9#include "util.h"
10#include "debug.h"
a067558e 11#include "string2.h"
6ae98ba6 12#include "vdso.h"
cdd059d7 13
9343e45b
MGP
14static const char * const debuglink_paths[] = {
15 "%.0s%s",
16 "%s/%s",
17 "%s/.debug/%s",
18 "/usr/lib/debug%s/%s"
19};
20
cdd059d7
JO
21char dso__symtab_origin(const struct dso *dso)
22{
23 static const char origin[] = {
9cd00941
RRD
24 [DSO_BINARY_TYPE__KALLSYMS] = 'k',
25 [DSO_BINARY_TYPE__VMLINUX] = 'v',
26 [DSO_BINARY_TYPE__JAVA_JIT] = 'j',
27 [DSO_BINARY_TYPE__DEBUGLINK] = 'l',
28 [DSO_BINARY_TYPE__BUILD_ID_CACHE] = 'B',
29 [DSO_BINARY_TYPE__FEDORA_DEBUGINFO] = 'f',
30 [DSO_BINARY_TYPE__UBUNTU_DEBUGINFO] = 'u',
31 [DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO] = 'o',
32 [DSO_BINARY_TYPE__BUILDID_DEBUGINFO] = 'b',
33 [DSO_BINARY_TYPE__SYSTEM_PATH_DSO] = 'd',
34 [DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE] = 'K',
c00c48fc 35 [DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP] = 'm',
9cd00941
RRD
36 [DSO_BINARY_TYPE__GUEST_KALLSYMS] = 'g',
37 [DSO_BINARY_TYPE__GUEST_KMODULE] = 'G',
c00c48fc 38 [DSO_BINARY_TYPE__GUEST_KMODULE_COMP] = 'M',
9cd00941 39 [DSO_BINARY_TYPE__GUEST_VMLINUX] = 'V',
cdd059d7
JO
40 };
41
42 if (dso == NULL || dso->symtab_type == DSO_BINARY_TYPE__NOT_FOUND)
43 return '!';
44 return origin[dso->symtab_type];
45}
46
ee4e9625
ACM
47int dso__read_binary_type_filename(const struct dso *dso,
48 enum dso_binary_type type,
49 char *root_dir, char *filename, size_t size)
cdd059d7 50{
b5d8bbe8 51 char build_id_hex[SBUILD_ID_SIZE];
cdd059d7 52 int ret = 0;
972f393b 53 size_t len;
cdd059d7
JO
54
55 switch (type) {
9343e45b
MGP
56 case DSO_BINARY_TYPE__DEBUGLINK:
57 {
58 const char *last_slash;
59 char dso_dir[PATH_MAX];
60 char symfile[PATH_MAX];
61 unsigned int i;
cdd059d7 62
dc6254cf 63 len = __symbol__join_symfs(filename, size, dso->long_name);
9343e45b
MGP
64 last_slash = filename + len;
65 while (last_slash != filename && *last_slash != '/')
66 last_slash--;
40356721 67
9343e45b
MGP
68 strncpy(dso_dir, filename, last_slash - filename);
69 dso_dir[last_slash-filename] = '\0';
70
71 if (!is_regular_file(filename)) {
72 ret = -1;
40356721 73 break;
9343e45b 74 }
40356721 75
9343e45b
MGP
76 ret = filename__read_debuglink(filename, symfile, PATH_MAX);
77 if (ret)
78 break;
79
80 /* Check predefined locations where debug file might reside */
81 ret = -1;
82 for (i = 0; i < ARRAY_SIZE(debuglink_paths); i++) {
83 snprintf(filename, size,
84 debuglink_paths[i], dso_dir, symfile);
85 if (is_regular_file(filename)) {
86 ret = 0;
87 break;
88 }
cdd059d7 89 }
9343e45b 90
cdd059d7 91 break;
9343e45b 92 }
cdd059d7 93 case DSO_BINARY_TYPE__BUILD_ID_CACHE:
a7066709 94 if (dso__build_id_filename(dso, filename, size) == NULL)
cdd059d7
JO
95 ret = -1;
96 break;
97
98 case DSO_BINARY_TYPE__FEDORA_DEBUGINFO:
972f393b
ACM
99 len = __symbol__join_symfs(filename, size, "/usr/lib/debug");
100 snprintf(filename + len, size - len, "%s.debug", dso->long_name);
cdd059d7
JO
101 break;
102
103 case DSO_BINARY_TYPE__UBUNTU_DEBUGINFO:
972f393b
ACM
104 len = __symbol__join_symfs(filename, size, "/usr/lib/debug");
105 snprintf(filename + len, size - len, "%s", dso->long_name);
cdd059d7
JO
106 break;
107
9cd00941
RRD
108 case DSO_BINARY_TYPE__OPENEMBEDDED_DEBUGINFO:
109 {
bf4414ae 110 const char *last_slash;
9cd00941
RRD
111 size_t dir_size;
112
113 last_slash = dso->long_name + dso->long_name_len;
114 while (last_slash != dso->long_name && *last_slash != '/')
115 last_slash--;
116
972f393b 117 len = __symbol__join_symfs(filename, size, "");
9cd00941
RRD
118 dir_size = last_slash - dso->long_name + 2;
119 if (dir_size > (size - len)) {
120 ret = -1;
121 break;
122 }
7d2a5122
ACM
123 len += scnprintf(filename + len, dir_size, "%s", dso->long_name);
124 len += scnprintf(filename + len , size - len, ".debug%s",
9cd00941
RRD
125 last_slash);
126 break;
127 }
128
cdd059d7
JO
129 case DSO_BINARY_TYPE__BUILDID_DEBUGINFO:
130 if (!dso->has_build_id) {
131 ret = -1;
132 break;
133 }
134
135 build_id__sprintf(dso->build_id,
136 sizeof(dso->build_id),
137 build_id_hex);
972f393b
ACM
138 len = __symbol__join_symfs(filename, size, "/usr/lib/debug/.build-id/");
139 snprintf(filename + len, size - len, "%.2s/%s.debug",
140 build_id_hex, build_id_hex + 2);
cdd059d7
JO
141 break;
142
39b12f78
AH
143 case DSO_BINARY_TYPE__VMLINUX:
144 case DSO_BINARY_TYPE__GUEST_VMLINUX:
cdd059d7 145 case DSO_BINARY_TYPE__SYSTEM_PATH_DSO:
972f393b 146 __symbol__join_symfs(filename, size, dso->long_name);
cdd059d7
JO
147 break;
148
149 case DSO_BINARY_TYPE__GUEST_KMODULE:
c00c48fc 150 case DSO_BINARY_TYPE__GUEST_KMODULE_COMP:
972f393b
ACM
151 path__join3(filename, size, symbol_conf.symfs,
152 root_dir, dso->long_name);
cdd059d7
JO
153 break;
154
155 case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE:
c00c48fc 156 case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP:
972f393b 157 __symbol__join_symfs(filename, size, dso->long_name);
cdd059d7
JO
158 break;
159
8e0cf965
AH
160 case DSO_BINARY_TYPE__KCORE:
161 case DSO_BINARY_TYPE__GUEST_KCORE:
7d2a5122 162 snprintf(filename, size, "%s", dso->long_name);
8e0cf965
AH
163 break;
164
cdd059d7
JO
165 default:
166 case DSO_BINARY_TYPE__KALLSYMS:
cdd059d7 167 case DSO_BINARY_TYPE__GUEST_KALLSYMS:
cdd059d7
JO
168 case DSO_BINARY_TYPE__JAVA_JIT:
169 case DSO_BINARY_TYPE__NOT_FOUND:
170 ret = -1;
171 break;
172 }
173
174 return ret;
175}
176
c00c48fc
NK
177static const struct {
178 const char *fmt;
179 int (*decompress)(const char *input, int output);
180} compressions[] = {
e92ce12e
NK
181#ifdef HAVE_ZLIB_SUPPORT
182 { "gz", gzip_decompress_to_file },
80a32e5b
JO
183#endif
184#ifdef HAVE_LZMA_SUPPORT
185 { "xz", lzma_decompress_to_file },
e92ce12e
NK
186#endif
187 { NULL, NULL },
c00c48fc
NK
188};
189
190bool is_supported_compression(const char *ext)
191{
192 unsigned i;
193
194 for (i = 0; compressions[i].fmt; i++) {
195 if (!strcmp(ext, compressions[i].fmt))
196 return true;
197 }
198 return false;
199}
200
1f121b03 201bool is_kernel_module(const char *pathname, int cpumode)
c00c48fc 202{
8dee9ff1 203 struct kmod_path m;
1f121b03
WN
204 int mode = cpumode & PERF_RECORD_MISC_CPUMODE_MASK;
205
206 WARN_ONCE(mode != cpumode,
207 "Internal error: passing unmasked cpumode (%x) to is_kernel_module",
208 cpumode);
209
210 switch (mode) {
211 case PERF_RECORD_MISC_USER:
212 case PERF_RECORD_MISC_HYPERVISOR:
213 case PERF_RECORD_MISC_GUEST_USER:
214 return false;
215 /* Treat PERF_RECORD_MISC_CPUMODE_UNKNOWN as kernel */
216 default:
217 if (kmod_path__parse(&m, pathname)) {
218 pr_err("Failed to check whether %s is a kernel module or not. Assume it is.",
219 pathname);
220 return true;
221 }
222 }
c00c48fc 223
8dee9ff1 224 return m.kmod;
c00c48fc
NK
225}
226
227bool decompress_to_file(const char *ext, const char *filename, int output_fd)
228{
229 unsigned i;
230
231 for (i = 0; compressions[i].fmt; i++) {
232 if (!strcmp(ext, compressions[i].fmt))
233 return !compressions[i].decompress(filename,
234 output_fd);
235 }
236 return false;
237}
238
239bool dso__needs_decompress(struct dso *dso)
240{
241 return dso->symtab_type == DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE_COMP ||
242 dso->symtab_type == DSO_BINARY_TYPE__GUEST_KMODULE_COMP;
243}
244
3c8a67f5
JO
245/*
246 * Parses kernel module specified in @path and updates
247 * @m argument like:
248 *
249 * @comp - true if @path contains supported compression suffix,
250 * false otherwise
251 * @kmod - true if @path contains '.ko' suffix in right position,
252 * false otherwise
253 * @name - if (@alloc_name && @kmod) is true, it contains strdup-ed base name
254 * of the kernel module without suffixes, otherwise strudup-ed
255 * base name of @path
256 * @ext - if (@alloc_ext && @comp) is true, it contains strdup-ed string
257 * the compression suffix
258 *
259 * Returns 0 if there's no strdup error, -ENOMEM otherwise.
260 */
261int __kmod_path__parse(struct kmod_path *m, const char *path,
262 bool alloc_name, bool alloc_ext)
263{
264 const char *name = strrchr(path, '/');
265 const char *ext = strrchr(path, '.');
1f121b03 266 bool is_simple_name = false;
3c8a67f5
JO
267
268 memset(m, 0x0, sizeof(*m));
269 name = name ? name + 1 : path;
270
1f121b03
WN
271 /*
272 * '.' is also a valid character for module name. For example:
273 * [aaa.bbb] is a valid module name. '[' should have higher
274 * priority than '.ko' suffix.
275 *
276 * The kernel names are from machine__mmap_name. Such
277 * name should belong to kernel itself, not kernel module.
278 */
279 if (name[0] == '[') {
280 is_simple_name = true;
281 if ((strncmp(name, "[kernel.kallsyms]", 17) == 0) ||
282 (strncmp(name, "[guest.kernel.kallsyms", 22) == 0) ||
283 (strncmp(name, "[vdso]", 6) == 0) ||
284 (strncmp(name, "[vsyscall]", 10) == 0)) {
285 m->kmod = false;
286
287 } else
288 m->kmod = true;
289 }
290
3c8a67f5 291 /* No extension, just return name. */
1f121b03 292 if ((ext == NULL) || is_simple_name) {
3c8a67f5
JO
293 if (alloc_name) {
294 m->name = strdup(name);
295 return m->name ? 0 : -ENOMEM;
296 }
297 return 0;
298 }
299
300 if (is_supported_compression(ext + 1)) {
301 m->comp = true;
302 ext -= 3;
303 }
304
305 /* Check .ko extension only if there's enough name left. */
306 if (ext > name)
307 m->kmod = !strncmp(ext, ".ko", 3);
308
309 if (alloc_name) {
310 if (m->kmod) {
311 if (asprintf(&m->name, "[%.*s]", (int) (ext - name), name) == -1)
312 return -ENOMEM;
313 } else {
314 if (asprintf(&m->name, "%s", name) == -1)
315 return -ENOMEM;
316 }
317
318 strxfrchar(m->name, '-', '_');
319 }
320
321 if (alloc_ext && m->comp) {
322 m->ext = strdup(ext + 4);
323 if (!m->ext) {
324 free((void *) m->name);
325 return -ENOMEM;
326 }
327 }
328
329 return 0;
330}
331
eba5102d 332/*
bda6ee4a 333 * Global list of open DSOs and the counter.
eba5102d
JO
334 */
335static LIST_HEAD(dso__data_open);
bda6ee4a 336static long dso__data_open_cnt;
33bdedce 337static pthread_mutex_t dso__data_open_lock = PTHREAD_MUTEX_INITIALIZER;
eba5102d
JO
338
339static void dso__list_add(struct dso *dso)
340{
341 list_add_tail(&dso->data.open_entry, &dso__data_open);
bda6ee4a 342 dso__data_open_cnt++;
eba5102d
JO
343}
344
345static void dso__list_del(struct dso *dso)
346{
347 list_del(&dso->data.open_entry);
bda6ee4a
JO
348 WARN_ONCE(dso__data_open_cnt <= 0,
349 "DSO data fd counter out of bounds.");
350 dso__data_open_cnt--;
eba5102d
JO
351}
352
a08cae03
JO
353static void close_first_dso(void);
354
355static int do_open(char *name)
356{
357 int fd;
6e81c74c 358 char sbuf[STRERR_BUFSIZE];
a08cae03
JO
359
360 do {
361 fd = open(name, O_RDONLY);
362 if (fd >= 0)
363 return fd;
364
a3c0cc2a 365 pr_debug("dso open failed: %s\n",
c8b5f2c9 366 str_error_r(errno, sbuf, sizeof(sbuf)));
a08cae03
JO
367 if (!dso__data_open_cnt || errno != EMFILE)
368 break;
369
370 close_first_dso();
371 } while (1);
372
373 return -1;
374}
375
eba5102d 376static int __open_dso(struct dso *dso, struct machine *machine)
cdd059d7 377{
cdd059d7 378 int fd;
ee4e9625
ACM
379 char *root_dir = (char *)"";
380 char *name = malloc(PATH_MAX);
cdd059d7 381
cdd059d7
JO
382 if (!name)
383 return -ENOMEM;
384
385 if (machine)
386 root_dir = machine->root_dir;
387
5f70619d 388 if (dso__read_binary_type_filename(dso, dso->binary_type,
ee4e9625 389 root_dir, name, PATH_MAX)) {
cdd059d7
JO
390 free(name);
391 return -EINVAL;
392 }
393
3c028a0c
JO
394 if (!is_regular_file(name))
395 return -EINVAL;
396
a08cae03 397 fd = do_open(name);
cdd059d7
JO
398 free(name);
399 return fd;
400}
401
c6580451
JO
402static void check_data_close(void);
403
c1f9aa0a
JO
404/**
405 * dso_close - Open DSO data file
406 * @dso: dso object
407 *
408 * Open @dso's data file descriptor and updates
409 * list/count of open DSO objects.
410 */
eba5102d
JO
411static int open_dso(struct dso *dso, struct machine *machine)
412{
413 int fd = __open_dso(dso, machine);
414
a6f6ae99 415 if (fd >= 0) {
eba5102d 416 dso__list_add(dso);
c6580451
JO
417 /*
418 * Check if we crossed the allowed number
419 * of opened DSOs and close one if needed.
420 */
421 check_data_close();
422 }
eba5102d
JO
423
424 return fd;
425}
426
427static void close_data_fd(struct dso *dso)
53fa8eaa
JO
428{
429 if (dso->data.fd >= 0) {
430 close(dso->data.fd);
431 dso->data.fd = -1;
c3fbd2a6 432 dso->data.file_size = 0;
eba5102d 433 dso__list_del(dso);
53fa8eaa
JO
434 }
435}
436
c1f9aa0a
JO
437/**
438 * dso_close - Close DSO data file
439 * @dso: dso object
440 *
441 * Close @dso's data file descriptor and updates
442 * list/count of open DSO objects.
443 */
eba5102d
JO
444static void close_dso(struct dso *dso)
445{
446 close_data_fd(dso);
447}
448
c6580451
JO
449static void close_first_dso(void)
450{
451 struct dso *dso;
452
453 dso = list_first_entry(&dso__data_open, struct dso, data.open_entry);
454 close_dso(dso);
455}
456
457static rlim_t get_fd_limit(void)
458{
459 struct rlimit l;
460 rlim_t limit = 0;
461
462 /* Allow half of the current open fd limit. */
463 if (getrlimit(RLIMIT_NOFILE, &l) == 0) {
464 if (l.rlim_cur == RLIM_INFINITY)
465 limit = l.rlim_cur;
466 else
467 limit = l.rlim_cur / 2;
468 } else {
469 pr_err("failed to get fd limit\n");
470 limit = 1;
471 }
472
473 return limit;
474}
475
f3069249
JO
476static rlim_t fd_limit;
477
478/*
479 * Used only by tests/dso-data.c to reset the environment
480 * for tests. I dont expect we should change this during
481 * standard runtime.
482 */
483void reset_fd_limit(void)
c6580451 484{
f3069249
JO
485 fd_limit = 0;
486}
c6580451 487
f3069249
JO
488static bool may_cache_fd(void)
489{
490 if (!fd_limit)
491 fd_limit = get_fd_limit();
c6580451 492
f3069249 493 if (fd_limit == RLIM_INFINITY)
c6580451
JO
494 return true;
495
f3069249 496 return fd_limit > (rlim_t) dso__data_open_cnt;
c6580451
JO
497}
498
c1f9aa0a
JO
499/*
500 * Check and close LRU dso if we crossed allowed limit
501 * for opened dso file descriptors. The limit is half
502 * of the RLIMIT_NOFILE files opened.
503*/
c6580451
JO
504static void check_data_close(void)
505{
506 bool cache_fd = may_cache_fd();
507
508 if (!cache_fd)
509 close_first_dso();
510}
511
c1f9aa0a
JO
512/**
513 * dso__data_close - Close DSO data file
514 * @dso: dso object
515 *
516 * External interface to close @dso's data file descriptor.
517 */
eba5102d
JO
518void dso__data_close(struct dso *dso)
519{
33bdedce 520 pthread_mutex_lock(&dso__data_open_lock);
eba5102d 521 close_dso(dso);
33bdedce 522 pthread_mutex_unlock(&dso__data_open_lock);
eba5102d
JO
523}
524
71ff824a 525static void try_to_open_dso(struct dso *dso, struct machine *machine)
cdd059d7 526{
631d34b5 527 enum dso_binary_type binary_type_data[] = {
cdd059d7
JO
528 DSO_BINARY_TYPE__BUILD_ID_CACHE,
529 DSO_BINARY_TYPE__SYSTEM_PATH_DSO,
530 DSO_BINARY_TYPE__NOT_FOUND,
531 };
532 int i = 0;
533
53fa8eaa 534 if (dso->data.fd >= 0)
71ff824a 535 return;
53fa8eaa
JO
536
537 if (dso->binary_type != DSO_BINARY_TYPE__NOT_FOUND) {
538 dso->data.fd = open_dso(dso, machine);
c27697d6 539 goto out;
53fa8eaa 540 }
cdd059d7
JO
541
542 do {
5f70619d 543 dso->binary_type = binary_type_data[i++];
cdd059d7 544
c27697d6
AH
545 dso->data.fd = open_dso(dso, machine);
546 if (dso->data.fd >= 0)
547 goto out;
cdd059d7 548
5f70619d 549 } while (dso->binary_type != DSO_BINARY_TYPE__NOT_FOUND);
c27697d6
AH
550out:
551 if (dso->data.fd >= 0)
552 dso->data.status = DSO_DATA_STATUS_OK;
553 else
554 dso->data.status = DSO_DATA_STATUS_ERROR;
71ff824a
NK
555}
556
557/**
4bb11d01 558 * dso__data_get_fd - Get dso's data file descriptor
71ff824a
NK
559 * @dso: dso object
560 * @machine: machine object
561 *
562 * External interface to find dso's file, open it and
4bb11d01
NK
563 * returns file descriptor. It should be paired with
564 * dso__data_put_fd() if it returns non-negative value.
71ff824a 565 */
4bb11d01 566int dso__data_get_fd(struct dso *dso, struct machine *machine)
71ff824a
NK
567{
568 if (dso->data.status == DSO_DATA_STATUS_ERROR)
569 return -1;
cdd059d7 570
4bb11d01
NK
571 if (pthread_mutex_lock(&dso__data_open_lock) < 0)
572 return -1;
573
71ff824a 574 try_to_open_dso(dso, machine);
4bb11d01
NK
575
576 if (dso->data.fd < 0)
577 pthread_mutex_unlock(&dso__data_open_lock);
71ff824a 578
c27697d6 579 return dso->data.fd;
cdd059d7
JO
580}
581
4bb11d01
NK
582void dso__data_put_fd(struct dso *dso __maybe_unused)
583{
584 pthread_mutex_unlock(&dso__data_open_lock);
585}
586
288be943
AH
587bool dso__data_status_seen(struct dso *dso, enum dso_data_status_seen by)
588{
589 u32 flag = 1 << by;
590
591 if (dso->data.status_seen & flag)
592 return true;
593
594 dso->data.status_seen |= flag;
595
596 return false;
597}
598
cdd059d7 599static void
8e67b725 600dso_cache__free(struct dso *dso)
cdd059d7 601{
8e67b725 602 struct rb_root *root = &dso->data.cache;
cdd059d7
JO
603 struct rb_node *next = rb_first(root);
604
8e67b725 605 pthread_mutex_lock(&dso->lock);
cdd059d7
JO
606 while (next) {
607 struct dso_cache *cache;
608
609 cache = rb_entry(next, struct dso_cache, rb_node);
610 next = rb_next(&cache->rb_node);
611 rb_erase(&cache->rb_node, root);
612 free(cache);
613 }
8e67b725 614 pthread_mutex_unlock(&dso->lock);
cdd059d7
JO
615}
616
8e67b725 617static struct dso_cache *dso_cache__find(struct dso *dso, u64 offset)
cdd059d7 618{
8e67b725 619 const struct rb_root *root = &dso->data.cache;
3344996e
ACM
620 struct rb_node * const *p = &root->rb_node;
621 const struct rb_node *parent = NULL;
cdd059d7
JO
622 struct dso_cache *cache;
623
624 while (*p != NULL) {
625 u64 end;
626
627 parent = *p;
628 cache = rb_entry(parent, struct dso_cache, rb_node);
629 end = cache->offset + DSO__DATA_CACHE_SIZE;
630
631 if (offset < cache->offset)
632 p = &(*p)->rb_left;
633 else if (offset >= end)
634 p = &(*p)->rb_right;
635 else
636 return cache;
637 }
8e67b725 638
cdd059d7
JO
639 return NULL;
640}
641
8e67b725
NK
642static struct dso_cache *
643dso_cache__insert(struct dso *dso, struct dso_cache *new)
cdd059d7 644{
8e67b725 645 struct rb_root *root = &dso->data.cache;
cdd059d7
JO
646 struct rb_node **p = &root->rb_node;
647 struct rb_node *parent = NULL;
648 struct dso_cache *cache;
649 u64 offset = new->offset;
650
8e67b725 651 pthread_mutex_lock(&dso->lock);
cdd059d7
JO
652 while (*p != NULL) {
653 u64 end;
654
655 parent = *p;
656 cache = rb_entry(parent, struct dso_cache, rb_node);
657 end = cache->offset + DSO__DATA_CACHE_SIZE;
658
659 if (offset < cache->offset)
660 p = &(*p)->rb_left;
661 else if (offset >= end)
662 p = &(*p)->rb_right;
8e67b725
NK
663 else
664 goto out;
cdd059d7
JO
665 }
666
667 rb_link_node(&new->rb_node, parent, p);
668 rb_insert_color(&new->rb_node, root);
8e67b725
NK
669
670 cache = NULL;
671out:
672 pthread_mutex_unlock(&dso->lock);
673 return cache;
cdd059d7
JO
674}
675
676static ssize_t
677dso_cache__memcpy(struct dso_cache *cache, u64 offset,
678 u8 *data, u64 size)
679{
680 u64 cache_offset = offset - cache->offset;
681 u64 cache_size = min(cache->size - cache_offset, size);
682
683 memcpy(data, cache->data + cache_offset, cache_size);
684 return cache_size;
685}
686
687static ssize_t
33bdedce
NK
688dso_cache__read(struct dso *dso, struct machine *machine,
689 u64 offset, u8 *data, ssize_t size)
cdd059d7
JO
690{
691 struct dso_cache *cache;
8e67b725 692 struct dso_cache *old;
cdd059d7 693 ssize_t ret;
cdd059d7
JO
694
695 do {
696 u64 cache_offset;
697
cdd059d7
JO
698 cache = zalloc(sizeof(*cache) + DSO__DATA_CACHE_SIZE);
699 if (!cache)
33bdedce
NK
700 return -ENOMEM;
701
702 pthread_mutex_lock(&dso__data_open_lock);
703
704 /*
705 * dso->data.fd might be closed if other thread opened another
706 * file (dso) due to open file limit (RLIMIT_NOFILE).
707 */
71ff824a
NK
708 try_to_open_dso(dso, machine);
709
33bdedce 710 if (dso->data.fd < 0) {
71ff824a
NK
711 ret = -errno;
712 dso->data.status = DSO_DATA_STATUS_ERROR;
713 break;
33bdedce 714 }
cdd059d7
JO
715
716 cache_offset = offset & DSO__DATA_CACHE_MASK;
cdd059d7 717
c52686f9 718 ret = pread(dso->data.fd, cache->data, DSO__DATA_CACHE_SIZE, cache_offset);
cdd059d7
JO
719 if (ret <= 0)
720 break;
721
722 cache->offset = cache_offset;
723 cache->size = ret;
33bdedce
NK
724 } while (0);
725
726 pthread_mutex_unlock(&dso__data_open_lock);
727
728 if (ret > 0) {
8e67b725
NK
729 old = dso_cache__insert(dso, cache);
730 if (old) {
731 /* we lose the race */
732 free(cache);
733 cache = old;
734 }
cdd059d7
JO
735
736 ret = dso_cache__memcpy(cache, offset, data, size);
33bdedce 737 }
cdd059d7
JO
738
739 if (ret <= 0)
740 free(cache);
741
cdd059d7
JO
742 return ret;
743}
744
33bdedce
NK
745static ssize_t dso_cache_read(struct dso *dso, struct machine *machine,
746 u64 offset, u8 *data, ssize_t size)
cdd059d7
JO
747{
748 struct dso_cache *cache;
749
8e67b725 750 cache = dso_cache__find(dso, offset);
cdd059d7
JO
751 if (cache)
752 return dso_cache__memcpy(cache, offset, data, size);
753 else
33bdedce 754 return dso_cache__read(dso, machine, offset, data, size);
cdd059d7
JO
755}
756
c1f9aa0a
JO
757/*
758 * Reads and caches dso data DSO__DATA_CACHE_SIZE size chunks
759 * in the rb_tree. Any read to already cached data is served
760 * by cached data.
761 */
33bdedce
NK
762static ssize_t cached_read(struct dso *dso, struct machine *machine,
763 u64 offset, u8 *data, ssize_t size)
cdd059d7
JO
764{
765 ssize_t r = 0;
766 u8 *p = data;
767
768 do {
769 ssize_t ret;
770
33bdedce 771 ret = dso_cache_read(dso, machine, offset, p, size);
cdd059d7
JO
772 if (ret < 0)
773 return ret;
774
775 /* Reached EOF, return what we have. */
776 if (!ret)
777 break;
778
779 BUG_ON(ret > size);
780
781 r += ret;
782 p += ret;
783 offset += ret;
784 size -= ret;
785
786 } while (size);
787
788 return r;
789}
790
33bdedce 791static int data_file_size(struct dso *dso, struct machine *machine)
c3fbd2a6 792{
33bdedce 793 int ret = 0;
c3fbd2a6 794 struct stat st;
6e81c74c 795 char sbuf[STRERR_BUFSIZE];
c3fbd2a6 796
33bdedce
NK
797 if (dso->data.file_size)
798 return 0;
799
71ff824a
NK
800 if (dso->data.status == DSO_DATA_STATUS_ERROR)
801 return -1;
802
33bdedce
NK
803 pthread_mutex_lock(&dso__data_open_lock);
804
805 /*
806 * dso->data.fd might be closed if other thread opened another
807 * file (dso) due to open file limit (RLIMIT_NOFILE).
808 */
71ff824a
NK
809 try_to_open_dso(dso, machine);
810
33bdedce 811 if (dso->data.fd < 0) {
71ff824a
NK
812 ret = -errno;
813 dso->data.status = DSO_DATA_STATUS_ERROR;
814 goto out;
c3fbd2a6
JO
815 }
816
33bdedce
NK
817 if (fstat(dso->data.fd, &st) < 0) {
818 ret = -errno;
819 pr_err("dso cache fstat failed: %s\n",
c8b5f2c9 820 str_error_r(errno, sbuf, sizeof(sbuf)));
33bdedce
NK
821 dso->data.status = DSO_DATA_STATUS_ERROR;
822 goto out;
823 }
824 dso->data.file_size = st.st_size;
825
826out:
827 pthread_mutex_unlock(&dso__data_open_lock);
828 return ret;
c3fbd2a6
JO
829}
830
6d363459
AH
831/**
832 * dso__data_size - Return dso data size
833 * @dso: dso object
834 * @machine: machine object
835 *
836 * Return: dso data size
837 */
838off_t dso__data_size(struct dso *dso, struct machine *machine)
839{
33bdedce 840 if (data_file_size(dso, machine))
6d363459
AH
841 return -1;
842
843 /* For now just estimate dso data size is close to file size */
844 return dso->data.file_size;
845}
846
33bdedce
NK
847static ssize_t data_read_offset(struct dso *dso, struct machine *machine,
848 u64 offset, u8 *data, ssize_t size)
c3fbd2a6 849{
33bdedce 850 if (data_file_size(dso, machine))
c3fbd2a6
JO
851 return -1;
852
853 /* Check the offset sanity. */
854 if (offset > dso->data.file_size)
855 return -1;
856
857 if (offset + size < offset)
858 return -1;
859
33bdedce 860 return cached_read(dso, machine, offset, data, size);
c3fbd2a6
JO
861}
862
c1f9aa0a
JO
863/**
864 * dso__data_read_offset - Read data from dso file offset
865 * @dso: dso object
866 * @machine: machine object
867 * @offset: file offset
868 * @data: buffer to store data
869 * @size: size of the @data buffer
870 *
871 * External interface to read data from dso file offset. Open
872 * dso data file and use cached_read to get the data.
873 */
c3fbd2a6
JO
874ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine,
875 u64 offset, u8 *data, ssize_t size)
876{
33bdedce 877 if (dso->data.status == DSO_DATA_STATUS_ERROR)
c3fbd2a6
JO
878 return -1;
879
33bdedce 880 return data_read_offset(dso, machine, offset, data, size);
c3fbd2a6
JO
881}
882
c1f9aa0a
JO
883/**
884 * dso__data_read_addr - Read data from dso address
885 * @dso: dso object
886 * @machine: machine object
887 * @add: virtual memory address
888 * @data: buffer to store data
889 * @size: size of the @data buffer
890 *
891 * External interface to read data from dso address.
892 */
cdd059d7
JO
893ssize_t dso__data_read_addr(struct dso *dso, struct map *map,
894 struct machine *machine, u64 addr,
895 u8 *data, ssize_t size)
896{
897 u64 offset = map->map_ip(map, addr);
898 return dso__data_read_offset(dso, machine, offset, data, size);
899}
900
901struct map *dso__new_map(const char *name)
902{
903 struct map *map = NULL;
904 struct dso *dso = dso__new(name);
905
906 if (dso)
907 map = map__new2(0, dso, MAP__FUNCTION);
908
909 return map;
910}
911
459ce518
ACM
912struct dso *machine__findnew_kernel(struct machine *machine, const char *name,
913 const char *short_name, int dso_type)
cdd059d7
JO
914{
915 /*
916 * The kernel dso could be created by build_id processing.
917 */
aa7cc2ae 918 struct dso *dso = machine__findnew_dso(machine, name);
cdd059d7
JO
919
920 /*
921 * We need to run this in all cases, since during the build_id
922 * processing we had no idea this was the kernel dso.
923 */
924 if (dso != NULL) {
58a98c9c 925 dso__set_short_name(dso, short_name, false);
cdd059d7
JO
926 dso->kernel = dso_type;
927 }
928
929 return dso;
930}
931
4598a0a6
WL
932/*
933 * Find a matching entry and/or link current entry to RB tree.
934 * Either one of the dso or name parameter must be non-NULL or the
935 * function will not work.
936 */
e8807844
ACM
937static struct dso *__dso__findlink_by_longname(struct rb_root *root,
938 struct dso *dso, const char *name)
4598a0a6
WL
939{
940 struct rb_node **p = &root->rb_node;
941 struct rb_node *parent = NULL;
942
943 if (!name)
944 name = dso->long_name;
945 /*
946 * Find node with the matching name
947 */
948 while (*p) {
949 struct dso *this = rb_entry(*p, struct dso, rb_node);
950 int rc = strcmp(name, this->long_name);
951
952 parent = *p;
953 if (rc == 0) {
954 /*
955 * In case the new DSO is a duplicate of an existing
0f5e1558 956 * one, print a one-time warning & put the new entry
4598a0a6
WL
957 * at the end of the list of duplicates.
958 */
959 if (!dso || (dso == this))
960 return this; /* Find matching dso */
961 /*
962 * The core kernel DSOs may have duplicated long name.
963 * In this case, the short name should be different.
964 * Comparing the short names to differentiate the DSOs.
965 */
966 rc = strcmp(dso->short_name, this->short_name);
967 if (rc == 0) {
968 pr_err("Duplicated dso name: %s\n", name);
969 return NULL;
970 }
971 }
972 if (rc < 0)
973 p = &parent->rb_left;
974 else
975 p = &parent->rb_right;
976 }
977 if (dso) {
978 /* Add new node and rebalance tree */
979 rb_link_node(&dso->rb_node, parent, p);
980 rb_insert_color(&dso->rb_node, root);
e266a753 981 dso->root = root;
4598a0a6
WL
982 }
983 return NULL;
984}
985
e8807844
ACM
986static inline struct dso *__dso__find_by_longname(struct rb_root *root,
987 const char *name)
4598a0a6 988{
e8807844 989 return __dso__findlink_by_longname(root, NULL, name);
4598a0a6
WL
990}
991
bf4414ae 992void dso__set_long_name(struct dso *dso, const char *name, bool name_allocated)
cdd059d7 993{
e266a753
AH
994 struct rb_root *root = dso->root;
995
cdd059d7
JO
996 if (name == NULL)
997 return;
7e155d4d
ACM
998
999 if (dso->long_name_allocated)
bf4414ae 1000 free((char *)dso->long_name);
7e155d4d 1001
e266a753
AH
1002 if (root) {
1003 rb_erase(&dso->rb_node, root);
1004 /*
1005 * __dso__findlink_by_longname() isn't guaranteed to add it
1006 * back, so a clean removal is required here.
1007 */
1008 RB_CLEAR_NODE(&dso->rb_node);
1009 dso->root = NULL;
1010 }
1011
7e155d4d
ACM
1012 dso->long_name = name;
1013 dso->long_name_len = strlen(name);
1014 dso->long_name_allocated = name_allocated;
e266a753
AH
1015
1016 if (root)
1017 __dso__findlink_by_longname(root, dso, NULL);
cdd059d7
JO
1018}
1019
58a98c9c 1020void dso__set_short_name(struct dso *dso, const char *name, bool name_allocated)
cdd059d7
JO
1021{
1022 if (name == NULL)
1023 return;
58a98c9c
AH
1024
1025 if (dso->short_name_allocated)
1026 free((char *)dso->short_name);
1027
1028 dso->short_name = name;
1029 dso->short_name_len = strlen(name);
1030 dso->short_name_allocated = name_allocated;
cdd059d7
JO
1031}
1032
1033static void dso__set_basename(struct dso *dso)
1034{
ac5e7f84
SE
1035 /*
1036 * basename() may modify path buffer, so we must pass
1037 * a copy.
1038 */
1039 char *base, *lname = strdup(dso->long_name);
1040
1041 if (!lname)
1042 return;
1043
1044 /*
1045 * basename() may return a pointer to internal
1046 * storage which is reused in subsequent calls
1047 * so copy the result.
1048 */
1049 base = strdup(basename(lname));
1050
1051 free(lname);
1052
1053 if (!base)
1054 return;
1055
1056 dso__set_short_name(dso, base, true);
cdd059d7
JO
1057}
1058
1059int dso__name_len(const struct dso *dso)
1060{
1061 if (!dso)
1062 return strlen("[unknown]");
bb963e16 1063 if (verbose > 0)
cdd059d7
JO
1064 return dso->long_name_len;
1065
1066 return dso->short_name_len;
1067}
1068
1069bool dso__loaded(const struct dso *dso, enum map_type type)
1070{
1071 return dso->loaded & (1 << type);
1072}
1073
1074bool dso__sorted_by_name(const struct dso *dso, enum map_type type)
1075{
1076 return dso->sorted_by_name & (1 << type);
1077}
1078
1079void dso__set_sorted_by_name(struct dso *dso, enum map_type type)
1080{
1081 dso->sorted_by_name |= (1 << type);
1082}
1083
1084struct dso *dso__new(const char *name)
1085{
1086 struct dso *dso = calloc(1, sizeof(*dso) + strlen(name) + 1);
1087
1088 if (dso != NULL) {
1089 int i;
1090 strcpy(dso->name, name);
7e155d4d 1091 dso__set_long_name(dso, dso->name, false);
58a98c9c 1092 dso__set_short_name(dso, dso->name, false);
cdd059d7
JO
1093 for (i = 0; i < MAP__NR_TYPES; ++i)
1094 dso->symbols[i] = dso->symbol_names[i] = RB_ROOT;
ca40e2af 1095 dso->data.cache = RB_ROOT;
53fa8eaa 1096 dso->data.fd = -1;
c27697d6 1097 dso->data.status = DSO_DATA_STATUS_UNKNOWN;
cdd059d7 1098 dso->symtab_type = DSO_BINARY_TYPE__NOT_FOUND;
5f70619d 1099 dso->binary_type = DSO_BINARY_TYPE__NOT_FOUND;
c6d8f2a4 1100 dso->is_64_bit = (sizeof(void *) == 8);
cdd059d7 1101 dso->loaded = 0;
0131c4ec 1102 dso->rel = 0;
cdd059d7
JO
1103 dso->sorted_by_name = 0;
1104 dso->has_build_id = 0;
2cc9d0ef 1105 dso->has_srcline = 1;
906049c8 1106 dso->a2l_fails = 1;
cdd059d7
JO
1107 dso->kernel = DSO_TYPE_USER;
1108 dso->needs_swap = DSO_SWAP__UNSET;
4598a0a6 1109 RB_CLEAR_NODE(&dso->rb_node);
e266a753 1110 dso->root = NULL;
cdd059d7 1111 INIT_LIST_HEAD(&dso->node);
eba5102d 1112 INIT_LIST_HEAD(&dso->data.open_entry);
4a936edc 1113 pthread_mutex_init(&dso->lock, NULL);
7100810a 1114 refcount_set(&dso->refcnt, 1);
cdd059d7
JO
1115 }
1116
1117 return dso;
1118}
1119
1120void dso__delete(struct dso *dso)
1121{
1122 int i;
4598a0a6
WL
1123
1124 if (!RB_EMPTY_NODE(&dso->rb_node))
1125 pr_err("DSO %s is still in rbtree when being deleted!\n",
1126 dso->long_name);
cdd059d7
JO
1127 for (i = 0; i < MAP__NR_TYPES; ++i)
1128 symbols__delete(&dso->symbols[i]);
ee021d42
ACM
1129
1130 if (dso->short_name_allocated) {
04662523 1131 zfree((char **)&dso->short_name);
ee021d42
ACM
1132 dso->short_name_allocated = false;
1133 }
1134
1135 if (dso->long_name_allocated) {
04662523 1136 zfree((char **)&dso->long_name);
ee021d42
ACM
1137 dso->long_name_allocated = false;
1138 }
1139
53fa8eaa 1140 dso__data_close(dso);
cfe9174f 1141 auxtrace_cache__free(dso->auxtrace_cache);
8e67b725 1142 dso_cache__free(dso);
454ff00f 1143 dso__free_a2l(dso);
04662523 1144 zfree(&dso->symsrc_filename);
4a936edc 1145 pthread_mutex_destroy(&dso->lock);
cdd059d7
JO
1146 free(dso);
1147}
1148
d3a7c489
ACM
1149struct dso *dso__get(struct dso *dso)
1150{
1151 if (dso)
7100810a 1152 refcount_inc(&dso->refcnt);
d3a7c489
ACM
1153 return dso;
1154}
1155
1156void dso__put(struct dso *dso)
1157{
7100810a 1158 if (dso && refcount_dec_and_test(&dso->refcnt))
d3a7c489
ACM
1159 dso__delete(dso);
1160}
1161
cdd059d7
JO
1162void dso__set_build_id(struct dso *dso, void *build_id)
1163{
1164 memcpy(dso->build_id, build_id, sizeof(dso->build_id));
1165 dso->has_build_id = 1;
1166}
1167
1168bool dso__build_id_equal(const struct dso *dso, u8 *build_id)
1169{
1170 return memcmp(dso->build_id, build_id, sizeof(dso->build_id)) == 0;
1171}
1172
1173void dso__read_running_kernel_build_id(struct dso *dso, struct machine *machine)
1174{
1175 char path[PATH_MAX];
1176
1177 if (machine__is_default_guest(machine))
1178 return;
1179 sprintf(path, "%s/sys/kernel/notes", machine->root_dir);
1180 if (sysfs__read_build_id(path, dso->build_id,
1181 sizeof(dso->build_id)) == 0)
1182 dso->has_build_id = true;
1183}
1184
1185int dso__kernel_module_get_build_id(struct dso *dso,
1186 const char *root_dir)
1187{
1188 char filename[PATH_MAX];
1189 /*
1190 * kernel module short names are of the form "[module]" and
1191 * we need just "module" here.
1192 */
1193 const char *name = dso->short_name + 1;
1194
1195 snprintf(filename, sizeof(filename),
1196 "%s/sys/module/%.*s/notes/.note.gnu.build-id",
1197 root_dir, (int)strlen(name) - 1, name);
1198
1199 if (sysfs__read_build_id(filename, dso->build_id,
1200 sizeof(dso->build_id)) == 0)
1201 dso->has_build_id = true;
1202
1203 return 0;
1204}
1205
1206bool __dsos__read_build_ids(struct list_head *head, bool with_hits)
1207{
1208 bool have_build_id = false;
1209 struct dso *pos;
1210
1211 list_for_each_entry(pos, head, node) {
6ae98ba6 1212 if (with_hits && !pos->hit && !dso__is_vdso(pos))
cdd059d7
JO
1213 continue;
1214 if (pos->has_build_id) {
1215 have_build_id = true;
1216 continue;
1217 }
1218 if (filename__read_build_id(pos->long_name, pos->build_id,
1219 sizeof(pos->build_id)) > 0) {
1220 have_build_id = true;
1221 pos->has_build_id = true;
1222 }
1223 }
1224
1225 return have_build_id;
1226}
1227
e8807844 1228void __dsos__add(struct dsos *dsos, struct dso *dso)
cdd059d7 1229{
8fa7d87f 1230 list_add_tail(&dso->node, &dsos->head);
e8807844 1231 __dso__findlink_by_longname(&dsos->root, dso, NULL);
d3a7c489
ACM
1232 /*
1233 * It is now in the linked list, grab a reference, then garbage collect
1234 * this when needing memory, by looking at LRU dso instances in the
1235 * list with atomic_read(&dso->refcnt) == 1, i.e. no references
1236 * anywhere besides the one for the list, do, under a lock for the
1237 * list: remove it from the list, then a dso__put(), that probably will
1238 * be the last and will then call dso__delete(), end of life.
1239 *
1240 * That, or at the end of the 'struct machine' lifetime, when all
1241 * 'struct dso' instances will be removed from the list, in
1242 * dsos__exit(), if they have no other reference from some other data
1243 * structure.
1244 *
1245 * E.g.: after processing a 'perf.data' file and storing references
1246 * to objects instantiated while processing events, we will have
1247 * references to the 'thread', 'map', 'dso' structs all from 'struct
1248 * hist_entry' instances, but we may not need anything not referenced,
1249 * so we might as well call machines__exit()/machines__delete() and
1250 * garbage collect it.
1251 */
1252 dso__get(dso);
e8807844
ACM
1253}
1254
1255void dsos__add(struct dsos *dsos, struct dso *dso)
1256{
1257 pthread_rwlock_wrlock(&dsos->lock);
1258 __dsos__add(dsos, dso);
1259 pthread_rwlock_unlock(&dsos->lock);
cdd059d7
JO
1260}
1261
e8807844 1262struct dso *__dsos__find(struct dsos *dsos, const char *name, bool cmp_short)
cdd059d7
JO
1263{
1264 struct dso *pos;
1265
f9ceffb6 1266 if (cmp_short) {
8fa7d87f 1267 list_for_each_entry(pos, &dsos->head, node)
f9ceffb6
WL
1268 if (strcmp(pos->short_name, name) == 0)
1269 return pos;
1270 return NULL;
1271 }
e8807844 1272 return __dso__find_by_longname(&dsos->root, name);
cdd059d7
JO
1273}
1274
e8807844
ACM
1275struct dso *dsos__find(struct dsos *dsos, const char *name, bool cmp_short)
1276{
1277 struct dso *dso;
1278 pthread_rwlock_rdlock(&dsos->lock);
1279 dso = __dsos__find(dsos, name, cmp_short);
1280 pthread_rwlock_unlock(&dsos->lock);
1281 return dso;
1282}
1283
1284struct dso *__dsos__addnew(struct dsos *dsos, const char *name)
cdd059d7 1285{
701d8d7f 1286 struct dso *dso = dso__new(name);
cdd059d7 1287
701d8d7f 1288 if (dso != NULL) {
e8807844 1289 __dsos__add(dsos, dso);
701d8d7f 1290 dso__set_basename(dso);
82de26ab
MH
1291 /* Put dso here because __dsos_add already got it */
1292 dso__put(dso);
cdd059d7 1293 }
cdd059d7
JO
1294 return dso;
1295}
1296
701d8d7f
JO
1297struct dso *__dsos__findnew(struct dsos *dsos, const char *name)
1298{
e8807844
ACM
1299 struct dso *dso = __dsos__find(dsos, name, false);
1300
1301 return dso ? dso : __dsos__addnew(dsos, name);
1302}
701d8d7f 1303
e8807844
ACM
1304struct dso *dsos__findnew(struct dsos *dsos, const char *name)
1305{
1306 struct dso *dso;
1307 pthread_rwlock_wrlock(&dsos->lock);
d3a7c489 1308 dso = dso__get(__dsos__findnew(dsos, name));
e8807844
ACM
1309 pthread_rwlock_unlock(&dsos->lock);
1310 return dso;
701d8d7f
JO
1311}
1312
cdd059d7 1313size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp,
417c2ff6 1314 bool (skip)(struct dso *dso, int parm), int parm)
cdd059d7
JO
1315{
1316 struct dso *pos;
1317 size_t ret = 0;
1318
1319 list_for_each_entry(pos, head, node) {
417c2ff6 1320 if (skip && skip(pos, parm))
cdd059d7
JO
1321 continue;
1322 ret += dso__fprintf_buildid(pos, fp);
1323 ret += fprintf(fp, " %s\n", pos->long_name);
1324 }
1325 return ret;
1326}
1327
1328size_t __dsos__fprintf(struct list_head *head, FILE *fp)
1329{
1330 struct dso *pos;
1331 size_t ret = 0;
1332
1333 list_for_each_entry(pos, head, node) {
1334 int i;
1335 for (i = 0; i < MAP__NR_TYPES; ++i)
1336 ret += dso__fprintf(pos, i, fp);
1337 }
1338
1339 return ret;
1340}
1341
1342size_t dso__fprintf_buildid(struct dso *dso, FILE *fp)
1343{
b5d8bbe8 1344 char sbuild_id[SBUILD_ID_SIZE];
cdd059d7
JO
1345
1346 build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
1347 return fprintf(fp, "%s", sbuild_id);
1348}
1349
1350size_t dso__fprintf(struct dso *dso, enum map_type type, FILE *fp)
1351{
1352 struct rb_node *nd;
1353 size_t ret = fprintf(fp, "dso: %s (", dso->short_name);
1354
1355 if (dso->short_name != dso->long_name)
1356 ret += fprintf(fp, "%s, ", dso->long_name);
1357 ret += fprintf(fp, "%s, %sloaded, ", map_type__name[type],
919d590f 1358 dso__loaded(dso, type) ? "" : "NOT ");
cdd059d7
JO
1359 ret += dso__fprintf_buildid(dso, fp);
1360 ret += fprintf(fp, ")\n");
1361 for (nd = rb_first(&dso->symbols[type]); nd; nd = rb_next(nd)) {
1362 struct symbol *pos = rb_entry(nd, struct symbol, rb_node);
1363 ret += symbol__fprintf(pos, fp);
1364 }
1365
1366 return ret;
1367}
2b5b8bb2
AH
1368
1369enum dso_type dso__type(struct dso *dso, struct machine *machine)
1370{
1371 int fd;
4bb11d01 1372 enum dso_type type = DSO__TYPE_UNKNOWN;
2b5b8bb2 1373
4bb11d01
NK
1374 fd = dso__data_get_fd(dso, machine);
1375 if (fd >= 0) {
1376 type = dso__type_fd(fd);
1377 dso__data_put_fd(dso);
1378 }
2b5b8bb2 1379
4bb11d01 1380 return type;
2b5b8bb2 1381}
18425f13
ACM
1382
1383int dso__strerror_load(struct dso *dso, char *buf, size_t buflen)
1384{
1385 int idx, errnum = dso->load_errno;
1386 /*
1387 * This must have a same ordering as the enum dso_load_errno.
1388 */
1389 static const char *dso_load__error_str[] = {
1390 "Internal tools/perf/ library error",
1391 "Invalid ELF file",
1392 "Can not read build id",
1393 "Mismatching build id",
1394 "Decompression failure",
1395 };
1396
1397 BUG_ON(buflen == 0);
1398
1399 if (errnum >= 0) {
c8b5f2c9 1400 const char *err = str_error_r(errnum, buf, buflen);
18425f13
ACM
1401
1402 if (err != buf)
1403 scnprintf(buf, buflen, "%s", err);
1404
1405 return 0;
1406 }
1407
1408 if (errnum < __DSO_LOAD_ERRNO__START || errnum >= __DSO_LOAD_ERRNO__END)
1409 return -1;
1410
1411 idx = errnum - __DSO_LOAD_ERRNO__START;
1412 scnprintf(buf, buflen, "%s", dso_load__error_str[idx]);
1413 return 0;
1414}