unexaix.c 15.6 KB
Newer Older
1
/* Dump an executable image.
2
   Copyright (C) 1985-1988, 1999, 2001-2011  Free Software Foundation, Inc.
Jim Blandy's avatar
Jim Blandy committed
3

4 5
This file is part of GNU Emacs.

6
GNU Emacs is free software: you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8 9
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
10 11 12 13 14 15 16

GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
17
along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
Jim Blandy's avatar
Jim Blandy committed
18

19
/*
Jim Blandy's avatar
Jim Blandy committed
20 21 22 23 24
In other words, you are welcome to use, share and improve this program.
You are forbidden to forbid anyone else to use, share and improve
what you give them.   Help stamp out software-hoarding!  */


25
/* Originally based on the COFF unexec.c by Spencer W. Thomas.
Jim Blandy's avatar
Jim Blandy committed
26
 *
27 28 29 30
 * Subsequently hacked on by
 * Bill Mann <Bill_Man@praxisint.com>
 * Andrew Vignaux <Andrew.Vignaux@comp.vuw.ac.nz>
 * Mike Sperber <sperber@informatik.uni-tuebingen.de>
31
 *
Jim Blandy's avatar
Jim Blandy committed
32
 * Synopsis:
33
 *	unexec (const char *new_name, const *old_name);
Jim Blandy's avatar
Jim Blandy committed
34 35 36 37 38 39 40 41
 *
 * Takes a snapshot of the program and makes an a.out format file in the
 * file named by the string argument new_name.
 * If a_name is non-NULL, the symbol table will be taken from the given file.
 * On some machines, an existing a_name file is required.
 *
 */

42
#include <config.h>
43 44
#include "unexec.h"

Jim Blandy's avatar
Jim Blandy committed
45 46 47 48 49 50
#define PERROR(file) report_error (file, new)
#include <a.out.h>
/* Define getpagesize () if the system does not.
   Note that this may depend on symbols defined in a.out.h
 */
#include "getpagesize.h"
Jim Blandy's avatar
Jim Blandy committed
51

Jim Blandy's avatar
Jim Blandy committed
52 53 54 55
#include <sys/types.h>
#include <stdio.h>
#include <sys/stat.h>
#include <errno.h>
56 57
#include <unistd.h>
#include <fcntl.h>
Jim Blandy's avatar
Jim Blandy committed
58

59
char *start_of_text (void);		        /* Start of text */
60
extern char *start_of_data (void);		/* Start of initialized data */
Jim Blandy's avatar
Jim Blandy committed
61 62 63

extern int _data;
extern int _text;
64

Jim Blandy's avatar
Jim Blandy committed
65 66 67 68
#include <filehdr.h>
#include <aouthdr.h>
#include <scnhdr.h>
#include <syms.h>
69

Jim Blandy's avatar
Jim Blandy committed
70 71
static struct filehdr f_hdr;		/* File header */
static struct aouthdr f_ohdr;		/* Optional file header (a.out) */
72 73
static long bias;			/* Bias to add for growth */
static long lnnoptr;			/* Pointer to line-number info within file */
Jim Blandy's avatar
Jim Blandy committed
74 75 76

static long text_scnptr;
static long data_scnptr;
77
#define ALIGN(val, pwr) (((val) + ((1L<<(pwr))-1)) & ~((1L<<(pwr))-1))
Jim Blandy's avatar
Jim Blandy committed
78 79 80
static long load_scnptr;
static long orig_load_scnptr;
static long orig_data_scnptr;
81
static int unrelocate_symbols (int, int, char *, char *);
Jim Blandy's avatar
Jim Blandy committed
82 83 84 85 86

#ifndef MAX_SECTIONS
#define MAX_SECTIONS	10
#endif

87
static int adjust_lnnoptrs (int, int, char *);
Jim Blandy's avatar
Jim Blandy committed
88 89 90

static int pagemask;

91
#include <setjmp.h>
92
#include "lisp.h"
Jim Blandy's avatar
Jim Blandy committed
93

94 95
static void
report_error (char *file, int fd)
Jim Blandy's avatar
Jim Blandy committed
96 97 98
{
  if (fd)
    close (fd);
99
  report_file_error ("Cannot unexec", Fcons (build_string (file), Qnil));
Jim Blandy's avatar
Jim Blandy committed
100
}
Jim Blandy's avatar
Jim Blandy committed
101

