VirtualBox

Ignore:
Timestamp:
Jul 27, 2022 2:38:01 AM (2 years ago)
Author:
vboxsync
Message:

IPRT/nocrt: Split up the startup code and added the basic DLL startup code. bugref:10261

Location:
trunk/src/VBox/Runtime/common/compiler/vcc
Files:
1 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/compiler/vcc/atexit-vcc.cpp

    r95834 r95870  
    11/* $Id$ */
    22/** @file
    3  * IPRT - No-CRT - Windows EXE startup code.
    4  *
    5  * @note Does not run static constructors and destructors!
     3 * IPRT - Visual C++ Compiler - Simple atexit implementation.
    64 */
    75
     
    3230*********************************************************************************************************************************/
    3331#include "internal/iprt.h"
    34 #include "internal/process.h"
    3532
    36 #include <iprt/nt/nt-and-windows.h>
    37 #include <iprt/getopt.h>
    38 #include <iprt/message.h>
    39 #include <iprt/path.h>
    40 #include <iprt/string.h>
    41 #include <iprt/utf16.h>
    42 
    43 #ifdef IPRT_NO_CRT
    44 # include <iprt/asm.h>
    45 # include <iprt/nocrt/stdlib.h>
    46 #endif
     33#include <iprt/asm.h>
     34#include <iprt/mem.h>
     35#include <iprt/nocrt/stdlib.h>
    4736
    4837#include "internal/compiler-vcc.h"
     
    5241*   Structures and Typedefs                                                                                                      *
    5342*********************************************************************************************************************************/
    54 #ifdef IPRT_NO_CRT
    5543typedef struct RTNOCRTATEXITCHUNK
    5644{
    5745    PFNRTNOCRTATEXITCALLBACK apfnCallbacks[256];
    5846} RTNOCRTATEXITCHUNK;
    59 #endif
    6047
    6148
     
    6350*   Global Variables                                                                                                             *
    6451*********************************************************************************************************************************/
    65 RT_C_DECLS_BEGIN
    66 DECL_HIDDEN_DATA(char)      g_szrtProcExePath[RTPATH_MAX] = "Unknown.exe";
    67 DECL_HIDDEN_DATA(size_t)    g_cchrtProcExePath = 11;
    68 DECL_HIDDEN_DATA(size_t)    g_cchrtProcExeDir = 0;
    69 DECL_HIDDEN_DATA(size_t)    g_offrtProcName = 0;
    70 RT_C_DECLS_END
    71 
    72 #ifdef IPRT_NO_CRT
    7352/** The first atexit() registration chunk. */
    7453static RTNOCRTATEXITCHUNK   g_aAtExitPrealloc;
     
    7756/** Chunk and callback index in one. */
    7857static volatile uint32_t    g_idxNextAtExit        = 0;
    79 #endif
    8058
    8159
    82 /*********************************************************************************************************************************
    83 *   External Symbols                                                                                                             *
    84 *********************************************************************************************************************************/
    85 extern DECLHIDDEN(void) InitStdHandles(PRTL_USER_PROCESS_PARAMETERS pParams); /* nocrt-streams-win.cpp */ /** @todo put in header */
    86 
    87 extern int main(int argc, char **argv, char **envp);    /* in program */
    88 
    89 
    90 #ifdef IPRT_NO_CRT
    91 extern "C"
    92 int rtnocrt_atexit(PFNRTNOCRTATEXITCALLBACK pfnCallback) RT_NOEXCEPT
     60/* Note! not using atexit here because it'll clash with built-in prototype.  */
     61extern "C" int rtnocrt_atexit(PFNRTNOCRTATEXITCALLBACK pfnCallback) RT_NOEXCEPT
    9362{
    9463    AssertPtr(pfnCallback);
     
    10877    if (!pChunk)
    10978    {
    110         pChunk = (RTNOCRTATEXITCHUNK *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pChunk));
     79        pChunk = (RTNOCRTATEXITCHUNK *)RTMemAllocZ(sizeof(*pChunk)); /* ASSUMES that the allocator works w/o initialization! */
    11180        AssertReturn(pChunk, -1); /* don't try decrement, someone could be racing us... */
    11281
    11382        if (!ASMAtomicCmpXchgPtr(&g_apAtExit[idxChunk], pChunk, NULL))
    11483        {
    115             HeapFree(GetProcessHeap(), 0, pChunk);
     84            RTMemFree(pChunk);
    11685
    11786            pChunk = ASMAtomicReadPtrT(&g_apAtExit[idxChunk], RTNOCRTATEXITCHUNK *);
     
    12695    return 0;
    12796}
    128 #endif
    12997
    13098
    131 static int rtTerminateProcess(int32_t rcExit, bool fDoAtExit)
     99void rtVccTermRunAtExit(void) RT_NOEXCEPT
    132100{
    133 #ifdef IPRT_NO_CRT
    134     /*
    135      * Run atexit callback in reverse order.
    136      */
    137     if (fDoAtExit)
     101    uint32_t idxAtExit = ASMAtomicReadU32(&g_idxNextAtExit);
     102    if (idxAtExit-- > 0)
    138103    {
    139         uint32_t idxAtExit = ASMAtomicReadU32(&g_idxNextAtExit);
    140         if (idxAtExit-- > 0)
     104        uint32_t idxChunk    = idxAtExit / RT_ELEMENTS(g_apAtExit[0]->apfnCallbacks);
     105        uint32_t idxCallback = idxAtExit % RT_ELEMENTS(g_apAtExit[0]->apfnCallbacks);
     106        for (;;)
    141107        {
    142             uint32_t idxChunk    = idxAtExit / RT_ELEMENTS(g_apAtExit[0]->apfnCallbacks);
    143             uint32_t idxCallback = idxAtExit % RT_ELEMENTS(g_apAtExit[0]->apfnCallbacks);
    144             for (;;)
     108            RTNOCRTATEXITCHUNK *pChunk = ASMAtomicReadPtrT(&g_apAtExit[idxChunk], RTNOCRTATEXITCHUNK *);
     109            if (pChunk)
    145110            {
    146                 RTNOCRTATEXITCHUNK *pChunk = ASMAtomicReadPtrT(&g_apAtExit[idxChunk], RTNOCRTATEXITCHUNK *);
    147                 if (pChunk)
     111                do
    148112                {
    149                     do
     113                    g_idxNextAtExit = idxAtExit--; /* Make sure we don't try problematic atexit callbacks! */
     114
     115                    PFNRTNOCRTATEXITCALLBACK pfnCallback = pChunk->apfnCallbacks[idxCallback];
     116                    if (pfnCallback) /* Can be NULL see registration code */
    150117                    {
    151                         PFNRTNOCRTATEXITCALLBACK pfnCallback = pChunk->apfnCallbacks[idxCallback];
    152                         if (pfnCallback) /* Can be NULL see registration code */
    153                             pfnCallback();
    154                     } while (idxCallback-- > 0);
    155                 }
    156                 if (idxChunk == 0)
    157                     break;
    158                 idxChunk--;
    159                 idxCallback = RT_ELEMENTS(g_apAtExit[0]->apfnCallbacks) - 1;
     118                        pfnCallback();
     119                        pChunk->apfnCallbacks[idxCallback] = NULL;
     120                    }
     121                } while (idxCallback-- > 0);
    160122            }
     123            else
     124                idxAtExit -= RT_ELEMENTS(g_apAtExit[0]->apfnCallbacks);
     125            if (idxChunk == 0)
     126                break;
     127            idxChunk--;
     128            idxCallback = RT_ELEMENTS(g_apAtExit[0]->apfnCallbacks) - 1;
    161129        }
    162130
    163         rtVccInitializersRunTerm();
     131        g_idxNextAtExit = 0;
    164132    }
    165 #else
    166     RT_NOREF(fDoAtExit);
    167 #endif
    168 
    169     /*
    170      * Terminate.
    171      */
    172     for (;;)
    173         NtTerminateProcess(NtCurrentProcess(), rcExit);
    174133}
    175134
    176 
    177 DECL_NO_INLINE(static, void) initProcExecPath(void)
    178 {
    179     WCHAR wszPath[RTPATH_MAX];
    180     UINT cwcPath = GetModuleFileNameW(NULL, wszPath, RT_ELEMENTS(wszPath));
    181     if (cwcPath)
    182     {
    183         char *pszDst = g_szrtProcExePath;
    184         int rc = RTUtf16ToUtf8Ex(wszPath, cwcPath, &pszDst, sizeof(g_szrtProcExePath), &g_cchrtProcExePath);
    185         if (RT_SUCCESS(rc))
    186         {
    187             g_cchrtProcExeDir = g_offrtProcName = RTPathFilename(pszDst) - g_szrtProcExePath;
    188             while (   g_cchrtProcExeDir >= 2
    189                    && RTPATH_IS_SLASH(g_szrtProcExePath[g_cchrtProcExeDir - 1])
    190                    && g_szrtProcExePath[g_cchrtProcExeDir - 2] != ':')
    191                 g_cchrtProcExeDir--;
    192         }
    193         else
    194             RTMsgError("initProcExecPath: RTUtf16ToUtf8Ex failed: %Rrc\n", rc);
    195     }
    196     else
    197         RTMsgError("initProcExecPath: GetModuleFileNameW failed: %Rhrc\n", GetLastError());
    198 }
    199 
    200 
    201 DECLASM(void) CustomMainEntrypoint(PPEB pPeb)
    202 {
    203     /*
    204      * Initialize stuff.
    205      */
    206     InitStdHandles(pPeb->ProcessParameters);
    207     initProcExecPath();
    208 
    209     RTEXITCODE rcExit;
    210 #ifdef IPRT_NO_CRT
    211     AssertCompile(sizeof(rcExit) == sizeof(int));
    212     rcExit = (RTEXITCODE)rtVccInitializersRunInit();
    213     if (rcExit == RTEXITCODE_SUCCESS)
    214 #endif
    215     {
    216         /*
    217          * Get and convert the command line to argc/argv format.
    218          */
    219         UNICODE_STRING const *pCmdLine = pPeb->ProcessParameters ? &pPeb->ProcessParameters->CommandLine : NULL;
    220         if (pCmdLine)
    221         {
    222             char *pszCmdLine = NULL;
    223             int rc = RTUtf16ToUtf8Ex(pCmdLine->Buffer, pCmdLine->Length / sizeof(WCHAR), &pszCmdLine, 0, NULL);
    224             if (RT_SUCCESS(rc))
    225             {
    226                 char **papszArgv;
    227                 int    cArgs = 0;
    228                 rc = RTGetOptArgvFromString(&papszArgv, &cArgs, pszCmdLine,
    229                                             RTGETOPTARGV_CNV_MODIFY_INPUT | RTGETOPTARGV_CNV_QUOTE_MS_CRT,  NULL);
    230                 if (RT_SUCCESS(rc))
    231                 {
    232                     /*
    233                      * Call the main function.
    234                      */
    235                     AssertCompile(sizeof(rcExit) == sizeof(int));
    236                     rcExit = (RTEXITCODE)main(cArgs, papszArgv, NULL /*envp*/);
    237                 }
    238                 else
    239                     rcExit = RTMsgErrorExitFailure("Error parsing command line: %Rrc\n", rc);
    240             }
    241             else
    242                 rcExit = RTMsgErrorExitFailure("Failed to convert command line to UTF-8: %Rrc\n", rc);
    243         }
    244         else
    245             rcExit = RTMsgErrorExitFailure("No command line\n");
    246         rtTerminateProcess(rcExit, true /*fDoAtExit*/);
    247     }
    248 #ifdef IPRT_NO_CRT
    249     else
    250     {
    251         RTMsgError("A C static initializor failed (%d)\n", rcExit);
    252         rtTerminateProcess(rcExit, false /*fDoAtExit*/);
    253     }
    254 #endif
    255 }
    256 
  • trunk/src/VBox/Runtime/common/compiler/vcc/stacksup-vcc.cpp

    r95847 r95870  
    3232
    3333#include <iprt/asm.h>
     34#include <iprt/asm-amd64-x86.h>
    3435#include <iprt/assert.h>
    3536
     
    9293
    9394
     95/**
     96 * Initializes the security cookie value.
     97 *
     98 * This must be called as the first thing by the startup code.  We must also no
     99 * do anything fancy here.
     100 */
     101void rtVccInitSecurityCookie(void) RT_NOEXCEPT
     102{
     103    __security_cookie = (uintptr_t)ASMReadTSC() ^ (uintptr_t)&__security_cookie;
     104}
     105
     106
    94107DECLASM(void) _RTC_StackVarCorrupted(uint8_t *pbFrame, RTC_VAR_DESC_T const *pVar)
    95108{
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