[6/7] Arm: Use read_description funcs in gdbserver

Message ID 20190705094525.51536-7-alan.hayward@arm.com
State Superseded
Headers show
Series
  • Arm: Use feature target descriptions
Related show

Commit Message

Alan Hayward July 5, 2019, 9:45 a.m.
Switch gdbserver over to using feature target descriptions.

Add a function for determining the type of a given target description,
and use where required.

2019-07-05  Alan Hayward  <alan.hayward@arm.com>

	* configure.srv: Add new files. Remove xml generated files.
	* linux-aarch32-low.c (initialize_low_arch_aarch32): Don't init
	registers.
	* linux-aarch32-low.h (tdesc_arm_with_neon): Remove.
	* linux-aarch32-tdesc.c: New file.
	* linux-aarch32-tdesc.h: New file.
	* linux-aarch64-low.c (aarch64_arch_setup): Call aarch32_linux_read_description.
	* linux-arm-low.c (init_registers_arm, tdesc_arm)
	(init_registers_arm_with_iwmmxt, tdesc_arm_with_iwmmxt)
	(init_registers_arm_with_vfpv2, tdesc_arm_with_vfpv2)
	(init_registers_arm_with_vfpv3, tdesc_arm_with_vfpv3): Remove.
	(arm_fill_wmmxregset, arm_store_wmmxregset, arm_fill_vfpregset)
	(arm_store_vfpregset): Call arm_linux_get_tdesc_fp_type.
	(arm_read_description): Call arm_linux_read_description.
	(initialize_low_arch): Don't init registers.
	* linux-arm-tdesc.c: New file.
	* linux-arm-tdesc.h: New file.
---
 gdb/gdbserver/configure.srv         | 14 +++---
 gdb/gdbserver/linux-aarch32-low.c   |  2 -
 gdb/gdbserver/linux-aarch32-low.h   |  2 -
 gdb/gdbserver/linux-aarch32-tdesc.c | 46 +++++++++++++++++
 gdb/gdbserver/linux-aarch32-tdesc.h | 29 +++++++++++
 gdb/gdbserver/linux-aarch64-low.c   |  3 +-
 gdb/gdbserver/linux-arm-low.c       | 77 ++++++++++++++---------------
 gdb/gdbserver/linux-arm-tdesc.c     | 62 +++++++++++++++++++++++
 gdb/gdbserver/linux-arm-tdesc.h     | 29 +++++++++++
 9 files changed, 211 insertions(+), 53 deletions(-)
 create mode 100644 gdb/gdbserver/linux-aarch32-tdesc.c
 create mode 100644 gdb/gdbserver/linux-aarch32-tdesc.h
 create mode 100644 gdb/gdbserver/linux-arm-tdesc.c
 create mode 100644 gdb/gdbserver/linux-arm-tdesc.h

-- 
2.20.1 (Apple Git-117)

Comments

Simon Marchi July 10, 2019, 4:04 a.m. | #1
> diff --git a/gdb/gdbserver/linux-aarch32-tdesc.c b/gdb/gdbserver/linux-aarch32-tdesc.c

> new file mode 100644

> index 0000000000..6f0e8c9aa9

> --- /dev/null

> +++ b/gdb/gdbserver/linux-aarch32-tdesc.c

> @@ -0,0 +1,46 @@

> +/* Copyright (C) 2019 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 "server.h"

> +#include "tdesc.h"

> +#include "arch/aarch32.h"

> +#include <inttypes.h>

> +

> +struct target_desc *tdesc_aarch32;


static

> diff --git a/gdb/gdbserver/linux-arm-tdesc.c b/gdb/gdbserver/linux-arm-tdesc.c

> new file mode 100644

> index 0000000000..fa54e48592

> --- /dev/null

> +++ b/gdb/gdbserver/linux-arm-tdesc.c

> @@ -0,0 +1,62 @@

> +/* Copyright (C) 2019 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 "server.h"

> +#include "tdesc.h"

> +#include "arch/arm.h"

> +#include <inttypes.h>

> +

> +/* All possible Arm target descriptors.  */

> +struct target_desc *tdesc_arm_list[ARM_FP_TYPE_INVALID];


static

> +

> +/* See linux-arm-tdesc.h.  */

> +

> +const target_desc *

> +arm_linux_read_description (arm_fp_type fp_type)

