Remote non-stop mode support.
[deliverable/binutils-gdb.git] / gdb / blockframe.c
index b3379009b30bf03efec5b92e31604992d688de47..5e2020d4a0bd934e7d26ff390290955c55ae4257 100644 (file)
-/* Get info from stack frames;
-   convert between frames, blocks, functions and pc values.
-   Copyright (C) 1986, 1987, 1988 Free Software Foundation, Inc.
-
-GDB is distributed in the hope that it will be useful, but WITHOUT ANY
-WARRANTY.  No author or distributor accepts responsibility to anyone
-for the consequences of using it or for whether it serves any
-particular purpose or works at all, unless he says so in writing.
-Refer to the GDB General Public License for full details.
-
-Everyone is granted permission to copy, modify and redistribute GDB,
-but only under the conditions described in the GDB General Public
-License.  A copy of this license is supposed to have been given to you
-along with GDB so you can know your rights and responsibilities.  It
-should be in a file named COPYING.  Among other things, the copyright
-notice and this notice must be preserved on all copies.
-
-In other words, go ahead and share GDB, but don't try to stop
-anyone else from sharing it farther.  Help stamp out software hoarding!
-*/
+/* Get info from stack frames; convert between frames, blocks,
+   functions and pc values.
 
-#include "defs.h"
-#include "initialize.h"
-#include "param.h"
-#include "symtab.h"
-#include "frame.h"
-
-/* Address of end of first object file.
-   This file is assumed to be a startup file
-   and frames with pc's inside it
-   are treated as nonexistent.  */
+   Copyright (C) 1986, 1987, 1988, 1989, 1990, 1991, 1992, 1993, 1994, 1995,
+   1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2007, 2008
+   Free Software Foundation, Inc.
 
-CORE_ADDR first_object_file_end;
+   This file is part of GDB.
 
-/* Address of innermost stack frame (contents of FP register) */
+   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.
 
-static FRAME current_frame;
+   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.
 
-struct block *block_for_pc ();
-CORE_ADDR get_pc_function_start ();
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
-START_FILE
+#include "defs.h"
+#include "symtab.h"
+#include "bfd.h"
+#include "objfiles.h"
+#include "frame.h"
+#include "gdbcore.h"
+#include "value.h"
+#include "target.h"
+#include "inferior.h"
+#include "annotate.h"
+#include "regcache.h"
+#include "gdb_assert.h"
+#include "dummy-frame.h"
+#include "command.h"
+#include "gdbcmd.h"
+#include "block.h"
+
+/* Prototypes for exported functions. */
+
+void _initialize_blockframe (void);
 
-/* Return the innermost (currently executing) stack frame.  */
+/* Return the innermost lexical block in execution
+   in a specified stack frame.  The frame address is assumed valid.
 
-FRAME
-get_current_frame ()
-{
-  /* We assume its address is kept in a general register;
-     param.h says which register.  */
+   If ADDR_IN_BLOCK is non-zero, set *ADDR_IN_BLOCK to the exact code
+   address we used to choose the block.  We use this to find a source
+   line, to decide which macro definitions are in scope.
 
-  return current_frame;
-}
+   The value returned in *ADDR_IN_BLOCK isn't necessarily the frame's
+   PC, and may not really be a valid PC at all.  For example, in the
+   caller of a function declared to never return, the code at the
+   return address will never be reached, so the call instruction may
+   be the very last instruction in the block.  So the address we use
+   to choose the block is actually one byte before the return address
+   --- hopefully pointing us at the call instruction, or its delay
+   slot instruction.  */
 
-void
-set_current_frame (frame)
-     FRAME frame;
+struct block *
+get_frame_block (struct frame_info *frame, CORE_ADDR *addr_in_block)
 {
-  current_frame = frame;
-}
+  const CORE_ADDR pc = get_frame_address_in_block (frame);
 
-/* Return the frame that called FRAME.
-   If FRAME is the original frame (it has no caller), return 0.  */
+  if (addr_in_block)
+    *addr_in_block = pc;
 
