root/fs/binfmt_elf.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. padzero
  2. create_elf_tables
  3. load_elf_interp
  4. load_aout_interp
  5. do_load_elf_binary
  6. load_elf_binary
  7. do_load_elf_library
  8. load_elf_library
  9. dump_write
  10. dump_seek
  11. maydump
  12. notesize
  13. dump_regs
  14. writenote
  15. elf_core_dump
  16. init_module
  17. cleanup_module

   1 /*
   2  * linux/fs/binfmt_elf.c
   3  *
   4  * These are the functions used to load ELF format executables as used
   5  * on SVr4 machines.  Information on the format may be found in the book
   6  * "UNIX SYSTEM V RELEASE 4 Programmers Guide: Ansi C and Programming Support
   7  * Tools".
   8  *
   9  * Copyright 1993, 1994: Eric Youngdale (ericy@cais.com).
  10  */
  11 
  12 #include <linux/module.h>
  13 
  14 #include <linux/fs.h>
  15 #include <linux/stat.h>
  16 #include <linux/sched.h>
  17 #include <linux/mm.h>
  18 #include <linux/mman.h>
  19 #include <linux/a.out.h>
  20 #include <linux/errno.h>
  21 #include <linux/signal.h>
  22 #include <linux/binfmts.h>
  23 #include <linux/string.h>
  24 #include <linux/fcntl.h>
  25 #include <linux/ptrace.h>
  26 #include <linux/malloc.h>
  27 #include <linux/shm.h>
  28 #include <linux/personality.h>
  29 #include <linux/elfcore.h>
  30 
  31 #include <asm/segment.h>
  32 #include <asm/pgtable.h>
  33 
  34 #include <linux/config.h>
  35 
  36 #include <linux/unistd.h>
  37 typedef int (*sysfun_p)(int, ...);
  38 extern sysfun_p sys_call_table[];
  39 #define SYS(name)       (sys_call_table[__NR_##name])
  40 
  41 #define DLINFO_ITEMS 12
  42 
  43 #include <linux/elf.h>
  44 
  45 static int load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs);
  46 static int load_elf_library(int fd);
  47 static int elf_core_dump(long signr, struct pt_regs * regs);
  48 extern int dump_fpu (elf_fpregset_t *);
  49 
  50 /*
  51  * Please do not change the default core dump format to ELF when most people
  52  * do not have a gdb capable of interpreting ELF core files.  Once a gdb has
  53  * been released that understands ELF, *THEN* switch the core dump format.
  54  */
  55 
  56 struct linux_binfmt elf_format = {
  57 #ifndef MODULE
  58         NULL, NULL, load_elf_binary, load_elf_library, elf_core_dump
  59 #else
  60         NULL, &mod_use_count_, load_elf_binary, load_elf_library, elf_core_dump
  61 #endif
  62 };
  63 
  64 /* We need to explicitly zero any fractional pages
  65    after the data section (i.e. bss).  This would
  66    contain the junk from the file that should not
  67    be in memory */
  68 
  69 
  70 static void padzero(unsigned long elf_bss)
     /* [previous][next][first][last][top][bottom][index][help] */
  71 {
  72         unsigned long nbyte;
  73         char * fpnt;
  74   
  75         nbyte = elf_bss & (PAGE_SIZE-1);
  76         if (nbyte) {
  77                 nbyte = PAGE_SIZE - nbyte;
  78                 verify_area(VERIFY_WRITE, (void *) elf_bss, nbyte);
  79                 fpnt = (char *) elf_bss;
  80                 do {
  81                         put_user(0, fpnt++);
  82                 } while (--nbyte);
  83         }
  84 }
  85 
  86 unsigned long * create_elf_tables(char * p,int argc,int envc,struct elfhdr * exec, unsigned int load_addr, unsigned int interp_load_addr, int ibcs)
     /* [previous][next][first][last][top][bottom][index][help] */
  87 {
  88         unsigned long *argv,*envp, *dlinfo;
  89         unsigned long * sp;
  90         struct vm_area_struct *mpnt;
  91 
  92         mpnt = (struct vm_area_struct *)kmalloc(sizeof(*mpnt), GFP_KERNEL);
  93         if (mpnt) {
  94                 mpnt->vm_mm = current->mm;
  95                 mpnt->vm_start = PAGE_MASK & (unsigned long) p;
  96                 mpnt->vm_end = TASK_SIZE;
  97                 mpnt->vm_page_prot = PAGE_COPY;
  98 #ifdef VM_STACK_FLAGS
  99                 mpnt->vm_flags = VM_STACK_FLAGS;
 100                 mpnt->vm_pte = 0;
 101 #else
 102 #  ifdef VM_GROWSDOWN
 103                 mpnt->vm_flags = VM_GROWSDOWN;
 104 #  endif
 105 #endif
 106                 mpnt->vm_inode = NULL;
 107                 mpnt->vm_offset = 0;
 108                 mpnt->vm_ops = NULL;
 109                 insert_vm_struct(current, mpnt);
 110 #ifndef VM_GROWSDOWN
 111                 current->mm->stk_vma = mpnt;
 112 #endif
 113 
 114         }
 115         sp = (unsigned long *) (0xfffffffc & (unsigned long) p);
 116         sp -= exec ? DLINFO_ITEMS*2 : 2;
 117         dlinfo = sp;
 118         sp -= envc+1;
 119         envp = sp;
 120         sp -= argc+1;
 121         argv = sp;
 122         if (!ibcs) {
 123                 put_user(envp,--sp);
 124                 put_user(argv,--sp);
 125         }
 126 
 127 #define NEW_AUX_ENT(id, val) \
 128           put_user ((id), dlinfo++); \
 129           put_user ((val), dlinfo++)
 130         if(exec) { /* Put this here for an ELF program interpreter */
 131           struct elf_phdr * eppnt;
 132           eppnt = (struct elf_phdr *) exec->e_phoff;
 133 
 134           NEW_AUX_ENT (AT_PHDR, load_addr + exec->e_phoff);
 135           NEW_AUX_ENT (AT_PHENT, sizeof (struct elf_phdr));
 136           NEW_AUX_ENT (AT_PHNUM, exec->e_phnum);
 137           NEW_AUX_ENT (AT_PAGESZ, PAGE_SIZE);
 138           NEW_AUX_ENT (AT_BASE, interp_load_addr);
 139           NEW_AUX_ENT (AT_FLAGS, 0);
 140           NEW_AUX_ENT (AT_ENTRY, (unsigned long) exec->e_entry);
 141           NEW_AUX_ENT (AT_UID, (unsigned long) current->uid);
 142           NEW_AUX_ENT (AT_EUID, (unsigned long) current->euid);
 143           NEW_AUX_ENT (AT_GID, (unsigned long) current->gid);
 144           NEW_AUX_ENT (AT_EGID, (unsigned long) current->egid);
 145         }
 146         NEW_AUX_ENT (AT_NULL, 0);
 147 #undef NEW_AUX_ENT
 148 
 149         put_user((unsigned long)argc,--sp);
 150         current->mm->arg_start = (unsigned long) p;
 151         while (argc-->0) {
 152                 put_user(p,argv++);
 153                 while (get_user(p++)) /* nothing */ ;
 154         }
 155         put_user(0,argv);
 156         current->mm->arg_end = current->mm->env_start = (unsigned long) p;
 157         while (envc-->0) {
 158                 put_user(p,envp++);
 159                 while (get_user(p++)) /* nothing */ ;
 160         }
 161         put_user(0,envp);
 162         current->mm->env_end = (unsigned long) p;
 163         return sp;
 164 }
 165 
 166 
 167 /* This is much more generalized than the library routine read function,
 168    so we keep this separate.  Technically the library read function
 169    is only provided so that we can read a.out libraries that have
 170    an ELF header */
 171 
 172 static unsigned int load_elf_interp(struct elfhdr * interp_elf_ex,
     /* [previous][next][first][last][top][bottom][index][help] */
 173                              struct inode * interpreter_inode, unsigned int *interp_load_addr)
 174 {
 175         struct file * file;
 176         struct elf_phdr *elf_phdata  =  NULL;
 177         struct elf_phdr *eppnt;
 178         unsigned int len;
 179         unsigned int load_addr;
 180         int elf_exec_fileno;
 181         int elf_bss;
 182         int retval;
 183         unsigned int last_bss;
 184         int error;
 185         int i, k;
 186         
 187         elf_bss = 0;
 188         last_bss = 0;
 189         error = load_addr = 0;
 190         
 191         /* First of all, some simple consistency checks */
 192         if((interp_elf_ex->e_type != ET_EXEC && 
 193             interp_elf_ex->e_type != ET_DYN) || 
 194            (interp_elf_ex->e_machine != EM_386 && interp_elf_ex->e_machine != EM_486) ||
 195            (!interpreter_inode->i_op ||
 196             !interpreter_inode->i_op->default_file_ops->mmap)){
 197                 return 0xffffffff;
 198         }
 199         
 200         /* Now read in all of the header information */
 201         
 202         if(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum > PAGE_SIZE) 
 203             return 0xffffffff;
 204         
 205         elf_phdata =  (struct elf_phdr *) 
 206                 kmalloc(sizeof(struct elf_phdr) * interp_elf_ex->e_phnum, GFP_KERNEL);
 207         if(!elf_phdata)
 208           return 0xffffffff;
 209         
 210         /*
 211          * If the size of this structure has changed, then punt, since
 212          * we will be doing the wrong thing.
 213          */
 214         if( interp_elf_ex->e_phentsize != 32 )
 215           {
 216             kfree(elf_phdata);
 217             return 0xffffffff;
 218           }
 219 
 220         retval = read_exec(interpreter_inode, interp_elf_ex->e_phoff, (char *) elf_phdata,
 221                            sizeof(struct elf_phdr) * interp_elf_ex->e_phnum, 1);
 222         
 223         elf_exec_fileno = open_inode(interpreter_inode, O_RDONLY);
 224         if (elf_exec_fileno < 0) {
 225           kfree(elf_phdata);
 226           return 0xffffffff;
 227         }
 228 
 229         file = current->files->fd[elf_exec_fileno];
 230 
 231         eppnt = elf_phdata;
 232         for(i=0; i<interp_elf_ex->e_phnum; i++, eppnt++)
 233           if(eppnt->p_type == PT_LOAD) {
 234             int elf_type = MAP_PRIVATE | MAP_DENYWRITE;
 235             int elf_prot = 0;
 236             unsigned long vaddr = 0;
 237             if (eppnt->p_flags & PF_R) elf_prot =  PROT_READ;
 238             if (eppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
 239             if (eppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
 240             if (interp_elf_ex->e_type == ET_EXEC) {
 241                 elf_type |= MAP_FIXED;
 242                 vaddr = eppnt->p_vaddr;
 243             }
 244             
 245             error = do_mmap(file, 
 246                             vaddr & 0xfffff000,
 247                             eppnt->p_filesz + (eppnt->p_vaddr & 0xfff),
 248                             elf_prot,
 249                             elf_type,
 250                             eppnt->p_offset & 0xfffff000);
 251             
 252             if(error < 0 && error > -1024) break;  /* Real error */
 253 
 254             if(!load_addr && interp_elf_ex->e_type == ET_DYN)
 255               load_addr = error;
 256 
 257             /*
 258              * Find the end of the file  mapping for this phdr, and keep
 259              * track of the largest address we see for this.
 260              */
 261             k = load_addr + eppnt->p_vaddr + eppnt->p_filesz;
 262             if(k > elf_bss) elf_bss = k;
 263 
 264             /*
 265              * Do the same thing for the memory mapping - between
 266              * elf_bss and last_bss is the bss section.
 267              */
 268             k = load_addr + eppnt->p_memsz + eppnt->p_vaddr;
 269             if(k > last_bss) last_bss = k;
 270           }
 271         
 272         /* Now use mmap to map the library into memory. */
 273 
 274         SYS(close)(elf_exec_fileno);
 275         if(error < 0 && error > -1024) {
 276                 kfree(elf_phdata);
 277                 return 0xffffffff;
 278         }
 279 
 280         /*
 281          * Now fill out the bss section.  First pad the last page up
 282          * to the page boundary, and then perform a mmap to make sure
 283          * that there are zeromapped pages up to and including the last
 284          * bss page.
 285          */
 286         padzero(elf_bss);
 287         len = (elf_bss + 0xfff) & 0xfffff000; /* What we have mapped so far */
 288 
 289         /* Map the last of the bss segment */
 290         if (last_bss > len)
 291           do_mmap(NULL, len, last_bss-len,
 292                   PROT_READ|PROT_WRITE|PROT_EXEC,
 293                   MAP_FIXED|MAP_PRIVATE, 0);
 294         kfree(elf_phdata);
 295 
 296         *interp_load_addr = load_addr;
 297         return ((unsigned int) interp_elf_ex->e_entry) + load_addr;
 298 }
 299 
 300 static unsigned int load_aout_interp(struct exec * interp_ex,
     /* [previous][next][first][last][top][bottom][index][help] */
 301                              struct inode * interpreter_inode)
 302 {
 303   int retval;
 304   unsigned int elf_entry;
 305   
 306   current->mm->brk = interp_ex->a_bss +
 307     (current->mm->end_data = interp_ex->a_data +
 308      (current->mm->end_code = interp_ex->a_text));
 309   elf_entry = interp_ex->a_entry;
 310   
 311   
 312   if (N_MAGIC(*interp_ex) == OMAGIC) {
 313     do_mmap(NULL, 0, interp_ex->a_text+interp_ex->a_data,
 314             PROT_READ|PROT_WRITE|PROT_EXEC,
 315             MAP_FIXED|MAP_PRIVATE, 0);
 316     retval = read_exec(interpreter_inode, 32, (char *) 0, 
 317                        interp_ex->a_text+interp_ex->a_data, 0);
 318   } else if (N_MAGIC(*interp_ex) == ZMAGIC || N_MAGIC(*interp_ex) == QMAGIC) {
 319     do_mmap(NULL, 0, interp_ex->a_text+interp_ex->a_data,
 320             PROT_READ|PROT_WRITE|PROT_EXEC,
 321             MAP_FIXED|MAP_PRIVATE, 0);
 322     retval = read_exec(interpreter_inode,
 323                        N_TXTOFF(*interp_ex) ,
 324                        (char *) N_TXTADDR(*interp_ex),
 325                        interp_ex->a_text+interp_ex->a_data, 0);
 326   } else
 327     retval = -1;
 328   
 329   if(retval >= 0)
 330     do_mmap(NULL, (interp_ex->a_text + interp_ex->a_data + 0xfff) & 
 331             0xfffff000, interp_ex->a_bss,
 332             PROT_READ|PROT_WRITE|PROT_EXEC,
 333             MAP_FIXED|MAP_PRIVATE, 0);
 334   if(retval < 0) return 0xffffffff;
 335   return elf_entry;
 336 }
 337 
 338 /*
 339  * These are the functions used to load ELF style executables and shared
 340  * libraries.  There is no binary dependent code anywhere else.
 341  */
 342 
 343 #define INTERPRETER_NONE 0
 344 #define INTERPRETER_AOUT 1
 345 #define INTERPRETER_ELF 2
 346 
 347 
 348 static inline int
 349 do_load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 350 {
 351         struct elfhdr elf_ex;
 352         struct elfhdr interp_elf_ex;
 353         struct file * file;
 354         struct exec interp_ex;
 355         struct inode *interpreter_inode;
 356         unsigned int load_addr;
 357         unsigned int interpreter_type = INTERPRETER_NONE;
 358         unsigned char ibcs2_interpreter;
 359         int i;
 360         int old_fs;
 361         int error;
 362         struct elf_phdr * elf_ppnt, *elf_phdata;
 363         int elf_exec_fileno;
 364         unsigned int elf_bss, k, elf_brk;
 365         int retval;
 366         char * elf_interpreter;
 367         unsigned int elf_entry, interp_load_addr = 0;
 368         int status;
 369         unsigned int start_code, end_code, end_data;
 370         unsigned int elf_stack;
 371         char passed_fileno[6];
 372         
 373         ibcs2_interpreter = 0;
 374         status = 0;
 375         load_addr = 0;
 376         elf_ex = *((struct elfhdr *) bprm->buf);          /* exec-header */
 377         
 378         if (elf_ex.e_ident[0] != 0x7f ||
 379             strncmp(&elf_ex.e_ident[1], "ELF",3) != 0) {
 380                 return  -ENOEXEC;
 381         }
 382         
 383         
 384         /* First of all, some simple consistency checks */
 385         if((elf_ex.e_type != ET_EXEC &&
 386             elf_ex.e_type != ET_DYN) || 
 387            (elf_ex.e_machine != EM_386 && elf_ex.e_machine != EM_486) ||
 388            (!bprm->inode->i_op || !bprm->inode->i_op->default_file_ops ||
 389             !bprm->inode->i_op->default_file_ops->mmap)){
 390                 return -ENOEXEC;
 391         }
 392         
 393         /* Now read in all of the header information */
 394         
 395         elf_phdata = (struct elf_phdr *) kmalloc(elf_ex.e_phentsize * 
 396                                                  elf_ex.e_phnum, GFP_KERNEL);
 397         if (elf_phdata == NULL) {
 398                 return -ENOMEM;
 399         }
 400         
 401         retval = read_exec(bprm->inode, elf_ex.e_phoff, (char *) elf_phdata,
 402                            elf_ex.e_phentsize * elf_ex.e_phnum, 1);
 403         if (retval < 0) {
 404                 kfree (elf_phdata);
 405                 return retval;
 406         }
 407         
 408         elf_ppnt = elf_phdata;
 409         
 410         elf_bss = 0;
 411         elf_brk = 0;
 412         
 413         elf_exec_fileno = open_inode(bprm->inode, O_RDONLY);
 414 
 415         if (elf_exec_fileno < 0) {
 416                 kfree (elf_phdata);
 417                 return elf_exec_fileno;
 418         }
 419         
 420         file = current->files->fd[elf_exec_fileno];
 421         
 422         elf_stack = 0xffffffff;
 423         elf_interpreter = NULL;
 424         start_code = 0;
 425         end_code = 0;
 426         end_data = 0;
 427         
 428         for(i=0;i < elf_ex.e_phnum; i++){
 429                 if(elf_ppnt->p_type == PT_INTERP) {
 430                         if( elf_interpreter != NULL )
 431                         {
 432                                 kfree (elf_phdata);
 433                                 kfree(elf_interpreter);
 434                                 return -EINVAL;
 435                         }
 436 
 437                         /* This is the program interpreter used for
 438                          * shared libraries - for now assume that this
 439                          * is an a.out format binary 
 440                          */
 441                         
 442                         elf_interpreter = (char *) kmalloc(elf_ppnt->p_filesz, 
 443                                                            GFP_KERNEL);
 444                         if (elf_interpreter == NULL) {
 445                                 kfree (elf_phdata);
 446                                 return -ENOMEM;
 447                         }
 448                         
 449                         retval = read_exec(bprm->inode,elf_ppnt->p_offset,elf_interpreter,
 450                                            elf_ppnt->p_filesz, 1);
 451                         /* If the program interpreter is one of these two,
 452                            then assume an iBCS2 image. Otherwise assume
 453                            a native linux image. */
 454                         if (strcmp(elf_interpreter,"/usr/lib/libc.so.1") == 0 ||
 455                             strcmp(elf_interpreter,"/usr/lib/ld.so.1") == 0)
 456                           ibcs2_interpreter = 1;
 457 #if 0
 458                         printk("Using ELF interpreter %s\n", elf_interpreter);
 459 #endif
 460                         if(retval >= 0) {
 461                                 old_fs = get_fs(); /* This could probably be optimized */
 462                                 set_fs(get_ds());
 463                                 retval = namei(elf_interpreter, &interpreter_inode);
 464                                 set_fs(old_fs);
 465                         }
 466 
 467                         if(retval >= 0)
 468                                 retval = read_exec(interpreter_inode,0,bprm->buf,128, 1);
 469                         
 470                         if(retval >= 0) {
 471                                 interp_ex = *((struct exec *) bprm->buf);               /* exec-header */
 472                                 interp_elf_ex = *((struct elfhdr *) bprm->buf);   /* exec-header */
 473                                 
 474                         }
 475                         if(retval < 0) {
 476                                 kfree (elf_phdata);
 477                                 kfree(elf_interpreter);
 478                                 return retval;
 479                         }
 480                 }
 481                 elf_ppnt++;
 482         }
 483         
 484         /* Some simple consistency checks for the interpreter */
 485         if(elf_interpreter){
 486                 interpreter_type = INTERPRETER_ELF | INTERPRETER_AOUT;
 487 
 488                 /* Now figure out which format our binary is */
 489                 if((N_MAGIC(interp_ex) != OMAGIC) && 
 490                    (N_MAGIC(interp_ex) != ZMAGIC) &&
 491                    (N_MAGIC(interp_ex) != QMAGIC)) 
 492                   interpreter_type = INTERPRETER_ELF;
 493 
 494                 if (interp_elf_ex.e_ident[0] != 0x7f ||
 495                     strncmp(&interp_elf_ex.e_ident[1], "ELF",3) != 0)
 496                   interpreter_type &= ~INTERPRETER_ELF;
 497 
 498                 if(!interpreter_type)
 499                   {
 500                     kfree(elf_interpreter);
 501                     kfree(elf_phdata);
 502                     return -ELIBBAD;
 503                   }
 504         }
 505         
 506         /* OK, we are done with that, now set up the arg stuff,
 507            and then start this sucker up */
 508         
 509         if (!bprm->sh_bang) {
 510                 char * passed_p;
 511                 
 512                 if(interpreter_type == INTERPRETER_AOUT) {
 513                   sprintf(passed_fileno, "%d", elf_exec_fileno);
 514                   passed_p = passed_fileno;
 515                 
 516                   if(elf_interpreter) {
 517                     bprm->p = copy_strings(1,&passed_p,bprm->page,bprm->p,2);
 518                     bprm->argc++;
 519                   }
 520                 }
 521                 if (!bprm->p) {
 522                         if(elf_interpreter) {
 523                               kfree(elf_interpreter);
 524                         }
 525                         kfree (elf_phdata);
 526                         return -E2BIG;
 527                 }
 528         }
 529         
 530         /* OK, This is the point of no return */
 531         flush_old_exec(bprm);
 532 
 533         current->mm->end_data = 0;
 534         current->mm->end_code = 0;
 535         current->mm->start_mmap = ELF_START_MMAP;
 536         current->mm->mmap = NULL;
 537         elf_entry = (unsigned int) elf_ex.e_entry;
 538         
 539         /* Do this so that we can load the interpreter, if need be.  We will
 540            change some of these later */
 541         current->mm->rss = 0;
 542         bprm->p += setup_arg_pages(0, bprm->page);
 543         current->mm->start_stack = bprm->p;
 544         
 545         /* Now we do a little grungy work by mmaping the ELF image into
 546            the correct location in memory.  At this point, we assume that
 547            the image should be loaded at fixed address, not at a variable
 548            address. */
 549         
 550         old_fs = get_fs();
 551         set_fs(get_ds());
 552         
 553         elf_ppnt = elf_phdata;
 554         for(i=0;i < elf_ex.e_phnum; i++){
 555                 
 556                 if(elf_ppnt->p_type == PT_INTERP) {
 557                         /* Set these up so that we are able to load the interpreter */
 558                   /* Now load the interpreter into user address space */
 559                   set_fs(old_fs);
 560 
 561                   if(interpreter_type & 1) elf_entry = 
 562                     load_aout_interp(&interp_ex, interpreter_inode);
 563 
 564                   if(interpreter_type & 2) elf_entry = 
 565                     load_elf_interp(&interp_elf_ex, interpreter_inode, &interp_load_addr);
 566 
 567                   old_fs = get_fs();
 568                   set_fs(get_ds());
 569 
 570                   iput(interpreter_inode);
 571                   kfree(elf_interpreter);
 572                         
 573                   if(elf_entry == 0xffffffff) { 
 574                     set_fs(old_fs);
 575                     printk("Unable to load interpreter\n");
 576                     kfree(elf_phdata);
 577                     send_sig(SIGSEGV, current, 0);
 578                     return 0;
 579                   }
 580                 }
 581                 
 582                 
 583                 if(elf_ppnt->p_type == PT_LOAD) {
 584                         int elf_prot = (elf_ppnt->p_flags & PF_R) ? PROT_READ : 0;
 585                         if (elf_ppnt->p_flags & PF_W) elf_prot |= PROT_WRITE;
 586                         if (elf_ppnt->p_flags & PF_X) elf_prot |= PROT_EXEC;
 587                         error = do_mmap(file,
 588                                         elf_ppnt->p_vaddr & 0xfffff000,
 589                                         elf_ppnt->p_filesz + (elf_ppnt->p_vaddr & 0xfff),
 590                                         elf_prot,
 591                                         MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
 592                                         elf_ppnt->p_offset & 0xfffff000);
 593                         
 594 #ifdef LOW_ELF_STACK
 595                         if((elf_ppnt->p_vaddr & 0xfffff000) < elf_stack) 
 596                                 elf_stack = elf_ppnt->p_vaddr & 0xfffff000;
 597 #endif
 598                         
 599                         if(!load_addr) 
 600                           load_addr = elf_ppnt->p_vaddr - elf_ppnt->p_offset;
 601                         k = elf_ppnt->p_vaddr;
 602                         if(k > start_code) start_code = k;
 603                         k = elf_ppnt->p_vaddr + elf_ppnt->p_filesz;
 604                         if(k > elf_bss) elf_bss = k;
 605 #if 1
 606                         if((elf_ppnt->p_flags | PF_W) && end_code <  k)
 607 #else
 608                         if( !(elf_ppnt->p_flags & PF_W) && end_code <  k)
 609 #endif
 610                                 end_code = k; 
 611                         if(end_data < k) end_data = k; 
 612                         k = elf_ppnt->p_vaddr + elf_ppnt->p_memsz;
 613                         if(k > elf_brk) elf_brk = k;                 
 614                       }
 615                 elf_ppnt++;
 616         }
 617         set_fs(old_fs);
 618         
 619         kfree(elf_phdata);
 620         
 621         if(interpreter_type != INTERPRETER_AOUT) SYS(close)(elf_exec_fileno);
 622         current->personality = (ibcs2_interpreter ? PER_SVR4 : PER_LINUX);
 623 
 624         if (current->exec_domain && current->exec_domain->use_count)
 625                 (*current->exec_domain->use_count)--;
 626         if (current->binfmt && current->binfmt->use_count)
 627                 (*current->binfmt->use_count)--;
 628         current->exec_domain = lookup_exec_domain(current->personality);
 629         current->binfmt = &elf_format;
 630         if (current->exec_domain && current->exec_domain->use_count)
 631                 (*current->exec_domain->use_count)++;
 632         if (current->binfmt && current->binfmt->use_count)
 633                 (*current->binfmt->use_count)++;
 634 
 635 #ifndef VM_STACK_FLAGS
 636         current->executable = bprm->inode;
 637         bprm->inode->i_count++;
 638 #endif
 639 #ifdef LOW_ELF_STACK
 640         current->start_stack = p = elf_stack - 4;
 641 #endif
 642         current->suid = current->euid = current->fsuid = bprm->e_uid;
 643         current->sgid = current->egid = current->fsgid = bprm->e_gid;
 644         bprm->p -= MAX_ARG_PAGES*PAGE_SIZE;
 645         bprm->p = (unsigned long) 
 646           create_elf_tables((char *)bprm->p,
 647                         bprm->argc,
 648                         bprm->envc,
 649                         (interpreter_type == INTERPRETER_ELF ? &elf_ex : NULL),
 650                         load_addr,
 651                         interp_load_addr,
 652                         (interpreter_type == INTERPRETER_AOUT ? 0 : 1));
 653         if(interpreter_type == INTERPRETER_AOUT)
 654           current->mm->arg_start += strlen(passed_fileno) + 1;
 655         current->mm->start_brk = current->mm->brk = elf_brk;
 656         current->mm->end_code = end_code;
 657         current->mm->start_code = start_code;
 658         current->mm->end_data = end_data;
 659         current->mm->start_stack = bprm->p;
 660 
 661         /* Calling sys_brk effectively mmaps the pages that we need for the bss and break
 662            sections */
 663         current->mm->brk = (elf_bss + 0xfff) & 0xfffff000;
 664         SYS(brk)((elf_brk + 0xfff) & 0xfffff000);
 665 
 666         padzero(elf_bss);
 667 
 668 #if 0
 669         printk("(start_brk) %x\n" , current->mm->start_brk);
 670         printk("(end_code) %x\n" , current->mm->end_code);
 671         printk("(start_code) %x\n" , current->mm->start_code);
 672         printk("(end_data) %x\n" , current->mm->end_data);
 673         printk("(start_stack) %x\n" , current->mm->start_stack);
 674         printk("(brk) %x\n" , current->mm->brk);
 675 #endif
 676 
 677         if( current->personality == PER_SVR4 )
 678         {
 679                 /* Why this, you ask???  Well SVr4 maps page 0 as read-only,
 680                    and some applications "depend" upon this behavior.
 681                    Since we do not have the power to recompile these, we
 682                    emulate the SVr4 behavior.  Sigh.  */
 683                 error = do_mmap(NULL, 0, 4096, PROT_READ | PROT_EXEC,
 684                                 MAP_FIXED | MAP_PRIVATE, 0);
 685         }
 686 
 687         /* SVR4/i386 ABI (pages 3-31, 3-32) says that when the program
 688            starts %edx contains a pointer to a function which might be
 689            registered using `atexit'.  This provides a mean for the
 690            dynamic linker to call DT_FINI functions for shared libraries
 691            that have been loaded before the code runs.
 692 
 693            A value of 0 tells we have no such handler.  */
 694         regs->edx = 0;
 695 
 696         start_thread(regs, elf_entry, bprm->p);
 697         if (current->flags & PF_PTRACED)
 698                 send_sig(SIGTRAP, current, 0);
 699         return 0;
 700 }
 701 
 702 static int
 703 load_elf_binary(struct linux_binprm * bprm, struct pt_regs * regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 704 {
 705         int retval;
 706 
 707         MOD_INC_USE_COUNT;
 708         retval = do_load_elf_binary(bprm, regs);
 709         MOD_DEC_USE_COUNT;
 710         return retval;
 711 }
 712 
 713 /* This is really simpleminded and specialized - we are loading an
 714    a.out library that is given an ELF header. */
 715 
 716 static inline int
 717 do_load_elf_library(int fd){
     /* [previous][next][first][last][top][bottom][index][help] */
 718         struct file * file;
 719         struct elfhdr elf_ex;
 720         struct elf_phdr *elf_phdata  =  NULL;
 721         struct  inode * inode;
 722         unsigned int len;
 723         int elf_bss;
 724         int retval;
 725         unsigned int bss;
 726         int error;
 727         int i,j, k;
 728 
 729         len = 0;
 730         file = current->files->fd[fd];
 731         inode = file->f_inode;
 732         elf_bss = 0;
 733         
 734         if (!file || !file->f_op)
 735                 return -EACCES;
 736 
 737         /* seek to the beginning of the file */
 738         if (file->f_op->lseek) {
 739                 if ((error = file->f_op->lseek(inode, file, 0, 0)) != 0)
 740                         return -ENOEXEC;
 741         } else
 742                 file->f_pos = 0;
 743 
 744         set_fs(KERNEL_DS);
 745         error = file->f_op->read(inode, file, (char *) &elf_ex, sizeof(elf_ex));
 746         set_fs(USER_DS);
 747         if (error != sizeof(elf_ex))
 748                 return -ENOEXEC;
 749 
 750         if (elf_ex.e_ident[0] != 0x7f ||
 751             strncmp(&elf_ex.e_ident[1], "ELF",3) != 0)
 752                 return -ENOEXEC;
 753 
 754         /* First of all, some simple consistency checks */
 755         if(elf_ex.e_type != ET_EXEC || elf_ex.e_phnum > 2 ||
 756            (elf_ex.e_machine != EM_386 && elf_ex.e_machine != EM_486) ||
 757            (!inode->i_op || !inode->i_op->default_file_ops->mmap))
 758                 return -ENOEXEC;
 759         
 760         /* Now read in all of the header information */
 761         
 762         if(sizeof(struct elf_phdr) * elf_ex.e_phnum > PAGE_SIZE)
 763                 return -ENOEXEC;
 764         
 765         elf_phdata =  (struct elf_phdr *) 
 766                 kmalloc(sizeof(struct elf_phdr) * elf_ex.e_phnum, GFP_KERNEL);
 767         if (elf_phdata == NULL)
 768                 return -ENOMEM;
 769         
 770         retval = read_exec(inode, elf_ex.e_phoff, (char *) elf_phdata,
 771                            sizeof(struct elf_phdr) * elf_ex.e_phnum, 1);
 772         
 773         j = 0;
 774         for(i=0; i<elf_ex.e_phnum; i++)
 775                 if((elf_phdata + i)->p_type == PT_LOAD) j++;
 776         
 777         if(j != 1)  {
 778                 kfree(elf_phdata);
 779                 return -ENOEXEC;
 780         }
 781         
 782         while(elf_phdata->p_type != PT_LOAD) elf_phdata++;
 783         
 784         /* Now use mmap to map the library into memory. */
 785         error = do_mmap(file,
 786                         elf_phdata->p_vaddr & 0xfffff000,
 787                         elf_phdata->p_filesz + (elf_phdata->p_vaddr & 0xfff),
 788                         PROT_READ | PROT_WRITE | PROT_EXEC,
 789                         MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
 790                         elf_phdata->p_offset & 0xfffff000);
 791 
 792         k = elf_phdata->p_vaddr + elf_phdata->p_filesz;
 793         if(k > elf_bss) elf_bss = k;
 794         
 795         SYS(close)(fd);
 796         if (error != (elf_phdata->p_vaddr & 0xfffff000)) {
 797                 kfree(elf_phdata);
 798                 return error;
 799         }
 800 
 801         padzero(elf_bss);
 802 
 803         len = (elf_phdata->p_filesz + elf_phdata->p_vaddr+ 0xfff) & 0xfffff000;
 804         bss = elf_phdata->p_memsz + elf_phdata->p_vaddr;
 805         if (bss > len)
 806           do_mmap(NULL, len, bss-len,
 807                   PROT_READ|PROT_WRITE|PROT_EXEC,
 808                   MAP_FIXED|MAP_PRIVATE, 0);
 809         kfree(elf_phdata);
 810         return 0;
 811 }
 812 
 813 static int load_elf_library(int fd)
     /* [previous][next][first][last][top][bottom][index][help] */
 814 {
 815         int retval;
 816 
 817         MOD_INC_USE_COUNT;
 818         retval = do_load_elf_library(fd);
 819         MOD_DEC_USE_COUNT;
 820         return retval;
 821 }
 822         
 823 /*
 824  * ELF core dumper
 825  *
 826  * Modelled on fs/exec.c:aout_core_dump()
 827  * Jeremy Fitzhardinge <jeremy@sw.oz.au>
 828  */
 829 /*
 830  * These are the only things you should do on a core-file: use only these
 831  * functions to write out all the necessary info.
 832  */
 833 static int dump_write(struct file *file, const void *addr, int nr)
     /* [previous][next][first][last][top][bottom][index][help] */
 834 {
 835         return file->f_op->write(file->f_inode, file, addr, nr) == nr;
 836 }
 837 
 838 static int dump_seek(struct file *file, off_t off)
     /* [previous][next][first][last][top][bottom][index][help] */
 839 {
 840         if (file->f_op->lseek) {
 841                 if (file->f_op->lseek(file->f_inode, file, off, 0) != off)
 842                         return 0;
 843         } else
 844                 file->f_pos = off;
 845         return 1;
 846 }
 847 
 848 /*
 849  * Decide whether a segment is worth dumping; default is yes to be
 850  * sure (missing info is worse than too much; etc).
 851  * Personally I'd include everything, and use the coredump limit...
 852  *
 853  * I think we should skip something. But I am not sure how. H.J.
 854  */
 855 static inline int maydump(struct vm_area_struct *vma)
     /* [previous][next][first][last][top][bottom][index][help] */
 856 {
 857 #if 1
 858         if (vma->vm_flags & (VM_WRITE|VM_GROWSUP|VM_GROWSDOWN))
 859                 return 1;
 860         if (vma->vm_flags & (VM_READ|VM_EXEC|VM_EXECUTABLE|VM_SHARED))
 861                 return 0;
 862 #endif
 863         return 1;
 864 }
 865 
 866 #define roundup(x, y)  ((((x)+((y)-1))/(y))*(y))
 867 
 868 /* An ELF note in memory */
 869 struct memelfnote
 870 {
 871         const char *name;
 872         int type;
 873         unsigned int datasz;
 874         void *data;
 875 };
 876 
 877 static int notesize(struct memelfnote *en)
     /* [previous][next][first][last][top][bottom][index][help] */
 878 {
 879         int sz;
 880         
 881         sz = sizeof(struct elf_note);
 882         sz += roundup(strlen(en->name), 4);
 883         sz += roundup(en->datasz, 4);
 884         
 885         return sz;
 886 }
 887 
 888 /* #define DEBUG */
 889 
 890 #ifdef DEBUG
 891 static void dump_regs(const char *str, elf_greg_t *r)
     /* [previous][next][first][last][top][bottom][index][help] */
 892 {
 893         int i;
 894         static const char *regs[] = { "ebx", "ecx", "edx", "esi", "edi", "ebp",
 895                                               "eax", "ds", "es", "fs", "gs",
 896                                               "orig_eax", "eip", "cs",
 897                                               "efl", "uesp", "ss"};
 898         printk("Registers: %s\n", str);
 899 
 900         for(i = 0; i < ELF_NGREG; i++)
 901         {
 902                 unsigned long val = r[i];
 903                 printk("   %-2d %-5s=%08lx %lu\n", i, regs[i], val, val);
 904         }
 905 }
 906 #endif
 907 
 908 #define DUMP_WRITE(addr, nr)    \
 909         do { if (!dump_write(file, (addr), (nr))) return 0; } while(0)
 910 #define DUMP_SEEK(off)  \
 911         do { if (!dump_seek(file, (off))) return 0; } while(0)
 912 
 913 static int writenote(struct memelfnote *men, struct file *file)
     /* [previous][next][first][last][top][bottom][index][help] */
 914 {
 915         struct elf_note en;
 916 
 917         en.n_namesz = strlen(men->name);
 918         en.n_descsz = men->datasz;
 919         en.n_type = men->type;
 920 
 921         DUMP_WRITE(&en, sizeof(en));
 922         DUMP_WRITE(men->name, en.n_namesz);
 923         /* XXX - cast from long long to long to avoid need for libgcc.a */
 924         DUMP_SEEK(roundup((unsigned long)file->f_pos, 4));      /* XXX */
 925         DUMP_WRITE(men->data, men->datasz);
 926         DUMP_SEEK(roundup((unsigned long)file->f_pos, 4));      /* XXX */
 927         
 928         return 1;
 929 }
 930 #undef DUMP_WRITE
 931 #undef DUMP_SEEK
 932 
 933 #define DUMP_WRITE(addr, nr)    \
 934         if (!dump_write(&file, (addr), (nr))) \
 935                 goto close_coredump;
 936 #define DUMP_SEEK(off)  \
 937         if (!dump_seek(&file, (off))) \
 938                 goto close_coredump;
 939 /*
 940  * Actual dumper
 941  *
 942  * This is a two-pass process; first we find the offsets of the bits,
 943  * and then they are actually written out.  If we run out of core limit
 944  * we just truncate.
 945  */
 946 static int elf_core_dump(long signr, struct pt_regs * regs)
     /* [previous][next][first][last][top][bottom][index][help] */
 947 {
 948         int has_dumped = 0;
 949         struct file file;
 950         struct inode *inode;
 951         unsigned short fs;
 952         char corefile[6+sizeof(current->comm)];
 953         int segs;
 954         int i;
 955         size_t size;
 956         struct vm_area_struct *vma;
 957         struct elfhdr elf;
 958         off_t offset = 0, dataoff;
 959         int limit = current->rlim[RLIMIT_CORE].rlim_cur;
 960         int numnote = 4;
 961         struct memelfnote notes[4];
 962         struct elf_prstatus prstatus;   /* NT_PRSTATUS */
 963         elf_fpregset_t fpu;             /* NT_PRFPREG */
 964         struct elf_prpsinfo psinfo;     /* NT_PRPSINFO */
 965         
 966         if (!current->dumpable || limit < PAGE_SIZE)
 967                 return 0;
 968         current->dumpable = 0;
 969 
 970 #ifndef CONFIG_BINFMT_ELF
 971         MOD_INC_USE_COUNT;
 972 #endif
 973 
 974         /* Count what's needed to dump, up to the limit of coredump size */
 975         segs = 0;
 976         size = 0;
 977         for(vma = current->mm->mmap; vma != NULL; vma = vma->vm_next) {
 978                 int sz = vma->vm_end-vma->vm_start;
 979                 
 980                 if (!maydump(vma))
 981                         continue;
 982 
 983                 if (size+sz > limit)
 984                         break;
 985                 
 986                 segs++;
 987                 size += sz;
 988         }
 989 #ifdef DEBUG
 990         printk("elf_core_dump: %d segs taking %d bytes\n", segs, size);
 991 #endif
 992 
 993         /* Set up header */
 994         memcpy(elf.e_ident, ELFMAG, SELFMAG);
 995         elf.e_ident[EI_CLASS] = ELFCLASS32;
 996         elf.e_ident[EI_DATA] = ELFDATA2LSB;
 997         elf.e_ident[EI_VERSION] = EV_CURRENT;
 998         memset(elf.e_ident+EI_PAD, 0, EI_NIDENT-EI_PAD);
 999         
1000         elf.e_type = ET_CORE;
1001         elf.e_machine = EM_386;
1002         elf.e_version = EV_CURRENT;
1003         elf.e_entry = 0;
1004         elf.e_phoff = sizeof(elf);
1005         elf.e_shoff = 0;
1006         elf.e_flags = 0;
1007         elf.e_ehsize = sizeof(elf);
1008         elf.e_phentsize = sizeof(struct elf_phdr);
1009         elf.e_phnum = segs+1;           /* Include notes */
1010         elf.e_shentsize = 0;
1011         elf.e_shnum = 0;
1012         elf.e_shstrndx = 0;
1013         
1014         fs = get_fs();
1015         set_fs(KERNEL_DS);
1016         memcpy(corefile,"core.",5);
1017 #if 0
1018         memcpy(corefile+5,current->comm,sizeof(current->comm));
1019 #else
1020         corefile[4] = '\0';
1021 #endif
1022         if (open_namei(corefile,O_CREAT | 2 | O_TRUNC,0600,&inode,NULL)) {
1023                 inode = NULL;
1024                 goto end_coredump;
1025         }
1026         if (!S_ISREG(inode->i_mode))
1027                 goto end_coredump;
1028         if (!inode->i_op || !inode->i_op->default_file_ops)
1029                 goto end_coredump;
1030         file.f_mode = 3;
1031         file.f_flags = 0;
1032         file.f_count = 1;
1033         file.f_inode = inode;
1034         file.f_pos = 0;
1035         file.f_reada = 0;
1036         file.f_op = inode->i_op->default_file_ops;
1037         if (file.f_op->open)
1038                 if (file.f_op->open(inode,&file))
1039                         goto end_coredump;
1040         if (!file.f_op->write)
1041                 goto close_coredump;
1042         has_dumped = 1;
1043 
1044         DUMP_WRITE(&elf, sizeof(elf));
1045         offset += sizeof(elf);                          /* Elf header */
1046         offset += (segs+1) * sizeof(struct elf_phdr);   /* Program headers */
1047 
1048         /*
1049          * Set up the notes in similar form to SVR4 core dumps made
1050          * with info from their /proc.
1051          */
1052         memset(&psinfo, 0, sizeof(psinfo));
1053         memset(&prstatus, 0, sizeof(prstatus));
1054 
1055         notes[0].name = "CORE";
1056         notes[0].type = NT_PRSTATUS;
1057         notes[0].datasz = sizeof(prstatus);
1058         notes[0].data = &prstatus;
1059         prstatus.pr_info.si_signo = prstatus.pr_cursig = signr;
1060         prstatus.pr_sigpend = current->signal;
1061         prstatus.pr_sighold = current->blocked;
1062         psinfo.pr_pid = prstatus.pr_pid = current->pid;
1063         psinfo.pr_ppid = prstatus.pr_ppid = current->p_pptr->pid;
1064         psinfo.pr_pgrp = prstatus.pr_pgrp = current->pgrp;
1065         psinfo.pr_sid = prstatus.pr_sid = current->session;
1066         prstatus.pr_utime.tv_sec = CT_TO_SECS(current->utime);
1067         prstatus.pr_utime.tv_usec = CT_TO_USECS(current->utime);
1068         prstatus.pr_stime.tv_sec = CT_TO_SECS(current->stime);
1069         prstatus.pr_stime.tv_usec = CT_TO_USECS(current->stime);
1070         prstatus.pr_cutime.tv_sec = CT_TO_SECS(current->cutime);
1071         prstatus.pr_cutime.tv_usec = CT_TO_USECS(current->cutime);
1072         prstatus.pr_cstime.tv_sec = CT_TO_SECS(current->cstime);
1073         prstatus.pr_cstime.tv_usec = CT_TO_USECS(current->cstime);
1074         if (sizeof(elf_gregset_t) != sizeof(struct pt_regs))
1075         {
1076                 printk("sizeof(elf_gregset_t) (%d) != sizeof(struct pt_regs) (%d)\n",
1077                         sizeof(elf_gregset_t), sizeof(struct pt_regs));
1078         }
1079         else
1080                 *(struct pt_regs *)&prstatus.pr_reg = *regs;
1081         
1082 #ifdef DEBUG
1083         dump_regs("Passed in regs", (elf_greg_t *)regs);
1084         dump_regs("prstatus regs", (elf_greg_t *)&prstatus.pr_reg);
1085 #endif
1086 
1087         notes[1].name = "CORE";
1088         notes[1].type = NT_PRPSINFO;
1089         notes[1].datasz = sizeof(psinfo);
1090         notes[1].data = &psinfo;
1091         psinfo.pr_state = current->state;
1092         psinfo.pr_sname = (current->state < 0 || current->state > 5) ? '.' : "RSDZTD"[current->state];
1093         psinfo.pr_zomb = psinfo.pr_sname == 'Z';
1094         psinfo.pr_nice = current->priority-15;
1095         psinfo.pr_flag = current->flags;
1096         psinfo.pr_uid = current->uid;
1097         psinfo.pr_gid = current->gid;
1098         {
1099                 int i, len;
1100 
1101                 set_fs(fs);
1102                 
1103                 len = current->mm->arg_end - current->mm->arg_start;
1104                 len = len >= ELF_PRARGSZ ? ELF_PRARGSZ : len;
1105                 memcpy_fromfs(&psinfo.pr_psargs,
1106                               (const char *)current->mm->arg_start, len);
1107                 for(i = 0; i < len; i++)
1108                         if (psinfo.pr_psargs[i] == 0)
1109                                 psinfo.pr_psargs[i] = ' ';
1110                 psinfo.pr_psargs[len] = 0;
1111 
1112                 set_fs(KERNEL_DS);
1113         }
1114         strncpy(psinfo.pr_fname, current->comm, sizeof(psinfo.pr_fname));
1115 
1116         notes[2].name = "CORE";
1117         notes[2].type = NT_TASKSTRUCT;
1118         notes[2].datasz = sizeof(*current);
1119         notes[2].data = current;
1120         
1121         /* Try to dump the fpu. */
1122         prstatus.pr_fpvalid = dump_fpu (&fpu);
1123         if (!prstatus.pr_fpvalid)
1124         {
1125                 numnote--;
1126         }
1127         else
1128         {
1129                 notes[3].name = "CORE";
1130                 notes[3].type = NT_PRFPREG;
1131                 notes[3].datasz = sizeof(fpu);
1132                 notes[3].data = &fpu;
1133         }
1134         
1135         /* Write notes phdr entry */
1136         {
1137                 struct elf_phdr phdr;
1138                 int sz = 0;
1139 
1140                 for(i = 0; i < numnote; i++)
1141                         sz += notesize(&notes[i]);
1142                 
1143                 phdr.p_type = PT_NOTE;
1144                 phdr.p_offset = offset;
1145                 phdr.p_vaddr = 0;
1146                 phdr.p_paddr = 0;
1147                 phdr.p_filesz = sz;
1148                 phdr.p_memsz = 0;
1149                 phdr.p_flags = 0;
1150                 phdr.p_align = 0;
1151 
1152                 offset += phdr.p_filesz;
1153                 DUMP_WRITE(&phdr, sizeof(phdr));
1154         }
1155 
1156         /* Page-align dumped data */
1157         dataoff = offset = roundup(offset, PAGE_SIZE);
1158         
1159         /* Write program headers for segments dump */
1160         for(vma = current->mm->mmap, i = 0;
1161                 i < segs && vma != NULL; vma = vma->vm_next) {
1162                 struct elf_phdr phdr;
1163                 size_t sz;
1164 
1165                 if (!maydump(vma))
1166                         continue;
1167                 i++;
1168 
1169                 sz = vma->vm_end - vma->vm_start;
1170                 
1171                 phdr.p_type = PT_LOAD;
1172                 phdr.p_offset = offset;
1173                 phdr.p_vaddr = vma->vm_start;
1174                 phdr.p_paddr = 0;
1175                 phdr.p_filesz = sz;
1176                 phdr.p_memsz = sz;
1177                 offset += sz;
1178                 phdr.p_flags = vma->vm_flags & VM_READ ? PF_R : 0;
1179                 if (vma->vm_flags & VM_WRITE) phdr.p_flags |= PF_W;
1180                 if (vma->vm_flags & VM_EXEC) phdr.p_flags |= PF_X;
1181                 phdr.p_align = PAGE_SIZE;
1182 
1183                 DUMP_WRITE(&phdr, sizeof(phdr));
1184         }
1185 
1186         for(i = 0; i < numnote; i++)
1187                 if (!writenote(&notes[i], &file))
1188                         goto close_coredump;
1189         
1190         set_fs(fs);
1191 
1192         DUMP_SEEK(dataoff);
1193         
1194         for(i = 0, vma = current->mm->mmap;
1195             i < segs && vma != NULL;
1196             vma = vma->vm_next) {
1197                 unsigned long addr = vma->vm_start;
1198                 unsigned long len = vma->vm_end - vma->vm_start;
1199                 
1200                 if (!maydump(vma))
1201                         continue;
1202                 i++;
1203 #ifdef DEBUG
1204                 printk("elf_core_dump: writing %08lx %lx\n", addr, len);
1205 #endif
1206                 DUMP_WRITE((void *)addr, len);
1207         }
1208 
1209         if ((off_t) file.f_pos != offset) {
1210                 /* Sanity check */
1211                 printk("elf_core_dump: file.f_pos (%ld) != offset (%ld)\n",
1212                        (off_t) file.f_pos, offset);
1213         }
1214 
1215  close_coredump:
1216         if (file.f_op->release)
1217                 file.f_op->release(inode,&file);
1218 
1219  end_coredump:
1220         set_fs(fs);
1221         iput(inode);
1222 #ifndef CONFIG_BINFMT_ELF
1223         MOD_DEC_USE_COUNT;
1224 #endif
1225         return has_dumped;
1226 }
1227 
1228 #ifdef MODULE
1229 
1230 int init_module(void) {
     /* [previous][next][first][last][top][bottom][index][help] */
1231         /* Install the COFF, ELF and XOUT loaders.
1232          * N.B. We *rely* on the table being the right size with the
1233          * right number of free slots...
1234          */
1235         return register_binfmt(&elf_format);
1236 }
1237 
1238 
1239 void cleanup_module( void) {
     /* [previous][next][first][last][top][bottom][index][help] */
1240         /* Remove the COFF and ELF loaders. */
1241         unregister_binfmt(&elf_format);
1242 }
1243 #endif

/* [previous][next][first][last][top][bottom][index][help] */