2005-04-16 15:20:36 -07:00
/ *
* linux/ a r c h / a r m / l i b / b a c k t r a c e . S
*
* Copyright ( C ) 1 9 9 5 , 1 9 9 6 R u s s e l l K i n g
*
* This p r o g r a m i s f r e e s o f t w a r e ; you can redistribute it and/or modify
* it u n d e r t h e t e r m s o f t h e G N U G e n e r a l P u b l i c L i c e n s e v e r s i o n 2 a s
* published b y t h e F r e e S o f t w a r e F o u n d a t i o n .
*
* 2 7 / 0 3 / 0 3 Ian M o l t o n C l e a n u p C O N F I G _ C P U
*
* /
# include < l i n u x / l i n k a g e . h >
# include < a s m / a s s e m b l e r . h >
.text
@ fp is 0 or stack frame
# define f r a m e r4
2007-03-02 15:01:36 +00:00
# define s v _ f p r5
# define s v _ p c r6
2005-04-16 15:20:36 -07:00
# define m a s k r7
# define o f f s e t r8
ENTRY( c _ b a c k t r a c e )
2006-03-25 21:58:03 +00:00
# if ! d e f i n e d ( C O N F I G _ F R A M E _ P O I N T E R ) | | ! d e f i n e d ( C O N F I G _ P R I N T K )
2005-04-16 15:20:36 -07:00
mov p c , l r
2008-08-28 11:22:32 +01:00
ENDPROC( c _ b a c k t r a c e )
2005-04-16 15:20:36 -07:00
# else
stmfd s p ! , { r4 - r8 , l r } @ Save an extra register so we have a location...
2007-03-02 15:01:36 +00:00
movs f r a m e , r0 @ if frame pointer is zero
beq n o _ f r a m e @ we have no stack frames
tst r1 , #0x10 @ 26 or 32-bit mode?
2009-07-24 12:32:57 +01:00
ARM( m o v e q m a s k , #0xfc000003 )
THUMB( m o v e q m a s k , #0xfc000000 )
THUMB( o r r e q m a s k , #0x03 )
2007-03-02 15:01:36 +00:00
movne m a s k , #0 @ mask for 32-bit
1 : stmfd s p ! , { p c } @ calculate offset of PC stored
ldr r0 , [ s p ] , #4 @ by stmfd for this CPU
adr r1 , 1 b
2005-04-16 15:20:36 -07:00
sub o f f s e t , r0 , r1
2007-03-02 15:01:36 +00:00
/ *
* Stack f r a m e l a y o u t :
* optionally s a v e d c a l l e r r e g i s t e r s ( r4 - r10 )
* saved f p
* saved s p
* saved l r
* frame = > s a v e d p c
* optionally s a v e d a r g u m e n t s ( r0 - r3 )
* saved s p = > < n e x t w o r d >
*
* Functions s t a r t w i t h t h e f o l l o w i n g c o d e s e q u e n c e :
* mov i p , s p
* stmfd s p ! , { r0 - r3 } ( o p t i o n a l )
* corrected p c = > s t m f d s p ! , { . . . , f p , i p , l r , p c }
* /
for_each_frame : tst f r a m e , m a s k @ Check for address exceptions
bne n o _ f r a m e
1001 : ldr s v _ p c , [ f r a m e , #0 ] @ get saved pc
1002 : ldr s v _ f p , [ f r a m e , #- 12 ] @ get saved fp
2005-04-16 15:20:36 -07:00
2007-03-02 15:01:36 +00:00
sub s v _ p c , s v _ p c , o f f s e t @ Correct PC for prefetching
bic s v _ p c , s v _ p c , m a s k @ mask PC/LR for the mode
1003 : ldr r2 , [ s v _ p c , #- 4 ] @ if stmfd sp!, {args} exists,
ldr r3 , . L d s i + 4 @ adjust saved 'pc' back one
teq r3 , r2 , l s r #10 @ instruction
subne r0 , s v _ p c , #4 @ allow for mov
subeq r0 , s v _ p c , #8 @ allow for mov + stmia
ldr r1 , [ f r a m e , #- 4 ] @ get saved lr
mov r2 , f r a m e
bic r1 , r1 , m a s k @ mask PC/LR for the mode
2005-04-16 15:20:36 -07:00
bl d u m p _ b a c k t r a c e _ e n t r y
2007-03-02 15:01:36 +00:00
ldr r1 , [ s v _ p c , #- 4 ] @ if stmfd sp!, {args} exists,
ldr r3 , . L d s i + 4
2013-10-20 15:34:10 +01:00
teq r3 , r1 , l s r #11
2007-03-02 15:01:36 +00:00
ldreq r0 , [ f r a m e , #- 8 ] @ get sp
subeq r0 , r0 , #4 @ point at the last arg
bleq . L d u m p s t m @ dump saved registers
2005-04-16 15:20:36 -07:00
2007-03-02 15:01:36 +00:00
1004 : ldr r1 , [ s v _ p c , #0 ] @ if stmfd sp!, {..., fp, ip, lr, pc}
ldr r3 , . L d s i @ instruction exists,
2013-10-20 15:34:10 +01:00
teq r3 , r1 , l s r #11
2007-03-02 15:01:36 +00:00
subeq r0 , f r a m e , #16
bleq . L d u m p s t m @ dump saved registers
teq s v _ f p , #0 @ zero saved fp means
beq n o _ f r a m e @ no further frames
cmp s v _ f p , f r a m e @ next frame must be
mov f r a m e , s v _ f p @ above the current frame
bhi f o r _ e a c h _ f r a m e
1006 : adr r0 , . L b a d
2005-04-16 15:20:36 -07:00
mov r1 , f r a m e
bl p r i n t k
2007-03-02 15:01:36 +00:00
no_frame : ldmfd s p ! , { r4 - r8 , p c }
2008-08-28 11:22:32 +01:00
ENDPROC( c _ b a c k t r a c e )
2005-04-16 15:20:36 -07:00
2010-04-19 10:15:03 +01:00
.pushsection _ _ ex_ t a b l e ," a "
2005-04-16 15:20:36 -07:00
.align 3
2007-03-02 15:01:36 +00:00
.long 1 0 0 1 b, 1 0 0 6 b
.long 1 0 0 2 b, 1 0 0 6 b
.long 1 0 0 3 b, 1 0 0 6 b
.long 1 0 0 4 b, 1 0 0 6 b
2010-04-19 10:15:03 +01:00
.popsection
2005-04-16 15:20:36 -07:00
# define i n s t r r4
# define r e g r5
# define s t a c k r6
2007-03-02 15:01:36 +00:00
.Ldumpstm : stmfd s p ! , { i n s t r , r e g , s t a c k , r7 , l r }
2005-04-16 15:20:36 -07:00
mov s t a c k , r0
mov i n s t r , r1
2007-03-02 15:01:36 +00:00
mov r e g , #10
2005-04-16 15:20:36 -07:00
mov r7 , #0
1 : mov r3 , #1
2009-07-24 12:32:57 +01:00
ARM( t s t i n s t r , r3 , l s l r e g )
THUMB( l s l r3 , r e g )
THUMB( t s t i n s t r , r3 )
2005-04-16 15:20:36 -07:00
beq 2 f
add r7 , r7 , #1
2007-03-02 15:01:36 +00:00
teq r7 , #6
2013-10-20 15:34:10 +01:00
moveq r7 , #0
adr r3 , . L c r
addne r3 , r3 , #1 @ skip newline
ldr r2 , [ s t a c k ] , #- 4
mov r1 , r e g
2005-04-16 15:20:36 -07:00
adr r0 , . L f p
bl p r i n t k
2 : subs r e g , r e g , #1
bpl 1 b
teq r7 , #0
adrne r0 , . L c r
blne p r i n t k
2007-03-02 15:01:36 +00:00
ldmfd s p ! , { i n s t r , r e g , s t a c k , r7 , p c }
2005-04-16 15:20:36 -07:00
2013-10-20 15:34:10 +01:00
.Lfp : .asciz " r% d : % 0 8 x % s "
2005-04-16 15:20:36 -07:00
.Lcr : .asciz " \ n"
.Lbad : .asciz " Backtrace a b o r t e d d u e t o b a d f r a m e p o i n t e r < % p > \ n "
.align
2013-10-20 15:34:10 +01:00
.Ldsi : .word 0xe92dd800 > > 1 1 @ stmfd sp!, {... fp, ip, lr, pc}
.word 0xe92d0000 > > 1 1 @ stmfd sp!, {}
2005-04-16 15:20:36 -07:00
# endif