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