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

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