backtrace.c 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. /*
  2. * SH specific backtracing code for oprofile
  3. *
  4. * Copyright 2007 STMicroelectronics Ltd.
  5. *
  6. * Author: Dave Peverley <dpeverley@mpc-data.co.uk>
  7. *
  8. * Based on ARM oprofile backtrace code by Richard Purdie and in turn, i386
  9. * oprofile backtrace code by John Levon, David Smith
  10. *
  11. * This program is free software; you can redistribute it and/or modify
  12. * it under the terms of the GNU General Public License version 2 as
  13. * published by the Free Software Foundation.
  14. *
  15. */
  16. #include <linux/oprofile.h>
  17. #include <linux/sched.h>
  18. #include <linux/kallsyms.h>
  19. #include <linux/mm.h>
  20. #include <asm/unwinder.h>
  21. #include <asm/ptrace.h>
  22. #include <asm/uaccess.h>
  23. #include <asm/sections.h>
  24. #include <asm/stacktrace.h>
  25. static void backtrace_warning_symbol(void *data, char *msg,
  26. unsigned long symbol)
  27. {
  28. /* Ignore warnings */
  29. }
  30. static void backtrace_warning(void *data, char *msg)
  31. {
  32. /* Ignore warnings */
  33. }
  34. static int backtrace_stack(void *data, char *name)
  35. {
  36. /* Yes, we want all stacks */
  37. return 0;
  38. }
  39. static void backtrace_address(void *data, unsigned long addr, int reliable)
  40. {
  41. unsigned int *depth = data;
  42. if ((*depth)--)
  43. oprofile_add_trace(addr);
  44. }
  45. static struct stacktrace_ops backtrace_ops = {
  46. .warning = backtrace_warning,
  47. .warning_symbol = backtrace_warning_symbol,
  48. .stack = backtrace_stack,
  49. .address = backtrace_address,
  50. };
  51. /* Limit to stop backtracing too far. */
  52. static int backtrace_limit = 20;
  53. static unsigned long *
  54. user_backtrace(unsigned long *stackaddr, struct pt_regs *regs)
  55. {
  56. unsigned long buf_stack;
  57. /* Also check accessibility of address */
  58. if (!access_ok(VERIFY_READ, stackaddr, sizeof(unsigned long)))
  59. return NULL;
  60. if (__copy_from_user_inatomic(&buf_stack, stackaddr, sizeof(unsigned long)))
  61. return NULL;
  62. /* Quick paranoia check */
  63. if (buf_stack & 3)
  64. return NULL;
  65. oprofile_add_trace(buf_stack);
  66. stackaddr++;
  67. return stackaddr;
  68. }
  69. void sh_backtrace(struct pt_regs * const regs, unsigned int depth)
  70. {
  71. unsigned long *stackaddr;
  72. /*
  73. * Paranoia - clip max depth as we could get lost in the weeds.
  74. */
  75. if (depth > backtrace_limit)
  76. depth = backtrace_limit;
  77. stackaddr = (unsigned long *)regs->regs[15];
  78. if (!user_mode(regs)) {
  79. if (depth)
  80. unwind_stack(NULL, regs, stackaddr,
  81. &backtrace_ops, &depth);
  82. return;
  83. }
  84. while (depth-- && (stackaddr != NULL))
  85. stackaddr = user_backtrace(stackaddr, regs);
  86. }