summary refs log tree commit diff
diff options
context:
space:
mode:
authorNguyễn Gia Phong <mcsinyx@disroot.org>2024-08-07 13:18:46 +0900
committerNguyễn Gia Phong <mcsinyx@disroot.org>2024-08-07 13:19:24 +0900
commit3ffe5c3ab044bafd0e64b3ba4a2947db9c8c7454 (patch)
tree7dd3671be7ede641e18e12661eebe6efb7e906c5
parentf117aa2ead7a31802363a84c26d3f6863bdd7414 (diff)
downloadguix-e9patch.tar.gz
gnu: Add e9patch. e9patch
* gnu/packages/engineering.scm (e9patch): New variable.

Change-Id: I8da4e76043bf6d577e8d14a89cc7bc35caa3933f
-rw-r--r--gnu/packages/engineering.scm42
-rw-r--r--gnu/packages/patches/e9patch-check.patch199
-rw-r--r--gnu/packages/patches/e9patch-devendor.patch61
3 files changed, 302 insertions, 0 deletions
diff --git a/gnu/packages/engineering.scm b/gnu/packages/engineering.scm
index 92bd7a63ff..a78b1eb157 100644
--- a/gnu/packages/engineering.scm
+++ b/gnu/packages/engineering.scm
@@ -96,6 +96,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)
@@ -165,6 +166,7 @@
   #:use-module (gnu packages tls)
   #: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)
@@ -1981,6 +1983,46 @@ and a fallback for environments without libc for Zydis.")
 @end itemize")
     (license license:expat)))
 
+(define-public e9patch
+  (let ((commit "5b17f53b4c76b91e2e13e5421012b2a75af59b90")
+        (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
+                  "0ydjpb5ij2jjwlaw1499xbi08rnadw39drazkc8jxin2z8dlb7b6"))
+                (file-name (git-file-name name version))
+                (patches (search-patches "e9patch-devendor.patch"
+                                         "e9patch-check.patch"))))
+      (build-system gnu-build-system)
+      (arguments `(#:phases (modify-phases %standard-phases
+                              (delete 'configure))))
+      (native-inputs (list 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..38c924da2f
--- /dev/null
+++ b/gnu/packages/patches/e9patch-check.patch
@@ -0,0 +1,199 @@
+diff --git a/Makefile b/Makefile
+index a5ea0d7ab1ad..acaa7dc64fd0 100644
+--- a/Makefile
++++ b/Makefile
+@@ -45,6 +45,8 @@ E9TOOL_LDFLAGS=\
+     -Wl,--dynamic-list=src/e9tool/e9tool.syms \
+     -lpthread -ldl -lz
+ 
++all: release tool
++
+ release: CXXFLAGS += -O2 -D NDEBUG
+ release: $(E9PATCH_OBJS)
+ 	$(CXX) $(CXXFLAGS) $(E9PATCH_OBJS) -o e9patch
+@@ -103,3 +105,12 @@ clean:
+ 	rm -rf $(E9PATCH_OBJS) e9patch \
+         src/e9patch/e9loader.c e9loader.out e9loader.o e9loader.bin
+ 
++regtest: e9tool
++	$(MAKE) -C test/regtest
++
++stresstest: e9tool
++	$(MAKE) -C test/stresstest
++
++check: regtest # stresstest
++
++.PHONY: regtest stresstest check
+diff --git a/e9compile.sh b/e9compile.sh
+index 0f2e3b31c7c2..c84c19161138 100755
+--- a/e9compile.sh
++++ b/e9compile.sh
+@@ -15,6 +15,8 @@
+ # You should have received a copy of the GNU General Public License
+ # along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ 
++set -e
++
+ if [ -t 1 ]
+ then
+     RED="\033[31m"
+@@ -95,8 +97,7 @@ then
+     exit 1
+ fi
+ 
+-RELOCS=`readelf -r "$BASENAME" | head -n 10 | grep 'R_X86_64_'`
+-if [ ! -z "$RELOCS" ]
++if readelf -r "$BASENAME" | head -n 10 | grep -q 'R_X86_64_'
+ then
+     echo >&2
+     echo "${RED}warning${OFF}: the generated file (${YELLOW}$BASENAME${OFF}) contains relocations" >&2
+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..f486415b83
--- /dev/null
+++ b/gnu/packages/patches/e9patch-devendor.patch
@@ -0,0 +1,61 @@
+diff --git a/Makefile b/Makefile
+index a5ea0d7ab1ad..cfab982a991d 100644
+--- a/Makefile
++++ b/Makefile
+@@ -33,17 +33,11 @@ E9TOOL_OBJS=\
+     src/e9tool/e9tool.o \
+     src/e9tool/e9types.o \
+     src/e9tool/e9x86_64.o
+-E9TOOL_LIBS=\
+-    contrib/zydis/libZydis.a \
+-    contrib/libdw/libdw.a
+-E9TOOL_CXXFLAGS=\
+-    -I src/e9tool/ -Wno-unused-function \
+-    -I contrib/libdw/ \
+-    -I contrib/zydis/include/ \
+-    -I contrib/zydis/dependencies/zycore/include/
++E9TOOL_LIBS=
++E9TOOL_CXXFLAGS=-fPIE -I src/e9tool/ -Wno-unused-function
+ E9TOOL_LDFLAGS=\
+     -Wl,--dynamic-list=src/e9tool/e9tool.syms \
+-    -lpthread -ldl -lz
++    -lpthread -ldl -ldw -lz -lZydis
+ 
+ release: CXXFLAGS += -O2 -D NDEBUG
+ release: $(E9PATCH_OBJS)
+diff --git a/src/e9tool/e9dwarf.cpp b/src/e9tool/e9dwarf.cpp
+index 03afee65a091..183684d2293d 100644
+--- a/src/e9tool/e9dwarf.cpp
++++ b/src/e9tool/e9dwarf.cpp
+@@ -28,7 +28,7 @@
+ #include "e9misc.h"
+ #include "e9tool.h"
+ 
+-#include "libdw.h"
++#include <elfutils/libdw.h>
+ 
+ using namespace e9tool;
+ 
+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);