~ubuntu-branches/ubuntu/vivid/gcl/vivid

« back to all changes in this revision

Viewing changes to o/unexec.c

  • Committer: Bazaar Package Importer
  • Author(s): Camm Maguire
  • Date: 2002-03-04 14:29:59 UTC
  • Revision ID: james.westby@ubuntu.com-20020304142959-dey14w08kr7lldu3
Tags: upstream-2.5.0.cvs20020219
ImportĀ upstreamĀ versionĀ 2.5.0.cvs20020219

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 1985,86,87,88,92,93,94 Free Software Foundation, Inc.
 
2
 
 
3
This file is part of GNU Emacs.
 
4
 
 
5
GNU Emacs is free software; you can redistribute it and/or modify
 
6
it under the terms of the GNU General Public License as published by
 
7
the Free Software Foundation; either version 2, or (at your option)
 
8
any later version.
 
9
 
 
10
GNU Emacs is distributed in the hope that it will be useful,
 
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
GNU General Public License for more details.
 
14
 
 
15
You should have received a copy of the GNU General Public License
 
16
along with GNU Emacs; see the file COPYING.  If not, write to
 
17
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
 
18
 
 
19
 
 
20
/*
 
21
 * unexec.c - Convert a running program into an a.out file.
 
22
 *
 
23
 * Author:      Spencer W. Thomas
 
24
 *              Computer Science Dept.
 
25
 *              University of Utah
 
26
 * Date:        Tue Mar  2 1982
 
27
 * Modified heavily since then.
 
28
 *
 
29
 * Synopsis:
 
30
 *      unexec (new_name, a_name, data_start, bss_start, entry_address)
 
31
 *      char *new_name, *a_name;
 
32
 *      unsigned data_start, bss_start, entry_address;
 
33
 *
 
34
 * Takes a snapshot of the program and makes an a.out format file in the
 
35
 * file named by the string argument new_name.
 
36
 * If a_name is non-NULL, the symbol table will be taken from the given file.
 
37
 * On some machines, an existing a_name file is required.
 
38
 *
 
39
 * The boundaries within the a.out file may be adjusted with the data_start
 
40
 * and bss_start arguments.  Either or both may be given as 0 for defaults.
 
41
 *
 
42
 * Data_start gives the boundary between the text segment and the data
 
43
 * segment of the program.  The text segment can contain shared, read-only
 
44
 * program code and literal data, while the data segment is always unshared
 
45
 * and unprotected.  Data_start gives the lowest unprotected address.
 
46
 * The value you specify may be rounded down to a suitable boundary
 
47
 * as required by the machine you are using.
 
48
 *
 
49
 * Specifying zero for data_start means the boundary between text and data
 
50
 * should not be the same as when the program was loaded.
 
51
 * If NO_REMAP is defined, the argument data_start is ignored and the
 
52
 * segment boundaries are never changed.
 
53
 *
 
54
 * Bss_start indicates how much of the data segment is to be saved in the
 
55
 * a.out file and restored when the program is executed.  It gives the lowest
 
56
 * unsaved address, and is rounded up to a page boundary.  The default when 0
 
57
 * is given assumes that the entire data segment is to be stored, including
 
58
 * the previous data and bss as well as any additional storage allocated with
 
59
 * break (2).
 
60
 *
 
61
 * The new file is set up to start at entry_address.
 
62
 *
 
63
 * If you make improvements I'd like to get them too.
 
64
 * harpo!utah-cs!thomas, thomas@Utah-20
 
65
 *
 
66
 */
 
67
 
 
68
/* Modified to support SysVr3 shared libraries by James Van Artsdalen
 
69
 * of Dell Computer Corporation.  james@bigtex.cactus.org.
 
70
 */
 
71
 
 
72
/* There are several compilation parameters affecting unexec:
 
73
 
 
74
* COFF
 
75
 
 
76
Define this if your system uses COFF for executables.
 
77
 
 
78
* COFF_ENCAPSULATE
 
79
 
 
80
Define this if you are using the GNU coff encapsulated a.out format.
 
81
This is closer to a.out than COFF. You should *not* define COFF if
 
82
you define COFF_ENCAPSULATE
 
83
 
 
84
Otherwise we assume you use Berkeley format.
 
85
 
 
86
* NO_REMAP
 
87
 
 
88
Define this if you do not want to try to save Emacs's pure data areas
 
89
as part of the text segment.
 
90
 
 
91
Saving them as text is good because it allows users to share more.
 
92
 
 
93
However, on machines that locate the text area far from the data area,
 
94
the boundary cannot feasibly be moved.  Such machines require
 
95
NO_REMAP.
 
96
 
 
97
Also, remapping can cause trouble with the built-in startup routine
 
98
/lib/crt0.o, which defines `environ' as an initialized variable.
 
99
Dumping `environ' as pure does not work!  So, to use remapping,
 
100
you must write a startup routine for your machine in Emacs's crt0.c.
 
101
If NO_REMAP is defined, Emacs uses the system's crt0.o.
 
102
 
 
103
* SECTION_ALIGNMENT
 
104
 
 
105
Some machines that use COFF executables require that each section
 
106
start on a certain boundary *in the COFF file*.  Such machines should
 
107
define SECTION_ALIGNMENT to a mask of the low-order bits that must be
 
108
zero on such a boundary.  This mask is used to control padding between
 
109
segments in the COFF file.
 
110
 
 
111
If SECTION_ALIGNMENT is not defined, the segments are written
 
112
consecutively with no attempt at alignment.  This is right for
 
113
unmodified system V.
 
114
 
 
115
* SEGMENT_MASK
 
116
 
 
117
Some machines require that the beginnings and ends of segments
 
118
*in core* be on certain boundaries.  For most machines, a page
 
119
boundary is sufficient.  That is the default.  When a larger
 
120
boundary is needed, define SEGMENT_MASK to a mask of
 
121
the bits that must be zero on such a boundary.
 
122
 
 
123
* A_TEXT_OFFSET(HDR)
 
124
 
 
125
Some machines count the a.out header as part of the size of the text
 
126
segment (a_text); they may actually load the header into core as the
 
127
first data in the text segment.  Some have additional padding between
 
128
the header and the real text of the program that is counted in a_text.
 
129
 
 
130
For these machines, define A_TEXT_OFFSET(HDR) to examine the header
 
131
structure HDR and return the number of bytes to add to `a_text'
 
132
before writing it (above and beyond the number of bytes of actual
 
133
program text).  HDR's standard fields are already correct, except that
 
134
this adjustment to the `a_text' field has not yet been made;
 
135
thus, the amount of offset can depend on the data in the file.
 
136
  
 
137
* A_TEXT_SEEK(HDR)
 
138
 
 
139
If defined, this macro specifies the number of bytes to seek into the
 
140
a.out file before starting to write the text segment.
 
141
 
 
142
* EXEC_MAGIC
 
143
 
 
144
For machines using COFF, this macro, if defined, is a value stored
 
145
into the magic number field of the output file.
 
146
 
 
147
* ADJUST_EXEC_HEADER
 
148
 
 
149
This macro can be used to generate statements to adjust or
 
150
initialize nonstandard fields in the file header
 
151
 
 
152
* ADDR_CORRECT(ADDR)
 
153
 
 
154
Macro to correct an int which is the bit pattern of a pointer to a byte
 
155
into an int which is the number of a byte.
 
156
 
 
157
This macro has a default definition which is usually right.
 
158
This default definition is a no-op on most machines (where a
 
159
pointer looks like an int) but not on all machines.
 
160
 
 
161
*/
 
162
 
 
163
#ifndef emacs
 
164
#define PERROR(arg) perror (arg); return -1
 
165
#else
 
166
#define IN_UNEXEC
 
167
#include "config.h"
 
168
#define PERROR(file) report_error (file, new)
 
169
#endif
 
170
 
 
171
#ifndef CANNOT_DUMP  /* all rest of file!  */
 
172
 
 
173
#ifdef COFF_ENCAPSULATE
 
174
int need_coff_header = 1;
 
175
#include <coff-encap/a.out.encap.h> /* The location might be a poor assumption */
 
176
#else
 
177
#ifdef MSDOS
 
178
#include <coff.h>
 
179
#define filehdr external_filehdr
 
180
#define scnhdr external_scnhdr
 
181
#define syment external_syment
 
182
#define auxent external_auxent
 
183
#define n_numaux e_numaux
 
184
#define n_type e_type
 
185
struct aouthdr
 
186
{
 
187
  unsigned short        magic;  /* type of file                         */
 
188
  unsigned short        vstamp; /* version stamp                        */
 
189
  unsigned long         tsize;  /* text size in bytes, padded to FW bdry*/
 
190
  unsigned long         dsize;  /* initialized data "  "                */
 
191
  unsigned long         bsize;  /* uninitialized data "   "             */
 
192
  unsigned long         entry;  /* entry pt.                            */
 
193
  unsigned long         text_start;/* base of text used for this file */
 
194
  unsigned long         data_start;/* base of data used for this file */
 
195
};
 
196
 
 
197
 
 
198
#else /* not MSDOS */
 
199
#include <a.out.h>
 
200
#endif /* not MSDOS */
 
201
#endif
 
202
 
 
203
/* Define getpagesize if the system does not.
 
204
   Note that this may depend on symbols defined in a.out.h.  */
 
205
#include "getpagesize.h"
 
206
 
 
207
#ifndef makedev                 /* Try to detect types.h already loaded */
 
208
#include <sys/types.h>
 
209
#endif /* makedev */
 
210
#include <stdio.h>
 
211
#include <sys/stat.h>
 
212
#include <errno.h>
 
213
 
 
214
#include <sys/file.h>   /* Must be after sys/types.h for USG and BSD4_1*/
 
215
 
 
216
#ifdef USG5
 
217
#include <fcntl.h>
 
218
#endif
 
219
 
 
220
#ifndef O_RDONLY
 
221
#define O_RDONLY 0
 
222
#endif
 
223
#ifndef O_RDWR
 
224
#define O_RDWR 2
 
