Annotation of GNUtools/emacs/src/unexelf.c, revision 1.1

1.1     ! root        1: /* Copyright (C) 1985, 1986, 1987, 1988 Free Software Foundation, Inc.
        !             2: 
        !             3:     This program is free software; you can redistribute it and/or modify
        !             4:     it under the terms of the GNU General Public License as published by
        !             5:     the Free Software Foundation; either version 1, or (at your option)
        !             6:     any later version.
        !             7: 
        !             8:     This program is distributed in the hope that it will be useful,
        !             9:     but WITHOUT ANY WARRANTY; without even the implied warranty of
        !            10:     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
        !            11:     GNU General Public License for more details.
        !            12: 
        !            13:     You should have received a copy of the GNU General Public License
        !            14:     along with this program; if not, write to the Free Software
        !            15:     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
        !            16: 
        !            17: In other words, you are welcome to use, share and improve this program.
        !            18: You are forbidden to forbid anyone else to use, share and improve
        !            19: what you give them.   Help stamp out software-hoarding!  */
        !            20: 
        !            21: 
        !            22: /*
        !            23:  * unexec.c - Convert a running program into an a.out file.
        !            24:  *
        !            25:  * Author:     Spencer W. Thomas
        !            26:  *             Computer Science Dept.
        !            27:  *             University of Utah
        !            28:  * Date:       Tue Mar  2 1982
        !            29:  * Modified heavily since then.
        !            30:  *
        !            31:  * Synopsis:
        !            32:  *     unexec (new_name, a_name, data_start, bss_start, entry_address)
        !            33:  *     char *new_name, *a_name;
        !            34:  *     unsigned data_start, bss_start, entry_address;
        !            35:  *
        !            36:  * Takes a snapshot of the program and makes an a.out format file in the
        !            37:  * file named by the string argument new_name.
        !            38:  * If a_name is non-NULL, the symbol table will be taken from the given file.
        !            39:  * On some machines, an existing a_name file is required.
        !            40:  *
        !            41:  * The boundaries within the a.out file may be adjusted with the data_start
        !            42:  * and bss_start arguments.  Either or both may be given as 0 for defaults.
        !            43:  *
        !            44:  * Data_start gives the boundary between the text segment and the data
        !            45:  * segment of the program.  The text segment can contain shared, read-only
        !            46:  * program code and literal data, while the data segment is always unshared
        !            47:  * and unprotected.  Data_start gives the lowest unprotected address.
        !            48:  * The value you specify may be rounded down to a suitable boundary
        !            49:  * as required by the machine you are using.
        !            50:  *
        !            51:  * Specifying zero for data_start means the boundary between text and data
        !            52:  * should not be the same as when the program was loaded.
        !            53:  * If NO_REMAP is defined, the argument data_start is ignored and the
        !            54:  * segment boundaries are never changed.
        !            55:  *
        !            56:  * Bss_start indicates how much of the data segment is to be saved in the
        !            57:  * a.out file and restored when the program is executed.  It gives the lowest
        !            58:  * unsaved address, and is rounded up to a page boundary.  The default when 0
        !            59:  * is given assumes that the entire data segment is to be stored, including
        !            60:  * the previous data and bss as well as any additional storage allocated with
        !            61:  * break (2).
        !            62:  *
        !            63:  * The new file is set up to start at entry_address.
        !            64:  *
        !            65:  * If you make improvements I'd like to get them too.
        !            66:  * harpo!utah-cs!thomas, thomas@Utah-20
        !            67:  *
        !            68:  */
        !            69: 
        !            70: /* Even more heavily modified by [email protected] of Dell Computer Co.
        !            71:  * ELF support added.
        !            72:  *
        !            73:  * Basic theory: the data space of the running process needs to be
        !            74:  * dumped to the output file.  Normally we would just enlarge the size
        !            75:  * of .data, scooting everything down.  But we can't do that in ELF,
        !            76:  * because there is often something between the .data space and the
        !            77:  * .bss space.
        !            78:  *
        !            79:  * In the temacs dump below, notice that the Global Offset Table
        !            80:  * (.got) and the Dynamic link data (.dynamic) come between .data1 and
        !            81:  * .bss.  It does not work to overlap .data with these fields.
        !            82:  *
        !            83:  * The solution is to create a new .data segment.  This segment is
        !            84:  * filled with data from the current process.  Since the contents of
        !            85:  * various sections refer to sections by index, the new .data segment
        !            86:  * is made the last in the table to avoid changing any existing index.
        !            87: 
        !            88:  * This is an example of how the section headers are changed.  "Addr"
        !            89:  * is a process virtual address.  "Offset" is a file offset.
        !            90: 
        !            91: raid:/nfs/raid/src/dist-18.56/src> dump -h temacs
        !            92: 
        !            93: temacs:
        !            94: 
        !            95:            **** SECTION HEADER TABLE ****
        !            96: [No]    Type    Flags   Addr         Offset       Size          Name
        !            97:         Link    Info    Adralgn      Entsize
        !            98: 
        !            99: [1]     1       2       0x80480d4    0xd4         0x13          .interp
        !           100:         0       0       0x1          0            
        !           101: 
        !           102: [2]     5       2       0x80480e8    0xe8         0x388         .hash
        !           103:         3       0       0x4          0x4          
        !           104: 
        !           105: [3]     11      2       0x8048470    0x470        0x7f0         .dynsym
        !           106:         4       1       0x4          0x10         
        !           107: 
        !           108: [4]     3       2       0x8048c60    0xc60        0x3ad         .dynstr
        !           109:         0       0       0x1          0            
        !           110: 
        !           111: [5]     9       2       0x8049010    0x1010       0x338         .rel.plt
        !           112:         3       7       0x4          0x8          
        !           113: 
        !           114: [6]     1       6       0x8049348    0x1348       0x3           .init
        !           115:         0       0       0x4          0            
        !           116: 
        !           117: [7]     1       6       0x804934c    0x134c       0x680         .plt
        !           118:         0       0       0x4          0x4          
        !           119: 
        !           120: [8]     1       6       0x80499cc    0x19cc       0x3c56f       .text
        !           121:         0       0       0x4          0            
        !           122: 
        !           123: [9]     1       6       0x8085f3c    0x3df3c      0x3           .fini
        !           124:         0       0       0x4          0            
        !           125: 
        !           126: [10]    1       2       0x8085f40    0x3df40      0x69c         .rodata
        !           127:         0       0       0x4          0            
        !           128: 
        !           129: [11]    1       2       0x80865dc    0x3e5dc      0xd51         .rodata1
        !           130:         0       0       0x4          0            
        !           131: 
        !           132: [12]    1       3       0x8088330    0x3f330      0x20afc       .data
        !           133:         0       0       0x4          0            
        !           134: 
        !           135: [13]    1       3       0x80a8e2c    0x5fe2c      0x89d         .data1
        !           136:         0       0       0x4          0            
        !           137: 
        !           138: [14]    1       3       0x80a96cc    0x606cc      0x1a8         .got
        !           139:         0       0       0x4          0x4          
        !           140: 
        !           141: [15]    6       3       0x80a9874    0x60874      0x80          .dynamic
        !           142:         4       0       0x4          0x8          
        !           143: 
        !           144: [16]    8       3       0x80a98f4    0x608f4      0x449c        .bss
        !           145:         0       0       0x4          0            
        !           146: 
        !           147: [17]    2       0       0            0x608f4      0x9b90        .symtab
        !           148:         18      371     0x4          0x10         
        !           149: 
        !           150: [18]    3       0       0            0x6a484      0x8526        .strtab
        !           151:         0       0       0x1          0            
        !           152: 
        !           153: [19]    3       0       0            0x729aa      0x93          .shstrtab
        !           154:         0       0       0x1          0            
        !           155: 
        !           156: [20]    1       0       0            0x72a3d      0x68b7        .comment
        !           157:         0       0       0x1          0            
        !           158: 
        !           159: raid:/nfs/raid/src/dist-18.56/src> dump -h xemacs
        !           160: 
        !           161: xemacs:
        !           162: 
        !           163:            **** SECTION HEADER TABLE ****
        !           164: [No]    Type    Flags   Addr         Offset       Size          Name
        !           165:         Link    Info    Adralgn      Entsize
        !           166: 
        !           167: [1]     1       2       0x80480d4    0xd4         0x13          .interp
        !           168:         0       0       0x1          0            
        !           169: 
        !           170: [2]     5       2       0x80480e8    0xe8         0x388         .hash
        !           171:         3       0       0x4          0x4          
        !           172: 
        !           173: [3]     11      2       0x8048470    0x470        0x7f0         .dynsym
        !           174:         4       1       0x4          0x10         
        !           175: 
        !           176: [4]     3       2       0x8048c60    0xc60        0x3ad         .dynstr
        !           177:         0       0       0x1          0            
        !           178: 
        !           179: [5]     9       2       0x8049010    0x1010       0x338         .rel.plt
        !           180:         3       7       0x4          0x8          
        !           181: 
        !           182: [6]     1       6       0x8049348    0x1348       0x3           .init
        !           183:         0       0       0x4          0            
        !           184: 
        !           185: [7]     1       6       0x804934c    0x134c       0x680         .plt
        !           186:         0       0       0x4          0x4          
        !           187: 
        !           188: [8]     1       6       0x80499cc    0x19cc       0x3c56f       .text
        !           189:         0       0       0x4          0            
        !           190: 
        !           191: [9]     1       6       0x8085f3c    0x3df3c      0x3           .fini
        !           192:         0       0       0x4          0            
        !           193: 
        !           194: [10]    1       2       0x8085f40    0x3df40      0x69c         .rodata
        !           195:         0       0       0x4          0            
        !           196: 
        !           197: [11]    1       2       0x80865dc    0x3e5dc      0xd51         .rodata1
        !           198:         0       0       0x4          0            
        !           199: 
        !           200: [12]    1       3       0x8088330    0x3f330      0x20afc       .data
        !           201:         0       0       0x4          0            
        !           202: 
        !           203: [13]    1       3       0x80a8e2c    0x5fe2c      0x89d         .data1
        !           204:         0       0       0x4          0            
        !           205: 
        !           206: [14]    1       3       0x80a96cc    0x606cc      0x1a8         .got
        !           207:         0       0       0x4          0x4          
        !           208: 
        !           209: [15]    6       3       0x80a9874    0x60874      0x80          .dynamic
        !           210:         4       0       0x4          0x8          
        !           211: 
        !           212: [16]    8       3       0x80c6800    0x7d800      0             .bss
        !           213:         0       0       0x4          0            
        !           214: 
        !           215: [17]    2       0       0            0x7d800      0x9b90        .symtab
        !           216:         18      371     0x4          0x10         
        !           217: 
        !           218: [18]    3       0       0            0x87390      0x8526        .strtab
        !           219:         0       0       0x1          0            
        !           220: 
        !           221: [19]    3       0       0            0x8f8b6      0x93          .shstrtab
        !           222:         0       0       0x1          0            
        !           223: 
        !           224: [20]    1       0       0            0x8f949      0x68b7        .comment
        !           225:         0       0       0x1          0            
        !           226: 
        !           227: [21]    1       3       0x80a98f4    0x608f4      0x1cf0c       .data
        !           228:         0       0       0x4          0            
        !           229: 
        !           230:  * This is an example of how the file header is changed.  "Shoff" is
        !           231:  * the section header offset within the file.  Since that table is
        !           232:  * after the new .data section, it is moved.  "Shnum" is the number of
        !           233:  * sections, which we increment.
        !           234:  *
        !           235:  * "Phoff" is the file offset to the program header.  "Phentsize" and
        !           236:  * "Shentsz" are the program and section header entries sizes respectively.
        !           237:  * These can be larger than the apparent struct sizes.
        !           238: 
        !           239: raid:/nfs/raid/src/dist-18.56/src> dump -f temacs
        !           240: 
        !           241: temacs:
        !           242: 
        !           243:                     **** ELF HEADER ****
        !           244: Class        Data       Type         Machine     Version
        !           245: Entry        Phoff      Shoff        Flags       Ehsize
        !           246: Phentsize    Phnum      Shentsz      Shnum       Shstrndx
        !           247: 
        !           248: 1            1          2            3           1
        !           249: 0x80499cc    0x34       0x792f4      0           0x34
        !           250: 0x20         5          0x28         21          19
        !           251: 
        !           252: raid:/nfs/raid/src/dist-18.56/src> dump -f xemacs
        !           253: 
        !           254: xemacs:
        !           255: 
        !           256:                     **** ELF HEADER ****
        !           257: Class        Data       Type         Machine     Version
        !           258: Entry        Phoff      Shoff        Flags       Ehsize
        !           259: Phentsize    Phnum      Shentsz      Shnum       Shstrndx
        !           260: 
        !           261: 1            1          2            3           1
        !           262: 0x80499cc    0x34       0x96200      0           0x34
        !           263: 0x20         5          0x28         22          19
        !           264: 
        !           265:  * These are the program headers.  "Offset" is the file offset to the
        !           266:  * segment.  "Vaddr" is the memory load address.  "Filesz" is the
        !           267:  * segment size as it appears in the file, and "Memsz" is the size in
        !           268:  * memory.  Below, the third segment is the code and the fourth is the
        !           269:  * data: the difference between Filesz and Memsz is .bss
        !           270: 
        !           271: raid:/nfs/raid/src/dist-18.56/src> dump -o temacs
        !           272: 
        !           273: temacs:
        !           274:  ***** PROGRAM EXECUTION HEADER *****
        !           275: Type        Offset      Vaddr       Paddr
        !           276: Filesz      Memsz       Flags       Align
        !           277: 
        !           278: 6           0x34        0x8048034   0           
        !           279: 0xa0        0xa0        5           0           
        !           280: 
        !           281: 3           0xd4        0           0           
        !           282: 0x13        0           4           0           
        !           283: 
        !           284: 1           0x34        0x8048034   0           
        !           285: 0x3f2f9     0x3f2f9     5           0x1000      
        !           286: 
        !           287: 1           0x3f330     0x8088330   0           
        !           288: 0x215c4     0x25a60     7           0x1000      
        !           289: 
        !           290: 2           0x60874     0x80a9874   0           
        !           291: 0x80        0           7           0           
        !           292: 
        !           293: raid:/nfs/raid/src/dist-18.56/src> dump -o xemacs
        !           294: 
        !           295: xemacs:
        !           296:  ***** PROGRAM EXECUTION HEADER *****
        !           297: Type        Offset      Vaddr       Paddr
        !           298: Filesz      Memsz       Flags       Align
        !           299: 
        !           300: 6           0x34        0x8048034   0           
        !           301: 0xa0        0xa0        5           0           
        !           302: 
        !           303: 3           0xd4        0           0           
        !           304: 0x13        0           4           0           
        !           305: 
        !           306: 1           0x34        0x8048034   0           
        !           307: 0x3f2f9     0x3f2f9     5           0x1000      
        !           308: 
        !           309: 1           0x3f330     0x8088330   0           
        !           310: 0x3e4d0     0x3e4d0     7           0x1000      
        !           311: 
        !           312: 2           0x60874     0x80a9874   0           
        !           313: 0x80        0           7           0           
        !           314: 
        !           315: 
        !           316:  */
        !           317: 
        !           318: #include <sys/types.h>
        !           319: #include <stdio.h>
        !           320: #include <sys/stat.h>
        !           321: #include <memory.h>
        !           322: #include <string.h>
        !           323: #include <errno.h>
        !           324: #include <unistd.h>
        !           325: #include <fcntl.h>
        !           326: #include <elf.h>
        !           327: #include <sys/mman.h>
        !           328: 
        !           329: #ifndef emacs
        !           330: #define fatal(a, b, c) fprintf(stderr, a, b, c), exit(1)
        !           331: #else
        !           332: extern void fatal(char *, ...);
        !           333: #endif
        !           334: 
        !           335: /* Get the address of a particular section or program header entry,
        !           336:  * accounting for the size of the entries.
        !           337:  */
        !           338: 
        !           339: #define OLD_SECTION_H(n) \
        !           340:      (*(Elf32_Shdr *) ((byte *) old_section_h + old_file_h->e_shentsize * (n)))
        !           341: #define NEW_SECTION_H(n) \
        !           342:      (*(Elf32_Shdr *) ((byte *) new_section_h + new_file_h->e_shentsize * (n)))
        !           343: #define OLD_PROGRAM_H(n) \
        !           344:      (*(Elf32_Phdr *) ((byte *) old_program_h + old_file_h->e_phentsize * (n)))
        !           345: #define NEW_PROGRAM_H(n) \
        !           346:      (*(Elf32_Phdr *) ((byte *) new_program_h + new_file_h->e_phentsize * (n)))
        !           347: 
        !           348: typedef unsigned char byte;
        !           349: 
        !           350: /* Round X up to a multiple of Y.  */
        !           351: 
        !           352: int
        !           353: round_up (x, y)
        !           354:      int x, y;
        !           355: {
        !           356:   int rem = x % y;
        !           357:   if (rem == 0)
        !           358:     return x;
        !           359:   return x - rem + y;
        !           360: }
        !           361: 
        !           362: /* ****************************************************************
        !           363:  * unexec
        !           364:  *
        !           365:  * driving logic.
        !           366:  *
        !           367:  * In ELF, this works by replacing the old .bss section with a new
        !           368:  * .data section, and inserting an empty .bss immediately afterwards.
        !           369:  *
        !           370:  */
        !           371: void
        !           372: unexec (new_name, old_name, data_start, bss_start, entry_address)
        !           373:      char *new_name, *old_name;
        !           374:      unsigned data_start, bss_start, entry_address;
        !           375: {
        !           376:   extern unsigned int bss_end;
        !           377:   int new_file, old_file, new_file_size;
        !           378: 
        !           379:   /* Pointers to the base of the image of the two files. */
        !           380:   caddr_t old_base, new_base;
        !           381: 
        !           382:   /* Pointers to the file, program and section headers for the old and new
        !           383:    * files.
        !           384:    */
        !           385:   Elf32_Ehdr *old_file_h, *new_file_h;
        !           386:   Elf32_Phdr *old_program_h, *new_program_h;
        !           387:   Elf32_Shdr *old_section_h, *new_section_h;
        !           388: 
        !           389:   /* Point to the section name table in the old file */
        !           390:   char *old_section_names;
        !           391: 
        !           392:   Elf32_Addr old_bss_addr, new_bss_addr;
        !           393:   Elf32_Word old_bss_size, new_data2_size;
        !           394:   Elf32_Off  new_data2_offset;
        !           395:   Elf32_Addr new_data2_addr;
        !           396: 
        !           397:   int n, old_bss_index, old_data_index, new_data2_index;
        !           398:   struct stat stat_buf;
        !           399: 
        !           400:   /* Open the old file & map it into the address space. */
        !           401: 
        !           402:   old_file = open (old_name, O_RDONLY);
        !           403: 
        !           404:   if (old_file < 0)
        !           405:     fatal ("Can't open %s for reading: errno %d\n", old_name, errno);
        !           406: 
        !           407:   if (fstat (old_file, &stat_buf) == -1)
        !           408:     fatal ("Can't fstat(%s): errno %d\n", old_name, errno);
        !           409: 
        !           410:   old_base = mmap (0, stat_buf.st_size, PROT_READ, MAP_SHARED, old_file, 0);
        !           411: 
        !           412:   if (old_base == (caddr_t) -1)
        !           413:     fatal ("Can't mmap(%s): errno %d\n", old_name, errno);
        !           414: 
        !           415: #ifdef DEBUG
        !           416:   fprintf (stderr, "mmap(%s, %x) -> %x\n", old_name, stat_buf.st_size,
        !           417:           old_base);
        !           418: #endif
        !           419: 
        !           420:   /* Get pointers to headers & section names */
        !           421: 
        !           422:   old_file_h = (Elf32_Ehdr *) old_base;
        !           423:   old_program_h = (Elf32_Phdr *) ((byte *) old_base + old_file_h->e_phoff);
        !           424:   old_section_h = (Elf32_Shdr *) ((byte *) old_base + old_file_h->e_shoff);
        !           425:   old_section_names = (char *) old_base
        !           426:     + OLD_SECTION_H(old_file_h->e_shstrndx).sh_offset;
        !           427: 
        !           428:   /* Find the old .bss section.  Figure out parameters of the new
        !           429:    * data2 and bss sections.
        !           430:    */
        !           431: 
        !           432:   for (old_bss_index = 1; old_bss_index < old_file_h->e_shnum; old_bss_index++)
        !           433:     {
        !           434: #ifdef DEBUG
        !           435:       fprintf (stderr, "Looking for .bss - found %s\n",
        !           436:               old_section_names + OLD_SECTION_H(old_bss_index).sh_name);
        !           437: #endif
        !           438:       if (!strcmp (old_section_names + OLD_SECTION_H(old_bss_index).sh_name,
        !           439:                   ".bss"))
        !           440:        break;
        !           441:     }
        !           442:   if (old_bss_index == old_file_h->e_shnum)
        !           443:     fatal ("Can't find .bss in %s.\n", old_name, 0);
        !           444: 
        !           445:   old_bss_addr = OLD_SECTION_H(old_bss_index).sh_addr;
        !           446:   old_bss_size = OLD_SECTION_H(old_bss_index).sh_size;
        !           447: #if defined(emacs) || !defined(DEBUG)
        !           448:   bss_end = (unsigned int) sbrk (0);
        !           449:   new_bss_addr = (Elf32_Addr) bss_end;
        !           450: #else
        !           451:   new_bss_addr = old_bss_addr + old_bss_size + 0x1234;
        !           452: #endif
        !           453:   new_data2_addr = old_bss_addr;
        !           454:   new_data2_size = new_bss_addr - old_bss_addr;
        !           455:   new_data2_offset = OLD_SECTION_H(old_bss_index).sh_offset;
        !           456: 
        !           457: #ifdef DEBUG
        !           458:   fprintf (stderr, "old_bss_index %d\n", old_bss_index);
        !           459:   fprintf (stderr, "old_bss_addr %x\n", old_bss_addr);
        !           460:   fprintf (stderr, "old_bss_size %x\n", old_bss_size);
        !           461:   fprintf (stderr, "new_bss_addr %x\n", new_bss_addr);
        !           462:   fprintf (stderr, "new_data2_addr %x\n", new_data2_addr);
        !           463:   fprintf (stderr, "new_data2_size %x\n", new_data2_size);
        !           464:   fprintf (stderr, "new_data2_offset %x\n", new_data2_offset);
        !           465: #endif
        !           466: 
        !           467:   if ((unsigned) new_bss_addr < (unsigned) old_bss_addr + old_bss_size)
        !           468:     fatal (".bss shrank when undumping???\n", 0, 0);
        !           469: 
        !           470:   /* Set the output file to the right size and mmap(2) it.  Set
        !           471:    * pointers to various interesting objects.  stat_buf still has
        !           472:    * old_file data.
        !           473:    */
        !           474: 
        !           475:   new_file = open (new_name, O_RDWR | O_CREAT, 0666);
        !           476:   if (new_file < 0)
        !           477:     fatal ("Can't creat(%s): errno %d\n", new_name, errno);
        !           478: 
        !           479:   new_file_size = stat_buf.st_size + old_file_h->e_shentsize + new_data2_size;
        !           480: 
        !           481:   if (ftruncate (new_file, new_file_size))
        !           482:     fatal ("Can't ftruncate(%s): errno %d\n", new_name, errno);
        !           483: 
        !           484:   new_base = mmap (0, new_file_size, PROT_READ | PROT_WRITE, MAP_SHARED,
        !           485:                   new_file, 0);
        !           486: 
        !           487:   if (new_base == (caddr_t) -1)
        !           488:     fatal ("Can't mmap(%s): errno %d\n", new_name, errno);
        !           489: 
        !           490:   new_file_h = (Elf32_Ehdr *) new_base;
        !           491:   new_program_h = (Elf32_Phdr *) ((byte *) new_base + old_file_h->e_phoff);
        !           492:   new_section_h = (Elf32_Shdr *)
        !           493:     ((byte *) new_base + old_file_h->e_shoff + new_data2_size);
        !           494: 
        !           495:   /* Make our new file, program and section headers as copies of the
        !           496:    * originals.
        !           497:    */
        !           498: 
        !           499:   memcpy (new_file_h, old_file_h, old_file_h->e_ehsize);
        !           500:   memcpy (new_program_h, old_program_h,
        !           501:          old_file_h->e_phnum * old_file_h->e_phentsize);
        !           502:   memcpy (new_section_h, old_section_h,
        !           503:          old_file_h->e_shnum * old_file_h->e_shentsize);
        !           504: 
        !           505:   /* Fix up file header.  We'll add one section.  Section header is
        !           506:    * further away now.
        !           507:    */
        !           508: 
        !           509:   new_file_h->e_shoff += new_data2_size;
        !           510:   new_file_h->e_shnum += 1;
        !           511: 
        !           512: #ifdef DEBUG
        !           513:   fprintf (stderr, "Old section offset %x\n", old_file_h->e_shoff);
        !           514:   fprintf (stderr, "Old section count %d\n", old_file_h->e_shnum);
        !           515:   fprintf (stderr, "New section offset %x\n", new_file_h->e_shoff);
        !           516:   fprintf (stderr, "New section count %d\n", new_file_h->e_shnum);
        !           517: #endif
        !           518: 
        !           519:   /* Fix up a new program header.  Extend the writable data segment so
        !           520:    * that the bss area is covered too. Find that segment by looking
        !           521:    * for a segment that ends just before the .bss area.  Make sure
        !           522:    * that no segments are above the new .data2.  Put a loop at the end
        !           523:    * to adjust the offset and address of any segment that is above
        !           524:    * data2, just in case we decide to allow this later.
        !           525:    */
        !           526: 
        !           527:   for (n = new_file_h->e_phnum - 1; n >= 0; n--)
        !           528:     {
        !           529:       /* Compute maximum of all requirements for alignment of section.  */
        !           530:       int alignment = (NEW_PROGRAM_H (n)).p_align;
        !           531:       if ((OLD_SECTION_H (old_bss_index)).sh_addralign > alignment)
        !           532:        alignment = OLD_SECTION_H (old_bss_index).sh_addralign;
        !           533: 
        !           534:       if (NEW_PROGRAM_H(n).p_vaddr + NEW_PROGRAM_H(n).p_filesz > old_bss_addr)
        !           535:        fatal ("Program segment above .bss in %s\n", old_name, 0);
        !           536: 
        !           537:       if (NEW_PROGRAM_H(n).p_type == PT_LOAD
        !           538:          && (round_up ((NEW_PROGRAM_H (n)).p_vaddr
        !           539:                        + (NEW_PROGRAM_H (n)).p_filesz,
        !           540:                        alignment)
        !           541:              == round_up (old_bss_addr, alignment)))
        !           542:        break;
        !           543:     }
        !           544:   if (n < 0)
        !           545:     fatal ("Couldn't find segment next to .bss in %s\n", old_name, 0);
        !           546: 
        !           547:   NEW_PROGRAM_H(n).p_filesz += new_data2_size;
        !           548:   NEW_PROGRAM_H(n).p_memsz = NEW_PROGRAM_H(n).p_filesz;
        !           549: 
        !           550: #if 0 /* Maybe allow section after data2 - does this ever happen? */
        !           551:   for (n = new_file_h->e_phnum - 1; n >= 0; n--)
        !           552:     {
        !           553:       if (NEW_PROGRAM_H(n).p_vaddr
        !           554:          && NEW_PROGRAM_H(n).p_vaddr >= new_data2_addr)
        !           555:        NEW_PROGRAM_H(n).p_vaddr += new_data2_size - old_bss_size;
        !           556: 
        !           557:       if (NEW_PROGRAM_H(n).p_offset >= new_data2_offset)
        !           558:        NEW_PROGRAM_H(n).p_offset += new_data2_size;
        !           559:     }
        !           560: #endif
        !           561: 
        !           562:   /* Fix up section headers based on new .data2 section.  Any section
        !           563:    * whose offset or virtual address is after the new .data2 section
        !           564:    * gets its value adjusted.  .bss size becomes zero and new address
        !           565:    * is set.  data2 section header gets added by copying the existing
        !           566:    * .data header and modifying the offset, address and size.
        !           567:    */
        !           568: 
        !           569:   for (n = 1; n < new_file_h->e_shnum; n++)
        !           570:     {
        !           571:       if (NEW_SECTION_H(n).sh_offset >= new_data2_offset)
        !           572:        NEW_SECTION_H(n).sh_offset += new_data2_size;
        !           573: 
        !           574:       if (NEW_SECTION_H(n).sh_addr
        !           575:          && NEW_SECTION_H(n).sh_addr >= new_data2_addr)
        !           576:        NEW_SECTION_H(n).sh_addr += new_data2_size - old_bss_size;
        !           577:     }
        !           578: 
        !           579:   new_data2_index = old_file_h->e_shnum;
        !           580: 
        !           581:   for (old_data_index = 1; old_data_index < old_file_h->e_shnum;
        !           582:        old_data_index++)
        !           583:     if (!strcmp (old_section_names + OLD_SECTION_H(old_data_index).sh_name,
        !           584:                 ".data"))
        !           585:       break;
        !           586:   if (old_data_index == old_file_h->e_shnum)
        !           587:     fatal ("Can't find .data in %s.\n", old_name, 0);
        !           588: 
        !           589:   memcpy (&NEW_SECTION_H(new_data2_index), &OLD_SECTION_H(old_data_index),
        !           590:          new_file_h->e_shentsize);
        !           591: 
        !           592:   NEW_SECTION_H(new_data2_index).sh_addr = new_data2_addr;
        !           593:   NEW_SECTION_H(new_data2_index).sh_offset = new_data2_offset;
        !           594:   NEW_SECTION_H(new_data2_index).sh_size = new_data2_size;
        !           595: 
        !           596:   NEW_SECTION_H(old_bss_index).sh_size = 0;
        !           597:   NEW_SECTION_H(old_bss_index).sh_addr = new_data2_addr + new_data2_size;
        !           598: 
        !           599:   /* Write out the sections. .data and .data1 (and data2, called
        !           600:    * ".data" in the strings table) get copied from the current process
        !           601:    * instead of the old file.
        !           602:    */
        !           603: 
        !           604:   for (n = new_file_h->e_shnum - 1; n; n--)
        !           605:     {
        !           606:       caddr_t src;
        !           607: 
        !           608:       if (NEW_SECTION_H(n).sh_type == SHT_NULL
        !           609:          || NEW_SECTION_H(n).sh_type == SHT_NOBITS)
        !           610:        continue;
        !           611: 
        !           612:       if (!strcmp (old_section_names + NEW_SECTION_H(n).sh_name, ".data")
        !           613:          || !strcmp ((old_section_names + NEW_SECTION_H(n).sh_name),
        !           614:                      ".data1"))
        !           615:        src = (caddr_t) NEW_SECTION_H(n).sh_addr;
        !           616:       else
        !           617:        src = old_base + OLD_SECTION_H(n).sh_offset;
        !           618: 
        !           619:       memcpy (NEW_SECTION_H(n).sh_offset + new_base, src,
        !           620:              NEW_SECTION_H(n).sh_size);
        !           621:     }
        !           622: 
        !           623:   /* Close the files and make the new file executable */
        !           624: 
        !           625:   if (close (old_file))
        !           626:     fatal ("Can't close(%s): errno %d\n", old_name, errno);
        !           627: 
        !           628:   if (close (new_file))
        !           629:     fatal ("Can't close(%s): errno %d\n", new_name, errno);
        !           630: 
        !           631:   if (stat (new_name, &stat_buf) == -1)
        !           632:     fatal ("Can't stat(%s): errno %d\n", new_name, errno);
        !           633: 
        !           634:   n = umask (777);
        !           635:   umask (n);
        !           636:   stat_buf.st_mode |= 0111 & ~n;
        !           637:   if (chmod (new_name, stat_buf.st_mode) == -1)
        !           638:     fatal ("Can't chmod(%s): errno %d\n", new_name, errno);
        !           639: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.