Patchwork Problem with GDB when debugging IRQ handlers

login
register
mail settings
Submitter Dmitry Eremin-Solenikov
Date June 28, 2011, 3:45 p.m.
Message ID <BANLkTi=dzYV5tdHaZL91oHjMfuVtXUCD5A@mail.gmail.com>
Download mbox | patch
Permalink /patch/102415/
State New
Headers show

Comments

Dmitry Eremin-Solenikov - June 28, 2011, 3:45 p.m.
On 6/28/11, Catalin Marinas <catalin.marinas@arm.com> wrote:
> On Tue, Jun 28, 2011 at 03:54:11PM +0100, Dmitry Eremin-Solenikov wrote:
>> On 6/28/11, Dmitry Eremin-Solenikov <dbaryshkov@gmail.com> wrote:
>> > On 6/28/11, Catalin Marinas <catalin.marinas@arm.com> wrote:
>> >> Actually since the return address is in S_PC (which maybe gdb assumes
>> >> it
>> >> would be the saved LR), this is probably not be correct. After SVC
>> >> entry, we have he following structure on the stack:
>> >>
>> >> 	ORIG_r0
>> >> 	CPSR
>> >> 		<--- assuming this is the Call Frame Address (SP+S_PC+4)
>> >> 	PC	<--- CFA - 4
>> >> 	LR	<--- don't care
>> >> 	SP	<--- CFA - 12
>> >> 	...
>> >>
>> >>
>> >> So we tell gdb about this with something like below (untested):
>> >>
>> >> 	.cfi_def_cfa_offset S_PC + 4
>> >> 	.cfi_offset 14, -4
>> >> 	.cfi_offset 13, -12
>> >
>> > This brings "unknown CFA rule" gdb exception, but it seems I got your
>> > idea.
>>
>> No, this seems to work, it was my fault. I got more or less reasonable
>> backtrace now.
>
> Does gdb manage to get into the parent stack frame?
>
> BTW, are you compiling with FRAME_POINTER enabled? In this case you
> would need to set some offset for the FP register (11). If you don't
> mind missing the first part in the parent context, maybe something like
> below:
>
> 	.cfi_def_cfa_offset S_PC
> 	.cfi_offset 14, -4
> 	.cfi_offset 13, -8
> 	.cfi_offset 11, -16

No, this seems wrong. Previous version was better. Here is a part of gdb log
generated using the attached patch:

Breakpoint 2, pxamci_start_cmd (host=0xc3bfd680, cmd=0xc3e7bed8,
cmdat=2112) at /run/shm/zigbee-kernel/drivers/mmc/host/pxamci.c:256
256		WARN_ON(host->cmd != NULL);
#0  pxamci_start_cmd (host=0xc3bfd680, cmd=0xc3e7bed8, cmdat=2112) at
/run/shm/zigbee-kernel/drivers/mmc/host/pxamci.c:256
#1  0xc0248870 in mmc_start_request (host=0xc3bfd400, mrq=0xc3e7beb0)
at /run/shm/zigbee-kernel/drivers/mmc/core/core.c:196
#2  0xc02488bc in mmc_wait_for_req (host=0xc3bfd400, mrq=0xc3e7beb0)
at /run/shm/zigbee-kernel/drivers/mmc/core/core.c:220
#3  0xc0248930 in mmc_wait_for_cmd (host=0xc3bfd400, cmd=0xc3e7bed8,
retries=0) at /run/shm/zigbee-kernel/drivers/mmc/core/core.c:249
#4  0xc024ef48 in mmc_io_rw_direct_host (host=0xc3bfd400, write=<value
optimized out>, fn=<value optimized out>, addr=<value optimized out>,
in=<value optimized out>, out=0xc3e7bf3f  <incomplete sequence \330>)
at /run/shm/zigbee-kernel/drivers/mmc/core/sdio_ops.c:89
#5  0xc024efd4 in sdio_reset (host=0xc3bfd400) at
/run/shm/zigbee-kernel/drivers/mmc/core/sdio_ops.c:191
#6  0xc0249974 in mmc_rescan_try_freq (host=0xc3bfd400, freq=<value
optimized out>) at /run/shm/zigbee-kernel/drivers/mmc/core/core.c:1548
#7  0xc0249b60 in mmc_rescan (work=0xc3bfd618) at
/run/shm/zigbee-kernel/drivers/mmc/core/core.c:1609
#8  0xc00638b0 in process_one_work (worker=0xc3e63580,
work=0xc3bfd618) at /run/shm/zigbee-kernel/kernel/workqueue.c:1868
#9  0xc0063e2c in worker_thread (__worker=<value optimized out>) at
/run/shm/zigbee-kernel/kernel/workqueue.c:1979
#10 0xc00675dc in kthread (_create=0xc3e41ef0) at
/run/shm/zigbee-kernel/kernel/kthread.c:96
#11 0xc0033810 in kernel_thread_helper ()
#12 0xc0033810 in kernel_thread_helper ()
Backtrace stopped: previous frame identical to this frame (corrupt stack?)