Jim Blandy's avatar
Jim Blandy committed
102 103 104
#define ERROR0(msg) report_error_1 (new, msg, 0, 0); return -1
#define ERROR1(msg,x) report_error_1 (new, msg, x, 0); return -1
#define ERROR2(msg,x,y) report_error_1 (new, msg, x, y); return -1
Jim Blandy's avatar
Jim Blandy committed
105

106 107
static void
report_error_1 (int fd, char *msg, int a1, int a2)
Jim Blandy's avatar
Jim Blandy committed
108
{
Jim Blandy's avatar
Jim Blandy committed
109 110 111 112
  close (fd);
  error (msg, a1, a2);
}

113 114 115 116 117
static int make_hdr (int, int, unsigned, unsigned, unsigned, char *, char *);
static void mark_x (char *);
static int copy_text_and_data (int);
static int copy_sym (int, int, char *, char *);
static void write_segment (int, char *, char *);
Jim Blandy's avatar
Jim Blandy committed
118 119 120 121 122 123

/* ****************************************************************
 * unexec
 *
 * driving logic.
 */
124 125
void
unexec (const char *new_name, const char *a_name)
Jim Blandy's avatar
Jim Blandy committed
126
{
127
  int new = -1, a_out = -1;
Jim Blandy's avatar
Jim Blandy committed
128

129
  if (a_name && (a_out = open (a_name, O_RDONLY)) < 0)
Jim Blandy's avatar
Jim Blandy committed
130 131 132 133 134 135 136
    {
      PERROR (a_name);
    }
  if ((new = creat (new_name, 0666)) < 0)
    {
      PERROR (new_name);
    }
137 138
  if (make_hdr (new, a_out,
		a_name, new_name) < 0
Jim Blandy's avatar
Jim Blandy committed
139 140 141
      || copy_text_and_data (new) < 0
      || copy_sym (new, a_out, a_name, new_name) < 0
      || adjust_lnnoptrs (new, a_out, new_name) < 0
142
      || unrelocate_symbols (new, a_out, a_name, new_name) < 0)
Jim Blandy's avatar
Jim Blandy committed
143
    {
Jim Blandy's avatar
Jim Blandy committed
144
      close (new);
Jim Blandy's avatar
Jim Blandy committed
145 146
    }

Jim Blandy's avatar
Jim Blandy committed
147 148 149 150 151 152 153 154 155 156 157 158 159
  close (new);
  if (a_out >= 0)
    close (a_out);
  mark_x (new_name);
}

/* ****************************************************************
 * make_hdr
 *
 * Make the header in the new a.out from the header in core.
 * Modify the text and data sizes.
 */
static int
160 161
make_hdr (int new, int a_out,
	  char *a_name, char *new_name)
