|
|
1.1 root 1: /* Unexec for HP 9000 Series 800 machines.
2: Bob Desinger <[email protected]>
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%[email protected].
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:
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:
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 */
58: {
59: int old, new;
60: int old_size, new_size;
61: struct header hdr;
62: struct som_exec_auxhdr auxhdr;
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 */
72: old = open(old_name, O_RDONLY);
73: if (old < 0)
74: { perror(old_name); exit(1); }
75: new = open(new_name, O_CREAT|O_RDWR|O_TRUNC, 0777);
76: if (new < 0)
77: { perror(new_name); exit(1); }
78:
79: /* Read the old headers */
80: read_header(old, &hdr, &auxhdr);
81:
82: /* Decide how large the new and old data areas are */
83: old_size = auxhdr.exec_dsize;
84: new_size = sbrk(0) - auxhdr.exec_dmem;
85:
86: /* Copy the old file to the new, up to the data space */
87: lseek(old, 0, 0);
88: copy_file(old, new, auxhdr.exec_dfile);
89:
90: /* Skip the old data segment and write a new one */
91: lseek(old, old_size, 1);
92: save_data_space(new, &hdr, &auxhdr, new_size);
93:
94: /* Copy the rest of the file */
95: copy_rest(old, new);
96:
97: /* Update file pointers since we probably changed size of data area */
98: update_file_ptrs(new, &hdr, &auxhdr, auxhdr.exec_dfile, new_size-old_size);
99:
100: /* Save the modified header */
101: write_header(new, &hdr, &auxhdr);
102:
103: /* Close the binary file */
104: close(old);
105: close(new);
106: exit(0);
107: }
108:
109: /* Save current data space in the file, update header. */
110:
111: save_data_space(file, hdr, auxhdr, size)
112: int file;
113: struct header *hdr;
114: struct som_exec_auxhdr *auxhdr;
115: int size;
116: {
117: /* Write the entire data space out to the file */
118: if (write(file, auxhdr->exec_dmem, size) != size)
119: { perror("Can't save new data space"); exit(1); }
120:
121: /* Update the header to reflect the new data size */
122: auxhdr->exec_dsize = size;
123: auxhdr->exec_bsize = 0;
124: }
125:
126: /* Update the values of file pointers when something is inserted. */
127:
128: update_file_ptrs(file, hdr, auxhdr, location, offset)
129: int file;
130: struct header *hdr;
131: struct som_exec_auxhdr *auxhdr;
132: unsigned int location;
133: int offset;
134: {
135: struct subspace_dictionary_record subspace;
136: int i;
137:
138: /* Increase the overall size of the module */
139: hdr->som_length += offset;
140:
141: /* Update the various file pointers in the header */
142: #define update(ptr) if (ptr > location) ptr = ptr + offset
143: update(hdr->aux_header_location);
144: update(hdr->space_strings_location);
145: update(hdr->init_array_location);
146: update(hdr->compiler_location);
147: update(hdr->symbol_location);
148: update(hdr->fixup_request_location);
149: update(hdr->symbol_strings_location);
150: update(hdr->unloadable_sp_location);
151: update(auxhdr->exec_tfile);
152: update(auxhdr->exec_dfile);
153:
154: /* Do for each subspace dictionary entry */
155: lseek(file, hdr->subspace_location, 0);
156: for (i = 0; i < hdr->subspace_total; i++)
157: {
158: if (read(file, &subspace, sizeof(subspace)) != sizeof(subspace))
159: { perror("Can't read subspace record"); exit(1); }
160:
161: /* If subspace has a file location, update it */
162: if (subspace.initialization_length > 0
163: && subspace.file_loc_init_value > location)
164: {
165: subspace.file_loc_init_value += offset;
166: lseek(file, -sizeof(subspace), 1);
167: if (write(file, &subspace, sizeof(subspace)) != sizeof(subspace))
168: { perror("Can't update subspace record"); exit(1); }
169: }
170: }
171:
172: /* Do for each initialization pointer record */
173: /* (I don't think it applies to executable files, only relocatables) */
174: #undef update
175: }
176:
177: /* Read in the header records from an a.out file. */
178:
179: read_header(file, hdr, auxhdr)
180: int file;
181: struct header *hdr;
182: struct som_exec_auxhdr *auxhdr;
183: {
184:
185: /* Read the header in */
186: lseek(file, 0, 0);
187: if (read(file, hdr, sizeof(*hdr)) != sizeof(*hdr))
188: { perror("Couldn't read header from a.out file"); exit(1); }
189:
190: if (hdr->a_magic != EXEC_MAGIC && hdr->a_magic != SHARE_MAGIC
191: && hdr->a_magic != DEMAND_MAGIC)
192: {
193: fprintf(stderr, "a.out file doesn't have legal magic number\n");
194: exit(1);
195: }
196:
197: lseek(file, hdr->aux_header_location, 0);
198: if (read(file, auxhdr, sizeof(*auxhdr)) != sizeof(*auxhdr))
199: {
200: perror("Couldn't read auxiliary header from a.out file");
201: exit(1);
202: }
203: }
204:
205: /* Write out the header records into an a.out file. */
206:
207: write_header(file, hdr, auxhdr)
208: int file;
209: struct header *hdr;
210: struct som_exec_auxhdr *auxhdr;
211: {
212: /* Update the checksum */
213: hdr->checksum = calculate_checksum(hdr);
214:
215: /* Write the header back into the a.out file */
216: lseek(file, 0, 0);
217: if (write(file, hdr, sizeof(*hdr)) != sizeof(*hdr))
218: { perror("Couldn't write header to a.out file"); exit(1); }
219: lseek(file, hdr->aux_header_location, 0);
220: if (write(file, auxhdr, sizeof(*auxhdr)) != sizeof(*auxhdr))
221: { perror("Couldn't write auxiliary header to a.out file"); exit(1); }
222: }
223:
224: /* Calculate the checksum of a SOM header record. */
225:
226: calculate_checksum(hdr)
227: struct header *hdr;
228: {
229: int checksum, i, *ptr;
230:
231: checksum = 0; ptr = (int *) hdr;
232:
233: for (i=0; i<sizeof(*hdr)/sizeof(int)-1; i++)
234: checksum ^= ptr[i];
235:
236: return(checksum);
237: }
238:
239: /* Copy size bytes from the old file to the new one. */
240:
241: copy_file(old, new, size)
242: int new, old;
243: int size;
244: {
245: int len;
246: int buffer[8196]; /* word aligned will be faster */
247:
248: for (; size > 0; size -= len)
249: {
250: len = min(size, sizeof(buffer));
251: if (read(old, buffer, len) != len)
252: { perror("Read failure on a.out file"); exit(1); }
253: if (write(new, buffer, len) != len)
254: { perror("Write failure in a.out file"); exit(1); }
255: }
256: }
257:
258: /* Copy the rest of the file, up to EOF. */
259:
260: copy_rest(old, new)
261: int new, old;
262: {
263: int buffer[4096];
264: int len;
265:
266: /* Copy bytes until end of file or error */
267: while ( (len = read(old, buffer, sizeof(buffer))) > 0)
268: if (write(new, buffer, len) != len) break;
269:
270: if (len != 0)
271: { perror("Unable to copy the rest of the file"); exit(1); }
272: }
273:
274: #ifdef DEBUG
275: display_header(hdr, auxhdr)
276: struct header *hdr;
277: struct som_exec_auxhdr *auxhdr;
278: {
279: /* Display the header information (debug) */
280: printf("\n\nFILE HEADER\n");
281: printf("magic number %d \n", hdr->a_magic);
282: printf("text loc %.8x size %d \n", auxhdr->exec_tmem, auxhdr->exec_tsize);
283: printf("data loc %.8x size %d \n", auxhdr->exec_dmem, auxhdr->exec_dsize);
284: printf("entry %x \n", auxhdr->exec_entry);
285: printf("Bss segment size %u\n", auxhdr->exec_bsize);
286: printf("\n");
287: printf("data file loc %d size %d\n",
288: auxhdr->exec_dfile, auxhdr->exec_dsize);
289: printf("som_length %d\n", hdr->som_length);
290: printf("unloadable sploc %d size %d\n",
291: hdr->unloadable_sp_location, hdr->unloadable_sp_size);
292: }
293: #endif /* DEBUG */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.