Breakpoint 1, pxamci_irq (irq=39, devid=0xc3bfd680) at
/run/shm/zigbee-kernel/drivers/mmc/host/pxamci.c:397
397		testtt();
#0  pxamci_irq (irq=39, devid=0xc3bfd680) at
/run/shm/zigbee-kernel/drivers/mmc/host/pxamci.c:397
#1  0xc0084fa4 in handle_irq_event_percpu (desc=0xc3e05ea0,
action=0xc399f1c0) at /run/shm/zigbee-kernel/kernel/irq/handle.c:126
#2  0xc0085128 in handle_irq_event (desc=0xc3e05ea0) at
/run/shm/zigbee-kernel/kernel/irq/handle.c:182
#3  0xc00871d0 in handle_level_irq (irq=<value optimized out>,
desc=0xc3e05ea0) at /run/shm/zigbee-kernel/kernel/irq/chip.c:345
#4  0xc0084f64 in generic_handle_irq_desc (irq=39) at
/run/shm/zigbee-kernel/include/linux/irqdesc.h:111
#5  generic_handle_irq (irq=39) at
/run/shm/zigbee-kernel/kernel/irq/irqdesc.c:304
#6  0xc0032060 in asm_do_IRQ (irq=39, regs=<value optimized out>) at
/run/shm/zigbee-kernel/arch/arm/kernel/irq.c:90
#7  0xc0032b50 in __irq_svc () at
/run/shm/zigbee-kernel/arch/arm/kernel/entry-armv.S:222
#8  0xc0253bc4 in arch_local_irq_restore (host=0xc3bfd680,
cmd=0xc3e7bed8, cmdat=2113) at
/run/shm/zigbee-kernel/arch/arm/include/asm/irqflags.h:142
#9  spin_unlock_irqrestore (host=0xc3bfd680, cmd=0xc3e7bed8,
cmdat=2113) at /run/shm/zigbee-kernel/include/linux/spinlock.h:340
#10 pxamci_enable_irq (host=0xc3bfd680, cmd=0xc3e7bed8, cmdat=2113) at
/run/shm/zigbee-kernel/drivers/mmc/host/pxamci.c:160
#11 pxamci_start_cmd (host=0xc3bfd680, cmd=0xc3e7bed8, cmdat=2113) at
/run/shm/zigbee-kernel/drivers/mmc/host/pxamci.c:285
#12 0xc0248870 in mmc_start_request (host=0xc3bfd400, mrq=0xc3e7beb0)
at /run/shm/zigbee-kernel/drivers/mmc/core/core.c:196
#13 0xc02488bc in mmc_wait_for_req (host=0xc3bfd400, mrq=0xc3e7beb0)
at /run/shm/zigbee-kernel/drivers/mmc/core/core.c:220
#14 0xc0248930 in mmc_wait_for_cmd (host=0xc3bfd400, cmd=0xc3e7bed8,
retries=0) at /run/shm/zigbee-kernel/drivers/mmc/core/core.c:249
#15 0xc024ef48 in mmc_io_rw_direct_host (host=0xc3bfd400, write=<value
optimized out>, fn=<value optimized out>, addr=<value optimized out>,
in=<value optimized out>, out=0xc3e7bf3f  <incomplete sequence \330>)
at /run/shm/zigbee-kernel/drivers/mmc/core/sdio_ops.c:89
#16 0xc024efd4 in sdio_reset (host=0xc3bfd400) at
/run/shm/zigbee-kernel/drivers/mmc/core/sdio_ops.c:191
#17 0xc0249974 in mmc_rescan_try_freq (host=0xc3bfd400, freq=<value
optimized out>) at /run/shm/zigbee-kernel/drivers/mmc/core/core.c:1548
#18 0xc0249b60 in mmc_rescan (work=0xc3bfd618) at
/run/shm/zigbee-kernel/drivers/mmc/core/core.c:1609
#19 0xc00638b0 in process_one_work (worker=0xc3e63580,
work=0xc3bfd618) at /run/shm/zigbee-kernel/kernel/workqueue.c:1868
#20 0xc0063e2c in worker_thread (__worker=<value optimized out>) at
/run/shm/zigbee-kernel/kernel/workqueue.c:1979
#21 0xc00675dc in kthread (_create=0xc3e41ef0) at
/run/shm/zigbee-kernel/kernel/kthread.c:96
#22 0xc0033810 in kernel_thread_helper ()
#23 0xc0033810 in kernel_thread_helper ()
Backtrace stopped: previous frame identical to this frame (corrupt stack?)