-FRAME
-get_prev_frame (frame)
-     FRAME frame;
-{
-  CORE_ADDR pointer;
-  /* The caller of "no frame" is the innermost frame.  */
-  if (frame == 0)
-    return get_current_frame ();
-
-  /* Two macros defined in param.h specify the machine-dependent
-     actions to be performed here.  */
-  /* First, get the frame's chain-pointer.
-     If that is zero, the frame is the outermost frame.  */
-  pointer = FRAME_CHAIN (frame);
-  if (!FRAME_CHAIN_VALID (pointer, frame))
-    return 0;
-  /* If frame has a caller, combine the chain pointer and the frame's own
-     address to get the address of the caller.  */
-  return FRAME_CHAIN_COMBINE (pointer, frame);
+  return block_for_pc (pc);
 }
 
-/* Return a structure containing various interesting information
-   about a specified stack frame.  */
-
-struct frame_info
-get_frame_info (frame)
-     FRAME frame;
+CORE_ADDR
+get_pc_function_start (CORE_ADDR pc)
 {
-  struct frame_info val;
-  FRAME current = get_current_frame ();
-  register FRAME frame1;
-
-  val.frame = frame;
+  struct block *bl;
+  struct minimal_symbol *msymbol;
 
-  if (frame == current)
+  bl = block_for_pc (pc);
+  if (bl)
     {
-      val.pc = read_pc ();
-      val.next_frame = 0;
+      struct symbol *symbol = block_linkage_function (bl);
+
+      if (symbol)
+       {
+         bl = SYMBOL_BLOCK_VALUE (symbol);
+         return BLOCK_START (bl);
+       }
     }
-  else 
+
+  msymbol = lookup_minimal_symbol_by_pc (pc);
+  if (msymbol)
     {
-      for (frame1 = current; frame1; frame1 = get_prev_frame (frame1))
-       {
-         QUIT;
-         if (frame1 == frame)
-           break;
+      CORE_ADDR fstart = SYMBOL_VALUE_ADDRESS (msymbol);
 
-         val.pc = FRAME_SAVED_PC (frame1);
-         val.next_frame = frame1;
-       }
+      if (find_pc_section (fstart))
+       return fstart;
     }
 
-  return val;
+  return 0;
 }
 
-/* Return a structure containing various interesting information
-   about the frame that called FRAME.
-
-   This is much faster than get_frame_info (get_prev_frame (FRAME))
-   because it does not need to search the entire stack
-   to find the frame called by the one being described -- that is FRAME.  */
+/* Return the symbol for the function executing in frame FRAME.  */
 
-struct frame_info
-get_prev_frame_info (next_frame)
-     FRAME next_frame;
+struct symbol *
+get_frame_function (struct frame_info *frame)
 {
-  struct frame_info val;
-  register FRAME frame = get_prev_frame (next_frame);
-
-  val.frame = frame;
-  val.next_frame = next_frame;
-
-  if (next_frame == 0)
-    {
-      val.pc = read_pc ();
-    }
-  else 
-    {
-      val.pc = FRAME_SAVED_PC (next_frame);
-    }
-
-  return val;
+  struct block *bl = get_frame_block (frame, 0);
+  if (bl == 0)
+    return 0;
+  return block_linkage_function (bl);
 }
+\f
 
-CORE_ADDR
-get_frame_pc (frame)
-     FRAME frame;
+/* Return the function containing pc value PC in section SECTION.
+   Returns 0 if function is not known.  */
+
+struct symbol *
+find_pc_sect_function (CORE_ADDR pc, struct obj_section *section)
 {
-  struct frame_info fi;
-  fi = get_frame_info (frame);
-  return fi.pc;
+  struct block *b = block_for_pc_sect (pc, section);
+  if (b == 0)
+    return 0;
+  return block_linkage_function (b);
 }
 
-/* Find the addresses in which registers are saved in FRAME.  */
+/* Return the function containing pc value PC.
+   Returns 0 if function is not known.  Backward compatibility, no section */
 
-void
-get_frame_saved_regs (frame_info_addr, saved_regs_addr)
-     struct frame_info *frame_info_addr;
-     struct frame_saved_regs *saved_regs_addr;
+struct symbol *
+find_pc_function (CORE_ADDR pc)
 {
-  FRAME_FIND_SAVED_REGS (*frame_info_addr, *saved_regs_addr);
+  return find_pc_sect_function (pc, find_pc_mapped_section (pc));
 }
 
-/* Return the innermost lexical block in execution
  in a specified stack frame.  The frame address is assumed valid.  */
