Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Free toolchains, Windows Driver Kit and Windows SDK interoperability #64

Open
KOLANICH opened this issue May 17, 2018 · 3 comments
Open
Labels
Advanced Projects that require a high level of understanding of the topics specified, or programming in gnrl. Much work This project takes little time to complete. (ETA several weeks+)

Comments

@KOLANICH
Copy link

KOLANICH commented May 17, 2018

Project description

Microsoft have managed to do a terrible thing: nearly everyone who tries to build a driver for Windows have to use their proprietary and untrustworthy compiler. It is not obvious: there are some examples of helloworld drivers buildable with MinGW, but they are helloworld, and in a few questions on StackOverflow it's just advised to use MSVC.

I have recently tried to build WinDivert (it is a library and a driver for tampering with network packets) using only a free toolchain. I couldn't!

As I understand (correct me, if I'm wrong):
1 To build a driver for Windows a one needs both Windows Driver Kit and Windows SDK. They are compatible only with the latest MSVC.
2 MinGW ships an own WDK in a /ddk folder, which is far from being complete.
3 ReactOS (a project trying to build an own OS with own kernel compatible with Windows drivers and programs) has own free SDKs used to build free drivers for ReactOS, but again they reflect the state of ReactOS, which is far from completion, and I don't know if the drivers built with this SDK compatible with Windows.

I guess the alternative SDKs will always be incomplete, so we need to find a way to use the Microsoft-provided SDK.

When I tried to build the driver I encountered the following troubles:
1 drivers usually include WDK headers directly, but free drivers include the headers from a ddk subdir. This is easily solved with cmake.
2 WDK is not enough! It uses some headers from Windows SDK.
3 WDK and Windows SDK have a very shitty installer installing all the architectures and all the unneeded libs and headers. This is solved by manually installing .msis from the folder.
4 WDK and Windows SDK still lack some headers, such as kernelspec.h. I don't know where are these headers, they are missing in both WDK and WSDK, and in mingw ddk too. But they are present in ReactOS SDK. Putting them into shared subfolder of Windows Kits allows us to suppress an error with missing header. But there are plenty of errors persisting.
5 One of the problems are large incompatibilities between MSVC and GCC. For example in inline assembly syntax. This can be solved 3 ways

a) write a script transforming MSVS inline assembly into GCC one:
1) using https://github.com/stasinek/stasm with nearly zero changes in the asm
2) using https://github.com/skywind3000/Intel2GAS , but it doesn't support variables and doesn't work.

b) implement MSVC inline assembly syntax and other things in GCC. I guess it is the best way since the syntax used in gcc is terrible and bloated with string literals.
c) use clang, which may has support for MS inline asm syntax and some other extensions, since it has a version with MSVC-compatible cli targeted to be used with Visual Studio. It is the most viable variant IMHO. Let's try to stick to it.

6 Using clang with MinGW headers has some troubles. One of them is that I haven't managed it work correctly with MinGW not in PATH. So you have to remove system-installed MinGW (for example the one installed by Theano in Anaconda) from PATH and put there the one you have downloaded. I don't know why so. Otherwise CMake build fails. Secondly you need a toolchain file:

here is my toolchain.cmake
#set(CMAKE_SYSTEM_NAME Windows) #this way all the compilers variables are changed by some script
set(CMAKE_SYSTEM_NAME Generic)

set(triple i686-pc-windows-gnu)
set(LLVM_DEFAULT_TARGET_TRIPLE ${triple})

set(DUMP_DIR "./" CACHE PATH "The dir where we have unpacked mingw and clang")

set(CLANG_ROOT "${DUMP_DIR}/LLVM-6.0.0-win32" CACHE PATH "Path to Clang root")
set(MINGW_ROOT "${DUMP_DIR}/i686-7.3.0-release-win32-dwarf-rt_v5-rev0/mingw32" CACHE PATH "Path to MinGW root")
set(REACTOS_SDK "${DUMP_DIR}/reactos-sdk/" CACHE PATH "Path to ReactOS SDK root")

message(STATUS ${CLANG_ROOT})
message(STATUS ${MINGW_ROOT})
message(STATUS ${REACTOS_SDK})

set(CLANG_BIN "${CLANG_ROOT}/bin")
set(MINGW_BIN "${MINGW_ROOT}/bin")

message(STATUS ${CLANG_BIN})
message(STATUS ${MINGW_BIN})

set(REST_OF_TOOLCHAIN_IS_LLVM ON CACHE BOOL "If this is selected, the rest of toolchain is LLVM, otherwise it is MinGW")

