Blame SOURCES/gdb-rhbz1225569-oom-killer-aarch64-frame-same-id-1of8.patch

2c2fa1
commit 1ec56e88aa9b052ab10b806d82fbdbc8d153d977
2c2fa1
Author: Pedro Alves <palves@redhat.com>
2c2fa1
Date:   Fri Nov 22 13:17:46 2013 +0000
2c2fa1
2c2fa1
    Eliminate dwarf2_frame_cache recursion, don't unwind from the dwarf2 sniffer (move dwarf2_tailcall_sniffer_first elsewhere).
2c2fa1
    
2c2fa1
    Two rationales, same patch.
2c2fa1
    
2c2fa1
    TL;DR 1:
2c2fa1
    
2c2fa1
     dwarf2_frame_cache recursion is evil.  dwarf2_frame_cache calls
2c2fa1
     dwarf2_tailcall_sniffer_first which then recurses into
2c2fa1
     dwarf2_frame_cache.
2c2fa1
    
2c2fa1
    TL;DR 2:
2c2fa1
    
2c2fa1
     An unwinder trying to unwind is evil.  dwarf2_frame_sniffer calls
2c2fa1
     dwarf2_frame_cache which calls dwarf2_tailcall_sniffer_first which
2c2fa1
     then tries to unwind the PC of the previous frame.
2c2fa1
    
2c2fa1
    Avoid all that by deferring dwarf2_tailcall_sniffer_first until it's
2c2fa1
    really necessary.
2c2fa1
    
2c2fa1
    Rationale 1
2c2fa1
    ===========
2c2fa1
    
2c2fa1
    A frame sniffer should not try to unwind, because that bypasses all
2c2fa1
    the validation checks done by get_prev_frame.  The UNWIND_SAME_ID
2c2fa1
    scenario is one such case where GDB is currently broken because (in
2c2fa1
    part) of this (the next patch adds a test that would fail without
2c2fa1
    this).
2c2fa1
    
2c2fa1
    GDB goes into an infinite loop in value_fetch_lazy, here:
2c2fa1
    
2c2fa1
          while (VALUE_LVAL (new_val) == lval_register && value_lazy (new_val))
2c2fa1
    	{
2c2fa1
    	  frame = frame_find_by_id (VALUE_FRAME_ID (new_val));
2c2fa1
    ...
2c2fa1
    	  new_val = get_frame_register_value (frame, regnum);
2c2fa1
    	}
2c2fa1
    
2c2fa1
    (top-gdb) bt
2c2fa1
    #0  value_fetch_lazy (val=0x11516d0) at ../../src/gdb/value.c:3510
2c2fa1
    #1  0x0000000000584bd8 in value_optimized_out (value=0x11516d0) at ../../src/gdb/value.c:1096
2c2fa1
    #2  0x00000000006fe7a1 in frame_register_unwind (frame=0x1492600, regnum=16, optimizedp=0x7fffffffcdec, unavailablep=0x7fffffffcde8, lvalp=0x7fffffffcdd8, addrp=
2c2fa1
        0x7fffffffcde0, realnump=0x7fffffffcddc, bufferp=0x7fffffffce10 "@\316\377\377\377\177") at ../../src/gdb/frame.c:940
2c2fa1
    #3  0x00000000006fea3a in frame_unwind_register (frame=0x1492600, regnum=16, buf=0x7fffffffce10 "@\316\377\377\377\177") at ../../src/gdb/frame.c:990
2c2fa1
    #4  0x0000000000473b9b in i386_unwind_pc (gdbarch=0xf54660, next_frame=0x1492600) at ../../src/gdb/i386-tdep.c:1771
2c2fa1
    #5  0x0000000000601dfa in gdbarch_unwind_pc (gdbarch=0xf54660, next_frame=0x1492600) at ../../src/gdb/gdbarch.c:2870
