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

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