Updated and expanded peldd for usage on Windows
- updated to newest pe-parse
- added experimental filesystem support and c++17 filesystem support in addition to boost
- tested on windows: compiles using
mingw-w64, runs on windows - improved windows compatibility with additional options to include
PATHand thecwdin the search path. - added some modern windows libraries to whitelist
Is this package still maintained at all? ping @gsauthof
Is this package still maintained at all? ping @gsauthof
Well, kind of. Although lately I don't have to target windows systems anymore. Thus, maintaining this project isn't my top priority.
However, please consider the following:
I prefer pull-requests that fix one thing and not bundle a bunch of issues together. Also, it's not sufficient to describe what is changed. It's more important to add why something is changed, i.e. adding some motivation.
For example, looking at this pull-request I really don't know why pe-utils was updated - is this update required to fix some issue? Why is experimental C++17 filesystem support added? etc.
Thus, this pull-request should be split into more digestible pieces.
This pull request does fix one thing, which is compiling and using pe-utils on Windows. Maybe a more detailed explanation should have been given, but every commit in this PR also improves the compilation/usage of pe-util on Windows.
Because the project seemed inactive, some modernizations were added as well. Keeping all the changes in one place instead of splitting them across PRs allows others having the same issue to just use the PR branch.
Why is experimental C++17 filesystem support added
A central part of making pe-util easy to compile for/on Windows was getting rid of the boost dependency. Since mingw-w64 supports (experimental) C++17 filesystem, it was added as an option to avoid having to deal with boost on Windows.
The Windows usage is also the motivation for expanding the whitelist, since Windows 10 introduces new system libraries and also why the search path and CWD options were added, since Windows searches these locations as well.
Thus, this pull-request should be split into more digestible pieces.
I am not sure how to split it in a way that makes sense. If you like, I can try to split the modernization part from the Windows support.
Resolved merge conflicts
Good work, @roussosalex , I will try your branch today, thanks!
I see this when I try to run cmake inside the msys2's mingw64.exe shell
zyh@WINMICR-0PLE9E2 MINGW64 /d/code/temp/pe-util/build
# cmake -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release ..
CMake Error at CMakeLists.txt:13 (else):
Flow control statements are not properly nested.
-- Configuring incomplete, errors occurred!
Sorry, I don't know cmake very much.
CMakeLists.txt | 1 +
1 file changed, 1 insertion(+)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2e43e20..6249991 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -16,6 +16,7 @@ else()
set(Boost_ARCHITECTURE "-x64")
else()
set(Boost_ARCHITECTURE "-x32")
+ endif()
endif()
find_package(Boost 1.54 COMPONENTS
This is the fix.
Fixed it. Thanks!
I passed the cmake, but failed when running the mingw32-make.exe, see the log below:
zyh@WINMICR-0PLE9E2 MINGW64 /d/code/temp/pe-util/build
# cmake -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release -DUSE_FILESYSTEM=1 ..
-- VERSION file: D:/code/temp/pe-util/pe-parse/pe-parser-library/../VERSION
-- Configuring done
-- Generating done
-- Build files have been written to: D:/code/temp/pe-util/build
zyh@WINMICR-0PLE9E2 MINGW64 /d/code/temp/pe-util/build
# mingw32-make
[ 12%] Building CXX object CMakeFiles/peldd.dir/peldd.cc.obj
D:\code\temp\pe-util\peldd.cc:4:10: fatal error: parser-library/parse.h: No such file or directory
4 | #include <parser-library/parse.h>
| ^~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
mingw32-make[2]: *** [CMakeFiles\peldd.dir\build.make:75: CMakeFiles/peldd.dir/peldd.cc.obj] Error 1
mingw32-make[1]: *** [CMakeFiles\Makefile2:99: CMakeFiles/peldd.dir/all] Error 2
mingw32-make: *** [Makefile:135: all] Error 2
Looks like you may be using native mingw32-make in a unix-like MSYS2 shell. According to CMake documentation use the "MinGW Makefiles" generator only in a native shell like cmd.exe. For MSYS2 shell use "MSYS Makefiles" generator.
NO, I think there are several kinds of shells.
When started by msys2.exe, it is a msys shell, but when started by mingw64.exe, it looks like a windows cmd.exe.
I just tried it in windows command line( I have put my F:\msys2\mingw64\bin in the PATH), it has the same error:
D:\code\temp\pe-util\build>cmake -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release -DUSE_FILESYSTEM=1 ..
-- The CXX compiler identification is GNU 11.2.0
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: F:/msys2/mingw64/bin/g++.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- The C compiler identification is GNU 11.2.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: F:/msys2/mingw64/bin/gcc.exe - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- VERSION file: D:/code/temp/pe-util/pe-parse/pe-parser-library/../VERSION
-- Configuring done
-- Generating done
-- Build files have been written to: D:/code/temp/pe-util/build
D:\code\temp\pe-util\build>mingw32-make
[ 12%] Building CXX object CMakeFiles/peldd.dir/peldd.cc.obj
D:\code\temp\pe-util\peldd.cc:4:10: fatal error: parser-library/parse.h: No such file or directory
4 | #include <parser-library/parse.h>
| ^~~~~~~~~~~~~~~~~~~~~~~~
compilation terminated.
mingw32-make[2]: *** [CMakeFiles\peldd.dir\build.make:75: CMakeFiles/peldd.dir/peldd.cc.obj] Error 1
mingw32-make[1]: *** [CMakeFiles\Makefile2:99: CMakeFiles/peldd.dir/all] Error 2
mingw32-make: *** [Makefile:135: all] Error 2
D:\code\temp\pe-util\build>
Do I have to build the parser-library first? I'm not good at cmake, but it looks like the git submodule is not build first.
Looks like you updated the git submodule a little too much. Run git submodule update in pe-util and it should work again.
OK, indeed, I have update the submodule too much(I mean I used the submodule's master head)
Now, the header issue is gone, but here comes another issue:
D:\code\temp\pe-util\build>cmake -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release -DUSE_FILESYSTEM=1 ..
-- The CXX compiler identification is GNU 11.2.0
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: F:/msys2/mingw64/bin/g++.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- The C compiler identification is GNU 11.2.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: F:/msys2/mingw64/bin/gcc.exe - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: D:/code/temp/pe-util/build
D:\code\temp\pe-util\build>mingw32-make
[ 14%] Building CXX object pe-parse/pe-parser-library/CMakeFiles/pe-parser-library.dir/src/buffer.cpp.obj
[ 28%] Building CXX object pe-parse/pe-parser-library/CMakeFiles/pe-parser-library.dir/src/parse.cpp.obj
[ 42%] Linking CXX static library libpe-parser-library.a
[ 42%] Built target pe-parser-library
[ 57%] Building CXX object CMakeFiles/peldd.dir/peldd.cc.obj
D:\code\temp\pe-util\peldd.cc:26:23: error: 'filesystem' is not a namespace-name; did you mean 'system'?
26 | namespace fs = std::filesystem;
| ^~~~~~~~~~
| system
D:\code\temp\pe-util\peldd.cc: In function 'std::string peparse::_get_cwd()':
D:\code\temp\pe-util\peldd.cc:109:10: error: 'fs' has not been declared
109 | return fs::current_path().string();
| ^~
D:\code\temp\pe-util\peldd.cc: In function 'std::pair<std::deque<std::__cxx11::basic_string<char> >, bool> names(const char*)':
D:\code\temp\pe-util\peldd.cc:288:8: error: 'fs' has not been declared
288 | if (!fs::exists(filename))
| ^~
D:\code\temp\pe-util\peldd.cc: In member function 'std::string Path_Cache::resolve(const std::deque<std::__cxx11::basic_string<char> >&, const string&)':
D:\code\temp\pe-util\peldd.cc:470:9: error: 'fs' has not been declared
470 | if (fs::exists(path)) {
| ^~
D:\code\temp\pe-util\peldd.cc:475:26: error: 'fs' has not been declared
475 | for (auto &e : fs::directory_iterator(path)) {
| ^~
D:\code\temp\pe-util\peldd.cc:480:31: error: 'fs' has not been declared
480 | return path + (char)fs::path::preferred_separator + resolve(r.first->second, filename);
| ^~
D:\code\temp\pe-util\peldd.cc:482:31: error: 'fs' has not been declared
482 | return path + (char)fs::path::preferred_separator + resolve(i->second, filename);
| ^~
D:\code\temp\pe-util\peldd.cc: In member function 'void Traverser::prepare_stack()':
D:\code\temp\pe-util\peldd.cc:518:24: error: 'fs' has not been declared
518 | auto p = make_pair(fs::path(a).filename().string(), a);
| ^~
mingw32-make[2]: *** [CMakeFiles\peldd.dir\build.make:76: CMakeFiles/peldd.dir/peldd.cc.obj] Error 1
mingw32-make[1]: *** [CMakeFiles\Makefile2:99: CMakeFiles/peldd.dir/all] Error 2
mingw32-make: *** [Makefile:135: all] Error 2
D:\code\temp\pe-util\build>
Yes your mingw compiler does not have C++17 filesystem, instead use USE_FILESYSTEM_EXPERIMENTAL=ON.
I'm using the latest msys2 and its 64bit gcc 11 mingw compiler, not sure why it does not have C++17
I enable the -d option of mingw32-make.exe, and here is the log:
[ 57%] Building CXX object CMakeFiles/peldd.dir/peldd.cc.obj
Reaping winning child 000000000032d4c0 PID 3292816
CreateProcess(F:\msys2\mingw64\bin\g++.exe,F:\msys2\mingw64\bin\g++.exe -DUSE_FILESYSTEM @CMakeFiles/peldd.dir/includes_CXX.rsp -O3 -DNDEBUG -Wall -Werror -std=gnu++11 -MD -MT CMak
eFiles/peldd.dir/peldd.cc.obj -MF CMakeFiles\peldd.dir\peldd.cc.obj.d -o CMakeFiles\peldd.dir\peldd.cc.obj -c D:\code\temp\pe-util\peldd.cc,...)
Live child 000000000032d4c0 (CMakeFiles/peldd.dir/peldd.cc.obj) PID 3292816
D:\code\temp\pe-util\peldd.cc:26:23: error: 'filesystem' is not a namespace-name; did you mean 'system'?
26 | namespace fs = std::filesystem;
| ^~~~~~~~~~
| system
D:\code\temp\pe-util\peldd.cc: In function 'std::string peparse::_get_cwd()':
D:\code\temp\pe-util\peldd.cc:109:10: error: 'fs' has not been declared
109 | return fs::current_path().string();
| ^~
D:\code\temp\pe-util\peldd.cc: In function 'std::pair<std::deque<std::__cxx11::basic_string<char> >, bool> names(const char*)':
D:\code\temp\pe-util\peldd.cc:288:8: error: 'fs' has not been declared
288 | if (!fs::exists(filename))
| ^~
Strange, it still use gnu c++ 11.
But if I look at the CMakefiles, it has:
cmake_minimum_required(VERSION 3.0...3.22.1)
project(mingw_util CXX)
if (USE_FILESYSTEM)
# available with gcc 8.0
set(CMAKE_CXX_STANDARD 17)
set(PE_COMPILE_DEF USE_FILESYSTEM)
set(PE_LINK_DEF stdc++fs)
elseif(USE_FILESYSTEM_EXPERIMENTAL)
# available with gcc 5.3
set(PE_COMPILE_DEF USE_FILESYSTEM_EXPERIMENTAL)
set(PE_LINK_DEF stdc++fs)
So, the question is: Why the C++ 17 is not enabled? My GCC certainly have such C++17 support, but the problem is the gnu++11 is passed in the command line.
This is a known issue with mingw. Use experimental filesystem instead.
This is a known issue with mingw. Use experimental filesystem instead.
Oh, I see that you have explicitly enabled C++11? Here is what I see in CMakefiles
set_target_properties(peldd PROPERTIES
CXX_STANDARD 11
CXX_STANDARD_REQUIRED ON
)
This is a known issue with mingw. Use experimental filesystem instead.
On, I see that you have expcitily enabled C++11? Here is what I see in CMakefiles
set_target_properties(peldd PROPERTIES CXX_STANDARD 11 CXX_STANDARD_REQUIRED ON )
I just change this value from 11 to 17, and it builds OK now, see the log below:
D:\code\temp\pe-util\build>cmake -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release -DUSE_FILESYSTEM=ON ..
-- Configuring done
-- Generating done
-- Build files have been written to: D:/code/temp/pe-util/build
D:\code\temp\pe-util\build>mingw32-make
Consolidate compiler generated dependencies of target pe-parser-library
[ 42%] Built target pe-parser-library
Consolidate compiler generated dependencies of target peldd
[ 57%] Building CXX object CMakeFiles/peldd.dir/peldd.cc.obj
[ 71%] Building CXX object CMakeFiles/peldd.dir/pe-parse/pe-parser-library/src/parse.cpp.obj
[ 85%] Building CXX object CMakeFiles/peldd.dir/pe-parse/pe-parser-library/src/buffer.cpp.obj
[100%] Linking CXX executable peldd.exe
[100%] Built target peldd
Here is the test result of the new built peldd.exe
F:\code\cb-64bit>peldd codeblocks.exe
SHFOLDER.dll
codeblocks.dll
exchndl.dll
libgcc_s_seh-1.dll
libstdc++-6.dll
wxmsw315u_gcc_cb.dll
F:\code\cb-64bit>peldd codeblocks.exe --all
Error: Could not resolve: SHFOLDER.dll
F:\code\cb-64bit>peldd codeblocks.dll
libgcc_s_seh-1.dll
libstdc++-6.dll
wxmsw315u_gcc_cb.dll
F:\code\cb-64bit>peldd codeblocks.dll --all
Error: Could not resolve: libgcc_s_seh-1.dll
F:\code\cb-64bit>
I'm not sure, but it looks like it can't do recursive resolve the dependency. I mean find the dependency of a dependency dll.
You need to provide the correct search paths using the options -p, --search-env or --search-cwd.
You need to provide the correct search paths using the options
-p,--search-envor--search-cwd.
OK, let me check it.
BTW: I used another good tool to find the dependencies/even copy the dependencies, which is also cross platform, see here: brechtsanders/pedeps: Cross-platform C library to read data from PE/PE+ files (the format of Windows .exe and .dll files)
I just tried, but still no luck:
F:\code\cb-64bit>peldd codeblocks.exe --search-env --all
Error: Could not resolve: wxmsw315u_gcc_cb.dll
In-fact, I can start the codeblocks.exe from the command line, and the wxmsw315u_gcc_cb.dll is the main dependency of the codeblocks, which is the wxWidgets library dll. I'm not sure it still can't resolve this dll.
You probably need --search-cwd as well.
You probably need
--search-cwdas well.
Oh, this works, see the log below, thanks!!
F:\code\cb-64bit>peldd codeblocks.exe --search-env --all --search-cwd
C:\Windows\System32\KernelBase.dll
C:\Windows\System32\ntdll.dll
C:\Windows\System32\rpcrt4.dll
C:\Windows\System32\shfolder.dll
C:\Windows\System32\wsock32.dll
F:\code\cb-64bit\codeblocks.dll
F:\code\cb-64bit\exchndl.dll
F:\code\cb-64bit\mgwhelp.dll
F:\code\cb-64bit\wxmsw315u_gcc_cb.dll
F:\msys2\mingw64\bin\libgcc_s_seh-1.dll
F:\msys2\mingw64\bin\libstdc++-6.dll
F:\msys2\mingw64\bin\libwinpthread-1.dll
codeblocks.exe
It looks like the search path parameter order matters, see this log:
F:\code\cb-64bit>peldd codeblocks.exe --search-cwd --all --search-env
C:\Windows\System32\KernelBase.dll
C:\Windows\System32\ntdll.dll
C:\Windows\System32\rpcrt4.dll
C:\Windows\System32\shfolder.dll
C:\Windows\System32\wsock32.dll
F:\code\cb-64bit\codeblocks.dll
F:\code\cb-64bit\exchndl.dll
F:\code\cb-64bit\libgcc_s_seh-1.dll
F:\code\cb-64bit\libstdc++-6.dll
F:\code\cb-64bit\libwinpthread-1.dll
F:\code\cb-64bit\mgwhelp.dll
F:\code\cb-64bit\wxmsw315u_gcc_cb.dll
codeblocks.exe
In this case, the dll in the same folder (cwd) is located first, which is the default way as the Windows OS.