gdb 系列(2) (build&debug gdb)

来源:互联网 发布:《java开发实战经典》 编辑:程序博客网 时间:2024/06/06 18:39

为什么要debug

上文我们提到的,1.很多时候你对一些ptrace系统调用为什么错误很感兴趣,这里面首要的问题就是在错误的时候错误码是什么?当然你可以在kernel里面打印,不过不经济,如果你不是深入调查这个错误的原因2.如果我自己实现一个类似gdb的东西那么我应该怎么传递ptrace参数,比如attach一个pid3.我想查看一些gdb工作原理,比如breakpoint是怎么工作的这些都需要在源代码里面进行修改android 一般的gdb 的工作模式是这样的 gdb + gdbserver这里一些实际的实现主要是在gdbserver里面,所以我们需要crossbuild它

build

网上搜索的crossbuild方法大多是起源于这里
How-to_Rebuild_gdbserver”>http://www.omappedia.org/wiki/Android-_How-to_Rebuild_gdbserver
这里讲的都是32bit gdbserver build方法,我尝试build 64bit gdbserver总是不过,然后使用了如下方式

git clone https://android.googlesource.com/toolchain/gdb~/Android/android-ndk-r13/build/tools/make-standalone-toolchain.sh \--arch=arm64 --platform=android-24 \--install-dir=/home/mi/Android/android-ndk-r13/standalone-toolchaincd gdb/gdb-7.11/gdb/gdbserver/export PATH=/home/mi/Android/android-ndk-r13/standalone-toolchain/bin/:$PATHexport CFLAGS="-pie -fPIE"export LDFLAGS="-pie -fPIE"./configure --host=aarch64-linux-androidmake adb push gdbserver /system/bin/gdbserver

实际应用(小patch)

我在这里看到了一个非常好的介绍gdb breakpoint实现原理的文章http://blog.jobbole.com/23463/
 那么,gdbserver在我们下一个breakpoint断点时,是如何工作的?

/* Copy LEN bytes of data from debugger memory at MYADDR to inferior's   memory at MEMADDR.  On failure (cannot write to the inferior)   returns the value of errno.  Always succeeds if LEN is zero.  */static intlinux_write_memory (CORE_ADDR memaddr, const unsigned char *myaddr, int len){  register int i;  /* Round starting address down to longword boundary.  */  register CORE_ADDR addr = memaddr & -(CORE_ADDR) sizeof (PTRACE_XFER_TYPE);  /* Round ending address up; get number of longwords that makes.  */  register int count    = (((memaddr + len) - addr) + sizeof (PTRACE_XFER_TYPE) - 1)    / sizeof (PTRACE_XFER_TYPE);  /* Allocate buffer of that many longwords.  */  register PTRACE_XFER_TYPE *buffer = XALLOCAVEC (PTRACE_XFER_TYPE, count);  int pid = lwpid_of (current_thread);  if (len == 0)    {      /* Zero length write always succeeds.  */      return 0;    }  if (debug_threads)    {      /* Dump up to four bytes.  */      char str[4 * 2 + 1];      char *p = str;      int dump = len < 4 ? len : 4;      for (i = 0; i < dump; i++)    {      sprintf (p, "%02x", myaddr[i]);      p += 2;    }      *p = '\0';      debug_printf ("Writing %s to 0x%08lx in process %d\n",            str, (long) memaddr, pid);    }  /* Fill start and end extra bytes of buffer with existing memory data.  */  errno = 0;  /* Coerce the 3rd arg to a uintptr_t first to avoid potential gcc warning     about coercing an 8 byte integer to a 4 byte pointer.  */  buffer[0] = ptrace (PTRACE_PEEKTEXT, pid,              (PTRACE_TYPE_ARG3) (uintptr_t) addr,              (PTRACE_TYPE_ARG4) 0);  if (errno)    return errno;  if (count > 1)    {      errno = 0;      buffer[count - 1]    = ptrace (PTRACE_PEEKTEXT, pid,          /* Coerce to a uintptr_t first to avoid potential gcc warning             about coercing an 8 byte integer to a 4 byte pointer.  */          (PTRACE_TYPE_ARG3) (uintptr_t) (addr + (count - 1)                          * sizeof (PTRACE_XFER_TYPE)),          (PTRACE_TYPE_ARG4) 0);      if (errno)    return errno;    }  /* Copy data to be written over corresponding part of buffer.  */  memcpy ((char *) buffer + (memaddr & (sizeof (PTRACE_XFER_TYPE) - 1)),      myaddr, len);  /* Write the entire buffer.  */  for (i = 0; i < count; i++, addr += sizeof (PTRACE_XFER_TYPE))    {      errno = 0;      // add by us      fprintf(stderr, "poketext addr:%p\n", addr);      ptrace (PTRACE_POKETEXT, pid,          /* Coerce to a uintptr_t first to avoid potential gcc warning         about coercing an 8 byte integer to a 4 byte pointer.  */          (PTRACE_TYPE_ARG3) (uintptr_t) addr,          (PTRACE_TYPE_ARG4) buffer[i]);      if (errno)    return errno;    }  return 0;}

 搜索add by us那一句,加到你的代码里就可以在gdb 执行break的时候在gdbserver的终端上看到打印信息了

0 0
原创粉丝点击