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