~ubuntu-branches/ubuntu/quantal/gclcvs/quantal

« back to all changes in this revision

Viewing changes to o/unexelfsgi.c

  • Committer: Bazaar Package Importer
  • Author(s): Camm Maguire
  • Date: 2004-06-24 15:13:46 UTC
  • Revision ID: james.westby@ubuntu.com-20040624151346-xh0xaaktyyp7aorc
Tags: 2.7.0-26
C_GC_OFFSET is 2 on m68k-linux

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 1985, 1986, 1987, 1988, 1990, 1992
 
2
   Free Software Foundation, Inc.
 
3
 
 
4
    This program is free software; you can redistribute it and/or modify
 
5
    it under the terms of the GNU General Public License as published by
 
6
    the Free Software Foundation; either version 2, or (at your option)
 
7
    any later version.
 
8
 
 
9
    This program is distributed in the hope that it will be useful,
 
10
    but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
    GNU General Public License for more details.
 
13
 
 
14
    You should have received a copy of the GNU General Public License
 
15
    along with this program; if not, write to the Free Software
 
16
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
17
 
 
18
In other words, you are welcome to use, share and improve this program.
 
19
You are forbidden to forbid anyone else to use, share and improve
 
20
what you give them.   Help stamp out software-hoarding!  */
 
21
 
 
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
 * Specifying zero for data_start means the boundary between text and data
 
53
 * should not be the same as when the program was loaded.
 
54
 * If NO_REMAP is defined, the argument data_start is ignored and the
 
55
 * segment boundaries are never changed.
 
56
 *
 
57
 * Bss_start indicates how much of the data segment is to be saved in the
 
58
 * a.out file and restored when the program is executed.  It gives the lowest
 
59
 * unsaved address, and is rounded up to a page boundary.  The default when 0
 
60
 * is given assumes that the entire data segment is to be stored, including
 
61
 * the previous data and bss as well as any additional storage allocated with
 
62
 * break (2).
 
63
 *
 
64
 * The new file is set up to start at entry_address.
 
65
 *
 
66
 * If you make improvements I'd like to get them too.
 
67
 * harpo!utah-cs!thomas, thomas@Utah-20
 
68
 *
 
69
 */
 
