Mercurial > emacs
annotate src/unexnext.c @ 4413:5a00cec8e9b0
(fill-region-as-paragraph): When we take one word
after the fill column, don't stop at period with just one space.
When checking whether at beginning of line, if no fill prefix,
ignore intervening whitespace.
author | Richard M. Stallman <rms@gnu.org> |
---|---|
date | Mon, 02 Aug 1993 05:55:56 +0000 |
parents | b70f4760d769 |
children | cec168152d88 |
rev | line source |
---|---|
1349 | 1 /* Dump Emacs in macho format. |
2660
b70f4760d769
Changes for Emacs 19 from Thorsten Ohl <ohl@chico.harvard.edu>:
Jim Blandy <jimb@redhat.com>
parents:
1349
diff
changeset
|
2 Copyright (C) 1990, 1993 Free Software Foundation, Inc. |
1349 | 3 Written by Bradley Taylor (btaylor@next.com). |
4 | |
5 This file is part of GNU Emacs. | |
6 | |
7 GNU Emacs is free software; you can redistribute it and/or modify | |
8 it under the terms of the GNU General Public License as published by | |
2660
b70f4760d769
Changes for Emacs 19 from Thorsten Ohl <ohl@chico.harvard.edu>:
Jim Blandy <jimb@redhat.com>
parents:
1349
diff
changeset
|
9 the Free Software Foundation; either version 2, or (at your option) |
1349 | 10 any later version. |
11 | |
12 GNU Emacs is distributed in the hope that it will be useful, | |
13 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 GNU General Public License for more details. | |
16 | |
17 You should have received a copy of the GNU General Public License | |
18 along with GNU Emacs; see the file COPYING. If not, write to | |
19 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ | |
20 | |
21 | |
22 #undef __STRICT_BSD__ | |
23 | |
24 #include <stdio.h> | |
25 #include <stdlib.h> | |
26 #include <stdarg.h> | |
2660
b70f4760d769
Changes for Emacs 19 from Thorsten Ohl <ohl@chico.harvard.edu>:
Jim Blandy <jimb@redhat.com>
parents:
1349
diff
changeset
|
27 #include <mach/mach.h> |
b70f4760d769
Changes for Emacs 19 from Thorsten Ohl <ohl@chico.harvard.edu>:
Jim Blandy <jimb@redhat.com>
parents:
1349
diff
changeset
|
28 #include <mach-o/loader.h> |
1349 | 29 #include <sys/file.h> |
30 #include <sys/stat.h> | |
31 #include <libc.h> | |
32 | |
33 | |
2660
b70f4760d769
Changes for Emacs 19 from Thorsten Ohl <ohl@chico.harvard.edu>:
Jim Blandy <jimb@redhat.com>
parents:
1349
diff
changeset
|
34 int malloc_cookie; |
1349 | 35 |
36 /* | |
37 * Kludge: we don't expect any program data beyond VM_HIGHDATA | |
38 * What is really needed is a way to find out from malloc() which | |
39 * pages it vm_allocated and write only those out into the data segment. | |
40 * | |
41 * This kludge may break when we stop using fixed virtual address | |
42 * shared libraries. Actually, emacs will probably continue working, but be | |
43 * much larger on disk than it needs to be (because non-malloced data will | |
44 * be in the file). | |
45 */ | |
46 static const unsigned VM_HIGHDATA = 0x2000000; | |
47 | |
48 typedef struct region_t { | |
49 vm_address_t address; | |
50 vm_size_t size; | |
51 vm_prot_t protection; | |
52 vm_prot_t max_protection; | |
53 vm_inherit_t inheritance; | |
54 boolean_t shared; | |
55 port_t object_name; | |
56 vm_offset_t offset; | |
57 } region_t; | |
58 | |
59 | |
60 static void | |
61 grow( | |
62 struct load_command ***the_commands, | |
63 unsigned *the_commands_len | |
64 ) | |
65 { | |
66 if (*the_commands == NULL) { | |
67 *the_commands_len = 1; | |
68 *the_commands = malloc(sizeof(*the_commands)); | |
69 } else { | |
70 (*the_commands_len)++; | |
71 *the_commands = realloc(*the_commands, | |
72 (*the_commands_len * | |
73 sizeof(**the_commands))); | |
74 } | |
75 } | |
76 | |
77 | |
78 static void | |
79 save_command( | |
80 struct load_command *command, | |
81 struct load_command ***the_commands, | |
82 unsigned *the_commands_len | |
83 ) | |
84 { | |
85 struct load_command **tmp; | |
86 | |
87 grow(the_commands, the_commands_len); | |
88 tmp = &(*the_commands)[*the_commands_len - 1]; | |
89 *tmp = malloc(command->cmdsize); | |
90 bcopy(command, *tmp, command->cmdsize); | |
91 } | |
92 | |
93 static void | |
94 fatal_unexec(char *format, ...) | |
95 { | |
96 va_list ap; | |
97 | |
98 va_start(ap, format); | |
99 fprintf(stderr, "unexec: "); | |
100 vfprintf(stderr, format, ap); | |
101 fprintf(stderr, "\n"); | |
102 va_end(ap); | |
103 } | |
104 | |
105 static int | |
106 read_macho( | |
107 int fd, | |
108 struct mach_header *the_header, | |
109 struct load_command ***the_commands, | |
110 unsigned *the_commands_len | |
111 ) | |
112 { | |
113 struct load_command command; | |
114 struct load_command *buf; | |
115 int i; | |
116 int size; | |
117 | |
118 if (read(fd, the_header, sizeof(*the_header)) != sizeof(*the_header)) { | |
119 fatal_unexec("cannot read macho header"); | |
120 return (0); | |
121 } | |
122 for (i = 0; i < the_header->ncmds; i++) { | |
123 if (read(fd, &command, sizeof(struct load_command)) != | |
124 sizeof(struct load_command)) { | |
125 fatal_unexec("cannot read macho load command header"); | |
126 return (0); | |
127 } | |
128 size = command.cmdsize - sizeof(struct load_command); | |
129 if (size < 0) { | |
130 fatal_unexec("bogus load command size"); | |
131 return (0); | |
132 } | |
133 buf = malloc(command.cmdsize); | |
134 buf->cmd = command.cmd; | |
135 buf->cmdsize = command.cmdsize; | |
136 if (read(fd, ((char *)buf + | |
137 sizeof(struct load_command)), | |
138 size) != size) { | |
139 fatal_unexec("cannot read load command data"); | |
140 return (0); | |
141 } | |
142 save_command(buf, the_commands, the_commands_len); | |
143 } | |
144 return (1); | |
145 } | |
146 | |
147 static int | |
148 filldatagap( | |
149 vm_address_t start_address, | |
150 vm_size_t *size, | |
151 vm_address_t end_address | |
152 ) | |
153 { | |
154 vm_address_t address; | |
155 vm_size_t gapsize; | |
156 | |
157 address = (start_address + *size); | |
158 gapsize = end_address - address; | |
159 *size += gapsize; | |
160 if (vm_allocate(task_self(), &address, gapsize, | |
161 FALSE) != KERN_SUCCESS) { | |
162 fatal_unexec("cannot vm_allocate"); | |
163 return (0); | |
164 } | |
165 return (1); | |
166 } | |
167 | |
168 static int | |
169 get_data_region( | |
170 vm_address_t *address, | |
171 vm_size_t *size | |
172 ) | |
173 { | |
174 region_t region; | |
175 kern_return_t ret; | |
176 struct section *sect; | |
177 | |
178 sect = getsectbyname(SEG_DATA, SECT_DATA); | |
179 region.address = 0; | |
180 *address = 0; | |
181 for (;;) { | |
182 ret = vm_region(task_self(), | |
183 ®ion.address, | |
184 ®ion.size, | |
185 ®ion.protection, | |
186 ®ion.max_protection, | |
187 ®ion.inheritance, | |
188 ®ion.shared, | |
189 ®ion.object_name, | |
190 ®ion.offset); | |
191 if (ret != KERN_SUCCESS || region.address >= VM_HIGHDATA) { | |
192 break; | |
193 } | |
194 if (*address != 0) { | |
195 if (region.address > *address + *size) { | |
196 if (!filldatagap(*address, size, | |
197 region.address)) { | |
198 return (0); | |
199 } | |
200 } | |
201 *size += region.size; | |
202 } else { | |
203 if (region.address == sect->addr) { | |
204 *address = region.address; | |
205 *size = region.size; | |
206 } | |
207 } | |
208 region.address += region.size; | |
209 } | |
210 return (1); | |
211 } | |
212 | |
213 static char * | |
214 my_malloc( | |
215 vm_size_t size | |
216 ) | |
217 { | |
218 vm_address_t address; | |
219 | |
220 if (vm_allocate(task_self(), &address, size, TRUE) != KERN_SUCCESS) { | |
221 return (NULL); | |
222 } | |
223 return ((char *)address); | |
224 } | |
225 | |
226 static void | |
227 my_free( | |
228 char *buf, | |
229 vm_size_t size | |
230 ) | |
231 { | |
232 vm_deallocate(task_self(), (vm_address_t)buf, size); | |
233 } | |
234 | |
235 static int | |
236 unexec_doit( | |
237 int infd, | |
238 int outfd | |
239 ) | |
240 { | |
241 int i; | |
242 struct load_command **the_commands = NULL; | |
243 unsigned the_commands_len; | |
244 struct mach_header the_header; | |
245 int fgrowth; | |
246 int fdatastart; | |
247 int fdatasize; | |
248 int size; | |
249 struct stat st; | |
250 char *buf; | |
251 vm_address_t data_address; | |
252 vm_size_t data_size; | |
253 | |
254 struct segment_command *segment; | |
255 | |
256 if (!read_macho(infd, &the_header, &the_commands, &the_commands_len)) { | |
257 return (0); | |
258 } | |
259 | |
260 | |
2660
b70f4760d769
Changes for Emacs 19 from Thorsten Ohl <ohl@chico.harvard.edu>:
Jim Blandy <jimb@redhat.com>
parents:
1349
diff
changeset
|
261 malloc_cookie = malloc_freezedry (); |
1349 | 262 if (!get_data_region(&data_address, &data_size)) { |
263 return (0); | |
264 } | |
265 | |
266 | |
267 /* | |
268 * DO NOT USE MALLOC IN THIS SECTION | |
269 */ | |
270 { | |
271 /* | |
272 * Fix offsets | |
273 */ | |
274 for (i = 0; i < the_commands_len; i++) { | |
275 switch (the_commands[i]->cmd) { | |
276 case LC_SEGMENT: | |
277 segment = ((struct segment_command *) | |
278 the_commands[i]); | |
279 if (strcmp(segment->segname, SEG_DATA) == 0) { | |
280 fdatastart = segment->fileoff; | |
281 fdatasize = segment->filesize; | |
282 fgrowth = (data_size - | |
283 segment->filesize); | |
284 segment->vmsize = data_size; | |
285 segment->filesize = data_size; | |
286 } | |
287 break; | |
288 case LC_SYMTAB: | |
289 ((struct symtab_command *) | |
290 the_commands[i])->symoff += fgrowth; | |
291 ((struct symtab_command *) | |
292 the_commands[i])->stroff += fgrowth; | |
293 break; | |
294 case LC_SYMSEG: | |
295 ((struct symseg_command *) | |
296 the_commands[i])->offset += fgrowth; | |
297 break; | |
298 default: | |
299 break; | |
300 } | |
301 } | |
302 | |
303 /* | |
304 * Write header | |
305 */ | |
306 if (write(outfd, &the_header, | |
307 sizeof(the_header)) != sizeof(the_header)) { | |
308 fatal_unexec("cannot write output file"); | |
309 return (0); | |
310 } | |
311 | |
312 /* | |
313 * Write commands | |
314 */ | |
315 for (i = 0; i < the_commands_len; i++) { | |
316 if (write(outfd, the_commands[i], | |
317 the_commands[i]->cmdsize) != | |
318 the_commands[i]->cmdsize) { | |
319 fatal_unexec("cannot write output file"); | |
320 return (0); | |
321 } | |
322 } | |
323 | |
324 /* | |
325 * Write original text | |
326 */ | |
327 if (lseek(infd, the_header.sizeofcmds + sizeof(the_header), | |
328 L_SET) < 0) { | |
329 fatal_unexec("cannot seek input file"); | |
330 return (0); | |
331 } | |
332 size = fdatastart - (sizeof(the_header) + | |
333 the_header.sizeofcmds); | |
334 buf = my_malloc(size); | |
335 if (read(infd, buf, size) != size) { | |
336 my_free(buf, size); | |
337 fatal_unexec("cannot read input file"); | |
338 } | |
339 if (write(outfd, buf, size) != size) { | |
340 my_free(buf, size); | |
341 fatal_unexec("cannot write output file"); | |
342 return (0); | |
343 } | |
344 my_free(buf, size); | |
345 | |
346 | |
347 /* | |
348 * Write new data | |
349 */ | |
350 if (write(outfd, (char *)data_address, | |
351 data_size) != data_size) { | |
352 fatal_unexec("cannot write output file"); | |
353 return (0); | |
354 } | |
355 | |
356 } | |
357 | |
358 /* | |
359 * OKAY TO USE MALLOC NOW | |
360 */ | |
361 | |
362 /* | |
363 * Write rest of file | |
364 */ | |
365 fstat(infd, &st); | |
366 if (lseek(infd, fdatasize, L_INCR) < 0) { | |
367 fatal_unexec("cannot seek input file"); | |
368 return (0); | |
369 } | |
370 size = st.st_size - lseek(infd, 0, L_INCR); | |
371 | |
372 buf = malloc(size); | |
373 if (read(infd, buf, size) != size) { | |
374 free(buf); | |
375 fatal_unexec("cannot read input file"); | |
376 return (0); | |
377 } | |
378 if (write(outfd, buf, size) != size) { | |
379 free(buf); | |
380 fatal_unexec("cannot write output file"); | |
381 return (0); | |
382 } | |
383 free(buf); | |
384 return (1); | |
385 } | |
386 | |
387 void | |
388 unexec( | |
389 char *outfile, | |
390 char *infile | |
391 ) | |
392 { | |
393 int infd; | |
394 int outfd; | |
395 char tmpbuf[L_tmpnam]; | |
396 char *tmpfile; | |
397 | |
398 infd = open(infile, O_RDONLY, 0); | |
399 if (infd < 0) { | |
400 fatal_unexec("cannot open input file `%s'", infile); | |
401 exit(1); | |
402 } | |
403 | |
404 tmpnam(tmpbuf); | |
405 tmpfile = rindex(tmpbuf, '/'); | |
406 if (tmpfile == NULL) { | |
407 tmpfile = tmpbuf; | |
408 } else { | |
409 tmpfile++; | |
410 } | |
411 outfd = open(tmpfile, O_WRONLY|O_TRUNC|O_CREAT, 0755); | |
412 if (outfd < 0) { | |
413 close(infd); | |
414 fatal_unexec("cannot open tmp file `%s'", tmpfile); | |
415 exit(1); | |
416 } | |
417 if (!unexec_doit(infd, outfd)) { | |
418 close(infd); | |
419 close(outfd); | |
420 unlink(tmpfile); | |
421 exit(1); | |
422 } | |
423 close(infd); | |
424 close(outfd); | |
425 if (rename(tmpfile, outfile) < 0) { | |
426 unlink(tmpfile); | |
427 fatal_unexec("cannot rename `%s' to `%s'", tmpfile, outfile); | |
428 exit(1); | |
429 } | |
430 } |