zephyr/include/exc_handle.h

46 lines
1.5 KiB
C
Raw Normal View History

/*
* Copyright (c) 2018 Intel Corporation.
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ZEPHYR_INCLUDE_EXC_HANDLE_H_
#define ZEPHYR_INCLUDE_EXC_HANDLE_H_
/*
* This is used by some architectures to define code ranges which may
* perform operations that could generate a CPU exception that should not
* be fatal. Instead, the exception should return but set the program
* counter to a 'fixup' memory address which will gracefully error out.
*
* For example, in the case where user mode passes in a C string via
* system call, the length of that string needs to be measured. A specially
* written assembly language version of strlen (z_arch_user_string_len)
* defines start and end symbols where the memory in the string is examined;
* if this generates a fault, jumping to the fixup symbol within the same
* function will return an error result to the caller.
*
* To ensure precise control of the state of registers and the stack pointer,
* these functions need to be written in assembly.
*
* The arch-specific fault handling code will define an array of these
* z_exc_handle structures and return from the exception with the PC updated
* to the fixup address if a match is found.
*/
struct z_exc_handle {
void *start;
void *end;
void *fixup;
};
#define Z_EXC_HANDLE(name) \
kernel: Fix type of Z_EXC_HANDLE The type of Z_EXC_HANDLE was incorrectly declared, this was causing the compiler to make incorrect inferences about what could be in exc_handle and caused a bug in fault.c. To get more specific ... An exception handler consists of three void pointers, or function pointers. The function pointers point to functions. An example of one such function is 'z_arch_user_string_nlen_fault_start' From userspace.S. The correct way of initalizing a function pointer from a function declared in another source file looks like this: void external_defined_function(void); { void * internal_initialized_function_ptr = external_defined_function; } But EXC_HANDLER is not doing this. Instead it does this: extern void (*external_defined_function)(void); { void * internal_initialized_function_ptr = &external_defined_function; } The declaration here is wrong. It declares that externally, there is stored a function pointer somewhere. Which is not true. There does not exist a function pointer anywhere. But this doesn't matter, because we don't actually de-reference the function pointer to find the address of the function, but instead we take the address of the function pointer. Taking the address of the function pointer to find the address of a function is wrong, one should de-reference function pointers to find function addresses. Luckily, these two bugs have been cancelling each other out, until recently. This patch corrects the type used. Signed-off-by: Sebastian Bøe <sebastian.boe@nordicsemi.no>
2018-11-16 20:54:01 +08:00
{ name ## _fault_start, name ## _fault_end, name ## _fixup }
kernel: Fix type of Z_EXC_HANDLE The type of Z_EXC_HANDLE was incorrectly declared, this was causing the compiler to make incorrect inferences about what could be in exc_handle and caused a bug in fault.c. To get more specific ... An exception handler consists of three void pointers, or function pointers. The function pointers point to functions. An example of one such function is 'z_arch_user_string_nlen_fault_start' From userspace.S. The correct way of initalizing a function pointer from a function declared in another source file looks like this: void external_defined_function(void); { void * internal_initialized_function_ptr = external_defined_function; } But EXC_HANDLER is not doing this. Instead it does this: extern void (*external_defined_function)(void); { void * internal_initialized_function_ptr = &external_defined_function; } The declaration here is wrong. It declares that externally, there is stored a function pointer somewhere. Which is not true. There does not exist a function pointer anywhere. But this doesn't matter, because we don't actually de-reference the function pointer to find the address of the function, but instead we take the address of the function pointer. Taking the address of the function pointer to find the address of a function is wrong, one should de-reference function pointers to find function addresses. Luckily, these two bugs have been cancelling each other out, until recently. This patch corrects the type used. Signed-off-by: Sebastian Bøe <sebastian.boe@nordicsemi.no>
2018-11-16 20:54:01 +08:00
#define Z_EXC_DECLARE(name) \
void name ## _fault_start(void); \
void name ## _fault_end(void); \
void name ## _fixup(void)
#endif /* ZEPHYR_INCLUDE_EXC_HANDLE_H_ */