225
#endif
 
226
 
 
227
#ifdef UNIXSAVE 
 
228
extern char etext;
 
229
#endif
 
230
 
 
231
#ifndef start_of_data
 
232
extern char *start_of_text ();          /* Start of text */
 
233
extern char *start_of_data ();          /* Start of initialized data */
 
234
#endif
 
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 HPUX
 
250
extern void *sbrk ();
 
251
#else
 
252
#if 0
 
253
/* Some systems with __STDC__ compilers still declare this `char *' in some
 
254
   header file, and our declaration conflicts.  The return value is always
 
255
   cast, so it should be harmless to leave it undefined.  Hopefully
 
256
   machines with different size pointers and ints declare sbrk in a header
 
257
   file.  */
 
258
#ifdef __STDC__
 
259
extern void *sbrk ();
 
260
#else
 
261
extern char *sbrk ();
 
262
#endif /* __STDC__ */
 
263
#endif
 
264
#endif /* HPUX */
 
265
 
 
266
#define SYMS_START ((long) N_SYMOFF (ohdr))
 
267
 
 
268
/* Some machines override the structure name for an a.out header.  */
 
269
#ifndef EXEC_HDR_TYPE
 
270
#define EXEC_HDR_TYPE struct exec
 
271
#endif
 
272
 
 
273
#ifdef HPUX
 
274
#ifdef HP9000S200_ID
 
275
#define MY_ID HP9000S200_ID
 
276
#else
 
277
#include <model.h>
 
278
#define MY_ID MYSYS
 
279
#endif /* no HP9000S200_ID */
 
280
static MAGIC OLDMAGIC = {MY_ID, SHARE_MAGIC};
 
281
static MAGIC NEWMAGIC = {MY_ID, DEMAND_MAGIC};
 
282
#define N_TXTOFF(x) TEXT_OFFSET(x)
 
283
#define N_SYMOFF(x) LESYM_OFFSET(x)
 
284
static EXEC_HDR_TYPE hdr, ohdr;
 
285
 
 
286
#else /* not HPUX */
 
287
 
 
288
#if defined (USG) && !defined (IBMAIX) && !defined (IRIS) && !defined (COFF_ENCAPSULATE) && !defined (LINUX)
 
289
static struct bhdr hdr, ohdr;
 
290
#define a_magic fmagic
 
291
#define a_text tsize
 
292
#define a_data dsize
 
293
#define a_bss bsize
 
294
#define a_syms ssize
 
295
#define a_trsize rtsize
 
296
#define a_drsize rdsize
 
297
#define a_entry entry
 
298
#define N_BADMAG(x) \
 
299
    (((x).fmagic)!=OMAGIC && ((x).fmagic)!=NMAGIC &&\
 
300
     ((x).fmagic)!=FMAGIC && ((x).fmagic)!=IMAGIC)
 
301
#define NEWMAGIC FMAGIC
 
302
#else /* IRIS or IBMAIX or not USG */
 
303
static EXEC_HDR_TYPE hdr, ohdr;
 
304
#define NEWMAGIC ZMAGIC
 
305
#endif /* IRIS or IBMAIX not USG */
 
306
#endif /* not HPUX */
 
307
 
 
308
static int unexec_text_start;
 
309
static int unexec_data_start;
 
310
 
 
311
#ifdef COFF_ENCAPSULATE
 
312
/* coffheader is defined in the GNU a.out.encap.h file.  */
 
313
struct coffheader coffheader;
 
314
#endif
 
315
 
 
316
#endif /* not COFF */
 
317
 
 
318
static int pagemask;
 
319
 
 
320
/* Correct an int which is the bit pattern of a pointer to a byte
 
321
   into an int which is the number of a byte.
 
322
   This is a no-op on ordinary machines, but not on all.  */
 
323
 
 
324
#ifndef ADDR_CORRECT   /* Let m-*.h files override this definition */
 
325
#define ADDR_CORRECT(x) ((char *)(x) - (char*)0)
 
326
#endif
 
327
 
 
328
#ifdef emacs
 
329
 
 
330
#include "lisp.h"
 
331
 
 
332
static
 
333
report_error (file, fd)
 
334
     char *file;
 
335
     int fd;
 
336
{
 
337
  if (fd)
 
338
    close (fd);
 
339
  report_file_error ("Cannot unexec", Fcons (build_string (file), Qnil));
 
340
}
 
341
#endif /* emacs */
 
342
 
 
343
#define ERROR0(msg) report_error_1 (new, msg, 0, 0); return -1
 
344
#define ERROR1(msg,x) report_error_1 (new, msg, x, 0); return -1
 
345
#define ERROR2(msg,x,y) report_error_1 (new, msg, x, y); return -1
 
346
 
 
347
static
 
348
report_error_1 (fd, msg, a1, a2)
 
349
     int fd;
 
350
     char *msg;
 
351
     int a1, a2;
 
352
{
 
353
  close (fd);
 
354
#ifdef emacs
 
355
  error (msg, a1, a2);
 
356
#else
 
357
  fprintf (stderr, msg, a1, a2);
 
358
  fprintf (stderr, "\n");
 
359
#endif
 
360
}
 
