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