This commit was manufactured by cvs2svn to create branch 'utf-2000'.
[chise/xemacs-chise.git-] / src / unexelf.c
1 /* Copyright (C) 1985, 1986, 1987, 1988, 1990, 1992, 1993, 1999, 2000
2    Free Software Foundation, Inc.
3
4 This file is part of XEmacs.
5
6 XEmacs is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
9 later version.
10
11 XEmacs is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with XEmacs; see the file COPYING.  If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA.  */
20
21 /* Synched up with: FSF 20.6.90. */
22
23 /*
24  * unexec.c - Convert a running program into an a.out file.
25  *
26  * Author:      Spencer W. Thomas
27  *              Computer Science Dept.
28  *              University of Utah
29  * Date:        Tue Mar  2 1982
30  * Modified heavily since then.
31  *
32  * Synopsis:
33  *      unexec (new_name, a_name, data_start, bss_start, entry_address)
34  *      char *new_name, *a_name;
35  *      unsigned data_start, bss_start, entry_address;
36  *
37  * Takes a snapshot of the program and makes an a.out format file in the
38  * file named by the string argument new_name.
39  * If a_name is non-NULL, the symbol table will be taken from the given file.
40  * On some machines, an existing a_name file is required.
41  *
42  * The boundaries within the a.out file may be adjusted with the data_start
43  * and bss_start arguments.  Either or both may be given as 0 for defaults.
44  *
45  * Data_start gives the boundary between the text segment and the data
46  * segment of the program.  The text segment can contain shared, read-only
47  * program code and literal data, while the data segment is always unshared
48  * and unprotected.  Data_start gives the lowest unprotected address.
49  * The value you specify may be rounded down to a suitable boundary
50  * as required by the machine you are using.
51  *
52  * Bss_start indicates how much of the data segment is to be saved in the
53  * a.out file and restored when the program is executed.  It gives the lowest
54  * unsaved address, and is rounded up to a page boundary.  The default when 0
55  * is given assumes that the entire data segment is to be stored, including
56  * the previous data and bss as well as any additional storage allocated with
57  * break (2).
58  *
59  * The new file is set up to start at entry_address.
60  *
61  */
62
63 /* Even more heavily modified by james@bigtex.cactus.org of Dell Computer Co.
64  * ELF support added.
65  *
66  * Basic theory: the data space of the running process needs to be
67  * dumped to the output file.  Normally we would just enlarge the size
68  * of .data, scooting everything down.  But we can't do that in ELF,
69  * because there is often something between the .data space and the
70  * .bss space.
71  *
72  * In the temacs dump below, notice that the Global Offset Table
73  * (.got) and the Dynamic link data (.dynamic) come between .data1 and
74  * .bss.  It does not work to overlap .data with these fields.
75  *
76  * The solution is to create a new .data segment.  This segment is
77  * filled with data from the current process.  Since the contents of
78  * various sections refer to sections by index, the new .data segment
79  * is made the last in the table to avoid changing any existing index.
80
81  * This is an example of how the section headers are changed.  "Addr"
82  * is a process virtual address.  "Offset" is a file offset.
83
84 raid:/nfs/raid/src/dist-18.56/src> dump -h temacs
85
86 temacs:
87
88            **** SECTION HEADER TABLE ****
89 [No]    Type    Flags   Addr         Offset       Size          Name
90         Link    Info    Adralgn      Entsize
91
92 [1]     1       2       0x80480d4    0xd4         0x13          .interp
93         0       0       0x1          0
94
95 [2]     5       2       0x80480e8    0xe8         0x388         .hash
96         3       0       0x4          0x4
97
98 [3]     11      2       0x8048470    0x470        0x7f0         .dynsym
99         4       1       0x4          0x10
100
101 [4]     3       2       0x8048c60    0xc60        0x3ad         .dynstr
102         0       0       0x1          0
103
104 [5]     9       2       0x8049010    0x1010       0x338         .rel.plt
105         3       7       0x4          0x8
106
107 [6]     1       6       0x8049348    0x1348       0x3           .init
108         0       0       0x4          0
109
110 [7]     1       6       0x804934c    0x134c       0x680         .plt
111         0       0       0x4          0x4
112
113 [8]     1       6       0x80499cc    0x19cc       0x3c56f       .text
114         0       0       0x4          0
115
116 [9]     1       6       0x8085f3c    0x3df3c      0x3           .fini
117         0       0       0x4          0
118
119 [10]    1       2       0x8085f40    0x3df40      0x69c         .rodata
120         0       0       0x4          0
121
122 [11]    1       2       0x80865dc    0x3e5dc      0xd51         .rodata1
123         0       0       0x4          0
124
125 [12]    1       3       0x8088330    0x3f330      0x20afc       .data
126         0       0       0x4          0
127
128 [13]    1       3       0x80a8e2c    0x5fe2c      0x89d         .data1
129         0       0       0x4          0
130
131 [14]    1       3       0x80a96cc    0x606cc      0x1a8         .got
132         0       0       0x4          0x4
133
134 [15]    6       3       0x80a9874    0x60874      0x80          .dynamic
135         4       0       0x4          0x8
136
137 [16]    8       3       0x80a98f4    0x608f4      0x449c        .bss
138         0       0       0x4          0
139
140 [17]    2       0       0            0x608f4      0x9b90        .symtab
141         18      371     0x4          0x10
142
143 [18]    3       0       0            0x6a484      0x8526        .strtab
144         0       0       0x1          0
145
146 [19]    3       0       0            0x729aa      0x93          .shstrtab
147         0       0       0x1          0
148
149 [20]    1       0       0            0x72a3d      0x68b7        .comment
150         0       0       0x1          0
151
152 raid:/nfs/raid/src/dist-18.56/src> dump -h xemacs
153
154 xemacs:
155
156            **** SECTION HEADER TABLE ****
157 [No]    Type    Flags   Addr         Offset       Size          Name
158         Link    Info    Adralgn      Entsize
159
160 [1]     1       2       0x80480d4    0xd4         0x13          .interp
161         0       0       0x1          0
162
163 [2]     5       2       0x80480e8    0xe8         0x388         .hash
164         3       0       0x4          0x4
165
166 [3]     11      2       0x8048470    0x470        0x7f0         .dynsym
167         4       1       0x4          0x10
168
169 [4]     3       2       0x8048c60    0xc60        0x3ad         .dynstr
170         0       0       0x1          0
171
172 [5]     9       2       0x8049010    0x1010       0x338         .rel.plt
173         3       7       0x4          0x8
174
175 [6]     1       6       0x8049348    0x1348       0x3           .init
176         0       0       0x4          0
177
178 [7]     1       6       0x804934c    0x134c       0x680         .plt
179         0       0       0x4          0x4
180
181 [8]     1       6       0x80499cc    0x19cc       0x3c56f       .text
182         0       0       0x4          0
183
184 [9]     1       6       0x8085f3c    0x3df3c      0x3           .fini
185         0       0       0x4          0
186
187 [10]    1       2       0x8085f40    0x3df40      0x69c         .rodata
188         0       0       0x4          0
189
190 [11]    1       2       0x80865dc    0x3e5dc      0xd51         .rodata1
191         0       0       0x4          0
192
193 [12]    1       3       0x8088330    0x3f330      0x20afc       .data
194         0       0       0x4          0
195
196 [13]    1       3       0x80a8e2c    0x5fe2c      0x89d         .data1
197         0       0       0x4          0
198
199 [14]    1       3       0x80a96cc    0x606cc      0x1a8         .got
200         0       0       0x4          0x4
201
202 [15]    6       3       0x80a9874    0x60874      0x80          .dynamic
203         4       0       0x4          0x8
204
205 [16]    8       3       0x80c6800    0x7d800      0             .bss
206         0       0       0x4          0
207
208 [17]    2       0       0            0x7d800      0x9b90        .symtab
209         18      371     0x4          0x10
210
211 [18]    3       0       0            0x87390      0x8526        .strtab
212         0       0       0x1          0
213
214 [19]    3       0       0            0x8f8b6      0x93          .shstrtab
215         0       0       0x1          0
216
217 [20]    1       0       0            0x8f949      0x68b7        .comment
218         0       0       0x1          0
219
220 [21]    1       3       0x80a98f4    0x608f4      0x1cf0c       .data
221         0       0       0x4          0
222
223  * This is an example of how the file header is changed.  "Shoff" is
224  * the section header offset within the file.  Since that table is
225  * after the new .data section, it is moved.  "Shnum" is the number of
226  * sections, which we increment.
227  *
228  * "Phoff" is the file offset to the program header.  "Phentsize" and
229  * "Shentsz" are the program and section header entries sizes respectively.
230  * These can be larger than the apparent struct sizes.
231
232 raid:/nfs/raid/src/dist-18.56/src> dump -f temacs
233
234 temacs:
235
236                     **** ELF HEADER ****
237 Class        Data       Type         Machine     Version
238 Entry        Phoff      Shoff        Flags       Ehsize
239 Phentsize    Phnum      Shentsz      Shnum       Shstrndx
240
241 1            1          2            3           1
242 0x80499cc    0x34       0x792f4      0           0x34
243 0x20         5          0x28         21          19
244
245 raid:/nfs/raid/src/dist-18.56/src> dump -f xemacs
246
247 xemacs:
248
249                     **** ELF HEADER ****
250 Class        Data       Type         Machine     Version
251 Entry        Phoff      Shoff        Flags       Ehsize
252 Phentsize    Phnum      Shentsz      Shnum       Shstrndx
253
254 1            1          2            3           1
255 0x80499cc    0x34       0x96200      0           0x34
256 0x20         5          0x28         22          19
257
258  * These are the program headers.  "Offset" is the file offset to the
259  * segment.  "Vaddr" is the memory load address.  "Filesz" is the
260  * segment size as it appears in the file, and "Memsz" is the size in
261  * memory.  Below, the third segment is the code and the fourth is the
262  * data: the difference between Filesz and Memsz is .bss
263
264 raid:/nfs/raid/src/dist-18.56/src> dump -o temacs
265
266 temacs:
267  ***** PROGRAM EXECUTION HEADER *****
268 Type        Offset      Vaddr       Paddr
269 Filesz      Memsz       Flags       Align
270
271 6           0x34        0x8048034   0
272 0xa0        0xa0        5           0
273
274 3           0xd4        0           0
275 0x13        0           4           0
276
277 1           0x34        0x8048034   0
278 0x3f2f9     0x3f2f9     5           0x1000
279
280 1           0x3f330     0x8088330   0
281 0x215c4     0x25a60     7           0x1000
282
283 2           0x60874     0x80a9874   0
284 0x80        0           7           0
285
286 raid:/nfs/raid/src/dist-18.56/src> dump -o xemacs
287
288 xemacs:
289  ***** PROGRAM EXECUTION HEADER *****
290 Type        Offset      Vaddr       Paddr
291 Filesz      Memsz       Flags       Align
292
293 6           0x34        0x8048034   0
294 0xa0        0xa0        5           0
295
296 3           0xd4        0           0
297 0x13        0           4           0
298
299 1           0x34        0x8048034   0
300 0x3f2f9     0x3f2f9     5           0x1000
301
302 1           0x3f330     0x8088330   0
303 0x3e4d0     0x3e4d0     7           0x1000
304
305 2           0x60874     0x80a9874   0
306 0x80        0           7           0
307
308
309  */
310 \f
311 /* Modified by wtien@urbana.mcd.mot.com of Motorola Inc.
312  *
313  * The above mechanism does not work if the unexeced ELF file is being
314  * re-layout by other applications (such as `strip'). All the applications
315  * that re-layout the internal of ELF will layout all sections in ascending
316  * order of their file offsets. After the re-layout, the data2 section will
317  * still be the LAST section in the section header vector, but its file offset
318  * is now being pushed far away down, and causes part of it not to be mapped
319  * in (ie. not covered by the load segment entry in PHDR vector), therefore
320  * causes the new binary to fail.
321  *
322  * The solution is to modify the unexec algorithm to insert the new data2
323  * section header right before the new bss section header, so their file
324  * offsets will be in the ascending order. Since some of the section's (all
325  * sections AFTER the bss section) indexes are now changed, we also need to
326  * modify some fields to make them point to the right sections. This is done
327  * by macro PATCH_INDEX. All the fields that need to be patched are:
328  *
329  * 1. ELF header e_shstrndx field.
330  * 2. section header sh_link and sh_info field.
331  * 3. symbol table entry st_shndx field.
332  *
333  * The above example now should look like:
334
335            **** SECTION HEADER TABLE ****
336 [No]    Type    Flags   Addr         Offset       Size          Name
337         Link    Info    Adralgn      Entsize
338
339 [1]     1       2       0x80480d4    0xd4         0x13          .interp
340         0       0       0x1          0
341
342 [2]     5       2       0x80480e8    0xe8         0x388         .hash
343         3       0       0x4          0x4
344
345 [3]     11      2       0x8048470    0x470        0x7f0         .dynsym
346         4       1       0x4          0x10
347
348 [4]     3       2       0x8048c60    0xc60        0x3ad         .dynstr
349         0       0       0x1          0
350
351 [5]     9       2       0x8049010    0x1010       0x338         .rel.plt
352         3       7       0x4          0x8
353
354 [6]     1       6       0x8049348    0x1348       0x3           .init
355         0       0       0x4          0
356
357 [7]     1       6       0x804934c    0x134c       0x680         .plt
358         0       0       0x4          0x4
359
360 [8]     1       6       0x80499cc    0x19cc       0x3c56f       .text
361         0       0       0x4          0
362
363 [9]     1       6       0x8085f3c    0x3df3c      0x3           .fini
364         0       0       0x4          0
365
366 [10]    1       2       0x8085f40    0x3df40      0x69c         .rodata
367         0       0       0x4          0
368
369 [11]    1       2       0x80865dc    0x3e5dc      0xd51         .rodata1
370         0       0       0x4          0
371
372 [12]    1       3       0x8088330    0x3f330      0x20afc       .data
373         0       0       0x4          0
374
375 [13]    1       3       0x80a8e2c    0x5fe2c      0x89d         .data1
376         0       0       0x4          0
377
378 [14]    1       3       0x80a96cc    0x606cc      0x1a8         .got
379         0       0       0x4          0x4
380
381 [15]    6       3       0x80a9874    0x60874      0x80          .dynamic
382         4       0       0x4          0x8
383
384 [16]    1       3       0x80a98f4    0x608f4      0x1cf0c       .data
385         0       0       0x4          0
386
387 [17]    8       3       0x80c6800    0x7d800      0             .bss
388         0       0       0x4          0
389
390 [18]    2       0       0            0x7d800      0x9b90        .symtab
391         19      371     0x4          0x10
392
393 [19]    3       0       0            0x87390      0x8526        .strtab
394         0       0       0x1          0
395
396 [20]    3       0       0            0x8f8b6      0x93          .shstrtab
397         0       0       0x1          0
398
399 [21]    1       0       0            0x8f949      0x68b7        .comment
400         0       0       0x1          0
401
402  */
403 \f
404 #ifndef emacs
405 #define fatal(a, b, c) fprintf (stderr, a, b, c), exit (1)
406 #else
407 #include <config.h>
408 extern void fatal (const char *, ...);
409 #endif
410
411 #include <sys/types.h>
412 #include <stdio.h>
413 #include <sys/stat.h>
414 #include <memory.h>
415 #include <string.h>
416 #include <errno.h>
417 #include <unistd.h>
418 #include <fcntl.h>
419 #if !defined (__NetBSD__) && !defined (__OpenBSD__)
420 #include <elf.h>
421 #endif
422 #include <sys/mman.h>
423 #if defined (__sony_news) && defined (_SYSTYPE_SYSV)
424 #include <sys/elf_mips.h>
425 #include <sym.h>
426 #endif /* __sony_news && _SYSTYPE_SYSV */
427 #ifdef __sgi
428 #include <syms.h> /* for HDRR declaration */
429 #endif /* __sgi */
430
431 #if defined (__alpha__) && !defined (__NetBSD__) && !defined (__OpenBSD__)
432 /* Declare COFF debugging symbol table.  This used to be in
433    /usr/include/sym.h, but this file is no longer included in Red Hat
434    5.0 and presumably in any other glibc 2.x based distribution.  */
435 typedef struct {
436         short magic;
437         short vstamp;
438         int ilineMax;
439         int idnMax;
440         int ipdMax;
441         int isymMax;
442         int ioptMax;
443         int iauxMax;
444         int issMax;
445         int issExtMax;
446         int ifdMax;
447         int crfd;
448         int iextMax;
449         long cbLine;
450         long cbLineOffset;
451         long cbDnOffset;
452         long cbPdOffset;
453         long cbSymOffset;
454         long cbOptOffset;
455         long cbAuxOffset;
456         long cbSsOffset;
457         long cbSsExtOffset;
458         long cbFdOffset;
459         long cbRfdOffset;
460         long cbExtOffset;
461 } HDRR, *pHDRR; 
462 #define cbHDRR sizeof(HDRR)
463 #define hdrNil ((pHDRR)0)
464 #endif
465
466 #ifdef __NetBSD__
467 /*
468  * NetBSD does not have normal-looking user-land ELF support.
469  */
470 # ifdef __alpha__
471 #  define ELFSIZE       64
472 # else
473 #  define ELFSIZE       32
474 # endif
475 # include <sys/exec_elf.h>
476
477 # ifndef PT_LOAD
478 #  define PT_LOAD       Elf_pt_load
479 #  define SHT_SYMTAB    Elf_sht_symtab
480 #  define SHT_DYNSYM    Elf_sht_dynsym
481 #  define SHT_NULL      Elf_sht_null
482 #  define SHT_NOBITS    Elf_sht_nobits
483 #  define SHT_REL       Elf_sht_rel
484 #  define SHT_RELA      Elf_sht_rela
485
486 #  define SHN_UNDEF     Elf_eshn_undefined
487 #  define SHN_ABS       Elf_eshn_absolute
488 #  define SHN_COMMON    Elf_eshn_common
489 # endif
490
491 # ifdef __alpha__
492 #  include <sys/exec_ecoff.h>
493 #  define HDRR          struct ecoff_symhdr
494 #  define pHDRR         HDRR *
495 # endif
496 #endif /* __NetBSD__ */
497
498 #ifdef __OpenBSD__
499 # include <sys/exec_elf.h>
500 #endif
501
502 #if __GNU_LIBRARY__ - 0 >= 6
503 # include <link.h>      /* get ElfW etc */
504 #endif
505
506 #ifndef ElfW
507 # ifdef __STDC__
508 #  define ElfBitsW(bits, type) Elf##bits##_##type
509 # else
510 #  define ElfBitsW(bits, type) Elf/**/bits/**/_/**/type
511 # endif
512 # ifdef _LP64
513 #  define ELFSIZE 64
514 # else
515 #  define ELFSIZE 32
516 # endif
517   /* This macro expands `bits' before invoking ElfBitsW.  */
518 # define ElfExpandBitsW(bits, type) ElfBitsW (bits, type)
519 # define ElfW(type) ElfExpandBitsW (ELFSIZE, type)
520 #endif
521
522 #ifndef ELF_BSS_SECTION_NAME
523 #define ELF_BSS_SECTION_NAME ".bss"
524 #endif
525
526 /* Get the address of a particular section or program header entry,
527  * accounting for the size of the entries.
528  */
529 /*
530    On PPC Reference Platform running Solaris 2.5.1
531    the plt section is also of type NOBI like the bss section.
532    (not really stored) and therefore sections after the bss
533    section start at the plt offset. The plt section is always
534    the one just before the bss section.
535    Thus, we modify the test from
536       if (NEW_SECTION_H (nn).sh_offset >= new_data2_offset)
537    to
538       if (NEW_SECTION_H (nn).sh_offset >=
539                OLD_SECTION_H (old_bss_index-1).sh_offset)
540    This is just a hack. We should put the new data section
541    before the .plt section.
542    And we should not have this routine at all but use
543    the libelf library to read the old file and create the new
544    file.
545    The changed code is minimal and depends on prep set in m/prep.h
546    Erik Deumens
547    Quantum Theory Project
548    University of Florida
549    deumens@qtp.ufl.edu
550    Apr 23, 1996
551    */
552
553 #define OLD_SECTION_H(n) \
554      (*(ElfW(Shdr) *) ((byte *) old_section_h + old_file_h->e_shentsize * (n)))
555 #define NEW_SECTION_H(n) \
556      (*(ElfW(Shdr) *) ((byte *) new_section_h + new_file_h->e_shentsize * (n)))
557 #define OLD_PROGRAM_H(n) \
558      (*(ElfW(Phdr) *) ((byte *) old_program_h + old_file_h->e_phentsize * (n)))
559 #define NEW_PROGRAM_H(n) \
560      (*(ElfW(Phdr) *) ((byte *) new_program_h + new_file_h->e_phentsize * (n)))
561
562 #define PATCH_INDEX(n) \
563   do { \
564          if ((int) (n) >= old_bss_index) \
565            (n)++; } while (0)
566 typedef unsigned char byte;
567
568 /* Round X up to a multiple of Y.  */
569
570 static ElfW(Addr)
571 round_up (ElfW(Addr) x, ElfW(Addr) y)
572 {
573   int rem = x % y;
574   if (rem == 0)
575     return x;
576   return x - rem + y;
577 }
578
579 /* Return the index of the section named NAME.
580    SECTION_NAMES, FILE_NAME and FILE_H give information
581    about the file we are looking in.
582
583    If we don't find the section NAME, that is a fatal error
584    if NOERROR is 0; we return -1 if NOERROR is nonzero.  */
585
586 static int
587 find_section (name, section_names, file_name, old_file_h, old_section_h, noerror)
588      char *name;
589      char *section_names;
590      char *file_name;
591      ElfW(Ehdr) *old_file_h;
592      ElfW(Shdr) *old_section_h;
593      int noerror;
594 {
595   int idx;
596
597   for (idx = 1; idx < old_file_h->e_shnum; idx++)
598     {
599 #ifdef DEBUG
600       fprintf (stderr, "Looking for %s - found %s\n", name,
601                section_names + OLD_SECTION_H (idx).sh_name);
602 #endif
603       if (!strcmp (section_names + OLD_SECTION_H (idx).sh_name,
604                    name))
605         break;
606     }
607   if (idx == old_file_h->e_shnum)
608     {
609       if (noerror)
610         return -1;
611       else
612         fatal ("Can't find %s in %s.\n", name, file_name, 0);
613     }
614
615   return idx;
616 }
617
618 /* ****************************************************************
619  * unexec
620  *
621  * driving logic.
622  *
623  * In ELF, this works by replacing the old .bss section with a new
624  * .data section, and inserting an empty .bss immediately afterwards.
625  *
626  */
627 void unexec (char *new_name, char *old_name, unsigned int data_start,
628             unsigned int bss_start, unsigned int entry_address);
629 void
630 unexec (char *new_name, char *old_name, unsigned int data_start,
631         unsigned int bss_start, unsigned int entry_address)
632 {
633   int new_file, old_file, new_file_size;
634
635   /* Pointers to the base of the image of the two files. */
636   caddr_t old_base, new_base;
637
638   /* Pointers to the file, program and section headers for the old and new
639    * files.
640    */
641   ElfW(Ehdr) *old_file_h, *new_file_h;
642   ElfW(Phdr) *old_program_h, *new_program_h;
643   ElfW(Shdr) *old_section_h, *new_section_h;
644
645   /* Point to the section name table in the old file */
646   char *old_section_names;
647
648   ElfW(Addr) old_bss_addr, new_bss_addr;
649   ElfW(Word) old_bss_size, new_data2_size;
650   ElfW(Off)  new_data2_offset;
651   ElfW(Addr) new_data2_addr;
652
653   int n, nn;
654   int old_bss_index, old_sbss_index;
655   int old_data_index, new_data2_index;
656   int old_mdebug_index;
657   struct stat stat_buf;
658
659   /* Open the old file & map it into the address space. */
660
661   old_file = open (old_name, O_RDONLY);
662
663   if (old_file < 0)
664     fatal ("Can't open %s for reading: errno %d\n", old_name, errno);
665
666   if (fstat (old_file, &stat_buf) == -1)
667     fatal ("Can't fstat (%s): errno %d\n", old_name, errno);
668
669   old_base = (caddr_t) mmap (0, stat_buf.st_size, PROT_READ, MAP_SHARED, old_file, 0);
670
671   if (old_base == (caddr_t) -1)
672     fatal ("Can't mmap (%s): errno %d\n", old_name, errno);
673
674 #ifdef DEBUG
675   fprintf (stderr, "mmap (%s, %x) -> %x\n", old_name, stat_buf.st_size,
676            old_base);
677 #endif
678
679   /* Get pointers to headers & section names */
680
681   old_file_h = (ElfW(Ehdr) *) old_base;
682   old_program_h = (ElfW(Phdr) *) ((byte *) old_base + old_file_h->e_phoff);
683   old_section_h = (ElfW(Shdr) *) ((byte *) old_base + old_file_h->e_shoff);
684   old_section_names = (char *) old_base
685     + OLD_SECTION_H (old_file_h->e_shstrndx).sh_offset;
686
687   /* Find the mdebug section, if any.  */
688
689   old_mdebug_index = find_section (".mdebug", old_section_names,
690                                    old_name, old_file_h, old_section_h, 1);
691
692   /* Find the old .bss section.  Figure out parameters of the new
693    * data2 and bss sections.
694    */
695
696   old_bss_index = find_section (".bss", old_section_names,
697                                 old_name, old_file_h, old_section_h, 0);
698
699   old_sbss_index = find_section (".sbss", old_section_names,
700                                  old_name, old_file_h, old_section_h, 1);
701   if (old_sbss_index != -1)
702     if (OLD_SECTION_H (old_sbss_index).sh_type == SHT_PROGBITS)
703       old_sbss_index = -1;
704
705   if (old_sbss_index == -1)
706     {
707       old_bss_addr = OLD_SECTION_H (old_bss_index).sh_addr;
708       old_bss_size = OLD_SECTION_H (old_bss_index).sh_size;
709       new_data2_index = old_bss_index;
710     }
711   else
712     {
713       old_bss_addr = OLD_SECTION_H (old_sbss_index).sh_addr;
714       old_bss_size = OLD_SECTION_H (old_bss_index).sh_size
715         + OLD_SECTION_H (old_sbss_index).sh_size;
716       new_data2_index = old_sbss_index;
717     }
718
719   /* Find the old .data section.  Figure out parameters of
720      the new data2 and bss sections.  */
721
722   old_data_index = find_section (".data", old_section_names,
723                                  old_name, old_file_h, old_section_h, 0);
724
725 #if defined (emacs) || !defined (DEBUG)
726   new_bss_addr = (ElfW(Addr)) sbrk (0);
727 #else
728   new_bss_addr = old_bss_addr + old_bss_size + 0x1234;
729 #endif
730   new_data2_addr = old_bss_addr;
731   new_data2_size = new_bss_addr - old_bss_addr;
732   new_data2_offset  = OLD_SECTION_H (old_data_index).sh_offset +
733     (new_data2_addr - OLD_SECTION_H (old_data_index).sh_addr);
734
735 #ifdef DEBUG
736   fprintf (stderr, "old_bss_index %d\n", old_bss_index);
737   fprintf (stderr, "old_bss_addr %x\n", old_bss_addr);
738   fprintf (stderr, "old_bss_size %x\n", old_bss_size);
739   fprintf (stderr, "new_bss_addr %x\n", new_bss_addr);
740   fprintf (stderr, "new_data2_addr %x\n", new_data2_addr);
741   fprintf (stderr, "new_data2_size %x\n", new_data2_size);
742   fprintf (stderr, "new_data2_offset %x\n", new_data2_offset);
743 #endif
744
745   if ((unsigned) new_bss_addr < (unsigned) old_bss_addr + old_bss_size)
746     fatal (".bss shrank when undumping???\n", 0, 0);
747
748   /* Set the output file to the right size and mmap it.  Set
749    * pointers to various interesting objects.  stat_buf still has
750    * old_file data.
751    */
752
753   new_file = open (new_name, O_RDWR | O_CREAT, 0666);
754   if (new_file < 0)
755     fatal ("Can't creat (%s): errno %d\n", new_name, errno);
756
757   new_file_size = stat_buf.st_size + old_file_h->e_shentsize + new_data2_size;
758
759   if (ftruncate (new_file, new_file_size))
760     fatal ("Can't ftruncate (%s): errno %d\n", new_name, errno);
761
762   new_base = (caddr_t) mmap (0, new_file_size, PROT_READ | PROT_WRITE,
763 #ifdef UNEXEC_USE_MAP_PRIVATE
764                              MAP_PRIVATE,
765 #else
766                              MAP_SHARED,
767 #endif
768                              new_file, 0);
769
770   if (new_base == (caddr_t) -1)
771     fatal ("Can't mmap (%s): errno %d\n", new_name, errno);
772
773   new_file_h = (ElfW(Ehdr) *) new_base;
774   new_program_h = (ElfW(Phdr) *) ((byte *) new_base + old_file_h->e_phoff);
775   new_section_h = (ElfW(Shdr) *)
776     ((byte *) new_base + old_file_h->e_shoff + new_data2_size);
777
778   /* Make our new file, program and section headers as copies of the
779    * originals.
780    */
781
782   memcpy (new_file_h, old_file_h, old_file_h->e_ehsize);
783   memcpy (new_program_h, old_program_h,
784           old_file_h->e_phnum * old_file_h->e_phentsize);
785
786   /* Modify the e_shstrndx if necessary. */
787   PATCH_INDEX (new_file_h->e_shstrndx);
788
789   /* Fix up file header.  We'll add one section.  Section header is
790    * further away now.
791    */
792
793   new_file_h->e_shoff += new_data2_size;
794   new_file_h->e_shnum += 1;
795
796 #ifdef DEBUG
797   fprintf (stderr, "Old section offset %x\n", old_file_h->e_shoff);
798   fprintf (stderr, "Old section count %d\n", old_file_h->e_shnum);
799   fprintf (stderr, "New section offset %x\n", new_file_h->e_shoff);
800   fprintf (stderr, "New section count %d\n", new_file_h->e_shnum);
801 #endif
802
803   /* Fix up a new program header.  Extend the writable data segment so
804    * that the bss area is covered too. Find that segment by looking
805    * for a segment that ends just before the .bss area.  Make sure
806    * that no segments are above the new .data2.  Put a loop at the end
807    * to adjust the offset and address of any segment that is above
808    * data2, just in case we decide to allow this later.
809    */
810
811   for (n = new_file_h->e_phnum - 1; n >= 0; n--)
812     {
813       /* Compute maximum of all requirements for alignment of section.  */
814       ElfW(Word) alignment = (NEW_PROGRAM_H (n)).p_align;
815       if ((OLD_SECTION_H (old_bss_index)).sh_addralign > alignment)
816         alignment = OLD_SECTION_H (old_bss_index).sh_addralign;
817
818 #ifdef __sgi
819           /* According to r02kar@x4u2.desy.de (Karsten Kuenne)
820              and oliva@gnu.org (Alexandre Oliva), on IRIX 5.2, we
821              always get "Program segment above .bss" when dumping
822              when the executable doesn't have an sbss section.  */
823       if (old_sbss_index != -1)
824 #endif /* __sgi */
825       if (NEW_PROGRAM_H (n).p_vaddr + NEW_PROGRAM_H (n).p_filesz
826           > (old_sbss_index == -1
827              ? old_bss_addr
828              : round_up (old_bss_addr, alignment)))
829           fatal ("Program segment above .bss in %s\n", old_name, 0);
830
831       if (NEW_PROGRAM_H (n).p_type == PT_LOAD
832           && (round_up ((NEW_PROGRAM_H (n)).p_vaddr
833                         + (NEW_PROGRAM_H (n)).p_filesz,
834                         alignment)
835               == round_up (old_bss_addr, alignment)))
836         break;
837     }
838   if (n < 0)
839     fatal ("Couldn't find segment next to .bss in %s\n", old_name, 0);
840
841   /* Make sure that the size includes any padding before the old .bss
842      section.  */
843   NEW_PROGRAM_H (n).p_filesz = new_bss_addr - NEW_PROGRAM_H (n).p_vaddr;
844   NEW_PROGRAM_H (n).p_memsz = NEW_PROGRAM_H (n).p_filesz;
845
846 #if 0 /* Maybe allow section after data2 - does this ever happen? */
847   for (n = new_file_h->e_phnum - 1; n >= 0; n--)
848     {
849       if (NEW_PROGRAM_H (n).p_vaddr
850           && NEW_PROGRAM_H (n).p_vaddr >= new_data2_addr)
851         NEW_PROGRAM_H (n).p_vaddr += new_data2_size - old_bss_size;
852
853       if (NEW_PROGRAM_H (n).p_offset >= new_data2_offset)
854         NEW_PROGRAM_H (n).p_offset += new_data2_size;
855     }
856 #endif
857
858   /* Fix up section headers based on new .data2 section.  Any section
859    * whose offset or virtual address is after the new .data2 section
860    * gets its value adjusted.  .bss size becomes zero and new address
861    * is set.  data2 section header gets added by copying the existing
862    * .data header and modifying the offset, address and size.
863    */
864   for (old_data_index = 1; old_data_index < (int) old_file_h->e_shnum;
865        old_data_index++)
866     if (!strcmp (old_section_names + OLD_SECTION_H (old_data_index).sh_name,
867                  ".data"))
868       break;
869   if (old_data_index == old_file_h->e_shnum)
870     fatal ("Can't find .data in %s.\n", old_name, 0);
871
872   /* Walk through all section headers, insert the new data2 section right
873      before the new bss section. */
874   for (n = 1, nn = 1; n < (int) old_file_h->e_shnum; n++, nn++)
875     {
876       caddr_t src;
877       /* If it is (s)bss section, insert the new data2 section before it.  */
878       /* new_data2_index is the index of either old_sbss or old_bss, that was
879          chosen as a section for new_data2.   */
880       if (n == new_data2_index)
881         {
882           /* Steal the data section header for this data2 section. */
883           memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (old_data_index),
884                   new_file_h->e_shentsize);
885
886           NEW_SECTION_H (nn).sh_addr = new_data2_addr;
887           NEW_SECTION_H (nn).sh_offset = new_data2_offset;
888           NEW_SECTION_H (nn).sh_size = new_data2_size;
889           /* Use the bss section's alignment. This will assure that the
890              new data2 section always be placed in the same spot as the old
891              bss section by any other application. */
892           NEW_SECTION_H (nn).sh_addralign = OLD_SECTION_H (n).sh_addralign;
893
894           /* Now copy over what we have in the memory now. */
895           memcpy (NEW_SECTION_H (nn).sh_offset + new_base,
896                   (caddr_t) OLD_SECTION_H (n).sh_addr,
897                   new_data2_size);
898           nn++;
899         }
900
901       memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (n),
902               old_file_h->e_shentsize);
903       
904       if (n == old_bss_index
905           /* The new bss and sbss section's size is zero, and its file offset
906              and virtual address should be off by NEW_DATA2_SIZE.  */
907           || n == old_sbss_index
908           )
909         {
910           /* NN should be `old_s?bss_index + 1' at this point. */
911           NEW_SECTION_H (nn).sh_offset =
912             NEW_SECTION_H (new_data2_index).sh_offset + new_data2_size;
913           NEW_SECTION_H (nn).sh_addr =
914             NEW_SECTION_H (new_data2_index).sh_addr + new_data2_size;
915           /* Let the new bss section address alignment be the same as the
916              section address alignment followed the old bss section, so
917              this section will be placed in exactly the same place. */
918           NEW_SECTION_H (nn).sh_addralign = OLD_SECTION_H (nn).sh_addralign;
919           NEW_SECTION_H (nn).sh_size = 0;
920         }
921       else
922         {
923           /* Any section that was original placed AFTER the bss
924              section should now be off by NEW_DATA2_SIZE. */
925 #ifdef SOLARIS_POWERPC
926           /* On PPC Reference Platform running Solaris 2.5.1
927              the plt section is also of type NOBI like the bss section.
928              (not really stored) and therefore sections after the bss
929              section start at the plt offset. The plt section is always
930              the one just before the bss section.
931              It would be better to put the new data section before
932              the .plt section, or use libelf instead.
933              Erik Deumens, deumens@qtp.ufl.edu.  */
934           if (NEW_SECTION_H (nn).sh_offset
935               >= OLD_SECTION_H (old_bss_index-1).sh_offset)
936             NEW_SECTION_H (nn).sh_offset += new_data2_size;
937 #else
938           if (round_up (NEW_SECTION_H (nn).sh_offset,
939                         OLD_SECTION_H (old_bss_index).sh_addralign)
940               >= new_data2_offset)
941             NEW_SECTION_H (nn).sh_offset += new_data2_size;
942 #endif
943           /* Any section that was originally placed after the section
944              header table should now be off by the size of one section
945              header table entry.  */
946           if (NEW_SECTION_H (nn).sh_offset > new_file_h->e_shoff)
947             NEW_SECTION_H (nn).sh_offset += new_file_h->e_shentsize;
948         }
949
950       /* If any section hdr refers to the section after the new .data
951          section, make it refer to next one because we have inserted
952          a new section in between.  */
953
954       PATCH_INDEX (NEW_SECTION_H (nn).sh_link);
955       /* For symbol tables, info is a symbol table index,
956          so don't change it.  */
957       if (NEW_SECTION_H (nn).sh_type != SHT_SYMTAB
958           && NEW_SECTION_H (nn).sh_type != SHT_DYNSYM)
959         PATCH_INDEX (NEW_SECTION_H (nn).sh_info);
960       
961       if (old_sbss_index != -1)
962         if (!strcmp (old_section_names + NEW_SECTION_H (nn).sh_name, ".sbss"))
963           {
964             NEW_SECTION_H (nn).sh_offset = 
965               round_up (NEW_SECTION_H (nn).sh_offset,
966                         NEW_SECTION_H (nn).sh_addralign);
967             NEW_SECTION_H (nn).sh_type = SHT_PROGBITS;
968           }
969
970       /* Now, start to copy the content of sections.  */
971       if (NEW_SECTION_H (nn).sh_type == SHT_NULL
972           || NEW_SECTION_H (nn).sh_type == SHT_NOBITS)
973         continue;
974
975       /* Write out the sections. .data and .data1 (and data2, called
976          ".data" in the strings table) get copied from the current process
977          instead of the old file.  */
978       if (!strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".data")
979           || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
980                       ".sdata")
981           /* Taking these sections from the current process, breaks
982              Linux in a subtle way. Binaries only run on the
983              architecture (e.g. i586 vs i686) of the dumping machine */
984           || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
985                       ".lit4")
986           || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
987                       ".lit8")
988           || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
989                       ".got")
990           || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
991                       ".sdata1")
992           || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
993                       ".data1")
994           || !strcmp (old_section_names + NEW_SECTION_H (nn).sh_name,
995                       ".sbss"))
996         src = (caddr_t) OLD_SECTION_H (n).sh_addr;
997       else
998         src = old_base + OLD_SECTION_H (n).sh_offset;
999
1000       memcpy (NEW_SECTION_H (nn).sh_offset + new_base, src,
1001               NEW_SECTION_H (nn).sh_size);
1002
1003 #ifdef __alpha__
1004       /* Update Alpha COFF symbol table: */
1005       if (strcmp (old_section_names + OLD_SECTION_H (n).sh_name, ".mdebug")
1006           == 0)
1007         {
1008           pHDRR symhdr = (pHDRR) (NEW_SECTION_H (nn).sh_offset + new_base);
1009
1010           symhdr->cbLineOffset += new_data2_size;
1011           symhdr->cbDnOffset += new_data2_size;
1012           symhdr->cbPdOffset += new_data2_size;
1013           symhdr->cbSymOffset += new_data2_size;
1014           symhdr->cbOptOffset += new_data2_size;
1015           symhdr->cbAuxOffset += new_data2_size;
1016           symhdr->cbSsOffset += new_data2_size;
1017           symhdr->cbSsExtOffset += new_data2_size;
1018           symhdr->cbFdOffset += new_data2_size;
1019           symhdr->cbRfdOffset += new_data2_size;
1020           symhdr->cbExtOffset += new_data2_size;
1021         }
1022 #endif /* __alpha__ */
1023
1024 #if defined (__sony_news) && defined (_SYSTYPE_SYSV)
1025       if (NEW_SECTION_H (nn).sh_type == SHT_MIPS_DEBUG
1026           && old_mdebug_index != -1) 
1027         {
1028           int diff = NEW_SECTION_H(nn).sh_offset 
1029                 - OLD_SECTION_H(old_mdebug_index).sh_offset;
1030           HDRR *phdr = (HDRR *)(NEW_SECTION_H (nn).sh_offset + new_base);
1031
1032           if (diff)
1033             {
1034               phdr->cbLineOffset += diff;
1035               phdr->cbDnOffset   += diff;
1036               phdr->cbPdOffset   += diff;
1037               phdr->cbSymOffset  += diff;
1038               phdr->cbOptOffset  += diff;
1039               phdr->cbAuxOffset  += diff;
1040               phdr->cbSsOffset   += diff;
1041               phdr->cbSsExtOffset += diff;
1042               phdr->cbFdOffset   += diff;
1043               phdr->cbRfdOffset  += diff;
1044               phdr->cbExtOffset  += diff;
1045             }
1046         }
1047 #endif /* __sony_news && _SYSTYPE_SYSV */
1048
1049 #ifdef __sgi
1050       /* Adjust  the HDRR offsets in .mdebug and copy the 
1051          line data if it's in its usual 'hole' in the object.
1052          Makes the new file debuggable with dbx.
1053          patches up two problems: the absolute file offsets
1054          in the HDRR record of .mdebug (see /usr/include/syms.h), and
1055          the ld bug that gets the line table in a hole in the
1056          elf file rather than in the .mdebug section proper.
1057          David Anderson. davea@sgi.com  Jan 16,1994.  */
1058       if (n == old_mdebug_index)
1059         {
1060 #define MDEBUGADJUST(__ct,__fileaddr)           \
1061   if (n_phdrr->__ct > 0)                        \
1062     {                                           \
1063       n_phdrr->__fileaddr += movement;          \
1064     }
1065
1066           HDRR * o_phdrr = (HDRR *)((byte *)old_base + OLD_SECTION_H (n).sh_offset);
1067           HDRR * n_phdrr = (HDRR *)((byte *)new_base + NEW_SECTION_H (nn).sh_offset);
1068           unsigned movement = new_data2_size;
1069
1070           MDEBUGADJUST (idnMax, cbDnOffset);
1071           MDEBUGADJUST (ipdMax, cbPdOffset);
1072           MDEBUGADJUST (isymMax, cbSymOffset);
1073           MDEBUGADJUST (ioptMax, cbOptOffset);
1074           MDEBUGADJUST (iauxMax, cbAuxOffset);
1075           MDEBUGADJUST (issMax, cbSsOffset);
1076           MDEBUGADJUST (issExtMax, cbSsExtOffset);
1077           MDEBUGADJUST (ifdMax, cbFdOffset);
1078           MDEBUGADJUST (crfd, cbRfdOffset);
1079           MDEBUGADJUST (iextMax, cbExtOffset);
1080           /* The Line Section, being possible off in a hole of the object,
1081              requires special handling.  */
1082           if (n_phdrr->cbLine > 0)
1083             {
1084               if (o_phdrr->cbLineOffset > (OLD_SECTION_H (n).sh_offset
1085                                            + OLD_SECTION_H (n).sh_size))
1086                 {
1087                   /* line data is in a hole in elf. do special copy and adjust
1088                      for this ld mistake.
1089                      */
1090                   n_phdrr->cbLineOffset += movement;
1091
1092                   memcpy (n_phdrr->cbLineOffset + new_base,
1093                           o_phdrr->cbLineOffset + old_base, n_phdrr->cbLine);
1094                 }
1095               else
1096                 {
1097                   /* somehow line data is in .mdebug as it is supposed to be.  */
1098                   MDEBUGADJUST (cbLine, cbLineOffset);
1099                 }
1100             }
1101         }
1102 #endif /* __sgi */
1103
1104       /* If it is the symbol table, its st_shndx field needs to be patched.  */
1105       if (NEW_SECTION_H (nn).sh_type == SHT_SYMTAB
1106           || NEW_SECTION_H (nn).sh_type == SHT_DYNSYM)
1107         {
1108           ElfW(Shdr) *spt = &NEW_SECTION_H (nn);
1109           unsigned int num = spt->sh_size / spt->sh_entsize;
1110           ElfW(Sym) * sym = (ElfW(Sym) *) (NEW_SECTION_H (nn).sh_offset +
1111                                            new_base);
1112           for (; num--; sym++)
1113             {
1114               if ((sym->st_shndx == SHN_UNDEF)
1115                   || (sym->st_shndx == SHN_ABS)
1116                   || (sym->st_shndx == SHN_COMMON))
1117                 continue;
1118
1119               PATCH_INDEX (sym->st_shndx);
1120             }
1121         }
1122     }
1123
1124   /* Update the symbol values of _edata and _end.  */
1125   for (n = new_file_h->e_shnum - 1; n; n--)
1126     {
1127       byte *symnames;
1128       ElfW(Sym) *symp, *symendp;
1129
1130       if (NEW_SECTION_H (n).sh_type != SHT_DYNSYM
1131           && NEW_SECTION_H (n).sh_type != SHT_SYMTAB)
1132         continue;
1133
1134       symnames = ((byte *) new_base
1135                   + NEW_SECTION_H (NEW_SECTION_H (n).sh_link).sh_offset);
1136       symp = (ElfW(Sym) *) (NEW_SECTION_H (n).sh_offset + new_base);
1137       symendp = (ElfW(Sym) *) ((byte *)symp + NEW_SECTION_H (n).sh_size);
1138
1139       for (; symp < symendp; symp ++)
1140         if (strcmp ((char *) (symnames + symp->st_name), "_end") == 0
1141             || strcmp ((char *) (symnames + symp->st_name), "end") == 0
1142             || strcmp ((char *) (symnames + symp->st_name), "_edata") == 0
1143             || strcmp ((char *) (symnames + symp->st_name), "edata") == 0)
1144           memcpy (&symp->st_value, &new_bss_addr, sizeof (new_bss_addr));
1145     }
1146
1147   /* This loop seeks out relocation sections for the data section, so
1148      that it can undo relocations performed by the runtime linker.  */
1149   for (n = new_file_h->e_shnum - 1; n; n--)
1150     {
1151       ElfW(Shdr) section = NEW_SECTION_H (n);
1152       switch (section.sh_type) {
1153       default:
1154         break;
1155       case SHT_REL:
1156       case SHT_RELA:
1157         /* This code handles two different size structs, but there should
1158            be no harm in that provided that r_offset is always the first
1159            member.  */
1160         nn = section.sh_info;
1161         if (!strcmp (old_section_names + NEW_SECTION_H (nn).sh_name, ".data")
1162             || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
1163                         ".sdata")
1164             || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
1165                         ".lit4")
1166             || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
1167                         ".lit8")
1168             || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
1169                         ".got")
1170             || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
1171                         ".sdata1")
1172             || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name),
1173                         ".data1"))
1174           {
1175             ElfW(Addr) offset = NEW_SECTION_H (nn).sh_addr -
1176               NEW_SECTION_H (nn).sh_offset;
1177             caddr_t reloc = old_base + section.sh_offset, end;
1178             for (end = reloc + section.sh_size; reloc < end;
1179                  reloc += section.sh_entsize)
1180               {
1181                 ElfW(Addr) addr = ((ElfW(Rel) *) reloc)->r_offset - offset;
1182 #ifdef __alpha__
1183                 /* The Alpha ELF binutils currently have a bug that
1184                    sometimes results in relocs that contain all
1185                    zeroes.  Work around this for now...  */
1186                 if (((ElfW(Rel) *) reloc)->r_offset == 0)
1187                     continue;
1188 #endif
1189                 memcpy (new_base + addr, old_base + addr, sizeof(ElfW(Addr)));
1190               }
1191           }
1192         break;
1193       }
1194     }
1195
1196 #ifdef UNEXEC_USE_MAP_PRIVATE
1197   if (lseek (new_file, 0, SEEK_SET) == -1)
1198     fatal ("Can't rewind (%s): errno %d\n", new_name, errno);
1199
1200   if (write (new_file, new_base, new_file_size) != new_file_size)
1201     fatal ("Can't write (%s): errno %d\n", new_name, errno);
1202 #endif
1203
1204   /* Close the files and make the new file executable.  */
1205
1206   if (close (old_file))
1207     fatal ("Can't close (%s): errno %d\n", old_name, errno);
1208
1209   if (close (new_file))
1210     fatal ("Can't close (%s): errno %d\n", new_name, errno);
1211
1212   if (stat (new_name, &stat_buf) == -1)
1213     fatal ("Can't stat (%s): errno %d\n", new_name, errno);
1214
1215   n = umask (777);
1216   umask (n);
1217   stat_buf.st_mode |= 0111 & ~n;
1218   if (chmod (new_name, stat_buf.st_mode) == -1)
1219     fatal ("Can't chmod (%s): errno %d\n", new_name, errno);
1220 }