lib: Add ASan support to ramstage on x86 arch
This patch adds address sanitizer module to the library and reserves a linker section representing the shadow region for ramstage. Also, it adds an instruction to initialize shadow region on x86 architecture when ramstage is loaded. Change-Id: Ica06bd2be78fcfc79fa888721ed920d4e8248f3b Signed-off-by: Harshit Sharma <harshitsharmajs@gmail.com> Reviewed-on: https://review.coreboot.org/c/coreboot/+/42496 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Werner Zeh <werner.zeh@siemens.com>
This commit is contained in:
parent
3b9cc859ff
commit
9c88fb8df0
|
@ -91,6 +91,10 @@ _start:
|
|||
|
||||
andl $0xFFFFFFF0, %esp
|
||||
|
||||
#if CONFIG(ASAN_IN_RAMSTAGE)
|
||||
call asan_init
|
||||
#endif
|
||||
|
||||
#if CONFIG(GDB_WAIT)
|
||||
call gdb_hw_init
|
||||
call gdb_stub_breakpoint
|
||||
|
|
|
@ -0,0 +1,113 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
|
||||
#ifndef __ASAN_H
|
||||
#define __ASAN_H
|
||||
|
||||
#define ASAN_SHADOW_SCALE_SHIFT 3
|
||||
|
||||
#define ASAN_SHADOW_SCALE_SIZE (1UL << ASAN_SHADOW_SCALE_SHIFT)
|
||||
#define ASAN_SHADOW_MASK (ASAN_SHADOW_SCALE_SIZE - 1)
|
||||
|
||||
#define ASAN_GLOBAL_REDZONE 0xFA
|
||||
#define ASAN_STACK_LEFT 0xF1
|
||||
#define ASAN_STACK_MID 0xF2
|
||||
#define ASAN_STACK_RIGHT 0xF3
|
||||
#define ASAN_STACK_PARTIAL 0xF4
|
||||
#define ASAN_USE_AFTER_SCOPE 0xF8
|
||||
|
||||
#define _RET_IP_ ((unsigned long)__builtin_return_address(0))
|
||||
#define likely(x) __builtin_expect(!!(x), 1)
|
||||
#define unlikely(x) __builtin_expect(!!(x), 0)
|
||||
|
||||
#define WARN_ON(condition) ({ \
|
||||
int __ret_warn_on = !!(condition); \
|
||||
unlikely(__ret_warn_on); \
|
||||
})
|
||||
|
||||
#ifndef ASAN_ABI_VERSION
|
||||
#define ASAN_ABI_VERSION 5
|
||||
#endif
|
||||
|
||||
/* The layout of struct dictated by compiler */
|
||||
struct asan_source_location {
|
||||
const char *filename;
|
||||
int line_no;
|
||||
int column_no;
|
||||
};
|
||||
|
||||
/* The layout of struct dictated by compiler */
|
||||
struct asan_global {
|
||||
const void *beg; /* Address of the beginning of the global variable. */
|
||||
size_t size; /* Size of the global variable. */
|
||||
size_t size_with_redzone; /* Size of the variable + size of the red zone
|
||||
32 bytes aligned. */
|
||||
const void *name;
|
||||
const void *module_name; /* Name of the module where the global variable
|
||||
is declared. */
|
||||
unsigned long has_dynamic_init; /* This needed for C++. */
|
||||
#if ASAN_ABI_VERSION >= 4
|
||||
struct asan_source_location *location;
|
||||
#endif
|
||||
#if ASAN_ABI_VERSION >= 5
|
||||
char *odr_indicator;
|
||||
#endif
|
||||
};
|
||||
|
||||
void asan_unpoison_shadow(const void *address, size_t size);
|
||||
void asan_report(unsigned long addr, size_t size, bool is_write,
|
||||
unsigned long ip);
|
||||
void asan_init(void);
|
||||
|
||||
uintptr_t __asan_shadow_offset(uintptr_t addr);
|
||||
void __asan_register_globals(struct asan_global *globals, size_t size);
|
||||
void __asan_unregister_globals(struct asan_global *globals, size_t size);
|
||||
void __asan_poison_stack_memory(const void *addr, size_t size);
|
||||
void __asan_unpoison_stack_memory(const void *addr, size_t size);
|
||||
|
||||
void __asan_load1(unsigned long addr);
|
||||
void __asan_store1(unsigned long addr);
|
||||
void __asan_load2(unsigned long addr);
|
||||
void __asan_store2(unsigned long addr);
|
||||
void __asan_load4(unsigned long addr);
|
||||
void __asan_store4(unsigned long addr);
|
||||
void __asan_load8(unsigned long addr);
|
||||
void __asan_store8(unsigned long addr);
|
||||
void __asan_load16(unsigned long addr);
|
||||
void __asan_store16(unsigned long addr);
|
||||
void __asan_loadN(unsigned long addr, size_t size);
|
||||
void __asan_storeN(unsigned long addr, size_t size);
|
||||
|
||||
void __asan_load1_noabort(unsigned long addr);
|
||||
void __asan_store1_noabort(unsigned long addr);
|
||||
void __asan_load2_noabort(unsigned long addr);
|
||||
void __asan_store2_noabort(unsigned long addr);
|
||||
void __asan_load4_noabort(unsigned long addr);
|
||||
void __asan_store4_noabort(unsigned long addr);
|
||||
void __asan_load8_noabort(unsigned long addr);
|
||||
void __asan_store8_noabort(unsigned long addr);
|
||||
void __asan_load16_noabort(unsigned long addr);
|
||||
void __asan_store16_noabort(unsigned long addr);
|
||||
void __asan_loadN_noabort(unsigned long addr, size_t size);
|
||||
void __asan_storeN_noabort(unsigned long addr, size_t size);
|
||||
void __asan_handle_no_return(void);
|
||||
|
||||
void __asan_set_shadow_00(const void *addr, size_t size);
|
||||
void __asan_set_shadow_f1(const void *addr, size_t size);
|
||||
void __asan_set_shadow_f2(const void *addr, size_t size);
|
||||
void __asan_set_shadow_f3(const void *addr, size_t size);
|
||||
void __asan_set_shadow_f5(const void *addr, size_t size);
|
||||
void __asan_set_shadow_f8(const void *addr, size_t size);
|
||||
|
||||
void __asan_report_load1_noabort(unsigned long addr);
|
||||
void __asan_report_store1_noabort(unsigned long addr);
|
||||
void __asan_report_load2_noabort(unsigned long addr);
|
||||
void __asan_report_store2_noabort(unsigned long addr);
|
||||
void __asan_report_load4_noabort(unsigned long addr);
|
||||
void __asan_report_store4_noabort(unsigned long addr);
|
||||
void __asan_report_load8_noabort(unsigned long addr);
|
||||
void __asan_report_store8_noabort(unsigned long addr);
|
||||
void __asan_report_load16_noabort(unsigned long addr);
|
||||
void __asan_report_store16_noabort(unsigned long addr);
|
||||
void __asan_report_load_n_noabort(unsigned long addr, size_t size);
|
||||
void __asan_report_store_n_noabort(unsigned long addr, size_t size);
|
||||
#endif
|
|
@ -24,6 +24,12 @@ DECLARE_REGION(cbfs_cache)
|
|||
DECLARE_REGION(fmap_cache)
|
||||
DECLARE_REGION(tpm_tcpa_log)
|
||||
|
||||
#if CONFIG(ASAN_IN_RAMSTAGE)
|
||||
DECLARE_REGION(data)
|
||||
DECLARE_REGION(heap)
|
||||
DECLARE_REGION(asan_shadow)
|
||||
#endif
|
||||
|
||||
/* Regions for execution units. */
|
||||
|
||||
DECLARE_REGION(payload)
|
||||
|
|
402
src/lib/asan.c
402
src/lib/asan.c
|
@ -1,16 +1,337 @@
|
|||
#include <stddef.h>
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
|
||||
#pragma GCC diagnostic ignored "-Wmissing-prototypes"
|
||||
/*
|
||||
* Address sanitizer support.
|
||||
*
|
||||
* Parts of this file are based on mm/kasan
|
||||
* from the Linux kernel 4.19.137.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <symbols.h>
|
||||
#include <assert.h>
|
||||
#include <asan.h>
|
||||
|
||||
static inline void *asan_mem_to_shadow(const void *addr)
|
||||
{
|
||||
return (void *)((uintptr_t)&_asan_shadow + (((uintptr_t)addr -
|
||||
(uintptr_t)&_data) >> ASAN_SHADOW_SCALE_SHIFT));
|
||||
}
|
||||
|
||||
static inline const void *asan_shadow_to_mem(const void *shadow_addr)
|
||||
{
|
||||
return (void *)((uintptr_t)&_data + (((uintptr_t)shadow_addr -
|
||||
(uintptr_t)&_asan_shadow) << ASAN_SHADOW_SCALE_SHIFT));
|
||||
}
|
||||
|
||||
static void asan_poison_shadow(const void *address, size_t size, u8 value)
|
||||
{
|
||||
void *shadow_start, *shadow_end;
|
||||
|
||||
shadow_start = asan_mem_to_shadow(address);
|
||||
shadow_end = asan_mem_to_shadow(address + size);
|
||||
|
||||
__builtin_memset(shadow_start, value, shadow_end - shadow_start);
|
||||
}
|
||||
|
||||
void asan_unpoison_shadow(const void *address, size_t size)
|
||||
{
|
||||
asan_poison_shadow(address, size, 0);
|
||||
|
||||
if (size & ASAN_SHADOW_MASK) {
|
||||
u8 *shadow = (u8 *)asan_mem_to_shadow(address + size);
|
||||
*shadow = size & ASAN_SHADOW_MASK;
|
||||
}
|
||||
}
|
||||
|
||||
static __always_inline bool memory_is_poisoned_1(unsigned long addr)
|
||||
{
|
||||
s8 shadow_value = *(s8 *)asan_mem_to_shadow((void *)addr);
|
||||
|
||||
if (unlikely(shadow_value)) {
|
||||
s8 last_accessible_byte = addr & ASAN_SHADOW_MASK;
|
||||
return unlikely(last_accessible_byte >= shadow_value);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static __always_inline bool memory_is_poisoned_2_4_8(unsigned long addr,
|
||||
unsigned long size)
|
||||
{
|
||||
u8 *shadow_addr = (u8 *)asan_mem_to_shadow((void *)addr);
|
||||
|
||||
if (unlikely(((addr + size - 1) & ASAN_SHADOW_MASK) < size - 1))
|
||||
return *shadow_addr || memory_is_poisoned_1(addr + size - 1);
|
||||
|
||||
return memory_is_poisoned_1(addr + size - 1);
|
||||
}
|
||||
|
||||
static __always_inline bool memory_is_poisoned_16(unsigned long addr)
|
||||
{
|
||||
u16 *shadow_addr = (u16 *)asan_mem_to_shadow((void *)addr);
|
||||
|
||||
if (unlikely(!IS_ALIGNED(addr, ASAN_SHADOW_SCALE_SIZE)))
|
||||
return *shadow_addr || memory_is_poisoned_1(addr + 15);
|
||||
|
||||
return *shadow_addr;
|
||||
}
|
||||
|
||||
static __always_inline unsigned long bytes_is_nonzero(const u8 *start,
|
||||
size_t size)
|
||||
{
|
||||
while (size) {
|
||||
if (unlikely(*start))
|
||||
return (unsigned long)start;
|
||||
start++;
|
||||
size--;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __always_inline unsigned long memory_is_nonzero(const void *start,
|
||||
const void *end)
|
||||
{
|
||||
unsigned int words;
|
||||
unsigned long ret;
|
||||
unsigned int prefix = (unsigned long)start % 8;
|
||||
|
||||
if (end - start <= 16)
|
||||
return bytes_is_nonzero(start, end - start);
|
||||
|
||||
if (prefix) {
|
||||
prefix = 8 - prefix;
|
||||
ret = bytes_is_nonzero(start, prefix);
|
||||
if (unlikely(ret))
|
||||
return ret;
|
||||
start += prefix;
|
||||
}
|
||||
|
||||
words = (end - start) / 8;
|
||||
while (words) {
|
||||
if (unlikely(*(u64 *)start))
|
||||
return bytes_is_nonzero(start, 8);
|
||||
start += 8;
|
||||
words--;
|
||||
}
|
||||
|
||||
return bytes_is_nonzero(start, (end - start) % 8);
|
||||
}
|
||||
|
||||
static __always_inline bool memory_is_poisoned_n(unsigned long addr,
|
||||
size_t size)
|
||||
{
|
||||
unsigned long ret;
|
||||
|
||||
ret = memory_is_nonzero(asan_mem_to_shadow((void *)addr),
|
||||
asan_mem_to_shadow((void *)addr + size - 1) + 1);
|
||||
|
||||
if (unlikely(ret)) {
|
||||
unsigned long last_byte = addr + size - 1;
|
||||
s8 *last_shadow = (s8 *)asan_mem_to_shadow((void *)last_byte);
|
||||
|
||||
if (unlikely(ret != (unsigned long)last_shadow ||
|
||||
((long)(last_byte & ASAN_SHADOW_MASK) >= *last_shadow)))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static __always_inline bool memory_is_poisoned(unsigned long addr, size_t size)
|
||||
{
|
||||
if (__builtin_constant_p(size)) {
|
||||
switch (size) {
|
||||
case 1:
|
||||
return memory_is_poisoned_1(addr);
|
||||
case 2:
|
||||
case 4:
|
||||
case 8:
|
||||
return memory_is_poisoned_2_4_8(addr, size);
|
||||
case 16:
|
||||
return memory_is_poisoned_16(addr);
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
return memory_is_poisoned_n(addr, size);
|
||||
}
|
||||
|
||||
static const void *find_first_bad_addr(const void *addr, size_t size)
|
||||
{
|
||||
u8 shadow_val = *(u8 *)asan_mem_to_shadow(addr);
|
||||
const void *first_bad_addr = addr;
|
||||
|
||||
while (!shadow_val && first_bad_addr < addr + size) {
|
||||
first_bad_addr += ASAN_SHADOW_SCALE_SIZE;
|
||||
shadow_val = *(u8 *)asan_mem_to_shadow(first_bad_addr);
|
||||
}
|
||||
return first_bad_addr;
|
||||
}
|
||||
|
||||
static const char *get_shadow_bug_type(const void *addr, size_t size)
|
||||
{
|
||||
const char *bug_type = "unknown-crash";
|
||||
u8 *shadow_addr;
|
||||
const void *first_bad_addr;
|
||||
|
||||
if (addr < asan_shadow_to_mem((void *) &_asan_shadow))
|
||||
return bug_type;
|
||||
|
||||
first_bad_addr = find_first_bad_addr(addr, size);
|
||||
|
||||
shadow_addr = (u8 *)asan_mem_to_shadow(first_bad_addr);
|
||||
|
||||
if (*shadow_addr > 0 && *shadow_addr <= ASAN_SHADOW_SCALE_SIZE - 1)
|
||||
shadow_addr++;
|
||||
|
||||
switch (*shadow_addr) {
|
||||
case 0 ... ASAN_SHADOW_SCALE_SIZE - 1:
|
||||
bug_type = "out-of-bounds";
|
||||
break;
|
||||
case ASAN_GLOBAL_REDZONE:
|
||||
bug_type = "global-out-of-bounds";
|
||||
break;
|
||||
case ASAN_STACK_LEFT:
|
||||
case ASAN_STACK_MID:
|
||||
case ASAN_STACK_RIGHT:
|
||||
case ASAN_STACK_PARTIAL:
|
||||
bug_type = "stack-out-of-bounds";
|
||||
break;
|
||||
case ASAN_USE_AFTER_SCOPE:
|
||||
bug_type = "use-after-scope";
|
||||
break;
|
||||
default:
|
||||
bug_type = "unknown-crash";
|
||||
}
|
||||
|
||||
return bug_type;
|
||||
}
|
||||
|
||||
void asan_report(unsigned long addr, size_t size, bool is_write,
|
||||
unsigned long ip)
|
||||
{
|
||||
const char *bug_type = get_shadow_bug_type((void *) addr, size);
|
||||
printk(BIOS_ERR, "\n");
|
||||
printk(BIOS_ERR, "ASan: %s in %p\n", bug_type, (void *) ip);
|
||||
printk(BIOS_ERR, "%s of %zu byte%s at addr %p\n",
|
||||
is_write ? "Write" : "Read", size, (size > 1 ? "s" : ""),
|
||||
(void *) addr);
|
||||
printk(BIOS_ERR, "\n");
|
||||
}
|
||||
|
||||
static __always_inline void check_memory_region_inline(unsigned long addr,
|
||||
size_t size, bool write,
|
||||
unsigned long ret_ip)
|
||||
{
|
||||
if (((uintptr_t)addr < (uintptr_t)&_data) ||
|
||||
((uintptr_t)addr > (uintptr_t)&_eheap))
|
||||
return;
|
||||
|
||||
if (unlikely(size == 0))
|
||||
return;
|
||||
|
||||
if (unlikely((void *)addr <
|
||||
asan_shadow_to_mem((void *) &_asan_shadow))) {
|
||||
asan_report(addr, size, write, ret_ip);
|
||||
return;
|
||||
}
|
||||
|
||||
if (likely(!memory_is_poisoned(addr, size)))
|
||||
return;
|
||||
|
||||
asan_report(addr, size, write, ret_ip);
|
||||
}
|
||||
|
||||
static void check_memory_region(unsigned long addr, size_t size, bool write,
|
||||
unsigned long ret_ip)
|
||||
{
|
||||
check_memory_region_inline(addr, size, write, ret_ip);
|
||||
}
|
||||
|
||||
uintptr_t __asan_shadow_offset(uintptr_t addr)
|
||||
{
|
||||
return (uintptr_t)&_asan_shadow - (((uintptr_t)&_data) >>
|
||||
ASAN_SHADOW_SCALE_SHIFT);
|
||||
}
|
||||
|
||||
static void register_global(struct asan_global *global)
|
||||
{
|
||||
size_t aligned_size = ALIGN_UP(global->size, ASAN_SHADOW_SCALE_SIZE);
|
||||
|
||||
asan_unpoison_shadow(global->beg, global->size);
|
||||
|
||||
asan_poison_shadow(global->beg + aligned_size,
|
||||
global->size_with_redzone - aligned_size,
|
||||
ASAN_GLOBAL_REDZONE);
|
||||
}
|
||||
|
||||
void __asan_register_globals(struct asan_global *globals, size_t size)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
register_global(&globals[i]);
|
||||
}
|
||||
|
||||
void __asan_unregister_globals(struct asan_global *globals, size_t size)
|
||||
{
|
||||
}
|
||||
|
||||
/*
|
||||
* GCC adds constructors invoking __asan_register_globals() and passes
|
||||
* information about global variable (address, size, size with redzone ...)
|
||||
* to it so we could poison variable's redzone.
|
||||
* This function calls those constructors.
|
||||
*/
|
||||
static void asan_ctors(void)
|
||||
{
|
||||
extern long __CTOR_LIST__;
|
||||
typedef void (*func_ptr)(void);
|
||||
func_ptr *ctor = (func_ptr *) &__CTOR_LIST__;
|
||||
if (ctor == NULL)
|
||||
return;
|
||||
|
||||
for (; *ctor != (func_ptr) 0; ctor++)
|
||||
(*ctor)();
|
||||
}
|
||||
|
||||
void asan_init(void)
|
||||
{
|
||||
size_t size = (size_t)&_eheap - (size_t)&_data;
|
||||
asan_unpoison_shadow((void *)&_data, size);
|
||||
asan_ctors();
|
||||
}
|
||||
|
||||
void __asan_poison_stack_memory(const void *addr, size_t size)
|
||||
{
|
||||
asan_poison_shadow(addr, ALIGN_UP(size, ASAN_SHADOW_SCALE_SIZE),
|
||||
ASAN_USE_AFTER_SCOPE);
|
||||
}
|
||||
|
||||
void __asan_unpoison_stack_memory(const void *addr, size_t size)
|
||||
{
|
||||
asan_unpoison_shadow(addr, size);
|
||||
}
|
||||
|
||||
#define DEFINE_ASAN_LOAD_STORE(size) \
|
||||
void __asan_load##size(unsigned long addr) \
|
||||
{} \
|
||||
{ \
|
||||
check_memory_region_inline(addr, size, false, _RET_IP_);\
|
||||
} \
|
||||
void __asan_load##size##_noabort(unsigned long addr) \
|
||||
{} \
|
||||
{ \
|
||||
check_memory_region_inline(addr, size, false, _RET_IP_);\
|
||||
} \
|
||||
void __asan_store##size(unsigned long addr) \
|
||||
{} \
|
||||
{ \
|
||||
check_memory_region_inline(addr, size, true, _RET_IP_); \
|
||||
} \
|
||||
void __asan_store##size##_noabort(unsigned long addr) \
|
||||
{}
|
||||
{ \
|
||||
check_memory_region_inline(addr, size, true, _RET_IP_); \
|
||||
}
|
||||
|
||||
DEFINE_ASAN_LOAD_STORE(1);
|
||||
DEFINE_ASAN_LOAD_STORE(2);
|
||||
|
@ -19,16 +340,71 @@ DEFINE_ASAN_LOAD_STORE(8);
|
|||
DEFINE_ASAN_LOAD_STORE(16);
|
||||
|
||||
void __asan_loadN(unsigned long addr, size_t size)
|
||||
{}
|
||||
|
||||
void __asan_loadN_noabort(unsigned long addr, size_t size)
|
||||
{}
|
||||
{
|
||||
check_memory_region(addr, size, false, _RET_IP_);
|
||||
}
|
||||
|
||||
void __asan_storeN(unsigned long addr, size_t size)
|
||||
{}
|
||||
{
|
||||
check_memory_region(addr, size, true, _RET_IP_);
|
||||
}
|
||||
|
||||
void __asan_loadN_noabort(unsigned long addr, size_t size)
|
||||
{
|
||||
check_memory_region(addr, size, false, _RET_IP_);
|
||||
}
|
||||
|
||||
void __asan_storeN_noabort(unsigned long addr, size_t size)
|
||||
{}
|
||||
{
|
||||
check_memory_region(addr, size, true, _RET_IP_);
|
||||
}
|
||||
|
||||
void __asan_handle_no_return(void)
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
#define DEFINE_ASAN_SET_SHADOW(byte) \
|
||||
void __asan_set_shadow_##byte(const void *addr, size_t size) \
|
||||
{ \
|
||||
__builtin_memset((void *)addr, 0x##byte, size); \
|
||||
}
|
||||
|
||||
DEFINE_ASAN_SET_SHADOW(00);
|
||||
DEFINE_ASAN_SET_SHADOW(f1);
|
||||
DEFINE_ASAN_SET_SHADOW(f2);
|
||||
DEFINE_ASAN_SET_SHADOW(f3);
|
||||
DEFINE_ASAN_SET_SHADOW(f5);
|
||||
DEFINE_ASAN_SET_SHADOW(f8);
|
||||
|
||||
#define DEFINE_ASAN_REPORT_LOAD(size) \
|
||||
void __asan_report_load##size##_noabort(unsigned long addr) \
|
||||
{ \
|
||||
asan_report(addr, size, false, _RET_IP_); \
|
||||
}
|
||||
|
||||
#define DEFINE_ASAN_REPORT_STORE(size) \
|
||||
void __asan_report_store##size##_noabort(unsigned long addr) \
|
||||
{ \
|
||||
asan_report(addr, size, true, _RET_IP_); \
|
||||
}
|
||||
|
||||
DEFINE_ASAN_REPORT_LOAD(1);
|
||||
DEFINE_ASAN_REPORT_LOAD(2);
|
||||
DEFINE_ASAN_REPORT_LOAD(4);
|
||||
DEFINE_ASAN_REPORT_LOAD(8);
|
||||
DEFINE_ASAN_REPORT_LOAD(16);
|
||||
DEFINE_ASAN_REPORT_STORE(1);
|
||||
DEFINE_ASAN_REPORT_STORE(2);
|
||||
DEFINE_ASAN_REPORT_STORE(4);
|
||||
DEFINE_ASAN_REPORT_STORE(8);
|
||||
DEFINE_ASAN_REPORT_STORE(16);
|
||||
|
||||
void __asan_report_load_n_noabort(unsigned long addr, size_t size)
|
||||
{
|
||||
asan_report(addr, size, false, _RET_IP_);
|
||||
}
|
||||
|
||||
void __asan_report_store_n_noabort(unsigned long addr, size_t size)
|
||||
{
|
||||
asan_report(addr, size, true, _RET_IP_);
|
||||
}
|
||||
|
|
|
@ -51,7 +51,7 @@
|
|||
_etext = .;
|
||||
} : to_load
|
||||
|
||||
#if ENV_RAMSTAGE && CONFIG(COVERAGE)
|
||||
#if ENV_RAMSTAGE && (CONFIG(COVERAGE) || CONFIG(ASAN_IN_RAMSTAGE))
|
||||
.ctors . : {
|
||||
. = ALIGN(0x100);
|
||||
__CTOR_LIST__ = .;
|
||||
|
@ -126,6 +126,11 @@
|
|||
}
|
||||
#endif
|
||||
|
||||
#if ENV_RAMSTAGE && CONFIG(ASAN_IN_RAMSTAGE)
|
||||
_shadow_size = (_eheap - _data) >> 3;
|
||||
REGION(asan_shadow, ., _shadow_size, ARCH_POINTER_ALIGN_SIZE)
|
||||
#endif
|
||||
|
||||
_eprogram = .;
|
||||
|
||||
/* Discard the sections we don't need/want */
|
||||
|
|
Loading…
Reference in New Issue