70
 
 
71
/* Even more heavily modified by james@bigtex.cactus.org of Dell Computer Co.
 
72
 * ELF support added.
 
73
 *
 
74
 * Basic theory: the data space of the running process needs to be
 
75
 * dumped to the output file.  Normally we would just enlarge the size
 
76
 * of .data, scooting everything down.  But we can't do that in ELF,
 
77
 * because there is often something between the .data space and the
 
78
 * .bss space.
 
79
 *
 
80
 * In the temacs dump below, notice that the Global Offset Table
 
81
 * (.got) and the Dynamic link data (.dynamic) come between .data1 and
 
82
 * .bss.  It does not work to overlap .data with these fields.
 
83
 *
 
84
 * The solution is to create a new .data segment.  This segment is
 
85
 * filled with data from the current process.  Since the contents of
 
86
 * various sections refer to sections by index, the new .data segment
 
87
 * is made the last in the table to avoid changing any existing index.
 
88
 
 
89
 * This is an example of how the section headers are changed.  "Addr"
 
90
 * is a process virtual address.  "Offset" is a file offset.
 
91
 
 
92
raid:/nfs/raid/src/dist-18.56/src> dump -h temacs
 
93
 
 
94
temacs:
 
95
 
 
96
           **** SECTION HEADER TABLE ****
 
97
[No]    Type    Flags   Addr         Offset       Size          Name
 
98
        Link    Info    Adralgn      Entsize
 
99
 
 
100
[1]     1       2       0x80480d4    0xd4         0x13          .interp
 
101
        0       0       0x1          0            
 
102
 
 
103
[2]     5       2       0x80480e8    0xe8         0x388         .hash
 
104
        3       0       0x4          0x4          
 
105
 
 
106
[3]     11      2       0x8048470    0x470        0x7f0         .dynsym
 
107
        4       1       0x4          0x10         
 
108
 
 
109
[4]     3       2       0x8048c60    0xc60        0x3ad         .dynstr
 
110
        0       0       0x1          0            
 
111
 
 
112
[5]     9       2       0x8049010    0x1010       0x338         .rel.plt
 
113
        3       7       0x4          0x8          
 
114
 
 
115
[6]     1       6       0x8049348    0x1348       0x3           .init
 
116
        0       0       0x4          0            
 
117
 
 
118
[7]     1       6       0x804934c    0x134c       0x680         .plt
 
119
        0       0       0x4          0x4          
 
120
 
 
121
[8]     1       6       0x80499cc    0x19cc       0x3c56f       .text
 
122
        0       0       0x4          0            
 
123
 
 
124
[9]     1       6       0x8085f3c    0x3df3c      0x3           .fini
 
125
        0       0       0x4          0            
 
126
 
 
127
[10]    1       2       0x8085f40    0x3df40      0x69c         .rodata
 
128
        0       0       0x4          0            
 
129
 
 
130
[11]    1       2       0x80865dc    0x3e5dc      0xd51         .rodata1
 
131
        0       0       0x4          0            
 
132
 
 
133
[12]    1       3       0x8088330    0x3f330      0x20afc       .data
 
134
        0       0       0x4          0            
 
135
 
 
136
[13]    1       3       0x80a8e2c    0x5fe2c      0x89d         .data1
 
137
        0       0       0x4          0            
 
138
 
 
139
[14]    1       3       0x80a96cc    0x606cc      0x1a8         .got
 
140
        0       0       0x4          0x4          
 
141
 
 
142
[15]    6       3       0x80a9874    0x60874      0x80          .dynamic
 
143
        4       0       0x4          0x8          
 
144
 
 
145
[16]    8       3       0x80a98f4    0x608f4      0x449c        .bss
 
146
        0       0       0x4          0            
 
147
 
 
148
[17]    2       0       0            0x608f4      0x9b90        .symtab
 
149
        18      371     0x4          0x10         
 
150
 
 
151
[18]    3       0       0            0x6a484      0x8526        .strtab
 
152
        0       0       0x1          0            
 
153
 
 
154
[19]    3       0       0            0x729aa      0x93          .shstrtab
 
155
        0       0       0x1          0            
 
156
 
 
157
[20]    1       0       0            0x72a3d      0x68b7        .comment
 
158
        0       0       0x1          0            
 
159
 
 
160
raid:/nfs/raid/src/dist-18.56/src> dump -h xemacs
 
161
 
 
162
xemacs:
 
163
 
 
164
           **** SECTION HEADER TABLE ****
 
165
[No]    Type    Flags   Addr         Offset       Size          Name
 
166
        Link    Info    Adralgn      Entsize
 
167
 
 
168
[1]     1       2       0x80480d4    0xd4         0x13          .interp
 
169
        0       0       0x1          0            
 
170
 
 
171
[2]     5       2       0x80480e8    0xe8         0x388         .hash
 
172
        3       0       0x4          0x4          
 
173
 
 
174
[3]     11      2       0x8048470    0x470        0x7f0         .dynsym
 
175
        4       1       0x4          0x10         
 
176
 
 
177
[4]     3       2       0x8048c60    0xc60        0x3ad         .dynstr
 
178
        0       0       0x1          0            
 
179
 
 
180
[5]     9       2       0x8049010    0x1010       0x338         .rel.plt
 
181
        3       7       0x4          0x8          
 
182
 
 
183
[6]     1       6       0x8049348    0x1348       0x3           .init
 
184
        0       0       0x4          0            
 
185
 
 
186
[7]     1       6       0x804934c    0x134c       0x680         .plt
 
187
        0       0       0x4          0x4          
 
188
 
 
189
[8]     1       6       0x80499cc    0x19cc       0x3c56f       .text
 
190
        0       0       0x4          0            
 
191
 
 
192
[9]     1       6       0x8085f3c    0x3df3c      0x3           .fini
 
193
        0       0       0x4          0            
 
194
 
 
195
[10]    1       2       0x8085f40    0x3df40      0x69c         .rodata
 
196
        0       0       0x4          0            
 
197
 
 
198
[11]    1       2       0x80865dc    0x3e5dc      0xd51         .rodata1
 
199
        0       0       0x4          0            
 
200
 
 
201
[12]    1       3       0x8088330    0x3f330      0x20afc       .data
 
202
        0       0       0x4          0            
 
203
 
 
204
[13]    1       3       0x80a8e2c    0x5fe2c      0x89d         .data1
 
205
        0       0       0x4          0            
 
206
 
 
207
[14]    1       3       0x80a96cc    0x606cc      0x1a8         .got
 
208
        0       0       0x4          0x4          
 
209
 
 
210
[15]    6       3       0x80a9874    0x60874      0x80          .dynamic
 
211
        4       0       0x4          0x8          
 
212
 
 
213
[16]    8       3       0x80c6800    0x7d800      0             .bss
 
214
        0       0       0x4          0            
 
215
 
 
216
[17]    2       0       0            0x7d800      0x9b90        .symtab
 
217
        18      371     0x4          0x10         
 
218
 
 
219
[18]    3       0       0            0x87390      0x8526        .strtab
 
220
        0       0       0x1          0            
 
221
 
 
222
[19]    3       0       0            0x8f8b6      0x93          .shstrtab
 
223
        0       0       0x1          0            
 
224
 
 
225
[20]    1       0       0            0x8f949      0x68b7        .comment
 
226
        0       0       0x1          0            
 
227
 
 
228
[21]    1       3       0x80a98f4    0x608f4      0x1cf0c       .data
 
229
        0       0       0x4          0            
 
230
 
 
231
 * This is an example of how the file header is changed.  "Shoff" is
 
232
 * the section header offset within the file.  Since that table is
 
233
 * after the new .data section, it is moved.  "Shnum" is the number of
 
234
 * sections, which we increment.
 
235
 *
 
236
 * "Phoff" is the file offset to the program header.  "Phentsize" and
 
237
 * "Shentsz" are the program and section header entries sizes respectively.
 
238
 * These can be larger than the apparent struct sizes.
 
239
 
 
240
raid:/nfs/raid/src/dist-18.56/src> dump -f temacs
 
241
 
 
242
temacs:
 
243
 
 
244
                    **** ELF HEADER ****
 
245
Class        Data       Type         Machine     Version
 
246
Entry        Phoff      Shoff        Flags       Ehsize
 
247
Phentsize    Phnum      Shentsz      Shnum       Shstrndx
 
248
 
 
249
1            1          2            3           1
 
250
0x80499cc    0x34       0x792f4      0           0x34
 
251
0x20         5          0x28         21          19
 
252
 
 
253
raid:/nfs/raid/src/dist-18.56/src> dump -f xemacs
 
254
 
 
255
xemacs:
 
256
 
 
257
                    **** ELF HEADER ****
 
258
Class        Data       Type         Machine     Version
 
259
Entry        Phoff      Shoff        Flags       Ehsize
 
260
Phentsize    Phnum      Shentsz      Shnum       Shstrndx
 
261
 
 
262
1            1          2            3           1
 
263
0x80499cc    0x34       0x96200      0           0x34
 
264
0x20         5          0x28         22          19
 
265
 
 
266
 * These are the program headers.  "Offset" is the file offset to the
 
267
 * segment.  "Vaddr" is the memory load address.  "Filesz" is the
 
268
 * segment size as it appears in the file, and "Memsz" is the size in
 
269
 * memory.  Below, the third segment is the code and the fourth is the
 
270
 * data: the difference between Filesz and Memsz is .bss
 
271
 
 
272
raid:/nfs/raid/src/dist-18.56/src> dump -o temacs
 
273
 
 
274
temacs:
 
275
 ***** PROGRAM EXECUTION HEADER *****
 
276
Type        Offset      Vaddr       Paddr
 
277
Filesz      Memsz       Flags       Align
 
278
 
 
279
6           0x34        0x8048034   0           
 
280
0xa0        0xa0        5           0           
 
281
 
 
282
3           0xd4        0           0           
 
283
0x13        0           4           0           
 
284
 
 
285
1           0x34        0x8048034   0           
 
286
0x3f2f9     0x3f2f9     5           0x1000      
 
287
 
 
288
1           0x3f330     0x8088330   0           
 
289
0x215c4     0x25a60     7           0x1000      
 
290
 
 
291
2           0x60874     0x80a9874   0           
 
292
0x80        0           7           0           
 
293
 
 
294
raid:/nfs/raid/src/dist-18.56/src> dump -o xemacs
 
295
 
 
296
xemacs:
 
297
 ***** PROGRAM EXECUTION HEADER *****
 
298
Type        Offset      Vaddr       Paddr
 
299
Filesz      Memsz       Flags       Align
 
300
 
 
301
6           0x34        0x8048034   0           
 
302
0xa0        0xa0        5           0           
 
303
 
 
304
3           0xd4        0           0           
 
305
0x13        0           4           0           
 
306
 
 
307
1           0x34        0x8048034   0           
 
308
0x3f2f9     0x3f2f9     5           0x1000      
 
309
 
 
310
1           0x3f330     0x8088330   0           
 
311
0x3e4d0     0x3e4d0     7           0x1000      
 
312
 
 
313
2           0x60874     0x80a9874   0           
 
314
0x80        0           7           0           
 
315
 
 
316
 
 
317
 */
 
