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