gdb/
authorPedro Alves <palves@redhat.com>
Fri, 18 Mar 2011 18:44:34 +0000 (18:44 +0000)
committerPedro Alves <palves@redhat.com>
Fri, 18 Mar 2011 18:44:34 +0000 (18:44 +0000)
* frame.c (frame_unwind_pc): Rename to ...
(frame_unwind_pc_if_available): ... this.  New `pc' output
parameter.  Change return type to int.  Gracefully handle
gdbarch_unwind_pc throwing NOT_AVAILABLE_ERROR.  Return 0 if that
happened, or 1 otherwise.
(frame_unwind_pc): Reimplement on top of
frame_unwind_pc_if_available.
(get_frame_func): Rename to ...
(get_frame_func_if_available): New `pc' output parameter.  Change
return type to int.  Gracefully handle the PC not being available.
(get_frame_func): Reimplement on top of
get_frame_func_if_available.
(select_frame): Handle the PC being unavailable.
(get_prev_frame): Handle the PC being unavailable.
(get_frame_pc_if_available): New.
(get_frame_address_in_block_if_available): New.
(find_frame_sal): Handle the frame PC not being available.
* frame.h (get_frame_pc_if_available): Declare.
(get_frame_address_in_block_if_available): Declare.
(get_frame_func_if_available): Declare.
* stack.c (print_frame_info): Handle the PC being unavailable.
(find_frame_funname): Ditto.
(print_frame): Handle the PC being unavailable.
(get_frame_language): Ditto.
* blockframe.c (get_frame_block): Ditto.
* macroscope.c (default_macro_scope): Ditto.
* tui/tui-stack.c (tui_show_frame_info): Ditto.

gdb/blockframe.c
gdb/frame.c
gdb/frame.h
gdb/macroscope.c
gdb/stack.c
gdb/testsuite/ChangeLog
gdb/tui/tui-stack.c

index b9aaf54da612185603ef9cadb9754c8a4f9d9b4d..5bc593034ea0bae7224f2a566aceaf51211b0e27 100644 (file)
 struct block *
 get_frame_block (struct frame_info *frame, CORE_ADDR *addr_in_block)
 {
-  const CORE_ADDR pc = get_frame_address_in_block (frame);
+  CORE_ADDR pc;
   struct block *bl;
   int inline_count;
 
+  if (!get_frame_address_in_block_if_available (frame, &pc))
+    return NULL;
+
   if (addr_in_block)
     *addr_in_block = pc;
 
index 5bd1b03966ac1b83410da409d0ff947bfb8e12ff..20d8404e9842de1a03ab5f794caa981156655d29 100644 (file)
@@ -619,15 +619,17 @@ frame_find_by_id (struct frame_id id)
   return NULL;
 }
 
