linux-xtensa-low.cc 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. /* GNU/Linux/Xtensa specific low level interface, for the remote server for GDB.
  2. Copyright (C) 2007-2022 Free Software Foundation, Inc.
  3. This file is part of GDB.
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 3 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program. If not, see <http://www.gnu.org/licenses/>. */
  14. #include "server.h"
  15. #include "linux-low.h"
  16. /* Linux target op definitions for the Xtensa architecture. */
  17. class xtensa_target : public linux_process_target
  18. {
  19. public:
  20. const regs_info *get_regs_info () override;
  21. const gdb_byte *sw_breakpoint_from_kind (int kind, int *size) override;
  22. protected:
  23. void low_arch_setup () override;
  24. bool low_cannot_fetch_register (int regno) override;
  25. bool low_cannot_store_register (int regno) override;
  26. bool low_supports_breakpoints () override;
  27. CORE_ADDR low_get_pc (regcache *regcache) override;
  28. void low_set_pc (regcache *regcache, CORE_ADDR newpc) override;
  29. bool low_breakpoint_at (CORE_ADDR pc) override;
  30. };
  31. /* The singleton target ops object. */
  32. static xtensa_target the_xtensa_target;
  33. bool
  34. xtensa_target::low_cannot_fetch_register (int regno)
  35. {
  36. gdb_assert_not_reached ("linux target op low_cannot_fetch_register "
  37. "is not implemented by the target");
  38. }
  39. bool
  40. xtensa_target::low_cannot_store_register (int regno)
  41. {
  42. gdb_assert_not_reached ("linux target op low_cannot_store_register "
  43. "is not implemented by the target");
  44. }
  45. bool
  46. xtensa_target::low_supports_breakpoints ()
  47. {
  48. return true;
  49. }
  50. CORE_ADDR
  51. xtensa_target::low_get_pc (regcache *regcache)
  52. {
  53. return linux_get_pc_32bit (regcache);
  54. }
  55. void
  56. xtensa_target::low_set_pc (regcache *regcache, CORE_ADDR pc)
  57. {
  58. linux_set_pc_32bit (regcache, pc);
  59. }
  60. /* Defined in auto-generated file reg-xtensa.c. */
  61. void init_registers_xtensa (void);
  62. extern const struct target_desc *tdesc_xtensa;
  63. #include <asm/ptrace.h>
  64. #include <xtensa-config.h>
  65. #include "arch/xtensa.h"
  66. #include "gdb_proc_service.h"
  67. #include "xtensa-xtregs.c"
  68. enum regnum {
  69. R_PC=0, R_PS,
  70. R_LBEG, R_LEND, R_LCOUNT,
  71. R_SAR,
  72. R_WS, R_WB,
  73. R_THREADPTR,
  74. R_A0 = 64
  75. };
  76. static void
  77. xtensa_fill_gregset (struct regcache *regcache, void *buf)
  78. {
  79. elf_greg_t* rset = (elf_greg_t*)buf;
  80. const struct target_desc *tdesc = regcache->tdesc;
  81. int ar0_regnum;
  82. char *ptr;
  83. int i;
  84. /* Take care of AR registers. */
  85. ar0_regnum = find_regno (tdesc, "ar0");
  86. ptr = (char*)&rset[R_A0];
  87. for (i = ar0_regnum; i < ar0_regnum + XCHAL_NUM_AREGS; i++)
  88. {
  89. collect_register (regcache, i, ptr);
  90. ptr += register_size (tdesc, i);
  91. }
  92. if (XSHAL_ABI == XTHAL_ABI_CALL0)
  93. {
  94. int a0_regnum = find_regno (tdesc, "a0");
  95. ptr = (char *) &rset[R_A0 + 4 * rset[R_WB]];
  96. for (i = a0_regnum; i < a0_regnum + C0_NREGS; i++)
  97. {
  98. if ((4 * rset[R_WB] + i - a0_regnum) == XCHAL_NUM_AREGS)
  99. ptr = (char *) &rset[R_A0];
  100. collect_register (regcache, i, ptr);
  101. ptr += register_size (tdesc, i);
  102. }
  103. }
  104. /* Loop registers, if hardware has it. */
  105. #if XCHAL_HAVE_LOOPS
  106. collect_register_by_name (regcache, "lbeg", (char*)&rset[R_LBEG]);
  107. collect_register_by_name (regcache, "lend", (char*)&rset[R_LEND]);
  108. collect_register_by_name (regcache, "lcount", (char*)&rset[R_LCOUNT]);
  109. #endif
  110. collect_register_by_name (regcache, "sar", (char*)&rset[R_SAR]);
  111. collect_register_by_name (regcache, "pc", (char*)&rset[R_PC]);
  112. collect_register_by_name (regcache, "ps", (char*)&rset[R_PS]);
  113. collect_register_by_name (regcache, "windowbase", (char*)&rset[R_WB]);
  114. collect_register_by_name (regcache, "windowstart", (char*)&rset[R_WS]);
  115. #if XCHAL_HAVE_THREADPTR
  116. collect_register_by_name (regcache, "threadptr",
  117. (char *) &rset[R_THREADPTR]);
  118. #endif
  119. }
  120. static void
  121. xtensa_store_gregset (struct regcache *regcache, const void *buf)
  122. {
  123. const elf_greg_t* rset = (const elf_greg_t*)buf;
  124. const struct target_desc *tdesc = regcache->tdesc;
  125. int ar0_regnum;
  126. char *ptr;
  127. int i;
  128. /* Take care of AR registers. */
  129. ar0_regnum = find_regno (tdesc, "ar0");
  130. ptr = (char *)&rset[R_A0];
  131. for (i = ar0_regnum; i < ar0_regnum + XCHAL_NUM_AREGS; i++)
  132. {
  133. supply_register (regcache, i, ptr);
  134. ptr += register_size (tdesc, i);
  135. }
  136. if (XSHAL_ABI == XTHAL_ABI_CALL0)
  137. {
  138. int a0_regnum = find_regno (tdesc, "a0");
  139. ptr = (char *) &rset[R_A0 + (4 * rset[R_WB]) % XCHAL_NUM_AREGS];
  140. for (i = a0_regnum; i < a0_regnum + C0_NREGS; i++)
  141. {
  142. if ((4 * rset[R_WB] + i - a0_regnum) == XCHAL_NUM_AREGS)
  143. ptr = (char *) &rset[R_A0];
  144. supply_register (regcache, i, ptr);
  145. ptr += register_size (tdesc, i);
  146. }
  147. }
  148. /* Loop registers, if hardware has it. */
  149. #if XCHAL_HAVE_LOOPS
  150. supply_register_by_name (regcache, "lbeg", (char*)&rset[R_LBEG]);
  151. supply_register_by_name (regcache, "lend", (char*)&rset[R_LEND]);
  152. supply_register_by_name (regcache, "lcount", (char*)&rset[R_LCOUNT]);
  153. #endif
  154. supply_register_by_name (regcache, "sar", (char*)&rset[R_SAR]);
  155. supply_register_by_name (regcache, "pc", (char*)&rset[R_PC]);
  156. supply_register_by_name (regcache, "ps", (char*)&rset[R_PS]);
  157. supply_register_by_name (regcache, "windowbase", (char*)&rset[R_WB]);
  158. supply_register_by_name (regcache, "windowstart", (char*)&rset[R_WS]);
  159. #if XCHAL_HAVE_THREADPTR
  160. supply_register_by_name (regcache, "threadptr",
  161. (char *) &rset[R_THREADPTR]);
  162. #endif
  163. }
  164. /* Xtensa GNU/Linux PTRACE interface includes extended register set. */
  165. static void
  166. xtensa_fill_xtregset (struct regcache *regcache, void *buf)
  167. {
  168. const xtensa_regtable_t *ptr;
  169. for (ptr = xtensa_regmap_table; ptr->name; ptr++)
  170. {
  171. collect_register_by_name (regcache, ptr->name,
  172. (char*)buf + ptr->ptrace_offset);
  173. }
  174. }
  175. static void
  176. xtensa_store_xtregset (struct regcache *regcache, const void *buf)
  177. {
  178. const xtensa_regtable_t *ptr;
  179. for (ptr = xtensa_regmap_table; ptr->name; ptr++)
  180. {
  181. supply_register_by_name (regcache, ptr->name,
  182. (char*)buf + ptr->ptrace_offset);
  183. }
  184. }
  185. static struct regset_info xtensa_regsets[] = {
  186. { PTRACE_GETREGS, PTRACE_SETREGS, 0, sizeof (elf_gregset_t),
  187. GENERAL_REGS,
  188. xtensa_fill_gregset, xtensa_store_gregset },
  189. { PTRACE_GETXTREGS, PTRACE_SETXTREGS, 0, XTENSA_ELF_XTREG_SIZE,
  190. EXTENDED_REGS,
  191. xtensa_fill_xtregset, xtensa_store_xtregset },
  192. NULL_REGSET
  193. };
  194. #if XCHAL_HAVE_BE
  195. #define XTENSA_BREAKPOINT {0xd2,0x0f}
  196. #else
  197. #define XTENSA_BREAKPOINT {0x2d,0xf0}
  198. #endif
  199. static const gdb_byte xtensa_breakpoint[] = XTENSA_BREAKPOINT;
  200. #define xtensa_breakpoint_len 2
  201. /* Implementation of target ops method "sw_breakpoint_from_kind". */
  202. const gdb_byte *
  203. xtensa_target::sw_breakpoint_from_kind (int kind, int *size)
  204. {
  205. *size = xtensa_breakpoint_len;
  206. return xtensa_breakpoint;
  207. }
  208. bool
  209. xtensa_target::low_breakpoint_at (CORE_ADDR where)
  210. {
  211. unsigned long insn;
  212. read_memory (where, (unsigned char *) &insn, xtensa_breakpoint_len);
  213. return memcmp((char *) &insn,
  214. xtensa_breakpoint, xtensa_breakpoint_len) == 0;
  215. }
  216. /* Called by libthread_db. */
  217. ps_err_e
  218. ps_get_thread_area (struct ps_prochandle *ph,
  219. lwpid_t lwpid, int idx, void **base)
  220. {
  221. xtensa_elf_gregset_t regs;
  222. if (ptrace (PTRACE_GETREGS, lwpid, NULL, &regs) != 0)
  223. return PS_ERR;
  224. /* IDX is the bias from the thread pointer to the beginning of the
  225. thread descriptor. It has to be subtracted due to implementation
  226. quirks in libthread_db. */
  227. *base = (void *) ((char *) regs.threadptr - idx);
  228. return PS_OK;
  229. }
  230. static struct regsets_info xtensa_regsets_info =
  231. {
  232. xtensa_regsets, /* regsets */
  233. 0, /* num_regsets */
  234. NULL, /* disabled_regsets */
  235. };
  236. static struct regs_info myregs_info =
  237. {
  238. NULL, /* regset_bitmap */
  239. NULL, /* usrregs */
  240. &xtensa_regsets_info
  241. };
  242. void
  243. xtensa_target::low_arch_setup ()
  244. {
  245. current_process ()->tdesc = tdesc_xtensa;
  246. }
  247. const regs_info *
  248. xtensa_target::get_regs_info ()
  249. {
  250. return &myregs_info;
  251. }
  252. /* The linux target ops object. */
  253. linux_process_target *the_linux_target = &the_xtensa_target;
  254. void
  255. initialize_low_arch (void)
  256. {
  257. /* Initialize the Linux target descriptions. */
  258. init_registers_xtensa ();
  259. initialize_regsets_info (&xtensa_regsets_info);
  260. }