> +{

> +  struct target_desc *tdesc = tdesc_arm_list[fp_type];

> +

> +  if (tdesc == nullptr)

> +    {

> +      tdesc = arm_create_target_description (fp_type);

> +

> +      static const char *expedite_regs[] = { "r11", "sp", "pc", 0 };

> +      init_target_desc (tdesc, expedite_regs);

> +

> +      tdesc_arm_list[fp_type] = tdesc;

> +    }

> +

> +  return tdesc;

> +}

> +

> +/* See linux-arm-tdesc.h.  */

> +

> +arm_fp_type arm_linux_get_tdesc_fp_type (const target_desc *tdesc)


Return type on its own line.

> +{

> +  if (tdesc == nullptr)

> +    return ARM_FP_TYPE_INVALID;


Can this (tdesc == nullptr) actually happen?  If you expect it's not possible,
don't hesitate to use a gdb_assert instead.  It helps catch bugs and acts as
some kind of self-documentation of the allowed values.

> +

> +  /* Many of the tdesc_arm_list entries may not have been initialised yet.  This

> +     is ok, because tdesc must be one of the initialised ones.  */

> +  for (int i = ARM_FP_TYPE_VFPV2; i < ARM_FP_TYPE_INVALID; i++)


Is it intended here that you skip ARM_FP_TYPE_NONE?  Why?

Simon
Alan Hayward July 10, 2019, 3:44 p.m. | #2
> On 10 Jul 2019, at 05:04, Simon Marchi <simark@simark.ca> wrote:

> 

>> diff --git a/gdb/gdbserver/linux-aarch32-tdesc.c b/gdb/gdbserver/linux-aarch32-tdesc.c

>> new file mode 100644

>> index 0000000000..6f0e8c9aa9

>> --- /dev/null

>> +++ b/gdb/gdbserver/linux-aarch32-tdesc.c

>> @@ -0,0 +1,46 @@

>> +/* Copyright (C) 2019 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 "server.h"

>> +#include "tdesc.h"

>> +#include "arch/aarch32.h"

>> +#include <inttypes.h>

>> +

>> +struct target_desc *tdesc_aarch32;

> 

> static


Done.

> 

>> diff --git a/gdb/gdbserver/linux-arm-tdesc.c b/gdb/gdbserver/linux-arm-tdesc.c

>> new file mode 100644

>> index 0000000000..fa54e48592

>> --- /dev/null

>> +++ b/gdb/gdbserver/linux-arm-tdesc.c

>> @@ -0,0 +1,62 @@

>> +/* Copyright (C) 2019 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 "server.h"

>> +#include "tdesc.h"

>> +#include "arch/arm.h"

>> +#include <inttypes.h>

>> +

>> +/* All possible Arm target descriptors.  */

>> +struct target_desc *tdesc_arm_list[ARM_FP_TYPE_INVALID];

> 

> static


Done.

> 

>> +

>> +/* See linux-arm-tdesc.h.  */

>> +

>> +const target_desc *

>> +arm_linux_read_description (arm_fp_type fp_type)

>> +{

>> +  struct target_desc *tdesc = tdesc_arm_list[fp_type];

>> +

>> +  if (tdesc == nullptr)

>> +    {

>> +      tdesc = arm_create_target_description (fp_type);

>> +

>> +      static const char *expedite_regs[] = { "r11", "sp", "pc", 0 };

>> +      init_target_desc (tdesc, expedite_regs);

>> +

>> +      tdesc_arm_list[fp_type] = tdesc;

>> +    }

>> +

>> +  return tdesc;

>> +}

>> +

>> +/* See linux-arm-tdesc.h.  */

>> +

>> +arm_fp_type arm_linux_get_tdesc_fp_type (const target_desc *tdesc)

> 

> Return type on its own line.


Done.

> 

>> +{

>> +  if (tdesc == nullptr)

>> +    return ARM_FP_TYPE_INVALID;

> 

> Can this (tdesc == nullptr) actually happen?  If you expect it's not possible,

> don't hesitate to use a gdb_assert instead.  It helps catch bugs and acts as

> some kind of self-documentation of the allowed values.


It would mean that regcache->tdesc was null, which as far as I can tell is not
possible. There are no fails when testing either.
I’ll switch to gdb_assert.

> 

>> +

>> +  /* Many of the tdesc_arm_list entries may not have been initialised yet.  This

>> +     is ok, because tdesc must be one of the initialised ones.  */

>> +  for (int i = ARM_FP_TYPE_VFPV2; i < ARM_FP_TYPE_INVALID; i++)

> 

> Is it intended here that you skip ARM_FP_TYPE_NONE?  Why?


My mistake. An earlier version didn’t have ARM_FP_TYPE_NONE, and I missed this.
Fixed to start with ARM_FP_TYPE_NONE.


> 

> Simon

>

Patch

diff --git a/gdb/gdbserver/configure.srv b/gdb/gdbserver/configure.srv
index c20177ef18..097dc4e9db 100644
--- a/gdb/gdbserver/configure.srv
+++ b/gdb/gdbserver/configure.srv
@@ -33,9 +33,10 @@  srv_linux_obj="linux-low.o linux-osdata.o linux-procfs.o linux-ptrace.o linux-wa
 # Input is taken from the "${target}" variable.
 
 case "${target}" in
-  aarch64*-*-linux*)	srv_regobj="arm-with-neon.o"
-			srv_tgtobj="linux-aarch64-low.o aarch64-linux-hw-point.o"
+  aarch64*-*-linux*)	srv_tgtobj="linux-aarch64-low.o aarch64-linux-hw-point.o"
 			srv_tgtobj="$srv_tgtobj linux-aarch32-low.o"