361
 
 
362
static int make_hdr ();
 
363
static int copy_text_and_data ();
 
364
static int copy_sym ();
 
365
static void mark_x ();
 
366
 
 
367
/* ****************************************************************
 
368
 * unexec
 
369
 *
 
370
 * driving logic.
 
371
 */
 
372
unexec (new_name, a_name, data_start, bss_start, entry_address)
 
373
     char *new_name, *a_name;
 
374
     unsigned data_start, bss_start, entry_address;
 
375
{
 
376
  int new, a_out = -1;
 
377
 
 
378
  if (a_name && (a_out = open (a_name, O_RDONLY)) < 0)
 
379
    {
 
380
      PERROR (a_name);
 
381
    }
 
382
  if ((new = creat (new_name, 0666)) < 0)
 
383
    {
 
384
      PERROR (new_name);
 
385
    }
 
386
 
 
387
  if (make_hdr (new, a_out, data_start, bss_start, entry_address, a_name, new_name) < 0
 
388
      || copy_text_and_data (new, a_out) < 0
 
389
      || copy_sym (new, a_out, a_name, new_name) < 0
 
390
#ifdef COFF
 
391
#ifndef COFF_BSD_SYMBOLS
 
392
      || adjust_lnnoptrs (new, a_out, new_name) < 0
 
393
#endif
 
394
#endif
 
395
      )
 
396
    {
 
397
      close (new);
 
398
      /* unlink (new_name);             /* Failed, unlink new a.out */
 
399
      return -1;        
 
400
    }
 
401
 
 
402
  close (new);
 
403
  if (a_out >= 0)
 
404
    close (a_out);
 
405
  mark_x (new_name);
 
406
  return 0;
 
407
}
 
408
 
 
409
/* ****************************************************************
 
410
 * make_hdr
 
411
 *
 
412
 * Make the header in the new a.out from the header in core.
 
413
 * Modify the text and data sizes.
 
414
 */
 
415
static int
 
416
make_hdr (new, a_out, data_start, bss_start, entry_address, a_name, new_name)
 
417
     int new, a_out;
 
418
     unsigned data_start, bss_start, entry_address;
 
419
     char *a_name;
 
420
     char *new_name;
 
