Commit b1a003da authored by Andrew Hsieh's avatar Andrew Hsieh
Browse files

Add gdbserver 7.3.x support

Change-Id: I1902f1dde5af9eceba45fb8240f363c88f783adb
parent e34b7c56
......@@ -199,6 +199,12 @@ case "$GDB_VERSION" in
# static executable.
CONFIGURE_FLAGS="--with-libthread-db=$BUILD_SYSROOT/usr/lib/libthread_db.a"
;;
7.3.x)
CONFIGURE_FLAGS="--with-libthread-db=$BUILD_SYSROOT/usr/lib/libthread_db.a"
# Disable libinproctrace.so which needs crtbegin_so.o and crtbend_so.o instead of
# CRTBEGIN/END above. Clean it up and re-enable it in the future.
CONFIGURE_FLAGS=$CONFIGURE_FLAGS" --disable-inprocess-agent"
;;
*)
CONFIGURE_FLAGS=""
esac
......
......@@ -104,6 +104,72 @@ index 638c228..a13117b 100644
])
if test "$srv_xmlfiles" != ""; then
diff --git a/gdb-7.3.x/gdb/gdbserver/Makefile.in b/gdb-7.3.x/gdb/gdbserver/Makefile.in
index 7d565af..e5e8ae4 100644
--- a/gdb-7.3.x/gdb/gdbserver/Makefile.in
+++ b/gdb-7.3.x/gdb/gdbserver/Makefile.in
@@ -233,13 +233,13 @@ clean-info:
gdbserver$(EXEEXT): $(OBS) ${ADD_DEPS} ${CDEPS}
rm -f gdbserver$(EXEEXT)
- ${CC-LD} $(INTERNAL_CFLAGS) $(INTERNAL_LDFLAGS) -o gdbserver$(EXEEXT) $(OBS) \
- $(GDBSERVER_LIBS) $(XM_CLIBS)
+ ${CC-LD} $(INTERNAL_CFLAGS) $(OBS) $(GDBSERVER_LIBS) $(XM_CLIBS) \
+ $(INTERNAL_LDFLAGS) -o gdbserver$(EXEEXT)
gdbreplay$(EXEEXT): $(GDBREPLAY_OBS)
rm -f gdbreplay$(EXEEXT)
- ${CC-LD} $(INTERNAL_CFLAGS) $(INTERNAL_LDFLAGS) -o gdbreplay$(EXEEXT) $(GDBREPLAY_OBS) \
- $(XM_CLIBS)
+ ${CC-LD} $(INTERNAL_CFLAGS) -o gdbreplay$(EXEEXT) $(GDBREPLAY_OBS) \
+ $(XM_CLIBS) $(INTERNAL_LDFLAGS)
IPA_OBJS=tracepoint-ipa.o utils-ipa.o regcache-ipa.o remote-utils-ipa.o ${IPA_DEPFILES}
diff --git a/gdb-7.3.x/gdb/gdbserver/configure b/gdb-7.3.x/gdb/gdbserver/configure
index 110e406..c50e9ac 100755
--- a/gdb-7.3.x/gdb/gdbserver/configure
+++ b/gdb-7.3.x/gdb/gdbserver/configure
@@ -4807,7 +4807,7 @@ rm -f core conftest.err conftest.$ac_objext \
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $found" >&5
$as_echo "$found" >&6; }
else
- srv_libs="-lthread_db"
+ srv_libs="-lthread_db -lc"
fi
srv_thread_depfiles="thread-db.o proc-service.o"
@@ -4848,7 +4848,7 @@ fi
# Check whether --with-libthread-db was given.
if test "${with_libthread_db+set}" = set; then :
withval=$with_libthread_db; srv_libthread_db_path="${withval}"
- srv_libs="$srv_libthread_db_path"
+ srv_libs="$srv_libthread_db_path -lc"
fi
diff --git a/gdb-7.3.x/gdb/gdbserver/configure.ac b/gdb-7.3.x/gdb/gdbserver/configure.ac
index 77e06c3..c70f3cf 100644
--- a/gdb-7.3.x/gdb/gdbserver/configure.ac
+++ b/gdb-7.3.x/gdb/gdbserver/configure.ac
@@ -315,7 +315,7 @@ if test "$srv_linux_thread_db" = "yes"; then
LDFLAGS="$old_LDFLAGS"
AC_MSG_RESULT($found)
else
- srv_libs="-lthread_db"
+ srv_libs="-lthread_db -lc"
fi
srv_thread_depfiles="thread-db.o proc-service.o"
@@ -332,7 +332,7 @@ fi
AC_ARG_WITH(libthread-db,
AS_HELP_STRING([--with-libthread-db=PATH], [use given libthread_db directly]),
[srv_libthread_db_path="${withval}"
- srv_libs="$srv_libthread_db_path"
+ srv_libs="$srv_libthread_db_path -lc"
])
if test "$srv_libs" != "" -a "$srv_libs" != "-ldl"; then
--
1.7.6.rc0
diff --git a/gdb-7.1.x/gdb/gdbserver/server.c b/gdb-7.1.x/gdb/gdbserver/server.c
index a03f877..c4214f9 100644
--- a/gdb-7.1.x/gdb/gdbserver/server.c
+++ b/gdb-7.1.x/gdb/gdbserver/server.c
@@ -76,12 +76,14 @@ pid_t old_foreground_pgrp;
/* Hand back terminal ownership to the original foreground group. */
+#ifndef __ANDROID__
static void
restore_old_foreground_pgrp (void)
{
tcsetpgrp (terminal_fd, old_foreground_pgrp);
}
#endif
+#endif
/* Set if you want to disable optional thread related packets support
in gdbserver, for the sake of testing GDB against stubs that don't
@@ -257,11 +259,13 @@ start_inferior (char **argv)
#ifdef SIGTTOU
signal (SIGTTOU, SIG_IGN);
signal (SIGTTIN, SIG_IGN);
+#ifndef __ANDROID__
terminal_fd = fileno (stderr);
old_foreground_pgrp = tcgetpgrp (terminal_fd);
tcsetpgrp (terminal_fd, signal_pid);
atexit (restore_old_foreground_pgrp);
#endif
+#endif
if (wrapper_argv != NULL)
{
diff --git a/gdb-7.3.x/gdb/gdbserver/config.in b/gdb-7.3.x/gdb/gdbserver/config.in
index 4882d80..62d2fe1 100644
--- a/gdb-7.3.x/gdb/gdbserver/config.in
+++ b/gdb-7.3.x/gdb/gdbserver/config.in
@@ -41,6 +41,12 @@
/* Define to 1 if you have the `dladdr' function. */
#undef HAVE_DLADDR
+/* Define to 1 if the system has the type `Elf32_auxv_t'. */
+#undef HAVE_ELF32_AUXV_T
+
+/* Define to 1 if the system has the type `Elf64_auxv_t'. */
+#undef HAVE_ELF64_AUXV_T
+
/* Define if <sys/procfs.h> has elf_fpregset_t. */
#undef HAVE_ELF_FPREGSET_T
diff --git a/gdb-7.3.x/gdb/gdbserver/configure b/gdb-7.3.x/gdb/gdbserver/configure
index 110e406..0696030 100755
--- a/gdb-7.3.x/gdb/gdbserver/configure
+++ b/gdb-7.3.x/gdb/gdbserver/configure
@@ -4319,6 +4319,30 @@ _ACEOF
fi
+ac_fn_c_check_type "$LINENO" "Elf32_auxv_t" "ac_cv_type_Elf32_auxv_t" "#include <elf.h>
+
+"
+if test "x$ac_cv_type_Elf32_auxv_t" = x""yes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_ELF32_AUXV_T 1
+_ACEOF
+
+
+fi
+ac_fn_c_check_type "$LINENO" "Elf64_auxv_t" "ac_cv_type_Elf64_auxv_t" "#include <elf.h>
+
+"
+if test "x$ac_cv_type_Elf64_auxv_t" = x""yes; then :
+
+cat >>confdefs.h <<_ACEOF
+#define HAVE_ELF64_AUXV_T 1
+_ACEOF
+
+
+fi
+
+
# Check whether --enable-googleisms was given.
if test "${enable_googleisms+set}" = set; then :
enableval=$enable_googleisms; case "${enableval}" in
diff --git a/gdb-7.3.x/gdb/gdbserver/linux-low.c b/gdb-7.3.x/gdb/gdbserver/linux-low.c
index e65ec96..f91129f 100644
--- a/gdb-7.3.x/gdb/gdbserver/linux-low.c
+++ b/gdb-7.3.x/gdb/gdbserver/linux-low.c
@@ -110,6 +110,36 @@
#endif
#endif
+#ifndef HAVE_ELF32_AUXV_T
+/* Copied from glibc's elf.h. */
+typedef struct
+{
+ uint32_t a_type; /* Entry type */
+ union
+ {
+ uint32_t a_val; /* Integer value */
+ /* We use to have pointer elements added here. We cannot do that,
+ though, since it does not work when using 32-bit definitions
+ on 64-bit platforms and vice versa. */
+ } a_un;
+} Elf32_auxv_t;
+#endif
+
+#ifndef HAVE_ELF64_AUXV_T
+/* Copied from glibc's elf.h. */
+typedef struct
+{
+ uint64_t a_type; /* Entry type */
+ union
+ {
+ uint64_t a_val; /* Integer value */
+ /* We use to have pointer elements added here. We cannot do that,
+ though, since it does not work when using 32-bit definitions
+ on 64-bit platforms and vice versa. */
+ } a_un;
+} Elf64_auxv_t;
+#endif
+
/* ``all_threads'' is keyed by the LWP ID, which we use as the GDB protocol
representation of the thread ID.
@@ -3816,7 +3846,7 @@ regsets_fetch_inferior_registers (struct regcache *regcache)
data = buf;
#ifndef __sparc__
- res = ptrace (regset->get_request, pid, nt_type, data);
+ res = ptrace (regset->get_request, pid, (PTRACE_ARG3_TYPE)nt_type, data);
#else
res = ptrace (regset->get_request, pid, data, nt_type);
#endif
@@ -3889,7 +3919,7 @@ regsets_store_inferior_registers (struct regcache *regcache)
data = buf;
#ifndef __sparc__
- res = ptrace (regset->get_request, pid, nt_type, data);
+ res = ptrace (regset->get_request, pid, (PTRACE_ARG3_TYPE)nt_type, data);
#else
res = ptrace (regset->get_request, pid, &iov, data);
#endif
@@ -3901,7 +3931,7 @@ regsets_store_inferior_registers (struct regcache *regcache)
/* Only now do we write the register set. */
#ifndef __sparc__
- res = ptrace (regset->set_request, pid, nt_type, data);
+ res = ptrace (regset->set_request, pid, (PTRACE_ARG3_TYPE)nt_type, data);
#else
res = ptrace (regset->set_request, pid, data, nt_type);
#endif
diff --git a/gdb-7.3.x/gdb/gdbserver/linux-x86-low.c b/gdb-7.3.x/gdb/gdbserver/linux-x86-low.c
index 69c6b57..cdc0a18 100644
--- a/gdb-7.3.x/gdb/gdbserver/linux-x86-low.c
+++ b/gdb-7.3.x/gdb/gdbserver/linux-x86-low.c
@@ -57,8 +57,13 @@ static const char *xmltarget_amd64_linux_no_xml = "@<target>\
</target>";
#endif
+#ifdef HAVE_SYS_REG_H
#include <sys/reg.h>
+#endif
+#ifdef HAVE_SYS_PROCFS_H
#include <sys/procfs.h>
+#endif
+
#include <sys/ptrace.h>
#include <sys/uio.h>
@@ -80,6 +85,9 @@ static const char *xmltarget_amd64_linux_no_xml = "@<target>\
#define PTRACE_ARCH_PRCTL 30
#endif
+#define PTRACE_ARG3_TYPE void*
+#define PTRACE_ARG4_TYPE void*
+
/* The following definitions come from prctl.h, but may be absent
for certain configurations. */
#ifndef ARCH_GET_FS
@@ -187,7 +195,7 @@ ps_get_thread_area (const struct ps_prochandle *ph,
unsigned int desc[4];
if (ptrace (PTRACE_GET_THREAD_AREA, lwpid,
- (void *) (intptr_t) idx, (unsigned long) &desc) < 0)
+ (void *) (intptr_t) idx, (PTRACE_ARG4_TYPE) &desc) < 0)
return PS_ERR;
*(int *)base = desc[1];
@@ -233,7 +241,7 @@ x86_get_thread_area (int lwpid, CORE_ADDR *addr)
if (ptrace (PTRACE_GET_THREAD_AREA,
lwpid_of (lwp),
- (void *) (long) idx, (unsigned long) &desc) < 0)
+ (void *) (long) idx, (PTRACE_ARG4_TYPE) &desc) < 0)
return -1;
*addr = desc[1];
@@ -441,7 +449,7 @@ x86_linux_dr_get (ptid_t ptid, int regnum)
errno = 0;
value = ptrace (PTRACE_PEEKUSER, tid,
- offsetof (struct user, u_debugreg[regnum]), 0);
+ (PTRACE_ARG3_TYPE)offsetof (struct user, u_debugreg[regnum]), 0);
if (errno != 0)
error ("Couldn't read debug register");
@@ -457,7 +465,7 @@ x86_linux_dr_set (ptid_t ptid, int regnum, unsigned long value)
errno = 0;
ptrace (PTRACE_POKEUSER, tid,
- offsetof (struct user, u_debugreg[regnum]), value);
+ (PTRACE_ARG3_TYPE)offsetof (struct user, u_debugreg[regnum]), (PTRACE_ARG4_TYPE)value);
if (errno != 0)
error ("Couldn't write debug register");
}
@@ -963,7 +971,7 @@ x86_linux_update_xmltarget (void)
{
elf_fpxregset_t fpxregs;
- if (ptrace (PTRACE_GETFPXREGS, pid, 0, (int) &fpxregs) < 0)
+ if (ptrace (PTRACE_GETFPXREGS, pid, 0, (PTRACE_ARG4_TYPE) &fpxregs) < 0)
{
have_ptrace_getfpxregs = 0;
x86_xcr0 = I386_XSTATE_X87_MASK;
@@ -1018,7 +1026,7 @@ x86_linux_update_xmltarget (void)
iov.iov_len = sizeof (xstateregs);
/* Check if PTRACE_GETREGSET works. */
- if (ptrace (PTRACE_GETREGSET, pid, (unsigned int) NT_X86_XSTATE,
+ if (ptrace (PTRACE_GETREGSET, pid, (PTRACE_ARG3_TYPE) NT_X86_XSTATE,
&iov) < 0)
{
have_ptrace_getregset = 0;
diff --git a/gdb-7.3.x/gdb/gdbserver/server.c b/gdb-7.3.x/gdb/gdbserver/server.c
index 5148dc8..9daceff 100644
--- a/gdb-7.3.x/gdb/gdbserver/server.c
+++ b/gdb-7.3.x/gdb/gdbserver/server.c
@@ -75,12 +75,14 @@ pid_t old_foreground_pgrp;
/* Hand back terminal ownership to the original foreground group. */
+#ifndef __ANDROID__
static void
restore_old_foreground_pgrp (void)
{
- tcsetpgrp (terminal_fd, old_foreground_pgrp);
+ tcsetpgrp (terminal_fd, old_foreground_pgrp);
}
#endif
+#endif
/* Set if you want to disable optional thread related packets support
in gdbserver, for the sake of testing GDB against stubs that don't
@@ -266,11 +268,13 @@ start_inferior (char **argv)
#ifdef SIGTTOU
signal (SIGTTOU, SIG_IGN);
signal (SIGTTIN, SIG_IGN);
+#ifndef __ANDROID__
terminal_fd = fileno (stderr);
old_foreground_pgrp = tcgetpgrp (terminal_fd);
tcsetpgrp (terminal_fd, signal_pid);
atexit (restore_old_foreground_pgrp);
#endif
+#endif
if (wrapper_argv != NULL)
{
diff --git a/gdb-7.3.x/gdb/gdbserver/thread-db.c b/gdb-7.3.x/gdb/gdbserver/thread-db.c
index 741c48b..3467b64 100644
--- a/gdb-7.3.x/gdb/gdbserver/thread-db.c
+++ b/gdb-7.3.x/gdb/gdbserver/thread-db.c
@@ -565,7 +565,7 @@ thread_db_load_search (void)
tdb->td_symbol_list_p = &td_symbol_list;
/* This is required only when thread_db_use_events is on. */
- tdb->td_thr_event_enable_p = &td_thr_event_enable;
+ tdb->td_thr_event_enable_p = (void*)&td_thr_event_enable;
/* These are not essential. */
tdb->td_ta_event_addr_p = &td_ta_event_addr;
diff --git a/gdb-7.3.x/include/elf/common.h b/gdb-7.3.x/include/elf/common.h
index 52ce9a5..a01e40c 100644
--- a/gdb-7.3.x/include/elf/common.h
+++ b/gdb-7.3.x/include/elf/common.h
@@ -35,7 +35,9 @@
/* Fields in e_ident[]. */
#define EI_MAG0 0 /* File identification byte 0 index */
+#ifndef ELFMAG0
#define ELFMAG0 0x7F /* Magic number byte 0 */
+#endif
#define EI_MAG1 1 /* File identification byte 1 index */
#define ELFMAG1 'E' /* Magic number byte 1 */
@@ -82,7 +84,9 @@
#define EI_ABIVERSION 8 /* ABI version */
+#ifndef EI_PAD
#define EI_PAD 9 /* Start of padding bytes */
+#endif
/* Values for e_type, which identifies the object file type. */
@@ -94,8 +98,12 @@
#define ET_CORE 4 /* Core file */
#define ET_LOOS 0xFE00 /* Operating system-specific */
#define ET_HIOS 0xFEFF /* Operating system-specific */
+#ifndef ET_LOPROC
#define ET_LOPROC 0xFF00 /* Processor-specific */
+#endif
+#ifndef ET_HIPROC
#define ET_HIPROC 0xFFFF /* Processor-specific */
+#endif
/* Values for e_machine, which identifies the architecture. These numbers
are officially assigned by registry@sco.com. See below for a list of
@@ -370,7 +378,9 @@
#define EM_CYGNUS_V850 0x9080
/* old S/390 backend magic number. Written in the absence of an ABI. */
+#ifndef EM_S390_OLD
#define EM_S390_OLD 0xa390
+#endif
/* Old, unofficial value for Xtensa. */
#define EM_XTENSA_OLD 0xabc7
@@ -423,18 +433,28 @@
#define PT_LOOS 0x60000000 /* OS-specific */
#define PT_HIOS 0x6fffffff /* OS-specific */
#define PT_LOPROC 0x70000000 /* Processor-specific */
+#ifndef PT_HIPROC
#define PT_HIPROC 0x7FFFFFFF /* Processor-specific */
+#endif
+#ifndef PT_GNU_EH_FRAME
#define PT_GNU_EH_FRAME (PT_LOOS + 0x474e550) /* Frame unwind information */
+#endif
#define PT_SUNW_EH_FRAME PT_GNU_EH_FRAME /* Solaris uses the same value */
#define PT_GNU_STACK (PT_LOOS + 0x474e551) /* Stack flags */
#define PT_GNU_RELRO (PT_LOOS + 0x474e552) /* Read-only after relocation */
/* Program segment permissions, in program header p_flags field. */
+#ifndef PF_X
#define PF_X (1 << 0) /* Segment is executable */
+#endif
+#ifndef PF_W
#define PF_W (1 << 1) /* Segment is writable */
+#endif
+#ifndef PF_R
#define PF_R (1 << 2) /* Segment is readable */
+#endif
/* #define PF_MASKOS 0x0F000000 *//* OS-specific reserved bits */
#define PF_MASKOS 0x0FF00000 /* New value, Oct 4, 1999 Draft */
#define PF_MASKPROC 0xF0000000 /* Processor-specific reserved bits */
@@ -480,16 +500,26 @@
#define SHT_GNU_versym SHT_SUNW_versym
#define SHT_LOPROC 0x70000000 /* Processor-specific semantics, lo */
+#ifndef SHT_HIPROC
#define SHT_HIPROC 0x7FFFFFFF /* Processor-specific semantics, hi */
+#endif
#define SHT_LOUSER 0x80000000 /* Application-specific semantics */
/* #define SHT_HIUSER 0x8FFFFFFF *//* Application-specific semantics */
+#ifndef SHT_HIUSER
#define SHT_HIUSER 0xFFFFFFFF /* New value, defined in Oct 4, 1999 Draft */
+#endif
/* Values for section header, sh_flags field. */
+#ifndef SHF_WRITE
#define SHF_WRITE (1 << 0) /* Writable data during execution */
+#endif
+#ifndef SHF_ALLOC
#define SHF_ALLOC (1 << 1) /* Occupies memory during execution */
+#endif
+#ifndef SHF_EXECINSTR
#define SHF_EXECINSTR (1 << 2) /* Executable machine instructions */
+#endif
#define SHF_MERGE (1 << 4) /* Data in this section can be merged */
#define SHF_STRINGS (1 << 5) /* Contains null terminated character strings */
#define SHF_INFO_LINK (1 << 6) /* sh_info holds section header table index */
@@ -500,7 +530,9 @@
/* #define SHF_MASKOS 0x0F000000 *//* OS-specific semantics */
#define SHF_MASKOS 0x0FF00000 /* New value, Oct 4, 1999 Draft */
+#ifndef SHF_MASKPROC
#define SHF_MASKPROC 0xF0000000 /* Processor-specific semantics */
+#endif
/* This used to be implemented as a processor specific section flag.
We just make it generic. */
@@ -607,17 +639,29 @@
which contains the symbol binding and symbol type. The STB_ and STT_
defines identify the binding and type. */
+#ifndef ELF_ST_BIND
#define ELF_ST_BIND(val) (((unsigned int)(val)) >> 4)
+#endif
+#ifndef ELF_ST_TYPE
#define ELF_ST_TYPE(val) ((val) & 0xF)
+#endif
#define ELF_ST_INFO(bind,type) (((bind) << 4) + ((type) & 0xF))
/* The 64bit and 32bit versions of these macros are identical, but
the ELF spec defines them, so here they are. */
+#ifndef ELF32_ST_BIND
#define ELF32_ST_BIND ELF_ST_BIND
+#endif
+#ifndef ELF32_ST_TYPE
#define ELF32_ST_TYPE ELF_ST_TYPE
+#endif
#define ELF32_ST_INFO ELF_ST_INFO
+#ifndef ELF64_ST_BIND
#define ELF64_ST_BIND ELF_ST_BIND
+#endif
+#ifndef ELF64_ST_TYPE
#define ELF64_ST_TYPE ELF_ST_TYPE
+#endif
#define ELF64_ST_INFO ELF_ST_INFO
/* This macro disassembles and assembles a symbol's visibility into
@@ -667,8 +711,12 @@
/* Relocation info handling macros. */
+#ifndef ELF32_R_SYM
#define ELF32_R_SYM(i) ((i) >> 8)
+#endif
+#ifndef ELF32_R_TYPE
#define ELF32_R_TYPE(i) ((i) & 0xff)
+#endif
#define ELF32_R_INFO(s,t) (((s) << 8) + ((t) & 0xff))
#define ELF64_R_SYM(i) ((i) >> 32)
/*
* Copyright 2006 The Android Open Source Project
*/
#include <dirent.h>
#include <sys/ptrace.h>
#include <stdint.h>
#include <thread_db.h>
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#define DEBUG 1
#if DEBUG
# include <string.h> /* for strerror() */
# define D(...) fprintf(stderr, "libthread_db:%s: ", __FUNCTION__), fprintf(stderr, __VA_ARGS__)
#else
# define D(...) do{}while(0)
#endif
extern int ps_pglobal_lookup (void *, const char *obj, const char *name, void **sym_addr);
extern pid_t ps_getpid(struct ps_prochandle *ph);
/*
* This is the list of "special" symbols we care about whose addresses are
* cached by gdbserver from the host at init time.
*/
enum {
SYM_TD_CREATE,
SYM_THREAD_LIST,
NUM_SYMS
};
static char const * gSymbols[] = {
[SYM_TD_CREATE] = "_thread_created_hook",
NULL
};
char const **
td_symbol_list(void)
{
return gSymbols;
}
/* Extract the permitted capabilities of a given task */
static int
_get_task_permitted_caps(int pid, int tid, uint64_t *cap)
{
char path[64];
char buff[1024];
int len;
int fd;
int result = -1;
char* perm;
char* end;
/* Open task status file */
snprintf(path, sizeof path, "/proc/%d/task/%d/status", pid, tid);
fd = open(path, O_RDONLY);
if (fd < 0) {
D("Could not open %s: %s\n", path, strerror(errno));
return -1;
}
/* Read its content, up to sizeof buff-1, then zero-terminate */
do {
len = read(fd, buff, sizeof buff-1);
} while (len < 0 && errno == EINTR);
if (len < 0) {
D("Could not read %s: %s\n", path, strerror(errno));
goto EXIT;
}
buff[len] = 0;
/* Look for "CapPrm: " in it */
perm = strstr(buff, "CapPrm:");
if (perm == NULL) {
D("Could not find CapPrm in %s!\n---- cut here ----\n%.*s\n----- cut here -----\n",
path, len, buff);
errno = EINVAL;
goto EXIT;
}
/* Now read the hexadecimal value after 'CapPrm: ' */
errno = 0;
*cap = (uint64_t) strtoull(perm+8, &end, 16);
if (errno == 0) {
D("Found CapPerm of %lld in %s\n", *cap, path);
result = 0;
} else {
D("Cannot read CapPerm from %s: '%.*s'\n", path, 24, perm);
}
EXIT:
close(fd);
return result;
}
td_err_e
td_ta_new(struct ps_prochandle * proc_handle, td_thragent_t ** agent_out)
{
td_thragent_t * agent;
/* Platforms before Android 2.3 contain a system bug that prevents
* gdbserver to attach to all threads in a target process when
* it is run as the same userID than the target (works fine if
* run as root).
*
* Due to the way gdbserver is coded, this makes gdbserver exit()
* immediately (see linux_attach_lwp in linux-low.c). Even if we
* modify the source code to not exit(), then signals will not
* be properly rerouted to gdbserver, preventing breakpoints from
* working correctly.
*
* The following code is here to test for this problematic condition.
* If it is detected, we return TD_NOLIBTHREAD to indicate that there
* are no threads to attach to (gdbserver will attach to the main thread
* though).
*/
do {
char path[64];
DIR* dir;
struct dirent *entry;
pid_t my_pid = getpid();
int target_pid = ps_getpid(proc_handle);
uint64_t my_caps, tid_caps;
D("Probing system for platform bug.\n");
/* nothing to do if we run as root */
if (geteuid() == 0) {
D("Running as root, nothing to do.\n");
break;
}
/* First, get our own permitted capabilities */
if (_get_task_permitted_caps(my_pid, my_pid, &my_caps) < 0) {
/* something is really fishy here */
D("Could not get gdbserver permitted caps!\n");
return TD_NOLIBTHREAD;
}
/* Now, for each thread in the target process, compare the
* permitted capabilities set to our own. If they differ,
* the thread attach will fail. Booo...
*/
snprintf(path, sizeof path, "/proc/%d/task", target_pid);
dir = opendir(path);
if (!dir) {
D("Could not open %s: %s\n", path, strerror(errno));
break;
}
while ((entry = readdir(dir)) != NULL) {
int tid;
if (entry->d_name[0] == '.') /* skip . and .. */
continue;
tid = atoi(entry->d_name);
if (tid == 0) /* should not happen - be safe */
continue;
if (_get_task_permitted_caps(target_pid, tid, &tid_caps) < 0) {
/* again, something is fishy */
D("Could not get permitted caps for thread %d\n", tid);
closedir(dir);
return TD_NOLIBTHREAD;
}
if (tid_caps != my_caps) {
/* AAAARGH !! The permitted capabilities set differ. */
D("AAAAAH, Can't debug threads!\n");
closedir(dir);
return TD_NOLIBTHREAD;
}
}
closedir(dir);
D("Victory: We can debug theads!\n");
} while (0);
/* We now return to our regularly scheduled program */
agent = (td_thragent_t *)malloc(sizeof(td_thragent_t));
if (!agent) {
return TD_MALLOC;
}
agent->pid = ps_getpid(proc_handle);
agent->ph = proc_handle;
*agent_out = agent;
return TD_OK;
}
td_err_e
td_ta_delete(td_thragent_t * ta)
{
free(ta);
// FIXME: anything else to do?
return TD_OK;
}
/* NOTE: not used by gdb 7.0 */
td_err_e
td_ta_set_event(td_thragent_t const * agent, td_thr_events_t * events)
{
return TD_OK;
}
/* NOTE: not used by gdb 7.0 */
static td_thrhandle_t gEventMsgHandle;
/* NOTE: not used by gdb 7.0 */
static int
_event_getmsg_helper(td_thrhandle_t const * handle, void * bkpt_addr)
{
void * pc;
pc = (void *)ptrace(PTRACE_PEEKUSR, handle->tid, (void *)60 /* r15/pc */, NULL);
if (pc == bkpt_addr) {
// The hook function takes the id of the new thread as it's first param,
// so grab it from r0.
gEventMsgHandle.pid = ptrace(PTRACE_PEEKUSR, handle->tid, (void *)0 /* r0 */, NULL);
gEventMsgHandle.tid = gEventMsgHandle.pid;
return 0x42;
}
return 0;
}
/* NOTE: not used by gdb 7.0 */
td_err_e
td_ta_event_getmsg(td_thragent_t const * agent, td_event_msg_t * event)
{
td_err_e err;
void * bkpt_addr;
err = ps_pglobal_lookup(NULL, NULL, gSymbols[SYM_TD_CREATE], &bkpt_addr);
if (err) {
return err;
}
err = td_ta_thr_iter(agent, _event_getmsg_helper, bkpt_addr, 0, 0, NULL, 0);
if (err != 0x42) {
return TD_NOMSG;
}
event->event = TD_CREATE;
event->th_p = &gEventMsgHandle; // Nasty hack, but it's the only way!
return TD_OK;
}
td_err_e
td_ta_map_lwp2thr(td_thragent_t const * agent, lwpid_t lwpid,
td_thrhandle_t *th)
{
th->pid = ps_getpid(agent->ph);
th->tid = lwpid;
return TD_OK;
}
td_err_e
td_thr_get_info(td_thrhandle_t const * handle, td_thrinfo_t * info)
{
info->ti_tid = handle->tid;
info->ti_lid = handle->tid; // Our pthreads uses kernel ids for tids
info->ti_state = TD_THR_SLEEP; /* XXX this needs to be read from /proc/<pid>/task/<tid>.
This is only used to see if the thread is a zombie or not */
return TD_OK;
}
/* NOTE: not used by gdb 7.0 */
td_err_e
td_thr_event_enable(td_thrhandle_t const * handle, td_event_e event)
{
// I don't think we need to do anything here...
return TD_OK;
}
/* NOTE: not used by gdb 7.0 */
td_err_e
td_ta_event_addr(td_thragent_t const * agent, td_event_e event, td_notify_t * notify_out)
{
int32_t err;
/*
* This is nasty, ps_pglobal_lookup is implemented in gdbserver and looks up
* the symbol from it's cache, which is populated at start time with the
* symbols returned from td_symbol_list via calls back to the host.
*/
switch (event) {
case TD_CREATE:
err = ps_pglobal_lookup(NULL, NULL, gSymbols[SYM_TD_CREATE], &notify_out->u.bptaddr);
if (err) {
return TD_NOEVENT;
}
return TD_OK;
}
return TD_NOEVENT;
}
td_err_e
td_ta_clear_event(const td_thragent_t * ta_arg, td_thr_events_t * event)
{
/* Given that gdb 7.0 doesn't use thread events,
there's nothing we need to do here. */
return TD_OK;
}
td_err_e
td_ta_thr_iter(td_thragent_t const * agent, td_thr_iter_f * func, void * cookie,
td_thr_state_e state, int32_t prio, sigset_t * sigmask, uint32_t user_flags)
{
td_err_e err = TD_OK;
char path[32];
DIR * dir;
struct dirent * entry;
td_thrhandle_t handle;
snprintf(path, sizeof(path), "/proc/%d/task/", agent->pid);
dir = opendir(path);
if (!dir) {
return TD_NOEVENT;
}
handle.pid = agent->pid;
while ((entry = readdir(dir)) != NULL) {
if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) {
continue;
}
handle.tid = atoi(entry->d_name);
if (func(&handle, cookie) != 0) {
err = TD_DBERR;
break;
}
}
closedir(dir);
return err;
}
td_err_e
td_thr_tls_get_addr(const td_thrhandle_t * th,
psaddr_t map_address, size_t offset, psaddr_t * address)
{
return TD_NOAPLIC; // FIXME: TODO
}
/*
* Copyright 2006 The Android Open Source Project
*/
#ifndef _LIBTHREAD_DB__THREAD_DB_H
#define _LIBTHREAD_DB__THREAD_DB_H
#include <pthread.h>
#include <signal.h>
#include <stdint.h>
#include <sys/types.h>
typedef void *psaddr_t;
#define HAVE_PSADDR_T 1
typedef pid_t lwpid_t;
#define HAVE_LWPID_T 1
#define TD_THR_ANY_USER_FLAGS 0xffffffff
#define TD_THR_LOWEST_PRIORITY -20
#define TD_SIGNO_MASK NULL
/* td_err_e values */
enum {
TD_OK,
TD_ERR,
TD_NOTHR,
TD_NOSV,
TD_NOLWP,
TD_BADPH,
TD_BADTH,
TD_BADSH,
TD_BADTA,
TD_BADKEY,
TD_NOMSG,
TD_NOFPREGS,
TD_NOLIBTHREAD,
TD_NOEVENT,
TD_NOCAPAB,
TD_DBERR,
TD_NOAPLIC,
TD_NOTSD,
TD_MALLOC,
TD_PARTIALREG,
TD_NOXREGS,
TD_VERSION
};
/*
* td_event_e values
* NOTE: There is a max of 32 events
*/
enum {
TD_CREATE,
TD_DEATH
};
/* td_thr_state_e values */
enum {
TD_THR_ANY_STATE,
TD_THR_UNKNOWN,
TD_THR_SLEEP,
TD_THR_ZOMBIE
};
typedef int32_t td_err_e;
typedef uint32_t td_event_e;
typedef uint32_t td_notify_e;
typedef uint32_t td_thr_state_e;
typedef pthread_t thread_t;
typedef struct
{
pid_t pid;
struct ps_prochandle *ph;
} td_thragent_t;
typedef struct
{
pid_t pid;
pid_t tid;
} td_thrhandle_t;
typedef struct
{
td_event_e event;
td_thrhandle_t const * th_p;
union {
void * data;
} msg;
} td_event_msg_t;
typedef struct
{
uint32_t events;
} td_thr_events_t;
typedef struct
{
union {
void * bptaddr;
} u;
} td_notify_t;
typedef struct
{
td_thr_state_e ti_state;
thread_t ti_tid; // pthread's id for the thread
int32_t ti_lid; // the kernel's id for the thread
} td_thrinfo_t;
#define td_event_emptyset(set) \
(set)->events = 0
#define td_event_fillset(set) \
(set)->events = 0xffffffff
#define td_event_addset(set, n) \
(set)->events |= (1 << n)
typedef int td_thr_iter_f(td_thrhandle_t const *, void *);
struct ps_prochandle;
#ifdef __cplusplus
extern "C"{
#endif
extern td_err_e td_ta_new(struct ps_prochandle * proc_handle, td_thragent_t ** thread_agent);
extern td_err_e td_ta_delete(td_thragent_t * ta);
extern td_err_e td_ta_set_event(td_thragent_t const * agent, td_thr_events_t * event);
extern td_err_e td_ta_event_addr(td_thragent_t const * agent, td_event_e event, td_notify_t * notify);
extern td_err_e td_ta_clear_event(const td_thragent_t * ta_arg,
td_thr_events_t * event);
extern td_err_e td_ta_event_getmsg(td_thragent_t const * agent, td_event_msg_t * event);
extern td_err_e td_ta_map_lwp2thr(td_thragent_t const * agent, lwpid_t lwpid,
td_thrhandle_t *th);
extern td_err_e td_thr_get_info(td_thrhandle_t const * handle,
td_thrinfo_t * info);
extern td_err_e td_thr_event_enable(td_thrhandle_t const * handle,
td_event_e event);
extern td_err_e td_ta_thr_iter(td_thragent_t const * agent, td_thr_iter_f * func, void * cookie,
td_thr_state_e state, int32_t prio, sigset_t * sigmask, uint32_t user_flags);
extern char const ** td_symbol_list(void);
extern td_err_e td_thr_event_enable(td_thrhandle_t const * handle, td_event_e event);
extern td_err_e td_thr_get_info(td_thrhandle_t const * handle, td_thrinfo_t * info);
extern td_err_e td_thr_tls_get_addr(const td_thrhandle_t * th,
psaddr_t map_address, size_t offset,
psaddr_t * address);
#ifdef __cplusplus
}
#endif
#endif
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment