/* Inline frame unwinder for GDB.

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

   This file is part of GDB.

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

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

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

#include "defs.h"
#include "inline-frame.h"
#include "addrmap.h"
#include "block.h"
#include "frame-unwind.h"
#include "inferior.h"
#include "regcache.h"
#include "symtab.h"
#include "vec.h"
#include "frame.h"

/* We need to save a few variables for every thread stopped at the
   virtual call site of an inlined function.  If there was always a
   "struct thread_info", we could hang it off that; in the mean time,
   keep our own list.  */
struct inline_state
{
  /* The thread this data relates to.  It should be a currently
     stopped thread; we assume thread IDs never change while the
     thread is stopped.  */
  ptid_t ptid;

  /* The number of inlined functions we are skipping.  Each of these
     functions can be stepped in to.  */
  int skipped_frames;

  /* Only valid if SKIPPED_FRAMES is non-zero.  This is the PC used
     when calculating SKIPPED_FRAMES; used to check whether we have
     moved to a new location by user request.  If so, we invalidate
     any skipped frames.  */
  CORE_ADDR saved_pc;

  /* Only valid if SKIPPED_FRAMES is non-zero.  This is the symbol
     of the outermost skipped inline function.  It's used to find the
     call site of the current frame.  */
  struct symbol *skipped_symbol;
};

typedef struct inline_state inline_state_s;
DEF_VEC_O(inline_state_s);

static VEC(inline_state_s) *inline_states;

/* Locate saved inlined frame state for PTID, if it exists
   and is valid.  */

static struct inline_state *
find_inline_frame_state (ptid_t ptid)
{
  struct inline_state *state;
  int ix;

  for (ix = 0; VEC_iterate (inline_state_s, inline_states, ix, state); ix++)
    {
      if (ptid_equal (state->ptid, ptid))
	{
	  struct regcache *regcache = get_thread_regcache (ptid);
	  CORE_ADDR current_pc = regcache_read_pc (regcache);

	  if (current_pc != state->saved_pc)
	    {
	      /* PC has changed - this context is invalid.  Use the
		 default behavior.  */
	      VEC_unordered_remove (inline_state_s, inline_states, ix);
	      return NULL;
	    }
	  else
	    return state;
	}
    }

  return NULL;
}

/* Allocate saved inlined frame state for PTID.  */

static struct inline_state *
allocate_inline_frame_state (ptid_t ptid)
{
  struct inline_state *state;

  state = VEC_safe_push (inline_state_s, inline_states, NULL);
  memset (state, 0, sizeof (*state));
  state->ptid = ptid;

  return state;
}

/* Forget about any hidden inlined functions in PTID, which is new or
   about to be resumed.  PTID may be minus_one_ptid (all processes)
   or a PID (all threads in this process).  */

void
clear_inline_frame_state (ptid_t ptid)
{
  struct inline_state *state;
  int ix;

  if (ptid_equal (ptid, minus_one_ptid))
    {
      VEC_free (inline_state_s, inline_states);
      return;
    }

  if (ptid_is_pid (ptid))
    {
      VEC (inline_state_s) *new_states = NULL;
      int pid = ptid_get_pid (ptid);

      for (ix = 0;
	   VEC_iterate (inline_state_s, inline_states, ix, state);
	   ix++)
	if (pid != ptid_get_pid (state->ptid))
	  VEC_safe_push (inline_state_s, new_states, state);
      VEC_free (inline_state_s, inline_states);
      inline_states = new_states;
      return;
    }

  for (ix = 0; VEC_iterate (inline_state_s, inline_states, ix, state); ix++)
    if (ptid_equal (state->ptid, ptid))
      {
	VEC_unordered_remove (inline_state_s, inline_states, ix);
	return;
      }
}

static void
inline_frame_this_id (struct frame_info *this_frame,
		      void **this_cache,
		      struct frame_id *this_id)
{
  struct symbol *func;

  /* In order to have a stable frame ID for a given inline function,
     we must get the stack / special addresses from the underlying
     real frame's this_id method.  So we must call
     get_prev_frame_always.  Because we are inlined into some
     function, there must be previous frames, so this is safe - as
     long as we're careful not to create any cycles.  */
  *this_id = get_frame_id (get_prev_frame_always (this_frame));