318
 
 
319
/* Modified by wtien@urbana.mcd.mot.com of Motorola Inc. 
 
320
 * 
 
321
 * The above mechanism does not work if the unexeced ELF file is being
 
322
 * re-layout by other applications (such as `strip'). All the applications 
 
323
 * that re-layout the internal of ELF will layout all sections in ascending
 
324
 * order of their file offsets. After the re-layout, the data2 section will 
 
325
 * still be the LAST section in the section header vector, but its file offset 
 
326
 * is now being pushed far away down, and causes part of it not to be mapped
 
327
 * in (ie. not covered by the load segment entry in PHDR vector), therefore 
 
328
 * causes the new binary to fail.
 
329
 *
 
330
 * The solution is to modify the unexec algorithm to insert the new data2
 
331
 * section header right before the new bss section header, so their file
 
332
 * offsets will be in the ascending order. Since some of the section's (all 
 
333
 * sections AFTER the bss section) indexes are now changed, we also need to 
 
334
 * modify some fields to make them point to the right sections. This is done 
 
335
 * by macro PATCH_INDEX. All the fields that need to be patched are:
 
336
 * 
 
337
 * 1. ELF header e_shstrndx field.
 
338
 * 2. section header sh_link and sh_info field.
 
339
 * 3. symbol table entry st_shndx field.
 
340
 *
 
341
 * The above example now should look like:
 
342
 
 
343
           **** SECTION HEADER TABLE ****
 
344
[No]    Type    Flags   Addr         Offset       Size          Name
 
345
        Link    Info    Adralgn      Entsize
 
346
 
 
347
[1]     1       2       0x80480d4    0xd4         0x13          .interp
 
348
        0       0       0x1          0            
 
349
 
 
350
[2]     5       2       0x80480e8    0xe8         0x388         .hash
 
351
        3       0       0x4          0x4          
 
352
 
 
353
[3]     11      2       0x8048470    0x470        0x7f0         .dynsym
 
354
        4       1       0x4          0x10         
 
355
 
 
356
[4]     3       2       0x8048c60    0xc60        0x3ad         .dynstr
 
357
        0       0       0x1          0            
 
358
 
 
359
[5]     9       2       0x8049010    0x1010       0x338         .rel.plt
 
360
        3       7       0x4          0x8          
 
361
 
 
362
[6]     1       6       0x8049348    0x1348       0x3           .init
 
363
        0       0       0x4          0            
 
364
 
 
365
[7]     1       6       0x804934c    0x134c       0x680         .plt
 
366
        0       0       0x4          0x4          
 
367
 
 
368
[8]     1       6       0x80499cc    0x19cc       0x3c56f       .text
 
369
        0       0       0x4          0            
 
370
 
 
371
[9]     1       6       0x8085f3c    0x3df3c      0x3           .fini
 
372
        0       0       0x4          0            
 
373
 
 
374
[10]    1       2       0x8085f40    0x3df40      0x69c         .rodata
 
375
        0       0       0x4          0            
 
376
 
 
377
[11]    1       2       0x80865dc    0x3e5dc      0xd51         .rodata1
 
378
        0       0       0x4          0            
 
379
 
 
380
[12]    1       3       0x8088330    0x3f330      0x20afc       .data
 
381
        0       0       0x4          0            
 
382
 
 
383
[13]    1       3       0x80a8e2c    0x5fe2c      0x89d         .data1
 
384
        0       0       0x4          0            
 
385
 
 
386
[14]    1       3       0x80a96cc    0x606cc      0x1a8         .got
 
387
        0       0       0x4          0x4          
 
388
 
 
389
[15]    6       3       0x80a9874    0x60874      0x80          .dynamic
 
390
        4       0       0x4          0x8          
 
391
 
 
392
[16]    1       3       0x80a98f4    0x608f4      0x1cf0c       .data
 
393
        0       0       0x4          0            
 
394
 
 
395
[17]    8       3       0x80c6800    0x7d800      0             .bss
 
396
        0       0       0x4          0            
 
397
 
 
398
[18]    2       0       0            0x7d800      0x9b90        .symtab
 
399
        19      371     0x4          0x10         
 
400
 
 
401
[19]    3       0       0            0x87390      0x8526        .strtab
 
402
        0       0       0x1          0            
 
403
 
 
404
[20]    3       0       0            0x8f8b6      0x93          .shstrtab
 
405
        0       0       0x1          0            
 
406
 
 
407
[21]    1       0       0            0x8f949      0x68b7        .comment
 
408
        0       0       0x1          0            
 
409
 
 
410
 */
 