set(CMAKE_C_COMPILER "${CLANG_BIN}/clang.exe")
set(CMAKE_CXX_COMPILER "${CLANG_BIN}/clang++.exe")
set(CMAKE_CPP_COMPILER "${CLANG_BIN}/clang++.exe")

set(CMAKE_RC_COMPILER "${MINGW_BIN}/windres.exe")
set(CMAKE_MAKE_PROGRAM "${MINGW_BIN}/mingw32-make.exe" FORCE)
set(CMAKE_NM "${MINGW_BIN}/nm.exe")
set(CMAKE_OBJCOPY "${MINGW_BIN}/objcopy.exe")
set(CMAKE_STRIP "${MINGW_BIN}/strip.exe")

if(REST_OF_TOOLCHAIN_IS_LLVM)
	set(CMAKE_AR "${CLANG_BIN}/llvm-ar.exe")
	set(CMAKE_OBJDUMP "${CLANG_BIN}/llvm-objdump.exe")
	set(CMAKE_RANLIB "${CLANG_BIN}/llvm-ranlib.exe")
	set(CMAKE_RANLIB "${CLANG_BIN}/lld.exe")
else()
	set(CMAKE_AR "${MINGW_BIN}/ar.exe")
	set(CMAKE_OBJDUMP "${MINGW_BIN}/objdump.exe")
	set(CMAKE_RANLIB "${MINGW_BIN}/ranlib.exe")
	set(CMAKE_LINKER "${MINGW_BIN}/link.exe")
endif()

set(CMAKE_C_COMPILER_TARGET ${triple})
set(CMAKE_CXX_COMPILER_TARGET ${triple})
set(CMAKE_CPP_COMPILER_TARGET ${triple})

set(CMAKE_FLAGS "-v --target=${triple}")
set(CMAKE_FLAGS "${CMAKE_FLAGS} -isystem \"${MINGW_ROOT}/opt/include\" -isystem \"${MINGW_ROOT}/i686-w64-mingw32/include\" -isystem \"${MINGW_ROOT}/include\"")
#set(CMAKE_FLAGS "${CMAKE_FLAGS} -W,L${MINGW_ROOT}/lib,L${MINGW_ROOT}/opt/lib")

#message(STATUS "CMAKE_FLAGS ${CMAKE_FLAGS}")

set(CMAKE_C_FLAGS ${CMAKE_FLAGS})
set(CMAKE_CXX_FLAGS ${CMAKE_FLAGS})

set(CMAKE_LINKER_FLAGS "-v \"-L${MINGW_ROOT}/lib\" \"-L${MINGW_ROOT}/opt/lib\"")
set(CMAKE_C_LINKER_FLAGS ${CMAKE_LINKER_FLAGS})
set(CMAKE_CXX_LINKER_FLAGS ${CMAKE_LINKER_FLAGS})


#'--sysroot=''

# target environment on the build host system
#   set 1st to dir with the cross compiler's C/C++ headers/libs
#set(CMAKE_FIND_ROOT_PATH "${CLANG_ROOT}/lib/clang/6.0.0")

#SET(CMAKE_FIND_ROOT_PATH ${MINGW_ROOT})

# modify default behavior of FIND_XXX() commands to
# search for headers/libs in the target environment and
# search for programs in the build host environment
#set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
#set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
#set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)

7 CLang doesn't have any own Windows SDK and WDK headers. You have to download and install them.

8 These headers depend on MSVC headers and MinGW headers cannot be used instead. They lack some definitions. I haven't managed to build WinDivert with it.

So I have run out of deadline I set on this project, so I hope that community can do something with it.

@FredrikAugust FredrikAugust added Much work This project takes little time to complete. (ETA several weeks+) Advanced Projects that require a high level of understanding of the topics specified, or programming in gnrl. labels Jun 20, 2018
@FredrikAugust
Copy link
Collaborator

Hey,

Sorry, but I don't know much about this.

Good luck!

@KOLANICH
Copy link
Author

KOLANICH commented Jan 4, 2019

I was able to build https://github.com/basil00/Divert successfully using MinGW on Windows 10

@sfhacker, could you, please, create an issue/PR to https://github.com/basil00/Divert sharing your experience?

However when I try to start the service, I get error 2: cannot find the specified file.

You may want to grep the code and insert there some traceback. Usually the driver's sys has to be in the same dir the app is, the dll should install it itself. Take attention to admin rights and signing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Advanced Projects that require a high level of understanding of the topics specified, or programming in gnrl. Much work This project takes little time to complete. (ETA several weeks+)
Projects
None yet
Development

No branches or pull requests

3 participants
@KOLANICH @FredrikAugust and others