421
{
 
422
  int tem;
 
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
  register 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
 
 
621
  if (write (new, &f_hdr, sizeof (f_hdr)) != sizeof (f_hdr))
 
622
    {
 
623
      PERROR (new_name);
 
624
    }
 
625
 
 
626
  if (write (new, &f_ohdr, sizeof (f_ohdr)) != sizeof (f_ohdr))
 
627
    {
 
628
      PERROR (new_name);
 
629
    }
 
630
 
 
631
#ifndef USG_SHARED_LIBRARIES
 
632
 
 
633
  if (write (new, &f_thdr, sizeof (f_thdr)) != sizeof (f_thdr))
 
634
    {
 
635
      PERROR (new_name);
 
636
    }
 
637
 
 
638
  if (write (new, &f_dhdr, sizeof (f_dhdr)) != sizeof (f_dhdr))
 
639
    {
 
640
      PERROR (new_name);
 
641
    }
 
642
 
 
643
  if (write (new, &f_bhdr, sizeof (f_bhdr)) != sizeof (f_bhdr))
 
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
        {
 
674
          if (write (new, &f_thdr, sizeof (f_thdr)) != sizeof (f_thdr))
 
675
            PERROR (new_name);
 
676
        }
 
677
      else if (!strcmp (scntemp.s_name, f_dhdr.s_name)) /* .data */
 
678
        {
 
679
          if (write (new, &f_dhdr, sizeof (f_dhdr)) != sizeof (f_dhdr))
 
680
            PERROR (new_name);
 
681
        }
 
682
      else if (!strcmp (scntemp.s_name, f_bhdr.s_name)) /* .bss */
 
683
        {
 
684
          if (write (new, &f_bhdr, sizeof (f_bhdr)) != sizeof (f_bhdr))
 
685
            PERROR (new_name);
 
686
        }
 
687
      else
 
688
        {
 
689
          if (scntemp.s_scnptr)
 
690
            scntemp.s_scnptr += bias;
 
691
          if (write (new, &scntemp, sizeof (scntemp)) != sizeof (scntemp))
 
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
 
705
      if (read (a_out, &coffheader, sizeof coffheader) != sizeof coffheader)
 
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
 
714
      if (read (a_out, &ohdr, sizeof hdr) != sizeof hdr)
 
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
 
733
#ifdef MSDOS    /* Demacs 1.1.1 91/10/16 HIRANO Satoshi */
 
734
      bzero ((void *)&hdr, sizeof hdr);
 
735
#else
 
736
      bzero (&hdr, sizeof hdr);
 
737
#endif
 
738
#endif
 
739
    }
 
740
 
 
741
  unexec_text_start = (long) start_of_text ();
 
742
  unexec_data_start = data_start;
 
743
 
 
744
  /* Machine-dependent fixup for header, or maybe for unexec_text_start */
 
745
#ifdef ADJUST_EXEC_HEADER
 
746
  ADJUST_EXEC_HEADER;
 
747
#endif /* ADJUST_EXEC_HEADER */
 
748
 
 
749
  hdr.a_trsize = 0;
 
750
  hdr.a_drsize = 0;
 
751
  if (entry_address != 0)
 
752
    hdr.a_entry = entry_address;
 
753
 
 
754
  hdr.a_bss = bss_end - bss_start;
 
755
  hdr.a_data = bss_start - data_start;
 
756
#ifdef NO_REMAP
 
757
  hdr.a_text = ohdr.a_text;
 
758
#else /* not NO_REMAP */
 
759
  hdr.a_text = data_start - unexec_text_start;
 
760
 
 
761
#ifdef A_TEXT_OFFSET
 
762
  hdr.a_text += A_TEXT_OFFSET (ohdr);
 
763
#endif
 
764
 
 
765
#endif /* not NO_REMAP */
 
766
 
 
767
#ifdef COFF_ENCAPSULATE
 
768
  /* We are encapsulating BSD format within COFF format.  */
 
769
  {
 
770
    struct coffscn *tp, *dp, *bp;
 
771
    tp = &coffheader.scns[0];
 
772
    dp = &coffheader.scns[1];
 
773
    bp = &coffheader.scns[2];
 
774
    tp->s_size = hdr.a_text + sizeof(struct exec);
 
775
    dp->s_paddr = data_start;
 
776
    dp->s_vaddr = data_start;
 
777
    dp->s_size = hdr.a_data;
 
778
    bp->s_paddr = dp->s_vaddr + dp->s_size;
 
779
    bp->s_vaddr = bp->s_paddr;
 
780
    bp->s_size = hdr.a_bss;
 
781
    coffheader.tsize = tp->s_size;
 
782
    coffheader.dsize = dp->s_size;
 
783
    coffheader.bsize = bp->s_size;
 
784
    coffheader.text_start = tp->s_vaddr;
 
785
    coffheader.data_start = dp->s_vaddr;
 
786
  }
 
787
  if (write (new, &coffheader, sizeof coffheader) != sizeof coffheader)
 
788
    {
 
789
      PERROR(new_name);
 
790
    }
 
791
#endif /* COFF_ENCAPSULATE */
 
792
 
 
793
  if (write (new, &hdr, sizeof hdr) != sizeof hdr)
 
794
    {
 
795
      PERROR (new_name);
 
796
    }
 
797
 
 
798
#if 0 /* This #ifndef caused a bug on Linux when using QMAGIC.  */
 
799
  /* This adjustment was done above only #ifndef NO_REMAP,
 
800
     so only undo it now #ifndef NO_REMAP.  */
 
801
  /* #ifndef NO_REMAP  */
 
802
#endif
 
803
#ifdef A_TEXT_OFFSET
 
804
  hdr.a_text -= A_TEXT_OFFSET (ohdr);
 
805
#endif
 
806
 
 
807
  return 0;
 
808
 
 
809
#endif /* not COFF */
 
810
}
 
811
 
 
812
/* ****************************************************************
 
813
 * copy_text_and_data
 
814
 *
 
815
 * Copy the text and data segments from memory to the new a.out
 
816
 */
 
817
static int
 
818
copy_text_and_data (new, a_out)
 
819
     int new, a_out;
 
