Exemplo n.º 1
0
/**
 * Duplicates a symbol.
 *
 * To save heap space, the returned symbol will not own more heap space than
 * it strictly need to. So, it's not possible to append stuff to the symbol
 * or anything of that kind.
 *
 * @returns Pointer to the duplicate.
 *          This must be freed using kDbgSymbolFree().
 * @param   pSymbol     The symbol to be duplicated.
 */
KDBG_DECL(PKDBGSYMBOL) kDbgSymbolDup(PCKDBGSYMBOL pSymbol)
{
    kDbgAssertPtrReturn(pSymbol, NULL);
    KSIZE cb = K_OFFSETOF(KDBGSYMBOL, szName[pSymbol->cchName + 1]);
    PKDBGSYMBOL pNewSymbol = (PKDBGSYMBOL)kHlpDup(pSymbol, cb);
    if (pNewSymbol)
        pNewSymbol->cbSelf = cb;
    return pNewSymbol;
}
Exemplo n.º 2
0
/**
 * Add a string to the string table.
 *
 * If already in the table, the index of the existing entry is returned.
 *
 * @returns String index on success,
 * @retval  KDEPDBG_STRTAB_IDX_ERROR on I/O and inconsistency errors.
 *
 * @param   pStrTab     The string table.
 * @param   pszString   The string to add.
 * @param   cchStringIn The length of the string.
 * @param   uHash       The hash of the string.
 */
static KU32 kDepDbStrTabAddHashed(KDEPDBINTSTRTAB *pStrTab, const char *pszString, size_t cchStringIn, KU32 uHash)
{
    KU32 const          cchString   = (KU32)cchStringIn;
    KDEPDBHASH         *pHash       = pStrTab->pHash;
    KDEPDBSTRING       *paStrings   = &pStrTab->pStrTab->aStrings[0];
    KU32 const          iStringEnd  = K_LE2H_U32(pStrTab->pStrTab->iStringEnd);
    KU32                iInsertAt   = KDEPDBHASH_UNUSED;
    KU32                cCollisions = 0;
    KU32                iHash;
    KU32                iString;
    KU32                cEntries;
    KDEPDBSTRING       *pNewString;

    /* sanity */
    if (cchString != cchStringIn)
        return KDEPDBG_STRTAB_IDX_NOT_FOUND;

    /*
     * Hash lookup of the string, finding either an existing copy or where to
     * insert the new string at in the hash table.
     */
    iHash = uHash % pHash->cEntries;
    for (;;)
    {
        iString = K_LE2H_U32(pHash->auEntries[iHash]);
        if (iString < iStringEnd)
        {
            KDEPDBSTRING const *pString = &paStrings[iString];
            if (    K_LE2H_U32(pString->uHash)     == uHash
                &&  K_LE2H_U32(pString->cchString) == cchString
                &&  !memcmp(pString->szString, pszString, cchString))
                return iString;
        }
        else
        {
            if (iInsertAt == KDEPDBHASH_UNUSED)
                iInsertAt = iHash;
            if (iString == KDEPDBHASH_UNUSED)
                break;
            if (iString != KDEPDBHASH_DELETED)
                return KDEPDBG_STRTAB_IDX_ERROR;
        }

        /* advance */
        cCollisions++;
        iHash = (iHash + 1) % pHash->cEntries;
    }

    /*
     * Add string to the string table.
     * The string table file is grown in 256KB increments and ensuring at least 64KB unused new space.
     */
    cEntries = cchString + 1 <= sizeof(paStrings[0].szString)
             ? 1
             : (cchString + 1 - sizeof(paStrings[0].szString) + sizeof(KDEPDBSTRING) - 1) / sizeof(KDEPDBSTRING);
    if (iStringEnd + cEntries > pStrTab->iStringAlloced)
    {
        KSIZE cbNewSize      = K_ALIGN_Z((iStringEnd + cEntries) * sizeof(KDEPDBSTRING) + 64*1024, 256*1024);
        KU32  iStringAlloced = (pStrTab->hStrTab.cb - K_OFFSETOF(KDEPDBSTRTAB, aStrings)) / sizeof(KDEPDBSTRING);
        if (    iStringAlloced <= pStrTab->iStringAlloced
            ||  iStringAlloced >= KDEPDBG_STRTAB_IDX_END
            ||  iStringAlloced >= KDEPDBHASH_END)
            return KDEPDBG_STRTAB_IDX_ERROR;
        if (kDepDbFHGrow(&pStrTab->hStrTab, cbNewSize, (void **)&pStrTab->pStrTab) != 0)
            return KDEPDBG_STRTAB_IDX_ERROR;
        pStrTab->iStringAlloced = iStringAlloced;
        paStrings = &pStrTab->pStrTab->aStrings[0];
    }

    pNewString = &paStrings[iStringEnd];
    pNewString->uHash     = K_H2LE_U32(uHash);
    pNewString->cchString = K_H2LE_U32(cchString);
    memcpy(&pNewString->szString, pszString, cchString);
    pNewString->szString[cchString] = '\0';

    pStrTab->pStrTab->iStringEnd = K_H2LE_U32(iStringEnd + cEntries);

    /*
     * Insert hash table entry, rehash it if necessary.
     */
    pHash->auEntries[iInsertAt] = K_H2LE_U32(iStringEnd);
    pHash->cUsedEntries = K_H2LE_U32(K_LE2H_U32(pHash->cUsedEntries) + 1);
    pHash->cCollisions  = K_H2LE_U32(K_LE2H_U32(pHash->cCollisions)  + cCollisions);
    if (    K_LE2H_U32(pHash->cUsedEntries) > K_LE2H_U32(pHash->cEntries) / 3 * 2
        &&  kDepDbStrTabReHash(pStrTab) != 0)
        return KDEPDBG_STRTAB_IDX_ERROR;

    return iStringEnd;
}
Exemplo n.º 3
0
/**
 * Doubles the hash table size and rehashes it.
 *
 * @returns 0 on success, -1 on failure.
 * @param   pStrTab         The string table.
 * @todo    Rebuild from string table, we'll be accessing it anyways.
 */
