0010-gdbserver-aarch64-support.patch 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320
  1. From eb79b2318066cafb75ffdce310e3bbd44f7c79e3 Mon Sep 17 00:00:00 2001
  2. From: Luis Machado <luis.machado@linaro.org>
  3. Date: Fri, 29 Oct 2021 14:54:36 -0300
  4. Subject: [PATCH] [AArch64] Make gdbserver register set selection dynamic
  5. The current register set selection mechanism for AArch64 is static, based
  6. on a pre-populated array of register sets.
  7. This means that we might potentially probe register sets that are not
  8. available. This is OK if the kernel errors out during ptrace, but probing the
  9. tag_ctl register, for example, does not result in a ptrace error if the kernel
  10. supports the tagged address ABI but not MTE (PR 28355).
  11. Making the register set selection dynamic, based on feature checks, solves
  12. this and simplifies the code a bit. It allows us to list all of the register
  13. sets only once, and pick and choose based on HWCAP/HWCAP2 or other properties.
  14. gdb/ChangeLog:
  15. 2021-11-03 Luis Machado <luis.machado@linaro.org>
  16. PR gdb/28355
  17. * arch/aarch64.h (struct aarch64_features): New struct.
  18. gdbserver/ChangeLog:
  19. 2021-11-03 Luis Machado <luis.machado@linaro.org>
  20. PR gdb/28355
  21. * linux-aarch64-low.cc (is_sve_tdesc): Remove.
  22. (aarch64_target::low_arch_setup): Rework to adjust the register sets.
  23. (aarch64_regsets): Update to list all register sets.
  24. (aarch64_regsets_info, regs_info_aarch64): Replace NULL with nullptr.
  25. (aarch64_sve_regsets, aarch64_sve_regsets_info)
  26. (regs_info_aarch64_sve): Remove.
  27. (aarch64_adjust_register_sets): New.
  28. (aarch64_target::get_regs_info): Remove references to removed structs.
  29. (initialize_low_arch): Likewise.
  30. Backported from: eb79b2318066cafb75ffdce310e3bbd44f7c79e3
  31. Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
  32. ---
  33. gdb/arch/aarch64.h | 9 ++
  34. gdbserver/linux-aarch64-low.cc | 186 ++++++++++++++++++---------------
  35. 4 files changed, 130 insertions(+), 85 deletions(-)
  36. diff --git a/gdb/arch/aarch64.h b/gdb/arch/aarch64.h
  37. index 0eb702c5b5e..95edb664b55 100644
  38. --- a/gdb/arch/aarch64.h
  39. +++ b/gdb/arch/aarch64.h
  40. @@ -22,6 +22,15 @@
  41. #include "gdbsupport/tdesc.h"
  42. +/* Holds information on what architectural features are available. This is
  43. + used to select register sets. */
  44. +struct aarch64_features
  45. +{
  46. + bool sve = false;
  47. + bool pauth = false;
  48. + bool mte = false;
  49. +};
  50. +
  51. /* Create the aarch64 target description. A non zero VQ value indicates both
  52. the presence of SVE and the Vector Quotient - the number of 128bit chunks in
  53. an SVE Z register. HAS_PAUTH_P indicates the presence of the PAUTH
  54. diff --git a/gdbserver/linux-aarch64-low.cc b/gdbserver/linux-aarch64-low.cc
  55. index daccfef746e..9a8cb4169a7 100644
  56. --- a/gdbserver/linux-aarch64-low.cc
  57. +++ b/gdbserver/linux-aarch64-low.cc
  58. @@ -196,16 +196,6 @@ is_64bit_tdesc (void)
  59. return register_size (regcache->tdesc, 0) == 8;
  60. }
  61. -/* Return true if the regcache contains the number of SVE registers. */
  62. -
  63. -static bool
  64. -is_sve_tdesc (void)
  65. -{
  66. - struct regcache *regcache = get_thread_regcache (current_thread, 0);
  67. -
  68. - return tdesc_contains_feature (regcache->tdesc, "org.gnu.gdb.aarch64.sve");
  69. -}
  70. -
  71. static void
  72. aarch64_fill_gregset (struct regcache *regcache, void *buf)
  73. {
  74. @@ -680,40 +670,6 @@ aarch64_target::low_new_fork (process_info *parent,
  75. *child->priv->arch_private = *parent->priv->arch_private;
  76. }
  77. -/* Matches HWCAP_PACA in kernel header arch/arm64/include/uapi/asm/hwcap.h. */
  78. -#define AARCH64_HWCAP_PACA (1 << 30)
  79. -
  80. -/* Implementation of linux target ops method "low_arch_setup". */
  81. -
  82. -void
  83. -aarch64_target::low_arch_setup ()
  84. -{
  85. - unsigned int machine;
  86. - int is_elf64;
  87. - int tid;
  88. -
  89. - tid = lwpid_of (current_thread);
  90. -
  91. - is_elf64 = linux_pid_exe_is_elf_64_file (tid, &machine);
  92. -
  93. - if (is_elf64)
  94. - {
  95. - uint64_t vq = aarch64_sve_get_vq (tid);
  96. - unsigned long hwcap = linux_get_hwcap (8);
  97. - unsigned long hwcap2 = linux_get_hwcap2 (8);
  98. - bool pauth_p = hwcap & AARCH64_HWCAP_PACA;
  99. - /* MTE is AArch64-only. */
  100. - bool mte_p = hwcap2 & HWCAP2_MTE;
  101. -
  102. - current_process ()->tdesc
  103. - = aarch64_linux_read_description (vq, pauth_p, mte_p);
  104. - }
  105. - else
  106. - current_process ()->tdesc = aarch32_linux_read_description ();
  107. -
  108. - aarch64_linux_get_debug_reg_capacity (lwpid_of (current_thread));
  109. -}
  110. -
  111. /* Wrapper for aarch64_sve_regs_copy_to_reg_buf. */
  112. static void
  113. @@ -730,21 +686,36 @@ aarch64_sve_regs_copy_from_regcache (struct regcache *regcache, void *buf)
  114. return aarch64_sve_regs_copy_from_reg_buf (regcache, buf);
  115. }
  116. +/* Array containing all the possible register sets for AArch64/Linux. During
  117. + architecture setup, these will be checked against the HWCAP/HWCAP2 bits for
  118. + validity and enabled/disabled accordingly.
  119. +
  120. + Their sizes are set to 0 here, but they will be adjusted later depending
  121. + on whether each register set is available or not. */
  122. static struct regset_info aarch64_regsets[] =
  123. {
  124. + /* GPR registers. */
  125. { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_PRSTATUS,
  126. - sizeof (struct user_pt_regs), GENERAL_REGS,
  127. + 0, GENERAL_REGS,
  128. aarch64_fill_gregset, aarch64_store_gregset },
  129. + /* Floating Point (FPU) registers. */
  130. { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_FPREGSET,
  131. - sizeof (struct user_fpsimd_state), FP_REGS,
  132. + 0, FP_REGS,
  133. aarch64_fill_fpregset, aarch64_store_fpregset
  134. },
  135. + /* Scalable Vector Extension (SVE) registers. */
  136. + { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_ARM_SVE,
  137. + 0, EXTENDED_REGS,
  138. + aarch64_sve_regs_copy_from_regcache, aarch64_sve_regs_copy_to_regcache
  139. + },
  140. + /* PAC registers. */
  141. { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_ARM_PAC_MASK,
  142. - AARCH64_PAUTH_REGS_SIZE, OPTIONAL_REGS,
  143. - NULL, aarch64_store_pauthregset },
  144. + 0, OPTIONAL_REGS,
  145. + nullptr, aarch64_store_pauthregset },
  146. + /* Tagged address control / MTE registers. */
  147. { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_ARM_TAGGED_ADDR_CTRL,
  148. - AARCH64_LINUX_SIZEOF_MTE, OPTIONAL_REGS, aarch64_fill_mteregset,
  149. - aarch64_store_mteregset },
  150. + 0, OPTIONAL_REGS,
  151. + aarch64_fill_mteregset, aarch64_store_mteregset },
  152. NULL_REGSET
  153. };
  154. @@ -752,47 +723,95 @@ static struct regsets_info aarch64_regsets_info =
  155. {
  156. aarch64_regsets, /* regsets */
  157. 0, /* num_regsets */
  158. - NULL, /* disabled_regsets */
  159. + nullptr, /* disabled_regsets */
  160. };
  161. static struct regs_info regs_info_aarch64 =
  162. {
  163. - NULL, /* regset_bitmap */
  164. - NULL, /* usrregs */
  165. + nullptr, /* regset_bitmap */
  166. + nullptr, /* usrregs */
  167. &aarch64_regsets_info,
  168. };
  169. -static struct regset_info aarch64_sve_regsets[] =
  170. +/* Given FEATURES, adjust the available register sets by setting their
  171. + sizes. A size of 0 means the register set is disabled and won't be
  172. + used. */
  173. +
  174. +static void
  175. +aarch64_adjust_register_sets (const struct aarch64_features &features)
  176. {
  177. - { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_PRSTATUS,
  178. - sizeof (struct user_pt_regs), GENERAL_REGS,
  179. - aarch64_fill_gregset, aarch64_store_gregset },
  180. - { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_ARM_SVE,
  181. - SVE_PT_SIZE (AARCH64_MAX_SVE_VQ, SVE_PT_REGS_SVE), EXTENDED_REGS,
  182. - aarch64_sve_regs_copy_from_regcache, aarch64_sve_regs_copy_to_regcache
  183. - },
  184. - { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_ARM_PAC_MASK,
  185. - AARCH64_PAUTH_REGS_SIZE, OPTIONAL_REGS,
  186. - NULL, aarch64_store_pauthregset },
  187. - { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_ARM_TAGGED_ADDR_CTRL,
  188. - AARCH64_LINUX_SIZEOF_MTE, OPTIONAL_REGS, aarch64_fill_mteregset,
  189. - aarch64_store_mteregset },
  190. - NULL_REGSET
  191. -};
  192. + struct regset_info *regset;
  193. -static struct regsets_info aarch64_sve_regsets_info =
  194. - {
  195. - aarch64_sve_regsets, /* regsets. */
  196. - 0, /* num_regsets. */
  197. - NULL, /* disabled_regsets. */
  198. - };
  199. + for (regset = aarch64_regsets; regset->size >= 0; regset++)
  200. + {
  201. + switch (regset->nt_type)
  202. + {
  203. + case NT_PRSTATUS:
  204. + /* General purpose registers are always present. */
  205. + regset->size = sizeof (struct user_pt_regs);
  206. + break;
  207. + case NT_FPREGSET:
  208. + /* This is unavailable when SVE is present. */
  209. + if (!features.sve)
  210. + regset->size = sizeof (struct user_fpsimd_state);
  211. + break;
  212. + case NT_ARM_SVE:
  213. + if (features.sve)
  214. + regset->size = SVE_PT_SIZE (AARCH64_MAX_SVE_VQ, SVE_PT_REGS_SVE);
  215. + break;
  216. + case NT_ARM_PAC_MASK:
  217. + if (features.pauth)
  218. + regset->size = AARCH64_PAUTH_REGS_SIZE;
  219. + break;
  220. + case NT_ARM_TAGGED_ADDR_CTRL:
  221. + if (features.mte)
  222. + regset->size = AARCH64_LINUX_SIZEOF_MTE;
  223. + break;
  224. + default:
  225. + gdb_assert_not_reached ("Unknown register set found.");
  226. + }
  227. + }
  228. +}
  229. -static struct regs_info regs_info_aarch64_sve =
  230. - {
  231. - NULL, /* regset_bitmap. */
  232. - NULL, /* usrregs. */
  233. - &aarch64_sve_regsets_info,
  234. - };
  235. +/* Matches HWCAP_PACA in kernel header arch/arm64/include/uapi/asm/hwcap.h. */
  236. +#define AARCH64_HWCAP_PACA (1 << 30)
  237. +
  238. +/* Implementation of linux target ops method "low_arch_setup". */
  239. +
  240. +void
  241. +aarch64_target::low_arch_setup ()
  242. +{
  243. + unsigned int machine;
  244. + int is_elf64;
  245. + int tid;
  246. +
  247. + tid = lwpid_of (current_thread);
  248. +
  249. + is_elf64 = linux_pid_exe_is_elf_64_file (tid, &machine);
  250. +
  251. + if (is_elf64)
  252. + {
  253. + struct aarch64_features features;
  254. +
  255. + uint64_t vq = aarch64_sve_get_vq (tid);
  256. + features.sve = (vq > 0);
  257. + /* A-profile PAC is 64-bit only. */
  258. + features.pauth = linux_get_hwcap (8) & AARCH64_HWCAP_PACA;
  259. + /* A-profile MTE is 64-bit only. */
  260. + features.mte = linux_get_hwcap2 (8) & HWCAP2_MTE;
  261. +
  262. + current_process ()->tdesc
  263. + = aarch64_linux_read_description (vq, features.pauth, features.mte);
  264. +
  265. + /* Adjust the register sets we should use for this particular set of
  266. + features. */
  267. + aarch64_adjust_register_sets (features);
  268. + }
  269. + else
  270. + current_process ()->tdesc = aarch32_linux_read_description ();
  271. +
  272. + aarch64_linux_get_debug_reg_capacity (lwpid_of (current_thread));
  273. +}
  274. /* Implementation of linux target ops method "get_regs_info". */
  275. @@ -802,9 +821,7 @@ aarch64_target::get_regs_info ()
  276. if (!is_64bit_tdesc ())
  277. return &regs_info_aarch32;
  278. - if (is_sve_tdesc ())
  279. - return &regs_info_aarch64_sve;
  280. -
  281. + /* AArch64 64-bit registers. */
  282. return &regs_info_aarch64;
  283. }
  284. @@ -3294,5 +3311,4 @@ initialize_low_arch (void)
  285. initialize_low_arch_aarch32 ();
  286. initialize_regsets_info (&aarch64_regsets_info);
  287. - initialize_regsets_info (&aarch64_sve_regsets_info);
  288. }
  289. --
  290. 2.27.0