xref: /openbmc/linux/tools/perf/tests/symbols.c (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
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 
init_test_info(struct test_info * ti)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 
exit_test_info(struct test_info * ti)381b69346eSAdrian Hunter static void exit_test_info(struct test_info *ti)
391b69346eSAdrian Hunter {
401b69346eSAdrian Hunter 	thread__put(ti->thread);
4182c6d83bSIan Rogers 	machine__delete(ti->machine);
421b69346eSAdrian Hunter }
431b69346eSAdrian Hunter 
get_test_dso_filename(char * filename,size_t max_sz)441b69346eSAdrian Hunter static void get_test_dso_filename(char *filename, size_t max_sz)
451b69346eSAdrian Hunter {
461b69346eSAdrian Hunter 	if (dso_to_test)
471b69346eSAdrian Hunter 		strlcpy(filename, dso_to_test, max_sz);
481b69346eSAdrian Hunter 	else
491b69346eSAdrian Hunter 		perf_exe(filename, max_sz);
501b69346eSAdrian Hunter }
511b69346eSAdrian Hunter 
create_map(struct test_info * ti,char * filename,struct map ** map_p)521b69346eSAdrian Hunter static int create_map(struct test_info *ti, char *filename, struct map **map_p)
531b69346eSAdrian Hunter {
541b69346eSAdrian Hunter 	/* Create a dummy map at 0x100000 */
551b69346eSAdrian Hunter 	*map_p = map__new(ti->machine, 0x100000, 0xffffffff, 0, NULL,
561b69346eSAdrian Hunter 			  PROT_EXEC, 0, NULL, filename, ti->thread);
571b69346eSAdrian Hunter 	if (!*map_p) {
581b69346eSAdrian Hunter 		pr_debug("Failed to create map!");
591b69346eSAdrian Hunter 		return TEST_FAIL;
601b69346eSAdrian Hunter 	}
611b69346eSAdrian Hunter 
621b69346eSAdrian Hunter 	return TEST_OK;
631b69346eSAdrian Hunter }
641b69346eSAdrian Hunter 
test_dso(struct dso * dso)651b69346eSAdrian Hunter static int test_dso(struct dso *dso)
661b69346eSAdrian Hunter {
671b69346eSAdrian Hunter 	struct symbol *last_sym = NULL;
681b69346eSAdrian Hunter 	struct rb_node *nd;
691b69346eSAdrian Hunter 	int ret = TEST_OK;
701b69346eSAdrian Hunter 
711b69346eSAdrian Hunter 	/* dso__fprintf() prints all the symbols */
721b69346eSAdrian Hunter 	if (verbose > 1)
731b69346eSAdrian Hunter 		dso__fprintf(dso, stderr);
741b69346eSAdrian Hunter 
751b69346eSAdrian Hunter 	for (nd = rb_first_cached(&dso->symbols); nd; nd = rb_next(nd)) {
761b69346eSAdrian Hunter 		struct symbol *sym = rb_entry(nd, struct symbol, rb_node);
771b69346eSAdrian Hunter 
781b69346eSAdrian Hunter 		if (sym->type != STT_FUNC && sym->type != STT_GNU_IFUNC)
791b69346eSAdrian Hunter 			continue;
801b69346eSAdrian Hunter 
811b69346eSAdrian Hunter 		/* Check for overlapping function symbols */
821b69346eSAdrian Hunter 		if (last_sym && sym->start < last_sym->end) {
831b69346eSAdrian Hunter 			pr_debug("Overlapping symbols:\n");
841b69346eSAdrian Hunter 			symbol__fprintf(last_sym, stderr);
851b69346eSAdrian Hunter 			symbol__fprintf(sym, stderr);
861b69346eSAdrian Hunter 			ret = TEST_FAIL;
871b69346eSAdrian Hunter 		}
881b69346eSAdrian Hunter 		/* Check for zero-length function symbol */
891b69346eSAdrian Hunter 		if (sym->start == sym->end) {
901b69346eSAdrian Hunter 			pr_debug("Zero-length symbol:\n");
911b69346eSAdrian Hunter 			symbol__fprintf(sym, stderr);
921b69346eSAdrian Hunter 			ret = TEST_FAIL;
931b69346eSAdrian Hunter 		}
941b69346eSAdrian Hunter 		last_sym = sym;
951b69346eSAdrian Hunter 	}
961b69346eSAdrian Hunter 
971b69346eSAdrian Hunter 	return ret;
981b69346eSAdrian Hunter }
991b69346eSAdrian Hunter 
test_file(struct test_info * ti,char * filename)1001b69346eSAdrian Hunter static int test_file(struct test_info *ti, char *filename)
1011b69346eSAdrian Hunter {
1021b69346eSAdrian Hunter 	struct map *map = NULL;
1031b69346eSAdrian Hunter 	int ret, nr;
1041b69346eSAdrian Hunter 	struct dso *dso;
105*63df0e4bSIan Rogers 
1061b69346eSAdrian Hunter 	pr_debug("Testing %s\n", filename);
1071b69346eSAdrian Hunter 
1081b69346eSAdrian Hunter 	ret = create_map(ti, filename, &map);
1091b69346eSAdrian Hunter 	if (ret != TEST_OK)
1101b69346eSAdrian Hunter 		return ret;
1111b69346eSAdrian Hunter 
1121b69346eSAdrian Hunter 	dso = map__dso(map);
113*63df0e4bSIan Rogers 	nr = dso__load(dso, map);
114*63df0e4bSIan Rogers 	if (nr < 0) {
1151b69346eSAdrian Hunter 		pr_debug("dso__load() failed!\n");
1161b69346eSAdrian Hunter 		ret = TEST_FAIL;
1171b69346eSAdrian Hunter 		goto out_put;
1181b69346eSAdrian Hunter 	}
1191b69346eSAdrian Hunter 
1201b69346eSAdrian Hunter 	if (nr == 0) {
1211b69346eSAdrian Hunter 		pr_debug("DSO has no symbols!\n");
1221b69346eSAdrian Hunter 		ret = TEST_SKIP;
1231b69346eSAdrian Hunter 		goto out_put;
1241b69346eSAdrian Hunter 	}
1251b69346eSAdrian Hunter 
1261b69346eSAdrian Hunter 	ret = test_dso(dso);
127*63df0e4bSIan Rogers out_put:
1281b69346eSAdrian Hunter 	map__put(map);
1291b69346eSAdrian Hunter 
1301b69346eSAdrian Hunter 	return ret;
1311b69346eSAdrian Hunter }
1321b69346eSAdrian Hunter 
test__symbols(struct test_suite * test __maybe_unused,int subtest __maybe_unused)1331b69346eSAdrian Hunter static int test__symbols(struct test_suite *test __maybe_unused, int subtest __maybe_unused)
1341b69346eSAdrian Hunter {
1351b69346eSAdrian Hunter 	char filename[PATH_MAX];
1361b69346eSAdrian Hunter 	struct test_info ti;
1371b69346eSAdrian Hunter 	int ret;
1381b69346eSAdrian Hunter 
1391b69346eSAdrian Hunter 	ret = init_test_info(&ti);
1401b69346eSAdrian Hunter 	if (ret != TEST_OK)
1411b69346eSAdrian Hunter 		return ret;
1421b69346eSAdrian Hunter 
1431b69346eSAdrian Hunter 	get_test_dso_filename(filename, sizeof(filename));
1441b69346eSAdrian Hunter 
1451b69346eSAdrian Hunter 	ret = test_file(&ti, filename);
1461b69346eSAdrian Hunter 
1471b69346eSAdrian Hunter 	exit_test_info(&ti);
1481b69346eSAdrian Hunter 
1491b69346eSAdrian Hunter 	return ret;
1501b69346eSAdrian Hunter }
1511b69346eSAdrian Hunter 
1521b69346eSAdrian Hunter DEFINE_SUITE("Symbols", symbols);
1531b69346eSAdrian Hunter