linux/arch/arm64/kernel/return_address.c
<<
>>
Prefs
   1/*
   2 * arch/arm64/kernel/return_address.c
   3 *
   4 * Copyright (C) 2013 Linaro Limited
   5 * Author: AKASHI Takahiro <takahiro.akashi@linaro.org>
   6 *
   7 * This program is free software; you can redistribute it and/or modify
   8 * it under the terms of the GNU General Public License version 2 as
   9 * published by the Free Software Foundation.
  10 */
  11
  12#include <linux/export.h>
  13#include <linux/ftrace.h>
  14
  15#include <asm/stack_pointer.h>
  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->pc;
  29                return 1;
  30        } else {
  31                --data->level;
  32                return 0;
  33        }
  34}
  35
  36void *return_address(unsigned int level)
  37{
  38        struct return_address_data data;
  39        struct stackframe frame;
  40
  41        data.level = level + 2;
  42        data.addr = NULL;
  43
  44        frame.fp = (unsigned long)__builtin_frame_address(0);
  45        frame.pc = (unsigned long)return_address; /* dummy */
  46#ifdef CONFIG_FUNCTION_GRAPH_TRACER
  47        frame.graph = current->curr_ret_stack;
  48#endif
  49
  50        walk_stackframe(current, &frame, save_return_addr, &data);
  51
  52        if (!data.level)
  53                return data.addr;
  54        else
  55                return NULL;
  56}
  57EXPORT_SYMBOL_GPL(return_address);
  58