]>
Commit | Line | Data |
---|---|---|
b77b02a5 YQ |
1 | /* Self tests for gdbarch for GDB, the GNU debugger. |
2 | ||
1d506c26 | 3 | Copyright (C) 2017-2024 Free Software Foundation, Inc. |
b77b02a5 YQ |
4 | |
5 | This file is part of GDB. | |
6 | ||
7 | This program is free software; you can redistribute it and/or modify | |
8 | it under the terms of the GNU General Public License as published by | |
9 | the Free Software Foundation; either version 3 of the License, or | |
10 | (at your option) any later version. | |
11 | ||
12 | This program is distributed in the hope that it will be useful, | |
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 | GNU General Public License for more details. | |
16 | ||
17 | You should have received a copy of the GNU General Public License | |
18 | along with this program. If not, see <http://www.gnu.org/licenses/>. */ | |
19 | ||
268a13a5 | 20 | #include "gdbsupport/selftest.h" |
b77b02a5 | 21 | #include "selftest-arch.h" |
55b11ddf | 22 | #include "target.h" |
c180496d | 23 | #include "test-target.h" |
f69fdf9b | 24 | #include "target-float.h" |
268a13a5 | 25 | #include "gdbsupport/def-vector.h" |
0d12e84c | 26 | #include "gdbarch.h" |
236ef034 | 27 | #include "scoped-mock-context.h" |
b77b02a5 | 28 | |
9a103324 AB |
29 | #include <map> |
30 | ||
b77b02a5 YQ |
31 | namespace selftests { |
32 | ||
b77b02a5 YQ |
33 | /* Test gdbarch methods register_to_value and value_to_register. */ |
34 | ||
35 | static void | |
36 | register_to_value_test (struct gdbarch *gdbarch) | |
37 | { | |
38 | const struct builtin_type *builtin = builtin_type (gdbarch); | |
39 | struct type *types[] = | |
40 | { | |
41 | builtin->builtin_void, | |
42 | builtin->builtin_char, | |
43 | builtin->builtin_short, | |
44 | builtin->builtin_int, | |
45 | builtin->builtin_long, | |
46 | builtin->builtin_signed_char, | |
47 | builtin->builtin_unsigned_short, | |
48 | builtin->builtin_unsigned_int, | |
49 | builtin->builtin_unsigned_long, | |
50 | builtin->builtin_float, | |
51 | builtin->builtin_double, | |
52 | builtin->builtin_long_double, | |
53 | builtin->builtin_complex, | |
54 | builtin->builtin_double_complex, | |
55 | builtin->builtin_string, | |
56 | builtin->builtin_bool, | |
57 | builtin->builtin_long_long, | |
58 | builtin->builtin_unsigned_long_long, | |
59 | builtin->builtin_int8, | |
60 | builtin->builtin_uint8, | |
61 | builtin->builtin_int16, | |
62 | builtin->builtin_uint16, | |
63 | builtin->builtin_int32, | |
64 | builtin->builtin_uint32, | |
65 | builtin->builtin_int64, | |
66 | builtin->builtin_uint64, | |
67 | builtin->builtin_int128, | |
68 | builtin->builtin_uint128, | |
69 | builtin->builtin_char16, | |
70 | builtin->builtin_char32, | |
71 | }; | |
72 | ||
236ef034 | 73 | scoped_mock_context<test_target_ops> mockctx (gdbarch); |
55b11ddf | 74 | |
bd2b40ac | 75 | frame_info_ptr frame = get_current_frame (); |
f6efe3f8 | 76 | const int num_regs = gdbarch_num_cooked_regs (gdbarch); |
b77b02a5 | 77 | |
b77b02a5 YQ |
78 | /* Test gdbarch methods register_to_value and value_to_register with |
79 | different combinations of register numbers and types. */ | |
80 | for (const auto &type : types) | |
81 | { | |
82 | for (auto regnum = 0; regnum < num_regs; regnum++) | |
83 | { | |
84 | if (gdbarch_convert_register_p (gdbarch, regnum, type)) | |
85 | { | |
df86565b | 86 | std::vector<gdb_byte> expected (type->length (), 0); |
b77b02a5 | 87 | |
78134374 | 88 | if (type->code () == TYPE_CODE_FLT) |
b77b02a5 | 89 | { |
b77b02a5 | 90 | /* Generate valid float format. */ |
f69fdf9b | 91 | target_float_from_string (expected.data (), type, "1.25"); |
b77b02a5 YQ |
92 | } |
93 | else | |
94 | { | |
95 | for (auto j = 0; j < expected.size (); j++) | |
96 | expected[j] = (regnum + j) % 16; | |
97 | } | |
98 | ||
99 | gdbarch_value_to_register (gdbarch, frame, regnum, type, | |
100 | expected.data ()); | |
101 | ||
102 | /* Allocate two bytes more for overflow check. */ | |
df86565b | 103 | std::vector<gdb_byte> buf (type->length () + 2, 0); |
b77b02a5 YQ |
104 | int optim, unavail, ok; |
105 | ||
106 | /* Set the fingerprint in the last two bytes. */ | |
df86565b SM |
107 | buf [type->length ()]= 'w'; |
108 | buf [type->length () + 1]= 'l'; | |
b77b02a5 YQ |
109 | ok = gdbarch_register_to_value (gdbarch, frame, regnum, type, |
110 | buf.data (), &optim, &unavail); | |
111 | ||
112 | SELF_CHECK (ok); | |
113 | SELF_CHECK (!optim); | |
114 | SELF_CHECK (!unavail); | |
115 | ||
df86565b SM |
116 | SELF_CHECK (buf[type->length ()] == 'w'); |
117 | SELF_CHECK (buf[type->length () + 1] == 'l'); | |
b77b02a5 | 118 | |
df86565b | 119 | for (auto k = 0; k < type->length (); k++) |
b77b02a5 YQ |
120 | SELF_CHECK (buf[k] == expected[k]); |
121 | } | |
122 | } | |
123 | } | |
124 | } | |
125 | ||
9a972b54 AB |
126 | /* Test function gdbarch_register_name. */ |
127 | ||
128 | static void | |
129 | register_name_test (struct gdbarch *gdbarch) | |
130 | { | |
131 | scoped_mock_context<test_target_ops> mockctx (gdbarch); | |
132 | ||
9a103324 AB |
133 | /* Track the number of times each register name appears. */ |
134 | std::map<const std::string, int> name_counts; | |
135 | ||
9a972b54 AB |
136 | const int num_regs = gdbarch_num_cooked_regs (gdbarch); |
137 | for (auto regnum = 0; regnum < num_regs; regnum++) | |
138 | { | |
139 | /* If a register is to be hidden from the user then we should get | |
140 | back an empty string, not nullptr. Every other register should | |
141 | return a non-empty string. */ | |
142 | const char *name = gdbarch_register_name (gdbarch, regnum); | |
143 | ||
144 | if (run_verbose() && name == nullptr) | |
145 | debug_printf ("arch: %s, register: %d returned nullptr\n", | |
146 | gdbarch_bfd_arch_info (gdbarch)->printable_name, | |
147 | regnum); | |
9a972b54 | 148 | SELF_CHECK (name != nullptr); |
9a103324 AB |
149 | |
150 | /* Every register name, that is not the empty string, should be | |
151 | unique. If this is not the case then the user will see duplicate | |
152 | copies of the register in e.g. 'info registers' output, but will | |
153 | only be able to interact with one of the copies. */ | |
154 | if (*name != '\0') | |
155 | { | |
156 | std::string s (name); | |
157 | name_counts[s]++; | |
158 | if (run_verbose() && name_counts[s] > 1) | |
159 | debug_printf ("arch: %s, register: %d (%s) is a duplicate\n", | |
160 | gdbarch_bfd_arch_info (gdbarch)->printable_name, | |
161 | regnum, name); | |
162 | SELF_CHECK (name_counts[s] == 1); | |
163 | } | |
9a972b54 AB |
164 | } |
165 | } | |
166 | ||
a4f76c07 AB |
167 | /* Test gdbarch_stack_grows_down. Stacks must either grow down or up. */ |
168 | ||
169 | static void | |
170 | check_stack_growth (struct gdbarch *gdbarch) | |
171 | { | |
172 | /* We don't call gdbarch_stack_grows_down here, instead we're testing the | |
173 | implementation by calling gdbarch_inner_than. GDB assumes that stacks | |
174 | either grow down or up (see uses of gdbarch_stack_grows_down), so exactly | |
175 | one of these needs to be true. */ | |
176 | bool stack_grows_down = gdbarch_inner_than (gdbarch, 1, 2) != 0; | |
177 | bool stack_grows_up = gdbarch_inner_than (gdbarch, 2, 1) != 0; | |
178 | ||
179 | SELF_CHECK (stack_grows_up != stack_grows_down); | |
180 | } | |
181 | ||
b77b02a5 | 182 | } // namespace selftests |
b77b02a5 | 183 | |
6c265988 | 184 | void _initialize_gdbarch_selftests (); |
b77b02a5 | 185 | void |
6c265988 | 186 | _initialize_gdbarch_selftests () |
b77b02a5 | 187 | { |
1526853e SM |
188 | selftests::register_test_foreach_arch ("register_to_value", |
189 | selftests::register_to_value_test); | |
9a972b54 AB |
190 | |
191 | selftests::register_test_foreach_arch ("register_name", | |
192 | selftests::register_name_test); | |
a4f76c07 AB |
193 | |
194 | selftests::register_test_foreach_arch ("stack_growth", | |
195 | selftests::check_stack_growth); | |
b77b02a5 | 196 | } |