428
+ − 1 /* Copyright (C) 1985, 1986, 1987, 1988, 1992, 1993, 1994
771
+ − 2 /* Copyright (C) 2001 Ben Wing.
428
+ − 3 Free Software Foundation, Inc.
+ − 4
+ − 5 This file is part of XEmacs.
+ − 6
+ − 7 XEmacs is free software; you can redistribute it and/or modify it
+ − 8 under the terms of the GNU General Public License as published by the
+ − 9 Free Software Foundation; either version 2, or (at your option) any
+ − 10 later version.
+ − 11
+ − 12 XEmacs is distributed in the hope that it will be useful, but WITHOUT
+ − 13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ − 14 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ − 15 for more details.
+ − 16
+ − 17 You should have received a copy of the GNU General Public License
+ − 18 along with XEmacs; see the file COPYING. If not, write to
+ − 19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ − 20 Boston, MA 02111-1307, USA. */
+ − 21
+ − 22 /* Synched up with: FSF 19.31. */
+ − 23
+ − 24 /*
+ − 25 * unexec.c - Convert a running program into an a.out file.
+ − 26 *
+ − 27 * Author: Spencer W. Thomas
+ − 28 * Computer Science Dept.
+ − 29 * University of Utah
+ − 30 * Date: Tue Mar 2 1982
+ − 31 * Modified heavily since then.
+ − 32 *
+ − 33 * Synopsis:
+ − 34 * unexec (new_name, a_name, data_start, bss_start, entry_address)
+ − 35 * char *new_name, *a_name;
+ − 36 * unsigned data_start, bss_start, entry_address;
+ − 37 *
+ − 38 * Takes a snapshot of the program and makes an a.out format file in the
+ − 39 * file named by the string argument new_name.
+ − 40 * If a_name is non-NULL, the symbol table will be taken from the given file.
+ − 41 * On some machines, an existing a_name file is required.
+ − 42 *
+ − 43 * The boundaries within the a.out file may be adjusted with the data_start
+ − 44 * and bss_start arguments. Either or both may be given as 0 for defaults.
+ − 45 *
+ − 46 * Data_start gives the boundary between the text segment and the data
+ − 47 * segment of the program. The text segment can contain shared, read-only
+ − 48 * program code and literal data, while the data segment is always unshared
+ − 49 * and unprotected. Data_start gives the lowest unprotected address.
+ − 50 * The value you specify may be rounded down to a suitable boundary
+ − 51 * as required by the machine you are using.
+ − 52 *
+ − 53 * Specifying zero for data_start means the boundary between text and data
+ − 54 * should not be the same as when the program was loaded.
+ − 55 * If NO_REMAP is defined, the argument data_start is ignored and the
+ − 56 * segment boundaries are never changed.
+ − 57 *
+ − 58 * Bss_start indicates how much of the data segment is to be saved in the
+ − 59 * a.out file and restored when the program is executed. It gives the lowest
+ − 60 * unsaved address, and is rounded up to a page boundary. The default when 0
+ − 61 * is given assumes that the entire data segment is to be stored, including
+ − 62 * the previous data and bss as well as any additional storage allocated with
+ − 63 * break (2).
+ − 64 *
+ − 65 * The new file is set up to start at entry_address.
+ − 66 *
+ − 67 * If you make improvements I'd like to get them too.
+ − 68 * harpo!utah-cs!thomas, thomas@Utah-20
+ − 69 *
+ − 70 */
+ − 71
+ − 72 /* Modified to support SysVr3 shared libraries by James Van Artsdalen
+ − 73 * of Dell Computer Corporation. james@bigtex.cactus.org.
+ − 74 */
+ − 75
+ − 76 /* There are several compilation parameters affecting unexec:
+ − 77
+ − 78 * COFF
+ − 79
+ − 80 Define this if your system uses COFF for executables.
+ − 81
+ − 82 * COFF_ENCAPSULATE
+ − 83
+ − 84 Define this if you are using the GNU coff encapsulated a.out format.
+ − 85 This is closer to a.out than COFF. You should *not* define COFF if
+ − 86 you define COFF_ENCAPSULATE
+ − 87
+ − 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.
438
+ − 140
428
+ − 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.
+ − 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 #ifndef emacs
+ − 168 #define PERROR(arg) perror (arg); return -1
+ − 169 #else
+ − 170 #define IN_UNEXEC
+ − 171 #include <config.h>
3025
+ − 172 #define PERROR(file) report_error (file, new_)
428
+ − 173 #endif
+ − 174
+ − 175 #if __STDC__ || defined(STDC_HEADERS)
+ − 176
+ − 177 /* I don't know how correct this attempt to get more prototypes is... */
+ − 178 # if defined(sun) && defined(_POSIX_SOURCE)
+ − 179 # undef _POSIX_SOURCE
+ − 180 # endif
+ − 181
+ − 182 # include <stddef.h>
+ − 183 # include <stdlib.h>
+ − 184 # include <unistd.h>
+ − 185 # include <string.h>
+ − 186 # include <stddef.h>
438
+ − 187 # include <errno.h>
428
+ − 188
+ − 189 #endif
+ − 190
+ − 191 /* I don't understand this, but it's necessary to get some slots in struct exec
+ − 192 from /usr/include/sys/exec.h when running LCC in strict ANSI mode. We don't
+ − 193 need this in K&R mode...
+ − 194 */
+ − 195 #if defined(__lucid) && defined(__sparc) && !defined(sun)
+ − 196 # define sun 1
+ − 197 #endif
+ − 198
+ − 199 #ifdef COFF_ENCAPSULATE
+ − 200 int need_coff_header = 1;
+ − 201 #include <coff-encap/a.out.encap.h> /* The location might be a poor assumption */
+ − 202 #else
+ − 203 #include <a.out.h>
+ − 204 #endif /* not COFF_ENCAPSULATE */
+ − 205
+ − 206 /* Define getpagesize if the system does not.
+ − 207 Note that this may depend on symbols defined in a.out.h. */
+ − 208 #include "getpagesize.h"
+ − 209
+ − 210 #ifndef makedev /* Try to detect types.h already loaded */
+ − 211 #include <sys/types.h>
+ − 212 #endif /* makedev */
+ − 213 #include <stdio.h>
+ − 214 #include <sys/stat.h>
+ − 215 #include <errno.h>
+ − 216
+ − 217 #include <sys/file.h> /* Must be after sys/types.h for USG and BSD4_1*/
+ − 218
+ − 219 #ifdef USG5
+ − 220 #include <fcntl.h>
+ − 221 #endif
+ − 222
2286
+ − 223 #include "compiler.h"
+ − 224
428
+ − 225 #ifndef O_RDONLY
+ − 226 #define O_RDONLY 0
+ − 227 #endif
+ − 228 #ifndef O_RDWR
+ − 229 #define O_RDWR 2
+ − 230 #endif
+ − 231
+ − 232 extern char *start_of_text (); /* Start of text */
+ − 233
+ − 234 extern void *start_of_data (); /* Start of initialized data */
+ − 235
+ − 236 #ifdef COFF
+ − 237 static long block_copy_start; /* Old executable start point */
+ − 238 static struct filehdr f_hdr; /* File header */
+ − 239 static struct aouthdr f_ohdr; /* Optional file header (a.out) */
+ − 240 long bias; /* Bias to add for growth */
+ − 241 long lnnoptr; /* Pointer to line-number info within file */
+ − 242 #define SYMS_START block_copy_start
+ − 243
+ − 244 static long text_scnptr;
+ − 245 static long data_scnptr;
+ − 246
+ − 247 #else /* not COFF */
+ − 248
+ − 249 #ifdef __STDC__
+ − 250 #ifndef __sys_stdtypes_h
+ − 251 #if !defined(_PTRDIFF_T) && !defined(_BSD_PTRDIFF_T_)
+ − 252 typedef long ptrdiff_t;
+ − 253 #endif
+ − 254 #endif
+ − 255 #ifndef HPUX
+ − 256 /* not sure where this for NetBSD should really go
+ − 257 and it probably applies to other systems */
+ − 258 #if !defined(__NetBSD__) && !defined(__bsdi__) && !defined(__OpenBSD__)
+ − 259 extern void *sbrk (ptrdiff_t);
+ − 260 #else
+ − 261 extern char *sbrk ();
+ − 262 #endif /* __NetBSD__ or __OpenBSD__ */
+ − 263 #endif /* HPUX */
+ − 264 #else
+ − 265 extern void *sbrk ();
+ − 266 #endif
+ − 267
+ − 268 #define SYMS_START ((long) N_SYMOFF (ohdr))
+ − 269
+ − 270 /* Some machines override the structure name for an a.out header. */
+ − 271 #ifndef EXEC_HDR_TYPE
+ − 272 #define EXEC_HDR_TYPE struct exec
+ − 273 #endif
+ − 274
+ − 275 #ifdef HPUX
+ − 276 #ifdef HP9000S200_ID
+ − 277 #define MY_ID HP9000S200_ID
+ − 278 #else
+ − 279 #include <model.h>
+ − 280 #define MY_ID MYSYS
+ − 281 #endif /* no HP9000S200_ID */
+ − 282 static MAGIC OLDMAGIC = {MY_ID, SHARE_MAGIC};
+ − 283 static MAGIC NEWMAGIC = {MY_ID, DEMAND_MAGIC};
+ − 284 #define N_TXTOFF(x) TEXT_OFFSET(x)
+ − 285 #define N_SYMOFF(x) LESYM_OFFSET(x)
+ − 286 static EXEC_HDR_TYPE hdr, ohdr;
+ − 287
+ − 288 #else /* not HPUX */
+ − 289
+ − 290 #if defined (USG) && !defined (IBMAIX) && !defined (IRIS) && !defined (COFF_ENCAPSULATE) && !defined (LINUX)
+ − 291 static struct bhdr hdr, ohdr;
+ − 292 #define a_magic fmagic
+ − 293 #define a_text tsize
+ − 294 #define a_data dsize
+ − 295 #define a_bss bsize
+ − 296 #define a_syms ssize
+ − 297 #define a_trsize rtsize
+ − 298 #define a_drsize rdsize
+ − 299 #define a_entry entry
+ − 300 #define N_BADMAG(x) \
+ − 301 (((x).fmagic)!=OMAGIC && ((x).fmagic)!=NMAGIC &&\
+ − 302 ((x).fmagic)!=FMAGIC && ((x).fmagic)!=IMAGIC)
+ − 303 #define NEWMAGIC FMAGIC
+ − 304 #else /* IRIS or IBMAIX or not USG */
+ − 305 static EXEC_HDR_TYPE hdr, ohdr;
+ − 306 #define NEWMAGIC ZMAGIC
+ − 307 #endif /* IRIS or IBMAIX not USG */
+ − 308 #endif /* not HPUX */
+ − 309
+ − 310 static int unexec_text_start;
+ − 311 static int unexec_data_start;
+ − 312
+ − 313 #ifdef COFF_ENCAPSULATE
+ − 314 /* coffheader is defined in the GNU a.out.encap.h file. */
+ − 315 struct coffheader coffheader;
+ − 316 #endif
+ − 317
+ − 318 #endif /* not COFF */
+ − 319
+ − 320 static int pagemask;
+ − 321
+ − 322 /* Correct an int which is the bit pattern of a pointer to a byte
+ − 323 into an int which is the number of a byte.
+ − 324 This is a no-op on ordinary machines, but not on all. */
+ − 325
+ − 326 #ifndef ADDR_CORRECT /* Let m-*.h files override this definition */
+ − 327 #define ADDR_CORRECT(x) ((char *)(x) - (char*)0)
+ − 328 #endif
+ − 329
+ − 330 #ifdef emacs
+ − 331
+ − 332 #include "lisp.h"
+ − 333
+ − 334 static void
440
+ − 335 report_error (const char *file, int fd)
428
+ − 336 {
+ − 337 if (fd)
+ − 338 close (fd);
563
+ − 339 report_error_with_errno (Qio_error, "Cannot unexec",
+ − 340 build_ext_string (file, Qfile_name));
428
+ − 341 }
+ − 342 #endif /* emacs */
+ − 343
3025
+ − 344 #define ERROR0(msg) report_error_1 (new_, msg, 0, 0); return -1
+ − 345 #define ERROR1(msg,x) report_error_1 (new_, msg, x, 0); return -1
+ − 346 #define ERROR2(msg,x,y) report_error_1 (new_, msg, x, y); return -1
428
+ − 347
+ − 348 static void
+ − 349 report_error_1 (fd, msg, a1, a2)
+ − 350 int fd;
442
+ − 351 const char *msg;
428
+ − 352 int a1, a2;
+ − 353 {
+ − 354 close (fd);
+ − 355 #ifdef emacs
563
+ − 356 signal_ferror (Qio_error, msg, a1, a2);
428
+ − 357 #else
+ − 358 fprintf (stderr, msg, a1, a2);
+ − 359 fprintf (stderr, "\n");
+ − 360 #endif
+ − 361 }
+ − 362
3025
+ − 363 static int make_hdr (int new_, int a_out, unsigned data_start,
428
+ − 364 unsigned bss_start, unsigned entry_address,
+ − 365 char *a_name, char *new_name);
3025
+ − 366 static int copy_text_and_data (int new_, int a_out);
+ − 367 static int copy_sym (int new_, int a_out, char *a_name, char *new_name);
428
+ − 368 static void mark_x (char *name);
+ − 369
+ − 370 /* ****************************************************************
+ − 371 * unexec
+ − 372 *
+ − 373 * driving logic.
+ − 374 */
+ − 375 int
+ − 376 unexec (new_name, a_name, data_start, bss_start, entry_address)
+ − 377 char *new_name, *a_name;
+ − 378 unsigned data_start, bss_start, entry_address;
+ − 379 {
3025
+ − 380 int new_, a_out = -1;
428
+ − 381
+ − 382 if (a_name && (a_out = open (a_name, O_RDONLY)) < 0)
+ − 383 {
+ − 384 PERROR (a_name);
+ − 385 }
3025
+ − 386 if ((new_ = creat (new_name, 0666)) < 0)
428
+ − 387 {
+ − 388 PERROR (new_name);
+ − 389 }
+ − 390
3025
+ − 391 if (make_hdr (new_, a_out, data_start, bss_start, entry_address, a_name, new_name) < 0
+ − 392 || copy_text_and_data (new_, a_out) < 0
+ − 393 || copy_sym (new_, a_out, a_name, new_name) < 0
428
+ − 394 #ifdef COFF
+ − 395 #ifndef COFF_BSD_SYMBOLS
3025
+ − 396 || adjust_lnnoptrs (new_, a_out, new_name) < 0
428
+ − 397 #endif
+ − 398 #endif
+ − 399 )
+ − 400 {
3025
+ − 401 close (new_);
428
+ − 402 /* unlink (new_name); / * Failed, unlink new a.out */
438
+ − 403 return -1;
428
+ − 404 }
+ − 405
3025
+ − 406 close (new_);
428
+ − 407 if (a_out >= 0)
+ − 408 close (a_out);
+ − 409 mark_x (new_name);
+ − 410 return 0;
+ − 411 }
+ − 412
+ − 413 /* ****************************************************************
+ − 414 * make_hdr
+ − 415 *
+ − 416 * Make the header in the new a.out from the header in core.
+ − 417 * Modify the text and data sizes.
+ − 418 */
+ − 419 static int
3025
+ − 420 make_hdr (int new_, int a_out, unsigned data_start, unsigned bss_start,
428
+ − 421 unsigned entry_address, char *a_name, char *new_name)
+ − 422 {
+ − 423 #ifdef COFF
+ − 424 auto struct scnhdr f_thdr; /* Text section header */
+ − 425 auto struct scnhdr f_dhdr; /* Data section header */
+ − 426 auto struct scnhdr f_bhdr; /* Bss section header */
+ − 427 auto struct scnhdr scntemp; /* Temporary section header */
+ − 428 int scns;
+ − 429 #endif /* COFF */
+ − 430 #ifdef USG_SHARED_LIBRARIES
+ − 431 extern unsigned int bss_end;
+ − 432 #else
+ − 433 unsigned int bss_end;
+ − 434 #endif
+ − 435
+ − 436 pagemask = getpagesize () - 1;
+ − 437
+ − 438 /* Adjust text/data boundary. */
+ − 439 #ifdef NO_REMAP
+ − 440 data_start = (int) start_of_data ();
+ − 441 #else /* not NO_REMAP */
+ − 442 if (!data_start)
+ − 443 data_start = (int) start_of_data ();
+ − 444 #endif /* not NO_REMAP */
+ − 445 data_start = ADDR_CORRECT (data_start);
+ − 446
+ − 447 #ifdef SEGMENT_MASK
+ − 448 data_start = data_start & ~SEGMENT_MASK; /* (Down) to segment boundary. */
+ − 449 #else
+ − 450 data_start = data_start & ~pagemask; /* (Down) to page boundary. */
+ − 451 #endif
+ − 452
+ − 453 bss_end = ADDR_CORRECT (sbrk (0)) + pagemask;
+ − 454 bss_end &= ~ pagemask;
+ − 455
+ − 456 /* Adjust data/bss boundary. */
+ − 457 if (bss_start != 0)
+ − 458 {
+ − 459 bss_start = (ADDR_CORRECT (bss_start) + pagemask);
+ − 460 /* (Up) to page bdry. */
+ − 461 bss_start &= ~ pagemask;
+ − 462 if (bss_start > bss_end)
+ − 463 {
+ − 464 ERROR1 ("unexec: Specified bss_start (%u) is past end of program",
+ − 465 bss_start);
+ − 466 }
+ − 467 }
+ − 468 else
+ − 469 bss_start = bss_end;
+ − 470
+ − 471 if (data_start > bss_start) /* Can't have negative data size. */
+ − 472 {
+ − 473 ERROR2 ("unexec: data_start (%u) can't be greater than bss_start (%u)",
+ − 474 data_start, bss_start);
+ − 475 }
+ − 476
+ − 477 #ifdef COFF
+ − 478 /* Salvage as much info from the existing file as possible */
+ − 479 if (a_out >= 0)
+ − 480 {
+ − 481 if (read (a_out, &f_hdr, sizeof (f_hdr)) != sizeof (f_hdr))
+ − 482 {
+ − 483 PERROR (a_name);
+ − 484 }
+ − 485 block_copy_start += sizeof (f_hdr);
+ − 486 if (f_hdr.f_opthdr > 0)
+ − 487 {
+ − 488 if (read (a_out, &f_ohdr, sizeof (f_ohdr)) != sizeof (f_ohdr))
+ − 489 {
+ − 490 PERROR (a_name);
+ − 491 }
+ − 492 block_copy_start += sizeof (f_ohdr);
+ − 493 }
+ − 494 /* Loop through section headers, copying them in */
+ − 495 lseek (a_out, sizeof (f_hdr) + f_hdr.f_opthdr, 0);
+ − 496 for (scns = f_hdr.f_nscns; scns > 0; scns--) {
+ − 497 if (read (a_out, &scntemp, sizeof (scntemp)) != sizeof (scntemp))
+ − 498 {
+ − 499 PERROR (a_name);
+ − 500 }
+ − 501 if (scntemp.s_scnptr > 0L)
+ − 502 {
+ − 503 if (block_copy_start < scntemp.s_scnptr + scntemp.s_size)
+ − 504 block_copy_start = scntemp.s_scnptr + scntemp.s_size;
+ − 505 }
+ − 506 if (strcmp (scntemp.s_name, ".text") == 0)
+ − 507 {
+ − 508 f_thdr = scntemp;
+ − 509 }
+ − 510 else if (strcmp (scntemp.s_name, ".data") == 0)
+ − 511 {
+ − 512 f_dhdr = scntemp;
+ − 513 }
+ − 514 else if (strcmp (scntemp.s_name, ".bss") == 0)
+ − 515 {
+ − 516 f_bhdr = scntemp;
+ − 517 }
+ − 518 }
+ − 519 }
+ − 520 else
+ − 521 {
+ − 522 ERROR0 ("can't build a COFF file from scratch yet");
+ − 523 }
+ − 524
+ − 525 /* Now we alter the contents of all the f_*hdr variables
+ − 526 to correspond to what we want to dump. */
+ − 527
+ − 528 #ifdef USG_SHARED_LIBRARIES
+ − 529
+ − 530 /* The amount of data we're adding to the file is distance from the
+ − 531 * end of the original .data space to the current end of the .data
+ − 532 * space.
+ − 533 */
+ − 534
+ − 535 bias = bss_start - (f_ohdr.data_start + f_dhdr.s_size);
+ − 536
+ − 537 #endif
+ − 538
+ − 539 f_hdr.f_flags |= (F_RELFLG | F_EXEC);
+ − 540 #ifdef TPIX
+ − 541 f_hdr.f_nscns = 3;
+ − 542 #endif
+ − 543 #ifdef EXEC_MAGIC
+ − 544 f_ohdr.magic = EXEC_MAGIC;
+ − 545 #endif
+ − 546 #ifndef NO_REMAP
+ − 547 f_ohdr.text_start = (long) start_of_text ();
+ − 548 f_ohdr.tsize = data_start - f_ohdr.text_start;
+ − 549 f_ohdr.data_start = data_start;
+ − 550 #endif /* NO_REMAP */
+ − 551 f_ohdr.dsize = bss_start - f_ohdr.data_start;
+ − 552 f_ohdr.bsize = bss_end - bss_start;
+ − 553 #ifndef KEEP_OLD_TEXT_SCNPTR
+ − 554 /* On some machines, the old values are right.
+ − 555 ??? Maybe on all machines with NO_REMAP. */
+ − 556 f_thdr.s_size = f_ohdr.tsize;
+ − 557 f_thdr.s_scnptr = sizeof (f_hdr) + sizeof (f_ohdr);
+ − 558 f_thdr.s_scnptr += (f_hdr.f_nscns) * (sizeof (f_thdr));
+ − 559 #endif /* KEEP_OLD_TEXT_SCNPTR */
+ − 560 #ifdef ADJUST_TEXT_SCNHDR_SIZE
+ − 561 /* On some machines, `text size' includes all headers. */
+ − 562 f_thdr.s_size -= f_thdr.s_scnptr;
+ − 563 #endif /* ADJUST_TEST_SCNHDR_SIZE */
+ − 564 lnnoptr = f_thdr.s_lnnoptr;
+ − 565 #ifdef SECTION_ALIGNMENT
+ − 566 /* Some systems require special alignment
+ − 567 of the sections in the file itself. */
+ − 568 f_thdr.s_scnptr
+ − 569 = (f_thdr.s_scnptr + SECTION_ALIGNMENT) & ~SECTION_ALIGNMENT;
+ − 570 #endif /* SECTION_ALIGNMENT */
+ − 571 #ifdef TPIX
+ − 572 f_thdr.s_scnptr = 0xd0;
+ − 573 #endif
+ − 574 text_scnptr = f_thdr.s_scnptr;
+ − 575 #ifdef ADJUST_TEXTBASE
+ − 576 text_scnptr = sizeof (f_hdr) + sizeof (f_ohdr) + (f_hdr.f_nscns) * (sizeof (f_thdr));
+ − 577 #endif
+ − 578 #ifndef KEEP_OLD_PADDR
+ − 579 f_dhdr.s_paddr = f_ohdr.data_start;
+ − 580 #endif /* KEEP_OLD_PADDR */
+ − 581 f_dhdr.s_vaddr = f_ohdr.data_start;
+ − 582 f_dhdr.s_size = f_ohdr.dsize;
+ − 583 f_dhdr.s_scnptr = f_thdr.s_scnptr + f_thdr.s_size;
+ − 584 #ifdef SECTION_ALIGNMENT
+ − 585 /* Some systems require special alignment
+ − 586 of the sections in the file itself. */
+ − 587 f_dhdr.s_scnptr
+ − 588 = (f_dhdr.s_scnptr + SECTION_ALIGNMENT) & ~SECTION_ALIGNMENT;
+ − 589 #endif /* SECTION_ALIGNMENT */
+ − 590 #ifdef DATA_SECTION_ALIGNMENT
+ − 591 /* Some systems require special alignment
+ − 592 of the data section only. */
+ − 593 f_dhdr.s_scnptr
+ − 594 = (f_dhdr.s_scnptr + DATA_SECTION_ALIGNMENT) & ~DATA_SECTION_ALIGNMENT;
+ − 595 #endif /* DATA_SECTION_ALIGNMENT */
+ − 596 data_scnptr = f_dhdr.s_scnptr;
+ − 597 #ifndef KEEP_OLD_PADDR
+ − 598 f_bhdr.s_paddr = f_ohdr.data_start + f_ohdr.dsize;
+ − 599 #endif /* KEEP_OLD_PADDR */
+ − 600 f_bhdr.s_vaddr = f_ohdr.data_start + f_ohdr.dsize;
+ − 601 f_bhdr.s_size = f_ohdr.bsize;
+ − 602 f_bhdr.s_scnptr = 0L;
+ − 603 #ifndef USG_SHARED_LIBRARIES
+ − 604 bias = f_dhdr.s_scnptr + f_dhdr.s_size - block_copy_start;
+ − 605 #endif
+ − 606
+ − 607 if (f_hdr.f_symptr > 0L)
+ − 608 {
+ − 609 f_hdr.f_symptr += bias;
+ − 610 }
+ − 611
+ − 612 if (f_thdr.s_lnnoptr > 0L)
+ − 613 {
+ − 614 f_thdr.s_lnnoptr += bias;
+ − 615 }
+ − 616
+ − 617 #ifdef ADJUST_EXEC_HEADER
+ − 618 ADJUST_EXEC_HEADER;
+ − 619 #endif /* ADJUST_EXEC_HEADER */
+ − 620
3025
+ − 621 if (write (new_, &f_hdr, sizeof (f_hdr)) != sizeof (f_hdr))
428
+ − 622 {
+ − 623 PERROR (new_name);
+ − 624 }
+ − 625
3025
+ − 626 if (write (new_, &f_ohdr, sizeof (f_ohdr)) != sizeof (f_ohdr))
428
+ − 627 {
+ − 628 PERROR (new_name);
+ − 629 }
+ − 630
+ − 631 #ifndef USG_SHARED_LIBRARIES
+ − 632
3025
+ − 633 if (write (new_, &f_thdr, sizeof (f_thdr)) != sizeof (f_thdr))
428
+ − 634 {
+ − 635 PERROR (new_name);
+ − 636 }
+ − 637
3025
+ − 638 if (write (new_, &f_dhdr, sizeof (f_dhdr)) != sizeof (f_dhdr))
428
+ − 639 {
+ − 640 PERROR (new_name);
+ − 641 }
+ − 642
3025
+ − 643 if (write (new_, &f_bhdr, sizeof (f_bhdr)) != sizeof (f_bhdr))
428
+ − 644 {
+ − 645 PERROR (new_name);
+ − 646 }
+ − 647
+ − 648 #else /* USG_SHARED_LIBRARIES */
+ − 649
+ − 650 /* The purpose of this code is to write out the new file's section
+ − 651 * header table.
+ − 652 *
+ − 653 * Scan through the original file's sections. If the encountered
+ − 654 * section is one we know (.text, .data or .bss), write out the
+ − 655 * correct header. If it is a section we do not know (such as
+ − 656 * .lib), adjust the address of where the section data is in the
+ − 657 * file, and write out the header.
+ − 658 *
+ − 659 * If any section precedes .text or .data in the file, this code
+ − 660 * will not adjust the file pointer for that section correctly.
+ − 661 */
+ − 662
+ − 663 /* This used to use sizeof (f_ohdr) instead of .f_opthdr.
+ − 664 .f_opthdr is said to be right when there is no optional header. */
+ − 665 lseek (a_out, sizeof (f_hdr) + f_hdr.f_opthdr, 0);
+ − 666
+ − 667 for (scns = f_hdr.f_nscns; scns > 0; scns--)
+ − 668 {
+ − 669 if (read (a_out, &scntemp, sizeof (scntemp)) != sizeof (scntemp))
+ − 670 PERROR (a_name);
+ − 671
+ − 672 if (!strcmp (scntemp.s_name, f_thdr.s_name)) /* .text */
+ − 673 {
3025
+ − 674 if (write (new_, &f_thdr, sizeof (f_thdr)) != sizeof (f_thdr))
428
+ − 675 PERROR (new_name);
+ − 676 }
+ − 677 else if (!strcmp (scntemp.s_name, f_dhdr.s_name)) /* .data */
+ − 678 {
3025
+ − 679 if (write (new_, &f_dhdr, sizeof (f_dhdr)) != sizeof (f_dhdr))
428
+ − 680 PERROR (new_name);
+ − 681 }
+ − 682 else if (!strcmp (scntemp.s_name, f_bhdr.s_name)) /* .bss */
+ − 683 {
3025
+ − 684 if (write (new_, &f_bhdr, sizeof (f_bhdr)) != sizeof (f_bhdr))
428
+ − 685 PERROR (new_name);
+ − 686 }
+ − 687 else
+ − 688 {
+ − 689 if (scntemp.s_scnptr)
+ − 690 scntemp.s_scnptr += bias;
3025
+ − 691 if (write (new_, &scntemp, sizeof (scntemp)) != sizeof (scntemp))
428
+ − 692 PERROR (new_name);
+ − 693 }
+ − 694 }
+ − 695 #endif /* USG_SHARED_LIBRARIES */
+ − 696
+ − 697 return (0);
+ − 698
+ − 699 #else /* if not COFF */
+ − 700
+ − 701 /* Get symbol table info from header of a.out file if given one. */
+ − 702 if (a_out >= 0)
+ − 703 {
+ − 704 #ifdef COFF_ENCAPSULATE
647
+ − 705 if (read (a_out, &coffheader, sizeof (coffheader)) != sizeof (coffheader))
428
+ − 706 {
+ − 707 PERROR(a_name);
+ − 708 }
+ − 709 if (coffheader.f_magic != COFF_MAGIC)
+ − 710 {
+ − 711 ERROR1("%s doesn't have legal coff magic number\n", a_name);
+ − 712 }
+ − 713 #endif
647
+ − 714 if (read (a_out, (char *) &ohdr, sizeof (hdr)) != sizeof (hdr))
428
+ − 715 {
+ − 716 PERROR (a_name);
+ − 717 }
+ − 718
+ − 719 if (N_BADMAG (ohdr))
+ − 720 {
+ − 721 ERROR1 ("invalid magic number in %s", a_name);
+ − 722 }
+ − 723 hdr = ohdr;
+ − 724 }
+ − 725 else
+ − 726 {
+ − 727 #ifdef COFF_ENCAPSULATE
+ − 728 /* We probably could without too much trouble. The code is in gld
+ − 729 * but I don't have that much time or incentive.
+ − 730 */
+ − 731 ERROR0 ("can't build a COFF file from scratch yet");
+ − 732 #else
647
+ − 733 memset ((void *)&hdr, 0, sizeof (hdr));
428
+ − 734 #endif
+ − 735 }
+ − 736
+ − 737 unexec_text_start = (long) start_of_text ();
+ − 738 unexec_data_start = data_start;
+ − 739
+ − 740 /* Machine-dependent fixup for header, or maybe for unexec_text_start */
+ − 741 #ifdef ADJUST_EXEC_HEADER
+ − 742 ADJUST_EXEC_HEADER;
+ − 743 #endif /* ADJUST_EXEC_HEADER */
+ − 744
+ − 745 hdr.a_trsize = 0;
+ − 746 hdr.a_drsize = 0;
+ − 747 if (entry_address != 0)
+ − 748 hdr.a_entry = entry_address;
+ − 749
+ − 750 hdr.a_bss = bss_end - bss_start;
+ − 751 hdr.a_data = bss_start - data_start;
+ − 752 #ifdef NO_REMAP
+ − 753 hdr.a_text = ohdr.a_text;
+ − 754 #else /* not NO_REMAP */
+ − 755 hdr.a_text = data_start - unexec_text_start;
+ − 756
+ − 757 #ifdef A_TEXT_OFFSET
+ − 758 hdr.a_text += A_TEXT_OFFSET (ohdr);
+ − 759 #endif
+ − 760
+ − 761 #endif /* not NO_REMAP */
+ − 762
+ − 763 #ifdef COFF_ENCAPSULATE
+ − 764 /* We are encapsulating BSD format within COFF format. */
+ − 765 {
+ − 766 struct coffscn *tp, *dp, *bp;
+ − 767 tp = &coffheader.scns[0];
+ − 768 dp = &coffheader.scns[1];
+ − 769 bp = &coffheader.scns[2];
+ − 770 tp->s_size = hdr.a_text + sizeof(struct exec);
+ − 771 dp->s_paddr = data_start;
+ − 772 dp->s_vaddr = data_start;
+ − 773 dp->s_size = hdr.a_data;
+ − 774 bp->s_paddr = dp->s_vaddr + dp->s_size;
+ − 775 bp->s_vaddr = bp->s_paddr;
+ − 776 bp->s_size = hdr.a_bss;
+ − 777 coffheader.tsize = tp->s_size;
+ − 778 coffheader.dsize = dp->s_size;
+ − 779 coffheader.bsize = bp->s_size;
+ − 780 coffheader.text_start = tp->s_vaddr;
+ − 781 coffheader.data_start = dp->s_vaddr;
+ − 782 }
3025
+ − 783 if (write (new_, &coffheader, sizeof (coffheader)) != sizeof (coffheader))
428
+ − 784 {
+ − 785 PERROR(new_name);
+ − 786 }
+ − 787 #endif /* COFF_ENCAPSULATE */
+ − 788
3025
+ − 789 if (write (new_, (char *) &hdr, sizeof (hdr)) != sizeof (hdr))
428
+ − 790 {
+ − 791 PERROR (new_name);
+ − 792 }
+ − 793
+ − 794 #if 0 /* This #ifndef caused a bug on Linux when using QMAGIC. */
+ − 795 /* This adjustment was done above only #ifndef NO_REMAP,
+ − 796 so only undo it now #ifndef NO_REMAP. */
+ − 797 /* #ifndef NO_REMAP */
+ − 798 #endif
+ − 799 #ifdef A_TEXT_OFFSET
+ − 800 hdr.a_text -= A_TEXT_OFFSET (ohdr);
+ − 801 #endif
+ − 802
+ − 803 return 0;
+ − 804
+ − 805 #endif /* not COFF */
+ − 806 }
+ − 807
+ − 808 static void write_segment (int, char *, char *);
+ − 809
+ − 810 /* ****************************************************************
+ − 811 * copy_text_and_data
+ − 812 *
+ − 813 * Copy the text and data segments from memory to the new a.out
+ − 814 */
+ − 815 static int
3025
+ − 816 copy_text_and_data (int new_,
2286
+ − 817 #if defined (COFF) && defined (USG_SHARED_LIBRARIES)
+ − 818 int a_out
+ − 819 #else
+ − 820 int UNUSED (a_out)
+ − 821 #endif
+ − 822 )
428
+ − 823 {
+ − 824 char *end;
+ − 825 char *ptr;
+ − 826
+ − 827 #ifdef COFF
+ − 828
+ − 829 #ifdef USG_SHARED_LIBRARIES
+ − 830
+ − 831 int scns;
+ − 832 struct scnhdr scntemp; /* Temporary section header */
+ − 833
+ − 834 /* The purpose of this code is to write out the new file's section
+ − 835 * contents.
+ − 836 *
+ − 837 * Step through the section table. If we know the section (.text,
+ − 838 * .data) do the appropriate thing. Otherwise, if the section has
+ − 839 * no allocated space in the file (.bss), do nothing. Otherwise,
+ − 840 * the section has space allocated in the file, and is not a section
+ − 841 * we know. So just copy it.
+ − 842 */
+ − 843
+ − 844 lseek (a_out, sizeof (struct filehdr) + sizeof (struct aouthdr), 0);
+ − 845
+ − 846 for (scns = f_hdr.f_nscns; scns > 0; scns--)
+ − 847 {
+ − 848 if (read (a_out, &scntemp, sizeof (scntemp)) != sizeof (scntemp))
+ − 849 PERROR ("temacs");
+ − 850
+ − 851 if (!strcmp (scntemp.s_name, ".text"))
+ − 852 {
3025
+ − 853 lseek (new_, (long) text_scnptr, 0);
428
+ − 854 ptr = (char *) f_ohdr.text_start;
+ − 855 end = ptr + f_ohdr.tsize;
3025
+ − 856 write_segment (new_, ptr, end);
428
+ − 857 }
+ − 858 else if (!strcmp (scntemp.s_name, ".data"))
+ − 859 {
3025
+ − 860 lseek (new_, (long) data_scnptr, 0);
428
+ − 861 ptr = (char *) f_ohdr.data_start;
+ − 862 end = ptr + f_ohdr.dsize;
3025
+ − 863 write_segment (new_, ptr, end);
428
+ − 864 }
+ − 865 else if (!scntemp.s_scnptr)
+ − 866 ; /* do nothing - no data for this section */
+ − 867 else
+ − 868 {
+ − 869 char page[BUFSIZ];
+ − 870 int size, n;
+ − 871 long old_a_out_ptr = lseek (a_out, 0, 1);
+ − 872
+ − 873 lseek (a_out, scntemp.s_scnptr, 0);
+ − 874 for (size = scntemp.s_size; size > 0; size -= sizeof (page))
+ − 875 {
+ − 876 n = size > sizeof (page) ? sizeof (page) : size;
3025
+ − 877 if (read (a_out, page, n) != n || write (new_, page, n) != n)
428
+ − 878 PERROR ("emacs");
+ − 879 }
+ − 880 lseek (a_out, old_a_out_ptr, 0);
+ − 881 }
+ − 882 }
+ − 883
+ − 884 #else /* COFF, but not USG_SHARED_LIBRARIES */
+ − 885
3025
+ − 886 lseek (new_, (long) text_scnptr, 0);
428
+ − 887 ptr = (char *) f_ohdr.text_start;
+ − 888 #ifdef HEADER_INCL_IN_TEXT
+ − 889 /* For Gould UTX/32, text starts after headers */
+ − 890 ptr = (char *) (ptr + text_scnptr);
+ − 891 #endif /* HEADER_INCL_IN_TEXT */
+ − 892 end = ptr + f_ohdr.tsize;
3025
+ − 893 write_segment (new_, ptr, end);
428
+ − 894
3025
+ − 895 lseek (new_, (long) data_scnptr, 0);
428
+ − 896 ptr = (char *) f_ohdr.data_start;
+ − 897 end = ptr + f_ohdr.dsize;
3025
+ − 898 write_segment (new_, ptr, end);
428
+ − 899
+ − 900 #endif /* USG_SHARED_LIBRARIES */
+ − 901
+ − 902 #else /* if not COFF */
+ − 903
+ − 904 /* Some machines count the header as part of the text segment.
+ − 905 That is to say, the header appears in core
+ − 906 just before the address that start_of_text returns.
+ − 907 For them, N_TXTOFF is the place where the header goes.
+ − 908 We must adjust the seek to the place after the header.
+ − 909 Note that at this point hdr.a_text does *not* count
+ − 910 the extra A_TEXT_OFFSET bytes, only the actual bytes of code. */
+ − 911
+ − 912 #ifdef A_TEXT_SEEK
3025
+ − 913 lseek (new_, (long) A_TEXT_SEEK (hdr), 0);
428
+ − 914 #else
3025
+ − 915 lseek (new_, (long) N_TXTOFF (hdr), 0);
428
+ − 916 #endif /* no A_TEXT_SEEK */
+ − 917
+ − 918 #ifdef RISCiX
+ − 919
+ − 920 /* Acorn's RISC-iX has a wacky way of initializing the position of the heap.
+ − 921 * There is a little table in crt0.o that is filled at link time with
+ − 922 * the min and current brk positions, among other things. When start
+ − 923 * runs, it copies the table to where these parameters live during
+ − 924 * execution. This data is in text space, so it cannot be modified here
+ − 925 * before saving the executable, so the data is written manually. In
+ − 926 * addition, the table does not have a label, and the nearest accessible
+ − 927 * label (mcount) is not prefixed with a '_', thus making it inaccessible
+ − 928 * from within C programs. To overcome this, emacs's executable is passed
+ − 929 * through the command 'nm %s | fgrep mcount' into a pipe, and the
+ − 930 * resultant output is then used to find the address of 'mcount'. As far as
+ − 931 * is possible to determine, in RISC-iX releases prior to 1.2, the negative
+ − 932 * offset of the table from mcount is 0x2c, whereas from 1.2 onwards it is
+ − 933 * 0x30. bss_end has been rounded up to page boundary. This solution is
+ − 934 * based on suggestions made by Kevin Welton and Steve Hunt of Acorn, and
+ − 935 * avoids the need for a custom version of crt0.o for emacs which has its
+ − 936 * table in data space.
+ − 937 */
+ − 938
+ − 939 {
+ − 940 char command[1024];
+ − 941 char errbuf[1024];
+ − 942 char address_text[32];
+ − 943 int proforma[4];
+ − 944 FILE *pfile;
+ − 945 char *temp_ptr;
+ − 946 char c;
+ − 947 int mcount_address, mcount_offset, count;
+ − 948 extern char *_execname;
438
+ − 949
428
+ − 950
+ − 951 /* The use of _execname is incompatible with RISCiX 1.1 */
+ − 952 sprintf (command, "nm %s | fgrep mcount", _execname);
+ − 953
+ − 954 if ( (pfile = popen(command, "r")) == NULL)
+ − 955 {
+ − 956 sprintf (errbuf, "Could not open pipe");
+ − 957 PERROR (errbuf);
+ − 958 }
+ − 959
+ − 960 count=0;
+ − 961 while ( ((c=getc(pfile)) != EOF) && (c != ' ') && (count < 31))
+ − 962 address_text[count++]=c;
+ − 963 address_text[count]=0;
+ − 964
+ − 965 if ((count == 0) || pclose(pfile) != NULL)
+ − 966 {
+ − 967 sprintf (errbuf, "Failed to execute the command '%s'\n", command);
+ − 968 PERROR (errbuf);
438
+ − 969 }
428
+ − 970
+ − 971 sscanf(address_text, "%x", &mcount_address);
+ − 972 ptr = (char *) unexec_text_start;
+ − 973 mcount_offset = (char *)mcount_address - ptr;
+ − 974
+ − 975 #ifdef RISCiX_1_1
+ − 976 #define EDATA_OFFSET 0x2c
+ − 977 #else
+ − 978 #define EDATA_OFFSET 0x30
+ − 979 #endif
+ − 980
+ − 981 end = ptr + mcount_offset - EDATA_OFFSET;
+ − 982
3025
+ − 983 write_segment (new_, ptr, end);
428
+ − 984
+ − 985 proforma[0] = bss_end; /* becomes _edata */
+ − 986 proforma[1] = bss_end; /* becomes _end */
+ − 987 proforma[2] = bss_end; /* becomes _minbrk */
+ − 988 proforma[3] = bss_end; /* becomes _curbrk */
+ − 989
3025
+ − 990 write (new_, proforma, 16);
428
+ − 991
+ − 992 temp_ptr = ptr;
+ − 993 ptr = end + 16;
+ − 994 end = temp_ptr + hdr.a_text;
+ − 995
3025
+ − 996 write_segment (new_, ptr, end);
428
+ − 997 }
+ − 998
+ − 999 #else /* !RISCiX */
+ − 1000 ptr = (char *) unexec_text_start;
+ − 1001 end = ptr + hdr.a_text;
3025
+ − 1002 write_segment (new_, ptr, end);
428
+ − 1003 #endif /* RISCiX */
+ − 1004
+ − 1005 ptr = (char *) unexec_data_start;
+ − 1006 end = ptr + hdr.a_data;
+ − 1007 /* This lseek is certainly incorrect when A_TEXT_OFFSET
+ − 1008 and I believe it is a no-op otherwise.
+ − 1009 Let's see if its absence ever fails. */
3025
+ − 1010 /* lseek (new_, (long) N_TXTOFF (hdr) + hdr.a_text, 0); */
+ − 1011 write_segment (new_, ptr, end);
428
+ − 1012
+ − 1013 #endif /* not COFF */
+ − 1014
+ − 1015 return 0;
+ − 1016 }
+ − 1017
+ − 1018 static void
3025
+ − 1019 write_segment (new_, ptr, end)
+ − 1020 int new_;
428
+ − 1021 char *ptr, *end;
+ − 1022 {
+ − 1023 int i, nwrite, ret;
+ − 1024 #if 0
+ − 1025 char buf[80];
+ − 1026 #endif
+ − 1027 /* This is the normal amount to write at once.
+ − 1028 It is the size of block that NFS uses. */
+ − 1029 int writesize = 1 << 13;
+ − 1030 int pagesize = getpagesize ();
+ − 1031 char zeros[1 << 13];
+ − 1032
+ − 1033 memset (zeros, 0, sizeof (zeros));
+ − 1034
+ − 1035 for (i = 0; ptr < end;)
+ − 1036 {
+ − 1037 /* Distance to next multiple of writesize. */
+ − 1038 nwrite = (((int) ptr + writesize) & -writesize) - (int) ptr;
+ − 1039 /* But not beyond specified end. */
+ − 1040 if (nwrite > end - ptr) nwrite = end - ptr;
3025
+ − 1041 ret = write (new_, ptr, nwrite);
428
+ − 1042 /* If write gets a page fault, it means we reached
+ − 1043 a gap between the old text segment and the old data segment.
+ − 1044 This gap has probably been remapped into part of the text segment.
+ − 1045 So write zeros for it. */
+ − 1046 if (ret == -1
+ − 1047 #ifdef EFAULT
+ − 1048 && errno == EFAULT
+ − 1049 #endif
+ − 1050 )
+ − 1051 {
+ − 1052 /* Write only a page of zeros at once,
+ − 1053 so that we don't overshoot the start
+ − 1054 of the valid memory in the old data segment. */
+ − 1055 if (nwrite > pagesize)
+ − 1056 nwrite = pagesize;
3025
+ − 1057 write (new_, zeros, nwrite);
428
+ − 1058 }
+ − 1059 #if 0 /* Now that we have can ask `write' to write more than a page,
+ − 1060 it is legit for write do less than the whole amount specified. */
+ − 1061 else if (nwrite != ret)
+ − 1062 {
+ − 1063 sprintf (buf,
+ − 1064 "unexec write failure: addr 0x%lx, fileno %d, size 0x%x, wrote 0x%x, errno %d",
3025
+ − 1065 (unsigned long) ptr, new_, nwrite, ret, errno);
428
+ − 1066 PERROR (buf);
+ − 1067 }
+ − 1068 #endif
+ − 1069 i += nwrite;
+ − 1070 ptr += nwrite;
+ − 1071 }
+ − 1072 }
+ − 1073
+ − 1074 /* ****************************************************************
+ − 1075 * copy_sym
+ − 1076 *
+ − 1077 * Copy the relocation information and symbol table from the a.out to the new
+ − 1078 */
+ − 1079 static int
3025
+ − 1080 copy_sym (int new_, int a_out, char *a_name, char *new_name)
428
+ − 1081 {
+ − 1082 char page[1024];
+ − 1083 int n;
+ − 1084
+ − 1085 if (a_out < 0)
+ − 1086 return 0;
+ − 1087
+ − 1088 #ifdef COFF
+ − 1089 if (SYMS_START == 0L)
+ − 1090 return 0;
+ − 1091 #endif /* COFF */
+ − 1092
+ − 1093 #ifdef COFF
+ − 1094 if (lnnoptr) /* if there is line number info */
+ − 1095 lseek (a_out, lnnoptr, 0); /* start copying from there */
+ − 1096 else
+ − 1097 #endif /* COFF */
+ − 1098 lseek (a_out, SYMS_START, 0); /* Position a.out to symtab. */
+ − 1099
647
+ − 1100 while ((n = read (a_out, page, sizeof (page))) > 0)
428
+ − 1101 {
3025
+ − 1102 if (write (new_, page, n) != n)
428
+ − 1103 {
+ − 1104 PERROR (new_name);
+ − 1105 }
+ − 1106 }
+ − 1107 if (n < 0)
+ − 1108 {
+ − 1109 PERROR (a_name);
+ − 1110 }
+ − 1111 return 0;
+ − 1112 }
+ − 1113
+ − 1114 /* ****************************************************************
+ − 1115 * mark_x
+ − 1116 *
+ − 1117 * After successfully building the new a.out, mark it executable
+ − 1118 */
+ − 1119 static void
+ − 1120 mark_x (char *name)
+ − 1121 {
+ − 1122 struct stat sbuf;
+ − 1123 int um;
3025
+ − 1124 int new_ = 0; /* for PERROR */
428
+ − 1125
+ − 1126 um = umask (777);
+ − 1127 umask (um);
+ − 1128 if (stat (name, &sbuf) == -1)
+ − 1129 {
+ − 1130 PERROR (name);
+ − 1131 }
+ − 1132 sbuf.st_mode |= 0111 & ~um;
+ − 1133 if (chmod (name, sbuf.st_mode) == -1)
+ − 1134 PERROR (name);
+ − 1135 }
+ − 1136
+ − 1137 #ifdef COFF
+ − 1138 #ifndef COFF_BSD_SYMBOLS
+ − 1139
+ − 1140 /*
+ − 1141 * If the COFF file contains a symbol table and a line number section,
+ − 1142 * then any auxiliary entries that have values for x_lnnoptr must
+ − 1143 * be adjusted by the amount that the line number section has moved
+ − 1144 * in the file (bias computed in make_hdr). The #@$%&* designers of
+ − 1145 * the auxiliary entry structures used the absolute file offsets for
+ − 1146 * the line number entry rather than an offset from the start of the
+ − 1147 * line number section!
+ − 1148 *
+ − 1149 * When I figure out how to scan through the symbol table and pick out
+ − 1150 * the auxiliary entries that need adjustment, this routine will
+ − 1151 * be fixed. As it is now, all such entries are wrong and sdb
+ − 1152 * will complain. Fred Fish, UniSoft Systems Inc.
+ − 1153 */
+ − 1154
+ − 1155 /* This function is probably very slow. Instead of reopening the new
+ − 1156 file for input and output it should copy from the old to the new
+ − 1157 using the two descriptors already open (WRITEDESC and READDESC).
+ − 1158 Instead of reading one small structure at a time it should use
+ − 1159 a reasonable size buffer. But I don't have time to work on such
+ − 1160 things, so I am installing it as submitted to me. -- RMS. */
+ − 1161
+ − 1162 int
+ − 1163 adjust_lnnoptrs (writedesc, readdesc, new_name)
2286
+ − 1164 int UNUSED (writedesc);
+ − 1165 int UNUSED (readdesc);
428
+ − 1166 char *new_name;
+ − 1167 {
+ − 1168 int nsyms;
3025
+ − 1169 int new_;
428
+ − 1170 #if defined (amdahl_uts) || defined (pfa)
+ − 1171 SYMENT symentry;
+ − 1172 AUXENT auxentry;
+ − 1173 #else
+ − 1174 struct syment symentry;
+ − 1175 union auxent auxentry;
+ − 1176 #endif
+ − 1177
+ − 1178 if (!lnnoptr || !f_hdr.f_symptr)
+ − 1179 return 0;
+ − 1180
3025
+ − 1181 if ((new_ = open (new_name, O_RDWR)) < 0)
428
+ − 1182 {
+ − 1183 PERROR (new_name);
+ − 1184 return -1;
+ − 1185 }
+ − 1186
3025
+ − 1187 lseek (new_, f_hdr.f_symptr, 0);
428
+ − 1188 for (nsyms = 0; nsyms < f_hdr.f_nsyms; nsyms++)
+ − 1189 {
3025
+ − 1190 read (new_, &symentry, SYMESZ);
428
+ − 1191 if (symentry.n_numaux)
+ − 1192 {
3025
+ − 1193 read (new_, &auxentry, AUXESZ);
428
+ − 1194 nsyms++;
+ − 1195 if (ISFCN (symentry.n_type) || symentry.n_type == 0x2400)
+ − 1196 {
+ − 1197 auxentry.x_sym.x_fcnary.x_fcn.x_lnnoptr += bias;
3025
+ − 1198 lseek (new_, -AUXESZ, 1);
+ − 1199 write (new_, &auxentry, AUXESZ);
428
+ − 1200 }
+ − 1201 }
+ − 1202 }
3025
+ − 1203 close (new_);
428
+ − 1204 return 0;
+ − 1205 }
+ − 1206
+ − 1207 #endif /* COFF_BSD_SYMBOLS */
+ − 1208
+ − 1209 #endif /* COFF */