]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
- Split up m_ume.c into m_ume/{main,elf,script}.c. This will make merging
authorNicholas Nethercote <njn@valgrind.org>
Wed, 21 Jan 2009 02:26:56 +0000 (02:26 +0000)
committerNicholas Nethercote <njn@valgrind.org>
Wed, 21 Jan 2009 02:26:56 +0000 (02:26 +0000)
  the DARWIN branch easier later.
- Remove the disabled vgtest_ume test, it's very unlikely it'll ever work
  again.
- Move VG_(find_auxv) to initimg-linux.c, the only place it's used, and make
  it static.

git-svn-id: svn://svn.valgrind.org/valgrind/trunk@9004

coregrind/Makefile.am
coregrind/m_initimg/initimg-linux.c
coregrind/m_ume/elf.c [moved from coregrind/m_ume.c with 50% similarity]
coregrind/m_ume/main.c [new file with mode: 0644]
coregrind/m_ume/script.c [new file with mode: 0644]
coregrind/pub_core_ume.h
memcheck/tests/Makefile.am
memcheck/tests/vgtest_ume.c [deleted file]
memcheck/tests/vgtest_ume.disabled [deleted file]
memcheck/tests/vgtest_ume.stderr.exp [deleted file]

index 9410b3c83c8eaf76a7f952ee91071843b0444f46..4f247e5597befaeeb8d9c8c8e612a2b5cf6dff8e 100644 (file)
@@ -140,6 +140,7 @@ noinst_HEADERS = \
        pub_core_vkiscnums.h    \
        pub_core_wordfm.h       \
        pub_core_xarray.h       \
+       m_aspacemgr/priv_aspacemgr.h \
        m_coredump/priv_elf.h   \
        m_debuginfo/priv_misc.h \
        m_debuginfo/priv_storage.h      \
@@ -163,7 +164,7 @@ noinst_HEADERS = \
        m_syswrap/priv_syswrap-linux-variants.h \
        m_syswrap/priv_syswrap-aix5.h \
        m_syswrap/priv_syswrap-main.h \
-       m_aspacemgr/priv_aspacemgr.h \
+       m_ume/priv_ume.h \
        launcher-aix5-bootblock.h \
        m_initimg/simple_huffman.c
 
@@ -203,7 +204,6 @@ COREGRIND_SOURCES_COMMON = \
        m_trampoline.S \
        m_translate.c \
        m_transtab.c \
-       m_ume.c \
        m_vki.c \
        m_vkiscnums.c \
        m_wordfm.c \
@@ -222,7 +222,10 @@ COREGRIND_SOURCES_COMMON = \
        m_replacemalloc/replacemalloc_core.c \
        m_scheduler/scheduler.c \
        m_scheduler/sema.c \
-       m_syswrap/syswrap-main.c
+       m_syswrap/syswrap-main.c \
+       m_ume/elf.c \
+       m_ume/main.c \
+       m_ume/script.c
 
 COREGRIND_LINUX_SOURCE = \
        m_coredump/coredump-elf.c \
index a886fba8d472820366fb42b06c5f716c6c3e00b9..4d8472d29eef847fd5f20d018bf10edbb9119bea 100644 (file)
@@ -412,6 +412,38 @@ static char *copy_str(char **tab, const char *str)
 
    ---------------------------------------------------------------- */
 