Colleagues, does this look suitable for you?
Catalin Marinas - June 28, 2011, 4:11 p.m.
On Tue, Jun 28, 2011 at 04:45:52PM +0100, Dmitry Eremin-Solenikov wrote:
> Here is a part of gdb log generated using the attached patch:
[...]
> #11 0xc0033810 in kernel_thread_helper ()
> #12 0xc0033810 in kernel_thread_helper ()
> Backtrace stopped: previous frame identical to this frame (corrupt stack?)

Maybe you can add something similar to the kernel_thread_helper in
arch/arm/kernel/process.c? I'm not sure whether there is something like
.cantunwind (as for the kernel unwinding information).

> diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
> index e8d8856..44daf40 100644
> --- a/arch/arm/kernel/entry-armv.S
> +++ b/arch/arm/kernel/entry-armv.S
> @@ -28,6 +28,7 @@
>  #include "entry-header.S"
>  #include <asm/entry-macro-multi.S>
>  
> +	.cfi_sections	.debug_frame
>  /*
>   * Interrupt handling.  Preserves r7, r8, r9
>   */
> @@ -113,6 +114,7 @@ ENDPROC(__und_invalid)
>  
>  	.macro	svc_entry, stack_hole=0
>   UNWIND(.fnstart		)
> +	.cfi_startproc
>   UNWIND(.save {r0 - pc}		)
>  	sub	sp, sp, #(S_FRAME_SIZE + \stack_hole - 4)
>  #ifdef CONFIG_THUMB2_KERNEL
> @@ -146,6 +148,24 @@ ENDPROC(__und_invalid)
>  	@  r4 - orig_r0 (see pt_regs definition in ptrace.h)
>  	@
>  	stmia	r5, {r0 - r4}
> +	.cfi_def_cfa_offset S_PC + 4
> +	.cfi_offset 14, -4
> +#define	CFI_REG_OFF(r) .cfi_offset r, (r - 16) * 4
> +	CFI_REG_OFF(13)
> +	CFI_REG_OFF(12)
> +	CFI_REG_OFF(11)
> +	CFI_REG_OFF(10)
> +	CFI_REG_OFF(9)
> +	CFI_REG_OFF(8)
> +	CFI_REG_OFF(7)
> +	CFI_REG_OFF(6)
> +	CFI_REG_OFF(5)
> +	CFI_REG_OFF(4)
> +	CFI_REG_OFF(3)
> +	CFI_REG_OFF(2)
> +	CFI_REG_OFF(1)
> +	CFI_REG_OFF(0)
> +#undef CFI_REG_OFF
>  	.endm

