18637c099SIngo Molnar /* 28637c099SIngo Molnar * kernel/stacktrace.c 38637c099SIngo Molnar * 48637c099SIngo Molnar * Stack trace management functions 58637c099SIngo Molnar * 68637c099SIngo Molnar * Copyright (C) 2006 Red Hat, Inc., Ingo Molnar <[email protected]> 78637c099SIngo Molnar */ 8*214d8ca6SThomas Gleixner #include <linux/sched/task_stack.h> 9*214d8ca6SThomas Gleixner #include <linux/sched/debug.h> 108637c099SIngo Molnar #include <linux/sched.h> 119212ddb5SIngo Molnar #include <linux/kernel.h> 129984de1aSPaul Gortmaker #include <linux/export.h> 138637c099SIngo Molnar #include <linux/kallsyms.h> 148637c099SIngo Molnar #include <linux/stacktrace.h> 158637c099SIngo Molnar 16e9b98e16SThomas Gleixner /** 17e9b98e16SThomas Gleixner * stack_trace_print - Print the entries in the stack trace 18e9b98e16SThomas Gleixner * @entries: Pointer to storage array 19e9b98e16SThomas Gleixner * @nr_entries: Number of entries in the storage array 20e9b98e16SThomas Gleixner * @spaces: Number of leading spaces to print 21e9b98e16SThomas Gleixner */ 22e9b98e16SThomas Gleixner void stack_trace_print(unsigned long *entries, unsigned int nr_entries, 23e9b98e16SThomas Gleixner int spaces) 248637c099SIngo Molnar { 25e9b98e16SThomas Gleixner unsigned int i; 268637c099SIngo Molnar 27e9b98e16SThomas Gleixner if (WARN_ON(!entries)) 28bfeeeeb9SJohannes Berg return; 29bfeeeeb9SJohannes Berg 30e9b98e16SThomas Gleixner for (i = 0; i < nr_entries; i++) 31e9b98e16SThomas Gleixner printk("%*c%pS\n", 1 + spaces, ' ', (void *)entries[i]); 32e9b98e16SThomas Gleixner } 33e9b98e16SThomas Gleixner EXPORT_SYMBOL_GPL(stack_trace_print); 34e9b98e16SThomas Gleixner 35e9b98e16SThomas Gleixner /** 36e9b98e16SThomas Gleixner * stack_trace_snprint - Print the entries in the stack trace into a buffer 37e9b98e16SThomas Gleixner * @buf: Pointer to the print buffer 38e9b98e16SThomas Gleixner * @size: Size of the print buffer 39e9b98e16SThomas Gleixner * @entries: Pointer to storage array 40e9b98e16SThomas Gleixner * @nr_entries: Number of entries in the storage array 41e9b98e16SThomas Gleixner * @spaces: Number of leading spaces to print 42e9b98e16SThomas Gleixner * 43e9b98e16SThomas Gleixner * Return: Number of bytes printed. 44e9b98e16SThomas Gleixner */ 45e9b98e16SThomas Gleixner int stack_trace_snprint(char *buf, size_t size, unsigned long *entries, 46e9b98e16SThomas Gleixner unsigned int nr_entries, int spaces) 479a92a6ceSJoonsoo Kim { 48e9b98e16SThomas Gleixner unsigned int generated, i, total = 0; 499a92a6ceSJoonsoo Kim 50e9b98e16SThomas Gleixner if (WARN_ON(!entries)) 519a92a6ceSJoonsoo Kim return 0; 529a92a6ceSJoonsoo Kim 53e9b98e16SThomas Gleixner for (i = 0; i < nr_entries && size; i++) { 54bfeda41dSOmar Sandoval generated = snprintf(buf, size, "%*c%pS\n", 1 + spaces, ' ', 55e9b98e16SThomas Gleixner (void *)entries[i]); 569a92a6ceSJoonsoo Kim 579a92a6ceSJoonsoo Kim total += generated; 589a92a6ceSJoonsoo Kim if (generated >= size) { 599a92a6ceSJoonsoo Kim buf += size; 609a92a6ceSJoonsoo Kim size = 0; 619a92a6ceSJoonsoo Kim } else { 629a92a6ceSJoonsoo Kim buf += generated; 639a92a6ceSJoonsoo Kim size -= generated; 649a92a6ceSJoonsoo Kim } 659a92a6ceSJoonsoo Kim } 669a92a6ceSJoonsoo Kim 679a92a6ceSJoonsoo Kim return total; 689a92a6ceSJoonsoo Kim } 69e9b98e16SThomas Gleixner EXPORT_SYMBOL_GPL(stack_trace_snprint); 70e9b98e16SThomas Gleixner 71*214d8ca6SThomas Gleixner #ifdef CONFIG_ARCH_STACKWALK 72*214d8ca6SThomas Gleixner 73*214d8ca6SThomas Gleixner struct stacktrace_cookie { 74*214d8ca6SThomas Gleixner unsigned long *store; 75*214d8ca6SThomas Gleixner unsigned int size; 76*214d8ca6SThomas Gleixner unsigned int skip; 77*214d8ca6SThomas Gleixner unsigned int len; 78*214d8ca6SThomas Gleixner }; 79*214d8ca6SThomas Gleixner 80*214d8ca6SThomas Gleixner static bool stack_trace_consume_entry(void *cookie, unsigned long addr, 81*214d8ca6SThomas Gleixner bool reliable) 82*214d8ca6SThomas Gleixner { 83*214d8ca6SThomas Gleixner struct stacktrace_cookie *c = cookie; 84*214d8ca6SThomas Gleixner 85*214d8ca6SThomas Gleixner if (c->len >= c->size) 86*214d8ca6SThomas Gleixner return false; 87*214d8ca6SThomas Gleixner 88*214d8ca6SThomas Gleixner if (c->skip > 0) { 89*214d8ca6SThomas Gleixner c->skip--; 90*214d8ca6SThomas Gleixner return true; 91*214d8ca6SThomas Gleixner } 92*214d8ca6SThomas Gleixner c->store[c->len++] = addr; 93*214d8ca6SThomas Gleixner return c->len < c->size; 94*214d8ca6SThomas Gleixner } 95*214d8ca6SThomas Gleixner 96*214d8ca6SThomas Gleixner static bool stack_trace_consume_entry_nosched(void *cookie, unsigned long addr, 97*214d8ca6SThomas Gleixner bool reliable) 98*214d8ca6SThomas Gleixner { 99*214d8ca6SThomas Gleixner if (in_sched_functions(addr)) 100*214d8ca6SThomas Gleixner return true; 101*214d8ca6SThomas Gleixner return stack_trace_consume_entry(cookie, addr, reliable); 102*214d8ca6SThomas Gleixner } 103*214d8ca6SThomas Gleixner 104*214d8ca6SThomas Gleixner /** 105*214d8ca6SThomas Gleixner * stack_trace_save - Save a stack trace into a storage array 106*214d8ca6SThomas Gleixner * @store: Pointer to storage array 107*214d8ca6SThomas Gleixner * @size: Size of the storage array 108*214d8ca6SThomas Gleixner * @skipnr: Number of entries to skip at the start of the stack trace 109*214d8ca6SThomas Gleixner * 110*214d8ca6SThomas Gleixner * Return: Number of trace entries stored. 111*214d8ca6SThomas Gleixner */ 112*214d8ca6SThomas Gleixner unsigned int stack_trace_save(unsigned long *store, unsigned int size, 113*214d8ca6SThomas Gleixner unsigned int skipnr) 114*214d8ca6SThomas Gleixner { 115*214d8ca6SThomas Gleixner stack_trace_consume_fn consume_entry = stack_trace_consume_entry; 116*214d8ca6SThomas Gleixner struct stacktrace_cookie c = { 117*214d8ca6SThomas Gleixner .store = store, 118*214d8ca6SThomas Gleixner .size = size, 119*214d8ca6SThomas Gleixner .skip = skipnr + 1, 120*214d8ca6SThomas Gleixner }; 121*214d8ca6SThomas Gleixner 122*214d8ca6SThomas Gleixner arch_stack_walk(consume_entry, &c, current, NULL); 123*214d8ca6SThomas Gleixner return c.len; 124*214d8ca6SThomas Gleixner } 125*214d8ca6SThomas Gleixner EXPORT_SYMBOL_GPL(stack_trace_save); 126*214d8ca6SThomas Gleixner 127*214d8ca6SThomas Gleixner /** 128*214d8ca6SThomas Gleixner * stack_trace_save_tsk - Save a task stack trace into a storage array 129*214d8ca6SThomas Gleixner * @task: The task to examine 130*214d8ca6SThomas Gleixner * @store: Pointer to storage array 131*214d8ca6SThomas Gleixner * @size: Size of the storage array 132*214d8ca6SThomas Gleixner * @skipnr: Number of entries to skip at the start of the stack trace 133*214d8ca6SThomas Gleixner * 134*214d8ca6SThomas Gleixner * Return: Number of trace entries stored. 135*214d8ca6SThomas Gleixner */ 136*214d8ca6SThomas Gleixner unsigned int stack_trace_save_tsk(struct task_struct *tsk, unsigned long *store, 137*214d8ca6SThomas Gleixner unsigned int size, unsigned int skipnr) 138*214d8ca6SThomas Gleixner { 139*214d8ca6SThomas Gleixner stack_trace_consume_fn consume_entry = stack_trace_consume_entry_nosched; 140*214d8ca6SThomas Gleixner struct stacktrace_cookie c = { 141*214d8ca6SThomas Gleixner .store = store, 142*214d8ca6SThomas Gleixner .size = size, 143*214d8ca6SThomas Gleixner .skip = skipnr + 1, 144*214d8ca6SThomas Gleixner }; 145*214d8ca6SThomas Gleixner 146*214d8ca6SThomas Gleixner if (!try_get_task_stack(tsk)) 147*214d8ca6SThomas Gleixner return 0; 148*214d8ca6SThomas Gleixner 149*214d8ca6SThomas Gleixner arch_stack_walk(consume_entry, &c, tsk, NULL); 150*214d8ca6SThomas Gleixner put_task_stack(tsk); 151*214d8ca6SThomas Gleixner return c.len; 152*214d8ca6SThomas Gleixner } 153*214d8ca6SThomas Gleixner 154*214d8ca6SThomas Gleixner /** 155*214d8ca6SThomas Gleixner * stack_trace_save_regs - Save a stack trace based on pt_regs into a storage array 156*214d8ca6SThomas Gleixner * @regs: Pointer to pt_regs to examine 157*214d8ca6SThomas Gleixner * @store: Pointer to storage array 158*214d8ca6SThomas Gleixner * @size: Size of the storage array 159*214d8ca6SThomas Gleixner * @skipnr: Number of entries to skip at the start of the stack trace 160*214d8ca6SThomas Gleixner * 161*214d8ca6SThomas Gleixner * Return: Number of trace entries stored. 162*214d8ca6SThomas Gleixner */ 163*214d8ca6SThomas Gleixner unsigned int stack_trace_save_regs(struct pt_regs *regs, unsigned long *store, 164*214d8ca6SThomas Gleixner unsigned int size, unsigned int skipnr) 165*214d8ca6SThomas Gleixner { 166*214d8ca6SThomas Gleixner stack_trace_consume_fn consume_entry = stack_trace_consume_entry; 167*214d8ca6SThomas Gleixner struct stacktrace_cookie c = { 168*214d8ca6SThomas Gleixner .store = store, 169*214d8ca6SThomas Gleixner .size = size, 170*214d8ca6SThomas Gleixner .skip = skipnr, 171*214d8ca6SThomas Gleixner }; 172*214d8ca6SThomas Gleixner 173*214d8ca6SThomas Gleixner arch_stack_walk(consume_entry, &c, current, regs); 174*214d8ca6SThomas Gleixner return c.len; 175*214d8ca6SThomas Gleixner } 176*214d8ca6SThomas Gleixner 177*214d8ca6SThomas Gleixner #ifdef CONFIG_HAVE_RELIABLE_STACKTRACE 178*214d8ca6SThomas Gleixner /** 179*214d8ca6SThomas Gleixner * stack_trace_save_tsk_reliable - Save task stack with verification 180*214d8ca6SThomas Gleixner * @tsk: Pointer to the task to examine 181*214d8ca6SThomas Gleixner * @store: Pointer to storage array 182*214d8ca6SThomas Gleixner * @size: Size of the storage array 183*214d8ca6SThomas Gleixner * 184*214d8ca6SThomas Gleixner * Return: An error if it detects any unreliable features of the 185*214d8ca6SThomas Gleixner * stack. Otherwise it guarantees that the stack trace is 186*214d8ca6SThomas Gleixner * reliable and returns the number of entries stored. 187*214d8ca6SThomas Gleixner * 188*214d8ca6SThomas Gleixner * If the task is not 'current', the caller *must* ensure the task is inactive. 189*214d8ca6SThomas Gleixner */ 190*214d8ca6SThomas Gleixner int stack_trace_save_tsk_reliable(struct task_struct *tsk, unsigned long *store, 191*214d8ca6SThomas Gleixner unsigned int size) 192*214d8ca6SThomas Gleixner { 193*214d8ca6SThomas Gleixner stack_trace_consume_fn consume_entry = stack_trace_consume_entry; 194*214d8ca6SThomas Gleixner struct stacktrace_cookie c = { 195*214d8ca6SThomas Gleixner .store = store, 196*214d8ca6SThomas Gleixner .size = size, 197*214d8ca6SThomas Gleixner }; 198*214d8ca6SThomas Gleixner int ret; 199*214d8ca6SThomas Gleixner 200*214d8ca6SThomas Gleixner /* 201*214d8ca6SThomas Gleixner * If the task doesn't have a stack (e.g., a zombie), the stack is 202*214d8ca6SThomas Gleixner * "reliably" empty. 203*214d8ca6SThomas Gleixner */ 204*214d8ca6SThomas Gleixner if (!try_get_task_stack(tsk)) 205*214d8ca6SThomas Gleixner return 0; 206*214d8ca6SThomas Gleixner 207*214d8ca6SThomas Gleixner ret = arch_stack_walk_reliable(consume_entry, &c, tsk); 208*214d8ca6SThomas Gleixner put_task_stack(tsk); 209*214d8ca6SThomas Gleixner return ret; 210*214d8ca6SThomas Gleixner } 211*214d8ca6SThomas Gleixner #endif 212*214d8ca6SThomas Gleixner 213*214d8ca6SThomas Gleixner #ifdef CONFIG_USER_STACKTRACE_SUPPORT 214*214d8ca6SThomas Gleixner /** 215*214d8ca6SThomas Gleixner * stack_trace_save_user - Save a user space stack trace into a storage array 216*214d8ca6SThomas Gleixner * @store: Pointer to storage array 217*214d8ca6SThomas Gleixner * @size: Size of the storage array 218*214d8ca6SThomas Gleixner * 219*214d8ca6SThomas Gleixner * Return: Number of trace entries stored. 220*214d8ca6SThomas Gleixner */ 221*214d8ca6SThomas Gleixner unsigned int stack_trace_save_user(unsigned long *store, unsigned int size) 222*214d8ca6SThomas Gleixner { 223*214d8ca6SThomas Gleixner stack_trace_consume_fn consume_entry = stack_trace_consume_entry; 224*214d8ca6SThomas Gleixner struct stacktrace_cookie c = { 225*214d8ca6SThomas Gleixner .store = store, 226*214d8ca6SThomas Gleixner .size = size, 227*214d8ca6SThomas Gleixner }; 228*214d8ca6SThomas Gleixner 229*214d8ca6SThomas Gleixner /* Trace user stack if not a kernel thread */ 230*214d8ca6SThomas Gleixner if (!current->mm) 231*214d8ca6SThomas Gleixner return 0; 232*214d8ca6SThomas Gleixner 233*214d8ca6SThomas Gleixner arch_stack_walk_user(consume_entry, &c, task_pt_regs(current)); 234*214d8ca6SThomas Gleixner return c.len; 235*214d8ca6SThomas Gleixner } 236*214d8ca6SThomas Gleixner #endif 237*214d8ca6SThomas Gleixner 238*214d8ca6SThomas Gleixner #else /* CONFIG_ARCH_STACKWALK */ 239*214d8ca6SThomas Gleixner 2409212ddb5SIngo Molnar /* 241af085d90SJosh Poimboeuf * Architectures that do not implement save_stack_trace_*() 242af085d90SJosh Poimboeuf * get these weak aliases and once-per-bootup warnings 243c624d33fSMasami Hiramatsu * (whenever this facility is utilized - for example by procfs): 2449212ddb5SIngo Molnar */ 2459212ddb5SIngo Molnar __weak void 2469212ddb5SIngo Molnar save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace) 2479212ddb5SIngo Molnar { 2489212ddb5SIngo Molnar WARN_ONCE(1, KERN_INFO "save_stack_trace_tsk() not implemented yet.\n"); 2499212ddb5SIngo Molnar } 250c624d33fSMasami Hiramatsu 251c624d33fSMasami Hiramatsu __weak void 252c624d33fSMasami Hiramatsu save_stack_trace_regs(struct pt_regs *regs, struct stack_trace *trace) 253c624d33fSMasami Hiramatsu { 254c624d33fSMasami Hiramatsu WARN_ONCE(1, KERN_INFO "save_stack_trace_regs() not implemented yet.\n"); 255c624d33fSMasami Hiramatsu } 256af085d90SJosh Poimboeuf 257af085d90SJosh Poimboeuf __weak int 258af085d90SJosh Poimboeuf save_stack_trace_tsk_reliable(struct task_struct *tsk, 259af085d90SJosh Poimboeuf struct stack_trace *trace) 260af085d90SJosh Poimboeuf { 261af085d90SJosh Poimboeuf WARN_ONCE(1, KERN_INFO "save_stack_tsk_reliable() not implemented yet.\n"); 262af085d90SJosh Poimboeuf return -ENOSYS; 263af085d90SJosh Poimboeuf } 264e9b98e16SThomas Gleixner 265e9b98e16SThomas Gleixner /** 266e9b98e16SThomas Gleixner * stack_trace_save - Save a stack trace into a storage array 267e9b98e16SThomas Gleixner * @store: Pointer to storage array 268e9b98e16SThomas Gleixner * @size: Size of the storage array 269e9b98e16SThomas Gleixner * @skipnr: Number of entries to skip at the start of the stack trace 270e9b98e16SThomas Gleixner * 271e9b98e16SThomas Gleixner * Return: Number of trace entries stored 272e9b98e16SThomas Gleixner */ 273e9b98e16SThomas Gleixner unsigned int stack_trace_save(unsigned long *store, unsigned int size, 274e9b98e16SThomas Gleixner unsigned int skipnr) 275e9b98e16SThomas Gleixner { 276e9b98e16SThomas Gleixner struct stack_trace trace = { 277e9b98e16SThomas Gleixner .entries = store, 278e9b98e16SThomas Gleixner .max_entries = size, 279e9b98e16SThomas Gleixner .skip = skipnr + 1, 280e9b98e16SThomas Gleixner }; 281e9b98e16SThomas Gleixner 282e9b98e16SThomas Gleixner save_stack_trace(&trace); 283e9b98e16SThomas Gleixner return trace.nr_entries; 284e9b98e16SThomas Gleixner } 285e9b98e16SThomas Gleixner EXPORT_SYMBOL_GPL(stack_trace_save); 286e9b98e16SThomas Gleixner 287e9b98e16SThomas Gleixner /** 288e9b98e16SThomas Gleixner * stack_trace_save_tsk - Save a task stack trace into a storage array 289e9b98e16SThomas Gleixner * @task: The task to examine 290e9b98e16SThomas Gleixner * @store: Pointer to storage array 291e9b98e16SThomas Gleixner * @size: Size of the storage array 292e9b98e16SThomas Gleixner * @skipnr: Number of entries to skip at the start of the stack trace 293e9b98e16SThomas Gleixner * 294e9b98e16SThomas Gleixner * Return: Number of trace entries stored 295e9b98e16SThomas Gleixner */ 296e9b98e16SThomas Gleixner unsigned int stack_trace_save_tsk(struct task_struct *task, 297e9b98e16SThomas Gleixner unsigned long *store, unsigned int size, 298e9b98e16SThomas Gleixner unsigned int skipnr) 299e9b98e16SThomas Gleixner { 300e9b98e16SThomas Gleixner struct stack_trace trace = { 301e9b98e16SThomas Gleixner .entries = store, 302e9b98e16SThomas Gleixner .max_entries = size, 303e9b98e16SThomas Gleixner .skip = skipnr + 1, 304e9b98e16SThomas Gleixner }; 305e9b98e16SThomas Gleixner 306e9b98e16SThomas Gleixner save_stack_trace_tsk(task, &trace); 307e9b98e16SThomas Gleixner return trace.nr_entries; 308e9b98e16SThomas Gleixner } 309e9b98e16SThomas Gleixner 310e9b98e16SThomas Gleixner /** 311e9b98e16SThomas Gleixner * stack_trace_save_regs - Save a stack trace based on pt_regs into a storage array 312e9b98e16SThomas Gleixner * @regs: Pointer to pt_regs to examine 313e9b98e16SThomas Gleixner * @store: Pointer to storage array 314e9b98e16SThomas Gleixner * @size: Size of the storage array 315e9b98e16SThomas Gleixner * @skipnr: Number of entries to skip at the start of the stack trace 316e9b98e16SThomas Gleixner * 317e9b98e16SThomas Gleixner * Return: Number of trace entries stored 318e9b98e16SThomas Gleixner */ 319e9b98e16SThomas Gleixner unsigned int stack_trace_save_regs(struct pt_regs *regs, unsigned long *store, 320e9b98e16SThomas Gleixner unsigned int size, unsigned int skipnr) 321e9b98e16SThomas Gleixner { 322e9b98e16SThomas Gleixner struct stack_trace trace = { 323e9b98e16SThomas Gleixner .entries = store, 324e9b98e16SThomas Gleixner .max_entries = size, 325e9b98e16SThomas Gleixner .skip = skipnr, 326e9b98e16SThomas Gleixner }; 327e9b98e16SThomas Gleixner 328e9b98e16SThomas Gleixner save_stack_trace_regs(regs, &trace); 329e9b98e16SThomas Gleixner return trace.nr_entries; 330e9b98e16SThomas Gleixner } 331e9b98e16SThomas Gleixner 332e9b98e16SThomas Gleixner #ifdef CONFIG_HAVE_RELIABLE_STACKTRACE 333e9b98e16SThomas Gleixner /** 334e9b98e16SThomas Gleixner * stack_trace_save_tsk_reliable - Save task stack with verification 335e9b98e16SThomas Gleixner * @tsk: Pointer to the task to examine 336e9b98e16SThomas Gleixner * @store: Pointer to storage array 337e9b98e16SThomas Gleixner * @size: Size of the storage array 338e9b98e16SThomas Gleixner * 339e9b98e16SThomas Gleixner * Return: An error if it detects any unreliable features of the 340e9b98e16SThomas Gleixner * stack. Otherwise it guarantees that the stack trace is 341e9b98e16SThomas Gleixner * reliable and returns the number of entries stored. 342e9b98e16SThomas Gleixner * 343e9b98e16SThomas Gleixner * If the task is not 'current', the caller *must* ensure the task is inactive. 344e9b98e16SThomas Gleixner */ 345e9b98e16SThomas Gleixner int stack_trace_save_tsk_reliable(struct task_struct *tsk, unsigned long *store, 346e9b98e16SThomas Gleixner unsigned int size) 347e9b98e16SThomas Gleixner { 348e9b98e16SThomas Gleixner struct stack_trace trace = { 349e9b98e16SThomas Gleixner .entries = store, 350e9b98e16SThomas Gleixner .max_entries = size, 351e9b98e16SThomas Gleixner }; 352e9b98e16SThomas Gleixner int ret = save_stack_trace_tsk_reliable(tsk, &trace); 353e9b98e16SThomas Gleixner 354e9b98e16SThomas Gleixner return ret ? ret : trace.nr_entries; 355e9b98e16SThomas Gleixner } 356e9b98e16SThomas Gleixner #endif 357e9b98e16SThomas Gleixner 358e9b98e16SThomas Gleixner #ifdef CONFIG_USER_STACKTRACE_SUPPORT 359e9b98e16SThomas Gleixner /** 360e9b98e16SThomas Gleixner * stack_trace_save_user - Save a user space stack trace into a storage array 361e9b98e16SThomas Gleixner * @store: Pointer to storage array 362e9b98e16SThomas Gleixner * @size: Size of the storage array 363e9b98e16SThomas Gleixner * 364e9b98e16SThomas Gleixner * Return: Number of trace entries stored 365e9b98e16SThomas Gleixner */ 366e9b98e16SThomas Gleixner unsigned int stack_trace_save_user(unsigned long *store, unsigned int size) 367e9b98e16SThomas Gleixner { 368e9b98e16SThomas Gleixner struct stack_trace trace = { 369e9b98e16SThomas Gleixner .entries = store, 370e9b98e16SThomas Gleixner .max_entries = size, 371e9b98e16SThomas Gleixner }; 372e9b98e16SThomas Gleixner 373e9b98e16SThomas Gleixner save_stack_trace_user(&trace); 374e9b98e16SThomas Gleixner return trace.nr_entries; 375e9b98e16SThomas Gleixner } 376e9b98e16SThomas Gleixner #endif /* CONFIG_USER_STACKTRACE_SUPPORT */ 377*214d8ca6SThomas Gleixner 378*214d8ca6SThomas Gleixner #endif /* !CONFIG_ARCH_STACKWALK */ 379