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