2020-04-24 23:36:52 +00:00
|
|
|
{ stdenv
|
|
|
|
, fetchFromGitHub
|
|
|
|
, fetchpatch
|
|
|
|
, fetchzip
|
2024-02-07 01:22:34 +00:00
|
|
|
, writeText
|
2020-04-24 23:36:52 +00:00
|
|
|
, lib
|
|
|
|
, openssl
|
|
|
|
, cmake
|
|
|
|
, autoconf
|
|
|
|
, automake
|
|
|
|
, libtool
|
2021-02-05 17:12:51 +00:00
|
|
|
, pkg-config
|
2020-04-24 23:36:52 +00:00
|
|
|
, bison
|
|
|
|
, flex
|
|
|
|
, groff
|
|
|
|
, perl
|
|
|
|
, python3
|
2024-02-07 01:22:34 +00:00
|
|
|
, ncurses
|
2020-04-24 23:36:52 +00:00
|
|
|
, time
|
|
|
|
, upx
|
2024-02-07 01:22:34 +00:00
|
|
|
, gtest
|
2020-04-24 23:36:52 +00:00
|
|
|
, libffi
|
|
|
|
, libxml2
|
|
|
|
, zlib
|
2024-02-07 01:22:34 +00:00
|
|
|
, enableTests ? true
|
|
|
|
, buildDevTools ? true
|
|
|
|
, compileYaraPatterns ? true
|
2020-04-24 23:36:52 +00:00
|
|
|
}:
|
|
|
|
|
|
|
|
let
|
2024-02-07 01:22:34 +00:00
|
|
|
# all dependencies that are normally fetched during build time (the subdirectories of `deps`)
|
|
|
|
# all of these need to be fetched through nix and applied via their <NAME>_URL cmake variable
|
2020-04-24 23:36:52 +00:00
|
|
|
capstone = fetchFromGitHub {
|
2024-02-07 01:22:34 +00:00
|
|
|
owner = "capstone-engine";
|
2020-04-24 23:36:52 +00:00
|
|
|
repo = "capstone";
|
2024-02-07 01:22:34 +00:00
|
|
|
rev = "5.0-rc2";
|
|
|
|
sha256 = "sha256-nB7FcgisBa8rRDS3k31BbkYB+tdqA6Qyj9hqCnFW+ME=";
|
2020-04-24 23:36:52 +00:00
|
|
|
};
|
|
|
|
llvm = fetchFromGitHub {
|
|
|
|
owner = "avast-tl";
|
|
|
|
repo = "llvm";
|
2024-02-07 01:22:34 +00:00
|
|
|
rev = "2a1f3d8a97241c6e91710be8f84cf3cf80c03390";
|
|
|
|
sha256 = "sha256-+v1T0VI9R92ed9ViqsfYZMJtPCjPHCr4FenoYdLuFOU=";
|
2020-04-24 23:36:52 +00:00
|
|
|
};
|
2024-02-07 01:22:34 +00:00
|
|
|
yaracpp = fetchFromGitHub {
|
|
|
|
owner = "VirusTotal";
|
|
|
|
repo = "yara";
|
|
|
|
rev = "v4.2.0-rc1";
|
|
|
|
sha256 = "sha256-WcN6ClYO2d+/MdG06RHx3kN0o0WVAY876dJiG7CwJ8w=";
|
2020-04-24 23:36:52 +00:00
|
|
|
};
|
|
|
|
yaramod = fetchFromGitHub {
|
2024-02-07 01:22:34 +00:00
|
|
|
owner = "avast";
|
2020-04-24 23:36:52 +00:00
|
|
|
repo = "yaramod";
|
2024-02-07 01:22:34 +00:00
|
|
|
rev = "aa06dd408c492a8f4488774caf2ee105ccc23ab5";
|
|
|
|
sha256 = "sha256-NVDRf2U5H92EN/Ks//uxNEaeKU+sT4VL4QyyYMO+zKk=";
|
2020-04-24 23:36:52 +00:00
|
|
|
};
|
2024-02-07 01:22:34 +00:00
|
|
|
keystone = fetchFromGitHub {
|
|
|
|
# only for tests
|
|
|
|
owner = "keystone-engine";
|
|
|
|
repo = "keystone";
|
|
|
|
rev = "d7ba8e378e5284e6384fc9ecd660ed5f6532e922";
|
|
|
|
sha256 = "1yzw3v8xvxh1rysh97y0i8y9svzbglx2zbsqjhrfx18vngh0x58f";
|
2020-04-24 23:36:52 +00:00
|
|
|
};
|
|
|
|
|
2024-02-07 01:22:34 +00:00
|
|
|
retdec-support-version = "2019-03-08";
|
|
|
|
retdec-support =
|
|
|
|
{ rev = retdec-support-version; } // # for checking the version against the expected version
|
|
|
|
fetchzip {
|
|
|
|
url = "https://github.com/avast-tl/retdec-support/releases/download/${retdec-support-version}/retdec-support_${retdec-support-version}.tar.xz";
|
|
|
|
hash = "sha256-t1tx4MfLW/lwtbO5JQ1nrFBIOeMclq+0dENuXW+ahIM=";
|
|
|
|
stripRoot = false;
|
|
|
|
};
|
|
|
|
|
|
|
|
check-dep = name: dep:
|
|
|
|
''
|
|
|
|
context="$(grep ${name}_URL --after-context 1 cmake/deps.cmake)"
|
|
|
|
expected="$(echo "$context" | grep --only-matching '".*"')"
|
|
|
|
have="${dep.rev}"
|
|
|
|
|
|
|
|
echo "checking ${name} dependency matches deps.cmake...";
|
|
|
|
if ! echo "$expected" | grep -q "$have"; then
|
|
|
|
printf '%s\n' "${name} version does not match!" " nix: $have, expected: $expected"
|
|
|
|
false
|
|
|
|
fi
|
2020-04-24 23:36:52 +00:00
|
|
|
'';
|
|
|
|
|
2024-02-07 01:22:34 +00:00
|
|
|
deps = {
|
|
|
|
CAPSTONE = capstone;
|
|
|
|
LLVM = llvm;
|
|
|
|
YARA = yaracpp;
|
|
|
|
YARAMOD = yaramod;
|
|
|
|
SUPPORT_PKG = retdec-support;
|
|
|
|
} // lib.optionalAttrs enableTests {
|
|
|
|
KEYSTONE = keystone;
|
|
|
|
# nixpkgs googletest is used
|
|
|
|
# GOOGLETEST = googletest;
|
|
|
|
};
|
2020-04-24 23:36:52 +00:00
|
|
|
|
2024-02-07 01:22:34 +00:00
|
|
|
# overwrite install-share.py to copy instead of download.
|
|
|
|
# we use this so the copy happens at the right time in the build,
|
|
|
|
# otherwise, the build process cleans the directory.
|
|
|
|
install-share =
|
|
|
|
writeText
|
|
|
|
"install-share.py"
|
|
|
|
''
|
|
|
|
import os, sys, shutil, subprocess
|
|
|
|
|
|
|
|
install_path, arch_url, sha256hash_ref, version = sys.argv[1:]
|
|
|
|
support_dir = os.path.join(install_path, 'share', 'retdec', 'support')
|
|
|
|
|
|
|
|
assert os.path.isdir(arch_url), "nix install-share.py expects a path for support url"
|
|
|
|
|
|
|
|
os.makedirs(support_dir, exist_ok=True)
|
|
|
|
shutil.copytree(arch_url, support_dir, dirs_exist_ok=True)
|
|
|
|
subprocess.check_call(['chmod', '-R', 'u+w', support_dir])
|
|
|
|
'';
|
|
|
|
in
|
|
|
|
stdenv.mkDerivation (self: {
|
2020-04-24 23:36:52 +00:00
|
|
|
pname = "retdec";
|
|
|
|
|
2024-02-07 01:22:34 +00:00
|
|
|
# If you update this you will also need to adjust the versions of the updated dependencies.
|
2020-04-24 23:36:52 +00:00
|
|
|
# I've notified upstream about this problem here:
|
|
|
|
# https://github.com/avast-tl/retdec/issues/412
|
2024-02-07 01:22:34 +00:00
|
|
|
#
|
|
|
|
# The dependencies and their sources are listed in this file:
|
|
|
|
# https://github.com/avast/retdec/blob/master/cmake/deps.cmake
|
|
|
|
version = "5.0";
|
2020-04-24 23:36:52 +00:00
|
|
|
|
|
|
|
src = fetchFromGitHub {
|
2024-02-07 01:22:34 +00:00
|
|
|
owner = "avast";
|
|
|
|
repo = "retdec";
|
|
|
|
rev = "refs/tags/v${self.version}";
|
|
|
|
sha256 = "sha256-H4e+aSgdBBbG6X6DzHGiDEIASPwBVNVsfHyeBTQLAKI=";
|
2020-04-24 23:36:52 +00:00
|
|
|
};
|
|
|
|
|
2024-02-07 01:22:34 +00:00
|
|
|
patches = [
|
|
|
|
# gcc 13 compatibility: https://github.com/avast/retdec/pull/1153
|
|
|
|
(fetchpatch {
|
|
|
|
url = "https://github.com/avast/retdec/commit/dbaab2c3d17b1eae22c581e8ab6bfefadf4ef6ae.patch";
|
|
|
|
hash = "sha256-YqHYPGAGWT4x6C+CpsOSsOIZ+NPM2FBQtGQFs74OUIQ=";
|
|
|
|
})
|
|
|
|
];
|
|
|
|
|
2020-04-24 23:36:52 +00:00
|
|
|
nativeBuildInputs = [
|
|
|
|
cmake
|
|
|
|
autoconf
|
|
|
|
automake
|
|
|
|
libtool
|
2021-02-05 17:12:51 +00:00
|
|
|
pkg-config
|
2020-04-24 23:36:52 +00:00
|
|
|
bison
|
|
|
|
flex
|
|
|
|
groff
|
|
|
|
perl
|
|
|
|
python3
|
|
|
|
];
|
|
|
|
|
|
|
|
buildInputs = [
|
|
|
|
openssl
|
|
|
|
ncurses
|
|
|
|
libffi
|
|
|
|
libxml2
|
|
|
|
zlib
|
2024-02-07 01:22:34 +00:00
|
|
|
] ++ lib.optional self.doInstallCheck gtest;
|
2020-04-24 23:36:52 +00:00
|
|
|
|
|
|
|
cmakeFlags = [
|
2024-02-07 01:22:34 +00:00
|
|
|
(lib.cmakeBool "RETDEC_TESTS" self.doInstallCheck) # build tests
|
|
|
|
(lib.cmakeBool "RETDEC_DEV_TOOLS" buildDevTools) # build tools e.g. capstone2llvmir, retdectool
|
|
|
|
(lib.cmakeBool "RETDEC_COMPILE_YARA" compileYaraPatterns) # build and install compiled patterns
|
|
|
|
] ++ lib.mapAttrsToList (k: v: lib.cmakeFeature "${k}_URL" "${v}") deps;
|
|
|
|
|
|
|
|
preConfigure =
|
|
|
|
lib.concatStringsSep "\n" (lib.mapAttrsToList check-dep deps)
|
|
|
|
+
|
|
|
|
''
|
|
|
|
cp -v ${install-share} ./support/install-share.py
|
|
|
|
|
|
|
|
# the CMakeLists assume CMAKE_INSTALL_BINDIR, etc are path components but in Nix, they are absolute.
|
|
|
|
# therefore, we need to remove the unnecessary CMAKE_INSTALL_PREFIX prepend.
|
|
|
|
substituteInPlace ./CMakeLists.txt \
|
|
|
|
--replace-warn "''$"{CMAKE_INSTALL_PREFIX}/"''$"{RETDEC_INSTALL_BIN_DIR} "''$"{CMAKE_INSTALL_FULL_BINDIR} \
|
|
|
|
--replace-warn "''$"{CMAKE_INSTALL_PREFIX}/"''$"{RETDEC_INSTALL_LIB_DIR} "''$"{CMAKE_INSTALL_FULL_LIBDIR} \
|
|
|
|
|
|
|
|
# --replace "''$"{CMAKE_INSTALL_PREFIX}/"''$"{RETDEC_INSTALL_SUPPORT_DIR} "''$"{RETDEC_INSTALL_SUPPORT_DIR}
|
|
|
|
# note! Nix does not set CMAKE_INSTALL_DATADIR to an absolute path, so this replacement would be incorrect
|
|
|
|
|
|
|
|
# similarly for yaramod. here, we fix the LIBDIR to lib64. for whatever reason, only "lib64" works.
|
|
|
|
substituteInPlace deps/yaramod/CMakeLists.txt \
|
|
|
|
--replace-fail "''$"{YARAMOD_INSTALL_DIR}/"''$"{CMAKE_INSTALL_LIBDIR} "''$"{YARAMOD_INSTALL_DIR}/lib64 \
|
|
|
|
--replace-fail CMAKE_ARGS 'CMAKE_ARGS -DCMAKE_INSTALL_LIBDIR=lib64'
|
|
|
|
|
|
|
|
# yara needs write permissions in the generated source directory.
|
|
|
|
echo ${lib.escapeShellArg ''
|
|
|
|
ExternalProject_Add_Step(
|
|
|
|
yara chmod WORKING_DIRECTORY ''${YARA_DIR}
|
|
|
|
DEPENDEES download COMMAND chmod -R u+w .
|
|
|
|
)
|
|
|
|
''} >> deps/yara/CMakeLists.txt
|
|
|
|
|
|
|
|
# patch gtest to use the system package
|
|
|
|
gtest=deps/googletest/CMakeLists.txt
|
|
|
|
old="$(cat $gtest)"
|
|
|
|
(echo 'find_package(GTest REQUIRED)'; echo "$old") > $gtest
|
|
|
|
sed -i 's/ExternalProject_[^(]\+[(]/ set(IGNORED /g' $gtest
|
|
|
|
|
|
|
|
substituteInPlace $gtest \
|
|
|
|
--replace-fail '$'{GTEST_LIB} "GTest::gtest"\
|
|
|
|
--replace-fail '$'{GMOCK_LIB} "GTest::gmock"\
|
|
|
|
--replace-fail '$'{GTEST_MAIN_LIB} "GTest::gtest_main"\
|
|
|
|
--replace-fail '$'{GMOCK_MAIN_LIB} "GTest::gmock_main"
|
|
|
|
|
|
|
|
# without git history, there is no chance these tests will pass.
|
|
|
|
substituteInPlace tests/utils/version_tests.cpp \
|
|
|
|
--replace-quiet VersionTests DISABLED_VersionTests
|
|
|
|
|
|
|
|
substituteInPlace scripts/retdec-utils.py \
|
|
|
|
--replace-warn /usr/bin/time ${time} \
|
|
|
|
--replace-warn /usr/local/bin/gtime ${time}
|
|
|
|
substituteInPlace scripts/retdec-unpacker.py \
|
|
|
|
--replace-warn "'upx'" "'${upx}'"
|
|
|
|
'';
|
2020-04-24 23:36:52 +00:00
|
|
|
|
2024-02-07 01:22:34 +00:00
|
|
|
doInstallCheck = enableTests;
|
2020-04-24 23:36:52 +00:00
|
|
|
installCheckPhase = ''
|
|
|
|
${python3.interpreter} "$out/bin/retdec-tests-runner.py"
|
|
|
|
|
|
|
|
rm -rf $out/bin/__pycache__
|
|
|
|
'';
|
|
|
|
|
|
|
|
meta = with lib; {
|
2024-06-20 14:57:18 +00:00
|
|
|
description = "Retargetable machine-code decompiler based on LLVM";
|
2020-04-24 23:36:52 +00:00
|
|
|
homepage = "https://retdec.com";
|
|
|
|
license = licenses.mit;
|
2024-02-07 01:22:34 +00:00
|
|
|
maintainers = with maintainers; [ dtzWill katrinafyi ];
|
|
|
|
platforms = [ "x86_64-linux" ];
|
2020-04-24 23:36:52 +00:00
|
|
|
};
|
2024-02-07 01:22:34 +00:00
|
|
|
})
|