This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[PATCH] TLS access support in cross- Linux GDB


TLS variable was not propagating from core dump file to GDB and this patch implements that behavior for multiarch GDB. This approach includes linux-thread-db.c to be compiled for multiarch GDB, where appropriate functions for getting TLS addresses are used. If the program being debugged is built for host architecture, we keep the old way of calculating TLS. For target architectures modified libthread_db functions (td_ta_new(), td_thr_tls_get_addr(), td_thr_tlsbase()) are used, which can work with any version of glibc. Also, additional functions are copied from glibc in order to satisfy missing dependencies.

Similar to native debugging, host libthread_db.so should be loaded into multiarch GDB. It should be the same version of the library which is used for getting core dump file. This is needed in order to initialize necessary thread data in libthread_db.so.

This patch won't work for MIPS because master branch is missing patch for extracting PID from core file. That patch is sent alone.
Currently,  we don't have copyright assignment, but our company is in process of getting it.


From 3f18cbbeea06a9a67c4e307eeee66cd029534890 Mon Sep 17 00:00:00 2001
From: Djordje Todorovic <djordje.todorovic@rt-rk.com>
Date: Thu, 18 May 2017 12:27:21 +0200
Subject: [PATCH] TLS Support for multiarch

TLS variable was not propagate from core dump file to GDB,
this patch implements that behavior for multiarch.

	* Makefile.in(INTERNAL_CCFLAGS): Add CFLAGS for glibc-dep/.
	(CCOMPILE): Force glibc-dep/ to be compiled with gcc.
	* gdb/config/glibc.mh(GLIBCFILES): Define object files that
	will be generated in order to read TLS with GDB Multiarch.
	[DCROSS_GDB]: Define if it's GDB Multiarch.
	* gdb/configure.ac(cross_makefile_frag): Add GLIBCFILES in
	order to generate Makefile for cross platforms to read TLS.
	* gdb/configure: Regenerate.
	* gdb/gdb_proc_service.h: Add necessary code in order to
	compile glibc-dep/ with GCC.
	* gdb/gdbarch.c: Likewise.
	* gdb/glibc-dep/README.txt: Brief explanation of glibc-dep/.
	* gdb/glibc-dep/gdb_td_ta_new.c(init_target_dep_constants): New
	function.
	(gdb_td_ta_new): Get current version of GLIBC from coredump file.
	* gdb/glibc-dep/native-check.c(get_host_mach): New function.
	(native_check): Check if it is native architecture when using
	GDB Multiarch.
	* gdb/glibc-dep/db-symbols.h: Take necessary code from GLIBC
	in order to annul differences between GLIBC versions for reading
	TLS.
	* gdb/glibc-dep/nptl_db/fetch-value.c: Likewise.
	* gdb/glibc-dep/nptl_db/structs.def: Likewise.
	* gdb/glibc-dep/nptl_db/td_symbol_list.c: Likewise.
	* gdb/glibc-dep/nptl_db/td_ta_map_lwp2thr.c: Likewise.
	* gdb/glibc-dep/nptl_db/td_thr_tls_get_addr.c: Likewise.
	* gdb/glibc-dep/nptl_db/td_thr_tlsbase.c: Likewise. Modify in
	order to work with different versions of GLIBC.
	* gdb/glibc-dep/nptl_db/thread_dbP.h: Likewise.
	* gdb/glibc-dep/nptl_db/tls.h: Likewise.
	* gdb/gregset.h: Remove deprecated gregset_t but use
	elf_gregset_t.
	* gdb/linux-thread-db.c: (try_thread_db_load_1): Set up TLS
	functions from glibc-dep/.
	* gdb/nat/gdb_thread_db.h: (gdb_td_ta_new, gdb_td_thr_tlsbase)
	(gdb_td_thr_tls_get_addr, native_check): Declare TLS functions.

Signed-off-by: Nikola Prica <nikola.prica@rt-rk.com>
Signed-off-by: Djordje Todorovic <djordje.todorovic@rt-rk.com>
---
 gdb/ChangeLog                               |  39 +++++
 gdb/Makefile.in                             |  17 +-
 gdb/config/glibc.mh                         |   6 +
 gdb/configure                               |  10 +-
 gdb/configure.ac                            |   7 +
 gdb/gdb_proc_service.h                      |  13 ++
 gdb/gdbarch.c                               |   4 +-
 gdb/gdbarch.h                               |   4 +-
 gdb/glibc-dep/README.txt                    |  42 +++++
 gdb/glibc-dep/gdb_td_ta_new.c               |  97 +++++++++++
 gdb/glibc-dep/native_check.c                |  65 ++++++++
 gdb/glibc-dep/native_check.h                |  19 +++
 gdb/glibc-dep/nptl_db/db-symbols.h          |  51 ++++++
 gdb/glibc-dep/nptl_db/fetch-value.c         | 191 +++++++++++++++++++++
 gdb/glibc-dep/nptl_db/structs.def           | 112 +++++++++++++
 gdb/glibc-dep/nptl_db/td_symbol_list.c      |  45 +++++
 gdb/glibc-dep/nptl_db/td_ta_map_lwp2thr.c   | 167 +++++++++++++++++++
 gdb/glibc-dep/nptl_db/td_thr_tls_get_addr.c |  42 +++++
 gdb/glibc-dep/nptl_db/td_thr_tlsbase.c      | 249 ++++++++++++++++++++++++++++
 gdb/glibc-dep/nptl_db/thread_dbP.h          | 206 +++++++++++++++++++++++
 gdb/glibc-dep/nptl_db/tls.h                 |  37 +++++
 gdb/gregset.h                               |   4 +-
 gdb/linux-thread-db.c                       |  29 ++++
 gdb/nat/gdb_thread_db.h                     |  15 ++
 24 files changed, 1463 insertions(+), 8 deletions(-)
 create mode 100644 gdb/config/glibc.mh
 create mode 100644 gdb/glibc-dep/README.txt
 create mode 100644 gdb/glibc-dep/gdb_td_ta_new.c
 create mode 100644 gdb/glibc-dep/native_check.c
 create mode 100644 gdb/glibc-dep/native_check.h
 create mode 100644 gdb/glibc-dep/nptl_db/db-symbols.h
 create mode 100644 gdb/glibc-dep/nptl_db/fetch-value.c
 create mode 100644 gdb/glibc-dep/nptl_db/structs.def
 create mode 100644 gdb/glibc-dep/nptl_db/td_symbol_list.c
 create mode 100644 gdb/glibc-dep/nptl_db/td_ta_map_lwp2thr.c
 create mode 100644 gdb/glibc-dep/nptl_db/td_thr_tls_get_addr.c
 create mode 100644 gdb/glibc-dep/nptl_db/td_thr_tlsbase.c
 create mode 100644 gdb/glibc-dep/nptl_db/thread_dbP.h
 create mode 100644 gdb/glibc-dep/nptl_db/tls.h

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index fdc2a40..5bb0821 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,42 @@
+2017-05-18  Djordje Todorovic  <djordje.todorovic@rt-rk.com>
+
+	* Makefile.in(INTERNAL_CCFLAGS): Add CFLAGS for glibc-dep/.
+	(CCOMPILE): Force glibc-dep/ to be compiled with gcc.
+	* gdb/config/glibc.mh(GLIBCFILES): Define object files that
+	will be generated in order to read TLS with GDB Multiarch.
+	[DCROSS_GDB]: Define if it's GDB Multiarch.
+	* gdb/configure.ac(cross_makefile_frag): Add GLIBCFILES in
+	order to generate Makefile for cross platforms to read TLS.
+	* gdb/configure: Regenerate.
+	* gdb/gdb_proc_service.h: Add necessary code in order to
+	compile glibc-dep/ with GCC.
+	* gdb/gdbarch.c: Likewise.
+	* gdb/glibc-dep/README.txt: Brief explanation of glibc-dep/.
+	* gdb/glibc-dep/gdb_td_ta_new.c(init_target_dep_constants): New
+	function.
+	(gdb_td_ta_new): Get current version of GLIBC from coredump file.
+	* gdb/glibc-dep/native-check.c(get_host_mach): New function.
+	(native_check): Check if it is native architecture when using
+	GDB Multiarch.
+	* gdb/glibc-dep/db-symbols.h: Take necessary code from GLIBC
+	in order to annul differences between GLIBC versions for reading
+	TLS.
+	* gdb/glibc-dep/nptl_db/fetch-value.c: Likewise.
+	* gdb/glibc-dep/nptl_db/structs.def: Likewise.
+	* gdb/glibc-dep/nptl_db/td_symbol_list.c: Likewise.
+	* gdb/glibc-dep/nptl_db/td_ta_map_lwp2thr.c: Likewise.
+	* gdb/glibc-dep/nptl_db/td_thr_tls_get_addr.c: Likewise.
+	* gdb/glibc-dep/nptl_db/td_thr_tlsbase.c: Likewise. Modify in
+	order to work with different versions of GLIBC.
+	* gdb/glibc-dep/nptl_db/thread_dbP.h: Likewise.
+	* gdb/glibc-dep/nptl_db/tls.h: Likewise.
+	* gdb/gregset.h: Remove deprecated gregset_t but use
+	elf_gregset_t.
+	* gdb/linux-thread-db.c: (try_thread_db_load_1): Set up TLS
+	functions from glibc-dep/.
+	* gdb/nat/gdb_thread_db.h: (gdb_td_ta_new, gdb_td_thr_tlsbase)
+	(gdb_td_thr_tls_get_addr, native_check): Declare TLS functions.
+
 2017-05-17  Yao Qi  <yao.qi@linaro.org>

 	* cli/cli-decode.c (add_alias_cmd): New function.
