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
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.
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.
37 sigsetreturn(_sigreturn);
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 */
60 int old_size
, new_size
;
62 struct som_exec_auxhdr auxhdr
;
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
);
75 { perror(old_name
); exit(1); }
76 new = open(new_name
, O_CREAT
|O_RDWR
|O_TRUNC
, 0777);
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. */
88 new_size
= i
- auxhdr
.exec_dmem
;
90 /* Copy the old file to the new, up to the data space */
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 */
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 */
113 /* Save current data space in the file, update header. */
115 save_data_space(file
, hdr
, auxhdr
, size
)
118 struct som_exec_auxhdr
*auxhdr
;
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
)
135 struct som_exec_auxhdr
*auxhdr
;
136 unsigned int location
;
139 struct subspace_dictionary_record subspace
;
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) */
181 /* Read in the header records from an a.out file. */
183 read_header(file
, hdr
, auxhdr
)
186 struct som_exec_auxhdr
*auxhdr
;
189 /* Read the header in */
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");
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");
209 /* Write out the header records into an a.out file. */
211 write_header(file
, hdr
, auxhdr
)
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 */
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
)
233 int checksum
, i
, *ptr
;
235 checksum
= 0; ptr
= (int *) hdr
;
237 for (i
=0; i
<sizeof(*hdr
)/sizeof(int)-1; i
++)
243 /* Copy size bytes from the old file to the new one. */
245 copy_file(old
, new, size
)
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. */
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;
275 { perror("Unable to copy the rest of the file"); exit(1); }
279 display_header(hdr
, auxhdr
)
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
);
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
);