• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /netgear-R7000-V1.0.7.12_1.2.5/components/opensource/linux/linux-2.6.36/arch/arm/kernel/
1/*
2 * arch/arm/kernel/return_address.c
3 *
4 * Copyright (C) 2009 Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
5 * for Pengutronix
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License version 2 as published by
9 * the Free Software Foundation.
10 */
11#include <linux/module.h>
12
13#if defined(CONFIG_FRAME_POINTER) && !defined(CONFIG_ARM_UNWIND)
14#include <linux/sched.h>
15
16#include <asm/stacktrace.h>
17
18struct return_address_data {
19	unsigned int level;
20	void *addr;
21};
22
23static int save_return_addr(struct stackframe *frame, void *d)
24{
25	struct return_address_data *data = d;
26
27	if (!data->level) {
28		data->addr = (void *)frame->lr;
29
30		return 1;
31	} else {
32		--data->level;
33		return 0;
34	}
35}
36
37void *return_address(unsigned int level)
38{
39	struct return_address_data data;
40	struct stackframe frame;
41	register unsigned long current_sp asm ("sp");
42
43	data.level = level + 1;
44
45	frame.fp = (unsigned long)__builtin_frame_address(0);
46	frame.sp = current_sp;
47	frame.lr = (unsigned long)__builtin_return_address(0);
48	frame.pc = (unsigned long)return_address;
49
50	walk_stackframe(&frame, save_return_addr, &data);
51
52	if (!data.level)
53		return data.addr;
54	else
55		return NULL;
56}
57
58#else /* if defined(CONFIG_FRAME_POINTER) && !defined(CONFIG_ARM_UNWIND) */
59
60#if defined(CONFIG_ARM_UNWIND)
61#warning "TODO: return_address should use unwind tables"
62#endif
63
64void *return_address(unsigned int level)
65{
66	return NULL;
67}
68
69#endif /* if defined(CONFIG_FRAME_POINTER) && !defined(CONFIG_ARM_UNWIND) / else */
70
71EXPORT_SYMBOL_GPL(return_address);
72