Whitespace fixes.
[bpt/emacs.git] / src / unexhp9k800.c
CommitLineData
dcfdbac7
JB
1/* Unexec for HP 9000 Series 800 machines.
2 Bob Desinger <hpsemc!bd@hplabs.hp.com>
3
4 Note that the GNU project considers support for HP operation a
5 peripheral activity which should not be allowed to divert effort
6 from development of the GNU system. Changes in this code will be
7 installed when users send them in, but aside from that we don't
8 plan to think about it, or about whether other Emacs maintenance
9 might break it.
10
11
12 Unexec creates a copy of the old a.out file, and replaces the old data
13 area with the current data area. When the new file is executed, the
14 process will see the same data structures and data values that the
15 original process had when unexec was called.
16
17 Unlike other versions of unexec, this one copies symbol table and
18 debug information to the new a.out file. Thus, the new a.out file
19 may be debugged with symbolic debuggers.
20
21 If you fix any bugs in this, I'd like to incorporate your fixes.
22 Send them to uunet!hpda!hpsemc!jmorris or jmorris%hpsemc@hplabs.HP.COM.
23
24 CAVEATS:
25 This routine saves the current value of all static and external
26 variables. This means that any data structure that needs to be
27 initialized must be explicitly reset. Variables will not have their
28 expected default values.
29
30 Unfortunately, the HP-UX signal handler has internal initialization
31 flags which are not explicitly reset. Thus, for signals to work in
32 conjunction with this routine, the following code must executed when
33 the new process starts up.
34
3f8a3241 35 void _sigreturn ();
dcfdbac7 36 ...
3f8a3241 37 sigsetreturn (_sigreturn);
dcfdbac7
JB
38*/
39\f
40#include <stdio.h>
41#include <fcntl.h>
42#include <errno.h>
43
44#include <a.out.h>
45
3f8a3241
RS
46#define roundup(x,n) (((x) + ((n) - 1)) & ~((n) - 1)) /* n is power of 2 */
47#define min(x,y) (((x) < (y)) ? (x) : (y))
dcfdbac7
JB
48
49
50/* Create a new a.out file, same as old but with current data space */
51
3f8a3241 52unexec (new_name, old_name, new_end_of_text, dummy1, dummy2)
dcfdbac7
JB
53 char new_name[]; /* name of the new a.out file to be created */
54 char old_name[]; /* name of the old a.out file */
55 char *new_end_of_text; /* ptr to new edata/etext; NOT USED YET */
56 int dummy1, dummy2; /* not used by emacs */
57{
58 int old, new;
59 int old_size, new_size;
60 struct header hdr;
61 struct som_exec_auxhdr auxhdr;
d427b66a 62 long i;
dcfdbac7
JB
63
64 /* For the greatest flexibility, should create a temporary file in
65 the same directory as the new file. When everything is complete,
66 rename the temp file to the new name.
67 This way, a program could update its own a.out file even while
68 it is still executing. If problems occur, everything is still
69 intact. NOT implemented. */
70
71 /* Open the input and output a.out files */
3f8a3241 72 old = open (old_name, O_RDONLY);
dcfdbac7 73 if (old < 0)
3f8a3241
RS
74 { perror (old_name); exit (1); }
75 new = open (new_name, O_CREAT|O_RDWR|O_TRUNC, 0777);
dcfdbac7 76 if (new < 0)
3f8a3241 77 { perror (new_name); exit (1); }
dcfdbac7
JB
78
79 /* Read the old headers */
3f8a3241 80 read_header (old, &hdr, &auxhdr);
dcfdbac7
JB
81
82 /* Decide how large the new and old data areas are */
83 old_size = auxhdr.exec_dsize;
d427b66a
JB
84 /* I suspect these two statements are separate
85 to avoid a compiler bug in hpux version 8. */
86 i = sbrk (0);
87 new_size = i - auxhdr.exec_dmem;
dcfdbac7
JB
88
89 /* Copy the old file to the new, up to the data space */
3f8a3241
RS
90 lseek (old, 0, 0);
91 copy_file (old, new, auxhdr.exec_dfile);
dcfdbac7
JB
92
93 /* Skip the old data segment and write a new one */
3f8a3241
RS
94 lseek (old, old_size, 1);
95 save_data_space (new, &hdr, &auxhdr, new_size);
dcfdbac7
JB
96
97 /* Copy the rest of the file */
3f8a3241 98 copy_rest (old, new);
dcfdbac7
JB
99
100 /* Update file pointers since we probably changed size of data area */
3f8a3241 101 update_file_ptrs (new, &hdr, &auxhdr, auxhdr.exec_dfile, new_size-old_size);
dcfdbac7
JB
102
103 /* Save the modified header */
3f8a3241 104 write_header (new, &hdr, &auxhdr);
dcfdbac7
JB
105
106 /* Close the binary file */
3f8a3241
RS
107 close (old);
108 close (new);
f3bca33c 109 return 0;
dcfdbac7
JB
110}
111
112/* Save current data space in the file, update header. */
113
3f8a3241 114save_data_space (file, hdr, auxhdr, size)
dcfdbac7
JB
115 int file;
116 struct header *hdr;
117 struct som_exec_auxhdr *auxhdr;
118 int size;
119{
120 /* Write the entire data space out to the file */
3f8a3241
RS
121 if (write (file, auxhdr->exec_dmem, size) != size)
122 { perror ("Can't save new data space"); exit (1); }
dcfdbac7
JB
123
124 /* Update the header to reflect the new data size */
125 auxhdr->exec_dsize = size;
126 auxhdr->exec_bsize = 0;
127}
128
129/* Update the values of file pointers when something is inserted. */
130
3f8a3241 131update_file_ptrs (file, hdr, auxhdr, location, offset)
dcfdbac7
JB
132 int file;
133 struct header *hdr;
134 struct som_exec_auxhdr *auxhdr;
135 unsigned int location;
136 int offset;
137{
138 struct subspace_dictionary_record subspace;
139 int i;
140
141 /* Increase the overall size of the module */
142 hdr->som_length += offset;
143
144 /* Update the various file pointers in the header */
145#define update(ptr) if (ptr > location) ptr = ptr + offset
3f8a3241
RS
146 update (hdr->aux_header_location);
147 update (hdr->space_strings_location);
148 update (hdr->init_array_location);
149 update (hdr->compiler_location);
150 update (hdr->symbol_location);
151 update (hdr->fixup_request_location);
152 update (hdr->symbol_strings_location);
153 update (hdr->unloadable_sp_location);
154 update (auxhdr->exec_tfile);
155 update (auxhdr->exec_dfile);
dcfdbac7
JB
156
157 /* Do for each subspace dictionary entry */
3f8a3241 158 lseek (file, hdr->subspace_location, 0);
dcfdbac7
JB
159 for (i = 0; i < hdr->subspace_total; i++)
160 {
3f8a3241
RS
161 if (read (file, &subspace, sizeof (subspace)) != sizeof (subspace))
162 { perror ("Can't read subspace record"); exit (1); }
dcfdbac7
JB
163
164 /* If subspace has a file location, update it */
165 if (subspace.initialization_length > 0
166 && subspace.file_loc_init_value > location)
167 {
168 subspace.file_loc_init_value += offset;
3f8a3241
RS
169 lseek (file, -sizeof (subspace), 1);
170 if (write (file, &subspace, sizeof (subspace)) != sizeof (subspace))
171 { perror ("Can't update subspace record"); exit (1); }
dcfdbac7
JB
172 }
173 }
174
175 /* Do for each initialization pointer record */
176 /* (I don't think it applies to executable files, only relocatables) */
177#undef update
178}
179
180/* Read in the header records from an a.out file. */
181
3f8a3241 182read_header (file, hdr, auxhdr)
dcfdbac7
JB
183 int file;
184 struct header *hdr;
185 struct som_exec_auxhdr *auxhdr;
186{
187
188 /* Read the header in */
3f8a3241
RS
189 lseek (file, 0, 0);
190 if (read (file, hdr, sizeof (*hdr)) != sizeof (*hdr))
191 { perror ("Couldn't read header from a.out file"); exit (1); }
dcfdbac7
JB
192
193 if (hdr->a_magic != EXEC_MAGIC && hdr->a_magic != SHARE_MAGIC
194 && hdr->a_magic != DEMAND_MAGIC)
195 {
3f8a3241
RS
196 fprintf (stderr, "a.out file doesn't have legal magic number\n");
197 exit (1);
dcfdbac7
JB
198 }
199
3f8a3241
RS
200 lseek (file, hdr->aux_header_location, 0);
201 if (read (file, auxhdr, sizeof (*auxhdr)) != sizeof (*auxhdr))
dcfdbac7 202 {
3f8a3241
RS
203 perror ("Couldn't read auxiliary header from a.out file");
204 exit (1);
dcfdbac7
JB
205 }
206}
207
208/* Write out the header records into an a.out file. */
209
3f8a3241 210write_header (file, hdr, auxhdr)
dcfdbac7
JB
211 int file;
212 struct header *hdr;
213 struct som_exec_auxhdr *auxhdr;
214{
215 /* Update the checksum */
3f8a3241 216 hdr->checksum = calculate_checksum (hdr);
dcfdbac7
JB
217
218 /* Write the header back into the a.out file */
3f8a3241
RS
219 lseek (file, 0, 0);
220 if (write (file, hdr, sizeof (*hdr)) != sizeof (*hdr))
221 { perror ("Couldn't write header to a.out file"); exit (1); }
222 lseek (file, hdr->aux_header_location, 0);
223 if (write (file, auxhdr, sizeof (*auxhdr)) != sizeof (*auxhdr))
224 { perror ("Couldn't write auxiliary header to a.out file"); exit (1); }
dcfdbac7
JB
225}
226
227/* Calculate the checksum of a SOM header record. */
228
3f8a3241 229calculate_checksum (hdr)
dcfdbac7
JB
230 struct header *hdr;
231{
232 int checksum, i, *ptr;
233
234 checksum = 0; ptr = (int *) hdr;
235
3f8a3241 236 for (i = 0; i < sizeof (*hdr) / sizeof (int) - 1; i++)
dcfdbac7
JB
237 checksum ^= ptr[i];
238
3f8a3241 239 return (checksum);
dcfdbac7
JB
240}
241
242/* Copy size bytes from the old file to the new one. */
243
3f8a3241 244copy_file (old, new, size)
dcfdbac7
JB
245 int new, old;
246 int size;
247{
248 int len;
249 int buffer[8196]; /* word aligned will be faster */
250
251 for (; size > 0; size -= len)
252 {
3f8a3241
RS
253 len = min (size, sizeof (buffer));
254 if (read (old, buffer, len) != len)
255 { perror ("Read failure on a.out file"); exit (1); }
256 if (write (new, buffer, len) != len)
257 { perror ("Write failure in a.out file"); exit (1); }
dcfdbac7
JB
258 }
259}
260
261/* Copy the rest of the file, up to EOF. */
262
3f8a3241 263copy_rest (old, new)
dcfdbac7
JB
264 int new, old;
265{
266 int buffer[4096];
267 int len;
268
269 /* Copy bytes until end of file or error */
3f8a3241
RS
270 while ((len = read (old, buffer, sizeof (buffer))) > 0)
271 if (write (new, buffer, len) != len) break;
dcfdbac7
JB
272
273 if (len != 0)
3f8a3241 274 { perror ("Unable to copy the rest of the file"); exit (1); }
dcfdbac7
JB
275}
276
277#ifdef DEBUG
3f8a3241 278display_header (hdr, auxhdr)
dcfdbac7
JB
279 struct header *hdr;
280 struct som_exec_auxhdr *auxhdr;
281{
282 /* Display the header information (debug) */
3f8a3241
RS
283 printf ("\n\nFILE HEADER\n");
284 printf ("magic number %d \n", hdr->a_magic);
285 printf ("text loc %.8x size %d \n", auxhdr->exec_tmem, auxhdr->exec_tsize);
286 printf ("data loc %.8x size %d \n", auxhdr->exec_dmem, auxhdr->exec_dsize);
287 printf ("entry %x \n", auxhdr->exec_entry);
288 printf ("Bss segment size %u\n", auxhdr->exec_bsize);
289 printf ("\n");
290 printf ("data file loc %d size %d\n",
291 auxhdr->exec_dfile, auxhdr->exec_dsize);
292 printf ("som_length %d\n", hdr->som_length);
293 printf ("unloadable sploc %d size %d\n",
294 hdr->unloadable_sp_location, hdr->unloadable_sp_size);
dcfdbac7
JB
295}
296#endif /* DEBUG */