From patchwork Thu Feb 1 18:54:55 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Bartosz Nitka X-Patchwork-Id: 25734 Received: (qmail 95118 invoked by alias); 1 Feb 2018 18:55:33 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 93704 invoked by uid 89); 1 Feb 2018 18:55:00 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-26.9 required=5.0 tests=BAYES_00, FREEMAIL_FROM, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.2 spammy=cust, glasgow, Glasgow X-HELO: mail-wm0-f44.google.com Received: from mail-wm0-f44.google.com (HELO mail-wm0-f44.google.com) (74.125.82.44) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 01 Feb 2018 18:54:59 +0000 Received: by mail-wm0-f44.google.com with SMTP id 141so7688956wme.3 for ; Thu, 01 Feb 2018 10:54:58 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:mime-version:from:date:message-id:subject:to; bh=ri2rxJ5v/bL8iXBVKOOhBLxq+Ig7lKMiBF/T/4Mjt+U=; b=BU3ZVbpSgLHPPlRsSwUk7BYDku7dImGKug0F18/qxzzhmXG9VUGhQftCHY2gwtUIc7 bXhQdwpjLTQZQ8WXpBTaSSAR/Mvn7bDDzlKvItfp76L2RVwoWm1RXr9JGxhpDktp3Be/ E08Bv/Gy90PYNxd4NSTM42ZR6iAzMEisfMBk5nGhfnqV6fzRJUBsTOwp2UA57hgvdjUP G0GTkhuZ2YOqg9XcIWFxk+IwkgOBBAFcLFvOidgpl7JODR3gKZRIFbiejJliOCTC9quG YmF/MBMxoyNYcI9MYIYzN9bDjmEm1Zuil5aT1gnu4XEvFC2yZt1PFLscKzd8+XMFXyod 4W7w== X-Gm-Message-State: AKwxytez4kMrSd+qS/tH3gWOoNdqsiLWToWo5CRCGpSly55JfDWlpYW2 +maTyDkc1eKVZNyihB5ciswOlVQApCodCUaFrpqgkZ3U X-Google-Smtp-Source: AH8x224k402Y575BF4Hjz4KJuLxlcsjcFRMrUJgI87Q4y2OqVTam+5Cg/wUzpnFdDef1Fu7kXeeIB1iXKfyt4yQaHGk= X-Received: by 10.80.146.29 with SMTP id i29mr63733705eda.27.1517511296578; Thu, 01 Feb 2018 10:54:56 -0800 (PST) MIME-Version: 1.0 Received: by 10.80.134.239 with HTTP; Thu, 1 Feb 2018 10:54:55 -0800 (PST) From: Bartosz Nitka Date: Thu, 1 Feb 2018 18:54:55 +0000 Message-ID: Subject: [PATCH] Don't rewind PC for GHC generated frames To: gdb-patches@sourceware.org GHC - the Haskell compiler generates code that violates one of GDB's assumptions. GDB assumes that the address in a frame was generated by the call instruction and that it is the address of the call instruction plus 1 (I'm rephrasing the comment in get_frame_address_in_block). So to get the real address, one has to substract 1. This is doubly beneficial because some functions are "noreturn" and don't have further instructions after call, so GDB would be looking at gibberish. All in all, this is good for C-like languages. GHC generates completely different code. It uses jumps instead of call and manages the stack itself. Furthermore every piece of code is preceeded by some metadata called the Info Table. If we substract from the program counter it ends up pointing to the metadata, which is undesirable. GHC has a workaround for this [1] that works most of the time, it basically lies in the DWARF data and extends the function one byte backwards. That helps with making unwinding succeed most of the time, but then the address is also used for looking up symbols and they can't be resolved. This change disables program counter rewinding for GHC generated compilation units. Some additional context can be found here [2]. [1] https://phabricator.haskell.org/diffusion/GHC/browse/master/compiler/nativeGen/Dwarf/Types.hs;e9ae0cae9eb6a340473b339b5711ae76c6bdd045$399-417 [2] https://ghc.haskell.org/trac/ghc/wiki/DWARF gdb/ChangeLog: * dwarf2read.c (process_full_comp_unit): Populate producer_is_ghc. * frame.c (get_frame_address_in_block): Don't rewind the program counter for code generated by GHC. * symtab.h (struct compunit_symtab): Add producer_is_ghc. --- gdb/ChangeLog | 7 +++++++ gdb/dwarf2read.c | 4 ++++ gdb/frame.c | 7 +++++++ gdb/symtab.h | 3 +++ 4 files changed, 21 insertions(+) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 5c3338f..ff62136 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,10 @@ +2018-02-01 Bartosz Nitka + + * dwarf2read.c (process_full_comp_unit): Populate producer_is_ghc. + * frame.c (get_frame_address_in_block): Don't rewind the program + counter for code generated by GHC. + * symtab.h (struct compunit_symtab): Add producer_is_ghc. + 2018-02-01 Yao Qi * arm-tdep.c (arm_record_extension_space): Change ret to signed. diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 51d0f39..2516c48 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -10501,6 +10501,10 @@ process_full_comp_unit (struct dwarf2_per_cu_data *per_cu, cust->epilogue_unwind_valid = 1; cust->call_site_htab = cu->call_site_htab; + + if (startswith (cu->producer, + "The Glorious Glasgow Haskell Compilation System")) + cust->producer_is_ghc = 1; } if (dwarf2_per_objfile->using_index) diff --git a/gdb/frame.c b/gdb/frame.c index 1384ecc..d00df70 100644 --- a/gdb/frame.c +++ b/gdb/frame.c @@ -2458,7 +2458,14 @@ get_frame_address_in_block (struct frame_info *this_frame) && (get_frame_type (this_frame) == NORMAL_FRAME || get_frame_type (this_frame) == TAILCALL_FRAME || get_frame_type (this_frame) == INLINE_FRAME)) + { + /* GHC intermixes metadata (info tables) with code, going back is + guaranteed to land us in the metadata. */ + struct compunit_symtab *cust = find_pc_compunit_symtab (pc); + if (cust != NULL && cust->producer_is_ghc) + return pc; return pc - 1; + } return pc; } diff --git a/gdb/symtab.h b/gdb/symtab.h index f9d52e7..c164e5b 100644 --- a/gdb/symtab.h +++ b/gdb/symtab.h @@ -1432,6 +1432,9 @@ struct compunit_symtab instruction). This is supported by GCC since 4.5.0. */ unsigned int epilogue_unwind_valid : 1; + /* This CU was produced by Glasgow Haskell Compiler */ + unsigned int producer_is_ghc : 1; + /* struct call_site entries for this compilation unit or NULL. */ htab_t call_site_htab;