mirror of
https://github.com/mirkobrombin/raven.git
synced 2026-11-05 21:56:33 +00:00
feat: resolve delay-loaded system libraries to the runtime's components
Assisted-by: Claude Code:claude-opus-5-5 AI-Scope: Made the loader follow delay imports when choosing components, with a delay-load test.
This commit is contained in:
1 parent
fdad9c4bd4
commit
cea6ca7a7a
4 files changed
+44
-2
No files matched your search
@@ -3537,6 +3537,20 @@ if(CMAKE_SYSTEM_PROCESSOR MATCHES "^(x86_64|amd64|AMD64)$")
|
||||
${DELAY_FIXTURES}/client.obj ${DELAY_FIXTURES}/helper.obj ${DELAY_FIXTURES}/delayed.lib ${RAVEN_KERNEL32_IMPORT}
|
||||
DEPENDS ${DELAY_FIXTURES}/client.obj ${DELAY_FIXTURES}/helper.obj ${DELAY_FIXTURES}/delayed.lib VERBATIM)
|
||||
add_custom_target(delay_pe_fixtures ALL DEPENDS ${DELAY_FIXTURES}/client.exe ${DELAY_FIXTURES}/delayed.dll)
|
||||
# A program that delay-loads the setup API gets the component behind it as one that imports it does; its name must not look like an
|
||||
# installer's, which gets the component anyway.
|
||||
# lld-link delay-loads only through an import library of its own format, written here for the one function the client calls.
|
||||
add_custom_command(OUTPUT ${DELAY_FIXTURES}/cabinet-client.exe
|
||||
COMMAND ${RAVEN_MINGW64} -O1 -fno-builtin -fno-stack-protector -c ${LOADER_SOURCES}/delay_setupapi_client.c
|
||||
-o ${DELAY_FIXTURES}/cabinet-client.obj
|
||||
COMMAND ${RAVEN_LLD_LINK} /lib /machine:x64 /def:${LOADER_SOURCES}/delay_setupapi.def /out:${DELAY_FIXTURES}/setupapi.lib
|
||||
COMMAND ${RAVEN_LLD_LINK} /entry:raven_entry /subsystem:console /nodefaultlib /base:0x192000000
|
||||
/delayload:setupapi.dll /out:${DELAY_FIXTURES}/cabinet-client.exe
|
||||
${DELAY_FIXTURES}/cabinet-client.obj ${DELAY_FIXTURES}/helper.obj ${DELAY_FIXTURES}/setupapi.lib ${RAVEN_KERNEL32_IMPORT}
|
||||
DEPENDS ${LOADER_SOURCES}/delay_setupapi_client.c ${LOADER_SOURCES}/delay_setupapi.def ${DELAY_FIXTURES}/helper.obj VERBATIM)
|
||||
add_custom_target(delay_setupapi_fixture ALL DEPENDS ${DELAY_FIXTURES}/cabinet-client.exe)
|
||||
add_test(NAME native_delay_setupapi COMMAND raven --run-process --execution=native ${DELAY_FIXTURES}/cabinet-client.exe)
|
||||
set_tests_properties(native_delay_setupapi PROPERTIES TIMEOUT 30 PASS_REGULAR_EXPRESSION "Native entry returned 0 ")
|
||||
add_executable(delay_loader_test nt/delay_loader_test.cpp)
|
||||
target_link_libraries(delay_loader_test PRIVATE raven_cpu)
|
||||
add_dependencies(delay_loader_test delay_pe_fixtures raven-bootstrap)
|
||||
|
||||
+5
-2
@@ -492,7 +492,7 @@ int main(int argc, char **argv)
|
||||
if (std::filesystem::exists(component))
|
||||
modules.add("raven-rtl.dll", read_file(component.c_str()));
|
||||
}
|
||||
// The libraries the program and the DLLs shipped beside it import, by lowercase file name.
|
||||
// The libraries the program and the DLLs shipped beside it import, at once or lazily, by lowercase file name.
|
||||
const auto imported_libraries = [&] {
|
||||
std::set<std::string> names;
|
||||
std::vector<std::string> pending;
|
||||
@@ -509,8 +509,11 @@ int main(int argc, char **argv)
|
||||
if (names.insert(lower(symbol.module)).second)
|
||||
pending.push_back(lower(symbol.module));
|
||||
};
|
||||
for (const auto &item : modules.all())
|
||||
for (const auto &item : modules.all()) {
|
||||
visit(item.second->imports);
|
||||
for (const auto &descriptor : item.second->image.delay_imports())
|
||||
visit(descriptor.imports);
|
||||
}
|
||||
while (!pending.empty()) {
|
||||
const auto name = pending.back();
|
||||
pending.pop_back();
|
||||
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
LIBRARY setupapi.dll
|
||||
EXPORTS
|
||||
SetupIterateCabinetW
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
#include <windows.h>
|
||||
#include <setupapi.h>
|
||||
#include <delayimp.h>
|
||||
|
||||
PfnDliHook __pfnDliNotifyHook2 = NULL;
|
||||
PfnDliHook __pfnDliFailureHook2 = NULL;
|
||||
|
||||
static UINT CALLBACK visit(PVOID context, UINT notification, UINT_PTR first, UINT_PTR second)
|
||||
{
|
||||
++*(int *)context;
|
||||
return NO_ERROR;
|
||||
}
|
||||
|
||||
/* A program that loads the setup API only lazily, as large installers delay-load it, still extracts cabinets through it: a cabinet that
|
||||
* does not exist is refused without visiting any file. */
|
||||
int raven_entry(void)
|
||||
{
|
||||
int visited = 0;
|
||||
if (SetupIterateCabinetW(L"C:\\raven-missing.cab", 0, visit, &visited)) return 1;
|
||||
if (visited) return 2;
|
||||
return 0;
|
||||
}
|
||||
Reference in new issue
Block a user