2c2fa1
    #6  0x0000000000693db5 in dwarf2_tailcall_sniffer_first (this_frame=0x1492600, tailcall_cachep=0x14926f0, entry_cfa_sp_offsetp=0x7fffffffcf00)
2c2fa1
        at ../../src/gdb/dwarf2-frame-tailcall.c:389
2c2fa1
    #7  0x0000000000690928 in dwarf2_frame_cache (this_frame=0x1492600, this_cache=0x1492618) at ../../src/gdb/dwarf2-frame.c:1245
2c2fa1
    #8  0x0000000000690f46 in dwarf2_frame_sniffer (self=0x8e4980, this_frame=0x1492600, this_cache=0x1492618) at ../../src/gdb/dwarf2-frame.c:1423
2c2fa1
    #9  0x000000000070203b in frame_unwind_find_by_frame (this_frame=0x1492600, this_cache=0x1492618) at ../../src/gdb/frame-unwind.c:112
2c2fa1
    #10 0x00000000006fd681 in get_frame_id (fi=0x1492600) at ../../src/gdb/frame.c:408
2c2fa1
    #11 0x00000000007006c2 in get_prev_frame_1 (this_frame=0xdc1860) at ../../src/gdb/frame.c:1826
2c2fa1
    #12 0x0000000000700b7a in get_prev_frame (this_frame=0xdc1860) at ../../src/gdb/frame.c:2056
2c2fa1
    #13 0x0000000000514588 in frame_info_to_frame_object (frame=0xdc1860) at ../../src/gdb/python/py-frame.c:322
2c2fa1
    #14 0x000000000051784c in bootstrap_python_frame_filters (frame=0xdc1860, frame_low=0, frame_high=-1) at ../../src/gdb/python/py-framefilter.c:1396
2c2fa1
    #15 0x0000000000517a6f in apply_frame_filter (frame=0xdc1860, flags=7, args_type=CLI_SCALAR_VALUES, out=0xed7a90, frame_low=0, frame_high=-1)
2c2fa1
        at ../../src/gdb/python/py-framefilter.c:1492
2c2fa1
    #16 0x00000000005e77b0 in backtrace_command_1 (count_exp=0x0, show_locals=0, no_filters=0, from_tty=1) at ../../src/gdb/stack.c:1777
2c2fa1
    #17 0x00000000005e7c0f in backtrace_command (arg=0x0, from_tty=1) at ../../src/gdb/stack.c:1891
2c2fa1
    #18 0x00000000004e37a7 in do_cfunc (c=0xda4fa0, args=0x0, from_tty=1) at ../../src/gdb/cli/cli-decode.c:107
2c2fa1
    #19 0x00000000004e683c in cmd_func (cmd=0xda4fa0, args=0x0, from_tty=1) at ../../src/gdb/cli/cli-decode.c:1882
2c2fa1
    #20 0x00000000006f35ed in execute_command (p=0xcc66c2 "", from_tty=1) at ../../src/gdb/top.c:468
2c2fa1
    #21 0x00000000005f8853 in command_handler (command=0xcc66c0 "bt") at ../../src/gdb/event-top.c:435
2c2fa1
    #22 0x00000000005f8e12 in command_line_handler (rl=0xfe05f0 "@") at ../../src/gdb/event-top.c:632
2c2fa1
    #23 0x000000000074d2c6 in rl_callback_read_char () at ../../src/readline/callback.c:220
2c2fa1
    #24 0x00000000005f8375 in rl_callback_read_char_wrapper (client_data=0x0) at ../../src/gdb/event-top.c:164
2c2fa1
    #25 0x00000000005f876a in stdin_event_handler (error=0, client_data=0x0) at ../../src/gdb/event-top.c:375
2c2fa1
    #26 0x00000000005f72fa in handle_file_event (data=...) at ../../src/gdb/event-loop.c:768
2c2fa1
    #27 0x00000000005f67a3 in process_event () at ../../src/gdb/event-loop.c:342
2c2fa1
    #28 0x00000000005f686a in gdb_do_one_event () at ../../src/gdb/event-loop.c:406