411
 
 
412
#include <sys/types.h>
 
413
#include <stdio.h>
 
414
#include <sys/stat.h>
 
415
#include <memory.h>
 
416
#include <string.h>
 
417
#include <errno.h>
 
418
#include <unistd.h>
 
419
#include <fcntl.h>
 
420
#include <elf.h>
 
421
#include <syms.h> /* for HDRR declaration */
 
422
#include <sys/mman.h>
 
423
 
 
424
#ifndef emacs
 
425
#define fatal(a, b, c) fprintf(stderr, a, b, c), exit(1)
 
426
#else
 
427
fatal()
 
428
{exit(1);}
 
429
#endif
 
430
 
 
431
/* Get the address of a particular section or program header entry,
 
432
 * accounting for the size of the entries.
 
433
 */
 
434
 
 
435
#define OLD_SECTION_H(n) \
 
436
     (*(Elf32_Shdr *) ((byte *) old_section_h + old_file_h->e_shentsize * (n)))
 
437
#define NEW_SECTION_H(n) \
 
438
     (*(Elf32_Shdr *) ((byte *) new_section_h + new_file_h->e_shentsize * (n)))
 
439
#define OLD_PROGRAM_H(n) \
 
440
     (*(Elf32_Phdr *) ((byte *) old_program_h + old_file_h->e_phentsize * (n)))
 
441
#define NEW_PROGRAM_H(n) \
 
442
     (*(Elf32_Phdr *) ((byte *) new_program_h + new_file_h->e_phentsize * (n)))
 
443
 
 
444
#define PATCH_INDEX(n) \
 
445
  do { \
 
446
         if ((n) >= old_bss_index) \
 
447
           (n)++; } while (0)
 
448
typedef unsigned char byte;
 
449
 
 
450
/* Round X up to a multiple of Y.  */
 
451
 
 
452
int
 
453
round_up (x, y)
 
454
     int x, y;
 
455
{
 
456
  int rem = x % y;
 
457
  if (rem == 0)
 
458
    return x;
 
459
  return x - rem + y;
 
460
}
 
461
 
 
462
/* ****************************************************************
 
463
 * unexec
 
464
 *
 
465
 * driving logic.
 
466
 *
 
467
 * In ELF, this works by replacing the old .bss section with a new
 
468
 * .data section, and inserting an empty .bss immediately afterwards.
 
469
 *
 
470
 */
 
471
void
 
472
unexec (new_name, old_name, data_start, bss_start, entry_address)
 
473
     char *new_name, *old_name;
 
474
     unsigned data_start, bss_start, entry_address;
 