+/* These variables are used to cache the most recent result
* of find_pc_partial_function. */
 
-struct block *
-get_frame_block (frame)
-     FRAME frame;
-{
-  struct frame_info fi;
+static CORE_ADDR cache_pc_function_low = 0;
+static CORE_ADDR cache_pc_function_high = 0;
+static char *cache_pc_function_name = 0;
+static struct obj_section *cache_pc_function_section = NULL;
 
-  fi = get_frame_info (frame);
-  return block_for_pc (fi.pc);
-}
+/* Clear cache, e.g. when symbol table is discarded. */
 
-struct block *
-get_current_block ()
+void
+clear_pc_function_cache (void)
 {
-  return block_for_pc (read_pc ());
+  cache_pc_function_low = 0;
+  cache_pc_function_high = 0;
+  cache_pc_function_name = (char *) 0;
+  cache_pc_function_section = NULL;
 }
 
-CORE_ADDR
-get_pc_function_start (pc)
-     CORE_ADDR pc;
-{
-  register struct block *bl = block_for_pc (pc);
-  register struct symbol *symbol;
-  if (bl == 0)
-    {
-      register int misc_index = find_pc_misc_function (pc);
-      if (misc_index >= 0)
-       return misc_function_vector[misc_index].address;
-      return 0;
-    }
-  symbol = block_function (bl);
-  bl = SYMBOL_BLOCK_VALUE (symbol);
-  return BLOCK_START (bl);
-}  
+/* Finds the "function" (text symbol) that is smaller than PC but
+   greatest of all of the potential text symbols in SECTION.  Sets
+   *NAME and/or *ADDRESS conditionally if that pointer is non-null.
+   If ENDADDR is non-null, then set *ENDADDR to be the end of the
+   function (exclusive), but passing ENDADDR as non-null means that
+   the function might cause symbols to be read.  This function either
+   succeeds or fails (not halfway succeeds).  If it succeeds, it sets
+   *NAME, *ADDRESS, and *ENDADDR to real information and returns 1.
+   If it fails, it sets *NAME, *ADDRESS, and *ENDADDR to zero and
+   returns 0.  */
 
-/* Return the symbol for the function executing in frame FRAME.  */
+/* Backward compatibility, no section argument.  */
 
