forked from Bananymous/banan-os
Kernel: Add ubsan
My brain has been melting since I'm getting very random bugs. I hope I can debug them better with ubsan :)
This commit is contained in:
parent
e480f9c195
commit
06db890d49
|
@ -18,6 +18,8 @@ export INCLUDEDIR=$PREFIX/include
|
|||
export CFLAGS='-O2 -g'
|
||||
export CPPFLAGS='--std=c++20'
|
||||
|
||||
export UBSAN=1
|
||||
|
||||
# Configure the cross-compiler to use the desired system root.
|
||||
export SYSROOT="$(pwd)/sysroot"
|
||||
export CC="$CC --sysroot=$SYSROOT"
|
||||
|
|
|
@ -27,6 +27,10 @@ CPPFLAGS:=$(CPPFLAGS) $(KERNEL_ARCH_CPPFLAGS)
|
|||
LDFLAGS:=$(LDFLAGS) $(KERNEL_ARCH_LDFLAGS)
|
||||
LIBS:=$(LIBS) $(KERNEL_ARCH_LIBS)
|
||||
|
||||
ifeq ($(UBSAN), 1)
|
||||
CFLAGS:=$(CFLAGS) -fsanitize=undefined
|
||||
endif
|
||||
|
||||
BUILDDIR=$(abspath build)
|
||||
|
||||
KERNEL_OBJS= \
|
||||
|
@ -58,6 +62,7 @@ kernel/Thread.o \
|
|||
kernel/TTY.o \
|
||||
kernel/VesaTerminalDriver.o \
|
||||
icxxabi.o \
|
||||
ubsan.o \
|
||||
|
||||
OBJS= \
|
||||
$(ARCHDIR)/crti.o \
|
||||
|
|
|
@ -47,9 +47,9 @@ MMU::MMU()
|
|||
m_highest_paging_struct[i] = (uint64_t)page_directory | Flags::Present;
|
||||
}
|
||||
|
||||
// create and identity map first 4 MiB
|
||||
// create and identity map first 6 MiB
|
||||
uint64_t* page_directory1 = (uint64_t*)(m_highest_paging_struct[0] & PAGE_MASK);
|
||||
for (uint64_t i = 0; i < 2; i++)
|
||||
for (uint64_t i = 0; i < 3; i++)
|
||||
{
|
||||
uint64_t* page_table = allocate_page_aligned_page();
|
||||
for (uint64_t j = 0; j < 512; j++)
|
||||
|
|
|
@ -118,9 +118,10 @@ enable_sse:
|
|||
ret
|
||||
|
||||
initialize_paging:
|
||||
# identity map first 4 MiB
|
||||
# identity map first 6 MiB
|
||||
movl $(0x00000000 + 0x83), boot_page_directory1 + 0
|
||||
movl $(0x00200000 + 0x83), boot_page_directory1 + 8
|
||||
movl $(0x00400000 + 0x83), boot_page_directory1 + 16
|
||||
movl $(boot_page_directory1 + 0x01), boot_page_directory_pointer_table
|
||||
|
||||
# enable PAE
|
||||
|
|
|
@ -35,7 +35,7 @@ static uint64_t* allocate_page_aligned_page()
|
|||
|
||||
MMU::MMU()
|
||||
{
|
||||
// Identity map from 4 KiB -> 4 MiB
|
||||
// Identity map from 4 KiB -> 6 MiB
|
||||
m_highest_paging_struct = allocate_page_aligned_page();
|
||||
|
||||
uint64_t* pdpt = allocate_page_aligned_page();
|
||||
|
@ -44,7 +44,7 @@ MMU::MMU()
|
|||
uint64_t* pd = allocate_page_aligned_page();
|
||||
pdpt[0] = (uint64_t)pd | Flags::ReadWrite | Flags::Present;
|
||||
|
||||
for (uint32_t i = 0; i < 2; i++)
|
||||
for (uint32_t i = 0; i < 3; i++)
|
||||
{
|
||||
uint64_t* pt = allocate_page_aligned_page();
|
||||
for (uint64_t j = 0; j < 512; j++)
|
||||
|
|
|
@ -41,9 +41,9 @@
|
|||
# we will identity map first 4 MiB
|
||||
|
||||
# 0 MiB -> 1 MiB: bootloader stuff
|
||||
# 1 MiB -> 2 MiB: kernel
|
||||
# 2 MiB -> 3 MiB: kmalloc
|
||||
# 3 MiB -> 4 MiB: kmalloc_fixed
|
||||
# 1 MiB -> 4 MiB: kernel
|
||||
# 4 MiB -> 5 MiB: kmalloc
|
||||
# 5 MiB -> 6 MiB: kmalloc_fixed
|
||||
.align 4096
|
||||
boot_pml4:
|
||||
.skip 512 * 8
|
||||
|
@ -127,9 +127,10 @@ enable_sse:
|
|||
ret
|
||||
|
||||
initialize_paging:
|
||||
# identity map first 4 MiB
|
||||
# identity map first 6 MiB
|
||||
movl $(0x00000000 + PG_PAGE_SIZE + PG_READ_WRITE + PG_PRESENT), boot_pd1 + 0
|
||||
movl $(0x00200000 + PG_PAGE_SIZE + PG_READ_WRITE + PG_PRESENT), boot_pd1 + 8
|
||||
movl $(0x00400000 + PG_PAGE_SIZE + PG_READ_WRITE + PG_PRESENT), boot_pd1 + 16
|
||||
|
||||
# set pdpte1 and pml4e1
|
||||
movl $(boot_pd1 + PG_READ_WRITE + PG_PRESENT), boot_pdpt1
|
||||
|
|
|
@ -65,7 +65,7 @@ private:
|
|||
static_assert(sizeof(kmalloc_node) == s_kmalloc_min_align);
|
||||
struct kmalloc_info
|
||||
{
|
||||
static constexpr uintptr_t base = 0x00200000;
|
||||
static constexpr uintptr_t base = 0x00400000;
|
||||
static constexpr size_t size = 1 * MB;
|
||||
static constexpr uintptr_t end = base + size;
|
||||
|
||||
|
@ -313,11 +313,10 @@ void* kmalloc(size_t size, size_t align)
|
|||
if (size == 0 || size >= info.size)
|
||||
return nullptr;
|
||||
|
||||
ASSERT(align);
|
||||
ASSERT(is_power_of_two(align));
|
||||
|
||||
// if the size fits into fixed node, we will try to use that since it is faster
|
||||
if (align == s_kmalloc_min_align && size < sizeof(kmalloc_fixed_info::node::data))
|
||||
if (align == s_kmalloc_min_align && size <= sizeof(kmalloc_fixed_info::node::data))
|
||||
if (void* result = kmalloc_fixed())
|
||||
return result;
|
||||
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
#include <kernel/Debug.h>
|
||||
#include <kernel/Panic.h>
|
||||
|
||||
extern "C"
|
||||
{
|
||||
|
||||
struct source_location
|
||||
{
|
||||
const char *file;
|
||||
uint32_t line;
|
||||
uint32_t column;
|
||||
};
|
||||
|
||||
struct type_descriptor
|
||||
{
|
||||
uint16_t kind;
|
||||
uint16_t info;
|
||||
char name[1];
|
||||
};
|
||||
|
||||
struct type_mismatch_data
|
||||
{
|
||||
source_location location;
|
||||
const type_descriptor& type;
|
||||
uint8_t alignment;
|
||||
uint8_t type_check_kind;
|
||||
};
|
||||
|
||||
struct out_of_bounds_data
|
||||
{
|
||||
source_location location;
|
||||
const type_descriptor& left_type;
|
||||
const type_descriptor& right_type;
|
||||
};
|
||||
|
||||
struct shift_out_of_bounds_data
|
||||
{
|
||||
source_location location;
|
||||
const type_descriptor& left_type;
|
||||
const type_descriptor& right_type;
|
||||
};
|
||||
|
||||
struct pointer_overflow_data
|
||||
{
|
||||
source_location location;
|
||||
};
|
||||
|
||||
struct invalid_value_data
|
||||
{
|
||||
source_location location;
|
||||
const type_descriptor& type;
|
||||
};
|
||||
|
||||
struct overflow_data
|
||||
{
|
||||
source_location location;
|
||||
const type_descriptor& type;
|
||||
};
|
||||
|
||||
using value_handle = uintptr_t;
|
||||
|
||||
static const char* type_check_kinds[] = {
|
||||
"load of", "store to", "reference binding to", "member access within",
|
||||
"member call on", "constructor call on", "downcast of", "downcast of",
|
||||
"upcast of", "cast to virtual base of", "_Nonnull binding to",
|
||||
"dynamic operation on"
|
||||
};
|
||||
|
||||
#define HANDLER(handler, fatal, ...) \
|
||||
void handler(__VA_ARGS__) \
|
||||
{ \
|
||||
if constexpr(fatal) \
|
||||
Kernel::panic("{}:{} {}", data->location.file, data->location.line, __FUNCTION__); \
|
||||
else \
|
||||
derrorln("{}:{} {}", data->location.file, data->location.line, __FUNCTION__); \
|
||||
}
|
||||
|
||||
static void print_location_impl(const source_location& location, const char* function)
|
||||
{
|
||||
derrorln("{}:{} {}", location.file, location.line, function);
|
||||
}
|
||||
#define print_location(location) print_location_impl(location, __FUNCTION__)
|
||||
|
||||
HANDLER(__ubsan_handle_pointer_overflow, false, pointer_overflow_data* data, value_handle, value_handle)
|
||||
HANDLER(__ubsan_handle_load_invalid_value, false, invalid_value_data* data, value_handle)
|
||||
HANDLER(__ubsan_handle_out_of_bounds, false, out_of_bounds_data* data, value_handle)
|
||||
HANDLER(__ubsan_handle_shift_out_of_bounds, false, shift_out_of_bounds_data* data, value_handle, value_handle)
|
||||
|
||||
HANDLER(__ubsan_handle_add_overflow, false, overflow_data* data, value_handle, value_handle)
|
||||
HANDLER(__ubsan_handle_sub_overflow, false, overflow_data* data, value_handle, value_handle)
|
||||
HANDLER(__ubsan_handle_mul_overflow, false, overflow_data* data, value_handle, value_handle)
|
||||
HANDLER(__ubsan_handle_divrem_overflow, false, overflow_data* data, value_handle, value_handle)
|
||||
HANDLER(__ubsan_handle_negate_overflow, false, overflow_data* data, value_handle)
|
||||
|
||||
void __ubsan_handle_type_mismatch_v1(type_mismatch_data* data, value_handle pointer)
|
||||
{
|
||||
print_location(data->location);
|
||||
const char* kind = type_check_kinds[data->type_check_kind];
|
||||
uintptr_t alignment = (uintptr_t)1 << data->alignment;
|
||||
if (!pointer)
|
||||
derrorln("{} null pointer of type {}", kind, data->type.name);
|
||||
else if (pointer & (alignment - 1))
|
||||
derrorln("{} misaligned address {} for type {}, which requires {} byte alignment", kind, (void*)pointer, data->type.name, alignment);
|
||||
else
|
||||
derrorln("{} address {} with insufficient space for an object of type {}", kind, (void*)pointer, data->type.name);
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue