/**
 * Find line by address (nearest).
 *
 * @returns VBox status.
 * @param   pVM                 VM handle.
 * @param   Address             Address.
 * @param   poffDisplacement    Where to store the line displacement from Address.
 * @param   pLine               Where to store the line info.
 */
VMMR3DECL(int) DBGFR3LineByAddr(PVM pVM, RTGCUINTPTR Address, PRTGCINTPTR poffDisplacement, PDBGFLINE pLine)
{
    /*
     * Lazy init.
     */
    if (!pVM->dbgf.s.fSymInited)
    {
        int rc = dbgfR3SymLazyInit(pVM);
        if (RT_FAILURE(rc))
            return rc;
    }

    /*
     * Look it up.
     */
#ifdef HAVE_DBGHELP
    IMAGEHLP_LINE64     Line = {0};
    DWORD               off = 0;
    Line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
    if (SymGetLineFromAddr64(pVM, Address, &off, &Line))
    {
        if (poffDisplacement)
            *poffDisplacement = (long)off;
        pLine->Address      = (RTGCUINTPTR)Line.Address;
        pLine->uLineNo      = Line.LineNumber;
        pLine->szFilename[0] = '\0';
        strncat(pLine->szFilename, Line.FileName, sizeof(pLine->szFilename));
        return VINF_SUCCESS;
    }
    return win32Error(pVM);
#else
    return VERR_NOT_IMPLEMENTED;
#endif
}
/**
 * Adds a symbol to the debug info manager.
 *
 * @returns VBox status.
 * @param   pVM             VM Handle.
 * @param   ModuleAddress   Module address. Use 0 if no module.
 * @param   SymbolAddress   Symbol address
 * @param   cbSymbol        Size of the symbol. Use 0 if info not available.
 * @param   pszSymbol       Symbol name.
 */
VMMR3DECL(int) DBGFR3SymbolAdd(PVM pVM, RTGCUINTPTR ModuleAddress, RTGCUINTPTR SymbolAddress, RTUINT cbSymbol, const char *pszSymbol)
{
    /*
     * Validate.
     */
    if (!pszSymbol || !*pszSymbol)
    {
        AssertMsgFailed(("No symbol name!\n"));
        return VERR_INVALID_PARAMETER;
    }

    /*
     * Lazy init.
     */
    if (!pVM->dbgf.s.fSymInited)
    {
        int rc = dbgfR3SymLazyInit(pVM);
        if (RT_FAILURE(rc))
            return rc;
    }

#ifdef HAVE_DBGHELP
    if (SymAddSymbol(pVM, ModuleAddress, (char *)(void *)pszSymbol, SymbolAddress, cbSymbol, 0))
        return VINF_SUCCESS;
    return win32Error(pVM);
#else
    /** @todo module lookup. */
    return dbgfR3SymbolInsert(pVM, pszSymbol, SymbolAddress, cbSymbol, NULL);
#endif
}
Beispiel #3
0
JNIEXPORT jint JNICALL
Java_java_lang_ProcessImpl_getExitCodeProcess(JNIEnv *env, jclass ignored, jlong handle)
{
    DWORD exit_code;
    if (GetExitCodeProcess((HANDLE) handle, &exit_code) == 0)
        win32Error(env, "GetExitCodeProcess");
    return exit_code;
}
/* Responsible for correct initialization of the [pHolder] structure
   (that is used for handles recycling) if needs,
   and appropriate setup of IOE handle [phStd] for child process based
   on created pipe or Java handle. */
static BOOL initHolder(
    JNIEnv *env,
    jlong *pjhandles,   /* IN OUT - the handle form Java,
                                    that can be a file, console or undefined */
    STDHOLDER *pHolder, /* OUT    - initialized structure that holds pipe
                                    handles */
    HANDLE *phStd       /* OUT    - initialized handle for child process */
) {
    /* Here we test the value from Java against invalid
       handle value. We are not using INVALID_HANDLE_VALUE macro
       due to double signed/unsigned and 32/64bit ambiguity.
       Otherwise it will be easy to get the wrong
       value   0x00000000FFFFFFFF
       instead 0xFFFFFFFFFFFFFFFF. */
    if (*pjhandles != JAVA_INVALID_HANDLE_VALUE) {
        /* Java file or console redirection */
        *phStd = (HANDLE) *pjhandles;
        /* Here we set the related Java stream (Process.getXXXXStream())
           to [ProcessBuilder.NullXXXXStream.INSTANCE] value.
           The initial Java handle [*pjhandles] will be closed in
           ANY case. It is not a handle leak. */
        *pjhandles = JAVA_INVALID_HANDLE_VALUE;
    } else {
        /* Creation of parent-child pipe */
        if (!CreatePipe(
            &pHolder->pipe[OFFSET_READ],
            &pHolder->pipe[OFFSET_WRITE],
            NULL, /* we would like to inherit
                     default process access,
                     instead of 'Everybody' access */
            PIPE_SIZE))
        {
            win32Error(env, L"CreatePipe");
            return FALSE;
        } else {
            /* [thisProcessEnd] has no the inherit flag because
               the [lpPipeAttributes] param of [CreatePipe]
               had the NULL value. */
            HANDLE thisProcessEnd = pHolder->pipe[OPPOSITE_END(pHolder->offset)];
            *phStd = pHolder->pipe[pHolder->offset];
            *pjhandles = (jlong) thisProcessEnd;
        }
    }
    /* Pipe handle will be closed in the [releaseHolder] call,
       file handle will be closed in Java.
       The long-live handle need to restore the inherit flag,
       we do it later in the [prepareIOEHandleState] call. */
    SetHandleInformation(
        *phStd,
        HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT);
    return TRUE;
}
Beispiel #5
0
JNIEXPORT void JNICALL
Java_java_lang_ProcessImpl_waitForInterruptibly(JNIEnv *env, jclass ignored, jlong handle)
{
    HANDLE events[2];
    events[0] = (HANDLE) handle;
    events[1] = JVM_GetThreadInterruptEvent();

    if (WaitForMultipleObjects(sizeof(events)/sizeof(events[0]), events,
                               FALSE,    /* Wait for ANY event */
                               INFINITE) /* Wait forever */
        == WAIT_FAILED)
        win32Error(env, "WaitForMultipleObjects");
}
/**
 * Find symbol by name (first).
 *
 * @returns VBox status.
 * @param   pVM                 VM handle.
 * @param   pszSymbol           Symbol name.
 * @param   pSymbol             Where to store the symbol info.
 */
VMMR3DECL(int) DBGFR3SymbolByName(PVM pVM, const char *pszSymbol, PDBGFSYMBOL pSymbol)
{
    /*
     * Lazy init.
     */
    if (!pVM->dbgf.s.fSymInited)
    {
        int rc = dbgfR3SymLazyInit(pVM);
        if (RT_FAILURE(rc))
            return rc;
    }

    /*
     * Look it up.
     */
#ifdef HAVE_DBGHELP
    char            achBuffer[sizeof(IMAGEHLP_SYMBOL64) + DBGF_SYMBOL_NAME_LENGTH * sizeof(TCHAR) + sizeof(ULONG64)];
    PIMAGEHLP_SYMBOL64 pSym = (PIMAGEHLP_SYMBOL64)&achBuffer[0];
    pSym->SizeOfStruct      = sizeof(IMAGEHLP_SYMBOL64);
    pSym->MaxNameLength     = DBGF_SYMBOL_NAME_LENGTH;

    if (SymGetSymFromName64(pVM, (char *)(void *)pszSymbol, pSym))
    {
        pSymbol->Value  = (RTGCUINTPTR)pSym->Address;
        pSymbol->cb     = pSym->Size;
        pSymbol->fFlags = pSym->Flags;
        strcpy(pSymbol->szName, pSym->Name);
        return VINF_SUCCESS;
    }
    return win32Error(pVM);
#else

    PDBGFSYM pSym = dbgfR3SymbolGetName(pVM, pszSymbol);
    if (pSym)
    {
        pSymbol->Value = pSym->Core.Key;
        pSymbol->cb = pSym->Core.KeyLast - pSym->Core.Key + 1;
        pSymbol->fFlags = 0;
        pSymbol->szName[0] = '\0';
        strncat(pSymbol->szName, pSym->szName, sizeof(pSymbol->szName) - 1);
        return VINF_SUCCESS;
    }

    return VERR_SYMBOL_NOT_FOUND;
#endif
}
Beispiel #7
0
JNIEXPORT void JNICALL
Java_java_lang_ProcessImpl_waitForTimeoutInterruptibly(JNIEnv *env,
                                                       jclass ignored,
                                                       jlong handle,
                                                       jlong timeout)
{
    HANDLE events[2];
    DWORD dwTimeout = (DWORD)timeout;
    DWORD result;
    events[0] = (HANDLE) handle;
    events[1] = JVM_GetThreadInterruptEvent();
    result = WaitForMultipleObjects(sizeof(events)/sizeof(events[0]), events,
                                    FALSE,    /* Wait for ANY event */
                                    dwTimeout);  /* Wait for dwTimeout */

    if (result == WAIT_FAILED)
        win32Error(env, L"WaitForMultipleObjects");
}
/**
 * We delay certain
 * Initialize the debug info for a VM.
 */
int dbgfR3SymLazyInit(PVM pVM)
{
    if (pVM->dbgf.s.fSymInited)
        return VINF_SUCCESS;
#ifdef HAVE_DBGHELP
    if (SymInitialize(pVM, NULL, FALSE))
    {
        pVM->dbgf.s.fSymInited = true;
        SymSetOptions(SYMOPT_LOAD_LINES | SYMOPT_AUTO_PUBLICS | SYMOPT_ALLOW_ABSOLUTE_SYMBOLS);

        /*
         * Enumerate all modules loaded by PDM and add them to the symbol database.
         */
        PDMR3LdrEnumModules(pVM, dbgfR3EnumModules, NULL);
        return VINF_SUCCESS;
    }
    return win32Error(pVM);
#else
    return VINF_SUCCESS;
#endif
}
Beispiel #9
0
JNIEXPORT jlong JNICALL
Java_java_lang_ProcessImpl_create(JNIEnv *env, jclass ignored,
                                  jstring cmd,
                                  jstring envBlock,
                                  jstring dir,
                                  jlongArray stdHandles,
                                  jboolean redirectErrorStream)
{
    HANDLE inRead   = INVALID_HANDLE_VALUE;
    HANDLE inWrite  = INVALID_HANDLE_VALUE;
    HANDLE outRead  = INVALID_HANDLE_VALUE;
    HANDLE outWrite = INVALID_HANDLE_VALUE;
    HANDLE errRead  = INVALID_HANDLE_VALUE;
    HANDLE errWrite = INVALID_HANDLE_VALUE;
    SECURITY_ATTRIBUTES sa;
    PROCESS_INFORMATION pi;
    STARTUPINFO si;
    LPTSTR  pcmd      = NULL;
    LPCTSTR pdir      = NULL;
    LPVOID  penvBlock = NULL;
    jlong  *handles   = NULL;
    jlong ret = 0;
    OSVERSIONINFO ver;
    jboolean onNT = JNI_FALSE;
    DWORD processFlag;

    ver.dwOSVersionInfoSize = sizeof(ver);
    GetVersionEx(&ver);
    if (ver.dwPlatformId == VER_PLATFORM_WIN32_NT)
        onNT = JNI_TRUE;

    assert(cmd != NULL);
    pcmd = (LPTSTR) JNU_GetStringPlatformChars(env, cmd, NULL);
    if (pcmd == NULL) goto Catch;

    if (dir != 0) {
        pdir = (LPCTSTR) JNU_GetStringPlatformChars(env, dir, NULL);
        if (pdir == NULL) goto Catch;
        pdir = (LPCTSTR) JVM_NativePath((char *)pdir);
    }

    if (envBlock != NULL) {
        penvBlock = onNT
            ? (LPVOID) ((*env)->GetStringChars(env, envBlock, NULL))
            : (LPVOID) JNU_GetStringPlatformChars(env, envBlock, NULL);
        if (penvBlock == NULL) goto Catch;
    }

    assert(stdHandles != NULL);
    handles = (*env)->GetLongArrayElements(env, stdHandles, NULL);
    if (handles == NULL) goto Catch;

    memset(&si, 0, sizeof(si));
    si.cb = sizeof(si);
    si.dwFlags = STARTF_USESTDHANDLES;

    sa.nLength = sizeof(sa);
    sa.lpSecurityDescriptor = 0;
    sa.bInheritHandle = TRUE;

    if (handles[0] != (jlong) -1) {
        si.hStdInput = (HANDLE) handles[0];
        handles[0] = (jlong) -1;
    } else {
        if (! CreatePipe(&inRead,  &inWrite,  &sa, PIPE_SIZE)) {
            win32Error(env, "CreatePipe");
            goto Catch;
        }
        si.hStdInput = inRead;
        SetHandleInformation(inWrite, HANDLE_FLAG_INHERIT, FALSE);
        handles[0] = (jlong) inWrite;
    }
    SetHandleInformation(si.hStdInput, HANDLE_FLAG_INHERIT, TRUE);

    if (handles[1] != (jlong) -1) {
        si.hStdOutput = (HANDLE) handles[1];
        handles[1] = (jlong) -1;
    } else {
        if (! CreatePipe(&outRead, &outWrite, &sa, PIPE_SIZE)) {
            win32Error(env, "CreatePipe");
            goto Catch;
        }
        si.hStdOutput = outWrite;
        SetHandleInformation(outRead, HANDLE_FLAG_INHERIT, FALSE);
        handles[1] = (jlong) outRead;
    }
    SetHandleInformation(si.hStdOutput, HANDLE_FLAG_INHERIT, TRUE);

    if (redirectErrorStream) {
        si.hStdError = si.hStdOutput;
        handles[2] = (jlong) -1;
    } else if (handles[2] != (jlong) -1) {
        si.hStdError = (HANDLE) handles[2];
        handles[2] = (jlong) -1;
    } else {
        if (! CreatePipe(&errRead, &errWrite, &sa, PIPE_SIZE)) {
            win32Error(env, "CreatePipe");
            goto Catch;
        }
        si.hStdError = errWrite;
        SetHandleInformation(errRead, HANDLE_FLAG_INHERIT, FALSE);
        handles[2] = (jlong) errRead;
    }
    SetHandleInformation(si.hStdError, HANDLE_FLAG_INHERIT, TRUE);

    if (onNT)
        processFlag = CREATE_NO_WINDOW | CREATE_UNICODE_ENVIRONMENT;
    else
        processFlag = selectProcessFlag(env, cmd);

    /* Java and Windows are both pure Unicode systems at heart.
     * Windows has both a legacy byte-based API and a 16-bit Unicode
     * "W" API.  The Right Thing here is to call CreateProcessW, since
     * that will allow all process-related information like command
     * line arguments to be passed properly to the child.  We don't do
     * that currently, since we would first have to have "W" versions
     * of JVM_NativePath and perhaps other functions.  In the
     * meantime, we can call CreateProcess with the magic flag
     * CREATE_UNICODE_ENVIRONMENT, which passes only the environment
     * in "W" mode.  We will fix this later. */

    ret = CreateProcess(0,           /* executable name */
                        pcmd,        /* command line */
                        0,           /* process security attribute */
                        0,           /* thread security attribute */
                        TRUE,        /* inherits system handles */
                        processFlag, /* selected based on exe type */
                        penvBlock,   /* environment block */
                        pdir,        /* change to the new current directory */
                        &si,         /* (in)  startup information */
                        &pi);        /* (out) process information */

    if (!ret) {
        win32Error(env, "CreateProcess");
        goto Catch;
    }

    CloseHandle(pi.hThread);
    ret = (jlong)pi.hProcess;

 Finally:
    /* Always clean up the child's side of the pipes */
    closeSafely(inRead);
    closeSafely(outWrite);
    closeSafely(errWrite);

    if (pcmd != NULL)
        JNU_ReleaseStringPlatformChars(env, cmd, (char *) pcmd);
    if (pdir != NULL)
        JNU_ReleaseStringPlatformChars(env, dir, (char *) pdir);
    if (penvBlock != NULL) {
        if (onNT)
            (*env)->ReleaseStringChars(env, envBlock, (jchar *) penvBlock);
        else
            JNU_ReleaseStringPlatformChars(env, dir, (char *) penvBlock);
    }
    if (handles != NULL)
        (*env)->ReleaseLongArrayElements(env, stdHandles, handles, 0);

    return ret;

 Catch:
    /* Clean up the parent's side of the pipes in case of failure only */
    closeSafely(inWrite);
    closeSafely(outRead);
    closeSafely(errRead);
    goto Finally;
}
/* Please, read about the MS inheritance problem
   http://support.microsoft.com/kb/315939
   and critical section/synchronized block solution. */
