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

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