613
|
1 /* unexec for XEmacs on Cygwin32.
|
428
|
2 Copyright (C) 1994, 1998 Free Software Foundation, Inc.
|
|
3
|
|
4 This file is part of XEmacs.
|
|
5
|
|
6 XEmacs is free software; you can redistribute it and/or modify it
|
|
7 under the terms of the GNU General Public License as published by the
|
|
8 Free Software Foundation; either version 2, or (at your option) any
|
|
9 later version.
|
|
10
|
|
11 XEmacs is distributed in the hope that it will be useful, but WITHOUT
|
|
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
14 for more details.
|
|
15
|
|
16 You should have received a copy of the GNU General Public License
|
|
17 along with XEmacs; see the file COPYING. If not, write to the Free
|
|
18 Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|
19 02111-1307, USA.
|
|
20
|
|
21 */
|
|
22
|
|
23 /* This is a complete rewrite, some code snarfed from unexnt.c and
|
|
24 unexec.c, Andy Piper (andy@xemacs.org) 13-1-98 */
|
|
25
|
448
|
26 #include <config.h>
|
|
27 #include "lisp.h"
|
|
28
|
428
|
29 #include "sysfile.h"
|
442
|
30
|
546
|
31 #define PERROR(arg) \
|
|
32 do { \
|
|
33 perror (arg); \
|
|
34 exit (-1); \
|
|
35 } while (0)
|
428
|
36
|
546
|
37 #if !defined (HAVE_A_OUT_H) && !defined (WIN32_NATIVE)
|
428
|
38 unexec (char *, char *, void *, void *, void *)
|
|
39 {
|
647
|
40 PERROR ("cannot unexec() a.out.h not installed");
|
428
|
41 }
|
|
42 #else
|
|
43
|
546
|
44 #ifdef MINGW
|
|
45 #include <../../include/a.out.h>
|
|
46 #else
|
428
|
47 #include <a.out.h>
|
546
|
48 #endif
|
428
|
49
|
1198
|
50 #define STACK_SIZE 0x800000
|
428
|
51 #define ALLOC_UNIT 0xFFFF
|
647
|
52 #define ALLOC_MASK ~((unsigned long) (ALLOC_UNIT))
|
428
|
53 #define ALIGN_ALLOC(addr) \
|
647
|
54 ((((unsigned long) addr) + ALLOC_UNIT) & ALLOC_MASK)
|
444
|
55 /* Note that all sections must be aligned on a 0x1000 boundary so
|
|
56 this is the minimum size that our dummy bss can be. */
|
448
|
57 #ifndef NO_DEBUG
|
444
|
58 #define BSS_PAD_SIZE 0x1000
|
446
|
59 #else
|
|
60 #define BSS_PAD_SIZE 0
|
|
61 #endif
|
428
|
62
|
|
63 /* To prevent zero-initialized variables from being placed into the bss
|
|
64 section, use non-zero values to represent an uninitialized state. */
|
|
65 #define UNINIT_PTR ((void *) 0xF0A0F0A0)
|
|
66 #define UNINIT_LONG (0xF0A0F0A0L)
|
|
67
|
|
68 static void get_section_info (int a_out, char* a_name);
|
|
69 static void copy_executable_and_dump_data_section (int a_out, int a_new);
|
647
|
70 static void dup_file_area (int a_out, int a_new, long size);
|
428
|
71 #if 0
|
647
|
72 static void write_int_to_bss (int a_out, int a_new, void* va, void* newval);
|
428
|
73 #endif
|
|
74
|
|
75 /* Cached info about the .data section in the executable. */
|
647
|
76 void *data_start_va = UNINIT_PTR;
|
|
77 long data_size = UNINIT_LONG;
|
428
|
78
|
|
79 /* Cached info about the .bss section in the executable. */
|
647
|
80 void *bss_start = UNINIT_PTR;
|
|
81 long bss_size = UNINIT_LONG;
|
428
|
82 int sections_reversed = 0;
|
|
83 FILHDR f_hdr;
|
|
84 PEAOUTHDR f_ohdr;
|
|
85 SCNHDR f_data, f_bss, f_text, f_nextdata;
|
|
86
|
647
|
87 #define CHECK_AOUT_POS(a) \
|
|
88 do { \
|
|
89 if (lseek (a_out, 0, SEEK_CUR) != a) \
|
|
90 { \
|
|
91 printf ("we are at %lx, should be at %lx\n", \
|
|
92 lseek (a_out, 0, SEEK_CUR), a); \
|
|
93 exit (-1); \
|
|
94 } \
|
|
95 } while (0)
|
428
|
96
|
|
97 /* Dump out .data and .bss sections into a new executable. */
|
448
|
98 int
|
|
99 unexec (char *out_name, char *in_name, uintptr_t start_data,
|
|
100 uintptr_t d1, uintptr_t d2)
|
428
|
101 {
|
|
102 /* ugly nt hack - should be in lisp */
|
|
103 int a_new, a_out = -1;
|
558
|
104 char new_name[PATH_MAX], a_name[PATH_MAX];
|
428
|
105 char *ptr;
|
|
106
|
|
107 /* Make sure that the input and output filenames have the
|
|
108 ".exe" extension...patch them up if they don't. */
|
|
109 strcpy (a_name, in_name);
|
|
110 ptr = a_name + strlen (a_name) - 4;
|
|
111 if (strcmp (ptr, ".exe"))
|
|
112 strcat (a_name, ".exe");
|
|
113
|
|
114 strcpy (new_name, out_name);
|
|
115 ptr = new_name + strlen (new_name) - 4;
|
|
116 if (strcmp (ptr, ".exe"))
|
|
117 strcat (new_name, ".exe");
|
|
118
|
|
119 /* We need to round off our heap to NT's allocation unit (64KB). */
|
|
120 /* round_heap (get_allocation_unit ()); */
|
|
121
|
|
122 if (a_name && (a_out = open (a_name, O_RDONLY | OPEN_BINARY)) < 0)
|
558
|
123 PERROR (a_name);
|
428
|
124
|
|
125 if ((a_new = open (new_name, O_WRONLY | O_TRUNC | O_CREAT | OPEN_BINARY,
|
446
|
126 0755)) < 0)
|
558
|
127 PERROR (new_name);
|
428
|
128
|
|
129 /* Get the interesting section info, like start and size of .bss... */
|
|
130 get_section_info (a_out, a_name);
|
|
131
|
|
132 copy_executable_and_dump_data_section (a_out, a_new);
|
|
133
|
647
|
134 close (a_out);
|
|
135 close (a_new);
|
448
|
136 return 0;
|
428
|
137 }
|
|
138
|
|
139 /* Flip through the executable and cache the info necessary for dumping. */
|
558
|
140 static void
|
|
141 get_section_info (int a_out, char* a_name)
|
428
|
142 {
|
448
|
143 extern char my_ebss[];
|
428
|
144 /* From lastfile.c */
|
|
145 extern char my_edata[];
|
|
146
|
|
147 if (read (a_out, &f_hdr, sizeof (f_hdr)) != sizeof (f_hdr))
|
558
|
148 PERROR (a_name);
|
428
|
149
|
|
150 if (f_hdr.e_magic != DOSMAGIC)
|
647
|
151 PERROR ("unknown exe header");
|
428
|
152
|
|
153 /* Check the NT header signature ... */
|
|
154 if (f_hdr.nt_signature != NT_SIGNATURE)
|
647
|
155 PERROR ("invalid nt header");
|
428
|
156
|
|
157 /* Flip through the sections for .data and .bss ... */
|
|
158 if (f_hdr.f_opthdr > 0)
|
|
159 {
|
|
160 if (read (a_out, &f_ohdr, AOUTSZ) != AOUTSZ)
|
558
|
161 PERROR (a_name);
|
428
|
162 }
|
|
163 /* Loop through .data & .bss section headers, copying them in.
|
|
164 With newer lds these are reversed so we have to cope with both */
|
|
165 lseek (a_out, sizeof (f_hdr) + f_hdr.f_opthdr, 0);
|
|
166
|
|
167 if (read (a_out, &f_text, sizeof (f_text)) != sizeof (f_text)
|
558
|
168 || strcmp (f_text.s_name, ".text"))
|
|
169 PERROR ("no .text section");
|
428
|
170
|
|
171 /* The .bss section. */
|
|
172 if (read (a_out, &f_bss, sizeof (f_bss)) != sizeof (f_bss)
|
558
|
173 || (strcmp (f_bss.s_name, ".bss") && strcmp (f_bss.s_name, ".data")))
|
|
174 PERROR ("no .bss / .data section");
|
428
|
175
|
|
176 /* check for reversed .bss and .data */
|
647
|
177 if (!strcmp (f_bss.s_name, ".data"))
|
428
|
178 {
|
647
|
179 printf (".data and .bss reversed\n");
|
428
|
180 sections_reversed = 1;
|
647
|
181 memcpy (&f_data, &f_bss, sizeof (f_bss));
|
428
|
182 }
|
|
183
|
|
184 /* The .data section. */
|
|
185 if (!sections_reversed)
|
|
186 {
|
|
187 if (read (a_out, &f_data, sizeof (f_data)) != sizeof (f_data)
|
558
|
188 || strcmp (f_data.s_name, ".data"))
|
|
189 PERROR ("no .data section");
|
428
|
190 }
|
|
191 else
|
|
192 {
|
|
193 if (read (a_out, &f_bss, sizeof (f_bss)) != sizeof (f_bss)
|
558
|
194 || strcmp (f_bss.s_name, ".bss"))
|
|
195 PERROR ("no .bss section");
|
428
|
196 }
|
|
197
|
|
198 bss_start = (void *) ((char*)f_ohdr.ImageBase + f_bss.s_vaddr);
|
|
199 bss_size = (unsigned long)((char*)&my_ebss-(char*)bss_start);
|
|
200
|
|
201 /* must keep bss data that we want to be blank as blank */
|
647
|
202 printf ("found bss - keeping %lx of %lx bytes\n", bss_size, f_ohdr.bsize);
|
428
|
203
|
|
204 /* The .data section. */
|
|
205 data_start_va = (void *) ((char*)f_ohdr.ImageBase + f_data.s_vaddr);
|
|
206
|
|
207 /* We want to only write Emacs data back to the executable,
|
|
208 not any of the library data (if library data is included,
|
|
209 then a dumped Emacs won't run on system versions other
|
|
210 than the one Emacs was dumped on). */
|
|
211 data_size = (unsigned long)my_edata - (unsigned long)data_start_va;
|
647
|
212 printf ("found data - keeping %lx of %lx bytes\n", data_size, f_ohdr.dsize);
|
428
|
213
|
|
214 /* The following data section - often .idata */
|
|
215 if (read (a_out, &f_nextdata, sizeof (f_nextdata)) != sizeof (f_nextdata)
|
647
|
216 && strcmp (&f_nextdata.s_name[2], "data"))
|
558
|
217 PERROR ("no other data section");
|
428
|
218 }
|
|
219
|
|
220 /* The dump routines. */
|
|
221
|
|
222 static void
|
|
223 copy_executable_and_dump_data_section (int a_out, int a_new)
|
|
224 {
|
647
|
225 long size = 0;
|
|
226 /* NOTE: Some of these were previously declared as unsigned long,
|
|
227 but the ones changed to long represent file sizes or pointers,
|
|
228 which can't reasonably get above 2G. (A 2G executable???)
|
|
229 Furthermore, some were even being compared as in if (x < 0) ... */
|
|
230 long new_data_size, new_bss_size, bss_padding, file_sz_change;
|
|
231 long data_padding = 0;
|
|
232 long f_data_s_scnptr = f_data.s_scnptr;
|
|
233 long f_nextdata_s_scnptr = f_nextdata.s_scnptr;
|
|
234 unsigned long f_data_s_vaddr = f_data.s_vaddr;
|
|
235 unsigned long f_bss_s_vaddr = f_bss.s_vaddr;
|
428
|
236
|
|
237 int i;
|
|
238 void* empty_space;
|
|
239 extern int static_heap_dumped;
|
|
240 SCNHDR section;
|
444
|
241 /* calculate new sizes:
|
558
|
242
|
444
|
243 f_ohdr.dsize is the total initialized data size on disk which is
|
|
244 f_data.s_size + f_idata.s_size.
|
558
|
245
|
444
|
246 f_ohdr.data_start is the base addres of all data and so should
|
|
247 not be changed.
|
|
248
|
|
249 *.s_vaddr is the virtual address of the start of the section
|
|
250 *normalized from f_ohdr.ImageBase.
|
558
|
251
|
444
|
252 *.s_paddr appears to be the number of bytes in the section
|
|
253 *actually used (whereas *.s_size is aligned).
|
558
|
254
|
428
|
255 bsize is now 0 since subsumed into .data
|
|
256 dsize is dsize + (f_data.s_vaddr - f_bss.s_vaddr)
|
|
257 f_data.s_vaddr is f_bss.s_vaddr
|
|
258 f_data.s_size is new dsize maybe.
|
|
259 what about s_paddr & s_scnptr? */
|
|
260
|
|
261 /* this is the amount the file increases in size */
|
|
262 if (!sections_reversed)
|
|
263 {
|
|
264 new_bss_size = f_data.s_vaddr - f_bss.s_vaddr;
|
|
265 data_padding = 0;
|
|
266 }
|
|
267 else
|
|
268 {
|
|
269 new_bss_size = f_nextdata.s_vaddr - f_bss.s_vaddr;
|
|
270 data_padding = (f_bss.s_vaddr - f_data.s_vaddr) - f_data.s_size;
|
|
271 }
|
|
272
|
448
|
273 if ((new_bss_size - bss_size) < BSS_PAD_SIZE)
|
558
|
274 PERROR (".bss free space too small");
|
448
|
275
|
647
|
276 file_sz_change = (new_bss_size + data_padding) - BSS_PAD_SIZE;
|
|
277 new_data_size = f_ohdr.dsize + file_sz_change;
|
428
|
278
|
|
279 if (!sections_reversed)
|
558
|
280 f_data.s_vaddr = f_bss.s_vaddr;
|
428
|
281 f_data.s_paddr += file_sz_change;
|
|
282 #if 0
|
|
283 if (f_data.s_size + f_nextdata.s_size != f_ohdr.dsize)
|
647
|
284 printf ("section size doesn't tally with dsize %lx != %lx\n",
|
558
|
285 f_data.s_size + f_nextdata.s_size, f_ohdr.dsize);
|
428
|
286 #endif
|
|
287 f_data.s_size += file_sz_change;
|
|
288 lseek (a_new, 0, SEEK_SET);
|
|
289 /* write file header */
|
|
290 f_hdr.f_symptr += file_sz_change;
|
448
|
291 #ifdef NO_DEBUG
|
446
|
292 f_hdr.f_nscns--;
|
|
293 #endif
|
444
|
294
|
647
|
295 printf ("writing file header\n");
|
|
296 if (write (a_new, &f_hdr, sizeof (f_hdr)) != sizeof (f_hdr))
|
|
297 PERROR ("failed to write file header");
|
428
|
298 /* write optional header fixing dsize & bsize*/
|
647
|
299 printf ("writing optional header\n");
|
|
300 printf ("new data size is %lx, >= %lx\n", new_data_size,
|
428
|
301 f_ohdr.dsize + f_ohdr.bsize);
|
647
|
302 if (new_data_size < (long) (f_ohdr.dsize + f_ohdr.bsize))
|
|
303 printf ("warning: new data size is < approx\n");
|
428
|
304 f_ohdr.dsize=new_data_size;
|
444
|
305 f_ohdr.bsize=BSS_PAD_SIZE;
|
1198
|
306 /* Prevent stack overflow with regexp usage. */
|
|
307 f_ohdr.SizeOfStackReserve = STACK_SIZE;
|
|
308
|
647
|
309 if (write (a_new, &f_ohdr, sizeof (f_ohdr)) != sizeof (f_ohdr))
|
|
310 PERROR ("failed to write optional header");
|
428
|
311 /* write text as is */
|
647
|
312 printf ("writing text header (unchanged)\n");
|
428
|
313
|
647
|
314 if (write (a_new, &f_text, sizeof (f_text)) != sizeof (f_text))
|
|
315 PERROR ("failed to write text header");
|
448
|
316 #ifndef NO_DEBUG
|
444
|
317 /* Write small bss section. */
|
|
318 if (!sections_reversed)
|
|
319 {
|
|
320 f_bss.s_size = BSS_PAD_SIZE;
|
|
321 f_bss.s_paddr = BSS_PAD_SIZE;
|
|
322 f_bss.s_vaddr = f_data.s_vaddr - BSS_PAD_SIZE;
|
647
|
323 if (write (a_new, &f_bss, sizeof (f_bss)) != sizeof (f_bss))
|
|
324 PERROR ("failed to write bss header");
|
444
|
325 }
|
446
|
326 #endif
|
428
|
327 /* write new data header */
|
647
|
328 printf ("writing .data header\n");
|
428
|
329
|
647
|
330 if (write (a_new, &f_data, sizeof (f_data)) != sizeof (f_data))
|
|
331 PERROR ("failed to write data header");
|
448
|
332 #ifndef NO_DEBUG
|
444
|
333 /* Write small bss section. */
|
|
334 if (sections_reversed)
|
|
335 {
|
|
336 f_bss.s_size = BSS_PAD_SIZE;
|
|
337 f_bss.s_paddr = BSS_PAD_SIZE;
|
|
338 f_bss.s_vaddr = f_nextdata.s_vaddr - BSS_PAD_SIZE;
|
647
|
339 if (write (a_new, &f_bss, sizeof (f_bss)) != sizeof (f_bss))
|
|
340 PERROR ("failed to write bss header");
|
444
|
341 }
|
446
|
342 #endif
|
647
|
343 printf ("writing following data header\n");
|
428
|
344 f_nextdata.s_scnptr += file_sz_change;
|
|
345 if (f_nextdata.s_lnnoptr != 0) f_nextdata.s_lnnoptr += file_sz_change;
|
|
346 if (f_nextdata.s_relptr != 0) f_nextdata.s_relptr += file_sz_change;
|
647
|
347 if (write (a_new, &f_nextdata, sizeof (f_nextdata)) != sizeof (f_nextdata))
|
|
348 PERROR ("failed to write nextdata header");
|
428
|
349
|
|
350 /* copy other section headers adjusting the file offset */
|
|
351 for (i=0; i<(f_hdr.f_nscns-3); i++)
|
|
352 {
|
|
353 if (read (a_out, §ion, sizeof (section)) != sizeof (section))
|
558
|
354 PERROR ("no .data section");
|
428
|
355
|
|
356 section.s_scnptr += file_sz_change;
|
|
357 if (section.s_lnnoptr != 0) section.s_lnnoptr += file_sz_change;
|
|
358 if (section.s_relptr != 0) section.s_relptr += file_sz_change;
|
|
359
|
647
|
360 if (write (a_new, §ion, sizeof (section)) != sizeof (section))
|
|
361 PERROR ("failed to write data header");
|
428
|
362 }
|
448
|
363 #ifdef NO_DEBUG
|
446
|
364 /* dump bss to maintain offsets */
|
647
|
365 memset (&f_bss, 0, sizeof (f_bss));
|
|
366 if (write (a_new, &f_bss, sizeof (f_bss)) != sizeof (f_bss))
|
|
367 PERROR ("failed to write bss header");
|
446
|
368 #endif
|
647
|
369 size = lseek (a_new, 0, SEEK_CUR);
|
|
370 CHECK_AOUT_POS (size);
|
428
|
371
|
|
372 /* copy eveything else until start of data */
|
|
373 size = f_data_s_scnptr - lseek (a_out, 0, SEEK_CUR);
|
|
374
|
|
375 printf ("copying executable up to data section ... %lx bytes\n",
|
|
376 size);
|
647
|
377 dup_file_area (a_out, a_new, size);
|
428
|
378
|
647
|
379 CHECK_AOUT_POS (f_data_s_scnptr);
|
428
|
380
|
|
381 if (!sections_reversed)
|
|
382 {
|
444
|
383 /* dump bss + padding between sections, sans small bss pad */
|
428
|
384 printf ("dumping .bss into executable... %lx bytes\n", bss_size);
|
647
|
385 if (write (a_new, bss_start, bss_size) != bss_size)
|
428
|
386 {
|
647
|
387 PERROR ("failed to write bss section");
|
428
|
388 }
|
|
389
|
|
390 /* pad, needs to be zero */
|
444
|
391 bss_padding = (new_bss_size - bss_size) - BSS_PAD_SIZE;
|
|
392 if (bss_padding < 0)
|
647
|
393 PERROR ("padded .bss too small");
|
428
|
394 printf ("padding .bss ... %lx bytes\n", bss_padding);
|
647
|
395 empty_space = malloc (bss_padding);
|
|
396 memset (empty_space, 0, bss_padding);
|
|
397 if (write (a_new, empty_space, bss_padding) != bss_padding)
|
|
398 PERROR ("failed to write bss section");
|
|
399 free (empty_space);
|
428
|
400 }
|
|
401
|
|
402 /* tell dumped version not to free pure heap */
|
|
403 static_heap_dumped = 1;
|
|
404 /* Get a pointer to the raw data in our address space. */
|
|
405 printf ("dumping .data section... %lx bytes\n", data_size);
|
647
|
406 if (write (a_new, data_start_va, data_size) != data_size)
|
|
407 PERROR ("failed to write data section");
|
428
|
408 /* were going to use free again ... */
|
|
409 static_heap_dumped = 0;
|
|
410
|
647
|
411 size = lseek (a_out, f_data_s_scnptr + data_size, SEEK_SET);
|
428
|
412
|
|
413 if (!sections_reversed)
|
|
414 {
|
|
415 size = f_nextdata_s_scnptr - size;
|
647
|
416 dup_file_area (a_out, a_new, size);
|
428
|
417 }
|
|
418 else
|
|
419 {
|
444
|
420 /* need to pad to bss with data in file */
|
428
|
421 printf ("padding .data ... %lx bytes\n", data_padding);
|
|
422 size = (f_bss_s_vaddr - f_data_s_vaddr) - data_size;
|
647
|
423 dup_file_area (a_out, a_new, size);
|
428
|
424
|
|
425 /* dump bss + padding between sections */
|
|
426 printf ("dumping .bss into executable... %lx bytes\n", bss_size);
|
647
|
427 if (write (a_new, bss_start, bss_size) != bss_size)
|
|
428 PERROR ("failed to write bss section");
|
428
|
429
|
|
430 /* pad, needs to be zero */
|
444
|
431 bss_padding = (new_bss_size - bss_size) - BSS_PAD_SIZE;
|
|
432 if (bss_padding < 0)
|
647
|
433 PERROR ("padded .bss too small");
|
428
|
434 printf ("padding .bss ... %lx bytes\n", bss_padding);
|
647
|
435 empty_space = malloc (bss_padding);
|
|
436 memset (empty_space, 0, bss_padding);
|
|
437 if (write (a_new, empty_space, bss_padding) != bss_padding)
|
|
438 PERROR ("failed to write bss section");
|
|
439 free (empty_space);
|
|
440 if (lseek (a_new, 0, SEEK_CUR) != (long) f_nextdata.s_scnptr)
|
428
|
441 {
|
647
|
442 printf ("at %lx should be at %lx\n",
|
|
443 lseek (a_new, 0, SEEK_CUR),
|
428
|
444 f_nextdata.s_scnptr);
|
647
|
445 PERROR ("file positioning error\n");
|
428
|
446 }
|
647
|
447 lseek (a_out, f_nextdata_s_scnptr, SEEK_SET);
|
428
|
448 }
|
|
449
|
647
|
450 CHECK_AOUT_POS (f_nextdata_s_scnptr);
|
428
|
451
|
|
452 /* now dump - nextdata don't need to do this cygwin ds is in .data! */
|
|
453 printf ("dumping following data section... %lx bytes\n", f_nextdata.s_size);
|
|
454
|
647
|
455 dup_file_area (a_out,a_new,f_nextdata.s_size);
|
428
|
456
|
|
457 /* write rest of file */
|
|
458 printf ("writing rest of file\n");
|
647
|
459 size = lseek (a_out, 0, SEEK_END);
|
428
|
460 size = size - (f_nextdata_s_scnptr + f_nextdata.s_size); /* length remaining in a_out */
|
647
|
461 lseek (a_out, f_nextdata_s_scnptr + f_nextdata.s_size, SEEK_SET);
|
428
|
462
|
647
|
463 dup_file_area (a_out, a_new, size);
|
428
|
464 }
|
|
465
|
|
466 /*
|
|
467 * copy from aout to anew
|
|
468 */
|
647
|
469 static void
|
|
470 dup_file_area (int a_out, int a_new, long size)
|
428
|
471 {
|
|
472 char page[BUFSIZ];
|
|
473 long n;
|
|
474 for (; size > 0; size -= sizeof (page))
|
|
475 {
|
1111
|
476 n = size > (long) sizeof (page) ? (long) sizeof (page) : size;
|
428
|
477 if (read (a_out, page, n) != n || write (a_new, page, n) != n)
|
558
|
478 PERROR ("dump_out()");
|
428
|
479 }
|
|
480 }
|
|
481
|
|
482 #if 0
|
647
|
483 static void
|
|
484 write_int_to_bss (int a_out, int a_new, void* va, void* newval)
|
428
|
485 {
|
|
486 int cpos;
|
|
487
|
647
|
488 cpos = lseek (a_new, 0, SEEK_CUR);
|
428
|
489 if (va < bss_start || va > bss_start + f_data.s_size)
|
647
|
490 PERROR ("address not in data space\n");
|
|
491 lseek (a_new, f_data.s_scnptr + ((unsigned long)va -
|
428
|
492 (unsigned long)bss_start), SEEK_SET);
|
647
|
493 if (write (a_new, newval, sizeof (int)) != (int) sizeof (int))
|
|
494 PERROR ("failed to write int value");
|
|
495 lseek (a_new, cpos, SEEK_SET);
|
428
|
496 }
|
|
497 #endif
|
|
498
|
|
499 #endif /* HAVE_A_OUT_H */
|