From patchwork Tue Mar 14 10:08:37 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Roman Pen X-Patchwork-Id: 19569 Received: (qmail 49836 invoked by alias); 14 Mar 2017 10:09:00 -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 49812 invoked by uid 89); 14 Mar 2017 10:08:59 -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, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SPF_PASS, URIBL_RED autolearn=ham version=3.3.2 spammy=H*Ad:U*dan, Hx-languages-length:3853, U*jan.kratochvil, 6206 X-HELO: mail-wr0-f180.google.com Received: from mail-wr0-f180.google.com (HELO mail-wr0-f180.google.com) (209.85.128.180) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 14 Mar 2017 10:08:57 +0000 Received: by mail-wr0-f180.google.com with SMTP id l37so120571939wrc.1 for ; Tue, 14 Mar 2017 03:08:57 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id; bh=j/TiWzTYZSweXA1t5wbajPri/mgzlyPQIu8cu+hr3q8=; b=sMVl8gn24VDMLQUmDvhbt6dPfzeI9Qggc1RNTLdi/LrZRnHos18IL2ZJhwppVuKHzm zgcbmWKOkaP11POZHZKSYBxv1aYujy/1Vbi2vqvpooJzA/lvVLD7n2DNYdEAxlKMOuSp 4+D9uyxXUoJazBS5UKYL1Uzy9RvGjTSrL7plEjcYgQexYrZeJRjyneEB8U/jPb/49Qzl G2BTAtiHh7wlPEUxriZ5e6W8hrekTZp3KhNKg1mwC1vCUc/xx6i9aV4UE8jtPnwksCcH hCSoVhDbvN8oNVhrx9sJNBDWeGYLUI6MEm5unnO1vigy2ULzqIquCIhsjYDaBwVB/lF0 Ir9Q== X-Gm-Message-State: AMke39kAfQZchX66ewi8AIALe1BmSB5Wd7L37XbQFQfnjmMa30GfZUDv8lLwz5zsZYKNYR/G X-Received: by 10.223.178.205 with SMTP id g71mr30533675wrd.158.1489486135899; Tue, 14 Mar 2017 03:08:55 -0700 (PDT) Received: from pb.pb.local ([62.217.45.26]) by smtp.gmail.com with ESMTPSA id 40sm28555118wry.22.2017.03.14.03.08.54 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 14 Mar 2017 03:08:55 -0700 (PDT) From: Roman Pen To: Cc: Roman Pen , Pedro Alves , Daniel Jacobowitz , Jan Kratochvil , gdb-patches@sourceware.org, Stefan Hajnoczi , Paolo Bonzini Subject: [PATCH 1/1] [RFC] gdb: corelow: make possible to modify (set) registers for a corefile Date: Tue, 14 Mar 2017 11:08:37 +0100 Message-Id: <20170314100838.12647-1-roman.penyaev@profitbricks.com> Despite the fact that this is a hairy hack this change eases debugging of a jmp_buf (setjmp()) and user contexts (makecontext()), which are highly used in QEMU project as a part of coroutines. This change allows setting registers for a corefile, thus QEMU gdb script (qemu/scripts/qemugdb/coroutine.py) is allowed to investigate backtrace of a preempted coroutine context. Previously only debugging of a live process was allowed. This patch caches all register on a first attempt to modify register '(gdb) set $REG = ADDR' and then cached copy is always returned from get_core_registers(). This change should not break previous behaviour if nobody sets any register, i.e. on each get_core_registers() call registers from a corefile will be reread. Signed-off-by: Roman Pen Cc: Pedro Alves Cc: Daniel Jacobowitz Cc: Jan Kratochvil Cc: gdb-patches@sourceware.org QEMU guys who can be interested in this new gdb behaviour: Cc: Stefan Hajnoczi Cc: Paolo Bonzini --- gdb/corelow.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/gdb/corelow.c b/gdb/corelow.c index c46af0a8a59d..4a4b20ed57a0 100644 --- a/gdb/corelow.c +++ b/gdb/corelow.c @@ -74,6 +74,15 @@ static struct gdbarch *core_gdbarch = NULL; unix child targets. */ static struct target_section_table *core_data; +/* Cached registers. Once registers are modified (set) for a corefile, + they are cached and then are always fetched from get_core_registers(). + This hairy hack is used only for one purpose: give a possibility to + debug jmp_buf (setjmp()) and user contexts (makecontext()). */ + +static struct cached_reg { + char regp[MAX_REGISTER_SIZE]; +} *core_cachedregs; + static void core_files_info (struct target_ops *); static struct core_fns *sniff_core_bfd (bfd *); @@ -213,6 +222,11 @@ core_close (struct target_ops *self) } core_vec = NULL; core_gdbarch = NULL; + if (core_cachedregs) + { + xfree(core_cachedregs); + core_cachedregs = NULL; + } } static void @@ -620,6 +634,18 @@ get_core_registers (struct target_ops *ops, } gdbarch = get_regcache_arch (regcache); + + if (core_cachedregs) + { + /* If registers were once modified (set) for a corefile, + follow this path and always return cached registers */ + + for (i = 0; i < gdbarch_num_regs(gdbarch); i++) + regcache_raw_supply(regcache, i, &core_cachedregs[i]); + + return; + } + if (gdbarch_iterate_over_regset_sections_p (gdbarch)) gdbarch_iterate_over_regset_sections (gdbarch, get_core_registers_cb, @@ -639,6 +665,29 @@ get_core_registers (struct target_ops *ops, } static void +set_core_registers (struct target_ops *self, struct regcache *regcache, + int regnum) +{ + struct gdbarch *gdbarch; + int i; + + gdbarch = get_regcache_arch(regcache); + + if (core_cachedregs == NULL) + core_cachedregs = (struct cached_reg*)xcalloc(gdbarch_num_regs(gdbarch), + sizeof(*core_cachedregs)); + + for (i = 0; i < gdbarch_num_regs(gdbarch); i++) + regcache_raw_collect(regcache, i, &core_cachedregs[i]); +} + +static void +prepare_core_registers (struct target_ops *self, struct regcache *arg1) +{ + /* nothing here */ +} + +static void core_files_info (struct target_ops *t) { print_section_info (core_data, core_bfd); @@ -1050,6 +1099,8 @@ init_core_ops (void) core_ops.to_close = core_close; core_ops.to_detach = core_detach; core_ops.to_fetch_registers = get_core_registers; + core_ops.to_store_registers = set_core_registers; + core_ops.to_prepare_to_store = prepare_core_registers; core_ops.to_xfer_partial = core_xfer_partial; core_ops.to_files_info = core_files_info; core_ops.to_insert_breakpoint = ignore;