xref: /openbsd-src/gnu/usr.bin/binutils/gdb/alpha-mdebug-tdep.c (revision b725ae7711052a2233e31a66fefb8a752c388d7a)
1*b725ae77Skettenis /* Target-dependent mdebug code for the ALPHA architecture.
2*b725ae77Skettenis    Copyright 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
3*b725ae77Skettenis    Free Software Foundation, Inc.
4*b725ae77Skettenis 
5*b725ae77Skettenis    This file is part of GDB.
6*b725ae77Skettenis 
7*b725ae77Skettenis    This program is free software; you can redistribute it and/or modify
8*b725ae77Skettenis    it under the terms of the GNU General Public License as published by
9*b725ae77Skettenis    the Free Software Foundation; either version 2 of the License, or
10*b725ae77Skettenis    (at your option) any later version.
11*b725ae77Skettenis 
12*b725ae77Skettenis    This program is distributed in the hope that it will be useful,
13*b725ae77Skettenis    but WITHOUT ANY WARRANTY; without even the implied warranty of
14*b725ae77Skettenis    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15*b725ae77Skettenis    GNU General Public License for more details.
16*b725ae77Skettenis 
17*b725ae77Skettenis    You should have received a copy of the GNU General Public License
18*b725ae77Skettenis    along with this program; if not, write to the Free Software
19*b725ae77Skettenis    Foundation, Inc., 59 Temple Place - Suite 330,
20*b725ae77Skettenis    Boston, MA 02111-1307, USA.  */
21*b725ae77Skettenis 
22*b725ae77Skettenis #include "defs.h"
23*b725ae77Skettenis #include "frame.h"
24*b725ae77Skettenis #include "frame-unwind.h"
25*b725ae77Skettenis #include "frame-base.h"
26*b725ae77Skettenis #include "symtab.h"
27*b725ae77Skettenis #include "gdbcore.h"
28*b725ae77Skettenis #include "block.h"
29*b725ae77Skettenis #include "gdb_assert.h"
30*b725ae77Skettenis 
31*b725ae77Skettenis #include "alpha-tdep.h"
32*b725ae77Skettenis 
33*b725ae77Skettenis /* FIXME: Some of this code should perhaps be merged with mips.  */
34*b725ae77Skettenis 
35*b725ae77Skettenis /* *INDENT-OFF* */
36*b725ae77Skettenis /* Layout of a stack frame on the alpha:
37*b725ae77Skettenis 
38*b725ae77Skettenis                 |				|
39*b725ae77Skettenis  pdr members:	|  7th ... nth arg,		|
40*b725ae77Skettenis                 |  `pushed' by caller.		|
41*b725ae77Skettenis                 |				|
42*b725ae77Skettenis ----------------|-------------------------------|<--  old_sp == vfp
43*b725ae77Skettenis    ^  ^  ^  ^	|				|
44*b725ae77Skettenis    |  |  |  |	|				|
45*b725ae77Skettenis    |  |localoff	|  Copies of 1st .. 6th		|
46*b725ae77Skettenis    |  |  |  |	|  argument if necessary.	|
47*b725ae77Skettenis    |  |  |  v	|				|
48*b725ae77Skettenis    |  |  |  ---	|-------------------------------|<-- LOCALS_ADDRESS
49*b725ae77Skettenis    |  |  |      |				|
50*b725ae77Skettenis    |  |  |      |  Locals and temporaries.	|
51*b725ae77Skettenis    |  |  |      |				|
52*b725ae77Skettenis    |  |  |      |-------------------------------|
53*b725ae77Skettenis    |  |  |      |				|
54*b725ae77Skettenis    |-fregoffset	|  Saved float registers.	|
55*b725ae77Skettenis    |  |  |      |  F9				|
56*b725ae77Skettenis    |  |  |      |   .				|
57*b725ae77Skettenis    |  |  |      |   .				|
58*b725ae77Skettenis    |  |  |      |  F2				|
59*b725ae77Skettenis    |  |  v      |				|
60*b725ae77Skettenis    |  |  -------|-------------------------------|
61*b725ae77Skettenis    |  |         |				|
62*b725ae77Skettenis    |  |         |  Saved registers.		|
63*b725ae77Skettenis    |  |         |  S6				|
64*b725ae77Skettenis    |-regoffset	|   .				|
65*b725ae77Skettenis    |  |         |   .				|
66*b725ae77Skettenis    |  |         |  S0				|
67*b725ae77Skettenis    |  |         |  pdr.pcreg			|
68*b725ae77Skettenis    |  v         |				|
69*b725ae77Skettenis    |  ----------|-------------------------------|
70*b725ae77Skettenis    |            |				|
71*b725ae77Skettenis  frameoffset    |  Argument build area, gets	|
72*b725ae77Skettenis    |            |  7th ... nth arg for any	|
73*b725ae77Skettenis    |            |  called procedure.		|
74*b725ae77Skettenis    v            |  				|
75*b725ae77Skettenis    -------------|-------------------------------|<-- sp
76*b725ae77Skettenis                 |				|
77*b725ae77Skettenis */
78*b725ae77Skettenis /* *INDENT-ON* */
79*b725ae77Skettenis 
80*b725ae77Skettenis #define PROC_LOW_ADDR(proc) ((proc)->pdr.adr)
81*b725ae77Skettenis #define PROC_FRAME_OFFSET(proc) ((proc)->pdr.frameoffset)
82*b725ae77Skettenis #define PROC_FRAME_REG(proc) ((proc)->pdr.framereg)
83*b725ae77Skettenis #define PROC_REG_MASK(proc) ((proc)->pdr.regmask)
84*b725ae77Skettenis #define PROC_FREG_MASK(proc) ((proc)->pdr.fregmask)
85*b725ae77Skettenis #define PROC_REG_OFFSET(proc) ((proc)->pdr.regoffset)
86*b725ae77Skettenis #define PROC_FREG_OFFSET(proc) ((proc)->pdr.fregoffset)
87*b725ae77Skettenis #define PROC_PC_REG(proc) ((proc)->pdr.pcreg)
88*b725ae77Skettenis #define PROC_LOCALOFF(proc) ((proc)->pdr.localoff)
89*b725ae77Skettenis 
90*b725ae77Skettenis /* Locate the mdebug PDR for the given PC.  Return null if one can't
91*b725ae77Skettenis    be found; you'll have to fall back to other methods in that case.  */
92*b725ae77Skettenis 
93*b725ae77Skettenis static alpha_extra_func_info_t
find_proc_desc(CORE_ADDR pc)94*b725ae77Skettenis find_proc_desc (CORE_ADDR pc)
95*b725ae77Skettenis {
96*b725ae77Skettenis   struct block *b = block_for_pc (pc);
97*b725ae77Skettenis   alpha_extra_func_info_t proc_desc = NULL;
98*b725ae77Skettenis   struct symbol *sym = NULL;
99*b725ae77Skettenis 
100*b725ae77Skettenis   if (b)
101*b725ae77Skettenis     {
102*b725ae77Skettenis       CORE_ADDR startaddr;
103*b725ae77Skettenis       find_pc_partial_function (pc, NULL, &startaddr, NULL);
104*b725ae77Skettenis 
105*b725ae77Skettenis       if (startaddr > BLOCK_START (b))
106*b725ae77Skettenis 	/* This is the "pathological" case referred to in a comment in
107*b725ae77Skettenis 	   print_frame_info.  It might be better to move this check into
108*b725ae77Skettenis 	   symbol reading.  */
109*b725ae77Skettenis 	sym = NULL;
110*b725ae77Skettenis       else
111*b725ae77Skettenis 	sym = lookup_symbol (MIPS_EFI_SYMBOL_NAME, b, LABEL_DOMAIN, 0, NULL);
112*b725ae77Skettenis     }
113*b725ae77Skettenis 
114*b725ae77Skettenis   if (sym)
115*b725ae77Skettenis     {
116*b725ae77Skettenis       proc_desc = (alpha_extra_func_info_t) SYMBOL_VALUE (sym);
117*b725ae77Skettenis 
118*b725ae77Skettenis       /* If we never found a PDR for this function in symbol reading,
119*b725ae77Skettenis 	 then examine prologues to find the information.  */
120*b725ae77Skettenis       if (proc_desc->pdr.framereg == -1)
121*b725ae77Skettenis 	proc_desc = NULL;
122*b725ae77Skettenis     }
123*b725ae77Skettenis 
124*b725ae77Skettenis   return proc_desc;
125*b725ae77Skettenis }
126*b725ae77Skettenis 
127*b725ae77Skettenis /* This returns the PC of the first inst after the prologue.  If we can't
128*b725ae77Skettenis    find the prologue, then return 0.  */
129*b725ae77Skettenis 
130*b725ae77Skettenis static CORE_ADDR
alpha_mdebug_after_prologue(CORE_ADDR pc,alpha_extra_func_info_t proc_desc)131*b725ae77Skettenis alpha_mdebug_after_prologue (CORE_ADDR pc, alpha_extra_func_info_t proc_desc)
132*b725ae77Skettenis {
133*b725ae77Skettenis   if (proc_desc)
134*b725ae77Skettenis     {
135*b725ae77Skettenis       /* If function is frameless, then we need to do it the hard way.  I
136*b725ae77Skettenis          strongly suspect that frameless always means prologueless... */
137*b725ae77Skettenis       if (PROC_FRAME_REG (proc_desc) == ALPHA_SP_REGNUM
138*b725ae77Skettenis 	  && PROC_FRAME_OFFSET (proc_desc) == 0)
139*b725ae77Skettenis 	return 0;
140*b725ae77Skettenis     }
141*b725ae77Skettenis 
142*b725ae77Skettenis   return alpha_after_prologue (pc);
143*b725ae77Skettenis }
144*b725ae77Skettenis 
145*b725ae77Skettenis /* Return non-zero if we *might* be in a function prologue.  Return zero
146*b725ae77Skettenis    if we are definitively *not* in a function prologue.  */
147*b725ae77Skettenis 
148*b725ae77Skettenis static int
alpha_mdebug_in_prologue(CORE_ADDR pc,alpha_extra_func_info_t proc_desc)149*b725ae77Skettenis alpha_mdebug_in_prologue (CORE_ADDR pc, alpha_extra_func_info_t proc_desc)
150*b725ae77Skettenis {
151*b725ae77Skettenis   CORE_ADDR after_prologue_pc = alpha_mdebug_after_prologue (pc, proc_desc);
152*b725ae77Skettenis   return (after_prologue_pc == 0 || pc < after_prologue_pc);
153*b725ae77Skettenis }
154*b725ae77Skettenis 
155*b725ae77Skettenis 
156*b725ae77Skettenis /* Frame unwinder that reads mdebug PDRs.  */
157*b725ae77Skettenis 
158*b725ae77Skettenis struct alpha_mdebug_unwind_cache
159*b725ae77Skettenis {
160*b725ae77Skettenis   alpha_extra_func_info_t proc_desc;
161*b725ae77Skettenis   CORE_ADDR vfp;
162*b725ae77Skettenis   CORE_ADDR *saved_regs;
163*b725ae77Skettenis };
164*b725ae77Skettenis 
165*b725ae77Skettenis /* Extract all of the information about the frame from PROC_DESC
166*b725ae77Skettenis    and store the resulting register save locations in the structure.  */
167*b725ae77Skettenis 
168*b725ae77Skettenis static struct alpha_mdebug_unwind_cache *
alpha_mdebug_frame_unwind_cache(struct frame_info * next_frame,void ** this_prologue_cache)169*b725ae77Skettenis alpha_mdebug_frame_unwind_cache (struct frame_info *next_frame,
170*b725ae77Skettenis 				 void **this_prologue_cache)
171*b725ae77Skettenis {
172*b725ae77Skettenis   struct alpha_mdebug_unwind_cache *info;
173*b725ae77Skettenis   alpha_extra_func_info_t proc_desc;
174*b725ae77Skettenis   ULONGEST vfp;
175*b725ae77Skettenis   CORE_ADDR pc, reg_position;
176*b725ae77Skettenis   unsigned long mask;
177*b725ae77Skettenis   int ireg, returnreg;
178*b725ae77Skettenis 
179*b725ae77Skettenis   if (*this_prologue_cache)
180*b725ae77Skettenis     return *this_prologue_cache;
181*b725ae77Skettenis 
182*b725ae77Skettenis   info = FRAME_OBSTACK_ZALLOC (struct alpha_mdebug_unwind_cache);
183*b725ae77Skettenis   *this_prologue_cache = info;
184*b725ae77Skettenis   pc = frame_pc_unwind (next_frame);
185*b725ae77Skettenis 
186*b725ae77Skettenis   /* ??? We don't seem to be able to cache the lookup of the PDR
187*b725ae77Skettenis      from alpha_mdebug_frame_p.  It'd be nice if we could change
188*b725ae77Skettenis      the arguments to that function.  Oh well.  */
189*b725ae77Skettenis   proc_desc = find_proc_desc (pc);
190*b725ae77Skettenis   info->proc_desc = proc_desc;
191*b725ae77Skettenis   gdb_assert (proc_desc != NULL);
192*b725ae77Skettenis 
193*b725ae77Skettenis   info->saved_regs = frame_obstack_zalloc (SIZEOF_FRAME_SAVED_REGS);
194*b725ae77Skettenis 
195*b725ae77Skettenis   /* The VFP of the frame is at FRAME_REG+FRAME_OFFSET.  */
196*b725ae77Skettenis   frame_unwind_unsigned_register (next_frame, PROC_FRAME_REG (proc_desc), &vfp);
197*b725ae77Skettenis   vfp += PROC_FRAME_OFFSET (info->proc_desc);
198*b725ae77Skettenis   info->vfp = vfp;
199*b725ae77Skettenis 
200*b725ae77Skettenis   /* Fill in the offsets for the registers which gen_mask says were saved.  */
201*b725ae77Skettenis 
202*b725ae77Skettenis   reg_position = vfp + PROC_REG_OFFSET (proc_desc);
203*b725ae77Skettenis   mask = PROC_REG_MASK (proc_desc);
204*b725ae77Skettenis   returnreg = PROC_PC_REG (proc_desc);
205*b725ae77Skettenis 
206*b725ae77Skettenis   /* Note that RA is always saved first, regardless of its actual
207*b725ae77Skettenis      register number.  */
208*b725ae77Skettenis   if (mask & (1 << returnreg))
209*b725ae77Skettenis     {
210*b725ae77Skettenis       /* Clear bit for RA so we don't save it again later. */
211*b725ae77Skettenis       mask &= ~(1 << returnreg);
212*b725ae77Skettenis 
213*b725ae77Skettenis       info->saved_regs[returnreg] = reg_position;
214*b725ae77Skettenis       reg_position += 8;
215*b725ae77Skettenis     }
216*b725ae77Skettenis 
217*b725ae77Skettenis   for (ireg = 0; ireg <= 31; ++ireg)
218*b725ae77Skettenis     if (mask & (1 << ireg))
219*b725ae77Skettenis       {
220*b725ae77Skettenis 	info->saved_regs[ireg] = reg_position;
221*b725ae77Skettenis 	reg_position += 8;
222*b725ae77Skettenis       }
223*b725ae77Skettenis 
224*b725ae77Skettenis   reg_position = vfp + PROC_FREG_OFFSET (proc_desc);
225*b725ae77Skettenis   mask = PROC_FREG_MASK (proc_desc);
226*b725ae77Skettenis 
227*b725ae77Skettenis   for (ireg = 0; ireg <= 31; ++ireg)
228*b725ae77Skettenis     if (mask & (1 << ireg))
229*b725ae77Skettenis       {
230*b725ae77Skettenis 	info->saved_regs[ALPHA_FP0_REGNUM + ireg] = reg_position;
231*b725ae77Skettenis 	reg_position += 8;
232*b725ae77Skettenis       }
233*b725ae77Skettenis 
234*b725ae77Skettenis   return info;
235*b725ae77Skettenis }
236*b725ae77Skettenis 
237*b725ae77Skettenis /* Given a GDB frame, determine the address of the calling function's
238*b725ae77Skettenis    frame.  This will be used to create a new GDB frame struct.  */
239*b725ae77Skettenis 
240*b725ae77Skettenis static void
alpha_mdebug_frame_this_id(struct frame_info * next_frame,void ** this_prologue_cache,struct frame_id * this_id)241*b725ae77Skettenis alpha_mdebug_frame_this_id (struct frame_info *next_frame,
242*b725ae77Skettenis 			    void **this_prologue_cache,
243*b725ae77Skettenis 			    struct frame_id *this_id)
244*b725ae77Skettenis {
245*b725ae77Skettenis   struct alpha_mdebug_unwind_cache *info
246*b725ae77Skettenis     = alpha_mdebug_frame_unwind_cache (next_frame, this_prologue_cache);
247*b725ae77Skettenis 
248*b725ae77Skettenis   *this_id = frame_id_build (info->vfp, frame_func_unwind (next_frame));
249*b725ae77Skettenis }
250*b725ae77Skettenis 
251*b725ae77Skettenis /* Retrieve the value of REGNUM in FRAME.  Don't give up!  */
252*b725ae77Skettenis 
253*b725ae77Skettenis static void
alpha_mdebug_frame_prev_register(struct frame_info * next_frame,void ** this_prologue_cache,int regnum,int * optimizedp,enum lval_type * lvalp,CORE_ADDR * addrp,int * realnump,void * bufferp)254*b725ae77Skettenis alpha_mdebug_frame_prev_register (struct frame_info *next_frame,
255*b725ae77Skettenis 				  void **this_prologue_cache,
256*b725ae77Skettenis 				  int regnum, int *optimizedp,
257*b725ae77Skettenis 				  enum lval_type *lvalp, CORE_ADDR *addrp,
258*b725ae77Skettenis 				  int *realnump, void *bufferp)
259*b725ae77Skettenis {
260*b725ae77Skettenis   struct alpha_mdebug_unwind_cache *info
261*b725ae77Skettenis     = alpha_mdebug_frame_unwind_cache (next_frame, this_prologue_cache);
262*b725ae77Skettenis 
263*b725ae77Skettenis   /* The PC of the previous frame is stored in the link register of
264*b725ae77Skettenis      the current frame.  Frob regnum so that we pull the value from
265*b725ae77Skettenis      the correct place.  */
266*b725ae77Skettenis   if (regnum == ALPHA_PC_REGNUM)
267*b725ae77Skettenis     regnum = PROC_PC_REG (info->proc_desc);
268*b725ae77Skettenis 
269*b725ae77Skettenis   /* For all registers known to be saved in the current frame,
270*b725ae77Skettenis      do the obvious and pull the value out.  */
271*b725ae77Skettenis   if (info->saved_regs[regnum])
272*b725ae77Skettenis     {
273*b725ae77Skettenis       *optimizedp = 0;
274*b725ae77Skettenis       *lvalp = lval_memory;
275*b725ae77Skettenis       *addrp = info->saved_regs[regnum];
276*b725ae77Skettenis       *realnump = -1;
277*b725ae77Skettenis       if (bufferp != NULL)
278*b725ae77Skettenis 	get_frame_memory (next_frame, *addrp, bufferp, ALPHA_REGISTER_SIZE);
279*b725ae77Skettenis       return;
280*b725ae77Skettenis     }
281*b725ae77Skettenis 
282*b725ae77Skettenis   /* The stack pointer of the previous frame is computed by popping
283*b725ae77Skettenis      the current stack frame.  */
284*b725ae77Skettenis   if (regnum == ALPHA_SP_REGNUM)
285*b725ae77Skettenis     {
286*b725ae77Skettenis       *optimizedp = 0;
287*b725ae77Skettenis       *lvalp = not_lval;
288*b725ae77Skettenis       *addrp = 0;
289*b725ae77Skettenis       *realnump = -1;
290*b725ae77Skettenis       if (bufferp != NULL)
291*b725ae77Skettenis 	store_unsigned_integer (bufferp, ALPHA_REGISTER_SIZE, info->vfp);
292*b725ae77Skettenis       return;
293*b725ae77Skettenis     }
294*b725ae77Skettenis 
295*b725ae77Skettenis   /* Otherwise assume the next frame has the same register value.  */
296*b725ae77Skettenis   frame_register (next_frame, regnum, optimizedp, lvalp, addrp,
297*b725ae77Skettenis   		  realnump, bufferp);
298*b725ae77Skettenis }
299*b725ae77Skettenis 
300*b725ae77Skettenis static const struct frame_unwind alpha_mdebug_frame_unwind = {
301*b725ae77Skettenis   NORMAL_FRAME,
302*b725ae77Skettenis   alpha_mdebug_frame_this_id,
303*b725ae77Skettenis   alpha_mdebug_frame_prev_register
304*b725ae77Skettenis };
305*b725ae77Skettenis 
306*b725ae77Skettenis const struct frame_unwind *
alpha_mdebug_frame_sniffer(struct frame_info * next_frame)307*b725ae77Skettenis alpha_mdebug_frame_sniffer (struct frame_info *next_frame)
308*b725ae77Skettenis {
309*b725ae77Skettenis   CORE_ADDR pc = frame_pc_unwind (next_frame);
310*b725ae77Skettenis   alpha_extra_func_info_t proc_desc;
311*b725ae77Skettenis 
312*b725ae77Skettenis   /* If this PC does not map to a PDR, then clearly this isn't an
313*b725ae77Skettenis      mdebug frame.  */
314*b725ae77Skettenis   proc_desc = find_proc_desc (pc);
315*b725ae77Skettenis   if (proc_desc == NULL)
316*b725ae77Skettenis     return NULL;
317*b725ae77Skettenis 
318*b725ae77Skettenis   /* If we're in the prologue, the PDR for this frame is not yet valid.
319*b725ae77Skettenis      Say no here and we'll fall back on the heuristic unwinder.  */
320*b725ae77Skettenis   if (alpha_mdebug_in_prologue (pc, proc_desc))
321*b725ae77Skettenis     return NULL;
322*b725ae77Skettenis 
323*b725ae77Skettenis   return &alpha_mdebug_frame_unwind;
324*b725ae77Skettenis }
325*b725ae77Skettenis 
326*b725ae77Skettenis static CORE_ADDR
alpha_mdebug_frame_base_address(struct frame_info * next_frame,void ** this_prologue_cache)327*b725ae77Skettenis alpha_mdebug_frame_base_address (struct frame_info *next_frame,
328*b725ae77Skettenis 				 void **this_prologue_cache)
329*b725ae77Skettenis {
330*b725ae77Skettenis   struct alpha_mdebug_unwind_cache *info
331*b725ae77Skettenis     = alpha_mdebug_frame_unwind_cache (next_frame, this_prologue_cache);
332*b725ae77Skettenis 
333*b725ae77Skettenis   return info->vfp;
334*b725ae77Skettenis }
335*b725ae77Skettenis 
336*b725ae77Skettenis static CORE_ADDR
alpha_mdebug_frame_locals_address(struct frame_info * next_frame,void ** this_prologue_cache)337*b725ae77Skettenis alpha_mdebug_frame_locals_address (struct frame_info *next_frame,
338*b725ae77Skettenis 				   void **this_prologue_cache)
339*b725ae77Skettenis {
340*b725ae77Skettenis   struct alpha_mdebug_unwind_cache *info
341*b725ae77Skettenis     = alpha_mdebug_frame_unwind_cache (next_frame, this_prologue_cache);
342*b725ae77Skettenis 
343*b725ae77Skettenis   return info->vfp - PROC_LOCALOFF (info->proc_desc);
344*b725ae77Skettenis }
345*b725ae77Skettenis 
346*b725ae77Skettenis static CORE_ADDR
alpha_mdebug_frame_args_address(struct frame_info * next_frame,void ** this_prologue_cache)347*b725ae77Skettenis alpha_mdebug_frame_args_address (struct frame_info *next_frame,
348*b725ae77Skettenis 				 void **this_prologue_cache)
349*b725ae77Skettenis {
350*b725ae77Skettenis   struct alpha_mdebug_unwind_cache *info
351*b725ae77Skettenis     = alpha_mdebug_frame_unwind_cache (next_frame, this_prologue_cache);
352*b725ae77Skettenis 
353*b725ae77Skettenis   return info->vfp - ALPHA_NUM_ARG_REGS * 8;
354*b725ae77Skettenis }
355*b725ae77Skettenis 
356*b725ae77Skettenis static const struct frame_base alpha_mdebug_frame_base = {
357*b725ae77Skettenis   &alpha_mdebug_frame_unwind,
358*b725ae77Skettenis   alpha_mdebug_frame_base_address,
359*b725ae77Skettenis   alpha_mdebug_frame_locals_address,
360*b725ae77Skettenis   alpha_mdebug_frame_args_address
361*b725ae77Skettenis };
362*b725ae77Skettenis 
363*b725ae77Skettenis static const struct frame_base *
alpha_mdebug_frame_base_sniffer(struct frame_info * next_frame)364*b725ae77Skettenis alpha_mdebug_frame_base_sniffer (struct frame_info *next_frame)
365*b725ae77Skettenis {
366*b725ae77Skettenis   CORE_ADDR pc = frame_pc_unwind (next_frame);
367*b725ae77Skettenis   alpha_extra_func_info_t proc_desc;
368*b725ae77Skettenis 
369*b725ae77Skettenis   /* If this PC does not map to a PDR, then clearly this isn't an
370*b725ae77Skettenis      mdebug frame.  */
371*b725ae77Skettenis   proc_desc = find_proc_desc (pc);
372*b725ae77Skettenis   if (proc_desc == NULL)
373*b725ae77Skettenis     return NULL;
374*b725ae77Skettenis 
375*b725ae77Skettenis   return &alpha_mdebug_frame_base;
376*b725ae77Skettenis }
377*b725ae77Skettenis 
378*b725ae77Skettenis 
379*b725ae77Skettenis void
alpha_mdebug_init_abi(struct gdbarch_info info,struct gdbarch * gdbarch)380*b725ae77Skettenis alpha_mdebug_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
381*b725ae77Skettenis {
382*b725ae77Skettenis   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
383*b725ae77Skettenis 
384*b725ae77Skettenis   frame_unwind_append_sniffer (gdbarch, alpha_mdebug_frame_sniffer);
385*b725ae77Skettenis   frame_base_append_sniffer (gdbarch, alpha_mdebug_frame_base_sniffer);
386*b725ae77Skettenis }
387