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