475
{
 
476
/*  extern unsigned int bss_end; */
 
477
  int new_file, old_file, new_file_size;
 
478
 
 
479
  /* Pointers to the base of the image of the two files.  */
 
480
  caddr_t old_base, new_base;
 
481
 
 
482
  /* Pointers to the file, program and section headers for the old and new
 
483
     files.  */
 
484
  Elf32_Ehdr *old_file_h, *new_file_h;
 
485
  Elf32_Phdr *old_program_h, *new_program_h;
 
486
  Elf32_Shdr *old_section_h, *new_section_h;
 
487
 
 
488
  /* Point to the section name table in the old file.  */
 
489
  char *old_section_names;
 
490
 
 
491
  Elf32_Addr old_bss_addr, new_bss_addr;
 
492
  Elf32_Word old_bss_size, new_data2_size;
 
493
  Elf32_Off  new_data2_offset;
 
494
  Elf32_Addr new_data2_addr;
 
495
 
 
496
  int n, nn, old_bss_index, old_data_index, new_data2_index;
 
497
  int old_mdebug_index;
 
498
  struct stat stat_buf;
 
499
 
 
500
  /* Open the old file & map it into the address space.  */
 
501
 
 
502
  old_file = open (old_name, O_RDONLY);
 
503
 
 
504
  if (old_file < 0)
 
505
    fatal ("Can't open %s for reading: errno %d\n", old_name, errno);
 
506
 
 
507
  if (fstat (old_file, &stat_buf) == -1)
 
508
    fatal ("Can't fstat(%s): errno %d\n", old_name, errno);
 
509
 
 
510
  old_base = mmap (0, stat_buf.st_size, PROT_READ, MAP_SHARED, old_file, 0);
 
511
 
 
512
  if (old_base == (caddr_t) -1)
 
513
    fatal ("Can't mmap(%s): errno %d\n", old_name, errno);
 
514
 
 
515
#ifdef DEBUG
 
516
  fprintf (stderr, "mmap(%s, %x) -> %x\n", old_name, stat_buf.st_size,
 
517
           old_base);
 
518
#endif
 
519
 
 
520
  /* Get pointers to headers & section names.  */
 
521
 
 
522
  old_file_h = (Elf32_Ehdr *) old_base;
 
523
  old_program_h = (Elf32_Phdr *) ((byte *) old_base + old_file_h->e_phoff);
 
524
  old_section_h = (Elf32_Shdr *) ((byte *) old_base + old_file_h->e_shoff);
 
525
  old_section_names
 
526
    = (char *) old_base + OLD_SECTION_H (old_file_h->e_shstrndx).sh_offset;
 
527
 
 
528
  /* Find the mdebug section, if any.  */
 
529
  for (old_mdebug_index = 1; old_mdebug_index < old_file_h->e_shnum; old_mdebug_index++)
 
530
    {
 
531
#ifdef DEBUG
 
532
      fprintf (stderr, "Looking for .mdebug - found %s\n",
 
533
               old_section_names + OLD_SECTION_H(old_mdebug_index).sh_name);
 
534
#endif
 
535
      if (!strcmp (old_section_names + OLD_SECTION_H(old_mdebug_index).sh_name,
 
536
                   ".mdebug"))
 
537
        break;
 
538
    }
 
539
  if (old_mdebug_index == old_file_h->e_shnum)
 
540
    old_mdebug_index = -1; /* just means no such section was present */
 
541
 
 
542
  /* Find the old .bss section.  Figure out parameters of the new
 
543
     data2 and bss sections.  */
 
544
 
 
545
  for (old_bss_index = 1; old_bss_index < old_file_h->e_shnum; old_bss_index++)
 
546
    {
 
547
#ifdef DEBUG
 
548
      fprintf (stderr, "Looking for .bss - found %s\n",
 
549
               old_section_names + OLD_SECTION_H(old_bss_index).sh_name);
 
550
#endif
 
551
      if (!strcmp (old_section_names + OLD_SECTION_H(old_bss_index).sh_name,
 
552
                   ".bss"))
 
553
        break;
 
554
    }
 
555
  if (old_bss_index == old_file_h->e_shnum)
 
556
    fatal ("Can't find .bss in %s.\n", old_name, 0);
 
557
 
 
558
  old_bss_addr = OLD_SECTION_H (old_bss_index).sh_addr;
 
559
  old_bss_size = OLD_SECTION_H (old_bss_index).sh_size;
 
560
#if defined(emacs) || !defined(DEBUG)
 
561
  bss_end = (unsigned int) sbrk (0);
 
562
  new_bss_addr = (Elf32_Addr) bss_end;
 
563
#else
 
564
  new_bss_addr = old_bss_addr + old_bss_size + 0x1234;
 
565
#endif
 
566
  new_data2_addr = old_bss_addr;
 
567
  new_data2_size = new_bss_addr - old_bss_addr;
 
568
  new_data2_offset = OLD_SECTION_H (old_bss_index).sh_offset;
 
569
 
 
570
#ifdef DEBUG
 
571
  fprintf (stderr, "old_bss_index %d\n", old_bss_index);
 
572
  fprintf (stderr, "old_bss_addr %x\n", old_bss_addr);
 
573
  fprintf (stderr, "old_bss_size %x\n", old_bss_size);
 
574
  fprintf (stderr, "new_bss_addr %x\n", new_bss_addr);
 
575
  fprintf (stderr, "new_data2_addr %x\n", new_data2_addr);
 
576
  fprintf (stderr, "new_data2_size %x\n", new_data2_size);
 
577
  fprintf (stderr, "new_data2_offset %x\n", new_data2_offset);
 
578
#endif
 
579
 
 
580
  if ((unsigned) new_bss_addr < (unsigned) old_bss_addr + old_bss_size)
 
581
    fatal (".bss shrank when undumping???\n", 0, 0);
 
582
 
 
583
  /* Set the output file to the right size and mmap it.  Set
 
584
     pointers to various interesting objects.  stat_buf still has
 
585
     old_file data.  */
 
586
 
 
587
  new_file = open (new_name, O_RDWR | O_CREAT, 0666);
 
588
  if (new_file < 0)
 
589
    fatal ("Can't creat (%s): errno %d\n", new_name, errno);
 
590
 
 
591
  new_file_size = stat_buf.st_size + old_file_h->e_shentsize + new_data2_size;
 
592
 
 
593
  if (ftruncate (new_file, new_file_size))
 
594
    fatal ("Can't ftruncate (%s): errno %d\n", new_name, errno);
 
595
 
 
596
  new_base = mmap (0, new_file_size, PROT_READ | PROT_WRITE, MAP_SHARED,
 
597
                   new_file, 0);
 
598
 
 
599
  if (new_base == (caddr_t) -1)
 
600
    fatal ("Can't mmap (%s): errno %d\n", new_name, errno);
 
601
 
 
602
  new_file_h = (Elf32_Ehdr *) new_base;
 
603
  new_program_h = (Elf32_Phdr *) ((byte *) new_base + old_file_h->e_phoff);
 
604
  new_section_h
 
605
    = (Elf32_Shdr *) ((byte *) new_base + old_file_h->e_shoff
 
606
                      + new_data2_size);
 
607
 
 
608
  /* Make our new file, program and section headers as copies of the
 
609
     originals.  */
 
610
 
 
611
  memcpy (new_file_h, old_file_h, old_file_h->e_ehsize);
 
612
  memcpy (new_program_h, old_program_h,
 
613
          old_file_h->e_phnum * old_file_h->e_phentsize);
 
614
 
 
615
  /* Modify the e_shstrndx if necessary. */
 
616
  PATCH_INDEX (new_file_h->e_shstrndx);
 
617
 
 
618
  /* Fix up file header.  We'll add one section.  Section header is
 
619
     further away now.  */
 
620
 
 
621
  new_file_h->e_shoff += new_data2_size;
 
622
  new_file_h->e_shnum += 1;
 
623
 
 
624
#ifdef DEBUG
 
625
  fprintf (stderr, "Old section offset %x\n", old_file_h->e_shoff);
 
626
  fprintf (stderr, "Old section count %d\n", old_file_h->e_shnum);
 
627
  fprintf (stderr, "New section offset %x\n", new_file_h->e_shoff);
 
628
  fprintf (stderr, "New section count %d\n", new_file_h->e_shnum);
 
629
#endif
 
630
 
 
631
  /* Fix up a new program header.  Extend the writable data segment so
 
632
     that the bss area is covered too. Find that segment by looking
 
633
     for a segment that ends just before the .bss area.  Make sure
 
634
     that no segments are above the new .data2.  Put a loop at the end
 
635
     to adjust the offset and address of any segment that is above
 
636
     data2, just in case we decide to allow this later.  */
 
637
 
 
638
  for (n = new_file_h->e_phnum - 1; n >= 0; n--)
 
639
    {
 
640
      /* Compute maximum of all requirements for alignment of section.  */
 
641
      int alignment = (NEW_PROGRAM_H (n)).p_align;
 
642
      if ((OLD_SECTION_H (old_bss_index)).sh_addralign > alignment)
 
643
        alignment = OLD_SECTION_H (old_bss_index).sh_addralign;
 
644
 
 
645
      /* Supposedly this condition is okay for the SGI.  */
 
646
#if 0
 
647
      if (NEW_PROGRAM_H (n).p_vaddr + NEW_PROGRAM_H (n).p_filesz > old_bss_addr)
 
648
        fatal ("Program segment above .bss in %s\n", old_name, 0);
 
649
#endif
 
650
 
 
651
      if (NEW_PROGRAM_H (n).p_type == PT_LOAD
 
652
          && (round_up ((NEW_PROGRAM_H (n)).p_vaddr
 
653
                        + (NEW_PROGRAM_H (n)).p_filesz,
 
654
                        alignment)
 
655
              == round_up (old_bss_addr, alignment)))
 
656
        break;
 
657
    }
 
658
  if (n < 0)
 
659
    fatal ("Couldn't find segment next to .bss in %s\n", old_name, 0);
 
660
 
 
661
  NEW_PROGRAM_H (n).p_filesz += new_data2_size;
 
662
  NEW_PROGRAM_H (n).p_memsz = NEW_PROGRAM_H (n).p_filesz;
 
663
 
 
664
#if 1 /* Maybe allow section after data2 - does this ever happen?  */
 
665
  for (n = new_file_h->e_phnum - 1; n >= 0; n--)
 
666
    {
 
667
      if (NEW_PROGRAM_H (n).p_vaddr
 
668
          && NEW_PROGRAM_H (n).p_vaddr >= new_data2_addr)
 
669
        NEW_PROGRAM_H (n).p_vaddr += new_data2_size - old_bss_size;
 
670
 
 
671
      if (NEW_PROGRAM_H (n).p_offset >= new_data2_offset)
 
672
        NEW_PROGRAM_H (n).p_offset += new_data2_size;
 
673
    }
 
674
#endif
 
675
 
 
676
  /* Fix up section headers based on new .data2 section.  Any section
 
677
     whose offset or virtual address is after the new .data2 section
 
678
     gets its value adjusted.  .bss size becomes zero and new address
 
679
     is set.  data2 section header gets added by copying the existing
 
680
     .data header and modifying the offset, address and size.  */
 
681
  for (old_data_index = 1; old_data_index < old_file_h->e_shnum;
 
682
       old_data_index++)
 
683
    if (!strcmp (old_section_names + OLD_SECTION_H (old_data_index).sh_name,
 
684
                 ".data"))
 
685
      break;
 
686
  if (old_data_index == old_file_h->e_shnum)
 
687
    fatal ("Can't find .data in %s.\n", old_name, 0);
 
688
 
 
689
  /* Walk through all section headers, insert the new data2 section right 
 
690
     before the new bss section.  */
 
691
  for (n = 1, nn = 1; n < old_file_h->e_shnum; n++, nn++)
 
692
    {
 
693
      caddr_t src;
 
694
      /* If it is bss section, insert the new data2 section before it.  */
 
695
      if (n == old_bss_index)
 
696
        {
 
697
          /* Steal the data section header for this data2 section.  */
 
698
          memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (old_data_index),
 
699
                  new_file_h->e_shentsize);
 
700
          
 
701
          NEW_SECTION_H (nn).sh_addr = new_data2_addr;
 
702
          NEW_SECTION_H (nn).sh_offset = new_data2_offset;
 
703
          NEW_SECTION_H (nn).sh_size = new_data2_size;
 
704
          /* Use the bss section's alignment. This will assure that the
 
705
             new data2 section always be placed in the same spot as the old
 
706
             bss section by any other application.  */
 
707
          NEW_SECTION_H (nn).sh_addralign = OLD_SECTION_H (n).sh_addralign;
 
708
 
 
709
          /* Now copy over what we have in the memory now.  */
 
710
          memcpy (NEW_SECTION_H (nn).sh_offset + new_base, 
 
711
                  (caddr_t) OLD_SECTION_H (n).sh_addr, 
 
712
                  new_data2_size);
 
713
          nn++;
 
714
        }
 
715
      
 
716
      memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (n), 
 
717
              old_file_h->e_shentsize);
 
