backtrace.S 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140
  1. /*
  2. * linux/arch/arm/lib/backtrace.S
  3. *
  4. * Copyright (C) 1995, 1996 Russell King
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License version 2 as
  8. * published by the Free Software Foundation.
  9. *
  10. * 27/03/03 Ian Molton Clean up CONFIG_CPU
  11. *
  12. */
  13. #include <linux/kern_levels.h>
  14. #include <linux/linkage.h>
  15. #include <asm/assembler.h>
  16. .extern _stext, _etext
  17. __stext:
  18. .word _stext
  19. __etext:
  20. .word _etext
  21. .text
  22. @ fp is 0 or stack frame
  23. #define frame r4
  24. #define sv_fp r5
  25. #define sv_pc r6
  26. #define mask r7
  27. #define offset r8
  28. ENTRY(c_backtrace)
  29. #if !defined(CONFIG_FRAME_POINTER) || !defined(CONFIG_PRINTK)
  30. ret lr
  31. ENDPROC(c_backtrace)
  32. #else
  33. stmfd sp!, {r4 - r8, lr} @ Save an extra register so we have a location...
  34. movs frame, r0 @ if frame pointer is zero
  35. beq no_frame @ we have no stack frames
  36. tst r1, #0x10 @ 26 or 32-bit mode?
  37. ARM( moveq mask, #0xfc000003 )
  38. THUMB( moveq mask, #0xfc000000 )
  39. THUMB( orreq mask, #0x03 )
  40. movne mask, #0 @ mask for 32-bit
  41. 1: stmfd sp!, {pc} @ calculate offset of PC stored
  42. ldr r0, [sp], #4 @ by stmfd for this CPU
  43. adr r1, 1b
  44. sub offset, r0, r1
  45. /*
  46. * Stack frame layout:
  47. * optionally saved caller registers (r4 - r10)
  48. * saved fp
  49. * saved sp
  50. * saved lr
  51. * frame => saved pc
  52. * optionally saved arguments (r0 - r3)
  53. * saved sp => <next word>
  54. *
  55. * Functions start with the following code sequence:
  56. * mov ip, sp
  57. * stmfd sp!, {r0 - r3} (optional)
  58. * corrected pc => stmfd sp!, {..., fp, ip, lr, pc}
  59. */
  60. for_each_frame: tst frame, mask @ Check for address exceptions
  61. bne no_frame
  62. 1001: ldr sv_pc, [frame, #0] @ get saved pc
  63. 1002: ldr sv_fp, [frame, #-12] @ get saved fp
  64. sub sv_pc, sv_pc, offset @ Correct PC for prefetching
  65. bic sv_pc, sv_pc, mask @ mask PC/LR for the mode
  66. ldr r0, __stext
  67. cmp sv_pc, r0
  68. blo .badpc
  69. ldr r0, __etext
  70. cmp sv_pc, r0
  71. bhs .badpc
  72. 1003: ldr r2, [sv_pc, #-4] @ if stmfd sp!, {args} exists,
  73. ldr r3, .Ldsi+4 @ adjust saved 'pc' back one
  74. teq r3, r2, lsr #10 @ instruction
  75. subne r0, sv_pc, #4 @ allow for mov
  76. subeq r0, sv_pc, #8 @ allow for mov + stmia
  77. ldr r1, [frame, #-4] @ get saved lr
  78. mov r2, frame
  79. bic r1, r1, mask @ mask PC/LR for the mode
  80. bl dump_backtrace_entry
  81. ldr r1, [sv_pc, #-4] @ if stmfd sp!, {args} exists,
  82. ldr r3, .Ldsi+4
  83. teq r3, r1, lsr #11
  84. ldreq r0, [frame, #-8] @ get sp
  85. subeq r0, r0, #4 @ point at the last arg
  86. bleq dump_backtrace_stm @ dump saved registers
  87. 1004: ldr r1, [sv_pc, #0] @ if stmfd sp!, {..., fp, ip, lr, pc}
  88. ldr r3, .Ldsi @ instruction exists,
  89. teq r3, r1, lsr #11
  90. subeq r0, frame, #16
  91. bleq dump_backtrace_stm @ dump saved registers
  92. teq sv_fp, #0 @ zero saved fp means
  93. beq no_frame @ no further frames
  94. cmp sv_fp, frame @ next frame must be
  95. mov frame, sv_fp @ above the current frame
  96. bhi for_each_frame
  97. 1006: adr r0, .Lbad
  98. mov r1, frame
  99. bl printk
  100. no_frame: ldmfd sp!, {r4 - r8, pc}
  101. ENDPROC(c_backtrace)
  102. .pushsection __ex_table,"a"
  103. .align 3
  104. .long 1001b, 1006b
  105. .long 1002b, 1006b
  106. .long 1003b, 1006b
  107. .long 1004b, 1006b
  108. .popsection
  109. .badpc:
  110. adr r0, .Lbadpc
  111. mov r1, sv_pc
  112. bl printk
  113. b no_frame
  114. .Lbad: .asciz "Backtrace aborted due to bad frame pointer <%p>\n"
  115. .align
  116. .Lbadpc: .asciz "Backtrace aborted due to bad pc <%p>\n"
  117. .align
  118. .Ldsi: .word 0xe92dd800 >> 11 @ stmfd sp!, {... fp, ip, lr, pc}
  119. .word 0xe92d0000 >> 11 @ stmfd sp!, {}
  120. #endif