static int kDepDbStrTabReHash(KDEPDBINTSTRTAB *pStrTab)
{
    KDEPDBSTRING const *paStrings   = &pStrTab->pStrTab->aStrings[0];
    KU32 const          iStringEnd  = K_LE2H_U32(pStrTab->pStrTab->iStringEnd);
    KDEPDBHASH         *pHash       = pStrTab->pHash;
    KDEPDBHASH          HashHdr     = *pHash;
    KU32               *pauNew;
    KU32                cEntriesNew;
    KU32                i;

    /*
     * Calc the size of the new hash table.
     */
    if (pHash->cEntries >= KU32_C(0x80000000))
        return -1;
    cEntriesNew = 1024;
    while (cEntriesNew <= pHash->cEntries)
        cEntriesNew <<= 1;

    /*
     * Allocate and initialize an empty hash table in memory.
     */
    pauNew = kDepDbAlloc(cEntriesNew * sizeof(KU32));
    if (!pauNew)
        return -1;
    i = cEntriesNew;
    while (i-- > 0)
        pauNew[i] = KDEPDBHASH_UNUSED;

    /*
     * Popuplate the new table.
     */
    HashHdr.cEntries     = K_LE2H_U32(cEntriesNew);
    HashHdr.cCollisions  = 0;
    HashHdr.cUsedEntries = 0;
    i = pHash->cEntries;
    while (i-- > 0)
    {
        KU32 iString = K_LE2H_U32(pHash->auEntries[i]);
        if (iString < iStringEnd)
        {
            KU32 iHash = (paStrings[iString].uHash % cEntriesNew);
            if (pauNew[iHash] != K_H2LE_U32(KDEPDBHASH_UNUSED))
            {
                do
                {
                    iHash = (iHash + 1) % cEntriesNew;
                    HashHdr.cCollisions++;
                } while (pauNew[iHash] != K_H2LE_U32(KDEPDBHASH_UNUSED));
            }
            pauNew[iHash] = iString;
            HashHdr.cUsedEntries++;
        }
        else if (   iString != KDEPDBHASH_UNUSED
                 && iString != KDEPDBHASH_DELETED)
        {
            kDepDbFree(pauNew);
            return -1;
        }
    }
    HashHdr.cCollisions  = K_H2LE_U32(HashHdr.cCollisions);
    HashHdr.cUsedEntries = K_H2LE_U32(HashHdr.cUsedEntries);

    /*
     * Unmap the hash, write the new hash table and map it again.
     */
    if (!kDepDbFHUnmap(&pStrTab->hHash, (void **)&pStrTab->pHash))
    {
        if (   !kDepDbFHWriteAt(&pStrTab->hHash, 0, &HashHdr, K_OFFSETOF(KDEPDBHASH, auEntries))
            && !kDepDbFHWriteAt(&pStrTab->hHash, K_OFFSETOF(KDEPDBHASH, auEntries), pauNew, sizeof(pauNew[0]) * cEntriesNew))
        {
            kDepDbFree(pauNew);
            pauNew = NULL;
            if (!kDepDbFHMap(&pStrTab->hHash, (void **)&pStrTab->pHash))
                return 0;
        }
        else
            kDepDbFHWriteAt(&pStrTab->hHash, 0, "\0\0\0\0", 4); /* file is screwed, trash the magic. */
    }

    kDepDbFree(pauNew);
    return -1;
}