diff options
| author | Dave Love | 1999-09-06 16:01:15 +0000 |
|---|---|---|
| committer | Dave Love | 1999-09-06 16:01:15 +0000 |
| commit | 0248680a42f0220d3b6a94c4c9a17253760abe37 (patch) | |
| tree | 1afff8e9ad5565dbb0e7f88c9a9c4e4d19f1cea6 /src | |
| parent | cace3098578cb4fb955c99ff7c114811b00b113c (diff) | |
| download | emacs-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.c | 420 |
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 | ||
| 5 | This file is part of GNU Emacs. | 4 | This file is part of GNU Emacs. |
| 6 | 5 | ||
| @@ -24,22 +23,12 @@ 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. | ||
| 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 | |||
| 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 | |||
| 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 | ||
| 191 | extern char *start_of_text (); /* Start of text */ | 74 | extern char *start_of_text (void); /* Start of text */ |
| 192 | extern char *start_of_data (); /* Start of initialized data */ | 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 | ||
| @@ -245,10 +114,8 @@ static int pagemask; | |||
| 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); |
| @@ -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 | ||
| 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 |
| @@ -275,23 +139,25 @@ report_error_1 (fd, msg, a1, a2) | |||
| 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, |
| 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 | */ |
| 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; | ||
| 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 | */ |
| 579 | static int | 420 | static int |
| 580 | copy_text_and_data (new) | 421 | copy_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 */ |
| 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; | ||
| 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 | */ |
| 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; |
| @@ -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 | */ |
| 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; |
| @@ -696,65 +532,32 @@ mark_x (name) | |||
| 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 | ||
| 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 | |||
| 725 | adjust_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 | ||
| 785 | unrelocate_symbols (new, a_out, a_name, new_name) | 582 | static int |
| 786 | int new, a_out; | 583 | unrelocate_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 */ | ||