Home | History | Annotate | Line # | Download | only in gdb
      1   1.1  christos /* Code dealing with dummy stack frames, for GDB, the GNU debugger.
      2   1.1  christos 
      3  1.11  christos    Copyright (C) 1986-2024 Free Software Foundation, Inc.
      4   1.1  christos 
      5   1.1  christos    This file is part of GDB.
      6   1.1  christos 
      7   1.1  christos    This program is free software; you can redistribute it and/or modify
      8   1.1  christos    it under the terms of the GNU General Public License as published by
      9   1.1  christos    the Free Software Foundation; either version 3 of the License, or
     10   1.1  christos    (at your option) any later version.
     11   1.1  christos 
     12   1.1  christos    This program is distributed in the hope that it will be useful,
     13   1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     14   1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     15   1.1  christos    GNU General Public License for more details.
     16   1.1  christos 
     17   1.1  christos    You should have received a copy of the GNU General Public License
     18   1.1  christos    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
     19   1.1  christos 
     20   1.1  christos 
     21   1.1  christos #include "dummy-frame.h"
     22   1.1  christos #include "regcache.h"
     23   1.1  christos #include "frame.h"
     24   1.1  christos #include "inferior.h"
     25   1.1  christos #include "frame-unwind.h"
     26   1.1  christos #include "command.h"
     27  1.11  christos #include "cli/cli-cmds.h"
     28   1.8  christos #include "observable.h"
     29   1.1  christos #include "gdbthread.h"
     30   1.5  christos #include "infcall.h"
     31   1.9  christos #include "gdbarch.h"
     32   1.1  christos 
     33   1.3  christos struct dummy_frame_id
     34   1.3  christos {
     35   1.3  christos   /* This frame's ID.  Must match the value returned by
     36   1.3  christos      gdbarch_dummy_id.  */
     37   1.3  christos   struct frame_id id;
     38   1.3  christos 
     39   1.3  christos   /* The thread this dummy_frame relates to.  */
     40   1.8  christos   thread_info *thread;
     41   1.3  christos };
     42   1.3  christos 
     43   1.3  christos /* Return whether dummy_frame_id *ID1 and *ID2 are equal.  */
     44   1.3  christos 
     45   1.3  christos static int
     46   1.3  christos dummy_frame_id_eq (struct dummy_frame_id *id1,
     47   1.3  christos 		   struct dummy_frame_id *id2)
     48   1.3  christos {
     49  1.10  christos   return id1->id == id2->id && id1->thread == id2->thread;
     50   1.3  christos }
     51   1.3  christos 
     52   1.5  christos /* List of dummy_frame destructors.  */
     53   1.5  christos 
     54   1.5  christos struct dummy_frame_dtor_list
     55   1.5  christos {
     56   1.5  christos   /* Next element in the list or NULL if this is the last element.  */
     57   1.5  christos   struct dummy_frame_dtor_list *next;
     58   1.5  christos 
     59   1.5  christos   /* If non-NULL, a destructor that is run when this dummy frame is freed.  */
     60   1.5  christos   dummy_frame_dtor_ftype *dtor;
     61   1.5  christos 
     62   1.5  christos   /* Arbitrary data that is passed to DTOR.  */
     63   1.5  christos   void *dtor_data;
     64   1.5  christos };
     65   1.5  christos 
     66   1.1  christos /* Dummy frame.  This saves the processor state just prior to setting
     67   1.1  christos    up the inferior function call.  Older targets save the registers
     68   1.1  christos    on the target stack (but that really slows down function calls).  */
     69   1.1  christos 
     70   1.1  christos struct dummy_frame
     71   1.1  christos {
     72   1.1  christos   struct dummy_frame *next;
     73   1.3  christos 
     74   1.3  christos   /* An id represents a dummy frame.  */
     75   1.3  christos   struct dummy_frame_id id;
     76   1.3  christos 
     77   1.1  christos   /* The caller's state prior to the call.  */
     78   1.1  christos   struct infcall_suspend_state *caller_state;
     79   1.3  christos 
     80   1.5  christos   /* First element of destructors list or NULL if there are no
     81   1.5  christos      destructors registered for this dummy_frame.  */
     82   1.5  christos   struct dummy_frame_dtor_list *dtor_list;
     83   1.1  christos };
     84   1.1  christos 
     85   1.1  christos static struct dummy_frame *dummy_frame_stack = NULL;
     86   1.1  christos 
     87   1.1  christos /* Push the caller's state, along with the dummy frame info, onto the
     88   1.1  christos    dummy-frame stack.  */
     89   1.1  christos 
     90   1.1  christos void
     91   1.1  christos dummy_frame_push (struct infcall_suspend_state *caller_state,
     92   1.8  christos 		  const frame_id *dummy_id, thread_info *thread)
     93   1.1  christos {
     94   1.1  christos   struct dummy_frame *dummy_frame;
     95   1.1  christos 
     96   1.3  christos   dummy_frame = XCNEW (struct dummy_frame);
     97   1.1  christos   dummy_frame->caller_state = caller_state;
     98   1.3  christos   dummy_frame->id.id = (*dummy_id);
     99   1.8  christos   dummy_frame->id.thread = thread;
    100   1.1  christos   dummy_frame->next = dummy_frame_stack;
    101   1.1  christos   dummy_frame_stack = dummy_frame;
    102   1.1  christos }
    103   1.1  christos 
    104   1.1  christos /* Remove *DUMMY_PTR from the dummy frame stack.  */
    105   1.1  christos 
    106   1.1  christos static void
    107   1.1  christos remove_dummy_frame (struct dummy_frame **dummy_ptr)
    108   1.1  christos {
    109   1.1  christos   struct dummy_frame *dummy = *dummy_ptr;
    110   1.1  christos 
    111   1.5  christos   while (dummy->dtor_list != NULL)
    112   1.5  christos     {
    113   1.5  christos       struct dummy_frame_dtor_list *list = dummy->dtor_list;
    114   1.5  christos 
    115   1.5  christos       dummy->dtor_list = list->next;
    116   1.5  christos       list->dtor (list->dtor_data, 0);
    117   1.5  christos       xfree (list);
    118   1.5  christos     }
    119   1.5  christos 
    120   1.1  christos   *dummy_ptr = dummy->next;
    121   1.1  christos   discard_infcall_suspend_state (dummy->caller_state);
    122   1.1  christos   xfree (dummy);
    123   1.1  christos }
    124   1.1  christos 
    125   1.1  christos /* Delete any breakpoint B which is a momentary breakpoint for return from
    126   1.1  christos    inferior call matching DUMMY_VOIDP.  */
    127   1.1  christos 
    128   1.9  christos static bool
    129   1.9  christos pop_dummy_frame_bpt (struct breakpoint *b, struct dummy_frame *dummy)
    130   1.1  christos {
    131   1.8  christos   if (b->thread == dummy->id.thread->global_num
    132  1.10  christos       && b->disposition == disp_del && b->frame_id == dummy->id.id)
    133   1.1  christos     {
    134   1.1  christos       while (b->related_breakpoint != b)
    135   1.1  christos 	delete_breakpoint (b->related_breakpoint);
    136   1.1  christos 
    137   1.1  christos       delete_breakpoint (b);
    138   1.1  christos 
    139   1.1  christos       /* Stop the traversal.  */
    140   1.9  christos       return true;
    141   1.1  christos     }
    142   1.1  christos 
    143   1.1  christos   /* Continue the traversal.  */
    144   1.9  christos   return false;
    145   1.1  christos }
    146   1.1  christos 
    147   1.1  christos /* Pop *DUMMY_PTR, restoring program state to that before the
    148   1.1  christos    frame was created.  */
    149   1.1  christos 
    150   1.1  christos static void
    151   1.1  christos pop_dummy_frame (struct dummy_frame **dummy_ptr)
    152   1.1  christos {
    153   1.1  christos   struct dummy_frame *dummy = *dummy_ptr;
    154   1.1  christos 
    155   1.8  christos   gdb_assert (dummy->id.thread == inferior_thread ());
    156   1.3  christos 
    157   1.5  christos   while (dummy->dtor_list != NULL)
    158   1.5  christos     {
    159   1.5  christos       struct dummy_frame_dtor_list *list = dummy->dtor_list;
    160   1.5  christos 
    161   1.5  christos       dummy->dtor_list = list->next;
    162   1.5  christos       list->dtor (list->dtor_data, 1);
    163   1.5  christos       xfree (list);
    164   1.5  christos     }
    165   1.3  christos 
    166   1.1  christos   restore_infcall_suspend_state (dummy->caller_state);
    167   1.1  christos 
    168  1.11  christos   for (breakpoint &bp : all_breakpoints_safe ())
    169  1.11  christos     if (pop_dummy_frame_bpt (&bp, dummy))
    170  1.10  christos       break;
    171   1.1  christos 
    172   1.1  christos   /* restore_infcall_control_state frees inf_state,
    173   1.1  christos      all that remains is to pop *dummy_ptr.  */
    174   1.1  christos   *dummy_ptr = dummy->next;
    175   1.1  christos   xfree (dummy);
    176   1.1  christos 
    177   1.1  christos   /* We've made right mess of GDB's local state, just discard
    178   1.1  christos      everything.  */
    179   1.1  christos   reinit_frame_cache ();
    180   1.1  christos }
    181   1.1  christos 
    182   1.1  christos /* Look up DUMMY_ID.
    183   1.1  christos    Return NULL if not found.  */
    184   1.1  christos 
    185   1.1  christos static struct dummy_frame **
    186   1.3  christos lookup_dummy_frame (struct dummy_frame_id *dummy_id)
    187   1.1  christos {
    188   1.1  christos   struct dummy_frame **dp;
    189   1.1  christos 
    190   1.1  christos   for (dp = &dummy_frame_stack; *dp != NULL; dp = &(*dp)->next)
    191   1.1  christos     {
    192   1.3  christos       if (dummy_frame_id_eq (&(*dp)->id, dummy_id))
    193   1.1  christos 	return dp;
    194   1.1  christos     }
    195   1.1  christos 
    196   1.1  christos   return NULL;
    197   1.1  christos }
    198   1.1  christos 
    199   1.8  christos /* Find the dummy frame by DUMMY_ID and THREAD, and pop it, restoring
    200   1.3  christos    program state to that before the frame was created.
    201   1.1  christos    On return reinit_frame_cache has been called.
    202   1.3  christos    If the frame isn't found, flag an internal error.  */
    203   1.1  christos 
    204   1.1  christos void
    205   1.8  christos dummy_frame_pop (frame_id dummy_id, thread_info *thread)
    206   1.1  christos {
    207   1.1  christos   struct dummy_frame **dp;
    208   1.8  christos   struct dummy_frame_id id = { dummy_id, thread };
    209   1.1  christos 
    210   1.3  christos   dp = lookup_dummy_frame (&id);
    211   1.1  christos   gdb_assert (dp != NULL);
    212   1.1  christos 
    213   1.1  christos   pop_dummy_frame (dp);
    214   1.1  christos }
    215   1.1  christos 
    216   1.3  christos /* Find the dummy frame by DUMMY_ID and PTID and drop it.  Do nothing
    217   1.3  christos    if it is not found.  Do not restore its state into inferior, just
    218   1.3  christos    free its memory.  */
    219   1.1  christos 
    220   1.1  christos void
    221   1.8  christos dummy_frame_discard (struct frame_id dummy_id, thread_info *thread)
    222   1.1  christos {
    223   1.1  christos   struct dummy_frame **dp;
    224   1.8  christos   struct dummy_frame_id id = { dummy_id, thread };
    225   1.1  christos 
    226   1.3  christos   dp = lookup_dummy_frame (&id);
    227   1.1  christos   if (dp)
    228   1.1  christos     remove_dummy_frame (dp);
    229   1.1  christos }
    230   1.1  christos 
    231   1.3  christos /* See dummy-frame.h.  */
    232   1.3  christos 
    233   1.3  christos void
    234   1.8  christos register_dummy_frame_dtor (frame_id dummy_id, thread_info *thread,
    235   1.3  christos 			   dummy_frame_dtor_ftype *dtor, void *dtor_data)
    236   1.3  christos {
    237   1.8  christos   struct dummy_frame_id id = { dummy_id, thread };
    238   1.3  christos   struct dummy_frame **dp, *d;
    239   1.5  christos   struct dummy_frame_dtor_list *list;
    240   1.3  christos 
    241   1.3  christos   dp = lookup_dummy_frame (&id);
    242   1.3  christos   gdb_assert (dp != NULL);
    243   1.3  christos   d = *dp;
    244   1.6  christos   list = XNEW (struct dummy_frame_dtor_list);
    245   1.5  christos   list->next = d->dtor_list;
    246   1.5  christos   d->dtor_list = list;
    247   1.5  christos   list->dtor = dtor;
    248   1.5  christos   list->dtor_data = dtor_data;
    249   1.3  christos }
    250   1.3  christos 
    251   1.3  christos /* See dummy-frame.h.  */
    252   1.3  christos 
    253   1.3  christos int
    254   1.3  christos find_dummy_frame_dtor (dummy_frame_dtor_ftype *dtor, void *dtor_data)
    255   1.3  christos {
    256   1.3  christos   struct dummy_frame *d;
    257   1.3  christos 
    258   1.3  christos   for (d = dummy_frame_stack; d != NULL; d = d->next)
    259   1.5  christos     {
    260   1.5  christos       struct dummy_frame_dtor_list *list;
    261   1.5  christos 
    262   1.5  christos       for (list = d->dtor_list; list != NULL; list = list->next)
    263   1.5  christos 	if (list->dtor == dtor && list->dtor_data == dtor_data)
    264   1.5  christos 	  return 1;
    265   1.5  christos     }
    266   1.3  christos   return 0;
    267   1.3  christos }
    268   1.3  christos 
    269   1.1  christos /* There may be stale dummy frames, perhaps left over from when an uncaught
    270   1.1  christos    longjmp took us out of a function that was called by the debugger.  Clean
    271   1.1  christos    them up at least once whenever we start a new inferior.  */
    272   1.1  christos 
    273   1.1  christos static void
    274  1.10  christos cleanup_dummy_frames (inferior *inf)
    275   1.1  christos {
    276   1.1  christos   while (dummy_frame_stack != NULL)
    277   1.1  christos     remove_dummy_frame (&dummy_frame_stack);
    278   1.1  christos }
    279   1.1  christos 
    280   1.1  christos /* Return the dummy frame cache, it contains both the ID, and a
    281   1.1  christos    pointer to the regcache.  */
    282   1.1  christos struct dummy_frame_cache
    283   1.1  christos {
    284   1.1  christos   struct frame_id this_id;
    285   1.8  christos   readonly_detached_regcache *prev_regcache;
    286   1.1  christos };
    287   1.1  christos 
    288   1.1  christos static int
    289   1.1  christos dummy_frame_sniffer (const struct frame_unwind *self,
    290  1.11  christos 		     const frame_info_ptr &this_frame,
    291   1.1  christos 		     void **this_prologue_cache)
    292   1.1  christos {
    293   1.1  christos   /* When unwinding a normal frame, the stack structure is determined
    294   1.1  christos      by analyzing the frame's function's code (be it using brute force
    295   1.1  christos      prologue analysis, or the dwarf2 CFI).  In the case of a dummy
    296   1.1  christos      frame, that simply isn't possible.  The PC is either the program
    297   1.1  christos      entry point, or some random address on the stack.  Trying to use
    298   1.1  christos      that PC to apply standard frame ID unwind techniques is just
    299   1.1  christos      asking for trouble.  */
    300   1.1  christos 
    301   1.1  christos   /* Don't bother unless there is at least one dummy frame.  */
    302   1.1  christos   if (dummy_frame_stack != NULL)
    303   1.1  christos     {
    304   1.3  christos       struct dummy_frame *dummyframe;
    305   1.1  christos       /* Use an architecture specific method to extract this frame's
    306   1.1  christos 	 dummy ID, assuming it is a dummy frame.  */
    307   1.3  christos       struct frame_id this_id
    308   1.3  christos 	= gdbarch_dummy_id (get_frame_arch (this_frame), this_frame);
    309   1.8  christos       struct dummy_frame_id dummy_id = { this_id, inferior_thread () };
    310   1.1  christos 
    311   1.1  christos       /* Use that ID to find the corresponding cache entry.  */
    312   1.1  christos       for (dummyframe = dummy_frame_stack;
    313   1.1  christos 	   dummyframe != NULL;
    314   1.1  christos 	   dummyframe = dummyframe->next)
    315   1.1  christos 	{
    316   1.3  christos 	  if (dummy_frame_id_eq (&dummyframe->id, &dummy_id))
    317   1.1  christos 	    {
    318   1.1  christos 	      struct dummy_frame_cache *cache;
    319   1.1  christos 
    320   1.1  christos 	      cache = FRAME_OBSTACK_ZALLOC (struct dummy_frame_cache);
    321   1.1  christos 	      cache->prev_regcache = get_infcall_suspend_state_regcache
    322   1.1  christos 						   (dummyframe->caller_state);
    323   1.1  christos 	      cache->this_id = this_id;
    324   1.1  christos 	      (*this_prologue_cache) = cache;
    325   1.1  christos 	      return 1;
    326   1.1  christos 	    }
    327   1.1  christos 	}
    328   1.1  christos     }
    329   1.1  christos   return 0;
    330   1.1  christos }
    331   1.1  christos 
    332   1.1  christos /* Given a call-dummy dummy-frame, return the registers.  Here the
    333   1.1  christos    register value is taken from the local copy of the register buffer.  */
    334   1.1  christos 
    335   1.1  christos static struct value *
    336  1.11  christos dummy_frame_prev_register (const frame_info_ptr &this_frame,
    337   1.1  christos 			   void **this_prologue_cache,
    338   1.1  christos 			   int regnum)
    339   1.1  christos {
    340   1.6  christos   struct dummy_frame_cache *cache
    341   1.6  christos     = (struct dummy_frame_cache *) *this_prologue_cache;
    342   1.1  christos   struct gdbarch *gdbarch = get_frame_arch (this_frame);
    343   1.1  christos   struct value *reg_val;
    344   1.1  christos 
    345   1.1  christos   /* The dummy-frame sniffer always fills in the cache.  */
    346   1.1  christos   gdb_assert (cache != NULL);
    347   1.1  christos 
    348   1.1  christos   /* Describe the register's location.  Generic dummy frames always
    349   1.1  christos      have the register value in an ``expression''.  */
    350  1.11  christos   reg_val = value::zero (register_type (gdbarch, regnum), not_lval);
    351   1.1  christos 
    352   1.1  christos   /* Use the regcache_cooked_read() method so that it, on the fly,
    353   1.1  christos      constructs either a raw or pseudo register from the raw
    354   1.1  christos      register cache.  */
    355  1.10  christos   cache->prev_regcache->cooked_read
    356  1.11  christos     (regnum, reg_val->contents_writeable ().data ());
    357   1.1  christos   return reg_val;
    358   1.1  christos }
    359   1.1  christos 
    360   1.1  christos /* Assuming that THIS_FRAME is a dummy, return its ID.  That ID is
    361   1.1  christos    determined by examining the NEXT frame's unwound registers using
    362   1.1  christos    the method dummy_id().  As a side effect, THIS dummy frame's
    363   1.1  christos    dummy cache is located and saved in THIS_PROLOGUE_CACHE.  */
    364   1.1  christos 
    365   1.1  christos static void
    366  1.11  christos dummy_frame_this_id (const frame_info_ptr &this_frame,
    367   1.1  christos 		     void **this_prologue_cache,
    368   1.1  christos 		     struct frame_id *this_id)
    369   1.1  christos {
    370   1.1  christos   /* The dummy-frame sniffer always fills in the cache.  */
    371   1.6  christos   struct dummy_frame_cache *cache
    372   1.6  christos     = (struct dummy_frame_cache *) *this_prologue_cache;
    373   1.1  christos 
    374   1.1  christos   gdb_assert (cache != NULL);
    375   1.1  christos   (*this_id) = cache->this_id;
    376   1.1  christos }
    377   1.1  christos 
    378   1.1  christos const struct frame_unwind dummy_frame_unwind =
    379   1.1  christos {
    380  1.10  christos   "dummy",
    381   1.1  christos   DUMMY_FRAME,
    382   1.1  christos   default_frame_unwind_stop_reason,
    383   1.1  christos   dummy_frame_this_id,
    384   1.1  christos   dummy_frame_prev_register,
    385   1.1  christos   NULL,
    386   1.1  christos   dummy_frame_sniffer,
    387   1.1  christos };
    388   1.1  christos 
    389   1.8  christos /* See dummy-frame.h.  */
    390   1.8  christos 
    391   1.8  christos struct frame_id
    392  1.11  christos default_dummy_id (struct gdbarch *gdbarch, const frame_info_ptr &this_frame)
    393   1.8  christos {
    394   1.8  christos   CORE_ADDR sp, pc;
    395   1.8  christos 
    396   1.8  christos   sp = get_frame_sp (this_frame);
    397   1.8  christos   pc = get_frame_pc (this_frame);
    398   1.8  christos   return frame_id_build (sp, pc);
    399   1.8  christos }
    400   1.8  christos 
    401   1.1  christos static void
    402   1.1  christos fprint_dummy_frames (struct ui_file *file)
    403   1.1  christos {
    404   1.1  christos   struct dummy_frame *s;
    405   1.1  christos 
    406   1.1  christos   for (s = dummy_frame_stack; s != NULL; s = s->next)
    407  1.10  christos     gdb_printf (file, "%s: id=%s, ptid=%s\n",
    408  1.10  christos 		host_address_to_string (s),
    409  1.10  christos 		s->id.id.to_string ().c_str (),
    410  1.10  christos 		s->id.thread->ptid.to_string ().c_str ());
    411   1.1  christos }
    412   1.1  christos 
    413   1.1  christos static void
    414   1.8  christos maintenance_print_dummy_frames (const char *args, int from_tty)
    415   1.1  christos {
    416   1.1  christos   if (args == NULL)
    417   1.1  christos     fprint_dummy_frames (gdb_stdout);
    418   1.1  christos   else
    419   1.1  christos     {
    420   1.7  christos       stdio_file file;
    421   1.1  christos 
    422   1.7  christos       if (!file.open (args, "w"))
    423   1.1  christos 	perror_with_name (_("maintenance print dummy-frames"));
    424   1.7  christos       fprint_dummy_frames (&file);
    425   1.1  christos     }
    426   1.1  christos }
    427   1.1  christos 
    428   1.9  christos void _initialize_dummy_frame ();
    429   1.1  christos void
    430   1.9  christos _initialize_dummy_frame ()
    431   1.1  christos {
    432   1.1  christos   add_cmd ("dummy-frames", class_maintenance, maintenance_print_dummy_frames,
    433   1.1  christos 	   _("Print the contents of the internal dummy-frame stack."),
    434   1.1  christos 	   &maintenanceprintlist);
    435   1.1  christos 
    436  1.10  christos   gdb::observers::inferior_created.attach (cleanup_dummy_frames, "dummy-frame");
    437   1.1  christos }
    438