2c2fa1
    #29 0x00000000005f68bb in start_event_loop () at ../../src/gdb/event-loop.c:431
2c2fa1
    #30 0x00000000005f83a7 in cli_command_loop (data=0x0) at ../../src/gdb/event-top.c:179
2c2fa1
    #31 0x00000000005eeed3 in current_interp_command_loop () at ../../src/gdb/interps.c:327
2c2fa1
    #32 0x00000000005ef8ff in captured_command_loop (data=0x0) at ../../src/gdb/main.c:267
2c2fa1
    #33 0x00000000005ed2f6 in catch_errors (func=0x5ef8e4 <captured_command_loop>, func_args=0x0, errstring=0x8b6554 "", mask=RETURN_MASK_ALL)
2c2fa1
        at ../../src/gdb/exceptions.c:524
2c2fa1
    #34 0x00000000005f0d21 in captured_main (data=0x7fffffffd9e0) at ../../src/gdb/main.c:1067
2c2fa1
    #35 0x00000000005ed2f6 in catch_errors (func=0x5efb9b <captured_main>, func_args=0x7fffffffd9e0, errstring=0x8b6554 "", mask=RETURN_MASK_ALL)
2c2fa1
        at ../../src/gdb/exceptions.c:524
2c2fa1
    #36 0x00000000005f0d57 in gdb_main (args=0x7fffffffd9e0) at ../../src/gdb/main.c:1076
2c2fa1
    #37 0x000000000045bb6a in main (argc=4, argv=0x7fffffffdae8) at ../../src/gdb/gdb.c:34
2c2fa1
    (top-gdb)
2c2fa1
    
