diff options
-rw-r--r-- | gnu/local.mk | 2 | ||||
-rw-r--r-- | gnu/packages/engineering.scm | 52 | ||||
-rw-r--r-- | gnu/packages/patches/e9patch-check.patch | 167 | ||||
-rw-r--r-- | gnu/packages/patches/e9patch-devendor.patch | 52 |
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); |