1 /* Target-dependent code for Xilinx MicroBlaze. 2 3 Copyright (C) 2009-2023 Free Software Foundation, Inc. 4 5 This file is part of GDB. 6 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 9 the Free Software Foundation; either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 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/>. */ 19 20 #include "defs.h" 21 #include "frame.h" 22 #include "inferior.h" 23 #include "symtab.h" 24 #include "target.h" 25 #include "gdbcore.h" 26 #include "gdbcmd.h" 27 #include "symfile.h" 28 #include "objfiles.h" 29 #include "regcache.h" 30 #include "value.h" 31 #include "osabi.h" 32 #include "regset.h" 33 #include "solib-svr4.h" 34 #include "microblaze-tdep.h" 35 #include "trad-frame.h" 36 #include "frame-unwind.h" 37 #include "tramp-frame.h" 38 #include "linux-tdep.h" 39 40 static int 41 microblaze_linux_memory_remove_breakpoint (struct gdbarch *gdbarch, 42 struct bp_target_info *bp_tgt) 43 { 44 CORE_ADDR addr = bp_tgt->reqstd_address; 45 const gdb_byte *bp; 46 int val; 47 int bplen; 48 gdb_byte old_contents[BREAKPOINT_MAX]; 49 50 /* Determine appropriate breakpoint contents and size for this address. */ 51 bp = gdbarch_breakpoint_from_pc (gdbarch, &addr, &bplen); 52 53 val = target_read_memory (addr, old_contents, bplen); 54 55 /* If our breakpoint is no longer at the address, this means that the 56 program modified the code on us, so it is wrong to put back the 57 old value. */ 58 if (val == 0 && memcmp (bp, old_contents, bplen) == 0) 59 val = target_write_raw_memory (addr, bp_tgt->shadow_contents, bplen); 60 61 return val; 62 } 63 64 static void 65 microblaze_linux_sigtramp_cache (frame_info_ptr next_frame, 66 struct trad_frame_cache *this_cache, 67 CORE_ADDR func, LONGEST offset, 68 int bias) 69 { 70 CORE_ADDR base; 71 CORE_ADDR gpregs; 72 int regnum; 73 74 base = frame_unwind_register_unsigned (next_frame, MICROBLAZE_SP_REGNUM); 75 if (bias > 0 && get_frame_address_in_block (next_frame) != func) 76 /* See below, some signal trampolines increment the stack as their 77 first instruction, need to compensate for that. */ 78 base -= bias; 79 80 /* Find the address of the register buffer. */ 81 gpregs = base + offset; 82 83 /* Registers saved on stack. */ 84 for (regnum = 0; regnum < MICROBLAZE_BTR_REGNUM; regnum++) 85 trad_frame_set_reg_addr (this_cache, regnum, 86 gpregs + regnum * MICROBLAZE_REGISTER_SIZE); 87 trad_frame_set_id (this_cache, frame_id_build (base, func)); 88 } 89 90 91 static void 92 microblaze_linux_sighandler_cache_init (const struct tramp_frame *self, 93 frame_info_ptr next_frame, 94 struct trad_frame_cache *this_cache, 95 CORE_ADDR func) 96 { 97 microblaze_linux_sigtramp_cache (next_frame, this_cache, func, 98 0 /* Offset to ucontext_t. */ 99 + 24 /* Offset to .reg. */, 100 0); 101 } 102 103 static struct tramp_frame microblaze_linux_sighandler_tramp_frame = 104 { 105 SIGTRAMP_FRAME, 106 4, 107 { 108 { 0x31800077, ULONGEST_MAX }, /* addik R12,R0,119. */ 109 { 0xb9cc0008, ULONGEST_MAX }, /* brki R14,8. */ 110 { TRAMP_SENTINEL_INSN }, 111 }, 112 microblaze_linux_sighandler_cache_init 113 }; 114 115 116 static void 117 microblaze_linux_init_abi (struct gdbarch_info info, 118 struct gdbarch *gdbarch) 119 { 120 linux_init_abi (info, gdbarch, 0); 121 122 set_gdbarch_memory_remove_breakpoint (gdbarch, 123 microblaze_linux_memory_remove_breakpoint); 124 125 /* Shared library handling. */ 126 set_solib_svr4_fetch_link_map_offsets (gdbarch, 127 linux_ilp32_fetch_link_map_offsets); 128 129 /* Trampolines. */ 130 tramp_frame_prepend_unwinder (gdbarch, 131 µblaze_linux_sighandler_tramp_frame); 132 } 133 134 void _initialize_microblaze_linux_tdep (); 135 void 136 _initialize_microblaze_linux_tdep () 137 { 138 gdbarch_register_osabi (bfd_arch_microblaze, 0, GDB_OSABI_LINUX, 139 microblaze_linux_init_abi); 140 } 141