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

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