+			srv_tgtobj="$srv_tgtobj linux-aarch32-tdesc.o"
+			srv_tgtobj="${srv_tgtobj} arch/aarch32.o"
 			srv_tgtobj="${srv_tgtobj} arch/arm.o"
 			srv_tgtobj="$srv_tgtobj aarch64-linux.o"
 			srv_tgtobj="$srv_tgtobj arch/aarch64-insn.o"
@@ -49,12 +50,11 @@  case "${target}" in
 			ipa_obj="${ipa_obj} linux-aarch64-tdesc-ipa.o"
 			ipa_obj="${ipa_obj} arch/aarch64-ipa.o"
 			;;
-  arm*-*-linux*)	srv_regobj="reg-arm.o arm-with-iwmmxt.o"
-			srv_regobj="${srv_regobj} arm-with-vfpv2.o"
-			srv_regobj="${srv_regobj} arm-with-vfpv3.o"
-			srv_regobj="${srv_regobj} arm-with-neon.o"
-			srv_tgtobj="$srv_linux_obj linux-arm-low.o"
+  arm*-*-linux*)	srv_tgtobj="$srv_linux_obj linux-arm-low.o"
+			srv_tgtobj="$srv_tgtobj linux-arm-tdesc.o"
 			srv_tgtobj="$srv_tgtobj linux-aarch32-low.o"
+			srv_tgtobj="$srv_tgtobj linux-aarch32-tdesc.o"
+			srv_tgtobj="${srv_tgtobj} arch/aarch32.o"
 			srv_tgtobj="${srv_tgtobj} arch/arm.o"
 			srv_tgtobj="${srv_tgtobj} arch/arm-linux.o"
 			srv_tgtobj="${srv_tgtobj} arch/arm-get-next-pcs.o"
diff --git a/gdb/gdbserver/linux-aarch32-low.c b/gdb/gdbserver/linux-aarch32-low.c
index a932373518..f1f2ae02a4 100644
--- a/gdb/gdbserver/linux-aarch32-low.c
+++ b/gdb/gdbserver/linux-aarch32-low.c
@@ -299,7 +299,5 @@  arm_breakpoint_kind_from_current_state (CORE_ADDR *pcptr)
 void
 initialize_low_arch_aarch32 (void)
 {
-  init_registers_arm_with_neon ();
-
   initialize_regsets_info (&aarch32_regsets_info);
 }
diff --git a/gdb/gdbserver/linux-aarch32-low.h b/gdb/gdbserver/linux-aarch32-low.h
index 44e626c719..3078fca35e 100644
--- a/gdb/gdbserver/linux-aarch32-low.h
+++ b/gdb/gdbserver/linux-aarch32-low.h
@@ -36,6 +36,4 @@  void initialize_low_arch_aarch32 (void);
 void init_registers_arm_with_neon (void);
 int arm_is_thumb_mode (void);
 
-extern const struct target_desc *tdesc_arm_with_neon;
-
 #endif /* GDBSERVER_LINUX_AARCH32_LOW_H */