2c2fa1
    GDB is trying to unwind the PC register of the previous frame (frame
2c2fa1
    #5 above), starting from the frame being sniffed (the THIS frame).
2c2fa1
    But the THIS frame's unwinder says the PC of the previous frame is
2c2fa1
    actually the same as the previous's frame's next frame (which is the
2c2fa1
    same frame we started with, the THIS frame), therefore it returns an
2c2fa1
    lval_register lazy value with frame set to THIS frame.  And so the
2c2fa1
    value_fetch_lazy loop never ends.
2c2fa1
    
2c2fa1
    
2c2fa1
    Rationale 2
2c2fa1
    ===========
2c2fa1
    
2c2fa1
    As an experiment, I tried making dwarf2-frame.c:read_addr_from_reg use
2c2fa1
    address_from_register.  That caused a bunch of regressions, but it
2c2fa1
    actually took me a long while to figure out what was going on.  Turns
2c2fa1
    out dwarf2-frame.c:read_addr_from_reg is called while computing the
2c2fa1
    frame's CFA, from within dwarf2_frame_cache.  address_from_register
2c2fa1
    wants to create a register with frame_id set to the frame being
2c2fa1
    constructed.  To create the frame id, we again call dwarf2_frame_cache,
2c2fa1
    which given:
2c2fa1
    
2c2fa1
    static struct dwarf2_frame_cache *
2c2fa1
    dwarf2_frame_cache (struct frame_info *this_frame, void **this_cache)
2c2fa1
    {
2c2fa1
    ...
2c2fa1
      if (*this_cache)
2c2fa1
        return *this_cache;
2c2fa1
    
2c2fa1
    returns an incomplete object to the caller:
2c2fa1
    static void
2c2fa1
    dwarf2_frame_this_id (struct frame_info *this_frame, void **this_cache,
2c2fa1
    		      struct frame_id *this_id)
2c2fa1
    {
2c2fa1
      struct dwarf2_frame_cache *cache =
2c2fa1
        dwarf2_frame_cache (this_frame, this_cache);
2c2fa1
    ...
2c2fa1
     (*this_id) = frame_id_build (cache->cfa, get_frame_func (this_frame));
2c2fa1
    }
2c2fa1
    
2c2fa1
    As cache->cfa is still 0 (we were trying to compute it!), and
2c2fa1
    get_frame_id recalls this id from here on, we end up with a broken
2c2fa1
    frame id in recorded for this frame.  Later, when inspecting locals,
2c2fa1
    the dwarf machinery needs to know the selected frame's base, which
2c2fa1
    calls get_frame_base:
2c2fa1
    
2c2fa1
    CORE_ADDR
2c2fa1
    get_frame_base (struct frame_info *fi)
2c2fa1
    {
2c2fa1
      return get_frame_id (fi).stack_addr;
2c2fa1
    }
2c2fa1
    
2c2fa1
    which as seen above then returns 0 ...
2c2fa1
    
2c2fa1
    So I gave up using address_from_register.
2c2fa1
    
2c2fa1
    But, the pain of investigating this made me want to have GDB itself
2c2fa1
    assert that recursion never happens here.  So I wrote a patch to do
2c2fa1
    that.  But, it triggers on current mainline, because
2c2fa1
    dwarf2_tailcall_sniffer_first, called from dwarf2_frame_cache, unwinds
2c2fa1
    the this_frame.
2c2fa1
    
2c2fa1
    A sniffer shouldn't be trying to unwind, exactly because of this sort
2c2fa1
    of tricky issue.  The patch defers calling
2c2fa1
    dwarf2_tailcall_sniffer_first until it's really necessary, in
2c2fa1
    dwarf2_frame_prev_register (thus actually outside the sniffer path).
2c2fa1
    As this makes the call to dwarf2_frame_sniffer in dwarf2_frame_cache
2c2fa1
    unnecessary again, the patch removes that too.
2c2fa1
    
2c2fa1
    Tested on x86_64 Fedora 17.
2c2fa1
    
2c2fa1
    gdb/
2c2fa1
    2013-11-22  Pedro Alves  <palves@redhat.com>
2c2fa1
    
2c2fa1
    	PR 16155
2c2fa1
    	* dwarf2-frame.c (struct dwarf2_frame_cache)
2c2fa1
    	
2c2fa1
    	entry_cfa_sp_offset_p>: New fields.
2c2fa1
    	(dwarf2_frame_cache): Adjust to use the new cache fields instead
2c2fa1
    	of locals.  Don't call dwarf2_tailcall_sniffer_first here.
2c2fa1
    	(dwarf2_frame_prev_register): Call it here, but only once.
2c2fa1
2c2fa1
Index: gdb-7.6.1/gdb/dwarf2-frame.c
2c2fa1
===================================================================
2c2fa1
--- gdb-7.6.1.orig/gdb/dwarf2-frame.c
2c2fa1
+++ gdb-7.6.1/gdb/dwarf2-frame.c
2c2fa1
@@ -984,12 +984,22 @@ struct dwarf2_frame_cache
2c2fa1
   /* The .text offset.  */
2c2fa1
   CORE_ADDR text_offset;
2c2fa1
 
2c2fa1
+  /* True if we already checked whether this frame is the bottom frame
2c2fa1
+     of a virtual tail call frame chain.  */
2c2fa1
+  int checked_tailcall_bottom;
2c2fa1
+
2c2fa1
   /* If not NULL then this frame is the bottom frame of a TAILCALL_FRAME
2c2fa1
      sequence.  If NULL then it is a normal case with no TAILCALL_FRAME
2c2fa1
      involved.  Non-bottom frames of a virtual tail call frames chain use
2c2fa1
      dwarf2_tailcall_frame_unwind unwinder so this field does not apply for
2c2fa1
      them.  */
2c2fa1
   void *tailcall_cache;
2c2fa1
+
2c2fa1
+  /* The number of bytes to subtract from TAILCALL_FRAME frames frame
2c2fa1
+     base to get the SP, to simulate the return address pushed on the
2c2fa1
+     stack.  */
2c2fa1
+  LONGEST entry_cfa_sp_offset;
2c2fa1
+  int entry_cfa_sp_offset_p;
2c2fa1
 };
2c2fa1
 
2c2fa1
 /* A cleanup that sets a pointer to NULL.  */
2c2fa1
@@ -1014,8 +1024,6 @@ dwarf2_frame_cache (struct frame_info *t
2c2fa1
   struct dwarf2_fde *fde;
2c2fa1
   volatile struct gdb_exception ex;
2c2fa1
   CORE_ADDR entry_pc;
2c2fa1
-  LONGEST entry_cfa_sp_offset;
2c2fa1
-  int entry_cfa_sp_offset_p = 0;
2c2fa1
   const gdb_byte *instr;
2c2fa1
 
2c2fa1
   if (*this_cache)
2c2fa1
@@ -1080,8 +1088,8 @@ dwarf2_frame_cache (struct frame_info *t
2c2fa1
 	  && (gdbarch_dwarf2_reg_to_regnum (gdbarch, fs->regs.cfa_reg)
2c2fa1
 	      == gdbarch_sp_regnum (gdbarch)))
2c2fa1
 	{
2c2fa1
-	  entry_cfa_sp_offset = fs->regs.cfa_offset;
2c2fa1
-	  entry_cfa_sp_offset_p = 1;
2c2fa1
+	  cache->entry_cfa_sp_offset = fs->regs.cfa_offset;
2c2fa1
+	  cache->entry_cfa_sp_offset_p = 1;
2c2fa1
 	}
2c2fa1
     }
2c2fa1
   else
2c2fa1
@@ -1230,13 +1238,6 @@ incomplete CFI data; unspecified registe
2c2fa1
     cache->undefined_retaddr = 1;
2c2fa1
 
2c2fa1
   do_cleanups (old_chain);
2c2fa1
-
2c2fa1
-  /* Try to find a virtual tail call frames chain with bottom (callee) frame
2c2fa1
-     starting at THIS_FRAME.  */
2c2fa1
-  dwarf2_tailcall_sniffer_first (this_frame, &cache->tailcall_cache,
2c2fa1
-				 (entry_cfa_sp_offset_p
2c2fa1
-				  ? &entry_cfa_sp_offset : NULL));
2c2fa1
-
2c2fa1
   discard_cleanups (reset_cache_cleanup);
2c2fa1
   return cache;
2c2fa1
 }
