From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 13919 invoked by alias); 23 Nov 2010 02:12:24 -0000 Received: (qmail 13817 invoked by uid 22791); 23 Nov 2010 02:12:20 -0000 X-SWARE-Spam-Status: No, hits=-5.4 required=5.0 tests=AWL,BAYES_00,KAM_STOCKGEN,RCVD_IN_DNSWL_HI,SPF_HELO_PASS,TW_BJ,TW_XZ,T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 23 Nov 2010 02:12:09 +0000 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id oAN2C86e010620 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Mon, 22 Nov 2010 21:12:08 -0500 Received: from host0.dyn.jankratochvil.net (ovpn01.gateway.prod.ext.phx2.redhat.com [10.5.9.1]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id oAN2C22j023942 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Mon, 22 Nov 2010 21:12:06 -0500 Received: from host0.dyn.jankratochvil.net (localhost.localdomain [127.0.0.1]) by host0.dyn.jankratochvil.net (8.14.4/8.14.4) with ESMTP id oAN2C1QQ019274; Tue, 23 Nov 2010 03:12:01 +0100 Received: (from jkratoch@localhost) by host0.dyn.jankratochvil.net (8.14.4/8.14.4/Submit) id oAN2BxS4019273; Tue, 23 Nov 2010 03:11:59 +0100 Date: Tue, 23 Nov 2010 02:12:00 -0000 From: Jan Kratochvil To: Doug Evans Cc: gdb-patches@sourceware.org, Ian Lance Taylor Subject: Re: [patch] Support -fsplit-stack (previous frame inner to this frame) Message-ID: <20101123021159.GA19258@host0.dyn.jankratochvil.net> References: <20101123001325.GA11983@host0.dyn.jankratochvil.net> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.21 (2010-09-15) X-IsSubscribed: yes 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 X-SW-Source: 2010-11/txt/msg00338.txt.bz2 On Tue, 23 Nov 2010 01:34:12 +0100, Doug Evans wrote: > Nit: Do we have the framework for recording these globals per process? > [or some such - e.g. if/when gdb can debug multiple different > programs] Oops. Thanks, Jan gdb/ 2010-11-23 Jan Kratochvil * frame.c (frame_inferior_data, struct frame_inferior_data) (frame_inferior_data_cleanup, frame_inferior_data_get) (frame_new_objfile): New. (frame_id_inner): New variable inf_data. Check l.code_addr with MORESTACK_START and MORESTACK_END. (_initialize_frame): Install frame_new_objfile). Initialize frame_inferior_data. gdb/testsuite/ 2010-11-23 Jan Kratochvil * gdb.base/morestack.exp: New file. * gdb.base/morestack.c: New file. --- a/gdb/frame.c +++ b/gdb/frame.c @@ -155,6 +155,40 @@ frame_stash_find (struct frame_id id) return NULL; } +/* Per-inferior data key. */ +static const struct inferior_data *frame_inferior_data; + +struct frame_inferior_data + { + /* Start and end of the `__morestack' function. MORESTACK_END address is + the end plus one (exclusive) one. */ + + CORE_ADDR morestack_start, morestack_end; + }; + +static void +frame_inferior_data_cleanup (struct inferior *inf, void *arg) +{ + struct frame_inferior_data *inf_data = arg; + + xfree (inf_data); +} + +static struct frame_inferior_data * +frame_inferior_data_get (void) +{ + struct frame_inferior_data *inf_data; + + inf_data = inferior_data (current_inferior (), frame_inferior_data); + if (inf_data == NULL) + { + inf_data = xzalloc (sizeof (*inf_data)); + set_inferior_data (current_inferior (), frame_inferior_data, inf_data); + } + + return inf_data; +} + /* Invalidate the frame stash by removing all entries in it. */ static void @@ -487,6 +521,29 @@ frame_id_eq (struct frame_id l, struct frame_id r) return eq; } +/* Initialize MORESTACK_START and MORESTACK_END. */ + +static void +frame_new_objfile (struct objfile *objfile) +{ + struct frame_inferior_data *inf_data = frame_inferior_data_get (); + struct minimal_symbol *msymbol; + + inf_data->morestack_start = inf_data->morestack_end = 0; + + msymbol = lookup_minimal_symbol ("__morestack", NULL, NULL); + if (msymbol == NULL) + return; + + inf_data->morestack_start + = gdbarch_convert_from_func_ptr_addr (target_gdbarch, + SYMBOL_VALUE_ADDRESS (msymbol), + ¤t_target); + + inf_data->morestack_end = (inf_data->morestack_start + + MSYMBOL_SIZE (msymbol)); +} + /* Safety net to check whether frame ID L should be inner to frame ID R, according to their stack addresses. @@ -522,6 +579,7 @@ frame_id_eq (struct frame_id l, struct frame_id r) static int frame_id_inner (struct gdbarch *gdbarch, struct frame_id l, struct frame_id r) { + struct frame_inferior_data *inf_data = frame_inferior_data_get (); int inner; if (!l.stack_addr_p || !r.stack_addr_p) @@ -550,6 +608,12 @@ frame_id_inner (struct gdbarch *gdbarch, struct frame_id l, struct frame_id r) block with the greater depth. */ inner = contained_in (lb, rb); } + else if (l.code_addr_p && inf_data->morestack_start <= l.code_addr + && l.code_addr < inf_data->morestack_end) + { + /* gcc -fsplit-stack __morestack can continue the stack anywhere. */ + inner = 0; + } else /* Only return non-zero when strictly inner than. Note that, per comment in "frame.h", there is some fuzz here. Frameless @@ -2218,6 +2282,7 @@ _initialize_frame (void) obstack_init (&frame_cache_obstack); observer_attach_target_changed (frame_observer_target_changed); + observer_attach_new_objfile (frame_new_objfile); add_prefix_cmd ("backtrace", class_maintenance, set_backtrace_cmd, _("\ Set backtrace specific variables.\n\ @@ -2275,4 +2340,7 @@ When non-zero, frame specific internal debugging is enabled."), NULL, show_frame_debug, &setdebuglist, &showdebuglist); + + frame_inferior_data + = register_inferior_data_with_cleanup (frame_inferior_data_cleanup); } --- /dev/null +++ b/gdb/testsuite/gdb.base/morestack.c @@ -0,0 +1,105 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2010 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . */ + +/* Based on the gcc testcase `gcc/testsuite/gcc.dg/split-1.c'. This test + needs to use setrlimit to set the stack size, so it can only run on Unix. + */ + +#include +#include +#include +#include +#include + +/* Use a noinline function to ensure that the buffer is not removed + from the stack. */ +static void use_buffer (char *buf) __attribute__ ((noinline)); +static void +use_buffer (char *buf) +{ + buf[0] = '\0'; +} + +static volatile int marker_var; + +static void +marker_miss (void) +{ + marker_var = 0; +} + +static void +marker_hit (void) +{ + marker_var = 0; +} + +void *reserved; +#define RESERVED_SIZE 0x1000000 + +/* Each recursive call uses 10,000 bytes. We call it 1000 times, + using a total of 10,000,000 bytes. If -fsplit-stack is not + working, that will overflow our stack limit. */ + +static void +down (int i) +{ + char buf[10000]; + static void *last; + + if (last && last < (void *) buf) + { + printf ("%d: %p < %p\n", i, last, buf); + marker_hit (); + } + last = buf; + + if (i == 500) + { + if (munmap (reserved, RESERVED_SIZE) != 0) + abort (); + reserved = NULL; + } + + if (i > 0) + { + use_buffer (buf); + down (i - 1); + } + else + marker_miss (); +} + +int +main (void) +{ + struct rlimit r; + + reserved = mmap (NULL, RESERVED_SIZE, PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + if (reserved == MAP_FAILED) + abort (); + + /* We set a stack limit because we are usually invoked via make, and + make sets the stack limit to be as large as possible. */ + r.rlim_cur = 8192 * 1024; + r.rlim_max = 8192 * 1024; + if (setrlimit (RLIMIT_STACK, &r) != 0) + abort (); + down (1000); + return 0; +} --- /dev/null +++ b/gdb/testsuite/gdb.base/morestack.exp @@ -0,0 +1,52 @@ +# Copyright (C) 2010 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +if [get_compiler_info "ignored"] { + return -1 +} + +if {$gcc_compiled == 0} { + return -1 +} + +set testfile morestack +if { [prepare_for_testing ${testfile}.exp ${testfile} ${testfile}.c {additional_flags=-fsplit-stack}] } { + return -1 +} + +if ![runto_main] { + return -1 +} + +gdb_breakpoint "marker_hit" +gdb_breakpoint "marker_miss" + +set test "continue" +gdb_test_multiple $test $test { + -re "marker_hit.*$gdb_prompt $" { + pass $test + } + -re "marker_miss.*$gdb_prompt $" { + # The testcase failed to violated the frame_id_inner condition by + # handing inner frame with higher (on the stack-grows-down arches) + # $sp address than the outer frame. + xfail $test + return 0 + } +} + +# FAIL was on `bt' producing: +# Backtrace stopped: previous frame inner to this frame (corrupt stack?) +gdb_test "up 3000" " in main .*"