1 /*
2 * Copyright (c) 2016, Linaro Limited
3 * Copyright (c) 2019, ARM Limited. All rights reserved.
4 *
5 * SPDX-License-Identifier: BSD-2-Clause
6 */
7
8 #include <arch_helpers.h>
9 #include <context.h>
10 #include <common/debug.h>
11 #include <plat/common/platform.h>
12
13 struct source_location {
14 const char *file_name;
15 uint32_t line;
16 uint32_t column;
17 };
18
19 struct type_descriptor {
20 uint16_t type_kind;
21 uint16_t type_info;
22 char type_name[1];
23 };
24
25 struct type_mismatch_data {
26 struct source_location loc;
27 struct type_descriptor *type;
28 unsigned long alignment;
29 unsigned char type_check_kind;
30 };
31
32 struct overflow_data {
33 struct source_location loc;
34 struct type_descriptor *type;
35 };
36
37 struct shift_out_of_bounds_data {
38 struct source_location loc;
39 struct type_descriptor *lhs_type;
40 struct type_descriptor *rhs_type;
41 };
42
43 struct out_of_bounds_data {
44 struct source_location loc;
45 struct type_descriptor *array_type;
46 struct type_descriptor *index_type;
47 };
48
49 struct unreachable_data {
50 struct source_location loc;
51 };
52
53 struct vla_bound_data {
54 struct source_location loc;
55 struct type_descriptor *type;
56 };
57
58 struct invalid_value_data {
59 struct source_location loc;
60 struct type_descriptor *type;
61 };
62
63 struct nonnull_arg_data {
64 struct source_location loc;
65 };
66
67 /*
68 * When compiling with -fsanitize=undefined the compiler expects functions
69 * with the following signatures. The functions are never called directly,
70 * only when undefined behavior is detected in instrumented code.
71 */
72 void __ubsan_handle_type_mismatch_abort(struct type_mismatch_data *data,
73 unsigned long ptr);
74 void __ubsan_handle_type_mismatch_v1_abort(struct type_mismatch_data *data,
75 unsigned long ptr);
76 void __ubsan_handle_add_overflow_abort(struct overflow_data *data,
77 unsigned long lhs, unsigned long rhs);
78 void __ubsan_handle_sub_overflow_abort(struct overflow_data *data,
79 unsigned long lhs, unsigned long rhs);
80 void __ubsan_handle_mul_overflow_abort(struct overflow_data *data,
81 unsigned long lhs, unsigned long rhs);
82 void __ubsan_handle_negate_overflow_abort(struct overflow_data *data,
83 unsigned long old_val);
84 void __ubsan_handle_pointer_overflow_abort(struct overflow_data *data,
85 unsigned long old_val);
86 void __ubsan_handle_divrem_overflow_abort(struct overflow_data *data,
87 unsigned long lhs, unsigned long rhs);
88 void __ubsan_handle_shift_out_of_bounds_abort(struct shift_out_of_bounds_data *data,
89 unsigned long lhs, unsigned long rhs);
90 void __ubsan_handle_out_of_bounds_abort(struct out_of_bounds_data *data,
91 unsigned long idx);
92 void __ubsan_handle_unreachable_abort(struct unreachable_data *data);
93 void __ubsan_handle_missing_return_abort(struct unreachable_data *data);
94 void __ubsan_handle_vla_bound_not_positive_abort(struct vla_bound_data *data,
95 unsigned long bound);
96 void __ubsan_handle_load_invalid_value_abort(struct invalid_value_data *data,
97 unsigned long val);
98 void __ubsan_handle_nonnull_arg_abort(struct nonnull_arg_data *data
99 #if __GCC_VERSION < 60000
100 , size_t arg_no
101 #endif
102 );
103
print_loc(const char * func,struct source_location * loc)104 static void print_loc(const char *func, struct source_location *loc)
105 {
106 ERROR("Undefined behavior at %s:%d col %d (%s)",
107 loc->file_name, loc->line, loc->column, func);
108 }
109
110
__ubsan_handle_type_mismatch_abort(struct type_mismatch_data * data,unsigned long ptr __unused)111 void __ubsan_handle_type_mismatch_abort(struct type_mismatch_data *data,
112 unsigned long ptr __unused)
113 {
114 print_loc(__func__, &data->loc);
115 plat_panic_handler();
116 }
117
__ubsan_handle_type_mismatch_v1_abort(struct type_mismatch_data * data,unsigned long ptr __unused)118 void __ubsan_handle_type_mismatch_v1_abort(struct type_mismatch_data *data,
119 unsigned long ptr __unused)
120 {
121 print_loc(__func__, &data->loc);
122 plat_panic_handler();
123 }
124
__ubsan_handle_add_overflow_abort(struct overflow_data * data,unsigned long lhs __unused,unsigned long rhs __unused)125 void __ubsan_handle_add_overflow_abort(struct overflow_data *data,
126 unsigned long lhs __unused,
127 unsigned long rhs __unused)
128 {
129 print_loc(__func__, &data->loc);
130 plat_panic_handler();
131 }
132
__ubsan_handle_sub_overflow_abort(struct overflow_data * data,unsigned long lhs __unused,unsigned long rhs __unused)133 void __ubsan_handle_sub_overflow_abort(struct overflow_data *data,
134 unsigned long lhs __unused,
135 unsigned long rhs __unused)
136 {
137 print_loc(__func__, &data->loc);
138 plat_panic_handler();
139 }
140
__ubsan_handle_mul_overflow_abort(struct overflow_data * data,unsigned long lhs __unused,unsigned long rhs __unused)141 void __ubsan_handle_mul_overflow_abort(struct overflow_data *data,
142 unsigned long lhs __unused,
143 unsigned long rhs __unused)
144 {
145 print_loc(__func__, &data->loc);
146 plat_panic_handler();
147 }
148
__ubsan_handle_negate_overflow_abort(struct overflow_data * data,unsigned long old_val __unused)149 void __ubsan_handle_negate_overflow_abort(struct overflow_data *data,
150 unsigned long old_val __unused)
151 {
152 print_loc(__func__, &data->loc);
153 plat_panic_handler();
154 }
155
__ubsan_handle_pointer_overflow_abort(struct overflow_data * data,unsigned long old_val __unused)156 void __ubsan_handle_pointer_overflow_abort(struct overflow_data *data,
157 unsigned long old_val __unused)
158 {
159 print_loc(__func__, &data->loc);
160 plat_panic_handler();
161 }
162
__ubsan_handle_divrem_overflow_abort(struct overflow_data * data,unsigned long lhs __unused,unsigned long rhs __unused)163 void __ubsan_handle_divrem_overflow_abort(struct overflow_data *data,
164 unsigned long lhs __unused,
165 unsigned long rhs __unused)
166 {
167 print_loc(__func__, &data->loc);
168 plat_panic_handler();
169 }
170
__ubsan_handle_shift_out_of_bounds_abort(struct shift_out_of_bounds_data * data,unsigned long lhs __unused,unsigned long rhs __unused)171 void __ubsan_handle_shift_out_of_bounds_abort(struct shift_out_of_bounds_data *data,
172 unsigned long lhs __unused,
173 unsigned long rhs __unused)
174 {
175 print_loc(__func__, &data->loc);
176 plat_panic_handler();
177 }
178
__ubsan_handle_out_of_bounds_abort(struct out_of_bounds_data * data,unsigned long idx __unused)179 void __ubsan_handle_out_of_bounds_abort(struct out_of_bounds_data *data,
180 unsigned long idx __unused)
181 {
182 print_loc(__func__, &data->loc);
183 plat_panic_handler();
184 }
185
__ubsan_handle_unreachable_abort(struct unreachable_data * data)186 void __ubsan_handle_unreachable_abort(struct unreachable_data *data)
187 {
188 print_loc(__func__, &data->loc);
189 plat_panic_handler();
190 }
191
__ubsan_handle_missing_return_abort(struct unreachable_data * data)192 void __ubsan_handle_missing_return_abort(struct unreachable_data *data)
193 {
194 print_loc(__func__, &data->loc);
195 plat_panic_handler();
196 }
197
__ubsan_handle_vla_bound_not_positive_abort(struct vla_bound_data * data,unsigned long bound __unused)198 void __ubsan_handle_vla_bound_not_positive_abort(struct vla_bound_data *data,
199 unsigned long bound __unused)
200 {
201 print_loc(__func__, &data->loc);
202 plat_panic_handler();
203 }
204
__ubsan_handle_load_invalid_value_abort(struct invalid_value_data * data,unsigned long val __unused)205 void __ubsan_handle_load_invalid_value_abort(struct invalid_value_data *data,
206 unsigned long val __unused)
207 {
208 print_loc(__func__, &data->loc);
209 plat_panic_handler();
210 }
211
__ubsan_handle_nonnull_arg_abort(struct nonnull_arg_data * data,size_t arg_no __unused)212 void __ubsan_handle_nonnull_arg_abort(struct nonnull_arg_data *data
213 #if __GCC_VERSION < 60000
214 , size_t arg_no __unused
215 #endif
216 )
217 {
218 print_loc(__func__, &data->loc);
219 plat_panic_handler();
220 }
221