void interpreter::get_running_vaiant(int frame, const char * name, int line, const char * & value, int & outline) { value = ""; outline = 0; if (!m_fb) { return; } m_fk->rn.cur_runinginfo.clear(); int deps = 0; int ip = m_ip; int bp = m_bp; const func_binary * fb = m_fb; while (!BP_END(bp)) { if (deps >= frame) { for (int i = 0; i < fb->m_debug_stack_variant_info_num; i++) { const stack_variant_info & info = fb->m_debug_stack_variant_info[i]; if ((line != -1 && !strcmp(info.name, name) && info.line == line) || (line == -1 && !strcmp(info.name, name))) { variant * v = 0; GET_STACK(bp, v, info.pos); if (v->type == variant::STRING) { m_fk->rn.cur_runinginfo += "\""; m_fk->rn.cur_runinginfo += vartostring(v); m_fk->rn.cur_runinginfo += "\""; } else { m_fk->rn.cur_runinginfo += vartostring(v); } value = m_fk->rn.cur_runinginfo.c_str(); outline = info.line; return; } } break; } BP_GET_FB(bp, fb); BP_GET_IP(bp, ip); int callbp = 0; BP_GET_BP(bp, callbp); bp = callbp; if (BP_END(bp)) { break; } deps++; } return; }
void interpreter::set_running_vaiant(int frame, const char * name, int line, const char * value) { if (!m_fb) { return; } int deps = 0; int ip = m_ip; int bp = m_bp; const func_binary * fb = m_fb; while (!BP_END(bp)) { if (deps >= frame) { for (int i = 0; i < fb->m_debug_stack_variant_info_num; i++) { const stack_variant_info & info = fb->m_debug_stack_variant_info[i]; if ((line != -1 && !strcmp(info.name, name) && info.line == line) || (line == -1 && !strcmp(info.name, name))) { fake * fk = m_fk; variant * v = 0; GET_STACK(bp, v, info.pos); std::string valuestr = value; if (valuestr.empty()) { return; } if (valuestr[0] == '\"') { valuestr[valuestr.size() - 1] = 0; V_SET_STRING(v, &valuestr[1]); } else { V_SET_REAL(v, atoi(value)); } return; } } break; } BP_GET_FB(bp, fb); BP_GET_IP(bp, ip); int callbp = 0; BP_GET_BP(bp, callbp); bp = callbp; if (BP_END(bp)) { break; } deps++; } }
const char * interpreter::get_running_call_stack() const { if (!m_fb) { return ""; } m_fk->rn.cur_runinginfo.clear(); int deps = 0; int ip = m_ip; int bp = m_bp; const func_binary * fb = m_fb; while (!BP_END(bp)) { m_fk->rn.cur_runinginfo += "#"; m_fk->rn.cur_runinginfo += fkitoa(deps); m_fk->rn.cur_runinginfo += " "; m_fk->rn.cur_runinginfo += fb ? FUNC_BINARY_NAME(*fb) : ""; m_fk->rn.cur_runinginfo += " at "; m_fk->rn.cur_runinginfo += fb ? FUNC_BINARY_FILENAME(*fb) : ""; m_fk->rn.cur_runinginfo += ":"; m_fk->rn.cur_runinginfo += fb ? fkitoa(GET_CMD_LINENO(*fb, ip)) : 0; m_fk->rn.cur_runinginfo += "\n"; for (int j = 0; fb && j < FUNC_BINARY_MAX_STACK(*fb); j++) { m_fk->rn.cur_runinginfo += " "; String variant_name; for (int i = 0; i < fb->m_debug_stack_variant_info_num; i++) { const stack_variant_info & info = fb->m_debug_stack_variant_info[i]; if (info.pos == j) { variant_name += info.name; variant_name += "(line:"; variant_name += fkitoa(info.line); variant_name += ") "; } } if (variant_name.empty()) { variant_name = "(anonymous)"; } m_fk->rn.cur_runinginfo += variant_name; m_fk->rn.cur_runinginfo += "\t["; m_fk->rn.cur_runinginfo += fkitoa(j); m_fk->rn.cur_runinginfo += "]\t"; variant * v = 0; GET_STACK(bp, v, j); m_fk->rn.cur_runinginfo += vartostring(v); m_fk->rn.cur_runinginfo += "\n"; } BP_GET_FB(bp, fb); BP_GET_IP(bp, ip); int callbp = 0; BP_GET_BP(bp, callbp); bp = callbp; if (BP_END(bp)) { break; } deps++; } return m_fk->rn.cur_runinginfo.c_str(); }
static uint32_t name[num_stacks][(stack_size + STACK_CANARY_SIZE) / \ sizeof(uint32_t)] \ __attribute__((section(".bss.prebss.stack"), \ aligned(STACK_ALIGNMENT))) #define GET_STACK(stack) \ ((vaddr_t)(stack) + sizeof(stack) - STACK_CANARY_SIZE / 2) DECLARE_STACK(stack_tmp, CFG_TEE_CORE_NB_CORE, STACK_TMP_SIZE); DECLARE_STACK(stack_abt, CFG_TEE_CORE_NB_CORE, STACK_ABT_SIZE); DECLARE_STACK(stack_sm, CFG_TEE_CORE_NB_CORE, SM_STACK_SIZE); DECLARE_STACK(stack_thread, NUM_THREADS, STACK_THREAD_SIZE); const vaddr_t stack_tmp_top[CFG_TEE_CORE_NB_CORE] = { GET_STACK(stack_tmp[0]), #if CFG_TEE_CORE_NB_CORE > 1 GET_STACK(stack_tmp[1]), #endif #if CFG_TEE_CORE_NB_CORE > 2 GET_STACK(stack_tmp[2]), #endif #if CFG_TEE_CORE_NB_CORE > 3 GET_STACK(stack_tmp[3]), #endif #if CFG_TEE_CORE_NB_CORE > 4 #error "Top of tmp stacks aren't defined for more than 4 CPUS" #endif }; static void main_fiq(void);
/* * Copyright (c) 2014, Linaro Limited * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE. */ #include <stdint.h> #include <string.h> #include <plat.h> #include <drivers/gic.h> #include <drivers/uart.h> #include <kprintf.h> #include <sm/sm.h> #include <sm/sm_defs.h> #include <kern/mmu.h> #include <kern/kern.h> #include <kern/resmem.h> #include <kern/arch_debug.h> #include <arm32.h> #include <kern/thread.h> #include <kern/panic.h> #include <tee/entry.h> #include <assert.h> #ifdef WITH_STACK_CANARIES #define STACK_CANARY_SIZE (4 * sizeof(uint32_t)) #define START_CANARY_VALUE 0xdededede #define END_CANARY_VALUE 0xabababab #define GET_START_CANARY(name, stack_num) name[stack_num][0] #define GET_END_CANARY(name, stack_num) \ name[stack_num][sizeof(name[stack_num]) / sizeof(uint32_t) - 1] #else #define STACK_CANARY_SIZE 0 #endif #define DECLARE_STACK(name, num_stacks, stack_size) \ static uint32_t name[num_stacks][(stack_size + STACK_CANARY_SIZE) / \ sizeof(uint32_t)] \ __attribute__((section(".bss.prebss.stack"), \ aligned(STACK_ALIGMENT))) #define GET_STACK(stack) \ ((vaddr_t)(stack) + sizeof(stack) - STACK_CANARY_SIZE / 2) DECLARE_STACK(stack_tmp, NUM_CPUS, STACK_TMP_SIZE); DECLARE_STACK(stack_abt, NUM_CPUS, STACK_ABT_SIZE); DECLARE_STACK(stack_sm, NUM_CPUS, SM_STACK_SIZE); DECLARE_STACK(stack_thread, NUM_THREADS, STACK_THREAD_SIZE); const vaddr_t stack_tmp_top[NUM_CPUS] = { GET_STACK(stack_tmp[0]), #if NUM_CPUS > 1 GET_STACK(stack_tmp[1]), #endif #if NUM_CPUS > 2 GET_STACK(stack_tmp[2]), #endif #if NUM_CPUS > 3 GET_STACK(stack_tmp[3]), #endif #if NUM_CPUS > 4 #error "Top of tmp stacks aren't defined for more than 4 CPUS" #endif }; static bool inited; uint32_t mmu_l1_table[MMU_L1_NUM_ENTRIES] __attribute__((section(".bss.prebss.mmu"), aligned(MMU_L1_ALIGNMENT))); extern uint32_t __text_start; extern uint32_t __rodata_end; extern uint32_t __data_start; extern uint32_t __bss_start; extern uint32_t __bss_end; extern uint32_t _end; extern uint32_t _end_of_ram; static void main_stdcall(struct thread_smc_args *args); static void main_fastcall(struct thread_smc_args *args); static void main_fiq(void); static void main_svc(struct thread_svc_regs *regs); static void main_abort(uint32_t abort_type, struct thread_abort_regs *regs); static void init_canaries(void) { 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; \ kprintf("#Stack canaries for %s[%zu] with top at %p\n", \ #name, n, (void *)(end_canary - 1)); \ kprintf("#watch inited && *%p\n", (void *)start_canary);\ kprintf("watch inited && *%p\n", (void *)end_canary); \ } INIT_CANARY(stack_tmp); INIT_CANARY(stack_abt); INIT_CANARY(stack_sm); INIT_CANARY(stack_thread); } void check_canaries(void) { #ifdef WITH_STACK_CANARIES size_t n; #define ASSERT_STACK_CANARIES(name) \ for (n = 0; n < ARRAY_SIZE(name); n++) { \ assert(GET_START_CANARY(name, n) == START_CANARY_VALUE);\ assert(GET_END_CANARY(name, n) == END_CANARY_VALUE); \ } while (0) ASSERT_STACK_CANARIES(stack_tmp); ASSERT_STACK_CANARIES(stack_abt); ASSERT_STACK_CANARIES(stack_sm); ASSERT_STACK_CANARIES(stack_thread); #endif /*WITH_STACK_CANARIES*/ } static const struct thread_handlers handlers = { .stdcall = main_stdcall, .fastcall = main_fastcall, .fiq = main_fiq, .svc = main_svc, .abort = main_abort }; void main_init(uint32_t nsec_entry); /* called from assembly only */ void main_init(uint32_t nsec_entry) { uintptr_t code_start = (uintptr_t)&__text_start; uintptr_t code_end = (uintptr_t)&__rodata_end; uintptr_t data_start = (uintptr_t)&__data_start; uintptr_t bss_start = (uintptr_t)&__bss_start; uintptr_t bss_end = (uintptr_t)&__bss_end; uintptr_t begin_resmem = (uintptr_t)&_end; uintptr_t end_resmem = (uintptr_t)&_end_of_ram; struct sm_nsec_ctx *nsec_ctx; size_t n; resmem_init(begin_resmem, end_resmem); /* Initialize user with physical address */ uart_init(UART1_BASE); kprintf_init((kvprintf_putc)uart_putc, (kprintf_flush_output)uart_flush_tx_fifo, (void *)UART1_BASE); kprintf("Trusted OS initializing\n"); mmu_init(mmu_l1_table, code_start, code_end, data_start, end_resmem); /* Reinitialize with virtual address now that MMU is enabled */ kprintf_init((kvprintf_putc)uart_putc, (kprintf_flush_output)uart_flush_tx_fifo, (void *)mmu_map_device(UART1_BASE, 0x1000)); /* * Map normal world DDR, TODO add an interface to let normal world * supply this. */ mmu_map_rwmem(DDR0_BASE, DDR0_SIZE, true /*ns*/); /* * Zero BSS area. Note that globals that would normally would go * into BSS which are used before this has to be put into * .bss.prebss.* to avoid getting overwritten. */ memset((void *)bss_start, 0, bss_end - bss_start); /* Initialize canries around the stacks */ init_canaries(); if (!thread_init_stack(THREAD_TMP_STACK, GET_STACK(stack_tmp[0]))) panic(); if (!thread_init_stack(THREAD_ABT_STACK, GET_STACK(stack_abt[0]))) panic(); for (n = 0; n < NUM_THREADS; n++) { if (!thread_init_stack(n, GET_STACK(stack_thread[n]))) panic(); } /* * Mask IRQ and FIQ before switch to the thread vector as the * thread handler requires IRQ and FIQ to be masked while executing * with the temporary stack. */ write_cpsr(read_cpsr() | CPSR_F | CPSR_I); thread_init_handlers(&handlers); /* Initialize secure monitor */ sm_init(GET_STACK(stack_sm[0])); nsec_ctx = sm_get_nsec_ctx(); nsec_ctx->mon_lr = nsec_entry; nsec_ctx->mon_spsr = CPSR_MODE_SVC | CPSR_I; /* Initialize GIC */ gic_init(mmu_map_device(GIC_BASE + GICC_OFFSET, 0x1000), mmu_map_device(GIC_BASE + GICD_OFFSET, 0x1000)); gic_it_add(IT_UART1); gic_it_set_cpu_mask(IT_UART1, 0x1); gic_it_set_prio(IT_UART1, 0xff); gic_it_enable(IT_UART1); inited = true; kprintf("Switching to normal world boot\n"); }
static uint32_t name[num_stacks][(stack_size + STACK_CANARY_SIZE) / \ sizeof(uint32_t)] \ __attribute__((section(".bss.prebss.stack"), \ aligned(STACK_ALIGNMENT))) #define GET_STACK(stack) \ ((vaddr_t)(stack) + sizeof(stack) - STACK_CANARY_SIZE / 2) DECLARE_STACK(stack_tmp, CFG_TEE_CORE_NB_CORE, STACK_TMP_SIZE); DECLARE_STACK(stack_abt, CFG_TEE_CORE_NB_CORE, STACK_ABT_SIZE); DECLARE_STACK(stack_sm, CFG_TEE_CORE_NB_CORE, SM_STACK_SIZE); DECLARE_STACK(stack_thread, NUM_THREADS, STACK_THREAD_SIZE); const vaddr_t stack_tmp_top[CFG_TEE_CORE_NB_CORE] = { GET_STACK(stack_tmp[0]), #if CFG_TEE_CORE_NB_CORE > 1 GET_STACK(stack_tmp[1]), #endif #if CFG_TEE_CORE_NB_CORE > 2 GET_STACK(stack_tmp[2]), #endif #if CFG_TEE_CORE_NB_CORE > 3 GET_STACK(stack_tmp[3]), #endif #if CFG_TEE_CORE_NB_CORE > 4 GET_STACK(stack_tmp[4]), #endif #if CFG_TEE_CORE_NB_CORE > 5 GET_STACK(stack_tmp[5]), #endif
/* This function is called when a segmentation fault is caught. The system is in an instable state now. This means especially that malloc() might not work anymore. */ static void catch_segfault (int signal, SIGCONTEXT ctx) { struct layout *current; void *__unbounded top_frame; void *__unbounded top_stack; int fd; void **arr; size_t cnt; struct sigaction sa; /* This is the name of the file we are writing to. If none is given or we cannot write to this file write to stderr. */ fd = 2; if (fname != NULL) { fd = open (fname, O_TRUNC | O_WRONLY | O_CREAT, 0666); if (fd == -1) fd = 2; } WRITE_STRING ("*** "); write_strsignal (fd, signal); WRITE_STRING ("\n"); #ifdef REGISTER_DUMP REGISTER_DUMP; #endif WRITE_STRING ("\nBacktrace:\n"); top_frame = GET_FRAME (ctx); top_stack = GET_STACK (ctx); /* First count how many entries we'll have. */ cnt = 1; current = BOUNDED_1 ((struct layout *) top_frame); while (!((void *) current INNER_THAN top_stack || !((void *) current INNER_THAN __libc_stack_end))) { ++cnt; current = ADVANCE_STACK_FRAME (current->next); } arr = alloca (cnt * sizeof (void *)); /* First handle the program counter from the structure. */ arr[0] = GET_PC (ctx); current = BOUNDED_1 ((struct layout *) top_frame); cnt = 1; while (!((void *) current INNER_THAN top_stack || !((void *) current INNER_THAN __libc_stack_end))) { arr[cnt++] = current->return_address; current = ADVANCE_STACK_FRAME (current->next); } /* If the last return address was NULL, assume that it doesn't count. */ if (arr[cnt-1] == NULL) cnt--; /* Now generate nicely formatted output. */ __backtrace_symbols_fd (arr, cnt, fd); /* Pass on the signal (so that a core file is produced). */ sa.sa_handler = SIG_DFL; sigemptyset (&sa.sa_mask); sa.sa_flags = 0; sigaction (signal, &sa, NULL); raise (signal); }