1 // SPDX-License-Identifier: GPL-2.0 2 #include <linux/compiler.h> 3 #include <linux/string.h> 4 #include <sys/mman.h> 5 #include <limits.h> 6 #include "debug.h" 7 #include "dso.h" 8 #include "machine.h" 9 #include "thread.h" 10 #include "symbol.h" 11 #include "map.h" 12 #include "util.h" 13 #include "tests.h" 14 15 struct test_info { 16 struct machine *machine; 17 struct thread *thread; 18 }; 19 20 static int init_test_info(struct test_info *ti) 21 { 22 ti->machine = machine__new_host(); 23 if (!ti->machine) { 24 pr_debug("machine__new_host() failed!\n"); 25 return TEST_FAIL; 26 } 27 28 /* Create a dummy thread */ 29 ti->thread = machine__findnew_thread(ti->machine, 100, 100); 30 if (!ti->thread) { 31 pr_debug("machine__findnew_thread() failed!\n"); 32 return TEST_FAIL; 33 } 34 35 return TEST_OK; 36 } 37 38 static void exit_test_info(struct test_info *ti) 39 { 40 thread__put(ti->thread); 41 machine__delete(ti->machine); 42 } 43 44 static void get_test_dso_filename(char *filename, size_t max_sz) 45 { 46 if (dso_to_test) 47 strlcpy(filename, dso_to_test, max_sz); 48 else 49 perf_exe(filename, max_sz); 50 } 51 52 static int create_map(struct test_info *ti, char *filename, struct map **map_p) 53 { 54 /* Create a dummy map at 0x100000 */ 55 *map_p = map__new(ti->machine, 0x100000, 0xffffffff, 0, NULL, 56 PROT_EXEC, 0, NULL, filename, ti->thread); 57 if (!*map_p) { 58 pr_debug("Failed to create map!"); 59 return TEST_FAIL; 60 } 61 62 return TEST_OK; 63 } 64 65 static int test_dso(struct dso *dso) 66 { 67 struct symbol *last_sym = NULL; 68 struct rb_node *nd; 69 int ret = TEST_OK; 70 71 /* dso__fprintf() prints all the symbols */ 72 if (verbose > 1) 73 dso__fprintf(dso, stderr); 74 75 for (nd = rb_first_cached(&dso->symbols); nd; nd = rb_next(nd)) { 76 struct symbol *sym = rb_entry(nd, struct symbol, rb_node); 77 78 if (sym->type != STT_FUNC && sym->type != STT_GNU_IFUNC) 79 continue; 80 81 /* Check for overlapping function symbols */ 82 if (last_sym && sym->start < last_sym->end) { 83 pr_debug("Overlapping symbols:\n"); 84 symbol__fprintf(last_sym, stderr); 85 symbol__fprintf(sym, stderr); 86 ret = TEST_FAIL; 87 } 88 /* Check for zero-length function symbol */ 89 if (sym->start == sym->end) { 90 pr_debug("Zero-length symbol:\n"); 91 symbol__fprintf(sym, stderr); 92 ret = TEST_FAIL; 93 } 94 last_sym = sym; 95 } 96 97 return ret; 98 } 99 100 static int test_file(struct test_info *ti, char *filename) 101 { 102 struct map *map = NULL; 103 int ret, nr; 104 105 pr_debug("Testing %s\n", filename); 106 107 ret = create_map(ti, filename, &map); 108 if (ret != TEST_OK) 109 return ret; 110 111 nr = dso__load(map->dso, map); 112 if (nr < 0) { 113 pr_debug("dso__load() failed!\n"); 114 ret = TEST_FAIL; 115 goto out_put; 116 } 117 118 if (nr == 0) { 119 pr_debug("DSO has no symbols!\n"); 120 ret = TEST_SKIP; 121 goto out_put; 122 } 123 124 ret = test_dso(map->dso); 125 out_put: 126 map__put(map); 127 128 return ret; 129 } 130 131 static int test__symbols(struct test_suite *test __maybe_unused, int subtest __maybe_unused) 132 { 133 char filename[PATH_MAX]; 134 struct test_info ti; 135 int ret; 136 137 ret = init_test_info(&ti); 138 if (ret != TEST_OK) 139 return ret; 140 141 get_test_dso_filename(filename, sizeof(filename)); 142 143 ret = test_file(&ti, filename); 144 145 exit_test_info(&ti); 146 147 return ret; 148 } 149 150 DEFINE_SUITE("Symbols", symbols); 151