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