static unsigned long get_mmap_base(elf_bin_t *elf) { unsigned long addr, pg_start, pg_end, mmap_min = ULONG_MAX, mmap_max = 0; int i; for (i=0; i<elf->hdr.e_phnum; i++) if ( elf->phdr[i].p_type == PT_LOAD) { pg_start = PAGE_BASE(elf->phdr[i].p_vaddr); pg_end = PAGE_NEXT(elf->phdr[i].p_vaddr + elf->phdr[i].p_memsz); if (pg_start < mmap_min) mmap_min = pg_start; if (pg_end > mmap_max) mmap_max = pg_end; } if (mmap_min > mmap_max) mmap_min = mmap_max; addr = do_mmap2(mmap_min, mmap_max-mmap_min, PROT_NONE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); if (addr & PG_MASK) /* not on page boundary -> error code */ return addr; sys_munmap(addr, mmap_max-mmap_min); return addr-mmap_min; }
/* * mmap2() is like mmap() except that the offset is expressed in units * of PAGE_SIZE (instead of bytes). This allows to mmap2() (pieces * of) files that are larger than the address space of the CPU. */ asmlinkage unsigned long sys_mmap2 (unsigned long addr, unsigned long len, int prot, int flags, int fd, long pgoff) { addr = do_mmap2(addr, len, prot, flags, fd, pgoff); if (!IS_ERR((void *) addr)) force_successful_syscall_return(); return addr; }
static int alloc_user_stack(elf_prog_t *prog, int prot) { long err = do_mmap2(prog->task_size-prog->stack_size, prog->stack_size,prot, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0); if (err & PG_MASK) return -1; return 0; }
asmlinkage long sys_mmap2(struct mmap_arg_struct *arg) { struct mmap_arg_struct a; int error = -EFAULT; if (copy_from_user(&a, arg, sizeof(a))) goto out; error = do_mmap2(a.addr, a.len, a.prot, a.flags, a.fd, a.offset); out: return error; }
/* * mmap2() is like mmap() except that the offset is expressed in units * of PAGE_SIZE (instead of bytes). This allows to mmap2() (pieces * of) files that are larger than the address space of the CPU. */ asmlinkage unsigned long sys_mmap2 (unsigned long addr, unsigned long len, int prot, int flags, int fd, long pgoff, long arg6, long arg7, long stack) { struct pt_regs *regs = (struct pt_regs *) &stack; addr = do_mmap2(addr, len, prot, flags, fd, pgoff); if (!IS_ERR((void *) addr)) regs->r8 = 0; /* ensure large addresses are not mistaken as failures... */ return addr; }
static long zerofill(unsigned long start, unsigned long end, int prot) { unsigned long pg_start = PAGE_NEXT(start), pg_end = PAGE_NEXT(end), padd_len = pg_start-start; if (start > end) return -1; if (prot & PROT_WRITE) memset((void *)start, 0, padd_len); return do_mmap2(pg_start, pg_end-pg_start, prot, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0); }
static long mmap_prog_section(elf_bin_t *elf, Elf32_Phdr *p) { unsigned long base = elf->base, brk_, bss, addr, pg_off, size; int prot = 0; if (p->p_flags & PF_R) prot |= PROT_READ; if (p->p_flags & PF_W) prot |= PROT_WRITE; if (p->p_flags & PF_X) prot |= PROT_EXEC; addr = PAGE_BASE(base+p->p_vaddr); size = PAGE_NEXT(base+p->p_vaddr + p->p_filesz) - addr; pg_off = p->p_offset/PG_SIZE; bss = base + p->p_vaddr + p->p_filesz; brk_ = base + p->p_vaddr + p->p_memsz; if ( ((p->p_vaddr-p->p_offset) & PG_MASK) || (bss > brk_) ) return -1; addr = do_mmap2(addr, size, prot, MAP_PRIVATE|MAP_FIXED, elf->fd, pg_off); if (addr & PG_MASK) /* not on page boundary -> error code */ return addr; if (elf->brk < brk_) elf->brk = brk_; if (elf->bss < bss) elf->bss = bss; /* linux does not fill in bss sections * between load segments for interpreters; * makes no difference to the standard ld.so */ addr = zerofill(bss, brk_, prot); if (addr & PG_MASK) /* not on page boundary -> error code */ return addr; return 0; }
asmlinkage long sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long pgoff) { return do_mmap2(addr, len, prot, flags, fd, pgoff); }
long sys_mmap2(unsigned long addr, unsigned long len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long pgoff) { return do_mmap2(current->mm, addr, len, prot, flags, fd, pgoff); }
unsigned long sys_mmap2(unsigned long addr, size_t len, unsigned long prot, unsigned long flags, unsigned long fd, unsigned long pgoff) { return do_mmap2(addr, len, prot, flags, fd, pgoff); }