dbgcfg.cpp revision b7a07b07543924f45c1fffd2f90de582038b8ba6
/* $Id$ */
/** @file
* IPRT - Debugging Configuration.
*/
/*
* Copyright (C) 2013 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*
* The contents of this file may alternatively be used under the terms
* of the Common Development and Distribution License Version 1.0
* (CDDL) only, as it comes in the "COPYING.CDDL" file of the
* VirtualBox OSE distribution, in which case the provisions of the
* CDDL are applicable instead of those of the GPL.
*
* You may elect to license modified versions of this file under the
* terms and conditions of either the GPL or the CDDL or both.
*/
/*******************************************************************************
* Header Files *
*******************************************************************************/
#include <iprt/critsect.h>
#include <iprt/semaphore.h>
/*******************************************************************************
* Structures and Typedefs *
*******************************************************************************/
/** @name Flags for path search strings
* @{ */
/** @}*/
/**
* String list entry.
*/
typedef struct RTDBGCFGSTR
{
/** List entry. */
/** Domain specific flags. */
/** The length of the string. */
/** The string. */
char sz[1];
} RTDBGCFGSTR;
/** Pointer to a string list entry. */
typedef RTDBGCFGSTR *PRTDBGCFGSTR;
/**
* Configuration instance.
*/
typedef struct RTDBGCFGINT
{
/** The magic value (RTDBGCFG_MAGIC). */
/** Reference counter. */
/** Flags, see RTDBGCFG_FLAGS_XXX. */
/** List of paths to search for debug files and executable images. */
/** List of debug file suffixes. */
/** List of paths to search for source files. */
#ifdef RT_OS_WINDOWS
/** The _NT_ALT_SYMBOL_PATH and _NT_SYMBOL_PATH combined. */
/** The _NT_EXECUTABLE_PATH. */
/** The _NT_SOURCE_PATH. */
#endif
/** Critical section protecting the instance data. */
} *PRTDBGCFGINT;
/**
* Mnemonics map entry for a 64-bit unsigned property value.
*/
typedef struct RTDBGCFGU64MNEMONIC
{
/** The flags to set or clear. */
/** The mnemonic. */
const char *pszMnemonic;
/** The length of the mnemonic. */
/** If @c true, the bits in fFlags will be set, if @c false they will be
* cleared. */
bool fSet;
/** Pointer to a read only mnemonic map entry for a uint64_t property. */
typedef RTDBGCFGU64MNEMONIC const *PCRTDBGCFGU64MNEMONIC;
/*******************************************************************************
* Defined Constants And Macros *
*******************************************************************************/
/** Validates a debug module handle and returns rc if not valid. */
do { \
} while (0)
/*******************************************************************************
* Global Variables *
*******************************************************************************/
/** Mnemonics map for RTDBGCFGPROP_FLAGS. */
static const RTDBGCFGU64MNEMONIC g_aDbgCfgFlags[] =
{
{ 0, NULL, 0, false }
};
/**
* Frees a string list.
*
* @param pList The list to free.
*/
{
{
}
}
/**
* Make changes to a string list, given a semicolon separated input string.
*
* @returns VINF_SUCCESS, VERR_FILENAME_TOO_LONG, VERR_NO_MEMORY
* @param pThis The config instance.
* @param enmOp The change operation.
* @param pszValue The input strings separated by semicolon.
* @param fPaths Indicates that this is a path list and that we
* should look for srv and cache prefixes.
* @param pList The string list anchor.
*/
static int rtDbgCfgChangeStringList(PRTDBGCFGINT pThis, RTDBGCFGOP enmOp, const char *pszValue, bool fPaths,
{
if (enmOp == RTDBGCFGOP_SET)
while (*pszValue)
{
/* Skip separators. */
while (*pszValue == ';')
pszValue++;
if (!*pszValue)
break;
/* Find the end of this path. */
char ch;
pszValue++;
if (cchPath >= UINT16_MAX)
return VERR_FILENAME_TOO_LONG;
if (enmOp != RTDBGCFGOP_REMOVE)
{
/*
* Remove all occurences.
*/
{
{
}
}
}
else
{
/*
* We're adding a new one.
*/
if (!pNew)
return VERR_NO_MEMORY;
if (fPaths)
{
}
if (enmOp == RTDBGCFGOP_PREPEND)
else
}
}
return VINF_SUCCESS;
}
/**
* Make changes to a 64-bit value
*
* @returns VINF_SUCCESS, VERR_DBG_CFG_INVALID_VALUE.
* @param pThis The config instance.
* @param enmOp The change operation.
* @param pszValue The input value.
* @param pszMnemonics The mnemonics map for this value.
* @param puValue The value to change.
*/
{
char ch;
{
/* skip whitespace and separators */
if (!ch)
break;
if (RT_C_IS_DIGIT(ch))
{
return VERR_DBG_CFG_INVALID_VALUE;
if (enmOp != RTDBGCFGOP_REMOVE)
else
}
else
{
/* A mnemonic, find the end of it. */
do
/* Look it up in the map and apply it. */
unsigned i = 0;
while (paMnemonics[i].pszMnemonic)
{
{
else
break;
}
i++;
}
if (!paMnemonics[i].pszMnemonic)
return VERR_DBG_CFG_INVALID_VALUE;
}
}
return VINF_SUCCESS;
}
RTDECL(int) RTDbgCfgChangeString(RTDBGCFG hDbgCfg, RTDBGCFGPROP enmProp, RTDBGCFGOP enmOp, const char *pszValue)
{
if (!pszValue)
pszValue = "";
else
if (RT_SUCCESS(rc))
{
switch (enmProp)
{
case RTDBGCFGPROP_FLAGS:
break;
case RTDBGCFGPROP_PATH:
break;
case RTDBGCFGPROP_SUFFIXES:
break;
case RTDBGCFGPROP_SRC_PATH:
break;
default:
AssertFailed();
}
}
return rc;
}
RTDECL(int) RTDbgCfgChangeUInt(RTDBGCFG hDbgCfg, RTDBGCFGPROP enmProp, RTDBGCFGOP enmOp, uint64_t uValue)
{
if (RT_SUCCESS(rc))
{
switch (enmProp)
{
case RTDBGCFGPROP_FLAGS:
break;
default:
}
if (RT_SUCCESS(rc))
{
switch (enmOp)
{
case RTDBGCFGOP_SET:
break;
case RTDBGCFGOP_APPEND:
case RTDBGCFGOP_PREPEND:
break;
case RTDBGCFGOP_REMOVE:
break;
default:
AssertFailed();
}
}
}
return rc;
}
/**
* Querys a string list as a single string (semicolon separators).
*
* @returns VINF_SUCCESS, VERR_BUFFER_OVERFLOW.
* @param pThis The config instance.
* @param pList The string list anchor.
* @param pszValue The output buffer.
* @param cbValue The size of the output buffer.
*/
{
/*
* Check the length first.
*/
return VERR_BUFFER_OVERFLOW;
/*
* Construct the string list in the buffer.
*/
{
*psz++ = ';';
}
*psz = '\0';
return VINF_SUCCESS;
}
/**
* Querys the string value of a 64-bit unsigned int.
*
* @returns VINF_SUCCESS, VERR_BUFFER_OVERFLOW.
* @param pThis The config instance.
* @param uValue The value to query.
* @param pszMnemonics The mnemonics map for this value.
* @param pszValue The output buffer.
* @param cbValue The size of the output buffer.
*/
static int rtDbgCfgQueryStringU64(RTDBGCFG hDbgCfg, uint64_t uValue, PCRTDBGCFGU64MNEMONIC paMnemonics,
{
/*
* If no mnemonics, just return the hex value.
*/
{
char szTmp[64];
return VERR_BUFFER_OVERFLOW;
return VINF_SUCCESS;
}
/*
* Check that there is sufficient buffer space first.
*/
for (unsigned i = 0; paMnemonics[i].pszMnemonic; i++)
if ( paMnemonics[i].fSet
return VERR_BUFFER_OVERFLOW;
/*
* Construct the string.
*/
for (unsigned i = 0; paMnemonics[i].pszMnemonic; i++)
if ( paMnemonics[i].fSet
{
*psz++ = ' ';
}
*psz = '\0';
return VINF_SUCCESS;
}
RTDECL(int) RTDbgCfgQueryString(RTDBGCFG hDbgCfg, RTDBGCFGPROP enmProp, char *pszValue, size_t cbValue)
{
if (RT_SUCCESS(rc))
{
switch (enmProp)
{
case RTDBGCFGPROP_FLAGS:
break;
case RTDBGCFGPROP_PATH:
break;
case RTDBGCFGPROP_SUFFIXES:
break;
case RTDBGCFGPROP_SRC_PATH:
break;
default:
AssertFailed();
}
}
return rc;
}
{
if (RT_SUCCESS(rc))
{
switch (enmProp)
{
case RTDBGCFGPROP_FLAGS:
break;
default:
}
}
return rc;
}
{
return cRefs;
}
{
if (hDbgCfg == NIL_RTDBGCFG)
return 0;
if (!cRefs)
{
/*
* Last reference - free all memory.
*/
#ifdef RT_OS_WINDOWS
#endif
}
else
return cRefs;
}
{
/*
* Validate input.
*/
if (pszEnvVarPrefix)
{
}
/*
* Allocate and initialize a new instance.
*/
if (!pThis)
return VERR_NO_MEMORY;
#ifdef RT_OS_WINDOWS
#endif
if (RT_FAILURE(rc))
{
return rc;
}
/*
* Read configurtion from the environment if requested to do so.
*/
if (pszEnvVarPrefix)
{
static struct
{
const char *pszVar;
void *pvAttr;
} const s_aProps[] =
{
{ RTDBGCFGPROP_FLAGS, "FLAGS" },
{ RTDBGCFGPROP_PATH, "PATH" },
{ RTDBGCFGPROP_SUFFIXES, "SUFFIXES" },
{ RTDBGCFGPROP_SRC_PATH, "SRC_PATH" },
};
int rc = VINF_SUCCESS;
if (pszEnvVar)
{
for (unsigned i = 0; i < RT_ELEMENTS(s_aProps); i++)
{
{
break;
}
if (RT_SUCCESS(rc))
{
if (RT_FAILURE(rc))
break;
}
else if (rc != VERR_ENV_VAR_NOT_FOUND)
break;
}
}
else
if (RT_FAILURE(rc))
{
/*
* Error, bail out.
*/
return rc;
}
}
/*
* Returns successfully.
*/
return VINF_SUCCESS;
}