aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDave Love1999-09-06 16:01:15 +0000
committerDave Love1999-09-06 16:01:15 +0000
commit0248680a42f0220d3b6a94c4c9a17253760abe37 (patch)
tree1afff8e9ad5565dbb0e7f88c9a9c4e4d19f1cea6 /src
parentcace3098578cb4fb955c99ff7c114811b00b113c (diff)
downloademacs-0248680a42f0220d3b6a94c4c9a17253760abe37.tar.gz
emacs-0248680a42f0220d3b6a94c4c9a17253760abe37.zip
New version incorporating Michael Sperber's changes from XEmacs.
Should solve problems on AIX 4.3.
Diffstat (limited to 'src')
-rw-r--r--src/unexaix.c420
1 files changed, 108 insertions, 312 deletions
diff --git a/src/unexaix.c b/src/unexaix.c
index 1243b650865..787af5ac9b2 100644
--- a/src/unexaix.c
+++ b/src/unexaix.c
@@ -1,6 +1,5 @@
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
5This file is part of GNU Emacs. 4This file is part of GNU Emacs.
6 5
@@ -24,22 +23,12 @@ You are forbidden to forbid anyone else to use, share and improve
24what you give them. Help stamp out software-hoarding! */ 23what 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.
29 *
30 * Author: Spencer W. Thomas
31 * Computer Science Dept.
32 * University of Utah
33 * Date: Tue Mar 2 1982
34 * Modified heavily since then.
35 * 27 *
36 * Updated for AIX 4.1.3 by Bill_Mann @ PraxisInt.com, Feb 1996 28 * Subsequently hacked on by
37 * As of AIX 4.1, text, data, and bss are pre-relocated by the binder in 29 * Bill Mann <Bill_Man@praxisint.com>
38 * such a way that the file can be mapped with code in one segment and 30 * Andrew Vignaux <Andrew.Vignaux@comp.vuw.ac.nz>
39 * data/bss in another segment, without reading or copying the file, by 31 * Mike Sperber <sperber@informatik.uni-tuebingen.de>
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)
@@ -51,123 +40,17 @@ what you give them. Help stamp out software-hoarding! */
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.
56 *
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 * 44 *
64 * Specifying zero for data_start means the boundary between text and data 45 * bss_start indicates how much of the data segment is to be saved in the
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 53
83/* There are several compilation parameters affecting unexec:
84
85* COFF
86
87Define this if your system uses COFF for executables.
88Otherwise we assume you use Berkeley format.
89
90* NO_REMAP
91
92Define this if you do not want to try to save Emacs's pure data areas
93as part of the text segment.
94
95Saving them as text is good because it allows users to share more.
96
97However, on machines that locate the text area far from the data area,
98the boundary cannot feasibly be moved. Such machines require
99NO_REMAP.
100
101Also, remapping can cause trouble with the built-in startup routine
102/lib/crt0.o, which defines `environ' as an initialized variable.
103Dumping `environ' as pure does not work! So, to use remapping,
104you must write a startup routine for your machine in Emacs's crt0.c.
105If NO_REMAP is defined, Emacs uses the system's crt0.o.
106
107* SECTION_ALIGNMENT
108
109Some machines that use COFF executables require that each section
110start on a certain boundary *in the COFF file*. Such machines should
111define SECTION_ALIGNMENT to a mask of the low-order bits that must be
112zero on such a boundary. This mask is used to control padding between
113segments in the COFF file.
114
115If SECTION_ALIGNMENT is not defined, the segments are written
116consecutively with no attempt at alignment. This is right for
117unmodified system V.
118
119* SEGMENT_MASK
120
121Some machines require that the beginnings and ends of segments
122*in core* be on certain boundaries. For most machines, a page
123boundary is sufficient. That is the default. When a larger
124boundary is needed, define SEGMENT_MASK to a mask of
125the bits that must be zero on such a boundary.
126
127* A_TEXT_OFFSET(HDR)
128
129Some machines count the a.out header as part of the size of the text
130segment (a_text); they may actually load the header into core as the
131first data in the text segment. Some have additional padding between
132the header and the real text of the program that is counted in a_text.
133
134For these machines, define A_TEXT_OFFSET(HDR) to examine the header
135structure HDR and return the number of bytes to add to `a_text'
136before writing it (above and beyond the number of bytes of actual
137program text). HDR's standard fields are already correct, except that
138this adjustment to the `a_text' field has not yet been made;
139thus, the amount of offset can depend on the data in the file.
140
141* A_TEXT_SEEK(HDR)
142
143If defined, this macro specifies the number of bytes to seek into the
144a.out file before starting to write the text segment.a
145
146* EXEC_MAGIC
147
148For machines using COFF, this macro, if defined, is a value stored
149into the magic number field of the output file.
150
151* ADJUST_EXEC_HEADER
152
153This macro can be used to generate statements to adjust or
154initialize nonstandard fields in the file header
155
156* ADDR_CORRECT(ADDR)
157
158Macro to correct an int which is the bit pattern of a pointer to a byte
159into an int which is the number of a byte.
160
161This macro has a default definition which is usually right.
162This default definition is a no-op on most machines (where a
163pointer looks like an int) but not on all machines.
164
165*/
166
167#define XCOFF
168#define COFF
169#define NO_REMAP
170
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
@@ -181,56 +64,42 @@ pointer looks like an int) but not on all machines.
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>
71#include <unistd.h>
72#include <fcntl.h>
190 73
191extern char *start_of_text (); /* Start of text */ 74extern char *start_of_text (void); /* Start of text */
192extern char *start_of_data (); /* Start of initialized data */ 75extern char *start_of_data (void); /* Start of initialized data */
193 76
194extern int _data; 77extern int _data;
195extern int _edata;
196extern int _text; 78extern int _text;
197extern int _etext; 79
198extern 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 */
214static struct filehdr f_hdr; /* File header */ 85static struct filehdr f_hdr; /* File header */
215static struct aouthdr f_ohdr; /* Optional file header (a.out) */ 86static struct aouthdr f_ohdr; /* Optional file header (a.out) */
216long bias; /* Bias to add for growth */ 87static long bias; /* Bias to add for growth */
217long lnnoptr; /* Pointer to line-number info within file */ 88static long lnnoptr; /* Pointer to line-number info within file */
218 89
219static long text_scnptr; 90static long text_scnptr;
220static long data_scnptr; 91static 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))
223static long load_scnptr; 93static long load_scnptr;
224static long orig_load_scnptr; 94static long orig_load_scnptr;
225static long orig_data_scnptr; 95static long orig_data_scnptr;
226#endif 96static int unrelocate_symbols (int, int, char *, char *);
227static 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 */ 102static int adjust_lnnoptrs (int, int, char *);
234 103
235static int pagemask; 104static int pagemask;
236 105
@@ -245,10 +114,8 @@ static int pagemask;
245#ifdef emacs 114#ifdef emacs
246#include "lisp.h" 115#include "lisp.h"
247 116
248static 117static void
249report_error (file, fd) 118report_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);
@@ -260,11 +127,8 @@ report_error (file, fd)
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
263static 130static void
264report_error_1 (fd, msg, a1, a2) 131report_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
@@ -275,23 +139,25 @@ report_error_1 (fd, msg, a1, a2)
275#endif 139#endif
276} 140}
277 141
278static int make_hdr (); 142static int make_hdr (int, int, unsigned, unsigned, unsigned, char *, char *);
279static void mark_x (); 143static void mark_x (char *);
280static int copy_text_and_data (); 144static int copy_text_and_data (int);
281static int copy_sym (); 145static int copy_sym (int, int, char *, char *);
146static void write_segment (int, char *, char *);
282 147
283/* **************************************************************** 148/* ****************************************************************
284 * unexec 149 * unexec
285 * 150 *
286 * driving logic. 151 * driving logic.
287 */ 152 */
288unexec (new_name, a_name, data_start, bss_start, entry_address) 153int 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,
156 uintptr_t entry_address)
291{ 157{
292 int new, a_out = -1; 158 int new = -1, a_out = -1;
293 159
294 if (a_name && (a_out = open (a_name, 0)) < 0) 160 if (a_name && (a_out = open (a_name, O_RDONLY)) < 0)
295 { 161 {
296 PERROR (a_name); 162 PERROR (a_name);
297 } 163 }
@@ -299,16 +165,14 @@ unexec (new_name, a_name, data_start, bss_start, entry_address)
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;
@@ -328,13 +192,12 @@ unexec (new_name, a_name, data_start, bss_start, entry_address)
328 * Modify the text and data sizes. 192 * Modify the text and data sizes.
329 */ 193 */
330static int 194static int
331make_hdr (new, a_out, data_start, bss_start, entry_address, a_name, new_name) 195make_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;
336{ 199{
337 register int scns; 200 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];
@@ -350,17 +213,10 @@ make_hdr (new, a_out, data_start, bss_start, entry_address, a_name, new_name)
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;
@@ -385,7 +241,6 @@ make_hdr (new, a_out, data_start, bss_start, entry_address, a_name, new_name)
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;
@@ -437,15 +292,15 @@ make_hdr (new, a_out, data_start, bss_start, entry_address, a_name, new_name)
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
@@ -462,15 +317,7 @@ make_hdr (new, a_out, data_start, bss_start, entry_address, a_name, new_name)
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;
@@ -541,10 +388,6 @@ make_hdr (new, a_out, data_start, bss_start, entry_address, a_name, new_name)
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);
@@ -567,8 +410,6 @@ make_hdr (new, a_out, data_start, bss_start, entry_address, a_name, new_name)
567 } 410 }
568 411
569 return (0); 412 return (0);
570
571#endif /* COFF */
572} 413}
573 414
574/* **************************************************************** 415/* ****************************************************************
@@ -577,19 +418,18 @@ make_hdr (new, a_out, data_start, bss_start, entry_address, a_name, new_name)
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 */
579static int 420static int
580copy_text_and_data (new) 421copy_text_and_data (int new)
581 int new;
582{ 422{
583 register char *end; 423 char *end;
584 register char *ptr; 424 char *ptr;
585 425
586 lseek (new, (long) text_scnptr, 0); 426 lseek (new, (long) text_scnptr, SEEK_SET);
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
@@ -597,11 +437,10 @@ copy_text_and_data (new)
597} 437}
598 438
599#define UnexBlockSz (1<<12) /* read/write block size */ 439#define UnexBlockSz (1<<12) /* read/write block size */
600write_segment (new, ptr, end) 440static void
601 int new; 441write_segment (int new, char *ptr, char *end)
602 register char *ptr, *end;
603{ 442{
604 register int i, nwrite, ret; 443 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];
@@ -619,7 +458,7 @@ write_segment (new, ptr, end)
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)
@@ -640,9 +479,7 @@ write_segment (new, ptr, end)
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 */
642static int 481static int
643copy_sym (new, a_out, a_name, new_name) 482copy_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;
@@ -654,9 +491,9 @@ copy_sym (new, a_out, a_name, new_name)
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 {
@@ -678,8 +515,7 @@ copy_sym (new, a_out, a_name, new_name)
678 * After successfully building the new a.out, mark it executable 515 * After successfully building the new a.out, mark it executable
679 */ 516 */
680static void 517static void
681mark_x (name) 518mark_x (char *name)
682 char *name;
683{ 519{
684 struct stat sbuf; 520 struct stat sbuf;
685 int um; 521 int um;
@@ -696,65 +532,32 @@ mark_x (name)
696 PERROR (name); 532 PERROR (name);
697} 533}
698 534
699/* 535static int
700 * If the COFF file contains a symbol table and a line number section, 536adjust_lnnoptrs (int writedesc, int readdesc, char *new_name)
701 * then any auxiliary entries that have values for x_lnnoptr must
702 * be adjusted by the amount that the line number section has moved
703 * in the file (bias computed in make_hdr). The #@$%&* designers of
704 * the auxiliary entry structures used the absolute file offsets for
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
725adjust_lnnoptrs (writedesc, readdesc, new_name)
726 int writedesc;
727 int readdesc;
728 char *new_name;
729{ 537{
730 register int nsyms; 538 int nsyms;
731 register int naux; 539 int naux;
732 register int new; 540 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
@@ -766,39 +569,36 @@ adjust_lnnoptrs (writedesc, readdesc, new_name)
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}
776
777#endif /* COFF */
778 578
779#ifdef XCOFF 579 return 0;
780 580}
781/* It is probably a false economy to optimise this routine (it used to
782 read one LDREL and do do two lseeks per iteration) but the wrath of
783 RMS (see above :-) would be too much to bear */
784 581
785unrelocate_symbols (new, a_out, a_name, new_name) 582static int
786 int new, a_out; 583unrelocate_symbols (int new, int a_out, char *a_name, char *new_name)
787 char *a_name, *new_name;
788{ 584{
789 register int i; 585 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);
@@ -807,55 +607,50 @@ unrelocate_symbols (new, a_out, a_name, new_name)
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;
811 for (i = 0; i < ldhdr.l_nreloc; i++, l--, ldrel++)
812 {
813 if (l == 0) {
814 lseek (a_out,
815 orig_load_scnptr + LDHDRSZ + LDSYMSZ*ldhdr.l_nsyms + LDRELSZ*i,
816 0);
817 610
818 l = ldhdr.l_nreloc - i; 611 for (i = 0; i < ldhdr.l_nreloc; i++)
819 if (l > sizeof (ldrel_buf) / LDRELSZ) 612 {
820 l = sizeof (ldrel_buf) / LDRELSZ; 613 lseek (a_out,
614 orig_load_scnptr + LDHDRSZ + LDSYMSZ*ldhdr.l_nsyms + LDRELSZ*i,
615 SEEK_SET);
821 616
822 if (read (a_out, ldrel_buf, l * LDRELSZ) != l * LDRELSZ) 617 if (read (a_out, &ldrel, LDRELSZ) != LDRELSZ)
823 { 618 {
824 PERROR (a_name); 619 PERROR (a_name);
825 } 620 }
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),
643 SEEK_SET);
850 644
851 if (read (a_out, (void *) &orig_int, sizeof (orig_int)) != sizeof (orig_int)) 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;
@@ -869,7 +664,8 @@ unrelocate_symbols (new, a_out, a_name, new_name)
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 {
@@ -878,5 +674,5 @@ unrelocate_symbols (new, a_out, a_name, new_name)
878 } 674 }
879 } 675 }
880 } 676 }
677 return 0;
881} 678}
882#endif /* XCOFF */