backtrace.S 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154
  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/linkage.h>
  14. #include <asm/assembler.h>
  15. .text
  16. @ fp is 0 or stack frame
  17. #define frame r4
  18. #define sv_fp r5
  19. #define sv_pc r6
  20. #define mask r7
  21. #define offset r8
  22. ENTRY(__backtrace)
  23. mov r1, #0x10
  24. mov r0, fp
  25. ENTRY(c_backtrace)
  26. #if !defined(CONFIG_FRAME_POINTER) || !defined(CONFIG_PRINTK)
  27. mov pc, lr
  28. ENDPROC(__backtrace)
  29. ENDPROC(c_backtrace)
  30. #else
  31. stmfd sp!, {r4 - r8, lr} @ Save an extra register so we have a location...
  32. movs frame, r0 @ if frame pointer is zero
  33. beq no_frame @ we have no stack frames
  34. tst r1, #0x10 @ 26 or 32-bit mode?
  35. moveq mask, #0xfc000003 @ mask for 26-bit
  36. movne mask, #0 @ mask for 32-bit
  37. 1: stmfd sp!, {pc} @ calculate offset of PC stored
  38. ldr r0, [sp], #4 @ by stmfd for this CPU
  39. adr r1, 1b
  40. sub offset, r0, r1
  41. /*
  42. * Stack frame layout:
  43. * optionally saved caller registers (r4 - r10)
  44. * saved fp
  45. * saved sp
  46. * saved lr
  47. * frame => saved pc
  48. * optionally saved arguments (r0 - r3)
  49. * saved sp => <next word>
  50. *
  51. * Functions start with the following code sequence:
  52. * mov ip, sp
  53. * stmfd sp!, {r0 - r3} (optional)
  54. * corrected pc => stmfd sp!, {..., fp, ip, lr, pc}
  55. */
  56. for_each_frame: tst frame, mask @ Check for address exceptions
  57. bne no_frame
  58. 1001: ldr sv_pc, [frame, #0] @ get saved pc
  59. 1002: ldr sv_fp, [frame, #-12] @ get saved fp
  60. sub sv_pc, sv_pc, offset @ Correct PC for prefetching
  61. bic sv_pc, sv_pc, mask @ mask PC/LR for the mode
  62. 1003: ldr r2, [sv_pc, #-4] @ if stmfd sp!, {args} exists,
  63. ldr r3, .Ldsi+4 @ adjust saved 'pc' back one
  64. teq r3, r2, lsr #10 @ instruction
  65. subne r0, sv_pc, #4 @ allow for mov
  66. subeq r0, sv_pc, #8 @ allow for mov + stmia
  67. ldr r1, [frame, #-4] @ get saved lr
  68. mov r2, frame
  69. bic r1, r1, mask @ mask PC/LR for the mode
  70. bl dump_backtrace_entry
  71. ldr r1, [sv_pc, #-4] @ if stmfd sp!, {args} exists,
  72. ldr r3, .Ldsi+4
  73. teq r3, r1, lsr #10
  74. ldreq r0, [frame, #-8] @ get sp
  75. subeq r0, r0, #4 @ point at the last arg
  76. bleq .Ldumpstm @ dump saved registers
  77. 1004: ldr r1, [sv_pc, #0] @ if stmfd sp!, {..., fp, ip, lr, pc}
  78. ldr r3, .Ldsi @ instruction exists,
  79. teq r3, r1, lsr #10
  80. subeq r0, frame, #16
  81. bleq .Ldumpstm @ dump saved registers
  82. teq sv_fp, #0 @ zero saved fp means
  83. beq no_frame @ no further frames
  84. cmp sv_fp, frame @ next frame must be
  85. mov frame, sv_fp @ above the current frame
  86. bhi for_each_frame
  87. 1006: adr r0, .Lbad
  88. mov r1, frame
  89. bl printk
  90. no_frame: ldmfd sp!, {r4 - r8, pc}
  91. ENDPROC(__backtrace)
  92. ENDPROC(c_backtrace)
  93. .section __ex_table,"a"
  94. .align 3
  95. .long 1001b, 1006b
  96. .long 1002b, 1006b
  97. .long 1003b, 1006b
  98. .long 1004b, 1006b
  99. .previous
  100. #define instr r4
  101. #define reg r5
  102. #define stack r6
  103. .Ldumpstm: stmfd sp!, {instr, reg, stack, r7, lr}
  104. mov stack, r0
  105. mov instr, r1
  106. mov reg, #10
  107. mov r7, #0
  108. 1: mov r3, #1
  109. tst instr, r3, lsl reg
  110. beq 2f
  111. add r7, r7, #1
  112. teq r7, #6
  113. moveq r7, #1
  114. moveq r1, #'\n'
  115. movne r1, #' '
  116. ldr r3, [stack], #-4
  117. mov r2, reg
  118. adr r0, .Lfp
  119. bl printk
  120. 2: subs reg, reg, #1
  121. bpl 1b
  122. teq r7, #0
  123. adrne r0, .Lcr
  124. blne printk
  125. ldmfd sp!, {instr, reg, stack, r7, pc}
  126. .Lfp: .asciz "%cr%d:%08x"
  127. .Lcr: .asciz "\n"
  128. .Lbad: .asciz "Backtrace aborted due to bad frame pointer <%p>\n"
  129. .align
  130. .Ldsi: .word 0xe92dd800 >> 10 @ stmfd sp!, {... fp, ip, lr, pc}
  131. .word 0xe92d0000 >> 10 @ stmfd sp!, {}
  132. #endif