return_address.c 1.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. /*
  2. * arch/sh/kernel/return_address.c
  3. *
  4. * Copyright (C) 2009 Matt Fleming
  5. * Copyright (C) 2009 Paul Mundt
  6. *
  7. * This file is subject to the terms and conditions of the GNU General Public
  8. * License. See the file "COPYING" in the main directory of this archive
  9. * for more details.
  10. */
  11. #include <linux/kernel.h>
  12. #include <linux/module.h>
  13. #include <asm/dwarf.h>
  14. #ifdef CONFIG_DWARF_UNWINDER
  15. void *return_address(unsigned int depth)
  16. {
  17. struct dwarf_frame *frame;
  18. unsigned long ra;
  19. int i;
  20. for (i = 0, frame = NULL, ra = 0; i <= depth; i++) {
  21. struct dwarf_frame *tmp;
  22. tmp = dwarf_unwind_stack(ra, frame);
  23. if (!tmp)
  24. return NULL;
  25. if (frame)
  26. dwarf_free_frame(frame);
  27. frame = tmp;
  28. if (!frame || !frame->return_addr)
  29. break;
  30. ra = frame->return_addr;
  31. }
  32. /* Failed to unwind the stack to the specified depth. */
  33. WARN_ON(i != depth + 1);
  34. if (frame)
  35. dwarf_free_frame(frame);
  36. return (void *)ra;
  37. }
  38. #else
  39. void *return_address(unsigned int depth)
  40. {
  41. return NULL;
  42. }
  43. #endif
  44. EXPORT_SYMBOL_GPL(return_address);