static jlong processCreate(
    JNIEnv *env,
    const jchar *pcmd,
    const jchar *penvBlock,
    const jchar *pdir,
    jlong *handles,
    jboolean redirectErrorStream)
{
    jlong ret = 0L;
    STARTUPINFOW si = {sizeof(si)};

    /* Handles for which the inheritance flag must be restored. */
    HANDLE stdIOE[HANDLE_STORAGE_SIZE] = {
        /* Current process standard IOE handles: JDK-7147084 */
        INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE,
        /* Child process IOE handles: JDK-6921885 */
        (HANDLE)handles[0], (HANDLE)handles[1], (HANDLE)handles[2]};
    BOOL inherit[HANDLE_STORAGE_SIZE] = {
        FALSE, FALSE, FALSE,
        FALSE, FALSE, FALSE};

    {
        /* Extraction of current process standard IOE handles */
        DWORD idsIOE[3] = {STD_INPUT_HANDLE, STD_OUTPUT_HANDLE, STD_ERROR_HANDLE};
        int i;
        for (i = 0; i < 3; ++i)
            /* Should not be closed by CloseHandle! */
            stdIOE[i] = GetStdHandle(idsIOE[i]);
    }

    prepareIOEHandleState(stdIOE, inherit);
    {
        /* Input */
        STDHOLDER holderIn = {{INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE}, OFFSET_READ};
        if (initHolder(env, &handles[0], &holderIn, &si.hStdInput)) {

            /* Output */
            STDHOLDER holderOut = {{INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE}, OFFSET_WRITE};
            if (initHolder(env, &handles[1], &holderOut, &si.hStdOutput)) {

                /* Error */
                STDHOLDER holderErr = {{INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE}, OFFSET_WRITE};
                BOOL success;
                if (redirectErrorStream) {
                    si.hStdError = si.hStdOutput;
                    /* Here we set the error stream to [ProcessBuilder.NullInputStream.INSTANCE]
                       value. That is in accordance with Java Doc for the redirection case.
                       The Java file for the [ handles[2] ] will be closed in ANY case. It is not
                       a handle leak. */
                    handles[2] = JAVA_INVALID_HANDLE_VALUE;
                    success = TRUE;
                } else {
                    success = initHolder(env, &handles[2], &holderErr, &si.hStdError);
                }

                if (success) {
                    PROCESS_INFORMATION pi;
                    DWORD processFlag = CREATE_UNICODE_ENVIRONMENT;

                    /* Suppress popping-up of a console window for non-console applications */
                    if (GetConsoleWindow() == NULL)
                        processFlag |= CREATE_NO_WINDOW;

                    si.dwFlags = STARTF_USESTDHANDLES;
                    if (!CreateProcessW(
                        NULL,             /* executable name */
                        (LPWSTR)pcmd,     /* command line */
                        NULL,             /* process security attribute */
                        NULL,             /* thread security attribute */
                        TRUE,             /* inherits system handles */
                        processFlag,      /* selected based on exe type */
                        (LPVOID)penvBlock,/* environment block */
                        (LPCWSTR)pdir,    /* change to the new current directory */
                        &si,              /* (in)  startup information */
                        &pi))             /* (out) process information */
                    {
                        win32Error(env, L"CreateProcess");
                    } else {
                        closeSafely(pi.hThread);
                        ret = (jlong)pi.hProcess;
                    }
                }
                releaseHolder(ret == 0, &holderErr);
                releaseHolder(ret == 0, &holderOut);
            }
            releaseHolder(ret == 0, &holderIn);
        }
    }
    restoreIOEHandleState(stdIOE, inherit);

    return ret;
}
/**
 * Load debug info, optionally related to a specific module.
 *
 * @returns VBox status.
 * @param   pVM             VM Handle.
 * @param   pszFilename     Path to the file containing the symbol information.
 *                          This can be the executable image, a flat symbol file of some kind or stripped debug info.
 * @param   AddressDelta    The value to add to the loaded symbols.
 * @param   pszName         Short hand name for the module. If not related to a module specify NULL.
 * @param   ModuleAddress   Address which the image is loaded at. This will be used to reference the module other places in the api.
 *                          Ignored when pszName is NULL.
 * @param   cbImage         Size of the image.
 *                          Ignored when pszName is NULL.
 */
