Fix unaligned word accesses
This commit is contained in:
+1
-37
@@ -86,43 +86,7 @@ void kernel_early_init(void) {
|
||||
cpuid_init();
|
||||
|
||||
if (multiboot_tag_sections) {
|
||||
kinfo("Loading kernel symbols\n");
|
||||
kinfo("%u section headers:\n", multiboot_tag_sections->num);
|
||||
size_t string_section_offset = multiboot_tag_sections->shndx * multiboot_tag_sections->entsize;
|
||||
Elf64_Shdr *string_section_hdr = (Elf64_Shdr *) &multiboot_tag_sections->sections[string_section_offset];
|
||||
const char *shstrtab = (const char *) MM_VIRTUALIZE(string_section_hdr->sh_addr);
|
||||
Elf64_Shdr *symtab_shdr = NULL, *strtab_shdr = NULL;
|
||||
|
||||
for (size_t i = 0; i < multiboot_tag_sections->num; ++i) {
|
||||
Elf64_Shdr *shdr = (Elf64_Shdr *) &multiboot_tag_sections->sections[i * multiboot_tag_sections->entsize];
|
||||
const char *name = &shstrtab[shdr->sh_name];
|
||||
switch (shdr->sh_type) {
|
||||
case SHT_SYMTAB:
|
||||
if (symtab_shdr) {
|
||||
panic("Kernel image has 2+ symbol tables\n");
|
||||
}
|
||||
symtab_shdr = shdr;
|
||||
break;
|
||||
case SHT_STRTAB:
|
||||
if (strcmp(name, ".strtab")) {
|
||||
break;
|
||||
}
|
||||
if (strtab_shdr) {
|
||||
panic("kernel image has 2+ string tables\n");
|
||||
}
|
||||
strtab_shdr = shdr;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (symtab_shdr && strtab_shdr) {
|
||||
uintptr_t symtab_ptr = MM_VIRTUALIZE(symtab_shdr->sh_addr);
|
||||
uintptr_t strtab_ptr = MM_VIRTUALIZE(strtab_shdr->sh_addr);
|
||||
|
||||
debug_symbol_table_set(symtab_ptr, strtab_ptr, symtab_shdr->sh_size, strtab_shdr->sh_size);
|
||||
}
|
||||
debug_symbol_table_multiboot2(multiboot_tag_sections);
|
||||
}
|
||||
|
||||
if (multiboot_tag_cmdline) {
|
||||
|
||||
@@ -38,7 +38,10 @@
|
||||
#define kfatal(f, ...) debugf(DEBUG_FATAL, "\033[41m" DEBUG_BASE_FMT f "\033[0m", DEBUG_BASE_ARGS, ##__VA_ARGS__)
|
||||
#define kprint(l, f, ...) debugf(l, DEBUG_BASE_FMT f, DEBUG_BASE_ARGS, ##__VA_ARGS__)
|
||||
|
||||
struct multiboot_tag_elf_sections;
|
||||
|
||||
void debug_symbol_table_set(uintptr_t symtab, uintptr_t strtab, size_t symtab_size, size_t strtab_size);
|
||||
void debug_symbol_table_multiboot2(struct multiboot_tag_elf_sections *tag);
|
||||
int debug_symbol_find(uintptr_t addr, const char **name, uintptr_t *base);
|
||||
int debug_symbol_find_by_name(const char *name, uintptr_t *value);
|
||||
void debug_backtrace(uintptr_t rbp, int depth, int limit);
|
||||
|
||||
@@ -5,6 +5,14 @@
|
||||
#pragma once
|
||||
#include "sys/types.h"
|
||||
|
||||
// A macro to properly read data from misaligned pointers, byte by byte
|
||||
// May be slower, but at least UBSan doesn't complain
|
||||
#define realigned(base, field) ({ \
|
||||
typeof(base->field) __v0; \
|
||||
memcpy(&__v0, (void *) (base) + offsetof(typeof(*base), field), sizeof(__v0)); \
|
||||
__v0; \
|
||||
})
|
||||
|
||||
#define MAX(x, y) ((x) > (y) ? (x) : (y))
|
||||
#define MIN(x, y) ((x) < (y) ? (x) : (y))
|
||||
|
||||
|
||||
+49
@@ -1,3 +1,4 @@
|
||||
#include "arch/amd64/multiboot2.h"
|
||||
#include "sys/string.h"
|
||||
#include "sys/debug.h"
|
||||
#include "sys/ctype.h"
|
||||
@@ -6,6 +7,8 @@
|
||||
#include "sys/config.h"
|
||||
#include "sys/elf.h"
|
||||
#include "sys/assert.h"
|
||||
#include "sys/mm.h"
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#if defined(ARCH_AMD64)
|
||||
@@ -20,6 +23,52 @@ static uintptr_t g_strtab_ptr = 0;
|
||||
static size_t g_symtab_size = 0;
|
||||
static size_t g_strtab_size = 0;
|
||||
|
||||
// Multiboot2-loaded sections are misaligned for some reason
|
||||
void debug_symbol_table_multiboot2(struct multiboot_tag_elf_sections *tag) {
|
||||
kinfo("Loading kernel symbols\n");
|
||||
kinfo("%u section headers:\n", tag->num);
|
||||
size_t string_section_offset = tag->shndx * tag->entsize;
|
||||
Elf64_Shdr *string_section_hdr = (Elf64_Shdr *) &tag->sections[string_section_offset];
|
||||
const char *shstrtab = (const char *) MM_VIRTUALIZE(realigned(string_section_hdr, sh_addr));
|
||||
|
||||
Elf64_Shdr *symtab_shdr = NULL, *strtab_shdr = NULL;
|
||||
|
||||
for (size_t i = 0; i < tag->num; ++i) {
|
||||
Elf64_Shdr *shdr = (Elf64_Shdr *) &tag->sections[i * tag->entsize];
|
||||
const char *name = &shstrtab[realigned(shdr, sh_name)];
|
||||
|
||||
switch (realigned(shdr, sh_type)) {
|
||||
case SHT_SYMTAB:
|
||||
if (symtab_shdr) {
|
||||
panic("Kernel image has 2+ symbol tables\n");
|
||||
}
|
||||
symtab_shdr = shdr;
|
||||
break;
|
||||
case SHT_STRTAB:
|
||||
if (strcmp(name, ".strtab")) {
|
||||
break;
|
||||
}
|
||||
if (strtab_shdr) {
|
||||
panic("kernel image has 2+ string tables\n");
|
||||
}
|
||||
strtab_shdr = shdr;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (symtab_shdr && strtab_shdr) {
|
||||
uintptr_t symtab_ptr = MM_VIRTUALIZE(realigned(symtab_shdr, sh_addr));
|
||||
uintptr_t strtab_ptr = MM_VIRTUALIZE(realigned(strtab_shdr, sh_addr));
|
||||
|
||||
debug_symbol_table_set(symtab_ptr,
|
||||
strtab_ptr,
|
||||
realigned(symtab_shdr, sh_size),
|
||||
realigned(strtab_shdr, sh_size));
|
||||
}
|
||||
}
|
||||
|
||||
void debug_symbol_table_set(uintptr_t s0, uintptr_t s1, size_t z0, size_t z1) {
|
||||
g_symtab_ptr = s0;
|
||||
g_symtab_size = z0;
|
||||
|
||||
@@ -143,7 +143,11 @@ static int elf_rela_apply(void *image, uintptr_t base, Elf64_Shdr *shdrs, Elf64_
|
||||
|
||||
switch (ELF64_R_TYPE(rela->r_info)) {
|
||||
case R_X86_64_64:
|
||||
*((uint64_t *) value_ptr) = (uint64_t) (value + (intptr_t) rela->r_addend);
|
||||
{
|
||||
uint64_t src = (uint64_t) (value + (intptr_t) rela->r_addend);
|
||||
// value_ptr most likely will be unaligned
|
||||
memcpy(value_ptr, &src, sizeof(uint64_t));
|
||||
}
|
||||
break;
|
||||
case R_X86_64_PLT32: // Treat this the same as PC32
|
||||
case R_X86_64_PC32:
|
||||
|
||||
+4
-4
@@ -2,8 +2,8 @@
|
||||
#include "sys/panic.h"
|
||||
#include "sys/debug.h"
|
||||
|
||||
//#define UBSAN_ABORT 1
|
||||
#undef UBSAN_ABORT
|
||||
#define UBSAN_ABORT 1
|
||||
//#undef UBSAN_ABORT
|
||||
|
||||
struct source_location {
|
||||
const char *file;
|
||||
@@ -123,7 +123,7 @@ void __ubsan_handle_vla_bound_not_positive(void *data_raw,
|
||||
struct type_mismatch_info {
|
||||
struct source_location location;
|
||||
struct type_descriptor *type;
|
||||
uintptr_t alignment;
|
||||
uint8_t alignment;
|
||||
uint8_t type_check_kind;
|
||||
};
|
||||
void __ubsan_handle_type_mismatch_v1(struct type_mismatch_info *type_mismatch,
|
||||
@@ -135,7 +135,7 @@ void __ubsan_handle_type_mismatch_v1(struct type_mismatch_info *type_mismatch,
|
||||
} else if (type_mismatch->alignment != 0 &&
|
||||
is_aligned(pointer, type_mismatch->alignment)) {
|
||||
// Most useful on architectures with stricter memory alignment requirements, like ARM.
|
||||
kfatal("Unaligned memory access\n");
|
||||
kfatal("Unaligned memory access: %p\n", pointer);
|
||||
} else {
|
||||
kfatal("Insufficient size:\n");
|
||||
if (type_mismatch->type_check_kind < sizeof(Type_Check_Kinds) / sizeof(Type_Check_Kinds[0])) {
|
||||
|
||||
Reference in New Issue
Block a user