-static CORE_ADDR
-frame_unwind_pc (struct frame_info *this_frame)
+static int
+frame_unwind_pc_if_available (struct frame_info *this_frame, CORE_ADDR *pc)
 {
   if (!this_frame->prev_pc.p)
     {
-      CORE_ADDR pc;
-
       if (gdbarch_unwind_pc_p (frame_unwind_arch (this_frame)))
        {
+         volatile struct gdb_exception ex;
+         struct gdbarch *prev_gdbarch;
+         CORE_ADDR pc = 0;
+
          /* The right way.  The `pure' way.  The one true way.  This
             method depends solely on the register-unwind code to
             determine the value of registers in THIS frame, and hence
@@ -644,20 +646,62 @@ frame_unwind_pc (struct frame_info *this_frame)
             frame.  This is all in stark contrast to the old
             FRAME_SAVED_PC which would try to directly handle all the
             different ways that a PC could be unwound.  */
-         pc = gdbarch_unwind_pc (frame_unwind_arch (this_frame), this_frame);
+         prev_gdbarch = frame_unwind_arch (this_frame);
+
+         TRY_CATCH (ex, RETURN_MASK_ERROR)
+           {
+             pc = gdbarch_unwind_pc (prev_gdbarch, this_frame);
+           }
+         if (ex.reason < 0 && ex.error == NOT_AVAILABLE_ERROR)
+           {
+             this_frame->prev_pc.p = -1;
+
+             if (frame_debug)
+               fprintf_unfiltered (gdb_stdlog,
+                                   "{ frame_unwind_pc (this_frame=%d)"
+                                   " -> <unavailable> }\n",
+                                   this_frame->level);
+           }
+         else if (ex.reason < 0)
+           {
+             throw_exception (ex);
+           }
+         else
+           {
+             this_frame->prev_pc.value = pc;
+             this_frame->prev_pc.p = 1;
+             if (frame_debug)
+               fprintf_unfiltered (gdb_stdlog,
+                                   "{ frame_unwind_pc (this_frame=%d) "
+                                   "-> %s }\n",
+                                   this_frame->level,
+                                   hex_string (this_frame->prev_pc.value));
+           }
        }
       else
        internal_error (__FILE__, __LINE__, _("No unwind_pc method"));
-      this_frame->prev_pc.value = pc;
-      this_frame->prev_pc.p = 1;
-      if (frame_debug)
-       fprintf_unfiltered (gdb_stdlog,
-                           "{ frame_unwind_caller_pc "
-                           "(this_frame=%d) -> %s }\n",
-                           this_frame->level,
-                           hex_string (this_frame->prev_pc.value));
     }
-  return this_frame->prev_pc.value;
+  if (this_frame->prev_pc.p < 0)
+    {
+      *pc = -1;
+      return 0;
+    }
+  else
+    {
+      *pc = this_frame->prev_pc.value;
+      return 1;
+    }
+}
+
+static CORE_ADDR
+frame_unwind_pc (struct frame_info *this_frame)
+{
+  CORE_ADDR pc;
+
+  if (!frame_unwind_pc_if_available (this_frame, &pc))
+    throw_error (NOT_AVAILABLE_ERROR, _("PC not available"));
+  else
+    return pc;
 }
 
 CORE_ADDR
@@ -666,25 +710,59 @@ frame_unwind_caller_pc (struct frame_info *this_frame)
   return frame_unwind_pc (skip_inlined_frames (this_frame));
 }
 
-CORE_ADDR
-get_frame_func (struct frame_info *this_frame)
+int
+get_frame_func_if_available (struct frame_info *this_frame, CORE_ADDR *pc)
 {
   struct frame_info *next_frame = this_frame->next;
 
   if (!next_frame->prev_func.p)
     {
+      CORE_ADDR addr_in_block;
+
       /* Make certain that this, and not the adjacent, function is
          found.  */
-      CORE_ADDR addr_in_block = get_frame_address_in_block (this_frame);
-      next_frame->prev_func.p = 1;
-      next_frame->prev_func.addr = get_pc_function_start (addr_in_block);
-      if (frame_debug)
-       fprintf_unfiltered (gdb_stdlog,
-                           "{ get_frame_func (this_frame=%d) -> %s }\n",
-                           this_frame->level,
-                           hex_string (next_frame->prev_func.addr));
+      if (!get_frame_address_in_block_if_available (this_frame, &addr_in_block))
+       {
+         next_frame->prev_func.p = -1;
+         if (frame_debug)
+           fprintf_unfiltered (gdb_stdlog,
+                               "{ get_frame_func (this_frame=%d)"
+                               " -> unavailable }\n",
+                               this_frame->level);
+       }
+      else
+       {
+         next_frame->prev_func.p = 1;
+         next_frame->prev_func.addr = get_pc_function_start (addr_in_block);
+         if (frame_debug)
+           fprintf_unfiltered (gdb_stdlog,
+                               "{ get_frame_func (this_frame=%d) -> %s }\n",
+                               this_frame->level,
+                               hex_string (next_frame->prev_func.addr));
+       }
+    }
+
+  if (next_frame->prev_func.p < 0)
+    {
+      *pc = -1;
+      return 0;
     }
-  return next_frame->prev_func.addr;
+  else
+    {
+      *pc = next_frame->prev_func.addr;
+      return 1;
+    }
+}
+
+CORE_ADDR
+get_frame_func (struct frame_info *this_frame)
+{
+  CORE_ADDR pc;
+
+  if (!get_frame_func_if_available (this_frame, &pc))
+    throw_error (NOT_AVAILABLE_ERROR, _("PC not available"));
+
+  return pc;
 }
 
 static enum register_status