2c2fa1
@@ -1282,6 +1283,16 @@ dwarf2_frame_prev_register (struct frame
2c2fa1
   CORE_ADDR addr;
2c2fa1
   int realnum;
2c2fa1
 
2c2fa1
+  /* Check whether THIS_FRAME is the bottom frame of a virtual tail
2c2fa1
+     call frame chain.  */
2c2fa1
+  if (!cache->checked_tailcall_bottom)
2c2fa1
+    {
2c2fa1
+      cache->checked_tailcall_bottom = 1;
2c2fa1
+      dwarf2_tailcall_sniffer_first (this_frame, &cache->tailcall_cache,
2c2fa1
+				     (cache->entry_cfa_sp_offset_p
2c2fa1
+				      ? &cache->entry_cfa_sp_offset : NULL));
2c2fa1
+    }
2c2fa1
+
2c2fa1
   /* Non-bottom frames of a virtual tail call frames chain use
2c2fa1
      dwarf2_tailcall_frame_unwind unwinder so this code does not apply for
2c2fa1
      them.  If dwarf2_tailcall_prev_register_first does not have specific value
2c2fa1
@@ -1408,10 +1419,6 @@ dwarf2_frame_sniffer (const struct frame
2c2fa1
   if (self->type != NORMAL_FRAME)
2c2fa1
     return 0;
2c2fa1
 
2c2fa1
-  /* Preinitializa the cache so that TAILCALL_FRAME can find the record by
2c2fa1
-     dwarf2_tailcall_sniffer_first.  */
2c2fa1
-  dwarf2_frame_cache (this_frame, this_cache);
2c2fa1
-
2c2fa1
   return 1;
2c2fa1
 }
2c2fa1