/* * Copyright (c) 2016, Linaro Limited * Copyright (c) 2019, ARM Limited. All rights reserved. * * SPDX-License-Identifier: BSD-2-Clause */ #include #include #include #include struct source_location { const char *file_name; uint32_t line; uint32_t column; }; struct type_descriptor { uint16_t type_kind; uint16_t type_info; char type_name[1]; }; struct type_mismatch_data { struct source_location loc; struct type_descriptor *type; unsigned long alignment; unsigned char type_check_kind; }; struct overflow_data { struct source_location loc; struct type_descriptor *type; }; struct shift_out_of_bounds_data { struct source_location loc; struct type_descriptor *lhs_type; struct type_descriptor *rhs_type; }; struct out_of_bounds_data { struct source_location loc; struct type_descriptor *array_type; struct type_descriptor *index_type; }; struct unreachable_data { struct source_location loc; }; struct vla_bound_data { struct source_location loc; struct type_descriptor *type; }; struct invalid_value_data { struct source_location loc; struct type_descriptor *type; }; struct nonnull_arg_data { struct source_location loc; }; /* * When compiling with -fsanitize=undefined the compiler expects functions * with the following signatures. The functions are never called directly, * only when undefined behavior is detected in instrumented code. */ void __ubsan_handle_type_mismatch_abort(struct type_mismatch_data *data, unsigned long ptr); void __ubsan_handle_type_mismatch_v1_abort(struct type_mismatch_data *data, unsigned long ptr); void __ubsan_handle_add_overflow_abort(struct overflow_data *data, unsigned long lhs, unsigned long rhs); void __ubsan_handle_sub_overflow_abort(struct overflow_data *data, unsigned long lhs, unsigned long rhs); void __ubsan_handle_mul_overflow_abort(struct overflow_data *data, unsigned long lhs, unsigned long rhs); void __ubsan_handle_negate_overflow_abort(struct overflow_data *data, unsigned long old_val); void __ubsan_handle_pointer_overflow_abort(struct overflow_data *data, unsigned long old_val); void __ubsan_handle_divrem_overflow_abort(struct overflow_data *data, unsigned long lhs, unsigned long rhs); void __ubsan_handle_shift_out_of_bounds_abort(struct shift_out_of_bounds_data *data, unsigned long lhs, unsigned long rhs); void __ubsan_handle_out_of_bounds_abort(struct out_of_bounds_data *data, unsigned long idx); void __ubsan_handle_unreachable_abort(struct unreachable_data *data); void __ubsan_handle_missing_return_abort(struct unreachable_data *data); void __ubsan_handle_vla_bound_not_positive_abort(struct vla_bound_data *data, unsigned long bound); void __ubsan_handle_load_invalid_value_abort(struct invalid_value_data *data, unsigned long val); void __ubsan_handle_nonnull_arg_abort(struct nonnull_arg_data *data #if __GCC_VERSION < 60000 , size_t arg_no #endif ); static void print_loc(const char *func, struct source_location *loc) { ERROR("Undefined behavior at %s:%d col %d (%s)", loc->file_name, loc->line, loc->column, func); } void __ubsan_handle_type_mismatch_abort(struct type_mismatch_data *data, unsigned long ptr __unused) { print_loc(__func__, &data->loc); plat_panic_handler(); } void __ubsan_handle_type_mismatch_v1_abort(struct type_mismatch_data *data, unsigned long ptr __unused) { print_loc(__func__, &data->loc); plat_panic_handler(); } void __ubsan_handle_add_overflow_abort(struct overflow_data *data, unsigned long lhs __unused, unsigned long rhs __unused) { print_loc(__func__, &data->loc); plat_panic_handler(); } void __ubsan_handle_sub_overflow_abort(struct overflow_data *data, unsigned long lhs __unused, unsigned long rhs __unused) { print_loc(__func__, &data->loc); plat_panic_handler(); } void __ubsan_handle_mul_overflow_abort(struct overflow_data *data, unsigned long lhs __unused, unsigned long rhs __unused) { print_loc(__func__, &data->loc); plat_panic_handler(); } void __ubsan_handle_negate_overflow_abort(struct overflow_data *data, unsigned long old_val __unused) { print_loc(__func__, &data->loc); plat_panic_handler(); } void __ubsan_handle_pointer_overflow_abort(struct overflow_data *data, unsigned long old_val __unused) { print_loc(__func__, &data->loc); plat_panic_handler(); } void __ubsan_handle_divrem_overflow_abort(struct overflow_data *data, unsigned long lhs __unused, unsigned long rhs __unused) { print_loc(__func__, &data->loc); plat_panic_handler(); } void __ubsan_handle_shift_out_of_bounds_abort(struct shift_out_of_bounds_data *data, unsigned long lhs __unused, unsigned long rhs __unused) { print_loc(__func__, &data->loc); plat_panic_handler(); } void __ubsan_handle_out_of_bounds_abort(struct out_of_bounds_data *data, unsigned long idx __unused) { print_loc(__func__, &data->loc); plat_panic_handler(); } void __ubsan_handle_unreachable_abort(struct unreachable_data *data) { print_loc(__func__, &data->loc); plat_panic_handler(); } void __ubsan_handle_missing_return_abort(struct unreachable_data *data) { print_loc(__func__, &data->loc); plat_panic_handler(); } void __ubsan_handle_vla_bound_not_positive_abort(struct vla_bound_data *data, unsigned long bound __unused) { print_loc(__func__, &data->loc); plat_panic_handler(); } void __ubsan_handle_load_invalid_value_abort(struct invalid_value_data *data, unsigned long val __unused) { print_loc(__func__, &data->loc); plat_panic_handler(); } void __ubsan_handle_nonnull_arg_abort(struct nonnull_arg_data *data #if __GCC_VERSION < 60000 , size_t arg_no __unused #endif ) { print_loc(__func__, &data->loc); plat_panic_handler(); }