162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci#ifndef _LIB_UBSAN_H
362306a36Sopenharmony_ci#define _LIB_UBSAN_H
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci/*
662306a36Sopenharmony_ci * ABI defined by Clang's UBSAN enum SanitizerHandler:
762306a36Sopenharmony_ci * https://github.com/llvm/llvm-project/blob/release/16.x/clang/lib/CodeGen/CodeGenFunction.h#L113
862306a36Sopenharmony_ci */
962306a36Sopenharmony_cienum ubsan_checks {
1062306a36Sopenharmony_ci	ubsan_add_overflow,
1162306a36Sopenharmony_ci	ubsan_builtin_unreachable,
1262306a36Sopenharmony_ci	ubsan_cfi_check_fail,
1362306a36Sopenharmony_ci	ubsan_divrem_overflow,
1462306a36Sopenharmony_ci	ubsan_dynamic_type_cache_miss,
1562306a36Sopenharmony_ci	ubsan_float_cast_overflow,
1662306a36Sopenharmony_ci	ubsan_function_type_mismatch,
1762306a36Sopenharmony_ci	ubsan_implicit_conversion,
1862306a36Sopenharmony_ci	ubsan_invalid_builtin,
1962306a36Sopenharmony_ci	ubsan_invalid_objc_cast,
2062306a36Sopenharmony_ci	ubsan_load_invalid_value,
2162306a36Sopenharmony_ci	ubsan_missing_return,
2262306a36Sopenharmony_ci	ubsan_mul_overflow,
2362306a36Sopenharmony_ci	ubsan_negate_overflow,
2462306a36Sopenharmony_ci	ubsan_nullability_arg,
2562306a36Sopenharmony_ci	ubsan_nullability_return,
2662306a36Sopenharmony_ci	ubsan_nonnull_arg,
2762306a36Sopenharmony_ci	ubsan_nonnull_return,
2862306a36Sopenharmony_ci	ubsan_out_of_bounds,
2962306a36Sopenharmony_ci	ubsan_pointer_overflow,
3062306a36Sopenharmony_ci	ubsan_shift_out_of_bounds,
3162306a36Sopenharmony_ci	ubsan_sub_overflow,
3262306a36Sopenharmony_ci	ubsan_type_mismatch,
3362306a36Sopenharmony_ci	ubsan_alignment_assumption,
3462306a36Sopenharmony_ci	ubsan_vla_bound_not_positive,
3562306a36Sopenharmony_ci};
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_cienum {
3862306a36Sopenharmony_ci	type_kind_int = 0,
3962306a36Sopenharmony_ci	type_kind_float = 1,
4062306a36Sopenharmony_ci	type_unknown = 0xffff
4162306a36Sopenharmony_ci};
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_cistruct type_descriptor {
4462306a36Sopenharmony_ci	u16 type_kind;
4562306a36Sopenharmony_ci	u16 type_info;
4662306a36Sopenharmony_ci	char type_name[1];
4762306a36Sopenharmony_ci};
4862306a36Sopenharmony_ci
4962306a36Sopenharmony_cistruct source_location {
5062306a36Sopenharmony_ci	const char *file_name;
5162306a36Sopenharmony_ci	union {
5262306a36Sopenharmony_ci		unsigned long reported;
5362306a36Sopenharmony_ci		struct {
5462306a36Sopenharmony_ci			u32 line;
5562306a36Sopenharmony_ci			u32 column;
5662306a36Sopenharmony_ci		};
5762306a36Sopenharmony_ci	};
5862306a36Sopenharmony_ci};
5962306a36Sopenharmony_ci
6062306a36Sopenharmony_cistruct overflow_data {
6162306a36Sopenharmony_ci	struct source_location location;
6262306a36Sopenharmony_ci	struct type_descriptor *type;
6362306a36Sopenharmony_ci};
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_cistruct type_mismatch_data {
6662306a36Sopenharmony_ci	struct source_location location;
6762306a36Sopenharmony_ci	struct type_descriptor *type;
6862306a36Sopenharmony_ci	unsigned long alignment;
6962306a36Sopenharmony_ci	unsigned char type_check_kind;
7062306a36Sopenharmony_ci};
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_cistruct type_mismatch_data_v1 {
7362306a36Sopenharmony_ci	struct source_location location;
7462306a36Sopenharmony_ci	struct type_descriptor *type;
7562306a36Sopenharmony_ci	unsigned char log_alignment;
7662306a36Sopenharmony_ci	unsigned char type_check_kind;
7762306a36Sopenharmony_ci};
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_cistruct type_mismatch_data_common {
8062306a36Sopenharmony_ci	struct source_location *location;
8162306a36Sopenharmony_ci	struct type_descriptor *type;
8262306a36Sopenharmony_ci	unsigned long alignment;
8362306a36Sopenharmony_ci	unsigned char type_check_kind;
8462306a36Sopenharmony_ci};
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_cistruct nonnull_arg_data {
8762306a36Sopenharmony_ci	struct source_location location;
8862306a36Sopenharmony_ci	struct source_location attr_location;
8962306a36Sopenharmony_ci	int arg_index;
9062306a36Sopenharmony_ci};
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_cistruct out_of_bounds_data {
9362306a36Sopenharmony_ci	struct source_location location;
9462306a36Sopenharmony_ci	struct type_descriptor *array_type;
9562306a36Sopenharmony_ci	struct type_descriptor *index_type;
9662306a36Sopenharmony_ci};
9762306a36Sopenharmony_ci
9862306a36Sopenharmony_cistruct shift_out_of_bounds_data {
9962306a36Sopenharmony_ci	struct source_location location;
10062306a36Sopenharmony_ci	struct type_descriptor *lhs_type;
10162306a36Sopenharmony_ci	struct type_descriptor *rhs_type;
10262306a36Sopenharmony_ci};
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_cistruct unreachable_data {
10562306a36Sopenharmony_ci	struct source_location location;
10662306a36Sopenharmony_ci};
10762306a36Sopenharmony_ci
10862306a36Sopenharmony_cistruct invalid_value_data {
10962306a36Sopenharmony_ci	struct source_location location;
11062306a36Sopenharmony_ci	struct type_descriptor *type;
11162306a36Sopenharmony_ci};
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_cistruct alignment_assumption_data {
11462306a36Sopenharmony_ci	struct source_location location;
11562306a36Sopenharmony_ci	struct source_location assumption_location;
11662306a36Sopenharmony_ci	struct type_descriptor *type;
11762306a36Sopenharmony_ci};
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ci#if defined(CONFIG_ARCH_SUPPORTS_INT128)
12062306a36Sopenharmony_citypedef __int128 s_max;
12162306a36Sopenharmony_citypedef unsigned __int128 u_max;
12262306a36Sopenharmony_ci#else
12362306a36Sopenharmony_citypedef s64 s_max;
12462306a36Sopenharmony_citypedef u64 u_max;
12562306a36Sopenharmony_ci#endif
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_civoid __ubsan_handle_divrem_overflow(void *_data, void *lhs, void *rhs);
12862306a36Sopenharmony_civoid __ubsan_handle_type_mismatch(struct type_mismatch_data *data, void *ptr);
12962306a36Sopenharmony_civoid __ubsan_handle_type_mismatch_v1(void *_data, void *ptr);
13062306a36Sopenharmony_civoid __ubsan_handle_out_of_bounds(void *_data, void *index);
13162306a36Sopenharmony_civoid __ubsan_handle_shift_out_of_bounds(void *_data, void *lhs, void *rhs);
13262306a36Sopenharmony_civoid __ubsan_handle_builtin_unreachable(void *_data);
13362306a36Sopenharmony_civoid __ubsan_handle_load_invalid_value(void *_data, void *val);
13462306a36Sopenharmony_civoid __ubsan_handle_alignment_assumption(void *_data, unsigned long ptr,
13562306a36Sopenharmony_ci					 unsigned long align,
13662306a36Sopenharmony_ci					 unsigned long offset);
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci#endif
139