Jim Blandy's avatar
Jim Blandy committed
162
{
163
  int scns;
164 165
  unsigned int bss_start;
  unsigned int data_start;
Jim Blandy's avatar
Jim Blandy committed
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184

  struct scnhdr section[MAX_SECTIONS];
  struct scnhdr * f_thdr;		/* Text section header */
  struct scnhdr * f_dhdr;		/* Data section header */
  struct scnhdr * f_bhdr;		/* Bss section header */
  struct scnhdr * f_lhdr;		/* Loader section header */
  struct scnhdr * f_tchdr;		/* Typechk section header */
  struct scnhdr * f_dbhdr;		/* Debug section header */
  struct scnhdr * f_xhdr;		/* Except section header */

  load_scnptr = orig_load_scnptr = lnnoptr = 0;
  pagemask = getpagesize () - 1;

  /* Adjust text/data boundary. */
  data_start = (long) start_of_data ();
  data_start = ADDR_CORRECT (data_start);

  data_start = data_start & ~pagemask; /* (Down) to page boundary. */

185 186
  bss_start = ADDR_CORRECT (sbrk (0)) + pagemask;
  bss_start &= ~ pagemask;
Jim Blandy's avatar
Jim Blandy committed
187

Jim Blandy's avatar
Jim Blandy committed
188 189 190 191 192
  if (data_start > bss_start)	/* Can't have negative data size. */
    {
      ERROR2 ("unexec: data_start (%u) can't be greater than bss_start (%u)",
	      data_start, bss_start);
    }
Jim Blandy's avatar
Jim Blandy committed
193

Jim Blandy's avatar
Jim Blandy committed
194 195 196 197
  /* Salvage as much info from the existing file as possible */
  f_thdr = NULL; f_dhdr = NULL; f_bhdr = NULL;
  f_lhdr = NULL; f_tchdr = NULL; f_dbhdr = NULL; f_xhdr = NULL;
  if (a_out >= 0)
Jim Blandy's avatar
Jim Blandy committed
198
    {
Jim Blandy's avatar
Jim Blandy committed
199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224
      if (read (a_out, &f_hdr, sizeof (f_hdr)) != sizeof (f_hdr))
	{
	  PERROR (a_name);
	}
      if (f_hdr.f_opthdr > 0)
	{
	  if (read (a_out, &f_ohdr, sizeof (f_ohdr)) != sizeof (f_ohdr))
	    {
	      PERROR (a_name);
	    }
	}
      if (f_hdr.f_nscns > MAX_SECTIONS)
	{
	  ERROR0 ("unexec: too many section headers -- increase MAX_SECTIONS");
	}
      /* Loop through section headers */
      for (scns = 0; scns < f_hdr.f_nscns; scns++) {
	struct scnhdr *s = &section[scns];
	if (read (a_out, s, sizeof (*s)) != sizeof (*s))
	  {
	    PERROR (a_name);
	  }

#define CHECK_SCNHDR(ptr, name, flags) \
  if (strcmp(s->s_name, name) == 0) { \
    if (s->s_flags != flags) { \
225 226
      fprintf(stderr, "unexec: %lx flags where %x expected in %s section.\n", \
	      (unsigned long)s->s_flags, flags, name); \
Jim Blandy's avatar
Jim Blandy committed
227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244
    } \
    if (ptr) { \
      fprintf(stderr, "unexec: duplicate section header for section %s.\n", \
	      name); \
    } \
    ptr = s; \
  }
	CHECK_SCNHDR(f_thdr, _TEXT, STYP_TEXT);
	CHECK_SCNHDR(f_dhdr, _DATA, STYP_DATA);
	CHECK_SCNHDR(f_bhdr, _BSS, STYP_BSS);
	CHECK_SCNHDR(f_lhdr, _LOADER, STYP_LOADER);
	CHECK_SCNHDR(f_dbhdr, _DEBUG,  STYP_DEBUG);
	CHECK_SCNHDR(f_tchdr, _TYPCHK,  STYP_TYPCHK);
	CHECK_SCNHDR(f_xhdr, _EXCEPT,  STYP_EXCEPT);
      }

      if (f_thdr == 0)
	{
245
	  ERROR1 ("unexec: couldn't find \"%s\" section", (int) _TEXT);
Jim Blandy's avatar
Jim Blandy committed
246 247 248
	}
      if (f_dhdr == 0)
	{
249
	  ERROR1 ("unexec: couldn't find \"%s\" section", (int) _DATA);
Jim Blandy's avatar
Jim Blandy committed
250 251 252
	}
      if (f_bhdr == 0)
	{
253
	  ERROR1 ("unexec: couldn't find \"%s\" section", (int) _BSS);
Jim Blandy's avatar
Jim Blandy committed
254
	}
Jim Blandy's avatar
Jim Blandy committed
255
    }
Jim Blandy's avatar
Jim Blandy committed
256
  else
Jim Blandy's avatar
Jim Blandy committed
257
    {
Jim Blandy's avatar
Jim Blandy committed
258
      ERROR0 ("can't build a COFF file from scratch yet");
Jim Blandy's avatar
Jim Blandy committed
259
    }
Jim Blandy's avatar
Jim Blandy committed
260 261 262 263 264
  orig_data_scnptr = f_dhdr->s_scnptr;
  orig_load_scnptr = f_lhdr ? f_lhdr->s_scnptr : 0;

  /* Now we alter the contents of all the f_*hdr variables
     to correspond to what we want to dump.  */
265 266 267 268 269

  /* Indicate that the reloc information is no longer valid for ld (bind);
     we only update it enough to fake out the exec-time loader.  */
  f_hdr.f_flags |= (F_RELFLG | F_EXEC);

270
  f_ohdr.dsize = bss_start - f_ohdr.data_start;
271
  f_ohdr.bsize = 0;
Jim Blandy's avatar
Jim Blandy committed
272 273 274

  f_dhdr->s_size = f_ohdr.dsize;
  f_bhdr->s_size = f_ohdr.bsize;
275 276
  f_bhdr->s_paddr = f_ohdr.data_start + f_ohdr.dsize;
  f_bhdr->s_vaddr = f_ohdr.data_start + f_ohdr.dsize;
Jim Blandy's avatar
Jim Blandy committed
277 278 279

  /* fix scnptr's */
  {
280
    ulong ptr = section[0].s_scnptr;
Jim Blandy's avatar
Jim Blandy committed
281

282 283 284 285
    bias = -1;
    for (scns = 0; scns < f_hdr.f_nscns; scns++)
      {
	struct scnhdr *s = &section[scns];
Jim Blandy's avatar
Jim Blandy committed
286

287 288 289 290 291 292 293 294 295 296 297 298 299 300 301
	if (s->s_flags & STYP_PAD)        /* .pad sections omitted in AIX 4.1 */
	  {
	    /*
	     * the text_start should probably be o_algntext but that doesn't
	     * seem to change
	     */
	    if (f_ohdr.text_start != 0) /* && scns != 0 */
	      {
		s->s_size = 512 - (ptr % 512);
		if (s->s_size == 512)
		  s->s_size = 0;
	      }
	    s->s_scnptr = ptr;
	  }
	else if (s->s_flags & STYP_DATA)
Jim Blandy's avatar
Jim Blandy committed
302
	  s->s_scnptr = ptr;
303 304 305 306
	else if (!(s->s_flags & (STYP_TEXT | STYP_BSS)))
	  {
	    if (bias == -1)                /* if first section after bss */
	      bias = ptr - s->s_scnptr;
Jim Blandy's avatar
Jim Blandy committed
307

308 309 310
	    s->s_scnptr += bias;
	    ptr = s->s_scnptr;
	  }
311

312 313
	ptr = ptr + s->s_size;
      }
Jim Blandy's avatar
Jim Blandy committed
314 315 316
  }

  /* fix other pointers */
317 318 319
  for (scns = 0; scns < f_hdr.f_nscns; scns++)
    {
      struct scnhdr *s = &section[scns];
Jim Blandy's avatar
Jim Blandy committed
320

321 322 323 324 325 326 327 328 329 330
      if (s->s_relptr != 0)
	{
	  s->s_relptr += bias;
	}
      if (s->s_lnnoptr != 0)
	{
	  if (lnnoptr == 0) lnnoptr = s->s_lnnoptr;
	  s->s_lnnoptr += bias;
	}
    }
Jim Blandy's avatar
Jim Blandy committed
331 332

  if (f_hdr.f_symptr > 0L)
Jim Blandy's avatar
Jim Blandy committed
333
    {
Jim Blandy's avatar
Jim Blandy committed
334
      f_hdr.f_symptr += bias;
Jim Blandy's avatar
Jim Blandy committed
335 336
    }

Jim Blandy's avatar
Jim Blandy committed
337 338 339
  text_scnptr = f_thdr->s_scnptr;
  data_scnptr = f_dhdr->s_scnptr;
  load_scnptr = f_lhdr ? f_lhdr->s_scnptr : 0;
Jim Blandy's avatar
Jim Blandy committed
340

Jim Blandy's avatar
Jim Blandy committed
341 342 343 344
  if (write (new, &f_hdr, sizeof (f_hdr)) != sizeof (f_hdr))
    {
      PERROR (new_name);
    }
Jim Blandy's avatar
Jim Blandy committed
345

Jim Blandy's avatar
Jim Blandy committed
346 347 348
  if (f_hdr.f_opthdr > 0)
    {
      if (write (new, &f_ohdr, sizeof (f_ohdr)) != sizeof (f_ohdr))
Jim Blandy's avatar
Jim Blandy committed
349
	{
Jim Blandy's avatar
Jim Blandy committed
350 351 352
	  PERROR (new_name);
	}
    }
Jim Blandy's avatar
Jim Blandy committed
353

Jim Blandy's avatar
Jim Blandy committed
354 355 356 357 358 359 360
  for (scns = 0; scns < f_hdr.f_nscns; scns++) {
    struct scnhdr *s = &section[scns];
    if (write (new, s, sizeof (*s)) != sizeof (*s))
      {
	PERROR (new_name);
      }
  }
Jim Blandy's avatar
Jim Blandy committed
361

Jim Blandy's avatar
Jim Blandy committed
362 363 364 365
  return (0);
}

/* ****************************************************************
366

Jim Blandy's avatar
Jim Blandy committed
367 368 369 370
 *
 * Copy the text and data segments from memory to the new a.out
 */
static int
371
copy_text_and_data (int new)
Jim Blandy's avatar
Jim Blandy committed
372
{
373 374
  char *end;
  char *ptr;
Jim Blandy's avatar
Jim Blandy committed
375

376
  lseek (new, (long) text_scnptr, SEEK_SET);
Jim Blandy's avatar
Jim Blandy committed
377 378 379 380
  ptr = start_of_text () + text_scnptr;
  end = ptr + f_ohdr.tsize;
  write_segment (new, ptr, end);

381 382
  lseek (new, (long) data_scnptr, SEEK_SET);
  ptr = (char *) f_ohdr.data_start;
Jim Blandy's avatar
Jim Blandy committed
383 384 385 386 387 388
  end = ptr + f_ohdr.dsize;
  write_segment (new, ptr, end);

  return 0;
}

389
#define UnexBlockSz (1<<12)			/* read/write block size */
390 391
static void
write_segment (int new, char *ptr, char *end)
Jim Blandy's avatar
Jim Blandy committed
392
{
393
  int i, nwrite, ret;
Jim Blandy's avatar
Jim Blandy committed
394
  char buf[80];
395
  char zeros[UnexBlockSz];
Jim Blandy's avatar
Jim Blandy committed
396 397 398

  for (i = 0; ptr < end;)
    {
399 400
      /* distance to next block.  */
      nwrite = (((int) ptr + UnexBlockSz) & -UnexBlockSz) - (int) ptr;
Jim Blandy's avatar
Jim Blandy committed
401 402 403 404 405 406 407 408
      /* But not beyond specified end.  */
      if (nwrite > end - ptr) nwrite = end - ptr;
      ret = write (new, ptr, nwrite);
      /* If write gets a page fault, it means we reached
	 a gap between the old text segment and the old data segment.
	 This gap has probably been remapped into part of the text segment.
	 So write zeros for it.  */
      if (ret == -1 && errno == EFAULT)
Jim Blandy's avatar
Jim Blandy committed
409
	{
410
	  memset (zeros, 0, nwrite);
411
	  write (new, zeros, nwrite);
Jim Blandy's avatar
Jim Blandy committed
412
	}
Jim Blandy's avatar
Jim Blandy committed
413
      else if (nwrite != ret)
Jim Blandy's avatar
Jim Blandy committed
414
	{
Jim Blandy's avatar
Jim Blandy committed
415
	  sprintf (buf,
416 417
		   "unexec write failure: addr 0x%lx, fileno %d, size 0x%x, wrote 0x%x, errno %d",
		   (unsigned long)ptr, new, nwrite, ret, errno);
Jim Blandy's avatar
Jim Blandy committed
418
	  PERROR (buf);
Jim Blandy's avatar
Jim Blandy committed
419
	}
Jim Blandy's avatar
Jim Blandy committed
420 421 422 423 424 425 426 427 428 429 430
      i += nwrite;
      ptr += nwrite;
    }
}