718
      
 
719
      /* The new bss section's size is zero, and its file offset and virtual
 
720
         address should be off by NEW_DATA2_SIZE.  */
 
721
      if (n == old_bss_index)
 
722
        {
 
723
          /* NN should be `old_bss_index + 1' at this point. */
 
724
          NEW_SECTION_H (nn).sh_offset += new_data2_size;
 
725
          NEW_SECTION_H (nn).sh_addr += new_data2_size;
 
726
          /* Let the new bss section address alignment be the same as the
 
727
             section address alignment followed the old bss section, so 
 
728
             this section will be placed in exactly the same place.  */
 
729
          NEW_SECTION_H (nn).sh_addralign = OLD_SECTION_H (nn).sh_addralign;
 
730
          NEW_SECTION_H (nn).sh_size = 0;
 
731
        }
 
732
      /* Any section that was original placed AFTER the bss section should now
 
733
         be off by NEW_DATA2_SIZE.  */
 
734
      else if (NEW_SECTION_H (nn).sh_offset >= new_data2_offset)
 
735
        NEW_SECTION_H (nn).sh_offset += new_data2_size;
 
736
      
 
737
      /* If any section hdr refers to the section after the new .data
 
738
         section, make it refer to next one because we have inserted 
 
739
         a new section in between.  */
 
