Mercurial > emacs
annotate src/unexcw.c @ 83542:2d56e13fd23d
Merged from emacs@sv.gnu.org
Patches applied:
* emacs@sv.gnu.org/emacs--devo--0--patch-413
Update from CVS
* emacs@sv.gnu.org/emacs--devo--0--patch-414
Update from CVS
* emacs@sv.gnu.org/emacs--devo--0--patch-415
Update from CVS
* emacs@sv.gnu.org/emacs--devo--0--patch-416
Update from CVS
* emacs@sv.gnu.org/emacs--devo--0--patch-417
Update from CVS
* emacs@sv.gnu.org/emacs--devo--0--patch-418
Merge from gnus--rel--5.10
* emacs@sv.gnu.org/emacs--devo--0--patch-419
Update from CVS
* emacs@sv.gnu.org/emacs--devo--0--patch-420
Update from CVS
* emacs@sv.gnu.org/emacs--devo--0--patch-421
Merge from gnus--rel--5.10
* emacs@sv.gnu.org/emacs--devo--0--patch-422
Update from CVS
* emacs@sv.gnu.org/emacs--devo--0--patch-423
Update from CVS
* emacs@sv.gnu.org/emacs--devo--0--patch-424
Merge from gnus--rel--5.10
* emacs@sv.gnu.org/emacs--devo--0--patch-425
Update from CVS
* emacs@sv.gnu.org/emacs--devo--0--patch-426
Update from CVS
* emacs@sv.gnu.org/emacs--devo--0--patch-427
Update from CVS
* emacs@sv.gnu.org/emacs--devo--0--patch-428
Merge from gnus--rel--5.10
* emacs@sv.gnu.org/emacs--devo--0--patch-429
Update from CVS
* emacs@sv.gnu.org/emacs--devo--0--patch-430
Update from CVS
* emacs@sv.gnu.org/emacs--devo--0--patch-431
Merge from gnus--rel--5.10
* emacs@sv.gnu.org/emacs--devo--0--patch-432
Update from CVS
* emacs@sv.gnu.org/emacs--devo--0--patch-433
Update from CVS
* emacs@sv.gnu.org/emacs--devo--0--patch-434
Update from CVS
* emacs@sv.gnu.org/emacs--devo--0--patch-435
Update from CVS
* emacs@sv.gnu.org/emacs--devo--0--patch-436
Update from CVS
* emacs@sv.gnu.org/emacs--devo--0--patch-437
Update from CVS
* emacs@sv.gnu.org/emacs--devo--0--patch-438
Update from CVS
* emacs@sv.gnu.org/emacs--devo--0--patch-439
Update from CVS
* emacs@sv.gnu.org/emacs--devo--0--patch-440
Update from CVS
* emacs@sv.gnu.org/emacs--devo--0--patch-441
lisp/url/url-methods.el: Fix format error when http_proxy is empty string
* emacs@sv.gnu.org/emacs--devo--0--patch-442
Update from CVS
* emacs@sv.gnu.org/emacs--devo--0--patch-443
Update from CVS
* emacs@sv.gnu.org/emacs--devo--0--patch-444
Update from CVS
* emacs@sv.gnu.org/emacs--devo--0--patch-445
Update from CVS
* emacs@sv.gnu.org/emacs--devo--0--patch-446
Merge from gnus--rel--5.10
* emacs@sv.gnu.org/emacs--devo--0--patch-447
Update from CVS
* emacs@sv.gnu.org/emacs--devo--0--patch-448
Update from CVS
* emacs@sv.gnu.org/emacs--devo--0--patch-449
Update from CVS
* emacs@sv.gnu.org/emacs--devo--0--patch-450
Update from CVS
* emacs@sv.gnu.org/emacs--devo--0--patch-451
Update from CVS
* emacs@sv.gnu.org/emacs--devo--0--patch-452
Update from CVS
* emacs@sv.gnu.org/emacs--devo--0--patch-453
Update from CVS
* emacs@sv.gnu.org/emacs--devo--0--patch-454
Update from CVS
* emacs@sv.gnu.org/emacs--devo--0--patch-455
Update from CVS
* emacs@sv.gnu.org/emacs--devo--0--patch-456
Update from CVS
* emacs@sv.gnu.org/emacs--devo--0--patch-457
Update from CVS
* emacs@sv.gnu.org/emacs--devo--0--patch-458
Update from CVS
* emacs@sv.gnu.org/emacs--devo--0--patch-459
Merge from gnus--rel--5.10
* emacs@sv.gnu.org/emacs--devo--0--patch-460
Update from CVS
* emacs@sv.gnu.org/emacs--devo--0--patch-461
Update from CVS
* emacs@sv.gnu.org/emacs--devo--0--patch-462
Update from CVS
* emacs@sv.gnu.org/emacs--devo--0--patch-463
Update from CVS
* emacs@sv.gnu.org/emacs--devo--0--patch-464
Update from CVS
* emacs@sv.gnu.org/emacs--devo--0--patch-465
Update from CVS
* emacs@sv.gnu.org/emacs--devo--0--patch-466
Merge from gnus--rel--5.10
* emacs@sv.gnu.org/emacs--devo--0--patch-467
Update from CVS
* emacs@sv.gnu.org/emacs--devo--0--patch-468
Merge from gnus--rel--5.10
* emacs@sv.gnu.org/emacs--devo--0--patch-469
Update from CVS
* emacs@sv.gnu.org/emacs--devo--0--patch-470
Update from CVS
* emacs@sv.gnu.org/emacs--devo--0--patch-471
Update from CVS
* emacs@sv.gnu.org/emacs--devo--0--patch-472
Update from CVS
* emacs@sv.gnu.org/emacs--devo--0--patch-473
Update from CVS
* emacs@sv.gnu.org/gnus--rel--5.10--patch-128
Update from CVS
* emacs@sv.gnu.org/gnus--rel--5.10--patch-129
Merge from emacs--devo--0
* emacs@sv.gnu.org/gnus--rel--5.10--patch-130
Update from CVS
* emacs@sv.gnu.org/gnus--rel--5.10--patch-131
Update from CVS
* emacs@sv.gnu.org/gnus--rel--5.10--patch-132
Update from CVS
* emacs@sv.gnu.org/gnus--rel--5.10--patch-133
Update from CVS
* emacs@sv.gnu.org/gnus--rel--5.10--patch-134
Merge from emacs--devo--0
* emacs@sv.gnu.org/gnus--rel--5.10--patch-135
Update from CVS
* emacs@sv.gnu.org/gnus--rel--5.10--patch-136
Update from CVS
* emacs@sv.gnu.org/gnus--rel--5.10--patch-137
Update from CVS
* emacs@sv.gnu.org/gnus--rel--5.10--patch-138
Update from CVS
* emacs@sv.gnu.org/gnus--rel--5.10--patch-139
Update from CVS
* emacs@sv.gnu.org/gnus--rel--5.10--patch-140
Update from CVS
* emacs@sv.gnu.org/gnus--rel--5.10--patch-141
Merge from emacs--devo--0
* emacs@sv.gnu.org/gnus--rel--5.10--patch-142
Update from CVS
* emacs@sv.gnu.org/gnus--rel--5.10--patch-143
Update from CVS
* emacs@sv.gnu.org/gnus--rel--5.10--patch-144
Update from CVS
* emacs@sv.gnu.org/gnus--rel--5.10--patch-145
Merge from emacs--devo--0
* emacs@sv.gnu.org/gnus--rel--5.10--patch-146
Update from CVS
* emacs@sv.gnu.org/gnus--rel--5.10--patch-147
Update from CVS
* emacs@sv.gnu.org/gnus--rel--5.10--patch-148
Update from CVS
* emacs@sv.gnu.org/gnus--rel--5.10--patch-149
Update from CVS
git-archimport-id: lorentey@elte.hu--2004/emacs--multi-tty--0--patch-582
author | Karoly Lorentey <lorentey@elte.hu> |
---|---|
date | Sat, 14 Oct 2006 17:36:28 +0000 |
parents | 3bd95f4f2941 |
children | f5b44958a759 c5406394f567 |
rev | line source |
---|---|
54844 | 1 /* unexec() support for Cygwin; |
2 complete rewrite of xemacs Cygwin unexec() code | |
3 | |
68651
3bd95f4f2941
Update years in copyright notice; nfc.
Thien-Thi Nguyen <ttn@gnuvola.org>
parents:
64770
diff
changeset
|
4 Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc. |
54844 | 5 |
6 This file is part of GNU Emacs. | |
7 | |
8 GNU Emacs is free software; you can redistribute it and/or modify | |
9 it under the terms of the GNU General Public License as published by | |
10 the Free Software Foundation; either version 2, or (at your option) | |
11 any later version. | |
12 | |
13 GNU Emacs is distributed in the hope that it will be useful, | |
14 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 GNU General Public License for more details. | |
17 | |
18 You should have received a copy of the GNU General Public License | |
19 along with GNU Emacs; see the file COPYING. If not, write to | |
64084 | 20 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, |
21 Boston, MA 02110-1301, USA. */ | |
54844 | 22 |
23 #include <config.h> | |
24 #include <lisp.h> | |
25 #include <stdio.h> | |
26 #include <fcntl.h> | |
27 #include <a.out.h> | |
28 #include <unistd.h> | |
29 #include <assert.h> | |
30 | |
31 #define DOTEXE ".exe" | |
32 | |
33 extern int bss_sbrk_did_unexec; | |
34 | |
35 /* emacs symbols that indicate where bss and data end for emacs internals */ | |
36 extern char my_endbss[]; | |
37 extern char my_edata[]; | |
38 | |
39 /* | |
40 ** header for Windows executable files | |
41 */ | |
42 typedef struct | |
43 { | |
44 FILHDR file_header; | |
45 PEAOUTHDR file_optional_header; | |
46 SCNHDR section_header[32]; | |
47 } exe_header_t; | |
48 | |
49 int debug_unexcw = 0; | |
50 | |
51 /* | |
52 ** Read the header from the executable into memory so we can more easily access it. | |
53 */ | |
54 static exe_header_t * | |
55 read_exe_header (int fd, exe_header_t * exe_header_buffer) | |
56 { | |
57 int i; | |
58 int ret; | |
59 | |
60 assert (fd >= 0); | |
61 assert (exe_header_buffer != 0); | |
62 | |
63 ret = lseek (fd, 0L, SEEK_SET); | |
64 assert (ret != -1); | |
65 | |
66 ret = | |
67 read (fd, &exe_header_buffer->file_header, | |
68 sizeof (exe_header_buffer->file_header)); | |
69 assert (ret == sizeof (exe_header_buffer->file_header)); | |
70 | |
71 assert (exe_header_buffer->file_header.e_magic == 0x5a4d); | |
72 assert (exe_header_buffer->file_header.nt_signature == 0x4550); | |
73 assert (exe_header_buffer->file_header.f_magic == 0x014c); | |
74 assert (exe_header_buffer->file_header.f_nscns > 0); | |
75 assert (exe_header_buffer->file_header.f_nscns <= | |
76 sizeof (exe_header_buffer->section_header) / | |
77 sizeof (exe_header_buffer->section_header[0])); | |
78 assert (exe_header_buffer->file_header.f_opthdr > 0); | |
79 | |
80 ret = | |
81 read (fd, &exe_header_buffer->file_optional_header, | |
82 sizeof (exe_header_buffer->file_optional_header)); | |
83 assert (ret == sizeof (exe_header_buffer->file_optional_header)); | |
84 | |
85 assert (exe_header_buffer->file_optional_header.magic == 0x010b); | |
86 | |
87 for (i = 0; i < exe_header_buffer->file_header.f_nscns; ++i) | |
88 { | |
89 ret = | |
90 read (fd, &exe_header_buffer->section_header[i], | |
91 sizeof (exe_header_buffer->section_header[i])); | |
92 assert (ret == sizeof (exe_header_buffer->section_header[i])); | |
93 } | |
94 | |
95 return (exe_header_buffer); | |
96 } | |
97 | |
98 /* | |
99 ** Fix the dumped emacs executable: | |
100 ** | |
101 ** - copy .data section data of interest from running executable into | |
102 ** output .exe file | |
103 ** | |
104 ** - convert .bss section into an initialized data section (like | |
105 ** .data) and copy .bss section data of interest from running | |
106 ** executable into output .exe file | |
107 */ | |
108 static void | |
109 fixup_executable (int fd) | |
110 { | |
111 exe_header_t exe_header_buffer; | |
112 exe_header_t *exe_header; | |
113 int i; | |
114 int ret; | |
115 int found_data = 0; | |
116 int found_bss = 0; | |
117 | |
118 exe_header = read_exe_header (fd, &exe_header_buffer); | |
119 assert (exe_header != 0); | |
120 | |
121 assert (exe_header->file_header.f_nscns > 0); | |
122 for (i = 0; i < exe_header->file_header.f_nscns; ++i) | |
123 { | |
124 unsigned long start_address = | |
125 exe_header->section_header[i].s_vaddr + | |
126 exe_header->file_optional_header.ImageBase; | |
127 unsigned long end_address = | |
128 exe_header->section_header[i].s_vaddr + | |
129 exe_header->file_optional_header.ImageBase + | |
130 exe_header->section_header[i].s_paddr; | |
131 if (debug_unexcw) | |
132 printf ("%8s start 0x%08x end 0x%08x\n", | |
133 exe_header->section_header[i].s_name, | |
134 start_address, end_address); | |
135 if (my_edata >= (char *) start_address | |
136 && my_edata < (char *) end_address) | |
137 { | |
138 /* data section */ | |
139 ret = | |
140 lseek (fd, (long) (exe_header->section_header[i].s_scnptr), | |
141 SEEK_SET); | |
142 assert (ret != -1); | |
143 ret = | |
144 write (fd, (char *) start_address, | |
145 my_edata - (char *) start_address); | |
146 assert (ret == my_edata - (char *) start_address); | |
147 ++found_data; | |
148 if (debug_unexcw) | |
149 printf (" .data, mem start 0x%08x mem length %d\n", | |
150 start_address, my_edata - (char *) start_address); | |
151 if (debug_unexcw) | |
152 printf (" .data, file start %d file length %d\n", | |
153 (int) exe_header->section_header[i].s_scnptr, | |
154 (int) exe_header->section_header[i].s_paddr); | |
155 } | |
156 else if (my_endbss >= (char *) start_address | |
157 && my_endbss < (char *) end_address) | |
158 { | |
159 /* bss section */ | |
160 ++found_bss; | |
161 if (exe_header->section_header[i].s_flags & 0x00000080) | |
162 { | |
163 /* convert uninitialized data section to initialized data section */ | |
164 struct stat statbuf; | |
165 ret = fstat (fd, &statbuf); | |
166 assert (ret != -1); | |
167 | |
168 exe_header->section_header[i].s_flags &= ~0x00000080; | |
169 exe_header->section_header[i].s_flags |= 0x00000040; | |
170 | |
171 exe_header->section_header[i].s_scnptr = | |
172 (statbuf.st_size + | |
173 exe_header->file_optional_header.FileAlignment) / | |
174 exe_header->file_optional_header.FileAlignment * | |
175 exe_header->file_optional_header.FileAlignment; | |
176 | |
177 exe_header->section_header[i].s_size = | |
178 (exe_header->section_header[i].s_paddr + | |
179 exe_header->file_optional_header.FileAlignment) / | |
180 exe_header->file_optional_header.FileAlignment * | |
181 exe_header->file_optional_header.FileAlignment; | |
182 | |
183 ret = | |
184 lseek (fd, | |
185 (long) (exe_header->section_header[i].s_scnptr + | |
186 exe_header->section_header[i].s_size - 1), | |
187 SEEK_SET); | |
188 assert (ret != -1); | |
189 ret = write (fd, "", 1); | |
190 assert (ret == 1); | |
191 | |
192 ret = | |
193 lseek (fd, | |
194 (long) ((char *) &exe_header->section_header[i] - | |
195 (char *) exe_header), SEEK_SET); | |
196 assert (ret != -1); | |
197 ret = | |
198 write (fd, &exe_header->section_header[i], | |
199 sizeof (exe_header->section_header[i])); | |
200 assert (ret == sizeof (exe_header->section_header[i])); | |
201 if (debug_unexcw) | |
202 printf (" seek to %ld, write %d\n", | |
203 (long) ((char *) &exe_header->section_header[i] - | |
204 (char *) exe_header), | |
205 sizeof (exe_header->section_header[i])); | |
206 } | |
207 /* write initialized data section */ | |
208 ret = | |
209 lseek (fd, (long) (exe_header->section_header[i].s_scnptr), | |
210 SEEK_SET); | |
211 assert (ret != -1); | |
212 ret = | |
213 write (fd, (char *) start_address, | |
214 my_endbss - (char *) start_address); | |
215 assert (ret == (my_endbss - (char *) start_address)); | |
216 if (debug_unexcw) | |
217 printf (" .bss, mem start 0x%08x mem length %d\n", | |
218 start_address, my_endbss - (char *) start_address); | |
219 if (debug_unexcw) | |
220 printf (" .bss, file start %d file length %d\n", | |
221 (int) exe_header->section_header[i].s_scnptr, | |
222 (int) exe_header->section_header[i].s_paddr); | |
223 } | |
224 } | |
225 assert (found_bss == 1); | |
226 assert (found_data == 1); | |
227 } | |
228 | |
229 /* | |
230 ** Windows likes .exe suffixes on executables. | |
231 */ | |
232 static char * | |
233 add_exe_suffix_if_necessary (const char *name, char *modified) | |
234 { | |
235 int i = strlen (name); | |
236 if (i <= (sizeof (DOTEXE) - 1)) | |
237 { | |
238 sprintf (modified, "%s%s", name, DOTEXE); | |
239 } | |
240 else if (!strcasecmp (name + i - (sizeof (DOTEXE) - 1), DOTEXE)) | |
241 { | |
242 strcpy (modified, name); | |
243 } | |
244 else | |
245 { | |
246 sprintf (modified, "%s%s", name, DOTEXE); | |
247 } | |
248 return (modified); | |
249 } | |
250 | |
251 int | |
252 unexec (char *outfile, char *infile, unsigned start_data, unsigned d1, | |
253 unsigned d2) | |
254 { | |
255 char infile_buffer[FILENAME_MAX]; | |
256 char outfile_buffer[FILENAME_MAX]; | |
257 int fd_in; | |
258 int fd_out; | |
259 int ret; | |
260 int ret2; | |
261 | |
262 if (bss_sbrk_did_unexec) | |
263 { | |
264 /* can only dump once */ | |
265 printf ("You can only dump emacs once on this platform.\n"); | |
266 return (1); | |
267 } | |
268 | |
269 report_sheap_usage (1); | |
270 | |
271 infile = add_exe_suffix_if_necessary (infile, infile_buffer); | |
272 outfile = add_exe_suffix_if_necessary (outfile, outfile_buffer); | |
273 | |
274 fd_in = open (infile, O_RDONLY | O_BINARY); | |
275 assert (fd_in >= 0); | |
276 fd_out = open (outfile, O_RDWR | O_TRUNC | O_CREAT | O_BINARY, 0755); | |
277 assert (fd_out >= 0); | |
278 for (;;) | |
279 { | |
280 char buffer[4096]; | |
281 ret = read (fd_in, buffer, sizeof (buffer)); | |
282 if (ret == 0) | |
283 { | |
284 /* eof */ | |
285 break; | |
286 } | |
287 assert (ret > 0); | |
288 /* data */ | |
289 ret2 = write (fd_out, buffer, ret); | |
290 assert (ret2 == ret); | |
291 } | |
292 ret = close (fd_in); | |
293 assert (ret == 0); | |
294 | |
295 bss_sbrk_did_unexec = 1; | |
296 fixup_executable (fd_out); | |
297 bss_sbrk_did_unexec = 0; | |
298 | |
299 ret = close (fd_out); | |
300 assert (ret == 0); | |
301 | |
302 return (0); | |
303 } | |
54858
44a3fff23885
Changes from arch/CVS synchronization
Miles Bader <miles@gnu.org>
parents:
54844
diff
changeset
|
304 |
44a3fff23885
Changes from arch/CVS synchronization
Miles Bader <miles@gnu.org>
parents:
54844
diff
changeset
|
305 /* arch-tag: fc44f6c3-ca0a-45e0-a5a2-58b6101b1e65 |
44a3fff23885
Changes from arch/CVS synchronization
Miles Bader <miles@gnu.org>
parents:
54844
diff
changeset
|
306 (do not change this comment) */ |