Do we need all the registers in here for gdb stack unwinding? In general
we would only need LR, SP and FP.
Dmitry Eremin-Solenikov - June 28, 2011, 10:26 p.m.
On 6/28/11, Catalin Marinas <catalin.marinas@arm.com> wrote:
> On Tue, Jun 28, 2011 at 04:45:52PM +0100, Dmitry Eremin-Solenikov wrote:
>> Here is a part of gdb log generated using the attached patch:
> [...]
>> #11 0xc0033810 in kernel_thread_helper ()
>> #12 0xc0033810 in kernel_thread_helper ()
>> Backtrace stopped: previous frame identical to this frame (corrupt stack?)
>
> Maybe you can add something similar to the kernel_thread_helper in
> arch/arm/kernel/process.c? I'm not sure whether there is something like
> .cantunwind (as for the kernel unwinding information).
>
>> diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
>> index e8d8856..44daf40 100644
>> --- a/arch/arm/kernel/entry-armv.S
>> +++ b/arch/arm/kernel/entry-armv.S
>> @@ -28,6 +28,7 @@
>>  #include "entry-header.S"
>>  #include <asm/entry-macro-multi.S>
>>
>> +	.cfi_sections	.debug_frame
>>  /*
>>   * Interrupt handling.  Preserves r7, r8, r9
>>   */
>> @@ -113,6 +114,7 @@ ENDPROC(__und_invalid)
>>
>>  	.macro	svc_entry, stack_hole=0
>>   UNWIND(.fnstart		)
>> +	.cfi_startproc
>>   UNWIND(.save {r0 - pc}		)
>>  	sub	sp, sp, #(S_FRAME_SIZE + \stack_hole - 4)
>>  #ifdef CONFIG_THUMB2_KERNEL
>> @@ -146,6 +148,24 @@ ENDPROC(__und_invalid)
>>  	@  r4 - orig_r0 (see pt_regs definition in ptrace.h)
>>  	@
>>  	stmia	r5, {r0 - r4}
>> +	.cfi_def_cfa_offset S_PC + 4
>> +	.cfi_offset 14, -4
>> +#define	CFI_REG_OFF(r) .cfi_offset r, (r - 16) * 4
>> +	CFI_REG_OFF(13)
>> +	CFI_REG_OFF(12)
>> +	CFI_REG_OFF(11)
>> +	CFI_REG_OFF(10)
>> +	CFI_REG_OFF(9)
>> +	CFI_REG_OFF(8)
>> +	CFI_REG_OFF(7)
>> +	CFI_REG_OFF(6)
>> +	CFI_REG_OFF(5)
>> +	CFI_REG_OFF(4)
>> +	CFI_REG_OFF(3)
>> +	CFI_REG_OFF(2)
>> +	CFI_REG_OFF(1)
>> +	CFI_REG_OFF(0)
>> +#undef CFI_REG_OFF
>>  	.endm
>
> Do we need all the registers in here for gdb stack unwinding? In general
> we would only need LR, SP and FP.

CFI info isn't only related to stack unwinding. IIUC (I'll have to run
more experiments)
these instrutions will help me to get correct variables/arguments
values in the before-exception stack frames.

>
> --
> Catalin
>
>
Catalin Marinas - June 29, 2011, 9:09 a.m.
On Tue, Jun 28, 2011 at 11:26:28PM +0100, Dmitry Eremin-Solenikov wrote:
> On 6/28/11, Catalin Marinas <catalin.marinas@arm.com> wrote:
> > On Tue, Jun 28, 2011 at 04:45:52PM +0100, Dmitry Eremin-Solenikov wrote:
> >>  	.macro	svc_entry, stack_hole=0
> >>   UNWIND(.fnstart		)
> >> +	.cfi_startproc
> >>   UNWIND(.save {r0 - pc}		)
> >>  	sub	sp, sp, #(S_FRAME_SIZE + \stack_hole - 4)
> >>  #ifdef CONFIG_THUMB2_KERNEL
> >> @@ -146,6 +148,24 @@ ENDPROC(__und_invalid)
> >>  	@  r4 - orig_r0 (see pt_regs definition in ptrace.h)
> >>  	@
> >>  	stmia	r5, {r0 - r4}
> >> +	.cfi_def_cfa_offset S_PC + 4
> >> +	.cfi_offset 14, -4
> >> +#define	CFI_REG_OFF(r) .cfi_offset r, (r - 16) * 4
> >> +	CFI_REG_OFF(13)
> >> +	CFI_REG_OFF(12)
> >> +	CFI_REG_OFF(11)
> >> +	CFI_REG_OFF(10)
> >> +	CFI_REG_OFF(9)
> >> +	CFI_REG_OFF(8)
> >> +	CFI_REG_OFF(7)
> >> +	CFI_REG_OFF(6)
> >> +	CFI_REG_OFF(5)
> >> +	CFI_REG_OFF(4)
> >> +	CFI_REG_OFF(3)
> >> +	CFI_REG_OFF(2)
> >> +	CFI_REG_OFF(1)
> >> +	CFI_REG_OFF(0)
> >> +#undef CFI_REG_OFF
> >>  	.endm
> >
> > Do we need all the registers in here for gdb stack unwinding? In general
> > we would only need LR, SP and FP.
> 
> CFI info isn't only related to stack unwinding. IIUC (I'll have to run
> more experiments) these instrutions will help me to get correct
> variables/arguments values in the before-exception stack frames.