  /* We need a valid frame ID, so we need to be based on a valid
     frame.  FSF submission NOTE: this would be a good assertion to
     apply to all frames, all the time.  That would fix the ambiguity
     of null_frame_id (between "no/any frame" and "the outermost
     frame").  This will take work.  */
  gdb_assert (frame_id_p (*this_id));

  /* For now, require we don't match outer_frame_id either (see
     comment above).  */
  gdb_assert (!frame_id_eq (*this_id, outer_frame_id));

  /* Future work NOTE: Alexandre Oliva applied a patch to GCC 4.3
     which generates DW_AT_entry_pc for inlined functions when
     possible.  If this attribute is available, we should use it
     in the frame ID (and eventually, to set breakpoints).  */
  func = get_frame_function (this_frame);
  gdb_assert (func != NULL);
  (*this_id).code_addr = BLOCK_START (SYMBOL_BLOCK_VALUE (func));
  (*this_id).artificial_depth++;
}

static struct value *
inline_frame_prev_register (struct frame_info *this_frame, void **this_cache,
			    int regnum)
{
  /* Use get_frame_register_value instead of
     frame_unwind_got_register, to avoid requiring this frame's ID.
     This frame's ID depends on the previous frame's ID (unusual), and
     the previous frame's ID depends on this frame's unwound
     registers.  If unwinding registers from this frame called
     get_frame_id, there would be a loop.

     Do not copy this code into any other unwinder!  Inlined functions
     are special; other unwinders must not have a dependency on the
     previous frame's ID, and therefore can and should use
     frame_unwind_got_register instead.  */
  return get_frame_register_value (this_frame, regnum);
}

/* Check whether we are at an inlining site that does not already
   have an associated frame.  */

static int
inline_frame_sniffer (const struct frame_unwind *self,
		      struct frame_info *this_frame,
		      void **this_cache)
{
  CORE_ADDR this_pc;
  const struct block *frame_block, *cur_block;
  int depth;
  struct frame_info *next_frame;
  struct inline_state *state = find_inline_frame_state (inferior_ptid);

  this_pc = get_frame_address_in_block (this_frame);
  frame_block = block_for_pc (this_pc);
  if (frame_block == NULL)
    return 0;

  /* Calculate DEPTH, the number of inlined functions at this
     location.  */
  depth = 0;
  cur_block = frame_block;
  while (BLOCK_SUPERBLOCK (cur_block))
    {
      if (block_inlined_p (cur_block))
	depth++;
      else if (BLOCK_FUNCTION (cur_block) != NULL)
	break;

      cur_block = BLOCK_SUPERBLOCK (cur_block);
    }

  /* Check how many inlined functions already have frames.  */
  for (next_frame = get_next_frame (this_frame);
       next_frame && get_frame_type (next_frame) == INLINE_FRAME;
       next_frame = get_next_frame (next_frame))
    {
      gdb_assert (depth > 0);
      depth--;
    }

  /* If this is the topmost frame, or all frames above us are inlined,
     then check whether we were requested to skip some frames (so they
     can be stepped into later).  */
  if (state != NULL && state->skipped_frames > 0 && next_frame == NULL)
    {
      gdb_assert (depth >= state->skipped_frames);
      depth -= state->skipped_frames;
    }

  /* If all the inlined functions here already have frames, then pass
     to the normal unwinder for this PC.  */
  if (depth == 0)
    return 0;

  /* If the next frame is an inlined function, but not the outermost, then
     we are the next outer.  If it is not an inlined function, then we
     are the innermost inlined function of a different real frame.  */
  return 1;
}

const struct frame_unwind inline_frame_unwind = {
  INLINE_FRAME,
  default_frame_unwind_stop_reason,
  inline_frame_this_id,
  inline_frame_prev_register,
  NULL,
  inline_frame_sniffer
};

/* Return non-zero if BLOCK, an inlined function block containing PC,
   has a group of contiguous instructions starting at PC (but not
   before it).  */

