diff --git a/pkgs/development/tools/analysis/rizin/cutter.nix b/pkgs/development/tools/analysis/rizin/cutter.nix index 18ca4e13d843..bb8ecb6e196a 100644 --- a/pkgs/development/tools/analysis/rizin/cutter.nix +++ b/pkgs/development/tools/analysis/rizin/cutter.nix @@ -1,4 +1,6 @@ { fetchFromGitHub, lib, mkDerivation +# for passthru.plugins +, pkgs # nativeBuildInputs , qmake, pkg-config, cmake # Qt @@ -10,7 +12,7 @@ , wrapQtAppsHook }: -mkDerivation rec { +let cutter = mkDerivation rec { pname = "cutter"; version = "2.3.0"; @@ -37,10 +39,24 @@ mkDerivation rec { qtWrapperArgs+=(--prefix PYTHONPATH : "$PYTHONPATH") ''; + passthru = rec { + plugins = rizin.plugins // { + rz-ghidra = rizin.plugins.rz-ghidra.override { + inherit cutter qtbase qtsvg; + enableCutterPlugin = true; + }; + }; + withPlugins = filter: pkgs.callPackage ./wrapper.nix { + unwrapped = cutter; + inherit rizin; + plugins = filter plugins; + }; + }; + meta = with lib; { description = "Free and Open Source Reverse Engineering Platform powered by rizin"; homepage = src.meta.homepage; license = licenses.gpl3; maintainers = with maintainers; [ mic92 dtzWill ]; }; -} +}; in cutter diff --git a/pkgs/development/tools/analysis/rizin/default.nix b/pkgs/development/tools/analysis/rizin/default.nix index df44b8fbbaab..46fe132a463e 100644 --- a/pkgs/development/tools/analysis/rizin/default.nix +++ b/pkgs/development/tools/analysis/rizin/default.nix @@ -1,4 +1,5 @@ { lib +, pkgs # for passthru.plugins , stdenv , fetchurl , pkg-config @@ -22,7 +23,7 @@ , tree-sitter }: -stdenv.mkDerivation rec { +let rizin = stdenv.mkDerivation rec { pname = "rizin"; version = "0.6.0"; @@ -42,8 +43,17 @@ stdenv.mkDerivation rec { "-Duse_sys_openssl=enabled" "-Duse_sys_libmspack=enabled" "-Duse_sys_tree_sitter=enabled" + # this is needed for wrapping (adding plugins) to work + "-Dportable=true" ]; + # Normally, Rizin only looks for files in the install prefix. With + # portable=true, it instead looks for files in relation to the parent + # of the directory of the binary file specified in /proc/self/exe, + # caching it. This patch replaces the entire logic to only look at + # the env var NIX_RZ_PREFIX + patches = [ ./librz-wrapper-support.patch ]; + nativeBuildInputs = [ pkg-config meson @@ -94,6 +104,25 @@ stdenv.mkDerivation rec { --replace "import('python').find_installation()" "find_program('python3')" ''; + passthru = rec { + plugins = { + jsdec = pkgs.callPackage ./jsdec.nix { + inherit rizin openssl; + }; + rz-ghidra = pkgs.libsForQt5.callPackage ./rz-ghidra.nix { + inherit rizin openssl; + enableCutterPlugin = false; + }; + # sigdb isn't a real plugin, but it's separated from the main rizin + # derivation so that only those who need it will download it + sigdb = pkgs.callPackage ./sigdb.nix { }; + }; + withPlugins = filter: pkgs.callPackage ./wrapper.nix { + unwrapped = rizin; + plugins = filter plugins; + }; + }; + meta = { description = "UNIX-like reverse engineering framework and command-line toolset."; homepage = "https://rizin.re/"; @@ -101,4 +130,4 @@ stdenv.mkDerivation rec { maintainers = with lib.maintainers; [ raskin makefu mic92 ]; platforms = with lib.platforms; unix; }; -} +}; in rizin diff --git a/pkgs/development/tools/analysis/rizin/jsdec.nix b/pkgs/development/tools/analysis/rizin/jsdec.nix new file mode 100644 index 000000000000..df291d169eb5 --- /dev/null +++ b/pkgs/development/tools/analysis/rizin/jsdec.nix @@ -0,0 +1,35 @@ +{ lib +, stdenv +, fetchFromGitHub +, meson +, pkg-config +, ninja +, rizin +, openssl +}: + +stdenv.mkDerivation rec { + pname = "jsdec"; + version = "0.6.0"; + + src = fetchFromGitHub { + owner = "rizinorg"; + repo = "jsdec"; + rev = "v${version}"; + hash = "sha256-iVaxxPBIJRhZrmejAOL/Fb4k66mGsZOBs7UikgMj5WA="; + }; + + nativeBuildInputs = [ meson ninja pkg-config ]; + preConfigure = '' + cd p + ''; + mesonFlags = [ "-Djsc_folder=.." ]; + buildInputs = [ openssl rizin ]; + + meta = with lib; { + description = "Simple decompiler for Rizin"; + homepage = src.meta.homepage; + license = with licenses; [ asl20 bsd3 mit ]; + maintainers = with maintainers; [ chayleaf ]; + }; +} diff --git a/pkgs/development/tools/analysis/rizin/librz-wrapper-support.patch b/pkgs/development/tools/analysis/rizin/librz-wrapper-support.patch new file mode 100644 index 000000000000..23df0d22c69a --- /dev/null +++ b/pkgs/development/tools/analysis/rizin/librz-wrapper-support.patch @@ -0,0 +1,13 @@ +diff --git a/librz/util/path.c b/librz/util/path.c +index 8ea3d67..f4a8918 100644 +--- a/librz/util/path.c ++++ b/librz/util/path.c +@@ -35,6 +35,8 @@ static void fini_portable_prefix(void) { + } + + static char *set_portable_prefix(void) { ++ return rz_sys_getenv("NIX_RZ_PREFIX"); ++ + char *pid_to_path = rz_sys_pid_to_path(rz_sys_getpid()); + if (!pid_to_path) { + return NULL; diff --git a/pkgs/development/tools/analysis/rizin/rz-ghidra.nix b/pkgs/development/tools/analysis/rizin/rz-ghidra.nix new file mode 100644 index 000000000000..d349a33af814 --- /dev/null +++ b/pkgs/development/tools/analysis/rizin/rz-ghidra.nix @@ -0,0 +1,62 @@ +{ lib +, stdenv +, fetchFromGitHub +, fetchpatch +, cmake +# buildInputs +, rizin +, openssl +, pugixml +# optional buildInputs +, enableCutterPlugin ? true +, cutter +, qtbase +, qtsvg +}: + +stdenv.mkDerivation rec { + pname = "rz-ghidra"; + version = "0.6.0"; + + src = fetchFromGitHub { + owner = "rizinorg"; + repo = "rz-ghidra"; + rev = "v${version}"; + hash = "sha256-tQAurouRr6fP1tbIkfd0a9UfeYcwiU1BpjOTcooXkT0="; + fetchSubmodules = true; + }; + + patches = [ + (fetchpatch { + url = "https://github.com/rizinorg/rz-ghidra/pull/327/commits/eba20e2c743ed3dfc5d1be090a5018f7267baa49.patch"; + hash = "sha256-aoXFClXZBcOnHl+6lLYrnui7sRb3cRJQhQfNDLxHtcs="; + }) + ]; + + nativeBuildInputs = [ cmake ]; + buildInputs = [ + openssl + pugixml + rizin + ] ++ lib.optionals enableCutterPlugin [ + cutter + qtbase + qtsvg + ]; + + dontWrapQtApps = true; + + cmakeFlags = [ + "-DUSE_SYSTEM_PUGIXML=ON" + ] ++ lib.optionals enableCutterPlugin [ + "-DBUILD_CUTTER_PLUGIN=ON" + "-DCUTTER_INSTALL_PLUGDIR=share/rizin/cutter/plugins/native" + ]; + + meta = with lib; { + description = "Deep ghidra decompiler and sleigh disassembler integration for rizin"; + homepage = src.meta.homepage; + license = licenses.lgpl3; + maintainers = with maintainers; [ chayleaf ]; + }; +} diff --git a/pkgs/development/tools/analysis/rizin/sigdb.nix b/pkgs/development/tools/analysis/rizin/sigdb.nix new file mode 100644 index 000000000000..2c4bdaebbaba --- /dev/null +++ b/pkgs/development/tools/analysis/rizin/sigdb.nix @@ -0,0 +1,36 @@ +{ lib +, fetchFromGitHub +, stdenvNoCC +}: + +stdenvNoCC.mkDerivation rec { + pname = "rizin-sigdb"; + version = "unstable-2023-02-13"; + + src = fetchFromGitHub { + owner = "rizinorg"; + # sigdb-source: source files (.pat and etc), around 2.5gb total + # sigdb: built and deflated .sig files, around 50mb total + repo = "sigdb"; + rev = "829baf835e3515923266898fd597f7f75046ebd2"; + hash = "sha256-zvGna2CEsDctc9P7hWTaz7kdtxAtPsXHNWOrRQ9ocdc="; + }; + + buildPhase = '' + mkdir installdir + cp -r elf pe installdir + .scripts/verify-sigs-install.sh + ''; + + installPhase = '' + mkdir -p $out/share/rizin + mv installdir $out/share/rizin/sigdb + ''; + + meta = with lib; { + description = "Rizin FLIRT Signature Database"; + homepage = src.meta.homepage; + license = licenses.lgpl3; + maintainers = with lib.maintainers; [ chayleaf ]; + }; +} diff --git a/pkgs/development/tools/analysis/rizin/wrapper.nix b/pkgs/development/tools/analysis/rizin/wrapper.nix new file mode 100644 index 000000000000..5ddee52f2324 --- /dev/null +++ b/pkgs/development/tools/analysis/rizin/wrapper.nix @@ -0,0 +1,46 @@ +{ lib +, makeWrapper +, symlinkJoin +, unwrapped +, plugins +# NIX_RZ_PREFIX only changes where *Rizin* locates files (plugins, +# themes, etc). But we must change it even for wrapping Cutter, because +# Cutter plugins often have associated Rizin plugins. This means that +# NIX_RZ_PREFIX must always contain Rizin files, even if we only wrap +# Cutter - so for Cutter, include Rizin to symlinkJoin paths. +, rizin ? null +}: + +symlinkJoin { + name = "${unwrapped.pname}-with-plugins-${unwrapped.version}"; + + paths = [ unwrapped ] ++ lib.optional (rizin != null) rizin ++ plugins; + + nativeBuildInputs = [ makeWrapper ]; + + passthru = { + inherit unwrapped; + }; + + postBuild = '' + rm $out/bin/* + wrapperArgs=(--set NIX_RZ_PREFIX $out) + if [ -d $out/share/rizin/cutter ]; then + wrapperArgs+=(--prefix XDG_DATA_DIRS : $out/share) + fi + for binary in $(ls ${unwrapped}/bin); do + makeWrapper ${unwrapped}/bin/$binary $out/bin/$binary "''${wrapperArgs[@]}" + done + ${lib.optionalString (rizin != null) '' + for binary in $(ls ${rizin}/bin); do + makeWrapper ${rizin}/bin/$binary $out/bin/$binary "''${wrapperArgs[@]}" + done + ''} + ''; + + meta = unwrapped.meta // { + # prefer wrapped over unwrapped, prefer cutter wrapper over rizin wrapper + # (because cutter versions of plugins also contain rizin plugins) + priority = (unwrapped.meta.priority or 0) - (if rizin != null then 2 else 1); + }; +} diff --git a/pkgs/top-level/all-packages.nix b/pkgs/top-level/all-packages.nix index 9e21817286a0..a5d7e8bb161f 100644 --- a/pkgs/top-level/all-packages.nix +++ b/pkgs/top-level/all-packages.nix @@ -19770,8 +19770,12 @@ with pkgs; rizin = pkgs.callPackage ../development/tools/analysis/rizin { }; + rizinPlugins = recurseIntoAttrs rizin.plugins; + cutter = libsForQt5.callPackage ../development/tools/analysis/rizin/cutter.nix { }; + cutterPlugins = recurseIntoAttrs rizin.plugins; + ragel = ragelStable; randoop = callPackage ../development/tools/analysis/randoop { };