OLD | NEW |
1 /* Target-dependent code for GNU/Linux Super-H. | 1 /* Target-dependent code for GNU/Linux Super-H. |
2 | 2 |
3 Copyright (C) 2005, 2007-2012 Free Software Foundation, Inc. | 3 Copyright (C) 2005, 2007-2012 Free Software Foundation, Inc. |
4 | 4 |
5 This file is part of GDB. | 5 This file is part of GDB. |
6 | 6 |
7 This program is free software; you can redistribute it and/or modify | 7 This program is free software; you can redistribute it and/or modify |
8 it under the terms of the GNU General Public License as published by | 8 it under the terms of the GNU General Public License as published by |
9 the Free Software Foundation; either version 3 of the License, or | 9 the Free Software Foundation; either version 3 of the License, or |
10 (at your option) any later version. | 10 (at your option) any later version. |
11 | 11 |
12 This program is distributed in the hope that it will be useful, | 12 This program is distributed in the hope that it will be useful, |
13 but WITHOUT ANY WARRANTY; without even the implied warranty of | 13 but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 GNU General Public License for more details. | 15 GNU General Public License for more details. |
16 | 16 |
17 You should have received a copy of the GNU General Public License | 17 You should have received a copy of the GNU General Public License |
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */ | 18 along with this program. If not, see <http://www.gnu.org/licenses/>. */ |
19 | 19 |
20 #include "defs.h" | 20 #include "defs.h" |
21 #include "osabi.h" | 21 #include "osabi.h" |
22 | 22 |
23 #include "solib-svr4.h" | 23 #include "solib-svr4.h" |
24 #include "symtab.h" | 24 #include "symtab.h" |
25 | 25 |
| 26 #include "trad-frame.h" |
| 27 #include "tramp-frame.h" |
| 28 |
26 #include "glibc-tdep.h" | 29 #include "glibc-tdep.h" |
27 #include "sh-tdep.h" | 30 #include "sh-tdep.h" |
28 #include "linux-tdep.h" | 31 #include "linux-tdep.h" |
29 | 32 |
30 #define REGSx16(base) \ | 33 #define REGSx16(base) \ |
31 {(base), 0}, \ | 34 {(base), 0}, \ |
32 {(base) + 1, 4}, \ | 35 {(base) + 1, 4}, \ |
33 {(base) + 2, 8}, \ | 36 {(base) + 2, 8}, \ |
34 {(base) + 3, 12}, \ | 37 {(base) + 3, 12}, \ |
35 {(base) + 4, 16}, \ | 38 {(base) + 4, 16}, \ |
(...skipping 27 matching lines...) Expand all Loading... |
63 | 66 |
64 static const struct sh_corefile_regmap fpregs_table[] = | 67 static const struct sh_corefile_regmap fpregs_table[] = |
65 { | 68 { |
66 REGSx16 (FR0_REGNUM), | 69 REGSx16 (FR0_REGNUM), |
67 /* REGSx16 xfp_regs omitted. */ | 70 /* REGSx16 xfp_regs omitted. */ |
68 {FPSCR_REGNUM, 128}, | 71 {FPSCR_REGNUM, 128}, |
69 {FPUL_REGNUM, 132}, | 72 {FPUL_REGNUM, 132}, |
70 {-1 /* Terminator. */, 0} | 73 {-1 /* Terminator. */, 0} |
71 }; | 74 }; |
72 | 75 |
| 76 /* SH signal handler frame support. */ |
| 77 |
| 78 static void |
| 79 sh_linux_sigtramp_cache (struct frame_info *this_frame, |
| 80 struct trad_frame_cache *this_cache, |
| 81 CORE_ADDR func, int regs_offset) |
| 82 { |
| 83 int i; |
| 84 struct gdbarch *gdbarch = get_frame_arch (this_frame); |
| 85 CORE_ADDR base = get_frame_register_unsigned (this_frame, |
| 86 gdbarch_sp_regnum (gdbarch)); |
| 87 CORE_ADDR regs = base + regs_offset; |
| 88 |
| 89 for (i = 0; i < 18; i++) |
| 90 trad_frame_set_reg_addr (this_cache, i, regs + i * 4); |
| 91 |
| 92 trad_frame_set_reg_addr (this_cache, SR_REGNUM, regs + 18 * 4); |
| 93 trad_frame_set_reg_addr (this_cache, GBR_REGNUM, regs + 19 * 4); |
| 94 trad_frame_set_reg_addr (this_cache, MACH_REGNUM, regs + 20 * 4); |
| 95 trad_frame_set_reg_addr (this_cache, MACL_REGNUM, regs + 21 * 4); |
| 96 |
| 97 /* Restore FP state if we have an FPU. */ |
| 98 if (gdbarch_fp0_regnum (gdbarch) != -1) |
| 99 { |
| 100 CORE_ADDR fpregs = regs + 22 * 4; |
| 101 for (i = FR0_REGNUM; i <= FP_LAST_REGNUM; i++) |
| 102 trad_frame_set_reg_addr (this_cache, i, fpregs + i * 4); |
| 103 trad_frame_set_reg_addr (this_cache, FPSCR_REGNUM, fpregs + 32 * 4); |
| 104 trad_frame_set_reg_addr (this_cache, FPUL_REGNUM, fpregs + 33 * 4); |
| 105 } |
| 106 |
| 107 /* Save a frame ID. */ |
| 108 trad_frame_set_id (this_cache, frame_id_build (base, func)); |
| 109 } |
| 110 |
| 111 /* Implement struct tramp_frame "init" callbacks for signal |
| 112 trampolines on 32-bit SH. */ |
| 113 |
| 114 static void |
| 115 sh_linux_sigreturn_init (const struct tramp_frame *self, |
| 116 struct frame_info *this_frame, |
| 117 struct trad_frame_cache *this_cache, |
| 118 CORE_ADDR func) |
| 119 { |
| 120 /* SH 32-bit sigframe: sigcontext at start of sigframe, |
| 121 registers start after a single 'oldmask' word. */ |
| 122 sh_linux_sigtramp_cache (this_frame, this_cache, func, 4); |
| 123 } |
| 124 |
| 125 static void |
| 126 sh_linux_rt_sigreturn_init (const struct tramp_frame *self, |
| 127 struct frame_info *this_frame, |
| 128 struct trad_frame_cache *this_cache, |
| 129 CORE_ADDR func) |
| 130 { |
| 131 /* SH 32-bit rt_sigframe: starts with a siginfo (128 bytes), then |
| 132 we can find sigcontext embedded within a ucontext (offset 20 bytes). |
| 133 Then registers start after a single 'oldmask' word. */ |
| 134 sh_linux_sigtramp_cache (this_frame, this_cache, func, |
| 135 128 /* sizeof (struct siginfo) */ |
| 136 + 20 /* offsetof (struct ucontext, uc_mcontext) */ |
| 137 + 4 /* oldmask word at start of sigcontext */); |
| 138 } |
| 139 |
| 140 /* Instruction patterns. */ |
| 141 #define SH_MOVW 0x9305 |
| 142 #define SH_TRAP 0xc300 |
| 143 #define SH_OR_R0_R0 0x200b |
| 144 |
| 145 /* SH sigreturn syscall numbers. */ |
| 146 #define SH_NR_SIGRETURN 0x0077 |
| 147 #define SH_NR_RT_SIGRETURN 0x00ad |
| 148 |
| 149 static struct tramp_frame sh_linux_sigreturn_tramp_frame = { |
| 150 SIGTRAMP_FRAME, |
| 151 2, |
| 152 { |
| 153 { SH_MOVW, 0xffff }, |
| 154 { SH_TRAP, 0xff00 }, /* #imm argument part filtered out. */ |
| 155 { SH_OR_R0_R0, 0xffff }, |
| 156 { SH_OR_R0_R0, 0xffff }, |
| 157 { SH_OR_R0_R0, 0xffff }, |
| 158 { SH_OR_R0_R0, 0xffff }, |
| 159 { SH_OR_R0_R0, 0xffff }, |
| 160 { SH_NR_SIGRETURN, 0xffff }, |
| 161 { TRAMP_SENTINEL_INSN } |
| 162 }, |
| 163 sh_linux_sigreturn_init |
| 164 }; |
| 165 |
| 166 static struct tramp_frame sh_linux_rt_sigreturn_tramp_frame = { |
| 167 SIGTRAMP_FRAME, |
| 168 2, |
| 169 { |
| 170 { SH_MOVW, 0xffff }, |
| 171 { SH_TRAP, 0xff00 }, /* #imm argument part filtered out. */ |
| 172 { SH_OR_R0_R0, 0xffff }, |
| 173 { SH_OR_R0_R0, 0xffff }, |
| 174 { SH_OR_R0_R0, 0xffff }, |
| 175 { SH_OR_R0_R0, 0xffff }, |
| 176 { SH_OR_R0_R0, 0xffff }, |
| 177 { SH_NR_RT_SIGRETURN, 0xffff }, |
| 178 { TRAMP_SENTINEL_INSN } |
| 179 }, |
| 180 sh_linux_rt_sigreturn_init |
| 181 }; |
| 182 |
73 static void | 183 static void |
74 sh_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) | 184 sh_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) |
75 { | 185 { |
76 linux_init_abi (info, gdbarch); | 186 linux_init_abi (info, gdbarch); |
77 | 187 |
78 /* GNU/Linux uses SVR4-style shared libraries. */ | 188 /* GNU/Linux uses SVR4-style shared libraries. */ |
79 set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target); | 189 set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target); |
80 set_solib_svr4_fetch_link_map_offsets | 190 set_solib_svr4_fetch_link_map_offsets |
81 (gdbarch, svr4_ilp32_fetch_link_map_offsets); | 191 (gdbarch, svr4_ilp32_fetch_link_map_offsets); |
82 set_gdbarch_skip_solib_resolver (gdbarch, glibc_skip_solib_resolver); | 192 set_gdbarch_skip_solib_resolver (gdbarch, glibc_skip_solib_resolver); |
83 | 193 |
84 set_gdbarch_fetch_tls_load_module_address (gdbarch, | 194 set_gdbarch_fetch_tls_load_module_address (gdbarch, |
85 svr4_fetch_objfile_link_map); | 195 svr4_fetch_objfile_link_map); |
86 | 196 |
87 /* Core files are supported for 32-bit SH only, at present. */ | 197 /* Core files and signal handler frame unwinding are supported for |
| 198 32-bit SH only, at present. */ |
88 if (info.bfd_arch_info->mach != bfd_mach_sh5) | 199 if (info.bfd_arch_info->mach != bfd_mach_sh5) |
89 { | 200 { |
90 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); | 201 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); |
91 | 202 |
92 tdep->core_gregmap = (struct sh_corefile_regmap *)gregs_table; | 203 tdep->core_gregmap = (struct sh_corefile_regmap *)gregs_table; |
93 tdep->core_fpregmap = (struct sh_corefile_regmap *)fpregs_table; | 204 tdep->core_fpregmap = (struct sh_corefile_regmap *)fpregs_table; |
| 205 |
| 206 tramp_frame_prepend_unwinder (gdbarch, &sh_linux_sigreturn_tramp_frame); |
| 207 tramp_frame_prepend_unwinder (gdbarch, &sh_linux_rt_sigreturn_tramp_frame)
; |
94 } | 208 } |
95 } | 209 } |
96 | 210 |
97 /* Provide a prototype to silence -Wmissing-prototypes. */ | 211 /* Provide a prototype to silence -Wmissing-prototypes. */ |
98 extern void _initialize_sh_linux_tdep (void); | 212 extern void _initialize_sh_linux_tdep (void); |
99 | 213 |
100 void | 214 void |
101 _initialize_sh_linux_tdep (void) | 215 _initialize_sh_linux_tdep (void) |
102 { | 216 { |
103 gdbarch_register_osabi (bfd_arch_sh, 0, GDB_OSABI_LINUX, sh_linux_init_abi); | 217 gdbarch_register_osabi (bfd_arch_sh, 0, GDB_OSABI_LINUX, sh_linux_init_abi); |
104 } | 218 } |
OLD | NEW |