static int
block_starting_point_at (CORE_ADDR pc, const struct block *block)
{
  const struct blockvector *bv;
  struct block *new_block;

  bv = blockvector_for_pc (pc, NULL);
  if (BLOCKVECTOR_MAP (bv) == NULL)
    return 0;

  new_block = addrmap_find (BLOCKVECTOR_MAP (bv), pc - 1);
  if (new_block == NULL)
    return 1;

  if (new_block == block || contained_in (new_block, block))
    return 0;

  /* The immediately preceding address belongs to a different block,
     which is not a child of this one.  Treat this as an entrance into
     BLOCK.  */
  return 1;
}

/* Skip all inlined functions whose call sites are at the current PC.
   Frames for the hidden functions will not appear in the backtrace until the
   user steps into them.  */

void
skip_inline_frames (ptid_t ptid)
{
  CORE_ADDR this_pc;
  const struct block *frame_block, *cur_block;
  struct symbol *last_sym = NULL;
  int skip_count = 0;
  struct inline_state *state;

  /* This function is called right after reinitializing the frame
     cache.  We try not to do more unwinding than absolutely
     necessary, for performance.  */
  this_pc = get_frame_pc (get_current_frame ());
  frame_block = block_for_pc (this_pc);

  if (frame_block != NULL)
    {
      cur_block = frame_block;
      while (BLOCK_SUPERBLOCK (cur_block))
	{
	  if (block_inlined_p (cur_block))
	    {
	      /* See comments in inline_frame_this_id about this use
		 of BLOCK_START.  */
	      if (BLOCK_START (cur_block) == this_pc
		  || block_starting_point_at (this_pc, cur_block))
		{
		  skip_count++;
		  last_sym = BLOCK_FUNCTION (cur_block);
		}
	      else
		break;
	    }
	  else if (BLOCK_FUNCTION (cur_block) != NULL)
	    break;

	  cur_block = BLOCK_SUPERBLOCK (cur_block);
	}
    }

  gdb_assert (find_inline_frame_state (ptid) == NULL);
  state = allocate_inline_frame_state (ptid);
  state->skipped_frames = skip_count;
  state->saved_pc = this_pc;
  state->skipped_symbol = last_sym;

  if (skip_count != 0)
    reinit_frame_cache ();
}

/* Step into an inlined function by unhiding it.  */

void
step_into_inline_frame (ptid_t ptid)
{
  struct inline_state *state = find_inline_frame_state (ptid);

  gdb_assert (state != NULL && state->skipped_frames > 0);
  state->skipped_frames--;
  reinit_frame_cache ();
}

/* Return the number of hidden functions inlined into the current
   frame.  */

int
inline_skipped_frames (ptid_t ptid)
{
  struct inline_state *state = find_inline_frame_state (ptid);

  if (state == NULL)
    return 0;
  else
    return state->skipped_frames;
}

/* If one or more inlined functions are hidden, return the symbol for
   the function inlined into the current frame.  */

struct symbol *
inline_skipped_symbol (ptid_t ptid)
{
  struct inline_state *state = find_inline_frame_state (ptid);

  gdb_assert (state != NULL);
  return state->skipped_symbol;
}

/* Return the number of functions inlined into THIS_FRAME.  Some of
   the callees may not have associated frames (see
   skip_inline_frames).  */

int
frame_inlined_callees (struct frame_info *this_frame)
{
  struct frame_info *next_frame;
  int inline_count = 0;

  /* First count how many inlined functions at this PC have frames
     above FRAME (are inlined into FRAME).  */
  for (next_frame = get_next_frame (this_frame);
       next_frame && get_frame_type (next_frame) == INLINE_FRAME;
       next_frame = get_next_frame (next_frame))
    inline_count++;

  /* Simulate some most-inner inlined frames which were suppressed, so
     they can be stepped into later.  If we are unwinding already
     outer frames from some non-inlined frame this does not apply.  */
  if (next_frame == NULL)
    inline_count += inline_skipped_frames (inferior_ptid);

  return inline_count;
}
