gdb/tramp-frame.c - gdb

Data types defined

Functions defined

Source code

  1. /* Signal trampoline unwinder, for GDB the GNU Debugger.

  2.    Copyright (C) 2004-2015 Free Software Foundation, Inc.

  3.    This file is part of GDB.

  4.    This program is free software; you can redistribute it and/or modify
  5.    it under the terms of the GNU General Public License as published by
  6.    the Free Software Foundation; either version 3 of the License, or
  7.    (at your option) any later version.

  8.    This program is distributed in the hope that it will be useful,
  9.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11.    GNU General Public License for more details.

  12.    You should have received a copy of the GNU General Public License
  13.    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

  14. #include "defs.h"
  15. #include "tramp-frame.h"
  16. #include "frame-unwind.h"
  17. #include "gdbcore.h"
  18. #include "symtab.h"
  19. #include "objfiles.h"
  20. #include "target.h"
  21. #include "trad-frame.h"
  22. #include "frame-base.h"

  23. struct frame_data
  24. {
  25.   const struct tramp_frame *tramp_frame;
  26. };

  27. struct tramp_frame_cache
  28. {
  29.   CORE_ADDR func;
  30.   const struct tramp_frame *tramp_frame;
  31.   struct trad_frame_cache *trad_cache;
  32. };

  33. static struct trad_frame_cache *
  34. tramp_frame_cache (struct frame_info *this_frame,
  35.                    void **this_cache)
  36. {
  37.   struct tramp_frame_cache *tramp_cache = (*this_cache);

  38.   if (tramp_cache->trad_cache == NULL)
  39.     {
  40.       tramp_cache->trad_cache = trad_frame_cache_zalloc (this_frame);
  41.       tramp_cache->tramp_frame->init (tramp_cache->tramp_frame,
  42.                                       this_frame,
  43.                                       tramp_cache->trad_cache,
  44.                                       tramp_cache->func);
  45.     }
  46.   return tramp_cache->trad_cache;
  47. }

  48. static void
  49. tramp_frame_this_id (struct frame_info *this_frame,
  50.                      void **this_cache,
  51.                      struct frame_id *this_id)
  52. {
  53.   struct trad_frame_cache *trad_cache
  54.     = tramp_frame_cache (this_frame, this_cache);

  55.   trad_frame_get_id (trad_cache, this_id);
  56. }

  57. static struct value *
  58. tramp_frame_prev_register (struct frame_info *this_frame,
  59.                            void **this_cache,
  60.                            int prev_regnum)
  61. {
  62.   struct trad_frame_cache *trad_cache
  63.     = tramp_frame_cache (this_frame, this_cache);

  64.   return trad_frame_get_register (trad_cache, this_frame, prev_regnum);
  65. }

  66. static CORE_ADDR
  67. tramp_frame_start (const struct tramp_frame *tramp,
  68.                    struct frame_info *this_frame, CORE_ADDR pc)
  69. {
  70.   struct gdbarch *gdbarch = get_frame_arch (this_frame);
  71.   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
  72.   int ti;

  73.   /* Check if we can use this trampoline.  */
  74.   if (tramp->validate && !tramp->validate (tramp, this_frame, &pc))
  75.     return 0;

  76.   /* Search through the trampoline for one that matches the
  77.      instruction sequence around PC.  */
  78.   for (ti = 0; tramp->insn[ti].bytes != TRAMP_SENTINEL_INSN; ti++)
  79.     {
  80.       CORE_ADDR func = pc - tramp->insn_size * ti;
  81.       int i;

  82.       for (i = 0; 1; i++)
  83.         {
  84.           gdb_byte buf[sizeof (tramp->insn[0])];
  85.           ULONGEST insn;

  86.           if (tramp->insn[i].bytes == TRAMP_SENTINEL_INSN)
  87.             return func;
  88.           if (!safe_frame_unwind_memory (this_frame,
  89.                                          func + i * tramp->insn_size,
  90.                                          buf, tramp->insn_size))
  91.             break;
  92.           insn = extract_unsigned_integer (buf, tramp->insn_size, byte_order);
  93.           if (tramp->insn[i].bytes != (insn & tramp->insn[i].mask))
  94.             break;
  95.         }
  96.     }
  97.   /* Trampoline doesn't match.  */
  98.   return 0;
  99. }

  100. static int
  101. tramp_frame_sniffer (const struct frame_unwind *self,
  102.                      struct frame_info *this_frame,
  103.                      void **this_cache)
  104. {
  105.   const struct tramp_frame *tramp = self->unwind_data->tramp_frame;
  106.   CORE_ADDR pc = get_frame_pc (this_frame);
  107.   CORE_ADDR func;
  108.   struct tramp_frame_cache *tramp_cache;

  109.   /* tausq/2004-12-12: We used to assume if pc has a name or is in a valid
  110.      section, then this is not a trampoline.  However, this assumption is
  111.      false on HPUX which has a signal trampoline that has a name; it can
  112.      also be false when using an alternative signal stack.  */
  113.   func = tramp_frame_start (tramp, this_frame, pc);
  114.   if (func == 0)
  115.     return 0;
  116.   tramp_cache = FRAME_OBSTACK_ZALLOC (struct tramp_frame_cache);
  117.   tramp_cache->func = func;
  118.   tramp_cache->tramp_frame = tramp;
  119.   (*this_cache) = tramp_cache;
  120.   return 1;
  121. }

  122. void
  123. tramp_frame_prepend_unwinder (struct gdbarch *gdbarch,
  124.                               const struct tramp_frame *tramp_frame)
  125. {
  126.   struct frame_data *data;
  127.   struct frame_unwind *unwinder;
  128.   int i;

  129.   /* Check that the instruction sequence contains a sentinel.  */
  130.   for (i = 0; i < ARRAY_SIZE (tramp_frame->insn); i++)
  131.     {
  132.       if (tramp_frame->insn[i].bytes == TRAMP_SENTINEL_INSN)
  133.         break;
  134.     }
  135.   gdb_assert (i < ARRAY_SIZE (tramp_frame->insn));
  136.   gdb_assert (tramp_frame->insn_size <= sizeof (tramp_frame->insn[0].bytes));

  137.   data = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct frame_data);
  138.   unwinder = GDBARCH_OBSTACK_ZALLOC (gdbarch, struct frame_unwind);

  139.   data->tramp_frame = tramp_frame;
  140.   unwinder->type = tramp_frame->frame_type;
  141.   unwinder->unwind_data = data;
  142.   unwinder->sniffer = tramp_frame_sniffer;
  143.   unwinder->stop_reason = default_frame_unwind_stop_reason;
  144.   unwinder->this_id = tramp_frame_this_id;
  145.   unwinder->prev_register = tramp_frame_prev_register;
  146.   frame_unwind_prepend_unwinder (gdbarch, unwinder);
  147. }