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

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