820
{
 
821
  register char *end;
 
822
  register char *ptr;
 
823
 
 
824
#ifdef COFF
 
825
 
 
826
#ifdef USG_SHARED_LIBRARIES
 
827
 
 
828
  int scns;
 
829
  struct scnhdr scntemp;                /* Temporary section header */
 
830
 
 
831
  /* The purpose of this code is to write out the new file's section
 
832
   * contents.
 
833
   *
 
834
   * Step through the section table.  If we know the section (.text,
 
835
   * .data) do the appropriate thing.  Otherwise, if the section has
 
836
   * no allocated space in the file (.bss), do nothing.  Otherwise,
 
837
   * the section has space allocated in the file, and is not a section
 
838
   * we know.  So just copy it.
 
839
   */
 
840
 
 
841
  lseek (a_out, sizeof (struct filehdr) + sizeof (struct aouthdr), 0);
 
842
 
 
843
  for (scns = f_hdr.f_nscns; scns > 0; scns--)
 
844
    {
 
845
      if (read (a_out, &scntemp, sizeof (scntemp)) != sizeof (scntemp))
 
846
        PERROR ("temacs");
 
847
 
 
848
      if (!strcmp (scntemp.s_name, ".text"))
 
849
        {
 
850
          lseek (new, (long) text_scnptr, 0);
 
851
          ptr = (char *) f_ohdr.text_start;
 
852
          end = ptr + f_ohdr.tsize;
 
853
          write_segment (new, ptr, end);
 
854
        }
 
855
      else if (!strcmp (scntemp.s_name, ".data"))
 
856
        {
 
857
          lseek (new, (long) data_scnptr, 0);
 
858
          ptr = (char *) f_ohdr.data_start;
 
859
          end = ptr + f_ohdr.dsize;
 
860
          write_segment (new, ptr, end);
 
861
        }
 
862
      else if (!scntemp.s_scnptr)
 
863
        ; /* do nothing - no data for this section */
 
864
      else
 
865
        {
 
866
          char page[BUFSIZ];
 
867
          int size, n;
 
868
          long old_a_out_ptr = lseek (a_out, 0, 1);
 
869
 
 
870
          lseek (a_out, scntemp.s_scnptr, 0);
 
871
          for (size = scntemp.s_size; size > 0; size -= sizeof (page))
 
872
            {
 
873
              n = size > sizeof (page) ? sizeof (page) : size;
 
874
              if (read (a_out, page, n) != n || write (new, page, n) != n)
 
875
                PERROR ("emacs");
 
876
            }
 
877
          lseek (a_out, old_a_out_ptr, 0);
 
878
        }
 
879
    }
 
880
 
 
881
#else /* COFF, but not USG_SHARED_LIBRARIES */
 
882
 
 
883
  lseek (new, (long) text_scnptr, 0);
 
884
  ptr = (char *) f_ohdr.text_start;
 
885
#ifdef HEADER_INCL_IN_TEXT
 
886
  /* For Gould UTX/32, text starts after headers */
 
887
  ptr = (char *) (ptr + text_scnptr);
 
888
#endif /* HEADER_INCL_IN_TEXT */
 
889
  end = ptr + f_ohdr.tsize;
 
890
  write_segment (new, ptr, end);
 
891
 
 
892
  lseek (new, (long) data_scnptr, 0);
 
893
  ptr = (char *) f_ohdr.data_start;
 
894
  end = ptr + f_ohdr.dsize;
 
895
  write_segment (new, ptr, end);
 
896
 
 
897
#endif /* USG_SHARED_LIBRARIES */
 
898
 
 
899
#else /* if not COFF */
 
900
 
 
901
/* Some machines count the header as part of the text segment.
 
902
   That is to say, the header appears in core
 
903
   just before the address that start_of_text returns.
 
904
   For them, N_TXTOFF is the place where the header goes.
 
905
   We must adjust the seek to the place after the header.
 
906
   Note that at this point hdr.a_text does *not* count
 
907
   the extra A_TEXT_OFFSET bytes, only the actual bytes of code.  */
 
908
 
 
909
#ifdef A_TEXT_SEEK
 
910
  lseek (new, (long) A_TEXT_SEEK (hdr), 0);
 
911
#else
 
912
  lseek (new, (long) N_TXTOFF (hdr), 0);
 
913
#endif /* no A_TEXT_SEEK */
 
914
 
 
915
#ifdef RISCiX
 
916
 
 
917
  /* Acorn's RISC-iX has a wacky way of initialising the position of the heap.
 
918
   * There is a little table in crt0.o that is filled at link time with
 
919
   * the min and current brk positions, among other things.  When start
 
920
   * runs, it copies the table to where these parameters live during
 
921
   * execution.  This data is in text space, so it cannot be modified here
 
922
   * before saving the executable, so the data is written manually.  In
 
923
   * addition, the table does not have a label, and the nearest accessable
 
924
   * label (mcount) is not prefixed with a '_', thus making it inaccessable
 
925
   * from within C programs.  To overcome this, emacs's executable is passed
 
926
   * through the command 'nm %s | fgrep mcount' into a pipe, and the
 
927
   * resultant output is then used to find the address of 'mcount'.  As far as
 
928
   * is possible to determine, in RISC-iX releases prior to 1.2, the negative
 
929
   * offset of the table from mcount is 0x2c, whereas from 1.2 onwards it is
 
930
   * 0x30.  bss_end has been rounded up to page boundary.  This solution is
 
931
   * based on suggestions made by Kevin Welton and Steve Hunt of Acorn, and
 
932
   * avoids the need for a custom version of crt0.o for emacs which has its
 
933
   * table in data space.
 
934
   */
 
935
 
 
936
  {
 
937
    char command[1024];
 
938
    char errbuf[1024];
 
939
    char address_text[32];
 
940
    int  proforma[4];
 
941
    FILE *pfile;
 
942
    char *temp_ptr;
 
943
    char c;
 
944
    int mcount_address, mcount_offset, count;
 
945
    extern char *_execname;
 
946
   
 
947
 
 
948
    /* The use of _execname is incompatible with RISCiX 1.1 */
 
949
    sprintf (command, "nm %s | fgrep mcount", _execname);
 
950
 
 
951
    if ( (pfile = popen(command, "r")) == NULL)
 
952
    {
 
953
      sprintf (errbuf, "Could not open pipe");
 
954
      PERROR (errbuf);
 
955
    }
 
956
 
 
957
    count=0;
 
958
    while ( ((c=getc(pfile)) != EOF) && (c != ' ') && (count < 31))
 
959
      address_text[count++]=c;
 
960
    address_text[count]=0;
 
961
 
 
962
    if ((count == 0) || pclose(pfile) != NULL)
 
963
    {
 
964
      sprintf (errbuf, "Failed to execute the command '%s'\n", command);
 
965
      PERROR (errbuf);
 
966
    }  
 
967
 
 
968
    sscanf(address_text, "%x", &mcount_address);
 
969
    ptr = (char *) unexec_text_start;
 
970
    mcount_offset = (char *)mcount_address - ptr;
 
971
 
 
972
#ifdef RISCiX_1_1
 
973
#define EDATA_OFFSET 0x2c
 
974
#else
 
975
#define EDATA_OFFSET 0x30
 
976
#endif
 
977
 
 
978
    end = ptr + mcount_offset - EDATA_OFFSET;
 
979
 
 
980
    write_segment (new, ptr, end);
 
981
 
 
982
    proforma[0] = bss_end;      /* becomes _edata */
 
983
    proforma[1] = bss_end;      /* becomes _end */
 
984
    proforma[2] = bss_end;      /* becomes _minbrk */
 
985
    proforma[3] = bss_end;      /* becomes _curbrk */
 
986
 
 
987
    write (new, proforma, 16);
 
988
 
 
989
    temp_ptr = ptr;
 
990
    ptr = end + 16;
 
991
    end = temp_ptr + hdr.a_text;
 
992
 
 
993
    write_segment (new, ptr, end);
 
994
  }
 
995
 
 
996
#else /* !RISCiX */
 
997
  ptr = (char *) unexec_text_start;
 
998
  end = ptr + hdr.a_text;
 
999
  write_segment (new, ptr, end);
 
1000
#endif /* RISCiX */
 
1001
 
 
1002
  ptr = (char *) unexec_data_start;
 
1003
  end = ptr + hdr.a_data;
 
1004
/*  This lseek is certainly incorrect when A_TEXT_OFFSET
 
1005
    and I believe it is a no-op otherwise.
 
1006
    Let's see if its absence ever fails.  */
 
1007
/*  lseek (new, (long) N_TXTOFF (hdr) + hdr.a_text, 0); */
 
1008
  write_segment (new, ptr, end);
 
1009
 
 
1010
#endif /* not COFF */
 
1011
 
 
1012
  return 0;
 
1013
}
 