OK, in this case we may need to add some annotations. You could actually
generate a .s file from and existing C one (including -g) and see what
.cfi directives it generates.
Dmitry Eremin-Solenikov - June 29, 2011, 11:20 a.m.
On 6/29/11, Catalin Marinas <catalin.marinas@arm.com> wrote:
> On Tue, Jun 28, 2011 at 11:26:28PM +0100, Dmitry Eremin-Solenikov wrote:
>> On 6/28/11, Catalin Marinas <catalin.marinas@arm.com> wrote:
>> > On Tue, Jun 28, 2011 at 04:45:52PM +0100, Dmitry Eremin-Solenikov wrote:
>> >>  	.macro	svc_entry, stack_hole=0
>> >>   UNWIND(.fnstart		)
>> >> +	.cfi_startproc
>> >>   UNWIND(.save {r0 - pc}		)
>> >>  	sub	sp, sp, #(S_FRAME_SIZE + \stack_hole - 4)
>> >>  #ifdef CONFIG_THUMB2_KERNEL
>> >> @@ -146,6 +148,24 @@ ENDPROC(__und_invalid)
>> >>  	@  r4 - orig_r0 (see pt_regs definition in ptrace.h)
>> >>  	@
>> >>  	stmia	r5, {r0 - r4}
>> >> +	.cfi_def_cfa_offset S_PC + 4
>> >> +	.cfi_offset 14, -4
>> >> +#define	CFI_REG_OFF(r) .cfi_offset r, (r - 16) * 4
>> >> +	CFI_REG_OFF(13)
>> >> +	CFI_REG_OFF(12)
>> >> +	CFI_REG_OFF(11)
>> >> +	CFI_REG_OFF(10)
>> >> +	CFI_REG_OFF(9)
>> >> +	CFI_REG_OFF(8)
>> >> +	CFI_REG_OFF(7)
>> >> +	CFI_REG_OFF(6)
>> >> +	CFI_REG_OFF(5)
>> >> +	CFI_REG_OFF(4)
>> >> +	CFI_REG_OFF(3)
>> >> +	CFI_REG_OFF(2)
>> >> +	CFI_REG_OFF(1)
>> >> +	CFI_REG_OFF(0)
>> >> +#undef CFI_REG_OFF
>> >>  	.endm
>> >
>> > Do we need all the registers in here for gdb stack unwinding? In general
>> > we would only need LR, SP and FP.
>>
>> CFI info isn't only related to stack unwinding. IIUC (I'll have to run
>> more experiments) these instrutions will help me to get correct
>> variables/arguments values in the before-exception stack frames.
>
> OK, in this case we may need to add some annotations. You could actually
> generate a .s file from and existing C one (including -g) and see what
> .cfi directives it generates.

Yes, that actually gave me some ideas. Unfortunately entry*.S files are
a bit ... uncommon, so there are nearly no 1-1 cases. BTW: It seems x86
has .cfi annotations connected to most if not all assembler commands.
I think this is a bit too much, but you got the idea.

Patch

diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index e8d8856..44daf40 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -28,6 +28,7 @@ 
 #include "entry-header.S"
 #include <asm/entry-macro-multi.S>
 
+	.cfi_sections	.debug_frame
 /*
  * Interrupt handling.  Preserves r7, r8, r9
  */
@@ -113,6 +114,7 @@  ENDPROC(__und_invalid)
 
 	.macro	svc_entry, stack_hole=0
  UNWIND(.fnstart		)
+	.cfi_startproc
  UNWIND(.save {r0 - pc}		)
 	sub	sp, sp, #(S_FRAME_SIZE + \stack_hole - 4)
 #ifdef CONFIG_THUMB2_KERNEL
@@ -146,6 +148,24 @@  ENDPROC(__und_invalid)
 	@  r4 - orig_r0 (see pt_regs definition in ptrace.h)
 	@
 	stmia	r5, {r0 - r4}
+	.cfi_def_cfa_offset S_PC + 4
+	.cfi_offset 14, -4
+#define	CFI_REG_OFF(r) .cfi_offset r, (r - 16) * 4
+	CFI_REG_OFF(13)
+	CFI_REG_OFF(12)
+	CFI_REG_OFF(11)
+	CFI_REG_OFF(10)
+	CFI_REG_OFF(9)
+	CFI_REG_OFF(8)
+	CFI_REG_OFF(7)
+	CFI_REG_OFF(6)
+	CFI_REG_OFF(5)
+	CFI_REG_OFF(4)
+	CFI_REG_OFF(3)
+	CFI_REG_OFF(2)
+	CFI_REG_OFF(1)
+	CFI_REG_OFF(0)
+#undef CFI_REG_OFF
 	.endm
 
 	.align	5
@@ -347,6 +367,7 @@  ENDPROC(__pabt_svc)
 	.macro	usr_entry
  UNWIND(.fnstart	)
  UNWIND(.cantunwind	)	@ don't unwind the user space
+	.cfi_startproc
 	sub	sp, sp, #S_FRAME_SIZE
  ARM(	stmib	sp, {r1 - r12}	)
  THUMB(	stmia	sp, {r0 - r12}	)
@@ -427,6 +448,7 @@  __dabt_usr:
 	mov	r2, sp
 	adr	lr, BSYM(ret_from_exception)
 	b	do_DataAbort
+	.cfi_endproc
  UNWIND(.fnend		)
 ENDPROC(__dabt_usr)
 
@@ -454,6 +476,7 @@  __irq_usr:
 
 	mov	why, #0
 	b	ret_to_user
+	.cfi_endproc
  UNWIND(.fnend		)
 ENDPROC(__irq_usr)
 
@@ -496,6 +519,7 @@  __und_usr:
 #else
 	b	__und_usr_unknown
 #endif
+	.cfi_endproc
  UNWIND(.fnend		)
 ENDPROC(__und_usr)
 
@@ -691,6 +715,7 @@  __pabt_usr:
 	enable_irq				@ Enable interrupts
 	mov	r2, sp				@ regs
 	bl	do_PrefetchAbort		@ call abort handler
+	.cfi_endproc
  UNWIND(.fnend		)
 	/* fall through */
 /*
@@ -699,9 +724,11 @@  __pabt_usr:
 ENTRY(ret_from_exception)
  UNWIND(.fnstart	)
  UNWIND(.cantunwind	)
+	.cfi_startproc
 	get_thread_info tsk
 	mov	why, #0
 	b	ret_to_user
+	.cfi_endproc
  UNWIND(.fnend		)
 ENDPROC(__pabt_usr)
 ENDPROC(ret_from_exception)
diff --git a/arch/arm/kernel/entry-header.S b/arch/arm/kernel/entry-header.S
index 051166c..5ed13ae 100644
--- a/arch/arm/kernel/entry-header.S
+++ b/arch/arm/kernel/entry-header.S
@@ -86,6 +86,7 @@ 
 #else
 	ldmia	sp, {r0 - pc}^			@ load r0 - pc, cpsr
 #endif
+	.cfi_endproc
 	.endm
 
 	.macro	restore_user_regs, fast = 0, offset = 0