221 lines
5.8 KiB
C
221 lines
5.8 KiB
C
/*
|
|
* Copyright (c) 2016, Linaro Limited
|
|
* Copyright (c) 2019, ARM Limited. All rights reserved.
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#include <arch_helpers.h>
|
|
#include <context.h>
|
|
#include <common/debug.h>
|
|
#include <plat/common/platform.h>
|
|
|
|
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();
|
|
}
|