xref: /linux/tools/perf/tests/symbols.c (revision 63df0e4bc368adbd12ed70ed4789d8d52d65661d)
11b69346eSAdrian Hunter // SPDX-License-Identifier: GPL-2.0
21b69346eSAdrian Hunter #include <linux/compiler.h>
31b69346eSAdrian Hunter #include <linux/string.h>
41b69346eSAdrian Hunter #include <sys/mman.h>
51b69346eSAdrian Hunter #include <limits.h>
61b69346eSAdrian Hunter #include "debug.h"
71b69346eSAdrian Hunter #include "dso.h"
81b69346eSAdrian Hunter #include "machine.h"
91b69346eSAdrian Hunter #include "thread.h"
101b69346eSAdrian Hunter #include "symbol.h"
111b69346eSAdrian Hunter #include "map.h"
121b69346eSAdrian Hunter #include "util.h"
131b69346eSAdrian Hunter #include "tests.h"
141b69346eSAdrian Hunter 
151b69346eSAdrian Hunter struct test_info {
161b69346eSAdrian Hunter 	struct machine *machine;
171b69346eSAdrian Hunter 	struct thread *thread;
181b69346eSAdrian Hunter };
191b69346eSAdrian Hunter 
201b69346eSAdrian Hunter static int init_test_info(struct test_info *ti)
211b69346eSAdrian Hunter {
221b69346eSAdrian Hunter 	ti->machine = machine__new_host();
231b69346eSAdrian Hunter 	if (!ti->machine) {
241b69346eSAdrian Hunter 		pr_debug("machine__new_host() failed!\n");
251b69346eSAdrian Hunter 		return TEST_FAIL;
261b69346eSAdrian Hunter 	}
271b69346eSAdrian Hunter 
281b69346eSAdrian Hunter 	/* Create a dummy thread */
291b69346eSAdrian Hunter 	ti->thread = machine__findnew_thread(ti->machine, 100, 100);
301b69346eSAdrian Hunter 	if (!ti->thread) {
311b69346eSAdrian Hunter 		pr_debug("machine__findnew_thread() failed!\n");
321b69346eSAdrian Hunter 		return TEST_FAIL;
331b69346eSAdrian Hunter 	}
341b69346eSAdrian Hunter 
351b69346eSAdrian Hunter 	return TEST_OK;
361b69346eSAdrian Hunter }
371b69346eSAdrian Hunter 
381b69346eSAdrian Hunter static void exit_test_info(struct test_info *ti)
391b69346eSAdrian Hunter {
401b69346eSAdrian Hunter 	thread__put(ti->thread);
4182c6d83bSIan Rogers 	machine__delete_threads(ti->machine);
421b69346eSAdrian Hunter 	machine__delete(ti->machine);
431b69346eSAdrian Hunter }
441b69346eSAdrian Hunter 
451b69346eSAdrian Hunter static void get_test_dso_filename(char *filename, size_t max_sz)
461b69346eSAdrian Hunter {
471b69346eSAdrian Hunter 	if (dso_to_test)
481b69346eSAdrian Hunter 		strlcpy(filename, dso_to_test, max_sz);
491b69346eSAdrian Hunter 	else
501b69346eSAdrian Hunter 		perf_exe(filename, max_sz);
511b69346eSAdrian Hunter }
521b69346eSAdrian Hunter 
531b69346eSAdrian Hunter static int create_map(struct test_info *ti, char *filename, struct map **map_p)
541b69346eSAdrian Hunter {
551b69346eSAdrian Hunter 	/* Create a dummy map at 0x100000 */
561b69346eSAdrian Hunter 	*map_p = map__new(ti->machine, 0x100000, 0xffffffff, 0, NULL,
571b69346eSAdrian Hunter 			  PROT_EXEC, 0, NULL, filename, ti->thread);
581b69346eSAdrian Hunter 	if (!*map_p) {
591b69346eSAdrian Hunter 		pr_debug("Failed to create map!");
601b69346eSAdrian Hunter 		return TEST_FAIL;
611b69346eSAdrian Hunter 	}
621b69346eSAdrian Hunter 
631b69346eSAdrian Hunter 	return TEST_OK;
641b69346eSAdrian Hunter }
651b69346eSAdrian Hunter 
661b69346eSAdrian Hunter static int test_dso(struct dso *dso)
671b69346eSAdrian Hunter {
681b69346eSAdrian Hunter 	struct symbol *last_sym = NULL;
691b69346eSAdrian Hunter 	struct rb_node *nd;
701b69346eSAdrian Hunter 	int ret = TEST_OK;
711b69346eSAdrian Hunter 
721b69346eSAdrian Hunter 	/* dso__fprintf() prints all the symbols */
731b69346eSAdrian Hunter 	if (verbose > 1)
741b69346eSAdrian Hunter 		dso__fprintf(dso, stderr);
751b69346eSAdrian Hunter 
761b69346eSAdrian Hunter 	for (nd = rb_first_cached(&dso->symbols); nd; nd = rb_next(nd)) {
771b69346eSAdrian Hunter 		struct symbol *sym = rb_entry(nd, struct symbol, rb_node);
781b69346eSAdrian Hunter 
791b69346eSAdrian Hunter 		if (sym->type != STT_FUNC && sym->type != STT_GNU_IFUNC)
801b69346eSAdrian Hunter 			continue;
811b69346eSAdrian Hunter 
821b69346eSAdrian Hunter 		/* Check for overlapping function symbols */
831b69346eSAdrian Hunter 		if (last_sym && sym->start < last_sym->end) {
841b69346eSAdrian Hunter 			pr_debug("Overlapping symbols:\n");
851b69346eSAdrian Hunter 			symbol__fprintf(last_sym, stderr);
861b69346eSAdrian Hunter 			symbol__fprintf(sym, stderr);
871b69346eSAdrian Hunter 			ret = TEST_FAIL;
881b69346eSAdrian Hunter 		}
891b69346eSAdrian Hunter 		/* Check for zero-length function symbol */
901b69346eSAdrian Hunter 		if (sym->start == sym->end) {
911b69346eSAdrian Hunter 			pr_debug("Zero-length symbol:\n");
921b69346eSAdrian Hunter 			symbol__fprintf(sym, stderr);
931b69346eSAdrian Hunter 			ret = TEST_FAIL;
941b69346eSAdrian Hunter 		}
951b69346eSAdrian Hunter 		last_sym = sym;
961b69346eSAdrian Hunter 	}
971b69346eSAdrian Hunter 
981b69346eSAdrian Hunter 	return ret;
991b69346eSAdrian Hunter }
1001b69346eSAdrian Hunter 
1011b69346eSAdrian Hunter static int test_file(struct test_info *ti, char *filename)
1021b69346eSAdrian Hunter {
1031b69346eSAdrian Hunter 	struct map *map = NULL;
1041b69346eSAdrian Hunter 	int ret, nr;
10563df0e4bSIan Rogers 	struct dso *dso;
1061b69346eSAdrian Hunter 
1071b69346eSAdrian Hunter 	pr_debug("Testing %s\n", filename);
1081b69346eSAdrian Hunter 
1091b69346eSAdrian Hunter 	ret = create_map(ti, filename, &map);
1101b69346eSAdrian Hunter 	if (ret != TEST_OK)
1111b69346eSAdrian Hunter 		return ret;
1121b69346eSAdrian Hunter 
11363df0e4bSIan Rogers 	dso = map__dso(map);
11463df0e4bSIan Rogers 	nr = dso__load(dso, map);
1151b69346eSAdrian Hunter 	if (nr < 0) {
1161b69346eSAdrian Hunter 		pr_debug("dso__load() failed!\n");
1171b69346eSAdrian Hunter 		ret = TEST_FAIL;
1181b69346eSAdrian Hunter 		goto out_put;
1191b69346eSAdrian Hunter 	}
1201b69346eSAdrian Hunter 
1211b69346eSAdrian Hunter 	if (nr == 0) {
1221b69346eSAdrian Hunter 		pr_debug("DSO has no symbols!\n");
1231b69346eSAdrian Hunter 		ret = TEST_SKIP;
1241b69346eSAdrian Hunter 		goto out_put;
1251b69346eSAdrian Hunter 	}
1261b69346eSAdrian Hunter 
12763df0e4bSIan Rogers 	ret = test_dso(dso);
1281b69346eSAdrian Hunter out_put:
1291b69346eSAdrian Hunter 	map__put(map);
1301b69346eSAdrian Hunter 
1311b69346eSAdrian Hunter 	return ret;
1321b69346eSAdrian Hunter }
1331b69346eSAdrian Hunter 
1341b69346eSAdrian Hunter static int test__symbols(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
1351b69346eSAdrian Hunter {
1361b69346eSAdrian Hunter 	char filename[PATH_MAX];
1371b69346eSAdrian Hunter 	struct test_info ti;
1381b69346eSAdrian Hunter 	int ret;
1391b69346eSAdrian Hunter 
1401b69346eSAdrian Hunter 	ret = init_test_info(&ti);
1411b69346eSAdrian Hunter 	if (ret != TEST_OK)
1421b69346eSAdrian Hunter 		return ret;
1431b69346eSAdrian Hunter 
1441b69346eSAdrian Hunter 	get_test_dso_filename(filename, sizeof(filename));
1451b69346eSAdrian Hunter 
1461b69346eSAdrian Hunter 	ret = test_file(&ti, filename);
1471b69346eSAdrian Hunter 
1481b69346eSAdrian Hunter 	exit_test_info(&ti);
1491b69346eSAdrian Hunter 
1501b69346eSAdrian Hunter 	return ret;
1511b69346eSAdrian Hunter }
1521b69346eSAdrian Hunter 
1531b69346eSAdrian Hunter DEFINE_SUITE("Symbols", symbols);
154