|
From: <sv...@va...> - 2005-06-21 22:47:56
|
Author: njn
Date: 2005-06-21 23:47:54 +0100 (Tue, 21 Jun 2005)
New Revision: 3992
Log:
Rename ume.c/ume.h as m_ume.c/pub_core_ume.h to be consistent with=20
all the other modules.
Added:
trunk/coregrind/m_ume.c
trunk/coregrind/pub_core_ume.h
Removed:
trunk/coregrind/ume.c
trunk/coregrind/ume.h
Modified:
trunk/coregrind/Makefile.am
trunk/coregrind/m_main.c
trunk/coregrind/stage1.c
Modified: trunk/coregrind/Makefile.am
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/Makefile.am 2005-06-21 22:27:19 UTC (rev 3991)
+++ trunk/coregrind/Makefile.am 2005-06-21 22:47:54 UTC (rev 3992)
@@ -72,7 +72,7 @@
pub_core_translate.h \
pub_core_transtab.h \
pub_core_transtab_asm.h \
- ume.h \
+ pub_core_ume.h \
vki_unistd.h \
vki_unistd-amd64-linux.h\
vki_unistd-arm-linux.h \
@@ -87,10 +87,9 @@
CLEANFILES =3D stage2.lds
=09
valgrind_SOURCES =3D \
- ume.c \
- \
stage1.c \
- m_debuglog.c
+ m_debuglog.c \
+ m_ume.c
valgrind_DEPENDENCIES =3D
valgrind_LDFLAGS=3D-static -g
valgrind_LDADD=3D
@@ -126,8 +125,7 @@
m_trampoline.S \
m_translate.c \
m_transtab.c \
- \
- ume.c
+ m_ume.c
=20
## Nb: libscheduler.a must precede libdispatch.a in this list.
stage2_extra=3D \
Modified: trunk/coregrind/m_main.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/m_main.c 2005-06-21 22:27:19 UTC (rev 3991)
+++ trunk/coregrind/m_main.c 2005-06-21 22:47:54 UTC (rev 3992)
@@ -56,7 +56,7 @@
#include "pub_core_tooliface.h"
#include "pub_core_trampoline.h"
#include "pub_core_transtab.h"
-#include "ume.h"
+#include "pub_core_ume.h"
=20
#include <dirent.h>
#include <dlfcn.h>
Copied: trunk/coregrind/m_ume.c (from rev 3989, trunk/coregrind/ume.c)
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/ume.c 2005-06-21 13:26:17 UTC (rev 3989)
+++ trunk/coregrind/m_ume.c 2005-06-21 22:47:54 UTC (rev 3992)
@@ -0,0 +1,747 @@
+
+/*--------------------------------------------------------------------*/
+/*--- User-mode execve(), and other stuff shared between stage1 ---*/
+/*--- and stage2. m_ume.c ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2000-2005 Julian Seward=20
+ js...@ac...
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+
+#define _GNU_SOURCE
+#define _FILE_OFFSET_BITS 64
+
+// It seems that on SuSE 9.1 (x86) something in <fcntl.h> messes up stuf=
f
+// acquired indirectly from vki-x86-linux.h. Therefore our headers must=
be
+// included ahead of the glibc ones. This fix is a kludge; the right
+// solution is to entirely remove the glibc dependency.
+#include "pub_core_basics.h"
+#include "pub_core_libcbase.h"
+#include "pub_core_machine.h"
+#include "pub_core_ume.h"
+
+#include <sys/mman.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <assert.h>
+
+#if VG_WORDSIZE =3D=3D 8
+#define ESZ(x) Elf64_##x
+#elif VG_WORDSIZE =3D=3D 4
+#define ESZ(x) Elf32_##x
+#else
+#error VG_WORDSIZE needs to =3D=3D4 or =3D=3D8
+#endif
+
+struct elfinfo
+{
+ ESZ(Ehdr) e;
+ ESZ(Phdr) *p;
+ int fd;
+};
+
+static void check_mmap(void* res, void* base, int len)
+{
+ if ((void*)-1 =3D=3D res) {
+ fprintf(stderr, "valgrind: mmap(%p, %d) failed in UME.\n", base, l=
en);
+ exit(1);
+ }
+}
+
+// 'extra' allows the caller to pass in extra args to 'fn', like free
+// variables to a closure.
+void foreach_map(int (*fn)(char *start, char *end,
+ const char *perm, off_t offset,
+ int maj, int min, int ino, void* extra),
+ void* extra)
+{
+ static char buf[10240];
+ char *bufptr =3D buf;
+ int ret, fd;
+
+ fd =3D open("/proc/self/maps", O_RDONLY);
+
+ if (fd =3D=3D -1) {
+ perror("open /proc/self/maps");
+ return;
+ }
+
+ ret =3D read(fd, buf, sizeof(buf));
+
+ if (ret =3D=3D -1) {
+ perror("read /proc/self/maps");
+ close(fd);
+ return;
+ }
+ close(fd);
+
+ if (ret =3D=3D sizeof(buf)) {
+ fprintf(stderr, "buf too small\n");
+ return;
+ }
+
+ while(bufptr && bufptr < buf+ret) {
+ char perm[5];
+ ULong offset;
+ int maj, min;
+ int ino;
+ void *segstart, *segend;
+
+ sscanf(bufptr, "%p-%p %s %llx %x:%x %d",
+ &segstart, &segend, perm, &offset, &maj, &min, &ino);
+ bufptr =3D strchr(bufptr, '\n');
+ if (bufptr !=3D NULL)
+ bufptr++; /* skip \n */
+
+ if (!(*fn)(segstart, segend, perm, offset, maj, min, ino, extra))
+ break;
+ }
+}
+
+/*------------------------------------------------------------*/
+/*--- Stack switching ---*/
+/*------------------------------------------------------------*/
+
+// __attribute__((noreturn))
+// void jump_and_switch_stacks ( Addr stack, Addr dst );
+#if defined(VGA_x86)
+// 4(%esp) =3D=3D stack
+// 8(%esp) =3D=3D dst
+asm(
+".global jump_and_switch_stacks\n"
+"jump_and_switch_stacks:\n"
+" movl %esp, %esi\n" // remember old stack pointer
+" movl 4(%esi), %esp\n" // set stack
+" pushl 8(%esi)\n" // dst to stack
+" movl $0, %eax\n" // zero all GP regs
+" movl $0, %ebx\n"
+" movl $0, %ecx\n"
+" movl $0, %edx\n"
+" movl $0, %esi\n"
+" movl $0, %edi\n"
+" movl $0, %ebp\n"
+" ret\n" // jump to dst
+" ud2\n" // should never get here
+);
+#elif defined(VGA_amd64)
+// %rdi =3D=3D stack
+// %rsi =3D=3D dst
+asm(
+".global jump_and_switch_stacks\n"
+"jump_and_switch_stacks:\n"
+" movq %rdi, %rsp\n" // set stack
+" pushq %rsi\n" // dst to stack
+" movq $0, %rax\n" // zero all GP regs
+" movq $0, %rbx\n"
+" movq $0, %rcx\n"
+" movq $0, %rdx\n"
+" movq $0, %rsi\n"
+" movq $0, %rdi\n"
+" movq $0, %rbp\n"
+" movq $0, %r8\n"\
+" movq $0, %r9\n"\
+" movq $0, %r10\n"
+" movq $0, %r11\n"
+" movq $0, %r12\n"
+" movq $0, %r13\n"
+" movq $0, %r14\n"
+" movq $0, %r15\n"
+" ret\n" // jump to dst
+" ud2\n" // should never get here
+);
+
+#elif defined(VGA_ppc32)
+/* Jump to 'dst', but first set the stack pointer to 'stack'. Also,
+ clear all the integer registers before entering 'dst'. It's
+ important that the stack pointer is set to exactly 'stack' and not
+ (eg) stack - apparently_harmless_looking_small_offset. Basically
+ because the code at 'dst' might be wanting to scan the area above
+ 'stack' (viz, the auxv array), and putting spurious words on the
+ stack confuses it.
+*/
+// %r3 =3D=3D stack
+// %r4 =3D=3D dst
+asm(
+".global jump_and_switch_stacks\n"
+"jump_and_switch_stacks:\n"
+" mtctr %r4\n\t" // dst to %ctr
+" mr %r1,%r3\n\t" // stack to %sp
+" li 0,0\n\t" // zero all GP regs
+" li 3,0\n\t"
+" li 4,0\n\t"
+" li 5,0\n\t"
+" li 6,0\n\t"
+" li 7,0\n\t"
+" li 8,0\n\t"
+" li 9,0\n\t"
+" li 10,0\n\t"
+" li 11,0\n\t"
+" li 12,0\n\t"
+" li 13,0\n\t" // CAB: This right? r13 =3D small data area p=
tr
+" li 14,0\n\t"
+" li 15,0\n\t"
+" li 16,0\n\t"
+" li 17,0\n\t"
+" li 18,0\n\t"
+" li 19,0\n\t"
+" li 20,0\n\t"
+" li 21,0\n\t"
+" li 22,0\n\t"
+" li 23,0\n\t"
+" li 24,0\n\t"
+" li 25,0\n\t"
+" li 26,0\n\t"
+" li 27,0\n\t"
+" li 28,0\n\t"
+" li 29,0\n\t"
+" li 30,0\n\t"
+" li 31,0\n\t"
+" mtxer 0\n\t"
+" mtcr 0\n\t"
+" mtlr %r0\n\t"
+" bctr\n\t" // jump to dst
+" trap\n" // should never get here
+);
+
+#else
+# error Unknown architecture
+#endif
+
+/*------------------------------------------------------------*/
+/*--- Finding auxv on the stack ---*/
+/*------------------------------------------------------------*/
+
+struct ume_auxv *find_auxv(UWord* sp)
+{
+ sp++; // skip argc (Nb: is word-sized, not int-sized!)
+
+ while (*sp !=3D 0) // skip argv
+ sp++;
+ sp++;
+
+ while (*sp !=3D 0) // skip env
+ sp++;
+ sp++;
+ =20
+#if defined(VGA_ppc32)
+# if defined AT_IGNOREPPC
+ while (*sp =3D=3D AT_IGNOREPPC) // skip AT_IGNOREPPC entries
+ sp +=3D 2;
+# endif
+#endif
+
+ return (struct ume_auxv *)sp;
+}
+
+/*------------------------------------------------------------*/
+/*--- Loading ELF files ---*/
+/*------------------------------------------------------------*/
+
+static=20
+struct elfinfo *readelf(int fd, const char *filename)
+{
+ struct elfinfo *e =3D malloc(sizeof(*e));
+ int phsz;
+
+ assert(e);
+ e->fd =3D fd;
+
+ if (pread(fd, &e->e, sizeof(e->e), 0) !=3D sizeof(e->e)) {
+ fprintf(stderr, "valgrind: %s: can't read ELF header: %s\n",=20
+ filename, strerror(errno));
+ return NULL;
+ }
+
+ if (memcmp(&e->e.e_ident[0], ELFMAG, SELFMAG) !=3D 0) {
+ fprintf(stderr, "valgrind: %s: bad ELF magic number\n", filename);
+ return NULL;
+ }
+ if (e->e.e_ident[EI_CLASS] !=3D VGA_ELF_CLASS) {
+ fprintf(stderr,=20
+ "valgrind: wrong ELF executable class "
+ "(eg. 32-bit instead of 64-bit)\n");
+ return NULL;
+ }
+ if (e->e.e_ident[EI_DATA] !=3D VGA_ELF_ENDIANNESS) {
+ fprintf(stderr, "valgrind: executable has wrong endian-ness\n");
+ return NULL;
+ }
+ if (!(e->e.e_type =3D=3D ET_EXEC || e->e.e_type =3D=3D ET_DYN)) {
+ fprintf(stderr, "valgrind: this is not an executable\n");
+ return NULL;
+ }
+
+ if (e->e.e_machine !=3D VGA_ELF_MACHINE) {
+ fprintf(stderr, "valgrind: executable is not for "
+ "this architecture\n");
+ return NULL;
+ }
+
+ if (e->e.e_phentsize !=3D sizeof(ESZ(Phdr))) {
+ fprintf(stderr, "valgrind: sizeof ELF Phdr wrong\n");
+ return NULL;
+ }
+
+ phsz =3D sizeof(ESZ(Phdr)) * e->e.e_phnum;
+ e->p =3D malloc(phsz);
+ assert(e->p);
+
+ if (pread(fd, e->p, phsz, e->e.e_phoff) !=3D phsz) {
+ fprintf(stderr, "valgrind: can't read phdr: %s\n", strerror(errno)=
);
+ return NULL;
+ }
+
+ return e;
+}
+
+/* Map an ELF file. Returns the brk address. */
+static
+ESZ(Addr) mapelf(struct elfinfo *e, ESZ(Addr) base)
+{
+ int i;
+ void* res;
+ ESZ(Addr) elfbrk =3D 0;
+
+ for(i =3D 0; i < e->e.e_phnum; i++) {
+ ESZ(Phdr) *ph =3D &e->p[i];
+ ESZ(Addr) addr, brkaddr;
+ ESZ(Word) memsz;
+
+ if (ph->p_type !=3D PT_LOAD)
+ continue;
+
+ addr =3D ph->p_vaddr+base;
+ memsz =3D ph->p_memsz;
+ brkaddr =3D addr+memsz;
+
+ if (brkaddr > elfbrk)
+ elfbrk =3D brkaddr;
+ }
+
+ for(i =3D 0; i < e->e.e_phnum; i++) {
+ ESZ(Phdr) *ph =3D &e->p[i];
+ ESZ(Addr) addr, bss, brkaddr;
+ ESZ(Off) off;
+ ESZ(Word) filesz;
+ ESZ(Word) memsz;
+ unsigned prot =3D 0;
+
+ if (ph->p_type !=3D PT_LOAD)
+ continue;
+
+ if (ph->p_flags & PF_X) prot |=3D PROT_EXEC;
+ if (ph->p_flags & PF_W) prot |=3D PROT_WRITE;
+ if (ph->p_flags & PF_R) prot |=3D PROT_READ;
+
+ addr =3D ph->p_vaddr+base;
+ off =3D ph->p_offset;
+ filesz =3D ph->p_filesz;
+ bss =3D addr+filesz;
+ memsz =3D ph->p_memsz;
+ brkaddr =3D addr+memsz;
+
+ // Tom says: In the following, do what the Linux kernel does and o=
nly
+ // map the pages that are required instead of rounding everything =
to
+ // the specified alignment (ph->p_align). (AMD64 doesn't work if =
you
+ // use ph->p_align -- part of stage2's memory gets trashed somehow=
.)
+ //
+ // The condition handles the case of a zero-length segment.
+ if (VG_PGROUNDUP(bss)-VG_PGROUNDDN(addr) > 0) {
+ res =3D mmap((char *)VG_PGROUNDDN(addr),
+ VG_PGROUNDUP(bss)-VG_PGROUNDDN(addr),
+ prot, MAP_FIXED|MAP_PRIVATE, e->fd, VG_PGROUNDDN(off=
));
+ check_mmap(res, (char*)VG_PGROUNDDN(addr),
+ VG_PGROUNDUP(bss)-VG_PGROUNDDN(addr));
+ }
+
+ // if memsz > filesz, fill the remainder with zeroed pages
+ if (memsz > filesz) {
+ UInt bytes;
+
+ bytes =3D VG_PGROUNDUP(brkaddr)-VG_PGROUNDUP(bss);
+ if (bytes > 0) {
+ res =3D mmap((char *)VG_PGROUNDUP(bss), bytes,
+ prot, MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
+ check_mmap(res, (char*)VG_PGROUNDUP(bss), bytes);
+ }
+
+ bytes =3D bss & (VKI_PAGE_SIZE - 1);
+
+ // The 'prot' condition allows for a read-only bss
+ if ((prot & PROT_WRITE) && (bytes > 0)) {
+ bytes =3D VKI_PAGE_SIZE - bytes;
+ memset((char *)bss, 0, bytes);
+ }
+ }
+ }
+
+ return elfbrk;
+}
+
+// Forward declaration.
+static int do_exec_inner(const char *exe, struct exeinfo *info);
+
+static int match_ELF(const char *hdr, int len)
+{
+ ESZ(Ehdr) *e =3D (ESZ(Ehdr) *)hdr;
+ return (len > sizeof(*e)) && memcmp(&e->e_ident[0], ELFMAG, SELFMAG) =
=3D=3D 0;
+}
+
+static int load_ELF(char *hdr, int len, int fd, const char *name,
+ struct exeinfo *info)
+{
+ struct elfinfo *e;
+ struct elfinfo *interp =3D NULL;
+ ESZ(Addr) minaddr =3D ~0; /* lowest mapped address */
+ ESZ(Addr) maxaddr =3D 0; /* highest mapped address */
+ ESZ(Addr) interp_addr =3D 0; /* interpreter (ld.so) address */
+ ESZ(Word) interp_size =3D 0; /* interpreter size */
+ ESZ(Word) interp_align =3D VKI_PAGE_SIZE;
+ int i;
+ void *entry;
+ ESZ(Addr) ebase =3D 0;
+
+#ifdef HAVE_PIE
+ ebase =3D info->exe_base;
+#endif
+
+ e =3D readelf(fd, name);
+
+ if (e =3D=3D NULL)
+ return ENOEXEC;
+
+ info->phnum =3D e->e.e_phnum;
+ info->entry =3D e->e.e_entry + ebase;
+ info->phdr =3D 0;
+
+ for(i =3D 0; i < e->e.e_phnum; i++) {
+ ESZ(Phdr) *ph =3D &e->p[i];
+
+ switch(ph->p_type) {
+ case PT_PHDR:
+ info->phdr =3D ph->p_vaddr + ebase;
+ break;
+
+ case PT_LOAD:
+ if (ph->p_vaddr < minaddr)
+ minaddr =3D ph->p_vaddr;
+ if (ph->p_vaddr+ph->p_memsz > maxaddr)
+ maxaddr =3D ph->p_vaddr+ph->p_memsz;
+ break;
+ =09
+ case PT_INTERP: {
+ char *buf =3D malloc(ph->p_filesz+1);
+ int j;
+ int intfd;
+ int baseaddr_set;
+
+ assert(buf);
+ pread(fd, buf, ph->p_filesz, ph->p_offset);
+ buf[ph->p_filesz] =3D '\0';
+
+ intfd =3D open(buf, O_RDONLY);
+ if (intfd =3D=3D -1) {
+ perror("open interp");
+ exit(1);
+ }
+
+ interp =3D readelf(intfd, buf);
+ if (interp =3D=3D NULL) {
+ fprintf(stderr, "Can't read interpreter\n");
+ return 1;
+ }
+ free(buf);
+
+ baseaddr_set =3D 0;
+ for(j =3D 0; j < interp->e.e_phnum; j++) {
+ ESZ(Phdr) *iph =3D &interp->p[j];
+ ESZ(Addr) end;
+
+ if (iph->p_type !=3D PT_LOAD)
+ continue;
+ =20
+ if (!baseaddr_set) {
+ interp_addr =3D iph->p_vaddr;
+ interp_align =3D iph->p_align;
+ baseaddr_set =3D 1;
+ }
+
+ /* assumes that all segments in the interp are close */
+ end =3D (iph->p_vaddr - interp_addr) + iph->p_memsz;
+
+ if (end > interp_size)
+ interp_size =3D end;
+ }
+ break;
+
+ default:
+ // do nothing
+ break;
+ }
+ }
+ }
+
+ if (info->phdr =3D=3D 0)
+ info->phdr =3D minaddr + e->e.e_phoff;
+
+ if (info->exe_base !=3D info->exe_end) {
+ if (minaddr >=3D maxaddr ||
+ (minaddr + ebase < info->exe_base ||
+ maxaddr + ebase > info->exe_end)) {
+ fprintf(stderr, "Executable range %p-%p is outside the\n"
+ "acceptable range %p-%p\n",
+ (void *)minaddr + ebase, (void *)maxaddr + ebase,
+ (void *)info->exe_base, (void *)info->exe_end);
+ return ENOMEM;
+ }
+ }
+
+ info->brkbase =3D mapelf(e, ebase); /* map the executable */
+
+ if (info->brkbase =3D=3D 0)
+ return ENOMEM;
+
+ if (interp !=3D NULL) {
+ /* reserve a chunk of address space for interpreter */
+ void* res;
+ char* base =3D (char *)info->exe_base;
+ char* baseoff;
+ int flags =3D MAP_PRIVATE|MAP_ANONYMOUS;
+
+ if (info->map_base !=3D 0) {
+ base =3D (char *)VG_ROUNDUP(info->map_base, interp_align);
+ flags |=3D MAP_FIXED;
+ }
+
+ res =3D mmap(base, interp_size, PROT_NONE, flags, -1, 0);
+ check_mmap(res, base, interp_size);
+ base =3D res;
+
+ baseoff =3D base - interp_addr;
+
+ mapelf(interp, (ESZ(Addr))baseoff);
+
+ close(interp->fd);
+
+ entry =3D baseoff + interp->e.e_entry;
+ info->interp_base =3D (ESZ(Addr))base;
+
+ free(interp->p);
+ free(interp);
+ } else
+ entry =3D (void *)e->e.e_entry;
+
+ info->exe_base =3D minaddr + ebase;
+ info->exe_end =3D maxaddr + ebase;
+
+ info->init_eip =3D (Addr)entry;
+
+ free(e->p);
+ free(e);
+
+ return 0;
+}
+
+
+static int match_script(const char *hdr, Int len)
+{
+ return (len > 2) && memcmp(hdr, "#!", 2) =3D=3D 0;
+}
+
+static int load_script(char *hdr, int len, int fd, const char *name,
+ struct exeinfo *info)
+{
+ char *interp;
+ char *const end =3D hdr+len;
+ char *cp;
+ char *arg =3D NULL;
+ int eol;
+
+ interp =3D hdr + 2;
+ while(interp < end && (*interp =3D=3D ' ' || *interp =3D=3D '\t'))
+ interp++;
+
+ if (*interp !=3D '/')
+ return ENOEXEC; /* absolute path only for interpreter */
+
+ /* skip over interpreter name */
+ for(cp =3D interp; cp < end && *cp !=3D ' ' && *cp !=3D '\t' && *cp !=
=3D '\n'; cp++)
+ ;
+
+ eol =3D (*cp =3D=3D '\n');
+
+ *cp++ =3D '\0';
+
+ if (!eol && cp < end) {
+ /* skip space before arg */
+ while (cp < end && (*cp =3D=3D '\t' || *cp =3D=3D ' '))
+ cp++;
+
+ /* arg is from here to eol */
+ arg =3D cp;
+ while (cp < end && *cp !=3D '\n')
+ cp++;
+ *cp =3D '\0';
+ }
+ =20
+ info->interp_name =3D strdup(interp);
+ assert(NULL !=3D info->interp_name);
+ if (arg !=3D NULL && *arg !=3D '\0') {
+ info->interp_args =3D strdup(arg);
+ assert(NULL !=3D info->interp_args);
+ }
+
+ if (info->argv && info->argv[0] !=3D NULL)
+ info->argv[0] =3D (char *)name;
+
+ if (0)
+ printf("#! script: interp_name=3D\"%s\" interp_args=3D\"%s\"\n",
+ info->interp_name, info->interp_args);
+
+ return do_exec_inner(interp, info);
+}
+
+/*=20
+ Emulate the normal Unix permissions checking algorithm.
+
+ If owner matches, then use the owner permissions, else
+ if group matches, then use the group permissions, else
+ use other permissions.
+
+ Note that we can't deal with SUID/SGID, so we refuse to run them
+ (otherwise the executable may misbehave if it doesn't have the
+ permissions it thinks it does).
+*/
+static int check_perms(int fd)
+{
+ struct stat st;
+
+ if (fstat(fd, &st) =3D=3D -1)=20
+ return errno;
+
+ if (st.st_mode & (S_ISUID | S_ISGID)) {
+ //fprintf(stderr, "Can't execute suid/sgid executable %s\n", exe);
+ return EACCES;
+ }
+
+ if (geteuid() =3D=3D st.st_uid) {
+ if (!(st.st_mode & S_IXUSR))
+ return EACCES;
+ } else {
+ int grpmatch =3D 0;
+
+ if (getegid() =3D=3D st.st_gid)
+ grpmatch =3D 1;
+ else {
+ gid_t groups[32];
+ int ngrp =3D getgroups(32, groups);
+ int i;
+
+ for(i =3D 0; i < ngrp; i++)
+ if (groups[i] =3D=3D st.st_gid) {
+ grpmatch =3D 1;
+ break;
+ }
+ }
+
+ if (grpmatch) {
+ if (!(st.st_mode & S_IXGRP))
+ return EACCES;
+ } else if (!(st.st_mode & S_IXOTH))
+ return EACCES;
+ }
+
+ return 0;
+}
+
+static int do_exec_inner(const char *exe, struct exeinfo *info)
+{
+ int fd;
+ int err;
+ char buf[VKI_PAGE_SIZE];
+ int bufsz;
+ int i;
+ int ret;
+ static const struct {
+ int (*match)(const char *hdr, int len);
+ int (*load) ( char *hdr, int len, int fd2, const char *name,
+ struct exeinfo *);
+ } formats[] =3D {
+ { match_ELF, load_ELF },
+ { match_script, load_script },
+ };
+
+ fd =3D open(exe, O_RDONLY);
+ if (fd =3D=3D -1) {
+ if (0)
+ fprintf(stderr, "Can't open executable %s: %s\n",
+ exe, strerror(errno));
+ return errno;
+ }
+
+ err =3D check_perms(fd);
+ if (err !=3D 0) {
+ close(fd);
+ return err;
+ }
+
+ bufsz =3D pread(fd, buf, sizeof(buf), 0);
+ if (bufsz < 0) {
+ fprintf(stderr, "Can't read executable header: %s\n",
+ strerror(errno));
+ close(fd);
+ return errno;
+ }
+
+ ret =3D ENOEXEC;
+ for(i =3D 0; i < sizeof(formats)/sizeof(*formats); i++) {
+ if ((formats[i].match)(buf, bufsz)) {
+ ret =3D (formats[i].load)(buf, bufsz, fd, exe, info);
+ break;
+ }
+ }
+
+ close(fd);
+
+ return ret;
+}
+
+// See ume.h for an indication of which entries of 'info' are inputs, wh=
ich
+// are outputs, and which are both.
+int do_exec(const char *exe, struct exeinfo *info)
+{
+ info->interp_name =3D NULL;
+ info->interp_args =3D NULL;
+
+ return do_exec_inner(exe, info);
+}
+
+/*--------------------------------------------------------------------*/
+/*--- end ---*/
+/*--------------------------------------------------------------------*/
Copied: trunk/coregrind/pub_core_ume.h (from rev 3989, trunk/coregrind/um=
e.h)
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/ume.h 2005-06-21 13:26:17 UTC (rev 3989)
+++ trunk/coregrind/pub_core_ume.h 2005-06-21 22:47:54 UTC (rev 3992)
@@ -0,0 +1,123 @@
+
+/*--------------------------------------------------------------------*/
+/*--- User-mode execve. pub_core_ume.h ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
+ framework.
+
+ Copyright (C) 2000-2005 Julian Seward=20
+ js...@ac...
+
+ This program is free software; you can redistribute it and/or
+ modify it under the terms of the GNU General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful, but
+ WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307, USA.
+
+ The GNU General Public License is contained in the file COPYING.
+*/
+
+#ifndef __PUB_CORE_UME_H
+#define __PUB_CORE_UME_H
+
+//--------------------------------------------------------------------
+// PURPOSE: This module implements user-mode execve, ie. program loading
+// and exec'ing. It is shared between stage1 and stage2.
+//--------------------------------------------------------------------
+
+#include <elf.h>
+#include <sys/types.h>
+
+/*------------------------------------------------------------*/
+/*--- General stuff ---*/
+/*------------------------------------------------------------*/
+
+/* This is only here so it can be shared between stage1 and stage2 */
+extern
+void foreach_map(int (*fn)(char *start, char *end,
+ const char *perm, off_t offset,
+ int maj, int min, int ino, void* extra),
+ void* extra);
+
+/* Jump to 'dst', but first set the stack pointer to 'stack'. Also,
+ clear all the integer registers before entering 'dst'. It's
+ important that the stack pointer is set to exactly 'stack' and not
+ (eg) stack - apparently_harmless_looking_small_offset. Basically
+ because the code at 'dst' might be wanting to scan the area above
+ 'stack' (viz, the auxv array), and putting spurious words on the
+ stack confuses it.
+
+ This is only exported so that vgtest_ume.c can use it.
+*/
+extern
+__attribute__((noreturn))
+void jump_and_switch_stacks ( Addr stack, Addr dst );
+
+
+/*------------------------------------------------------------*/
+/*--- Loading ELF files ---*/
+/*------------------------------------------------------------*/
+
+// Info needed to load and run a program. IN/INOUT/OUT refers to the
+// inputs/outputs of do_exec().
+struct exeinfo
+{
+ Addr map_base; // IN: if non-zero, base address of mappings
+ char** argv; // IN: the original argv
+
+ Addr exe_base; // INOUT: lowest (allowed) address of exe
+ Addr exe_end; // INOUT: highest (allowed) address
+
+ Addr phdr; // OUT: address phdr was mapped at
+ int phnum; // OUT: number of phdrs
+ Addr interp_base; // OUT: where interpreter (ld.so) was mapped
+ Addr entry; // OUT: entrypoint in main executable
+ Addr init_eip; // OUT: initial eip
+ Addr brkbase; // OUT: base address of brk segment
+
+ // These are the extra args added by #! scripts
+ char* interp_name; // OUT: the interpreter name
+ char* interp_args; // OUT: the args for the interpreter
+};
+
+// Does everything short of actually running 'exe': finds the file,
+// checks execute permissions, sets up interpreter if program is a scrip=
t,=20
+// reads headers, maps file into memory, and returns important info abou=
t
+// the program.
+extern int do_exec(const char *exe, struct exeinfo *info);
+
+/*------------------------------------------------------------*/
+/*--- Finding and dealing with auxv ---*/
+/*------------------------------------------------------------*/
+
+struct ume_auxv
+{
+ Word a_type;
+ union {
+ void *a_ptr;
+ Word a_val;
+ } u;
+};
+
+extern struct ume_auxv *find_auxv(UWord* orig_esp);
+
+/* Our private auxv entries */
+#define AT_UME_PADFD 0xff01 /* padding file fd */
+#define AT_UME_EXECFD 0xff02 /* stage1 executable fd */
+
+#endif /* __PUB_CORE_UME_H */
+
+/*--------------------------------------------------------------------*/
+/*--- end ---*/
+/*--------------------------------------------------------------------*/
Modified: trunk/coregrind/stage1.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/stage1.c 2005-06-21 22:27:19 UTC (rev 3991)
+++ trunk/coregrind/stage1.c 2005-06-21 22:47:54 UTC (rev 3992)
@@ -44,9 +44,9 @@
#include "memcheck/memcheck.h"
#include "pub_core_basics.h"
#include "pub_core_debuglog.h"
-#include "pub_core_libcbase.h"
-#include "pub_core_libcproc.h"
-#include "ume.h"
+#include "pub_core_libcbase.h" // For VG_PGROUNDUP, VG_PGROUNDDN
+#include "pub_core_libcproc.h" // For VALGRINDLIB
+#include "pub_core_ume.h"
=20
=20
static int stack[SIGSTKSZ*4];
Deleted: trunk/coregrind/ume.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/ume.c 2005-06-21 22:27:19 UTC (rev 3991)
+++ trunk/coregrind/ume.c 2005-06-21 22:47:54 UTC (rev 3992)
@@ -1,747 +0,0 @@
-
-/*--------------------------------------------------------------------*/
-/*--- User-mode execve(), and other stuff shared between stage1 ---*/
-/*--- and stage2. ume.c ---*/
-/*--------------------------------------------------------------------*/
-
-/*
- This file is part of Valgrind, a dynamic binary instrumentation
- framework.
-
- Copyright (C) 2000-2005 Julian Seward=20
- js...@ac...
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307, USA.
-
- The GNU General Public License is contained in the file COPYING.
-*/
-
-
-#define _GNU_SOURCE
-#define _FILE_OFFSET_BITS 64
-
-// It seems that on SuSE 9.1 (x86) something in <fcntl.h> messes up stuf=
f
-// acquired indirectly from vki-x86-linux.h. Therefore our headers must=
be
-// included ahead of the glibc ones. This fix is a kludge; the right
-// solution is to entirely remove the glibc dependency.
-#include "pub_core_basics.h"
-#include "pub_core_libcbase.h"
-#include "pub_core_machine.h"
-#include "ume.h"
-
-#include <sys/mman.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <assert.h>
-
-#if VG_WORDSIZE =3D=3D 8
-#define ESZ(x) Elf64_##x
-#elif VG_WORDSIZE =3D=3D 4
-#define ESZ(x) Elf32_##x
-#else
-#error VG_WORDSIZE needs to =3D=3D4 or =3D=3D8
-#endif
-
-struct elfinfo
-{
- ESZ(Ehdr) e;
- ESZ(Phdr) *p;
- int fd;
-};
-
-static void check_mmap(void* res, void* base, int len)
-{
- if ((void*)-1 =3D=3D res) {
- fprintf(stderr, "valgrind: mmap(%p, %d) failed in UME.\n", base, l=
en);
- exit(1);
- }
-}
-
-// 'extra' allows the caller to pass in extra args to 'fn', like free
-// variables to a closure.
-void foreach_map(int (*fn)(char *start, char *end,
- const char *perm, off_t offset,
- int maj, int min, int ino, void* extra),
- void* extra)
-{
- static char buf[10240];
- char *bufptr =3D buf;
- int ret, fd;
-
- fd =3D open("/proc/self/maps", O_RDONLY);
-
- if (fd =3D=3D -1) {
- perror("open /proc/self/maps");
- return;
- }
-
- ret =3D read(fd, buf, sizeof(buf));
-
- if (ret =3D=3D -1) {
- perror("read /proc/self/maps");
- close(fd);
- return;
- }
- close(fd);
-
- if (ret =3D=3D sizeof(buf)) {
- fprintf(stderr, "buf too small\n");
- return;
- }
-
- while(bufptr && bufptr < buf+ret) {
- char perm[5];
- ULong offset;
- int maj, min;
- int ino;
- void *segstart, *segend;
-
- sscanf(bufptr, "%p-%p %s %llx %x:%x %d",
- &segstart, &segend, perm, &offset, &maj, &min, &ino);
- bufptr =3D strchr(bufptr, '\n');
- if (bufptr !=3D NULL)
- bufptr++; /* skip \n */
-
- if (!(*fn)(segstart, segend, perm, offset, maj, min, ino, extra))
- break;
- }
-}
-
-/*------------------------------------------------------------*/
-/*--- Stack switching ---*/
-/*------------------------------------------------------------*/
-
-// __attribute__((noreturn))
-// void jump_and_switch_stacks ( Addr stack, Addr dst );
-#if defined(VGA_x86)
-// 4(%esp) =3D=3D stack
-// 8(%esp) =3D=3D dst
-asm(
-".global jump_and_switch_stacks\n"
-"jump_and_switch_stacks:\n"
-" movl %esp, %esi\n" // remember old stack pointer
-" movl 4(%esi), %esp\n" // set stack
-" pushl 8(%esi)\n" // dst to stack
-" movl $0, %eax\n" // zero all GP regs
-" movl $0, %ebx\n"
-" movl $0, %ecx\n"
-" movl $0, %edx\n"
-" movl $0, %esi\n"
-" movl $0, %edi\n"
-" movl $0, %ebp\n"
-" ret\n" // jump to dst
-" ud2\n" // should never get here
-);
-#elif defined(VGA_amd64)
-// %rdi =3D=3D stack
-// %rsi =3D=3D dst
-asm(
-".global jump_and_switch_stacks\n"
-"jump_and_switch_stacks:\n"
-" movq %rdi, %rsp\n" // set stack
-" pushq %rsi\n" // dst to stack
-" movq $0, %rax\n" // zero all GP regs
-" movq $0, %rbx\n"
-" movq $0, %rcx\n"
-" movq $0, %rdx\n"
-" movq $0, %rsi\n"
-" movq $0, %rdi\n"
-" movq $0, %rbp\n"
-" movq $0, %r8\n"\
-" movq $0, %r9\n"\
-" movq $0, %r10\n"
-" movq $0, %r11\n"
-" movq $0, %r12\n"
-" movq $0, %r13\n"
-" movq $0, %r14\n"
-" movq $0, %r15\n"
-" ret\n" // jump to dst
-" ud2\n" // should never get here
-);
-
-#elif defined(VGA_ppc32)
-/* Jump to 'dst', but first set the stack pointer to 'stack'. Also,
- clear all the integer registers before entering 'dst'. It's
- important that the stack pointer is set to exactly 'stack' and not
- (eg) stack - apparently_harmless_looking_small_offset. Basically
- because the code at 'dst' might be wanting to scan the area above
- 'stack' (viz, the auxv array), and putting spurious words on the
- stack confuses it.
-*/
-// %r3 =3D=3D stack
-// %r4 =3D=3D dst
-asm(
-".global jump_and_switch_stacks\n"
-"jump_and_switch_stacks:\n"
-" mtctr %r4\n\t" // dst to %ctr
-" mr %r1,%r3\n\t" // stack to %sp
-" li 0,0\n\t" // zero all GP regs
-" li 3,0\n\t"
-" li 4,0\n\t"
-" li 5,0\n\t"
-" li 6,0\n\t"
-" li 7,0\n\t"
-" li 8,0\n\t"
-" li 9,0\n\t"
-" li 10,0\n\t"
-" li 11,0\n\t"
-" li 12,0\n\t"
-" li 13,0\n\t" // CAB: This right? r13 =3D small data area p=
tr
-" li 14,0\n\t"
-" li 15,0\n\t"
-" li 16,0\n\t"
-" li 17,0\n\t"
-" li 18,0\n\t"
-" li 19,0\n\t"
-" li 20,0\n\t"
-" li 21,0\n\t"
-" li 22,0\n\t"
-" li 23,0\n\t"
-" li 24,0\n\t"
-" li 25,0\n\t"
-" li 26,0\n\t"
-" li 27,0\n\t"
-" li 28,0\n\t"
-" li 29,0\n\t"
-" li 30,0\n\t"
-" li 31,0\n\t"
-" mtxer 0\n\t"
-" mtcr 0\n\t"
-" mtlr %r0\n\t"
-" bctr\n\t" // jump to dst
-" trap\n" // should never get here
-);
-
-#else
-# error Unknown architecture
-#endif
-
-/*------------------------------------------------------------*/
-/*--- Finding auxv on the stack ---*/
-/*------------------------------------------------------------*/
-
-struct ume_auxv *find_auxv(UWord* sp)
-{
- sp++; // skip argc (Nb: is word-sized, not int-sized!)
-
- while (*sp !=3D 0) // skip argv
- sp++;
- sp++;
-
- while (*sp !=3D 0) // skip env
- sp++;
- sp++;
- =20
-#if defined(VGA_ppc32)
-# if defined AT_IGNOREPPC
- while (*sp =3D=3D AT_IGNOREPPC) // skip AT_IGNOREPPC entries
- sp +=3D 2;
-# endif
-#endif
-
- return (struct ume_auxv *)sp;
-}
-
-/*------------------------------------------------------------*/
-/*--- Loading ELF files ---*/
-/*------------------------------------------------------------*/
-
-static=20
-struct elfinfo *readelf(int fd, const char *filename)
-{
- struct elfinfo *e =3D malloc(sizeof(*e));
- int phsz;
-
- assert(e);
- e->fd =3D fd;
-
- if (pread(fd, &e->e, sizeof(e->e), 0) !=3D sizeof(e->e)) {
- fprintf(stderr, "valgrind: %s: can't read ELF header: %s\n",=20
- filename, strerror(errno));
- return NULL;
- }
-
- if (memcmp(&e->e.e_ident[0], ELFMAG, SELFMAG) !=3D 0) {
- fprintf(stderr, "valgrind: %s: bad ELF magic number\n", filename);
- return NULL;
- }
- if (e->e.e_ident[EI_CLASS] !=3D VGA_ELF_CLASS) {
- fprintf(stderr,=20
- "valgrind: wrong ELF executable class "
- "(eg. 32-bit instead of 64-bit)\n");
- return NULL;
- }
- if (e->e.e_ident[EI_DATA] !=3D VGA_ELF_ENDIANNESS) {
- fprintf(stderr, "valgrind: executable has wrong endian-ness\n");
- return NULL;
- }
- if (!(e->e.e_type =3D=3D ET_EXEC || e->e.e_type =3D=3D ET_DYN)) {
- fprintf(stderr, "valgrind: this is not an executable\n");
- return NULL;
- }
-
- if (e->e.e_machine !=3D VGA_ELF_MACHINE) {
- fprintf(stderr, "valgrind: executable is not for "
- "this architecture\n");
- return NULL;
- }
-
- if (e->e.e_phentsize !=3D sizeof(ESZ(Phdr))) {
- fprintf(stderr, "valgrind: sizeof ELF Phdr wrong\n");
- return NULL;
- }
-
- phsz =3D sizeof(ESZ(Phdr)) * e->e.e_phnum;
- e->p =3D malloc(phsz);
- assert(e->p);
-
- if (pread(fd, e->p, phsz, e->e.e_phoff) !=3D phsz) {
- fprintf(stderr, "valgrind: can't read phdr: %s\n", strerror(errno)=
);
- return NULL;
- }
-
- return e;
-}
-
-/* Map an ELF file. Returns the brk address. */
-static
-ESZ(Addr) mapelf(struct elfinfo *e, ESZ(Addr) base)
-{
- int i;
- void* res;
- ESZ(Addr) elfbrk =3D 0;
-
- for(i =3D 0; i < e->e.e_phnum; i++) {
- ESZ(Phdr) *ph =3D &e->p[i];
- ESZ(Addr) addr, brkaddr;
- ESZ(Word) memsz;
-
- if (ph->p_type !=3D PT_LOAD)
- continue;
-
- addr =3D ph->p_vaddr+base;
- memsz =3D ph->p_memsz;
- brkaddr =3D addr+memsz;
-
- if (brkaddr > elfbrk)
- elfbrk =3D brkaddr;
- }
-
- for(i =3D 0; i < e->e.e_phnum; i++) {
- ESZ(Phdr) *ph =3D &e->p[i];
- ESZ(Addr) addr, bss, brkaddr;
- ESZ(Off) off;
- ESZ(Word) filesz;
- ESZ(Word) memsz;
- unsigned prot =3D 0;
-
- if (ph->p_type !=3D PT_LOAD)
- continue;
-
- if (ph->p_flags & PF_X) prot |=3D PROT_EXEC;
- if (ph->p_flags & PF_W) prot |=3D PROT_WRITE;
- if (ph->p_flags & PF_R) prot |=3D PROT_READ;
-
- addr =3D ph->p_vaddr+base;
- off =3D ph->p_offset;
- filesz =3D ph->p_filesz;
- bss =3D addr+filesz;
- memsz =3D ph->p_memsz;
- brkaddr =3D addr+memsz;
-
- // Tom says: In the following, do what the Linux kernel does and o=
nly
- // map the pages that are required instead of rounding everything =
to
- // the specified alignment (ph->p_align). (AMD64 doesn't work if =
you
- // use ph->p_align -- part of stage2's memory gets trashed somehow=
.)
- //
- // The condition handles the case of a zero-length segment.
- if (VG_PGROUNDUP(bss)-VG_PGROUNDDN(addr) > 0) {
- res =3D mmap((char *)VG_PGROUNDDN(addr),
- VG_PGROUNDUP(bss)-VG_PGROUNDDN(addr),
- prot, MAP_FIXED|MAP_PRIVATE, e->fd, VG_PGROUNDDN(off=
));
- check_mmap(res, (char*)VG_PGROUNDDN(addr),
- VG_PGROUNDUP(bss)-VG_PGROUNDDN(addr));
- }
-
- // if memsz > filesz, fill the remainder with zeroed pages
- if (memsz > filesz) {
- UInt bytes;
-
- bytes =3D VG_PGROUNDUP(brkaddr)-VG_PGROUNDUP(bss);
- if (bytes > 0) {
- res =3D mmap((char *)VG_PGROUNDUP(bss), bytes,
- prot, MAP_FIXED|MAP_ANONYMOUS|MAP_PRIVATE, -1, 0);
- check_mmap(res, (char*)VG_PGROUNDUP(bss), bytes);
- }
-
- bytes =3D bss & (VKI_PAGE_SIZE - 1);
-
- // The 'prot' condition allows for a read-only bss
- if ((prot & PROT_WRITE) && (bytes > 0)) {
- bytes =3D VKI_PAGE_SIZE - bytes;
- memset((char *)bss, 0, bytes);
- }
- }
- }
-
- return elfbrk;
-}
-
-// Forward declaration.
-static int do_exec_inner(const char *exe, struct exeinfo *info);
-
-static int match_ELF(const char *hdr, int len)
-{
- ESZ(Ehdr) *e =3D (ESZ(Ehdr) *)hdr;
- return (len > sizeof(*e)) && memcmp(&e->e_ident[0], ELFMAG, SELFMAG) =
=3D=3D 0;
-}
-
-static int load_ELF(char *hdr, int len, int fd, const char *name,
- struct exeinfo *info)
-{
- struct elfinfo *e;
- struct elfinfo *interp =3D NULL;
- ESZ(Addr) minaddr =3D ~0; /* lowest mapped address */
- ESZ(Addr) maxaddr =3D 0; /* highest mapped address */
- ESZ(Addr) interp_addr =3D 0; /* interpreter (ld.so) address */
- ESZ(Word) interp_size =3D 0; /* interpreter size */
- ESZ(Word) interp_align =3D VKI_PAGE_SIZE;
- int i;
- void *entry;
- ESZ(Addr) ebase =3D 0;
-
-#ifdef HAVE_PIE
- ebase =3D info->exe_base;
-#endif
-
- e =3D readelf(fd, name);
-
- if (e =3D=3D NULL)
- return ENOEXEC;
-
- info->phnum =3D e->e.e_phnum;
- info->entry =3D e->e.e_entry + ebase;
- info->phdr =3D 0;
-
- for(i =3D 0; i < e->e.e_phnum; i++) {
- ESZ(Phdr) *ph =3D &e->p[i];
-
- switch(ph->p_type) {
- case PT_PHDR:
- info->phdr =3D ph->p_vaddr + ebase;
- break;
-
- case PT_LOAD:
- if (ph->p_vaddr < minaddr)
- minaddr =3D ph->p_vaddr;
- if (ph->p_vaddr+ph->p_memsz > maxaddr)
- maxaddr =3D ph->p_vaddr+ph->p_memsz;
- break;
- =09
- case PT_INTERP: {
- char *buf =3D malloc(ph->p_filesz+1);
- int j;
- int intfd;
- int baseaddr_set;
-
- assert(buf);
- pread(fd, buf, ph->p_filesz, ph->p_offset);
- buf[ph->p_filesz] =3D '\0';
-
- intfd =3D open(buf, O_RDONLY);
- if (intfd =3D=3D -1) {
- perror("open interp");
- exit(1);
- }
-
- interp =3D readelf(intfd, buf);
- if (interp =3D=3D NULL) {
- fprintf(stderr, "Can't read interpreter\n");
- return 1;
- }
- free(buf);
-
- baseaddr_set =3D 0;
- for(j =3D 0; j < interp->e.e_phnum; j++) {
- ESZ(Phdr) *iph =3D &interp->p[j];
- ESZ(Addr) end;
-
- if (iph->p_type !=3D PT_LOAD)
- continue;
- =20
- if (!baseaddr_set) {
- interp_addr =3D iph->p_vaddr;
- interp_align =3D iph->p_align;
- baseaddr_set =3D 1;
- }
-
- /* assumes that all segments in the interp are close */
- end =3D (iph->p_vaddr - interp_addr) + iph->p_memsz;
-
- if (end > interp_size)
- interp_size =3D end;
- }
- break;
-
- default:
- // do nothing
- break;
- }
- }
- }
-
- if (info->phdr =3D=3D 0)
- info->phdr =3D minaddr + e->e.e_phoff;
-
- if (info->exe_base !=3D info->exe_end) {
- if (minaddr >=3D maxaddr ||
- (minaddr + ebase < info->exe_base ||
- maxaddr + ebase > info->exe_end)) {
- fprintf(stderr, "Executable range %p-%p is outside the\n"
- "acceptable range %p-%p\n",
- (void *)minaddr + ebase, (void *)maxaddr + ebase,
- (void *)info->exe_base, (void *)info->exe_end);
- return ENOMEM;
- }
- }
-
- info->brkbase =3D mapelf(e, ebase); /* map the executable */
-
- if (info->brkbase =3D=3D 0)
- return ENOMEM;
-
- if (interp !=3D NULL) {
- /* reserve a chunk of address space for interpreter */
- void* res;
- char* base =3D (char *)info->exe_base;
- char* baseoff;
- int flags =3D MAP_PRIVATE|MAP_ANONYMOUS;
-
- if (info->map_base !=3D 0) {
- base =3D (char *)VG_ROUNDUP(info->map_base, interp_align);
- flags |=3D MAP_FIXED;
- }
-
- res =3D mmap(base, interp_size, PROT_NONE, flags, -1, 0);
- check_mmap(res, base, interp_size);
- base =3D res;
-
- baseoff =3D base - interp_addr;
-
- mapelf(interp, (ESZ(Addr))baseoff);
-
- close(interp->fd);
-
- entry =3D baseoff + interp->e.e_entry;
- info->interp_base =3D (ESZ(Addr))base;
-
- free(interp->p);
- free(interp);
- } else
- entry =3D (void *)e->e.e_entry;
-
- info->exe_base =3D minaddr + ebase;
- info->exe_end =3D maxaddr + ebase;
-
- info->init_eip =3D (Addr)entry;
-
- free(e->p);
- free(e);
-
- return 0;
-}
-
-
-static int match_script(const char *hdr, Int len)
-{
- return (len > 2) && memcmp(hdr, "#!", 2) =3D=3D 0;
-}
-
-static int load_script(char *hdr, int len, int fd, const char *name,
- struct exeinfo *info)
-{
- char *interp;
- char *const end =3D hdr+len;
- char *cp;
- char *arg =3D NULL;
- int eol;
-
- interp =3D hdr + 2;
- while(interp < end && (*interp =3D=3D ' ' || *interp =3D=3D '\t'))
- interp++;
-
- if (*interp !=3D '/')
- return ENOEXEC; /* absolute path only for interpreter */
-
- /* skip over interpreter name */
- for(cp =3D interp; cp < end && *cp !=3D ' ' && *cp !=3D '\t' && *cp !=
=3D '\n'; cp++)
- ;
-
- eol =3D (*cp =3D=3D '\n');
-
- *cp++ =3D '\0';
-
- if (!eol && cp < end) {
- /* skip space before arg */
- while (cp < end && (*cp =3D=3D '\t' || *cp =3D=3D ' '))
- cp++;
-
- /* arg is from here to eol */
- arg =3D cp;
- while (cp < end && *cp !=3D '\n')
- cp++;
- *cp =3D '\0';
- }
- =20
- info->interp_name =3D strdup(interp);
- assert(NULL !=3D info->interp_name);
- if (arg !=3D NULL && *arg !=3D '\0') {
- info->interp_args =3D strdup(arg);
- assert(NULL !=3D info->interp_args);
- }
-
- if (info->argv && info->argv[0] !=3D NULL)
- info->argv[0] =3D (char *)name;
-
- if (0)
- printf("#! script: interp_name=3D\"%s\" interp_args=3D\"%s\"\n",
- info->interp_name, info->interp_args);
-
- return do_exec_inner(interp, info);
-}
-
-/*=20
- Emulate the normal Unix permissions checking algorithm.
-
- If owner matches, then use the owner permissions, else
- if group matches, then use the group permissions, else
- use other permissions.
-
- Note that we can't deal with SUID/SGID, so we refuse to run them
- (otherwise the executable may misbehave if it doesn't have the
- permissions it thinks it does).
-*/
-static int check_perms(int fd)
-{
- struct stat st;
-
- if (fstat(fd, &st) =3D=3D -1)=20
- return errno;
-
- if (st.st_mode & (S_ISUID | S_ISGID)) {
- //fprintf(stderr, "Can't execute suid/sgid executable %s\n", exe);
- return EACCES;
- }
-
- if (geteuid() =3D=3D st.st_uid) {
- if (!(st.st_mode & S_IXUSR))
- return EACCES;
- } else {
- int grpmatch =3D 0;
-
- if (getegid() =3D=3D st.st_gid)
- grpmatch =3D 1;
- else {
- gid_t groups[32];
- int ngrp =3D getgroups(32, groups);
- int i;
-
- for(i =3D 0; i < ngrp; i++)
- if (groups[i] =3D=3D st.st_gid) {
- grpmatch =3D 1;
- break;
- }
- }
-
- if (grpmatch) {
- if (!(st.st_mode & S_IXGRP))
- return EACCES;
- } else if (!(st.st_mode & S_IXOTH))
- return EACCES;
- }
-
- return 0;
-}
-
-static int do_exec_inner(const char *exe, struct exeinfo *info)
-{
- int fd;
- int err;
- char buf[VKI_PAGE_SIZE];
- int bufsz;
- int i;
- int ret;
- static const struct {
- int (*match)(const char *hdr, int len);
- int (*load) ( char *hdr, int len, int fd2, const char *name,
- struct exeinfo *);
- } formats[] =3D {
- { match_ELF, load_ELF },
- { match_script, load_script },
- };
-
- fd =3D open(exe, O_RDONLY);
- if (fd =3D=3D -1) {
- if (0)
- fprintf(stderr, "Can't open executable %s: %s\n",
- exe, strerror(errno));
- return errno;
- }
-
- err =3D check_perms(fd);
- if (err !=3D 0) {
- close(fd);
- return err;
- }
-
- bufsz =3D pread(fd, buf, sizeof(buf), 0);
- if (bufsz < 0) {
- fprintf(stderr, "Can't read executable header: %s\n",
- strerror(errno));
- close(fd);
- return errno;
- }
-
- ret =3D ENOEXEC;
- for(i =3D 0; i < sizeof(formats)/sizeof(*formats); i++) {
- if ((formats[i].match)(buf, bufsz)) {
- ret =3D (formats[i].load)(buf, bufsz, fd, exe, info);
- break;
- }
- }
-
- close(fd);
-
- return ret;
-}
-
-// See ume.h for an indication of which entries of 'info' are inputs, wh=
ich
-// are outputs, and which are both.
-int do_exec(const char *exe, struct exeinfo *info)
-{
- info->interp_name =3D NULL;
- info->interp_args =3D NULL;
-
- return do_exec_inner(exe, info);
-}
-
-/*--------------------------------------------------------------------*/
-/*--- end ume.c ---*/
-/*--------------------------------------------------------------------*/
Deleted: trunk/coregrind/ume.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/ume.h 2005-06-21 22:27:19 UTC (rev 3991)
+++ trunk/coregrind/ume.h 2005-06-21 22:47:54 UTC (rev 3992)
@@ -1,118 +0,0 @@
-
-/*--------------------------------------------------------------------*/
-/*--- A header file used by both stage1 and stage2. ---*/
-/*--- ume.h ---*/
-/*--------------------------------------------------------------------*/
-
-/*
- This file is part of Valgrind, a dynamic binary instrumentation
- framework.
-
- Copyright (C) 2000-2005 Julian Seward=20
- js...@ac...
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License as
- published by the Free Software Foundation; either version 2 of the
- License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful, but
- WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
- 02111-1307, USA.
-
- The GNU General Public License is contained in the file COPYING.
-*/
-
-#ifndef _COREGRIND_UME_H
-#define _COREGRIND_UME_H
-
-#include <elf.h>
-#include <sys/types.h>
-
-/*------------------------------------------------------------*/
-/*--- General stuff ---*/
-/*------------------------------------------------------------*/
-
-extern
-void foreach_map(int (*fn)(char *start, char *end,
- const char *perm, off_t offset,
- int maj, int min, int ino, void* extra),
- void* extra);
-
-/* Jump to 'dst', but first set the stack pointer to 'stack'. Also,
- clear all the integer registers before entering 'dst'. It's
- important that the stack pointer is set to exactly 'stack' and not
- (eg) stack - apparently_harmless_looking_small_offset. Basically
- because the code at 'dst' might be wanting to scan the area above
- 'stack' (viz, the auxv array), and putting spurious words on the
- stack confuses it.
-
- This is only exported so that vgtest_ume.c can use it.
-*/
-extern
-__attribute__((noreturn))
-void jump_and_switch_stacks ( Addr stack, Addr dst );
-
-
-/*------------------------------------------------------------*/
-/*--- Loading ELF files ---*/
-/*------------------------------------------------------------*/
-
-// Info needed to load and run a program. IN/INOUT/OUT refers to the
-// inputs/outputs of do_exec().
-struct exeinfo
-{
- Addr map_base; // IN: if non-zero, base address of mappings
- char** argv; // IN: the original argv
-
- Addr exe_base; // INOUT: lowest (allowed) address of exe
- Addr exe_end; // INOUT: highest (allowed) address
-
- Addr phdr; // OUT: address phdr was mapped at
- int phnum; // OUT: number of phdrs
- Addr interp_base; // OUT: where interpreter (ld.so) was mapped
- Addr entry; // OUT: entrypoint in main executable
- Addr init_eip; // OUT: initial eip
- Addr brkbase; // OUT: base address of brk segment
-
- // These are the extra args added by #! scripts
- char* interp_name; // OUT: the interpreter name
- char* interp_args; // OUT: the args for the interpreter
-};
-
-// Does everything short of actually running 'exe': finds the file,
-// checks execute permissions, sets up interpreter if program is a scrip=
t,=20
-// reads headers, maps file into memory, and returns important info abou=
t
-// the program.
-extern int do_exec(const char *exe, struct exeinfo *info);
-
-/*------------------------------------------------------------*/
-/*--- Finding and dealing with auxv ---*/
-/*------------------------------------------------------------*/
-
-struct ume_auxv
-{
- Word a_type;
- union {
- void *a_ptr;
- Word a_val;
- } u;
-};
-
-extern struct ume_auxv *find_auxv(UWord* orig_esp);
-
-/* Our private auxv entries */
-#define AT_UME_PADFD 0xff01 /* padding file fd */
-#define AT_UME_EXECFD 0xff02 /* stage1 executable fd */
-
-#endif /* _COREGRIND_UME_H */
-
-/*--------------------------------------------------------------------*/
-/*--- end ume.h ---*/
-/*--------------------------------------------------------------------*/
|