VirtualBox

Changeset 70309 in vbox for trunk/src/VBox/Runtime/common


Ignore:
Timestamp:
Dec 22, 2017 11:46:23 AM (7 years ago)
Author:
vboxsync
Message:

IPRT/ldr: Added VFS chain based loader open APIs.

File:
1 copied

Legend:

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

    r70228 r70309  
    11/* $Id$ */
    22/** @file
    3  * IPRT - Binary Image Loader, The File Oriented Parts.
     3 * IPRT - Binary Image Loader, The File Oriented Parts, VFS variant.
    44 */
    55
     
    3939#include <iprt/err.h>
    4040#include <iprt/string.h>
     41#include <iprt/vfs.h>
    4142#include <iprt/formats/mz.h>
    4243#include "internal/ldr.h"
     
    4748*********************************************************************************************************************************/
    4849/**
    49  * File Reader instance.
     50 * VFS file Reader instance.
    5051 * This provides raw image bits from a file.
    5152 */
    52 typedef struct RTLDRREADERFILE
     53typedef struct RTLDRREADERVFSFILE
    5354{
    5455    /** The core. */
    5556    RTLDRREADER     Core;
    56     /** The file. */
    57     RTFILE          hFile;
    58     /** The file size. */
    59     RTFOFF          cbFile;
    60     /** The current offset. */
    61     RTFOFF          off;
     57    /** The VFS file. */
     58    RTVFSFILE       hVfsFile;
    6259    /** Number of users or the mapping. */
    6360    RTUINT          cMappings;
     
    6663    /** The filename (variable size). */
    6764    char            szFilename[1];
    68 } RTLDRREADERFILE, *PRTLDRREADERFILE;
     65} RTLDRREADERVFSFILE;
     66typedef RTLDRREADERVFSFILE *PRTLDRREADERVFSFILE;
    6967
    7068
    7169/** @copydoc RTLDRREADER::pfnRead */
    72 static DECLCALLBACK(int) rtldrFileRead(PRTLDRREADER pReader, void *pvBuf, size_t cb, RTFOFF off)
    73 {
    74     PRTLDRREADERFILE pFileReader = (PRTLDRREADERFILE)pReader;
    75 
    76     /*
    77      * Seek.
    78      */
    79     if (pFileReader->off != off)
    80     {
    81         int rc = RTFileSeek(pFileReader->hFile, off, RTFILE_SEEK_BEGIN, NULL);
    82         if (RT_FAILURE(rc))
    83         {
    84             pFileReader->off = -1;
    85             return rc;
    86         }
    87         pFileReader->off = off;
    88     }
    89 
    90     /*
    91      * Read.
    92      */
    93     int rc = RTFileRead(pFileReader->hFile, pvBuf, cb, NULL);
     70static DECLCALLBACK(int) rtldrVfsFileRead(PRTLDRREADER pReader, void *pvBuf, size_t cb, RTFOFF off)
     71{
     72    PRTLDRREADERVFSFILE pFileReader = (PRTLDRREADERVFSFILE)pReader;
     73    return RTVfsFileReadAt(pFileReader->hVfsFile, off, pvBuf, cb, NULL);
     74}
     75
     76
     77/** @copydoc RTLDRREADER::pfnTell */
     78static DECLCALLBACK(RTFOFF) rtldrVfsFileTell(PRTLDRREADER pReader)
     79{
     80    PRTLDRREADERVFSFILE pFileReader = (PRTLDRREADERVFSFILE)pReader;
     81    return RTVfsFileTell(pFileReader->hVfsFile);
     82}
     83
     84
     85/** @copydoc RTLDRREADER::pfnSize */
     86static DECLCALLBACK(RTFOFF) rtldrVfsFileSize(PRTLDRREADER pReader)
     87{
     88    PRTLDRREADERVFSFILE pFileReader = (PRTLDRREADERVFSFILE)pReader;
     89    uint64_t cbFile;
     90    int rc = RTVfsFileGetSize(pFileReader->hVfsFile, &cbFile);
    9491    if (RT_SUCCESS(rc))
    95         pFileReader->off += cb;
    96     else
    97         pFileReader->off = -1;
    98     return rc;
    99 }
    100 
    101 
    102 /** @copydoc RTLDRREADER::pfnTell */
    103 static DECLCALLBACK(RTFOFF) rtldrFileTell(PRTLDRREADER pReader)
    104 {
    105     PRTLDRREADERFILE pFileReader = (PRTLDRREADERFILE)pReader;
    106     return pFileReader->off;
    107 }
    108 
    109 
    110 /** @copydoc RTLDRREADER::pfnSize */
    111 static DECLCALLBACK(RTFOFF) rtldrFileSize(PRTLDRREADER pReader)
    112 {
    113     PRTLDRREADERFILE pFileReader = (PRTLDRREADERFILE)pReader;
    114     return pFileReader->cbFile;
     92        return cbFile;
     93    return 0;
    11594}
    11695
    11796
    11897/** @copydoc RTLDRREADER::pfnLogName */
    119 static DECLCALLBACK(const char *) rtldrFileLogName(PRTLDRREADER pReader)
    120 {
    121     PRTLDRREADERFILE pFileReader = (PRTLDRREADERFILE)pReader;
     98static DECLCALLBACK(const char *) rtldrVfsFileLogName(PRTLDRREADER pReader)
     99{
     100    PRTLDRREADERVFSFILE pFileReader = (PRTLDRREADERVFSFILE)pReader;
    122101    return pFileReader->szFilename;
    123102}
     
    125104
    126105/** @copydoc RTLDRREADER::pfnMap */
    127 static DECLCALLBACK(int) rtldrFileMap(PRTLDRREADER pReader, const void **ppvBits)
    128 {
    129     PRTLDRREADERFILE pFileReader = (PRTLDRREADERFILE)pReader;
     106static DECLCALLBACK(int) rtldrVfsFileMap(PRTLDRREADER pReader, const void **ppvBits)
     107{
     108    PRTLDRREADERVFSFILE pFileReader = (PRTLDRREADERVFSFILE)pReader;
    130109
    131110    /*
     
    142121     * Allocate memory.
    143122     */
    144     size_t cb = (size_t)pFileReader->cbFile;
    145     if ((RTFOFF)cb != pFileReader->cbFile)
     123    RTFOFF cbFile = rtldrVfsFileSize(pReader);
     124    size_t cb = (size_t)cbFile;
     125    if ((RTFOFF)cb != cbFile)
    146126        return VERR_IMAGE_TOO_BIG;
    147127    pFileReader->pvMapping = RTMemAlloc(cb);
    148128    if (!pFileReader->pvMapping)
    149129        return VERR_NO_MEMORY;
    150     int rc = rtldrFileRead(pReader, pFileReader->pvMapping, cb, 0);
     130    int rc = rtldrVfsFileRead(pReader, pFileReader->pvMapping, cb, 0);
    151131    if (RT_SUCCESS(rc))
    152132    {
     
    165145
    166146/** @copydoc RTLDRREADER::pfnUnmap */
    167 static DECLCALLBACK(int) rtldrFileUnmap(PRTLDRREADER pReader, const void *pvBits)
    168 {
    169     PRTLDRREADERFILE pFileReader = (PRTLDRREADERFILE)pReader;
     147static DECLCALLBACK(int) rtldrVfsFileUnmap(PRTLDRREADER pReader, const void *pvBits)
     148{
     149    PRTLDRREADERVFSFILE pFileReader = (PRTLDRREADERVFSFILE)pReader;
    170150    AssertReturn(pFileReader->cMappings > 0, VERR_INVALID_PARAMETER);
    171151
     
    182162
    183163/** @copydoc RTLDRREADER::pfnDestroy */
    184 static DECLCALLBACK(int) rtldrFileDestroy(PRTLDRREADER pReader)
    185 {
    186     int rc = VINF_SUCCESS;
    187     PRTLDRREADERFILE pFileReader = (PRTLDRREADERFILE)pReader;
    188     if (pFileReader->hFile != NIL_RTFILE)
    189     {
    190         rc = RTFileClose(pFileReader->hFile);
    191         AssertRC(rc);
    192         pFileReader->hFile = NIL_RTFILE;
     164static DECLCALLBACK(int) rtldrVfsFileDestroy(PRTLDRREADER pReader)
     165{
     166    PRTLDRREADERVFSFILE pFileReader = (PRTLDRREADERVFSFILE)pReader;
     167    if (pFileReader->hVfsFile != NIL_RTVFSFILE)
     168    {
     169        RTVfsFileRelease(pFileReader->hVfsFile);
     170        pFileReader->hVfsFile = NIL_RTVFSFILE;
    193171    }
    194172    RTMemFree(pFileReader);
    195     return rc;
     173    return VINF_SUCCESS;
    196174}
    197175
     
    201179 *
    202180 * @returns iprt status code.
     181 * @param   pszFilename     The file to open, can be VFS chain.
    203182 * @param   ppReader        Where to store the reader instance on success.
    204  * @param   pszFilename     The file to open.
    205  */
    206 static int rtldrFileCreate(PRTLDRREADER *ppReader, const char *pszFilename)
    207 {
    208     size_t cchFilename = strlen(pszFilename);
     183 * @param   poffError       Where to return the offset into @a pszFilename of an VFS
     184 *                          chain element causing trouble.  Optional.
     185 * @param   pErrInfo        Where to return extended error information.  Optional.
     186 */
     187static int rtldrVfsFileCreate(const char *pszFilename, PRTLDRREADER *ppReader, uint32_t *poffError, PRTERRINFO pErrInfo)
     188{
     189    size_t cbFilename = strlen(pszFilename) + 1;
    209190    int rc = VERR_NO_MEMORY;
    210     PRTLDRREADERFILE pFileReader = (PRTLDRREADERFILE)RTMemAlloc(sizeof(*pFileReader) + cchFilename);
     191    PRTLDRREADERVFSFILE pFileReader = (PRTLDRREADERVFSFILE)RTMemAlloc(RT_OFFSETOF(RTLDRREADERVFSFILE, szFilename[cbFilename]));
    211192    if (pFileReader)
    212193    {
    213         memcpy(pFileReader->szFilename, pszFilename, cchFilename + 1);
    214         rc = RTFileOpen(&pFileReader->hFile, pszFilename, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE);
     194        memcpy(pFileReader->szFilename, pszFilename, cbFilename);
     195        pFileReader->szFilename[0] = '\0';
     196        rc = RTVfsChainOpenFile(pszFilename, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE, &pFileReader->hVfsFile,
     197                                poffError, pErrInfo);
    215198        if (RT_SUCCESS(rc))
    216199        {
    217             rc = RTFileGetSize(pFileReader->hFile, (uint64_t *)&pFileReader->cbFile);
    218             if (RT_SUCCESS(rc))
    219             {
    220                 pFileReader->Core.uMagic     = RTLDRREADER_MAGIC;
    221                 pFileReader->Core.pfnRead    = rtldrFileRead;
    222                 pFileReader->Core.pfnTell    = rtldrFileTell;
    223                 pFileReader->Core.pfnSize    = rtldrFileSize;
    224                 pFileReader->Core.pfnLogName = rtldrFileLogName;
    225                 pFileReader->Core.pfnMap     = rtldrFileMap;
    226                 pFileReader->Core.pfnUnmap   = rtldrFileUnmap;
    227                 pFileReader->Core.pfnDestroy = rtldrFileDestroy;
    228                 pFileReader->off       = 0;
    229                 pFileReader->cMappings = 0;
    230                 pFileReader->pvMapping = NULL;
    231                 *ppReader = &pFileReader->Core;
    232                 return VINF_SUCCESS;
    233             }
    234 
    235             RTFileClose(pFileReader->hFile);
     200            pFileReader->Core.uMagic     = RTLDRREADER_MAGIC;
     201            pFileReader->Core.pfnRead    = rtldrVfsFileRead;
     202            pFileReader->Core.pfnTell    = rtldrVfsFileTell;
     203            pFileReader->Core.pfnSize    = rtldrVfsFileSize;
     204            pFileReader->Core.pfnLogName = rtldrVfsFileLogName;
     205            pFileReader->Core.pfnMap     = rtldrVfsFileMap;
     206            pFileReader->Core.pfnUnmap   = rtldrVfsFileUnmap;
     207            pFileReader->Core.pfnDestroy = rtldrVfsFileDestroy;
     208            pFileReader->cMappings = 0;
     209            pFileReader->pvMapping = NULL;
     210            *ppReader = &pFileReader->Core;
     211            return VINF_SUCCESS;
    236212        }
    237213        RTMemFree(pFileReader);
     
    243219
    244220/**
    245  * Open a binary image file.
     221 * Open a binary image file allowing VFS chains in the filename.
    246222 *
    247223 * @returns iprt status code.
    248  * @param   pszFilename Image filename.
     224 * @param   pszFilename Image filename, VFS chain specifiers allowed.
    249225 * @param   fFlags      Valid RTLDR_O_XXX combination.
    250226 * @param   enmArch     CPU architecture specifier for the image to be loaded.
    251227 * @param   phLdrMod    Where to store the handle to the loader module.
    252  */
    253 RTDECL(int) RTLdrOpen(const char *pszFilename, uint32_t fFlags, RTLDRARCH enmArch, PRTLDRMOD phLdrMod)
    254 {
    255     return RTLdrOpenEx(pszFilename, fFlags, enmArch, phLdrMod, NULL /*pErrInfo*/);
    256 }
    257 RT_EXPORT_SYMBOL(RTLdrOpen);
    258 
    259 
    260 /**
    261  * Open a binary image file, extended version.
    262  *
    263  * @returns iprt status code.
    264  * @param   pszFilename Image filename.
    265  * @param   fFlags      Valid RTLDR_O_XXX combination.
    266  * @param   enmArch     CPU architecture specifier for the image to be loaded.
    267  * @param   phLdrMod    Where to store the handle to the loader module.
    268  * @param   pErrInfo    Where to return extended error information. Optional.
    269  */
    270 RTDECL(int) RTLdrOpenEx(const char *pszFilename, uint32_t fFlags, RTLDRARCH enmArch, PRTLDRMOD phLdrMod, PRTERRINFO pErrInfo)
    271 {
    272     LogFlow(("RTLdrOpenEx: pszFilename=%p:{%s} fFlags=%#x enmArch=%d phLdrMod=%p\n",
     228 * @param   poffError   Where to return the offset into @a pszFilename of an VFS
     229 *                      chain element causing trouble.  Optional.
     230 * @param   pErrInfo    Where to return extended error information.  Optional.
     231 */
     232RTDECL(int) RTLdrOpenVfsChain(const char *pszFilename, uint32_t fFlags, RTLDRARCH enmArch,
     233                              PRTLDRMOD phLdrMod, uint32_t *poffError, PRTERRINFO pErrInfo)
     234{
     235    LogFlow(("RTLdrOpenVfsChain: pszFilename=%p:{%s} fFlags=%#x enmArch=%d phLdrMod=%p\n",
    273236             pszFilename, pszFilename, fFlags, enmArch, phLdrMod));
    274237    AssertMsgReturn(!(fFlags & ~RTLDR_O_VALID_MASK), ("%#x\n", fFlags), VERR_INVALID_PARAMETER);
     
    279242     */
    280243    PRTLDRREADER pReader;
    281     int rc = rtldrFileCreate(&pReader, pszFilename);
     244    int rc = rtldrVfsFileCreate(pszFilename, &pReader, poffError, pErrInfo);
    282245    if (RT_SUCCESS(rc))
    283246    {
     247        if (poffError)
     248            *poffError = 0;
    284249        rc = RTLdrOpenWithReader(pReader, fFlags, enmArch, phLdrMod, pErrInfo);
    285250        if (RT_SUCCESS(rc))
     
    294259    return rc;
    295260}
    296 RT_EXPORT_SYMBOL(RTLdrOpenEx);
     261RT_EXPORT_SYMBOL(RTLdrOpenVfsChain);
    297262
    298263
    299264/**
    300  * Opens a binary image file using kLdr.
     265 * Open a binary image file using kLdr allowing VFS chains in the filename.
    301266 *
    302267 * @returns iprt status code.
     
    305270 * @param   enmArch     CPU architecture specifier for the image to be loaded.
    306271 * @param   phLdrMod    Where to store the handle to the loaded module.
     272 * @param   poffError   Where to return the offset into @a pszFilename of an VFS
     273 *                      chain element causing trouble.  Optional.
     274 * @param   pErrInfo    Where to return extended error information.  Optional.
    307275 * @remark  Primarily for testing the loader.
    308276 */
    309 RTDECL(int) RTLdrOpenkLdr(const char *pszFilename, uint32_t fFlags, RTLDRARCH enmArch, PRTLDRMOD phLdrMod)
     277RTDECL(int) RTLdrOpenVfsChainkLdr(const char *pszFilename, uint32_t fFlags, RTLDRARCH enmArch,
     278                                  PRTLDRMOD phLdrMod, uint32_t *poffError, PRTERRINFO pErrInfo)
    310279{
    311280#ifdef LDR_WITH_KLDR
    312     LogFlow(("RTLdrOpenkLdr: pszFilename=%p:{%s} fFlags=%#x enmArch=%d phLdrMod=%p\n",
     281    LogFlow(("RTLdrOpenVfsChainkLdr: pszFilename=%p:{%s} fFlags=%#x enmArch=%d phLdrMod=%p\n",
    313282             pszFilename, pszFilename, fFlags, enmArch, phLdrMod));
    314283    AssertMsgReturn(!(fFlags & ~RTLDR_O_VALID_MASK), ("%#x\n", fFlags), VERR_INVALID_PARAMETER);
     
    318287     */
    319288    PRTLDRREADER pReader;
    320     int rc = rtldrFileCreate(&pReader, pszFilename);
     289    int rc = rtldrVfsFileCreate(pszFilename, &pReader, poffError, pErrInfo);
    321290    if (RT_SUCCESS(rc))
    322291    {
    323         rc = rtldrkLdrOpen(pReader, fFlags, enmArch, phLdrMod, NULL);
     292        if (poffError)
     293            *poffError = 0;
     294        rc = rtldrkLdrOpen(pReader, fFlags, enmArch, phLdrMod, pErrInfo);
    324295        if (RT_SUCCESS(rc))
    325296        {
     
    330301    }
    331302    *phLdrMod = NIL_RTLDRMOD;
    332     LogFlow(("RTLdrOpenkLdr: return %Rrc\n", rc));
     303    LogFlow(("RTLdrOpenVfsChainkLdr: return %Rrc\n", rc));
    333304    return rc;
    334305
    335306#else
    336     return RTLdrOpen(pszFilename, fFlags, enmArch, phLdrMod);
     307    return RTLdrOpenVfsChain(pszFilename, fFlags, enmArch, phLdrMod, poffError, pErrInfo);
    337308#endif
    338309}
    339 RT_EXPORT_SYMBOL(RTLdrOpenkLdr);
    340 
     310RT_EXPORT_SYMBOL(RTLdrOpenVfsChainkLdr);
     311
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