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(c_backtrace)
  26
  27#if !defined(CONFIG_FRAME_POINTER) || !defined(CONFIG_PRINTK)
  28                ret     lr
  29ENDPROC(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
  35                tst     r1, #0x10               @ 26 or 32-bit mode?
  36 ARM(           moveq   mask, #0xfc000003       )
  37 THUMB(         moveq   mask, #0xfc000000       )
  38 THUMB(         orreq   mask, #0x03             )
  39                movne   mask, #0                @ mask for 32-bit
  40
  411:              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/*
  47 * Stack frame layout:
  48 *             optionally saved caller registers (r4 - r10)
  49 *             saved fp
  50 *             saved sp
  51 *             saved lr
  52 *    frame => saved pc
  53 *             optionally saved arguments (r0 - r3)
  54 * saved sp => <next word>
  55 *
  56 * Functions start with the following code sequence:
  57 *                  mov   ip, sp
  58 *                  stmfd sp!, {r0 - r3} (optional)
  59 * corrected pc =>  stmfd sp!, {..., fp, ip, lr, pc}
  60 */
  61for_each_frame: tst     frame, mask             @ Check for address exceptions
  62                bne     no_frame
  63
  641001:           ldr     sv_pc, [frame, #0]      @ get saved pc
  651002:           ldr     sv_fp, [frame, #-12]    @ get saved fp
  66
  67                sub     sv_pc, sv_pc, offset    @ Correct PC for prefetching
  68                bic     sv_pc, sv_pc, mask      @ mask PC/LR for the mode
  69
  701003:           ldr     r2, [sv_pc, #-4]        @ if stmfd sp!, {args} exists,
  71                ldr     r3, .Ldsi+4             @ adjust saved 'pc' back one
  72                teq     r3, r2, lsr #10         @ instruction
  73                subne   r0, sv_pc, #4           @ allow for mov
  74                subeq   r0, sv_pc, #8           @ allow for mov + stmia
  75
  76                ldr     r1, [frame, #-4]        @ get saved lr
  77                mov     r2, frame
  78                bic     r1, r1, mask            @ mask PC/LR for the mode
  79                bl      dump_backtrace_entry
  80
  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    .Ldumpstm               @ dump saved registers
  87
  881004:           ldr     r1, [sv_pc, #0]         @ if stmfd sp!, {..., fp, ip, lr, pc}
  89                ldr     r3, .Ldsi               @ instruction exists,
  90                teq     r3, r1, lsr #11
  91                subeq   r0, frame, #16
  92                bleq    .Ldumpstm               @ dump saved registers
  93
  94                teq     sv_fp, #0               @ zero saved fp means
  95                beq     no_frame                @ no further frames
  96
  97                cmp     sv_fp, frame            @ next frame must be
  98                mov     frame, sv_fp            @ above the current frame
  99                bhi     for_each_frame
 100
 1011006:           adr     r0, .Lbad
 102                mov     r1, frame
 103                bl      printk
 104no_frame:       ldmfd   sp!, {r4 - r8, pc}
 105ENDPROC(c_backtrace)
 106                
 107                .pushsection __ex_table,"a"
 108                .align  3
 109                .long   1001b, 1006b
 110                .long   1002b, 1006b
 111                .long   1003b, 1006b
 112                .long   1004b, 1006b
 113                .popsection
 114
 115#define instr r4
 116#define reg   r5
 117#define stack r6
 118
 119.Ldumpstm:      stmfd   sp!, {instr, reg, stack, r7, lr}
 120                mov     stack, r0
 121                mov     instr, r1
 122                mov     reg, #10
 123                mov     r7, #0
 1241:              mov     r3, #1
 125 ARM(           tst     instr, r3, lsl reg      )
 126 THUMB(         lsl     r3, reg                 )
 127 THUMB(         tst     instr, r3               )
 128                beq     2f
 129                add     r7, r7, #1
 130                teq     r7, #6
 131                moveq   r7, #0
 132                adr     r3, .Lcr
 133                addne   r3, r3, #1              @ skip newline
 134                ldr     r2, [stack], #-4
 135                mov     r1, reg
 136                adr     r0, .Lfp
 137                bl      printk
 1382:              subs    reg, reg, #1
 139                bpl     1b
 140                teq     r7, #0
 141                adrne   r0, .Lcr
 142                blne    printk
 143                ldmfd   sp!, {instr, reg, stack, r7, pc}
 144
 145.Lfp:           .asciz  " r%d:%08x%s"
 146.Lcr:           .asciz  "\n"
 147.Lbad:          .asciz  "Backtrace aborted due to bad frame pointer <%p>\n"
 148                .align
 149.Ldsi:          .word   0xe92dd800 >> 11        @ stmfd sp!, {... fp, ip, lr, pc}
 150                .word   0xe92d0000 >> 11        @ stmfd sp!, {}
 151
 152#endif
 153