740
      
 
741
      PATCH_INDEX (NEW_SECTION_H (nn).sh_link);
 
742
      /* For symbol tables, info is a symbol table index,
 
743
         so don't change it.  */
 
744
      if (NEW_SECTION_H (nn).sh_type != SHT_SYMTAB
 
745
          && NEW_SECTION_H (nn).sh_type != SHT_DYNSYM)
 
746
        PATCH_INDEX (NEW_SECTION_H (nn).sh_info);
 
747
      
 
748
      /* Now, start to copy the content of sections. */
 
749
      if (NEW_SECTION_H (nn).sh_type == SHT_NULL
 
750
          || NEW_SECTION_H (nn).sh_type == SHT_NOBITS)
 
751
        continue;
 
752
      
 
753
      /* Write out the sections. .data and .data1 (and data2, called
 
754
         ".data" in the strings table) get copied from the current process
 
755
         instead of the old file.  */
 
756
      if (!strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".data")
 
757
          || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name),
 
758
                      ".data1"))
 
759
        src = (caddr_t) OLD_SECTION_H (n).sh_addr;
 
760
      else
 
761
        src = old_base + OLD_SECTION_H (n).sh_offset;
 
762
      
 
763
      memcpy (NEW_SECTION_H (nn).sh_offset + new_base, src,
 
764
              NEW_SECTION_H (nn).sh_size);
 
