Files
empty/lib/ubsan.c
2025-10-26 15:21:48 +01:00

155 lines
5.1 KiB
C

#include <stdint.h>
#include <stddef.h>
#include <arch/bsp/yellow_led.h>
#include <config.h>
#define halt() \
do { \
asm("cpsid if"); \
while (true) { \
asm("wfi"); \
} \
} while (0)
void kprintf [[gnu::format(printf, 1, 2)]] (const char *format, ...);
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wsuggest-attribute=noreturn"
void kprintf [[gnu::weak, gnu::format(printf, 1, 2)]] (const char *, ...)
{
init_yellow();
while (true) {
for (volatile unsigned int i = 0; i < BUSY_WAIT_COUNTER; i++) {
}
yellow_on();
for (volatile unsigned int i = 0; i < BUSY_WAIT_COUNTER; i++) {
}
yellow_off();
}
}
#pragma GCC diagnostic pop
// structs copyed form the linux kernel
// https://github.com/torvalds/linux/blob/master/lib/ubsan.h
struct source_location {
const char *file_name;
const uint32_t line;
const uint32_t column;
};
struct type_descriptor {
const uint16_t type_kind;
const uint16_t type_info;
const char type_name[1];
const char unused[3];
};
struct type_mismatch_data_v1 {
const struct source_location location;
const struct type_descriptor *type;
const unsigned char log_alignment;
const unsigned char type_check_kind;
const char unused[2];
};
struct out_of_bounds_data {
struct source_location loc;
struct type_descriptor *array_type;
struct type_descriptor *index_type;
};
static_assert(sizeof(unsigned int) == sizeof(long));
static void print_source_location(const struct source_location *location)
{
kprintf("%s:%u:%u", location->file_name, (unsigned int)location->line,
(unsigned int)location->column);
}
#define DEF_UBSAN_HANDLER(name) \
void __ubsan_handle_##name [[noreturn]] (const struct source_location *location); \
void __ubsan_handle_##name [[noreturn]] (const struct source_location *location) \
{ \
kprintf("Undefined behavior detected: " #name " at "); \
print_source_location(location); \
kprintf("\n"); \
halt(); \
}
DEF_UBSAN_HANDLER(add_overflow)
DEF_UBSAN_HANDLER(add_overflow_abort)
DEF_UBSAN_HANDLER(alignment_assumption)
DEF_UBSAN_HANDLER(builtin_unreachable)
DEF_UBSAN_HANDLER(alignment_assumption_abort)
DEF_UBSAN_HANDLER(cfi_check_fail)
DEF_UBSAN_HANDLER(cfi_bad_type)
DEF_UBSAN_HANDLER(divrem_overflow)
DEF_UBSAN_HANDLER(cfi_check_fail_abort)
DEF_UBSAN_HANDLER(dynamic_type_cache_miss)
DEF_UBSAN_HANDLER(divrem_overflow_abort)
DEF_UBSAN_HANDLER(float_cast_overflow)
DEF_UBSAN_HANDLER(dynamic_type_cache_miss_abort)
DEF_UBSAN_HANDLER(function_type_mismatch_v1)
DEF_UBSAN_HANDLER(float_cast_overflow_abort)
DEF_UBSAN_HANDLER(implicit_conversion)
DEF_UBSAN_HANDLER(function_type_mismatch_v1_abort)
DEF_UBSAN_HANDLER(invalid_builtin)
DEF_UBSAN_HANDLER(implicit_conversion_abort)
DEF_UBSAN_HANDLER(invalid_objc_cast)
DEF_UBSAN_HANDLER(invalid_builtin_abort)
DEF_UBSAN_HANDLER(load_invalid_value)
DEF_UBSAN_HANDLER(invalid_objc_cast_abort)
DEF_UBSAN_HANDLER(missing_return)
DEF_UBSAN_HANDLER(load_invalid_value_abort)
DEF_UBSAN_HANDLER(mul_overflow_abort)
DEF_UBSAN_HANDLER(mul_overflow)
DEF_UBSAN_HANDLER(negate_overflow_abort)
DEF_UBSAN_HANDLER(negate_overflow)
DEF_UBSAN_HANDLER(nonnull_arg_abort)
DEF_UBSAN_HANDLER(nonnull_arg)
DEF_UBSAN_HANDLER(nonnull_return_v1_abort)
DEF_UBSAN_HANDLER(nonnull_return_v1)
DEF_UBSAN_HANDLER(nullability_arg_abort)
DEF_UBSAN_HANDLER(nullability_arg)
DEF_UBSAN_HANDLER(nullability_return_v1_abort)
DEF_UBSAN_HANDLER(nullability_return_v1)
DEF_UBSAN_HANDLER(out_of_bounds_abort)
DEF_UBSAN_HANDLER(pointer_overflow_abort)
DEF_UBSAN_HANDLER(pointer_overflow)
DEF_UBSAN_HANDLER(shift_out_of_bounds_abort)
DEF_UBSAN_HANDLER(shift_out_of_bounds)
DEF_UBSAN_HANDLER(sub_overflow_abort)
DEF_UBSAN_HANDLER(sub_overflow)
DEF_UBSAN_HANDLER(type_mismatch_v1_abort)
DEF_UBSAN_HANDLER(vla_bound_not_positive_abort)
DEF_UBSAN_HANDLER(vla_bound_not_positive)
void __ubsan_handle_out_of_bounds
[[noreturn]] (struct out_of_bounds_data *data, unsigned long index);
void __ubsan_handle_out_of_bounds
[[noreturn]] (struct out_of_bounds_data *data, unsigned long index)
{
kprintf("Undefined behavior detected: out of bounds access index %u at ",
(unsigned int)index);
print_source_location(&data->loc);
kprintf("\n");
halt();
}
void __ubsan_handle_type_mismatch_v1 [[noreturn]] (struct type_mismatch_data_v1 *data_v1, int ptr);
void __ubsan_handle_type_mismatch_v1 [[noreturn]] (struct type_mismatch_data_v1 *data_v1, int ptr)
{
if (ptr == (uint32_t)NULL) {
kprintf("Undefined behavior detected: null pointer access at ");
} else if (data_v1->log_alignment && (ptr & (data_v1->log_alignment - 1))) {
kprintf("Undefined behavior detected: unaligned access at ");
} else {
kprintf("Undefined behavior detected: type mismatch at ");
}
print_source_location(&data_v1->location);
kprintf("\n");
halt();
}