1014
 
 
1015
write_segment (new, ptr, end)
 
1016
     int new;
 
1017
     register char *ptr, *end;
 
1018
{
 
1019
  register int i, nwrite, ret;
 
1020
  char buf[80];
 
1021
  extern int errno;
 
1022
  char zeros[128];
 
1023
  int amt_to_write = (1 << 13);
 
1024
 
 
1025
  bzero (zeros, sizeof zeros);
 
1026
 
 
1027
  for (i = 0; ptr < end;)
 
1028
    {
 
1029
      /* distance to next multiple of amt_to_write .  */
 
1030
  AGAIN:
 
1031
      nwrite = (((int) ptr + amt_to_write) & -amt_to_write) - (int) ptr;
 
1032
      /* But not beyond specified end.  */
 
1033
      if (nwrite > end - ptr) nwrite = end - ptr;
 
1034
      ret = write (new, ptr, nwrite);
 
1035
      /* If write gets a page fault, it means we reached
 
1036
         a gap between the old text segment and the old data segment.
 
1037
         This gap has probably been remapped into part of the text segment.
 
1038
         So write zeros for it.  */
 
1039
      if (ret == -1
 
1040
#ifdef EFAULT
 
1041
          && errno == EFAULT
 
1042
#endif
 
1043
          )
 
1044
       { if (amt_to_write > sizeof(zeros))
 
1045
           { amt_to_write =  sizeof(zeros);
 
1046
             goto AGAIN;
 
1047
           }
 
1048
        write (new, zeros, nwrite);
 
1049
       }
 
1050
      else if (nwrite != ret)
 
1051
        {
 
1052
          sprintf (buf,
 
1053
                   "unexec write failure: addr 0x%x, fileno %d, size 0x%x, wrote 0x%x, errno %d",
 
1054
                   ptr, new, nwrite, ret, errno);
 
1055
          PERROR (buf);
 
1056
        }
 
1057
      i += nwrite;
 
1058
      ptr += nwrite;
 
1059
    }
 
1060
}
 
1061
 
 
1062
/* ****************************************************************
 
1063
 * copy_sym
 
1064
 *
 
1065
 * Copy the relocation information and symbol table from the a.out to the new
 
1066
 */
 
1067
static int
 
1068
copy_sym (new, a_out, a_name, new_name)
 
1069
     int new, a_out;
 
1070
     char *a_name, *new_name;
 
1071
{
 
1072
  char page[1024];
 
1073
  int n;
 
1074
 
 
1075
  if (a_out < 0)
 
1076
    return 0;
 
1077
 
 
1078
#ifdef COFF
 
1079
  if (SYMS_START == 0L)
 
1080
    return 0;
 
1081
#endif  /* COFF */
 
1082
 
 
1083
#ifdef COFF
 
1084
  if (lnnoptr)                  /* if there is line number info */
 
1085
    lseek (a_out, lnnoptr, 0);  /* start copying from there */
 
1086
  else
 
1087
#endif /* COFF */
 
1088
    lseek (a_out, SYMS_START, 0);       /* Position a.out to symtab. */
 
1089
 
 
1090
  while ((n = read (a_out, page, sizeof page)) > 0)
 
1091
    {
 
1092
      if (write (new, page, n) != n)
 
1093
        {
 
1094
          PERROR (new_name);
 
1095
        }
 
1096
    }
 
1097
  if (n < 0)
 
1098
    {
 
1099
      PERROR (a_name);
 
1100
    }
 
1101
  return 0;
 
1102
}
 
