about summary refs log tree commit diff
path: root/nixpkgs/pkgs/development/tools/analysis/radare2
diff options
context:
space:
mode:
Diffstat (limited to 'nixpkgs/pkgs/development/tools/analysis/radare2')
-rw-r--r--nixpkgs/pkgs/development/tools/analysis/radare2/cutter.nix54
-rw-r--r--nixpkgs/pkgs/development/tools/analysis/radare2/default.nix133
-rwxr-xr-xnixpkgs/pkgs/development/tools/analysis/radare2/update.py141
3 files changed, 328 insertions, 0 deletions
diff --git a/nixpkgs/pkgs/development/tools/analysis/radare2/cutter.nix b/nixpkgs/pkgs/development/tools/analysis/radare2/cutter.nix
new file mode 100644
index 000000000000..25c6d6d58792
--- /dev/null
+++ b/nixpkgs/pkgs/development/tools/analysis/radare2/cutter.nix
@@ -0,0 +1,54 @@
+{ stdenv, fetchFromGitHub
+# nativeBuildInputs
+, qmake, pkgconfig
+# Qt
+, qtbase, qtsvg, qtwebengine
+# buildInputs
+, r2-for-cutter
+, python3 }:
+
+let
+  version = "1.7.2";
+in
+stdenv.mkDerivation rec {
+  name = "radare2-cutter-${version}";
+
+  src = fetchFromGitHub {
+    owner = "radareorg";
+    repo = "cutter";
+    rev = "v${version}";
+    sha256 = "09cqfz66r3830jkz1rwyfqw1xl1jfj6xg4pcccd2ml456kddh9dn";
+  };
+
+  postUnpack = "export sourceRoot=$sourceRoot/src";
+
+  # Remove this "very helpful" helper file intended for discovering r2,
+  # as it's a doozy of harddcoded paths and unexpected behavior.
+  # Happily Nix has everything all set so we don't need it,
+  # other than as basis for the qmakeFlags set below.
+  postPatch = ''
+    substituteInPlace Cutter.pro \
+      --replace "include(lib_radare2.pri)" ""
+  '';
+
+  nativeBuildInputs = [ qmake pkgconfig ];
+  buildInputs = [ qtbase qtsvg qtwebengine r2-for-cutter python3 ];
+
+  qmakeFlags = [
+    "CONFIG+=link_pkgconfig"
+    "PKGCONFIG+=r_core"
+    # Leaving this enabled doesn't break build but generates errors
+    # at runtime (to console) about being unable to load needed bits.
+    # Disable until can be looked at.
+    "CUTTER_ENABLE_JUPYTER=false"
+  ];
+
+  enableParallelBuilding = true;
+
+  meta = with stdenv.lib; {
+    description = "A Qt and C++ GUI for radare2 reverse engineering framework";
+    homepage = src.meta.homepage;
+    license = licenses.gpl3;
+    maintainers = with maintainers; [ mic92 dtzWill ];
+  };
+}
diff --git a/nixpkgs/pkgs/development/tools/analysis/radare2/default.nix b/nixpkgs/pkgs/development/tools/analysis/radare2/default.nix
new file mode 100644
index 000000000000..f88dc3f6d333
--- /dev/null
+++ b/nixpkgs/pkgs/development/tools/analysis/radare2/default.nix
@@ -0,0 +1,133 @@
+{stdenv, fetchFromGitHub
+, buildPackages
+, callPackage
+, pkgconfig
+, libusb, readline, libewf, perl, zlib, openssl
+, libuv, file, libzip, xxHash
+, gtk2 ? null, vte ? null, gtkdialog ? null
+, python3 ? null
+, ruby ? null
+, lua ? null
+, useX11 ? false
+, rubyBindings ? false
+, pythonBindings ? false
+, luaBindings ? false
+}:
+
+assert useX11 -> (gtk2 != null && vte != null && gtkdialog != null);
+assert rubyBindings -> ruby != null;
+assert pythonBindings -> python3 != null;
+
+
+let
+  inherit (stdenv.lib) optional;
+
+  generic = {
+    version_commit,
+    gittap,
+    gittip,
+    rev,
+    version,
+    sha256,
+    cs_ver,
+    cs_sha256
+  }:
+    stdenv.mkDerivation rec {
+      name = "radare2-${version}";
+
+      src = fetchFromGitHub {
+        owner = "radare";
+        repo = "radare2";
+        inherit rev sha256;
+      };
+
+      postPatch = let
+        capstone = fetchFromGitHub {
+          owner = "aquynh";
+          repo = "capstone";
+          # version from $sourceRoot/shlr/Makefile
+          rev = cs_ver;
+          sha256 = cs_sha256;
+        };
+      in ''
+        mkdir -p build/shlr
+        cp -r ${capstone} capstone-${cs_ver}
+        chmod -R +w capstone-${cs_ver}
+        # radare 3.3 compat for radare2-cutter
+        (cd shlr && ln -s ../capstone-${cs_ver} capstone)
+        tar -czvf shlr/capstone-${cs_ver}.tar.gz capstone-${cs_ver}
+        # necessary because they broke the offline-build:
+        # https://github.com/radare/radare2/commit/6290e4ff4cc167e1f2c28ab924e9b99783fb1b38#diff-a44d840c10f1f1feaf401917ae4ccd54R258
+        # https://github.com/radare/radare2/issues/13087#issuecomment-465159716
+        curl() { true; }
+        export -f curl
+      '';
+
+      postInstall = ''
+        install -D -m755 $src/binr/r2pm/r2pm $out/bin/r2pm
+      '';
+
+      WITHOUT_PULL="1";
+      makeFlags = [
+        "GITTAP=${gittap}"
+        "GITTIP=${gittip}"
+        "RANLIB=${stdenv.cc.bintools.bintools}/bin/${stdenv.cc.bintools.targetPrefix}ranlib"
+      ];
+      configureFlags = [
+        "--with-sysmagic"
+        "--with-syszip"
+        "--with-sysxxhash"
+        "--with-openssl"
+      ];
+
+      enableParallelBuilding = true;
+      depsBuildBuild = [ buildPackages.stdenv.cc ];
+
+      nativeBuildInputs = [ pkgconfig ];
+      buildInputs = [ file readline libusb libewf perl zlib openssl libuv ]
+        ++ optional useX11 [ gtkdialog vte gtk2 ]
+        ++ optional rubyBindings [ ruby ]
+        ++ optional pythonBindings [ python3 ]
+        ++ optional luaBindings [ lua ];
+
+      propagatedBuildInputs = [
+        # radare2 exposes r_lib which depends on these libraries
+        file # for its list of magic numbers (`libmagic`)
+        libzip
+        xxHash
+      ];
+
+      meta = {
+        description = "unix-like reverse engineering framework and commandline tools";
+        homepage = http://radare.org/;
+        license = stdenv.lib.licenses.gpl2Plus;
+        maintainers = with stdenv.lib.maintainers; [ raskin makefu mic92 ];
+        platforms = with stdenv.lib.platforms; linux;
+        inherit version;
+      };
+  };
+in {
+  #<generated>
+  # DO NOT EDIT! Automatically generated by ./update.py
+  radare2 = generic {
+    version_commit = "20942";
+    gittap = "3.3.0";
+    gittip = "5a9127d2599c8ff61d8544be7d4c9384402e94a3";
+    rev = "3.3.0";
+    version = "3.3.0";
+    sha256 = "11ap3icr8w0y49lq5dxch2h589qdmwf3qv9lsdyfsz4l0mjm49ri";
+    cs_ver = "4.0.1";
+    cs_sha256 = "0ijwxxk71nr9z91yxw20zfj4bbsbrgvixps5c7cpj163xlzlwba6";
+  };
+  r2-for-cutter = generic {
+    version_commit = "20942";
+    gittap = "2.9.0-310-gcb62c376b";
+    gittip = "cb62c376bef6c7427019a7c28910c33c364436dd";
+    rev = "cb62c376bef6c7427019a7c28910c33c364436dd";
+    version = "2018-10-07";
+    sha256 = "0z4nr1d2ca8ibq34441j15pj22wh46brcbr00j5hcqvn8y2lh96l";
+    cs_ver = "e2c1cd46c06744beaceff42dd882de3a90f0a37c";
+    cs_sha256 = "1czzqj8zdjgh7h2ixi26ij3mm4bgm4xw2slin6fv73nic8yaw722";
+  };
+  #</generated>
+}
diff --git a/nixpkgs/pkgs/development/tools/analysis/radare2/update.py b/nixpkgs/pkgs/development/tools/analysis/radare2/update.py
new file mode 100755
index 000000000000..794581bca7ad
--- /dev/null
+++ b/nixpkgs/pkgs/development/tools/analysis/radare2/update.py
@@ -0,0 +1,141 @@
+#!/usr/bin/env nix-shell
+#!nix-shell -p nix -p python3 -p git -i python
+# USAGE - just run the script: ./update.py
+# When editing this file, make also sure it passes the mypy typecheck
+# and is formatted with black.
+import fileinput
+import json
+import re
+import subprocess
+import tempfile
+import urllib.request
+from datetime import datetime
+from pathlib import Path
+from typing import Dict
+
+SCRIPT_DIR = Path(__file__).parent.resolve()
+
+
+def sh(*args: str) -> str:
+    out = subprocess.check_output(list(args))
+    return out.strip().decode("utf-8")
+
+
+def prefetch_github(owner: str, repo: str, ref: str) -> str:
+    return sh(
+        "nix-prefetch-url",
+        "--unpack",
+        f"https://github.com/{owner}/{repo}/archive/{ref}.tar.gz",
+    )
+
+
+def get_radare2_rev() -> str:
+    url = "https://api.github.com/repos/radare/radare2/releases/latest"
+    with urllib.request.urlopen(url) as response:
+        release = json.load(response)  # type: ignore
+    return release["tag_name"]
+
+
+def get_cutter_version() -> str:
+    version_expr = """
+(with import <nixpkgs> {}; (builtins.parseDrvName (qt5.callPackage <radare2/cutter.nix> {}).name).version)
+"""
+    return sh("nix", "eval", "--raw", version_expr.strip(), "-I", "radare2={0}".format(SCRIPT_DIR))
+
+
+def get_r2_cutter_rev() -> str:
+    version = get_cutter_version()
+    url = f"https://api.github.com/repos/radareorg/cutter/contents?ref=v{version}"
+    with urllib.request.urlopen(url) as response:
+        data = json.load(response)  # type: ignore
+    for entry in data:
+        if entry["name"] == "radare2":
+            return entry["sha"]
+    raise Exception("no radare2 submodule found in github.com/radareorg/cutter")
+
+
+def git(dirname: str, *args: str) -> str:
+    return sh("git", "-C", dirname, *args)
+
+
+def get_repo_info(dirname: str, rev: str) -> Dict[str, str]:
+    sha256 = prefetch_github("radare", "radare2", rev)
+
+    cs_ver = None
+    with open(Path(dirname).joinpath("shlr", "Makefile")) as makefile:
+        for l in makefile:
+            match = re.match("CS_VER=(\S+)", l)
+            if match:
+                cs_ver = match.group(1)
+    assert cs_ver is not None
+
+    cs_sha256 = prefetch_github("aquynh", "capstone", cs_ver)
+
+    return dict(
+        rev=rev,
+        sha256=sha256,
+        version_commit=git(dirname, "rev-list", "--all", "--count"),
+        gittap=git(dirname, "describe", "--tags", "--match", "[0-9]*"),
+        gittip=git(dirname, "rev-parse", "HEAD"),
+        cs_ver=cs_ver,
+        cs_sha256=cs_sha256,
+    )
+
+
+def write_package_expr(version: str, info: Dict[str, str]) -> str:
+    return f"""generic {{
+    version_commit = "{info["version_commit"]}";
+    gittap = "{info["gittap"]}";
+    gittip = "{info["gittip"]}";
+    rev = "{info["rev"]}";
+    version = "{version}";
+    sha256 = "{info["sha256"]}";
+    cs_ver = "{info["cs_ver"]}";
+    cs_sha256 = "{info["cs_sha256"]}";
+  }}"""
+
+
+def main() -> None:
+    radare2_rev = get_radare2_rev()
+    r2_cutter_rev = get_r2_cutter_rev()
+
+    with tempfile.TemporaryDirectory() as dirname:
+        git(
+            dirname,
+            "clone",
+            "--branch",
+            radare2_rev,
+            "https://github.com/radare/radare2",
+            ".",
+        )
+        nix_file = str(SCRIPT_DIR.joinpath("default.nix"))
+
+        radare2_info = get_repo_info(dirname, radare2_rev)
+
+        git(dirname, "checkout", r2_cutter_rev)
+
+        timestamp = git(dirname, "log", "-n1", "--format=%at")
+        r2_cutter_version = datetime.fromtimestamp(int(timestamp)).strftime("%Y-%m-%d")
+
+        r2_cutter_info = get_repo_info(dirname, r2_cutter_rev)
+
+        in_block = False
+        with fileinput.FileInput(nix_file, inplace=True) as f:
+            for l in f:
+                if "#<generated>" in l:
+                    in_block = True
+                    print(
+                        f"""  #<generated>
+  # DO NOT EDIT! Automatically generated by ./update.py
+  radare2 = {write_package_expr(radare2_rev, radare2_info)};
+  r2-for-cutter = {write_package_expr(r2_cutter_version, r2_cutter_info)};
+  #</generated>"""
+                    )
+                elif "#</generated>" in l:
+                    in_block = False
+                elif not in_block:
+                    print(l, end="")
+
+
+if __name__ == "__main__":
+    main()