Port-arm archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: gdb on ODROID-C1



The patch worked. Thanks.

Regards,
--Gopi




On Friday, 19 May 2017, 16:25, Nick Hudson <skrll%netbsd.org@localhost> wrote:


On 05/19/17 10:08, Gopikrishnan S wrote:
> Hello,
> I have NetBSD 7.1 running on an Odroid-C1.
> diablo:~$ uname -a
> NetBSD diablo 7.1 NetBSD 7.1 (ODROID-C1.201703111743Z) evbarm
>
> I am trying to debug a simple "Hello, world!" program using gdb:
>
> Reading symbols from ./hello_world...done.
> (gdb) b main
> Breakpoint 1 at 0x107a4: file test.c, line 6.
> (gdb) r
> Starting program: /home//C/hello_world
>
> Program received signal SIGILL, Illegal instruction.
> 0x400257a8 in _rtld () from /usr/libexec/ld.elf_so
> (gdb) n
> Single stepping until exit from function _rtld,
> which has no line number information.
>
> Program terminated with signal SIGILL, Illegal instruction.
> The program no longer exists.
>
> The program hits an illegal instruction before it enters main, in the loader itself. This happens about 9 times out of 10 when debugging this program. In the 10th instance, the program hits the breakpoint at main(). But further debugging is impossible:
> (gdb) r
> Starting program: /home//C/hello_world
>
> Breakpoint 1, main () at test.c:6
> 6              printf("Hello, world!\n");
> (gdb) n
> Hello, world!
> [Inferior 1 (process 1428) exited normally]
>
> As you can see, I tried to step the program with "n", but it did not stop at the next line. The program continued without stopping and ran to completion.
>
> On x86, gdb is usable and the same program can be debugged without any issues.
>
> I did some debugging on gdb and with some modification to gdb it can be made usable (note: this is not a patch for gdb. This change is to work around what
> seems to be a kernel bug).
>
> diff --git a/external/gpl3/gdb/dist/gdb/mem-break.c b/external/gpl3/gdb/dist/gdb/mem-break.c
> index c206687..5a920fe 100644
> --- a/external/gpl3/gdb/dist/gdb/mem-break.c
> +++ b/external/gpl3/gdb/dist/gdb/mem-break.c
> @@ -26,6 +26,7 @@
>  #include "target.h"
>  #include <string.h>

>  /* Insert a breakpoint on targets that don't have any better
>      breakpoint support.  We read the contents of the target location
> @@ -61,6 +62,9 @@ default_memory_insert_breakpoint (struct gdbarch *gdbarch,
>        memcpy (bp_tgt->shadow_contents, readbuf, bp_tgt->placed_size);
>        val = target_write_raw_memory (bp_tgt->placed_address, bp,
>                                      bp_tgt->placed_size);
> +      target_read_memory (bp_tgt->placed_address, readbuf, bp_tgt->placed_size);
>      }

>    return val;
> @@ -71,8 +75,19 @@ int
>  default_memory_remove_breakpoint (struct gdbarch *gdbarch,
>                                    struct bp_target_info *bp_tgt)
>  {
> -  return target_write_raw_memory (bp_tgt->placed_address, bp_tgt->shadow_contents,
> +  int ret = 0;
> +  gdb_byte *readbuf = NULL;
> +
> +  readbuf = alloca (bp_tgt->placed_size);
> +  ret = target_write_raw_memory (bp_tgt->placed_address, bp_tgt->shadow_contents,
>                                    bp_tgt->placed_size);
> +  target_read_memory (bp_tgt->placed_address, readbuf, bp_tgt->placed_size);
> +  return ret;
> }
>
> Basically, I am reading back the value gdb writes to the inferior's memory whenever gdb inserts or removes a breakpoint. target_read_memory() and
> target_write_memory() ultimately devolve into calls to ptrace(PT_IO,...). With this change, my debugging session goes fine:
>
> Reading symbols from hello_world...done.
> (gdb) b main
> Breakpoint 1 at 0x107a4: file test.c, line 6.
> (gdb) r
> Starting program: /home//C/hello_world
>
> Breakpoint 1, main () at test.c:6
> 6              printf("Hello, world!\n");
> (gdb) n
> Hello, world!
> 7              return EXIT_SUCCESS;
> (gdb)
> 8      }
> (gdb)
> 0x00010708 in ___start ()
> (gdb)
> Single stepping until exit from function ___start,
> which has no line number information.
> [Inferior 1 (process 802) exited normally]
> (gdb)
>
> To restate: Every time gdb writes to the inferior's memory with ptrace(), the  value written has to be read back before it is executed. Otherwise, there is no
> guarantee that the instructions that gdb writes are actually executed.
>
> The only thing the ARM port does differently in this work-flow when compared to  x86 is the following bit of code in sys/kern/sys_process.c:process_domem(),
> which is called from sys_ptrace():
>
> #ifdef PMAP_NEED_PROCWR
>      if (error == 0 && uio->uio_rw == UIO_WRITE)
>          pmap_procwr(p, addr, len);
> #endif
>
> pmap_procwr() calls armv7_icache_sync_range(). As per pmap(9), this function is used to flush the i-cache after code modifictation.
>
> My hypothesis is that pmap_procwr()/armv7_icache_sync_range() is not working as expected on the Odroid-C1.
>
> How do I confirm this hypothesis and debug this issue further?
> Thanks and regards,--Gopi
>
>

Please try the attached patch


Thanks,

Nick







Home | Main Index | Thread Index | Old Index