summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--gnu/local.mk2
-rw-r--r--gnu/packages/engineering.scm52
-rw-r--r--gnu/packages/patches/e9patch-check.patch167
-rw-r--r--gnu/packages/patches/e9patch-devendor.patch52
4 files changed, 273 insertions, 0 deletions
diff --git a/gnu/local.mk b/gnu/local.mk
index 89a795bfbd..d128bb61a4 100644
--- a/gnu/local.mk
+++ b/gnu/local.mk
@@ -1168,6 +1168,8 @@ dist_patch_DATA =						\
   %D%/packages/patches/dvd+rw-tools-add-include.patch 		\
   %D%/packages/patches/dwarves-threading-reproducibility.patch	\
   %D%/packages/patches/dynaconf-unvendor-deps.patch		\
+  %D%/packages/patches/e9patch-check.patch			\
+  %D%/packages/patches/e9patch-devendor.patch			\
   %D%/packages/patches/efivar-211.patch			\
   %D%/packages/patches/eigen-fix-strict-aliasing-bug.patch	\
   %D%/packages/patches/einstein-build.patch			\
diff --git a/gnu/packages/engineering.scm b/gnu/packages/engineering.scm
index 6f449f0c39..c124ca537f 100644
--- a/gnu/packages/engineering.scm
+++ b/gnu/packages/engineering.scm
@@ -97,6 +97,7 @@
   #:use-module (gnu packages digest)
   #:use-module (gnu packages docbook)
   #:use-module (gnu packages documentation)
+  #:use-module (gnu packages elf)
   #:use-module (gnu packages file)
   #:use-module (gnu packages flex)
   #:use-module (gnu packages fontutils)
@@ -167,6 +168,7 @@
   #:use-module (gnu packages toolkits)
   #:use-module (gnu packages tree-sitter)
   #:use-module (gnu packages version-control)
+  #:use-module (gnu packages vim)
   #:use-module (gnu packages web)
   #:use-module (gnu packages wxwidgets)
   #:use-module (gnu packages xdisorg)
@@ -1995,6 +1997,56 @@ and a fallback for environments without libc for Zydis.")
 @end itemize")
     (license license:expat)))
 
