/* * Perform stack unwinding by using the _Unwind_Backtrace. * * User application that wants to use backtrace needs to be * compiled with -fexceptions option and -rdynamic to get full * symbols printed. */ int backtrace (void **array, int size) { struct trace_arg arg = { .array = array, .size = size, .cnt = -1 }; if (unwind_backtrace == NULL) backtrace_init(); if (size >= 1) unwind_backtrace (backtrace_helper, &arg); return arg.cnt != -1 ? arg.cnt : 0; }
static int KBacktraceIterator_restart(struct KBacktraceIterator *kbt) { struct pt_regs *p; p = valid_fault_handler(kbt); if (p == NULL) p = valid_sigframe(kbt); if (p == NULL) return 0; backtrace_init(&kbt->it, read_memory_func, kbt, p->pc, p->lr, p->sp, p->regs[52]); kbt->new_context = 1; return 1; }
void KBacktraceIterator_init(struct KBacktraceIterator *kbt, struct task_struct *t, struct pt_regs *regs) { unsigned long pc, lr, sp, r52; int is_current; /* * Set up callback information. We grab the kernel stack base * so we will allow reads of that address range, and if we're * asking about the current process we grab the page table * so we can check user accesses before trying to read them. * We flush the TLB to avoid any weird skew issues. */ is_current = (t == NULL); kbt->is_current = is_current; if (is_current) t = validate_current(); kbt->task = t; kbt->pgtable = NULL; kbt->verbose = 0; /* override in caller if desired */ kbt->profile = 0; /* override in caller if desired */ kbt->end = KBT_ONGOING; kbt->new_context = 0; if (is_current) { HV_PhysAddr pgdir_pa = hv_inquire_context().page_table; if (pgdir_pa == (unsigned long)swapper_pg_dir - PAGE_OFFSET) { /* * Not just an optimization: this also allows * this to work at all before va/pa mappings * are set up. */ kbt->pgtable = swapper_pg_dir; } else { struct page *page = pfn_to_page(PFN_DOWN(pgdir_pa)); if (!PageHighMem(page)) kbt->pgtable = __va(pgdir_pa); else pr_err("page table not in LOWMEM" " (%#llx)\n", pgdir_pa); } local_flush_tlb_all(); validate_stack(regs); } if (regs == NULL) { if (is_current || t->state == TASK_RUNNING) { /* Can't do this; we need registers */ kbt->end = KBT_RUNNING; return; } pc = get_switch_to_pc(); lr = t->thread.pc; sp = t->thread.ksp; r52 = 0; } else { pc = regs->pc; lr = regs->lr; sp = regs->sp; r52 = regs->regs[52]; } backtrace_init(&kbt->it, read_memory_func, kbt, pc, lr, sp, r52); kbt->end = KBacktraceIterator_next_item_inclusive(kbt); }