LoadLibrary fails with error code 193

后端 未结 2 761
独厮守ぢ
独厮守ぢ 2020-12-12 00:40

I\'m stuck as to why I can\'t load my dll \"interfac\" using LoadLibrary. It seems to be failing when loading a dependency but I\'m not sure why.

Here\'s the code: <

相关标签:
2条回答
  • 2020-12-12 01:19

    One likely explanation for the ERROR_BAD_EXE_FORMAT error from LoadLibrary is that INTERFAC.DLL was linked with a PCDLRN.LIB import library that declares PCDLRN exports, but the PCDLRN.EXE found at runtime does not have an exports table.

    • The gflags (x86)'s loader snaps shows that the error is triggered while loading PCDLRN.EXE, specifically while resolving the import table of INTERFAC.DLL:

      18a0:2a40 @ 06859098 - LdrpHandleOneOldFormatImportDescriptor - INFO: DLL "C:\QA\Pcdlrn\Win32\Release\INTERFAC.DLL" imports "PCDLRN.exe"
      [...]
      18a0:2a40 @ 06859597 - LdrpHandleOneOldFormatImportDescriptor - ERROR: Loading "?????" from the import table of DLL "C:\QA\Pcdlrn\Win32\Release\INTERFAC.DLL" failed with status 0xc000007b
    • Status 0xc000007b is STATUS_INVALID_IMAGE_FORMAT:

      {Bad Image} %hs is either not designed to run on Windows or it contains an error. Try installing the program again using the original installation media or contact your system administrator or the software vendor for support.

    • NTSTATUS STATUS_INVALID_IMAGE_FORMAT is mapped to Win32 error code ERROR_BAD_EXE_FORMAT per INFO: Mapping NT Status Error Codes to Win32 Error Codes.

    I was able to duplicate the same ERROR_BAD_EXE_FORMAT with a mockup of the given scenario: link INTERFAC.DLL to a PCDLRN.LIB that declares an exported foo, then substitute a PCDLRN.EXE without an exports table, and finally attempt to LoadLibrary INTERFAC.DLL.

    As a side note, linking a DLL to the import library of another EXE is uncommon and fraught with pitfalls. In the case here, even if error 193 is fixed, the functions in the EXE would not be directly usable from the DLL. See for example Load EXE as DLL: Mission Possible for more details.

    0 讨论(0)
  • Edit: Though what follows makes sense it is actually incorrect. I'm keeping it here just for reference, but I may delete the answer later.

    Note however that (at least on Windows 10, which I used to check) even if relocation information is available in the file, if the module is not a DLL it is not applied, so even if you didn't get that error, unless your INTERFAC.DLL applies relocations to PCLDRN.exe after loading it, trying to use it is likely to break somewhere along the way.


    With the loader snaps output the situation seems pretty obvious to me.

    The loader snaps output once the file is found are (I numbered the lines):

    (1)  18a0:2a40 @ 06859098 - LdrpMapViewOfSection - ENTER: DLL name: C:\QA\Pcdlrn\Win32\Release\PCDLRN.exe
    (2)  'CNCServer.exe': Loaded 'C:\QA\Pcdlrn\Win32\Release\PCDLRN.exe', Symbols loaded.
    (3)  18a0:2a40 @ 06859597 - LdrpMapViewOfSection - RETURN: Status: 0x40000003
    (4)  'CNCServer.exe': Unloaded 'C:\QA\Pcdlrn\Win32\Release\PCDLRN.exe'
    (5)  18a0:2a40 @ 06859597 - LdrpFindOrMapDll - RETURN: Status: 0xc000007b
    (6)  18a0:2a40 @ 06859597 - LdrpLoadImportModule - ERROR: Loading DLL PCDLRN.exe from path C:\QA\Pcdlrn\CNCSERVER\Win32\Release;C:\Windows\system32;C:\Windows\system;C:\Windows;.;C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\CommonExtensions\Microsoft\TeamFoundation\Team Explorer\NativeBinaries\x86;C:\windows\system32;C:\windows;C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common;C:\Program Files (x86)\Intel\iCLS Client\;C:\Program Files\Intel\iCLS Client\;C:\Windows\system32;C:\Windows;C:
    (7)  18a0:2a40 @ 06859597 - LdrpLoadImportModule - RETURN: Status: 0xc000007b
    (8)  18a0:2a40 @ 06859597 - LdrpHandleOneOldFormatImportDescriptor - ERROR: Loading "?????" from the import table of DLL "C:\QA\Pcdlrn\Win32\Release\INTERFAC.DLL" failed with status 0xc000007b
    (9)  18a0:2a40 @ 06859613 - LdrpUnloadDll - INFO: Unmapping DLL "C:\QA\Pcdlrn\Win32\Release\INTERFAC.DLL"
    (10) 'CNCServer.exe': Unloaded 'C:\QA\Pcdlrn\Win32\Release\INTERFAC.dll'
    (11) 18a0:2a40 @ 06859613 - LdrpLoadDll - RETURN: Status: 0xc000007b
    (12) 18a0:2a40 @ 06859613 - LdrLoadDll - RETURN: Status: 0xc000007b
    

    LdrpMapViewOfSection returns an error code (0x40000003) on line 3 which causes the module to unload (line 4) and then LdrpMapViewOfSection's caller - LdrpFindOrMapDll - translates the error code to 0xc000007b (STATUS_INVALID_IMAGE_FORMAT).

    But the error that caused the load to fail was 0x40000003 - STATUS_IMAGE_NOT_AT_BASE. The description of this NTSTATUS is:

    {Image Relocated} An image file could not be mapped at the address that is specified in the image file. Local fixes must be performed on this image.

    (Source: NTSTATUS Values)

    By default, EXEs don't contain relocation information (as was mentioned in the comments). Usually that's not a problem as the address space is rather free when the EXE is loaded into it. But your address space isn't free. To make matters worse, all EXEs compiled by Visual C++ share the same base address by default:

    The /BASE option sets a base address for the program, overriding the default location for an .exe or DLL file. The default base address for an .exe file is 0x400000 for 32-bit images or 0x140000000 for 64-bit images. For a DLL, the default base address is 0x10000000 for 32-bit images or 0x180000000 for 64-bit images.

    (Source: Linker Options: /BASE (Base Address))

    That's probably the situation you have. CNCServer.exe already occupies 0x400000 and that's the only place PCDLRN.exe can go. LdrpMapViewOfSection can't map PCDLRN.exe to 0x400000 because it isn't free and fails to map in anywhere else because there's no relocation information.

    And from there it goes up the call stack and changes the error, but not the underlying problem. Which is lack of relocation information.

    You can see what happened when this error is encountered for a DLL with relocation information in your output too. When INTERFAC.dll is initially loaded:

    18a0:2a40 @ 06858989 - LdrpFindOrMapDll - ENTER: DLL name: C:\QA\Pcdlrn\Win32\Release\INTERFAC.DLL DLL path: C:\QA\Pcdlrn\CNCSERVER\Win32\Release;C:\Windows\system32;C:\Windows\system;C:\Windows;.;C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\CommonExtensions\Microsoft\TeamFoundation\Team Explorer\NativeBinaries\x86;C:\windows\system32;C:\windows;C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common;C:\Program Files (x86)\Intel\iCLS Client\;C:\Program Files\Intel\iCLS Client\;C:\Windows
        18a0:2a40 @ 06858989 - LdrpSearchPath - ENTER: DLL name: C:\QA\Pcdlrn\Win32\Release\INTERFAC.DLL DLL path: C:\QA\Pcdlrn\CNCSERVER\Win32\Release;C:\Windows\system32;C:\Windows\system;C:\Windows;.;C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\CommonExtensions\Microsoft\TeamFoundation\Team Explorer\NativeBinaries\x86;C:\windows\system32;C:\windows;C:\Program Files (x86)\NVIDIA Corporation\PhysX\Common;C:\Program Files (x86)\Intel\iCLS Client\;C:\Program Files\Intel\iCLS Client\;C:\Windows\s
            18a0:2a40 @ 06858989 - LdrpResolveFileName - ENTER: DLL name: C:\QA\Pcdlrn\Win32\Release\INTERFAC.DLL
            18a0:2a40 @ 06858989 - LdrpResolveFileName - RETURN: Status: 0x00000000
            18a0:2a40 @ 06858989 - LdrpResolveDllName - ENTER: DLL name: C:\QA\Pcdlrn\Win32\Release\INTERFAC.DLL
            18a0:2a40 @ 06858989 - LdrpResolveDllName - RETURN: Status: 0x00000000
        18a0:2a40 @ 06858989 - LdrpSearchPath - RETURN: Status: 0x00000000
        18a0:2a40 @ 06859036 - LdrpMapViewOfSection - ENTER: DLL name: C:\QA\Pcdlrn\Win32\Release\INTERFAC.DLL
    'CNCServer.exe': Loaded 'C:\QA\Pcdlrn\Win32\Release\INTERFAC.dll', Symbols loaded.
        18a0:2a40 @ 06859098 - LdrpMapViewOfSection - RETURN: Status: 0x40000003
        18a0:2a40 @ 06859098 - LdrpRelocateImage - ENTER: DLL name: C:\QA\Pcdlrn\Win32\Release\INTERFAC.DLL
            18a0:2a40 @ 06859098 - LdrpProtectAndRelocateImage - RETURN: Status: 0x00000000
        18a0:2a40 @ 06859098 - LdrpRelocateImage - RETURN: Status: 0x00000000
    18a0:2a40 @ 06859098 - LdrpFindOrMapDll - RETURN: Status: 0x00000000
    

    When LdrpMapViewOfSection returns STATUS_IMAGE_NOT_AT_BASE, it's caller (LdrpFindOrMapDll) goes ahead and calls LdrpRelocateImage, something it apparently can't to for PCDLRN.exe.

    0 讨论(0)
提交回复
热议问题