@@ -1298,8 +1376,6 @@ deprecated_safe_get_selected_frame (void)
 void
 select_frame (struct frame_info *fi)
 {
-  struct symtab *s;
-
   selected_frame = fi;
   /* NOTE: cagney/2002-05-04: FI can be NULL.  This occurs when the
      frame is being invalidated.  */
@@ -1319,23 +1395,28 @@ select_frame (struct frame_info *fi)
      source language of this frame, and switch to it if desired.  */
   if (fi)
     {
-      /* We retrieve the frame's symtab by using the frame PC.  However
-         we cannot use the frame PC as-is, because it usually points to
-         the instruction following the "call", which is sometimes the
-         first instruction of another function.  So we rely on
-         get_frame_address_in_block() which provides us with a PC which
-         is guaranteed to be inside the frame's code block.  */
-      s = find_pc_symtab (get_frame_address_in_block (fi));
-      if (s
-         && s->language != current_language->la_language
-         && s->language != language_unknown
-         && language_mode == language_mode_auto)
+      CORE_ADDR pc;
+
+      /* We retrieve the frame's symtab by using the frame PC.
+        However we cannot use the frame PC as-is, because it usually
+        points to the instruction following the "call", which is
+        sometimes the first instruction of another function.  So we
+        rely on get_frame_address_in_block() which provides us with a
+        PC which is guaranteed to be inside the frame's code
+        block.  */
+      if (get_frame_address_in_block_if_available (fi, &pc))
        {
-         set_language (s->language);
+         struct symtab *s = find_pc_symtab (pc);
+
+         if (s
+             && s->language != current_language->la_language
+             && s->language != language_unknown
+             && language_mode == language_mode_auto)
+           set_language (s->language);
        }
     }
 }
-       
+
 /* Create an arbitrary (i.e. address specified by user) or innermost frame.
    Always returns a non-NULL value.  */
 
@@ -1755,10 +1836,14 @@ inside_entry_func (struct frame_info *this_frame)
 struct frame_info *
 get_prev_frame (struct frame_info *this_frame)
 {
+  CORE_ADDR frame_pc;
+  int frame_pc_p;
+
   /* There is always a frame.  If this assertion fails, suspect that
      something should be calling get_selected_frame() or
      get_current_frame().  */
   gdb_assert (this_frame != NULL);
+  frame_pc_p = get_frame_pc_if_available (this_frame, &frame_pc);
 
   /* tausq/2004-12-07: Dummy frames are skipped because it doesn't make much
      sense to stop unwinding at a dummy frame.  One place where a dummy
@@ -1773,6 +1858,7 @@ get_prev_frame (struct frame_info *this_frame)
   if (this_frame->level >= 0
       && get_frame_type (this_frame) == NORMAL_FRAME
       && !backtrace_past_main
+      && frame_pc_p
       && inside_main_func (this_frame))
     /* Don't unwind past main().  Note, this is done _before_ the
        frame has been marked as previously unwound.  That way if the
@@ -1819,6 +1905,7 @@ get_prev_frame (struct frame_info *this_frame)
   if (this_frame->level >= 0
       && get_frame_type (this_frame) == NORMAL_FRAME
       && !backtrace_past_entry
+      && frame_pc_p
       && inside_entry_func (this_frame))
     {
       frame_debug_got_null_frame (this_frame, "inside entry func");
@@ -1832,7 +1919,7 @@ get_prev_frame (struct frame_info *this_frame)
       && (get_frame_type (this_frame) == NORMAL_FRAME
          || get_frame_type (this_frame) == INLINE_FRAME)
       && get_frame_type (get_next_frame (this_frame)) == NORMAL_FRAME
-      && get_frame_pc (this_frame) == 0)
+      && frame_pc_p && frame_pc == 0)
     {
       frame_debug_got_null_frame (this_frame, "zero PC");
       return NULL;
@@ -1848,6 +1935,28 @@ get_frame_pc (struct frame_info *frame)
   return frame_unwind_pc (frame->next);
 }
 
+int
+get_frame_pc_if_available (struct frame_info *frame, CORE_ADDR *pc)
+{
+  volatile struct gdb_exception ex;
+
+  gdb_assert (frame->next != NULL);
+
+  TRY_CATCH (ex, RETURN_MASK_ERROR)
+    {
+      *pc = frame_unwind_pc (frame->next);
+    }
+  if (ex.reason < 0)
+    {
+      if (ex.error == NOT_AVAILABLE_ERROR)
+       return 0;
+      else
+       throw_exception (ex);
+    }
+
+  return 1;
+}
+
 /* Return an address that falls within THIS_FRAME's code block.  */
 
 CORE_ADDR
@@ -1908,11 +2017,30 @@ get_frame_address_in_block (struct frame_info *this_frame)
   return pc;
 }
 
