(construct_menu_click, construct_mouse_click):
[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
35 void _sigreturn();
36 ...
37 sigsetreturn(_sigreturn);
38*/
39\f
40#include <stdio.h>
41#include <fcntl.h>
42#include <errno.h>
43
44#include <a.out.h>
45
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) )
49
50
51/* Create a new a.out file, same as old but with current data space */
52
53unexec(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 */
58{
59 int old, new;
60 int old_size, new_size;
61 struct header hdr;
62 struct som_exec_auxhdr auxhdr;
d427b66a 63 long i;
dcfdbac7
JB
64
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. */
71
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); }
79
80 /* Read the old headers */
81 read_header(old, &hdr, &auxhdr);
82
83 /* Decide how large the new and old data areas are */
84 old_size = auxhdr.exec_dsize;
d427b66a
JB
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;
dcfdbac7
JB
89
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);
93
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);
97
98 /* Copy the rest of the file */
99 copy_rest(old, new);
100
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);
103
104 /* Save the modified header */
105 write_header(new, &hdr, &auxhdr);
106
107 /* Close the binary file */
108 close(old);
109 close(new);
f3bca33c 110 return 0;
dcfdbac7
JB
111}
112
113/* Save current data space in the file, update header. */
114
115save_data_space(file, hdr, auxhdr, size)
116 int file;
117 struct header *hdr;
118 struct som_exec_auxhdr *auxhdr;
119 int size;
120{
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); }
124
125 /* Update the header to reflect the new data size */
126 auxhdr->exec_dsize = size;
127 auxhdr->exec_bsize = 0;
128}
129
130/* Update the values of file pointers when something is inserted. */
131
132update_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;
138{
139 struct subspace_dictionary_record subspace;
140 int i;
141
142 /* Increase the overall size of the module */
143 hdr->som_length += offset;
144
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);
157
158 /* Do for each subspace dictionary entry */
159 lseek(file, hdr->subspace_location, 0);
160 for (i = 0; i < hdr->subspace_total; i++)
161 {
162 if (read(file, &subspace, sizeof(subspace)) != sizeof(subspace))
163 { perror("Can't read subspace record"); exit(1); }
164
165 /* If subspace has a file location, update it */
166 if (subspace.initialization_length > 0
167 && subspace.file_loc_init_value > location)
168 {
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); }
173 }
174 }
175
176 /* Do for each initialization pointer record */
177 /* (I don't think it applies to executable files, only relocatables) */
178#undef update
179}
180
181/* Read in the header records from an a.out file. */
182
183read_header(file, hdr, auxhdr)
184 int file;
185 struct header *hdr;
186 struct som_exec_auxhdr *auxhdr;
187{
188
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); }
193
194 if (hdr->a_magic != EXEC_MAGIC && hdr->a_magic != SHARE_MAGIC
195 && hdr->a_magic != DEMAND_MAGIC)
196 {
197 fprintf(stderr, "a.out file doesn't have legal magic number\n");
198 exit(1);
199 }
200
201 lseek(file, hdr->aux_header_location, 0);
202 if (read(file, auxhdr, sizeof(*auxhdr)) != sizeof(*auxhdr))
203 {
204 perror("Couldn't read auxiliary header from a.out file");
205 exit(1);
206 }
207}
208
209/* Write out the header records into an a.out file. */
210
211write_header(file, hdr, auxhdr)
212 int file;
213 struct header *hdr;
214 struct som_exec_auxhdr *auxhdr;
215{
216 /* Update the checksum */
217 hdr->checksum = calculate_checksum(hdr);
218
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); }
226}
227
228/* Calculate the checksum of a SOM header record. */
229
230calculate_checksum(hdr)
231 struct header *hdr;
232{
233 int checksum, i, *ptr;
234
235 checksum = 0; ptr = (int *) hdr;
236
237 for (i=0; i<sizeof(*hdr)/sizeof(int)-1; i++)
238 checksum ^= ptr[i];
239
240 return(checksum);
241}
242
243/* Copy size bytes from the old file to the new one. */
244
245copy_file(old, new, size)
246 int new, old;
247 int size;
248{
249 int len;
250 int buffer[8196]; /* word aligned will be faster */
251
252 for (; size > 0; size -= len)
253 {
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); }
259 }
260}
261
262/* Copy the rest of the file, up to EOF. */
263
264copy_rest(old, new)
265 int new, old;
266{
267 int buffer[4096];
268 int len;
269
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;
273
274 if (len != 0)
275 { perror("Unable to copy the rest of the file"); exit(1); }
276}
277
278#ifdef DEBUG
279display_header(hdr, auxhdr)
280 struct header *hdr;
281 struct som_exec_auxhdr *auxhdr;
282{
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);
296}
297#endif /* DEBUG */