optee中定义了三种stack
#define DECLARE_STACK(name, num_stacks, stack_size, linkage) \
linkage uint32_t name[num_stacks] \
[ROUNDUP(stack_size + STACK_CANARY_SIZE + STACK_CHECK_EXTRA, \
STACK_ALIGNMENT) / sizeof(uint32_t)] \
__attribute__((section(".nozi_stack." # name), \
aligned(STACK_ALIGNMENT)))
#define GET_STACK(stack) ((vaddr_t)(stack) + STACK_SIZE(stack))
DECLARE_STACK(stack_tmp, CFG_TEE_CORE_NB_CORE,
STACK_TMP_SIZE + CFG_STACK_TMP_EXTRA, static);
DECLARE_STACK(stack_abt, CFG_TEE_CORE_NB_CORE, STACK_ABT_SIZE, static);
#ifndef CFG_WITH_PAGER
DECLARE_STACK(stack_thread, CFG_NUM_THREADS,
STACK_THREAD_SIZE + CFG_STACK_THREAD_EXTRA, static);
#endif
这里的stack基本就是一个二维数组,且这些数组都会被放到一段特殊的段中".nozi_stack."。以stack_thread,其第二个参数CFG_NUM_THREADS表示为每个线程都有一个stack,
其大小是STACK_THREAD_SIZE,如果开启debug stack的话,会额外增加一个大小#define STACK_CHECK_EXTRA 1536
在这些栈被使用之前会通过init_canaries 来为这些栈的起始和结束的地址写一个特殊的字符,例如起始写的是*start_canary = START_CANARY_VALUE
static void init_canaries(void)
{
#ifdef CFG_WITH_STACK_CANARIES
size_t n;
#define INIT_CANARY(name) \
for (n = 0; n < ARRAY_SIZE(name); n++) { \
uint32_t *start_canary = &GET_START_CANARY(name, n); \
uint32_t *end_canary = &GET_END_CANARY(name, n); \
\
*start_canary = START_CANARY_VALUE; \
*end_canary = END_CANARY_VALUE; \
}
INIT_CANARY(stack_tmp);
INIT_CANARY(stack_abt);
#if !defined(CFG_WITH_PAGER) && !defined(CFG_VIRTUALIZATION)
INIT_CANARY(stack_thread);
#endif
#endif/*CFG_WITH_STACK_CANARIES*/
}
这主要是防止使用栈超过其初始的大小.例如就会调用下面的函数来检查栈
void thread_check_canaries(void)
{
#ifdef CFG_WITH_STACK_CANARIES
uint32_t *canary = NULL;
size_t n = 0;
#if !defined(CFG_WITH_PAGER) && !defined(CFG_VIRTUALIZATION)
for (n = 0; n < ARRAY_SIZE(stack_thread); n++) {
canary = &GET_START_CANARY(stack_thread, n);
if (*canary != START_CANARY_VALUE)
CANARY_DIED(stack_thread, start, n, canary);
canary = &GET_END_CANARY(stack_thread, n);
if (*canary != END_CANARY_VALUE)
CANARY_DIED(stack_thread, end, n, canary);
}
#endif
#endif/*CFG_WITH_STACK_CANARIES*/
}
具体哪些地方用栈呢?还是以stack_thread为例,当我们申请thread的时候就会从stack_thread拿到栈
static void init_thread_stacks(void)
{
size_t n;
/* Assign the thread stacks */
for (n = 0; n < CFG_NUM_THREADS; n++) {
if (!thread_init_stack(n, GET_STACK_BOTTOM(stack_thread, n)))
panic("thread_init_stack failed");
}
}
从GET_STACK_BOTTOM(stack_thread, n))可以看出这些栈是从bottom涨到up的,也就是说栈是从地址大的忘地址小的一次减小