GDB (API)
|
00001 /* Target-dependent code for PowerPC systems running FreeBSD. 00002 00003 Copyright (C) 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 "arch-utils.h" 00022 #include "frame.h" 00023 #include "gdbcore.h" 00024 #include "frame-unwind.h" 00025 #include "gdbtypes.h" 00026 #include "osabi.h" 00027 #include "regcache.h" 00028 #include "regset.h" 00029 #include "symtab.h" 00030 #include "target.h" 00031 #include "trad-frame.h" 00032 00033 #include "gdb_assert.h" 00034 #include "gdb_string.h" 00035 00036 #include "ppc-tdep.h" 00037 #include "ppc64-tdep.h" 00038 #include "ppcfbsd-tdep.h" 00039 #include "solib-svr4.h" 00040 00041 00042 /* 32-bit regset descriptions. */ 00043 00044 static const struct ppc_reg_offsets ppc32_fbsd_reg_offsets = 00045 { 00046 /* General-purpose registers. */ 00047 /* .r0_offset = */ 0, 00048 /* .gpr_size = */ 4, 00049 /* .xr_size = */ 4, 00050 /* .pc_offset = */ 144, 00051 /* .ps_offset = */ -1, 00052 /* .cr_offset = */ 132, 00053 /* .lr_offset = */ 128, 00054 /* .ctr_offset = */ 140, 00055 /* .xer_offset = */ 136, 00056 /* .mq_offset = */ -1, 00057 00058 /* Floating-point registers. */ 00059 /* .f0_offset = */ 0, 00060 /* .fpscr_offset = */ 256, 00061 /* .fpscr_size = */ 8, 00062 #ifdef NOTYET 00063 /* AltiVec registers. */ 00064 /* .vr0_offset = */ 0, 00065 /* .vscr_offset = */ 512 + 12, 00066 /* .vrsave_offset = */ 512 00067 #endif 00068 }; 00069 00070 /* 64-bit regset descriptions. */ 00071 00072 static const struct ppc_reg_offsets ppc64_fbsd_reg_offsets = 00073 { 00074 /* General-purpose registers. */ 00075 /* .r0_offset = */ 0, 00076 /* .gpr_size = */ 8, 00077 /* .xr_size = */ 8, 00078 /* .pc_offset = */ 288, 00079 /* .ps_offset = */ -1, 00080 /* .cr_offset = */ 264, 00081 /* .lr_offset = */ 256, 00082 /* .ctr_offset = */ 280, 00083 /* .xer_offset = */ 272, 00084 /* .mq_offset = */ -1, 00085 00086 /* Floating-point registers. */ 00087 /* .f0_offset = */ 0, 00088 /* .fpscr_offset = */ 256, 00089 /* .fpscr_size = */ 8, 00090 #ifdef NOYET 00091 /* AltiVec registers. */ 00092 /* .vr0_offset = */ 0, 00093 /* .vscr_offset = */ 512 + 12, 00094 /* .vrsave_offset = */ 528 00095 #endif 00096 }; 00097 00098 /* 32-bit general-purpose register set. */ 00099 00100 static const struct regset ppc32_fbsd_gregset = { 00101 &ppc32_fbsd_reg_offsets, 00102 ppc_supply_gregset, 00103 ppc_collect_gregset, 00104 NULL 00105 }; 00106 00107 /* 64-bit general-purpose register set. */ 00108 00109 static const struct regset ppc64_fbsd_gregset = { 00110 &ppc64_fbsd_reg_offsets, 00111 ppc_supply_gregset, 00112 ppc_collect_gregset, 00113 NULL 00114 }; 00115 00116 /* 32-/64-bit floating-point register set. */ 00117 00118 static struct regset ppc32_fbsd_fpregset = { 00119 &ppc32_fbsd_reg_offsets, 00120 ppc_supply_fpregset, 00121 ppc_collect_fpregset 00122 }; 00123 00124 const struct regset * 00125 ppc_fbsd_gregset (int wordsize) 00126 { 00127 return wordsize == 8 ? &ppc64_fbsd_gregset : &ppc32_fbsd_gregset; 00128 } 00129 00130 const struct regset * 00131 ppc_fbsd_fpregset (void) 00132 { 00133 return &ppc32_fbsd_fpregset; 00134 } 00135 00136 /* Return the appropriate register set for the core section identified 00137 by SECT_NAME and SECT_SIZE. */ 00138 00139 static const struct regset * 00140 ppcfbsd_regset_from_core_section (struct gdbarch *gdbarch, 00141 const char *sect_name, size_t sect_size) 00142 { 00143 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); 00144 if (strcmp (sect_name, ".reg") == 0 && sect_size >= 148) 00145 { 00146 if (tdep->wordsize == 4) 00147 return &ppc32_fbsd_gregset; 00148 else 00149 return &ppc64_fbsd_gregset; 00150 } 00151 if (strcmp (sect_name, ".reg2") == 0 && sect_size >= 264) 00152 return &ppc32_fbsd_fpregset; 00153 return NULL; 00154 } 00155 00156 /* Default page size. */ 00157 00158 static const int ppcfbsd_page_size = 4096; 00159 00160 /* Offset for sigreturn(2). */ 00161 00162 static const int ppcfbsd_sigreturn_offset[] = { 00163 0xc, /* FreeBSD 32-bit */ 00164 -1 00165 }; 00166 00167 /* Signal trampolines. */ 00168 00169 static int 00170 ppcfbsd_sigtramp_frame_sniffer (const struct frame_unwind *self, 00171 struct frame_info *this_frame, 00172 void **this_cache) 00173 { 00174 struct gdbarch *gdbarch = get_frame_arch (this_frame); 00175 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); 00176 CORE_ADDR pc = get_frame_pc (this_frame); 00177 CORE_ADDR start_pc = (pc & ~(ppcfbsd_page_size - 1)); 00178 const int *offset; 00179 const char *name; 00180 00181 /* A stack trampoline is detected if no name is associated 00182 to the current pc and if it points inside a trampoline 00183 sequence. */ 00184 00185 find_pc_partial_function (pc, &name, NULL, NULL); 00186 00187 /* If we have a name, we have no trampoline, return. */ 00188 if (name) 00189 return 0; 00190 00191 for (offset = ppcfbsd_sigreturn_offset; *offset != -1; offset++) 00192 { 00193 gdb_byte buf[2 * PPC_INSN_SIZE]; 00194 unsigned long insn; 00195 00196 if (!safe_frame_unwind_memory (this_frame, start_pc + *offset, 00197 buf, sizeof buf)) 00198 continue; 00199 00200 /* Check for "li r0,SYS_sigreturn". */ 00201 insn = extract_unsigned_integer (buf, PPC_INSN_SIZE, byte_order); 00202 if (insn != 0x380001a1) 00203 continue; 00204 00205 /* Check for "sc". */ 00206 insn = extract_unsigned_integer (buf + PPC_INSN_SIZE, 00207 PPC_INSN_SIZE, byte_order); 00208 if (insn != 0x44000002) 00209 continue; 00210 00211 return 1; 00212 } 00213 00214 return 0; 00215 } 00216 00217 static struct trad_frame_cache * 00218 ppcfbsd_sigtramp_frame_cache (struct frame_info *this_frame, void **this_cache) 00219 { 00220 struct gdbarch *gdbarch = get_frame_arch (this_frame); 00221 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); 00222 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); 00223 struct trad_frame_cache *cache; 00224 CORE_ADDR addr, base, func; 00225 gdb_byte buf[PPC_INSN_SIZE]; 00226 int i; 00227 00228 if (*this_cache) 00229 return *this_cache; 00230 00231 cache = trad_frame_cache_zalloc (this_frame); 00232 *this_cache = cache; 00233 00234 func = get_frame_pc (this_frame); 00235 func &= ~(ppcfbsd_page_size - 1); 00236 if (!safe_frame_unwind_memory (this_frame, func, buf, sizeof buf)) 00237 return cache; 00238 00239 base = get_frame_register_unsigned (this_frame, gdbarch_sp_regnum (gdbarch)); 00240 addr = base + 0x10 + 2 * tdep->wordsize; 00241 for (i = 0; i < ppc_num_gprs; i++, addr += tdep->wordsize) 00242 { 00243 int regnum = i + tdep->ppc_gp0_regnum; 00244 trad_frame_set_reg_addr (cache, regnum, addr); 00245 } 00246 trad_frame_set_reg_addr (cache, tdep->ppc_lr_regnum, addr); 00247 addr += tdep->wordsize; 00248 trad_frame_set_reg_addr (cache, tdep->ppc_cr_regnum, addr); 00249 addr += tdep->wordsize; 00250 trad_frame_set_reg_addr (cache, tdep->ppc_xer_regnum, addr); 00251 addr += tdep->wordsize; 00252 trad_frame_set_reg_addr (cache, tdep->ppc_ctr_regnum, addr); 00253 addr += tdep->wordsize; 00254 trad_frame_set_reg_addr (cache, gdbarch_pc_regnum (gdbarch), addr); 00255 /* SRR0? */ 00256 addr += tdep->wordsize; 00257 00258 /* Construct the frame ID using the function start. */ 00259 trad_frame_set_id (cache, frame_id_build (base, func)); 00260 00261 return cache; 00262 } 00263 00264 static void 00265 ppcfbsd_sigtramp_frame_this_id (struct frame_info *this_frame, 00266 void **this_cache, struct frame_id *this_id) 00267 { 00268 struct trad_frame_cache *cache = 00269 ppcfbsd_sigtramp_frame_cache (this_frame, this_cache); 00270 00271 trad_frame_get_id (cache, this_id); 00272 } 00273 00274 static struct value * 00275 ppcfbsd_sigtramp_frame_prev_register (struct frame_info *this_frame, 00276 void **this_cache, int regnum) 00277 { 00278 struct trad_frame_cache *cache = 00279 ppcfbsd_sigtramp_frame_cache (this_frame, this_cache); 00280 00281 return trad_frame_get_register (cache, this_frame, regnum); 00282 } 00283 00284 static const struct frame_unwind ppcfbsd_sigtramp_frame_unwind = { 00285 SIGTRAMP_FRAME, 00286 default_frame_unwind_stop_reason, 00287 ppcfbsd_sigtramp_frame_this_id, 00288 ppcfbsd_sigtramp_frame_prev_register, 00289 NULL, 00290 ppcfbsd_sigtramp_frame_sniffer 00291 }; 00292 00293 static enum return_value_convention 00294 ppcfbsd_return_value (struct gdbarch *gdbarch, struct value *function, 00295 struct type *valtype, struct regcache *regcache, 00296 gdb_byte *readbuf, const gdb_byte *writebuf) 00297 { 00298 return ppc_sysv_abi_broken_return_value (gdbarch, function, valtype, 00299 regcache, readbuf, writebuf); 00300 } 00301 00302 00303 static void 00304 ppcfbsd_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) 00305 { 00306 struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); 00307 00308 /* FreeBSD doesn't support the 128-bit `long double' from the psABI. */ 00309 set_gdbarch_long_double_bit (gdbarch, 64); 00310 set_gdbarch_long_double_format (gdbarch, floatformats_ieee_double); 00311 00312 if (tdep->wordsize == 4) 00313 { 00314 set_gdbarch_return_value (gdbarch, ppcfbsd_return_value); 00315 00316 set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target); 00317 set_solib_svr4_fetch_link_map_offsets (gdbarch, 00318 svr4_ilp32_fetch_link_map_offsets); 00319 00320 frame_unwind_append_unwinder (gdbarch, &ppcfbsd_sigtramp_frame_unwind); 00321 set_gdbarch_gcore_bfd_target (gdbarch, "elf32-powerpc"); 00322 } 00323 00324 if (tdep->wordsize == 8) 00325 { 00326 set_gdbarch_convert_from_func_ptr_addr 00327 (gdbarch, ppc64_convert_from_func_ptr_addr); 00328 set_gdbarch_elf_make_msymbol_special (gdbarch, 00329 ppc64_elf_make_msymbol_special); 00330 00331 set_gdbarch_skip_trampoline_code (gdbarch, ppc64_skip_trampoline_code); 00332 set_solib_svr4_fetch_link_map_offsets (gdbarch, 00333 svr4_lp64_fetch_link_map_offsets); 00334 set_gdbarch_gcore_bfd_target (gdbarch, "elf64-powerpc"); 00335 } 00336 00337 set_gdbarch_regset_from_core_section 00338 (gdbarch, ppcfbsd_regset_from_core_section); 00339 00340 set_gdbarch_fetch_tls_load_module_address (gdbarch, 00341 svr4_fetch_objfile_link_map); 00342 } 00343 00344 /* Provide a prototype to silence -Wmissing-prototypes. */ 00345 00346 void _initialize_ppcfbsd_tdep (void); 00347 00348 void 00349 _initialize_ppcfbsd_tdep (void) 00350 { 00351 gdbarch_register_osabi (bfd_arch_powerpc, bfd_mach_ppc, GDB_OSABI_FREEBSD_ELF, 00352 ppcfbsd_init_abi); 00353 gdbarch_register_osabi (bfd_arch_powerpc, bfd_mach_ppc64, 00354 GDB_OSABI_FREEBSD_ELF, 00355 ppcfbsd_init_abi); 00356 gdbarch_register_osabi (bfd_arch_rs6000, 0, GDB_OSABI_FREEBSD_ELF, 00357 ppcfbsd_init_abi); 00358 }