/* ****************************************************************
 * copy_sym
 *
 * Copy the relocation information and symbol table from the a.out to the new
 */
static int
431
copy_sym (int new, int a_out, char *a_name, char *new_name)
Jim Blandy's avatar
Jim Blandy committed
432
{
433
  char page[UnexBlockSz];
Jim Blandy's avatar
Jim Blandy committed
434
  int n;
Jim Blandy's avatar
Jim Blandy committed
435

Jim Blandy's avatar
Jim Blandy committed
436 437
  if (a_out < 0)
    return 0;
Jim Blandy's avatar
Jim Blandy committed
438

439
  if (orig_load_scnptr == 0L)
Jim Blandy's avatar
Jim Blandy committed
440
    return 0;
Jim Blandy's avatar
Jim Blandy committed
441

442
  if (lnnoptr && lnnoptr < orig_load_scnptr) /* if there is line number info  */
443
    lseek (a_out, lnnoptr, SEEK_SET);  /* start copying from there */
Jim Blandy's avatar
Jim Blandy committed
444
  else
445
    lseek (a_out, orig_load_scnptr, SEEK_SET); /* Position a.out to symtab. */
Jim Blandy's avatar
Jim Blandy committed
446 447 448 449

  while ((n = read (a_out, page, sizeof page)) > 0)
    {
      if (write (new, page, n) != n)
Jim Blandy's avatar
Jim Blandy committed
450
	{
Jim Blandy's avatar
Jim Blandy committed
451
	  PERROR (new_name);
Jim Blandy's avatar
Jim Blandy committed
452 453
	}
    }
Jim Blandy's avatar
Jim Blandy committed
454 455 456 457 458 459 460 461 462 463
  if (n < 0)
    {
      PERROR (a_name);
    }
  return 0;
}