1103
 
 
1104
/* ****************************************************************
 
1105
 * mark_x
 
1106
 *
 
1107
 * After successfully building the new a.out, mark it executable
 
1108
 */
 
1109
static void
 
1110
mark_x (name)
 
1111
     char *name;
 
1112
{
 
1113
  struct stat sbuf;
 
1114
  int um;
 
1115
  int new = 0;  /* for PERROR */
 
1116
 
 
1117
  um = umask (777);
 
1118
  umask (um);
 
1119
  if (stat (name, &sbuf) == -1)
 
1120
    {
 
1121
      PERROR (name);
 
1122
    }
 
1123
  sbuf.st_mode |= 0111 & ~um;
 
1124
  if (chmod (name, sbuf.st_mode) == -1)
 
1125
    PERROR (name);
 
1126
}
 
1127
 
 
1128
#ifdef COFF
 
1129
#ifndef COFF_BSD_SYMBOLS
 
1130
 
 
1131
/*
 
1132
 *      If the COFF file contains a symbol table and a line number section,
 
1133
 *      then any auxiliary entries that have values for x_lnnoptr must
 
1134
 *      be adjusted by the amount that the line number section has moved
 
1135
 *      in the file (bias computed in make_hdr).  The #@$%&* designers of
 
1136
 *      the auxiliary entry structures used the absolute file offsets for
 
1137
 *      the line number entry rather than an offset from the start of the
 
1138
 *      line number section!
 
1139
 *
 
1140
 *      When I figure out how to scan through the symbol table and pick out
 
1141
 *      the auxiliary entries that need adjustment, this routine will
 
1142
 *      be fixed.  As it is now, all such entries are wrong and sdb
 
1143
 *      will complain.   Fred Fish, UniSoft Systems Inc.
 
1144
 */
 
1145
 
 
1146
/* This function is probably very slow.  Instead of reopening the new
 
1147
   file for input and output it should copy from the old to the new
 
1148
   using the two descriptors already open (WRITEDESC and READDESC).
 
1149
   Instead of reading one small structure at a time it should use
 
1150
   a reasonable size buffer.  But I don't have time to work on such
 
1151
   things, so I am installing it as submitted to me.  -- RMS.  */
 
1152
 
 
1153
adjust_lnnoptrs (writedesc, readdesc, new_name)
 
1154
     int writedesc;
 
1155
     int readdesc;
 
1156
     char *new_name;
 
1157
{
 
1158
  register int nsyms;
 
1159
  register int new;
 
1160
#if defined (amdahl_uts) || defined (pfa)
 
1161
  SYMENT symentry;
 
1162
  AUXENT auxentry;
 
1163
#else
 
1164
  struct syment symentry;
 
1165
  union auxent auxentry;
 
1166
#endif
 
1167
 
 
1168
  if (!lnnoptr || !f_hdr.f_symptr)
 
1169
    return 0;
 
1170
 
 
1171
#ifdef MSDOS
 
1172
  if ((new = writedesc) < 0)
 
1173
#else
 
1174
  if ((new = open (new_name, O_RDWR)) < 0)
 
1175
#endif
 
1176
    {
 
1177
      PERROR (new_name);
 
1178
      return -1;
 
1179
    }
 
1180
 
 
1181
  lseek (new, f_hdr.f_symptr, 0);
 
1182
  for (nsyms = 0; nsyms < f_hdr.f_nsyms; nsyms++)
 
1183
    {
 
1184
      read (new, &symentry, SYMESZ);
 
1185
      if (symentry.n_numaux)
 
1186
        {
 
1187
          read (new, &auxentry, AUXESZ);
 
1188
          nsyms++;
 
1189
          if (ISFCN (symentry.n_type) || symentry.n_type == 0x2400)
 
1190
            {
 
1191
              auxentry.x_sym.x_fcnary.x_fcn.x_lnnoptr += bias;
 
1192
              lseek (new, -AUXESZ, 1);
 
1193
              write (new, &auxentry, AUXESZ);
 
1194
            }
 
1195
        }
 
1196
    }
 
1197
#ifndef MSDOS
 
1198
  close (new);
 
1199
#endif
 
1200
  return 0;
 
1201
}
 
1202
 
 
1203
#endif /* COFF_BSD_SYMBOLS */
 
1204
 
 
1205
#endif /* COFF */
 
1206
 
 
1207
#endif /* not CANNOT_DUMP */
 
1208
 
 
1209
 
 
1210
#ifdef UNIXSAVE
 
1211
#include "save.c"
 
1212
#endif