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 = &section[scns]; 331 struct scnhdr *s = &section[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 }