public inbox for gdb@sourceware.org
 help / color / mirror / Atom feed
* ARM EABI Linux, breakpoints cause SIGILL and target dies
       [not found] <CADwwazYuWuicgqL=4JyxbdoN+6MmVg354bD6UTzC=Ew-po8JzA@mail.gmail.com>
@ 2012-01-20  2:45 ` Nicholas Sherlock
  2012-01-20 10:45   ` Ulrich Weigand
  0 siblings, 1 reply; 8+ messages in thread
From: Nicholas Sherlock @ 2012-01-20  2:45 UTC (permalink / raw)
  To: gdb

Hey all,

I have Ubuntu's userspace code running inside a chroot on top of
Android's Linux kernel on my phone. Using this, I've built GDB 7.3
from Ubuntu's source package. Here's the system details:

# uname -a
Linux localhost 2.6.35.13 #4 PREEMPT Wed Jan 18 20:25:06 PST 2012
armv7l armv7l armv7l GNU/Linux

# cat /proc/cpuinfo
Processor       : ARMv7 Processor rev 2 (v7l)
BogoMIPS        : 163.57
Features        : swp half thumb fastmult vfp edsp thumbee neon vfpv3
CPU implementer : 0x51
CPU architecture: 7
CPU variant     : 0x1
CPU part        : 0x00f
CPU revision    : 2

Hardware        : runnymede
Revision        : 0002
EngineerID      : 0001
Serial          : 0000000000000000

Here's my source file test.c:

#include <stdio.h>

int main(void) {
  printf("Hello, world!\n");
  printf("Goodbye, world!\n");
  return 0;
}

I'm building it on my target with this GCC:

# gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/arm-linux-gnueabi/gcc/arm-linux-gnueabi/4.5.2/lto-wrapper
Target: arm-linux-gnueabi
Configured with: ../src/configure -v --with-pkgversion='Ubuntu/Linaro
4.5.2-8ubuntu4'
--with-bugurl=file:///usr/share/doc/gcc-4.5/README.Bugs
--enable-languages=c,c++,fortran,objc,obj-c++ --prefix=/usr
--program-suffix=-4.5 --enable-shared --enable-multiarch
--with-multiarch-defaults=arm-linux-gnueabi --enable-linker-build-id
--with-system-zlib --libexecdir=/usr/lib/arm-linux-gnueabi
--without-included-gettext --enable-threads=posix
--with-gxx-include-dir=/usr/include/c++/4.5
--libdir=/usr/lib/arm-linux-gnueabi --enable-nls --with-sysroot=/
--enable-clocale=gnu --enable-libstdcxx-debug
--enable-libstdcxx-time=yes --enable-plugin --enable-gold
--enable-ld=default --with-plugin-ld=ld.gold --enable-objc-gc
--disable-sjlj-exceptions --with-arch=armv7-a --with-float=softfp
--with-fpu=vfpv3-d16 --with-mode=thumb --disable-werror
--enable-checking=release --build=arm-linux-gnueabi
--host=arm-linux-gnueabi --target=arm-linux-gnueabi
Thread model: posix
gcc version 4.5.2 (Ubuntu/Linaro 4.5.2-8ubuntu4)

And this command line:

gcc -g3 -static -o a.out test.c

Running a.out alone or with GDB works fine, but any operation that
causes GDB to set a breakpoint results in the target being killed by
SIGILL:

# gdb a.out
GNU gdb (Ubuntu/Linaro 7.3.1-2011.12-0ubuntu2) 7.3-2011.12
Copyright (C) 2011 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "arm-linux-gnueabi".
For bug reporting instructions, please see:
<http://bugs.launchpad.net/gdb-linaro/>...
Reading symbols from /root/a.out...done.
(gdb) run
Starting program: /root/a.out
Hello, world!
Goodbye, world!
[Inferior 1 (process 14296) exited normally]
(gdb) start
Temporary breakpoint 1 at 0x81f4: file test.c, line 4.
Starting program: /root/a.out

Program received signal SIGILL, Illegal instruction.
0x000081f6 in main () at test.c:4
4         printf("Hello, world!\n");
(gdb) next

Program terminated with signal SIGILL, Illegal instruction.
The program no longer exists.

I noticed that this patch was supposed to add support for SIGILL breakpoints:

http://old.nabble.com/RFC%3A-Updates-support-for-breakpoints-that-generate-SIGILL-p27363713.html

And the target-specific code says that it tries to generate a SIGILL
(arm-linux-tdep.c):

