Mercurial > hg > xemacs-beta
comparison src/unexaix.c @ 286:57709be46d1b r21-0b41
Import from CVS: tag r21-0b41
author | cvs |
---|---|
date | Mon, 13 Aug 2007 10:35:03 +0200 |
parents | c42ec1d1cded |
children | 4b85ae5eabfb |
comparison
equal
deleted
inserted
replaced
285:9a3756523c1b | 286:57709be46d1b |
---|---|
1 /* Copyright (C) 1985, 1986, 1987, 1988 Free Software Foundation, Inc. | 1 /* Dump an executable image. |
2 Copyright (C) 1985, 1986, 1987, 1988 Free Software Foundation, Inc. | |
2 | 3 |
3 This file is part of XEmacs. | 4 This file is part of XEmacs. |
4 | 5 |
5 XEmacs is free software; you can redistribute it and/or modify it | 6 XEmacs is free software; you can redistribute it and/or modify it |
6 under the terms of the GNU General Public License as published by the | 7 under the terms of the GNU General Public License as published by the |
15 You should have received a copy of the GNU General Public License | 16 You should have received a copy of the GNU General Public License |
16 along with XEmacs; see the file COPYING. If not, write to | 17 along with XEmacs; see the file COPYING. If not, write to |
17 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | 18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, |
18 Boston, MA 02111-1307, USA. */ | 19 Boston, MA 02111-1307, USA. */ |
19 | 20 |
20 /* Synched up with: FSF 19.31. */ | 21 /* Synched up with: FSF 20.2. */ |
21 | 22 |
22 /* Modified by Andrew.Vignaux@comp.vuw.ac.nz to get it to work :-) */ | 23 /* Originally based on the COFF unexec.c by Spencer W. Thomas. |
23 | 24 * |
24 /* | 25 * Subsequently hacked on by |
25 * unexec.c - Convert a running program into an a.out file. | 26 * Bill Mann <Bill_Man@praxisint.com> |
26 * | 27 * Andrew Vignaux <Andrew.Vignaux@comp.vuw.ac.nz> |
27 * Author: Spencer W. Thomas | 28 * Mike Sperber <sperber@informatik.uni-tuebingen.de> |
28 * Computer Science Dept. | |
29 * University of Utah | |
30 * Date: Tue Mar 2 1982 | |
31 * Modified heavily since then. | |
32 * | |
33 * Updated for AIX 4.1.3 by Bill_Mann @ PraxisInt.com, Feb 1996 | |
34 * As of AIX 4.1, text, data, and bss are pre-relocated by the binder in | |
35 * such a way that the file can be mapped with code in one segment and | |
36 * data/bss in another segment, without reading or copying the file, by | |
37 * the AIX exec loader. Padding sections are omitted, nevertheless | |
38 * small amounts of 'padding' still occurs between sections in the file. | |
39 * As modified, this code handles both 3.2 and 4.1 conventions. | |
40 * | 29 * |
41 * Synopsis: | 30 * Synopsis: |
42 * unexec (new_name, a_name, data_start, bss_start, entry_address) | 31 * unexec (new_name, a_name, data_start, bss_start, entry_address) |
43 * char *new_name, *a_name; | 32 * char *new_name, *a_name; |
44 * unsigned data_start, bss_start, entry_address; | 33 * unsigned data_start, bss_start, entry_address; |
46 * Takes a snapshot of the program and makes an a.out format file in the | 35 * Takes a snapshot of the program and makes an a.out format file in the |
47 * file named by the string argument new_name. | 36 * file named by the string argument new_name. |
48 * If a_name is non-NULL, the symbol table will be taken from the given file. | 37 * If a_name is non-NULL, the symbol table will be taken from the given file. |
49 * On some machines, an existing a_name file is required. | 38 * On some machines, an existing a_name file is required. |
50 * | 39 * |
51 * The boundaries within the a.out file may be adjusted with the data_start | 40 * data_start and entry_address are ignored. |
52 * and bss_start arguments. Either or both may be given as 0 for defaults. | 41 * |
53 * | 42 * bss_start indicates how much of the data segment is to be saved in the |
54 * Data_start gives the boundary between the text segment and the data | |
55 * segment of the program. The text segment can contain shared, read-only | |
56 * program code and literal data, while the data segment is always unshared | |
57 * and unprotected. Data_start gives the lowest unprotected address. | |
58 * The value you specify may be rounded down to a suitable boundary | |
59 * as required by the machine you are using. | |
60 * | |
61 * Specifying zero for data_start means the boundary between text and data | |
62 * should not be the same as when the program was loaded. | |
63 * If NO_REMAP is defined, the argument data_start is ignored and the | |
64 * segment boundaries are never changed. | |
65 * | |
66 * Bss_start indicates how much of the data segment is to be saved in the | |
67 * a.out file and restored when the program is executed. It gives the lowest | 43 * a.out file and restored when the program is executed. It gives the lowest |
68 * unsaved address, and is rounded up to a page boundary. The default when 0 | 44 * unsaved address, and is rounded up to a page boundary. The default when 0 |
69 * is given assumes that the entire data segment is to be stored, including | 45 * is given assumes that the entire data segment is to be stored, including |
70 * the previous data and bss as well as any additional storage allocated with | 46 * the previous data and bss as well as any additional storage allocated with |
71 * break (2). | 47 * sbrk(2). |
72 * | |
73 * The new file is set up to start at entry_address. | |
74 * | |
75 * If you make improvements I'd like to get them too. | |
76 * harpo!utah-cs!thomas, thomas@Utah-20 | |
77 * | 48 * |
78 */ | 49 */ |
79 | |
80 /* There are several compilation parameters affecting unexec: | |
81 | |
82 * COFF | |
83 | |
84 Define this if your system uses COFF for executables. | |
85 Otherwise we assume you use Berkeley format. | |
86 | |
87 * NO_REMAP | |
88 | |
89 Define this if you do not want to try to save Emacs's pure data areas | |
90 as part of the text segment. | |
91 | |
92 Saving them as text is good because it allows users to share more. | |
93 | |
94 However, on machines that locate the text area far from the data area, | |
95 the boundary cannot feasibly be moved. Such machines require | |
96 NO_REMAP. | |
97 | |
98 Also, remapping can cause trouble with the built-in startup routine | |
99 /lib/crt0.o, which defines `environ' as an initialized variable. | |
100 Dumping `environ' as pure does not work! So, to use remapping, | |
101 you must write a startup routine for your machine in Emacs's crt0.c. | |
102 If NO_REMAP is defined, Emacs uses the system's crt0.o. | |
103 | |
104 * SECTION_ALIGNMENT | |
105 | |
106 Some machines that use COFF executables require that each section | |
107 start on a certain boundary *in the COFF file*. Such machines should | |
108 define SECTION_ALIGNMENT to a mask of the low-order bits that must be | |
109 zero on such a boundary. This mask is used to control padding between | |
110 segments in the COFF file. | |
111 | |
112 If SECTION_ALIGNMENT is not defined, the segments are written | |
113 consecutively with no attempt at alignment. This is right for | |
114 unmodified system V. | |
115 | |
116 * SEGMENT_MASK | |
117 | |
118 Some machines require that the beginnings and ends of segments | |
119 *in core* be on certain boundaries. For most machines, a page | |
120 boundary is sufficient. That is the default. When a larger | |
121 boundary is needed, define SEGMENT_MASK to a mask of | |
122 the bits that must be zero on such a boundary. | |
123 | |
124 * A_TEXT_OFFSET(HDR) | |
125 | |
126 Some machines count the a.out header as part of the size of the text | |
127 segment (a_text); they may actually load the header into core as the | |
128 first data in the text segment. Some have additional padding between | |
129 the header and the real text of the program that is counted in a_text. | |
130 | |
131 For these machines, define A_TEXT_OFFSET(HDR) to examine the header | |
132 structure HDR and return the number of bytes to add to `a_text' | |
133 before writing it (above and beyond the number of bytes of actual | |
134 program text). HDR's standard fields are already correct, except that | |
135 this adjustment to the `a_text' field has not yet been made; | |
136 thus, the amount of offset can depend on the data in the file. | |
137 | |
138 * A_TEXT_SEEK(HDR) | |
139 | |
140 If defined, this macro specifies the number of bytes to seek into the | |
141 a.out file before starting to write the text segment.a | |
142 | |
143 * EXEC_MAGIC | |
144 | |
145 For machines using COFF, this macro, if defined, is a value stored | |
146 into the magic number field of the output file. | |
147 | |
148 * ADJUST_EXEC_HEADER | |
149 | |
150 This macro can be used to generate statements to adjust or | |
151 initialize nonstandard fields in the file header | |
152 | |
153 * ADDR_CORRECT(ADDR) | |
154 | |
155 Macro to correct an int which is the bit pattern of a pointer to a byte | |
156 into an int which is the number of a byte. | |
157 | |
158 This macro has a default definition which is usually right. | |
159 This default definition is a no-op on most machines (where a | |
160 pointer looks like an int) but not on all machines. | |
161 | |
162 */ | |
163 | |
164 #define XCOFF | |
165 #define COFF | |
166 #define NO_REMAP | |
167 | 50 |
168 #ifndef emacs | 51 #ifndef emacs |
169 #define PERROR(arg) perror (arg); return -1 | 52 #define PERROR(arg) perror (arg); return -1 |
170 #else | 53 #else |
171 #include <config.h> | 54 #include <config.h> |
176 /* Define getpagesize () if the system does not. | 59 /* Define getpagesize () if the system does not. |
177 Note that this may depend on symbols defined in a.out.h | 60 Note that this may depend on symbols defined in a.out.h |
178 */ | 61 */ |
179 #include "getpagesize.h" | 62 #include "getpagesize.h" |
180 | 63 |
181 #ifndef makedev /* Try to detect types.h already loaded */ | |
182 #include <sys/types.h> | 64 #include <sys/types.h> |
183 #endif | |
184 #include <stdio.h> | 65 #include <stdio.h> |
185 #include <sys/stat.h> | 66 #include <sys/stat.h> |
186 #include <errno.h> | 67 #include <errno.h> |
68 #include <unistd.h> | |
69 #include <fcntl.h> | |
187 | 70 |
188 extern char *start_of_text (void); /* Start of text */ | 71 extern char *start_of_text (void); /* Start of text */ |
189 extern char *start_of_data (void); /* Start of initialized data */ | 72 extern char *start_of_data (void); /* Start of initialized data */ |
190 | 73 |
191 extern int _data; | 74 extern int _data; |
192 extern int _edata; | |
193 extern int _text; | 75 extern int _text; |
194 extern int _etext; | 76 |
195 extern int _end; | |
196 #ifdef COFF | |
197 #ifndef USG | |
198 #ifndef STRIDE | |
199 #ifndef UMAX | |
200 #ifndef sun386 | |
201 /* I have a suspicion that these are turned off on all systems | |
202 and can be deleted. Try it in version 19. */ | |
203 #include <filehdr.h> | 77 #include <filehdr.h> |
204 #include <aouthdr.h> | 78 #include <aouthdr.h> |
205 #include <scnhdr.h> | 79 #include <scnhdr.h> |
206 #include <syms.h> | 80 #include <syms.h> |
207 #endif /* not sun386 */ | 81 |
208 #endif /* not UMAX */ | |
209 #endif /* Not STRIDE */ | |
210 #endif /* not USG */ | |
211 static struct filehdr f_hdr; /* File header */ | 82 static struct filehdr f_hdr; /* File header */ |
212 static struct aouthdr f_ohdr; /* Optional file header (a.out) */ | 83 static struct aouthdr f_ohdr; /* Optional file header (a.out) */ |
213 long bias; /* Bias to add for growth */ | 84 static long bias; /* Bias to add for growth */ |
214 long lnnoptr; /* Pointer to line-number info within file */ | 85 static long lnnoptr; /* Pointer to line-number info within file */ |
215 | 86 |
216 static long text_scnptr; | 87 static long text_scnptr; |
217 static long data_scnptr; | 88 static long data_scnptr; |
218 #ifdef XCOFF | |
219 #define ALIGN(val, pwr) (((val) + ((1L<<(pwr))-1)) & ~((1L<<(pwr))-1)) | 89 #define ALIGN(val, pwr) (((val) + ((1L<<(pwr))-1)) & ~((1L<<(pwr))-1)) |
220 static long load_scnptr; | 90 static long load_scnptr; |
221 static long orig_load_scnptr; | 91 static long orig_load_scnptr; |
222 static long orig_data_scnptr; | 92 static long orig_data_scnptr; |
223 static unrelocate_symbols (int, int, char *, char *); | 93 static int unrelocate_symbols (int, int, char *, char *); |
224 #endif | |
225 static ulong data_st; /* start of data area written out */ | |
226 | 94 |
227 #ifndef MAX_SECTIONS | 95 #ifndef MAX_SECTIONS |
228 #define MAX_SECTIONS 10 | 96 #define MAX_SECTIONS 10 |
229 #endif | 97 #endif |
230 | 98 |
231 static adjust_lnnoptrs (int, int, char *); | 99 static int adjust_lnnoptrs (int, int, char *); |
232 #endif /* COFF */ | |
233 | 100 |
234 static int pagemask; | 101 static int pagemask; |
235 | 102 |
236 /* Correct an int which is the bit pattern of a pointer to a byte | 103 /* Correct an int which is the bit pattern of a pointer to a byte |
237 into an int which is the number of a byte. | 104 into an int which is the number of a byte. |
242 #endif | 109 #endif |
243 | 110 |
244 #ifdef emacs | 111 #ifdef emacs |
245 #include "lisp.h" | 112 #include "lisp.h" |
246 | 113 |
247 static | 114 static void |
248 report_error (char *file, int fd) | 115 report_error (char *file, int fd) |
249 { | 116 { |
250 if (fd) | 117 if (fd) |
251 close (fd); | 118 close (fd); |
252 report_file_error ("Cannot unexec", Fcons (build_string (file), Qnil)); | 119 report_file_error ("Cannot unexec", Fcons (build_string (file), Qnil)); |
255 | 122 |
256 #define ERROR0(msg) report_error_1 (new, msg, 0, 0); return -1 | 123 #define ERROR0(msg) report_error_1 (new, msg, 0, 0); return -1 |
257 #define ERROR1(msg,x) report_error_1 (new, msg, x, 0); return -1 | 124 #define ERROR1(msg,x) report_error_1 (new, msg, x, 0); return -1 |
258 #define ERROR2(msg,x,y) report_error_1 (new, msg, x, y); return -1 | 125 #define ERROR2(msg,x,y) report_error_1 (new, msg, x, y); return -1 |
259 | 126 |
260 static | 127 static void |
261 report_error_1 (int fd, char *msg, int a1, int a2) | 128 report_error_1 (int fd, char *msg, int a1, int a2) |
262 { | 129 { |
263 close (fd); | 130 close (fd); |
264 #ifdef emacs | 131 #ifdef emacs |
265 error (msg, a1, a2); | 132 error (msg, a1, a2); |
271 | 138 |
272 static int make_hdr (int, int, unsigned, unsigned, unsigned, char *, char *); | 139 static int make_hdr (int, int, unsigned, unsigned, unsigned, char *, char *); |
273 static void mark_x (char *); | 140 static void mark_x (char *); |
274 static int copy_text_and_data (int); | 141 static int copy_text_and_data (int); |
275 static int copy_sym (int, int, char *, char *); | 142 static int copy_sym (int, int, char *, char *); |
276 static write_segment (int, char *, char *); | 143 static void write_segment (int, char *, char *); |
277 | 144 |
278 /* **************************************************************** | 145 /* **************************************************************** |
279 * unexec | 146 * unexec |
280 * | 147 * |
281 * driving logic. | 148 * driving logic. |
282 */ | 149 */ |
283 int unexec (char *new_name, char *a_name, | 150 int unexec (char *new_name, char *a_name, |
284 uintptr_t data_start, | 151 uintptr_t data_start, |
285 uintptr_t bss_start, | 152 uintptr_t bss_start, |
286 uintptr_t entry_address) | 153 uintptr_t entry_address) |
287 { | 154 { |
288 int new, a_out = -1; | 155 int new = -1, a_out = -1; |
289 | 156 |
290 if (a_name && (a_out = open (a_name, 0)) < 0) | 157 if (a_name && (a_out = open (a_name, 0)) < 0) |
291 { | 158 { |
292 PERROR (a_name); | 159 PERROR (a_name); |
293 } | 160 } |
294 if ((new = creat (new_name, 0666)) < 0) | 161 if ((new = creat (new_name, 0666)) < 0) |
295 { | 162 { |
296 PERROR (new_name); | 163 PERROR (new_name); |
297 } | 164 } |
298 if (make_hdr (new,a_out,data_start,bss_start,entry_address,a_name,new_name) < 0 | 165 if (make_hdr (new, a_out, |
166 data_start, bss_start, | |
167 entry_address, | |
168 a_name, new_name) < 0 | |
299 || copy_text_and_data (new) < 0 | 169 || copy_text_and_data (new) < 0 |
300 || copy_sym (new, a_out, a_name, new_name) < 0 | 170 || copy_sym (new, a_out, a_name, new_name) < 0 |
301 #ifdef COFF | |
302 || adjust_lnnoptrs (new, a_out, new_name) < 0 | 171 || adjust_lnnoptrs (new, a_out, new_name) < 0 |
303 #endif | 172 || unrelocate_symbols (new, a_out, a_name, new_name) < 0) |
304 #ifdef XCOFF | |
305 || unrelocate_symbols (new, a_out, a_name, new_name) < 0 | |
306 #endif | |
307 ) | |
308 { | 173 { |
309 close (new); | 174 close (new); |
310 /* unlink (new_name); */ /* Failed, unlink new a.out */ | |
311 return -1; | 175 return -1; |
312 } | 176 } |
313 | 177 |
314 close (new); | 178 close (new); |
315 if (a_out >= 0) | 179 if (a_out >= 0) |
323 * | 187 * |
324 * Make the header in the new a.out from the header in core. | 188 * Make the header in the new a.out from the header in core. |
325 * Modify the text and data sizes. | 189 * Modify the text and data sizes. |
326 */ | 190 */ |
327 static int | 191 static int |
328 make_hdr (int new, int a_out, unsigned data_start, unsigned bss_start, unsigned entry_address, char *a_name, char *new_name) | 192 make_hdr (int new, int a_out, |
193 unsigned data_start, unsigned bss_start, | |
194 unsigned entry_address, | |
195 char *a_name, char *new_name) | |
329 { | 196 { |
330 int scns; | 197 int scns; |
331 unsigned int bss_end; | 198 unsigned int bss_end; |
332 | 199 |
333 struct scnhdr section[MAX_SECTIONS]; | 200 struct scnhdr section[MAX_SECTIONS]; |
341 | 208 |
342 load_scnptr = orig_load_scnptr = lnnoptr = 0; | 209 load_scnptr = orig_load_scnptr = lnnoptr = 0; |
343 pagemask = getpagesize () - 1; | 210 pagemask = getpagesize () - 1; |
344 | 211 |
345 /* Adjust text/data boundary. */ | 212 /* Adjust text/data boundary. */ |
346 #ifdef NO_REMAP | |
347 data_start = (long) start_of_data (); | 213 data_start = (long) start_of_data (); |
348 #endif /* NO_REMAP */ | |
349 data_start = ADDR_CORRECT (data_start); | 214 data_start = ADDR_CORRECT (data_start); |
350 | 215 |
351 #ifdef SEGMENT_MASK | |
352 data_start = data_start & ~SEGMENT_MASK; /* (Down) to segment boundary. */ | |
353 #else | |
354 data_start = data_start & ~pagemask; /* (Down) to page boundary. */ | 216 data_start = data_start & ~pagemask; /* (Down) to page boundary. */ |
355 #endif | |
356 | |
357 | 217 |
358 bss_end = ADDR_CORRECT (sbrk (0)) + pagemask; | 218 bss_end = ADDR_CORRECT (sbrk (0)) + pagemask; |
359 bss_end &= ~ pagemask; | 219 bss_end &= ~ pagemask; |
360 /* Adjust data/bss boundary. */ | 220 /* Adjust data/bss boundary. */ |
361 if (bss_start != 0) | 221 if (bss_start != 0) |
376 { | 236 { |
377 ERROR2 ("unexec: data_start (%u) can't be greater than bss_start (%u)", | 237 ERROR2 ("unexec: data_start (%u) can't be greater than bss_start (%u)", |
378 data_start, bss_start); | 238 data_start, bss_start); |
379 } | 239 } |
380 | 240 |
381 #ifdef COFF | |
382 /* Salvage as much info from the existing file as possible */ | 241 /* Salvage as much info from the existing file as possible */ |
383 f_thdr = NULL; f_dhdr = NULL; f_bhdr = NULL; | 242 f_thdr = NULL; f_dhdr = NULL; f_bhdr = NULL; |
384 f_lhdr = NULL; f_tchdr = NULL; f_dbhdr = NULL; f_xhdr = NULL; | 243 f_lhdr = NULL; f_tchdr = NULL; f_dbhdr = NULL; f_xhdr = NULL; |
385 if (a_out >= 0) | 244 if (a_out >= 0) |
386 { | 245 { |
453 | 312 |
454 /* Indicate that the reloc information is no longer valid for ld (bind); | 313 /* Indicate that the reloc information is no longer valid for ld (bind); |
455 we only update it enough to fake out the exec-time loader. */ | 314 we only update it enough to fake out the exec-time loader. */ |
456 f_hdr.f_flags |= (F_RELFLG | F_EXEC); | 315 f_hdr.f_flags |= (F_RELFLG | F_EXEC); |
457 | 316 |
458 #ifdef EXEC_MAGIC | 317 f_ohdr.dsize = bss_start - f_ohdr.data_start; |
459 f_ohdr.magic = EXEC_MAGIC; | |
460 #endif | |
461 #ifndef NO_REMAP | |
462 f_ohdr.tsize = data_start - f_ohdr.text_start; | |
463 f_ohdr.text_start = (long) start_of_text (); | |
464 #endif | |
465 data_st = f_ohdr.data_start ? f_ohdr.data_start : (ulong) &_data; | |
466 f_ohdr.dsize = bss_start - data_st; | |
467 f_ohdr.bsize = bss_end - bss_start; | 318 f_ohdr.bsize = bss_end - bss_start; |
468 | 319 |
469 f_dhdr->s_size = f_ohdr.dsize; | 320 f_dhdr->s_size = f_ohdr.dsize; |
470 f_bhdr->s_size = f_ohdr.bsize; | 321 f_bhdr->s_size = f_ohdr.bsize; |
471 f_bhdr->s_paddr = f_ohdr.data_start + f_ohdr.dsize; | 322 f_bhdr->s_paddr = f_ohdr.data_start + f_ohdr.dsize; |
473 | 324 |
474 /* fix scnptr's */ | 325 /* fix scnptr's */ |
475 { | 326 { |
476 ulong ptr = section[0].s_scnptr; | 327 ulong ptr = section[0].s_scnptr; |
477 | 328 |
478 bias = -1; | |
479 for (scns = 0; scns < f_hdr.f_nscns; scns++) | 329 for (scns = 0; scns < f_hdr.f_nscns; scns++) |
480 { | 330 { |
481 struct scnhdr *s = §ion[scns]; | 331 struct scnhdr *s = §ion[scns]; |
482 | 332 |
483 if (s->s_flags & STYP_PAD) /* .pad sections omitted in AIX 4.1 */ | 333 if (s->s_flags & STYP_PAD) /* .pad sections omitted in AIX 4.1 */ |
492 if (s->s_size == 512) | 342 if (s->s_size == 512) |
493 s->s_size = 0; | 343 s->s_size = 0; |
494 } | 344 } |
495 s->s_scnptr = ptr; | 345 s->s_scnptr = ptr; |
496 } | 346 } |
497 else if (s->s_flags & STYP_DATA) | 347 else |
498 s->s_scnptr = ptr; | |
499 else if (!(s->s_flags & (STYP_TEXT | STYP_BSS))) | |
500 { | 348 { |
501 if (bias == -1) /* if first section after bss */ | |
502 bias = ptr - s->s_scnptr; | 349 bias = ptr - s->s_scnptr; |
503 | 350 s->s_scnptr = ptr; |
504 s->s_scnptr += bias; | |
505 ptr = s->s_scnptr; | |
506 } | 351 } |
507 | 352 |
508 ptr = ptr + s->s_size; | 353 ptr = ptr + s->s_size; |
509 } | 354 } |
510 } | 355 } |
511 | 356 |
512 /* fix other pointers */ | 357 /* fix other pointers */ |
531 } | 376 } |
532 | 377 |
533 text_scnptr = f_thdr->s_scnptr; | 378 text_scnptr = f_thdr->s_scnptr; |
534 data_scnptr = f_dhdr->s_scnptr; | 379 data_scnptr = f_dhdr->s_scnptr; |
535 load_scnptr = f_lhdr ? f_lhdr->s_scnptr : 0; | 380 load_scnptr = f_lhdr ? f_lhdr->s_scnptr : 0; |
536 | |
537 #ifdef ADJUST_EXEC_HEADER | |
538 ADJUST_EXEC_HEADER | |
539 #endif /* ADJUST_EXEC_HEADER */ | |
540 | 381 |
541 if (write (new, &f_hdr, sizeof (f_hdr)) != sizeof (f_hdr)) | 382 if (write (new, &f_hdr, sizeof (f_hdr)) != sizeof (f_hdr)) |
542 { | 383 { |
543 PERROR (new_name); | 384 PERROR (new_name); |
544 } | 385 } |
558 PERROR (new_name); | 399 PERROR (new_name); |
559 } | 400 } |
560 } | 401 } |
561 | 402 |
562 return (0); | 403 return (0); |
563 | |
564 #endif /* COFF */ | |
565 } | 404 } |
566 | 405 |
567 /* **************************************************************** | 406 /* **************************************************************** |
568 | 407 |
569 * | 408 * |
573 copy_text_and_data (int new) | 412 copy_text_and_data (int new) |
574 { | 413 { |
575 char *end; | 414 char *end; |
576 char *ptr; | 415 char *ptr; |
577 | 416 |
578 lseek (new, (long) text_scnptr, 0); | 417 lseek (new, (long) text_scnptr, SEEK_SET); |
579 ptr = start_of_text () + text_scnptr; | 418 ptr = start_of_text () + text_scnptr; |
580 end = ptr + f_ohdr.tsize; | 419 end = ptr + f_ohdr.tsize; |
581 write_segment (new, ptr, end); | 420 write_segment (new, ptr, end); |
582 | 421 |
583 lseek (new, (long) data_scnptr, 0); | 422 lseek (new, (long) data_scnptr, SEEK_SET); |
584 ptr = (char *) data_st; | 423 ptr = (char *) f_ohdr.data_start; |
585 end = ptr + f_ohdr.dsize; | 424 end = ptr + f_ohdr.dsize; |
586 write_segment (new, ptr, end); | 425 write_segment (new, ptr, end); |
587 | 426 |
588 return 0; | 427 return 0; |
589 } | 428 } |
590 | 429 |
591 #define UnexBlockSz (1<<12) /* read/write block size */ | 430 #define UnexBlockSz (1<<12) /* read/write block size */ |
431 static void | |
592 write_segment (int new, char *ptr, char *end) | 432 write_segment (int new, char *ptr, char *end) |
593 { | 433 { |
594 int i, nwrite, ret; | 434 int i, nwrite, ret; |
595 char buf[80]; | 435 char buf[80]; |
596 extern int errno; | 436 extern int errno; |
640 | 480 |
641 if (orig_load_scnptr == 0L) | 481 if (orig_load_scnptr == 0L) |
642 return 0; | 482 return 0; |
643 | 483 |
644 if (lnnoptr && lnnoptr < orig_load_scnptr) /* if there is line number info */ | 484 if (lnnoptr && lnnoptr < orig_load_scnptr) /* if there is line number info */ |
645 lseek (a_out, lnnoptr, 0); /* start copying from there */ | 485 lseek (a_out, lnnoptr, SEEK_SET); /* start copying from there */ |
646 else | 486 else |
647 lseek (a_out, orig_load_scnptr, 0); /* Position a.out to symtab. */ | 487 lseek (a_out, orig_load_scnptr, SEEK_SET); /* Position a.out to symtab. */ |
648 | 488 |
649 while ((n = read (a_out, page, sizeof page)) > 0) | 489 while ((n = read (a_out, page, sizeof page)) > 0) |
650 { | 490 { |
651 if (write (new, page, n) != n) | 491 if (write (new, page, n) != n) |
652 { | 492 { |
681 sbuf.st_mode |= 0111 & ~um; | 521 sbuf.st_mode |= 0111 & ~um; |
682 if (chmod (name, sbuf.st_mode) == -1) | 522 if (chmod (name, sbuf.st_mode) == -1) |
683 PERROR (name); | 523 PERROR (name); |
684 } | 524 } |
685 | 525 |
686 /* | 526 static int |
687 * If the COFF file contains a symbol table and a line number section, | |
688 * then any auxiliary entries that have values for x_lnnoptr must | |
689 * be adjusted by the amount that the line number section has moved | |
690 * in the file (bias computed in make_hdr). The #@$%&* designers of | |
691 * the auxiliary entry structures used the absolute file offsets for | |
692 * the line number entry rather than an offset from the start of the | |
693 * line number section! | |
694 * | |
695 * When I figure out how to scan through the symbol table and pick out | |
696 * the auxiliary entries that need adjustment, this routine will | |
697 * be fixed. As it is now, all such entries are wrong and sdb | |
698 * will complain. Fred Fish, UniSoft Systems Inc. | |
699 * | |
700 * I believe this is now fixed correctly. Bill Mann | |
701 */ | |
702 | |
703 #ifdef COFF | |
704 | |
705 /* This function is probably very slow. Instead of reopening the new | |
706 file for input and output it should copy from the old to the new | |
707 using the two descriptors already open (WRITEDESC and READDESC). | |
708 Instead of reading one small structure at a time it should use | |
709 a reasonable size buffer. But I don't have time to work on such | |
710 things, so I am installing it as submitted to me. -- RMS. */ | |
711 | |
712 adjust_lnnoptrs (int writedesc, int readdesc, char *new_name) | 527 adjust_lnnoptrs (int writedesc, int readdesc, char *new_name) |
713 { | 528 { |
714 int nsyms; | 529 int nsyms; |
715 int naux; | 530 int naux; |
716 int new; | 531 int new; |
717 #ifdef amdahl_uts | |
718 SYMENT symentry; | |
719 AUXENT auxentry; | |
720 #else | |
721 struct syment symentry; | 532 struct syment symentry; |
722 union auxent auxentry; | 533 union auxent auxentry; |
723 #endif | |
724 | 534 |
725 if (!lnnoptr || !f_hdr.f_symptr) | 535 if (!lnnoptr || !f_hdr.f_symptr) |
726 return 0; | 536 return 0; |
727 | 537 |
728 if ((new = open (new_name, 2)) < 0) | 538 if ((new = open (new_name, 2)) < 0) |
729 { | 539 { |
730 PERROR (new_name); | 540 PERROR (new_name); |
731 return -1; | 541 return -1; |
732 } | 542 } |
733 | 543 |
734 lseek (new, f_hdr.f_symptr, 0); | 544 lseek (new, f_hdr.f_symptr, SEEK_SET); |
735 for (nsyms = 0; nsyms < f_hdr.f_nsyms; nsyms++) | 545 for (nsyms = 0; nsyms < f_hdr.f_nsyms; nsyms++) |
736 { | 546 { |
737 read (new, &symentry, SYMESZ); | 547 read (new, &symentry, SYMESZ); |
738 if (symentry.n_sclass == C_BINCL || symentry.n_sclass == C_EINCL) | 548 if (symentry.n_sclass == C_BINCL || symentry.n_sclass == C_EINCL) |
739 { | 549 { |
740 symentry.n_value += bias; | 550 symentry.n_value += bias; |
741 lseek (new, -SYMESZ, 1); | 551 lseek (new, -SYMESZ, SEEK_CUR); |
742 write (new, &symentry, SYMESZ); | 552 write (new, &symentry, SYMESZ); |
743 } | 553 } |
744 | 554 |
745 for (naux = symentry.n_numaux; naux-- != 0; ) | 555 for (naux = symentry.n_numaux; naux-- != 0; ) |
746 { | 556 { |
748 nsyms++; | 558 nsyms++; |
749 if (naux != 0 /* skip csect auxentry (last entry) */ | 559 if (naux != 0 /* skip csect auxentry (last entry) */ |
750 && (symentry.n_sclass == C_EXT || symentry.n_sclass == C_HIDEXT)) | 560 && (symentry.n_sclass == C_EXT || symentry.n_sclass == C_HIDEXT)) |
751 { | 561 { |
752 auxentry.x_sym.x_fcnary.x_fcn.x_lnnoptr += bias; | 562 auxentry.x_sym.x_fcnary.x_fcn.x_lnnoptr += bias; |
753 lseek (new, -AUXESZ, 1); | 563 lseek (new, -AUXESZ, SEEK_CUR); |
754 write (new, &auxentry, AUXESZ); | 564 write (new, &auxentry, AUXESZ); |
755 } | 565 } |
756 } | 566 } |
757 } | 567 } |
758 close (new); | 568 close (new); |
759 } | 569 |
760 | 570 return 0; |
761 #endif /* COFF */ | 571 } |
762 | 572 |
763 #ifdef XCOFF | 573 static int |
764 | |
765 /* It is probably a false economy to optimise this routine (it used to | |
766 read one LDREL and do do two lseeks per iteration) but the wrath of | |
767 RMS (see above :-) would be too much to bear */ | |
768 | |
769 unrelocate_symbols (int new, int a_out, char *a_name, char *new_name) | 574 unrelocate_symbols (int new, int a_out, char *a_name, char *new_name) |
770 { | 575 { |
771 int i; | 576 int i; |
772 int l; | |
773 LDREL *ldrel; | |
774 LDHDR ldhdr; | 577 LDHDR ldhdr; |
775 LDREL ldrel_buf [20]; | 578 LDREL ldrel; |
776 ulong t_reloc = (ulong) &_text - f_ohdr.text_start; | 579 ulong t_reloc = (ulong) &_text - f_ohdr.text_start; |
580 #ifndef ALIGN_DATA_RELOC | |
581 ulong d_reloc = (ulong) &_data - f_ohdr.data_start; | |
582 #else | |
583 /* This worked (and was needed) before AIX 4.2. | |
584 I have no idea why. -- Mike */ | |
777 ulong d_reloc = (ulong) &_data - ALIGN(f_ohdr.data_start, 2); | 585 ulong d_reloc = (ulong) &_data - ALIGN(f_ohdr.data_start, 2); |
586 #endif | |
778 int * p; | 587 int * p; |
779 | 588 |
780 if (load_scnptr == 0) | 589 if (load_scnptr == 0) |
781 return 0; | 590 return 0; |
782 | 591 |
783 lseek (a_out, orig_load_scnptr, 0); | 592 lseek (a_out, orig_load_scnptr, SEEK_SET); |
784 if (read (a_out, &ldhdr, sizeof (ldhdr)) != sizeof (ldhdr)) | 593 if (read (a_out, &ldhdr, sizeof (ldhdr)) != sizeof (ldhdr)) |
785 { | 594 { |
786 PERROR (new_name); | 595 PERROR (new_name); |
787 } | 596 } |
788 | 597 |
789 #define SYMNDX_TEXT 0 | 598 #define SYMNDX_TEXT 0 |
790 #define SYMNDX_DATA 1 | 599 #define SYMNDX_DATA 1 |
791 #define SYMNDX_BSS 2 | 600 #define SYMNDX_BSS 2 |
792 l = 0; | 601 |
793 for (i = 0; i < ldhdr.l_nreloc; i++, l--, ldrel++) | 602 for (i = 0; i < ldhdr.l_nreloc; i++) |
794 { | 603 { |
795 if (l == 0) { | 604 lseek (a_out, |
796 lseek (a_out, | 605 orig_load_scnptr + LDHDRSZ + LDSYMSZ*ldhdr.l_nsyms + LDRELSZ*i, |
797 orig_load_scnptr + LDHDRSZ + LDSYMSZ*ldhdr.l_nsyms + LDRELSZ*i, | 606 SEEK_SET); |
798 0); | 607 |
799 | 608 if (read (a_out, &ldrel, LDRELSZ) != LDRELSZ) |
800 l = ldhdr.l_nreloc - i; | 609 { |
801 if (l > sizeof (ldrel_buf) / LDRELSZ) | 610 PERROR (a_name); |
802 l = sizeof (ldrel_buf) / LDRELSZ; | 611 } |
803 | |
804 if (read (a_out, ldrel_buf, l * LDRELSZ) != l * LDRELSZ) | |
805 { | |
806 PERROR (a_name); | |
807 } | |
808 ldrel = ldrel_buf; | |
809 } | |
810 | 612 |
811 /* move the BSS loader symbols to the DATA segment */ | 613 /* move the BSS loader symbols to the DATA segment */ |
812 if (ldrel->l_symndx == SYMNDX_BSS) | 614 if (ldrel.l_symndx == SYMNDX_BSS) |
813 { | 615 { |
814 ldrel->l_symndx = SYMNDX_DATA; | 616 ldrel.l_symndx = SYMNDX_DATA; |
815 | 617 |
816 lseek (new, | 618 lseek (new, |
817 load_scnptr + LDHDRSZ + LDSYMSZ*ldhdr.l_nsyms + LDRELSZ*i, | 619 load_scnptr + LDHDRSZ + LDSYMSZ*ldhdr.l_nsyms + LDRELSZ*i, |
818 0); | 620 SEEK_SET); |
819 | 621 |
820 if (write (new, ldrel, LDRELSZ) != LDRELSZ) | 622 if (write (new, &ldrel, LDRELSZ) != LDRELSZ) |
821 { | 623 { |
822 PERROR (new_name); | 624 PERROR (new_name); |
823 } | 625 } |
824 } | 626 } |
825 | 627 |
826 if (ldrel->l_rsecnm == f_ohdr.o_sndata) | 628 if (ldrel.l_rsecnm == f_ohdr.o_sndata) |
827 { | 629 { |
828 int orig_int; | 630 int orig_int; |
829 | 631 |
830 lseek (a_out, | 632 lseek (a_out, |
831 orig_data_scnptr + (ldrel->l_vaddr - f_ohdr.data_start), 0); | 633 orig_data_scnptr + (ldrel.l_vaddr - f_ohdr.data_start), |
634 SEEK_SET); | |
832 | 635 |
833 if (read (a_out, (void *) &orig_int, sizeof (orig_int)) | 636 if (read (a_out, (void *) &orig_int, sizeof (orig_int)) |
834 != sizeof (orig_int)) | 637 != sizeof (orig_int)) |
835 { | 638 { |
836 PERROR (a_name); | 639 PERROR (a_name); |
837 } | 640 } |
838 | 641 |
839 p = (int *) (ldrel->l_vaddr + d_reloc); | 642 p = (int *) (ldrel.l_vaddr + d_reloc); |
840 | 643 |
841 switch (ldrel->l_symndx) { | 644 switch (ldrel.l_symndx) { |
842 case SYMNDX_TEXT: | 645 case SYMNDX_TEXT: |
843 orig_int = * p - t_reloc; | 646 orig_int = * p - t_reloc; |
844 break; | 647 break; |
845 | 648 |
846 case SYMNDX_DATA: | 649 case SYMNDX_DATA: |
850 } | 653 } |
851 | 654 |
852 if (orig_int != * p) | 655 if (orig_int != * p) |
853 { | 656 { |
854 lseek (new, | 657 lseek (new, |
855 data_scnptr + (ldrel->l_vaddr - f_ohdr.data_start), 0); | 658 data_scnptr + (ldrel.l_vaddr - f_ohdr.data_start), |
659 SEEK_SET); | |
856 if (write (new, (void *) &orig_int, sizeof (orig_int)) | 660 if (write (new, (void *) &orig_int, sizeof (orig_int)) |
857 != sizeof (orig_int)) | 661 != sizeof (orig_int)) |
858 { | 662 { |
859 PERROR (new_name); | 663 PERROR (new_name); |
860 } | 664 } |
861 } | 665 } |
862 } | 666 } |
863 } | 667 } |
864 } | 668 return 0; |
865 #endif /* XCOFF */ | 669 } |