-struct symbol *
-get_frame_function (frame)
-     FRAME frame;
+int
+find_pc_partial_function (CORE_ADDR pc, char **name, CORE_ADDR *address,
+                         CORE_ADDR *endaddr)
 {
-  register struct block *bl = get_frame_block (frame);
-  if (bl == 0)
-    return 0;
-  return block_function (bl);
-}
-\f
-/* Return the innermost lexical block containing the specified pc value,
-   or 0 if there is none.  */
+  struct obj_section *section;
+  struct partial_symtab *pst;
+  struct symbol *f;
+  struct minimal_symbol *msymbol;
+  struct partial_symbol *psb;
+  int i;
+  CORE_ADDR mapped_pc;
+
+  /* To ensure that the symbol returned belongs to the correct setion
+     (and that the last [random] symbol from the previous section
+     isn't returned) try to find the section containing PC.  First try
+     the overlay code (which by default returns NULL); and second try
+     the normal section code (which almost always succeeds).  */
+  section = find_pc_overlay (pc);
+  if (section == NULL)
+    section = find_pc_section (pc);
+
+  mapped_pc = overlay_mapped_address (pc, section);
+
+  if (mapped_pc >= cache_pc_function_low
+      && mapped_pc < cache_pc_function_high
+      && section == cache_pc_function_section)
+    goto return_cached_value;
+
+  msymbol = lookup_minimal_symbol_by_pc_section (mapped_pc, section);
+  pst = find_pc_sect_psymtab (mapped_pc, section);
+  if (pst)
+    {
+      /* Need to read the symbols to get a good value for the end address.  */
+      if (endaddr != NULL && !pst->readin)
+       {
+         /* Need to get the terminal in case symbol-reading produces
+            output.  */
+         target_terminal_ours_for_output ();
+         PSYMTAB_TO_SYMTAB (pst);
+       }
 
-struct block *
-block_for_pc (pc)
-     register CORE_ADDR pc;
-{
-  register struct block *b;
-  register int bot, top, half;
-  register struct symtab *s;
-  struct blockvector *bl;
+      if (pst->readin)
+       {
+         /* Checking whether the msymbol has a larger value is for the
+            "pathological" case mentioned in print_frame_info.  */
+         f = find_pc_sect_function (mapped_pc, section);
+         if (f != NULL
+             && (msymbol == NULL
+                 || (BLOCK_START (SYMBOL_BLOCK_VALUE (f))
+                     >= SYMBOL_VALUE_ADDRESS (msymbol))))
+           {
+             cache_pc_function_low = BLOCK_START (SYMBOL_BLOCK_VALUE (f));
+             cache_pc_function_high = BLOCK_END (SYMBOL_BLOCK_VALUE (f));
+             cache_pc_function_name = SYMBOL_LINKAGE_NAME (f);
+             cache_pc_function_section = section;
+             goto return_cached_value;
+           }
+       }
+      else
+       {
+         /* Now that static symbols go in the minimal symbol table, perhaps
+            we could just ignore the partial symbols.  But at least for now
+            we use the partial or minimal symbol, whichever is larger.  */
+         psb = find_pc_sect_psymbol (pst, mapped_pc, section);
+
+         if (psb
+             && (msymbol == NULL ||
+                 (SYMBOL_VALUE_ADDRESS (psb)
+                  >= SYMBOL_VALUE_ADDRESS (msymbol))))
+           {
+             /* This case isn't being cached currently. */
+             if (address)
+               *address = SYMBOL_VALUE_ADDRESS (psb);
+             if (name)
+               *name = SYMBOL_LINKAGE_NAME (psb);
+             /* endaddr non-NULL can't happen here.  */
+             return 1;
+           }
+       }
+    }
+
+  /* Not in the normal symbol tables, see if the pc is in a known section.
+     If it's not, then give up.  This ensures that anything beyond the end
+     of the text seg doesn't appear to be part of the last function in the
+     text segment.  */
 
-  /* First search all symtabs for one whose file contains our pc */
+  if (!section)
+    msymbol = NULL;
 
-  for (s = symtab_list; s; s = s->next)
+  /* Must be in the minimal symbol table.  */
+  if (msymbol == NULL)
     {
-      bl = BLOCKVECTOR (s);
-      b = BLOCKVECTOR_BLOCK (bl, 0);
-      if (BLOCK_START (b) <= pc
-         && BLOCK_END (b) > pc)
-       break;
+      /* No available symbol.  */
+      if (name != NULL)
+       *name = 0;
+      if (address != NULL)
+       *address = 0;
+      if (endaddr != NULL)
+       *endaddr = 0;
+      return 0;
     }
 
-  if (s == 0)
-    return 0;
-
-  /* Then search that symtab for the smallest block that wins.  */
-  /* Use binary search to find the last block that starts before PC.  */
+  cache_pc_function_low = SYMBOL_VALUE_ADDRESS (msymbol);
+  cache_pc_function_name = SYMBOL_LINKAGE_NAME (msymbol);
+  cache_pc_function_section = section;
 
-  bot = 0;
-  top = BLOCKVECTOR_NBLOCKS (bl);
+  /* If the minimal symbol has a size, use it for the cache.
+     Otherwise use the lesser of the next minimal symbol in the same
+     section, or the end of the section, as the end of the
+     function.  */
 
-  while (top - bot > 1)
+  if (MSYMBOL_SIZE (msymbol) != 0)
+    cache_pc_function_high = cache_pc_function_low + MSYMBOL_SIZE (msymbol);
+  else
     {
-      half = (top - bot + 1) >> 1;
-      b = BLOCKVECTOR_BLOCK (bl, bot + half);
-      if (BLOCK_START (b) <= pc)
-       bot += half;
+      /* Step over other symbols at this same address, and symbols in
+        other sections, to find the next symbol in this section with
+        a different address.  */
+
+      for (i = 1; SYMBOL_LINKAGE_NAME (msymbol + i) != NULL; i++)
+       {
+         if (SYMBOL_VALUE_ADDRESS (msymbol + i) != SYMBOL_VALUE_ADDRESS (msymbol)
+             && SYMBOL_OBJ_SECTION (msymbol + i) == SYMBOL_OBJ_SECTION (msymbol))
+           break;
+       }
+
+      if (SYMBOL_LINKAGE_NAME (msymbol + i) != NULL
+         && SYMBOL_VALUE_ADDRESS (msymbol + i) < obj_section_endaddr (section))
+       cache_pc_function_high = SYMBOL_VALUE_ADDRESS (msymbol + i);
       else
-       top = bot + half;
+       /* We got the start address from the last msymbol in the objfile.
+          So the end address is the end of the section.  */
+       cache_pc_function_high = obj_section_endaddr (section);
     }
 
-  /* Now search backward for a block that ends after PC.  */
+ return_cached_value:
 
-  while (bot >= 0)
+  if (address)
     {
-      b = BLOCKVECTOR_BLOCK (bl, bot);
-      if (BLOCK_END (b) > pc)
-       return b;
-      bot--;
+      if (pc_in_unmapped_range (pc, section))
+       *address = overlay_unmapped_address (cache_pc_function_low, section);
+      else
+       *address = cache_pc_function_low;
     }
 
-  return 0;
-}
+  if (name)
+    *name = cache_pc_function_name;
 