VMMR3DECL(int) DBGFR3ModuleLoad(PVM pVM, const char *pszFilename, RTGCUINTPTR AddressDelta, const char *pszName, RTGCUINTPTR ModuleAddress, unsigned cbImage)
{
    /*
     * Lazy init.
     */
    if (!pVM->dbgf.s.fSymInited)
    {
        int rc = dbgfR3SymLazyInit(pVM);
        if (RT_FAILURE(rc))
            return rc;
    }

    /*
     * Open the load file.
     */
    FILE *pFile = NULL;
    char szFoundFile[RTPATH_MAX];
    int rc = dbgfR3ModuleLocateAndOpen(pVM, pszFilename, szFoundFile, sizeof(szFoundFile), &pFile);
    if (pFile)
    {
        /*
         * Probe the file type.
         */
        SYMFILETYPE enmType = dbgfR3ModuleProbe(pFile);
        if (enmType != SYMFILETYPE_UNKNOWN)
        {
            /*
             * Add the module.
             */
            if (pszName)
            {
                #ifdef HAVE_DBGHELP
                /** @todo arg! checkout the inserting of modules and then loading them again.... Or just the module representation.... */
                DWORD64 ImageBase = SymLoadModule64(pVM, NULL, (char *)(void *)szFoundFile, (char *)(void *)pszName, ModuleAddress, cbImage);
                if (!ImageBase)
                    ImageBase = SymLoadModule64(pVM, NULL, (char *)(void *)pszName, (char *)(void *)pszName, ModuleAddress, cbImage);
                if (ImageBase)
                {
                    AssertMsg(ModuleAddress == 0 || ModuleAddress == ImageBase, ("ModuleAddres=%RGv ImageBase=%llx\n", ModuleAddress, ImageBase));
                    ModuleAddress = ImageBase;
                }
                else
                    rc = win32Error(pVM);
                #else
                rc = VERR_NOT_IMPLEMENTED;
                #endif
            }
            if (RT_SUCCESS(rc))
            {
                /*
                 * Seek to the start of the file.
                 */
                rc = fseek(pFile, 0, SEEK_SET);
                Assert(!rc);

                /*
                 * Process the specific.
                 */
                switch (enmType)
                {
                    case SYMFILETYPE_LINUX_SYSTEM_MAP:
                        rc = dbgfR3LoadLinuxSystemMap(pVM, pFile, ModuleAddress, AddressDelta);
                        break;

                    case SYMFILETYPE_PDB:
                    case SYMFILETYPE_DBG:
                    case SYMFILETYPE_MZ:
                #ifdef HAVE_DBGHELP
                        /* done it all above! */
                        break;
                #endif
                    case SYMFILETYPE_LD_MAP:
                    case SYMFILETYPE_MS_MAP:
                    case SYMFILETYPE_OBJDUMP:
                    case SYMFILETYPE_ELF:
                        rc = VERR_NOT_SUPPORTED;
                        break;

                    default:
                        AssertFailed();
                        rc = VERR_INTERNAL_ERROR;
                        break;
                } /* file switch. */
            } /* module added successfully. */
        } /* format identified */
        else
            rc = VERR_NOT_SUPPORTED;
        /** @todo check for read errors */
        fclose(pFile);
    }
    return rc;
}