diff --git a/gdb/Makefile.in b/gdb/Makefile.in
index 452f146..fb46538 100644
--- a/gdb/Makefile.in
+++ b/gdb/Makefile.in
@@ -117,6 +117,9 @@ depcomp = $(SHELL) $(srcdir)/../depcomp
 COMPILE.pre = $(CXX) $(CXX_DIALECT)
 COMPILE.post = -c -o $@
 COMPILE = $(COMPILE.pre) $(INTERNAL_CFLAGS) $(COMPILE.post)
+INTERNAL_CCFLAGS_TMP = $(filter-out -Wpointer-arith, $(INTERNAL_CFLAGS))
+INTERNAL_CCFLAGS = $(filter-out -Werror, $(INTERNAL_CCFLAGS_TMP))
+CCOMPILE = $(CC) $(INTERNAL_CCFLAGS) $(COMPILE.post)
 POSTCOMPILE = @true

 # Directory containing source files.
@@ -920,6 +923,10 @@ HAVE_NATIVE_GCORE_HOST = @HAVE_NATIVE_GCORE_HOST@

 # End of native-target dependent variables.

+# Cross fragment
+@cross_makefile_frag@
+# End of cross fragment
+
 FLAGS_TO_PASS = \
 	"prefix=$(prefix)" \
 	"exec_prefix=$(exec_prefix)" \
@@ -1616,7 +1623,7 @@ INFOFILES = gdb.info*
 # Makefile.in

 DEPFILES = $(TARGET_OBS) $(SER_HARDWIRE) $(NATDEPFILES) \
-	   $(REMOTE_OBS) $(SIM_OBS)
+	   $(REMOTE_OBS) $(SIM_OBS) $(GLIBCFILES)

 SOURCES = $(SFILES) $(ALLDEPFILES) $(YYFILES) $(CONFIG_SRCS)
 # Don't include YYFILES (*.c) because we already include *.y in SFILES,
@@ -1945,6 +1952,14 @@ all: gdb$(EXEEXT) $(CONFIG_ALL)
 	$(COMPILE) $<
 	$(POSTCOMPILE)

+%.o: $(srcdir)/glibc-dep/%.c
+	$(CCOMPILE) $<
+	$(POSTCOMPILE)
+
+%.o: ${srcdir}/glibc-dep/nptl_db/%.c
+	$(CCOMPILE) $<
+	$(POSTCOMPILE)
+
 # Specify an explicit rule for gdb/common/agent.c, to avoid a clash with the
 # object file generate by gdb/agent.c.
 common-agent.o: $(srcdir)/common/agent.c
diff --git a/gdb/config/glibc.mh b/gdb/config/glibc.mh
new file mode 100644
index 0000000..0687442
--- /dev/null
+++ b/gdb/config/glibc.mh
@@ -0,0 +1,6 @@
+# GLIBC fragment comes in here
+GLIBCFILES = td_symbol_list.o \
+	fetch-value.o gdb_td_ta_new.o \
+	td_thr_tlsbase.o td_thr_tls_get_addr.o \
+	td_ta_map_lwp2thr.o native_check.o
+INTERNAL_CFLAGS += -DCROSS_GDB
diff --git a/gdb/configure b/gdb/configure
index 8df81ac..5766a24 100755
--- a/gdb/configure
+++ b/gdb/configure
@@ -806,7 +806,8 @@ PACKAGE_TARNAME
 PACKAGE_NAME
 PATH_SEPARATOR
 SHELL'
-ac_subst_files='nat_makefile_frag'
+ac_subst_files='nat_makefile_frag
+cross_makefile_frag'
 ac_user_opts='
 enable_option_checking
 enable_maintainer_mode
@@ -16738,6 +16739,13 @@ if test "${gdb_native}" = "yes"; then
   nativefile=$NAT_FILE
 fi

+if test "${gdb_native}" = "no" || test "${enable_targets}" != ""; then
+  cross_makefile_frag=${srcdir}/config/glibc.mh
+else
+  cross_makefile_frag=/dev/null
+fi
+
+



diff --git a/gdb/configure.ac b/gdb/configure.ac
index fd11cf0..b732223 100644
--- a/gdb/configure.ac
+++ b/gdb/configure.ac
@@ -2206,6 +2206,12 @@ if test "${gdb_native}" = "yes"; then
   nativefile=$NAT_FILE
 fi

+if test "${gdb_native}" = "no" || test "${enable_targets}" != ""; then
+  cross_makefile_frag=${srcdir}/config/glibc.mh
+else
+  cross_makefile_frag=/dev/null
+fi
+
 AC_SUBST(NAT_FILE)
 AC_SUBST(NATDEPFILES)
 AC_SUBST(NAT_CDEPS)
@@ -2215,6 +2221,7 @@ AC_SUBST(XM_CLIBS)
 AC_SUBST(NAT_GENERATED_FILES)
 AC_SUBST(HAVE_NATIVE_GCORE_HOST)
 AC_SUBST_FILE(nat_makefile_frag)
