GDB (API)
|
00001 /* Target-dependent code for GNU/Linux Super-H. 00002 00003 Copyright (C) 2005-2013 Free Software Foundation, Inc. 00004 00005 This file is part of GDB. 00006 00007 This program is free software; you can redistribute it and/or modify 00008 it under the terms of the GNU General Public License as published by 00009 the Free Software Foundation; either version 3 of the License, or 00010 (at your option) any later version. 00011 00012 This program is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 GNU General Public License for more details. 00016 00017 You should have received a copy of the GNU General Public License 00018 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 00019 00020 #include "defs.h" 00021 #include "osabi.h" 00022 00023 #include "solib-svr4.h" 00024 #include "symtab.h" 00025 00026 #include "trad-frame.h" 00027 #include "tramp-frame.h" 00028 00029 #include "glibc-tdep.h" 00030 #include "sh-tdep.h" 00031 #include "linux-tdep.h" 00032 00033 #define REGSx16(base) \ 00034 {(base), 0}, \ 00035 {(base) + 1, 4}, \ 00036 {(base) + 2, 8}, \ 00037 {(base) + 3, 12}, \ 00038 {(base) + 4, 16}, \ 00039 {(base) + 5, 20}, \ 00040 {(base) + 6, 24}, \ 00041 {(base) + 7, 28}, \ 00042 {(base) + 8, 32}, \ 00043 {(base) + 9, 36}, \ 00044 {(base) + 10, 40}, \ 00045 {(base) + 11, 44}, \ 00046 {(base) + 12, 48}, \ 00047 {(base) + 13, 52}, \ 00048 {(base) + 14, 56}, \ 00049 {(base) + 15, 60} 00050 00051 /* Describe the contents of the .reg section of the core file. */ 00052 00053 static const struct sh_corefile_regmap gregs_table[] = 00054 { 00055 REGSx16 (R0_REGNUM), 00056 {PC_REGNUM, 64}, 00057 {PR_REGNUM, 68}, 00058 {SR_REGNUM, 72}, 00059 {GBR_REGNUM, 76}, 00060 {MACH_REGNUM, 80}, 00061 {MACL_REGNUM, 84}, 00062 {-1 /* Terminator. */, 0} 00063 }; 00064 00065 /* Describe the contents of the .reg2 section of the core file. */ 00066 00067 static const struct sh_corefile_regmap fpregs_table[] = 00068 { 00069 REGSx16 (FR0_REGNUM), 00070 /* REGSx16 xfp_regs omitted. */ 00071 {FPSCR_REGNUM, 128}, 00072 {FPUL_REGNUM, 132}, 00073 {-1 /* Terminator. */, 0} 00074 }; 00075 00076 /* SH signal handler frame support. */ 00077 00078 static void 00079 sh_linux_sigtramp_cache (struct frame_info *this_frame, 00080 struct trad_frame_cache *this_cache, 00081 CORE_ADDR func, int regs_offset) 00082 { 00083 int i; 00084 struct gdbarch *gdbarch = get_frame_arch (this_frame); 00085 CORE_ADDR base = get_frame_register_unsigned (this_frame, 00086 gdbarch_sp_regnum (gdbarch)); 00087 CORE_ADDR regs = base + regs_offset; 00088 00089 for (i = 0; i < 18; i++) 00090 trad_frame_set_reg_addr (this_cache, i, regs + i * 4); 00091 00092 trad_frame_set_reg_addr (this_cache, SR_REGNUM, regs + 18 * 4); 00093 trad_frame_set_reg_addr (this_cache, GBR_REGNUM, regs + 19 * 4); 00094 trad_frame_set_reg_addr (this_cache, MACH_REGNUM, regs + 20 * 4); 00095 trad_frame_set_reg_addr (this_cache, MACL_REGNUM, regs + 21 * 4); 00096 00097 /* Restore FP state if we have an FPU. */ 00098 if (gdbarch_fp0_regnum (gdbarch) != -1) 00099 { 00100 CORE_ADDR fpregs = regs + 22 * 4; 00101 for (i = FR0_REGNUM; i <= FP_LAST_REGNUM; i++) 00102 trad_frame_set_reg_addr (this_cache, i, fpregs + i * 4); 00103 trad_frame_set_reg_addr (this_cache, FPSCR_REGNUM, fpregs + 32 * 4); 00104 trad_frame_set_reg_addr (this_cache, FPUL_REGNUM, fpregs + 33 * 4); 00105 } 00106 00107 /* Save a frame ID. */ 00108 trad_frame_set_id (this_cache, frame_id_build (base, func)); 00109 } 00110 00111 /* Implement struct tramp_frame "init" callbacks for signal 00112 trampolines on 32-bit SH. */ 00113 00114 static void 00115 sh_linux_sigreturn_init (const struct tramp_frame *self, 00116 struct frame_info *this_frame, 00117 struct trad_frame_cache *this_cache, 00118 CORE_ADDR func) 00119 { 00120 /* SH 32-bit sigframe: sigcontext at start of sigframe, 00121 registers start after a single 'oldmask' word. */ 00122 sh_linux_sigtramp_cache (this_frame, this_cache, func, 4); 00123 } 00124 00125 static void 00126 sh_linux_rt_sigreturn_init (const struct tramp_frame *self, 00127 struct frame_info *this_frame, 00128 struct trad_frame_cache *this_cache, 00129 CORE_ADDR func) 00130 { 00131 /* SH 32-bit rt_sigframe: starts with a siginfo (128 bytes), then 00132 we can find sigcontext embedded within a ucontext (offset 20 bytes). 00133 Then registers start after a single 'oldmask' word. */ 00134 sh_linux_sigtramp_cache (this_frame, this_cache, func, 00135 128 /* sizeof (struct siginfo) */ 00136 + 20 /* offsetof (struct ucontext, uc_mcontext) */ 00137 + 4 /* oldmask word at start of sigcontext */); 00138 } 00139 00140 /* Instruction patterns. */ 00141 #define SH_MOVW 0x9305 00142 #define SH_TRAP 0xc300 00143 #define SH_OR_R0_R0 0x200b 00144 00145 /* SH sigreturn syscall numbers. */ 00146 #define SH_NR_SIGRETURN 0x0077 00147 #define SH_NR_RT_SIGRETURN 0x00ad 00148 00149 static struct tramp_frame sh_linux_sigreturn_tramp_frame = { 00150 SIGTRAMP_FRAME, 00151 2, 00152 { 00153 { SH_MOVW, 0xffff }, 00154 { SH_TRAP, 0xff00 }, /* #imm argument part filtered out. */ 00155 { SH_OR_R0_R0, 0xffff }, 00156 { SH_OR_R0_R0, 0xffff }, 00157 { SH_OR_R0_R0, 0xffff }, 00158 { SH_OR_R0_R0, 0xffff }, 00159 { SH_OR_R0_R0, 0xffff }, 00160 { SH_NR_SIGRETURN, 0xffff }, 00161 { TRAMP_SENTINEL_INSN } 00162 }, 00163 sh_linux_sigreturn_init 00164 }; 00165 00166 static struct tramp_frame sh_linux_rt_sigreturn_tramp_frame = { 00167 SIGTRAMP_FRAME, 00168 2, 00169 { 00170 { SH_MOVW, 0xffff }, 00171 { SH_TRAP, 0xff00 }, /* #imm argument part filtered out. */ 00172 { SH_OR_R0_R0, 0xffff }, 00173 { SH_OR_R0_R0, 0xffff }, 00174 { SH_OR_R0_R0, 0xffff }, 00175 { SH_OR_R0_R0, 0xffff }, 00176 { SH_OR_R0_R0, 0xffff }, 00177 { SH_NR_RT_SIGRETURN, 0xffff }, 00178 { TRAMP_SENTINEL_INSN } 00179 }, 00180 sh_linux_rt_sigreturn_init 00181 }; 00182 00183 static void 00184 sh_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) 00185 { 00186 linux_init_abi (info, gdbarch); 00187 00188 /* GNU/Linux uses SVR4-style shared libraries. */ 00189 set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target); 00190 set_solib_svr4_fetch_link_map_offsets 00191 (gdbarch, svr4_ilp32_fetch_link_map_offsets); 00192 set_gdbarch_skip_solib_resolver (gdbarch, glibc_skip_solib_resolver); 00193 00194 set_gdbarch_fetch_tls_load_module_address (gdbarch, 00195 svr4_fetch_objfile_link_map); 00196 00197 /* Core files and signal handler frame unwinding are supported for 00198 32-bit SH only, at present. */ 00199 if (info.bfd_arch_info->mach != bfd_mach_sh5) 00200 { 00201 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); 00202 00203 tdep->core_gregmap = (struct sh_corefile_regmap *)gregs_table; 00204 tdep->core_fpregmap = (struct sh_corefile_regmap *)fpregs_table; 00205 00206 tramp_frame_prepend_unwinder (gdbarch, &sh_linux_sigreturn_tramp_frame); 00207 tramp_frame_prepend_unwinder (gdbarch, &sh_linux_rt_sigreturn_tramp_frame); 00208 } 00209 } 00210 00211 /* Provide a prototype to silence -Wmissing-prototypes. */ 00212 extern void _initialize_sh_linux_tdep (void); 00213 00214 void 00215 _initialize_sh_linux_tdep (void) 00216 { 00217 gdbarch_register_osabi (bfd_arch_sh, 0, GDB_OSABI_LINUX, sh_linux_init_abi); 00218 }