*** empty log message ***
[emacs.git] / src / unexhp9k800.c
blob8d34a3a3d7a2fad0c882ab791afabddbe7c3ed4e
1 /* Unexec for HP 9000 Series 800 machines.
2 Bob Desinger <hpsemc!bd@hplabs.hp.com>
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.
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.
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.
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.
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.
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.
35 void _sigreturn();
36 ...
37 sigsetreturn(_sigreturn);
40 #include <stdio.h>
41 #include <fcntl.h>
42 #include <errno.h>
44 #include <a.out.h>
46 #define NBPG 2048
47 #define roundup(x,n) ( ( (x)+(n-1) ) & ~(n-1) ) /* n is power of 2 */
48 #define min(x,y) ( ((x)<(y))?(x):(y) )
51 /* Create a new a.out file, same as old but with current data space */
53 unexec(new_name, old_name, new_end_of_text, dummy1, dummy2)
54 char new_name[]; /* name of the new a.out file to be created */
55 char old_name[]; /* name of the old a.out file */
56 char *new_end_of_text; /* ptr to new edata/etext; NOT USED YET */
57 int dummy1, dummy2; /* not used by emacs */
59 int old, new;
60 int old_size, new_size;
61 struct header hdr;
62 struct som_exec_auxhdr auxhdr;
63 long i;
65 /* For the greatest flexibility, should create a temporary file in
66 the same directory as the new file. When everything is complete,
67 rename the temp file to the new name.
68 This way, a program could update its own a.out file even while
69 it is still executing. If problems occur, everything is still
70 intact. NOT implemented. */
72 /* Open the input and output a.out files */
73 old = open(old_name, O_RDONLY);
74 if (old < 0)
75 { perror(old_name); exit(1); }
76 new = open(new_name, O_CREAT|O_RDWR|O_TRUNC, 0777);
77 if (new < 0)
78 { perror(new_name); exit(1); }
80 /* Read the old headers */
81 read_header(old, &hdr, &auxhdr);
83 /* Decide how large the new and old data areas are */
84 old_size = auxhdr.exec_dsize;
85 /* I suspect these two statements are separate
86 to avoid a compiler bug in hpux version 8. */
87 i = sbrk (0);
88 new_size = i - auxhdr.exec_dmem;
90 /* Copy the old file to the new, up to the data space */
91 lseek(old, 0, 0);
92 copy_file(old, new, auxhdr.exec_dfile);
94 /* Skip the old data segment and write a new one */
95 lseek(old, old_size, 1);
96 save_data_space(new, &hdr, &auxhdr, new_size);
98 /* Copy the rest of the file */
99 copy_rest(old, new);
101 /* Update file pointers since we probably changed size of data area */
102 update_file_ptrs(new, &hdr, &auxhdr, auxhdr.exec_dfile, new_size-old_size);
104 /* Save the modified header */
105 write_header(new, &hdr, &auxhdr);
107 /* Close the binary file */
108 close(old);
109 close(new);
110 exit(0);
113 /* Save current data space in the file, update header. */
115 save_data_space(file, hdr, auxhdr, size)
116 int file;
117 struct header *hdr;
118 struct som_exec_auxhdr *auxhdr;
119 int size;
121 /* Write the entire data space out to the file */
122 if (write(file, auxhdr->exec_dmem, size) != size)
123 { perror("Can't save new data space"); exit(1); }
125 /* Update the header to reflect the new data size */
126 auxhdr->exec_dsize = size;
127 auxhdr->exec_bsize = 0;
130 /* Update the values of file pointers when something is inserted. */
132 update_file_ptrs(file, hdr, auxhdr, location, offset)
133 int file;
134 struct header *hdr;
135 struct som_exec_auxhdr *auxhdr;
136 unsigned int location;
137 int offset;
139 struct subspace_dictionary_record subspace;
140 int i;
142 /* Increase the overall size of the module */
143 hdr->som_length += offset;
145 /* Update the various file pointers in the header */
146 #define update(ptr) if (ptr > location) ptr = ptr + offset
147 update(hdr->aux_header_location);
148 update(hdr->space_strings_location);
149 update(hdr->init_array_location);
150 update(hdr->compiler_location);
151 update(hdr->symbol_location);
152 update(hdr->fixup_request_location);
153 update(hdr->symbol_strings_location);
154 update(hdr->unloadable_sp_location);
155 update(auxhdr->exec_tfile);
156 update(auxhdr->exec_dfile);
158 /* Do for each subspace dictionary entry */
159 lseek(file, hdr->subspace_location, 0);
160 for (i = 0; i < hdr->subspace_total; i++)
162 if (read(file, &subspace, sizeof(subspace)) != sizeof(subspace))
163 { perror("Can't read subspace record"); exit(1); }
165 /* If subspace has a file location, update it */
166 if (subspace.initialization_length > 0
167 && subspace.file_loc_init_value > location)
169 subspace.file_loc_init_value += offset;
170 lseek(file, -sizeof(subspace), 1);
171 if (write(file, &subspace, sizeof(subspace)) != sizeof(subspace))
172 { perror("Can't update subspace record"); exit(1); }
176 /* Do for each initialization pointer record */
177 /* (I don't think it applies to executable files, only relocatables) */
178 #undef update
181 /* Read in the header records from an a.out file. */
183 read_header(file, hdr, auxhdr)
184 int file;
185 struct header *hdr;
186 struct som_exec_auxhdr *auxhdr;
189 /* Read the header in */
190 lseek(file, 0, 0);
191 if (read(file, hdr, sizeof(*hdr)) != sizeof(*hdr))
192 { perror("Couldn't read header from a.out file"); exit(1); }
194 if (hdr->a_magic != EXEC_MAGIC && hdr->a_magic != SHARE_MAGIC
195 && hdr->a_magic != DEMAND_MAGIC)
197 fprintf(stderr, "a.out file doesn't have legal magic number\n");
198 exit(1);
201 lseek(file, hdr->aux_header_location, 0);
202 if (read(file, auxhdr, sizeof(*auxhdr)) != sizeof(*auxhdr))
204 perror("Couldn't read auxiliary header from a.out file");
205 exit(1);
209 /* Write out the header records into an a.out file. */
211 write_header(file, hdr, auxhdr)
212 int file;
213 struct header *hdr;
214 struct som_exec_auxhdr *auxhdr;
216 /* Update the checksum */
217 hdr->checksum = calculate_checksum(hdr);
219 /* Write the header back into the a.out file */
220 lseek(file, 0, 0);
221 if (write(file, hdr, sizeof(*hdr)) != sizeof(*hdr))
222 { perror("Couldn't write header to a.out file"); exit(1); }
223 lseek(file, hdr->aux_header_location, 0);
224 if (write(file, auxhdr, sizeof(*auxhdr)) != sizeof(*auxhdr))
225 { perror("Couldn't write auxiliary header to a.out file"); exit(1); }
228 /* Calculate the checksum of a SOM header record. */
230 calculate_checksum(hdr)
231 struct header *hdr;
233 int checksum, i, *ptr;
235 checksum = 0; ptr = (int *) hdr;
237 for (i=0; i<sizeof(*hdr)/sizeof(int)-1; i++)
238 checksum ^= ptr[i];
240 return(checksum);
243 /* Copy size bytes from the old file to the new one. */
245 copy_file(old, new, size)
246 int new, old;
247 int size;
249 int len;
250 int buffer[8196]; /* word aligned will be faster */
252 for (; size > 0; size -= len)
254 len = min(size, sizeof(buffer));
255 if (read(old, buffer, len) != len)
256 { perror("Read failure on a.out file"); exit(1); }
257 if (write(new, buffer, len) != len)
258 { perror("Write failure in a.out file"); exit(1); }
262 /* Copy the rest of the file, up to EOF. */
264 copy_rest(old, new)
265 int new, old;
267 int buffer[4096];
268 int len;
270 /* Copy bytes until end of file or error */
271 while ( (len = read(old, buffer, sizeof(buffer))) > 0)
272 if (write(new, buffer, len) != len) break;
274 if (len != 0)
275 { perror("Unable to copy the rest of the file"); exit(1); }
278 #ifdef DEBUG
279 display_header(hdr, auxhdr)
280 struct header *hdr;
281 struct som_exec_auxhdr *auxhdr;
283 /* Display the header information (debug) */
284 printf("\n\nFILE HEADER\n");
285 printf("magic number %d \n", hdr->a_magic);
286 printf("text loc %.8x size %d \n", auxhdr->exec_tmem, auxhdr->exec_tsize);
287 printf("data loc %.8x size %d \n", auxhdr->exec_dmem, auxhdr->exec_dsize);
288 printf("entry %x \n", auxhdr->exec_entry);
289 printf("Bss segment size %u\n", auxhdr->exec_bsize);
290 printf("\n");
291 printf("data file loc %d size %d\n",
292 auxhdr->exec_dfile, auxhdr->exec_dsize);
293 printf("som_length %d\n", hdr->som_length);
294 printf("unloadable sploc %d size %d\n",
295 hdr->unloadable_sp_location, hdr->unloadable_sp_size);
297 #endif /* DEBUG */