diff --git a/gdb/gdbserver/linux-aarch32-tdesc.c b/gdb/gdbserver/linux-aarch32-tdesc.c
new file mode 100644
index 0000000000..6f0e8c9aa9
--- /dev/null
+++ b/gdb/gdbserver/linux-aarch32-tdesc.c
@@ -0,0 +1,46 @@ 
+/* Copyright (C) 2019 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 "server.h"
+#include "tdesc.h"
+#include "arch/aarch32.h"
+#include <inttypes.h>
+
+struct target_desc *tdesc_aarch32;
+
+/* See linux-aarch32-tdesc.h.  */
+
+const target_desc *
+aarch32_linux_read_description ()
+{
+  if (tdesc_aarch32 == nullptr)
+    {
+      tdesc_aarch32 = aarch32_create_target_description ();
+
+      static const char *expedite_regs[] = { "r11", "sp", "pc", 0 };
+      init_target_desc (tdesc_aarch32, expedite_regs);
+    }
+  return tdesc_aarch32;
+}
+
+/* See linux-aarch32-tdesc.h.  */
+
+bool
+is_aarch32_linux_description (const target_desc *tdesc)
+{
+  return tdesc != nullptr && tdesc == tdesc_aarch32;
+}
diff --git a/gdb/gdbserver/linux-aarch32-tdesc.h b/gdb/gdbserver/linux-aarch32-tdesc.h
new file mode 100644
index 0000000000..8887cbfdf4
--- /dev/null
+++ b/gdb/gdbserver/linux-aarch32-tdesc.h
@@ -0,0 +1,29 @@ 
+/* Copyright (C) 2019 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/>.  */
+
+#ifndef GDBSERVER_LINUX_AARCH32_TDESC_H
+#define GDBSERVER_LINUX_AARCH32_TDESC_H
+
+/* Return the AArch32 target description.  */
+
+const target_desc * aarch32_linux_read_description ();
+
+/* Return true if TDESC is the AArch32 target description.  */
+
+bool is_aarch32_linux_description (const target_desc *tdesc);
+
+#endif /* linux-aarch32-tdesc.h.  */
diff --git a/gdb/gdbserver/linux-aarch64-low.c b/gdb/gdbserver/linux-aarch64-low.c
index 5aea5de372..ab2f40ea98 100644
--- a/gdb/gdbserver/linux-aarch64-low.c
+++ b/gdb/gdbserver/linux-aarch64-low.c
@@ -39,6 +39,7 @@ 
 
 #include "gdb_proc_service.h"
 #include "arch/aarch64.h"
+#include "linux-aarch32-tdesc.h"
 #include "linux-aarch64-tdesc.h"
 #include "nat/aarch64-sve-linux-ptrace.h"
 #include "tdesc.h"
@@ -527,7 +528,7 @@  aarch64_arch_setup (void)
       current_process ()->tdesc = aarch64_linux_read_description (vq, pauth_p);
     }
   else
-    current_process ()->tdesc = tdesc_arm_with_neon;
+    current_process ()->tdesc = aarch32_linux_read_description ();
 
   aarch64_linux_get_debug_reg_capacity (lwpid_of (current_thread));
 }
diff --git a/gdb/gdbserver/linux-arm-low.c b/gdb/gdbserver/linux-arm-low.c
index 7d6c9d9dd9..0e30af3562 100644
--- a/gdb/gdbserver/linux-arm-low.c
+++ b/gdb/gdbserver/linux-arm-low.c
@@ -22,6 +22,8 @@ 
 #include "arch/arm-linux.h"
 #include "arch/arm-get-next-pcs.h"
 #include "linux-aarch32-low.h"
+#include "linux-aarch32-tdesc.h"
+#include "linux-arm-tdesc.h"
 
 #include <sys/uio.h>
 /* Don't include elf.h if linux/elf.h got included by gdb_proc_service.h.
@@ -33,19 +35,6 @@ 
 #include <signal.h>
 #include <sys/syscall.h>
 
-/* Defined in auto-generated files.  */
-void init_registers_arm (void);
-extern const struct target_desc *tdesc_arm;
-
-void init_registers_arm_with_iwmmxt (void);
-extern const struct target_desc *tdesc_arm_with_iwmmxt;
-
-void init_registers_arm_with_vfpv2 (void);
-extern const struct target_desc *tdesc_arm_with_vfpv2;
-
-void init_registers_arm_with_vfpv3 (void);
-extern const struct target_desc *tdesc_arm_with_vfpv3;
-
 #ifndef PTRACE_GET_THREAD_AREA
 #define PTRACE_GET_THREAD_AREA 22
 #endif
@@ -175,7 +164,7 @@  arm_cannot_fetch_register (int regno)
 static void
 arm_fill_wmmxregset (struct regcache *regcache, void *buf)
 {
-  if (regcache->tdesc != tdesc_arm_with_iwmmxt)
+  if (arm_linux_get_tdesc_fp_type (regcache->tdesc) != ARM_FP_TYPE_IWMMXT)
     return;
 
   for (int i = 0; i < 16; i++)
@@ -190,7 +179,7 @@  arm_fill_wmmxregset (struct regcache *regcache, void *buf)
 static void
 arm_store_wmmxregset (struct regcache *regcache, const void *buf)
 {
-  if (regcache->tdesc != tdesc_arm_with_iwmmxt)
+  if (arm_linux_get_tdesc_fp_type (regcache->tdesc) != ARM_FP_TYPE_IWMMXT)
     return;
 
   for (int i = 0; i < 16; i++)
@@ -207,13 +196,19 @@  arm_fill_vfpregset (struct regcache *regcache, void *buf)
 {
   int num;
 
-  if (regcache->tdesc == tdesc_arm_with_neon
-      || regcache->tdesc == tdesc_arm_with_vfpv3)
+  if (is_aarch32_linux_description (regcache->tdesc))
     num = 32;
-  else if (regcache->tdesc == tdesc_arm_with_vfpv2)
-    num = 16;
   else
-    return;
+    {
+      arm_fp_type fp_type = arm_linux_get_tdesc_fp_type (regcache->tdesc);
+
+      if (fp_type == ARM_FP_TYPE_VFPV3)
+	num = 32;
+      else if (fp_type == ARM_FP_TYPE_VFPV2)
+	num = 16;
+      else
+	return;
+    }
 
   arm_fill_vfpregset_num (regcache, buf, num);
 }
@@ -230,13 +225,19 @@  arm_store_vfpregset (struct regcache *regcache, const void *buf)
 {
   int num;
 
-  if (regcache->tdesc == tdesc_arm_with_neon
-      || regcache->tdesc == tdesc_arm_with_vfpv3)
+  if (is_aarch32_linux_description (regcache->tdesc))
     num = 32;
-  else if (regcache->tdesc == tdesc_arm_with_vfpv2)
-    num = 16;
   else
-    return;
+    {
+      arm_fp_type fp_type = arm_linux_get_tdesc_fp_type (regcache->tdesc);
+
+      if (fp_type == ARM_FP_TYPE_VFPV3)
+	num = 32;
+      else if (fp_type == ARM_FP_TYPE_VFPV2)
+	num = 16;
+      else
+	return;
+    }
 
   arm_store_vfpregset_num (regcache, buf, num);
 }
@@ -849,7 +850,7 @@  arm_read_description (void)
   unsigned long arm_hwcap = linux_get_hwcap (4);
 
   if (arm_hwcap & HWCAP_IWMMXT)
-    return tdesc_arm_with_iwmmxt;
+    return arm_linux_read_description (ARM_FP_TYPE_IWMMXT);
 
   if (arm_hwcap & HWCAP_VFP)
     {
@@ -859,21 +860,21 @@  arm_read_description (void)
       errno = 0;
       char *buf = (char *) alloca (ARM_VFP3_REGS_SIZE);
       if (ptrace (PTRACE_GETVFPREGS, pid, 0, buf) < 0 && errno == EIO)
-	return tdesc_arm;
+	return arm_linux_read_description (ARM_FP_TYPE_NONE);
 
       /* NEON implies either no VFP, or VFPv3-D32.  We only support
 	 it with VFP.  */
       if (arm_hwcap & HWCAP_NEON)
-	return tdesc_arm_with_neon;
+	return aarch32_linux_read_description ();
       else if ((arm_hwcap & (HWCAP_VFPv3 | HWCAP_VFPv3D16)) == HWCAP_VFPv3)
-	return tdesc_arm_with_vfpv3;
+	return arm_linux_read_description (ARM_FP_TYPE_VFPV3);
       else
-	return tdesc_arm_with_vfpv2;
+	return arm_linux_read_description (ARM_FP_TYPE_VFPV2);
     }
 
   /* The default configuration uses legacy FPA registers, probably
      simulated.  */
-  return tdesc_arm;
+  return arm_linux_read_description (ARM_FP_TYPE_NONE);
 }
 
 static void
@@ -997,10 +998,11 @@  arm_regs_info (void)
   const struct target_desc *tdesc = current_process ()->tdesc;
 
   if (have_ptrace_getregset == 1
-      && (tdesc == tdesc_arm_with_neon || tdesc == tdesc_arm_with_vfpv3))
+      && (is_aarch32_linux_description (tdesc)
+	  || arm_linux_get_tdesc_fp_type (tdesc) == ARM_FP_TYPE_VFPV3))
     return &regs_info_aarch32;
