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

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