ARM: 8225/1: Add unwinding support for memory copy functions
authorLin Yongting <linyongting@gmail.com>
Wed, 26 Nov 2014 13:38:33 +0000 (14:38 +0100)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Thu, 27 Nov 2014 16:00:25 +0000 (16:00 +0000)
The memory copy functions(memcpy, __copy_from_user, __copy_to_user)
never had unwinding annotations added. Currently, when accessing
invalid pointer by these functions occurs the backtrace shown will
stop at these functions or some completely unrelated function.
Add unwinding annotations in hopes of getting a more useful backtrace
in following cases:
1. die on accessing invalid pointer by these functions
2. kprobe trapped at any instruction within these functions
3. interrupted at any instruction within these functions

Signed-off-by: Lin Yongting <linyongting@gmail.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
arch/arm/lib/copy_from_user.S
arch/arm/lib/copy_template.S
arch/arm/lib/copy_to_user.S
arch/arm/lib/memcpy.S

index 66a477a3e3cc6b039c3d48e2ec4d42c57651626a..7a235b9952be04e3ed8acd8892d5ca4d63ee27ff 100644 (file)
@@ -12,6 +12,7 @@
 
 #include <linux/linkage.h>
 #include <asm/assembler.h>
+#include <asm/unwind.h>
 
 /*
  * Prototype:
        stmdb   sp!, {r0, r2, r3, \reg1, \reg2}
        .endm
 
+       .macro usave reg1 reg2
+       UNWIND( .save {r0, r2, r3, \reg1, \reg2}        )
+       .endm
+
        .macro exit reg1 reg2
        add     sp, sp, #8
        ldmfd   sp!, {r0, \reg1, \reg2}
index 3bc8eb811a732cda131927a5c009bf7d34e2b987..652e4d98cd47b7c56fefbbc055451ace6d3e99e1 100644 (file)
  *     data as needed by the implementation including this code. Called
  *     upon code entry.
  *
+ * usave reg1 reg2
+ *
+ *     Unwind annotation macro is corresponding for 'enter' macro.
+ *     It tell unwinder that preserved some provided registers on the stack
+ *     and additional data by a prior 'enter' macro.
+ *
  * exit reg1 reg2
  *
  *     Restore registers with the values previously saved with the
  */
 
 
+       UNWIND( .fnstart                        )
                enter   r4, lr
+       UNWIND( .fnend                          )
+
+       UNWIND( .fnstart                        )
+               usave   r4, lr                    @ in first stmdb block
 
                subs    r2, r2, #4
                blt     8f
 
 1:             subs    r2, r2, #(28)
                stmfd   sp!, {r5 - r8}
+       UNWIND( .fnend                          )
+
+       UNWIND( .fnstart                        )
+               usave   r4, lr
+       UNWIND( .save   {r5 - r8}               ) @ in second stmfd block
                blt     5f
 
        CALGN(  ands    ip, r0, #31             )
        CALGN(  bcs     2b                      )
 
 7:             ldmfd   sp!, {r5 - r8}
+       UNWIND( .fnend                          ) @ end of second stmfd block
 
+       UNWIND( .fnstart                        )
+               usave   r4, lr                    @ still in first stmdb block
 8:             movs    r2, r2, lsl #31
                ldr1b   r1, r3, ne, abort=21f
                ldr1b   r1, r4, cs, abort=21f
                ldr1w   r1, lr, abort=21f
                beq     17f
                bgt     18f
+       UNWIND( .fnend                          )
 
 
                .macro  forward_copy_shift pull push
 
+       UNWIND( .fnstart                        )
+               usave   r4, lr                    @ still in first stmdb block
                subs    r2, r2, #28
                blt     14f
 
        CALGN(  bcc     15f                     )
 
 11:            stmfd   sp!, {r5 - r9}
+       UNWIND( .fnend                          )
 
+       UNWIND( .fnstart                        )
+               usave   r4, lr
+       UNWIND( .save   {r5 - r9}               ) @ in new second stmfd block
        PLD(    pld     [r1, #0]                )
        PLD(    subs    r2, r2, #96             )
        PLD(    pld     [r1, #28]               )
        PLD(    bge     13b                     )
 
                ldmfd   sp!, {r5 - r9}
+       UNWIND( .fnend                          ) @ end of the second stmfd block
 
+       UNWIND( .fnstart                        )
+               usave   r4, lr                    @ still in first stmdb block
 14:            ands    ip, r2, #28
                beq     16f
 
 
 16:            sub     r1, r1, #(\push / 8)
                b       8b
+       UNWIND( .fnend                          )
 
                .endm
 
index d066df686e17877c9e5efbbd57e07615398f6a0a..a9d3db16ecb5738234dc14defe8a4d2f21f60fef 100644 (file)
@@ -12,6 +12,7 @@
 
 #include <linux/linkage.h>
 #include <asm/assembler.h>
+#include <asm/unwind.h>
 
 /*
  * Prototype:
        stmdb   sp!, {r0, r2, r3, \reg1, \reg2}
        .endm
 
+       .macro usave reg1 reg2
+       UNWIND( .save {r0, r2, r3, \reg1, \reg2}        )
+       .endm
+
        .macro exit reg1 reg2
        add     sp, sp, #8
        ldmfd   sp!, {r0, \reg1, \reg2}
index a9b9e2287a096af7ce249d2d0d9f7a6589ebd4eb..7797e81e40e00f72a85ba90dc5abcc1227504b44 100644 (file)
@@ -12,6 +12,7 @@
 
 #include <linux/linkage.h>
 #include <asm/assembler.h>
+#include <asm/unwind.h>
 
 #define LDR1W_SHIFT    0
 #define STR1W_SHIFT    0
        stmdb sp!, {r0, \reg1, \reg2}
        .endm
 
+       .macro usave reg1 reg2
+       UNWIND( .save   {r0, \reg1, \reg2}      )
+       .endm
+
        .macro exit reg1 reg2
        ldmfd sp!, {r0, \reg1, \reg2}
        .endm