Просмотр исходного кода

ARM: 8225/1: Add unwinding support for memory copy functions

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>
Lin Yongting 10 лет назад
Родитель
Сommit
279f487e0b
4 измененных файлов с 45 добавлено и 0 удалено
  1. 5 0
      arch/arm/lib/copy_from_user.S
  2. 30 0
      arch/arm/lib/copy_template.S
  3. 5 0
      arch/arm/lib/copy_to_user.S
  4. 5 0
      arch/arm/lib/memcpy.S

+ 5 - 0
arch/arm/lib/copy_from_user.S

@@ -12,6 +12,7 @@
 
 
 #include <linux/linkage.h>
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 #include <asm/assembler.h>
+#include <asm/unwind.h>
 
 
 /*
 /*
  * Prototype:
  * Prototype:
@@ -77,6 +78,10 @@
 	stmdb	sp!, {r0, r2, r3, \reg1, \reg2}
 	stmdb	sp!, {r0, r2, r3, \reg1, \reg2}
 	.endm
 	.endm
 
 
+	.macro usave reg1 reg2
+	UNWIND(	.save {r0, r2, r3, \reg1, \reg2}	)
+	.endm
+
 	.macro exit reg1 reg2
 	.macro exit reg1 reg2
 	add	sp, sp, #8
 	add	sp, sp, #8
 	ldmfd	sp!, {r0, \reg1, \reg2}
 	ldmfd	sp!, {r0, \reg1, \reg2}

+ 30 - 0
arch/arm/lib/copy_template.S

@@ -53,6 +53,12 @@
  *	data as needed by the implementation including this code. Called
  *	data as needed by the implementation including this code. Called
  *	upon code entry.
  *	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
  * exit reg1 reg2
  *
  *
  *	Restore registers with the values previously saved with the
  *	Restore registers with the values previously saved with the
@@ -67,7 +73,12 @@
  */
  */
 
 
 
 
+	UNWIND(	.fnstart			)
 		enter	r4, lr
 		enter	r4, lr
+	UNWIND(	.fnend				)
+
+	UNWIND(	.fnstart			)
+		usave	r4, lr			  @ in first stmdb block
 
 
 		subs	r2, r2, #4
 		subs	r2, r2, #4
 		blt	8f
 		blt	8f
@@ -79,6 +90,11 @@
 
 
 1:		subs	r2, r2, #(28)
 1:		subs	r2, r2, #(28)
 		stmfd	sp!, {r5 - r8}
 		stmfd	sp!, {r5 - r8}
+	UNWIND(	.fnend				)
+
+	UNWIND(	.fnstart			)
+		usave	r4, lr
+	UNWIND(	.save	{r5 - r8}		) @ in second stmfd block
 		blt	5f
 		blt	5f
 
 
 	CALGN(	ands	ip, r0, #31		)
 	CALGN(	ands	ip, r0, #31		)
@@ -144,7 +160,10 @@
 	CALGN(	bcs	2b			)
 	CALGN(	bcs	2b			)
 
 
 7:		ldmfd	sp!, {r5 - r8}
 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
 8:		movs	r2, r2, lsl #31
 		ldr1b	r1, r3, ne, abort=21f
 		ldr1b	r1, r3, ne, abort=21f
 		ldr1b	r1, r4, cs, abort=21f
 		ldr1b	r1, r4, cs, abort=21f
@@ -173,10 +192,13 @@
 		ldr1w	r1, lr, abort=21f
 		ldr1w	r1, lr, abort=21f
 		beq	17f
 		beq	17f
 		bgt	18f
 		bgt	18f
+	UNWIND(	.fnend				)
 
 
 
 
 		.macro	forward_copy_shift pull push
 		.macro	forward_copy_shift pull push
 
 
+	UNWIND(	.fnstart			)
+		usave	r4, lr			  @ still in first stmdb block
 		subs	r2, r2, #28
 		subs	r2, r2, #28
 		blt	14f
 		blt	14f
 
 
@@ -187,7 +209,11 @@
 	CALGN(	bcc	15f			)
 	CALGN(	bcc	15f			)
 
 
 11:		stmfd	sp!, {r5 - r9}
 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(	pld	[r1, #0]		)
 	PLD(	subs	r2, r2, #96		)
 	PLD(	subs	r2, r2, #96		)
 	PLD(	pld	[r1, #28]		)
 	PLD(	pld	[r1, #28]		)
@@ -221,7 +247,10 @@
 	PLD(	bge	13b			)
 	PLD(	bge	13b			)
 
 
 		ldmfd	sp!, {r5 - r9}
 		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
 14:		ands	ip, r2, #28
 		beq	16f
 		beq	16f
 
 
@@ -236,6 +265,7 @@
 
 
 16:		sub	r1, r1, #(\push / 8)
 16:		sub	r1, r1, #(\push / 8)
 		b	8b
 		b	8b
+	UNWIND(	.fnend				)
 
 
 		.endm
 		.endm
 
 

+ 5 - 0
arch/arm/lib/copy_to_user.S

@@ -12,6 +12,7 @@
 
 
 #include <linux/linkage.h>
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 #include <asm/assembler.h>
+#include <asm/unwind.h>
 
 
 /*
 /*
  * Prototype:
  * Prototype:
@@ -80,6 +81,10 @@
 	stmdb	sp!, {r0, r2, r3, \reg1, \reg2}
 	stmdb	sp!, {r0, r2, r3, \reg1, \reg2}
 	.endm
 	.endm
 
 
+	.macro usave reg1 reg2
+	UNWIND(	.save {r0, r2, r3, \reg1, \reg2}	)
+	.endm
+
 	.macro exit reg1 reg2
 	.macro exit reg1 reg2
 	add	sp, sp, #8
 	add	sp, sp, #8
 	ldmfd	sp!, {r0, \reg1, \reg2}
 	ldmfd	sp!, {r0, \reg1, \reg2}

+ 5 - 0
arch/arm/lib/memcpy.S

@@ -12,6 +12,7 @@
 
 
 #include <linux/linkage.h>
 #include <linux/linkage.h>
 #include <asm/assembler.h>
 #include <asm/assembler.h>
+#include <asm/unwind.h>
 
 
 #define LDR1W_SHIFT	0
 #define LDR1W_SHIFT	0
 #define STR1W_SHIFT	0
 #define STR1W_SHIFT	0
@@ -48,6 +49,10 @@
 	stmdb sp!, {r0, \reg1, \reg2}
 	stmdb sp!, {r0, \reg1, \reg2}
 	.endm
 	.endm
 
 
+	.macro usave reg1 reg2
+	UNWIND(	.save	{r0, \reg1, \reg2}	)
+	.endm
+
 	.macro exit reg1 reg2
 	.macro exit reg1 reg2
 	ldmfd sp!, {r0, \reg1, \reg2}
 	ldmfd sp!, {r0, \reg1, \reg2}
 	.endm
 	.endm