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

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