• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 	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 
dso__name_len(const struct dso * dso)414 int 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 
dso__loaded(const struct dso * dso,enum map_type type)424 bool dso__loaded(const struct dso *dso, enum map_type type)
425 {
426 	return dso->loaded & (1 << type);
427 }
428 
dso__sorted_by_name(const struct dso * dso,enum map_type type)429 bool dso__sorted_by_name(const struct dso *dso, enum map_type type)
430 {
431 	return dso->sorted_by_name & (1 << type);
432 }
433 
dso__set_sorted_by_name(struct dso * dso,enum map_type type)434 void dso__set_sorted_by_name(struct dso *dso, enum map_type type)
435 {
436 	dso->sorted_by_name |= (1 << type);
437 }
438 
dso__new(const char * name)439 struct 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 
dso__delete(struct dso * dso)465 void 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 
dso__set_build_id(struct dso * dso,void * build_id)478 void 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 
dso__build_id_equal(const struct dso * dso,u8 * build_id)484 bool 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 
dso__read_running_kernel_build_id(struct dso * dso,struct machine * machine)489 void 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 
dso__kernel_module_get_build_id(struct dso * dso,const char * root_dir)501 int 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 
__dsos__read_build_ids(struct list_head * head,bool with_hits)522 bool __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 
dsos__add(struct list_head * head,struct dso * dso)544 void dsos__add(struct list_head *head, struct dso *dso)
545 {
546 	list_add_tail(&dso->node, head);
547 }
548 
dsos__find(struct list_head * head,const char * name,bool cmp_short)549 struct 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 
__dsos__findnew(struct list_head * head,const char * name)565 struct 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 
__dsos__fprintf_buildid(struct list_head * head,FILE * fp,bool (skip)(struct dso * dso,int parm),int parm)580 size_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 
__dsos__fprintf(struct list_head * head,FILE * fp)595 size_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 
dso__fprintf_buildid(struct dso * dso,FILE * fp)609 size_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 
dso__fprintf(struct dso * dso,enum map_type type,FILE * fp)617 size_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