+(define-public e9patch
+  (let ((commit "b4e7175abb8bd49ebbb6d09c7057aa43ddacac10")
+        (revision "0"))
+    (package
+      (name "e9patch")
+      (version (git-version "1.0.0-dev" revision commit))
+      (source (origin
+                (method git-fetch)
+                (uri (git-reference
+                     (url "https://github.com/GJDuck/e9patch")
+                     (commit commit)))
+                (sha256
+                 (base32
+                  "0a9s7h43ryyl4bvn0sid0dq78v24bnbcf271smj1a8wvffsih0jy"))
+                (file-name (git-file-name name version))
+                (patches (search-patches "e9patch-devendor.patch"
+                                         "e9patch-check.patch"))))
+      (build-system gnu-build-system)
+      (arguments (list #:modules `((ice-9 string-fun) ; string-replace-substring
+                                   ,@%default-gnu-modules)
+                       #:phases
+                       #~(modify-phases %standard-phases
+                           (add-after 'unpack 'fix-prefix
+                             (lambda _
+                               (substitute* "Makefile"
+                                 ;; https://github.com/GJDuck/e9patch/pull/87
+                                 (("\\\\/usr")
+                                  (string-replace-substring #$output "/" "\\/"))
+                                 (("/usr") #$output))))
+                           (delete 'configure))))
+      (native-inputs (list markdown xxd))
+      (inputs (list elfutils zycore zydis zlib))
+      (home-page "https://github.com/GJDuck/e9patch")
+      (synopsis "Static binary rewriting tool")
+      (description
+       "E9Patch is a static binary rewriting tool for x86-64 ELF binaries.
+E9Patch is:
+@itemize
+@item Scalable: E9Patch can reliably rewrite large/complex binaries
+      including web browsers (>100MB in size).
+@item Compatible: The rewritten binary is a drop-in replacement of the original,
+      with no additional dependencies.
+@item Fast: E9Patch can rewrite most binaries in a few seconds.
+@item Low Overheads: Both performance and memory.
+@item Programmable: E9Patch is designed so that it can be easily integrated
+      into other projects.
+@end itemize")
+      (license (list license:expat ;src/e9patch/e9loader_*.cpp
+                     license:gpl3+))))) ;rest
+
 (define-public asco
   (package
     (name "asco")
diff --git a/gnu/packages/patches/e9patch-check.patch b/gnu/packages/patches/e9patch-check.patch
new file mode 100644
index 0000000000..2c36df9a7b
--- /dev/null
+++ b/gnu/packages/patches/e9patch-check.patch
@@ -0,0 +1,167 @@
+diff --git a/Makefile b/Makefile
+index 1218c65d1818..b7a0e3edbc75 100644
+--- a/Makefile
++++ b/Makefile
+@@ -181,3 +181,12 @@ tool.sanitize: $(E9TOOL_OBJS) $(E9TOOL_LIBS)
+ 	$(CXX) $(CXXFLAGS) $(E9TOOL_OBJS) $(E9TOOL_LIBS) -o e9tool \
+         $(E9TOOL_LDFLAGS)
+ 
++regtest: e9tool
++	$(MAKE) -C test/regtest
++
++stresstest: e9tool
++	$(MAKE) -C test/stresstest
++
++check: regtest # stresstest
++
++.PHONY: regtest stresstest check
+diff --git a/test/regtest/Makefile b/test/regtest/Makefile
+index 992b1bc40984..142d29e54276 100644
+--- a/test/regtest/Makefile
++++ b/test/regtest/Makefile
+@@ -3,32 +3,63 @@ FCF_NONE := $(shell \
+         then true; \
+         else echo -fcf-protection=none; fi)
+ 
+-all:
++check: regtest test test.pie test.libc test_c test_c.debug bugs inst patch dl init fini example.so
++	./$<
++
++test:
+ 	gcc -x assembler-with-cpp -o test test.s -no-pie -nostdlib \
+         -Wl,--section-start=.text=0xa000000 -Wl,--section-start=.bss=0xc000000 \
+         -Wl,-z -Wl,max-page-size=4096 -DPIE=0
++
++test.pie:
+ 	gcc -x assembler-with-cpp -o test.pie test.s -pie -nostdlib \
+         -Wl,--section-start=.text=0xa000000 -Wl,--section-start=.bss=0xc000000 \
+         -Wl,-z -Wl,max-page-size=4096 -DPIE=1 \
+ 		-Wl,--export-dynamic
++
++bugs:
+ 	gcc -x assembler-with-cpp -o bugs bugs.s -no-pie -nostdlib \
+         -Wl,--section-start=.text=0xa000000 -Wl,--section-start=.bss=0xc000000 \
+         -Wl,-z -Wl,max-page-size=4096 -DPIE=0
++
++test.libc:
+ 	gcc -x assembler-with-cpp -o test.libc test_libc.s -pie -Wl,--export-dynamic
++
++libtest.so:
+ 	gcc -x assembler-with-cpp -shared -o libtest.so libtest.s 
++
++test_c:
+ 	gcc -O2 -fPIC $(FCF_NONE) -pie -o test_c test_c.c \
+ 		-Wl,--export-dynamic -U_FORTIFY_SOURCE
+ 	strip test_c
++
++test_c.debug:
+ 	gcc -O0 -g -fPIC -pie -o test_c.debug test_c.c
++
++inst:
+ 	../../e9compile.sh inst.c -I ../../examples/ 
++
++patch:
+ 	../../e9compile.sh patch.cpp -std=c++11 -I ../../examples/ 
++
++dl:
+ 	NO_SIMD_CHECK=1 ../../e9compile.sh dl.c -I ../../examples/
++
++init:
+ 	../../e9compile.sh init.c -I ../../examples/ 
++
++fini:
+ 	../../e9compile.sh fini.c -I ../../examples/
++
++example.so:
+ 	g++ -std=c++11 -fPIC -shared -o example.so -O2 \
+         ../../examples/plugins/example.cpp -I ../../src/e9tool/
++
++regtest:
+ 	g++ -std=c++11 -pie -fPIC -o regtest regtest.cpp -O2
+ 
+ clean:
+ 	rm -f *.log *.out *.exe test test.pie test.libc libtest.so inst inst.o \
+         patch patch.o init init.o regtest
++
++.PHONY: check clean
+diff --git a/test/regtest/regtest.cpp b/test/regtest/regtest.cpp
+index e86e0af03228..9d78f9c6d670 100644
+--- a/test/regtest/regtest.cpp
++++ b/test/regtest/regtest.cpp
+@@ -164,11 +164,11 @@ static bool runTest(const struct dirent *test, const std::string &options)
+         {
+             fclose(OUT); fclose(EXP);
+             command.clear();
+-            command += "diff ";
++            command += "diff -u ";
+             command += out;
+             command += ' ';
+             command += exp;
+-            command += " >";
++            command += " | tee ";
+             command += diff;
+             printf("\t%s\n", command.c_str());
+             (void)system(command.c_str());
+diff --git a/test/stresstest/Makefile b/test/stresstest/Makefile
+index 64bcb5432a0e..2c8b98e7577c 100644
+--- a/test/stresstest/Makefile
++++ b/test/stresstest/Makefile
+@@ -1,2 +1,15 @@
++ROOT_DIR = ../..
++
++check: stresstest.sh nop example.so
++	./$<
++
++nop: $(ROOT_DIR)/e9compile.sh $(ROOT_DIR)/examples/nop.c
++	$^
++
++example.so: $(ROOT_DIR)/examples/plugins/example.cpp
++	g++ -std=c++11 -fPIC -shared -I$(ROOT_DIR)/src/e9tool -o $@ -O2 $<
++
+ clean:
+ 	rm -rf example.so nop nop.o tmp
++
++.PHONY: check clean
+diff --git a/test/stresstest/stresstest.sh b/test/stresstest/stresstest.sh
+index 86ac9e0db1f4..be4048f52f27 100755
+--- a/test/stresstest/stresstest.sh
++++ b/test/stresstest/stresstest.sh
+@@ -1,4 +1,5 @@
+-#!/bin/bash
++#!/bin/sh
++set -e
+ 
+ if [ -t 1 ]
+ then
+@@ -15,20 +16,14 @@ else
+     OFF=
+ fi
+ 
+-set -e
+-mkdir -p tmp
+-../../e9compile.sh ../../examples/nop.c >/dev/null 2>&1 
+-
+-# Setup the example.so plugin
+-g++ -std=c++11 -fPIC -shared -o example.so -O2 \
+-    ../../examples/plugins/example.cpp -I ../../src/e9tool/ 
+-
+ runtest()
+ {
+     MATCH=$1
+     PATCH=$2
+     EXTRA=$3
+ 
++    mkdir tmp
++
+     # Step (1): duplicate the tools
+     if ! ../../e9tool ../../e9tool "--match=$MATCH" "--patch=$PATCH" $EXTRA \
+             -o tmp/e9tool.patched  -c 6 -s >/dev/null 2>&1
+@@ -72,6 +67,8 @@ runtest()
+     else
+         echo -e "${RED}FAILED${OFF}: e9patch ${YELLOW}-M $MATCH -P $PATCH${OFF}"
+     fi
++
++    rm -r tmp
+ }
+ 
+ runtest true empty
diff --git a/gnu/packages/patches/e9patch-devendor.patch b/gnu/packages/patches/e9patch-devendor.patch
new file mode 100644
index 0000000000..e9ee2921d9
--- /dev/null
+++ b/gnu/packages/patches/e9patch-devendor.patch
@@ -0,0 +1,52 @@
+diff --git a/Makefile b/Makefile
+index 1218c65d1818..0ebdf24ea259 100644
+--- a/Makefile
++++ b/Makefile
+@@ -37,10 +37,7 @@ E9TOOL_OBJS=\
+ E9TOOL_LIBS=\
+     contrib/zydis/libZydis.a \
+     contrib/libdw/libdw.a
+-E9TOOL_CXXFLAGS=\
+-    -I src/e9tool/ -Wno-unused-function \
+-    -I contrib/zydis/include/ \
+-    -I contrib/zydis/dependencies/zycore/include/
++E9TOOL_CXXFLAGS= -I src/e9tool/ -Wno-unused-function
+ E9TOOL_LDFLAGS=\
+     -Wl,--dynamic-list=src/e9tool/e9tool.syms \
+     -ldl -lz
+@@ -52,9 +49,9 @@ E9TOOL_LDFLAGS=\
+ all: e9tool e9patch
+ 
+ e9tool: CXXFLAGS += -O2 -DSYSTEM_LIBDW $(E9TOOL_CXXFLAGS)
+-e9tool: contrib/zydis/libZydis.a $(E9TOOL_OBJS)
+-	$(CXX) $(CXXFLAGS) $(E9TOOL_OBJS) contrib/zydis/libZydis.a -o e9tool \
+-	    $(E9TOOL_LDFLAGS) -ldw
++e9tool: $(E9TOOL_OBJS)
++	$(CXX) $(CXXFLAGS) $(E9TOOL_OBJS) -o e9tool \
++	    $(E9TOOL_LDFLAGS) -ldw -lZydis
+ 	strip e9tool
+ 
+ e9patch: CXXFLAGS += -O2 
+diff --git a/src/e9tool/e9x86_64.cpp b/src/e9tool/e9x86_64.cpp
+index 6a7f5cff3692..03eb3a41dd66 100644
+--- a/src/e9tool/e9x86_64.cpp
++++ b/src/e9tool/e9x86_64.cpp
+@@ -152,8 +152,7 @@ void e9tool::getInstrInfo(const ELF *elf, const Instr *I, InstrInfo *info,
+     ZydisDecodedOperand operands[ZYDIS_MAX_OPERAND_COUNT];
+ 
+     ZyanStatus result = ZydisDecoderDecodeFull(&decoder,
+-        elf->data + I->offset, I->size, D, operands, ZYDIS_MAX_OPERAND_COUNT,
+-        0);
++        elf->data + I->offset, I->size, D, operands);
+     if (!ZYAN_SUCCESS(result) || I->size != D->length ||
+             D->operand_count > sizeof(info->op) / sizeof(info->op[0]))
+         error("failed to decompress instruction at address 0x%lx; decode "
+@@ -336,7 +335,7 @@ void e9tool::getInstrInfo(const ELF *elf, const Instr *I, InstrInfo *info,
+         info->string.section    = elf->strs + shdr->sh_name;
+         result = ZydisFormatterFormatInstruction(&formatter, D, operands,
+             D->operand_count_visible, info->string.instr,
+-            sizeof(info->string.instr)-1, I->address);
++            sizeof(info->string.instr)-1, I->address, ZYAN_NULL);
+         if (!ZYAN_SUCCESS(result))
+             error("failed to decompress instruction at address 0x%lx; "
+                 "formatting failed", I->address);