sh-linux-tdep.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. /* Target-dependent code for GNU/Linux Super-H.
  2. Copyright (C) 2005-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 "defs.h"
  15. #include "osabi.h"
  16. #include "solib-svr4.h"
  17. #include "symtab.h"
  18. #include "trad-frame.h"
  19. #include "tramp-frame.h"
  20. #include "glibc-tdep.h"
  21. #include "sh-tdep.h"
  22. #include "linux-tdep.h"
  23. #include "gdbarch.h"
  24. #define REGSx16(base) \
  25. {(base), 0}, \
  26. {(base) + 1, 4}, \
  27. {(base) + 2, 8}, \
  28. {(base) + 3, 12}, \
  29. {(base) + 4, 16}, \
  30. {(base) + 5, 20}, \
  31. {(base) + 6, 24}, \
  32. {(base) + 7, 28}, \
  33. {(base) + 8, 32}, \
  34. {(base) + 9, 36}, \
  35. {(base) + 10, 40}, \
  36. {(base) + 11, 44}, \
  37. {(base) + 12, 48}, \
  38. {(base) + 13, 52}, \
  39. {(base) + 14, 56}, \
  40. {(base) + 15, 60}
  41. /* Describe the contents of the .reg section of the core file. */
  42. static const struct sh_corefile_regmap gregs_table[] =
  43. {
  44. REGSx16 (R0_REGNUM),
  45. {PC_REGNUM, 64},
  46. {PR_REGNUM, 68},
  47. {SR_REGNUM, 72},
  48. {GBR_REGNUM, 76},
  49. {MACH_REGNUM, 80},
  50. {MACL_REGNUM, 84},
  51. {-1 /* Terminator. */, 0}
  52. };
  53. /* Describe the contents of the .reg2 section of the core file. */
  54. static const struct sh_corefile_regmap fpregs_table[] =
  55. {
  56. REGSx16 (FR0_REGNUM),
  57. /* REGSx16 xfp_regs omitted. */
  58. {FPSCR_REGNUM, 128},
  59. {FPUL_REGNUM, 132},
  60. {-1 /* Terminator. */, 0}
  61. };
  62. /* SH signal handler frame support. */
  63. static void
  64. sh_linux_sigtramp_cache (struct frame_info *this_frame,
  65. struct trad_frame_cache *this_cache,
  66. CORE_ADDR func, int regs_offset)
  67. {
  68. int i;
  69. struct gdbarch *gdbarch = get_frame_arch (this_frame);
  70. CORE_ADDR base = get_frame_register_unsigned (this_frame,
  71. gdbarch_sp_regnum (gdbarch));
  72. CORE_ADDR regs = base + regs_offset;
  73. for (i = 0; i < 18; i++)
  74. trad_frame_set_reg_addr (this_cache, i, regs + i * 4);
  75. trad_frame_set_reg_addr (this_cache, SR_REGNUM, regs + 18 * 4);
  76. trad_frame_set_reg_addr (this_cache, GBR_REGNUM, regs + 19 * 4);
  77. trad_frame_set_reg_addr (this_cache, MACH_REGNUM, regs + 20 * 4);
  78. trad_frame_set_reg_addr (this_cache, MACL_REGNUM, regs + 21 * 4);
  79. /* Restore FP state if we have an FPU. */
  80. if (gdbarch_fp0_regnum (gdbarch) != -1)
  81. {
  82. CORE_ADDR fpregs = regs + 22 * 4;
  83. for (i = FR0_REGNUM; i <= FP_LAST_REGNUM; i++)
  84. trad_frame_set_reg_addr (this_cache, i, fpregs + i * 4);
  85. trad_frame_set_reg_addr (this_cache, FPSCR_REGNUM, fpregs + 32 * 4);
  86. trad_frame_set_reg_addr (this_cache, FPUL_REGNUM, fpregs + 33 * 4);
  87. }
  88. /* Save a frame ID. */
  89. trad_frame_set_id (this_cache, frame_id_build (base, func));
  90. }
  91. /* Implement struct tramp_frame "init" callbacks for signal
  92. trampolines on 32-bit SH. */
  93. static void
  94. sh_linux_sigreturn_init (const struct tramp_frame *self,
  95. struct frame_info *this_frame,
  96. struct trad_frame_cache *this_cache,
  97. CORE_ADDR func)
  98. {
  99. /* SH 32-bit sigframe: sigcontext at start of sigframe,
  100. registers start after a single 'oldmask' word. */
  101. sh_linux_sigtramp_cache (this_frame, this_cache, func, 4);
  102. }
  103. static void
  104. sh_linux_rt_sigreturn_init (const struct tramp_frame *self,
  105. struct frame_info *this_frame,
  106. struct trad_frame_cache *this_cache,
  107. CORE_ADDR func)
  108. {
  109. /* SH 32-bit rt_sigframe: starts with a siginfo (128 bytes), then
  110. we can find sigcontext embedded within a ucontext (offset 20 bytes).
  111. Then registers start after a single 'oldmask' word. */
  112. sh_linux_sigtramp_cache (this_frame, this_cache, func,
  113. 128 /* sizeof (struct siginfo) */
  114. + 20 /* offsetof (struct ucontext, uc_mcontext) */
  115. + 4 /* oldmask word at start of sigcontext */);
  116. }
  117. /* Instruction patterns. */
  118. #define SH_MOVW 0x9305
  119. #define SH_TRAP 0xc300
  120. #define SH_OR_R0_R0 0x200b
  121. /* SH sigreturn syscall numbers. */
  122. #define SH_NR_SIGRETURN 0x0077
  123. #define SH_NR_RT_SIGRETURN 0x00ad
  124. static struct tramp_frame sh_linux_sigreturn_tramp_frame = {
  125. SIGTRAMP_FRAME,
  126. 2,
  127. {
  128. { SH_MOVW, 0xffff },
  129. { SH_TRAP, 0xff00 }, /* #imm argument part filtered out. */
  130. { SH_OR_R0_R0, 0xffff },
  131. { SH_OR_R0_R0, 0xffff },
  132. { SH_OR_R0_R0, 0xffff },
  133. { SH_OR_R0_R0, 0xffff },
  134. { SH_OR_R0_R0, 0xffff },
  135. { SH_NR_SIGRETURN, 0xffff },
  136. { TRAMP_SENTINEL_INSN }
  137. },
  138. sh_linux_sigreturn_init
  139. };
  140. static struct tramp_frame sh_linux_rt_sigreturn_tramp_frame = {
  141. SIGTRAMP_FRAME,
  142. 2,
  143. {
  144. { SH_MOVW, 0xffff },
  145. { SH_TRAP, 0xff00 }, /* #imm argument part filtered out. */
  146. { SH_OR_R0_R0, 0xffff },
  147. { SH_OR_R0_R0, 0xffff },
  148. { SH_OR_R0_R0, 0xffff },
  149. { SH_OR_R0_R0, 0xffff },
  150. { SH_OR_R0_R0, 0xffff },
  151. { SH_NR_RT_SIGRETURN, 0xffff },
  152. { TRAMP_SENTINEL_INSN }
  153. },
  154. sh_linux_rt_sigreturn_init
  155. };
  156. static void
  157. sh_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
  158. {
  159. linux_init_abi (info, gdbarch, 0);
  160. /* GNU/Linux uses SVR4-style shared libraries. */
  161. set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target);
  162. set_solib_svr4_fetch_link_map_offsets
  163. (gdbarch, linux_ilp32_fetch_link_map_offsets);
  164. set_gdbarch_skip_solib_resolver (gdbarch, glibc_skip_solib_resolver);
  165. set_gdbarch_fetch_tls_load_module_address (gdbarch,
  166. svr4_fetch_objfile_link_map);
  167. sh_gdbarch_tdep *tdep = (sh_gdbarch_tdep *) gdbarch_tdep (gdbarch);
  168. /* Remember regset characteristics. The sizes should match
  169. elf_gregset_t and elf_fpregset_t from Linux. */
  170. tdep->core_gregmap = (struct sh_corefile_regmap *) gregs_table;
  171. tdep->sizeof_gregset = 92;
  172. tdep->core_fpregmap = (struct sh_corefile_regmap *) fpregs_table;
  173. tdep->sizeof_fpregset = 136;
  174. tramp_frame_prepend_unwinder (gdbarch, &sh_linux_sigreturn_tramp_frame);
  175. tramp_frame_prepend_unwinder (gdbarch, &sh_linux_rt_sigreturn_tramp_frame);
  176. }
  177. void _initialize_sh_linux_tdep ();
  178. void
  179. _initialize_sh_linux_tdep ()
  180. {
  181. gdbarch_register_osabi (bfd_arch_sh, 0, GDB_OSABI_LINUX, sh_linux_init_abi);
  182. }