backtrace.S 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. /* SPDX-License-Identifier: GPL-2.0-only */
  2. /*
  3. * linux/arch/arm/lib/backtrace.S
  4. *
  5. * Copyright (C) 1995, 1996 Russell King
  6. *
  7. * 27/03/03 Ian Molton Clean up CONFIG_CPU
  8. */
  9. #include <linux/kern_levels.h>
  10. #include <linux/linkage.h>
  11. #include <asm/assembler.h>
  12. .text
  13. @ fp is 0 or stack frame
  14. #define frame r4
  15. #define sv_fp r5
  16. #define sv_pc r6
  17. #define mask r7
  18. #define offset r8
  19. #define loglvl r9
  20. ENTRY(c_backtrace)
  21. #if !defined(CONFIG_FRAME_POINTER) || !defined(CONFIG_PRINTK)
  22. ret lr
  23. ENDPROC(c_backtrace)
  24. #else
  25. stmfd sp!, {r4 - r9, lr} @ Save an extra register so we have a location...
  26. movs frame, r0 @ if frame pointer is zero
  27. beq no_frame @ we have no stack frames
  28. mov loglvl, r2
  29. tst r1, #0x10 @ 26 or 32-bit mode?
  30. ARM( moveq mask, #0xfc000003 )
  31. THUMB( moveq mask, #0xfc000000 )
  32. THUMB( orreq mask, #0x03 )
  33. movne mask, #0 @ mask for 32-bit
  34. 1: stmfd sp!, {pc} @ calculate offset of PC stored
  35. ldr r0, [sp], #4 @ by stmfd for this CPU
  36. adr r1, 1b
  37. sub offset, r0, r1
  38. /*
  39. * Stack frame layout:
  40. * optionally saved caller registers (r4 - r10)
  41. * saved fp
  42. * saved sp
  43. * saved lr
  44. * frame => saved pc
  45. * optionally saved arguments (r0 - r3)
  46. * saved sp => <next word>
  47. *
  48. * Functions start with the following code sequence:
  49. * mov ip, sp
  50. * stmfd sp!, {r0 - r3} (optional)
  51. * corrected pc => stmfd sp!, {..., fp, ip, lr, pc}
  52. */
  53. for_each_frame: tst frame, mask @ Check for address exceptions
  54. bne no_frame
  55. 1001: ldr sv_pc, [frame, #0] @ get saved pc
  56. 1002: ldr sv_fp, [frame, #-12] @ get saved fp
  57. sub sv_pc, sv_pc, offset @ Correct PC for prefetching
  58. bic sv_pc, sv_pc, mask @ mask PC/LR for the mode
  59. 1003: ldr r2, [sv_pc, #-4] @ if stmfd sp!, {args} exists,
  60. ldr r3, .Ldsi+4 @ adjust saved 'pc' back one
  61. teq r3, r2, lsr #11 @ instruction
  62. subne r0, sv_pc, #4 @ allow for mov
  63. subeq r0, sv_pc, #8 @ allow for mov + stmia
  64. ldr r1, [frame, #-4] @ get saved lr
  65. mov r2, frame
  66. bic r1, r1, mask @ mask PC/LR for the mode
  67. mov r3, loglvl
  68. bl dump_backtrace_entry
  69. ldr r1, [sv_pc, #-4] @ if stmfd sp!, {args} exists,
  70. ldr r3, .Ldsi+4
  71. teq r3, r1, lsr #11
  72. ldreq r0, [frame, #-8] @ get sp
  73. subeq r0, r0, #4 @ point at the last arg
  74. mov r2, loglvl
  75. bleq dump_backtrace_stm @ dump saved registers
  76. 1004: ldr r1, [sv_pc, #0] @ if stmfd sp!, {..., fp, ip, lr, pc}
  77. ldr r3, .Ldsi @ instruction exists,
  78. teq r3, r1, lsr #11
  79. subeq r0, frame, #16
  80. mov r2, loglvl
  81. bleq dump_backtrace_stm @ 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. #ifdef CONFIG_IRQSTACKS
  87. @
  88. @ Kernel stacks may be discontiguous in memory. If the next
  89. @ frame is below the previous frame, accept it as long as it
  90. @ lives in kernel memory.
  91. @
  92. cmpls sv_fp, #PAGE_OFFSET
  93. #endif
  94. bhi for_each_frame
  95. 1006: adr r0, .Lbad
  96. mov r1, loglvl
  97. mov r2, frame
  98. bl _printk
  99. no_frame: ldmfd sp!, {r4 - r9, pc}
  100. ENDPROC(c_backtrace)
  101. .pushsection __ex_table,"a"
  102. .align 3
  103. .long 1001b, 1006b
  104. .long 1002b, 1006b
  105. .long 1003b, 1006b
  106. .long 1004b, 1006b
  107. .popsection
  108. .Lbad: .asciz "%sBacktrace aborted due to bad frame pointer <%p>\n"
  109. .align
  110. .Ldsi: .word 0xe92dd800 >> 11 @ stmfd sp!, {... fp, ip, lr, pc}
  111. .word 0xe92d0000 >> 11 @ stmfd sp!, {}
  112. #endif