linux/arch/arm/kernel/return_address.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * arch/arm/kernel/return_address.c
   4 *
   5 * Copyright (C) 2009 Uwe Kleine-Koenig <u.kleine-koenig@pengutronix.de>
   6 * for Pengutronix
   7 */
   8#include <linux/export.h>
   9#include <linux/ftrace.h>
  10#include <linux/sched.h>
  11
  12#include <asm/stacktrace.h>
  13
  14struct return_address_data {
  15        unsigned int level;
  16        void *addr;
  17};
  18
  19static int save_return_addr(struct stackframe *frame, void *d)
  20{
  21        struct return_address_data *data = d;
  22
  23        if (!data->level) {
  24                data->addr = (void *)frame->pc;
  25
  26                return 1;
  27        } else {
  28                --data->level;
  29                return 0;
  30        }
  31}
  32
  33void *return_address(unsigned int level)
  34{
  35        struct return_address_data data;
  36        struct stackframe frame;
  37
  38        data.level = level + 2;
  39        data.addr = NULL;
  40
  41        frame.fp = (unsigned long)__builtin_frame_address(0);
  42        frame.sp = current_stack_pointer;
  43        frame.lr = (unsigned long)__builtin_return_address(0);
  44        frame.pc = (unsigned long)return_address;
  45
  46        walk_stackframe(&frame, save_return_addr, &data);
  47
  48        if (!data.level)
  49                return data.addr;
  50        else
  51                return NULL;
  52}
  53
  54EXPORT_SYMBOL_GPL(return_address);
  55