1 /*
2 * Copyright 2024 Meta Platforms
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/debug/symtab.h>
8 #include <zephyr/ztest.h>
9
10 const struct symtab_info *symtab;
11
setup(void)12 static void *setup(void)
13 {
14 symtab = symtab_get();
15
16 return NULL;
17 }
18
19 ZTEST_SUITE(test_symtab, NULL, setup, NULL, NULL, NULL);
20
ZTEST(test_symtab,test_size)21 ZTEST(test_symtab, test_size)
22 {
23 zassert_true(symtab->length > 0);
24 }
25
ZTEST(test_symtab,test_symtab_find_symbol_name)26 ZTEST(test_symtab, test_symtab_find_symbol_name)
27 {
28 extern int main(void);
29 const uintptr_t first_addr = symtab->first_addr;
30 const uintptr_t last_addr = first_addr + symtab->entries[symtab->length - 1].offset;
31 uint32_t offset;
32 const char *symbol_name;
33
34 zassert_between_inclusive((uintptr_t)main, first_addr, last_addr,
35 "No valid address found for `main()`");
36
37 /* Find the name of functions with `symtab_find_symbol_name()` */
38 offset = -1;
39 symbol_name = symtab_find_symbol_name((uintptr_t)main, &offset);
40 zassert_str_equal(symbol_name, "main");
41 zassert_equal(offset, 0);
42
43 /* Do a few more just for fun */
44 symbol_name = symtab_find_symbol_name((uintptr_t)strcmp, NULL);
45 zassert_str_equal(symbol_name, "strcmp");
46
47 symbol_name = symtab_find_symbol_name((uintptr_t)symtab_find_symbol_name, NULL);
48 zassert_str_equal(symbol_name, "symtab_find_symbol_name");
49
50 symbol_name = symtab_find_symbol_name((uintptr_t)test_main, NULL);
51 zassert_str_equal(symbol_name, "test_main");
52
53 symbol_name = symtab_find_symbol_name((uintptr_t)setup, NULL);
54 zassert_str_equal(symbol_name, "setup");
55 }
56
57 /**
58 * This testsuite tests the following position in the symbol table
59 *
60 *
61 * [SYMBOL ADDR] | Name Offset
62 * before first--> . | "?" (not found) 0x0
63 * first--> 0x100 | <first> 0x0
64 * 0x101 | <first> 0x1
65 * . |
66 * . |
67 * . |
68 * last--> 0x300 | <last> 0x0
69 * after last--> 0x301 | <last> 0x1
70 * . |
71 * 0x310 (dummy) | "?" (not found) 0x0
72 * . |
73 * after dummy--> 0x342 | "?" (not found) 0x0
74 */
75
ZTEST(test_symtab,test_before_first)76 ZTEST(test_symtab, test_before_first)
77 {
78 const uintptr_t first_addr = symtab->first_addr;
79 const char *symbol_name;
80 uint32_t offset;
81
82 /* No symbol should appear before first_addr, but make sure that first_addr != 0 */
83 if (first_addr > 0) {
84 offset = -1;
85 symbol_name = symtab_find_symbol_name(first_addr - 1, &offset);
86 zassert_str_equal(symbol_name, "?");
87 zassert_equal(offset, 0);
88 } else {
89 ztest_test_skip();
90 }
91 }
92
ZTEST(test_symtab,test_first)93 ZTEST(test_symtab, test_first)
94 {
95 const uintptr_t first_addr = symtab->first_addr;
96 const char *symbol_name;
97 uint32_t offset;
98
99 offset = -1;
100 symbol_name = symtab_find_symbol_name(first_addr, &offset);
101 zassert_str_equal(symbol_name, symtab->entries[0].name);
102 zassert_equal(offset, 0);
103
104 if ((symtab->entries[0].offset + 1) != symtab->entries[1].offset) {
105 offset = -1;
106 symbol_name = symtab_find_symbol_name(first_addr + 1, &offset);
107 zassert_str_equal(symbol_name, symtab->entries[0].name);
108 zassert_equal(offset, 1);
109 }
110 }
111
ZTEST(test_symtab,test_last)112 ZTEST(test_symtab, test_last)
113 {
114 const uintptr_t first_addr = symtab->first_addr;
115 const int last_idx = symtab->length - 1;
116 const uintptr_t last_addr = first_addr + symtab->entries[last_idx].offset;
117 const char *symbol_name;
118 uint32_t offset;
119
120 offset = -1;
121 symbol_name = symtab_find_symbol_name(last_addr, &offset);
122 zassert_str_equal(symbol_name, symtab->entries[last_idx].name);
123 zassert_equal(offset, 0);
124 }
125
ZTEST(test_symtab,test_after_last)126 ZTEST(test_symtab, test_after_last)
127 {
128 const uintptr_t first_addr = symtab->first_addr;
129 const uintptr_t last_offset = symtab->entries[symtab->length - 1].offset;
130 const uintptr_t last_addr = first_addr + last_offset;
131 const char *symbol_name;
132 uint32_t offset;
133
134 /* Test `offset` output with last symbol */
135 if (last_offset + 0x1 != symtab->entries[symtab->length].offset) {
136 offset = -1;
137 symbol_name = symtab_find_symbol_name(last_addr + 0x1, &offset);
138 zassert_str_equal(symbol_name,
139 symtab->entries[symtab->length - 1].name);
140 zassert_equal(offset, 0x1);
141 } else {
142 ztest_test_skip();
143 }
144 }
145
ZTEST(test_symtab,test_after_dummy)146 ZTEST(test_symtab, test_after_dummy)
147 {
148 const uintptr_t first_addr = symtab->first_addr;
149 const uintptr_t last_dummy_offset = symtab->entries[symtab->length].offset;
150 const uintptr_t last_dummy_addr = first_addr + last_dummy_offset;
151 const char *symbol_name;
152 uint32_t offset;
153
154 /* Test `offset` output with dummy symbol (after last dymbol) */
155 offset = -1;
156 symbol_name = symtab_find_symbol_name(last_dummy_addr + 0x42, &offset);
157 zassert_str_equal(symbol_name, "?");
158 zassert_equal(offset, 0);
159 }
160