GDB (API)
|
00001 /* Signal trampoline unwinder, for GDB the GNU Debugger. 00002 00003 Copyright (C) 2004-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 "tramp-frame.h" 00022 #include "frame-unwind.h" 00023 #include "gdbcore.h" 00024 #include "symtab.h" 00025 #include "objfiles.h" 00026 #include "target.h" 00027 #include "trad-frame.h" 00028 #include "frame-base.h" 00029 #include "gdb_assert.h" 00030 00031 struct frame_data 00032 { 00033 const struct tramp_frame *tramp_frame; 00034 }; 00035 00036 struct tramp_frame_cache 00037 { 00038 CORE_ADDR func; 00039 const struct tramp_frame *tramp_frame; 00040 struct trad_frame_cache *trad_cache; 00041 }; 00042 00043 static struct trad_frame_cache * 00044 tramp_frame_cache (struct frame_info *this_frame, 00045 void **this_cache) 00046 { 00047 struct tramp_frame_cache *tramp_cache = (*this_cache); 00048 00049 if (tramp_cache->trad_cache == NULL) 00050 { 00051 tramp_cache->trad_cache = trad_frame_cache_zalloc (this_frame); 00052 tramp_cache->tramp_frame->init (tramp_cache->tramp_frame, 00053 this_frame, 00054 tramp_cache->trad_cache, 00055 tramp_cache->func); 00056 } 00057 return tramp_cache->trad_cache; 00058 } 00059 00060 static void 00061 tramp_frame_this_id (struct frame_info *this_frame, 00062 void **this_cache, 00063 struct frame_id *this_id) 00064 { 00065 struct trad_frame_cache *trad_cache 00066 = tramp_frame_cache (this_frame, this_cache); 00067 00068 trad_frame_get_id (trad_cache, this_id); 00069 } 00070 00071 static struct value * 00072 tramp_frame_prev_register (struct frame_info *this_frame, 00073 void **this_cache, 00074 int prev_regnum) 00075 { 00076 struct trad_frame_cache *trad_cache 00077 = tramp_frame_cache (this_frame, this_cache); 00078 00079 return trad_frame_get_register (trad_cache, this_frame, prev_regnum); 00080 } 00081 00082 static CORE_ADDR 00083 tramp_frame_start (const struct tramp_frame *tramp, 00084 struct frame_info *this_frame, CORE_ADDR pc) 00085 { 00086 struct gdbarch *gdbarch = get_frame_arch (this_frame); 00087 enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); 00088 int ti; 00089 00090 /* Search through the trampoline for one that matches the 00091 instruction sequence around PC. */ 00092 for (ti = 0; tramp->insn[ti].bytes != TRAMP_SENTINEL_INSN; ti++) 00093 { 00094 CORE_ADDR func = pc - tramp->insn_size * ti; 00095 int i; 00096 00097 for (i = 0; 1; i++) 00098 { 00099 gdb_byte buf[sizeof (tramp->insn[0])]; 00100 ULONGEST insn; 00101 00102 if (tramp->insn[i].bytes == TRAMP_SENTINEL_INSN) 00103 return func; 00104 if (!safe_frame_unwind_memory (this_frame, 00105 func + i * tramp->insn_size, 00106 buf, tramp->insn_size)) 00107 break; 00108 insn = extract_unsigned_integer (buf, tramp->insn_size, byte_order); 00109 if (tramp->insn[i].bytes != (insn & tramp->insn[i].mask)) 00110 break; 00111 } 00112 } 00113 /* Trampoline doesn't match. */ 00114 return 0; 00115 } 00116 00117 static int 00118 tramp_frame_sniffer (const struct frame_unwind *self, 00119 struct frame_info *this_frame, 00120 void **this_cache) 00121 { 00122 const struct tramp_frame *tramp = self->unwind_data->tramp_frame; 00123 CORE_ADDR pc = get_frame_pc (this_frame); 00124 CORE_ADDR func; 00125 struct tramp_frame_cache *tramp_cache; 00126 00127 /* tausq/2004-12-12: We used to assume if pc has a name or is in a valid 00128 section, then this is not a trampoline. However, this assumption is 00129 false on HPUX which has a signal trampoline that has a name; it can 00130 also be false when using an alternative signal stack. */ 00131 func = tramp_frame_start (tramp, this_frame, pc); 00132 if (func == 0) 00133 return 0; 00134 tramp_cache = FRAME_OBSTACK_ZALLOC (struct tramp_frame_cache); 00135 tramp_cache->func = func; 00136 tramp_cache->tramp_frame = tramp; 00137 (*this_cache) = tramp_cache; 00138 return 1; 00139 } 00140 00141 void 00142 tramp_frame_prepend_unwinder (struct gdbarch *gdbarch, 00143 const struct tramp_frame *tramp_frame) 00144 { 00145 struct frame_data *data; 00146 struct frame_unwind *unwinder; 00147 int i; 00148 00149 /* Check that the instruction sequence contains a sentinel. */ 00150 for (i = 0; i < ARRAY_SIZE (tramp_frame->insn); i++) 00151 { 00152 if (tramp_frame->insn[i].bytes == TRAMP_SENTINEL_INSN) 00153 break; 00154 } 00155 gdb_assert (i < ARRAY_SIZE (tramp_frame->insn)); 00156 gdb_assert (tramp_frame->insn_size <= sizeof (tramp_frame->insn[0].bytes)); 00157 00158 data = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct frame_data); 00159 unwinder = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct frame_unwind); 00160 00161 data->tramp_frame = tramp_frame; 00162 unwinder->type = tramp_frame->frame_type; 00163 unwinder->unwind_data = data; 00164 unwinder->sniffer = tramp_frame_sniffer; 00165 unwinder->stop_reason = default_frame_unwind_stop_reason; 00166 unwinder->this_id = tramp_frame_this_id; 00167 unwinder->prev_register = tramp_frame_prev_register; 00168 frame_unwind_prepend_unwinder (gdbarch, unwinder); 00169 }