-/* Return the function containing pc value PC.
-   Returns 0 if function is not known.  */
+  if (endaddr)
+    {
+      if (pc_in_unmapped_range (pc, section))
+       {
+         /* Because the high address is actually beyond the end of
+            the function (and therefore possibly beyond the end of
+            the overlay), we must actually convert (high - 1) and
+            then add one to that. */
 
-struct symbol *
-find_pc_function (pc)
-     CORE_ADDR pc;
-{
-  register struct block *b = block_for_pc (pc);
-  if (b == 0)
-    return 0;
-  return block_function (b);
+         *endaddr = 1 + overlay_unmapped_address (cache_pc_function_high - 1,
+                                                  section);
+       }
+      else
+       *endaddr = cache_pc_function_high;
+    }
+
+  return 1;
 }
 
-/* Find the misc function whose address is the largest
-   while being less than PC.  Return its index in misc_function_vector.
-   Returns -1 if PC is not in suitable range.  */
+/* Return the innermost stack frame executing inside of BLOCK,
+   or NULL if there is no such frame.  If BLOCK is NULL, just return NULL.  */
 
-int
-find_pc_misc_function (pc)
-     register CORE_ADDR pc;
+struct frame_info *
+block_innermost_frame (struct block *block)
 {
-  register int lo = 0;
-  register int hi = misc_function_count-1;
-  register int new;
-  register int distance;
-
-  /* Note that the last thing in the vector is always _etext.  */
-
-  /* trivial reject range test */
-  if (pc < misc_function_vector[0].address || 
-      pc > misc_function_vector[hi].address)
-    return -1;
-
-  do {
-    new = (lo + hi) >> 1;
-    distance = misc_function_vector[new].address - pc;
-    if (distance == 0)
-      return new;              /* an exact match */
-    else if (distance > 0)
-      hi = new;
-    else
-      lo = new;
-  } while (hi-lo != 1);
-
-  /* if here, we had no exact match, so return the lower choice */
-  return lo;
-}
+  struct frame_info *frame;
+  CORE_ADDR start;
+  CORE_ADDR end;
+  CORE_ADDR calling_pc;
 
-/* Return the innermost stack frame executing inside of the specified block,
-   or zero if there is no such frame.  */
+  if (block == NULL)
+    return NULL;
 
-FRAME
-block_innermost_frame (block)
-     struct block *block;
-{
-  struct frame_info fi;
-  register FRAME frame;
-  register CORE_ADDR start = BLOCK_START (block);
-  register CORE_ADDR end = BLOCK_END (block);
+  start = BLOCK_START (block);
+  end = BLOCK_END (block);
 
-  frame = 0;
-  while (1)
+  frame = get_current_frame ();
+  while (frame != NULL)
     {
-      fi = get_prev_frame_info (frame);
-      frame = fi.frame;
-      if (frame == 0)
-       return 0;
-      if (fi.pc >= start && fi.pc < end)
+      calling_pc = get_frame_address_in_block (frame);
+      if (calling_pc >= start && calling_pc < end)
        return frame;
+
+      frame = get_prev_frame (frame);
     }
-}
 
-static
-initialize ()
-{
+  return NULL;
 }
-
-END_FILE
This page took 0.029207 seconds and 4 git commands to generate.