+int
+get_frame_address_in_block_if_available (struct frame_info *this_frame,
+                                        CORE_ADDR *pc)
+{
+  volatile struct gdb_exception ex;
+
+  TRY_CATCH (ex, RETURN_MASK_ERROR)
+    {
+      *pc = get_frame_address_in_block (this_frame);
+    }
+  if (ex.reason < 0 && ex.error == NOT_AVAILABLE_ERROR)
+    return 0;
+  else if (ex.reason < 0)
+    throw_exception (ex);
+  else
+    return 1;
+}
+
 void
 find_frame_sal (struct frame_info *frame, struct symtab_and_line *sal)
 {
   struct frame_info *next_frame;
   int notcurrent;
+  CORE_ADDR pc;
 
   /* If the next frame represents an inlined function call, this frame's
      sal is the "call site" of that inlined function, which can not
@@ -1953,8 +2081,14 @@ find_frame_sal (struct frame_info *frame, struct symtab_and_line *sal)
      PC and such a PC indicates the current (rather than next)
      instruction/line, consequently, for such cases, want to get the
      line containing fi->pc.  */
-  notcurrent = (get_frame_pc (frame) != get_frame_address_in_block (frame));
-  (*sal) = find_pc_line (get_frame_pc (frame), notcurrent);
+  if (!get_frame_pc_if_available (frame, &pc))
+    {
+      init_sal (sal);
+      return;
+    }
+
+  notcurrent = (pc != get_frame_address_in_block (frame));
+  (*sal) = find_pc_line (pc, notcurrent);
 }
 
 /* Per "frame.h", return the ``address'' of the frame.  Code should
index e7053a8e7f5a6c5fbceb2b87fdfae6f383459418..25f20a944f7500ca36b396d02406037cc1818786 100644 (file)
@@ -284,6 +284,12 @@ extern struct frame_info *frame_find_by_id (struct frame_id id);
    This replaced: frame->pc; */
 extern CORE_ADDR get_frame_pc (struct frame_info *);
 
+/* Same as get_frame_pc, but return a boolean indication of whether
+   the PC is actually available, instead of throwing an error.  */
+
+extern int get_frame_pc_if_available (struct frame_info *frame,
+                                     CORE_ADDR *pc);
+
 /* An address (not necessarily aligned to an instruction boundary)
    that falls within THIS frame's code block.
 
@@ -299,6 +305,15 @@ extern CORE_ADDR get_frame_pc (struct frame_info *);
 
 extern CORE_ADDR get_frame_address_in_block (struct frame_info *this_frame);
 
+/* Same as get_frame_address_in_block, but returns a boolean
+   indication of whether the frame address is determinable (when the
+   PC is unavailable, it will not be), instead of possibly throwing an
+   error trying to read an unavailable PC.  */
+
+extern int
+  get_frame_address_in_block_if_available (struct frame_info *this_frame,
+                                          CORE_ADDR *pc);
+
 /* The frame's inner-most bound.  AKA the stack-pointer.  Confusingly
    known as top-of-stack.  */
 
@@ -309,6 +324,13 @@ extern CORE_ADDR get_frame_sp (struct frame_info *);
    that function isn't known.  */
 extern CORE_ADDR get_frame_func (struct frame_info *fi);
 
+/* Same as get_frame_func, but returns a boolean indication of whether
+   the frame function is determinable (when the PC is unavailable, it
+   will not be), instead of possibly throwing an error trying to read
+   an unavailable PC.  */
+
+extern int get_frame_func_if_available (struct frame_info *fi, CORE_ADDR *);
+
 /* Closely related to the resume address, various symbol table
    attributes that are determined by the PC.  Note that for a normal
    frame, the PC refers to the resume address after the return, and
index a93d175b22fe0011328cbc82c60c127ce4409f78..b529e68c1fd102e88a299ebd43816856ca9986ed 100644 (file)
@@ -102,12 +102,13 @@ default_macro_scope (void)
   struct symtab_and_line sal;
   struct macro_scope *ms;
   struct frame_info *frame;
+  CORE_ADDR pc;
 
   /* If there's a selected frame, use its PC.  */
   frame = deprecated_safe_get_selected_frame ();
