1 #include "symbol.h"
2 #include "dso.h"
3 #include "machine.h"
4 #include "util.h"
5 #include "debug.h"
6 
dso__symtab_origin(const struct dso * dso)7 char 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 
dso__binary_type_file(struct dso * dso,enum dso_binary_type type,char * root_dir,char * file,size_t size)30 int 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 
open_dso(struct dso * dso,struct machine * machine)115 static 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 
dso__data_fd(struct dso * dso,struct machine * machine)139 int 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 
165 static void
dso_cache__free(struct rb_root * root)166 dso_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 
180 static struct dso_cache*
dso_cache__find(struct rb_root * root,u64 offset)181 dso_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 
204 static void
dso_cache__insert(struct rb_root * root,struct dso_cache * new)205 dso_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 
229 static ssize_t
dso_cache__memcpy(struct dso_cache * cache,u64 offset,u8 * data,u64 size)230 dso_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 
240 static ssize_t
dso_cache__read(struct dso * dso,struct machine * machine,u64 offset,u8 * data,ssize_t size)241 dso_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 
dso_cache_read(struct dso * dso,struct machine * machine,u64 offset,u8 * data,ssize_t size)286 static 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 
dso__data_read_offset(struct dso * dso,struct machine * machine,u64 offset,u8 * data,ssize_t size)298 ssize_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 
dso__data_read_addr(struct dso * dso,struct map * map,struct machine * machine,u64 addr,u8 * data,ssize_t size)327 ssize_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 
dso__new_map(const char * name)335 struct 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 
dso__kernel_findnew(struct machine * machine,const char * name,const char * short_name,int dso_type)346 struct 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 
dso__set_long_name(struct dso * dso,char * name)366 void 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 
dso__set_short_name(struct dso * dso,const char * name)374 void 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 
dso__set_basename(struct dso * dso)382 static void dso__set_basename(struct dso *dso)
383 {
384 	dso__set_short_name(dso, basename(dso->long_name));
385 }
386 
dso__name_len(const struct dso * dso)387 int dso__name_len(const struct dso *dso)
388 {
389 	if (!dso)
390 		return strlen("[unknown]");
391 	if (verbose)
392 		return dso->long_name_len;
393 
394 	return dso->short_name_len;
395 }
396 
dso__loaded(const struct dso * dso,enum map_type type)397 bool dso__loaded(const struct dso *dso, enum map_type type)
398 {
399 	return dso->loaded & (1 << type);
400 }
401 
dso__sorted_by_name(const struct dso * dso,enum map_type type)402 bool dso__sorted_by_name(const struct dso *dso, enum map_type type)
403 {
404 	return dso->sorted_by_name & (1 << type);
405 }
406 
dso__set_sorted_by_name(struct dso * dso,enum map_type type)407 void dso__set_sorted_by_name(struct dso *dso, enum map_type type)
408 {
409 	dso->sorted_by_name |= (1 << type);
410 }
411 
dso__new(const char * name)412 struct dso *dso__new(const char *name)
413 {
414 	struct dso *dso = calloc(1, sizeof(*dso) + strlen(name) + 1);
415 
416 	if (dso != NULL) {
417 		int i;
418 		strcpy(dso->name, name);
419 		dso__set_long_name(dso, dso->name);
420 		dso__set_short_name(dso, dso->name);
421 		for (i = 0; i < MAP__NR_TYPES; ++i)
422 			dso->symbols[i] = dso->symbol_names[i] = RB_ROOT;
423 		dso->cache = RB_ROOT;
424 		dso->symtab_type = DSO_BINARY_TYPE__NOT_FOUND;
425 		dso->data_type   = DSO_BINARY_TYPE__NOT_FOUND;
426 		dso->loaded = 0;
427 		dso->rel = 0;
428 		dso->sorted_by_name = 0;
429 		dso->has_build_id = 0;
430 		dso->kernel = DSO_TYPE_USER;
431 		dso->needs_swap = DSO_SWAP__UNSET;
432 		INIT_LIST_HEAD(&dso->node);
433 	}
434 
435 	return dso;
436 }
437 
dso__delete(struct dso * dso)438 void dso__delete(struct dso *dso)
439 {
440 	int i;
441 	for (i = 0; i < MAP__NR_TYPES; ++i)
442 		symbols__delete(&dso->symbols[i]);
443 	if (dso->sname_alloc)
444 		free((char *)dso->short_name);
445 	if (dso->lname_alloc)
446 		free(dso->long_name);
447 	dso_cache__free(&dso->cache);
448 	free(dso);
449 }
450 
dso__set_build_id(struct dso * dso,void * build_id)451 void dso__set_build_id(struct dso *dso, void *build_id)
452 {
453 	memcpy(dso->build_id, build_id, sizeof(dso->build_id));
454 	dso->has_build_id = 1;
455 }
456 
dso__build_id_equal(const struct dso * dso,u8 * build_id)457 bool dso__build_id_equal(const struct dso *dso, u8 *build_id)
458 {
459 	return memcmp(dso->build_id, build_id, sizeof(dso->build_id)) == 0;
460 }
461 
dso__read_running_kernel_build_id(struct dso * dso,struct machine * machine)462 void dso__read_running_kernel_build_id(struct dso *dso, struct machine *machine)
463 {
464 	char path[PATH_MAX];
465 
466 	if (machine__is_default_guest(machine))
467 		return;
468 	sprintf(path, "%s/sys/kernel/notes", machine->root_dir);
469 	if (sysfs__read_build_id(path, dso->build_id,
470 				 sizeof(dso->build_id)) == 0)
471 		dso->has_build_id = true;
472 }
473 
dso__kernel_module_get_build_id(struct dso * dso,const char * root_dir)474 int dso__kernel_module_get_build_id(struct dso *dso,
475 				    const char *root_dir)
476 {
477 	char filename[PATH_MAX];
478 	/*
479 	 * kernel module short names are of the form "[module]" and
480 	 * we need just "module" here.
481 	 */
482 	const char *name = dso->short_name + 1;
483 
484 	snprintf(filename, sizeof(filename),
485 		 "%s/sys/module/%.*s/notes/.note.gnu.build-id",
486 		 root_dir, (int)strlen(name) - 1, name);
487 
488 	if (sysfs__read_build_id(filename, dso->build_id,
489 				 sizeof(dso->build_id)) == 0)
490 		dso->has_build_id = true;
491 
492 	return 0;
493 }
494 
__dsos__read_build_ids(struct list_head * head,bool with_hits)495 bool __dsos__read_build_ids(struct list_head *head, bool with_hits)
496 {
497 	bool have_build_id = false;
498 	struct dso *pos;
499 
500 	list_for_each_entry(pos, head, node) {
501 		if (with_hits && !pos->hit)
502 			continue;
503 		if (pos->has_build_id) {
504 			have_build_id = true;
505 			continue;
506 		}
507 		if (filename__read_build_id(pos->long_name, pos->build_id,
508 					    sizeof(pos->build_id)) > 0) {
509 			have_build_id	  = true;
510 			pos->has_build_id = true;
511 		}
512 	}
513 
514 	return have_build_id;
515 }
516 
dsos__add(struct list_head * head,struct dso * dso)517 void dsos__add(struct list_head *head, struct dso *dso)
518 {
519 	list_add_tail(&dso->node, head);
520 }
521 
dsos__find(struct list_head * head,const char * name,bool cmp_short)522 struct dso *dsos__find(struct list_head *head, const char *name, bool cmp_short)
523 {
524 	struct dso *pos;
525 
526 	if (cmp_short) {
527 		list_for_each_entry(pos, head, node)
528 			if (strcmp(pos->short_name, name) == 0)
529 				return pos;
530 		return NULL;
531 	}
532 	list_for_each_entry(pos, head, node)
533 		if (strcmp(pos->long_name, name) == 0)
534 			return pos;
535 	return NULL;
536 }
537 
__dsos__findnew(struct list_head * head,const char * name)538 struct dso *__dsos__findnew(struct list_head *head, const char *name)
539 {
540 	struct dso *dso = dsos__find(head, name, false);
541 
542 	if (!dso) {
543 		dso = dso__new(name);
544 		if (dso != NULL) {
545 			dsos__add(head, dso);
546 			dso__set_basename(dso);
547 		}
548 	}
549 
550 	return dso;
551 }
552 
__dsos__fprintf_buildid(struct list_head * head,FILE * fp,bool (skip)(struct dso * dso,int parm),int parm)553 size_t __dsos__fprintf_buildid(struct list_head *head, FILE *fp,
554 			       bool (skip)(struct dso *dso, int parm), int parm)
555 {
556 	struct dso *pos;
557 	size_t ret = 0;
558 
559 	list_for_each_entry(pos, head, node) {
560 		if (skip && skip(pos, parm))
561 			continue;
562 		ret += dso__fprintf_buildid(pos, fp);
563 		ret += fprintf(fp, " %s\n", pos->long_name);
564 	}
565 	return ret;
566 }
567 
__dsos__fprintf(struct list_head * head,FILE * fp)568 size_t __dsos__fprintf(struct list_head *head, FILE *fp)
569 {
570 	struct dso *pos;
571 	size_t ret = 0;
572 
573 	list_for_each_entry(pos, head, node) {
574 		int i;
575 		for (i = 0; i < MAP__NR_TYPES; ++i)
576 			ret += dso__fprintf(pos, i, fp);
577 	}
578 
579 	return ret;
580 }
581 
dso__fprintf_buildid(struct dso * dso,FILE * fp)582 size_t dso__fprintf_buildid(struct dso *dso, FILE *fp)
583 {
584 	char sbuild_id[BUILD_ID_SIZE * 2 + 1];
585 
586 	build_id__sprintf(dso->build_id, sizeof(dso->build_id), sbuild_id);
587 	return fprintf(fp, "%s", sbuild_id);
588 }
589 
dso__fprintf(struct dso * dso,enum map_type type,FILE * fp)590 size_t dso__fprintf(struct dso *dso, enum map_type type, FILE *fp)
591 {
592 	struct rb_node *nd;
593 	size_t ret = fprintf(fp, "dso: %s (", dso->short_name);
594 
595 	if (dso->short_name != dso->long_name)
596 		ret += fprintf(fp, "%s, ", dso->long_name);
597 	ret += fprintf(fp, "%s, %sloaded, ", map_type__name[type],
598 		       dso__loaded(dso, type) ? "" : "NOT ");
599 	ret += dso__fprintf_buildid(dso, fp);
600 	ret += fprintf(fp, ")\n");
601 	for (nd = rb_first(&dso->symbols[type]); nd; nd = rb_next(nd)) {
602 		struct symbol *pos = rb_entry(nd, struct symbol, rb_node);
603 		ret += symbol__fprintf(pos, fp);
604 	}
605 
606 	return ret;
607 }
608