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 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 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 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 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 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 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 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 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 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 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 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 186 void __ubsan_handle_unreachable_abort(struct unreachable_data *data) 187 { 188 print_loc(__func__, &data->loc); 189 plat_panic_handler(); 190 } 191 192 void __ubsan_handle_missing_return_abort(struct unreachable_data *data) 193 { 194 print_loc(__func__, &data->loc); 195 plat_panic_handler(); 196 } 197 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 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 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