GDB (API)
|
00001 /* Target-dependent code for Analog Devices Blackfin processor, for GDB. 00002 00003 Copyright (C) 2005-2013 Free Software Foundation, Inc. 00004 00005 Contributed by Analog Devices, Inc. 00006 00007 This file is part of GDB. 00008 00009 This program is free software; you can redistribute it and/or modify 00010 it under the terms of the GNU General Public License as published by 00011 the Free Software Foundation; either version 3 of the License, or 00012 (at your option) any later version. 00013 00014 This program is distributed in the hope that it will be useful, 00015 but WITHOUT ANY WARRANTY; without even the implied warranty of 00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00017 GNU General Public License for more details. 00018 00019 You should have received a copy of the GNU General Public License 00020 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 00021 00022 #include "defs.h" 00023 #include "arch-utils.h" 00024 #include "regcache.h" 00025 #include "tramp-frame.h" 00026 #include "trad-frame.h" 00027 #include "osabi.h" 00028 #include "xml-syscall.h" 00029 #include "linux-tdep.h" 00030 #include "bfin-tdep.h" 00031 00032 /* From <asm/sigcontext.h>. */ 00033 00034 #define SIGCONTEXT_OFFSET 168 00035 00036 static const int bfin_linux_sigcontext_reg_offset[BFIN_NUM_REGS] = 00037 { 00038 0 * 4, /* %r0 */ 00039 1 * 4, /* %r1 */ 00040 2 * 4, /* %r2 */ 00041 3 * 4, /* %r3 */ 00042 4 * 4, /* %r4 */ 00043 5 * 4, /* %r5 */ 00044 6 * 4, /* %r6 */ 00045 7 * 4, /* %r7 */ 00046 8 * 4, /* %p0 */ 00047 9 * 4, /* %p1 */ 00048 10 * 4, /* %p2 */ 00049 11 * 4, /* %p3 */ 00050 12 * 4, /* %p4 */ 00051 13 * 4, /* %p5 */ 00052 14 * 4, /* %sp */ 00053 23 * 4, /* %fp */ 00054 24 * 4, /* %i0 */ 00055 25 * 4, /* %i1 */ 00056 26 * 4, /* %i2 */ 00057 27 * 4, /* %i3 */ 00058 28 * 4, /* %m0 */ 00059 29 * 4, /* %m1 */ 00060 30 * 4, /* %m2 */ 00061 31 * 4, /* %m3 */ 00062 36 * 4, /* %b0 */ 00063 37 * 4, /* %b1 */ 00064 38 * 4, /* %b2 */ 00065 39 * 4, /* %b3 */ 00066 32 * 4, /* %l0 */ 00067 33 * 4, /* %l1 */ 00068 34 * 4, /* %l2 */ 00069 35 * 4, /* %l3 */ 00070 17 * 4, /* %a0x */ 00071 15 * 4, /* %a0w */ 00072 18 * 4, /* %a1x */ 00073 16 * 4, /* %a1w */ 00074 19 * 4, /* %astat */ 00075 20 * 4, /* %rets */ 00076 40 * 4, /* %lc0 */ 00077 42 * 4, /* %lt0 */ 00078 44 * 4, /* %lb0 */ 00079 41 * 4, /* %lc1 */ 00080 43 * 4, /* %lt1 */ 00081 45 * 4, /* %lb1 */ 00082 -1, /* %cycles */ 00083 -1, /* %cycles2 */ 00084 -1, /* %usp */ 00085 46 * 4, /* %seqstat */ 00086 -1, /* syscfg */ 00087 21 * 4, /* %reti */ 00088 22 * 4, /* %retx */ 00089 -1, /* %retn */ 00090 -1, /* %rete */ 00091 21 * 4, /* %pc */ 00092 }; 00093 00094 /* Signal trampolines. */ 00095 00096 static void 00097 bfin_linux_sigframe_init (const struct tramp_frame *self, 00098 struct frame_info *this_frame, 00099 struct trad_frame_cache *this_cache, 00100 CORE_ADDR func) 00101 { 00102 struct gdbarch *gdbarch = get_frame_arch (this_frame); 00103 CORE_ADDR sp = get_frame_sp (this_frame); 00104 CORE_ADDR pc = get_frame_pc (this_frame); 00105 CORE_ADDR sigcontext = sp + SIGCONTEXT_OFFSET; 00106 const int *reg_offset = bfin_linux_sigcontext_reg_offset; 00107 int i; 00108 00109 for (i = 0; i < BFIN_NUM_REGS; i++) 00110 if (reg_offset[i] != -1) 00111 trad_frame_set_reg_addr (this_cache, i, sigcontext + reg_offset[i]); 00112 00113 /* This would come after the LINK instruction in the ret_from_signal 00114 function, hence the frame id would be SP + 8. */ 00115 trad_frame_set_id (this_cache, frame_id_build (sp + 8, pc)); 00116 } 00117 00118 static const struct tramp_frame bfin_linux_sigframe = 00119 { 00120 SIGTRAMP_FRAME, 00121 4, 00122 { 00123 { 0x00ADE128, 0xffffffff }, /* P0 = __NR_rt_sigreturn; */ 00124 { 0x00A0, 0xffff }, /* EXCPT 0; */ 00125 { TRAMP_SENTINEL_INSN, -1 }, 00126 }, 00127 bfin_linux_sigframe_init, 00128 }; 00129 00130 static LONGEST 00131 bfin_linux_get_syscall_number (struct gdbarch *gdbarch, 00132 ptid_t ptid) 00133 { 00134 struct regcache *regcache = get_thread_regcache (ptid); 00135 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); 00136 /* The content of a register. */ 00137 gdb_byte buf[4]; 00138 /* The result. */ 00139 LONGEST ret; 00140 00141 /* Getting the system call number from the register. 00142 When dealing with Blackfin architecture, this information 00143 is stored at %p0 register. */ 00144 regcache_cooked_read (regcache, BFIN_P0_REGNUM, buf); 00145 00146 ret = extract_signed_integer (buf, 4, byte_order); 00147 00148 return ret; 00149 } 00150 00151 static void 00152 bfin_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) 00153 { 00154 linux_init_abi (info, gdbarch); 00155 00156 /* Set the sigtramp frame sniffer. */ 00157 tramp_frame_prepend_unwinder (gdbarch, &bfin_linux_sigframe); 00158 00159 /* Functions for 'catch syscall'. */ 00160 set_xml_syscall_file_name ("syscalls/bfin-linux.xml"); 00161 set_gdbarch_get_syscall_number (gdbarch, 00162 bfin_linux_get_syscall_number); 00163 } 00164 00165 /* Provide a prototype to silence -Wmissing-prototypes. */ 00166 extern initialize_file_ftype _initialize_bfin_linux_tdep; 00167 00168 void 00169 _initialize_bfin_linux_tdep (void) 00170 { 00171 gdbarch_register_osabi (bfd_arch_bfin, 0, GDB_OSABI_LINUX, 00172 bfin_linux_init_abi); 00173 }