comparison src/unexhp9k800.c @ 272:c5d627a313b1 r21-0b34

Import from CVS: tag r21-0b34
author cvs
date Mon, 13 Aug 2007 10:28:48 +0200
parents 376386a54a3c
children 7df0dd720c89
comparison
equal deleted inserted replaced
271:c7b7086b0a39 272:c5d627a313b1
24 24
25 Unexec creates a copy of the old a.out file, and replaces the old data 25 Unexec creates a copy of the old a.out file, and replaces the old data
26 area with the current data area. When the new file is executed, the 26 area with the current data area. When the new file is executed, the
27 process will see the same data structures and data values that the 27 process will see the same data structures and data values that the
28 original process had when unexec was called. 28 original process had when unexec was called.
29 29
30 Unlike other versions of unexec, this one copies symbol table and 30 Unlike other versions of unexec, this one copies symbol table and
31 debug information to the new a.out file. Thus, the new a.out file 31 debug information to the new a.out file. Thus, the new a.out file
32 may be debugged with symbolic debuggers. 32 may be debugged with symbolic debuggers.
33 33
34 If you fix any bugs in this, I'd like to incorporate your fixes. 34 If you fix any bugs in this, I'd like to incorporate your fixes.
35 Send them to uunet!hpda!hpsemc!jmorris or jmorris%hpsemc@hplabs.HP.COM. 35 Send them to uunet!hpda!hpsemc!jmorris or jmorris%hpsemc@hplabs.HP.COM.
36 36
37 CAVEATS: 37 CAVEATS:
38 This routine saves the current value of all static and external 38 This routine saves the current value of all static and external
39 variables. This means that any data structure that needs to be 39 variables. This means that any data structure that needs to be
40 initialized must be explicitly reset. Variables will not have their 40 initialized must be explicitly reset. Variables will not have their
41 expected default values. 41 expected default values.
42 42
43 Unfortunately, the HP-UX signal handler has internal initialization 43 Unfortunately, the HP-UX signal handler has internal initialization
44 flags which are not explicitly reset. Thus, for signals to work in 44 flags which are not explicitly reset. Thus, for signals to work in
45 conjunction with this routine, the following code must executed when 45 conjunction with this routine, the following code must executed when
46 the new process starts up. 46 the new process starts up.
47 47
48 void _sigreturn(); 48 void _sigreturn();
49 ... 49 ...
50 sigsetreturn(_sigreturn); 50 sigsetreturn(_sigreturn);
51 */ 51 */
52 52
73 * 73 *
74 * 2. Assumes that the data and bss area are adjacent, which is true of the 74 * 2. Assumes that the data and bss area are adjacent, which is true of the
75 * current VM implementation. 75 * current VM implementation.
76 * 76 *
77 * 3. Any setup that defines HPUX_USE_SHLIBS *must* also define 77 * 3. Any setup that defines HPUX_USE_SHLIBS *must* also define
78 * RUN_TIME_REMAP. 78 * RUN_TIME_REMAP.
79 */ 79 */
80 80
81 #ifdef HPUX_USE_SHLIBS 81 #ifdef HPUX_USE_SHLIBS
82 #include <dl.h> /* User-space dynamic loader entry points */ 82 #include <dl.h> /* User-space dynamic loader entry points */
83 void Save_Shared_Data(); 83 void Save_Shared_Data();
85 #endif 85 #endif
86 86
87 #define roundup(x,n) ( ( (x)+(n-1) ) & ~(n-1) ) /* n is power of 2 */ 87 #define roundup(x,n) ( ( (x)+(n-1) ) & ~(n-1) ) /* n is power of 2 */
88 #define min(x,y) ( ((x)<(y))?(x):(y) ) 88 #define min(x,y) ( ((x)<(y))?(x):(y) )
89 89
90 void write_header(int file, struct header *hdr, struct som_exec_auxhdr *auxhdr);
91 void read_header (int file, struct header *hdr, struct som_exec_auxhdr *auxhdr);
92 void save_data_space (int file, struct header *hdr,
93 struct som_exec_auxhdr *auxhdr, int size);
94 void copy_rest (int old, int new);
95 void copy_file (int old, int new, int size);
96 void update_file_ptrs(int file, struct header *hdr,
97 struct som_exec_auxhdr *auxhdr,
98 unsigned int location, int offset);
90 99
91 /* Create a new a.out file, same as old but with current data space */ 100 /* Create a new a.out file, same as old but with current data space */
92 101 int
93 unexec(new_name, old_name, new_end_of_text, dummy1, dummy2) 102 unexec(char new_name[], /* name of the new a.out file to be created */
94 char new_name[]; /* name of the new a.out file to be created */ 103 char old_name[], /* name of the old a.out file */
95 char old_name[]; /* name of the old a.out file */ 104 char *new_end_of_text, /* ptr to new edata/etext; NOT USED YET */
96 char *new_end_of_text; /* ptr to new edata/etext; NOT USED YET */ 105 int dummy1, int dummy2) /* not used by emacs */
97 int dummy1, dummy2; /* not used by emacs */
98 { 106 {
99 int old, new; 107 int old, new;
100 int old_size, new_size; 108 int old_size, new_size;
101 struct header hdr; 109 struct header hdr;
102 struct som_exec_auxhdr auxhdr; 110 struct som_exec_auxhdr auxhdr;
103 long i; 111 long i;
104 112
105 /* For the greatest flexibility, should create a temporary file in 113 /* For the greatest flexibility, should create a temporary file in
106 the same directory as the new file. When everything is complete, 114 the same directory as the new file. When everything is complete,
107 rename the temp file to the new name. 115 rename the temp file to the new name.
108 This way, a program could update its own a.out file even while 116 This way, a program could update its own a.out file even while
109 it is still executing. If problems occur, everything is still 117 it is still executing. If problems occur, everything is still
110 intact. NOT implemented. */ 118 intact. NOT implemented. */
111 119
112 /* Open the input and output a.out files */ 120 /* Open the input and output a.out files */
113 old = open (old_name, O_RDONLY); 121 old = open (old_name, O_RDONLY);
114 if (old < 0) 122 if (old < 0)
115 { perror(old_name); exit(1); } 123 { perror(old_name); exit(1); }
116 new = open (new_name, O_CREAT|O_RDWR|O_TRUNC, 0777); 124 new = open (new_name, O_CREAT|O_RDWR|O_TRUNC, 0777);
117 if (new < 0) 125 if (new < 0)
118 { perror(new_name); exit(1); } 126 { perror(new_name); exit(1); }
119 127
120 /* Read the old headers */ 128 /* Read the old headers */
121 read_header(old, &hdr, &auxhdr); 129 read_header(old, &hdr, &auxhdr);
122 130
123 #ifdef HPUX_USE_SHLIBS 131 #ifdef HPUX_USE_SHLIBS
124 Save_Shared_Data(); /* Save break value (added: dg@hplb.hpl.hp.com) */ 132 Save_Shared_Data(); /* Save break value (added: dg@hplb.hpl.hp.com) */
125 #endif 133 #endif
126 /* Decide how large the new and old data areas are */ 134 /* Decide how large the new and old data areas are */
127 old_size = auxhdr.exec_dsize; 135 old_size = auxhdr.exec_dsize;
128 /* I suspect these two statements are separate 136 /* I suspect these two statements are separate
129 to avoid a compiler bug in hpux version 8. */ 137 to avoid a compiler bug in hpux version 8. */
130 i = (long) sbrk (0); 138 i = (long) sbrk (0);
131 new_size = i - auxhdr.exec_dmem; 139 new_size = i - auxhdr.exec_dmem;
132 140
133 /* Copy the old file to the new, up to the data space */ 141 /* Copy the old file to the new, up to the data space */
134 lseek(old, 0, 0); 142 lseek(old, 0, 0);
135 copy_file(old, new, auxhdr.exec_dfile); 143 copy_file(old, new, auxhdr.exec_dfile);
136 144
137 /* Skip the old data segment and write a new one */ 145 /* Skip the old data segment and write a new one */
138 lseek(old, old_size, 1); 146 lseek(old, old_size, 1);
139 save_data_space(new, &hdr, &auxhdr, new_size); 147 save_data_space(new, &hdr, &auxhdr, new_size);
140 148
141 /* Copy the rest of the file */ 149 /* Copy the rest of the file */
142 copy_rest(old, new); 150 copy_rest(old, new);
143 151
144 /* Update file pointers since we probably changed size of data area */ 152 /* Update file pointers since we probably changed size of data area */
145 update_file_ptrs(new, &hdr, &auxhdr, auxhdr.exec_dfile, new_size-old_size); 153 update_file_ptrs(new, &hdr, &auxhdr, auxhdr.exec_dfile, new_size-old_size);
146 154
147 /* Save the modified header */ 155 /* Save the modified header */
148 write_header(new, &hdr, &auxhdr); 156 write_header(new, &hdr, &auxhdr);
149 157
150 /* Close the binary file */ 158 /* Close the binary file */
151 close (old); 159 close (old);
152 close (new); 160 close (new);
153 return 0; 161 return 0;
154 } 162 }
155 163
156 /* Save current data space in the file, update header. */ 164 /* Save current data space in the file, update header. */
157 165
158 save_data_space(file, hdr, auxhdr, size) 166 void
159 int file; 167 save_data_space (int file, struct header *hdr,
160 struct header *hdr; 168 struct som_exec_auxhdr *auxhdr, int size)
161 struct som_exec_auxhdr *auxhdr;
162 int size;
163 { 169 {
164 /* Write the entire data space out to the file */ 170 /* Write the entire data space out to the file */
165 if (write(file, (void *)auxhdr->exec_dmem, size) != size) 171 if (write(file, (void *)auxhdr->exec_dmem, size) != size)
166 { perror("Can't save new data space"); exit(1); } 172 { perror("Can't save new data space"); exit(1); }
167 173
168 /* Update the header to reflect the new data size */ 174 /* Update the header to reflect the new data size */
169 auxhdr->exec_dsize = size; 175 auxhdr->exec_dsize = size;
170 auxhdr->exec_bsize = 0; 176 auxhdr->exec_bsize = 0;
171 } 177 }
172 178
173 /* Update the values of file pointers when something is inserted. */ 179 /* Update the values of file pointers when something is inserted. */
174 180
175 update_file_ptrs(file, hdr, auxhdr, location, offset) 181 void
176 int file; 182 update_file_ptrs(int file, struct header *hdr,
177 struct header *hdr; 183 struct som_exec_auxhdr *auxhdr,
178 struct som_exec_auxhdr *auxhdr; 184 unsigned int location, int offset)
179 unsigned int location;
180 int offset;
181 { 185 {
182 struct subspace_dictionary_record subspace; 186 struct subspace_dictionary_record subspace;
183 int i; 187 int i;
184 188
185 /* Increase the overall size of the module */ 189 /* Increase the overall size of the module */
186 hdr->som_length += offset; 190 hdr->som_length += offset;
187 191
188 /* Update the various file pointers in the header */ 192 /* Update the various file pointers in the header */
189 #define update(ptr) if (ptr > location) ptr = ptr + offset 193 #define update(ptr) if (ptr > location) ptr = ptr + offset
190 update(hdr->aux_header_location); 194 update(hdr->aux_header_location);
191 update(hdr->space_strings_location); 195 update(hdr->space_strings_location);
192 update(hdr->init_array_location); 196 update(hdr->init_array_location);
195 update(hdr->fixup_request_location); 199 update(hdr->fixup_request_location);
196 update(hdr->symbol_strings_location); 200 update(hdr->symbol_strings_location);
197 update(hdr->unloadable_sp_location); 201 update(hdr->unloadable_sp_location);
198 update(auxhdr->exec_tfile); 202 update(auxhdr->exec_tfile);
199 update(auxhdr->exec_dfile); 203 update(auxhdr->exec_dfile);
200 204
201 /* Do for each subspace dictionary entry */ 205 /* Do for each subspace dictionary entry */
202 lseek(file, hdr->subspace_location, 0); 206 lseek(file, hdr->subspace_location, 0);
203 for (i = 0; i < hdr->subspace_total; i++) 207 for (i = 0; i < hdr->subspace_total; i++)
204 { 208 {
205 if (read(file, &subspace, sizeof(subspace)) != sizeof(subspace)) 209 if (read(file, &subspace, sizeof(subspace)) != sizeof(subspace))
206 { perror("Can't read subspace record"); exit(1); } 210 { perror("Can't read subspace record"); exit(1); }
207 211
208 /* If subspace has a file location, update it */ 212 /* If subspace has a file location, update it */
209 if (subspace.initialization_length > 0 213 if (subspace.initialization_length > 0
210 && subspace.file_loc_init_value > location) 214 && subspace.file_loc_init_value > location)
211 { 215 {
212 subspace.file_loc_init_value += offset; 216 subspace.file_loc_init_value += offset;
213 lseek(file, -sizeof(subspace), 1); 217 lseek(file, -sizeof(subspace), 1);
214 if (write(file, &subspace, sizeof(subspace)) != sizeof(subspace)) 218 if (write(file, &subspace, sizeof(subspace)) != sizeof(subspace))
215 { perror("Can't update subspace record"); exit(1); } 219 { perror("Can't update subspace record"); exit(1); }
216 } 220 }
217 } 221 }
218 222
219 /* Do for each initialization pointer record */ 223 /* Do for each initialization pointer record */
220 /* (I don't think it applies to executable files, only relocatables) */ 224 /* (I don't think it applies to executable files, only relocatables) */
221 #undef update 225 #undef update
222 } 226 }
223 227
224 /* Read in the header records from an a.out file. */ 228 /* Read in the header records from an a.out file. */
225 229
226 read_header(file, hdr, auxhdr) 230 void
227 int file; 231 read_header(int file, struct header *hdr, struct som_exec_auxhdr *auxhdr)
228 struct header *hdr; 232 {
229 struct som_exec_auxhdr *auxhdr; 233
230 {
231
232 /* Read the header in */ 234 /* Read the header in */
233 lseek(file, 0, 0); 235 lseek(file, 0, 0);
234 if (read(file, hdr, sizeof(*hdr)) != sizeof(*hdr)) 236 if (read(file, hdr, sizeof(*hdr)) != sizeof(*hdr))
235 { perror("Couldn't read header from a.out file"); exit(1); } 237 { perror("Couldn't read header from a.out file"); exit(1); }
236 238
237 if (hdr->a_magic != EXEC_MAGIC && hdr->a_magic != SHARE_MAGIC 239 if (hdr->a_magic != EXEC_MAGIC && hdr->a_magic != SHARE_MAGIC
238 && hdr->a_magic != DEMAND_MAGIC) 240 && hdr->a_magic != DEMAND_MAGIC)
239 { 241 {
240 fprintf(stderr, "a.out file doesn't have legal magic number\n"); 242 fprintf(stderr, "a.out file doesn't have legal magic number\n");
241 exit(1); 243 exit(1);
242 } 244 }
243 245
244 lseek(file, hdr->aux_header_location, 0); 246 lseek(file, hdr->aux_header_location, 0);
245 if (read(file, auxhdr, sizeof(*auxhdr)) != sizeof(*auxhdr)) 247 if (read(file, auxhdr, sizeof(*auxhdr)) != sizeof(*auxhdr))
246 { 248 {
247 perror("Couldn't read auxiliary header from a.out file"); 249 perror("Couldn't read auxiliary header from a.out file");
248 exit(1); 250 exit(1);
249 } 251 }
250 } 252 }
251 253
252 /* Write out the header records into an a.out file. */ 254 /* Write out the header records into an a.out file. */
253 255 void
254 write_header(file, hdr, auxhdr) 256 write_header(int file, struct header *hdr, struct som_exec_auxhdr *auxhdr)
255 int file;
256 struct header *hdr;
257 struct som_exec_auxhdr *auxhdr;
258 { 257 {
259 /* Update the checksum */ 258 /* Update the checksum */
260 hdr->checksum = calculate_checksum(hdr); 259 hdr->checksum = calculate_checksum(hdr);
261 260
262 /* Write the header back into the a.out file */ 261 /* Write the header back into the a.out file */
263 lseek(file, 0, 0); 262 lseek(file, 0, 0);
264 if (write(file, hdr, sizeof(*hdr)) != sizeof(*hdr)) 263 if (write(file, hdr, sizeof(*hdr)) != sizeof(*hdr))
265 { perror("Couldn't write header to a.out file"); exit(1); } 264 { perror("Couldn't write header to a.out file"); exit(1); }
266 lseek(file, hdr->aux_header_location, 0); 265 lseek(file, hdr->aux_header_location, 0);
267 if (write(file, auxhdr, sizeof(*auxhdr)) != sizeof(*auxhdr)) 266 if (write(file, auxhdr, sizeof(*auxhdr)) != sizeof(*auxhdr))
268 { perror("Couldn't write auxiliary header to a.out file"); exit(1); } 267 { perror("Couldn't write auxiliary header to a.out file"); exit(1); }
269 } 268 }
270 269
271 /* Calculate the checksum of a SOM header record. */ 270 /* Calculate the checksum of a SOM header record. */
272 271 int
273 calculate_checksum(hdr) 272 calculate_checksum(struct header *hdr)
274 struct header *hdr;
275 { 273 {
276 int checksum, i, *ptr; 274 int checksum, i, *ptr;
277 275
278 checksum = 0; ptr = (int *) hdr; 276 checksum = 0; ptr = (int *) hdr;
279 277
280 for (i=0; i<sizeof(*hdr)/sizeof(int)-1; i++) 278 for (i=0; i<sizeof(*hdr)/sizeof(int)-1; i++)
281 checksum ^= ptr[i]; 279 checksum ^= ptr[i];
282 280
283 return(checksum); 281 return(checksum);
284 } 282 }
285 283
286 /* Copy size bytes from the old file to the new one. */ 284 /* Copy size bytes from the old file to the new one. */
287 285 void
288 copy_file(old, new, size) 286 copy_file (int old, int new, int size)
289 int new, old;
290 int size;
291 { 287 {
292 int len; 288 int len;
293 int buffer[8192]; /* word aligned will be faster */ 289 int buffer[8192]; /* word aligned will be faster */
294 290
295 for (; size > 0; size -= len) 291 for (; size > 0; size -= len)
296 { 292 {
297 len = min(size, sizeof(buffer)); 293 len = min(size, sizeof(buffer));
298 if (read(old, buffer, len) != len) 294 if (read(old, buffer, len) != len)
299 { perror("Read failure on a.out file"); exit(1); } 295 { perror("Read failure on a.out file"); exit(1); }
301 { perror("Write failure in a.out file"); exit(1); } 297 { perror("Write failure in a.out file"); exit(1); }
302 } 298 }
303 } 299 }
304 300
305 /* Copy the rest of the file, up to EOF. */ 301 /* Copy the rest of the file, up to EOF. */
306 302 void
307 copy_rest(old, new) 303 copy_rest (int old, int new)
308 int new, old;
309 { 304 {
310 int buffer[4096]; 305 int buffer[4096];
311 int len; 306 int len;
312 307
313 /* Copy bytes until end of file or error */ 308 /* Copy bytes until end of file or error */
314 while ( (len = read(old, buffer, sizeof(buffer))) > 0) 309 while ( (len = read(old, buffer, sizeof(buffer))) > 0)
315 if (write(new, buffer, len) != len) break; 310 if (write(new, buffer, len) != len) break;
316 311
317 if (len != 0) 312 if (len != 0)
318 { perror("Unable to copy the rest of the file"); exit(1); } 313 { perror("Unable to copy the rest of the file"); exit(1); }
319 } 314 }
320 315
321 #ifdef DEBUG 316 #ifdef DEBUG
322 display_header(hdr, auxhdr) 317 display_header(struct header *hdr, struct som_exec_auxhdr *auxhdr)
323 struct header *hdr;
324 struct som_exec_auxhdr *auxhdr;
325 { 318 {
326 /* Display the header information (debug) */ 319 /* Display the header information (debug) */
327 printf("\n\nFILE HEADER\n"); 320 printf("\n\nFILE HEADER\n");
328 printf("magic number %d \n", hdr->a_magic); 321 printf("magic number %d \n", hdr->a_magic);
329 printf("text loc %.8x size %d \n", auxhdr->exec_tmem, auxhdr->exec_tsize); 322 printf("text loc %.8x size %d \n", auxhdr->exec_tmem, auxhdr->exec_tsize);
330 printf("data loc %.8x size %d \n", auxhdr->exec_dmem, auxhdr->exec_dsize); 323 printf("data loc %.8x size %d \n", auxhdr->exec_dmem, auxhdr->exec_dsize);
331 printf("entry %x \n", auxhdr->exec_entry); 324 printf("entry %x \n", auxhdr->exec_entry);
332 printf("Bss segment size %u\n", auxhdr->exec_bsize); 325 printf("Bss segment size %u\n", auxhdr->exec_bsize);
333 printf("\n"); 326 printf("\n");
345 void *Brk_On_Dump = 0; /* Brk value to restore... stored as a global */ 338 void *Brk_On_Dump = 0; /* Brk value to restore... stored as a global */
346 339
347 void Save_Shared_Data () { 340 void Save_Shared_Data () {
348 Brk_On_Dump = sbrk( 0 ); 341 Brk_On_Dump = sbrk( 0 );
349 } 342 }
350 343
351 void Restore_Shared_Data () { 344 void Restore_Shared_Data () {
352 brk ( Brk_On_Dump ); 345 brk ( Brk_On_Dump );
353 } 346 }
354 347
355 int run_time_remap (int d) { 348 int run_time_remap (int d) {
356 Restore_Shared_Data(); 349 Restore_Shared_Data();
357 } 350 }
358 351
359 /* run_time_remap is the magic called by startup code in the dumped executable 352 /* run_time_remap is the magic called by startup code in the dumped executable
360 * if RUN_TIME_REMAP is set. 353 * if RUN_TIME_REMAP is set.
361 */ 354 */
362 #endif /* HPUX_USE_SHLIBS */ 355 #endif /* HPUX_USE_SHLIBS */