-  if (frame)
-    sal = find_pc_line (get_frame_pc (frame), 0);
-  
+  if (frame && get_frame_pc_if_available (frame, &pc))
+    sal = find_pc_line (pc, 0);
+
   /* Fall back to the current listing position.  */
   else
     {
index 79c3a433dc38182044d6c0b10915a43c98fc99c0..de204182e7bf59abbb6e240c02525a3a7ea589fc 100644 (file)
@@ -654,8 +654,14 @@ print_frame_info (struct frame_info *frame, int print_level,
     }
 
   if (print_what != LOCATION)
-    set_default_breakpoint (1, sal.pspace,
-                           get_frame_pc (frame), sal.symtab, sal.line);
+    {
+      CORE_ADDR pc;
+
+      if (get_frame_pc_if_available (frame, &pc))
+       set_default_breakpoint (1, sal.pspace, pc, sal.symtab, sal.line);
+      else
+       set_default_breakpoint (0, 0, 0, 0, 0);
+    }
 
   annotate_frame_end ();
 
@@ -740,9 +746,13 @@ find_frame_funname (struct frame_info *frame, char **funname,
     }
   else
     {
-      struct minimal_symbol *msymbol = 
-       lookup_minimal_symbol_by_pc (get_frame_address_in_block (frame));
+      struct minimal_symbol *msymbol;
+      CORE_ADDR pc;
 
+      if (!get_frame_address_in_block_if_available (frame, &pc))
+       return;
+
+      msymbol = lookup_minimal_symbol_by_pc (pc);
       if (msymbol != NULL)
        {
          *funname = SYMBOL_PRINT_NAME (msymbol);
@@ -763,6 +773,10 @@ print_frame (struct frame_info *frame, int print_level,
   struct cleanup *old_chain, *list_chain;
   struct value_print_options opts;
   struct symbol *func;
+  CORE_ADDR pc = 0;
+  int pc_p;
+
+  pc_p = get_frame_pc_if_available (frame, &pc);
 
   stb = ui_out_stream_new (uiout);
   old_chain = make_cleanup_ui_out_stream_delete (stb);
@@ -770,7 +784,7 @@ print_frame (struct frame_info *frame, int print_level,
   find_frame_funname (frame, &funname, &funlang, &func);
 
   annotate_frame_begin (print_level ? frame_relative_level (frame) : 0,
-                       gdbarch, get_frame_pc (frame));
+                       gdbarch, pc);
 
   list_chain = make_cleanup_ui_out_tuple_begin_end (uiout, "frame");
 
@@ -782,11 +796,15 @@ print_frame (struct frame_info *frame, int print_level,
     }
   get_user_print_options (&opts);
   if (opts.addressprint)
-    if (frame_show_address (frame, sal) || !sal.symtab
+    if (!sal.symtab
+       || frame_show_address (frame, sal)
        || print_what == LOC_AND_ADDRESS)
       {
        annotate_frame_address ();
-       ui_out_field_core_addr (uiout, "addr", gdbarch, get_frame_pc (frame));
+       if (pc_p)
+         ui_out_field_core_addr (uiout, "addr", gdbarch, pc);
+       else
+         ui_out_field_string (uiout, "addr", "<unavailable>");
        annotate_frame_address_end ();
        ui_out_text (uiout, " in ");
       }
@@ -836,7 +854,7 @@ print_frame (struct frame_info *frame, int print_level,
       annotate_frame_source_end ();
     }
 
-  if (!funname || (!sal.symtab || !sal.symtab->filename))
+  if (pc_p && (!funname || (!sal.symtab || !sal.symtab->filename)))
     {
 #ifdef PC_SOLIB
       char *lib = PC_SOLIB (get_frame_pc (frame));
@@ -2142,6 +2160,10 @@ get_frame_language (void)
 
   if (frame)
     {
+      volatile struct gdb_exception ex;
+      CORE_ADDR pc = 0;
+      struct symtab *s;
+
       /* We determine the current frame language by looking up its
          associated symtab.  To retrieve this symtab, we use the frame
          PC.  However we cannot use the frame PC as is, because it
@@ -2150,11 +2172,22 @@ get_frame_language (void)
          we rely on get_frame_address_in_block(), it provides us with
          a PC that is guaranteed to be inside the frame's code
          block.  */
-      CORE_ADDR pc = get_frame_address_in_block (frame);
-      struct symtab *s = find_pc_symtab (pc);
 
-      if (s)
-       return s->language;
+      TRY_CATCH (ex, RETURN_MASK_ERROR)
+       {
+         pc = get_frame_address_in_block (frame);
+       }
+      if (ex.reason < 0)
+       {
+         if (ex.error != NOT_AVAILABLE_ERROR)
+           throw_exception (ex);
+       }
+      else
+       {
+         s = find_pc_symtab (pc);
+         if (s != NULL)
+           return s->language;
+       }
     }
 
   return language_unknown;
index 8bb59b62918cabde35ea8ee9c9fc851351babd13..e3b1a8a2930efe00dc45e47366134775f96c8e24 100644 (file)
@@ -1,3 +1,33 @@
+2011-03-18  Pedro Alves  <pedro@codesourcery.com>
+
+       * frame.c (frame_unwind_pc): Rename to ...
+       (frame_unwind_pc_if_available): ... this.  New `pc' output
+       parameter.  Change return type to int.  Gracefully handle
+       gdbarch_unwind_pc throwing NOT_AVAILABLE_ERROR.  Return 0 if that
+       happened, or 1 otherwise.
+       (frame_unwind_pc): Reimplement on top of
+       frame_unwind_pc_if_available.
+       (get_frame_func): Rename to ...
+       (get_frame_func_if_available): New `pc' output parameter.  Change
+       return type to int.  Gracefully handle the PC not being available.
+       (get_frame_func): Reimplement on top of
+       get_frame_func_if_available.
+       (select_frame): Handle the PC being unavailable.
+       (get_prev_frame): Handle the PC being unavailable.
+       (get_frame_pc_if_available): New.
+       (get_frame_address_in_block_if_available): New.
+       (find_frame_sal): Handle the frame PC not being available.
+       * frame.h (get_frame_pc_if_available): Declare.
+       (get_frame_address_in_block_if_available): Declare.
+       (get_frame_func_if_available): Declare.
+       * stack.c (print_frame_info): Handle the PC being unavailable.
+       (find_frame_funname): Ditto.
+       (print_frame): Handle the PC being unavailable.
+       (get_frame_language): Ditto.
+       * blockframe.c (get_frame_block): Ditto.
+       * macroscope.c (default_macro_scope): Ditto.
+       * tui/tui-stack.c (tui_show_frame_info): Ditto.
+
 2011-03-18  Pedro Alves  <pedro@codesourcery.com>
 
        * dwarf2loc.c (dwarf2_evaluate_loc_desc): Catch
index f618d7c03cb4e87e4933a6e7428f6fdd28f03fce..0068610727ded59a50ac37035faf303ab3763348 100644 (file)
@@ -342,16 +342,23 @@ tui_show_frame_info (struct frame_info *fi)
       struct tui_gen_win_info *locator = tui_locator_win_info_ptr ();
       int source_already_displayed;
       struct symtab_and_line sal;
+      CORE_ADDR pc;
 
       find_frame_sal (fi, &sal);
 
       source_already_displayed = sal.symtab != 0
         && tui_source_is_displayed (sal.symtab->filename);
-      tui_set_locator_info (get_frame_arch (fi),
-                           sal.symtab == 0 ? "??" : sal.symtab->filename,
-                            tui_get_function_from_frame (fi),
-                            sal.line,
-                            get_frame_pc (fi));
+
+      if (get_frame_pc_if_available (fi, &pc))
+       tui_set_locator_info (get_frame_arch (fi),
+                             sal.symtab == 0 ? "??" : sal.symtab->filename,
+                             tui_get_function_from_frame (fi),
+                             sal.line,
+                             pc);
+      else
+       tui_set_locator_info (get_frame_arch (fi),
+                             "??", _("<unavailable>"), sal.line, 0);
+
       tui_show_locator_content ();
       start_line = 0;
       for (i = 0; i < (tui_source_windows ())->count; i++)