This source file includes following definitions.
- run_time_remap
- unexec_error
- check_lseek
- save_data_space
- update_file_ptrs
- read_header
- write_header
- calculate_checksum
- copy_file
- copy_rest
- display_header
- unexec
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52 #include <config.h>
53 #include "unexec.h"
54 #include "lisp.h"
55 #include "sysstdio.h"
56
57 #include <fcntl.h>
58 #include <errno.h>
59 #include <a.out.h>
60 #include <dl.h>
61
62
63
64 static long brk_on_dump = 0;
65
66
67 int
68 run_time_remap (char *ignored)
69 {
70 brk ((char *) brk_on_dump);
71 }
72
73 #undef roundup
74 #define roundup(x,n) (((x) + ((n) - 1)) & ~((n) - 1))
75
76
77 static _Noreturn void
78 unexec_error (char const *msg)
79 {
80 perror (msg);
81 exit (1);
82 }
83
84
85 static void
86 check_lseek (int fd, off_t offset, int whence)
87 {
88 if (lseek (fd, offset, whence) < 0)
89 unexec_error ("Cannot lseek");
90 }
91
92
93
94 static void
95 save_data_space (int file, struct header *hdr, struct som_exec_auxhdr *auxhdr,
96 int size)
97 {
98
99 if (write (file, auxhdr->exec_dmem, size) != size)
100 unexec_error ("Can't save new data space");
101
102
103 auxhdr->exec_dsize = size;
104 auxhdr->exec_bsize = 0;
105 }
106
107
108
109 static void
110 update_file_ptrs (int file, struct header *hdr, struct som_exec_auxhdr *auxhdr,
111 unsigned int location, int offset)
112 {
113 struct subspace_dictionary_record subspace;
114 int i;
115
116
117 hdr->som_length += offset;
118
119
120 #define update(ptr) if (ptr > location) ptr = ptr + offset
121 update (hdr->aux_header_location);
122 update (hdr->space_strings_location);
123 update (hdr->init_array_location);
124 update (hdr->compiler_location);
125 update (hdr->symbol_location);
126 update (hdr->fixup_request_location);
127 update (hdr->symbol_strings_location);
128 update (hdr->unloadable_sp_location);
129 update (auxhdr->exec_tfile);
130 update (auxhdr->exec_dfile);
131
132
133 check_lseek (file, hdr->subspace_location, 0);
134 for (i = 0; i < hdr->subspace_total; i++)
135 {
136 ptrdiff_t subspace_size = sizeof subspace;
137 if (read (file, &subspace, subspace_size) != subspace_size)
138 unexec_error ("Can't read subspace record");
139
140
141 if (subspace.initialization_length > 0
142 && subspace.file_loc_init_value > location)
143 {
144 subspace.file_loc_init_value += offset;
145 check_lseek (file, -subspace_size, 1);
146 if (write (file, &subspace, subspace_size) != subspace_size)
147 unexec_error ("Can't update subspace record");
148 }
149 }
150
151
152
153 #undef update
154 }
155
156
157
158 static void
159 read_header (int file, struct header *hdr, struct som_exec_auxhdr *auxhdr)
160 {
161
162
163 check_lseek (file, 0, 0);
164 if (read (file, hdr, sizeof (*hdr)) != sizeof (*hdr))
165 unexec_error ("Couldn't read header from a.out file");
166
167 if (hdr->a_magic != EXEC_MAGIC && hdr->a_magic != SHARE_MAGIC
168 && hdr->a_magic != DEMAND_MAGIC)
169 {
170 fputs ("a.out file doesn't have valid magic number\n", stderr);
171 exit (1);
172 }
173
174 check_lseek (file, hdr->aux_header_location, 0);
175 if (read (file, auxhdr, sizeof (*auxhdr)) != sizeof (*auxhdr))
176 unexec_error ("Couldn't read auxiliary header from a.out file");
177 }
178
179
180
181 static void
182 write_header (int file, struct header *hdr, struct som_exec_auxhdr *auxhdr)
183 {
184
185 hdr->checksum = calculate_checksum (hdr);
186
187
188 check_lseek (file, 0, 0);
189 if (write (file, hdr, sizeof (*hdr)) != sizeof (*hdr))
190 unexec_error ("Couldn't write header to a.out file");
191 check_lseek (file, hdr->aux_header_location, 0);
192 if (write (file, auxhdr, sizeof (*auxhdr)) != sizeof (*auxhdr))
193 unexec_error ("Couldn't write auxiliary header to a.out file");
194 }
195
196
197
198 static int
199 calculate_checksum (struct header *hdr)
200 {
201 int checksum, i, *ptr;
202
203 checksum = 0; ptr = (int *) hdr;
204
205 for (i = 0; i < sizeof (*hdr) / sizeof (int) - 1; i++)
206 checksum ^= ptr[i];
207
208 return (checksum);
209 }
210
211
212
213 static void
214 copy_file (int old, int new, int size)
215 {
216 int len;
217 int buffer[8192];
218
219 for (; size > 0; size -= len)
220 {
221 len = min (size, sizeof (buffer));
222 if (read (old, buffer, len) != len)
223 unexec_error ("Read failure on a.out file");
224 if (write (new, buffer, len) != len)
225 unexec_error ("Write failure in a.out file");
226 }
227 }
228
229
230
231 static void
232 copy_rest (int old, int new)
233 {
234 int buffer[4096];
235 int len;
236
237
238 while ((len = read (old, buffer, sizeof (buffer))) > 0)
239 if (write (new, buffer, len) != len) break;
240
241 if (len != 0)
242 unexec_error ("Unable to copy the rest of the file");
243 }
244
245 #ifdef DEBUG
246 static void
247 display_header (struct header *hdr, struct som_exec_auxhdr *auxhdr)
248 {
249
250 printf ("\n\nFILE HEADER\n");
251 printf ("magic number %d \n", hdr->a_magic);
252 printf ("text loc %.8x size %d \n", auxhdr->exec_tmem, auxhdr->exec_tsize);
253 printf ("data loc %.8x size %d \n", auxhdr->exec_dmem, auxhdr->exec_dsize);
254 printf ("entry %x \n", auxhdr->exec_entry);
255 printf ("Bss segment size %u\n", auxhdr->exec_bsize);
256 printf ("\n");
257 printf ("data file loc %d size %d\n",
258 auxhdr->exec_dfile, auxhdr->exec_dsize);
259 printf ("som_length %d\n", hdr->som_length);
260 printf ("unloadable sploc %d size %d\n",
261 hdr->unloadable_sp_location, hdr->unloadable_sp_size);
262 }
263 #endif
264
265
266
267 void
268 unexec (const char *new_name,
269 const char *old_name)
270 {
271 int old, new;
272 int old_size, new_size;
273 struct header hdr;
274 struct som_exec_auxhdr auxhdr;
275 long i;
276
277
278
279
280
281
282
283
284
285 old = emacs_open (old_name, O_RDONLY, 0);
286 if (old < 0)
287 unexec_error (old_name);
288 new = emacs_open (new_name, O_CREAT | O_RDWR | O_TRUNC, 0777);
289 if (new < 0)
290 unexec_error (new_name);
291
292
293 read_header (old, &hdr, &auxhdr);
294
295 brk_on_dump = (long) sbrk (0);
296
297
298 old_size = auxhdr.exec_dsize;
299
300
301 i = (long) sbrk (0);
302 new_size = i - auxhdr.exec_dmem;
303
304
305 check_lseek (old, 0, 0);
306 copy_file (old, new, auxhdr.exec_dfile);
307
308
309 check_lseek (old, old_size, 1);
310 save_data_space (new, &hdr, &auxhdr, new_size);
311
312
313 copy_rest (old, new);
314
315
316 update_file_ptrs (new, &hdr, &auxhdr, auxhdr.exec_dfile, new_size-old_size);
317
318
319 write_header (new, &hdr, &auxhdr);
320
321
322 emacs_close (old);
323 emacs_close (new);
324 }