/* ****************************************************************
 * mark_x
 *
464
 * After successfully building the new a.out, mark it executable
Jim Blandy's avatar
Jim Blandy committed
465 466
 */
static void
467
mark_x (char *name)
Jim Blandy's avatar
Jim Blandy committed
468 469 470 471
{
  struct stat sbuf;
  int um;
  int new = 0;  /* for PERROR */
Jim Blandy's avatar
Jim Blandy committed
472

Jim Blandy's avatar
Jim Blandy committed
473 474 475 476 477 478 479 480 481 482 483
  um = umask (777);
  umask (um);
  if (stat (name, &sbuf) == -1)
    {
      PERROR (name);
    }
  sbuf.st_mode |= 0111 & ~um;
  if (chmod (name, sbuf.st_mode) == -1)
    PERROR (name);
}

484 485
static int
adjust_lnnoptrs (int writedesc, int readdesc, char *new_name)
Jim Blandy's avatar
Jim Blandy committed
486
{
487 488 489
  int nsyms;
  int naux;
  int new;
Jim Blandy's avatar
Jim Blandy committed
490 491 492 493 494 495
  struct syment symentry;
  union auxent auxentry;

  if (!lnnoptr || !f_hdr.f_symptr)
    return 0;

496
  if ((new = open (new_name, O_RDWR)) < 0)
Jim Blandy's avatar
Jim Blandy committed
497 498 499 500 501
    {
      PERROR (new_name);
      return -1;
    }

502
  lseek (new, f_hdr.f_symptr, SEEK_SET);
Jim Blandy's avatar
Jim Blandy committed
503 504 505
  for (nsyms = 0; nsyms < f_hdr.f_nsyms; nsyms++)
    {
      read (new, &symentry, SYMESZ);
506 507 508
      if (symentry.n_sclass == C_BINCL || symentry.n_sclass == C_EINCL)
	{
	  symentry.n_value += bias;
509
	  lseek (new, -SYMESZ, SEEK_CUR);
510 511 512
	  write (new, &symentry, SYMESZ);
	}

513
      for (naux = symentry.n_numaux; naux-- != 0; )
Jim Blandy's avatar
Jim Blandy committed
514 515 516
	{
	  read (new, &auxentry, AUXESZ);
	  nsyms++;
517 518 519 520
	  if (naux != 0              /* skip csect auxentry (last entry) */
              && (symentry.n_sclass == C_EXT || symentry.n_sclass == C_HIDEXT))
            {
              auxentry.x_sym.x_fcnary.x_fcn.x_lnnoptr += bias;
521
              lseek (new, -AUXESZ, SEEK_CUR);
522 523
              write (new, &auxentry, AUXESZ);
            }
Jim Blandy's avatar
Jim Blandy committed
524 525 526
	}
    }
  close (new);
Jim Blandy's avatar
Jim Blandy committed
527

528 529
  return 0;
}
Jim Blandy's avatar
Jim Blandy committed
530

