Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
From: Andrew Cagney <ac131313@redhat.com>
To: gdb-patches@sources.redhat.com
Subject: [patch/rfc/testsuite] Test GDB on not-so-little core files
Date: Wed, 14 Jan 2004 02:40:00 -0000	[thread overview]
Message-ID: <4004AC30.1040300@redhat.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 1158 bytes --]

Hello,

This test:

- runs a program that allocates a bit of memory
- lets the program dump core
- compares the corefile against a a running version of the program

On my i386 GNU/Linux system I'm seeing the failure:

> KFAIL: gdb.base/bigcore.exp: check heap (address 0xb7449008) (PRMS: gdb/1509)
> 
>                 === gdb Summary ===
> 
> # of expected passes            7
> # of known failures             1

from:

> (gdb) print $.next
> $55 = (struct list *) 0x400c0490
> (gdb) print $.next
> $56 = (struct list *) 0xbffc6008
> (gdb) print $.next
> Error accessing memory address 0xbffc6008: Invalid argument.
> (gdb) KFAIL: gdb.base/bigcore.exp: check heap (address 0xb7449008) (PRMS: gdb/15

which I suspect is due to the core file being a little big:

$ du -b bigcore.corefile
282624  bigcore.corefile
$ ls -l bigcore.corefile
-rw-------    1 cagney   cagney   3084910592 Jan 13 21:21 bigcore.corefile

and gdb having difficulty accessing the 2nd gb.

Given that people might want a bit of time to digest this (on some 
systems may not be so efficient at dumping core files making the test 
too slow) I'll follow this up in a week.

enjoy,
Andrew

[-- Attachment #2: diffs --]
[-- Type: text/plain, Size: 10443 bytes --]

2004-01-13  Andrew Cagney  <cagney@redhat.com>

	* gdb.base/bigcore.exp: New file.
	* gdb.base/bigcore.c: New file.

Index: gdb.base/bigcore.c
===================================================================
RCS file: gdb.base/bigcore.c
diff -N gdb.base/bigcore.c
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gdb.base/bigcore.c	14 Jan 2004 02:21:36 -0000
@@ -0,0 +1,181 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2004 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 2 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, write to the Free Software
+   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+   Please email any bugs, comments, and/or additions to this file to:
+   bug-gdb@prep.ai.mit.edu  */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/resource.h>
+
+/* Print routines:
+
+   The following are so that printf et.al. can be avoided.  Those
+   might try to use malloc() and that, for this code, would be a
+   disaster.  */
+
+#define printf do not use
+
+const char digit[] = "0123456789abcdefghijklmnopqrstuvwxyz";
+
+static void
+print_char (char c)
+{
+  write (1, &c, sizeof (c));
+}
+
+static void
+print_unsigned (unsigned long u)
+{
+  if (u >= 10)
+    print_unsigned (u / 10);
+  print_char (digit[u % 10]);
+}
+
+static void
+print_hex (unsigned long u)
+{
+  if (u >= 16)
+    print_hex (u / 16);
+  print_char (digit[u % 16]);
+}
+
+static void
+print_string (const char *s)
+{
+  for (; (*s) != '\0'; s++)
+    print_char ((*s));
+}
+
+/* Print the current values of RESOURCE.  */
+
+static void
+print_rlimit (int resource)
+{
+  struct rlimit rl;
+  getrlimit (resource, &rl);
+  print_string ("cur=0x");
+  print_hex (rl.rlim_cur);
+  print_string (" max=0x");
+  print_hex (rl.rlim_max);
+}
+
+static void
+maximize_rlimit (int resource, const char *prefix)
+{
+  struct rlimit rl;
+  print_string ("  ");
+  print_string (prefix);
+  print_string (": ");
+  print_rlimit (resource);
+  getrlimit (resource, &rl);
+  rl.rlim_cur = rl.rlim_max;
+  setrlimit (resource, &rl);
+  print_string (" -> ");
+  print_rlimit (resource);
+  print_string ("\n");
+}
+
+struct list
+{
+  struct list *next;
+  size_t size;
+};
+
+/* Put the "heap" pointer in the BSS section.  That way it is more
+   likely that the variable will occure early in the core file (an
+   address before the heap) and hence more likely that GDB will at
+   least get its value right.  */
+
+static struct list *heap;
+
+int
+main ()
+{
+
+  /* Try to expand all the resource limits beyond the point of sanity
+     - we're after the biggest possible core file.  */
+
+  print_string ("Maximize resource limits ...\n");
+#ifdef RLIMIT_CORE
+  maximize_rlimit (RLIMIT_CORE, "core");
+#endif
+#ifdef RLIMIT_DATA
+  maximize_rlimit (RLIMIT_DATA, "data");
+#endif
+#ifdef RLIMIT_STACK
+  maximize_rlimit (RLIMIT_STACK, "stack");
+#endif
+
+  /* Allocate as much memory as possible creating a linked list of
+     each section.  The linking ensures that some, but not all, the
+     memory is allocated.  NB: Some kernels handle this efficiently -
+     only allocating and writing out referenced pages leaving holes in
+     the file for unreferend pages - while others handle this poorly -
+     writing out all pages including those that wern't referenced.  */
+
+  print_string ("Alocating the entire heap ...\n");
+  {
+    size_t chunk_size;
+
+    /* Compute the largest power-of-two value that fits in chunk_size.  */
+    {
+      size_t tmp;
+      for (tmp = 1; tmp > 0; tmp <<= 1)
+	chunk_size = tmp;
+    }
+
+    /* Create a linked list of memory chunks.  Start with CHUNK_SIZE
+       blocks of memory and then try allocating smaller and smaller
+       amounts until all (well at least most) memory has been
+       allocated.  */
+    heap = NULL;
+    while (chunk_size >= sizeof (struct list))
+      {
+	while (1)
+	  {
+	    struct list *chunk = malloc (chunk_size);
+	    if (chunk == NULL)
+	      {
+		if (heap != NULL && heap->size == chunk_size)
+		  print_string ("\n");
+		break;
+	      }
+	    if (heap == NULL || heap->size != chunk_size)
+	      {
+		print_string ("  ");
+		print_unsigned (chunk_size);
+		print_string (" bytes @ ");
+	      }
+	    else
+	      print_string (", ");
+	    chunk->size = chunk_size;
+	    chunk->next = heap;
+	    print_string ("0x");
+	    print_hex ((unsigned long) chunk);
+	    heap = chunk;
+	  }
+	chunk_size >>= 1;
+      }
+  }
+
+  /* Push everything out to disk.  */
+
+  print_string ("Dump core ....\n");
+  *(char*)0 = 0;
+}
Index: gdb.base/bigcore.exp
===================================================================
RCS file: gdb.base/bigcore.exp
diff -N gdb.base/bigcore.exp
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ gdb.base/bigcore.exp	14 Jan 2004 02:21:36 -0000
@@ -0,0 +1,172 @@
+# Copyright 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2004
+# 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 2 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, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.  
+
+# Please email any bugs, comments, and/or additions to this file to:
+# bug-gdb@prep.ai.mit.edu
+
+# This file is based on corefile.exp which was written by Fred
+# Fish. (fnf@cygnus.com)
+
+if $tracelevel then {
+	strace $tracelevel
+}
+
+set prms_id 0
+set bug_id 0
+
+# are we on a target board
+if ![isnative] then {
+    return
+}
+
+set testfile "bigcore"
+set srcfile ${testfile}.c
+set binfile ${objdir}/${subdir}/${testfile}
+set corefile ${objdir}/${subdir}/${testfile}.corefile
+
+if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+     gdb_suppress_entire_file "Testcase compile failed, so all tests in this file will automatically fail."
+}
+
+# Create a core file named "TESTFILE.corefile" rather than just
+# "core", to avoid problems with sys admin types that like to
+# regularly prune all files named "core" from the system.
+
+# Some systems append "core" to the name of the program; others append
+# the name of the program to "core"; still others (like Linux, as of
+# May 2003) create cores named "core.PID".  In the latter case, we
+# could have many core files lying around, and it may be difficult to
+# tell which one is ours, so let's run the program in a subdirectory.
+
+set found 0
+set coredir "${objdir}/${subdir}/coredir.[getpid]"
+file mkdir $coredir
+catch "system \"(cd ${coredir}; ${binfile}; true) >/dev/null 2>&1\""
+set names [glob -nocomplain -directory $coredir *core*]
+if {[llength $names] == 1} {
+    set file [file join $coredir [lindex $names 0]]
+    remote_exec build "mv $file $corefile"
+    set found 1
+}
+
+# Try to clean up after ourselves. 
+remote_file build delete [file join $coredir coremmap.data]
+remote_exec build "rmdir $coredir"
+    
+if { $found == 0  } {
+    warning "can't generate a core file - core tests suppressed - check ulimit -c"
+    return 0
+}
+
+# Run GDB on the bigcore program up-to where it will dump core.
+
+gdb_exit
+gdb_start
+gdb_reinitialize_dir $srcdir/$subdir
+gdb_load ${binfile}
+gdb_test "set print sevenbit-strings" "" \
+	"set print sevenbit-strings; ${testfile}"
+gdb_test "set width 0" "" \
+	"set width 0; ${testfile}"
+if { ![runto_main] } then {
+    gdb_suppress_tests;
+}
+set print_core_line [gdb_get_line_number "Dump core"]
+gdb_test "tbreak $print_core_line"
+gdb_test continue ".*print_string.*"
+gdb_test next ".*0 = 0.*"
+
+# Traverse bigcore's linked list, saving each chunk's address.  I
+# don't know why but expect_out didn't work with gdb_test_multiple.
+
+set heap ""
+set test "extract heap"
+set lim 0
+send_gdb "print heap\n"
+gdb_expect {
+    -re " = \\(struct list \\*\\) 0x0.*$gdb_prompt $" {
+	pass "$test"
+    }
+    -re " = \\(struct list \\*\\) (0x\[0-9a-f\]*).*$gdb_prompt $" {
+	set heap [concat $heap $expect_out(1,string)]
+	if { $lim > 100 } {
+	    fail "$test (limit $lim exceeded)"
+	} else {
+	    incr lim
+	    send_gdb "print $.next\n"
+	    exp_continue
+	}
+    }
+    -re ".*$gdb_prompt $" {
+	fail "$test (entry $lim)"
+    }
+    timeout {
+	fail "$test (timeout)"
+    }
+}
+
+# Now load up that core file
+
+set test "load corefile"
+gdb_test_multiple "core $corefile" "$test" {
+    -re "A program is being debugged already.  Kill it. .y or n. " {
+	send_gdb "y\n"
+	exp_continue
+    }
+    -re "Core was generated by.*$gdb_prompt $" {
+	pass "$test"
+    }
+}
+
+# Finally, re-traverse bigcore's linked list, checking each chunk's
+# address against the executable.  Don't use gdb_test_multiple as want
+# only one pass/fail.
+
+set test "check heap"
+set lim 0
+set ok 1
+send_gdb "print heap\n"
+while { $ok } {
+    gdb_expect {
+	-re " = \\(struct list \\*\\) 0x0.*$gdb_prompt $" {
+	    set ok 0
+	    if { $lim == [length $heap] } {
+		pass "$test"
+	    } else {
+		fail "$test (short list)"
+	    }
+	}
+	-re " = \\(struct list \\*\\) [lindex $heap $lim].*$gdb_prompt $" {
+	    incr lim
+	    if { $lim > 100 } {
+		set ok 0
+		fail "$test (limit $lim exceeded)"
+	    } else {
+		send_gdb "print \$.next\n"
+	    }
+	}
+	-re ".*$gdb_prompt $" {
+	    set ok 0
+	    setup_kfail i*86-*-linux* gdb/1509
+	    fail "$test (address [lindex $heap $lim])"
+	}
+	timeout {
+	    set ok 0
+	    fail "$test (timeout)"
+	}
+    }
+}

             reply	other threads:[~2004-01-14  2:40 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2004-01-14  2:40 Andrew Cagney [this message]
2004-01-14  3:11 Michael Elizabeth Chastain
2004-01-14 14:48 ` Andrew Cagney
2004-01-14 14:56 Michael Elizabeth Chastain
2004-01-14 15:07 ` Andrew Cagney
2004-01-14 15:16   ` Daniel Jacobowitz
2004-01-14 15:38     ` Andrew Cagney
2004-01-14 15:44       ` Daniel Jacobowitz
2004-01-15 19:09     ` Andrew Cagney
2004-01-15 19:13       ` Daniel Jacobowitz
2004-01-20 22:02 ` Andrew Cagney
2004-01-21  4:42 Michael Elizabeth Chastain
2004-01-21  5:23 ` Andrew Cagney
2004-01-21  8:18 Michael Elizabeth Chastain

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4004AC30.1040300@redhat.com \
    --to=ac131313@redhat.com \
    --cc=gdb-patches@sources.redhat.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox