]> git.ipfire.org Git - thirdparty/open-vm-tools.git/commitdiff
Internal branch sync. Included in this change:
authorVMware, Inc <>
Wed, 18 Sep 2013 03:28:22 +0000 (20:28 -0700)
committerDmitry Torokhov <dmitry.torokhov@gmail.com>
Mon, 23 Sep 2013 05:10:49 +0000 (22:10 -0700)
. Untangle Util_Backtrace and friends so they don't pull in lib/file
. changes in shared code that don't affect open-vm-tools functionality

Signed-off-by: Dmitry Torokhov <dtor@vmware.com>
open-vm-tools/lib/file/filePosix.c
open-vm-tools/lib/include/vm_product_versions.h
open-vm-tools/lib/user/Makefile.am
open-vm-tools/lib/user/util.c
open-vm-tools/lib/user/utilBacktrace.c [new file with mode: 0644]

index a46a5b74cdcba2d90e73ba636fc1b6e0632801d3..0f0dd55ebc47c5268c29a454c90f4935ab0cf62d 100644 (file)
@@ -572,227 +572,6 @@ FileStripFwdSlashes(ConstUnicode pathName)  // IN:
 }
 
 
-#if defined(VMX86_SERVER)
-/*
- *----------------------------------------------------------------------------
- *
- * FileVMFSGetCanonicalPath --
- *
- *    Given an absolute pathname of a VM directory/file, return its canonical
- *    pathname.
- *
- *    Canonical name for a VM directory has a special significance only for
- *    the case of NFS config VVols where the absolute pathname of VM directory
- *    could be an NFS PE based path.
- *    f.e. the VM directory on an NFS config VVol could have the absolute
- *    pathname /vmfs/volumes/nfs_pe_2/vvol36/meta_vvol36/, whereas the
- *    canonical name would be the one containing the VVol container name,
- *    f.e. /vmfs/volumes/vvol:26acd2ae55ea49c3-87dd47a44e4f327/rfc4122.d140c97a-7208-474e-95c7-a4ee6cac7f15/
- *    Both pathnames refer to the same directory (using bind mount), but
- *    canonical pathname is important as it is used in many places to identify
- *    object-backed storage from regular filesystem-backed storage.
- *
- *    It can also correctly handle cases where 'absVMDirName' is not the
- *    config-vvol directory but is a sub-directory inside the config-vvol
- *    directory. It will climb up one directory at a time looking for an
- *    NFS config VVol. The max number of directory components it'll check
- *    is MAX_SUBDIR_LEVEL.
- *
- *    It can also be called with 'absVMDirName' referring to a file
- *    (typically vmdk) and not a directory. The file can even be non-existent,
- *    f.e. it can correctly resolve
- *    /vmfs/volumes/nfs_pe_2/vvol36/meta_vvol36/DataVVol.vmdk to
- *    /vmfs/volumes/vvol:26acd2ae55ea49c3-87dd47a44e4f327/rfc4122.d140c97a-7208-474e-95c7-a4ee6cac7f15/DataVVol.vmdk
- *    for non-existent file DataVVol.vmdk.
- *    This workflow is typical when a new vmdk is being created
- *    f.e. by diskCreate.
- *
- * Note:
- *    'absVMDirName' should not have extra slashes in the name. This will
- *    be true if we have gotten it from Posix_RealPath or friends.
- *
- * Results:
- *    Returns a unicode string containing the canonical pathname to use.
- *    For VM directories not on NFS config VVol, this will be the same as
- *    absVMDirName.
- *    Caller has to free the returned unicode string using Unicode_Free.
- *
- * Side effects:
- *    None.
- *
- *----------------------------------------------------------------------------
- */
-
-static Unicode
-FileVMFSGetCanonicalPath(ConstUnicode absVMDirName)   // IN
-{
-   /*
-    * Max directory level that we will climb looking for an NFS config VVol.
-    * Don't set it very high or else we will hurt the common case.
-    */
-#define MAX_SUBDIR_LEVEL   1
-
-   VVol_IoctlArgs args;
-   VVolGetNFSCanonicalPathArgs *getCanonArgs = NULL;
-   uint16 fsType;
-   int ctrlfd = -1;
-   int searchDepth = MAX_SUBDIR_LEVEL;
-   /*
-    * Directory that we are currently verifying. This starts as
-    * absVMDirName and then keeps climbing to the parent one level
-    * at a time, till we exhaust searchDepth or we get a successful
-    * translation, indicating that we have hit an NFS config vvol
-    * directory, or we run outside the NFS filesystem.
-    */
-   Unicode currDir = NULL;
-   /*
-    * This holds the path fragment after the NFS config VVol. This will be
-    * non-empty in the case when absVMDirName refers to some subdir
-    * inside the NFS config VVol directory or it refers to a file (and not
-    * a directory). We keep collecting the path components as we change
-    * currDir one level at a time, and in the end append it to the resolved
-    * pathname before returning to the caller.
-    */
-   Unicode dirPath = NULL;
-   Unicode canonPath = NULL;  /* result */
-
-   /*
-    * The very first thing that we do is to open the VVol control node.
-    * This will fail if the VVol module is not loaded. In that case we
-    * short circuit to the failure case. This helps systems which do not
-    * use VVols, as we avoid the extra file opens (by File_IsDirectory
-    * and File_GetVMFSFSType) in those cases.
-    * Note that file opens are especially expensive on NFS.
-    * See PR 1007403.
-    */
-   ctrlfd = Posix_Open(VVOL_NAMESPACE_CONTROL_NODE, O_RDONLY);
-   if (ctrlfd < 0) {
-      goto use_same_path;
-   }
-
-   /*
-    * absVMDirName should start with /vmfs/volumes/.
-    */
-   if (!Unicode_StartsWith(absVMDirName, VCFS_MOUNT_PATH)) {
-      goto use_same_path;
-   }
-
-   /*
-    * If not already a directory, get the containing directory since the
-    * rest of the code works best on the containing directory, for following
-    * reasons:
-    *
-    * 1. File may be non-existent (diskCreate workflow).
-    * 2. File open may fail because of exclusive open by another process.
-    *    Directory open does not have this problem.
-    */
-   if (!File_IsDirectory(absVMDirName)) {
-      File_GetPathName(absVMDirName, &currDir, &dirPath);
-      ASSERT(currDir);
-      ASSERT(dirPath);
-   }
-
-   /*
-    * Only NFS config vvols can have a canonical name different from the
-    * absolute pathname provided. This will do the validity check also.
-    * Note that we make use of the fact that a file is on the same filesystem
-    * as it's containing directory.
-    */
-   if (File_GetVMFSFSType(currDir ? currDir : absVMDirName, -1, &fsType) != 0 ||
-       (fsType != NFSCLIENT_FSTYPENUM && fsType != NFS41CLIENT_FSTYPENUM)) {
-      goto use_same_path;
-   }
-
-   /*
-    * VM directory is on an NFS fileystem. It could be a regular NFS filesystem
-    * backed storage or an NFS config VVol. We need to check.
-    */
-   getCanonArgs = Util_SafeCalloc(1, sizeof(*getCanonArgs));
-
-   args.type = VVOL_GET_NFS_CANONICAL_PATH;
-   args.data = (uint64)(VA) getCanonArgs;
-   args.length = sizeof(*getCanonArgs);
-
-   /*
-    * Start searching for the NFS config VVol starting from absVMDirName
-    * (or currDir, if absVMDirName is not a directory).
-    * In most case this will be the NFS config VVol directory, but we also
-    * support cases where absVMDirName refers to a subdir inside the NFS
-    * config VVol directory.
-    */
-   do {
-      Unicode pathname, basename;
-
-      Unicode_CopyBytes(getCanonArgs->absNFSPath,
-                        currDir ? currDir : absVMDirName,
-                        sizeof(getCanonArgs->absNFSPath),
-                        NULL, STRING_ENCODING_UTF8);
-
-      if (ioctl(ctrlfd, IOCTLCMD_VMFS_VVOL, &args) == 0) {
-         /*
-          * ioctl successful. currDir refers to an NFS config VVol directory.
-          * getCanonArgs->canonPath contains the canonical path to use.
-          * This is the fastpath.
-          */
-         break;
-      } else if (errno != ENOENT) {
-         /*
-          * ENOENT indicates that the kernel did not find a matching bind
-          * mount. In that case we try climbing up one level and test that
-          * for an NFS config VVol.
-          */
-         goto use_same_path;
-      }
-
-      if (searchDepth == 0) {
-         goto use_same_path;
-      }
-      /*
-       * Try the next level dir.
-       */
-      File_GetPathName(currDir ? currDir : absVMDirName, &pathname, &basename);
-      Unicode_Free(currDir);
-      currDir = pathname;
-      /*
-       * Update dirPath that we eventually need to append to get the full path.
-       */
-      if (dirPath == NULL) {
-         dirPath = basename;
-      } else {
-         Unicode tmpDirPath = Unicode_Join(basename, DIRSEPS, dirPath, NULL);
-         Unicode_Free(basename);
-         Unicode_Free(dirPath);
-         dirPath = tmpDirPath;
-      }
-      /*
-       * If we have fallen off the NFS filesystem no need to search further,
-       * we can never find the config VVol.
-       */
-      if (File_GetVMFSFSType(currDir, -1, &fsType) != 0 ||
-          (fsType != NFSCLIENT_FSTYPENUM && fsType != NFS41CLIENT_FSTYPENUM)) {
-         goto use_same_path;
-      }
-   } while (searchDepth-- > 0);
-
-   canonPath = Unicode_Format("%s%s", getCanonArgs->canonPath,
-                              dirPath ? dirPath : "");
-
-done:
-   close(ctrlfd);
-   free(getCanonArgs);
-   Unicode_Free(currDir);
-   Unicode_Free(dirPath);
-   ASSERT(canonPath != NULL);
-   return canonPath;
-
-use_same_path:
-   ASSERT(canonPath == NULL);
-   canonPath = Unicode_Alloc(absVMDirName, STRING_ENCODING_DEFAULT);
-   goto done;
-}
-#endif
-
-
 /*
  *----------------------------------------------------------------------
  *
@@ -815,9 +594,6 @@ File_FullPath(ConstUnicode pathName)  // IN:
 {
    Unicode cwd;
    Unicode ret;
-#if defined(VMX86_SERVER)
-   Unicode canonPath;
-#endif
 
    if ((pathName != NULL) && File_IsFullPath(pathName)) {
       cwd = NULL;
@@ -848,21 +624,7 @@ File_FullPath(ConstUnicode pathName)  // IN:
 
    Unicode_Free(cwd);
 
-#if defined(VMX86_SERVER)
-   /*
-    * NFS config-VVols introduce a special type of in-kernel link called the
-    * bind mount. Posix_RealPath() doesn't resolve that. We need to resolve
-    * it explicitly.
-    * We don't want to store PE based path in any file. All configuration
-    * files should contain canonical path only.
-    */
-   canonPath = FileVMFSGetCanonicalPath(ret);
-   Unicode_Free(ret);
-
-   return canonPath;
-#else
    return ret;
-#endif
 }
 
 
index c30c0ebe1f1a92b84314e78ef123d5c170e74a73..a010c223de0f4c51de441446ec88d7f5c73a4963 100644 (file)
 #    endif
 #  elif defined(VMX86_VPX)
 #    define PRODUCT_LICENSE_VERSION "5.0"
-#    define PRODUCT_LICENSE_FILE_VERSION "5.5.0.0"
+#    define PRODUCT_LICENSE_FILE_VERSION "5.5.0.1"
 #  elif defined(VMX86_WBC)
 #    define PRODUCT_LICENSE_VERSION "1.0"
 #  elif defined(VMX86_SDK)
index fab4bda5106874f1304f53d3f6c8bfc4982f46cf..31e8005b9c275c8a067a2fd170f394dc1bc302d6 100644 (file)
@@ -19,5 +19,6 @@ noinst_LTLIBRARIES = libUser.la
 
 libUser_la_SOURCES =
 libUser_la_SOURCES += util.c
+libUser_la_SOURCES += utilBacktrace.c
 
 AM_CFLAGS = @LIB_USER_CPPFLAGS@
index 9c2d2dd8d1acbb4a36a03384e53c8e8dd728f0d0..2fa0bc5d81a070e545db9cece2f5abb021c95a1d 100644 (file)
@@ -35,7 +35,6 @@
 # include <winsock2.h> // also includes windows.h
 # include <io.h>
 # include <process.h>
-# include "coreDump.h"
 # include "getoptWin32.h"
 #endif
 
@@ -62,6 +61,8 @@
 #include "msg.h"
 #include "util.h"
 #include "str.h"
+/* For HARD_EXPIRE --hpreg */
+#include "vm_version.h"
 #include "su.h"
 #include "posix.h"
 #include "file.h"
 
 struct UtilVector {
    void *base;
-   int len;
+   int   len;
 };
 
 
-#ifdef VM_X86_64
-#   if defined(__GNUC__) && (!defined(USING_AUTOCONF) || defined(HAVE_UNWIND_H))
-#      define UTIL_BACKTRACE_USE_UNWIND
-#   endif
-#endif
-
-#ifdef UTIL_BACKTRACE_USE_UNWIND
-#include <unwind.h>
-
-#define MAX_SKIPPED_FRAMES 10
-
-struct UtilBacktraceFromPointerData {
-   uintptr_t        basePtr;
-   Util_OutputFunc  outFunc;
-   void            *outFuncData;
-   unsigned int     frameNr;
-   unsigned int     skippedFrames;
-};
-
-struct UtilBacktraceToBufferData {
-   uintptr_t        basePtr;
-   uintptr_t       *buffer;
-   size_t           len;
-};
-#endif /* UTIL_BACKTRACE_USE_UNWIND */
-
 
 /*
  *----------------------------------------------------------------------
@@ -279,384 +254,6 @@ Util_HashString(const char *str)  // IN:
 }
 
 
-/*
- *-----------------------------------------------------------------------------
- *
- * UtilLogWrapper --
- *
- *      Adapts the Log function to meet the interface required by backtracing
- *      functions by adding an ignored void* argument.
- *
- *      NOTE: This function needs to be static on linux (and any other
- *      platform appLoader might be ported to).  See bug 403780.
- *
- * Results:
- *      Same effect as Log(fmt, ...)
- *
- * Side effects:
- *      None.
- *
- *-----------------------------------------------------------------------------
- */
-
-static void
-UtilLogWrapper(void *ignored,    // IN:
-               const char *fmt,  // IN:
-               ...)              // IN:
-{
-   uint32 len;
-   va_list ap;
-   char thisLine[UTIL_BACKTRACE_LINE_LEN];
-
-   va_start(ap, fmt);
-   len = Str_Vsnprintf(thisLine, UTIL_BACKTRACE_LINE_LEN - 2, fmt, ap);
-   va_end(ap);
-
-   if (len >= UTIL_BACKTRACE_LINE_LEN - 2) {
-      len = UTIL_BACKTRACE_LINE_LEN - 3;
-   }
-
-   if (thisLine[len - 1] != '\n') {
-      thisLine[len] = '\n';
-      thisLine[len + 1] = '\0';
-   }
-
-   Log("%s", thisLine);
-}
-
-
-#ifdef UTIL_BACKTRACE_USE_UNWIND
-/*
- *-----------------------------------------------------------------------------
- *
- * UtilBacktraceToBufferCallback --
- *
- *      Callback from _Unwind_Backtrace to add one entry to the backtrace
- *      buffer.
- *
- * Results:
- *      _URC_NO_REASON : Please continue with backtrace.
- *      _URC_END_OF_STACK : Abort backtrace, we run out of space (*).
- *
- *          (*) Caller does not care.  Anything else than NO_REASON is fatal
- *              and forces _Unwind_Backtrace to report PHASE1 error.
- *
- * Side effects:
- *      None.
- *
- *-----------------------------------------------------------------------------
- */
-
-static _Unwind_Reason_Code
-UtilBacktraceToBufferCallback(struct _Unwind_Context *ctx, // IN: Unwind context
-                              void *cbData)                // IN/OUT: Our data
-{
-   struct UtilBacktraceToBufferData *data = cbData;
-   uintptr_t cfa = _Unwind_GetCFA(ctx);
-
-   /*
-    * Stack grows down.  So if we are below basePtr, do nothing...
-    */
-   if (cfa >= data->basePtr) {
-      if (data->len) {
-         *data->buffer++ = _Unwind_GetIP(ctx);
-         data->len--;
-      } else {
-         return _URC_END_OF_STACK;
-      }
-   }
-   return _URC_NO_REASON;
-}
-
-
-/*
- *-----------------------------------------------------------------------------
- *
- * UtilBacktraceFromPointerCallback --
- *
- *      Callback from _Unwind_Backtrace to print one backtrace entry
- *      to the backtrace output.
- *
- * Results:
- *      _URC_NO_REASON : Please continue with backtrace.
- *      _URC_END_OF_STACK : Abort backtrace.
- *
- * Side effects:
- *      None.
- *
- *-----------------------------------------------------------------------------
- */
-
-static _Unwind_Reason_Code
-UtilBacktraceFromPointerCallback(struct _Unwind_Context *ctx, // IN: Unwind context
-                                 void *cbData)                // IN/OUT: Our status
-{
-   struct UtilBacktraceFromPointerData *data = cbData;
-   uintptr_t cfa = _Unwind_GetCFA(ctx);
-
-   /*
-    * Stack grows down.  So if we are below basePtr, do nothing...
-    */
-
-   if (cfa >= data->basePtr && data->frameNr < 500) {
-#ifndef VM_X86_64
-#   error You should not build this on 32bit - there is no eh_frame there.
-#endif
-      /* bump basePtr for glibc unwind bug, see [302237] */
-      data->basePtr = cfa + 8;
-      /* Do output without leading '0x' to save some horizontal space... */
-      data->outFunc(data->outFuncData,
-                    "Backtrace[%u] %016lx rip=%016lx rbx=%016lx rbp=%016lx "
-                    "r12=%016lx r13=%016lx r14=%016lx r15=%016lx\n",
-                    data->frameNr, cfa, _Unwind_GetIP(ctx),
-                    _Unwind_GetGR(ctx, 3), _Unwind_GetGR(ctx, 6),
-                    _Unwind_GetGR(ctx, 12), _Unwind_GetGR(ctx, 13),
-                    _Unwind_GetGR(ctx, 14), _Unwind_GetGR(ctx, 15));
-      data->frameNr++;
-      return _URC_NO_REASON;
-   } else if (data->skippedFrames < MAX_SKIPPED_FRAMES && !data->frameNr) {
-      /*
-       * Skip over the frames before the specified starting point of the
-       * backtrace.
-       */
-
-      data->skippedFrames++;
-      return _URC_NO_REASON;
-   }
-   return _URC_END_OF_STACK;
-}
-
-#if !defined(_WIN32) && !defined(VMX86_TOOLS) && !defined(__ANDROID__)
-/*
- *-----------------------------------------------------------------------------
- *
- * UtilSymbolBacktraceFromPointerCallback --
- *
- *      Callback from _Unwind_Backtrace to print one backtrace entry
- *      to the backtrace output.  This version includes symbol information,
- *      if available.
- *
- * Results:
- *      _URC_NO_REASON : Please continue with backtrace.
- *
- * Side effects:
- *      None.
- *
- *-----------------------------------------------------------------------------
- */
-
-static _Unwind_Reason_Code
-UtilSymbolBacktraceFromPointerCallback(struct _Unwind_Context *ctx, // IN: Unwind context
-                                       void *cbData)                // IN/OUT: Our status
-{
-   struct UtilBacktraceFromPointerData *data = cbData;
-   uintptr_t cfa = _Unwind_GetCFA(ctx);   
-
-   /*
-    * Stack grows down.  So if we are below basePtr, do nothing...
-    */
-
-   if (cfa >= data->basePtr && data->frameNr < 500) {
-#ifndef VM_X86_64
-#   error You should not build this on 32bit - there is no eh_frame there.
-#endif
-      void *enclFuncAddr;
-      Dl_info dli;
-
-      /* bump basePtr for glibc unwind bug, see [302237] */
-      data->basePtr = cfa + 8;
-#ifdef __linux__
-      enclFuncAddr = _Unwind_FindEnclosingFunction((void *)_Unwind_GetIP(ctx));
-#else
-      enclFuncAddr = NULL;
-#endif
-      if (dladdr(enclFuncAddr, &dli) ||
-          dladdr((void *)_Unwind_GetIP(ctx), &dli)) {
-         data->outFunc(data->outFuncData,
-                      "SymBacktrace[%u] %016lx rip=%016lx in function %s "
-                      "in object %s loaded at %016lx\n",
-                      data->frameNr, cfa, _Unwind_GetIP(ctx),
-                      dli.dli_sname, dli.dli_fname, dli.dli_fbase);
-      } else {
-         data->outFunc(data->outFuncData,
-                      "SymBacktrace[%u] %016lx rip=%016lx \n",
-                      data->frameNr, cfa, _Unwind_GetIP(ctx));
-      }
-      data->frameNr++;
-      return _URC_NO_REASON;
-   } else if (data->skippedFrames < MAX_SKIPPED_FRAMES && !data->frameNr) {
-      /*
-       * Skip over the frames before the specified starting point of the
-       * backtrace.
-       */
-
-      data->skippedFrames++;
-      return _URC_NO_REASON;
-   }
-   return _URC_END_OF_STACK;
-}
-#endif
-#endif
-
-
-/*
- *----------------------------------------------------------------------
- *
- * Util_BacktraceFromPointer --
- *
- *      log the stack backtrace given a frame pointer
- *
- * Results:
- *
- *      void
- *
- * Side effects:
- *      None.
- *
- *----------------------------------------------------------------------
- */
-
-void
-Util_BacktraceFromPointer(uintptr_t *basePtr)
-{
-   Util_BacktraceFromPointerWithFunc(basePtr, UtilLogWrapper, NULL);
-}
-
-
-/*
- *-----------------------------------------------------------------------------
- *
- * Util_BacktraceFromPointerWithFunc --
- *
- *      Output a backtrace from the given frame porinter, using
- *      "outputFunc" as the logging function. For each line of the backtrace,
- *      this will call "outputFunc(outputFuncData, fmt, ...)"
- *
- * Results:
- *      None.
- *
- * Side effects:
- *      Calls outFunc repeatedly.
- *
- *-----------------------------------------------------------------------------
- */
-
-void
-Util_BacktraceFromPointerWithFunc(uintptr_t *basePtr,
-                                  Util_OutputFunc outFunc,
-                                  void *outFuncData)
-{
-#if defined(UTIL_BACKTRACE_USE_UNWIND)
-   struct UtilBacktraceFromPointerData data;
-
-   data.basePtr = (uintptr_t)basePtr;
-   data.outFunc = outFunc;
-   data.outFuncData = outFuncData;
-   data.frameNr = 0;
-   data.skippedFrames = 0;
-   _Unwind_Backtrace(UtilBacktraceFromPointerCallback, &data);
-
-#if !defined(_WIN32) && !defined(VMX86_TOOLS)
-   /* 
-    * We do a separate pass here that includes symbols in order to
-    * make sure the base backtrace that does not call dladdr() etc.
-    * is safely produced.
-    */
-   data.basePtr = (uintptr_t)basePtr;
-   data.outFunc = outFunc;
-   data.outFuncData = outFuncData;
-   data.frameNr = 0;
-   data.skippedFrames = 0;
-   _Unwind_Backtrace(UtilSymbolBacktraceFromPointerCallback, &data);
-#endif
-
-#elif !defined(VM_X86_64)
-   uintptr_t *x = basePtr;
-   int i;
-#if !defined(_WIN32) && !defined(VMX86_TOOLS) && !defined(__ANDROID__)
-   Dl_info dli;
-#endif
-
-   for (i = 0; i < 256; i++) {
-      if (x < basePtr ||
-         (uintptr_t) x - (uintptr_t) basePtr > 0x8000) {
-         break;
-      }
-      outFunc(outFuncData, "Backtrace[%d] %#08x eip %#08x \n", i, x[0], x[1]);
-      x = (uintptr_t *) x[0];
-   }
-
-#if !defined(_WIN32) && !defined(VMX86_TOOLS) && !defined(__ANDROID__)
-   /* 
-    * We do a separate pass here that includes symbols in order to
-    * make sure the base backtrace that does not call dladdr() etc.
-    * is safely produced.
-    */
-   x = basePtr;
-   for (i = 0; i < 256; i++) {
-      if (x < basePtr ||
-         (uintptr_t) x - (uintptr_t) basePtr > 0x8000) {
-         break;
-      }
-      if (dladdr((uintptr_t *)x[1], &dli)) {
-         outFunc(outFuncData, "SymBacktrace[%d] %#08x eip %#08x in function %s "
-                              "in object %s loaded at %#08x\n",
-                               i, x[0], x[1], dli.dli_sname, dli.dli_fname,
-                                dli.dli_fbase);
-      } else {
-         outFunc(outFuncData, "SymBacktrace[%d] %#08x eip %#08x \n", i, x[0], x[1]);
-      }
-      x = (uintptr_t *) x[0];
-   }
-#endif
-#endif
-}
-
-
-/*
- *-----------------------------------------------------------------------------
- *
- * Util_BacktraceToBuffer --
- *
- *      Output a backtrace from the given frame pointer to supplied buffer.
- *
- * Results:
- *      None.
- *
- * Side effects:
- *      See above.
- *
- *-----------------------------------------------------------------------------
- */
-
-void
-Util_BacktraceToBuffer(uintptr_t *basePtr,
-                       uintptr_t *buffer,
-                       int len)
-{
-#if defined(UTIL_BACKTRACE_USE_UNWIND)
-   struct UtilBacktraceToBufferData data;
-
-   data.basePtr = (uintptr_t)basePtr;
-   data.buffer = buffer;
-   data.len = len;
-   _Unwind_Backtrace(UtilBacktraceToBufferCallback, &data);
-#elif !defined(VM_X86_64)
-   uintptr_t *x = basePtr;
-   int i;
-
-   for (i = 0; i < 256 && i < len; i++) {
-      if (x < basePtr ||
-         (uintptr_t) x - (uintptr_t) basePtr > 0x8000) {
-         break;
-      }
-      buffer[i] = x[1];
-      x = (uintptr_t *) x[0];
-   }
-#endif
-}
-
-
 /*
  *----------------------------------------------------------------------
  *
@@ -707,131 +304,6 @@ Util_Data2Buffer(char *buf,         // OUT
 }
 
 
-/*
- *----------------------------------------------------------------------
- *
- * Util_Backtrace --
- *
- *      log the stack backtrace for a particular bug number
- *
- * Results:
- *
- *      void
- *
- * Side effects:
- *      None.
- *
- *----------------------------------------------------------------------
- */
-
-void
-Util_Backtrace(int bugNr) // IN
-{
-   Util_BacktraceWithFunc(bugNr, UtilLogWrapper, NULL);
-}
-
-
-/*
- *-----------------------------------------------------------------------------
- *
- * Util_BacktraceWithFunc --
- *
- *      Outputs the stack backtrace for the bug "bugNr," using the
- *      log function "outFunc" as described in the comment for
- *      Util_BacktraceFromPointerWithFunc.
- *
- * Results:
- *      None.
- *
- * Side effects:
- *      Calls outFunc several times.
- *
- *-----------------------------------------------------------------------------
- */
-
-void
-Util_BacktraceWithFunc(int bugNr, Util_OutputFunc outFunc, void *outFuncData)
-{
-#if !defined(_WIN32)
-   uintptr_t *x = (uintptr_t *) &bugNr;
-#endif
-
-   if (bugNr == 0) {
-      outFunc(outFuncData, "Backtrace:\n");
-   } else {
-      outFunc(outFuncData, "Backtrace for bugNr=%d\n",bugNr);
-   }
-#if defined(_WIN32)
-   CoreDump_Backtrace(outFunc, outFuncData);
-#else
-   Util_BacktraceFromPointerWithFunc(&x[-2], outFunc, outFuncData);
-#endif
-}
-
-
-/* XXX This should go in a separate utilPosix.c file --hpreg */
-#if !defined(_WIN32)
-/*
- *----------------------------------------------------------------------
- *
- * Util_MakeSureDirExists --
- *
- *    Make sure a directory exists
- *
- * Results:
- *    TRUE on success
- *    FALSE on failure
- *
- * Side effects:
- *    None
- *
- *----------------------------------------------------------------------
- */
-
-Bool
-Util_MakeSureDirExistsAndAccessible(char const *path,  // IN
-                                   unsigned int mode) // IN
-{
-   char *epath;
-   struct stat statbuf;
-
-   epath = Util_ExpandString(path);
-   if (epath == NULL) {
-      return FALSE;
-   }
-
-   if (Posix_Stat(epath, &statbuf) == 0) {
-      if (! S_ISDIR(statbuf.st_mode)) {
-        Msg_Append(MSGID(util.msde.notDir)
-                   "The path \"%s\" exists, but it is not a directory.\n",
-                   epath);
-        free(epath);
-        return FALSE;
-      }
-   } else {
-      if (Posix_Mkdir(epath, mode) != 0) {
-        Msg_Append(MSGID(util.msde.mkdir)
-                   "Cannot create directory \"%s\": %s.\n",
-                   epath, Msg_ErrString());
-        free(epath);
-        return FALSE;
-      }
-   }
-   if (FileIO_Access(epath, FILEIO_ACCESS_READ | FILEIO_ACCESS_WRITE | FILEIO_ACCESS_EXEC | FILEIO_ACCESS_EXISTS) ==
-       FILEIO_ERROR) {
-      Msg_Append(MSGID(util.msde.noAccess)
-                "Directory \"%s\" is not accessible: %s.\n",
-                epath, Msg_ErrString());
-      free(epath);
-      return FALSE;
-   }
-   free(epath);
-
-   return TRUE;
-}
-#endif
-
-
 /*
  *----------------------------------------------------------------------
  *
@@ -839,7 +311,7 @@ Util_MakeSureDirExistsAndAccessible(char const *path,  // IN
  *
  *    On Win32, terminate the process and all of its threads, without
  *    calling any of the DLL termination handlers.
-
+ *
  *    On Linux, call _exit().
  *
  * Results:
diff --git a/open-vm-tools/lib/user/utilBacktrace.c b/open-vm-tools/lib/user/utilBacktrace.c
new file mode 100644 (file)
index 0000000..90d6b56
--- /dev/null
@@ -0,0 +1,521 @@
+/*********************************************************
+ * Copyright (C) 2013 VMware, Inc. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published
+ * by the Free Software Foundation version 2.1 and no 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 Lesser GNU General Public
+ * License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA.
+ *
+ *********************************************************/
+
+/*
+ * utilBacktrace.c --
+ *
+ *    misc util functions
+ */
+
+#undef WIN32_LEAN_AND_MEAN
+
+#if defined(__linux__) && !defined(VMX86_TOOLS)
+#define _GNU_SOURCE
+#endif
+
+#include "vm_ctype.h"
+#include "safetime.h"
+
+#if defined(_WIN32)
+# include <winsock2.h> // also includes windows.h
+# include <io.h>
+# include <process.h>
+# include "coreDump.h"
+#endif
+
+#if !defined(_WIN32)
+#  include <unistd.h>
+#  include <pwd.h>
+#  include <dlfcn.h>
+#endif
+
+#if defined(__linux__) && !defined(VMX86_TOOLS) && !defined(__ANDROID__)
+#  include <link.h>
+#endif
+
+#include "vmware.h"
+#include "util.h"
+#include "str.h"
+
+#ifdef VM_X86_64
+#   if defined(__GNUC__) && (!defined(USING_AUTOCONF) || defined(HAVE_UNWIND_H))
+#      define UTIL_BACKTRACE_USE_UNWIND
+#   endif
+#endif
+
+#ifdef UTIL_BACKTRACE_USE_UNWIND
+#include <unwind.h>
+
+#define MAX_SKIPPED_FRAMES 10
+
+struct UtilBacktraceFromPointerData {
+   uintptr_t        basePtr;
+   Util_OutputFunc  outFunc;
+   void            *outFuncData;
+   unsigned int     frameNr;
+   unsigned int     skippedFrames;
+};
+
+struct UtilBacktraceToBufferData {
+   uintptr_t        basePtr;
+   uintptr_t       *buffer;
+   size_t           len;
+};
+#endif /* UTIL_BACKTRACE_USE_UNWIND */
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * UtilLogWrapper --
+ *
+ *      Adapts the Log function to meet the interface required by backtracing
+ *      functions by adding an ignored void* argument.
+ *
+ *      NOTE: This function needs to be static on linux (and any other
+ *      platform appLoader might be ported to).  See bug 403780.
+ *
+ * Results:
+ *      Same effect as Log(fmt, ...)
+ *
+ * Side effects:
+ *      None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static void
+UtilLogWrapper(void *ignored,    // IN:
+               const char *fmt,  // IN:
+               ...)              // IN:
+{
+   uint32 len;
+   va_list ap;
+   char thisLine[UTIL_BACKTRACE_LINE_LEN];
+
+   va_start(ap, fmt);
+   len = Str_Vsnprintf(thisLine, UTIL_BACKTRACE_LINE_LEN - 2, fmt, ap);
+   va_end(ap);
+
+   if (len >= UTIL_BACKTRACE_LINE_LEN - 2) {
+      len = UTIL_BACKTRACE_LINE_LEN - 3;
+   }
+
+   if (thisLine[len - 1] != '\n') {
+      thisLine[len] = '\n';
+      thisLine[len + 1] = '\0';
+   }
+
+   Log("%s", thisLine);
+}
+
+
+#ifdef UTIL_BACKTRACE_USE_UNWIND
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * UtilBacktraceToBufferCallback --
+ *
+ *      Callback from _Unwind_Backtrace to add one entry to the backtrace
+ *      buffer.
+ *
+ * Results:
+ *      _URC_NO_REASON : Please continue with backtrace.
+ *      _URC_END_OF_STACK : Abort backtrace, we run out of space (*).
+ *
+ *          (*) Caller does not care.  Anything else than NO_REASON is fatal
+ *              and forces _Unwind_Backtrace to report PHASE1 error.
+ *
+ * Side effects:
+ *      None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static _Unwind_Reason_Code
+UtilBacktraceToBufferCallback(struct _Unwind_Context *ctx, // IN: Unwind context
+                              void *cbData)                // IN/OUT: Our data
+{
+   struct UtilBacktraceToBufferData *data = cbData;
+   uintptr_t cfa = _Unwind_GetCFA(ctx);
+
+   /*
+    * Stack grows down.  So if we are below basePtr, do nothing...
+    */
+   if (cfa >= data->basePtr) {
+      if (data->len) {
+         *data->buffer++ = _Unwind_GetIP(ctx);
+         data->len--;
+      } else {
+         return _URC_END_OF_STACK;
+      }
+   }
+   return _URC_NO_REASON;
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * UtilBacktraceFromPointerCallback --
+ *
+ *      Callback from _Unwind_Backtrace to print one backtrace entry
+ *      to the backtrace output.
+ *
+ * Results:
+ *      _URC_NO_REASON : Please continue with backtrace.
+ *      _URC_END_OF_STACK : Abort backtrace.
+ *
+ * Side effects:
+ *      None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static _Unwind_Reason_Code
+UtilBacktraceFromPointerCallback(struct _Unwind_Context *ctx, // IN: Unwind context
+                                 void *cbData)                // IN/OUT: Our status
+{
+   struct UtilBacktraceFromPointerData *data = cbData;
+   uintptr_t cfa = _Unwind_GetCFA(ctx);
+
+   /*
+    * Stack grows down.  So if we are below basePtr, do nothing...
+    */
+
+   if (cfa >= data->basePtr && data->frameNr < 500) {
+#ifndef VM_X86_64
+#   error You should not build this on 32bit - there is no eh_frame there.
+#endif
+      /* bump basePtr for glibc unwind bug, see [302237] */
+      data->basePtr = cfa + 8;
+      /* Do output without leading '0x' to save some horizontal space... */
+      data->outFunc(data->outFuncData,
+                    "Backtrace[%u] %016lx rip=%016lx rbx=%016lx rbp=%016lx "
+                    "r12=%016lx r13=%016lx r14=%016lx r15=%016lx\n",
+                    data->frameNr, cfa, _Unwind_GetIP(ctx),
+                    _Unwind_GetGR(ctx, 3), _Unwind_GetGR(ctx, 6),
+                    _Unwind_GetGR(ctx, 12), _Unwind_GetGR(ctx, 13),
+                    _Unwind_GetGR(ctx, 14), _Unwind_GetGR(ctx, 15));
+      data->frameNr++;
+      return _URC_NO_REASON;
+   } else if (data->skippedFrames < MAX_SKIPPED_FRAMES && !data->frameNr) {
+      /*
+       * Skip over the frames before the specified starting point of the
+       * backtrace.
+       */
+
+      data->skippedFrames++;
+      return _URC_NO_REASON;
+   }
+   return _URC_END_OF_STACK;
+}
+
+#if !defined(_WIN32) && !defined(VMX86_TOOLS) && !defined(__ANDROID__)
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * UtilSymbolBacktraceFromPointerCallback --
+ *
+ *      Callback from _Unwind_Backtrace to print one backtrace entry
+ *      to the backtrace output.  This version includes symbol information,
+ *      if available.
+ *
+ * Results:
+ *      _URC_NO_REASON : Please continue with backtrace.
+ *
+ * Side effects:
+ *      None.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static _Unwind_Reason_Code
+UtilSymbolBacktraceFromPointerCallback(struct _Unwind_Context *ctx, // IN: Unwind context
+                                       void *cbData)                // IN/OUT: Our status
+{
+   struct UtilBacktraceFromPointerData *data = cbData;
+   uintptr_t cfa = _Unwind_GetCFA(ctx);
+
+   /*
+    * Stack grows down.  So if we are below basePtr, do nothing...
+    */
+
+   if (cfa >= data->basePtr && data->frameNr < 500) {
+#ifndef VM_X86_64
+#   error You should not build this on 32bit - there is no eh_frame there.
+#endif
+      void *enclFuncAddr;
+      Dl_info dli;
+
+      /* bump basePtr for glibc unwind bug, see [302237] */
+      data->basePtr = cfa + 8;
+#ifdef __linux__
+      enclFuncAddr = _Unwind_FindEnclosingFunction((void *)_Unwind_GetIP(ctx));
+#else
+      enclFuncAddr = NULL;
+#endif
+      if (dladdr(enclFuncAddr, &dli) ||
+          dladdr((void *)_Unwind_GetIP(ctx), &dli)) {
+         data->outFunc(data->outFuncData,
+                      "SymBacktrace[%u] %016lx rip=%016lx in function %s "
+                      "in object %s loaded at %016lx\n",
+                      data->frameNr, cfa, _Unwind_GetIP(ctx),
+                      dli.dli_sname, dli.dli_fname, dli.dli_fbase);
+      } else {
+         data->outFunc(data->outFuncData,
+                      "SymBacktrace[%u] %016lx rip=%016lx \n",
+                      data->frameNr, cfa, _Unwind_GetIP(ctx));
+      }
+      data->frameNr++;
+      return _URC_NO_REASON;
+   } else if (data->skippedFrames < MAX_SKIPPED_FRAMES && !data->frameNr) {
+      /*
+       * Skip over the frames before the specified starting point of the
+       * backtrace.
+       */
+
+      data->skippedFrames++;
+      return _URC_NO_REASON;
+   }
+   return _URC_END_OF_STACK;
+}
+#endif
+#endif
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Util_BacktraceFromPointer --
+ *
+ *      log the stack backtrace given a frame pointer
+ *
+ * Results:
+ *
+ *      void
+ *
+ * Side effects:
+ *      None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Util_BacktraceFromPointer(uintptr_t *basePtr)  // IN:
+{
+   Util_BacktraceFromPointerWithFunc(basePtr, UtilLogWrapper, NULL);
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Util_BacktraceFromPointerWithFunc --
+ *
+ *      Output a backtrace from the given frame porinter, using
+ *      "outputFunc" as the logging function. For each line of the backtrace,
+ *      this will call "outputFunc(outputFuncData, fmt, ...)"
+ *
+ * Results:
+ *      None.
+ *
+ * Side effects:
+ *      Calls outFunc repeatedly.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+Util_BacktraceFromPointerWithFunc(uintptr_t *basePtr,       // IN:
+                                  Util_OutputFunc outFunc,  // IN:
+                                  void *outFuncData)        // IN:
+{
+#if defined(UTIL_BACKTRACE_USE_UNWIND)
+   struct UtilBacktraceFromPointerData data;
+
+   data.basePtr = (uintptr_t)basePtr;
+   data.outFunc = outFunc;
+   data.outFuncData = outFuncData;
+   data.frameNr = 0;
+   data.skippedFrames = 0;
+   _Unwind_Backtrace(UtilBacktraceFromPointerCallback, &data);
+
+#if !defined(_WIN32) && !defined(VMX86_TOOLS)
+   /*
+    * We do a separate pass here that includes symbols in order to
+    * make sure the base backtrace that does not call dladdr() etc.
+    * is safely produced.
+    */
+   data.basePtr = (uintptr_t)basePtr;
+   data.outFunc = outFunc;
+   data.outFuncData = outFuncData;
+   data.frameNr = 0;
+   data.skippedFrames = 0;
+   _Unwind_Backtrace(UtilSymbolBacktraceFromPointerCallback, &data);
+#endif
+
+#elif !defined(VM_X86_64)
+   uintptr_t *x = basePtr;
+   int i;
+#if !defined(_WIN32) && !defined(VMX86_TOOLS) && !defined(__ANDROID__)
+   Dl_info dli;
+#endif
+
+   for (i = 0; i < 256; i++) {
+      if (x < basePtr ||
+         (uintptr_t) x - (uintptr_t) basePtr > 0x8000) {
+         break;
+      }
+      outFunc(outFuncData, "Backtrace[%d] %#08x eip %#08x \n", i, x[0], x[1]);
+      x = (uintptr_t *) x[0];
+   }
+
+#if !defined(_WIN32) && !defined(VMX86_TOOLS) && !defined(__ANDROID__)
+   /*
+    * We do a separate pass here that includes symbols in order to
+    * make sure the base backtrace that does not call dladdr() etc.
+    * is safely produced.
+    */
+   x = basePtr;
+   for (i = 0; i < 256; i++) {
+      if (x < basePtr ||
+         (uintptr_t) x - (uintptr_t) basePtr > 0x8000) {
+         break;
+      }
+      if (dladdr((uintptr_t *)x[1], &dli)) {
+         outFunc(outFuncData, "SymBacktrace[%d] %#08x eip %#08x in function %s "
+                              "in object %s loaded at %#08x\n",
+                               i, x[0], x[1], dli.dli_sname, dli.dli_fname,
+                                dli.dli_fbase);
+      } else {
+         outFunc(outFuncData, "SymBacktrace[%d] %#08x eip %#08x \n", i, x[0], x[1]);
+      }
+      x = (uintptr_t *) x[0];
+   }
+#endif
+#endif
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Util_BacktraceToBuffer --
+ *
+ *      Output a backtrace from the given frame pointer to supplied buffer.
+ *
+ * Results:
+ *      None.
+ *
+ * Side effects:
+ *      See above.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+Util_BacktraceToBuffer(uintptr_t *basePtr,  // IN:
+                       uintptr_t *buffer,   // IN:
+                       int len)             // IN:
+{
+#if defined(UTIL_BACKTRACE_USE_UNWIND)
+   struct UtilBacktraceToBufferData data;
+
+   data.basePtr = (uintptr_t)basePtr;
+   data.buffer = buffer;
+   data.len = len;
+   _Unwind_Backtrace(UtilBacktraceToBufferCallback, &data);
+#elif !defined(VM_X86_64)
+   uintptr_t *x = basePtr;
+   int i;
+
+   for (i = 0; i < 256 && i < len; i++) {
+      if (x < basePtr ||
+         (uintptr_t) x - (uintptr_t) basePtr > 0x8000) {
+         break;
+      }
+      buffer[i] = x[1];
+      x = (uintptr_t *) x[0];
+   }
+#endif
+}
+
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Util_Backtrace --
+ *
+ *      log the stack backtrace for a particular bug number
+ *
+ * Results:
+ *
+ *      void
+ *
+ * Side effects:
+ *      None.
+ *
+ *----------------------------------------------------------------------
+ */
+
+void
+Util_Backtrace(int bugNr) // IN
+{
+   Util_BacktraceWithFunc(bugNr, UtilLogWrapper, NULL);
+}
+
+
+/*
+ *-----------------------------------------------------------------------------
+ *
+ * Util_BacktraceWithFunc --
+ *
+ *      Outputs the stack backtrace for the bug "bugNr," using the
+ *      log function "outFunc" as described in the comment for
+ *      Util_BacktraceFromPointerWithFunc.
+ *
+ * Results:
+ *      None.
+ *
+ * Side effects:
+ *      Calls outFunc several times.
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+void
+Util_BacktraceWithFunc(int bugNr,                // IN:
+                       Util_OutputFunc outFunc,  // IN:
+                       void *outFuncData)        // IN:
+{
+#if !defined(_WIN32)
+   uintptr_t *x = (uintptr_t *) &bugNr;
+#endif
+
+   if (bugNr == 0) {
+      outFunc(outFuncData, "Backtrace:\n");
+   } else {
+      outFunc(outFuncData, "Backtrace for bugNr=%d\n",bugNr);
+   }
+#if defined(_WIN32)
+   CoreDump_Backtrace(outFunc, outFuncData);
+#else
+   Util_BacktraceFromPointerWithFunc(&x[-2], outFunc, outFuncData);
+#endif
+}