531 532
static int
unrelocate_symbols (int new, int a_out, char *a_name, char *new_name)
Jim Blandy's avatar
Jim Blandy committed
533
{
534
  int i;
Jim Blandy's avatar
Jim Blandy committed
535
  LDHDR ldhdr;
536
  LDREL ldrel;
537
  ulong t_reloc = (ulong) &_text - f_ohdr.text_start;
538 539 540
#ifndef ALIGN_DATA_RELOC
  ulong d_reloc = (ulong) &_data - f_ohdr.data_start;
#else
541
  /* This worked (and was needed) before AIX 4.2.
542
     I have no idea why. -- Mike */
543
  ulong d_reloc = (ulong) &_data - ALIGN(f_ohdr.data_start, 2);
544
#endif
Jim Blandy's avatar
Jim Blandy committed
545 546 547 548 549
  int * p;

  if (load_scnptr == 0)
    return 0;

550
  lseek (a_out, orig_load_scnptr, SEEK_SET);
Jim Blandy's avatar
Jim Blandy committed
551 552 553 554 555 556 557 558 559
  if (read (a_out, &ldhdr, sizeof (ldhdr)) != sizeof (ldhdr))
    {
      PERROR (new_name);
    }

#define SYMNDX_TEXT	0
#define SYMNDX_DATA	1
#define SYMNDX_BSS	2

560 561 562 563 564
  for (i = 0; i < ldhdr.l_nreloc; i++)
    {
      lseek (a_out,
	     orig_load_scnptr + LDHDRSZ + LDSYMSZ*ldhdr.l_nsyms + LDRELSZ*i,
	     SEEK_SET);
Jim Blandy's avatar
Jim Blandy committed
565

566 567 568 569
      if (read (a_out, &ldrel, LDRELSZ) != LDRELSZ)
	{
	  PERROR (a_name);
	}
Jim Blandy's avatar
Jim Blandy committed
570 571

      /* move the BSS loader symbols to the DATA segment */
572
      if (ldrel.l_symndx == SYMNDX_BSS)
Jim Blandy's avatar
Jim Blandy committed
573
	{
574
	  ldrel.l_symndx = SYMNDX_DATA;
575

Jim Blandy's avatar
Jim Blandy committed
576 577
	  lseek (new,
		 load_scnptr + LDHDRSZ + LDSYMSZ*ldhdr.l_nsyms + LDRELSZ*i,
578
		 SEEK_SET);
Jim Blandy's avatar
Jim Blandy committed
579

580
	  if (write (new, &ldrel, LDRELSZ) != LDRELSZ)
Jim Blandy's avatar
Jim Blandy committed
581 582 583 584 585
	    {
	      PERROR (new_name);
	    }
	}

586
      if (ldrel.l_rsecnm == f_ohdr.o_sndata)
Jim Blandy's avatar
Jim Blandy committed
587 588 589
	{
	  int orig_int;

590
	  lseek (a_out,
591 592
                 orig_data_scnptr + (ldrel.l_vaddr - f_ohdr.data_start),
		 SEEK_SET);
Jim Blandy's avatar
Jim Blandy committed
593

594 595
	  if (read (a_out, (void *) &orig_int, sizeof (orig_int))
	      != sizeof (orig_int))
Jim Blandy's avatar
Jim Blandy committed
596 597 598 599
	    {
	      PERROR (a_name);
	    }

600
          p = (int *) (ldrel.l_vaddr + d_reloc);
601

602
	  switch (ldrel.l_symndx) {
Jim Blandy's avatar
Jim Blandy committed
603
	  case SYMNDX_TEXT:
604
	    orig_int = * p - t_reloc;
Jim Blandy's avatar
Jim Blandy committed
605 606 607 608
	    break;

	  case SYMNDX_DATA:
	  case SYMNDX_BSS:
609
	    orig_int = * p - d_reloc;
Jim Blandy's avatar
Jim Blandy committed
610 611 612
	    break;
	  }

613 614 615
          if (orig_int != * p)
            {
              lseek (new,
616 617
                     data_scnptr + (ldrel.l_vaddr - f_ohdr.data_start),
		     SEEK_SET);
618 619 620 621 622 623
              if (write (new, (void *) &orig_int, sizeof (orig_int))
                  != sizeof (orig_int))
                {
                  PERROR (new_name);
                }
            }
Jim Blandy's avatar
Jim Blandy committed
624 625
	}
    }
626
  return 0;
Jim Blandy's avatar
Jim Blandy committed
627
}
Miles Bader's avatar
Miles Bader committed
628

629 630 631 632 633 634 635 636 637 638 639 640
/*
 *	Return the address of the start of the text segment prior to
 *	doing an unexec.  After unexec the return value is undefined.
 *	See crt0.c for further explanation and _start.
 *
 */

char *
start_of_text (void)
{
  return ((char *) 0x10000000);
}