From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 7333 invoked by alias); 27 Sep 2013 13:55:35 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Received: (qmail 7322 invoked by uid 89); 27 Sep 2013 13:55:35 -0000 Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 27 Sep 2013 13:55:35 +0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=0.1 required=5.0 tests=AWL,BAYES_20,RP_MATCHES_RCVD,SPAM_SUBJECT autolearn=no version=3.3.2 X-HELO: mx1.redhat.com Received: from int-mx10.intmail.prod.int.phx2.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.23]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id r8RDtQTc020793 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK); Fri, 27 Sep 2013 09:55:26 -0400 Received: from host2.jankratochvil.net (ovpn-116-66.ams2.redhat.com [10.36.116.66]) by int-mx10.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id r8RDtMJv002692 (version=TLSv1/SSLv3 cipher=AES128-SHA bits=128 verify=NO); Fri, 27 Sep 2013 09:55:24 -0400 Date: Fri, 27 Sep 2013 13:55:00 -0000 From: Jan Kratochvil To: "Metzger, Markus T" Cc: "gdb-patches@sourceware.org" Subject: Re: [patch v4 18/24] record-btrace: extend unwinder Message-ID: <20130927135521.GB13376@host2.jankratochvil.net> References: <1372842874-28951-1-git-send-email-markus.t.metzger@intel.com> <1372842874-28951-19-git-send-email-markus.t.metzger@intel.com> <20130818190842.GN24153@host2.jankratochvil.net> MIME-Version: 1.0 Content-Type: multipart/mixed; boundary="ikeVEW9yuYc//A+q" Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.21 (2010-09-15) X-IsSubscribed: yes X-SW-Source: 2013-09/txt/msg00955.txt.bz2 --ikeVEW9yuYc//A+q Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-length: 4232 On Mon, 16 Sep 2013 13:21:29 +0200, Metzger, Markus T wrote: > > > An assertion in get_frame_id at frame.c:340 requires that a frame > > > provides a stack address. The record-btrace unwinder can't provide > > > this since the trace does not contain data. I incorrectly set > > > stack_addr_p to 1 to avoid the assertion. > > > > Primarily record-btrace can provide the stack address. You know $sp at the > > end of the recoding and you can query .eh_frame/.debug_frame at any PC > > address what is the difference between $sp and caller's $sp at that exact PC. > > This assumes either all the involved binaries were built with -fasynchronous- > > unwind-tables (for .eh_frame) or that debug info (for .debug_frame) is > > present. The former is true in Fedora / Red Hat distros, unaware how others. > > This would only hold for functions that have not yet returned to their caller. > If we go back far enough, the branch trace will also contain functions that > have already returned to their caller for which we do not have any information. > I would even argue that this is the majority of functions in the branch trace. In many cases one can reconstruct $sp. But for example if alloca() was in use I see now $sp cannot be reconstructed. So I agree now GDB has to handle cases when $sp is not known for a frame_id. BTW in many cases one realy can reconstruct all past $sp addresses from the btrace buffer. I have tried it for one backtrace of /usr/bin/gdb : It will not work (at least) in two cases: * for -O0 code (not -O2) GCC does not produce DW_CFA_def_cfa_offset but it provides just: DW_CFA_def_cfa_register: r6 (rbp) As you describe we do not know $rbp that time anymore. * Even in -O2 code if a function uses alloca() GCC will produce again: DW_CFA_def_cfa_register: r6 (rbp) I have no idea in which percentage of real world code the DW_CFA_def_cfa_offset dependency would work, C++ code CFI may look differently than GDB in plain C I tried below: CIE has always: DW_CFA_def_cfa: r7 (rsp) ofs 8 #0 0x00007ffff5eef950 in __poll_nocancel DW_CFA_def_cfa: r7 (rsp) ofs 8 #1 0x000000000059bb63 in poll DW_CFA_def_cfa_offset: 80 #2 gdb_wait_for_event #3 0x000000000059c2da in gdb_do_one_event DW_CFA_def_cfa_offset: 64 #4 0x000000000059c517 in start_event_loop DW_CFA_def_cfa_offset: 48 #5 0x00000000005953a3 in captured_command_loop DW_CFA_def_cfa_offset: 16 #6 0x00000000005934aa in catch_errors DW_CFA_def_cfa_offset: 112 #7 0x000000000059607e in captured_main DW_CFA_def_cfa_offset: 192 #8 0x00000000005934aa in catch_errors DW_CFA_def_cfa_offset: 112 #9 0x0000000000596c44 in gdb_main DW_CFA_def_cfa_offset: 16 #10 0x000000000045526e in main DW_CFA_def_cfa_offset: 64 As an obvious check $sp in #10 main 0x7fffffffd940 - $sp in #0 0x7fffffffd6b8: (gdb) p 0x7fffffffd940 - 0x7fffffffd6b8 $1 = 648 8+80+64+48+16+112+192+112+16 = 648 This is just FYI, I do not ask to implement it. I do not think knowing just $sp is too important when it works only sometimes. > > The current method of constant STACK_ADDR may have some problems with > > frame_id_inner() but I did not investigate it more. > > By looking at the code, frame_id_inner () should always fail since all btrace > frames have stack_addr == 0. > > On the other hand, frame_id_inner is only called for frames of type > NORMAL_FRAME, whereas btrace frames have type BTRACE_FRAME. OK, I agree now frame_id_inner() is not needed. > This has meanwhile been resolved. This had been a side-effect of throwing > an error in to_fetch_registers. When I just return, function arguments are > correctly displayed as unavailable and the "can't compute CFA for this frame" > message is gone. With v6 patchset it is only sometimes gone, I still get it. Tested with (results are the same): gcc (GCC) 4.8.2 20130927 (prerelease) gcc-4.8.1-10.fc21.x86_64 int f(int i) { return i; } int main(void) { f(1); return 0; } gcc -o test3 test3.c -Wall -g ./gdb ./test3 -ex start -ex 'record btrace' -ex step -ex step -ex reverse-step -ex frame #0 f (i=) at test3.c:2 2 return i; (gdb) _ It gets fixed by the attached patch. Thanks, Jan --ikeVEW9yuYc//A+q Content-Type: text/plain; charset=us-ascii Content-Disposition: inline; filename="cfa.patch" Content-length: 1824 diff --git a/gdb/dwarf2-frame.c b/gdb/dwarf2-frame.c index 2aff23e..518b0b9 100644 --- a/gdb/dwarf2-frame.c +++ b/gdb/dwarf2-frame.c @@ -1495,9 +1495,13 @@ dwarf2_frame_base_sniffer (struct frame_info *this_frame) CORE_ADDR dwarf2_frame_cfa (struct frame_info *this_frame) { + extern const struct frame_unwind record_btrace_frame_unwind; + extern const struct frame_unwind record_btrace_tailcall_frame_unwind; while (get_frame_type (this_frame) == INLINE_FRAME) this_frame = get_prev_frame (this_frame); - if (get_frame_unwind_stop_reason (this_frame) == UNWIND_UNAVAILABLE) + if (get_frame_unwind_stop_reason (this_frame) == UNWIND_UNAVAILABLE + || frame_unwinder_is (this_frame, &record_btrace_frame_unwind) + || frame_unwinder_is (this_frame, &record_btrace_tailcall_frame_unwind)) throw_error (NOT_AVAILABLE_ERROR, _("can't compute CFA for this frame: " "required registers or memory are unavailable")); diff --git a/gdb/record-btrace.c b/gdb/record-btrace.c index d634712..9a4287b 100644 --- a/gdb/record-btrace.c +++ b/gdb/record-btrace.c @@ -1217,7 +1217,7 @@ record_btrace_frame_dealloc_cache (struct frame_info *self, void *this_cache) Therefore this unwinder reports any possibly unwound registers as . */ -static const struct frame_unwind record_btrace_frame_unwind = +const struct frame_unwind record_btrace_frame_unwind = { BTRACE_FRAME, record_btrace_frame_unwind_stop_reason, @@ -1228,7 +1228,7 @@ static const struct frame_unwind record_btrace_frame_unwind = record_btrace_frame_dealloc_cache }; -static const struct frame_unwind record_btrace_tailcall_frame_unwind = +const struct frame_unwind record_btrace_tailcall_frame_unwind = { BTRACE_TAILCALL_FRAME, record_btrace_frame_unwind_stop_reason, --ikeVEW9yuYc//A+q--