xref: /openbsd-src/gnu/usr.bin/binutils/gdb/testsuite/gdb.base/bigcore.c (revision 11efff7f3ac2b3cfeff0c0cddc14294d9b3aca4f)
1b725ae77Skettenis /* This testcase is part of GDB, the GNU debugger.
2b725ae77Skettenis 
3b725ae77Skettenis    Copyright 2004 Free Software Foundation, Inc.
4b725ae77Skettenis 
5b725ae77Skettenis    This program is free software; you can redistribute it and/or modify
6b725ae77Skettenis    it under the terms of the GNU General Public License as published by
7b725ae77Skettenis    the Free Software Foundation; either version 2 of the License, or
8b725ae77Skettenis    (at your option) any later version.
9b725ae77Skettenis 
10b725ae77Skettenis    This program is distributed in the hope that it will be useful,
11b725ae77Skettenis    but WITHOUT ANY WARRANTY; without even the implied warranty of
12b725ae77Skettenis    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13b725ae77Skettenis    GNU General Public License for more details.
14b725ae77Skettenis 
15b725ae77Skettenis    You should have received a copy of the GNU General Public License
16b725ae77Skettenis    along with this program; if not, write to the Free Software
17b725ae77Skettenis    Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18b725ae77Skettenis 
19b725ae77Skettenis    Please email any bugs, comments, and/or additions to this file to:
20b725ae77Skettenis    bug-gdb@prep.ai.mit.edu  */
21b725ae77Skettenis 
22*11efff7fSkettenis /* Get 64-bit stuff if on a GNU system.  */
23*11efff7fSkettenis #define _GNU_SOURCE
24*11efff7fSkettenis 
25*11efff7fSkettenis #include <sys/types.h>
26*11efff7fSkettenis #include <sys/time.h>
27b725ae77Skettenis #include <sys/resource.h>
28*11efff7fSkettenis #include <sys/stat.h>
29*11efff7fSkettenis #include <fcntl.h>
30*11efff7fSkettenis 
31*11efff7fSkettenis #include <stdlib.h>
32*11efff7fSkettenis #include <unistd.h>
33b725ae77Skettenis 
34b725ae77Skettenis /* Print routines:
35b725ae77Skettenis 
36b725ae77Skettenis    The following are so that printf et.al. can be avoided.  Those
37b725ae77Skettenis    might try to use malloc() and that, for this code, would be a
38b725ae77Skettenis    disaster.  */
39b725ae77Skettenis 
40b725ae77Skettenis #define printf do not use
41b725ae77Skettenis 
42b725ae77Skettenis const char digit[] = "0123456789abcdefghijklmnopqrstuvwxyz";
43b725ae77Skettenis 
44b725ae77Skettenis static void
print_char(char c)45b725ae77Skettenis print_char (char c)
46b725ae77Skettenis {
47b725ae77Skettenis   write (1, &c, sizeof (c));
48b725ae77Skettenis }
49b725ae77Skettenis 
50b725ae77Skettenis static void
print_unsigned(unsigned long long u)51*11efff7fSkettenis print_unsigned (unsigned long long u)
52b725ae77Skettenis {
53b725ae77Skettenis   if (u >= 10)
54b725ae77Skettenis     print_unsigned (u / 10);
55b725ae77Skettenis   print_char (digit[u % 10]);
56b725ae77Skettenis }
57b725ae77Skettenis 
58b725ae77Skettenis static void
print_hex(unsigned long long u)59*11efff7fSkettenis print_hex (unsigned long long u)
60b725ae77Skettenis {
61b725ae77Skettenis   if (u >= 16)
62b725ae77Skettenis     print_hex (u / 16);
63b725ae77Skettenis   print_char (digit[u % 16]);
64b725ae77Skettenis }
65b725ae77Skettenis 
66b725ae77Skettenis static void
print_string(const char * s)67b725ae77Skettenis print_string (const char *s)
68b725ae77Skettenis {
69b725ae77Skettenis   for (; (*s) != '\0'; s++)
70b725ae77Skettenis     print_char ((*s));
71b725ae77Skettenis }
72b725ae77Skettenis 
73b725ae77Skettenis static void
print_address(const void * a)74b725ae77Skettenis print_address (const void *a)
75b725ae77Skettenis {
76b725ae77Skettenis   print_string ("0x");
77b725ae77Skettenis   print_hex ((unsigned long) a);
78b725ae77Skettenis }
79b725ae77Skettenis 
80*11efff7fSkettenis static void
print_byte_count(unsigned long long u)81*11efff7fSkettenis print_byte_count (unsigned long long u)
82*11efff7fSkettenis {
83*11efff7fSkettenis   print_unsigned (u);
84*11efff7fSkettenis   print_string (" (");
85*11efff7fSkettenis   print_string ("0x");
86*11efff7fSkettenis   print_hex (u);
87*11efff7fSkettenis   print_string (") bytes");
88*11efff7fSkettenis }
89*11efff7fSkettenis 
90b725ae77Skettenis /* Print the current values of RESOURCE.  */
91b725ae77Skettenis 
92b725ae77Skettenis static void
print_rlimit(int resource)93b725ae77Skettenis print_rlimit (int resource)
94b725ae77Skettenis {
95b725ae77Skettenis   struct rlimit rl;
96b725ae77Skettenis   getrlimit (resource, &rl);
97b725ae77Skettenis   print_string ("cur=0x");
98b725ae77Skettenis   print_hex (rl.rlim_cur);
99b725ae77Skettenis   print_string (" max=0x");
100b725ae77Skettenis   print_hex (rl.rlim_max);
101b725ae77Skettenis }
102b725ae77Skettenis 
103b725ae77Skettenis static void
maximize_rlimit(int resource,const char * prefix)104b725ae77Skettenis maximize_rlimit (int resource, const char *prefix)
105b725ae77Skettenis {
106b725ae77Skettenis   struct rlimit rl;
107b725ae77Skettenis   print_string ("  ");
108b725ae77Skettenis   print_string (prefix);
109b725ae77Skettenis   print_string (": ");
110b725ae77Skettenis   print_rlimit (resource);
111b725ae77Skettenis   getrlimit (resource, &rl);
112b725ae77Skettenis   rl.rlim_cur = rl.rlim_max;
113b725ae77Skettenis   setrlimit (resource, &rl);
114b725ae77Skettenis   print_string (" -> ");
115b725ae77Skettenis   print_rlimit (resource);
116b725ae77Skettenis   print_string ("\n");
117b725ae77Skettenis }
118b725ae77Skettenis 
119b725ae77Skettenis /* Maintain a doublely linked list.  */
120b725ae77Skettenis struct list
121b725ae77Skettenis {
122b725ae77Skettenis   struct list *next;
123b725ae77Skettenis   struct list *prev;
124b725ae77Skettenis   size_t size;
125b725ae77Skettenis };
126b725ae77Skettenis 
127b725ae77Skettenis /* Put the "heap" in the DATA section.  That way it is more likely
128b725ae77Skettenis    that the variable will occur early in the core file (an address
129b725ae77Skettenis    before the heap) and hence more likely that GDB will at least get
130b725ae77Skettenis    its value right.
131b725ae77Skettenis 
132b725ae77Skettenis    To simplify the list append logic, start the heap out with one
133b725ae77Skettenis    entry (that lives in the BSS section).  */
134b725ae77Skettenis 
135b725ae77Skettenis static struct list dummy;
136b725ae77Skettenis static struct list heap = { &dummy, &dummy };
137b725ae77Skettenis 
138*11efff7fSkettenis static unsigned long bytes_allocated;
139*11efff7fSkettenis 
140*11efff7fSkettenis #ifdef O_LARGEFILE
141*11efff7fSkettenis #define large_off_t off64_t
142*11efff7fSkettenis #define large_lseek lseek64
143*11efff7fSkettenis #else
144*11efff7fSkettenis #define large_off_t off_t
145*11efff7fSkettenis #define O_LARGEFILE 0
146*11efff7fSkettenis #define large_lseek lseek
147*11efff7fSkettenis #endif
148*11efff7fSkettenis 
149b725ae77Skettenis int
main()150b725ae77Skettenis main ()
151b725ae77Skettenis {
152b725ae77Skettenis   size_t max_chunk_size;
153*11efff7fSkettenis   large_off_t max_core_size;
154b725ae77Skettenis 
155b725ae77Skettenis   /* Try to expand all the resource limits beyond the point of sanity
156b725ae77Skettenis      - we're after the biggest possible core file.  */
157b725ae77Skettenis 
158b725ae77Skettenis   print_string ("Maximize resource limits ...\n");
159b725ae77Skettenis #ifdef RLIMIT_CORE
160b725ae77Skettenis   maximize_rlimit (RLIMIT_CORE, "core");
161b725ae77Skettenis #endif
162b725ae77Skettenis #ifdef RLIMIT_DATA
163b725ae77Skettenis   maximize_rlimit (RLIMIT_DATA, "data");
164b725ae77Skettenis #endif
165b725ae77Skettenis #ifdef RLIMIT_STACK
166b725ae77Skettenis   maximize_rlimit (RLIMIT_STACK, "stack");
167b725ae77Skettenis #endif
168b725ae77Skettenis #ifdef RLIMIT_AS
169b725ae77Skettenis   maximize_rlimit (RLIMIT_AS, "stack");
170b725ae77Skettenis #endif
171b725ae77Skettenis 
172*11efff7fSkettenis   print_string ("Maximize allocation limits ...\n");
173*11efff7fSkettenis 
174*11efff7fSkettenis   /* Compute the largest possible corefile size.  No point in trying
175*11efff7fSkettenis      to create a corefile larger than the largest file supported by
176*11efff7fSkettenis      the file system.  What about 64-bit lseek64?  */
177*11efff7fSkettenis   {
178*11efff7fSkettenis     int fd;
179*11efff7fSkettenis     large_off_t tmp;
180*11efff7fSkettenis     unlink ("bigcore.corefile");
181*11efff7fSkettenis     fd = open ("bigcore.corefile", O_RDWR | O_CREAT | O_TRUNC | O_LARGEFILE);
182*11efff7fSkettenis     for (tmp = 1; tmp > 0; tmp <<= 1)
183*11efff7fSkettenis       {
184*11efff7fSkettenis 	if (large_lseek (fd, tmp, SEEK_SET) > 0)
185*11efff7fSkettenis 	  max_core_size = tmp;
186*11efff7fSkettenis       }
187*11efff7fSkettenis     close (fd);
188*11efff7fSkettenis   }
189*11efff7fSkettenis 
190b725ae77Skettenis   /* Compute an initial chunk size.  The math is dodgy but it works
191*11efff7fSkettenis      for the moment.  Perhaphs there's a constant around somewhere.
192*11efff7fSkettenis      Limit this to max_core_size bytes - no point in trying to
193*11efff7fSkettenis      allocate more than can be written to the corefile.  */
194b725ae77Skettenis   {
195b725ae77Skettenis     size_t tmp;
196*11efff7fSkettenis     for (tmp = 1; tmp > 0 && tmp < max_core_size; tmp <<= 1)
197b725ae77Skettenis       max_chunk_size = tmp;
198b725ae77Skettenis   }
199b725ae77Skettenis 
200*11efff7fSkettenis   print_string ("  core: ");
201*11efff7fSkettenis   print_byte_count (max_core_size);
202*11efff7fSkettenis   print_string ("\n");
203*11efff7fSkettenis   print_string ("  chunk: ");
204*11efff7fSkettenis   print_byte_count (max_chunk_size);
205*11efff7fSkettenis   print_string ("\n");
206*11efff7fSkettenis   print_string ("  large? ");
207*11efff7fSkettenis   if (O_LARGEFILE)
208*11efff7fSkettenis     print_string ("yes\n");
209*11efff7fSkettenis   else
210*11efff7fSkettenis     print_string ("no\n");
211*11efff7fSkettenis 
212b725ae77Skettenis   /* Allocate as much memory as possible creating a linked list of
213b725ae77Skettenis      each section.  The linking ensures that some, but not all, the
214b725ae77Skettenis      memory is allocated.  NB: Some kernels handle this efficiently -
215b725ae77Skettenis      only allocating and writing out referenced pages leaving holes in
216*11efff7fSkettenis      the file for unmodified pages - while others handle this poorly -
217*11efff7fSkettenis      writing out all pages including those that weren't modified.  */
218b725ae77Skettenis 
219b725ae77Skettenis   print_string ("Alocating the entire heap ...\n");
220b725ae77Skettenis   {
221b725ae77Skettenis     size_t chunk_size;
222*11efff7fSkettenis     unsigned long chunks_allocated = 0;
223b725ae77Skettenis     /* Create a linked list of memory chunks.  Start with
224b725ae77Skettenis        MAX_CHUNK_SIZE blocks of memory and then try allocating smaller
225b725ae77Skettenis        and smaller amounts until all (well at least most) memory has
226b725ae77Skettenis        been allocated.  */
227b725ae77Skettenis     for (chunk_size = max_chunk_size;
228b725ae77Skettenis 	 chunk_size >= sizeof (struct list);
229b725ae77Skettenis 	 chunk_size >>= 1)
230b725ae77Skettenis       {
231b725ae77Skettenis 	unsigned long count = 0;
232b725ae77Skettenis 	print_string ("  ");
233*11efff7fSkettenis 	print_byte_count (chunk_size);
234*11efff7fSkettenis 	print_string (" ... ");
235*11efff7fSkettenis 	while (bytes_allocated + (1 + count) * chunk_size
236*11efff7fSkettenis 	       < max_core_size)
237b725ae77Skettenis 	  {
238b725ae77Skettenis 	    struct list *chunk = malloc (chunk_size);
239b725ae77Skettenis 	    if (chunk == NULL)
240b725ae77Skettenis 	      break;
241b725ae77Skettenis 	    chunk->size = chunk_size;
242b725ae77Skettenis 	    /* Link it in.  */
243b725ae77Skettenis 	    chunk->next = NULL;
244b725ae77Skettenis 	    chunk->prev = heap.prev;
245b725ae77Skettenis 	    heap.prev->next = chunk;
246b725ae77Skettenis 	    heap.prev = chunk;
247b725ae77Skettenis 	    count++;
248b725ae77Skettenis 	  }
249b725ae77Skettenis 	print_unsigned (count);
250b725ae77Skettenis 	print_string (" chunks\n");
251b725ae77Skettenis 	chunks_allocated += count;
252b725ae77Skettenis 	bytes_allocated += chunk_size * count;
253b725ae77Skettenis       }
254b725ae77Skettenis     print_string ("Total of ");
255*11efff7fSkettenis     print_byte_count (bytes_allocated);
256b725ae77Skettenis     print_string (" bytes ");
257b725ae77Skettenis     print_unsigned (chunks_allocated);
258b725ae77Skettenis     print_string (" chunks\n");
259b725ae77Skettenis   }
260b725ae77Skettenis 
261b725ae77Skettenis   /* Push everything out to disk.  */
262b725ae77Skettenis 
263b725ae77Skettenis   print_string ("Dump core ....\n");
264b725ae77Skettenis   *(char*)0 = 0;
265b725ae77Skettenis }
266