/* However, the EABI syscall interface (new in Nov. 2005) does not look at
   the operand of the swi if old-ABI compatibility is disabled.  Therefore,
   use an undefined instruction instead.  This is supported as of kernel
   version 2.5.70 (May 2003), so should be a safe assumption for EABI
   binaries.  */

So I would expect that this would work. Another piece of the puzzle, I
have a different phone here running a different Linux kernel, but the
same Ubuntu usermode binaries, where GDB breakpoints work perfectly:

$ uname -a
Linux localhost 2.6.37.6-cyanogenmod-01509-g8913be8 #1 PREEMPT Wed Jul
27 21:31:24 EDT 2011 armv7l GNU/Linux

$ cat /proc/cpuinfo

Processor       : ARMv7 Processor rev 2 (v7l)
BogoMIPS: 662.40
Features: swp half thumb fastmult vfp edsp thumbee neon
CPU implementer : 0x51
CPU architecture: 7
CPU variant     : 0x0
CPU part: 0x00f
CPU revision    : 2

Hardware: mahimahi
Revision: 0081
Serial  : 0000000000000000

How do I begin to debug this problem? I have the source code available
for both kernels if there is something to investigate there.

Thanks,
Nicholas Sherlock

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: ARM EABI Linux, breakpoints cause SIGILL and target dies
  2012-01-20  2:45 ` ARM EABI Linux, breakpoints cause SIGILL and target dies Nicholas Sherlock
@ 2012-01-20 10:45   ` Ulrich Weigand
  2012-01-22 23:34     ` Nicholas Sherlock
  0 siblings, 1 reply; 8+ messages in thread
From: Ulrich Weigand @ 2012-01-20 10:45 UTC (permalink / raw)
  To: Nicholas Sherlock; +Cc: gdb

Nicholas Sherlock wrote:

> Running a.out alone or with GDB works fine, but any operation that
> causes GDB to set a breakpoint results in the target being killed by
> SIGILL:
[snip]
> So I would expect that this would work. Another piece of the puzzle, I
> have a different phone here running a different Linux kernel, but the
> same Ubuntu usermode binaries, where GDB breakpoints work perfectly:
[snip]
> How do I begin to debug this problem? I have the source code available
> for both kernels if there is something to investigate there.

So there's two issues here:

- The kernel is supposed to recognize the special undefined instructions
  use to implement breakpoints, and deliver SIGTRAP instead of SIGILL if
  execution hits one of those.  It may be that the older of the two kernels
  does not properly handle this, in particular for Thumb-2 breakpoints
  which were added only recently.

  If you have the kernel sources, you might want to compare the routines
  installed via register_undef_hook in arch/arm/kernel/ptrace.c.

- Even on old kernels that return SIGILL, there is apparently some code
  in GDB that tries to recognize breakpoints anyway.  It may well be
  that this code does not (any longer) work correctly; it is never
  exercised on recent kernels, so a bug might have crept in ...

  Can you do a run with "set debug infrun 1" in the case where you
  get the SIGILL?


Bye,
Ulrich


-- 
  Dr. Ulrich Weigand
  GNU Toolchain for Linux on System z and Cell BE
  Ulrich.Weigand@de.ibm.com

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: ARM EABI Linux, breakpoints cause SIGILL and target dies
  2012-01-20 10:45   ` Ulrich Weigand
@ 2012-01-22 23:34     ` Nicholas Sherlock
  2012-01-23  1:29       ` Nicholas Sherlock
  0 siblings, 1 reply; 8+ messages in thread
From: Nicholas Sherlock @ 2012-01-22 23:34 UTC (permalink / raw)
  To: Ulrich Weigand, gdb

Hi Ulrich, thanks for the reply,

>  If you have the kernel sources, you might want to compare the routines
>  installed via register_undef_hook in arch/arm/kernel/ptrace.c.

So, the new kernel adds a bunch of code to support hardware
breakpoints, but I couldn't see any other changes there:

http://pastebin.com/HqTtdayG

> - Even on old kernels that return SIGILL, there is apparently some code
>  in GDB that tries to recognize breakpoints anyway.  It may well be
>  that this code does not (any longer) work correctly; it is never
>  exercised on recent kernels, so a bug might have crept in ...
>
>  Can you do a run with "set debug infrun 1" in the case where you
>  get the SIGILL?

Yep, here's the result:

Reading symbols from /root/a.out...done.
(gdb) set debug infrun 1
(gdb) start
Temporary breakpoint 1 at 0x81f4: file test.c, line 4.
Starting program: /root/a.out
infrun: proceed (addr=0x8170, signal=0, step=0)
infrun: resume (step=0, signal=0), trap_expected=0
infrun: wait_for_inferior (treat_exec_as_sigtrap=0)
infrun: target_wait (-1, status) =
infrun:   19563 [process 19563],
infrun:   status->kind = stopped, signal = SIGILL
infrun: infwait_normal_state
infrun: TARGET_WAITKIND_STOPPED
infrun: stop_pc = 0x81f6
infrun: random signal 4

Program received signal SIGILL, Illegal instruction.
infrun: stop_stepping
0x000081f6 in main () at test.c:4
4         printf("Hello, world!\n");
(gdb)

Cheers,
Nicholas Sherlock

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: ARM EABI Linux, breakpoints cause SIGILL and target dies
  2012-01-22 23:34     ` Nicholas Sherlock
@ 2012-01-23  1:29       ` Nicholas Sherlock
  2012-01-23 13:29         ` Ulrich Weigand
  0 siblings, 1 reply; 8+ messages in thread
From: Nicholas Sherlock @ 2012-01-23  1:29 UTC (permalink / raw)
  To: Ulrich Weigand, gdb

So, I patched this line in infrun.c which is supposed to check that
the SIGILL was caused by a breakpoint:

      if (breakpoint_inserted_here_p (get_regcache_aspace (regcache),
				      regcache_read_pc (regcache)))

And changed it to:

      if (ecs->ws.value.sig == TARGET_SIGNAL_ILL ||
breakpoint_inserted_here_p (get_regcache_aspace (regcache),
				      regcache_read_pc (regcache)))

Now the signal is corrected reinterpreted as SIGTRAP:

Program received signal SIGTRAP, Trace/breakpoint trap.
0x000081f6 in main () at test.c:4
4         printf("Hello, world!\n");

But the break address is incorrect, it's halfway through the code for
calling printf:

    81f4:       f24b 60a4       movw    r0, #46756      ; 0xb6a4
    81f8:       f2c0 0004       movt    r0, #4
    81fc:       f000 fce8       bl      8bd0 <_IO_puts>

So now I'm trying to fix the code for adjusting the PC after the trap.

Cheers,
Nicholas Sherlock

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: ARM EABI Linux, breakpoints cause SIGILL and target dies
  2012-01-23  1:29       ` Nicholas Sherlock
@ 2012-01-23 13:29         ` Ulrich Weigand
  2012-01-24  2:44           ` Nicholas Sherlock
  0 siblings, 1 reply; 8+ messages in thread
From: Ulrich Weigand @ 2012-01-23 13:29 UTC (permalink / raw)
  To: Nicholas Sherlock; +Cc: gdb

Nicholas Sherlock wrote:

> So, I patched this line in infrun.c which is supposed to check that
> the SIGILL was caused by a breakpoint:
> 
>       if (breakpoint_inserted_here_p (get_regcache_aspace (regcache),
> 				      regcache_read_pc (regcache)))
> 
> And changed it to:
> 
>       if (ecs->ws.value.sig == TARGET_SIGNAL_ILL ||
> breakpoint_inserted_here_p (get_regcache_aspace (regcache),
> 				      regcache_read_pc (regcache)))
> 
> Now the signal is corrected reinterpreted as SIGTRAP:
> 
> Program received signal SIGTRAP, Trace/breakpoint trap.
> 0x000081f6 in main () at test.c:4
> 4         printf("Hello, world!\n");
> 
> But the break address is incorrect, it's halfway through the code for
> calling printf:
> 
>     81f4:       f24b 60a4       movw    r0, #46756      ; 0xb6a4
>     81f8:       f2c0 0004       movt    r0, #4
>     81fc:       f000 fce8       bl      8bd0 <_IO_puts>

This is quite odd; it reports a breakpoint in the middle of a
Thumb-2 instruction.  On ARM, the *kernel* is supposed to adjust the
PC so that it points to the start of the breakpoint instructions.

If this does not work correctly for some reason, this would explain
both why GDB doesn't recognize the situation *and* also why the
kernel doesn't recognize the breakpoint instruction to convert the
signal into a SIGTRAP.

> So now I'm trying to fix the code for adjusting the PC after the trap.

GDB is not supposed to do any adjusting on ARM, this is done by the kernel;
see e.g. arch/arm/traps.c:

asmlinkage void __exception do_undefinstr(struct pt_regs *regs)
{
        unsigned int correction = thumb_mode(regs) ? 2 : 4;
        unsigned int instr;
        siginfo_t info;
        void __user *pc;

        /*
         * According to the ARM ARM, PC is 2 or 4 bytes ahead,
         * depending whether we're in Thumb mode or not.
         * Correct this offset.
         */
        regs->ARM_pc -= correction;


Do you see any differences either here in traps.c, or in one of the
entry-*.S assembler files, between your two kernels?

Bye,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU Toolchain for Linux on System z and Cell BE
  Ulrich.Weigand@de.ibm.com

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: ARM EABI Linux, breakpoints cause SIGILL and target dies
  2012-01-23 13:29         ` Ulrich Weigand
@ 2012-01-24  2:44           ` Nicholas Sherlock
  2012-01-24  3:02             ` Nicholas Sherlock
  0 siblings, 1 reply; 8+ messages in thread
From: Nicholas Sherlock @ 2012-01-24  2:44 UTC (permalink / raw)
  To: Ulrich Weigand; +Cc: gdb

On 24 January 2012 02:29, Ulrich Weigand <uweigand@de.ibm.com> wrote:
> If this does not work correctly for some reason, this would explain
> both why GDB doesn't recognize the situation *and* also why the
> kernel doesn't recognize the breakpoint instruction to convert the
> signal into a SIGTRAP.

Yeah, that sounds likely.

> Do you see any differences either here in traps.c, or in one of the
> entry-*.S assembler files, between your two kernels?

Thanks for the pointer! I found the commit that fixed this bug in the
ARM kernel entry routine:

https://github.com/cyanogen/cm-kernel-exp/commit/d12aee22b3e025a4b76d4078f76542ea8cbd0315#diff-0

I'll port that patch over to my kernel and see if it fixes GDB.

Cheers,
Nicholas Sherlock

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: ARM EABI Linux, breakpoints cause SIGILL and target dies
  2012-01-24  2:44           ` Nicholas Sherlock
@ 2012-01-24  3:02             ` Nicholas Sherlock
  2012-01-24 13:37               ` Ulrich Weigand
  0 siblings, 1 reply; 8+ messages in thread
From: Nicholas Sherlock @ 2012-01-24  3:02 UTC (permalink / raw)
  To: Ulrich Weigand; +Cc: gdb

On 24 January 2012 15:43, Nicholas Sherlock <n.sherlock@gmail.com> wrote:
> Thanks for the pointer! I found the commit that fixed this bug in the
> ARM kernel entry routine:
>
> https://github.com/cyanogen/cm-kernel-exp/commit/d12aee22b3e025a4b76d4078f76542ea8cbd0315#diff-0
>
> I'll port that patch over to my kernel and see if it fixes GDB.

The fix does indeed fix the issue and now GDB works perfectly. Thanks
for the help!

Cheers,
Nicholas Sherlock

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: ARM EABI Linux, breakpoints cause SIGILL and target dies
  2012-01-24  3:02             ` Nicholas Sherlock
@ 2012-01-24 13:37               ` Ulrich Weigand
  0 siblings, 0 replies; 8+ messages in thread
From: Ulrich Weigand @ 2012-01-24 13:37 UTC (permalink / raw)
  To: Nicholas Sherlock; +Cc: gdb

Nicholas Sherlock rwote:
> On 24 January 2012 15:43, Nicholas Sherlock <n.sherlock@gmail.com> wrote:
> > Thanks for the pointer! I found the commit that fixed this bug in the
> > ARM kernel entry routine:
> >
> > https://github.com/cyanogen/cm-kernel-exp/commit/d12aee22b3e025a4b76d4078f76542ea8cbd0315#diff-0
> >
> > I'll port that patch over to my kernel and see if it fixes GDB.
> 
> The fix does indeed fix the issue and now GDB works perfectly. Thanks
> for the help!

Great, thanks for the follow-up!

Bye,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU Toolchain for Linux on System z and Cell BE
  Ulrich.Weigand@de.ibm.com

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2012-01-24 13:37 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
     [not found] <CADwwazYuWuicgqL=4JyxbdoN+6MmVg354bD6UTzC=Ew-po8JzA@mail.gmail.com>
2012-01-20  2:45 ` ARM EABI Linux, breakpoints cause SIGILL and target dies Nicholas Sherlock
2012-01-20 10:45   ` Ulrich Weigand
2012-01-22 23:34     ` Nicholas Sherlock
2012-01-23  1:29       ` Nicholas Sherlock
2012-01-23 13:29         ` Ulrich Weigand
2012-01-24  2:44           ` Nicholas Sherlock
2012-01-24  3:02             ` Nicholas Sherlock
2012-01-24 13:37               ` Ulrich Weigand

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).