-  else
-    return &regs_info_arm;
+
+  return &regs_info_arm;
 }
 
 struct linux_target_ops the_low_target = {
@@ -1045,13 +1047,6 @@  struct linux_target_ops the_low_target = {
 void
 initialize_low_arch (void)
 {
-  /* Initialize the Linux target descriptions.  */
-  init_registers_arm ();
-  init_registers_arm_with_iwmmxt ();
-  init_registers_arm_with_vfpv2 ();
-  init_registers_arm_with_vfpv3 ();
-
   initialize_low_arch_aarch32 ();
-
   initialize_regsets_info (&arm_regsets_info);
 }
diff --git a/gdb/gdbserver/linux-arm-tdesc.c b/gdb/gdbserver/linux-arm-tdesc.c
new file mode 100644
index 0000000000..fa54e48592
--- /dev/null
+++ b/gdb/gdbserver/linux-arm-tdesc.c
@@ -0,0 +1,62 @@ 
+/* Copyright (C) 2019 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 "server.h"
+#include "tdesc.h"
+#include "arch/arm.h"
+#include <inttypes.h>
+
+/* All possible Arm target descriptors.  */
+struct target_desc *tdesc_arm_list[ARM_FP_TYPE_INVALID];
+
+/* See linux-arm-tdesc.h.  */
+
+const target_desc *
+arm_linux_read_description (arm_fp_type fp_type)
+{
+  struct target_desc *tdesc = tdesc_arm_list[fp_type];
+
+  if (tdesc == nullptr)
+    {
+      tdesc = arm_create_target_description (fp_type);
+
+      static const char *expedite_regs[] = { "r11", "sp", "pc", 0 };
+      init_target_desc (tdesc, expedite_regs);
+
+      tdesc_arm_list[fp_type] = tdesc;
+    }
+
+  return tdesc;
+}
+
+/* See linux-arm-tdesc.h.  */
+
+arm_fp_type arm_linux_get_tdesc_fp_type (const target_desc *tdesc)
+{
+  if (tdesc == nullptr)
+    return ARM_FP_TYPE_INVALID;
+
+  /* Many of the tdesc_arm_list entries may not have been initialised yet.  This
+     is ok, because tdesc must be one of the initialised ones.  */
+  for (int i = ARM_FP_TYPE_VFPV2; i < ARM_FP_TYPE_INVALID; i++)
+    {
+      if (tdesc == tdesc_arm_list[i])
+	return (arm_fp_type) i;
+    }
+
+  return ARM_FP_TYPE_INVALID;
+}
diff --git a/gdb/gdbserver/linux-arm-tdesc.h b/gdb/gdbserver/linux-arm-tdesc.h
new file mode 100644
index 0000000000..51efb9fb48
--- /dev/null
+++ b/gdb/gdbserver/linux-arm-tdesc.h
@@ -0,0 +1,29 @@ 
+/* Copyright (C) 2019 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/>.  */
+
+#ifndef GDBSERVER_LINUX_ARM_TDESC_H
+#define GDBSERVER_LINUX_ARM_TDESC_H
+
+/* Return the Arm target description with fp registers FP_TYPE.  */
+
+const target_desc * arm_linux_read_description (arm_fp_type fp_type);
+
+/* For a target description TDESC, return its fp type.  */
+
+arm_fp_type arm_linux_get_tdesc_fp_type (const target_desc *tdesc);
+
+#endif /* linux-arm-tdesc.h.  */