+struct auxv
+{
+   Word a_type;
+   union {
+      void *a_ptr;
+      Word a_val;
+   } u;
+};
+
+static
+struct auxv *find_auxv(UWord* sp)
+{
+   sp++;                // skip argc (Nb: is word-sized, not int-sized!)
+
+   while (*sp != 0)     // skip argv
+      sp++;
+   sp++;
+
+   while (*sp != 0)     // skip env
+      sp++;
+   sp++;
+   
+#if defined(VGA_ppc32) || defined(VGA_ppc64)
+# if defined AT_IGNOREPPC
+   while (*sp == AT_IGNOREPPC)        // skip AT_IGNOREPPC entries
+      sp += 2;
+# endif
+#endif
+
+   return (struct auxv *)sp;
+}
+
 static 
 Addr setup_client_stack( void*  init_sp,
                          char** orig_envp, 
@@ -425,9 +457,9 @@ Addr setup_client_stack( void*  init_sp,
    char *strtab;               /* string table */
    char *stringbase;
    Addr *ptr;
-   struct ume_auxv *auxv;
-   const struct ume_auxv *orig_auxv;
-   const struct ume_auxv *cauxv;
+   struct auxv *auxv;
+   const struct auxv *orig_auxv;
+   const struct auxv *cauxv;
    unsigned stringsize;                /* total size of strings in bytes */
    unsigned auxsize;           /* total size of auxv in bytes */
    Int argc;                   /* total argc */
@@ -442,7 +474,7 @@ Addr setup_client_stack( void*  init_sp,
    vg_assert( VG_(args_for_client) );
 
    /* use our own auxv as a prototype */
-   orig_auxv = VG_(find_auxv)(init_sp);
+   orig_auxv = find_auxv(init_sp);
 
    /* ==================== compute sizes ==================== */
 
@@ -636,7 +668,7 @@ Addr setup_client_stack( void*  init_sp,
    *ptr++ = 0;
 
    /* --- auxv --- */
-   auxv = (struct ume_auxv *)ptr;
+   auxv = (struct auxv *)ptr;
    *client_auxv = (UInt *)auxv;
 
 #  if defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
similarity index 50%
rename from coregrind/m_ume.c
rename to coregrind/m_ume/elf.c
index 9e13a8e751d285f3b3594fe20181ddecb466d849..ec5d77c64545ac66ee682d5d451ffbc4a8578b07 100644 (file)
@@ -1,7 +1,6 @@
 
 /*--------------------------------------------------------------------*/
-/*--- User-mode execve(), and other stuff shared between stage1    ---*/
-/*--- and stage2.                                          m_ume.c ---*/
+/*--- User-mode execve() for ELF executables           m_ume_elf.c ---*/
 /*--------------------------------------------------------------------*/
 
 /*
    The GNU General Public License is contained in the file COPYING.
 */
 
-
 #include "pub_core_basics.h"
 #include "pub_core_vki.h"
 
-#if defined(VGO_linux)
-
-#include "pub_core_aspacemgr.h"   // various mapping fns
+#include "pub_core_aspacemgr.h"     // various mapping fns
 #include "pub_core_debuglog.h"
-#include "pub_core_libcbase.h"
-#include "pub_core_machine.h"
+#include "pub_core_libcassert.h"    // VG_(exit), vg_assert
+#include "pub_core_libcbase.h"      // VG_(memcmp), etc
 #include "pub_core_libcprint.h"
-#include "pub_core_libcfile.h"    // VG_(close) et al
-#include "pub_core_libcproc.h"    // VG_(geteuid), VG_(getegid)
-#include "pub_core_libcassert.h"  // VG_(exit), vg_assert
-#include "pub_core_mallocfree.h"  // VG_(malloc), VG_(free)
-#include "pub_core_syscall.h"     // VG_(strerror)
-#include "pub_core_options.h"     // VG_(clo_xml)
-#include "pub_core_ume.h"         // self
+#include "pub_core_libcfile.h"      // VG_(open) et al
+#include "pub_core_machine.h"       // VG_ELF_CLASS (XXX: which should be moved)
+#include "pub_core_mallocfree.h"    // VG_(malloc), VG_(free)
+#include "pub_core_syscall.h"       // VG_(strerror)
+#include "pub_core_ume.h"           // self
+
+#include "priv_ume.h"
+
+
+#if defined(HAVE_ELF)
 
 /* --- !!! --- EXTERNAL HEADERS start --- !!! --- */
 #define _GNU_SOURCE
 /* --- !!! --- EXTERNAL HEADERS end --- !!! --- */
 
 
-#if    VG_WORDSIZE == 8
-#define ESZ(x) Elf64_##x
-#elif  VG_WORDSIZE == 4
-#define ESZ(x) Elf32_##x
+#if     VG_WORDSIZE == 8
+#define ESZ(x)  Elf64_##x
+#elif   VG_WORDSIZE == 4
+#define ESZ(x)  Elf32_##x
 #else
 #error VG_WORDSIZE needs to ==4 or ==8
 #endif
 
 struct elfinfo
 {
-   ESZ(Ehdr)   e;
-   ESZ(Phdr)   *p;
-   Int         fd;
+   ESZ(Ehdr)    e;
+   ESZ(Phdr)    *p;
+   Int          fd;
 };
 
 static void check_mmap(SysRes res, Addr base, SizeT len)
@@ -86,32 +85,6 @@ static void check_mmap(SysRes res, Addr base, SizeT len)
    }
 }
 
-/*------------------------------------------------------------*/
-/*--- Finding auxv on the stack                            ---*/
-/*------------------------------------------------------------*/
-
-struct ume_auxv *VG_(find_auxv)(UWord* sp)
-{
-   sp++;                // skip argc (Nb: is word-sized, not int-sized!)
-
-   while (*sp != 0)     // skip argv
-      sp++;
-   sp++;
-
-   while (*sp != 0)     // skip env
-      sp++;
-   sp++;
-   
-#if defined(VGA_ppc32) || defined(VGA_ppc64)
-# if defined AT_IGNOREPPC
-   while (*sp == AT_IGNOREPPC)        // skip AT_IGNOREPPC entries
-      sp += 2;
-# endif
-#endif
-
-   return (struct ume_auxv *)sp;
-}
-
 /*------------------------------------------------------------*/
 /*--- Loading ELF files                                    ---*/
 /*------------------------------------------------------------*/
@@ -189,23 +162,23 @@ ESZ(Addr) mapelf(struct elfinfo *e, ESZ(Addr) base)
    SysRes res;
    ESZ(Addr) elfbrk = 0;
 
-   for(i = 0; i < e->e.e_phnum; i++) {
+   for (i = 0; i < e->e.e_phnum; i++) {
       ESZ(Phdr) *ph = &e->p[i];
       ESZ(Addr) addr, brkaddr;
       ESZ(Word) memsz;
 
       if (ph->p_type != PT_LOAD)
-        continue;
+         continue;
 
       addr    = ph->p_vaddr+base;
       memsz   = ph->p_memsz;
       brkaddr = addr+memsz;
 
       if (brkaddr > elfbrk)
-        elfbrk = brkaddr;
+         elfbrk = brkaddr;
    }
 
-   for(i = 0; i < e->e.e_phnum; i++) {
+   for (i = 0; i < e->e.e_phnum; i++) {
       ESZ(Phdr) *ph = &e->p[i];
       ESZ(Addr) addr, bss, brkaddr;
       ESZ(Off) off;
@@ -214,7 +187,7 @@ ESZ(Addr) mapelf(struct elfinfo *e, ESZ(Addr) base)
       unsigned prot = 0;
 
       if (ph->p_type != PT_LOAD)
-        continue;
+         continue;
 
       if (ph->p_flags & PF_X) prot |= VKI_PROT_EXEC;
       if (ph->p_flags & PF_W) prot |= VKI_PROT_WRITE;
@@ -248,33 +221,33 @@ ESZ(Addr) mapelf(struct elfinfo *e, ESZ(Addr) base)
 
       // if memsz > filesz, fill the remainder with zeroed pages
       if (memsz > filesz) {
-        UInt bytes;
+         UInt bytes;
 
-        bytes = VG_PGROUNDUP(brkaddr)-VG_PGROUNDUP(bss);
-        if (bytes > 0) {
+         bytes = VG_PGROUNDUP(brkaddr)-VG_PGROUNDUP(bss);
+         if (bytes > 0) {
             if (0) VG_(debugLog)(0,"ume","mmap_anon_fixed_client #2\n");
-           res = VG_(am_mmap_anon_fixed_client)(
+            res = VG_(am_mmap_anon_fixed_client)(
                      VG_PGROUNDUP(bss), bytes,
-                    prot
+                     prot
                   );
             if (0) VG_(am_show_nsegments)(0,"after #2");
             check_mmap(res, VG_PGROUNDUP(bss), bytes);
          }
 
-        bytes = bss & (VKI_PAGE_SIZE - 1);
+         bytes = bss & (VKI_PAGE_SIZE - 1);
 
          // The 'prot' condition allows for a read-only bss
          if ((prot & VKI_PROT_WRITE) && (bytes > 0)) {
-           bytes = VKI_PAGE_SIZE - bytes;
-           VG_(memset)((char *)bss, 0, bytes);
-        }
+            bytes = VKI_PAGE_SIZE - bytes;
+            VG_(memset)((char *)bss, 0, bytes);
+         }
       }
    }
 
    return elfbrk;
 }
 
-static Bool match_ELF(const char *hdr, Int len)
+Bool VG_(match_ELF)(Char *hdr, Int len)
 {
    ESZ(Ehdr) *e = (ESZ(Ehdr) *)hdr;
    return (len > sizeof(*e)) && VG_(memcmp)(&e->e_ident[0], ELFMAG, SELFMAG) == 0;
@@ -324,15 +297,15 @@ static Bool match_ELF(const char *hdr, Int len)
 
    - The entry point in INFO is set to the interpreter's entry point,
      and we're done.  */
-static Int load_ELF(Int fd, const HChar* name, /*MOD*/ExeInfo* info)
+Int VG_(load_ELF)(Int fd, const HChar* name, /*MOD*/ExeInfo* info)
 {
    SysRes sres;
    struct elfinfo *e;
    struct elfinfo *interp = NULL;
-   ESZ(Addr) minaddr = ~0;     /* lowest mapped address */
-   ESZ(Addr) maxaddr = 0;      /* highest mapped address */
-   ESZ(Addr) interp_addr = 0;  /* interpreter (ld.so) address */
-   ESZ(Word) interp_size = 0;  /* interpreter size */
+   ESZ(Addr) minaddr = ~0;      /* lowest mapped address */
+   ESZ(Addr) maxaddr = 0;       /* highest mapped address */
+   ESZ(Addr) interp_addr = 0;   /* interpreter (ld.so) address */
+   ESZ(Word) interp_size = 0;   /* interpreter size */
    ESZ(Word) interp_align = VKI_PAGE_SIZE;
    Int i;
    void *entry;
@@ -374,66 +347,66 @@ static Int load_ELF(Int fd, const HChar* name, /*MOD*/ExeInfo* info)
    info->entry = e->e.e_entry + ebase;
    info->phdr = 0;
 
-   for(i = 0; i < e->e.e_phnum; i++) {
+   for (i = 0; i < e->e.e_phnum; i++) {
       ESZ(Phdr) *ph = &e->p[i];
 
       switch(ph->p_type) {
       case PT_PHDR:
-        info->phdr = ph->p_vaddr + ebase;
-        break;
+         info->phdr = ph->p_vaddr + ebase;
+         break;
 
       case PT_LOAD:
-        if (ph->p_vaddr < minaddr)
-           minaddr = ph->p_vaddr;
-        if (ph->p_vaddr+ph->p_memsz > maxaddr)
-           maxaddr = ph->p_vaddr+ph->p_memsz;
-        break;
-                       
+         if (ph->p_vaddr < minaddr)
+            minaddr = ph->p_vaddr;
+         if (ph->p_vaddr+ph->p_memsz > maxaddr)
+            maxaddr = ph->p_vaddr+ph->p_memsz;
+         break;
+                        
       case PT_INTERP: {
          HChar *buf = VG_(malloc)("ume.LE.1", ph->p_filesz+1);
-        Int j;
-        Int intfd;
-        Int baseaddr_set;
+         Int j;
+         Int intfd;
+         Int baseaddr_set;
 
          vg_assert(buf);
-        VG_(pread)(fd, buf, ph->p_filesz, ph->p_offset);
-        buf[ph->p_filesz] = '\0';
+         VG_(pread)(fd, buf, ph->p_filesz, ph->p_offset);
+         buf[ph->p_filesz] = '\0';
 
-        sres = VG_(open)(buf, VKI_O_RDONLY, 0);
+         sres = VG_(open)(buf, VKI_O_RDONLY, 0);
          if (sres.isError) {
-           VG_(printf)("valgrind: m_ume.c: can't open interpreter\n");
-           VG_(exit)(1);
-        }
+            VG_(printf)("valgrind: m_ume.c: can't open interpreter\n");
+            VG_(exit)(1);
+         }
          intfd = sres.res;
 
-        interp = readelf(intfd, buf);
-        if (interp == NULL) {
-           VG_(printf)("valgrind: m_ume.c: can't read interpreter\n");
-           return 1;
-        }
-        VG_(free)(buf);
-
-        baseaddr_set = 0;
-        for(j = 0; j < interp->e.e_phnum; j++) {
-           ESZ(Phdr) *iph = &interp->p[j];
-           ESZ(Addr) end;
-
-           if (iph->p_type != PT_LOAD)
-              continue;
-           
-           if (!baseaddr_set) {
-              interp_addr  = iph->p_vaddr;
-              interp_align = iph->p_align;
-              baseaddr_set = 1;
-           }
-
-           /* assumes that all segments in the interp are close */
-           end = (iph->p_vaddr - interp_addr) + iph->p_memsz;
-
-           if (end > interp_size)
-              interp_size = end;
-        }
-        break;
+         interp = readelf(intfd, buf);
+         if (interp == NULL) {
+            VG_(printf)("valgrind: m_ume.c: can't read interpreter\n");
+            return 1;
+         }
+         VG_(free)(buf);
+
+         baseaddr_set = 0;
+         for (j = 0; j < interp->e.e_phnum; j++) {
+            ESZ(Phdr) *iph = &interp->p[j];
+            ESZ(Addr) end;
+
+            if (iph->p_type != PT_LOAD)
+               continue;
+            
+            if (!baseaddr_set) {
+               interp_addr  = iph->p_vaddr;
+               interp_align = iph->p_align;
+               baseaddr_set = 1;
+            }
+
+            /* assumes that all segments in the interp are close */
+            end = (iph->p_vaddr - interp_addr) + iph->p_memsz;
+
+            if (end > interp_size)
+               interp_size = end;
+         }
+         break;
 
       default:
          // do nothing
@@ -447,17 +420,17 @@ static Int load_ELF(Int fd, const HChar* name, /*MOD*/ExeInfo* info)
 
    if (info->exe_base != info->exe_end) {
       if (minaddr >= maxaddr ||
-         (minaddr + ebase < info->exe_base ||
-          maxaddr + ebase > info->exe_end)) {
-        VG_(printf)("Executable range %p-%p is outside the\n"
+          (minaddr + ebase < info->exe_base ||
+           maxaddr + ebase > info->exe_end)) {
+         VG_(printf)("Executable range %p-%p is outside the\n"
                      "acceptable range %p-%p\n",
                      (char *)minaddr + ebase, (char *)maxaddr + ebase,
                      (char *)info->exe_base,  (char *)info->exe_end);
-        return VKI_ENOMEM;
+         return VKI_ENOMEM;
       }
    }
 
-   info->brkbase = mapelf(e, ebase);   /* map the executable */
+   info->brkbase = mapelf(e, ebase);    /* map the executable */
 
    if (info->brkbase == 0)
       return VKI_ENOMEM;
@@ -539,334 +512,7 @@ static Int load_ELF(Int fd, const HChar* name, /*MOD*/ExeInfo* info)
    return 0;
 }
 
-
-static Bool match_script(char *hdr, Int len)
-{
-   Char* end    = hdr + len;
-   Char* interp = hdr + 2;
-
-   // len < 4: need '#', '!', plus at least a '/' and one more char
-   if (len < 4) return False;    
-   if (0 != VG_(memcmp)(hdr, "#!", 2)) return False;
-
-   // Find interpreter name, make sure it's an absolute path (starts with
-   // '/') and has at least one more char.  First, skip over any space
-   // between the #! and the start of the interpreter name
-   while (interp < end && VG_(isspace)(*interp)) interp++;
-
-   // overrun?
-   if (interp >= end)   return False;  // can't find start of interp name
-
-   // interp should now point at the /
-   if (*interp != '/')  return False;  // absolute path only for interpreter
-
-   // check for something plausible after the /
-   interp++;
-   if (interp >= end)   return False;
-   if (VG_(isspace)(*interp)) return False;
-
-   // Here we should get the full interpreter name and check it with
-   // check_executable().  See the "EXEC FAILED" failure when running shell
-   // for an example.
-
-   return True;   // looks like a #! script
-}
-
-// Forward declaration.
-static Int do_exec_inner(const HChar* exe, ExeInfo* info);
-
-/* returns: 0 = success, non-0 is failure */
-static Int load_script(Int fd, const HChar* name, ExeInfo* info)
-{
-   Char  hdr[4096];
-   Int   len = 4096;
-   Int   eol;
-   Char* interp;
-   Char* end;
-   Char* cp;
-   Char* arg = NULL;
-   SysRes res;
-
-   // Read the first part of the file.
-   res = VG_(pread)(fd, hdr, len, 0);
-   if (res.isError) {
-      VG_(close)(fd);
-      return VKI_EACCES;
-   } else {
-      len = res.res;
-   }
-
-   vg_assert('#' == hdr[0] && '!' == hdr[1]);
-
-   end    = hdr + len;
-   interp = hdr + 2;
-   while (interp < end && VG_(isspace)(*interp))
-      interp++;
-
-   vg_assert(*interp == '/');   /* absolute path only for interpreter */
-
-   /* skip over interpreter name */
-   for (cp = interp; cp < end && !VG_(isspace)(*cp); cp++)
-      ;
-
-   eol = (*cp == '\n');
-
-   *cp++ = '\0';
-
-   if (!eol && cp < end) {
-      /* skip space before arg */
-      while (cp < end && VG_(isspace)(*cp) && *cp != '\n')
-        cp++;
-
-      /* arg is from here to eol */
-      arg = cp;
-      while (cp < end && *cp != '\n')
-        cp++;
-      *cp = '\0';
-   }
-   
-   info->interp_name = VG_(strdup)("ume.ls.1", interp);
-   vg_assert(NULL != info->interp_name);
-   if (arg != NULL && *arg != '\0') {
-      info->interp_args = VG_(strdup)("ume.ls.2", arg);
-      vg_assert(NULL != info->interp_args);
-   }
-
-   if (info->argv && info->argv[0] != NULL)
-      info->argv[0] = (char *)name;
-
-   if (0)
-      VG_(printf)("#! script: interp_name=\"%s\" interp_args=\"%s\"\n",
-                  info->interp_name, info->interp_args);
-
-   return do_exec_inner(interp, info);
-}
-
-
-typedef enum {
-   VG_EXE_FORMAT_ELF    = 1,
-   VG_EXE_FORMAT_SCRIPT = 2,
-} ExeFormat;
-
-// Check the file looks executable.
-SysRes 
-VG_(pre_exec_check)(const HChar* exe_name, Int* out_fd, Bool allow_setuid)
-{
-   Int fd, ret;
-   SysRes res;
-   Char  buf[4096];
-   SizeT bufsz = 4096, fsz;
-   Bool is_setuid = False;
-
-   // Check it's readable
-   res = VG_(open)(exe_name, VKI_O_RDONLY, 0);
-   if (res.isError) {
-      return res;
-   }
-   fd = res.res;
-
-   // Check we have execute permissions
-   ret = VG_(check_executable)(&is_setuid, (HChar*)exe_name, allow_setuid);
-   if (0 != ret) {
-      VG_(close)(fd);
-      if (is_setuid && !VG_(clo_xml)) {
-         VG_(message)(Vg_UserMsg, "");
-         VG_(message)(Vg_UserMsg,
-                      "Warning: Can't execute setuid/setgid executable: %s",
-                      exe_name);
-         VG_(message)(Vg_UserMsg, "Possible workaround: remove "
-                      "--trace-children=yes, if in effect");
-         VG_(message)(Vg_UserMsg, "");
-      }
-      return VG_(mk_SysRes_Error)(ret);
-   }
-
-   fsz = (SizeT)VG_(fsize)(fd);
-   if (fsz < bufsz)
-      bufsz = fsz;
-
-   res = VG_(pread)(fd, buf, bufsz, 0);
-   if (res.isError || res.res != bufsz) {
-      VG_(close)(fd);
-      return VG_(mk_SysRes_Error)(VKI_EACCES);
-   }
-   bufsz = res.res;
-
-   if (match_ELF(buf, bufsz)) {
-      res = VG_(mk_SysRes_Success)(VG_EXE_FORMAT_ELF);
-   } else if (match_script(buf, bufsz)) {
-      res = VG_(mk_SysRes_Success)(VG_EXE_FORMAT_SCRIPT);
-   } else {
-      res = VG_(mk_SysRes_Error)(VKI_ENOEXEC);
-   }
-
-   // Write the 'out_fd' param if necessary, or close the file.
-   if (!res.isError && out_fd) {
-      *out_fd = fd; 
-   } else { 
-      VG_(close)(fd);
-   }
-
-   return res;
-}
-
-// returns: 0 = success, non-0 is failure
-//
-// We can execute only ELF binaries or scripts that begin with "#!".  (Not,
-// for example, scripts that don't begin with "#!";  see the VG_(do_exec)()
-// invocation from m_main.c for how that's handled.)
-static Int do_exec_inner(const HChar *exe, ExeInfo* info)
-{
-   SysRes res;
-   Int fd;
-   Int ret;
-
-   res = VG_(pre_exec_check)(exe, &fd, False/*allow_setuid*/);
-   if (res.isError)
-      return res.err;
-
-   switch (res.res) {
-    case VG_EXE_FORMAT_ELF:    ret = load_ELF   (fd, exe, info); break;
-    case VG_EXE_FORMAT_SCRIPT: ret = load_script(fd, exe, info); break;
-    default:
-      vg_assert2(0, "unrecognised VG_EXE_FORMAT value\n");
-   }
-
-   VG_(close)(fd);
-
-   return ret;
-}
-
-
-static Bool is_hash_bang_file(Char* f)
-{
-   SysRes res = VG_(open)(f, VKI_O_RDONLY, 0);
-   if (!res.isError) {
-      Char buf[3] = {0,0,0};
-      Int fd = res.res;
-      Int n  = VG_(read)(fd, buf, 2); 
-      if (n == 2 && VG_STREQ("#!", buf))
-         return True;
-   }
-   return False;
-}
-
-// Look at the first 80 chars, and if any are greater than 127, it's binary.
-// This is crude, but should be good enough.  Note that it fails on a
-// zero-length file, as we want.
-static Bool is_binary_file(Char* f)
-{
-   SysRes res = VG_(open)(f, VKI_O_RDONLY, 0);
-   if (!res.isError) {
-      UChar buf[80];
-      Int fd = res.res;
-      Int n  = VG_(read)(fd, buf, 80); 
-      Int i;
-      for (i = 0; i < n; i++) {
-         if (buf[i] > 127)
-            return True;      // binary char found
-      }
-      return False;
-   } else {
-      // Something went wrong.  This will only happen if we earlier
-      // succeeded in opening the file but fail here (eg. the file was
-      // deleted between then and now).
-      VG_(printf)("valgrind: %s: unknown error\n", f);
-      VG_(exit)(126);      // 126 == NOEXEC
-   }
-}
-
-// If the do_exec fails we try to emulate what the shell does (I used
-// bash as a guide).  It's worth noting that the shell can execute some
-// things that VG_(do_exec)() (which subsitutes for the kernel's exec())
-// will refuse to (eg. scripts lacking a "#!" prefix).
-static Int do_exec_shell_followup(Int ret, HChar* exe_name,
-                                  ExeInfo* info)
-{
-   Char*  default_interp_name = "/bin/sh";
-   SysRes res;
-   struct vg_stat st;
-
-   if (VKI_ENOEXEC == ret) {
-      // It was an executable file, but in an unacceptable format.  Probably
-      // is a shell script lacking the "#!" prefix;  try to execute it so.
-
-      // Is it a binary file?  
-      if (is_binary_file(exe_name)) {
-         VG_(printf)("valgrind: %s: cannot execute binary file\n", exe_name);
-         VG_(exit)(126);      // 126 == NOEXEC
-      }
-
-      // Looks like a script.  Run it with /bin/sh.  This includes
-      // zero-length files.
-
-      info->interp_name = VG_(strdup)("ume.desf.1", default_interp_name);
-      info->interp_args = NULL;
-      if (info->argv && info->argv[0] != NULL)
-         info->argv[0] = (char *)exe_name;
-
-      ret = do_exec_inner(info->interp_name, info);
-
-      if (0 != ret) {
-         // Something went wrong with executing the default interpreter
-         VG_(printf)("valgrind: %s: bad interpreter (%s): %s\n",
-                     exe_name, info->interp_name, VG_(strerror)(ret));
-         VG_(exit)(126);      // 126 == NOEXEC
-      }
-
-   } else if (0 != ret) {
-      // Something else went wrong.  Try to make the error more specific,
-      // and then print a message and abort.
-   
-      // Was it a directory?
-      res = VG_(stat)(exe_name, &st);
-      if (!res.isError && VKI_S_ISDIR(st.st_mode)) {
-         VG_(printf)("valgrind: %s: is a directory\n", exe_name);
-      
-      // Was it not executable?
-      } else if (0 != VG_(check_executable)(NULL, exe_name, 
-                                            False/*allow_setuid*/)) {
-         VG_(printf)("valgrind: %s: %s\n", exe_name, VG_(strerror)(ret));
-
-      // Did it start with "#!"?  If so, it must have been a bad interpreter.
-      } else if (is_hash_bang_file(exe_name)) {
-         VG_(printf)("valgrind: %s: bad interpreter: %s\n",
-                     exe_name, VG_(strerror)(ret));
-
-      // Otherwise it was something else.
-      } else {
-         VG_(printf)("valgrind: %s: %s\n", exe_name, VG_(strerror)(ret));
-      }
-      // 126 means NOEXEC;  I think this is Posix, and that in some cases we
-      // should be returning 127, meaning NOTFOUND.  Oh well.
-      VG_(exit)(126);
-   }
-   return ret;
-}
-
-
-// This emulates the kernel's exec().  If it fails, it then emulates the
-// shell's handling of the situation.
-// See ume.h for an indication of which entries of 'info' are inputs, which
-// are outputs, and which are both.
-/* returns: 0 = success, non-0 is failure */
-Int VG_(do_exec)(const HChar* exe_name, ExeInfo* info)
-{
-   Int ret;
-   
-   info->interp_name = NULL;
-   info->interp_args = NULL;
-
-   ret = do_exec_inner(exe_name, info);
-
-   if (0 != ret) {
-      Char* exe_name_casted = (Char*)exe_name;
-      ret = do_exec_shell_followup(ret, exe_name_casted, info);
-   }
-   return ret;
-}
-
-#endif /* defined(VGO_linux) */
+#endif /* defined(HAVE_ELF) */
 
 /*--------------------------------------------------------------------*/
 /*--- end                                                          ---*/
diff --git a/coregrind/m_ume/main.c b/coregrind/m_ume/main.c
new file mode 100644 (file)
index 0000000..45530b7
--- /dev/null
@@ -0,0 +1,286 @@
+
+/*--------------------------------------------------------------------*/
+/*--- 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-2008 Julian Seward 
+      jseward@acm.org
+
+   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.
+*/
+
+
+#include "pub_core_basics.h"
+#include "pub_core_vki.h"
+
+#include "pub_core_libcbase.h"
+#include "pub_core_libcassert.h"    // VG_(exit), vg_assert
+#include "pub_core_libcfile.h"      // VG_(close) et al
+#include "pub_core_libcprint.h"     // VG_(message)
+#include "pub_core_mallocfree.h"    // VG_(strdup)
+#include "pub_core_syscall.h"       // VG_(mk_SysRes_Error)
+#include "pub_core_options.h"       // VG_(clo_xml)
+#include "pub_core_ume.h"           // self
+
+#include "priv_ume.h"
+
+
+typedef struct {
+   const HChar *name;
+   Bool (*match_fn)(Char *hdr, Int len);
+   Int  (*load_fn)(Int fd, const HChar *name, ExeInfo *info);
+} ExeHandler;
+
+static ExeHandler exe_handlers[] = {
+#if defined(HAVE_ELF)
+   { "ELF",    VG_(match_ELF),    VG_(load_ELF) },
+#endif
+#if defined(HAVE_SCRIPT)
+   { "script", VG_(match_script), VG_(load_script) },
+#endif
+};
+#define EXE_HANDLER_COUNT (sizeof(exe_handlers)/sizeof(exe_handlers[0]))
+
+
+// Check the file looks executable.
+SysRes 
+VG_(pre_exec_check)(const HChar* exe_name, Int* out_fd, Bool allow_setuid)
+{
+   Int fd, ret, i;
+   SysRes res;
+   Char  buf[4096];
+   SizeT bufsz = 4096, fsz;
+   Bool is_setuid = False;
+
+   // Check it's readable
+   res = VG_(open)(exe_name, VKI_O_RDONLY, 0);
+   if (res.isError) {
+      return res;
+   }
+   fd = res.res;
+
+   // Check we have execute permissions
+   ret = VG_(check_executable)(&is_setuid, (HChar*)exe_name, allow_setuid);
+   if (0 != ret) {
+      VG_(close)(fd);
+      if (is_setuid && !VG_(clo_xml)) {
+         VG_(message)(Vg_UserMsg, "");
+         VG_(message)(Vg_UserMsg,
+                      "Warning: Can't execute setuid/setgid executable: %s",
+                      exe_name);
+         VG_(message)(Vg_UserMsg, "Possible workaround: remove "
+                      "--trace-children=yes, if in effect");
+         VG_(message)(Vg_UserMsg, "");
+      }
+      return VG_(mk_SysRes_Error)(ret);
+   }
+
+   fsz = (SizeT)VG_(fsize)(fd);
+   if (fsz < bufsz)
+      bufsz = fsz;
+
+   res = VG_(pread)(fd, buf, bufsz, 0);
+   if (res.isError || res.res != bufsz) {
+      VG_(close)(fd);
+      return VG_(mk_SysRes_Error)(VKI_EACCES);
+   }
+   bufsz = res.res;
+
+   // Look for a matching executable format
+   for (i = 0; i < EXE_HANDLER_COUNT; i++) {
+      if ((*exe_handlers[i].match_fn)(buf, bufsz)) {
+         res = VG_(mk_SysRes_Success)(i);
+         break;
+      }
+   }
+   if (i == EXE_HANDLER_COUNT) {
+      // Rejected by all executable format handlers.
+      res = VG_(mk_SysRes_Error)(VKI_ENOEXEC);
+   }
+
+   // Write the 'out_fd' param if necessary, or close the file.
+   if (!res.isError && out_fd) {
+      *out_fd = fd; 
+   } else { 
+      VG_(close)(fd);
+   }
+
+   return res;
+}
+
+// returns: 0 = success, non-0 is failure
+//
+// We can execute only binaries (ELF, etc) or scripts that begin with "#!".
+// (Not, for example, scripts that don't begin with "#!";  see the
+// VG_(do_exec)() invocation from m_main.c for how that's handled.)
+Int VG_(do_exec_inner)(const HChar* exe, ExeInfo* info)
+{
+   SysRes res;
+   Int fd;
+   Int ret;
+
+   res = VG_(pre_exec_check)(exe, &fd, False/*allow_setuid*/);
+   if (res.isError)
+      return res.err;
+
+   vg_assert2(res.res >= 0 && res.res < EXE_HANDLER_COUNT, 
+              "invalid VG_(pre_exec_check) result");
+
+   ret = (*exe_handlers[res.res].load_fn)(fd, exe, info);
+
+   VG_(close)(fd);
+
+   return ret;
+}
+
+
+static Bool is_hash_bang_file(Char* f)
+{
+   SysRes res = VG_(open)(f, VKI_O_RDONLY, 0);
+   if (!res.isError) {
+      Char buf[3] = {0,0,0};
+      Int fd = res.res;
+      Int n  = VG_(read)(fd, buf, 2); 
+      if (n == 2 && VG_STREQ("#!", buf))
+         return True;
+   }
+   return False;
+}
+
+// Look at the first 80 chars, and if any are greater than 127, it's binary.
+// This is crude, but should be good enough.  Note that it fails on a
+// zero-length file, as we want.
+static Bool is_binary_file(Char* f)
+{
+   SysRes res = VG_(open)(f, VKI_O_RDONLY, 0);
+   if (!res.isError) {
+      UChar buf[80];
+      Int fd = res.res;
+      Int n  = VG_(read)(fd, buf, 80); 
+      Int i;
+      for (i = 0; i < n; i++) {
+         if (buf[i] > 127)
+            return True;      // binary char found
+      }
+      return False;
+   } else {
+      // Something went wrong.  This will only happen if we earlier
+      // succeeded in opening the file but fail here (eg. the file was
+      // deleted between then and now).
+      VG_(printf)("valgrind: %s: unknown error\n", f);
+      VG_(exit)(126);      // 126 == NOEXEC
+   }
+}
+
+// If the do_exec fails we try to emulate what the shell does (I used
+// bash as a guide).  It's worth noting that the shell can execute some
+// things that VG_(do_exec)() (which subsitutes for the kernel's exec())
+// will refuse to (eg. scripts lacking a "#!" prefix).
+static Int do_exec_shell_followup(Int ret, HChar* exe_name, ExeInfo* info)
+{
+   Char*  default_interp_name = "/bin/sh";
+   SysRes res;
+   struct vg_stat st;
+
+   if (VKI_ENOEXEC == ret) {
+      // It was an executable file, but in an unacceptable format.  Probably
+      // is a shell script lacking the "#!" prefix;  try to execute it so.
+
+      // Is it a binary file?  
+      if (is_binary_file(exe_name)) {
+         VG_(printf)("valgrind: %s: cannot execute binary file\n", exe_name);
+         VG_(exit)(126);      // 126 == NOEXEC
+      }
+
+      // Looks like a script.  Run it with /bin/sh.  This includes
+      // zero-length files.
+
+      info->interp_name = VG_(strdup)("ume.desf.1", default_interp_name);
+      info->interp_args = NULL;
+      if (info->argv && info->argv[0] != NULL)
+         info->argv[0] = (char *)exe_name;
+
+      ret = VG_(do_exec_inner)(info->interp_name, info);
+
+      if (0 != ret) {
+         // Something went wrong with executing the default interpreter
+         VG_(printf)("valgrind: %s: bad interpreter (%s): %s\n",
+                     exe_name, info->interp_name, VG_(strerror)(ret));
+         VG_(exit)(126);      // 126 == NOEXEC
+      }
+
+   } else if (0 != ret) {
+      // Something else went wrong.  Try to make the error more specific,
+      // and then print a message and abort.
+   
+      // Was it a directory?
+      res = VG_(stat)(exe_name, &st);
+      if (!res.isError && VKI_S_ISDIR(st.st_mode)) {
+         VG_(printf)("valgrind: %s: is a directory\n", exe_name);
+      
+      // Was it not executable?
+      } else if (0 != VG_(check_executable)(NULL, exe_name, 
+                                            False/*allow_setuid*/)) {
+         VG_(printf)("valgrind: %s: %s\n", exe_name, VG_(strerror)(ret));
+
+      // Did it start with "#!"?  If so, it must have been a bad interpreter.
+      } else if (is_hash_bang_file(exe_name)) {
+         VG_(printf)("valgrind: %s: bad interpreter: %s\n",
+                     exe_name, VG_(strerror)(ret));
+
+      // Otherwise it was something else.
+      } else {
+         VG_(printf)("valgrind: %s: %s\n", exe_name, VG_(strerror)(ret));
+      }
+      // 126 means NOEXEC;  I think this is Posix, and that in some cases we
+      // should be returning 127, meaning NOTFOUND.  Oh well.
+      VG_(exit)(126);
+   }
+   return ret;
+}
+
+
+// This emulates the kernel's exec().  If it fails, it then emulates the
+// shell's handling of the situation.
+// See ume.h for an indication of which entries of 'info' are inputs, which
+// are outputs, and which are both.
+/* returns: 0 = success, non-0 is failure */
+Int VG_(do_exec)(const HChar* exe_name, ExeInfo* info)
+{
+   Int ret;
+   
+   info->interp_name = NULL;
+   info->interp_args = NULL;
+
+   ret = VG_(do_exec_inner)(exe_name, info);
+
+   if (0 != ret) {
+      Char* exe_name_casted = (Char*)exe_name;
+      ret = do_exec_shell_followup(ret, exe_name_casted, info);
+   }
+   return ret;
+}
+
+/*--------------------------------------------------------------------*/
+/*--- end                                                          ---*/
+/*--------------------------------------------------------------------*/
diff --git a/coregrind/m_ume/script.c b/coregrind/m_ume/script.c
new file mode 100644 (file)
index 0000000..77bc6d0
--- /dev/null
@@ -0,0 +1,150 @@
+
+/*--------------------------------------------------------------------*/
+/*--- User-mode execve() for #! scripts.            m_ume_script.c ---*/
+/*--------------------------------------------------------------------*/
+
+/*
+   This file is part of Valgrind, a dynamic binary instrumentation
+   framework.
+
+   Copyright (C) 2000-2008 Julian Seward 
+      jseward@acm.org
+
+   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.
+*/
+
+#include "pub_core_basics.h"
+#include "pub_core_vki.h"
+
+#include "pub_core_libcbase.h"
+#include "pub_core_libcassert.h"  // VG_(exit), vg_assert
+#include "pub_core_libcfile.h"      // VG_(close) et al
+#include "pub_core_libcprint.h"
+#include "pub_core_mallocfree.h"    // VG_(strdup)
+#include "pub_core_ume.h"           // self
+
+#include "priv_ume.h"               // self
+
+
+#if defined(HAVE_SCRIPT)
+
+Bool VG_(match_script)(Char *hdr, Int len)
+{
+   Char* end    = hdr + len;
+   Char* interp = hdr + 2;
+
+   // len < 4: need '#', '!', plus at least a '/' and one more char
+   if (len < 4) return False;    
+   if (0 != VG_(memcmp)(hdr, "#!", 2)) return False;
+
+   // Find interpreter name, make sure it's an absolute path (starts with
+   // '/') and has at least one more char.  First, skip over any space
+   // between the #! and the start of the interpreter name
+   while (interp < end && VG_(isspace)(*interp)) interp++;
+
+   // overrun?
+   if (interp >= end)   return False;  // can't find start of interp name
+
+   // interp should now point at the /
+   if (*interp != '/')  return False;  // absolute path only for interpreter
+
+   // check for something plausible after the /
+   interp++;
+   if (interp >= end)   return False;
+   if (VG_(isspace)(*interp)) return False;
+
+   // Here we should get the full interpreter name and check it with
+   // check_executable().  See the "EXEC FAILED" failure when running shell
+   // for an example.
+
+   return True;   // looks like a #! script
+}
+
+
+/* returns: 0 = success, non-0 is failure */
+Int VG_(load_script)(Int fd, const HChar* name, ExeInfo* info)
+{
+   Char  hdr[4096];
+   Int   len = 4096;
+   Int   eol;
+   Char* interp;
+   Char* end;
+   Char* cp;
+   Char* arg = NULL;
+   SysRes res;
+
+   // Read the first part of the file.
+   res = VG_(pread)(fd, hdr, len, 0);
+   if (res.isError) {
+      VG_(close)(fd);
+      return VKI_EACCES;
+   } else {
+      len = res.res;
+   }
+
+   vg_assert('#' == hdr[0] && '!' == hdr[1]);
+
+   end    = hdr + len;
+   interp = hdr + 2;
+   while (interp < end && VG_(isspace)(*interp))
+      interp++;
+
+   vg_assert(*interp == '/');   /* absolute path only for interpreter */
+
+   /* skip over interpreter name */
+   for (cp = interp; cp < end && !VG_(isspace)(*cp); cp++)
+      ;
+
+   eol = (*cp == '\n');
+
+   *cp++ = '\0';
+
+   if (!eol && cp < end) {
+      /* skip space before arg */
+      while (cp < end && VG_(isspace)(*cp) && *cp != '\n')
+         cp++;
+
+      /* arg is from here to eol */
+      arg = cp;
+      while (cp < end && *cp != '\n')
+         cp++;
+      *cp = '\0';
+   }
+   
+   info->interp_name = VG_(strdup)("ume.ls.1", interp);
+   vg_assert(NULL != info->interp_name);
+   if (arg != NULL && *arg != '\0') {
+      info->interp_args = VG_(strdup)("ume.ls.2", arg);
+      vg_assert(NULL != info->interp_args);
+   }
+
+   if (info->argv && info->argv[0] != NULL)
+      info->argv[0] = (char *)name;
+
+   if (0)
+      VG_(printf)("#! script: interp_name=\"%s\" interp_args=\"%s\"\n",
+                  info->interp_name, info->interp_args);
+
+   return VG_(do_exec_inner)(interp, info);
+}
+
+#endif /* defined(HAVE_SCRIPT) */
+
+/*--------------------------------------------------------------------*/
+/*--- end                                                          ---*/
+/*--------------------------------------------------------------------*/
index 18859310b51360c42d2e7c3ceb3961b335ba9964..21e8c08fccbe62be1ecf4bbed1222d4df35d1d80 100644 (file)
@@ -37,7 +37,7 @@
 //--------------------------------------------------------------------
 
 /*------------------------------------------------------------*/
-/*--- Loading ELF files                                    ---*/
+/*--- Loading files                                        ---*/
 /*------------------------------------------------------------*/
 
 // Info needed to load and run a program.  IN/INOUT/OUT refers to the
@@ -67,7 +67,7 @@ typedef
 
 // Do a number of appropriate checks to see if the file looks executable by
 // the kernel: ie. it's a file, it's readable and executable, and it's in
-// either ELF or "#!" format.  On success, 'out_fd' gets the fd of the file
+// either binary or "#!" format.  On success, 'out_fd' gets the fd of the file
 // if it's non-NULL.  Otherwise the fd is closed.
 extern SysRes VG_(pre_exec_check)(const HChar* exe_name, Int* out_fd,
                                   Bool allow_setuid);
@@ -78,21 +78,6 @@ extern SysRes VG_(pre_exec_check)(const HChar* exe_name, Int* out_fd,
 // the program.
 extern Int VG_(do_exec)(const HChar* exe, 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 *VG_(find_auxv)(UWord* orig_esp);
-
 #endif /* __PUB_CORE_UME_H */
 
 /*--------------------------------------------------------------------*/
index 8f54377f13049be310508f3dc503f4e26509c82a..54cdbfc2379b2832e13bcdb54d9d1c3ed54245d6 100644 (file)
@@ -172,7 +172,6 @@ EXTRA_DIST = $(noinst_SCRIPTS) \
        vcpu_fbench.stdout.exp vcpu_fbench.stderr.exp vcpu_fbench.vgtest \
        vcpu_fnfns.stdout.exp vcpu_fnfns.stdout.exp-glibc28-amd64 \
        vcpu_fnfns.stderr.exp vcpu_fnfns.vgtest \
-       vgtest_ume.stderr.exp vgtest_ume.disabled \
        with-space.stderr.exp with-space.stdout.exp with-space.vgtest \
        wrap1.vgtest wrap1.stdout.exp wrap1.stderr.exp \
        wrap2.vgtest wrap2.stdout.exp wrap2.stderr.exp \
@@ -190,7 +189,6 @@ EXTRA_DIST = $(noinst_SCRIPTS) \
        zeropage.stderr.exp zeropage.stderr.exp2 zeropage.stdout.exp \
        zeropage.vgtest
 
-# vgtest_ume is not working
 check_PROGRAMS = \
        addressable \
        badaddrvalue badfree badjump badjump2 \
@@ -370,7 +368,3 @@ endif
 #                        -Wl,-T,$(top_builddir)/valt_load_address.lds
 #hello_DEPENDENCIES    = $(top_builddir)/valt_load_address.lds
 
-# vgtest_ume is not working
-#vgtest_ume_CFLAGS     = -DVGA_$(VG_ARCH_PRI) -DVGO_$(VG_OS)
-#vgtest_ume_LDADD      = ../../coregrind/m_ume.o
-
diff --git a/memcheck/tests/vgtest_ume.c b/memcheck/tests/vgtest_ume.c
deleted file mode 100644 (file)
index 0dcee7b..0000000
+++ /dev/null
@@ -1,150 +0,0 @@
-
-// This file is a unit self-test for ume.c, jmp_with_stack.c
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <assert.h>
-#include <elf.h>
-#include "../../include/pub_tool_basics.h"
-#include "../../coregrind/pub_core_ume.h"
-
-#define STKSZ   (64*1024)
-
-static void* init_sp;
-
-//-------------------------------------------------------------------
-// Test VG_(foreach_map)()
-//-------------------------------------------------------------------
-
-static int x[8];
-
-static int f(char *start, char *end, const char *perm, off_t off,
-             int maj, int min, int ino, void* dummy) {
-   // Just do some nonsense action with each of the values so that Memcheck
-   // checks that they are valid.
-   x[0] = ( start == 0 ? 0 : 1 );
-   x[1] = ( end   == 0 ? 0 : 1 );
-   x[2] = ( perm  == 0 ? 0 : 1 );
-   x[3] = ( off   == 0 ? 0 : 1 );
-   x[4] = ( maj   == 0 ? 0 : 1 );
-   x[5] = ( min   == 0 ? 0 : 1 );
-   x[6] = ( ino   == 0 ? 0 : 1 );
-   x[7] = ( dummy == 0 ? 0 : 1 );
-
-   return /*True*/1 + x[0] + x[1] + x[2] + x[3] + x[4] + x[5] + x[6] + x[7];
-}  
-
-static void test__foreach_map(void)
-{
-   fprintf(stderr, "Calling VG_(foreach_map)()\n");
-   VG_(foreach_map)(f, /*dummy*/NULL);
-}
-
-//-------------------------------------------------------------------
-// Test VG_(find_auxv)()
-//-------------------------------------------------------------------
-
-static void test__find_auxv(void)
-{
-   struct ume_auxv *auxv;
-
-   assert(init_sp != NULL);
-   
-   fprintf(stderr, "Calling VG_(find_auxv)()\n");
-   auxv = VG_(find_auxv)((UWord*)init_sp);
-
-   // Check the auxv value looks sane
-   assert((void*)auxv > (void*)init_sp);
-   assert((unsigned int)auxv - (unsigned int)init_sp < 0x10000);
-
-   // Scan the auxv, check it looks sane
-   for (; auxv->a_type != AT_NULL; auxv++) {
-      switch(auxv->a_type) {
-      // Check a_type value looks like a plausible small constant
-      case 1 ... 64:
-         break;
-   
-      default:
-         fprintf(stderr, "auxv->a_type = %lld\n", (Long)auxv->a_type);
-         assert(0);
-      }
-   }
-}
-
-//-------------------------------------------------------------------
-// Test VG_(do_exec)()
-//-------------------------------------------------------------------
-
-static void push_auxv(unsigned char **espp, int type, void *val)
-{
-        struct ume_auxv *auxp = (struct ume_auxv *)*espp;
-        auxp--;
-        auxp->a_type = type;
-        auxp->u.a_ptr = val;
-        *espp = (unsigned char *)auxp;
-}
-
-static void push(unsigned char **espp, void *v)
-{
-        void **vp = *(void ***)espp;
-        *--vp = v;
-        *espp = (unsigned char *)vp;
-}
-
-static void test__do_exec(void)
-{
-   struct exeinfo info;
-   int err;
-   unsigned char* newstack;
-   unsigned char *esp;
-
-   info.argv     = NULL;
-   info.exe_base = 0x50000000;
-   info.exe_end  = 0x50ffffff;
-   
-   fprintf(stderr, "Calling VG_(do_exec)(\"hello\")\n");
-   err = VG_(do_exec)("hello", &info);
-   assert(0 == err);
-
-//   printf("info.exe_base=%p exe_end=%p\n", 
-//          (void*)info.exe_base, (void*)info.exe_end);
-
-   newstack = malloc(STKSZ);
-   assert(0 != newstack);
-
-   esp = newstack+STKSZ;
-
-   /* 
-      Set the new executable's stack up like the kernel would after
-      exec.
-
-      These are being pushed onto the stack, towards decreasing
-      addresses.
-    */
-   push_auxv(&esp, AT_NULL, 0);                         // auxv terminator
-   push_auxv(&esp, AT_ENTRY, (void *)info.entry);       // entrypoint of the main executable */
-   push_auxv(&esp, AT_BASE, (void *)info.interp_base);  // base address of ld-linux.so
-   push_auxv(&esp, AT_PHDR, (void *)info.phdr);         // where the ELF PHDRs are mapped
-   push_auxv(&esp, AT_PHNUM, (void*)info.phnum);        // and how many of them
-
-   push(&esp, 0);               /* no env */
-   push(&esp, 0);               /* no argv */
-   push(&esp, 0);               /* argc=0 */
-
-//   fprintf(stderr, "ume_go: %p %p\n", (void*)info.init_eip, (void*)esp);
-
-   VG_(jump_and_switch_stacks)((Addr)esp, info.init_eip);
-
-   assert(0);  // UNREACHABLE
-}
-
-int main(int argc, char** argv)
-{
-   init_sp = argv - 1;
-   
-   test__foreach_map();
-   test__find_auxv();
-   test__do_exec();
-   
-   return 0;
-}
diff --git a/memcheck/tests/vgtest_ume.disabled b/memcheck/tests/vgtest_ume.disabled
deleted file mode 100644 (file)
index 118d937..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-# This one currently not used because it doesn't compile any more
-prog: vgtest_ume
-vgopts: -q
diff --git a/memcheck/tests/vgtest_ume.stderr.exp b/memcheck/tests/vgtest_ume.stderr.exp
deleted file mode 100644 (file)
index 518a10a..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-Calling VG_(foreach_map)()
-Calling VG_(find_auxv)()
-Calling VG_(do_exec)("hello")
-Hello, world!