+AC_SUBST_FILE(cross_makefile_frag)

 if test x"${gdb_osabi}" != x ; then
     AC_DEFINE_UNQUOTED(GDB_OSABI_DEFAULT, $gdb_osabi,
diff --git a/gdb/gdb_proc_service.h b/gdb/gdb_proc_service.h
index 734fcb2..5db14f4 100644
--- a/gdb/gdb_proc_service.h
+++ b/gdb/gdb_proc_service.h
@@ -62,7 +62,9 @@ EXTERN_C_POP
 #include <sys/procfs.h>
 #endif

+#ifdef __cplusplus
 EXTERN_C_PUSH
+#endif

 /* Functions in this interface return one of these status codes.  */
 typedef enum
@@ -159,7 +161,9 @@ extern ps_err_e ps_lsetxregs (struct ps_prochandle *ph, lwpid_t lwpid,
 /* Log a message (sends to gdb_stderr).  */
 extern void ps_plog (const char *fmt, ...);

+#ifdef __cplusplus
 EXTERN_C_POP
+#endif

 #endif /* HAVE_PROC_SERVICE_H */

@@ -175,11 +179,20 @@ typedef gdb_fpregset_t gdb_prfpregset_t;
 typedef prfpregset_t gdb_prfpregset_t;
 #endif

+/* The macro is called because gdb_proc_service.h is included from
+   glibc-dep/nptl_db/thread_dbP.h which is used when compiling
+   glibc-dep files with gcc and the structure below has c++ class
+   ptid as field. When this header is included from
+   glibc-dep/nptl_db/thread_dbP.h there is only need for functions
+   definitions and struct ps_prochandle forward declaration.
+*/
+#ifndef _THREAD_DBP_H
 /* GDB specific structure that identifies the target process.  */
 struct ps_prochandle
 {
   /* The LWP we use for memory reads.  */
   ptid_t ptid;
 };
+#endif

 #endif /* gdb_proc_service.h */
diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c
index 9c827ac..9732a18 100644
--- a/gdb/gdbarch.c
+++ b/gdb/gdbarch.c
@@ -1497,7 +1497,7 @@ gdbarch_tdep (struct gdbarch *gdbarch)
 }


-const struct bfd_arch_info *
+EXTERN_C const struct bfd_arch_info *
 gdbarch_bfd_arch_info (struct gdbarch *gdbarch)
 {
   gdb_assert (gdbarch != NULL);
@@ -5465,7 +5465,7 @@ set_target_gdbarch (struct gdbarch *new_gdbarch)

 /* Return the current inferior's arch.  */

-struct gdbarch *
+EXTERN_C struct gdbarch *
 target_gdbarch (void)
 {
   return current_inferior ()->gdbarch;
diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h
index 15a8141..d587c02 100644
--- a/gdb/gdbarch.h
+++ b/gdb/gdbarch.h
@@ -83,7 +83,7 @@ struct ui_out;
    gdbarch.  */

 /* This is a convenience wrapper for 'current_inferior ()->gdbarch'.  */
-extern struct gdbarch *target_gdbarch (void);
+EXTERN_C struct gdbarch *target_gdbarch (void);

 /* Callback type for the 'iterate_over_objfiles_in_search_order'
    gdbarch  method.  */
@@ -103,8 +103,8 @@ typedef void (iterate_over_regset_sections_cb)


 /* The following are pre-initialized by GDBARCH.  */
+EXTERN_C const struct bfd_arch_info * gdbarch_bfd_arch_info (struct gdbarch *gdbarch);

-extern const struct bfd_arch_info * gdbarch_bfd_arch_info (struct gdbarch *gdbarch);
 /* set_gdbarch_bfd_arch_info() - not applicable - pre-initialized.  */

 extern enum bfd_endian gdbarch_byte_order (struct gdbarch *gdbarch);
diff --git a/gdb/glibc-dep/README.txt b/gdb/glibc-dep/README.txt
new file mode 100644
index 0000000..917d0d0
--- /dev/null
+++ b/gdb/glibc-dep/README.txt
@@ -0,0 +1,42 @@
+Files and functions taken from GLIBC source code (${glibc_src}/nptl_db/) necessary for getting
+TLS variables (from coredump file) when cross GDB using GLIBC version 2.22 and higher are stored into
+${gdb_src}/glibc-dep/nptl_db directory.
+
+gdb_td_ta_new() is stored into ${gdb_src}/glibc-dep/ because functionality of function (td_ta_new())
+from GLIBC source has changed in order to get current version of GLIBC from coredump file.
+
+gdb_td_thr_tlsbase is function taken from nptl_db/td_thr_tlsbase.c,
+which has modified in GLIBC 2.22 and higher, so all dependent files had to be included into GDB source.
+
+------------------------
+
+${gdb_src}/glibc-dep/nptl_db
+
+* thread_dbP.h
+Taken needed definitions and macros.
+
+* db-symbols.h
+Unmodified.
+
+* fetch-value.c
+Taken needed functions.
+
+* structs.def
+Unmodified.
+
+* td_symbol_list.c
+Taken necessary definitions and modified td_lookup function.
+
+* td_ta_map_lwp2thr.c
+Taken only __td_ta_lookup_th_unique function unmodified.
+
+* td_thr_tlsbase.c
+gdb_td_thr_tlsbase(), modified in order to work with all GLIBC versions.
+${gdb_src}/gdb/config/${arch}/tls.h depending on architecture got different
+values of TLS_TCB_AT_TP and TLS_DTV_AT_TP macros taken
+from ${glibc_src}/sysdeps/${arch}/nptl/tls.h.
+
+* td_thr_tls_get_addr.c
+Unmodified.
+
+-------------------------
\ No newline at end of file
diff --git a/gdb/glibc-dep/gdb_td_ta_new.c b/gdb/glibc-dep/gdb_td_ta_new.c
new file mode 100644
index 0000000..4c6d3a8
--- /dev/null
+++ b/gdb/glibc-dep/gdb_td_ta_new.c
@@ -0,0 +1,97 @@
+/* Copyright (C) 2000-2017 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <version.h>
+
+#include "nptl_db/thread_dbP.h"
+#include "nat/gdb_thread_db.h"
+#include "nptl_db/tls.h"
+#include "bfd.h"
+
+struct gdbarch;
+extern const struct bfd_arch_info *gdbarch_bfd_arch_info (struct gdbarch *gdbarch);
+extern struct gdbarch *target_gdbarch (void);
+
+static td_err_e
+init_target_dep_constants ()
+{
+  const struct bfd_arch_info *bfdarch = gdbarch_bfd_arch_info (target_gdbarch ());
+  unsigned arch = bfdarch->arch;
+  switch (arch)
+    {
+       case bfd_arch_mips:
+         tls_tcb_at_tp = 0;
+         tls_dtv_at_tp = 1;
+         forced_dynamic_tls_offset = -2;
+         no_tls_offset = -1;
+         tcb_alignment = 16;
+         break;
+       case bfd_arch_arm:
+         tls_tcb_at_tp = 0;
+         tls_dtv_at_tp = 1;
+         forced_dynamic_tls_offset = -2;
+         no_tls_offset = -1;
+         /* Set to zero because not in use for TLS_PRE_TCB_SIZE. */
+         tcb_alignment = 0;
+         break;
+       case bfd_arch_i386:
+         tls_tcb_at_tp = 1;
+         tls_dtv_at_tp = 0;
+         forced_dynamic_tls_offset = -1;
+         no_tls_offset = 0;
+         /* Set to zero because not in use for TLS_PRE_TCB_SIZE. */
+         tcb_alignment = 0;
+         break;
+       case bfd_arch_powerpc:
+         tls_tcb_at_tp = 0;
+         tls_dtv_at_tp = 1;
+         forced_dynamic_tls_offset = -2;
+         no_tls_offset = -1;
+         tcb_alignment = 48;
+         break;
+       case bfd_arch_aarch64:
+         tls_tcb_at_tp = 0;
+         tls_dtv_at_tp = 1;
+         forced_dynamic_tls_offset = -1;
+         no_tls_offset = 0;
+         /* Set to zero because not in use for TLS_PRE_TCB_SIZE. */
+         tcb_alignment = 0;
+         break;
+       default:
+         return TD_ERR;
+    }
+  return TD_OK;
+}
+
+
+td_err_e
+gdb_td_ta_new (struct ps_prochandle *ps, td_thragent_t **ta)
+{
+  psaddr_t versaddr;
+
+  /* Check whether the versions match. */
+  if (td_lookup (ps, SYM_nptl_version, &versaddr) != PS_OK)
+    return TD_NOLIBTHREAD;
+  if (ps_pdread (ps, versaddr, versbuf, sizeof (versbuf)) != PS_OK)
+    return TD_ERR;
+  if (init_target_dep_constants () != TD_OK)
+    return TD_ERR;
+  return TD_OK;
+}
diff --git a/gdb/glibc-dep/native_check.c b/gdb/glibc-dep/native_check.c
new file mode 100644
index 0000000..732db10
--- /dev/null
+++ b/gdb/glibc-dep/native_check.c
@@ -0,0 +1,65 @@
+/* Copyright (C) 2000-2017 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "native_check.h"
+#include <string.h>
+#include <stdio.h>
+#include "../config.h"
+#include "bfd.h"
+#include <sys/utsname.h>
+
+unsigned get_host_mach (char *name_of_arch)
+{
+  unsigned result;
+
+  if (strstr (name_of_arch, "x86_64") != NULL)
+    result = bfd_arch_i386;
+  else if (strstr (name_of_arch, "i386") != NULL)
+    result = bfd_arch_i386;
+  else if (strstr (name_of_arch, "mips") != NULL)
+    result = bfd_arch_mips;
+  else if (strstr (name_of_arch, "arm") != NULL)
+    result = bfd_arch_arm;
+  else if (strstr (name_of_arch, "powerpc") != NULL)
+    result = bfd_arch_powerpc;
+  else if (strstr (name_of_arch, "aarch64") != NULL)
+    result = bfd_arch_aarch64;
+  else
+    result = -1;
+
+  return result;
+}
+
+int native_check (unsigned bfd_arch)
+{
+  struct utsname buf;
+  if (uname (&buf) == 0)
+    {
+      unsigned host_mach = get_host_mach (buf.machine);
+
+      if (host_mach == bfd_arch)
+        {
+          /* zero if it's host */
+          return 0;
+        }
+      else
+        {
+          return 1;
+        }
+    }
+  return -1;
+}
\ No newline at end of file
diff --git a/gdb/glibc-dep/native_check.h b/gdb/glibc-dep/native_check.h
new file mode 100644
index 0000000..2ed7554
--- /dev/null
+++ b/gdb/glibc-dep/native_check.h
@@ -0,0 +1,19 @@
+/* Copyright (C) 2000-2017 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+unsigned get_host_mach (char *name_of_arch);
+int native_check (unsigned bfd_arch);
\ No newline at end of file
diff --git a/gdb/glibc-dep/nptl_db/db-symbols.h b/gdb/glibc-dep/nptl_db/db-symbols.h
new file mode 100644
index 0000000..37c285a
--- /dev/null
+++ b/gdb/glibc-dep/nptl_db/db-symbols.h
@@ -0,0 +1,51 @@
+/* List of symbols in libpthread examined by libthread_db.
+   Copyright (C) 2009-2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#define DOT(x)  x   /* No prefix.  */
+
+#define STRINGIFY(name)   STRINGIFY_1(name)
+#define STRINGIFY_1(name) #name
+
+#define DB_STRUCT(type) \
+  DB_LOOKUP_NAME (SYM_SIZEOF_##type, _thread_db_sizeof_##type)
+#define DB_STRUCT_FIELD(type, field) \
+  DB_LOOKUP_NAME (SYM_##type##_FIELD_##field, _thread_db_##type##_##field)
+#define DB_SYMBOL(name) \
+  DB_LOOKUP_NAME (SYM_##name, name)
+#define DB_FUNCTION(name) \
+  DB_LOOKUP_NAME (SYM_##name, DOT (name))
+#define DB_VARIABLE(name) \
+  DB_LOOKUP_NAME (SYM_##name, name) \
+  DB_LOOKUP_NAME (SYM_DESC_##name, _thread_db_##name)
+
+# include "structs.def"
+
+# undef DB_STRUCT
+# undef DB_FUNCTION
+# undef DB_SYMBOL
+# undef DB_VARIABLE
+# undef DOT
+
+DB_LOOKUP_NAME_TH_UNIQUE (SYM_TH_UNIQUE_REGISTER64, _thread_db_register64)
+DB_LOOKUP_NAME_TH_UNIQUE (SYM_TH_UNIQUE_REGISTER32, _thread_db_register32)
+DB_LOOKUP_NAME_TH_UNIQUE (SYM_TH_UNIQUE_CONST_THREAD_AREA,
+        _thread_db_const_thread_area)
+DB_LOOKUP_NAME_TH_UNIQUE (SYM_TH_UNIQUE_REGISTER32_THREAD_AREA,
+        _thread_db_register32_thread_area)
+DB_LOOKUP_NAME_TH_UNIQUE (SYM_TH_UNIQUE_REGISTER64_THREAD_AREA,
+        _thread_db_register64_thread_area)
diff --git a/gdb/glibc-dep/nptl_db/fetch-value.c b/gdb/glibc-dep/nptl_db/fetch-value.c
new file mode 100644
index 0000000..07ae14d
--- /dev/null
+++ b/gdb/glibc-dep/nptl_db/fetch-value.c
@@ -0,0 +1,191 @@
+/* Helper routines for libthread_db.
+   Copyright (C) 2003-2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "thread_dbP.h"
+#include <byteswap.h>
+#include <assert.h>
+#include <stdint.h>
+
+
+td_err_e
+_td_check_sizeof (td_thragent_t *ta, uint32_t *sizep, int sizep_name)
+{
+  if (*sizep == 0)
+    {
+      psaddr_t descptr;
+      ps_err_e err = td_lookup (ta->ph, sizep_name, &descptr);
+      if (err == PS_NOSYM)
+	return TD_NOCAPAB;
+      if (err == PS_OK)
+	err = ps_pdread (ta->ph, descptr, sizep, sizeof *sizep);
+      if (err != PS_OK)
+	return TD_ERR;
+      if (*sizep & 0xff000000U)
+	*sizep = bswap_32 (*sizep);
+    }
+  return TD_OK;
+}
+
+td_err_e
+_td_locate_field (td_thragent_t *ta,
+		  db_desc_t desc, int descriptor_name,
+		  psaddr_t idx, psaddr_t *address)
+{
+  uint32_t elemsize;
+
+  if (DB_DESC_SIZE (desc) == 0)
+    {
+      /* Read the information about this field from the inferior.  */
+      psaddr_t descptr;
+      ps_err_e err = td_lookup (ta->ph, descriptor_name, &descptr);
+      if (err == PS_NOSYM)
+	return TD_NOCAPAB;
+      if (err == PS_OK)
+	err = ps_pdread (ta->ph, descptr, desc, DB_SIZEOF_DESC);
+      if (err != PS_OK)
+	return TD_ERR;
+      if (DB_DESC_SIZE (desc) == 0)
+	return TD_DBERR;
+      if (DB_DESC_SIZE (desc) & 0xff000000U)
+	{
+	  /* Byte-swap these words, though we leave the size word
+	     in native order as the handy way to distinguish.  */
+	  DB_DESC_OFFSET (desc) = bswap_32 (DB_DESC_OFFSET (desc));
+	  DB_DESC_NELEM (desc) = bswap_32 (DB_DESC_NELEM (desc));
+	}
+    }
+
+  if (idx != 0 && DB_DESC_NELEM (desc) != 0
+      && idx - (psaddr_t) 0 > DB_DESC_NELEM (desc))
+    /* This is an internal indicator to callers with nonzero IDX
+       that the IDX value is too big.  */
+    return TD_NOAPLIC;
+
+  elemsize = DB_DESC_SIZE (desc);
+  if (elemsize & 0xff000000U)
+    elemsize = bswap_32 (elemsize);
+
+  *address += (int32_t) DB_DESC_OFFSET (desc);
+  *address += (elemsize / 8 * (idx - (psaddr_t) 0));
+  return TD_OK;
+}
+
+td_err_e
+_td_fetch_value (td_thragent_t *ta,
+		 db_desc_t desc, int descriptor_name,
+		 psaddr_t idx, psaddr_t address,
+		 psaddr_t *result)
+{
+  ps_err_e err;
+  td_err_e terr = _td_locate_field (ta, desc, descriptor_name, idx, &address);
+  if (terr != TD_OK)
+    return terr;
+
+  if (DB_DESC_SIZE (desc) == 8 || DB_DESC_SIZE (desc) == bswap_32 (8))
+    {
+      uint8_t value;
+      err = ps_pdread (ta->ph, address, &value, sizeof value);
+      *result = (psaddr_t) 0 + value;
+    }
+  else if (DB_DESC_SIZE (desc) == 32)
+    {
+      uint32_t value;
+      err = ps_pdread (ta->ph, address, &value, sizeof value);
+      *result = (psaddr_t) 0 + value;
+    }
+  else if (DB_DESC_SIZE (desc) == 64)
+    {
+      uint64_t value;
+      if (sizeof (psaddr_t) < 8)
+	return TD_NOCAPAB;
+      err = ps_pdread (ta->ph, address, &value, sizeof value);
+      *result = (psaddr_t) 0 + value;
+    }
+  else if (DB_DESC_SIZE (desc) == bswap_32 (32))
+    {
+      uint32_t value;
+      err = ps_pdread (ta->ph, address, &value, sizeof value);
+      value = bswap_32 (value);
+      *result = (psaddr_t) 0 + value;
+    }
+  else if (DB_DESC_SIZE (desc) == bswap_32 (64))
+    {
+      uint64_t value;
+      if (sizeof (psaddr_t) < 8)
+	return TD_NOCAPAB;
+      err = ps_pdread (ta->ph, address, &value, sizeof value);
+      value = bswap_64 (value);
+      *result = (psaddr_t) 0 + value;
+    }
+  else
+    return TD_DBERR;
+
+  return err == PS_OK ? TD_OK : TD_ERR;
+}
+
+td_err_e
+_td_fetch_value_local (td_thragent_t *ta,
+		       db_desc_t desc, int descriptor_name, psaddr_t idx,
+		       void *address,
+		       psaddr_t *result)
+{
+  td_err_e terr = _td_locate_field (ta, desc, descriptor_name, idx, &address);
+  if (terr != TD_OK)
+    return terr;
+
+  if (DB_DESC_SIZE (desc) == 8 || DB_DESC_SIZE (desc) == bswap_32 (8))
+    {
+      uint8_t value;
+      memcpy (&value, address, sizeof value);
+      *result = (psaddr_t) 0 + value;
+    }
+  else if (DB_DESC_SIZE (desc) == 32)
+    {
+      uint32_t value;
+      memcpy (&value, address, sizeof value);
+      *result = (psaddr_t) 0 + value;
+    }
+  else if (DB_DESC_SIZE (desc) == 64)
+    {
+      uint64_t value;
+      if (sizeof (psaddr_t) < 8)
+	return TD_NOCAPAB;
+      memcpy (&value, address, sizeof value);
+      *result = (psaddr_t) 0 + value;
+    }
+  else if (DB_DESC_SIZE (desc) == bswap_32 (32))
+    {
+      uint32_t value;
+      memcpy (&value, address, sizeof value);
+      value = bswap_32 (value);
+      *result = (psaddr_t) 0 + value;
+    }
+  else if (DB_DESC_SIZE (desc) == bswap_32 (64))
+    {
+      uint64_t value;
+      if (sizeof (psaddr_t) < 8)
+	return TD_NOCAPAB;
+      memcpy (&value, address, sizeof value);
+      value = bswap_64 (value);
+      *result = (psaddr_t) 0 + value;
+    }
+  else
+    return TD_DBERR;
+
+  return TD_OK;
+}
diff --git a/gdb/glibc-dep/nptl_db/structs.def b/gdb/glibc-dep/nptl_db/structs.def
new file mode 100644
index 0000000..5c218a9
--- /dev/null
+++ b/gdb/glibc-dep/nptl_db/structs.def
@@ -0,0 +1,112 @@
+/* List of types and symbols in libpthread examined by libthread_db.
+   Copyright (C) 2003-2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef DB_STRUCT_ARRAY_FIELD
+# define DB_STRUCT_ARRAY_FIELD(type, field) DB_STRUCT_FIELD (type, field)
+# define DB_ARRAY_VARIABLE(name) DB_VARIABLE (name)
+# define STRUCTS_DEF_DEFAULTS 1
+#endif
+
+#ifndef DB_RTLD_VARIABLE
+# define DB_RTLD_VARIABLE(name) DB_VARIABLE (name)
+#endif
+
+#ifndef DB_MAIN_VARIABLE
+# define DB_MAIN_VARIABLE(name) DB_VARIABLE (name)
+#endif
+
+#ifndef DB_RTLD_GLOBAL_FIELD
+#define DB_RTLD_GLOBAL_FIELD(field)     \
+  DB_STRUCT_FIELD (rtld_global, _##field) \
+  DB_MAIN_VARIABLE (_##field)
+#endif /* DB_RTLD_GLOBAL_FIELD */
+
+DB_STRUCT (pthread)
+DB_STRUCT_FIELD (pthread, list)
+DB_STRUCT_FIELD (pthread, report_events)
+DB_STRUCT_FIELD (pthread, tid)
+DB_STRUCT_FIELD (pthread, pid)
+DB_STRUCT_FIELD (pthread, start_routine)
+DB_STRUCT_FIELD (pthread, cancelhandling)
+DB_STRUCT_FIELD (pthread, schedpolicy)
+DB_STRUCT_FIELD (pthread, schedparam_sched_priority)
+DB_STRUCT_FIELD (pthread, specific)
+DB_STRUCT_FIELD (pthread, eventbuf)
+DB_STRUCT_FIELD (pthread, eventbuf_eventmask)
+DB_STRUCT_ARRAY_FIELD (pthread, eventbuf_eventmask_event_bits)
+DB_STRUCT_FIELD (pthread, nextevent)
+
+DB_STRUCT (list_t)
+DB_STRUCT_FIELD (list_t, next)
+DB_STRUCT_FIELD (list_t, prev)
+
+DB_STRUCT (td_thr_events_t)
+DB_STRUCT_ARRAY_FIELD (td_thr_events_t, event_bits)
+
+DB_STRUCT (td_eventbuf_t)
+DB_STRUCT_FIELD (td_eventbuf_t, eventnum)
+DB_STRUCT_FIELD (td_eventbuf_t, eventdata)
+
+DB_SYMBOL (stack_used)
+DB_SYMBOL (__stack_user)
+DB_SYMBOL (nptl_version)
+DB_FUNCTION (__nptl_create_event)
+DB_FUNCTION (__nptl_death_event)
+DB_SYMBOL (__nptl_threads_events)
+DB_VARIABLE (__nptl_nthreads)
+DB_VARIABLE (__nptl_last_event)
+DB_VARIABLE (__nptl_initial_report_events)
+
+DB_ARRAY_VARIABLE (__pthread_keys)
+DB_STRUCT (pthread_key_struct)
+DB_STRUCT_FIELD (pthread_key_struct, seq)
+DB_STRUCT_FIELD (pthread_key_struct, destr)
+
+DB_STRUCT (pthread_key_data)
+DB_STRUCT_FIELD (pthread_key_data, seq)
+DB_STRUCT_FIELD (pthread_key_data, data)
+DB_STRUCT (pthread_key_data_level2)
+DB_STRUCT_ARRAY_FIELD (pthread_key_data_level2, data)
+
+DB_STRUCT_FIELD (link_map, l_tls_modid)
+DB_STRUCT_FIELD (link_map, l_tls_offset)
+
+DB_STRUCT_ARRAY_FIELD (dtv, dtv)
+#define pointer_val pointer.val /* Field of anonymous struct in dtv_t.  */
+DB_STRUCT_FIELD (dtv_t, pointer_val)
+DB_STRUCT_FIELD (dtv_t, counter)
+DB_STRUCT_FIELD (pthread, dtvp)
+
+DB_STRUCT (rtld_global)
+DB_RTLD_VARIABLE (_rtld_global)
+DB_RTLD_GLOBAL_FIELD (dl_tls_dtv_slotinfo_list)
+
+DB_STRUCT (dtv_slotinfo_list)
+DB_STRUCT_FIELD (dtv_slotinfo_list, len)
+DB_STRUCT_FIELD (dtv_slotinfo_list, next)
+DB_STRUCT_ARRAY_FIELD (dtv_slotinfo_list, slotinfo)
+
+DB_STRUCT (dtv_slotinfo)
+DB_STRUCT_FIELD (dtv_slotinfo, gen)
+DB_STRUCT_FIELD (dtv_slotinfo, map)
+
+#ifdef STRUCTS_DEF_DEFAULTS
+# undef DB_STRUCT_ARRAY_FIELD
+# undef DB_ARRAY_VARIABLE
+# undef STRUCTS_DEF_DEFAULTS
+#endif
diff --git a/gdb/glibc-dep/nptl_db/td_symbol_list.c b/gdb/glibc-dep/nptl_db/td_symbol_list.c
new file mode 100644
index 0000000..bd61caa
--- /dev/null
+++ b/gdb/glibc-dep/nptl_db/td_symbol_list.c
@@ -0,0 +1,45 @@
+/* Return list of symbols the library can request.
+   Copyright (C) 2001,2002,2003,2009 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@redhat.com>, 2001.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <assert.h>
+#include <gnu/lib-names.h>
+#include "thread_dbP.h"
+
+
+static const char *symbol_list_arr[] =
+{
+# define DB_LOOKUP_NAME(idx, name)		[idx] = STRINGIFY (name),
+# define DB_LOOKUP_NAME_TH_UNIQUE(idx, name)	[idx] = STRINGIFY (name),
+# include "db-symbols.h"
+# undef	DB_LOOKUP_NAME
+# undef	DB_LOOKUP_NAME_TH_UNIQUE
+
+  [SYM_NUM_MESSAGES] = NULL
+};
+
+ps_err_e
+td_mod_lookup (struct ps_prochandle *ps, const char *mod,
+         int idx, psaddr_t *sym_addr)
+{
+  ps_err_e result;
+  assert (idx >= 0 && idx < SYM_NUM_MESSAGES);
+  result = ps_pglobal_lookup (ps, mod, symbol_list_arr[idx], sym_addr);
+
+  return result;
+}
\ No newline at end of file
diff --git a/gdb/glibc-dep/nptl_db/td_ta_map_lwp2thr.c b/gdb/glibc-dep/nptl_db/td_ta_map_lwp2thr.c
new file mode 100644
index 0000000..60f9574
--- /dev/null
+++ b/gdb/glibc-dep/nptl_db/td_ta_map_lwp2thr.c
@@ -0,0 +1,167 @@
+/* Which thread is running on an LWP?
+   Copyright (C) 2003-2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "thread_dbP.h"
+#include <byteswap.h>
+
+
+td_err_e
+__td_ta_lookup_th_unique (const td_thragent_t *ta_arg,
+        lwpid_t lwpid, td_thrhandle_t *th)
+{
+  td_thragent_t *const ta = (td_thragent_t *) ta_arg;
+  ps_err_e err;
+  td_err_e terr;
+  prgregset_t regs;
+  psaddr_t addr;
+
+  if (ta->ta_howto == ta_howto_unknown)
+    {
+      /* We need to read in from the inferior the instructions what to do.  */
+      psaddr_t howto;
+
+      err = td_lookup (ta->ph, SYM_TH_UNIQUE_CONST_THREAD_AREA, &howto);
+      if (err == PS_OK)
+  {
+    err = ps_pdread (ta->ph, howto,
+         &ta->ta_howto_data.const_thread_area,
+         sizeof ta->ta_howto_data.const_thread_area);
+    if (err != PS_OK)
+      return TD_ERR;
+    ta->ta_howto = ta_howto_const_thread_area;
+    if (ta->ta_howto_data.const_thread_area & 0xff000000U)
+      ta->ta_howto_data.const_thread_area
+        = bswap_32 (ta->ta_howto_data.const_thread_area);
+  }
+      else
+  {
+    switch (sizeof (regs[0]))
+      {
+      case 8:
+        err = td_lookup (ta->ph, SYM_TH_UNIQUE_REGISTER64, &howto);
+        if (err == PS_OK)
+    ta->ta_howto = ta_howto_reg;
+        else if (err == PS_NOSYM)
+    {
+      err = td_lookup (ta->ph,
+           SYM_TH_UNIQUE_REGISTER64_THREAD_AREA,
+           &howto);
+      if (err == PS_OK)
+        ta->ta_howto = ta_howto_reg_thread_area;
+    }
+        break;
+
+      case 4:
+        err = td_lookup (ta->ph, SYM_TH_UNIQUE_REGISTER32, &howto);
+        if (err == PS_OK)
+    ta->ta_howto = ta_howto_reg;
+        else if (err == PS_NOSYM)
+    {
+      err = td_lookup (ta->ph,
+           SYM_TH_UNIQUE_REGISTER32_THREAD_AREA,
+           &howto);
+      if (err == PS_OK)
+        ta->ta_howto = ta_howto_reg_thread_area;
+    }
+        break;
+
+      default:
+        abort ();
+        return TD_DBERR;
+      }
+
+    if (err != PS_OK)
+      return TD_DBERR;
+
+    /* For either of these methods we read in the same descriptor.  */
+    err = ps_pdread (ta->ph, howto,
+         ta->ta_howto_data.reg, DB_SIZEOF_DESC);
+    if (err != PS_OK)
+      return TD_ERR;
+    if (DB_DESC_SIZE (ta->ta_howto_data.reg) == 0)
+      return TD_DBERR;
+    if (DB_DESC_SIZE (ta->ta_howto_data.reg) & 0xff000000U)
+      {
+        /* Byte-swap these words, though we leave the size word
+     in native order as the handy way to distinguish.  */
+        DB_DESC_OFFSET (ta->ta_howto_data.reg)
+    = bswap_32 (DB_DESC_OFFSET (ta->ta_howto_data.reg));
+        DB_DESC_NELEM (ta->ta_howto_data.reg)
+    = bswap_32 (DB_DESC_NELEM (ta->ta_howto_data.reg));
+      }
+  }
+    }
+
+  switch (ta->ta_howto)
+    {
+    default:
+      return TD_DBERR;
+
+    case ta_howto_reg:
+      /* On most machines, we are just looking at a register.  */
+      if (ps_lgetregs (ta->ph, lwpid, regs) != PS_OK)
+  return TD_ERR;
+      terr = _td_fetch_value_local (ta, ta->ta_howto_data.reg, -1,
+            0, regs, &addr);
+      if (terr != TD_OK)
+  return terr;
+
+      /* In this descriptor the nelem word is overloaded as the bias.  */
+      addr += (int32_t) DB_DESC_NELEM (ta->ta_howto_data.reg);
+      th->th_unique = addr;
+      break;
+
+    case ta_howto_const_thread_area:
+      /* Some hosts don't have this call and this case won't be used.  */
+# pragma weak ps_get_thread_area
+      if (&ps_get_thread_area == NULL)
+  return TD_NOCAPAB;
+
+      /* A la x86-64, there is a magic index for get_thread_area.  */
+      if (ps_get_thread_area (ta->ph, lwpid,
+            ta->ta_howto_data.const_thread_area,
+            &th->th_unique) != PS_OK)
+  return TD_ERR;  /* XXX Other error value?  */
+      break;
+
+    case ta_howto_reg_thread_area:
+      if (&ps_get_thread_area == NULL)
+  return TD_NOCAPAB;
+
+      /* A la i386, a register holds the index for get_thread_area.  */
+      if (ps_lgetregs (ta->ph, lwpid, regs) != PS_OK)
+  return TD_ERR;
+      terr = _td_fetch_value_local (ta, ta->ta_howto_data.reg_thread_area,
+            -1, 0, regs, &addr);
+      if (terr != TD_OK)
+  return terr;
+      /* In this descriptor the nelem word is overloaded as scale factor.  */
+      if (ps_get_thread_area
+    (ta->ph, lwpid,
+     ((addr - (psaddr_t) 0)
+      >> DB_DESC_NELEM (ta->ta_howto_data.reg_thread_area)),
+     &th->th_unique) != PS_OK)
+  return TD_ERR;  /* XXX Other error value?  */
+      break;
+    }
+
+  /* Found it.  Now complete the `td_thrhandle_t' object.  */
+  th->th_ta_p = ta;
+
+  return TD_OK;
+}
\ No newline at end of file
diff --git a/gdb/glibc-dep/nptl_db/td_thr_tls_get_addr.c b/gdb/glibc-dep/nptl_db/td_thr_tls_get_addr.c
new file mode 100644
index 0000000..f1630a1
--- /dev/null
+++ b/gdb/glibc-dep/nptl_db/td_thr_tls_get_addr.c
@@ -0,0 +1,42 @@
+/* Get address of thread local variable.
+   Copyright (C) 2002-2015 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+   Contributed by Ulrich Drepper <drepper@cygnus.com>, 2002.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "thread_dbP.h"
+
+
+td_err_e
+gdb_td_thr_tls_get_addr (const td_thrhandle_t *th,
+         psaddr_t map_address, size_t offset, psaddr_t *address)
+{
+  td_err_e err;
+  psaddr_t modid;
+
+  /* Get the TLS module ID from the `struct link_map' in the inferior.  */
+  err = DB_GET_FIELD (modid, th->th_ta_p, map_address, link_map,
+          l_tls_modid, 0);
+  if (err == TD_NOCAPAB)
+    return TD_NOAPLIC;
+  if (err == TD_OK)
+    {
+      err = gdb_td_thr_tlsbase (th, (uintptr_t) modid, address);
+      if (err == TD_OK)
+  *address += offset;
+    }
+  return err;
+}
diff --git a/gdb/glibc-dep/nptl_db/td_thr_tlsbase.c b/gdb/glibc-dep/nptl_db/td_thr_tlsbase.c
new file mode 100644
index 0000000..04e1af7
--- /dev/null
+++ b/gdb/glibc-dep/nptl_db/td_thr_tlsbase.c
@@ -0,0 +1,249 @@
+/* Locate TLS data for a thread.
+   Copyright (C) 2003-2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "thread_dbP.h"
+#include "nat/gdb_thread_db.h"
+#include "tls.h"
+
+/* Get the DTV slotinfo list head entry from the dynamic loader state
+   into *LISTHEAD.  */
+static td_err_e
+dtv_slotinfo_list (td_thragent_t *ta,
+       psaddr_t *listhead)
+{
+  td_err_e err;
+  psaddr_t head;
+
+  if (ta->ta_addr__rtld_global == 0
+      && td_mod_lookup (ta->ph, LD_SO, SYM__rtld_global,
+      &ta->ta_addr__rtld_global) != PS_OK)
+    ta->ta_addr__rtld_global = (void*)-1;
+
+  if (ta->ta_addr__rtld_global != (void*)-1)
+    {
+      err = DB_GET_FIELD (head, ta, ta->ta_addr__rtld_global,
+        rtld_global, _dl_tls_dtv_slotinfo_list, 0);
+      if (err != TD_OK)
+  return err;
+    }
+  else
+    {
+      if (ta->ta_addr__dl_tls_dtv_slotinfo_list == 0
+    && td_mod_lookup (ta->ph, NULL, SYM__dl_tls_dtv_slotinfo_list,
+          &ta->ta_addr__dl_tls_dtv_slotinfo_list) != PS_OK)
+  return TD_ERR;
+
+      err = _td_fetch_value (ta, ta->ta_var__dl_tls_dtv_slotinfo_list,
+           SYM_DESC__dl_tls_dtv_slotinfo_list,
+           0, ta->ta_addr__dl_tls_dtv_slotinfo_list, &head);
+      if (err != TD_OK)
+  return err;
+    }
+
+  *listhead = head;
+  return TD_OK;
+}
+
+/* Get the address of the DTV slotinfo entry for MODID into
+   *DTVSLOTINFO.  */
+static td_err_e
+dtv_slotinfo (td_thragent_t *ta,
+        unsigned long int modid,
+        psaddr_t *dtvslotinfo)
+{
+  td_err_e err;
+  psaddr_t slot, temp;
+  size_t slbase = 0;
+
+  err = dtv_slotinfo_list (ta, &slot);
+  if (err != TD_OK)
+    return err;
+
+  while (slot)
+    {
+      /* Get the number of entries in this list entry's array.  */
+      err = DB_GET_FIELD (temp, ta, slot, dtv_slotinfo_list, len, 0);
+      if (err != TD_OK)
+  return err;
+      size_t len = (uintptr_t)temp;
+
+      /* Did we find the list entry for modid?  */
+      if (modid < slbase + len)
+  break;
+
+      /* We didn't, so get the next list entry.  */
+      slbase += len;
+      err = DB_GET_FIELD (temp, ta, slot, dtv_slotinfo_list,
+        next, 0);
+      if (err != TD_OK)
+  return err;
+      slot = temp;
+    }
+
+  /* We reached the end of the list and found nothing.  */
+  if (!slot)
+    return TD_ERR;
+
+  /* Take the slotinfo for modid from the list entry.  */
+  err = DB_GET_FIELD_ADDRESS (temp, ta, slot, dtv_slotinfo_list,
+            slotinfo, modid - slbase);
+  if (err != TD_OK)
+    return err;
+  slot = temp;
+
+  *dtvslotinfo = slot;
+  return TD_OK;
+}
+
+/* Return in *BASE the base address of the TLS block for MODID within
+   TH.
+
+   It should return success and yield the correct pointer in any
+   circumstance where the TLS block for the module and thread
+   requested has already been initialized.
+
+   It should fail with TD_TLSDEFER only when the thread could not
+   possibly have observed any values in that TLS block.  That way, the
+   debugger can fall back to showing initial values from the PT_TLS
+   segment (and refusing attempts to mutate) for the TD_TLSDEFER case,
+   and never fail to make the values the program will actually see
+   available to the user of the debugger.  */
+td_err_e
+gdb_td_thr_tlsbase (const td_thrhandle_t *th,
+    unsigned long int modid,
+    psaddr_t *base)
+{
+  td_err_e err;
+  psaddr_t dtv, dtvslot, dtvptr, temp;
+  psaddr_t map;
+  size_t modgen;
+
+  if (modid < 1)
+    return TD_NOTLS;
+
+  psaddr_t pd = th->th_unique;
+  if (pd == 0)
+    {
+      /* This is the fake handle for the main thread before libpthread
+   initialization.  We are using 0 for its th_unique because we can't
+   trust that its thread register has been initialized.  But we need
+   a real pointer to have any TLS access work.  In case of dlopen'd
+   libpthread, initialization might not be for quite some time.  So
+   try looking up the thread register now.  Worst case, it's nonzero
+   uninitialized garbage and we get bogus results for TLS access
+   attempted too early.  Tough.  */
+
+      td_thrhandle_t main_th;
+      err = __td_ta_lookup_th_unique (th->th_ta_p, ps_getpid (th->th_ta_p->ph),
+              &main_th);
+      if (err == 0)
+  pd = main_th.th_unique;
+      if (pd == 0)
+  return TD_TLSDEFER;
+    }
+
+  if (strcmp (versbuf,"2.22") >= 0)
+    {
+      err = dtv_slotinfo (th->th_ta_p, modid, &temp);
+      if (err != TD_OK)
+        return err;
+
+      psaddr_t slot;
+      err = DB_GET_STRUCT (slot, th->th_ta_p, temp, dtv_slotinfo);
+      if (err != TD_OK)
+        return err;
+
+      /* Take the link_map from the slotinfo.  */
+      err = DB_GET_FIELD_LOCAL (map, th->th_ta_p, slot, dtv_slotinfo, map, 0);
+      if (err != TD_OK)
+        return err;
+      if (!map)
+        return TD_ERR;
+
+      /* Ok, the modid is good, now find out what DTV generation it
+         requires.  */
+      err = DB_GET_FIELD_LOCAL (temp, th->th_ta_p, slot, dtv_slotinfo, gen, 0);
+      if (err != TD_OK)
+        return err;
+      modgen = (uintptr_t)temp;
+    }
+
+  /* Get the DTV pointer from the thread descriptor.  */
+  err = DB_GET_FIELD (dtv, th->th_ta_p, pd, pthread, dtvp, 0);
+  if (err != TD_OK)
+    return err;
+
+  if (strcmp (versbuf,"2.22") >= 0)
+    {
+      psaddr_t dtvgenloc;
+      /* Get the DTV generation count at dtv[0].counter.  */
+      err = DB_GET_FIELD_ADDRESS (dtvgenloc, th->th_ta_p, dtv, dtv, dtv, 0);
+      if (err != TD_OK)
+        return err;
+      err = DB_GET_FIELD (temp, th->th_ta_p, dtvgenloc, dtv_t, counter, 0);
+      if (err != TD_OK)
+        return err;
+      size_t dtvgen = (uintptr_t)temp;
+
+      /* Is the DTV current enough?  */
+      if (dtvgen < modgen)
+        {
+        try_static_tls:
+          /* If the module uses Static TLS, we're still good.  */
+          err = DB_GET_FIELD (temp, th->th_ta_p, map, link_map, l_tls_offset, 0);
+          if (err != TD_OK)
+      return err;
+          ptrdiff_t tlsoff = (uintptr_t)temp;
+
+          if (tlsoff != FORCED_DYNAMIC_TLS_OFFSET
+        && tlsoff != NO_TLS_OFFSET)
+      {
+        psaddr_t tp = pd;
+
+        if (TLS_TCB_AT_TP == 1)
+            dtvptr = tp - tlsoff;
+        else if (TLS_DTV_AT_TP == 1)
+            dtvptr = tp + tlsoff + TLS_PRE_TCB_SIZE;
+        else
+          return TD_ERR;
+
+        *base = dtvptr;
+        return TD_OK;
+      }
+
+          return TD_TLSDEFER;
+        }
+    }
+  /* Find the corresponding entry in the DTV.  */
+  err = DB_GET_FIELD_ADDRESS (dtvslot, th->th_ta_p, dtv, dtv, dtv, modid);
+  if (err != TD_OK)
+    return err;
+
+  /* Extract the TLS block address from that DTV slot.  */
+  err = DB_GET_FIELD (dtvptr, th->th_ta_p, dtvslot, dtv_t, pointer_val, 0);
+  if (err != TD_OK)
+    return err;
+
+  /* It could be that the memory for this module is not allocated for
+     the given thread.  */
+  if ((uintptr_t) dtvptr & 1)
+    goto try_static_tls;
+
+  *base = dtvptr;
+  return TD_OK;
+}
diff --git a/gdb/glibc-dep/nptl_db/thread_dbP.h b/gdb/glibc-dep/nptl_db/thread_dbP.h
new file mode 100644
index 0000000..b7a934d
--- /dev/null
+++ b/gdb/glibc-dep/nptl_db/thread_dbP.h
@@ -0,0 +1,206 @@
+/* Private header for thread debug library
+   Copyright (C) 2003, 2004, 2007, 2011 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef _THREAD_DBP_H
+#define _THREAD_DBP_H 1
+
+#ifndef HAVE_SYS_PROCFS_H
+#define HAVE_SYS_PROCFS_H
+#endif
+#ifndef HAVE_LWPID_T
+#define HAVE_LWPID_T
+#endif
+#ifndef HAVE_PSADDR_T
+#define HAVE_PSADDR_T
+#endif
+
+#include <stdbool.h>
+#include <stdint.h>
+#include <string.h>
+#include <stdlib.h>
+#include <alloca.h>
+#include <assert.h>
+#include "../config.h"
+#include "gdb_proc_service.h"
+#include <gnu/lib-names.h>
+#ifdef HAVE_THREAD_DB_H
+#include <thread_db.h>
+#else
+#include "nat/glibc_thread_db.h"
+#endif
+
+# define attribute_hidden __attribute__ ((visibility ("hidden")))
+
+char versbuf[5];
+
+/* Indeces for the symbol names.  */
+enum
+  {
+# define DB_STRUCT(type)		SYM_SIZEOF_##type,
+# define DB_STRUCT_FIELD(type, field)	SYM_##type##_FIELD_##field,
+# define DB_SYMBOL(name)		SYM_##name,
+# define DB_FUNCTION(name)		SYM_##name,
+# define DB_VARIABLE(name)		SYM_##name, SYM_DESC_##name,
+# include "structs.def"
+# undef DB_STRUCT
+# undef DB_STRUCT_FIELD
+# undef DB_SYMBOL
+# undef DB_FUNCTION
+# undef DB_VARIABLE
+
+    SYM_TH_UNIQUE_CONST_THREAD_AREA,
+    SYM_TH_UNIQUE_REGISTER64,
+    SYM_TH_UNIQUE_REGISTER32,
+    SYM_TH_UNIQUE_REGISTER64_THREAD_AREA,
+    SYM_TH_UNIQUE_REGISTER32_THREAD_AREA,
+
+    SYM_NUM_MESSAGES
+  };
+
+#define DB_DESC_SIZE(desc)	((desc)[0])
+#define DB_DESC_NELEM(desc)	((desc)[1])
+#define DB_DESC_OFFSET(desc)	((desc)[2])
+#define DB_SIZEOF_DESC		(3 * sizeof (uint32_t))
+#define DB_DEFINE_DESC(name, size, nelem, offset) \
+  const uint32_t name[3] = { (size), (nelem), (offset) }
+typedef uint32_t db_desc_t[3];
+
+typedef struct list_head
+{
+  struct list_head *next;
+  struct list_head *prev;
+} list_t;
+
+/* Handle for a process.  This type is opaque.  */
+struct td_thragent
+{
+  /* Chain on the list of all agent structures.  */
+  list_t list;
+
+  /* Delivered by the debugger and we have to pass it back in the
+     proc callbacks.  */
+  struct ps_prochandle *ph;
+
+  /* Cached values read from the inferior.  */
+# define DB_STRUCT(type) \
+  uint32_t ta_sizeof_##type;
+# define DB_STRUCT_FIELD(type, field) \
+  db_desc_t ta_field_##type##_##field;
+# define DB_SYMBOL(name) \
+  psaddr_t ta_addr_##name;
+# define DB_FUNCTION(name) \
+  psaddr_t ta_addr_##name;
+# define DB_VARIABLE(name) \
+  psaddr_t ta_addr_##name; \
+  db_desc_t ta_var_##name;
+# include "structs.def"
+# undef DB_STRUCT
+# undef DB_STRUCT_FIELD
+# undef DB_FUNCTION
+# undef DB_SYMBOL
+# undef DB_VARIABLE
+
+  /* The method of locating a thread's th_unique value.  */
+  enum
+    {
+      ta_howto_unknown,
+      ta_howto_reg,
+      ta_howto_reg_thread_area,
+      ta_howto_const_thread_area
+    } ta_howto;
+  union
+  {
+    uint32_t const_thread_area;	/* Constant argument to ps_get_thread_area.  */
+    /* These are as if the descriptor of the field in prregset_t,
+       but DB_DESC_NELEM is overloaded as follows: */
+    db_desc_t reg;		/* Signed bias applied to register value.  */
+    db_desc_t reg_thread_area;	/* Bits to scale down register value.  */
+  } ta_howto_data;
+};
+
+/* Internal wrappers around ps_pglobal_lookup.  */
+extern ps_err_e td_mod_lookup (struct ps_prochandle *ps, const char *modname,
+             int idx, psaddr_t *sym_addr) attribute_hidden;
+#define td_lookup(ps, idx, sym_addr) \
+  td_mod_lookup ((ps), LIBPTHREAD_SO, (idx), (sym_addr))
+
+/* Store in psaddr_t VAR the address of inferior's symbol NAME.  */
+#define DB_GET_SYMBOL(var, ta, name)					      \
+  (((ta)->ta_addr_##name == 0						      \
+    && td_lookup ((ta)->ph, SYM_##name, &(ta)->ta_addr_##name) != PS_OK)      \
+   ? TD_ERR : ((var) = (ta)->ta_addr_##name, TD_OK))
+
+/* Store in psaddr_t VAR the value of ((TYPE) PTR)->FIELD[IDX] in the inferior.
+   A target field smaller than psaddr_t is zero-extended.  */
+#define DB_GET_FIELD(var, ta, ptr, type, field, idx) \
+  _td_fetch_value ((ta), (ta)->ta_field_##type##_##field, \
+		   SYM_##type##_FIELD_##field, \
+		   (psaddr_t) 0 + (idx), (ptr), &(var))
+
+#define DB_GET_FIELD_ADDRESS(var, ta, ptr, type, field, idx) \
+  ((var) = (ptr), _td_locate_field ((ta), (ta)->ta_field_##type##_##field, \
+				    SYM_##type##_FIELD_##field, \
+				    (psaddr_t) 0 + (idx), &(var)))
+
+extern td_err_e _td_locate_field (td_thragent_t *ta,
+				  db_desc_t desc, int descriptor_name,
+				  psaddr_t idx,
+				  psaddr_t *address) attribute_hidden;
+
+
+/* Like DB_GET_FIELD, but PTR is a local pointer to a structure that
+   has already been copied in from the inferior.  */
+#define DB_GET_FIELD_LOCAL(var, ta, ptr, type, field, idx) \
+  _td_fetch_value_local ((ta), (ta)->ta_field_##type##_##field, \
+		         SYM_##type##_FIELD_##field, \
+			 (psaddr_t) 0 + (idx), (ptr), &(var))
+
+/* Helper functions for those.  */
+extern td_err_e _td_fetch_value (td_thragent_t *ta,
+				 db_desc_t field, int descriptor_name,
+				 psaddr_t idx, psaddr_t address,
+				 psaddr_t *result) attribute_hidden;
+extern td_err_e _td_fetch_value_local (td_thragent_t *ta,
+				       db_desc_t field,
+				       int descriptor_name,
+				       psaddr_t idx, void *address,
+				       psaddr_t *result) attribute_hidden;
+
+/* Helper functions for those.  */
+#define DB_GET_STRUCT(var, ta, ptr, type)				      \
+  ({ td_err_e _err = TD_OK;						      \
+     if ((ta)->ta_sizeof_##type == 0)					      \
+       _err = _td_check_sizeof ((ta), &(ta)->ta_sizeof_##type,		      \
+				      SYM_SIZEOF_##type);		      \
+     if (_err == TD_OK)							      \
+       _err = ps_pdread ((ta)->ph, (ptr),				      \
+			 (var) = alloca ((ta)->ta_sizeof_##type),	      \
+			 (ta)->ta_sizeof_##type)			      \
+	 == PS_OK ? TD_OK : TD_ERR;					      \
+     else								      \
+       (var) = NULL; 							      \
+     _err;								      \
+  })
+
+extern td_err_e _td_check_sizeof (td_thragent_t *ta, uint32_t *sizep,
+				  int sizep_name) attribute_hidden;
+
+extern td_err_e __td_ta_lookup_th_unique (const td_thragent_t *ta,
+					  lwpid_t lwpid, td_thrhandle_t *th);
+
+#endif /* thread_dbP.h */
diff --git a/gdb/glibc-dep/nptl_db/tls.h b/gdb/glibc-dep/nptl_db/tls.h
new file mode 100644
index 0000000..abe2923
--- /dev/null
+++ b/gdb/glibc-dep/nptl_db/tls.h
@@ -0,0 +1,37 @@
+/* Private header for thread debug library
+   Copyright (C) 2003, 2004, 2007, 2011 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#ifndef __TLS_H__
+#define __TLS_H__
+
+unsigned tls_tcb_at_tp;
+unsigned tls_dtv_at_tp;
+int forced_dynamic_tls_offset;
+int no_tls_offset;
+unsigned tcb_alignment;
+
+#define TLS_DTV_AT_TP tls_dtv_at_tp
+#define TLS_TCB_AT_TP tls_tcb_at_tp
+#define TCB_ALIGNMENT tcb_alignment
+
+#define TLS_PRE_TCB_SIZE th->th_ta_p->ta_sizeof_pthread + TCB_ALIGNMENT
+
+#define NO_TLS_OFFSET no_tls_offset
+#define FORCED_DYNAMIC_TLS_OFFSET forced_dynamic_tls_offset
+
+#endif
\ No newline at end of file
diff --git a/gdb/gregset.h b/gdb/gregset.h
index 3101edc..03b6792 100644
--- a/gdb/gregset.h
+++ b/gdb/gregset.h
@@ -24,11 +24,11 @@
 #endif

 #ifndef GDB_GREGSET_T
-#define GDB_GREGSET_T gregset_t
+#define GDB_GREGSET_T elf_gregset_t
 #endif

 #ifndef GDB_FPREGSET_T
-#define GDB_FPREGSET_T fpregset_t
+#define GDB_FPREGSET_T elf_fpregset_t
 #endif

 typedef GDB_GREGSET_T gdb_gregset_t;
diff --git a/gdb/linux-thread-db.c b/gdb/linux-thread-db.c
index 86254f8..b622ddb 100644
--- a/gdb/linux-thread-db.c
+++ b/gdb/linux-thread-db.c
@@ -19,8 +19,10 @@

 #include "defs.h"
 #include <dlfcn.h>
+EXTERN_C_PUSH
 #include "gdb_proc_service.h"
 #include "nat/gdb_thread_db.h"
+EXTERN_C_POP
 #include "gdb_vecs.h"
 #include "bfd.h"
 #include "command.h"
@@ -46,6 +48,7 @@
 #include <ctype.h>
 #include "nat/linux-namespaces.h"
 #include <algorithm>
+#include "bfd.h"

 /* GNU/Linux libthread_db support.

@@ -536,6 +539,18 @@ try_thread_db_load_1 (struct thread_db_info *info)
   info->proc_handle.ptid = inferior_ptid;

   /* Now attempt to open a connection to the thread library.  */
+#ifdef CROSS_GDB
+  const struct bfd_arch_info *bfdarch = gdbarch_bfd_arch_info (target_gdbarch ());
+  unsigned arch = bfdarch->arch;
+
+  /* If it's host we want to keep old way of counting tls address. */
+  if (native_check (arch) != 0)
+    {
+       /* gdb_td_ta_new has similar behavior as td_ta_new, so if any
+          occurs same error will be catched in td_ta_new */
+       gdb_td_ta_new (&info->proc_handle, &info->thread_agent);
+    }
+#endif
   err = info->td_ta_new_p (&info->proc_handle, &info->thread_agent);
   if (err != TD_OK)
     {
@@ -564,8 +579,22 @@ try_thread_db_load_1 (struct thread_db_info *info)
   CHK (TDB_VERBOSE_DLSYM (info, td_thr_get_info));

   /* These are not essential.  */
+#ifdef CROSS_GDB
+  if (native_check (arch) != 0)
+    {
+      info->td_thr_tls_get_addr_p = gdb_td_thr_tls_get_addr;
+      info->td_thr_tlsbase_p = gdb_td_thr_tlsbase;
+    }
+  else
+    {
+      /* If it's host we want to keep old way of counting tls address. */
+      TDB_DLSYM (info, td_thr_tls_get_addr);
+      TDB_DLSYM (info, td_thr_tlsbase);
+    }
+#else
   TDB_DLSYM (info, td_thr_tls_get_addr);
   TDB_DLSYM (info, td_thr_tlsbase);
+#endif

   /* It's best to avoid td_ta_thr_iter if possible.  That walks data
      structures in the inferior's address space that may be corrupted,
diff --git a/gdb/nat/gdb_thread_db.h b/gdb/nat/gdb_thread_db.h
index a577d49..a8fe2df 100644
--- a/gdb/nat/gdb_thread_db.h
+++ b/gdb/nat/gdb_thread_db.h
@@ -28,6 +28,10 @@
 #define LIBTHREAD_DB_SO "libthread_db.so.1"
 #endif

+#ifndef LD_SO
+#define LD_SO "ld.so.1"
+#endif
+
 #ifndef LIBTHREAD_DB_SEARCH_PATH
 /* $sdir appears before $pdir for some minimal security protection:
    we trust the system libthread_db.so a bit more than some random
@@ -72,4 +76,15 @@ typedef td_err_e (td_thr_tlsbase_ftype) (const td_thrhandle_t *th,
 typedef const char ** (td_symbol_list_ftype) (void);
 typedef td_err_e (td_ta_delete_ftype) (td_thragent_t *);

+
+extern td_err_e gdb_td_ta_new (struct ps_prochandle *__ps, td_thragent_t **__ta);
+
+extern td_err_e gdb_td_thr_tlsbase (const td_thrhandle_t *th,
+         unsigned long int modid,
+         psaddr_t *base);
+extern td_err_e gdb_td_thr_tls_get_addr (const td_thrhandle_t *th,
+         psaddr_t map_address, size_t offset, psaddr_t *address);
+
+extern int native_check (unsigned bfd_arch);
+
 #endif /* GDB_THREAD_DB_H */
--
1.9.1


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]