netlib.narod.ru< Назад | Оглавление | Далее >

fs/binfmt_elf.c

 7656 /*
 7657  * linux/fs/binfmt_elf.c
 7658  *
 7659  * These are the functions used to load ELF format
 7660  * executables as used on SVr4 machines.  Information on
 7661  * the format may be found in the book "UNIX SYSTEM V
 7662  * RELEASE 4 Programmers Guide: Ansi C and Programming
 7663  * Support Tools".
 7664  *
 7665  * Copyright 1993, 1994: Eric Youngdale (ericy@cais.com).
 7666  */
 7667 
 7668 #include <linux/module.h>
 7669 
 7670 #include <linux/fs.h>
 7671 #include <linux/stat.h>
 7672 #include <linux/sched.h>
 7673 #include <linux/mm.h>
 7674 #include <linux/mman.h>
 7675 #include <linux/a.out.h>
 7676 #include <linux/errno.h>
 7677 #include <linux/signal.h>
 7678 #include <linux/binfmts.h>
 7679 #include <linux/string.h>
 7680 #include <linux/file.h>
 7681 #include <linux/fcntl.h>
 7682 #include <linux/ptrace.h>
 7683 #include <linux/malloc.h>
 7684 #include <linux/shm.h>
 7685 #include <linux/personality.h>
 7686 #include <linux/elfcore.h>
 7687 #include <linux/init.h>
 7688 
 7689 #include <asm/uaccess.h>
 7690 #include <asm/pgtable.h>
 7691 
 7692 #include <linux/config.h>
 7693 
 7694 #define DLINFO_ITEMS 13
 7695 
 7696 #include <linux/elf.h>
 7697 
 7698 static int load_elf_binary(struct linux_binprm * bprm,
 7699                            struct pt_regs * regs);
 7700 static int load_elf_library(int fd);
 7701 extern int dump_fpu (struct pt_regs *, elf_fpregset_t *);
 7702 extern void dump_thread(struct pt_regs *, struct user *);
 7703 
 7704 #ifndef elf_addr_t
 7705 #define elf_addr_t unsigned long
 7706 #define elf_caddr_t char *
 7707 #endif
 7708 
 7709 /* If we don't support core dumping, then supply a NULL
 7710  * so we don't even try.  */
 7711 #ifdef USE_ELF_CORE_DUMP
 7712 static int elf_core_dump(long signr,
 7713                          struct pt_regs * regs);
 7714 #else
 7715 #define elf_core_dump   NULL
 7716 #endif
 7717 
 7718 #define ELF_PAGESTART(_v) \
 7719   ((_v) & ~(unsigned long)(ELF_EXEC_PAGESIZE-1))
 7720 #define ELF_PAGEOFFSET(_v) \
 7721   ((_v) & (ELF_EXEC_PAGESIZE-1))
 7722 #define ELF_PAGEALIGN(_v) \
 7723   (((_v) + ELF_EXEC_PAGESIZE - 1) & \
 7724    ~(ELF_EXEC_PAGESIZE - 1))
 7725 
 7726 static struct linux_binfmt elf_format = {
 7727 #ifndef MODULE
 7728   NULL, NULL,
 7729   load_elf_binary, load_elf_library, elf_core_dump
 7730 #else
 7731   NULL, &__this_module,
 7732   load_elf_binary, load_elf_library, elf_core_dump
 7733 #endif
 7734 };
 7735 
 7736 static void set_brk(unsigned long start,
 7737                     unsigned long end)
 7738 {
 7739   start = ELF_PAGEALIGN(start);
 7740   end = ELF_PAGEALIGN(end);
 7741   if (end <= start)
 7742     return;
 7743   do_mmap(NULL, start, end - start,
 7744     PROT_READ | PROT_WRITE | PROT_EXEC,
 7745     MAP_FIXED | MAP_PRIVATE, 0);
 7746 }
 7747 
 7748 
 7749 /* We need to explicitly zero any fractional pages
 7750    after the data section (i.e. bss).  This would
 7751    contain the junk from the file that should not
 7752    be in memory */
 7753 
 7754 
 7755 static void padzero(unsigned long elf_bss)
 7756 {
 7757   unsigned long nbyte;
 7758 
 7759   nbyte = ELF_PAGEOFFSET(elf_bss);
 7760   if (nbyte) {
 7761     nbyte = ELF_EXEC_PAGESIZE - nbyte;
 7762     clear_user((void *) elf_bss, nbyte);
 7763   }
 7764 }
 7765 
 7766 static elf_addr_t * 
 7767 create_elf_tables(char *p, int argc, int envc,
 7768       struct elfhdr * exec,
 7769       unsigned long load_addr,
 7770       unsigned long load_bias,
 7771       unsigned long interp_load_addr, int ibcs)
 7772 {
 7773   elf_caddr_t *argv;
 7774   elf_caddr_t *envp;
 7775   elf_addr_t *sp, *csp;
 7776   char *k_platform, *u_platform;
 7777   long hwcap;
 7778   size_t platform_len = 0;
 7779 
 7780   /* Get hold of platform and hardware capabilities masks
 7781    * for the machine we are running on.  In some cases
 7782    * (Sparc), this info is impossible to get, in others
 7783    * (i386) it is merely difficult.  */
 7784   hwcap = ELF_HWCAP;
 7785   k_platform = ELF_PLATFORM;
 7786 
 7787   if (k_platform) {
 7788     platform_len = strlen(k_platform) + 1;
 7789     u_platform = p - platform_len;
 7790     __copy_to_user(u_platform, k_platform, platform_len);
 7791   } else
 7792     u_platform = p;
 7793 
 7794   /* Force 16 byte _final_ alignment here for generality.
 7795    * Leave an extra 16 bytes free so that on the PowerPC
 7796    * we can move the aux table up to start on a 16-byte
 7797    * boundary.  */
 7798   sp = (elf_addr_t *)
 7799          ((~15UL & (unsigned long)(u_platform)) - 16UL);
 7800   csp = sp;
 7801   csp -= ((exec ? DLINFO_ITEMS*2 : 4) +
 7802           (k_platform ? 2 : 0));
 7803   csp -= envc+1;
 7804   csp -= argc+1;
 7805   csp -= (!ibcs ? 3 : 1); /* argc itself */
 7806   if ((unsigned long)csp & 15UL)
 7807     sp -= ((unsigned long)csp & 15UL) / sizeof(*sp);
 7808 
 7809   /* Put the ELF interpreter info on the stack */
 7810 #define NEW_AUX_ENT(nr, id, val) \
 7811     __put_user ((id), sp+(nr*2)); \
 7812     __put_user ((val), sp+(nr*2+1)); \
 7813 
 7814   sp -= 2;
 7815   NEW_AUX_ENT(0, AT_NULL, 0);
 7816   if (k_platform) {
 7817     sp -= 2;
 7818     NEW_AUX_ENT(0, AT_PLATFORM,
 7819                 (elf_addr_t)(unsigned long) u_platform);
 7820   }
 7821   sp -= 2;
 7822   NEW_AUX_ENT(0, AT_HWCAP, hwcap);
 7823 
 7824   if (exec) {
 7825     sp -= 11*2;
 7826 
 7827     NEW_AUX_ENT(0, AT_PHDR, load_addr + exec->e_phoff);
 7828     NEW_AUX_ENT(1, AT_PHENT, sizeof (struct elf_phdr));
 7829     NEW_AUX_ENT(2, AT_PHNUM, exec->e_phnum);
 7830     NEW_AUX_ENT(3, AT_PAGESZ, ELF_EXEC_PAGESIZE);
 7831     NEW_AUX_ENT(4, AT_BASE, interp_load_addr);
 7832     NEW_AUX_ENT(5, AT_FLAGS, 0);
 7833     NEW_AUX_ENT(6, AT_ENTRY, load_bias + exec->e_entry);
 7834     NEW_AUX_ENT(7, AT_UID, (elf_addr_t) current->uid);
 7835     NEW_AUX_ENT(8, AT_EUID, (elf_addr_t) current->euid);
 7836     NEW_AUX_ENT(9, AT_GID, (elf_addr_t) current->gid);
 7837     NEW_AUX_ENT(10, AT_EGID, (elf_addr_t) current->egid);
 7838   }
 7839 #undef NEW_AUX_ENT
 7840 
 7841   sp -= envc+1;
 7842   envp = (elf_caddr_t *) sp;
 7843   sp -= argc+1;
 7844   argv = (elf_caddr_t *) sp;
 7845   if (!ibcs) {
 7846     __put_user((elf_addr_t)(unsigned long) envp,--sp);
 7847     __put_user((elf_addr_t)(unsigned long) argv,--sp);
 7848   }
 7849 
 7850   __put_user((elf_addr_t)argc,--sp);
 7851   current->mm->arg_start = (unsigned long) p;
 7852   while (argc-->0) {
 7853     __put_user((elf_caddr_t)(unsigned long)p,argv++);
 7854     p += strlen_user(p);
 7855   }
 7856   __put_user(NULL, argv);
 7857   current->mm->arg_end =
 7858     current->mm->env_start = (unsigned long) p;
 7859   while (envc-->0) {
 7860     __put_user((elf_caddr_t)(unsigned long)p,envp++);
 7861     p += strlen_user(p);
 7862   }
 7863   __put_user(NULL, envp);
 7864   current->mm->env_end = (unsigned long) p;
 7865   return sp;
 7866 }
 7867 
 7868 
 7869 /* This is much more generalized than the library routine
 7870    read function, so we keep this separate.  Technically
 7871    the library read function is only provided so that we
 7872    can read a.out libraries that have an ELF header */
 7873 
 7874 static unsigned long load_elf_interp(
 7875   struct elfhdr * interp_elf_ex,
 7876   struct dentry * interpreter_dentry,
 7877   unsigned long *interp_load_addr)
 7878 {
 7879   struct file * file;
 7880   struct elf_phdr *elf_phdata;
 7881   struct elf_phdr *eppnt;
 7882   unsigned long load_addr = 0;
 7883   int load_addr_set = 0;
 7884   unsigned long last_bss = 0, elf_bss = 0;
 7885   unsigned long error = ~0UL;
 7886   int elf_exec_fileno;
 7887   int retval, i, size;
 7888 
 7889   /* First of all, some simple consistency checks */
 7890   if (interp_elf_ex->e_type != ET_EXEC &&
 7891       interp_elf_ex->e_type != ET_DYN)
 7892     goto out;
 7893   if (!elf_check_arch(interp_elf_ex->e_machine))
 7894     goto out;
 7895   if (!interpreter_dentry->d_inode->i_op ||
 7896       !interpreter_dentry->d_inode->i_op->
 7897                                   default_file_ops->mmap)
 7898     goto out;
 7899 
 7900   /* If the size of this structure has changed, then
 7901    * punt, since we will be doing the wrong thing.  */
 7902   if (interp_elf_ex->e_phentsize !=
 7903       sizeof(struct elf_phdr))
 7904     goto out;
 7905 
 7906   /* Now read in all of the header information */
 7907 
 7908   size = sizeof(struct elf_phdr) *interp_elf_ex->e_phnum;
 7909   if (size > ELF_EXEC_PAGESIZE)
 7910     goto out;
 7911   elf_phdata =
 7912     (struct elf_phdr *) kmalloc(size, GFP_KERNEL);
 7913   if (!elf_phdata)
 7914     goto out;
 7915 
 7916   retval = read_exec(interpreter_dentry,
 7917                      interp_elf_ex->e_phoff,
 7918                      (char *) elf_phdata, size, 1);
 7919   error = retval;
 7920   if (retval < 0)
 7921     goto out_free;
 7922 
 7923   error = ~0UL;
 7924   elf_exec_fileno = open_dentry(interpreter_dentry,
 7925                                 O_RDONLY);
 7926   if (elf_exec_fileno < 0)
 7927     goto out_free;
 7928   file = fget(elf_exec_fileno);
 7929 
 7930   eppnt = elf_phdata;
 7931   for (i=0; i<interp_elf_ex->e_phnum; i++, eppnt++) {
 7932     if (eppnt->p_type == PT_LOAD) {
 7933       int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
 7934       int elf_prot = 0;
 7935       unsigned long vaddr = 0;
 7936       unsigned long k, map_addr;
 7937 
 7938       if (eppnt->p_flags & PF_R) elf_prot =  PROT_READ;
 7939       if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
 7940       if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
 7941       vaddr = eppnt->p_vaddr;
 7942       if (interp_elf_ex->e_type == ET_EXEC ||
 7943           load_addr_set) {
 7944     elf_type |= MAP_FIXED;
 7945 #ifdef __sparc__
 7946       } else {
 7947     load_addr = get_unmapped_area(0, eppnt->p_filesz +
 7948           ELF_PAGEOFFSET(vaddr));
 7949 #endif
 7950       }
 7951 
 7952       map_addr = do_mmap(file,
 7953           load_addr + ELF_PAGESTART(vaddr),
 7954           eppnt->p_filesz +
 7955             ELF_PAGEOFFSET(eppnt->p_vaddr),
 7956           elf_prot,
 7957           elf_type,
 7958           eppnt->p_offset -
 7959             ELF_PAGEOFFSET(eppnt->p_vaddr));
 7960       if (map_addr > -1024UL) /* Real error */
 7961         goto out_close;
 7962 
 7963       if (!load_addr_set &&
 7964           interp_elf_ex->e_type == ET_DYN) {
 7965         load_addr = map_addr - ELF_PAGESTART(vaddr);
 7966         load_addr_set = 1;
 7967       }
 7968 
 7969       /* Find the end of the file mapping for this phdr,
 7970        * and keep track of the largest address we see for
 7971        * this.  */
 7972       k = load_addr + eppnt->p_vaddr + eppnt->p_filesz;
 7973       if (k > elf_bss)
 7974         elf_bss = k;
 7975 
 7976       /* Do the same thing for the memory mapping -
 7977        * between elf_bss and last_bss is the bss section.
 7978        */
 7979       k = load_addr + eppnt->p_memsz + eppnt->p_vaddr;
 7980       if (k > last_bss)
 7981         last_bss = k;
 7982     }
 7983   }
 7984 
 7985   /* Now use mmap to map the library into memory. */
 7986 
 7987   /* Now fill out the bss section.  First pad the last
 7988    * page up to the page boundary, and then perform a
 7989    * mmap to make sure that there are zero-mapped pages
 7990    * up to and including the last bss page.  */
 7991   padzero(elf_bss);
 7992   /* What we have mapped so far */
 7993   elf_bss = ELF_PAGESTART(elf_bss +
 7994                           ELF_EXEC_PAGESIZE - 1);
 7995 
 7996   /* Map the last of the bss segment */
 7997   if (last_bss > elf_bss)
 7998     do_mmap(NULL, elf_bss, last_bss - elf_bss,
 7999       PROT_READ|PROT_WRITE|PROT_EXEC,
 8000       MAP_FIXED|MAP_PRIVATE, 0);
 8001 
 8002   *interp_load_addr = load_addr;
 8003   error =
 8004     ((unsigned long) interp_elf_ex->e_entry) + load_addr;
 8005 
 8006 out_close:
 8007   fput(file);
 8008   sys_close(elf_exec_fileno);
 8009 out_free:
 8010   kfree(elf_phdata);
 8011 out:
 8012   return error;
 8013 }
 8014 
 8015 static unsigned long load_aout_interp(
 8016   struct exec * interp_ex,
 8017   struct dentry * interpreter_dentry)
 8018 {
 8019   unsigned long text_data, offset, elf_entry = ~0UL;
 8020   char * addr;
 8021   int retval;
 8022 
 8023   current->mm->end_code = interp_ex->a_text;
 8024   text_data = interp_ex->a_text + interp_ex->a_data;
 8025   current->mm->end_data = text_data;
 8026   current->mm->brk = interp_ex->a_bss + text_data;
 8027 
 8028   switch (N_MAGIC(*interp_ex)) {
 8029   case OMAGIC:
 8030     offset = 32;
 8031     addr = (char *) 0;
 8032     break;
 8033   case ZMAGIC:
 8034   case QMAGIC:
 8035     offset = N_TXTOFF(*interp_ex);
 8036     addr = (char *) N_TXTADDR(*interp_ex);
 8037     break;
 8038   default:
 8039     goto out;
 8040   }
 8041 
 8042   do_mmap(NULL, 0, text_data,
 8043           PROT_READ|PROT_WRITE|PROT_EXEC,
 8044           MAP_FIXED|MAP_PRIVATE, 0);
 8045   retval = read_exec(interpreter_dentry, offset, addr,
 8046                      text_data, 0);
 8047   if (retval < 0)
 8048     goto out;
 8049   flush_icache_range((unsigned long)addr,
 8050                      (unsigned long)addr + text_data);
 8051 
 8052   do_mmap(NULL,
 8053           ELF_PAGESTART(text_data + ELF_EXEC_PAGESIZE-1),
 8054           interp_ex->a_bss,
 8055           PROT_READ|PROT_WRITE|PROT_EXEC,
 8056           MAP_FIXED|MAP_PRIVATE, 0);
 8057   elf_entry = interp_ex->a_entry;
 8058 
 8059 out:
 8060   return elf_entry;
 8061 }
 8062 
 8063 /* These are the functions used to load ELF style
 8064  * executables and shared libraries.  There is no binary
 8065  * dependent code anywhere else.  */
 8066 
 8067 #define INTERPRETER_NONE 0
 8068 #define INTERPRETER_AOUT 1
 8069 #define INTERPRETER_ELF 2
 8070 
 8071 
 8072 static inline int
 8073 do_load_elf_binary(struct linux_binprm * bprm,
 8074                    struct pt_regs * regs)
 8075 {
 8076   struct file * file;
 8077   struct dentry *interpreter_dentry = NULL;
 8078   unsigned long load_addr = 0, load_bias;
 8079   int load_addr_set = 0;
 8080   char * elf_interpreter = NULL;
 8081   unsigned int interpreter_type = INTERPRETER_NONE;
 8082   unsigned char ibcs2_interpreter = 0;
 8083   mm_segment_t old_fs;
 8084   unsigned long error;
 8085   struct elf_phdr * elf_ppnt, *elf_phdata;
 8086   unsigned long elf_bss, k, elf_brk;
 8087   int elf_exec_fileno;
 8088   int retval, size, i;
 8089   unsigned long elf_entry, interp_load_addr = 0;
 8090   unsigned long start_code, end_code, end_data;
 8091   struct elfhdr elf_ex;
 8092   struct elfhdr interp_elf_ex;
 8093   struct exec interp_ex;
 8094   char passed_fileno[6];
 8095 
 8096   /* Get the exec-header */
 8097   elf_ex = *((struct elfhdr *) bprm->buf);
 8098 
 8099   retval = -ENOEXEC;
 8100   /* First of all, some simple consistency checks */
 8101   if (elf_ex.e_ident[0] != 0x7f ||
 8102       strncmp(&elf_ex.e_ident[1], "ELF", 3) != 0)
 8103     goto out;
 8104 
 8105   if (elf_ex.e_type != ET_EXEC &&
 8106       elf_ex.e_type != ET_DYN)
 8107     goto out;
 8108   if (!elf_check_arch(elf_ex.e_machine))
 8109     goto out;
 8110 #ifdef __mips__
 8111   /* IRIX binaries handled elsewhere. */
 8112   if (elf_ex.e_flags & EF_MIPS_ARCH) {
 8113     retval = -ENOEXEC;
 8114     goto out;
 8115   }
 8116 #endif
 8117   if (!bprm->dentry->d_inode->i_op                   ||
 8118       !bprm->dentry->d_inode->i_op->default_file_ops ||
 8119       !bprm->dentry->d_inode->i_op->default_file_ops->
 8120                                                     mmap)
 8121     goto out;
 8122 
 8123   /* Now read in all of the header information */
 8124 
 8125   retval = -ENOMEM;
 8126   size = elf_ex.e_phentsize * elf_ex.e_phnum;
 8127   elf_phdata =
 8128     (struct elf_phdr *) kmalloc(size, GFP_KERNEL);
 8129   if (!elf_phdata)
 8130     goto out;
 8131 
 8132   retval = read_exec(bprm->dentry, elf_ex.e_phoff,
 8133         (char *) elf_phdata, size, 1);
 8134   if (retval < 0)
 8135     goto out_free_ph;
 8136 
 8137   retval = open_dentry(bprm->dentry, O_RDONLY);
 8138   if (retval < 0)
 8139     goto out_free_ph;
 8140   elf_exec_fileno = retval;
 8141   file = fget(elf_exec_fileno);
 8142 
 8143   elf_ppnt = elf_phdata;
 8144   elf_bss = 0;
 8145   elf_brk = 0;
 8146 
 8147   start_code = ~0UL;
 8148   end_code = 0;
 8149   end_data = 0;
 8150 
 8151   for (i = 0; i < elf_ex.e_phnum; i++) {
 8152     if (elf_ppnt->p_type == PT_INTERP) {
 8153       retval = -EINVAL;
 8154       if (elf_interpreter)
 8155         goto out_free_interp;
 8156 
 8157       /* This is the program interpreter used for
 8158        * shared libraries - for now assume that this
 8159        * is an a.out format binary
 8160        */
 8161 
 8162       retval = -ENOMEM;
 8163       elf_interpreter =
 8164         (char *) kmalloc(elf_ppnt->p_filesz, GFP_KERNEL);
 8165       if (!elf_interpreter)
 8166         goto out_free_file;
 8167 
 8168       retval = read_exec(bprm->dentry,
 8169                          elf_ppnt->p_offset,
 8170                          elf_interpreter,
 8171                          elf_ppnt->p_filesz, 1);
 8172       if (retval < 0)
 8173         goto out_free_interp;
 8174       /* If the program interpreter is one of these two,
 8175        * then assume an iBCS2 image. Otherwise assume
 8176        * a native linux image.
 8177        */
 8178       if (!strcmp(elf_interpreter,"/usr/lib/libc.so.1") 
 8179           || !strcmp(elf_interpreter,"/usr/lib/ld.so.1"))
 8180         ibcs2_interpreter = 1;
 8181 #if 0
 8182       printk("Using ELF interpreter %s\n",
 8183              elf_interpreter);
 8184 #endif
 8185       old_fs = get_fs(); /* Could probably be optimized*/
 8186       set_fs(get_ds());
 8187 #ifdef __sparc__
 8188       if (ibcs2_interpreter) {
 8189         unsigned long old_pers = current->personality;
 8190           
 8191         current->personality = PER_SVR4;
 8192         interpreter_dentry = open_namei(elf_interpreter,
 8193                 0, 0);
 8194         current->personality = old_pers;
 8195       } else
 8196 #endif                                  
 8197         interpreter_dentry = open_namei(elf_interpreter,
 8198                 0, 0);
 8199       set_fs(old_fs);
 8200       retval = PTR_ERR(interpreter_dentry);
 8201       if (IS_ERR(interpreter_dentry))
 8202         goto out_free_interp;
 8203       retval = permission(interpreter_dentry->d_inode,
 8204                           MAY_EXEC);
 8205       if (retval < 0)
 8206         goto out_free_dentry;
 8207       retval = read_exec(interpreter_dentry, 0,
 8208                          bprm->buf, 128, 1);
 8209       if (retval < 0)
 8210         goto out_free_dentry;
 8211 
 8212       /* Get the exec headers */
 8213       interp_ex = *((struct exec *) bprm->buf);
 8214       interp_elf_ex = *((struct elfhdr *) bprm->buf);
 8215     }
 8216     elf_ppnt++;
 8217   }
 8218 
 8219   /* Some simple consistency checks for the interpreter*/
 8220   if (elf_interpreter) {
 8221     interpreter_type = INTERPRETER_ELF|INTERPRETER_AOUT;
 8222 
 8223     /* Now figure out which format our binary is */
 8224     if ((N_MAGIC(interp_ex) != OMAGIC) &&
 8225         (N_MAGIC(interp_ex) != ZMAGIC) &&
 8226         (N_MAGIC(interp_ex) != QMAGIC))
 8227       interpreter_type = INTERPRETER_ELF;
 8228 
 8229     if (interp_elf_ex.e_ident[0] != 0x7f ||
 8230         strncmp(&interp_elf_ex.e_ident[1], "ELF", 3))
 8231       interpreter_type &= ~INTERPRETER_ELF;
 8232 
 8233     retval = -ELIBBAD;
 8234     if (!interpreter_type)
 8235       goto out_free_dentry;
 8236 
 8237     /* Make sure only one type was selected */
 8238     if ((interpreter_type & INTERPRETER_ELF) &&
 8239          interpreter_type != INTERPRETER_ELF) {
 8240       printk(KERN_WARNING
 8241              "ELF: Ambiguous type, using ELF\n");
 8242       interpreter_type = INTERPRETER_ELF;
 8243     }
 8244   }
 8245 
 8246   /* OK, we are done with that, now set up the arg stuff,
 8247      and then start this sucker up */
 8248 
 8249   if (!bprm->sh_bang) {
 8250     char * passed_p;
 8251 
 8252     if (interpreter_type == INTERPRETER_AOUT) {
 8253       sprintf(passed_fileno, "%d", elf_exec_fileno);
 8254       passed_p = passed_fileno;
 8255 
 8256       if (elf_interpreter) {
 8257         bprm->p = copy_strings(1, &passed_p, bprm->page,
 8258                                bprm->p, 2);
 8259         bprm->argc++;
 8260       }
 8261     }
 8262     retval = -E2BIG;
 8263     if (!bprm->p)
 8264       goto out_free_dentry;
 8265   }
 8266 
 8267   /* Flush all traces of the currently running exe */
 8268   retval = flush_old_exec(bprm);
 8269   if (retval)
 8270     goto out_free_dentry;
 8271 
 8272   /* OK, This is the point of no return */
 8273   current->mm->end_data = 0;
 8274   current->mm->end_code = 0;
 8275   current->mm->mmap = NULL;
 8276   current->flags &= ~PF_FORKNOEXEC;
 8277   elf_entry = (unsigned long) elf_ex.e_entry;
 8278 
 8279   /* Do this immediately, since STACK_TOP as used in
 8280      setup_arg_pages may depend on the personality.  */
 8281   SET_PERSONALITY(elf_ex, ibcs2_interpreter);
 8282 
 8283   /* Do this so that we can load the interpreter, if need
 8284      be.  We will change some of these later */
 8285   current->mm->rss = 0;
 8286   bprm->p = setup_arg_pages(bprm->p, bprm);
 8287   current->mm->start_stack = bprm->p;
 8288 
 8289   /* Try and get dynamic programs out of the way of the
 8290      default mmap base, as well as whatever program they
 8291      might try to exec.  This is because the brk will
 8292      follow the loader, and is not movable.  */
 8293 
 8294   load_bias = ELF_PAGESTART(elf_ex.e_type == ET_DYN
 8295                             ?  ELF_ET_DYN_BASE  :  0);
 8296 
 8297   /* Now we do a little grungy work by mmaping the ELF
 8298      image into the correct location in memory.  At this
 8299      point, we assume that the image should be loaded at
 8300      fixed address, not at a variable address. */
 8301 
 8302   old_fs = get_fs();
 8303   set_fs(get_ds());
 8304   for(i = 0, elf_ppnt = elf_phdata; i < elf_ex.e_phnum;
 8305       i++, elf_ppnt++) {
 8306     int elf_prot = 0, elf_flags;
 8307     unsigned long vaddr;
 8308 
 8309     if (elf_ppnt->p_type != PT_LOAD)
 8310       continue;
 8311 
 8312     if (elf_ppnt->p_flags & PF_R) elf_prot |= PROT_READ;
 8313     if (elf_ppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
 8314     if (elf_ppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
 8315 
 8316     elf_flags = MAP_PRIVATE|MAP_DENYWRITE|MAP_EXECUTABLE;
 8317 
 8318     vaddr = elf_ppnt->p_vaddr;
 8319     if (elf_ex.e_type == ET_EXEC || load_addr_set) {
 8320       elf_flags |= MAP_FIXED;
 8321     }
 8322 
 8323     error = do_mmap(file,
 8324         ELF_PAGESTART(load_bias + vaddr),
 8325         (elf_ppnt->p_filesz +
 8326         ELF_PAGEOFFSET(elf_ppnt->p_vaddr)),
 8327         elf_prot, elf_flags, (elf_ppnt->p_offset -
 8328         ELF_PAGEOFFSET(elf_ppnt->p_vaddr)));
 8329 
 8330     if (!load_addr_set) {
 8331       load_addr_set = 1;
 8332       load_addr =
 8333         (elf_ppnt->p_vaddr - elf_ppnt->p_offset);
 8334       if (elf_ex.e_type == ET_DYN) {
 8335         load_bias += error -
 8336                ELF_PAGESTART(load_bias + vaddr);
 8337         load_addr += error;
 8338       }
 8339     }
 8340     k = elf_ppnt->p_vaddr;
 8341     if (k < start_code) start_code = k;
 8342     k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz;
 8343     if (k > elf_bss)
 8344       elf_bss = k;
 8345     if ((elf_ppnt->p_flags & PF_X) && end_code <  k)
 8346       end_code = k;
 8347     if (end_data < k)
 8348       end_data = k;
 8349     k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz;
 8350     if (k > elf_brk)
 8351       elf_brk = k;
 8352   }
 8353   set_fs(old_fs);
 8354   fput(file); /* all done with the file */
 8355 
 8356   elf_entry += load_bias;
 8357   elf_bss += load_bias;
 8358   elf_brk += load_bias;
 8359   start_code += load_bias;
 8360   end_code += load_bias;
 8361   end_data += load_bias;
 8362 
 8363   if (elf_interpreter) {
 8364     if (interpreter_type == INTERPRETER_AOUT)
 8365       elf_entry = load_aout_interp(&interp_ex,
 8366                  interpreter_dentry);
 8367     else
 8368       elf_entry = load_elf_interp(&interp_elf_ex,
 8369                 interpreter_dentry,
 8370                 &interp_load_addr);
 8371 
 8372     dput(interpreter_dentry);
 8373     kfree(elf_interpreter);
 8374 
 8375     if (elf_entry == ~0UL) {
 8376       printk(KERN_ERR "Unable to load interpreter\n");
 8377       kfree(elf_phdata);
 8378       send_sig(SIGSEGV, current, 0);
 8379       return 0;
 8380     }
 8381   }
 8382 
 8383   kfree(elf_phdata);
 8384 
 8385   if (interpreter_type != INTERPRETER_AOUT)
 8386     sys_close(elf_exec_fileno);
 8387 
 8388   if (current->exec_domain &&
 8389       current->exec_domain->module)
 8390     __MOD_DEC_USE_COUNT(current->exec_domain->module);
 8391   if (current->binfmt && current->binfmt->module)
 8392     __MOD_DEC_USE_COUNT(current->binfmt->module);
 8393   current->exec_domain =
 8394     lookup_exec_domain(current->personality);
 8395   current->binfmt = &elf_format;
 8396   if (current->exec_domain &&
 8397       current->exec_domain->module)
 8398     __MOD_INC_USE_COUNT(current->exec_domain->module);
 8399   if (current->binfmt && current->binfmt->module)
 8400     __MOD_INC_USE_COUNT(current->binfmt->module);
 8401 
 8402 #ifndef VM_STACK_FLAGS
 8403   current->executable = dget(bprm->dentry);
 8404 #endif
 8405   compute_creds(bprm);
 8406   current->flags &= ~PF_FORKNOEXEC;
 8407   bprm->p = (unsigned long)
 8408     create_elf_tables((char *)bprm->p,
 8409       bprm->argc,
 8410       bprm->envc,
 8411       (interpreter_type == INTERPRETER_ELF
 8412        ?  &elf_ex  :  NULL),
 8413       load_addr, load_bias,
 8414       interp_load_addr,
 8415       (interpreter_type == INTERPRETER_AOUT ? 0 : 1));
 8416   /* N.B. passed_fileno might not be initialized? */
 8417   if (interpreter_type == INTERPRETER_AOUT)
 8418     current->mm->arg_start += strlen(passed_fileno) + 1;
 8419   current->mm->start_brk = current->mm->brk = elf_brk;
 8420   current->mm->end_code = end_code;
 8421   current->mm->start_code = start_code;
 8422   current->mm->end_data = end_data;
 8423   current->mm->start_stack = bprm->p;
 8424 
 8425   /* Calling set_brk effectively mmaps the pages that we
 8426    * need for the bss and break sections */
 8427   set_brk(elf_bss, elf_brk);
 8428 
 8429   padzero(elf_bss);
 8430 
 8431 #if 0
 8432   printk("(start_brk) %x\n"  , current->mm->start_brk);
 8433   printk("(end_code) %x\n"   , current->mm->end_code);
 8434   printk("(start_code) %x\n" , current->mm->start_code);
 8435   printk("(end_data) %x\n"   , current->mm->end_data);
 8436   printk("(start_stack) %x\n", current->mm->start_stack);
 8437   printk("(brk) %x\n" , current->mm->brk);
 8438 #endif
 8439 
 8440   if ( current->personality == PER_SVR4 )
 8441   {
 8442     /* Why this, you ask???  Well SVr4 maps page 0 as
 8443        read-only, and some applications "depend" upon
 8444        this behavior.  Since we do not have the power to
 8445        recompile these, we emulate the SVr4 behavior.
 8446        Sigh.  */
 8447     /* N.B. Shouldn't the size here be PAGE_SIZE?? */
 8448     error = do_mmap(NULL, 0, 4096, PROT_READ | PROT_EXEC,
 8449         MAP_FIXED | MAP_PRIVATE, 0);
 8450   }
 8451 
 8452 #ifdef ELF_PLAT_INIT
 8453   /* The ABI may specify that certain registers be set up
 8454    * in special ways (on i386 %edx is the address of a
 8455    * DT_FINI function, for example.  This macro performs
 8456    * whatever initialization to the regs structure is
 8457    * required.  */
 8458   ELF_PLAT_INIT(regs);
 8459 #endif
 8460 
 8461   start_thread(regs, elf_entry, bprm->p);
 8462   if (current->flags & PF_PTRACED)
 8463     send_sig(SIGTRAP, current, 0);
 8464   retval = 0;
 8465 out:
 8466   return retval;
 8467 
 8468   /* error cleanup */
 8469 out_free_dentry:
 8470   dput(interpreter_dentry);
 8471 out_free_interp:
 8472   if (elf_interpreter)
 8473     kfree(elf_interpreter);
 8474 out_free_file:
 8475   fput(file);
 8476   sys_close(elf_exec_fileno);
 8477 out_free_ph:
 8478   kfree(elf_phdata);
 8479   goto out;
 8480 }
 8481 
 8482 static int
 8483 load_elf_binary(struct linux_binprm * bprm,
 8484                 struct pt_regs * regs)
 8485 {
 8486   int retval;
 8487 
 8488   MOD_INC_USE_COUNT;
 8489   retval = do_load_elf_binary(bprm, regs);
 8490   MOD_DEC_USE_COUNT;
 8491   return retval;
 8492 }
 8493 
 8494 /* This is really simpleminded and specialized - we are
 8495    loading an a.out library that is given an ELF
 8496    header. */
 8497 
 8498 static inline int
 8499 do_load_elf_library(int fd)
 8500 {
 8501   struct file * file;
 8502   struct dentry * dentry;
 8503   struct inode * inode;
 8504   struct elf_phdr *elf_phdata;
 8505   unsigned long elf_bss = 0, bss, len, k;
 8506   int retval, error, i, j;
 8507   struct elfhdr elf_ex;
 8508   loff_t offset = 0;
 8509 
 8510   error = -EACCES;
 8511   file = fget(fd);
 8512   if (!file || !file->f_op)
 8513     goto out;
 8514   dentry = file->f_dentry;
 8515   inode = dentry->d_inode;
 8516 
 8517   /* seek to the beginning of the file */
 8518   error = -ENOEXEC;
 8519 
 8520   /* N.B. save current DS?? */
 8521   set_fs(KERNEL_DS);
 8522   retval = file->f_op->read(file, (char *) &elf_ex,
 8523                             sizeof(elf_ex), &offset);
 8524   set_fs(USER_DS);
 8525   if (retval != sizeof(elf_ex))
 8526     goto out_putf;
 8527 
 8528   if (elf_ex.e_ident[0] != 0x7f ||
 8529       strncmp(&elf_ex.e_ident[1], "ELF", 3) != 0)
 8530     goto out_putf;
 8531 
 8532   /* First of all, some simple consistency checks */
 8533   if (elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 ||
 8534      !elf_check_arch(elf_ex.e_machine) ||
 8535      (!inode->i_op ||
 8536       !inode->i_op->default_file_ops->mmap))
 8537     goto out_putf;
 8538 
 8539   /* Now read in all of the header information */
 8540 
 8541   j = sizeof(struct elf_phdr) * elf_ex.e_phnum;
 8542   if (j > ELF_EXEC_PAGESIZE)
 8543     goto out_putf;
 8544 
 8545   error = -ENOMEM;
 8546   elf_phdata = (struct elf_phdr *) kmalloc(j,GFP_KERNEL);
 8547   if (!elf_phdata)
 8548     goto out_putf;
 8549 
 8550   /* N.B. check for error return?? */
 8551   retval = read_exec(dentry, elf_ex.e_phoff,
 8552             (char *) elf_phdata,
 8553             sizeof(struct elf_phdr) * elf_ex.e_phnum, 1);
 8554 
 8555   error = -ENOEXEC;
 8556   for (j = 0, i = 0; i<elf_ex.e_phnum; i++)
 8557     if ((elf_phdata + i)->p_type == PT_LOAD) j++;
 8558   if (j != 1)
 8559     goto out_free_ph;
 8560 
 8561   while (elf_phdata->p_type != PT_LOAD) elf_phdata++;
 8562 
 8563   /* Now use mmap to map the library into memory. */
 8564   error = do_mmap(file,
 8565       ELF_PAGESTART(elf_phdata->p_vaddr),
 8566       (elf_phdata->p_filesz +
 8567        ELF_PAGEOFFSET(elf_phdata->p_vaddr)),
 8568       PROT_READ | PROT_WRITE | PROT_EXEC,
 8569       MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
 8570       (elf_phdata->p_offset -
 8571        ELF_PAGEOFFSET(elf_phdata->p_vaddr)));
 8572   if (error != ELF_PAGESTART(elf_phdata->p_vaddr))
 8573     goto out_free_ph;
 8574 
 8575   k = elf_phdata->p_vaddr + elf_phdata->p_filesz;
 8576   if (k > elf_bss)
 8577     elf_bss = k;
 8578   padzero(elf_bss);
 8579 
 8580   len = ELF_PAGESTART(elf_phdata->p_filesz +
 8581                       elf_phdata->p_vaddr + 
 8582                       ELF_EXEC_PAGESIZE - 1);
 8583   bss = elf_phdata->p_memsz + elf_phdata->p_vaddr;
 8584   if (bss > len)
 8585     do_mmap(NULL, len, bss - len,
 8586       PROT_READ|PROT_WRITE|PROT_EXEC,
 8587       MAP_FIXED|MAP_PRIVATE, 0);
 8588   error = 0;
 8589 
 8590 out_free_ph:
 8591   kfree(elf_phdata);
 8592 out_putf:
 8593   fput(file);
 8594 out:
 8595   return error;
 8596 }
 8597 
 8598 static int load_elf_library(int fd)
 8599 {
 8600   int retval;
 8601 
 8602   MOD_INC_USE_COUNT;
 8603   retval = do_load_elf_library(fd);
 8604   MOD_DEC_USE_COUNT;
 8605   return retval;
 8606 }
 8607 
 8608 /* Note that some platforms still use traditional core
 8609  * dumps and not the ELF core dump.  Each platform can
 8610  * select it as appropriate.  */
 8611 #ifdef USE_ELF_CORE_DUMP
 8612 
 8613 /* ELF core dumper
 8614  *
 8615  * Modelled on fs/exec.c:aout_core_dump()
 8616  * Jeremy Fitzhardinge <jeremy@sw.oz.au>
 8617  */
 8618 /* These are the only things you should do on a
 8619  * core-file: use only these functions to write out all
 8620  * the necessary info.  */
 8621 static int dump_write(struct file *file,
 8622                       const void *addr, int nr)
 8623 {
 8624   return file->f_op->write(file, addr, nr, &file->f_pos)
 8625          == nr;
 8626 }
 8627 
 8628 static int dump_seek(struct file *file, off_t off)
 8629 {
 8630   if (file->f_op->llseek) {
 8631     if (file->f_op->llseek(file, off, 0) != off)
 8632       return 0;
 8633   } else
 8634     file->f_pos = off;
 8635   return 1;
 8636 }
 8637 
 8638 /* Decide whether a segment is worth dumping; default is
 8639  * yes to be sure (missing info is worse than too much;
 8640  * etc).  Personally I'd include everything, and use the
 8641  * coredump limit...
 8642  *
 8643  * I think we should skip something. But I am not sure
 8644  * how. H.J.  */
 8645 static inline int maydump(struct vm_area_struct *vma)
 8646 {
 8647   if (!(vma->vm_flags & (VM_READ|VM_WRITE|VM_EXEC)))
 8648     return 0;
 8649 
 8650   /* Do not dump I/O mapped devices! -DaveM */
 8651   if(vma->vm_flags & VM_IO)
 8652     return 0;
 8653 #if 1
 8654   if (vma->vm_flags & (VM_WRITE|VM_GROWSUP|VM_GROWSDOWN))
 8655     return 1;
 8656   if (vma->vm_flags & (VM_READ|VM_EXEC|VM_EXECUTABLE|
 8657                        VM_SHARED))
 8658     return 0;
 8659 #endif
 8660   return 1;
 8661 }
 8662 
 8663 #define roundup(x, y)  ((((x)+((y)-1))/(y))*(y))
 8664 
 8665 /* An ELF note in memory */
 8666 struct memelfnote
 8667 {
 8668   const char *name;
 8669   int type;
 8670   unsigned int datasz;
 8671   void *data;
 8672 };
 8673 
 8674 static int notesize(struct memelfnote *en)
 8675 {
 8676   int sz;
 8677 
 8678   sz = sizeof(struct elf_note);
 8679   sz += roundup(strlen(en->name), 4);
 8680   sz += roundup(en->datasz, 4);
 8681 
 8682   return sz;
 8683 }
 8684 
 8685 /* #define DEBUG */
 8686 
 8687 #ifdef DEBUG
 8688 static void dump_regs(const char *str, elf_greg_t *r)
 8689 {
 8690   int i;
 8691   static const char *regs[] = {
 8692     "ebx", "ecx", "edx", "esi", "edi", "ebp",
 8693     "eax", "ds", "es", "fs", "gs",
 8694     "orig_eax", "eip", "cs",
 8695     "efl", "uesp", "ss"};
 8696   printk("Registers: %s\n", str);
 8697 
 8698   for(i = 0; i < ELF_NGREG; i++)
 8699   {
 8700     unsigned long val = r[i];
 8701     printk("   %-2d %-5s=%08lx %lu\n",
 8702            i, regs[i], val, val);
 8703   }
 8704 }
 8705 #endif
 8706 
 8707 #define DUMP_WRITE(addr, nr)    \
 8708   do { if (!dump_write(file, (addr), (nr))) return 0; } \
 8709      while(0)
 8710 #define DUMP_SEEK(off)  \
 8711   do { if (!dump_seek(file, (off))) return 0; } while(0)
 8712 
 8713 static int writenote(struct memelfnote *men,
 8714                      struct file *file)
 8715 {
 8716   struct elf_note en;
 8717 
 8718   en.n_namesz = strlen(men->name);
 8719   en.n_descsz = men->datasz;
 8720   en.n_type = men->type;
 8721 
 8722   DUMP_WRITE(&en, sizeof(en));
 8723   DUMP_WRITE(men->name, en.n_namesz);
 8724   /* XXX - cast from long long to long to avoid need for
 8725    * libgcc.a */
 8726   /* XXX */
 8727   DUMP_SEEK(roundup((unsigned long)file->f_pos, 4));
 8728   DUMP_WRITE(men->data, men->datasz);
 8729   /* XXX */
 8730   DUMP_SEEK(roundup((unsigned long)file->f_pos, 4));
 8731 
 8732   return 1;
 8733 }
 8734 #undef DUMP_WRITE
 8735 #undef DUMP_SEEK
 8736 
 8737 #define DUMP_WRITE(addr, nr)    \
 8738   if (!dump_write(&file, (addr), (nr))) \
 8739     goto close_coredump;
 8740 #define DUMP_SEEK(off)  \
 8741   if (!dump_seek(&file, (off))) \
 8742     goto close_coredump;
 8743 /* Actual dumper
 8744  *
 8745  * This is a two-pass process; first we find the offsets
 8746  * of the bits, and then they are actually written out.
 8747  * If we run out of core limit we just truncate.  */
 Комментарий
 8748 static int elf_core_dump(long signr,
 8749                          struct pt_regs * regs)
 8750 {
 8751   int has_dumped = 0;
 8752   struct file file;
 8753   struct dentry *dentry;
 8754   struct inode *inode;
 8755   mm_segment_t fs;
 8756   char corefile[6+sizeof(current->comm)];
 8757   int segs;
 8758   int i;
 8759   size_t size;
 8760   struct vm_area_struct *vma;
 8761   struct elfhdr elf;
 8762   off_t offset = 0, dataoff;
 8763   unsigned long limit =
 8764     current->rlim[RLIMIT_CORE].rlim_cur;
 8765   int numnote = 4;
 8766   struct memelfnote notes[4];
 8767   struct elf_prstatus prstatus;   /* NT_PRSTATUS */
 8768   elf_fpregset_t fpu;             /* NT_PRFPREG */
 8769   struct elf_prpsinfo psinfo;     /* NT_PRPSINFO */
 8770 
 8771   if (!current->dumpable ||
 8772       limit < ELF_EXEC_PAGESIZE ||
 8773       atomic_read(&current->mm->count) != 1)
 8774     return 0;
 8775   current->dumpable = 0;
 8776 
 8777 #ifndef CONFIG_BINFMT_ELF
 8778   MOD_INC_USE_COUNT;
 8779 #endif
 8780 
 8781   /* Count what's needed to dump, up to the limit of
 8782    * coredump size */
 8783   segs = 0;
 8784   size = 0;
 8785   for(vma = current->mm->mmap; vma != NULL;
 8786       vma = vma->vm_next) {
 8787     if (maydump(vma))
 8788     {
 8789       unsigned long sz = vma->vm_end-vma->vm_start;
 8790 
 8791       if (size+sz >= limit)
 8792         break;
 8793       else
 8794         size += sz;
 8795     }
 8796 
 8797     segs++;
 8798   }
 8799 #ifdef DEBUG
 8800   printk("elf_core_dump: %d segs taking %d bytes\n",
 8801          segs, size);
 8802 #endif
 8803 
 8804   /* Set up header */
 8805   memcpy(elf.e_ident, ELFMAG, SELFMAG);
 8806   elf.e_ident[EI_CLASS] = ELF_CLASS;
 8807   elf.e_ident[EI_DATA] = ELF_DATA;
 8808   elf.e_ident[EI_VERSION] = EV_CURRENT;
 8809   memset(elf.e_ident+EI_PAD, 0, EI_NIDENT-EI_PAD);
 8810 
 8811   elf.e_type = ET_CORE;
 8812   elf.e_machine = ELF_ARCH;
 8813   elf.e_version = EV_CURRENT;
 8814   elf.e_entry = 0;
 8815   elf.e_phoff = sizeof(elf);
 8816   elf.e_shoff = 0;
 8817   elf.e_flags = 0;
 8818   elf.e_ehsize = sizeof(elf);
 8819   elf.e_phentsize = sizeof(struct elf_phdr);
 8820   elf.e_phnum = segs+1;           /* Include notes */
 8821   elf.e_shentsize = 0;
 8822   elf.e_shnum = 0;
 8823   elf.e_shstrndx = 0;
 8824 
 8825   fs = get_fs();
 8826   set_fs(KERNEL_DS);
 8827   memcpy(corefile,"core.",5);
 8828 #if 0
 8829   memcpy(corefile+5,current->comm,sizeof(current->comm));
 8830 #else
 8831   corefile[4] = '\0';
 8832 #endif
 8833   dentry = open_namei(corefile,
 8834                O_CREAT | 2 | O_TRUNC | O_NOFOLLOW, 0600);
 8835   if (IS_ERR(dentry)) {
 8836     dentry = NULL;
 8837     goto end_coredump;
 8838   }
 8839   inode = dentry->d_inode;
 8840 
 8841   if(inode->i_nlink > 1)
 8842     goto end_coredump;  /* multiple links - don't dump */
 8843 
 8844   if (!S_ISREG(inode->i_mode))
 8845     goto end_coredump;
 8846   if (!inode->i_op || !inode->i_op->default_file_ops)
 8847     goto end_coredump;
 8848   if (init_private_file(&file, dentry, 3))
 8849     goto end_coredump;
 8850   if (!file.f_op->write)
 8851     goto close_coredump;
 8852   has_dumped = 1;
 8853   current->flags |= PF_DUMPCORE;
 8854 
 8855   DUMP_WRITE(&elf, sizeof(elf));
 8856   offset += sizeof(elf); /* Elf header */
 8857   /* Program headers */
 8858   offset += (segs+1) * sizeof(struct elf_phdr);
 8859 
 8860   /* Set up the notes in similar form to SVR4 core dumps
 8861    * made with info from their /proc.  */
 8862   memset(&psinfo, 0, sizeof(psinfo));
 8863   memset(&prstatus, 0, sizeof(prstatus));
 8864 
 Комментарий
 8865   notes[0].name = "CORE";
 8866   notes[0].type = NT_PRSTATUS;
 8867   notes[0].datasz = sizeof(prstatus);
 8868   notes[0].data = &prstatus;
 8869   prstatus.pr_info.si_signo = prstatus.pr_cursig = signr;
 8870   prstatus.pr_sigpend = current->signal.sig[0];
 8871   prstatus.pr_sighold = current->blocked.sig[0];
 8872   psinfo.pr_pid = prstatus.pr_pid = current->pid;
 8873   psinfo.pr_ppid = prstatus.pr_ppid =
 8874     current->p_pptr->pid;
 8875   psinfo.pr_pgrp = prstatus.pr_pgrp = current->pgrp;
 8876   psinfo.pr_sid = prstatus.pr_sid = current->session;
 8877   prstatus.pr_utime.tv_sec =
 8878     CT_TO_SECS(current->times.tms_utime);
 8879   prstatus.pr_utime.tv_usec =
 8880     CT_TO_USECS(current->times.tms_utime);
 8881   prstatus.pr_stime.tv_sec =
 8882     CT_TO_SECS(current->times.tms_stime);
 8883   prstatus.pr_stime.tv_usec =
 8884     CT_TO_USECS(current->times.tms_stime);
 8885   prstatus.pr_cutime.tv_sec =
 8886     CT_TO_SECS(current->times.tms_cutime);
 8887   prstatus.pr_cutime.tv_usec =
 8888     CT_TO_USECS(current->times.tms_cutime);
 8889   prstatus.pr_cstime.tv_sec =
 8890     CT_TO_SECS(current->times.tms_cstime);
 8891   prstatus.pr_cstime.tv_usec =
 8892     CT_TO_USECS(current->times.tms_cstime);
 8893 
 8894   /* This transfers the registers from regs into the
 8895    * standard coredump arrangement, whatever that is.  */
 8896 #ifdef ELF_CORE_COPY_REGS
 8897   ELF_CORE_COPY_REGS(prstatus.pr_reg, regs)
 8898 #else
 8899   if (sizeof(elf_gregset_t) != sizeof(struct pt_regs))
 8900   {
 8901     printk("sizeof(elf_gregset_t) (%ld) != "
 8902            "sizeof(struct pt_regs) (%ld)\n",
 8903            (long)sizeof(elf_gregset_t),
 8904            (long)sizeof(struct pt_regs));
 8905   }
 8906   else
 8907     *(struct pt_regs *)&prstatus.pr_reg = *regs;
 8908 #endif
 8909 
 8910 #ifdef DEBUG
 8911   dump_regs("Passed in regs", (elf_greg_t *)regs);
 8912   dump_regs("prstatus regs",
 8913             (elf_greg_t *)&prstatus.pr_reg);
 8914 #endif
 8915 
 8916   notes[1].name = "CORE";
 8917   notes[1].type = NT_PRPSINFO;
 8918   notes[1].datasz = sizeof(psinfo);
 8919   notes[1].data = &psinfo;
 8920   i = current->state ? ffz(~current->state) + 1 : 0;
 8921   psinfo.pr_state = i;
 8922   psinfo.pr_sname = (i < 0 || i > 5) ? '.' : "RSDZTD"[i];
 8923   psinfo.pr_zomb = psinfo.pr_sname == 'Z';
 8924   psinfo.pr_nice = current->priority-15;
 8925   psinfo.pr_flag = current->flags;
 8926   psinfo.pr_uid = current->uid;
 8927   psinfo.pr_gid = current->gid;
 8928   {
 8929     int i, len;
 8930 
 8931     set_fs(fs);
 8932 
 8933     len = current->mm->arg_end - current->mm->arg_start;
 8934     if (len >= ELF_PRARGSZ)
 8935       len = ELF_PRARGSZ-1;
 8936     copy_from_user(&psinfo.pr_psargs,
 8937             (const char *)current->mm->arg_start, len);
 8938     for(i = 0; i < len; i++)
 8939       if (psinfo.pr_psargs[i] == 0)
 8940         psinfo.pr_psargs[i] = ' ';
 8941     psinfo.pr_psargs[len] = 0;
 8942 
 8943     set_fs(KERNEL_DS);
 8944   }
 8945   strncpy(psinfo.pr_fname, current->comm,
 8946           sizeof(psinfo.pr_fname));
 8947 
 8948   notes[2].name = "CORE";
 8949   notes[2].type = NT_TASKSTRUCT;
 8950   notes[2].datasz = sizeof(*current);
 8951   notes[2].data = current;
 8952 
 8953   /* Try to dump the FPU. */
 8954   prstatus.pr_fpvalid = dump_fpu (regs, &fpu);
 8955   if (!prstatus.pr_fpvalid)
 8956   {
 8957     numnote--;
 8958   }
 8959   else
 8960   {
 8961     notes[3].name = "CORE";
 8962     notes[3].type = NT_PRFPREG;
 8963     notes[3].datasz = sizeof(fpu);
 8964     notes[3].data = &fpu;
 8965   }
 8966   
 8967   /* Write notes phdr entry */
 8968   {
 8969     struct elf_phdr phdr;
 8970     int sz = 0;
 8971 
 8972     for(i = 0; i < numnote; i++)
 8973       sz += notesize(&notes[i]);
 8974 
 8975     phdr.p_type = PT_NOTE;
 8976     phdr.p_offset = offset;
 8977     phdr.p_vaddr = 0;
 8978     phdr.p_paddr = 0;
 8979     phdr.p_filesz = sz;
 8980     phdr.p_memsz = 0;
 8981     phdr.p_flags = 0;
 8982     phdr.p_align = 0;
 8983 
 8984     offset += phdr.p_filesz;
 8985     DUMP_WRITE(&phdr, sizeof(phdr));
 8986   }
 8987 
 8988   /* Page-align dumped data */
 8989   dataoff = offset = roundup(offset, ELF_EXEC_PAGESIZE);
 8990 
 8991   /* Write program headers for segments dump */
 8992   for(vma = current->mm->mmap, i = 0;
 8993     i < segs && vma != NULL; vma = vma->vm_next) {
 8994     struct elf_phdr phdr;
 8995     size_t sz;
 8996 
 8997     i++;
 8998 
 8999     sz = vma->vm_end - vma->vm_start;
 9000 
 9001     phdr.p_type = PT_LOAD;
 9002     phdr.p_offset = offset;
 9003     phdr.p_vaddr = vma->vm_start;
 9004     phdr.p_paddr = 0;
 9005     phdr.p_filesz = maydump(vma) ? sz : 0;
 9006     phdr.p_memsz = sz;
 9007     offset += phdr.p_filesz;
 9008     phdr.p_flags = vma->vm_flags & VM_READ ? PF_R : 0;
 9009     if (vma->vm_flags & VM_WRITE) phdr.p_flags |= PF_W;
 9010     if (vma->vm_flags & VM_EXEC) phdr.p_flags |= PF_X;
 9011     phdr.p_align = ELF_EXEC_PAGESIZE;
 9012 
 9013     DUMP_WRITE(&phdr, sizeof(phdr));
 9014   }
 9015 
 9016   for(i = 0; i < numnote; i++)
 9017     if (!writenote(&notes[i], &file))
 9018       goto close_coredump;
 9019 
 9020   set_fs(fs);
 9021 
 9022   DUMP_SEEK(dataoff);
 9023 
 9024   for(i = 0, vma = current->mm->mmap;
 9025       i < segs && vma != NULL;
 9026       vma = vma->vm_next) {
 9027     unsigned long addr = vma->vm_start;
 9028     unsigned long len = vma->vm_end - vma->vm_start;
 9029 
 9030     i++;
 9031     if (!maydump(vma))
 9032       continue;
 9033 #ifdef DEBUG
 9034     printk("elf_core_dump: writing %08lx %lx\n",
 9035            addr, len);
 9036 #endif
 9037     DUMP_WRITE((void *)addr, len);
 9038   }
 9039 
 9040   if ((off_t) file.f_pos != offset) {
 9041     /* Sanity check */
 9042     printk("elf_core_dump: file.f_pos (%ld) != "
 9043            "offset (%ld)\n",
 9044            (off_t) file.f_pos, offset);
 9045   }
 9046 
 9047  close_coredump:
 9048   if (file.f_op->release)
 9049     file.f_op->release(inode,&file);
 9050 
 9051  end_coredump:
 9052   set_fs(fs);
 9053   dput(dentry);
 9054 #ifndef CONFIG_BINFMT_ELF
 9055   MOD_DEC_USE_COUNT;
 9056 #endif
 9057   return has_dumped;
 9058 }
 9059 #endif          /* USE_ELF_CORE_DUMP */
 9060 
 9061 int __init init_elf_binfmt(void)
 9062 {
 9063   return register_binfmt(&elf_format);
 9064 }
 9065 
 9066 #ifdef MODULE
 9067 
 9068 int init_module(void)
 9069 {
 9070   /* Install the COFF, ELF and XOUT loaders.  N.B. We
 9071    * *rely* on the table being the right size with the
 9072    * right number of free slots...  */
 9073   return init_elf_binfmt();
 9074 }
 9075 
 9076 
 9077 void cleanup_module( void)
 9078 {
 9079   /* Remove the COFF and ELF loaders. */
 9080   unregister_binfmt(&elf_format);
 9081 }
 9082 #endif

netlib.narod.ru< Назад | Оглавление | Далее >

Сайт управляется системой uCoz