765
 
 
766
      /* Adjust  the HDRR offsets in .mdebug and copy the 
 
767
         line data if it's in its usual 'hole' in the object.
 
768
         Makes the new file debuggable with dbx.
 
769
         patches up two problems: the absolute file offsets
 
770
         in the HDRR record of .mdebug (see /usr/include/syms.h), and
 
771
         the ld bug that gets the line table in a hole in the
 
772
         elf file rather than in the .mdebug section proper.
 
773
         David Anderson. davea@sgi.com  Jan 16,1994.  */
 
774
      if (n == old_mdebug_index)
 
775
        {
 
776
#define MDEBUGADJUST(__ct,__fileaddr)           \
 
777
  if (n_phdrr->__ct > 0)                        \
 
778
    {                                           \
 
779
      n_phdrr->__fileaddr += movement;          \
 
780
    }
 
781
 
 
782
        HDRR * o_phdrr = (HDRR *)((byte *)old_base + OLD_SECTION_H (n).sh_offset);
 
783
        HDRR * n_phdrr = (HDRR *)((byte *)new_base + NEW_SECTION_H (nn).sh_offset);
 
784
        unsigned movement = new_data2_size;
 
785
 
 
786
        MDEBUGADJUST (idnMax, cbDnOffset);
 
787
        MDEBUGADJUST (ipdMax, cbPdOffset);
 
788
        MDEBUGADJUST (isymMax, cbSymOffset);
 
789
        MDEBUGADJUST (ioptMax, cbOptOffset);
 
790
        MDEBUGADJUST (iauxMax, cbAuxOffset);
 
791
        MDEBUGADJUST (issMax, cbSsOffset);
 
792
        MDEBUGADJUST (issExtMax, cbSsExtOffset);
 
793
        MDEBUGADJUST (ifdMax, cbFdOffset);
 
794
        MDEBUGADJUST (crfd, cbRfdOffset);
 
795
        MDEBUGADJUST (iextMax, cbExtOffset);
 
796
        /* The Line Section, being possible off in a hole of the object,
 
797
           requires special handling.  */
 
798
        if (n_phdrr->cbLine > 0)
 
799
          {
 
800
            if (o_phdrr->cbLineOffset > (OLD_SECTION_H (n).sh_offset
 
801
                                         + OLD_SECTION_H (n).sh_size))
 
802
              {
 
803
                /* line data is in a hole in elf. do special copy and adjust
 
804
                   for this ld mistake.
 
805
                   */
 
806
                n_phdrr->cbLineOffset += movement;
 
807
 
 
808
                memcpy (n_phdrr->cbLineOffset + new_base,
 
809
                        o_phdrr->cbLineOffset + old_base, n_phdrr->cbLine);
 
810
              }
 
811
            else
 
812
              {
 
813
                /* somehow line data is in .mdebug as it is supposed to be.  */
 
814
                MDEBUGADJUST (cbLine, cbLineOffset);
 
815
              }
 
816
          }
 
817
      }
 
818
 
 
819
      /* If it is the symbol table, its st_shndx field needs to be patched. */
 
820
      if (NEW_SECTION_H (nn).sh_type == SHT_SYMTAB
 
821
          || NEW_SECTION_H (nn).sh_type == SHT_DYNSYM)
 
822
        {
 
823
          Elf32_Shdr *spt = &NEW_SECTION_H (nn);
 
824
          unsigned int num = spt->sh_size / spt->sh_entsize;
 
825
          Elf32_Sym * sym = (Elf32_Sym *) (NEW_SECTION_H (nn).sh_offset
 
826
                                           + new_base);
 
827
          for (; num--; sym++)
 
828
            {
 
829
              if (sym->st_shndx == SHN_UNDEF
 
830
                  || sym->st_shndx == SHN_ABS
 
831
                  || sym->st_shndx == SHN_COMMON)
 
832
                continue;
 
833
        
 
834
              PATCH_INDEX (sym->st_shndx);
 
835
            }
 
836
        }
 
837
    }
 
838
 
 
839
  /* Close the files and make the new file executable.  */
 
840
 
 
841
  if (close (old_file))
 
842
    fatal ("Can't close (%s): errno %d\n", old_name, errno);
 
843
 
 
844
  if (close (new_file))
 
845
    fatal ("Can't close (%s): errno %d\n", new_name, errno);
 
846
 
 
847
  if (stat (new_name, &stat_buf) == -1)
 
848
    fatal ("Can't stat (%s): errno %d\n", new_name, errno);
 
849
 
 
850
  n = umask (777);
 
851
  umask (n);
 
852
  stat_buf.st_mode |= 0111 & ~n;
 
853
  if (chmod (new_name, stat_buf.st_mode) == -1)
 
854
    fatal ("Can't chmod (%s): errno %d\n", new_name, errno);
 
855
}
 
856
 
 
857
 
 
858
 
 
859
#ifdef UNIXSAVE
 
860
#include "save.c"
 
861
#endif