VirtualBox

Ignore:
Timestamp:
May 16, 2013 5:07:57 PM (12 years ago)
Author:
vboxsync
Message:

ldrPE.cpp: Added fallback pfnEnumSymbols implementation that works when we cannot load the whole image into memory. This makes windows symbols from exports work a little bit on non-windows hosts.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/ldr/ldrPE.cpp

    r46118 r46131  
    893893
    894894
     895/**
     896 * Slow version of rtldrPEEnumSymbols that'll work without all of the image
     897 * being accessible.
     898 *
     899 * This is mainly for use in debuggers and similar.
     900 */
     901static int rtldrPEEnumSymbolsSlow(PRTLDRMODPE pThis, unsigned fFlags, RTUINTPTR BaseAddress,
     902                                  PFNRTLDRENUMSYMS pfnCallback, void *pvUser)
     903{
     904    /*
     905     * We enumerates by ordinal, which means using a slow linear search for
     906     * getting any name
     907     */
     908    PCIMAGE_EXPORT_DIRECTORY pExpDir = NULL;
     909    int rc = rtldrPEReadPartByRva(pThis, NULL, pThis->ExportDir.VirtualAddress, pThis->ExportDir.Size,
     910                                  (void const **)&pExpDir);
     911    if (RT_FAILURE(rc))
     912        return rc;
     913    uint32_t const cOrdinals = RT_MAX(pExpDir->NumberOfNames, pExpDir->NumberOfFunctions);
     914
     915    uint32_t const *paAddress  = NULL;
     916    rc = rtldrPEReadPartByRva(pThis, NULL, pExpDir->AddressOfFunctions, cOrdinals * sizeof(uint32_t),
     917                              (void const **)&paAddress);
     918    uint32_t const *paRVANames = NULL;
     919    if (RT_SUCCESS(rc) && pExpDir->NumberOfNames)
     920        rc = rtldrPEReadPartByRva(pThis, NULL, pExpDir->AddressOfNames, pExpDir->NumberOfNames * sizeof(uint32_t),
     921                                  (void const **)&paRVANames);
     922    uint16_t const *paOrdinals = NULL;
     923    if (RT_SUCCESS(rc) && pExpDir->NumberOfNames)
     924        rc = rtldrPEReadPartByRva(pThis, NULL, pExpDir->AddressOfNameOrdinals, pExpDir->NumberOfNames * sizeof(uint16_t),
     925                                  (void const **)&paOrdinals);
     926    if (RT_SUCCESS(rc))
     927    {
     928        uintptr_t   uNamePrev = 0;
     929        for (uint32_t uOrdinal = 0; uOrdinal < cOrdinals; uOrdinal++)
     930        {
     931            if (paAddress[uOrdinal] /* needed? */)
     932            {
     933                /*
     934                 * Look for name.
     935                 */
     936                uint32_t    uRvaName = UINT32_MAX;
     937                /* Search from previous + 1 to the end.  */
     938                unsigned    uName = uNamePrev + 1;
     939                while (uName < pExpDir->NumberOfNames)
     940                {
     941                    if (paOrdinals[uName] == uOrdinal)
     942                    {
     943                        uRvaName = paRVANames[uName];
     944                        uNamePrev = uName;
     945                        break;
     946                    }
     947                    uName++;
     948                }
     949                if (uRvaName == UINT32_MAX)
     950                {
     951                    /* Search from start to the previous. */
     952                    uName = 0;
     953                    for (uName = 0 ; uName <= uNamePrev; uName++)
     954                    {
     955                        if (paOrdinals[uName] == uOrdinal)
     956                        {
     957                            uRvaName = paRVANames[uName];
     958                            uNamePrev = uName;
     959                            break;
     960                        }
     961                    }
     962                }
     963
     964                /*
     965                 * Get address.
     966                 */
     967                uintptr_t   uRVAExport = paAddress[uOrdinal];
     968                RTUINTPTR Value;
     969                if (  uRVAExport - (uintptr_t)pThis->ExportDir.VirtualAddress
     970                    < pThis->ExportDir.Size)
     971                {
     972                    if (!(fFlags & RTLDR_ENUM_SYMBOL_FLAGS_NO_FWD))
     973                    {
     974                        /* Resolve forwarder. */
     975                        AssertMsgFailed(("Forwarders are not supported!\n"));
     976                    }
     977                    continue;
     978                }
     979
     980                /* Get plain export address */
     981                Value = PE_RVA2TYPE(BaseAddress, uRVAExport, RTUINTPTR);
     982
     983                /* Read in the name if found one. */
     984                char szAltName[32];
     985                const char *pszName = NULL;
     986                if (uRvaName != UINT32_MAX)
     987                {
     988                    size_t cbName = 0x1000 - (uRvaName & 0xfff);
     989                    if (cbName < 10 || cbName > 512)
     990                        cbName = 128;
     991                    rc = rtldrPEReadPartByRva(pThis, NULL, uRvaName, cbName, (void const **)&pszName);
     992                    while (RT_SUCCESS(rc) && RTStrNLen(pszName, cbName) == cbName)
     993                    {
     994                        rtldrPEFreePart(pThis, NULL, pszName);
     995                        pszName = NULL;
     996                        if (cbName >= _4K)
     997                            break;
     998                        cbName += 128;
     999                        rc = rtldrPEReadPartByRva(pThis, NULL, uRvaName, cbName, (void const **)&pszName);
     1000                    }
     1001                }
     1002                if (!pszName)
     1003                {
     1004                    RTStrPrintf(szAltName, sizeof(szAltName), "Ordinal%#x", uOrdinal);
     1005                    pszName = szAltName;
     1006                }
     1007
     1008                /*
     1009                 * Call back.
     1010                 */
     1011                rc = pfnCallback(&pThis->Core, pszName, uOrdinal + pExpDir->Base, Value, pvUser);
     1012                if (pszName != szAltName && pszName)
     1013                    rtldrPEFreePart(pThis, NULL, pszName);
     1014                if (rc)
     1015                    break;
     1016            }
     1017        }
     1018    }
     1019
     1020    rtldrPEFreePart(pThis, NULL, paOrdinals);
     1021    rtldrPEFreePart(pThis, NULL, paRVANames);
     1022    rtldrPEFreePart(pThis, NULL, paAddress);
     1023    rtldrPEFreePart(pThis, NULL, pExpDir);
     1024    return rc;
     1025
     1026}
     1027
     1028
    8951029/** @copydoc RTLDROPS::pfnEnumSymbols */
    8961030static DECLCALLBACK(int) rtldrPEEnumSymbols(PRTLDRMODINTERNAL pMod, unsigned fFlags, const void *pvBits, RTUINTPTR BaseAddress,
     
    9161050            int rc = rtldrPEReadBits(pModPe);
    9171051            if (RT_FAILURE(rc))
    918                 return rc;
     1052                return rtldrPEEnumSymbolsSlow(pModPe, fFlags, BaseAddress, pfnCallback, pvUser);
    9191053        }
    9201054        pvBits = pModPe->pvBits;
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette