diff --git a/sdk/cmake/CMakeMacros.cmake b/sdk/cmake/CMakeMacros.cmake index 2d5628f02a2..9df6eb608e2 100644 --- a/sdk/cmake/CMakeMacros.cmake +++ b/sdk/cmake/CMakeMacros.cmake @@ -541,7 +541,10 @@ function(add_importlibs _module) endfunction() # Some helper lists -list(APPEND KERNEL_MODULE_TYPES kerneldll kernelmodedriver wdmdriver) +list(APPEND VALID_MODULE_TYPES kernel kerneldll kernelmodedriver wdmdriver nativecui nativedll win32cui win32gui win32dll win32ocx cpl module) +list(APPEND KERNEL_MODULE_TYPES kernel kerneldll kernelmodedriver wdmdriver) +list(APPEND NATIVE_MODULE_TYPES kernel kerneldll kernelmodedriver wdmdriver nativecui nativedll) + function(set_module_type MODULE TYPE) cmake_parse_arguments(__module "UNICODE" "IMAGEBASE" "ENTRYPOINT" ${ARGN}) @@ -549,38 +552,34 @@ function(set_module_type MODULE TYPE) message(STATUS "set_module_type : unparsed arguments ${__module_UNPARSED_ARGUMENTS}, module : ${MODULE}") endif() - # Add the module to the module group list, if it is defined - if(DEFINED CURRENT_MODULE_GROUP) - set_property(GLOBAL APPEND PROPERTY ${CURRENT_MODULE_GROUP}_MODULE_LIST "${MODULE}") - endif() - - # Set subsystem. Also take this as an occasion - # to error out if someone gave a non existing type - if((${TYPE} STREQUAL nativecui) OR (${TYPE} STREQUAL nativedll) - OR (${TYPE} STREQUAL kernelmodedriver) OR (${TYPE} STREQUAL wdmdriver) OR (${TYPE} STREQUAL kerneldll)) - set(__subsystem native) - elseif(${TYPE} STREQUAL win32cui) - set(__subsystem console) - elseif(${TYPE} STREQUAL win32gui) - set(__subsystem windows) - elseif(NOT ((${TYPE} STREQUAL win32dll) OR (${TYPE} STREQUAL win32ocx) - OR (${TYPE} STREQUAL cpl) OR (${TYPE} STREQUAL module))) + # Check this is a type that we know + if (NOT TYPE IN_LIST VALID_MODULE_TYPES) message(FATAL_ERROR "Unknown type ${TYPE} for module ${MODULE}") endif() # Set our target property set_target_properties(${MODULE} PROPERTIES REACTOS_MODULE_TYPE ${TYPE}) - if(DEFINED __subsystem) - set_subsystem(${MODULE} ${__subsystem}) + # Add the module to the module group list, if it is defined + if(DEFINED CURRENT_MODULE_GROUP) + set_property(GLOBAL APPEND PROPERTY ${CURRENT_MODULE_GROUP}_MODULE_LIST "${MODULE}") + endif() + + # Set subsystem. + if(TYPE IN_LIST NATIVE_MODULE_TYPES) + set_subsystem(${MODULE} native) + elseif(${TYPE} STREQUAL win32cui) + set_subsystem(${MODULE} console) + elseif(${TYPE} STREQUAL win32gui) + set_subsystem(${MODULE} windows) endif() # Set the PE image version numbers from the NT OS version ReactOS is based on if(MSVC) - add_target_link_flags(${MODULE} "/VERSION:5.01") + target_link_options(${MODULE} PRIVATE "/VERSION:5.01") else() - add_target_link_flags(${MODULE} "-Wl,--major-image-version,5 -Wl,--minor-image-version,01") - add_target_link_flags(${MODULE} "-Wl,--major-os-version,5 -Wl,--minor-os-version,01") + target_link_options(${MODULE} PRIVATE + -Wl,--major-image-version,5 -Wl,--minor-image-version,01 -Wl,--major-os-version,5 -Wl,--minor-os-version,01) endif() # Set unicode definitions @@ -590,49 +589,32 @@ function(set_module_type MODULE TYPE) # Set entry point if(__module_ENTRYPOINT OR (__module_ENTRYPOINT STREQUAL "0")) - list(GET __module_ENTRYPOINT 0 __entrypoint) - list(LENGTH __module_ENTRYPOINT __length) - if(${__length} EQUAL 2) - list(GET __module_ENTRYPOINT 1 __entrystack) - elseif(NOT ${__length} EQUAL 1) - message(FATAL_ERROR "Wrong arguments for ENTRYPOINT parameter of set_module_type : ${__module_ENTRYPOINT}") - endif() - unset(__length) + set_entrypoint(${MODULE} ${__module_ENTRYPOINT}) elseif(${TYPE} STREQUAL nativecui) - set(__entrypoint NtProcessStartup) - set(__entrystack 4) + set_entrypoint(${MODULE} NtProcessStartup 4) elseif(${TYPE} STREQUAL win32cui) if(__module_UNICODE) - set(__entrypoint wmainCRTStartup) + set_entrypoint(${MODULE} wmainCRTStartup) else() - set(__entrypoint mainCRTStartup) + set_entrypoint(${MODULE} mainCRTStartup) endif() elseif(${TYPE} STREQUAL win32gui) if(__module_UNICODE) - set(__entrypoint wWinMainCRTStartup) + set_entrypoint(${MODULE} wWinMainCRTStartup) else() - set(__entrypoint WinMainCRTStartup) + set_entrypoint(${MODULE} WinMainCRTStartup) endif() elseif((${TYPE} STREQUAL win32dll) OR (${TYPE} STREQUAL win32ocx) OR (${TYPE} STREQUAL cpl)) - set(__entrypoint DllMainCRTStartup) - set(__entrystack 12) + set_entrypoint(${MODULE} DllMainCRTStartup 12) elseif((${TYPE} STREQUAL kernelmodedriver) OR (${TYPE} STREQUAL wdmdriver)) - set(__entrypoint DriverEntry) - set(__entrystack 8) + set_entrypoint(${MODULE} DriverEntry 8) elseif(${TYPE} STREQUAL nativedll) - set(__entrypoint DllMain) - set(__entrystack 12) + set_entrypoint(${MODULE} DllMain 12) + elseif(TYPE STREQUAL kernel) + set_entrypoint(${MODULE} KiSystemStartup 4) elseif(${TYPE} STREQUAL module) - set(__entrypoint 0) - endif() - - if(DEFINED __entrypoint) - if(DEFINED __entrystack) - set_entrypoint(${MODULE} ${__entrypoint} ${__entrystack}) - else() - set_entrypoint(${MODULE} ${__entrypoint}) - endif() + set_entrypoint(${MODULE} 0) endif() # Set base address @@ -644,18 +626,29 @@ function(set_module_type MODULE TYPE) else() message(STATUS "${MODULE} has no base address") endif() - elseif((${TYPE} STREQUAL kernelmodedriver) OR (${TYPE} STREQUAL wdmdriver) OR (${TYPE} STREQUAL kerneldll)) - set_image_base(${MODULE} 0x00010000) + elseif(TYPE IN_LIST KERNEL_MODULE_TYPES) + # special case for kernel + if (TYPE STREQUAL kernel) + set_image_base(${MODULE} 0x00400000) + else() + set_image_base(${MODULE} 0x00010000) + endif() endif() # Now do some stuff which is specific to each type - if((${TYPE} STREQUAL kernelmodedriver) OR (${TYPE} STREQUAL wdmdriver) OR (${TYPE} STREQUAL kerneldll)) + if(TYPE IN_LIST KERNEL_MODULE_TYPES) add_dependencies(${MODULE} bugcodes xdk) if((${TYPE} STREQUAL kernelmodedriver) OR (${TYPE} STREQUAL wdmdriver)) set_target_properties(${MODULE} PROPERTIES SUFFIX ".sys") endif() endif() + if (TYPE STREQUAL kernel) + # Kernels are executables with exports + set_property(TARGET ${MODULE} PROPERTY ENABLE_EXPORTS TRUE) + set_target_properties(${MODULE} PROPERTIES DEFINE_SYMBOL "") + endif() + if(${TYPE} STREQUAL win32ocx) set_target_properties(${MODULE} PROPERTIES SUFFIX ".ocx") endif() diff --git a/sdk/cmake/gcc.cmake b/sdk/cmake/gcc.cmake index 442422a74dc..cd9585dc6cf 100644 --- a/sdk/cmake/gcc.cmake +++ b/sdk/cmake/gcc.cmake @@ -285,11 +285,15 @@ function(set_module_type_toolchain MODULE TYPE) if(${TYPE} STREQUAL "wdmdriver") target_link_options(${MODULE} PRIVATE "-Wl,--wdmdriver") endif() - # Place INIT section at the tail of the module + # Place INIT &.rsrc section at the tail of the module, before .reloc add_linker_script(${MODULE} ${REACTOS_SOURCE_DIR}/sdk/cmake/init-section.lds) - # Fixup section characteristiscs + # Fixup section characteristics + # - Remove flags that LD overzealously puts (alignment flag, Initialized flags for code sections) + # - INIT section is made discardable + # - .rsrc is made read-only + # - PAGE & .edata sections are made pageable. add_custom_command(TARGET ${MODULE} POST_BUILD - COMMAND native-pefixup --driver $) + COMMAND native-pefixup --${TYPE} $) # Believe it or not, cmake doesn't do that set_property(TARGET ${MODULE} APPEND PROPERTY LINK_DEPENDS $) endif() diff --git a/sdk/cmake/msvc.cmake b/sdk/cmake/msvc.cmake index 33fdbea00f0..fd716b96266 100644 --- a/sdk/cmake/msvc.cmake +++ b/sdk/cmake/msvc.cmake @@ -249,13 +249,20 @@ function(set_image_base MODULE IMAGE_BASE) endfunction() function(set_module_type_toolchain MODULE TYPE) - if((${TYPE} STREQUAL "win32dll") OR (${TYPE} STREQUAL "win32ocx") OR (${TYPE} STREQUAL "cpl")) - add_target_link_flags(${MODULE} "/DLL") - elseif(${TYPE} STREQUAL "kernelmodedriver") - # Disable linker warning 4078 (multiple sections found with different attributes) for INIT section use - add_target_link_flags(${MODULE} "/DRIVER /SECTION:INIT,ERWD") - elseif(${TYPE} STREQUAL "wdmdriver") - add_target_link_flags(${MODULE} "/DRIVER:WDM /SECTION:INIT,ERWD") + if((TYPE STREQUAL win32dll) OR (TYPE STREQUAL win32ocx) OR (TYPE STREQUAL cpl)) + target_link_options(${MODULE} PRIVATE /DLL) + elseif(TYPE IN_LIST KERNEL_MODULE_TYPES) + # Mark INIT section as Executable Read Write Discardable + target_link_options(${MODULE} PRIVATE /SECTION:INIT,ERWD) + + if(TYPE STREQUAL kernelmodedriver) + target_link_options(${MODULE} PRIVATE /DRIVER) + elseif(TYPE STREQUAL wdmdriver) + target_link_options(${MODULE} PRIVATE /DRIVER:WDM) + elseif (TYPE STREQUAL kernel) + # Mark .rsrc section as non-disposable non-pageable, as bugcheck code needs to access it + target_link_options(${MODULE} PRIVATE /SECTION:.rsrc,!DP ) + endif() endif() if(RUNTIME_CHECKS) diff --git a/sdk/include/host/pecoff.h b/sdk/include/host/pecoff.h index 28daca13da4..74104075fb6 100644 --- a/sdk/include/host/pecoff.h +++ b/sdk/include/host/pecoff.h @@ -39,6 +39,22 @@ #define IMAGE_SCN_MEM_READ 0x40000000 #define IMAGE_SCN_MEM_WRITE 0x80000000 +#define IMAGE_SCN_ALIGN_1BYTES 0x00100000 +#define IMAGE_SCN_ALIGN_2BYTES 0x00200000 +#define IMAGE_SCN_ALIGN_4BYTES 0x00300000 +#define IMAGE_SCN_ALIGN_8BYTES 0x00400000 +#define IMAGE_SCN_ALIGN_16BYTES 0x00500000 +#define IMAGE_SCN_ALIGN_32BYTES 0x00600000 +#define IMAGE_SCN_ALIGN_64BYTES 0x00700000 +#define IMAGE_SCN_ALIGN_128BYTES 0x00800000 +#define IMAGE_SCN_ALIGN_256BYTES 0x00900000 +#define IMAGE_SCN_ALIGN_512BYTES 0x00A00000 +#define IMAGE_SCN_ALIGN_1024BYTES 0x00B00000 +#define IMAGE_SCN_ALIGN_2048BYTES 0x00C00000 +#define IMAGE_SCN_ALIGN_4096BYTES 0x00D00000 +#define IMAGE_SCN_ALIGN_8192BYTES 0x00E00000 +#define IMAGE_SCN_ALIGN_MASK 0x00F00000 + #define IMAGE_NUMBEROF_DIRECTORY_ENTRIES 16 #define IMAGE_REL_I386_ABSOLUTE 0x0001 diff --git a/sdk/tools/pefixup.c b/sdk/tools/pefixup.c index 81dfcc96c5a..3ea638653a0 100644 --- a/sdk/tools/pefixup.c +++ b/sdk/tools/pefixup.c @@ -27,7 +27,10 @@ static const char* g_Target; enum fixup_mode { MODE_LOADCONFIG, - MODE_DRIVER + MODE_KERNELDRIVER, + MODE_WDMDRIVER, + MODE_KERNELDLL, + MODE_KERNEL }; void *rva_to_ptr(unsigned char *buffer, PIMAGE_NT_HEADERS nt_header, DWORD rva) @@ -127,13 +130,27 @@ static int add_loadconfig(unsigned char *buffer, PIMAGE_NT_HEADERS nt_header) return 1; } -static int driver_fixup(unsigned char *buffer, PIMAGE_NT_HEADERS nt_header) +static int driver_fixup(int mode, unsigned char *buffer, PIMAGE_NT_HEADERS nt_header) { /* GNU LD just doesn't know what a driver is, and has notably no idea of paged vs non-paged sections */ for (unsigned i = 0; i < nt_header->FileHeader.NumberOfSections; i++) { PIMAGE_SECTION_HEADER Section = IMAGE_FIRST_SECTION(nt_header) + i; + /* LD puts alignment crap that nobody asked for */ + Section->Characteristics &= ~IMAGE_SCN_ALIGN_MASK; + + /* LD overdoes it and puts the initialized flag everywhere */ + if (Section->Characteristics & IMAGE_SCN_CNT_CODE) + Section->Characteristics &= ~IMAGE_SCN_CNT_INITIALIZED_DATA; + + /* For some reason, .rsrc is made writable by windres */ + if (strncasecmp((char*)Section->Name, ".rsrc", 5) == 0) + { + Section->Characteristics &= ~IMAGE_SCN_MEM_WRITE; + continue; + } + /* Known sections which can be discarded */ if (strncasecmp((char*)Section->Name, "INIT", 4) == 0) { @@ -143,6 +160,8 @@ static int driver_fixup(unsigned char *buffer, PIMAGE_NT_HEADERS nt_header) /* Known sections which can be paged */ if ((strncasecmp((char*)Section->Name, "PAGE", 4) == 0) + || (strncasecmp((char*)Section->Name, ".rsrc", 5) == 0) + || (strncasecmp((char*)Section->Name, ".edata", 6) == 0) || (strncasecmp((char*)Section->Name, ".reloc", 6) == 0)) { continue; @@ -164,8 +183,11 @@ print_usage(void) { printf("Usage: %s \n", g_ApplicationName); printf("Where is on of the following:\n"); - printf(" --loadconfig Fix the LOAD_CONFIG directory entry\n"); - printf(" --driver Fix code and data sections for driver images\n"); + printf(" --loadconfig Fix the LOAD_CONFIG directory entry\n"); + printf(" --kernelmodedriver Fix code and data sections for driver images\n"); + printf(" --wdmdriver Fix code and data sections for WDM drivers\n"); + printf(" --kerneldll Fix code and data sections for Kernel-Mode DLLs\n"); + printf(" --kernel Fix code and data sections for kernels\n"); } int main(int argc, char **argv) @@ -189,9 +211,21 @@ int main(int argc, char **argv) { mode = MODE_LOADCONFIG; } - else if (strcmp(argv[1], "--driver") == 0) + else if (strcmp(argv[1], "--kernelmodedriver") == 0) { - mode = MODE_DRIVER; + mode = MODE_KERNELDRIVER; + } + else if (strcmp(argv[1], "--wdmdriver") == 0) + { + mode = MODE_WDMDRIVER; + } + else if (strcmp(argv[1], "--kerneldll") == 0) + { + mode = MODE_KERNELDLL; + } + else if (strcmp(argv[1], "--kernel") == 0) + { + mode = MODE_KERNEL; } else { @@ -245,7 +279,7 @@ int main(int argc, char **argv) if (mode == MODE_LOADCONFIG) result = add_loadconfig(buffer, nt_header); else - result = driver_fixup(buffer, nt_header); + result = driver_fixup(mode, buffer, nt_header); if (!result) {