comparison src/unexaix.c @ 25564:d0383ec2061e

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