├── .gitignore ├── .gitmodules ├── .travis.yml ├── AUTHORS ├── LICENSE ├── Makefile ├── README ├── STYLE ├── app ├── .gitignore ├── Makefile ├── README-python ├── cet │ └── inject │ │ └── cet.c ├── config.h ├── coverage │ ├── etcoverage.cpp │ ├── etcoverage.h │ └── inject │ │ ├── calls.h │ │ ├── calls.s │ │ └── shmem.c ├── elf │ ├── etelf.cpp │ └── etelf.h ├── exectrl.py ├── harden │ ├── etharden.cpp │ └── etharden.h ├── objdump │ ├── objdump.cpp │ └── objdump.h ├── order │ ├── etorder.cpp │ └── etorder.h ├── profile │ └── etprofile.cpp ├── python │ ├── bindings.cpp │ └── shell.py ├── sandbox │ ├── etsandbox.cpp │ ├── etsandbox.h │ └── inject │ │ └── sandbox.c ├── shell │ ├── chain.cpp │ ├── chain.h │ ├── command.cpp │ ├── command.h │ ├── disass.cpp │ ├── disass.h │ ├── loop.cpp │ ├── loop.h │ ├── readline.cpp │ ├── readline.h │ └── shell.cpp ├── shell2 │ ├── chunks.cpp │ ├── chunks.h │ ├── code.cpp │ ├── code.h │ ├── command.cpp │ ├── command.h │ ├── passes.cpp │ ├── passes.h │ ├── readline.cpp │ ├── readline.h │ ├── shell.cpp │ ├── shell.h │ ├── state.cpp │ └── state.h └── twocode │ ├── ettwocode.cpp │ └── ettwocode.h ├── config ├── .gitignore ├── Makefile ├── aarch64-Ubuntu.h ├── aarch64-openSUSE.h ├── riscv64-Debian.h ├── x86_64-Debian.h ├── x86_64-Devuan.h ├── x86_64-Gentoo.h ├── x86_64-Ubuntu.h └── x86_64-openSUSE.h ├── dep ├── .gitignore ├── Makefile ├── ifunc │ ├── .gitignore │ ├── Makefile │ ├── determine.c │ ├── determine.gdb │ └── determine.py └── rtld │ ├── .gitignore │ ├── Makefile │ ├── assign1.gdb │ ├── assign2.gdb │ ├── generate1.gdb │ ├── generate2.gdb │ ├── load_test.c │ ├── pthread.gdb │ ├── reconstruct.py │ ├── reproduce.c │ ├── rtld.gdb │ ├── tcbhead.gdb │ └── test.c ├── env.mk ├── runtime └── override │ ├── libcrypto.1.0.2 │ └── libffi ├── src ├── .gitignore ├── Makefile ├── analysis │ ├── call.cpp │ ├── call.h │ ├── controlflow.cpp │ ├── controlflow.h │ ├── dataflow.cpp │ ├── dataflow.h │ ├── dominance.cpp │ ├── dominance.h │ ├── flow.cpp │ ├── flow.h │ ├── frametype.cpp │ ├── frametype.h │ ├── graph.cpp │ ├── graph.h │ ├── jumptable.cpp │ ├── jumptable.h │ ├── jumptabledetection.cpp │ ├── jumptabledetection.h │ ├── liveregister.cpp │ ├── liveregister.h │ ├── pointerdetection.cpp │ ├── pointerdetection.h │ ├── reachingdef.cpp │ ├── reachingdef.h │ ├── reguse.cpp │ ├── reguse.h │ ├── savedregister.cpp │ ├── savedregister.h │ ├── slicing.cpp │ ├── slicing.h │ ├── slicingmatch.cpp │ ├── slicingmatch.h │ ├── slicingtree.cpp │ ├── slicingtree.h │ ├── usedef.cpp │ ├── usedef.h │ ├── usedefutil.cpp │ ├── usedefutil.h │ ├── walker.cpp │ └── walker.h ├── archive │ ├── archive.cpp │ ├── archive.h │ ├── chunktypes.cpp │ ├── chunktypes.h │ ├── filesystem.cpp │ ├── filesystem.h │ ├── flatchunk.cpp │ ├── flatchunk.h │ ├── operations.cpp │ ├── operations.h │ ├── reader.cpp │ ├── reader.h │ ├── stream.cpp │ ├── stream.h │ ├── writer.cpp │ └── writer.h ├── break │ ├── breakpoint.cpp │ ├── breakpoint.h │ ├── signals.cpp │ └── signals.h ├── chunk │ ├── aliasmap.cpp │ ├── aliasmap.h │ ├── block.cpp │ ├── block.h │ ├── cache.cpp │ ├── cache.h │ ├── chunk.cpp │ ├── chunk.h │ ├── chunkfwd.h │ ├── chunkiter.h │ ├── chunklist.cpp │ ├── chunklist.h │ ├── chunkref.h │ ├── concrete.cpp │ ├── concrete.h │ ├── dataregion.cpp │ ├── dataregion.h │ ├── dump.cpp │ ├── dump.h │ ├── external.cpp │ ├── external.h │ ├── function.cpp │ ├── function.h │ ├── gstable.cpp │ ├── gstable.h │ ├── ifunc.cpp │ ├── ifunc.h │ ├── initfunction.cpp │ ├── initfunction.h │ ├── jumptable.cpp │ ├── jumptable.h │ ├── library.cpp │ ├── library.h │ ├── link.cpp │ ├── link.h │ ├── marker.cpp │ ├── marker.h │ ├── module.cpp │ ├── module.h │ ├── plt.cpp │ ├── plt.h │ ├── position.cpp │ ├── position.h │ ├── program.cpp │ ├── program.h │ ├── resolver.cpp │ ├── resolver.h │ ├── serializer.cpp │ ├── serializer.h │ ├── size.cpp │ ├── size.h │ ├── tls.cpp │ ├── tls.h │ ├── visitor.h │ ├── vtable.cpp │ └── vtable.h ├── cminus │ ├── print.c │ └── print.h ├── conductor │ ├── bridge.cpp │ ├── bridge.h │ ├── bridgeentries.h │ ├── conductor.cpp │ ├── conductor.h │ ├── filesystem.cpp │ ├── filesystem.h │ ├── interface.cpp │ ├── interface.h │ ├── parseoverride.cpp │ ├── parseoverride.h │ ├── passes.cpp │ ├── passes.h │ ├── setup.cpp │ └── setup.h ├── config.h ├── debug │ ├── disasm │ ├── load │ └── quiet ├── disasm │ ├── aarch64-regbits.cpp │ ├── aarch64-regbits.h │ ├── disassemble.cpp │ ├── disassemble.h │ ├── dump.cpp │ ├── dump.h │ ├── formatter.cpp │ ├── formatter.h │ ├── handle.cpp │ ├── handle.h │ ├── makesemantic.cpp │ ├── makesemantic.h │ ├── objectoriented.cpp │ ├── objectoriented.h │ ├── reassemble.cpp │ ├── reassemble.h │ ├── riscv-disas.cpp │ └── riscv-disas.h ├── dwarf │ ├── cursor.cpp │ ├── cursor.h │ ├── defines.h │ ├── entry.cpp │ ├── entry.h │ ├── parser.cpp │ ├── parser.h │ ├── platform.cpp │ ├── platform.h │ ├── state.cpp │ └── state.h ├── elf │ ├── auxv.cpp │ ├── auxv.h │ ├── elfdynamic.cpp │ ├── elfdynamic.h │ ├── elfmap.cpp │ ├── elfmap.h │ ├── elfspace.cpp │ ├── elfspace.h │ ├── elfxx.h │ ├── reloc.cpp │ ├── reloc.h │ ├── riscv-elf.h │ ├── sharedlib.cpp │ ├── sharedlib.h │ ├── symbol.cpp │ ├── symbol.h │ ├── unionfind.cpp │ └── unionfind.h ├── generate │ ├── anygen.cpp │ ├── anygen.h │ ├── basegen.cpp │ ├── basegen.h │ ├── bingen.cpp │ ├── bingen.h │ ├── concrete.cpp │ ├── concrete.h │ ├── concretedeferred.cpp │ ├── concretedeferred.h │ ├── data.cpp │ ├── data.h │ ├── debugelf.cpp │ ├── debugelf.h │ ├── deferred.cpp │ ├── deferred.h │ ├── integerdeferred.cpp │ ├── integerdeferred.h │ ├── kernelgen.cpp │ ├── kernelgen.h │ ├── mirrorgen.cpp │ ├── mirrorgen.h │ ├── modulegen.cpp │ ├── modulegen.h │ ├── objgen.cpp │ ├── objgen.h │ ├── section.cpp │ ├── section.h │ ├── sectionlist.cpp │ ├── sectionlist.h │ ├── uniongen.cpp │ └── uniongen.h ├── instr │ ├── assembly.cpp │ ├── assembly.h │ ├── concrete.cpp │ ├── concrete.h │ ├── instr.cpp │ ├── instr.h │ ├── isolated.h │ ├── linked-aarch64.cpp │ ├── linked-aarch64.h │ ├── linked-arm.cpp │ ├── linked-arm.h │ ├── linked-riscv.cpp │ ├── linked-riscv.h │ ├── linked-x86_64.cpp │ ├── linked-x86_64.h │ ├── linked.h │ ├── memory.cpp │ ├── memory.h │ ├── register.cpp │ ├── register.h │ ├── semantic.cpp │ ├── semantic.h │ ├── serializer.cpp │ ├── serializer.h │ ├── storage.cpp │ ├── storage.h │ ├── visitor.cpp │ ├── visitor.h │ ├── writer.cpp │ └── writer.h ├── load │ ├── bootstrap-aarch64.S │ ├── bootstrap-arm.s │ ├── bootstrap-x86_64.s │ ├── callinit.cpp │ ├── callinit.h │ ├── datastruct.cpp │ ├── datastruct.h │ ├── emulator.cpp │ ├── emulator.h │ ├── loader.cpp │ ├── loader.h │ ├── makebridge.cpp │ ├── makebridge.h │ ├── preparetls.cpp │ ├── preparetls.h │ ├── segmap.cpp │ ├── segmap.h │ ├── usage.cpp │ └── usage.h ├── log │ ├── defaults.h │ ├── log.cpp │ ├── log.h │ ├── registry.cpp │ ├── registry.h │ ├── temp.cpp │ └── temp.h ├── operation │ ├── addinline.cpp │ ├── addinline.h │ ├── cursor.cpp │ ├── cursor.h │ ├── find.cpp │ ├── find.h │ ├── find2.cpp │ ├── find2.h │ ├── mutator.cpp │ └── mutator.h ├── pass │ ├── aflcoverage.cpp │ ├── aflcoverage.h │ ├── cancelpush.cpp │ ├── cancelpush.h │ ├── chunkpass.cpp │ ├── chunkpass.h │ ├── clearplts.cpp │ ├── clearplts.h │ ├── clearspatial.cpp │ ├── clearspatial.h │ ├── collapseplt.cpp │ ├── collapseplt.h │ ├── collectglobals.cpp │ ├── collectglobals.h │ ├── condwatchpoint.cpp │ ├── condwatchpoint.h │ ├── debloat.cpp │ ├── debloat.h │ ├── detectnullptr.cpp │ ├── detectnullptr.h │ ├── dumplink.cpp │ ├── dumplink.h │ ├── dumptlsinstr.cpp │ ├── dumptlsinstr.h │ ├── encodingcheckpass.cpp │ ├── encodingcheckpass.h │ ├── endbradd.cpp │ ├── endbradd.h │ ├── endbrenforce.cpp │ ├── endbrenforce.h │ ├── externalcalls.cpp │ ├── externalcalls.h │ ├── externalsymbollinks.cpp │ ├── externalsymbollinks.h │ ├── fallthrough.cpp │ ├── fallthrough.h │ ├── findendbr.cpp │ ├── findendbr.h │ ├── findinitfuncs.cpp │ ├── findinitfuncs.h │ ├── findsyscalls.cpp │ ├── findsyscalls.h │ ├── fixdataregions.cpp │ ├── fixdataregions.h │ ├── fixenviron.cpp │ ├── fixenviron.h │ ├── fixjumptables.cpp │ ├── fixjumptables.h │ ├── handlecopyrelocs.cpp │ ├── handlecopyrelocs.h │ ├── handledatarelocs.cpp │ ├── handledatarelocs.h │ ├── handlerelocs.cpp │ ├── handlerelocs.h │ ├── hijack.cpp │ ├── hijack.h │ ├── ifunclazy.cpp │ ├── ifunclazy.h │ ├── ifuncplts.cpp │ ├── ifuncplts.h │ ├── inferlinks.cpp │ ├── inferlinks.h │ ├── injectbridge.cpp │ ├── injectbridge.h │ ├── instrumentcalls.cpp │ ├── instrumentcalls.h │ ├── instrumentinstr.cpp │ ├── instrumentinstr.h │ ├── internalcalls.cpp │ ├── internalcalls.h │ ├── jitgsfixup.cpp │ ├── jitgsfixup.h │ ├── jitgssetup.cpp │ ├── jitgssetup.h │ ├── jtoverestimate.cpp │ ├── jtoverestimate.h │ ├── jumptablebounds.cpp │ ├── jumptablebounds.h │ ├── jumptablepass.cpp │ ├── jumptablepass.h │ ├── ldsorefs.cpp │ ├── ldsorefs.h │ ├── logcalls.cpp │ ├── logcalls.h │ ├── loginstr.cpp │ ├── loginstr.h │ ├── makecache.cpp │ ├── makecache.h │ ├── nonreturn.cpp │ ├── nonreturn.h │ ├── noppass.cpp │ ├── noppass.h │ ├── permutedata.cpp │ ├── permutedata.h │ ├── populateplt.cpp │ ├── populateplt.h │ ├── positiondump.cpp │ ├── positiondump.h │ ├── profileinstrument.cpp │ ├── profileinstrument.h │ ├── profilesave.cpp │ ├── profilesave.h │ ├── promotejumps.cpp │ ├── promotejumps.h │ ├── regreplace.cpp │ ├── regreplace.h │ ├── relocheck.cpp │ ├── relocheck.h │ ├── removepadding.cpp │ ├── removepadding.h │ ├── reorderpush.cpp │ ├── reorderpush.h │ ├── resolveexternallinks.cpp │ ├── resolveexternallinks.h │ ├── resolveplt.cpp │ ├── resolveplt.h │ ├── resolvetls.cpp │ ├── resolvetls.h │ ├── retpoline.cpp │ ├── retpoline.h │ ├── run.cpp │ ├── run.h │ ├── shadowstack.cpp │ ├── shadowstack.h │ ├── splitbasicblock.cpp │ ├── splitbasicblock.h │ ├── splitfunction.cpp │ ├── splitfunction.h │ ├── stackextend.cpp │ ├── stackextend.h │ ├── stackxor.cpp │ ├── stackxor.h │ ├── switchcontext.cpp │ ├── switchcontext.h │ ├── syscallsandbox.cpp │ ├── syscallsandbox.h │ ├── twocodealloc.cpp │ ├── twocodealloc.h │ ├── twocodegs.cpp │ ├── twocodegs.h │ ├── twocodemerge.cpp │ ├── twocodemerge.h │ ├── twocodevars.cpp │ ├── twocodevars.h │ ├── updatelink.cpp │ ├── updatelink.h │ ├── usegstable.cpp │ └── usegstable.h ├── runtime │ ├── managegs.cpp │ └── managegs.h ├── snippet │ ├── bss.S │ ├── hook-aarch64.S │ ├── hook-x86_64.S │ ├── hook.h │ ├── ifunc-x86_64.S │ ├── logfunction.c │ ├── logfunction.h │ ├── pthread.cpp │ ├── signal.cpp │ ├── start2-aarch64.S │ ├── start2-x86_64.S │ └── syscall-iface.s ├── transform │ ├── data.cpp │ ├── data.h │ ├── generator.cpp │ ├── generator.h │ ├── sandbox.cpp │ ├── sandbox.h │ └── slot.h ├── types.h └── util │ ├── explicit_bzero.c │ ├── explicit_bzero.h │ ├── feature.h │ ├── intervaltree.cpp │ ├── intervaltree.h │ ├── iter.h │ ├── range.cpp │ ├── range.h │ ├── streamasstring.h │ ├── timing.cpp │ └── timing.h ├── test ├── Makefile ├── README.txt ├── codegen │ ├── .gitignore │ ├── Makefile │ ├── run-basic.sh │ ├── run-build.sh │ └── run-system.sh ├── docker │ ├── .gitignore │ ├── Dockerfile_aarch64 │ ├── Dockerfile_arm │ ├── Dockerfile_x86_64 │ ├── Dockerfile_x86_64-aarch64 │ ├── README.md │ ├── docker.pl │ └── scripts │ │ └── entrypoint.sh ├── example │ ├── .gitignore │ ├── Makefile │ ├── cfg.c │ ├── detectnull.c │ ├── detectnullfail.c │ ├── firmware.c │ ├── fp.c │ ├── getenv.c │ ├── global2.c │ ├── hello-obj.c │ ├── hello.c │ ├── hellocpp.cpp │ ├── hi0-s.S │ ├── hi0.c │ ├── hi2.c │ ├── hi5-s.S │ ├── hi5.c │ ├── islower.c │ ├── jumptable.c │ ├── log.c │ ├── sandbox-stage3.c │ ├── sandbox-write.c │ ├── stack.c │ └── stderr.c ├── framework │ ├── .gitignore │ ├── Makefile │ ├── catch.hpp │ ├── include.h │ └── runner.cpp ├── integration │ ├── .gitignore │ ├── Makefile │ └── defense │ │ └── cet.cpp ├── script │ ├── Makefile │ ├── a2f.py │ ├── add-nops.expected │ ├── add-nops.sh │ ├── argv.expected │ ├── argv.sh │ ├── codeform-debloat.sh │ ├── codeform-dwarf-syms.sh │ ├── codeform-s.sh │ ├── codeform.sh │ ├── compare-syms.sh │ ├── coreutils-functions-aarch64.sh │ ├── coreutils-functions.sh │ ├── coreutils-relocs.sh │ ├── coreutils.sh │ ├── cout.expected │ ├── cout.sh │ ├── detectnull.sh │ ├── dwarf-diff.sh │ ├── environ.sh │ ├── func-diff.pl │ ├── hello-process.sh │ ├── hello-q.sh │ ├── hello-thread.expected │ ├── hello-thread.sh │ ├── hello.expected │ ├── hello.sh │ ├── hi5.expected │ ├── islower.expected │ ├── islower.sh │ ├── jumptable-diff-f3.pl │ ├── jumptable-diff.pl │ ├── jumptable-libc-mktable.sh │ ├── jumptable-libc.sh │ ├── jumptable-rtl.sh │ ├── jumptables.pl │ ├── nginx-jitonce.sh │ ├── nginx-jitshuffle.sh │ ├── nginx-perf.sh │ ├── nginx-thread-jitonce.sh │ ├── nginx-thread-jitshuffle.sh │ ├── nginx-thread.sh │ ├── nginx.sh │ ├── relocheck.sh │ ├── relocs-diff.pl │ ├── relocs.pl │ ├── sandbox-stage3.sh │ └── verify-redzone.sh └── unit │ ├── .gitignore │ ├── Makefile │ ├── StreamAsString.h │ ├── analysis │ ├── _flow.cpp │ ├── _jumptable.cpp │ └── _walker.cpp │ ├── chunk │ ├── _mutator.cpp │ └── _position.cpp │ ├── disasm │ └── _disassemble.cpp │ ├── elf │ ├── _elfmap.cpp │ └── _symbol.cpp │ ├── log │ └── _temp.cpp │ ├── pass │ ├── _instrumentcalls.cpp │ ├── _promotejumps.cpp │ ├── _regreplace.cpp │ └── _stackextend.cpp │ └── util │ └── _intervaltree.cpp ├── travis_aarch64_config.mk └── travis_build.sh /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "test/binary"] 2 | path = test/binary 3 | url = git@github.com:columbia/egalito-tests 4 | [submodule "dep/capstone"] 5 | path = dep/capstone 6 | url = git@github.com:columbia/egalito-capstone 7 | [submodule "dep/distorm3"] 8 | path = dep/distorm3 9 | url = https://github.com/gdabah/distorm 10 | [submodule "docs"] 11 | path = docs 12 | url = git@github.com:columbia/egalito-docs.git 13 | [submodule "dep/keystone"] 14 | path = dep/keystone 15 | url = git@github.com:keystone-engine/keystone.git 16 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | sudo: required 2 | 3 | services: 4 | - docker 5 | env: 6 | matrix: 7 | - ARCH=x86_64 8 | - ARCH=x86_64 CROSS=aarch64 9 | 10 | script: 11 | - ./travis_build.sh 12 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Primary developers: 2 | David Williams-King 3 | Hidenori Kobayashi 4 | Kent Williams-King 5 | 6 | Significant contributors: 7 | Graham Gobieski 8 | Miguel Arroyo 9 | Graham Patterson 10 | Frank Spano 11 | Yu Jian Wu 12 | 13 | Thanks to all! 14 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # root Makefile for egalito 2 | # to change settings, see env.mk 3 | 4 | ifdef USE_CONFIG 5 | include $(USE_CONFIG) 6 | export 7 | endif 8 | 9 | ifneq ($(MAKEVERBOSE),) 10 | MAKE += --no-print-directory 11 | short-make = @+echo '>>>' MAKE -C ${1} ${2} ;\ 12 | $(MAKE) -C ${1} ${2} && echo '<<<' MAKE -C ${1} ${2} 13 | else 14 | short-make = +$(MAKE) -C ${1} ${2} 15 | endif 16 | 17 | .PHONY: all config src test app clean realclean 18 | all: dep src test app 19 | @true 20 | src: dep | config 21 | $(call short-make,src) 22 | test: src 23 | $(call short-make,test) 24 | $(call short-make,test/example) 25 | $(call short-make,test/binary all symlinks) 26 | app: src | test 27 | $(call short-make,app) 28 | dep: dep/built # note: dep is not phony 29 | dep/built: dep/Makefile 30 | $(call short-make,dep) 31 | 32 | config: 33 | $(call short-make,config) 34 | 35 | clean realclean: 36 | $(call short-make,app,clean) 37 | $(call short-make,src,clean) 38 | $(call short-make,test,$@) 39 | $(call short-make,test/example,clean) 40 | $(call short-make,test/binary,clean) 41 | $(call short-make,dep,$@) 42 | $(call short-make,config,clean) 43 | -------------------------------------------------------------------------------- /STYLE: -------------------------------------------------------------------------------- 1 | Indent style: 2 | - indent 4 spaces 3 | - use same-line brace placement without cuddled else, i.e. 4 | if(something) { 5 | code(); 6 | } 7 | else { 8 | more_code(); 9 | } 10 | - if statements without braces must be on one line: 11 | if(x) LOG(1, "error"); 12 | - if code is longer than ~80 characters, wrap and indent 4 chars, e.g. 13 | if(this && that && something_else() && ... 14 | && ...) { 15 | 16 | // ... code 17 | } 18 | void long_function_name(arg1, arg2, ..., 19 | argN, argN+1) { 20 | 21 | // ... code 22 | } 23 | - for functions in header files, write on one line or wrap at braces: 24 | virtual Chunk *getParent() const { return parent; } 25 | virtual SpatialChunkList *getSpatial() 26 | { if(!spatial) createSpatial(); return spatial; } 27 | 28 | 29 | Other points: 30 | - consider forward declaring classes to reduce header dependencies 31 | - all output should go through LOG macros 32 | - if log/log.h is included in any .cpp file, it should be the last #include 33 | - all getter functions should be const if possible 34 | - use address_t for addresses (not void*, unsigned long, etc) 35 | - wrap arch-specific code in ARCH_* macros, or #error if not supported 36 | -------------------------------------------------------------------------------- /app/.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | /.symlinks 3 | /etshell 4 | /etshell2 5 | /etobjdump 6 | /etsandbox 7 | /etcoverage 8 | /etelf 9 | /etharden 10 | /etprofile 11 | /ettwocode 12 | /etorder 13 | /pyshell 14 | /libsandbox.so 15 | /libcoverage.so 16 | /libcet.so 17 | /build_x86_64 18 | /build_aarch64 19 | /build_riscv 20 | /.etshell_history 21 | /core 22 | 23 | -------------------------------------------------------------------------------- /app/README-python: -------------------------------------------------------------------------------- 1 | To build the python shell, first install the following: 2 | $ sudo apt-get install libboost-python-dev python3-cmd2 python3-colorama 3 | Next, update the following lines in the Makefile as appropriate: 4 | BOOST_PYTHON_LIB = boost_python3 5 | PYTHON_LIB = python3.6m 6 | PYTHON_INC_DIR = /usr/include/python3.6m 7 | Then run 8 | $ make python 9 | 10 | Run the shell with this (use "python3 ./pyshell" if needed): 11 | $ ./pyshell 12 | Type "help" to get help on instructions. Mostly compatible with the C++ shell. 13 | 14 | Getting errors while trying to run the python shell? 15 | 1) "ImportError: dynamic module does not define init function (initpython_egalito)" 16 | means you compiled against python 3 but are running with python 2 17 | 2) "ImportError: .../python_egalito.so: undefined symbol: _ZN5boost6python..." 18 | means your boost python library and python library are different versions 19 | 3) "ImportError: ...: undefined symbol: PyString_Type" 20 | means you compiled against python 2 but are running with python 3 21 | -------------------------------------------------------------------------------- /app/config.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_CONFIG_H 2 | #define EGALITO_CONFIG_H 3 | #include "../config/config.h" 4 | #endif 5 | -------------------------------------------------------------------------------- /app/coverage/etcoverage.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_APP_COVERAGE_H 2 | #define EGALITO_APP_COVERAGE_H 3 | 4 | #endif 5 | -------------------------------------------------------------------------------- /app/coverage/inject/calls.h: -------------------------------------------------------------------------------- 1 | #ifndef SHUFFLE_CMINUS_CALLS_H 2 | #define SHUFFLE_CMINUS_CALLS_H 3 | 4 | #include /* for size_t, ssize_t */ 5 | 6 | void exit(int status); 7 | void *shmat(int shmid, const void *shmaddr, int shmflg); 8 | int shmdt(const void *shmaddr); 9 | ssize_t write(int fd, const void *buf, size_t count); 10 | void *__mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset); 11 | 12 | #define stdout 1 13 | #define stderr 2 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /app/coverage/inject/calls.s: -------------------------------------------------------------------------------- 1 | .global shmat 2 | .global shmdt 3 | .global exit 4 | .global write 5 | .global __mmap 6 | .hidden shmat 7 | .hidden shmdt 8 | .hidden exit 9 | .hidden write 10 | .hidden __mmap 11 | 12 | .section .text 13 | 14 | exit: 15 | mov $60, %rax # exit 16 | syscall # other arg in %rdi 17 | hlt 18 | 19 | shmat: 20 | push %rcx 21 | push %r11 22 | mov $30, %rax # shmat 23 | syscall # other args in %rdi, %rsi, %rdx 24 | pop %r11 25 | pop %rcx 26 | retq 27 | 28 | shmdt: 29 | push %rcx 30 | push %r11 31 | mov $67, %rax # shmdt 32 | syscall # other arg in %rdi 33 | pop %r11 34 | pop %rcx 35 | retq 36 | 37 | write: 38 | push %rcx 39 | push %r11 40 | mov $1, %rax # write 41 | syscall # other args in %rdi, %rsi, %rdx 42 | pop %r11 43 | pop %rcx 44 | retq 45 | 46 | __mmap: 47 | push %rcx 48 | push %r11 49 | push %rcx 50 | mov %r10, %rcx 51 | pop %r10 52 | mov $9, %rax # mmap 53 | syscall # other args in everything 54 | pop %r11 55 | pop %rcx 56 | retq 57 | .size __mmap, .-__mmap 58 | -------------------------------------------------------------------------------- /app/elf/etelf.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_APP_ELF_H 2 | #define EGALITO_APP_ELF_H 3 | 4 | #endif 5 | -------------------------------------------------------------------------------- /app/harden/etharden.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_APP_HARDEN_H 2 | #define EGALITO_APP_HARDEN_H 3 | 4 | #include "conductor/interface.h" 5 | 6 | class HardenApp { 7 | private: 8 | bool quiet; 9 | EgalitoInterface *egalito; 10 | public: 11 | HardenApp() : quiet(true) {} 12 | void run(int argc, char **argv); 13 | void parse(const std::string &filename, bool oneToOne); 14 | void generate(const std::string &filename, bool oneToOne); 15 | Program *getProgram() const { return egalito->getProgram(); } 16 | private: 17 | void doCFI(); 18 | void doShadowStack(bool gsMode); 19 | void doPermuteData(); 20 | void doProfiling(); 21 | void doWatching(); 22 | void doRetpolines(); 23 | }; 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /app/objdump/objdump.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_APP_OBJDUMP_H 2 | #define EGALITO_APP_OBJDUMP_H 3 | 4 | #include "conductor/setup.h" 5 | 6 | class ObjDumpOptions { 7 | private: 8 | bool debugMessages = false; 9 | bool recursive = false; 10 | bool showBasicBlocks = false; 11 | bool showBytes = false; 12 | public: 13 | bool getDebugMessages() const { return debugMessages; } 14 | bool getRecursive() const { return recursive; } 15 | bool getShowBasicBlocks() const { return showBasicBlocks; } 16 | bool getShowBytes() const { return showBytes; } 17 | 18 | void setDebugMessages(bool d) { debugMessages = d; } 19 | void setRecursive(bool r) { recursive = r; } 20 | void setShowBasicBlocks(bool s) { showBasicBlocks = s; } 21 | void setShowBytes(bool s) { showBytes = s; } 22 | }; 23 | 24 | class ObjDump { 25 | private: 26 | ObjDumpOptions options; 27 | ConductorSetup setup; 28 | public: 29 | void parse(const char *filename); 30 | 31 | ObjDumpOptions &getOptions() { return options; } 32 | }; 33 | 34 | #endif 35 | -------------------------------------------------------------------------------- /app/order/etorder.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_APP_ORDER_H 2 | #define EGALITO_APP_ORDER_H 3 | 4 | #endif 5 | -------------------------------------------------------------------------------- /app/sandbox/etsandbox.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_APP_SANDBOX_H 2 | #define EGALITO_APP_SANDBOX_H 3 | 4 | #endif 5 | -------------------------------------------------------------------------------- /app/shell/chain.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_SHELL_CHAIN_H 2 | #define EGALITO_SHELL_CHAIN_H 3 | 4 | #include "command.h" 5 | #include "conductor/setup.h" 6 | 7 | void executeLoader(ConductorSetup *setup, Arguments args); 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /app/shell/disass.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_SHELL_DISASS_H 2 | #define EGALITO_SHELL_DISASS_H 3 | 4 | #include "command.h" 5 | 6 | class ConductorSetup; 7 | 8 | class DisassCommands { 9 | private: 10 | ConductorSetup *setup; 11 | public: 12 | DisassCommands(ConductorSetup *setup) : setup(setup) {} 13 | 14 | void registerCommands(CompositeCommand *topLevel); 15 | }; 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /app/shell/loop.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_SHELL_LOOP_H 2 | #define EGALITO_SHELL_LOOP_H 3 | 4 | #include "command.h" 5 | 6 | class TopLevelCommand : public CompositeCommand { 7 | public: 8 | TopLevelCommand() : CompositeCommand("", "") {} 9 | virtual void invokeNull(Arguments args) {} 10 | virtual void invokeDefault(Arguments args); 11 | }; 12 | 13 | void mainLoop(); 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /app/shell/readline.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_SHELL_READLINE_H 2 | #define EGALITO_SHELL_READLINE_H 3 | 4 | #include 5 | 6 | class Readline { 7 | public: 8 | Readline(); 9 | ~Readline(); 10 | std::string get(const std::string &prompt); 11 | }; 12 | 13 | #endif 14 | -------------------------------------------------------------------------------- /app/shell/shell.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "log/registry.h" 3 | #include "loop.h" 4 | 5 | #ifndef GIT_VERSION 6 | #define GIT_VERSION (unknown) 7 | #endif 8 | 9 | #define _STRINGIZE(x) # x 10 | #define _STRINGIZE2(x) _STRINGIZE(x) 11 | 12 | int main(int argc, char *argv[]) { 13 | SettingsParser().parseEnvVar("EGALITO_DEBUG"); 14 | 15 | std::cout << "Welcome to the egalito shell version " 16 | << _STRINGIZE2(GIT_VERSION) << ". Type \"help\" for usage.\n"; 17 | mainLoop(); 18 | 19 | return 0; 20 | } 21 | -------------------------------------------------------------------------------- /app/shell2/chunks.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_SHELL2_CHUNKS_H 2 | #define EGALITO_SHELL2_CHUNKS_H 3 | 4 | #include "code.h" 5 | #include "command.h" 6 | #include "conductor/interface.h" 7 | 8 | class ChunkCommands { 9 | private: 10 | FullCommandList *fullList; 11 | public: 12 | ChunkCommands(FullCommandList *fullList) : fullList(fullList) {} 13 | void construct(EgalitoInterface *egalito); 14 | }; 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /app/shell2/code.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_SHELL2_CODE_H 2 | #define EGALITO_SHELL2_CODE_H 3 | 4 | #include 5 | #include 6 | #include "state.h" 7 | #include "command.h" 8 | 9 | class FullCommandList { 10 | private: 11 | std::map commandMap; 12 | public: 13 | FullCommandList(EgalitoInterface *egalito); 14 | 15 | void add(Command *command); 16 | Command *lookup(const std::string &name) const; 17 | std::vector lookupPrefix(const std::string &prefix) const; 18 | std::vector getCommandList() const; 19 | private: 20 | bool helpCommand(ShellState &state, ArgumentValueList &args) const; 21 | bool runCommand1(const char *file, ShellState &state, ArgumentValueList &args) const 22 | { return runCommandN(file, state, args, {}); } 23 | bool runCommandN(const char *file, ShellState &state, 24 | ArgumentValueList &args, std::vector extraArgv) const; 25 | bool runGeneratedFile(const char *file, ShellState &state, 26 | ArgumentValueList &args) const; 27 | }; 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /app/shell2/readline.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_SHELL_READLINE_H 2 | #define EGALITO_SHELL_READLINE_H 3 | 4 | #include 5 | 6 | class Shell2App; 7 | class FullCommandList; 8 | 9 | class Readline { 10 | public: 11 | Readline(Shell2App *app, FullCommandList *commandList); 12 | ~Readline(); 13 | std::string get(const std::string &prompt); 14 | }; 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /app/shell2/state.cpp: -------------------------------------------------------------------------------- 1 | #include "state.h" 2 | 3 | void ShellState::setChunk(Chunk *chunk) { 4 | if(this->chunk) reflog.push_back(this->chunk); 5 | 6 | this->chunk = chunk; 7 | } 8 | 9 | Chunk *ShellState::popReflog() { 10 | if(reflog.empty()) return nullptr; 11 | 12 | auto last = reflog.back(); 13 | reflog.pop_back(); 14 | return last; 15 | } 16 | -------------------------------------------------------------------------------- /app/twocode/ettwocode.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_APP_TWOCODE_H 2 | #define EGALITO_APP_TWOCODE_H 3 | 4 | #include "conductor/interface.h" 5 | 6 | class TwocodeApp { 7 | private: 8 | bool quiet; 9 | EgalitoInterface *egalito; 10 | Module *extraModule; 11 | public: 12 | TwocodeApp() : quiet(true), extraModule(nullptr) {} 13 | void run(int argc, char **argv); 14 | void parse(const std::string &filename, const std::string &extra, bool oneToOne); 15 | void generate(const std::string &filename, bool oneToOne); 16 | Program *getProgram() const { return egalito->getProgram(); } 17 | private: 18 | void doWatching(); 19 | void doTwocode(); 20 | }; 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /config/.gitignore: -------------------------------------------------------------------------------- 1 | config.h 2 | -------------------------------------------------------------------------------- /config/Makefile: -------------------------------------------------------------------------------- 1 | 2 | include ../env.mk 3 | 4 | PLATFORM_CONFIG_FILE = $(P_ARCH)-$(DISTRO).h 5 | 6 | DIFF = $(if $(wildcard config.h),$(shell diff $(PLATFORM_CONFIG_FILE) config.h)) 7 | 8 | all: config.h 9 | @true 10 | 11 | config.h: $(PLATFORM_CONFIG_FILE) 12 | @if [ -e $(PLATFORM_CONFIG_FILE) ]; then \ 13 | if [ ! -e config.h ]; then \ 14 | cp $(PLATFORM_CONFIG_FILE) config.h; \ 15 | else \ 16 | if [ "$(DIFF)" != "" ]; then \ 17 | echo "default config is updated: please remove config.h to apply."; \ 18 | diff $(PLATFORM_CONFIG_FILE) config.h; \ 19 | fi \ 20 | fi \ 21 | fi 22 | 23 | $(PLATFORM_CONFIG_FILE): 24 | $(error "Please add a new configuration file ($(PLATFORM_CONFIG_FILE)).") 25 | 26 | clean: 27 | @if [ "$(DIFF)" != "" ]; then \ 28 | echo "config.h was modified: please remove manually."; \ 29 | diff $(PLATFORM_CONFIG_FILE) config.h; \ 30 | else \ 31 | rm -f config.h; \ 32 | fi 33 | 34 | force-update: 35 | cp -a $(PLATFORM_CONFIG_FILE) config.h 36 | -------------------------------------------------------------------------------- /config/aarch64-Ubuntu.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_CONFIG_AARCH64_UBUNTU_H 2 | #define EGALITO_CONFIG_AARCH64_UBUNTU_H 3 | 4 | /* For Ubuntu on AARCH64 */ 5 | 6 | /* common */ 7 | 8 | /* src */ 9 | 10 | #define CACHE_DIR "_cache" 11 | #define SANDBOX_BASE_ADDRESS 0x40000000 12 | #define JIT_TABLE_SIZE 64 * 0x1000 // must fit in 32-bit 13 | 14 | /* app */ 15 | 16 | #define PROMPT_COLOR C_GREEN 17 | 18 | /* test */ 19 | 20 | #define ANALYSIS_JUMPTABLE_MAIN_COUNT 1 21 | #define ANALYSIS_JUMPTABLE_PARSE_EXPRESSION_COUNT 2 22 | 23 | #define PASS_STACKEXTEND_RESTORE_SP_FROM_X29 1 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /config/aarch64-openSUSE.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_CONFIG_AARCH64_OPENSUSE_H 2 | #define EGALITO_CONFIG_AARCH64_OPENSUSE_H 3 | 4 | /* For openSUSE on AARCH64 */ 5 | 6 | /* common */ 7 | 8 | /* src */ 9 | 10 | #define CACHE_DIR "_cache" 11 | #define SANDBOX_BASE_ADDRESS 0x40000000 12 | #define JIT_TABLE_SIZE 64 * 0x1000 // must fit in 32-bit 13 | 14 | /* app */ 15 | 16 | #define PROMPT_COLOR C_GREEN 17 | 18 | /* test */ 19 | 20 | #if defined(__GNUC__) && (__GNUC__ >= 7) /* tumbleweed */ 21 | #define ANALYSIS_JUMPTABLE_MAIN_COUNT 0 22 | #define ANALYSIS_JUMPTABLE_PARSE_EXPRESSION_COUNT 1 23 | #else 24 | #define ANALYSIS_JUMPTABLE_MAIN_COUNT 1 25 | #define ANALYSIS_JUMPTABLE_PARSE_EXPRESSION_COUNT 2 26 | #endif 27 | 28 | #if defined(__GNUC__) && (__GNUC__ >= 7) /* tumbleweed */ 29 | #define PASS_STACKEXTEND_RESTORE_SP_FROM_X29 0 30 | #else /* gcc-6 */ 31 | #define PASS_STACKEXTEND_RESTORE_SP_FROM_X29 1 32 | #endif 33 | #endif 34 | -------------------------------------------------------------------------------- /config/riscv64-Debian.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_CONFIG_X86_64_DEBIAN_H 2 | #define EGALITO_CONFIG_X86_64_DEBIAN_H 3 | 4 | /* For Debian testing (buster) on riscv */ 5 | 6 | /* common */ 7 | 8 | /* src */ 9 | 10 | #define SANDBOX_BASE_ADDRESS 0x40000000 11 | #define JIT_TABLE_SIZE 64 * 0x1000 // must fit in 32-bit 12 | 13 | /* app */ 14 | 15 | #define PROMPT_COLOR C_WHITE 16 | 17 | /* test */ 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /config/x86_64-Debian.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_CONFIG_X86_64_DEBIAN_H 2 | #define EGALITO_CONFIG_X86_64_DEBIAN_H 3 | 4 | /* For Debian testing (buster) on X86_64 */ 5 | 6 | /* common */ 7 | 8 | /* src */ 9 | 10 | #define SANDBOX_BASE_ADDRESS 0x40000000 11 | #define JIT_TABLE_SIZE 64 * 0x1000 // must fit in 32-bit 12 | 13 | /* app */ 14 | 15 | #define PROMPT_COLOR C_WHITE 16 | 17 | /* test */ 18 | 19 | #define ANALYSIS_JUMPTABLE_MAIN_COUNT 1 20 | #define ANALYSIS_JUMPTABLE_PARSE_EXPRESSION_COUNT 2 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /config/x86_64-Devuan.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_CONFIG_X86_64_DEVUAN_H 2 | #define EGALITO_CONFIG_X86_64_DEVUAN_H 3 | 4 | /* For Debian testing (buster) on X86_64 */ 5 | 6 | /* common */ 7 | 8 | /* src */ 9 | 10 | #define SANDBOX_BASE_ADDRESS 0x40000000 11 | #define JIT_TABLE_SIZE 64 * 0x1000 // must fit in 32-bit 12 | 13 | /* app */ 14 | 15 | #define PROMPT_COLOR C_WHITE 16 | 17 | /* test */ 18 | 19 | #define ANALYSIS_JUMPTABLE_MAIN_COUNT 1 20 | #define ANALYSIS_JUMPTABLE_PARSE_EXPRESSION_COUNT 2 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /config/x86_64-Gentoo.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_CONFIG_X86_64_GENTOO_H 2 | #define EGALITO_CONFIG_X86_64_GENTOO_H 3 | 4 | /* For Gentoo on X86_64 */ 5 | 6 | /* common */ 7 | 8 | /* src */ 9 | 10 | #define SANDBOX_BASE_ADDRESS 0x40000000 11 | #define JIT_TABLE_SIZE 64 * 0x1000 // must fit in 32-bit 12 | 13 | /* app */ 14 | 15 | #define PROMPT_COLOR C_WHITE 16 | 17 | /* test */ 18 | 19 | #define ANALYSIS_JUMPTABLE_MAIN_COUNT 1 20 | #define ANALYSIS_JUMPTABLE_PARSE_EXPRESSION_COUNT 2 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /config/x86_64-Ubuntu.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_CONFIG_X86_64_UBUNTU_H 2 | #define EGALITO_CONFIG_X86_64_UBUNTU_H 3 | 4 | /* For Ubuntu 16.04 LTS on X86_64 */ 5 | 6 | /* common */ 7 | 8 | /* src */ 9 | 10 | #define SANDBOX_BASE_ADDRESS 0x40000000 11 | #define JIT_TABLE_SIZE 64 * 0x1000 // must fit in 32-bit 12 | 13 | /* app */ 14 | 15 | #define PROMPT_COLOR C_GREEN 16 | 17 | /* test */ 18 | 19 | #define ANALYSIS_JUMPTABLE_MAIN_COUNT 1 20 | #define ANALYSIS_JUMPTABLE_PARSE_EXPRESSION_COUNT 2 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /config/x86_64-openSUSE.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_CONFIG_X86_64_OPENSUSE_H 2 | #define EGALITO_CONFIG_X86_64_OPENSUSE_H 3 | 4 | /* For openSUSE tumbleweed on X86_64 */ 5 | 6 | /* common */ 7 | 8 | /* src */ 9 | 10 | #define HAVE_EXPLICIT_BZERO 11 | #define SANDBOX_BASE_ADDRESS 0x40000000 12 | #define JIT_TABLE_SIZE 64 * 0x1000 // must fit in 32-bit 13 | //#define JIT_RESET_THRESHOLD 10000 14 | 15 | /* app */ 16 | 17 | #define PROMPT_COLOR C_GREEN 18 | 19 | /* test */ 20 | 21 | #define ANALYSIS_JUMPTABLE_MAIN_COUNT 1 22 | #define ANALYSIS_JUMPTABLE_PARSE_EXPRESSION_COUNT 2 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /dep/.gitignore: -------------------------------------------------------------------------------- 1 | /built 2 | -------------------------------------------------------------------------------- /dep/ifunc/.gitignore: -------------------------------------------------------------------------------- 1 | /ifunc.h 2 | /determine 3 | -------------------------------------------------------------------------------- /dep/ifunc/Makefile: -------------------------------------------------------------------------------- 1 | include ../../env.mk 2 | 3 | GDB = $(CROSS)gdb 4 | RUN_GDB = $(GDB) -n -batch-silent -x determine.py 5 | 6 | .PHONY: all 7 | all: ifunc.h 8 | 9 | ifunc.h: determine 10 | touch ifunc.h 11 | 12 | determine: determine.c 13 | @$(CC) -O0 -fno-builtin -o $@ $^ -lm 14 | @$(RUN_GDB) -x determine.gdb $@ 15 | 16 | clean realclean: 17 | -@rm -f determine ifunc.h 18 | -------------------------------------------------------------------------------- /dep/ifunc/determine.gdb: -------------------------------------------------------------------------------- 1 | set pagination off 2 | set confirm off 3 | b *breakpoint 4 | command 5 | DetermineIFuncTarget 6 | end 7 | run 8 | quit 9 | -------------------------------------------------------------------------------- /dep/rtld/.gitignore: -------------------------------------------------------------------------------- 1 | /assign1.c 2 | /assign2.c 3 | /generate1.c 4 | /generate2.c 5 | /reproduce 6 | /rtld.h 7 | /rtld_data1.c 8 | /rtld_data2.c 9 | /pthread.h 10 | /tcbhead.h 11 | /test 12 | /reproduce 13 | /build_x86_64 14 | /build_aarch64 15 | /build_riscv 16 | -------------------------------------------------------------------------------- /dep/rtld/assign1.gdb: -------------------------------------------------------------------------------- 1 | set pagination off 2 | reconstruct dump struct rtld_global 3 | quit 4 | -------------------------------------------------------------------------------- /dep/rtld/assign2.gdb: -------------------------------------------------------------------------------- 1 | set pagination off 2 | reconstruct dump struct rtld_global_ro 3 | quit 4 | -------------------------------------------------------------------------------- /dep/rtld/generate1.gdb: -------------------------------------------------------------------------------- 1 | set pagination off 2 | reconstruct assign struct rtld_global 3 | quit 4 | -------------------------------------------------------------------------------- /dep/rtld/generate2.gdb: -------------------------------------------------------------------------------- 1 | set pagination off 2 | reconstruct assign struct rtld_global_ro 3 | quit 4 | -------------------------------------------------------------------------------- /dep/rtld/load_test.c: -------------------------------------------------------------------------------- 1 | #include 2 | char *test = "hi"; 3 | int main() { 4 | printf("hello world"); 5 | return 0; 6 | } 7 | -------------------------------------------------------------------------------- /dep/rtld/pthread.gdb: -------------------------------------------------------------------------------- 1 | set pagination off 2 | reconstruct c struct pthread 3 | quit 4 | -------------------------------------------------------------------------------- /dep/rtld/reproduce.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include // auto-gen code uses bool 3 | #include 4 | #include "rtld.h" 5 | 6 | void assign1(struct my_rtld_global *s) { 7 | #include "rtld_data1.c" 8 | } 9 | 10 | void assign2(struct my_rtld_global_ro *s) { 11 | #include "rtld_data2.c" 12 | } 13 | 14 | void print_raw(char *data, size_t size, const char *name) { 15 | typedef unsigned long element_t; 16 | const size_t count = sizeof(element_t); 17 | 18 | printf("%s:\n", name); 19 | for(size_t i = 0; i < size; i += count) { 20 | printf("0x%-16lx ", *(element_t *)(data + i)); 21 | if((i + count) % (4 * count) == 0) printf("\n"); 22 | } 23 | printf("\n"); 24 | } 25 | 26 | int main() { 27 | struct my_rtld_global global; 28 | memset(&global, 0, sizeof(global)); 29 | assign1(&global); 30 | print_raw((char *)&global, sizeof(global), "rtld_global"); 31 | 32 | struct my_rtld_global_ro global_ro; 33 | memset(&global_ro, 0, sizeof(global_ro)); 34 | assign2(&global_ro); 35 | print_raw((char *)&global_ro, sizeof(global_ro), "rtld_global_ro"); 36 | return 0; 37 | } 38 | -------------------------------------------------------------------------------- /dep/rtld/rtld.gdb: -------------------------------------------------------------------------------- 1 | set pagination off 2 | reconstruct c struct rtld_global 3 | reconstruct c struct rtld_global_ro 4 | quit 5 | -------------------------------------------------------------------------------- /dep/rtld/tcbhead.gdb: -------------------------------------------------------------------------------- 1 | set pagination off 2 | reconstruct c tcbhead_t 3 | quit 4 | -------------------------------------------------------------------------------- /runtime/override/libcrypto.1.0.2: -------------------------------------------------------------------------------- 1 | blockoverride module libcrypto.so.1.0.2 func K256 2 | 0x0 0x0 3 | blockoverride module libcrypto.so.1.0.2 func K256_shaext 4 | 0x0 0x0 5 | blockoverride module libcrypto.so.1.0.2 func K512 6 | 0x0 0x0 7 | blockoverride module libcrypto.so.1.0.2 func K_XX_XX 8 | 0x0 0x0 9 | blockoverride module libcrypto.so.1.0.2 func RC4_options 10 | 0x0 0x13 11 | 0x13 0x6 12 | 0x19 0x6 13 | 0x1f 0x6 14 | blockoverride func K256 15 | 0x0 0x0 16 | blockoverride func K256_shaext 17 | 0x0 0x0 18 | blockoverride func K512 19 | 0x0 0x0 20 | blockoverride func K_XX_XX 21 | 0x0 0x0 22 | blockoverride func RC4_options 23 | 0x0 0x13 24 | 0x13 0x6 25 | 0x19 0x6 26 | 0x1f 0x6 27 | -------------------------------------------------------------------------------- /runtime/override/libffi: -------------------------------------------------------------------------------- 1 | blockoverride module libffi.so.6 func ffi_call_unix64 2 | 0x0 0x71 3 | 0xad 0xc1 4 | blockoverride module libffi.so.6 func ffi_closure_unix64 5 | 0x0 0x62 6 | 0x9e 0x9c 7 | blockoverride func ffi_call_unix64 8 | 0x0 0x71 9 | 0xad 0xc1 10 | blockoverride func ffi_closure_unix64 11 | 0x0 0x62 12 | 0x9e 0x9c 13 | -------------------------------------------------------------------------------- /src/.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.d 3 | *.swp 4 | /.symlinks 5 | /loader 6 | /egalito 7 | /libegalito.a 8 | /libegalito.so 9 | /libaddon.so 10 | /example 11 | /ex 12 | /regression/elfgen_test 13 | /regression/output/* 14 | /build_x86_64 15 | /build_aarch64 16 | /build_riscv 17 | /symbols.elf 18 | /core 19 | -------------------------------------------------------------------------------- /src/analysis/dataflow.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_ANALYSIS_DATAFLOW_H 2 | #define EGALITO_ANALYSIS_DATAFLOW_H 3 | 4 | #include "analysis/usedef.h" 5 | #include "analysis/liveregister.h" 6 | 7 | class Module; 8 | class Program; 9 | 10 | class DataFlow { 11 | private: 12 | std::map flowList; 13 | std::vector workingList; 14 | std::vector configList; 15 | std::vector graphList; 16 | 17 | public: 18 | ~DataFlow(); 19 | void addUseDefFor(Function *function); 20 | void adjustCallUse(LiveRegister *live, Function *function, Module *module); 21 | void adjustPLTCallUse(LiveRegister *live, Function *function, 22 | Program *program); 23 | UDRegMemWorkingSet *getWorkingSet(Function *function); 24 | 25 | private: 26 | bool isTLSdescResolveCall(UDState *state, Module *module); 27 | void adjustUse(LiveRegister *live, Instruction *instruction, 28 | Function *source, Function *target, bool viaTrampoline); 29 | }; 30 | 31 | #endif 32 | -------------------------------------------------------------------------------- /src/analysis/dominance.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_ANALYSIS_DOMINANCE_H 2 | #define EGALITO_ANALYSIS_DOMINANCE_H 3 | 4 | #include 5 | #include 6 | #include "controlflow.h" 7 | 8 | class Dominance { 9 | public: 10 | using id_t = ControlFlow::id_t; 11 | 12 | private: 13 | ControlFlowGraph *cfg; 14 | std::vector idoms; // immediate dominator 15 | std::vector idMap; // id_t => order ID 16 | 17 | public: 18 | Dominance(ControlFlowGraph *cfg); 19 | std::vector getDominators(id_t id); 20 | std::vector getPostDominators(id_t id); 21 | 22 | private: 23 | id_t intersect(id_t i1, id_t i2); 24 | 25 | void dump(); 26 | }; 27 | #endif 28 | -------------------------------------------------------------------------------- /src/analysis/frametype.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_ANALYSIS_FRAMETYPE_H 2 | #define EGALITO_ANALYSIS_FRAMETYPE_H 3 | 4 | #include 5 | 6 | class Function; 7 | class Instruction; 8 | class ControlFlowInstruction; 9 | 10 | class FrameType { 11 | private: 12 | bool hasFrame; 13 | Instruction *setBPInstr; 14 | Instruction *setSPInstr; 15 | std::vector resetSPInstrs; 16 | std::vector epilogueInstrs; 17 | std::vector jumpToEpilogueInstrs; 18 | 19 | public: 20 | FrameType(Function *function); 21 | bool createsFrame() { return hasFrame; } 22 | Instruction *getSetBPInstr() const { return setBPInstr; } 23 | Instruction *getSetSPInstr() const { return setSPInstr; } 24 | std::vector getResetSPInstrs() const 25 | { return resetSPInstrs; } 26 | std::vector getEpilogueInstrs() const 27 | { return epilogueInstrs; } 28 | void fixEpilogue(Instruction *oldInstr, Instruction *newInstr); 29 | void setSetBPInstr(Instruction *newInstr) { setBPInstr = newInstr; } 30 | void dump(); 31 | 32 | static bool hasStackFrame(Function *function); 33 | }; 34 | 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /src/analysis/graph.cpp: -------------------------------------------------------------------------------- 1 | #include "graph.h" 2 | -------------------------------------------------------------------------------- /src/analysis/graph.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_ANALYSIS_GRAPH_H 2 | #define EGALITO_ANALYSIS_GRAPH_H 3 | 4 | #include 5 | #include 6 | #include "util/iter.h" 7 | 8 | class GraphLinkBase { 9 | public: 10 | virtual ~GraphLinkBase() {} 11 | virtual int getTargetID() const = 0; 12 | }; 13 | 14 | class GraphLinkRef { 15 | private: 16 | GraphLinkBase *link; 17 | public: 18 | GraphLinkRef(GraphLinkBase *link) : link(link) {} 19 | GraphLinkBase &operator * () const { return *link; } 20 | GraphLinkBase *operator -> () const { return link; } 21 | }; 22 | 23 | class GraphNodeBase { 24 | public: 25 | typedef std::vector ListType; 26 | virtual int getID() const = 0; 27 | virtual ConcreteIterable getLinks(int direction) = 0; 28 | }; 29 | 30 | class GraphBase { 31 | public: 32 | virtual GraphNodeBase *get(int id) = 0; 33 | virtual size_t getCount() const = 0; 34 | }; 35 | 36 | 37 | #endif 38 | -------------------------------------------------------------------------------- /src/analysis/liveregister.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_ANALYSIS_LIVEDREGISTER_H 2 | #define EGALITO_ANALYSIS_LIVEDREGISTER_H 3 | 4 | #include 5 | #include 6 | #include "analysis/usedef.h" 7 | 8 | class Function; 9 | class UDState; 10 | 11 | class LiveInfo { 12 | private: 13 | std::bitset<32> regs; 14 | 15 | public: 16 | LiveInfo() : regs(0xFFFFFFFF) {} 17 | void kill(int reg); 18 | void live(int reg); 19 | bool get(int reg) { return regs[reg]; } 20 | const std::bitset<32>& get() const { return regs; } 21 | }; 22 | 23 | class LiveRegister { 24 | private: 25 | std::map list; 26 | 27 | public: 28 | LiveInfo getInfo(Function *function); 29 | LiveInfo getInfo(UDRegMemWorkingSet *working); 30 | 31 | void detect(Function *function); 32 | void detect(UDRegMemWorkingSet *working); 33 | }; 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /src/analysis/reguse.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_ANALYSIS_REGUSE_H 2 | #define EGALITO_ANALYSIS_REGUSE_H 3 | 4 | #include 5 | #include 6 | 7 | #include "instr/register.h" 8 | 9 | class Function; 10 | class Instruction; 11 | 12 | #ifdef ARCH_AARCH64 13 | class AARCH64RegisterUsageX { 14 | private: 15 | Function *function; 16 | PhysicalRegister regX; 17 | 18 | std::vector xList; 19 | 20 | public: 21 | AARCH64RegisterUsageX(Function *function, AARCH64GPRegister::ID id); 22 | 23 | std::vector getInstructionList() const { return xList; } 24 | std::vector getUnusableRegister(); 25 | }; 26 | 27 | class AARCH64RegisterUsage { 28 | public: 29 | AARCH64RegisterUsage() {} 30 | 31 | std::vector getAllUseCounts(Function *function); 32 | }; 33 | #endif 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /src/analysis/savedregister.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_ANALYSIS_SAVEDREGISTER_H 2 | #define EGALITO_ANALYSIS_SAVEDREGISTER_H 3 | 4 | #include 5 | 6 | #ifdef ARCH_AARCH64 7 | class Function; 8 | class UDState; 9 | class UDRegMemWorkingSet; 10 | 11 | class SavedRegister { 12 | public: 13 | std::vector getList(Function *function); 14 | std::vector getList(UDRegMemWorkingSet *working); 15 | 16 | private: 17 | void detectSaveRegister(const UDState& state, std::vector& list); 18 | }; 19 | #endif 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /src/analysis/slicingmatch.cpp: -------------------------------------------------------------------------------- 1 | #include "slicingmatch.h" 2 | 3 | void TreeCapture::append(const TreeCapture& capture) { 4 | captureList.insert(captureList.end(), 5 | capture.captureList.begin(), capture.captureList.end()); 6 | } 7 | -------------------------------------------------------------------------------- /src/analysis/usedefutil.cpp: -------------------------------------------------------------------------------- 1 | #include "usedefutil.h" 2 | -------------------------------------------------------------------------------- /src/analysis/walker.cpp: -------------------------------------------------------------------------------- 1 | #include "walker.h" 2 | 3 | -------------------------------------------------------------------------------- /src/archive/archive.cpp: -------------------------------------------------------------------------------- 1 | #include "archive.h" 2 | 3 | const char *EgalitoArchive::SIGNATURE = "egalito\xc4"; 4 | -------------------------------------------------------------------------------- /src/archive/archive.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_ARCHIVE_ARCHIVE_H 2 | #define EGALITO_ARCHIVE_ARCHIVE_H 3 | 4 | #include 5 | #include "flatchunk.h" 6 | #include "chunktypes.h" 7 | 8 | class EgalitoArchive { 9 | public: 10 | static const char *SIGNATURE; 11 | static const uint32_t VERSION = 24; 12 | private: 13 | FlatChunkList flatList; 14 | std::string sourceFilename; 15 | int version; 16 | public: 17 | EgalitoArchive() : sourceFilename("(in-memory)"), version(VERSION) {} 18 | EgalitoArchive(std::string filename, int version) 19 | : sourceFilename(filename), version(version) {} 20 | 21 | FlatChunkList &getFlatList() { return flatList; } 22 | const FlatChunkList &getFlatList() const { return flatList; } 23 | 24 | int getVersion() const { return version; } 25 | }; 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /src/archive/chunktypes.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_ARCHIVE_CHUNK_TYPES_H 2 | #define EGALITO_ARCHIVE_CHUNK_TYPES_H 3 | 4 | #include 5 | 6 | enum EgalitoChunkType { 7 | TYPE_UNKNOWN = 0, 8 | TYPE_Program, 9 | TYPE_Module, 10 | TYPE_FunctionList, 11 | TYPE_PLTList, 12 | TYPE_JumpTableList, 13 | TYPE_DataRegionList, 14 | TYPE_InitFunctionList, 15 | TYPE_ExternalSymbolList, 16 | TYPE_LibraryList, 17 | TYPE_VTableList, 18 | TYPE_Function, 19 | TYPE_Block, 20 | TYPE_Instruction, 21 | TYPE_PLTTrampoline, 22 | TYPE_JumpTable, 23 | TYPE_JumpTableEntry, 24 | TYPE_DataRegion, 25 | TYPE_TLSDataRegion, 26 | TYPE_DataSection, 27 | TYPE_DataVariable, 28 | TYPE_GlobalVariable, 29 | TYPE_MarkerList, 30 | TYPE_Marker, 31 | TYPE_VTable, 32 | TYPE_VTableEntry, 33 | TYPE_InitFunction, 34 | TYPE_ExternalSymbol, 35 | TYPE_Library, 36 | TYPE_TOTAL 37 | }; 38 | 39 | uint8_t encodeChunkType(EgalitoChunkType type); 40 | EgalitoChunkType decodeChunkType(uint8_t encoded); 41 | const char *getChunkTypeName(EgalitoChunkType type); 42 | 43 | #endif 44 | -------------------------------------------------------------------------------- /src/archive/filesystem.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_ARCHIVE_FILESYSTEM_H 2 | #define EGALITO_ARCHIVE_FILESYSTEM_H 3 | 4 | #include 5 | 6 | class Program; 7 | class Module; 8 | 9 | class ArchiveFileSystem { 10 | private: 11 | std::string root; 12 | public: 13 | ArchiveFileSystem(const std::string &root = ".hobbit") 14 | : root(root) {} 15 | 16 | std::string getArchivePathFor(Module *module, 17 | const std::string &mode = "default"); 18 | std::string getArchivePathFor(Program *program, 19 | const std::string &mode = "default"); 20 | void makeArchivePath(const std::string &archivePath); 21 | 22 | std::string getModuleArchivePath(const std::string &path, 23 | const std::string &mode = "default"); 24 | std::string getProgramArchivePath(const std::string &path, 25 | const std::string &mode = "default"); 26 | bool archivePathExists(const std::string &archivePath); 27 | private: 28 | std::string getArchivePath(const std::string &mode, 29 | const std::string &type, const std::string &path); 30 | std::string canonicalPath(const std::string &filename); 31 | }; 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /src/archive/operations.cpp: -------------------------------------------------------------------------------- 1 | #include "operations.h" 2 | -------------------------------------------------------------------------------- /src/archive/reader.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_ARCHIVE_READER_H 2 | #define EGALITO_ARCHIVE_READER_H 3 | 4 | #include 5 | #include "archive.h" 6 | 7 | class LibraryList; 8 | 9 | class EgalitoArchiveReader { 10 | public: 11 | EgalitoArchive *read(std::string filename); 12 | EgalitoArchive *read(std::string filename, LibraryList *libraryList); 13 | private: 14 | bool readHeader(std::ifstream &file, uint32_t &flatCount, 15 | uint32_t &version); 16 | }; 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /src/archive/writer.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_ARCHIVE_WRITER_H 2 | #define EGALITO_ARCHIVE_WRITER_H 3 | 4 | #include 5 | #include "archive.h" 6 | 7 | class EgalitoArchiveWriter { 8 | private: 9 | EgalitoArchive *archive; 10 | public: 11 | EgalitoArchiveWriter(EgalitoArchive *archive) : archive(archive) {} 12 | void write(std::string filename); 13 | private: 14 | void assignOffsets(); 15 | void writeData(std::string filename); 16 | }; 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /src/break/breakpoint.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "breakpoint.h" 4 | 5 | static void aligned_mprotect(unsigned long dest, unsigned long size, int protection) { 6 | unsigned long dest_page = dest & ~0xFFF; 7 | unsigned long bytes_rounded = ((dest + size + 0xFFF) & ~0xFFF) - dest_page; 8 | mprotect((void *)dest_page, bytes_rounded, protection); 9 | } 10 | 11 | Breakpoint::Breakpoint(address_t address) : address(address) { 12 | char *p = reinterpret_cast(address); 13 | 14 | aligned_mprotect(address, 1, PROT_READ | PROT_WRITE); 15 | originalData = *p; 16 | *p = 0xf4; 17 | aligned_mprotect(address, 1, PROT_READ | PROT_EXEC); 18 | } 19 | 20 | Breakpoint *BreakpointManager::set(address_t address) { 21 | std::cout << "SETTING BREAKPOINT at " << address << std::endl; 22 | Breakpoint *b = new Breakpoint(address); 23 | 24 | list.push_back(b); 25 | return b; 26 | } 27 | -------------------------------------------------------------------------------- /src/break/breakpoint.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_BREAK_BREAKPOINT_H 2 | #define EGALITO_BREAK_BREAKPOINT_H 3 | 4 | #include 5 | #include "types.h" 6 | 7 | class Breakpoint { 8 | private: 9 | address_t address; 10 | char originalData; 11 | public: 12 | Breakpoint(address_t address); 13 | }; 14 | 15 | class BreakpointManager { 16 | private: 17 | std::vector list; 18 | public: 19 | Breakpoint *set(address_t address); 20 | }; 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /src/break/signals.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "signals.h" 5 | 6 | static void sigsegv_handler(int sig, siginfo_t *info, void *context); 7 | 8 | void Signals::registerHandlers() { 9 | { 10 | struct sigaction act = {}; 11 | act.sa_sigaction = sigsegv_handler; 12 | sigemptyset(&act.sa_mask); 13 | act.sa_flags = SA_SIGINFO /*| SA_ONSTACK*/; 14 | 15 | sigaction(SIGSEGV, &act, nullptr); 16 | } 17 | } 18 | 19 | void sigsegv_handler(int sig, siginfo_t *info, void *context) { 20 | ucontext_t *uc = (ucontext_t *)context; 21 | #ifdef ARCH_X86_64 22 | unsigned long rip = uc->uc_mcontext.gregs[REG_RIP]; 23 | #elif defined(ARCH_AARCH64) 24 | unsigned long rip = uc->uc_mcontext.pc; 25 | #elif defined(ARCH_ARM) 26 | unsigned long rip = 0; 27 | #elif defined(ARCH_RISCV) 28 | unsigned long rip = 0; 29 | #endif 30 | std::printf("received SIGSEGV at 0x%lx\n", rip); 31 | std::exit(1); 32 | } 33 | -------------------------------------------------------------------------------- /src/break/signals.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_BREAK_SIGNALS_H 2 | #define EGALITO_BREAK_SIGNALS_H 3 | 4 | class Signals { 5 | public: 6 | static void registerHandlers(); 7 | }; 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /src/chunk/aliasmap.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_CHUNK_ALIAS_MAP_H 2 | #define EGALITO_CHUNK_ALIAS_MAP_H 3 | 4 | #include 5 | #include 6 | 7 | class Function; 8 | class Module; 9 | 10 | /** Allows functions to be looked up by their alias names. 11 | 12 | Note: a function's main name is not registered in this data structure. 13 | */ 14 | class FunctionAliasMap { 15 | private: 16 | std::map aliasMap; 17 | public: 18 | FunctionAliasMap(Module *module); 19 | 20 | Function *find(const std::string &alias); 21 | private: 22 | void maybeSpecialAlias(const char *alias, Function *func); 23 | }; 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /src/chunk/block.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_CHUNK_BLOCK_H 2 | #define EGALITO_CHUNK_BLOCK_H 3 | 4 | #include "chunk.h" 5 | #include "chunklist.h" 6 | #include "instr/instr.h" 7 | #include "archive/chunktypes.h" 8 | 9 | class Block : public ChunkSerializerImpl> { 11 | public: 12 | virtual std::string getName() const; 13 | 14 | virtual void serialize(ChunkSerializerOperations &op, 15 | ArchiveStreamWriter &writer); 16 | virtual bool deserialize(ChunkSerializerOperations &op, 17 | ArchiveStreamReader &reader); 18 | 19 | virtual void accept(ChunkVisitor *visitor); 20 | }; 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /src/chunk/cache.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_CHUNK_CACHE_H 2 | #define EGALITO_CHUNK_CACHE_H 3 | 4 | #include 5 | #include 6 | 7 | #include "instr/instr.h" 8 | 9 | class Chunk; 10 | 11 | class ChunkCache { 12 | private: 13 | address_t address; 14 | std::string data; 15 | std::vector fixups; 16 | public: 17 | ChunkCache(Chunk *chunk) { make(chunk); } 18 | void copyAndFix(char *output); 19 | private: 20 | void make(Chunk *chunk); 21 | }; 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /src/chunk/chunk.cpp: -------------------------------------------------------------------------------- 1 | #include "chunk.h" 2 | #include "chunk/position.h" 3 | #include "log/log.h" 4 | 5 | void ChunkImpl::setPosition(Position *newPosition) { 6 | throw "Operation not supported: ChunkImpl::setPosition" 7 | " (use ChunkSinglePositionDecorator)"; 8 | } 9 | 10 | void ChunkImpl::setSize(size_t newSize) { 11 | throw "Operation not supported: ChunkImpl::setSize"; 12 | } 13 | 14 | void ChunkImpl::addToSize(diff_t add) { 15 | throw "Operation not supported: ChunkImpl::addToSize"; 16 | } 17 | 18 | address_t ChunkImpl::getAddress() const { 19 | //return getPosition()->get(); 20 | return PositionManager::getAddress(this); 21 | } 22 | 23 | Range ChunkImpl::getRange() const { 24 | return std::move(Range(getAddress(), getSize())); 25 | } 26 | -------------------------------------------------------------------------------- /src/chunk/chunkfwd.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_CHUNK_CHUNKFWD_H 2 | #define EGALITO_CHUNK_CHUNKFWD_H 3 | 4 | class Program; 5 | class Module; 6 | class FunctionList; 7 | class PLTList; 8 | class JumpTableList; 9 | class DataRegionList; 10 | class VTableList; 11 | class InitFunctionList; 12 | class ExternalSymbolList; 13 | class LibraryList; 14 | class Function; 15 | class Block; 16 | class Instruction; 17 | class PLTTrampoline; 18 | class JumpTable; 19 | class JumpTableEntry; 20 | class DataRegion; 21 | class DataSection; 22 | class DataVariable; 23 | class GlobalVariable; 24 | class MarkerList; 25 | class Marker; 26 | class VTable; 27 | class VTableEntry; 28 | class InitFunction; 29 | class ExternalSymbol; 30 | class Library; 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /src/chunk/chunklist.cpp: -------------------------------------------------------------------------------- 1 | #include "chunklist.h" 2 | -------------------------------------------------------------------------------- /src/chunk/chunkref.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_CHUNK_CHUNKREF_H 2 | #define EGALITO_CHUNK_CHUNKREF_H 3 | 4 | class Chunk; // forward declaration 5 | 6 | typedef Chunk *ChunkRef; 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /src/chunk/concrete.cpp: -------------------------------------------------------------------------------- 1 | #include "concrete.h" 2 | -------------------------------------------------------------------------------- /src/chunk/concrete.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_CHUNK_CONCRETE_H 2 | #define EGALITO_CHUNK_CONCRETE_H 3 | 4 | #include "chunk.h" 5 | #include "chunklist.h" 6 | #include "chunkfwd.h" 7 | 8 | #include "program.h" 9 | 10 | #include "module.h" 11 | #include "library.h" 12 | 13 | #include "function.h" 14 | #include "block.h" 15 | 16 | #include "instr/instr.h" 17 | 18 | #include "plt.h" 19 | #include "jumptable.h" 20 | #include "dataregion.h" 21 | #include "gstable.h" 22 | 23 | #include "marker.h" 24 | #include "vtable.h" 25 | #include "initfunction.h" 26 | #include "ifunc.h" 27 | #include "external.h" 28 | 29 | #define INCLUDE_FROM_CONCRETE_H 30 | #include "chunkiter.h" 31 | #undef INCLUDE_FROM_CONCRETE_H 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /src/chunk/ifunc.cpp: -------------------------------------------------------------------------------- 1 | #include "ifunc.h" 2 | #include "cminus/print.h" 3 | 4 | extern IFuncList *egalito_ifuncList; 5 | 6 | extern "C" 7 | void ifunc_select(address_t address) { 8 | //egalito_printf("IFUNC: resolve %lx...\n", (uintptr_t)address); 9 | auto ifunc = egalito_ifuncList->getFor(address); 10 | //egalito_printf("IFUNC: resolver is %lx...\n", (uintptr_t)ifunc); 11 | auto funcaddr = reinterpret_cast(ifunc()); 12 | #if 0 13 | egalito_printf("IFUNC: resolver %lx for %lx selected %lx\n", 14 | (uintptr_t)ifunc, address, funcaddr); 15 | #endif 16 | *reinterpret_cast(address) = funcaddr; 17 | } 18 | 19 | void IFuncList::addIFuncFor(address_t address, Chunk *target) { 20 | auto ifuncEntry = new IFunc(target); 21 | getChildren()->add(ifuncEntry); 22 | map[address] = ifuncEntry; 23 | } 24 | 25 | auto IFuncList::getFor(address_t address) const -> IFuncType { 26 | auto it = map.find(address); 27 | if(it == map.end()) return nullptr; 28 | 29 | return reinterpret_cast(it->second->getAddress()); 30 | } 31 | 32 | -------------------------------------------------------------------------------- /src/chunk/ifunc.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_CHUNK_IFUNC_H 2 | #define EGALITO_CHUNK_IFUNC_H 3 | 4 | #include 5 | #include 6 | #include "chunk.h" 7 | #include "chunklist.h" 8 | #include "link.h" 9 | 10 | class IFunc : public ChunkImpl { 11 | private: 12 | Link *link; 13 | public: 14 | IFunc(Chunk *target) : link( 15 | new NormalLink(target, Link::SCOPE_EXTERNAL_CODE)) {} 16 | address_t getAddress() const { return link->getTargetAddress(); } 17 | Link *getLink() const { return link; } 18 | void setLink(Link *link) { this->link = link; } 19 | virtual void accept(ChunkVisitor *visitor) {} 20 | }; 21 | 22 | class IFuncList : public CollectionChunkImpl { 23 | public: 24 | using IFuncType = void *(*)(); 25 | private: 26 | std::map map; 27 | public: 28 | void addIFuncFor(address_t address, Chunk *target); 29 | IFuncType getFor(address_t address) const; 30 | virtual void accept(ChunkVisitor *visitor) {} 31 | }; 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /src/chunk/size.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "size.h" 3 | 4 | void ComputedSize::adjustBy(diff_t add) { 5 | assert(static_cast(size + add) >= 0); 6 | size += add; 7 | } 8 | -------------------------------------------------------------------------------- /src/chunk/size.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_CHUNK_SIZE_H 2 | #define EGALITO_CHUNK_SIZE_H 3 | 4 | #include "types.h" 5 | #include "util/range.h" 6 | 7 | class ComputedSize { 8 | private: 9 | size_t size; 10 | public: 11 | ComputedSize() : size(0) {} 12 | size_t get() const { return size; } 13 | void set(size_t newSize) { size = newSize; } 14 | void adjustBy(diff_t add); 15 | }; 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /src/cminus/print.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_CMINUS_PRINT_H 2 | #define EGALITO_CMINUS_PRINT_H 3 | 4 | #include 5 | #include 6 | 7 | #ifdef __cplusplus 8 | extern "C" { 9 | #endif 10 | 11 | #define NAME(x) egalito_ ## x 12 | #define egalito_stdout STDOUT_FILENO 13 | #define egalito_stderr STDERR_FILENO 14 | 15 | int NAME(printf) (const char *format, ...) 16 | #ifdef __GNUC__ 17 | __attribute__(( format(printf, 1, 2) )) 18 | #endif 19 | ; 20 | int NAME(fprintf) (int stream, const char *format, ...); 21 | int NAME(vfprintf) (int stream, const char *format, va_list args); 22 | 23 | int NAME(sprintf) (char *s, const char *format, ...) 24 | #ifdef __GNUC__ 25 | __attribute__(( format(printf, 2, 3) )) 26 | #endif 27 | ; 28 | int NAME(snprintf) (char *s, size_t size, const char *format, ...) 29 | #ifdef __GNUC__ 30 | __attribute__(( format(printf, 3, 4) )) 31 | #endif 32 | ; 33 | int NAME(vsnprintf) (char *s, size_t size, const char *format, va_list args); 34 | 35 | int NAME(puts) (const char *s); 36 | 37 | #ifdef __cplusplus 38 | } // extern "C" 39 | #endif 40 | 41 | #endif 42 | -------------------------------------------------------------------------------- /src/conductor/bridge.cpp: -------------------------------------------------------------------------------- 1 | #include "bridge.h" 2 | #include "log/log.h" 3 | 4 | LoaderBridge::LoaderBridge() { 5 | #define EGALITO_BRIDGE_ENTRY(type, name) \ 6 | valueMap[#name] = 0; 7 | #include "bridgeentries.h" 8 | #undef EGALITO_BRIDGE_ENTRY 9 | } 10 | 11 | LoaderBridge LoaderBridge::instance; 12 | 13 | bool LoaderBridge::containsName(const std::string &name) { 14 | return valueMap.find(name) != valueMap.end(); 15 | } 16 | 17 | void LoaderBridge::assignAddress(const std::string &name, address_t value) { 18 | if(valueMap.find(name) == valueMap.end()) { 19 | LOG(1, "ERROR: assigning value " << value << " to non-existent name \"" 20 | << name << "\" in LoaderBridge"); 21 | return; 22 | } 23 | valueMap[name] = value; 24 | } 25 | 26 | address_t LoaderBridge::getAddress(const std::string &name) { 27 | auto it = valueMap.find(name); 28 | 29 | if(it == valueMap.end()) { 30 | LOG(1, "ERROR: can't find \"" << name << "\" in LoaderBridge"); 31 | throw "unknown LoaderBridge entry"; 32 | } 33 | 34 | return (*it).second; 35 | } 36 | -------------------------------------------------------------------------------- /src/conductor/bridge.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_CONDUCTOR_BRIDGE_H 2 | #define EGALITO_CONDUCTOR_BRIDGE_H 3 | 4 | #include 5 | #include 6 | #include "types.h" 7 | 8 | #if 0 9 | enum BridgeEntryType { 10 | #define EGALITO_BRIDGE_ENTRY(type, name) \ 11 | BRIDGE_ ## name, 12 | #include "bridgeentries.h" 13 | #undef EGALITO_BRIDGE_ENTRY 14 | BRIDGES 15 | }; 16 | #endif 17 | 18 | class LoaderBridge { 19 | private: 20 | static LoaderBridge instance; 21 | LoaderBridge(); 22 | public: 23 | static LoaderBridge *getInstance() { return &instance; } 24 | private: 25 | std::map valueMap; 26 | public: 27 | bool containsName(const std::string &name); 28 | void assignAddress(const std::string &name, address_t value); 29 | address_t getAddress(const std::string &name); 30 | }; 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /src/conductor/bridgeentries.h: -------------------------------------------------------------------------------- 1 | // no include guards to allow reuse in different context 2 | 3 | #ifndef EGALITO_BRIDGE_ENTRY 4 | #error "Please define EGALITO_BRIDGE_ENTRY(type,name) before including bridgeentries.h" 5 | #endif 6 | 7 | #ifdef EGALITO_BRIDGE_FORWARD_DECLARE 8 | #include "types.h" 9 | class ConductorSetup; 10 | class Conductor; 11 | class Chunk; 12 | class IFuncList; 13 | #endif 14 | 15 | EGALITO_BRIDGE_ENTRY(address_t, egalito_entry) 16 | EGALITO_BRIDGE_ENTRY(const char *, egalito_initial_stack) 17 | EGALITO_BRIDGE_ENTRY(address_t, egalito_init_array) 18 | 19 | EGALITO_BRIDGE_ENTRY(ConductorSetup *, egalito_conductor_setup) 20 | EGALITO_BRIDGE_ENTRY(Conductor *, egalito_conductor) 21 | EGALITO_BRIDGE_ENTRY(Chunk *, egalito_gsCallback) 22 | EGALITO_BRIDGE_ENTRY(IFuncList *, egalito_ifuncList) 23 | EGALITO_BRIDGE_ENTRY(bool, egalito_init_done) 24 | EGALITO_BRIDGE_ENTRY(address_t, egalito_hook_function_entry_hook) 25 | EGALITO_BRIDGE_ENTRY(address_t, egalito_hook_function_exit_hook) 26 | EGALITO_BRIDGE_ENTRY(address_t, egalito_hook_instruction_hook) 27 | -------------------------------------------------------------------------------- /src/conductor/filesystem.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "filesystem.h" 4 | 5 | #include "log/log.h" 6 | 7 | ConductorFilesystem::ConductorFilesystem() { 8 | const char *csysroot = getenv("EGALITO_SYSROOT"); 9 | if(csysroot) sysroot = csysroot; 10 | } 11 | 12 | std::string ConductorFilesystem::transform(const std::string &path) { 13 | if(path.length() == 0) return ""; 14 | 15 | // only affect absolute paths for now 16 | if(path[0] == '/') return sysroot + path; 17 | // don't touch relative paths 18 | else return path; 19 | } 20 | 21 | std::string ConductorFilesystem::untransform(const std::string &path) { 22 | if(path.substr(0, sysroot.size()) == sysroot) return path.substr(sysroot.size()); 23 | else { 24 | LOG(1, "unsure how to untransform path [" << path << "]"); 25 | return path; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/conductor/filesystem.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_CONDUCTOR_FILESYSTEM_H 2 | #define EGALITO_CONDUCTOR_FILESYSTEM_H 3 | 4 | #include 5 | 6 | class ConductorFilesystem { 7 | private: 8 | std::string sysroot; 9 | 10 | ConductorFilesystem(); 11 | public: 12 | static ConductorFilesystem *getInstance() { 13 | static ConductorFilesystem instance; 14 | return &instance; 15 | } 16 | std::string transform(const std::string &path); 17 | std::string untransform(const std::string &path); 18 | }; 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /src/conductor/passes.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_CONDUCTOR_PASSES_H 2 | #define EGALITO_CONDUCTOR_PASSES_H 3 | 4 | #include "elf/elfspace.h" 5 | 6 | class Conductor; 7 | 8 | class ConductorPasses { 9 | private: 10 | Conductor *conductor; 11 | public: 12 | ConductorPasses(Conductor *conductor) : conductor(conductor) {} 13 | void newElfPasses(ElfSpace *space); 14 | void newArchivePasses(Program *program); 15 | void newExecutablePasses(Program *program); 16 | void newMirrorPasses(Program *program); 17 | void reloadedArchivePasses(Module *module); 18 | }; 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /src/config.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_CONFIG_H 2 | #define EGALITO_CONFIG_H 3 | #include "../config/config.h" 4 | 5 | #ifndef EGALITO_PATH 6 | // unless overridden here, will look for libegalito in the same 7 | // directory that the etshell/loader executable is run from 8 | //#define EGALITO_PATH "./libegalito.so" 9 | #endif 10 | 11 | // just to make the code compile 12 | #ifndef LINUX_KERNEL_BASE 13 | #define LINUX_KERNEL_BASE 0 14 | #endif 15 | #ifndef LINUX_KERNEL_CODE_BASE 16 | #define LINUX_KERNEL_CODE_BASE 0 17 | #endif 18 | #endif 19 | -------------------------------------------------------------------------------- /src/debug/disasm: -------------------------------------------------------------------------------- 1 | disasm=10 2 | -------------------------------------------------------------------------------- /src/debug/load: -------------------------------------------------------------------------------- 1 | load = 9 2 | -------------------------------------------------------------------------------- /src/debug/quiet: -------------------------------------------------------------------------------- 1 | !analysis 2 | !break 3 | !chunk 4 | !conductor 5 | !disasm 6 | !elf 7 | !generate 8 | !instr 9 | !load 10 | !log 11 | !main 12 | !operation 13 | !pass 14 | !transform 15 | 16 | !dsymbol 17 | !dreloc 18 | !djumptable 19 | !dplt 20 | !dloadtime 21 | !dassign 22 | -------------------------------------------------------------------------------- /src/disasm/aarch64-regbits.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_AARCH64_REGBITS_H 2 | #define EGALITO_AARCH64_REGBITS_H 3 | 4 | #include 5 | #include 6 | #include "instr/register.h" 7 | 8 | #if defined(ARCH_AARCH64) || defined(ARCH_ARM) 9 | class AARCH64RegBits { 10 | private: 11 | uint32_t bin; 12 | const uint32_t regMask; 13 | bool cached; 14 | 15 | typedef std::vector RegPositions; 16 | typedef std::pair RegPositionsList; 17 | RegPositionsList list; 18 | 19 | public: 20 | AARCH64RegBits() : regMask(0x1F), cached(false) {} 21 | void decode(const char *bytes); 22 | void encode(char *bytes); 23 | bool isReading(PhysicalRegister ®); 24 | bool isWriting(PhysicalRegister ®); 25 | void replaceRegister(PhysicalRegister& oldReg, 26 | PhysicalRegister& newReg); 27 | 28 | private: 29 | RegPositionsList getRegPositionList(); 30 | void makeDPImm_RegPositionList(); 31 | void makeBranch_RegPositionList(); 32 | void makeLDST_RegPositionList(); 33 | void makeDPIReg_RegPositionList(); 34 | 35 | void invalidateCache(); 36 | }; 37 | #endif 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /src/disasm/formatter.cpp: -------------------------------------------------------------------------------- 1 | #include "disasm/formatter.h" 2 | 3 | size_t findHash(const string &str) { 4 | size_t startPos = 0; 5 | while (true) { 6 | size_t pos = str.find('#', startPos); 7 | if (pos == string::npos) 8 | return string::npos; 9 | if (pos == str.length() - 1) 10 | return string::npos; 11 | if (str[pos + 1] == '#') 12 | startPos = pos + 2; 13 | if (str[pos + 1] != 'x' && str[pos + 1] != 'd' && str[pos + 1] != 's') 14 | startPos = pos + 2; 15 | else 16 | return pos; 17 | } 18 | } 19 | 20 | template <> 21 | inline string replaceOne(const string &str, const char *t) { 22 | size_t pos = findHash(str); 23 | if (str[pos + 1] == 's') { 24 | string ret = str; 25 | ret.replace(pos, 2, t); 26 | return ret; 27 | } 28 | 29 | return str; 30 | } 31 | -------------------------------------------------------------------------------- /src/disasm/formatter.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_DISASM_FORMATTER_H 2 | #define EGALITO_DISASM_FORMATTER_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | using namespace std; 9 | 10 | size_t findHash(const string &str); 11 | 12 | template inline string toHexString(T t) { 13 | static_assert(std::is_integral::value, "Integral required."); 14 | stringstream sstream; 15 | sstream << hex << t; 16 | return "0x" + sstream.str(); 17 | } 18 | 19 | template string replaceOne(const string &str, T t) { 20 | size_t pos = findHash(str); 21 | if (pos == string::npos) { 22 | assert(!"expecting #d or #x, found end of string."); 23 | abort(); 24 | } 25 | 26 | string ret = str; 27 | if (str[pos + 1] == 'x') { 28 | ret.replace(pos, 2, toHexString(t)); 29 | } else { 30 | ret.replace(pos, 2, to_string(t)); 31 | } 32 | 33 | return ret; 34 | } 35 | 36 | template inline string stringFormat(const string &str, T t) { 37 | return replaceOne(str, t); 38 | } 39 | 40 | template 41 | inline string stringFormat(const string &str, T t, Args... args) { 42 | return stringFormat(replaceOne(str, t), args...); 43 | } 44 | 45 | #endif 46 | -------------------------------------------------------------------------------- /src/disasm/handle.cpp: -------------------------------------------------------------------------------- 1 | #include "handle.h" 2 | 3 | bool DisasmHandle::initialized[2] = {false, false}; 4 | csh DisasmHandle::handle[2]; 5 | 6 | DisasmHandle::DisasmHandle(bool detailed) { 7 | this->which = detailed ? 1 : 0; 8 | csh *h = &handle[which]; 9 | if(!initialized[which]) { 10 | #ifdef ARCH_X86_64 11 | if(cs_open(CS_ARCH_X86, CS_MODE_64, h) != CS_ERR_OK) { 12 | throw "Can't initialize capstone handle!"; 13 | } 14 | #elif defined(ARCH_AARCH64) 15 | if(cs_open(CS_ARCH_ARM64, CS_MODE_LITTLE_ENDIAN, h) != CS_ERR_OK) { 16 | throw "Can't initialize capstone handle!"; 17 | } 18 | #elif defined(ARCH_ARM) 19 | if(cs_open(CS_ARCH_ARM, CS_MODE_ARM, h) != CS_ERR_OK) { 20 | throw "Can't initialize capstone handle!"; 21 | } 22 | #endif 23 | 24 | cs_option(*h, CS_OPT_SYNTAX, CS_OPT_SYNTAX_ATT); // AT&T syntax 25 | if(detailed) { 26 | cs_option(*h, CS_OPT_DETAIL, CS_OPT_ON); 27 | } 28 | 29 | initialized[which] = true; 30 | } 31 | } 32 | 33 | DisasmHandle::~DisasmHandle() { 34 | //cs_close(&handle); 35 | } 36 | 37 | -------------------------------------------------------------------------------- /src/disasm/handle.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_DISASM_HANDLE_H 2 | #define EGALITO_DISASM_HANDLE_H 3 | 4 | #include 5 | 6 | class DisasmHandle { 7 | private: 8 | static bool initialized[2]; 9 | static csh handle[2]; 10 | int which; 11 | public: 12 | DisasmHandle(bool detailed = false); 13 | ~DisasmHandle(); 14 | 15 | csh &raw() { return handle[which]; } 16 | }; 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /src/disasm/makesemantic.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_DISASM_MAKE_SEMANTIC_H 2 | #define EGALITO_DISASM_MAKE_SEMANTIC_H 3 | 4 | #include 5 | #include "riscv-disas.h" 6 | 7 | class Instruction; 8 | class InstructionSemantic; 9 | class Assembly; 10 | 11 | class MakeSemantic { 12 | public: 13 | static InstructionSemantic *makeNormalSemantic( 14 | Instruction *instruction, cs_insn *ins); 15 | #ifdef ARCH_RISCV 16 | static InstructionSemantic *makeNormalSemantic( 17 | Instruction *instruction, rv_instr *ins); 18 | #endif 19 | 20 | static bool isRIPRelative(Assembly *assembly, int opIndex); 21 | static int determineDisplacementSize(Assembly *assembly, int opIndex); 22 | static int getDispOffset(Assembly *assembly, int opIndex); 23 | static int getOpIndex(Assembly *assembly, size_t offset); 24 | }; 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /src/disasm/objectoriented.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_DISASM_OBJECT_ORIENTED_H 2 | #define EGALITO_DISASM_OBJECT_ORIENTED_H 3 | 4 | #include "elf/elfmap.h" 5 | #include "elf/symbol.h" 6 | #include "elf/reloc.h" 7 | #include "chunk/vtable.h" 8 | 9 | class Module; 10 | class Program; 11 | 12 | class DisassembleVTables { 13 | public: 14 | VTableList *makeVTableList(ElfMap *elfMap, SymbolList *symbolList, 15 | RelocList *relocList, Module *module, Program *program); 16 | private: 17 | VTable *makeVTable(ElfMap *elfMap, SymbolList *symbolList, 18 | RelocList *relocList, Module *module, Program *program, 19 | Symbol *vtableSymbol, Symbol *typeinfoSymbol, Symbol *stringSymbol); 20 | }; 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /src/dwarf/parser.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_DWARF_PARSER_H 2 | #define EGALITO_DWARF_PARSER_H 3 | 4 | #include 5 | #include 6 | #include "cursor.h" 7 | #include "defines.h" 8 | 9 | class ElfMap; 10 | 11 | class DwarfCIE; 12 | class DwarfFDE; 13 | class DwarfUnwindInfo; 14 | class DwarfState; 15 | 16 | /** Parses DWARF information from a .eh_frame section. 17 | 18 | Note: if debugging info is enabled, this class prints out DWARF 19 | information in the same format as `objdump -g`. 20 | */ 21 | class DwarfParser { 22 | private: 23 | DwarfUnwindInfo *info; 24 | address_t readAddress; 25 | address_t virtualAddress; 26 | public: 27 | DwarfParser(ElfMap *elfMap); 28 | 29 | DwarfUnwindInfo *getUnwindInfo() const { return info; } 30 | private: 31 | void parse(size_t virtualSize); 32 | DwarfCIE *parseCIE(DwarfCursor start, DwarfCursor end, uint64_t length, 33 | uint64_t index); 34 | DwarfFDE *parseFDE(DwarfCursor start, DwarfCursor end, uint64_t length, 35 | size_t cieIndex, uint32_t entryID); 36 | }; 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /src/dwarf/platform.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_DWARF_PLATFORM_H 2 | #define EGALITO_DWARF_PLATFORM_H 3 | 4 | #include 5 | 6 | std::string getRegisterName(unsigned int reg); 7 | const char *shortRegisterName(unsigned int reg); 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /src/dwarf/state.cpp: -------------------------------------------------------------------------------- 1 | #include "state.h" 2 | 3 | DwarfState::DwarfState() : next(nullptr), cfaRegister(0), cfaOffset(0), 4 | cfaExpression(0), cfaExpressionLength(0) { 5 | 6 | } 7 | 8 | DwarfState::DwarfState(const DwarfState &other) 9 | : registers(other.registers), next(other.next), 10 | cfaRegister(other.cfaRegister), cfaOffset(other.cfaOffset), 11 | cfaExpression(other.cfaExpression), 12 | cfaExpressionLength(other.cfaExpressionLength) { 13 | 14 | } 15 | -------------------------------------------------------------------------------- /src/elf/auxv.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_ELF_AUXV_H 2 | #define EGALITO_ELF_AUXV_H 3 | 4 | #include "types.h" 5 | #include "elf/elfmap.h" 6 | 7 | void adjustAuxiliaryVector(char **argv, ElfMap *elf, ElfMap *interpreter); 8 | int removeLoaderFromArgv(void *argv); 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /src/elf/riscv-elf.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_ELF_RISCV_ELF_H 2 | #define EGALITO_ELF_RISCV_ELF_H 3 | 4 | /* Mainline glibc doesn't have the RISC-V relocation information yet, so if 5 | it's not present, define it. */ 6 | 7 | #if defined(ARCH_RISCV) && !defined(R_RISCV_NONE) 8 | 9 | /* RISC-V relocations. */ 10 | #define R_RISCV_NONE 0 11 | #define R_RISCV_32 1 12 | #define R_RISCV_64 2 13 | #define R_RISCV_RELATIVE 3 14 | #define R_RISCV_COPY 4 15 | #define R_RISCV_JUMP_SLOT 5 16 | #define R_RISCV_TLS_DTPMOD32 6 17 | #define R_RISCV_TLS_DTPMOD64 7 18 | #define R_RISCV_TLS_DTPREL32 8 19 | #define R_RISCV_TLS_DTPREL64 9 20 | #define R_RISCV_TLS_TPREL32 10 21 | #define R_RISCV_TLS_TPREL64 11 22 | 23 | #endif 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /src/elf/sharedlib.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_ELF_SHAREDLIB_H 2 | #define EGALITO_ELF_SHAREDLIB_H 3 | 4 | 5 | #endif 6 | -------------------------------------------------------------------------------- /src/elf/unionfind.cpp: -------------------------------------------------------------------------------- 1 | #include "unionfind.h" 2 | 3 | UnionFind::UnionFind(size_t count) { 4 | for(size_t i = 0; i < count; i++) { 5 | parent.push_back(i); 6 | } 7 | } 8 | 9 | void UnionFind::join(size_t x1, size_t x2) { 10 | auto p1 = find(x1); 11 | auto p2 = find(x2); 12 | setEdge(p1, p2); 13 | } 14 | 15 | size_t UnionFind::find(size_t x) { 16 | while(parent[x] != x) { x = parent[x]; } 17 | parent[x] = x; // path compression 18 | return x; 19 | } 20 | 21 | void UnionFind::setEdge(size_t x1, size_t x2) { 22 | if(x1 < x2) parent[x2] = x1; 23 | if(x1 > x2) parent[x1] = x2; 24 | } 25 | 26 | -------------------------------------------------------------------------------- /src/elf/unionfind.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_ELF_UNIONFIND_H 2 | #define EGALITO_ELF_UNIONFIND_H 3 | 4 | #include 5 | #include 6 | 7 | class UnionFind { 8 | protected: 9 | std::vector parent; 10 | 11 | public: 12 | UnionFind(size_t count); 13 | virtual ~UnionFind() {} 14 | 15 | void join(size_t x1, size_t x2); 16 | size_t find(size_t x); 17 | 18 | private: 19 | virtual void setEdge(size_t x1, size_t x2); 20 | }; 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /src/generate/anygen.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_GENERATE_ANYGEN_H 2 | #define EGALITO_GENERATE_ANYGEN_H 3 | 4 | #include 5 | #include "types.h" 6 | #include "section.h" 7 | #include "sectionlist.h" 8 | 9 | class Module; 10 | class Function; 11 | class MemoryBufferBacking; 12 | 13 | class AnyGen { 14 | private: 15 | Module *module; 16 | MemoryBufferBacking *backing; 17 | SectionList sectionList; 18 | public: 19 | AnyGen(Module *module, MemoryBufferBacking *backing); 20 | 21 | void generate(const std::string &filename); 22 | private: 23 | void makeHeader(); 24 | void makeSymtabSection(); 25 | void makeSectionSymbols(); 26 | void makeShdrTable(); 27 | void makePhdrTable(); 28 | private: 29 | void updateOffsets(); 30 | void serialize(const std::string &filename); 31 | private: 32 | size_t shdrIndexOf(Section *section); 33 | size_t shdrIndexOf(const std::string &name); 34 | }; 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /src/generate/basegen.cpp: -------------------------------------------------------------------------------- 1 | #include "basegen.h" 2 | 3 | ElfGeneratorImpl::ElfGeneratorImpl(Program *program, SandboxBacking *backing) 4 | : data(new ElfDataImpl(program, backing)) { 5 | 6 | } 7 | -------------------------------------------------------------------------------- /src/generate/basegen.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_GENERATE_BASEGEN_H 2 | #define EGALITO_GENERATE_BASEGEN_H 3 | 4 | #include 5 | #include "data.h" 6 | 7 | class ElfGeneratorBase { 8 | public: 9 | virtual ~ElfGeneratorBase() {} 10 | 11 | /** Run before any generate-specific code. */ 12 | virtual void preCodeGeneration() = 0; 13 | 14 | /** Run after addresses are assigned to functions, but before their 15 | code is generated. Function sizes are fixed at this point. 16 | */ 17 | virtual void afterAddressAssign() = 0; 18 | 19 | /** Run after functions and data have been copied into memory. 20 | */ 21 | virtual void generateContent(const std::string &filename) = 0; 22 | }; 23 | 24 | class ElfGeneratorImpl : public ElfGeneratorBase { 25 | private: 26 | ElfData *data; 27 | ElfConfig config; 28 | public: 29 | ElfGeneratorImpl(Program *program, SandboxBacking *backing); 30 | 31 | ElfData *getData() { return data; } 32 | ElfConfig *getConfig() { return &config; } 33 | }; 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /src/generate/debugelf.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_INTROSPECT_GENELF_H 2 | #define EGALITO_INTROSPECT_GENELF_H 3 | 4 | #include 5 | #include 6 | #include "elf/elfxx.h" 7 | 8 | class Function; 9 | 10 | /** Ported from Shuffler. Originally written by Kent. 11 | 12 | This code is designed to only use system calls directly with no 13 | external dependencies. 14 | */ 15 | class DebugElf { 16 | private: 17 | ElfXX_Sym *symbols; 18 | size_t symbols_size, symbols_used; 19 | char *strtable; 20 | size_t strtable_size, strtable_used; 21 | unsigned long start, end; 22 | public: 23 | DebugElf(); 24 | ~DebugElf(); 25 | 26 | void writeTo(int fd); 27 | void writeTo(const char *filename); 28 | 29 | void add(unsigned long address, unsigned long size, const char *name); 30 | void add(Function *func, const char *suffix); 31 | }; 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /src/generate/deferred.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include // for strlen 3 | #include "deferred.h" 4 | #include "log/log.h" 5 | 6 | std::ostream &operator << (std::ostream &stream, DeferredValue &dv) { 7 | dv.writeTo(stream); 8 | return stream; 9 | } 10 | 11 | void DeferredValueCString::writeTo(std::ostream &stream) { 12 | LOG0(10, "writing " << getSize() << " bytes:"); 13 | for(size_t i = 0; i < getSize(); i ++) { 14 | CLOG0(10, " %02x", int(getPtr()[i]) & 0xff); 15 | } 16 | LOG(10, ""); 17 | stream.write(getPtr(), getSize()); 18 | } 19 | 20 | size_t DeferredStringList::add(const std::string &data, bool withNull) { 21 | size_t oldIndex = output.length(); 22 | size_t len = data.length(); 23 | if(withNull) len ++; 24 | output.append(data.c_str(), len); 25 | return oldIndex; 26 | } 27 | 28 | size_t DeferredStringList::add(const char *str, bool withNull) { 29 | size_t oldIndex = output.length(); 30 | size_t len = std::strlen(str); 31 | if(withNull) len ++; 32 | output.append(str, len); 33 | return oldIndex; 34 | } 35 | -------------------------------------------------------------------------------- /src/generate/integerdeferred.cpp: -------------------------------------------------------------------------------- 1 | #include "integerdeferred.h" 2 | 3 | void DeferredIntegerList::add(uint32_t value) { 4 | std::string str{reinterpret_cast(&value), sizeof(value)}; 5 | stream << str; 6 | } 7 | 8 | void DeferredIntegerList::add(uint64_t value) { 9 | std::string str{reinterpret_cast(&value), sizeof(value)}; 10 | stream << str; 11 | } 12 | 13 | size_t DeferredIntegerList::getSize() const { 14 | auto data = this->stream.str(); 15 | return data.length(); 16 | } 17 | 18 | void DeferredIntegerList::writeTo(std::ostream &stream) { 19 | auto data = this->stream.str(); 20 | stream << data; 21 | } 22 | -------------------------------------------------------------------------------- /src/generate/integerdeferred.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_GENERATE_INTEGER_DEFERRED_H 2 | #define EGALITO_GENERATE_INTEGER_DEFERRED_H 3 | 4 | #include 5 | #include "deferred.h" 6 | 7 | class DeferredIntegerList : public DeferredValue { 8 | private: 9 | std::ostringstream stream; 10 | public: 11 | void add(uint32_t value); 12 | void add(uint64_t value); 13 | virtual size_t getSize() const; 14 | virtual void writeTo(std::ostream &stream); 15 | }; 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /src/generate/kernelgen.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_GENERATE_KERNELGEN_H 2 | #define EGALITO_GENERATE_KERNELGEN_H 3 | 4 | #include "basegen.h" 5 | 6 | class KernelGen : public ElfGeneratorImpl { 7 | public: 8 | KernelGen(Program *program, SandboxBacking *backing); 9 | 10 | virtual void preCodeGeneration(); 11 | virtual void afterAddressAssign(); 12 | virtual void generateContent(const std::string &filename); 13 | }; 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /src/generate/mirrorgen.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_GENERATE_MIRRORGEN_H 2 | #define EGALITO_GENERATE_MIRRORGEN_H 3 | 4 | #include "basegen.h" 5 | 6 | class MakeGlobalPLT; 7 | class MirrorGen : public ElfGeneratorImpl { 8 | public: 9 | MirrorGen(Program *program, SandboxBacking *backing); 10 | 11 | virtual void preCodeGeneration(); 12 | virtual void afterAddressAssign(); 13 | virtual void generateContent(const std::string &filename); 14 | }; 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /src/generate/objgen.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_ELF_OBJGEN_H 2 | #define EGALITO_ELF_OBJGEN_H 3 | 4 | #include "transform/sandbox.h" 5 | #include "elf/elfspace.h" 6 | #include "section.h" 7 | #include "sectionlist.h" 8 | 9 | class ObjGen { 10 | private: 11 | ElfSpace *elfSpace; 12 | MemoryBacking *backing; 13 | std::string filename; 14 | SectionList sectionList; 15 | int sectionSymbolCount; 16 | public: 17 | ObjGen(ElfSpace *elfSpace, MemoryBacking *backing, std::string filename); 18 | public: 19 | void generate(); 20 | private: 21 | void makeHeader(); 22 | void makeSymbolInfo(); 23 | void makeRelocInfo(const std::string &textSection); 24 | void makeText(); 25 | void makeSymbolsAndRelocs(address_t begin, size_t size, 26 | const std::string &textSection); 27 | void makeSymbolInText(Function *func, const std::string &textSection); 28 | void makeRelocInText(Function *func, const std::string &textSection); 29 | void makeRoData(); 30 | void makeShdrTable(); 31 | private: 32 | void updateSymbolTable(); 33 | void updateOffsets(); 34 | void serialize(); 35 | private: 36 | static bool blacklistedSymbol(const std::string &name); 37 | }; 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /src/generate/section.cpp: -------------------------------------------------------------------------------- 1 | #include // for memset 2 | #include "section.h" 3 | #include "sectionlist.h" 4 | #include "elf/symbol.h" 5 | #include "elf/elfxx.h" 6 | #include "chunk/concrete.h" // for Function 7 | #include "log/log.h" 8 | 9 | SectionHeader::SectionHeader(Section *outer, ElfXX_Word type, 10 | ElfXX_Xword flags) : outer(outer), address(0), 11 | shdrType(type), shdrFlags(flags), sectionLink(nullptr) { 12 | 13 | } 14 | 15 | Section::Section(const std::string &name, ElfXX_Word type, 16 | ElfXX_Xword flags) : name(name), offset(0), content(nullptr) { 17 | 18 | header = new SectionHeader(this, type, flags); 19 | } 20 | 21 | Section::Section(const std::string &name, DeferredValue *content) 22 | : name(name), offset(0), header(nullptr), content(content) { 23 | } 24 | 25 | std::ostream &operator << (std::ostream &stream, Section &rhs) { 26 | if(rhs.hasContent()) { 27 | rhs.getContent()->writeTo(stream); 28 | } 29 | return stream; 30 | } 31 | -------------------------------------------------------------------------------- /src/generate/uniongen.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_GENERATE_UNIONGEN_H 2 | #define EGALITO_GENERATE_UNIONGEN_H 3 | 4 | #include "basegen.h" 5 | 6 | class MakeGlobalPLT; 7 | class UnionGen : public ElfGeneratorImpl { 8 | public: 9 | UnionGen(Program *program, SandboxBacking *backing); 10 | 11 | virtual void preCodeGeneration(); 12 | virtual void afterAddressAssign(); 13 | virtual void generateContent(const std::string &filename); 14 | }; 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /src/instr/concrete.cpp: -------------------------------------------------------------------------------- 1 | #include "concrete.h" 2 | -------------------------------------------------------------------------------- /src/instr/instr.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_INSTR_INSTR_H 2 | #define EGALITO_INSTR_INSTR_H 3 | 4 | #include "chunk/chunk.h" 5 | #include "archive/chunktypes.h" 6 | #include "types.h" 7 | 8 | class InstructionSemantic; 9 | class SemanticVisitor; 10 | class ChunkVisitor; 11 | 12 | class Instruction : public ChunkSerializerImpl { 14 | private: 15 | InstructionSemantic *semantic; 16 | public: 17 | Instruction(InstructionSemantic *semantic = nullptr) 18 | : semantic(semantic) {} 19 | 20 | virtual std::string getName() const; 21 | 22 | InstructionSemantic *getSemantic() const { return semantic; } 23 | void setSemantic(InstructionSemantic *semantic) 24 | { this->semantic = semantic; } 25 | 26 | virtual size_t getSize() const; 27 | 28 | virtual void serialize(ChunkSerializerOperations &op, 29 | ArchiveStreamWriter &writer); 30 | virtual bool deserialize(ChunkSerializerOperations &op, 31 | ArchiveStreamReader &reader); 32 | 33 | virtual void accept(ChunkVisitor *visitor); 34 | }; 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /src/instr/isolated.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_INSTR_ISOLATED_H 2 | #define EGALITO_INSTR_ISOLATED_H 3 | 4 | // no-op 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /src/instr/linked.h: -------------------------------------------------------------------------------- 1 | #ifdef ARCH_X86_64 2 | #include "instr/linked-x86_64.h" 3 | #elif defined(ARCH_AARCH64) 4 | #include "instr/linked-aarch64.h" 5 | #elif defined(ARCH_RISCV) 6 | #include "instr/linked-riscv.h" 7 | #else 8 | #error "No linked instructions header for current arch!" 9 | #endif 10 | -------------------------------------------------------------------------------- /src/instr/memory.cpp: -------------------------------------------------------------------------------- 1 | #include "memory.h" 2 | -------------------------------------------------------------------------------- /src/instr/memory.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_INSTR_MEMORY_H 2 | #define EGALITO_INSTR_MEMORY_H 3 | #include "register.h" 4 | 5 | class Memory { 6 | private: 7 | Register base; 8 | Register index; 9 | unsigned long displacement; 10 | public: 11 | Memory(Register base, Register index, unsigned long displacement) 12 | : base(base), index(index), displacement(displacement) {} 13 | Register getBase() const { return base; } 14 | Register getIndex() const { return index; } 15 | unsigned long getDisplacement() const { return displacement; } 16 | }; 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /src/instr/semantic.cpp: -------------------------------------------------------------------------------- 1 | #include "semantic.h" 2 | #include "assembly.h" 3 | 4 | -------------------------------------------------------------------------------- /src/instr/serializer.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_INSTR_SERIALIZER_H 2 | #define EGALITO_INSTR_SERIALIZER_H 3 | 4 | #include "semantic.h" 5 | #include "archive/stream.h" 6 | 7 | class Chunk; 8 | class Instruction; 9 | class ChunkSerializerOperations; 10 | 11 | class InstrSerializer { 12 | private: 13 | ChunkSerializerOperations &op; 14 | public: 15 | InstrSerializer(ChunkSerializerOperations &op) : op(op) {} 16 | 17 | void serialize(InstructionSemantic *semantic, 18 | ArchiveStreamWriter &writer); 19 | InstructionSemantic *deserialize(Instruction *instruction, 20 | address_t address, ArchiveStreamReader &reader); 21 | private: 22 | InstructionSemantic *defaultDeserialize(Instruction *instruction, 23 | address_t address, ArchiveStreamReader &reader); 24 | }; 25 | 26 | class LinkSerializer { 27 | private: 28 | ChunkSerializerOperations &op; 29 | public: 30 | LinkSerializer(ChunkSerializerOperations &op) : op(op) {} 31 | 32 | void serialize(Link *link, ArchiveStreamWriter &writer); 33 | Link *deserialize(ArchiveStreamReader &reader); 34 | private: 35 | Chunk *deserializeLinkTarget(ArchiveStreamReader &reader); 36 | }; 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /src/instr/storage.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_INSTR_STORAGE_H 2 | #define EGALITO_INSTR_STORAGE_H 3 | 4 | #include 5 | #include 6 | #include "assembly.h" 7 | 8 | class InstructionStorage { 9 | private: 10 | std::string rawData; 11 | std::weak_ptr assembly; 12 | public: 13 | const std::string &getData() const; 14 | size_t getSize() const; 15 | 16 | AssemblyPtr getAssembly(address_t address); 17 | 18 | void setData(const std::string &data) { this->rawData = data; } 19 | void setAssembly(AssemblyPtr assembly); 20 | void clearAssembly() { assembly.reset(); } 21 | }; 22 | 23 | class AssemblyFactory { 24 | private: 25 | static AssemblyFactory instance; 26 | public: 27 | static AssemblyFactory *getInstance() { return &instance; } 28 | private: 29 | std::vector assemblyList; 30 | public: 31 | AssemblyPtr buildAssembly(InstructionStorage *storage, address_t address); 32 | void registerAssembly(AssemblyPtr assembly); 33 | void clearCache(); 34 | }; 35 | 36 | #endif 37 | -------------------------------------------------------------------------------- /src/instr/visitor.cpp: -------------------------------------------------------------------------------- 1 | #include "visitor.h" 2 | #include "concrete.h" 3 | 4 | void InstructionVisitor::visit(ReturnInstruction *retInstr) { 5 | visit(static_cast(retInstr)); 6 | } 7 | 8 | void InstructionVisitor::visit(IndirectJumpInstruction *indirect) { 9 | visit(static_cast(indirect)); 10 | } 11 | 12 | void InstructionVisitor::visit(IndirectCallInstruction *indirect) { 13 | visit(static_cast(indirect)); 14 | } 15 | -------------------------------------------------------------------------------- /src/load/bootstrap-arm.s: -------------------------------------------------------------------------------- 1 | .global entry 2 | .global initial_stack 3 | .global _start2 4 | 5 | .section .bss 6 | .align 8 7 | initial_stack: 8 | .skip 8 9 | entry: 10 | .skip 8 11 | 12 | .text 13 | .globl _start 14 | .type _start,#function 15 | _start: 16 | 17 | _start2: 18 | -------------------------------------------------------------------------------- /src/load/callinit.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_LOAD_CALL_INIT_H 2 | #define EGALITO_LOAD_CALL_INIT_H 3 | 4 | class Program; 5 | class GSTable; 6 | class Conductor; 7 | 8 | class CallInit { 9 | private: 10 | using Start2Type = void (*)(); 11 | public: 12 | static void makeInitArray(Program *program, int argc, char **argv, 13 | char **envp, GSTable *gsTable); 14 | static Start2Type getStart2(Conductor *conductor); 15 | }; 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /src/load/datastruct.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_LOAD_DATA_STRUCT_H 2 | #define EGALITO_LOAD_DATA_STRUCT_H 3 | 4 | #include 5 | #include 6 | #include "types.h" 7 | 8 | class ConductorSetup; 9 | class VTableList; 10 | class VTable; 11 | 12 | class DataStructMigrator { 13 | private: 14 | std::vector> fixupList; 15 | public: 16 | void migrate(ConductorSetup *setup); 17 | private: 18 | void migrateList(VTableList *loaderVTableList, VTableList *sourceList); 19 | void migrateTable(VTable *loaderVTableList, VTable *egalitoVTable); 20 | void commit(); 21 | }; 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /src/load/emulator.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_LOAD_EMULATOR_H 2 | #define EGALITO_LOAD_EMULATOR_H 3 | 4 | #include 5 | #include 6 | #include "types.h" 7 | 8 | class Conductor; 9 | class Module; 10 | class Function; 11 | class Link; 12 | class DataVariable; 13 | 14 | /** Emulate functionality provided by ld.so. */ 15 | class LoaderEmulator { 16 | private: 17 | Module *egalito; 18 | static LoaderEmulator instance; 19 | public: 20 | static LoaderEmulator &getInstance() { return instance; } 21 | private: 22 | std::map functionMap; 23 | std::map dataMap; 24 | public: 25 | void setup(Conductor *conductor); 26 | void setupForExecutableGen(Conductor *conductor); 27 | 28 | void setStackLinks(char **argv, char **envp); 29 | void initRT(Conductor *conductor); 30 | 31 | Function *findFunction(const std::string &symbol); 32 | Link *makeDataLink(const std::string &symbol, bool afterMapping); 33 | private: 34 | LoaderEmulator() : egalito(nullptr) {} 35 | 36 | DataVariable *findEgalitoDataVariable(const char *name); 37 | 38 | void addFunction(const std::string &symbol, Function *function); 39 | void addData(const std::string &symbol, address_t address); 40 | }; 41 | 42 | #endif 43 | -------------------------------------------------------------------------------- /src/load/loader.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_LOAD_LOADER_H 2 | #define EGALITO_LOAD_LOADER_H 3 | 4 | #include "conductor/setup.h" 5 | 6 | class EgalitoLoader { 7 | private: 8 | ConductorSetup *setup; 9 | Sandbox *sandbox; 10 | int argc; 11 | char **argv; 12 | char **envp; 13 | bool fromArchive; 14 | public: 15 | EgalitoLoader(); 16 | bool parse(const char *filename); 17 | 18 | /* these must be called in this order */ 19 | void setupEnvironment(int argc, char *argv[]); 20 | void generateCode(); 21 | void run(); 22 | private: 23 | void otherPasses(); 24 | void otherPassesAfterMove(); 25 | }; 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /src/load/makebridge.cpp: -------------------------------------------------------------------------------- 1 | #include "makebridge.h" 2 | #include "conductor/bridge.h" 3 | 4 | #define EGALITO_BRIDGE_FORWARD_DECLARE 5 | #define EGALITO_BRIDGE_ENTRY(type, name) \ 6 | extern type name; 7 | #include "conductor/bridgeentries.h" 8 | #undef EGALITO_BRIDGE_ENTRY 9 | #undef EGALITO_BRIDGE_FORWARD_DECLARE 10 | 11 | void MakeLoaderBridge::make() { 12 | LoaderBridge *bridge = LoaderBridge::getInstance(); 13 | 14 | #define EGALITO_BRIDGE_ENTRY(type, name) \ 15 | bridge->assignAddress(#name, reinterpret_cast(&name)); 16 | #include "conductor/bridgeentries.h" 17 | #undef EGALITO_BRIDGE_ENTRY 18 | } 19 | -------------------------------------------------------------------------------- /src/load/makebridge.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_LOAD_MAKE_BRIDGE_H 2 | #define EGALITO_LOAD_MAKE_BRIDGE_H 3 | 4 | class MakeLoaderBridge { 5 | public: 6 | static void make(); 7 | }; 8 | 9 | #endif 10 | -------------------------------------------------------------------------------- /src/load/preparetls.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_LOAD_PREPARE_TLS_H 2 | #define EGALITO_LOAD_PREPARE_TLS_H 3 | 4 | class Conductor; 5 | 6 | class PrepareTLS { 7 | public: 8 | static void prepare(Conductor *conductor); 9 | }; 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /src/load/segmap.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_LOAD_SEGMAP_H 2 | #define EGALITO_LOAD_SEGMAP_H 3 | 4 | #include // for Elf64_Phdr 5 | #include "elf/elfmap.h" 6 | #include "types.h" 7 | 8 | class ConductorSetup; 9 | class DataRegion; 10 | 11 | class SegMap { 12 | public: 13 | static void mapAllSegments(ConductorSetup *setup); 14 | static void mapSegments(ElfMap &elf, address_t baseAddress = 0); 15 | private: 16 | static void mapElfSegment(ElfMap &elf, Elf64_Phdr *phdr, address_t baseAddress); 17 | static void mapRegion(DataRegion *region); 18 | }; 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /src/load/usage.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "usage.h" 3 | 4 | #ifndef GIT_VERSION 5 | #define GIT_VERSION (unknown) 6 | #endif 7 | 8 | #define _STRINGIZE(x) # x 9 | #define _STRINGIZE2(x) _STRINGIZE(x) 10 | 11 | void printUsage(const char *exepath) { 12 | std::fprintf(stderr, 13 | "This is the Egalito loader version %s\n", _STRINGIZE2(GIT_VERSION)); 14 | 15 | std::fprintf(stderr, "\n" 16 | "Usage: %s executable [arguments...]\n" 17 | " OR set the executable's program interpreter permanently with\n" 18 | " /usr/bin/patchelf --set-interpreter %s executable\n", 19 | exepath, exepath); 20 | 21 | std::fprintf(stderr, "\n" 22 | "Debug options: EGALITO_DEBUG=/dev/null|(some/settings/file)|(setting)\n" 23 | " where a setting may be e.g. load, load=2, !load\n" 24 | " and a settings file contains one setting/filename per line\n"); 25 | } 26 | -------------------------------------------------------------------------------- /src/load/usage.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_LOAD_USAGE_H 2 | #define EGALITO_LOAD_USAGE_H 3 | 4 | void printUsage(const char *exepath); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /src/log/temp.cpp: -------------------------------------------------------------------------------- 1 | #include "temp.h" 2 | #include "log/registry.h" 3 | 4 | TemporaryLogLevel::TemporaryLogLevel(const std::string &name, int level, 5 | bool cond) 6 | : name(name), previous(GroupRegistry::getInstance()->getSetting(name)) { 7 | 8 | if(cond) { 9 | GroupRegistry::getInstance()->applySetting(name, level); 10 | } 11 | } 12 | 13 | TemporaryLogLevel::~TemporaryLogLevel() { 14 | GroupRegistry::getInstance()->applySetting(name, previous); 15 | } 16 | 17 | TemporaryLogMuter::TemporaryLogMuter() { 18 | for(auto &name : GroupRegistry::getInstance()->getSettingNames()) { 19 | levels[name] = GroupRegistry::getInstance()->getSetting(name); 20 | } 21 | GroupRegistry::getInstance()->muteAllSettings(); 22 | } 23 | 24 | TemporaryLogMuter::~TemporaryLogMuter() { 25 | for(auto &name : GroupRegistry::getInstance()->getSettingNames()) { 26 | GroupRegistry::getInstance()->applySetting(name, levels[name]); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/log/temp.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_LOG_TEMP_H 2 | #define EGALITO_LOG_TEMP_H 3 | 4 | #include 5 | #include 6 | 7 | class TemporaryLogLevel { 8 | private: 9 | const std::string name; 10 | int previous; 11 | 12 | public: 13 | TemporaryLogLevel(const std::string &name, int level, bool cond=true); 14 | ~TemporaryLogLevel(); 15 | }; 16 | 17 | class TemporaryLogMuter { 18 | private: 19 | std::map levels; 20 | public: 21 | TemporaryLogMuter(); 22 | ~TemporaryLogMuter(); 23 | }; 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /src/operation/cursor.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_OPERATION_CURSOR_H 2 | #define EGALITO_OPERATION_CURSOR_H 3 | 4 | #include "types.h" 5 | 6 | class ChunkList; 7 | class Chunk; 8 | 9 | class ChunkCursor { 10 | private: 11 | ChunkList *list; 12 | size_t index; 13 | public: 14 | ChunkCursor(Chunk *parent, size_t index); 15 | ChunkCursor(Chunk *chunk); 16 | ChunkCursor(Chunk *parent, Chunk *chunk); 17 | 18 | Chunk *get() const; 19 | size_t getIndex() const { return index; } 20 | 21 | bool prev(); 22 | bool next(); 23 | bool isEnd() const; 24 | 25 | static ChunkCursor makeBegin(Chunk *parent); 26 | static ChunkCursor makeEnd(Chunk *parent); 27 | }; 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /src/operation/find.cpp: -------------------------------------------------------------------------------- 1 | #include "find.h" 2 | 3 | template <> 4 | Chunk *ChunkFind::findImpl(Instruction *root, address_t target, 5 | bool compositeContains, bool instructionContains) { 6 | 7 | if(instructionContains) { 8 | return (root->getRange().contains(target) ? root : nullptr); 9 | } 10 | else { 11 | return (root->getAddress() == target ? root : nullptr); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /src/operation/find2.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_OPERATION_FIND2_H 2 | #define EGALITO_OPERATION_FIND2_H 3 | 4 | #include "types.h" 5 | 6 | class Conductor; 7 | class Program; 8 | class Module; 9 | class Function; 10 | 11 | class ChunkFind2 { 12 | private: 13 | Program *program; 14 | public: 15 | ChunkFind2(Conductor *conductor); 16 | ChunkFind2(Program *program) : program(program) {} 17 | ChunkFind2() : program(nullptr) {} 18 | 19 | Function *findFunction(const char *name, Module *source = nullptr); 20 | Function *findFunctionInModule(const char *name, Module *module); 21 | 22 | Function *findFunctionContaining(address_t address); 23 | Function *findFunctionContainingInModule(address_t address, Module *module); 24 | private: 25 | Function *findFunctionHelper(const char *name, Module *module); 26 | }; 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /src/pass/aflcoverage.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_AFL_COVERAGE_H 2 | #define EGALITO_PASS_AFL_COVERAGE_H 3 | 4 | #include "chunkpass.h" 5 | 6 | class AFLCoveragePass : public ChunkPass { 7 | private: 8 | Function *entryPoint; 9 | unsigned long blockID; 10 | public: 11 | AFLCoveragePass() : blockID(1) {} 12 | virtual void visit(Program *program); 13 | virtual void visit(Module *module); 14 | virtual void visit(Function *function); 15 | virtual void visit(Block *block); 16 | private: 17 | void addCoverageCode(Block *block); 18 | }; 19 | 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /src/pass/chunkpass.cpp: -------------------------------------------------------------------------------- 1 | #include "chunkpass.h" 2 | -------------------------------------------------------------------------------- /src/pass/clearplts.cpp: -------------------------------------------------------------------------------- 1 | #include "clearplts.h" 2 | 3 | void ClearPLTs::visit(Module *module) { 4 | recurse(module->getPLTList()); 5 | } 6 | 7 | void ClearPLTs::visit(PLTTrampoline *plt) { 8 | if(!clearIFuncs && plt->isIFunc()) return; 9 | 10 | freeChildren(plt, 2); 11 | } 12 | 13 | void ClearPLTs::freeChildren(Chunk *chunk, int level) { 14 | if(level > 0) { 15 | for(int i = chunk->getChildren()->genericGetSize() - 1; i >= 0; i --) { 16 | auto child = chunk->getChildren()->genericGetAt(i); 17 | freeChildren(child, level-1); 18 | chunk->getChildren()->genericRemoveLast(); 19 | delete child; 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /src/pass/clearplts.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_CLEAR_PLTS_H 2 | #define EGALITO_PASS_CLEAR_PLTS_H 3 | 4 | #include "chunkpass.h" 5 | 6 | class ClearPLTs : public ChunkPass { 7 | private: 8 | bool clearIFuncs; 9 | public: 10 | ClearPLTs(bool clearIFuncs = false) : clearIFuncs(clearIFuncs) {} 11 | virtual void visit(Module *module); 12 | virtual void visit(PLTTrampoline *plt); 13 | private: 14 | void freeChildren(Chunk *chunk, int level); 15 | }; 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /src/pass/clearspatial.cpp: -------------------------------------------------------------------------------- 1 | #include "clearspatial.h" 2 | 3 | void ClearSpatialPass::visit(FunctionList *functionList) { 4 | functionList->getChildren()->clearSpatial(); 5 | recurse(functionList); 6 | } 7 | 8 | void ClearSpatialPass::visit(Function *function) { 9 | function->getChildren()->clearSpatial(); 10 | recurse(function); 11 | } 12 | 13 | void ClearSpatialPass::visit(Block *block) { 14 | block->getChildren()->clearSpatial(); 15 | } 16 | 17 | void ClearSpatialPass::visit(DataRegionList *regionList) { 18 | regionList->getChildren()->clearSpatial(); 19 | recurse(regionList); 20 | } 21 | 22 | void ClearSpatialPass::visit(DataRegion *region) { 23 | region->getChildren()->clearSpatial(); 24 | recurse(region); 25 | } 26 | 27 | void ClearSpatialPass::visit(DataSection *section) { 28 | section->getChildren()->clearSpatial(); 29 | } 30 | -------------------------------------------------------------------------------- /src/pass/clearspatial.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_CLEARSPATIAL_H 2 | #define EGALITO_PASS_CLEARSPATIAL_H 3 | 4 | #include "chunkpass.h" 5 | 6 | class ClearSpatialPass : public ChunkPass { 7 | private: 8 | public: 9 | virtual void visit(FunctionList *functionList); 10 | virtual void visit(Function *function); 11 | virtual void visit(Block *block); 12 | virtual void visit(DataRegionList *regionList); 13 | virtual void visit(DataRegion *region); 14 | virtual void visit(DataSection *section); 15 | }; 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /src/pass/collapseplt.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_COLLAPSE_PLT_H 2 | #define EGALITO_PASS_COLLAPSE_PLT_H 3 | 4 | #include 5 | #include "chunkpass.h" 6 | 7 | class Conductor; 8 | class Function; 9 | 10 | class CollapsePLTPass : public ChunkPass { 11 | private: 12 | Conductor *conductor; 13 | std::map ifuncMap; 14 | public: 15 | CollapsePLTPass(Conductor *conductor); 16 | virtual void visit(Module *module); 17 | virtual void visit(Instruction *instr); 18 | virtual void visit(DataSection *section); 19 | }; 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /src/pass/collectglobals.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_COLLECT_GLOBALS_H 2 | #define EGALITO_PASS_COLLECT_GLOBALS_H 3 | 4 | #include "pass/chunkpass.h" 5 | 6 | class CollectGlobalsPass : public ChunkPass { 7 | public: 8 | virtual void visit(Module *module); 9 | }; 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /src/pass/condwatchpoint.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_COND_WATCHPOINT_H 2 | #define EGALITO_PASS_COND_WATCHPOINT_H 3 | 4 | #include 5 | #include "chunkpass.h" 6 | #include "chunk/dataregion.h" 7 | #include "chunk/function.h" 8 | 9 | class CondWatchpointPass : public ChunkPass { 10 | private: 11 | Function *condTarget; 12 | public: 13 | virtual void visit(Module *module); 14 | virtual void visit(Function *function); 15 | private: 16 | std::pair createDataSection(Module *module); 17 | Link *addVariable(DataSection *section, Function *function); 18 | void appendFunctionName(DataSection *nameSection, const std::string &name); 19 | }; 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /src/pass/debloat.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_DEBLOAT_H 2 | #define EGALITO_PASS_DEBLOAT_H 3 | 4 | #include "chunkpass.h" 5 | #include "analysis/call.h" 6 | 7 | class DebloatPass : public ChunkPass { 8 | private: 9 | Program *program; 10 | CallGraph graph; 11 | std::set usedList; 12 | public: 13 | DebloatPass(Program *program); 14 | virtual void visit(Module *module); 15 | private: 16 | void useFromDynamicInitFini(); 17 | void useFromPointerArray(address_t start, size_t size, Module *module); 18 | void useFromEntry(); 19 | void useFromIndirectCallee(); 20 | void useFromCodeLinks(); 21 | void useFromSpecialName(); 22 | void markTreeAsUsed(Function *root); 23 | }; 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /src/pass/detectnullptr.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_DETECT_NULL_PTR_H 2 | #define EGALITO_PASS_DETECT_NULL_PTR_H 3 | 4 | #include "chunkpass.h" 5 | 6 | class Symbol; 7 | 8 | class DetectNullPtrPass : public ChunkPass { 9 | private: 10 | Symbol *failFunc; 11 | public: 12 | virtual void visit(Module *module); 13 | virtual void visit(Instruction *instruction); 14 | }; 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /src/pass/dumplink.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_DUMPLINK_H 2 | #define EGALITO_PASS_DUMPLINK_H 3 | 4 | #include "chunkpass.h" 5 | 6 | class DumpLinkPass : public ChunkPass { 7 | private: 8 | Module *module; 9 | address_t mapbase; 10 | public: 11 | virtual void visit(Module *module); 12 | private: 13 | virtual void visit(Instruction *instruction); 14 | virtual void visit(DataSection *section); 15 | void dump(Reloc *reloc, Module *module); 16 | void output(address_t source, Link *link); 17 | void outputPair(address_t addr1, address_t addr2); 18 | }; 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /src/pass/dumptlsinstr.cpp: -------------------------------------------------------------------------------- 1 | #include "dumptlsinstr.h" 2 | #include "chunk/concrete.h" 3 | #include "chunk/dump.h" 4 | #include "log/log.h" 5 | 6 | void DumpTLSInstrPass::visit(Instruction *instruction) { 7 | auto assembly = instruction->getSemantic()->getAssembly(); 8 | if(!assembly) return; 9 | 10 | #ifdef ARCH_X86_64 11 | auto asmOps = assembly->getAsmOperands(); 12 | for(size_t i = 0; i < asmOps->getOpCount(); i ++) { 13 | const cs_x86_op *op = &asmOps->getOperands()[i]; 14 | if((op->type == X86_OP_REG && op->reg == X86_REG_FS) 15 | || (op->type == X86_OP_MEM && op->mem.segment == X86_REG_FS)) { 16 | 17 | LOG(1, "TLS (fs) instruction " << instruction->getName() 18 | << " inside " 19 | << instruction->getParent()->getParent()->getName()); 20 | ChunkDumper dumper; 21 | instruction->accept(&dumper); 22 | break; 23 | } 24 | } 25 | #endif 26 | } 27 | -------------------------------------------------------------------------------- /src/pass/dumptlsinstr.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_DUMP_TLS_INSTR_H 2 | #define EGALITO_PASS_DUMP_TLS_INSTR_H 3 | 4 | #include "chunkpass.h" 5 | 6 | class DumpTLSInstrPass : public ChunkPass { 7 | public: 8 | virtual void visit(Instruction *instruction); 9 | }; 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /src/pass/encodingcheckpass.cpp: -------------------------------------------------------------------------------- 1 | #include "encodingcheckpass.h" 2 | #include "instr/linked-aarch64.h" 3 | #include "log/log.h" 4 | 5 | void EncodingCheckPass::visit(Module *module) { 6 | LOG(10, "CheckPass " << module->getName()); 7 | recurse(module); 8 | } 9 | 10 | void EncodingCheckPass::visit(Instruction *instruction) { 11 | #ifdef ARCH_AARCH64 12 | if(auto linked = dynamic_cast( 13 | instruction->getSemantic())) { 14 | 15 | LOG(10, "checking " << std::hex << instruction->getAddress()); 16 | linked->check(); 17 | } 18 | #endif 19 | } 20 | -------------------------------------------------------------------------------- /src/pass/encodingcheckpass.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_CHECKPASS_H 2 | #define EGALITO_PASS_CHECKPASS_H 3 | 4 | #include "pass/chunkpass.h" 5 | 6 | class EncodingCheckPass : public ChunkPass { 7 | private: 8 | virtual void visit(Module *module); 9 | virtual void visit(Instruction *instruction); 10 | }; 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /src/pass/endbradd.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_ENDBR_ADD_H 2 | #define EGALITO_PASS_ENDBR_ADD_H 3 | 4 | #include 5 | #include "chunkpass.h" 6 | 7 | class EndbrAddPass : public ChunkPass { 8 | private: 9 | bool haveCollapsedPLT; 10 | std::set indirectTargets; 11 | public: 12 | EndbrAddPass(bool haveCollapsedPLT = true) 13 | : haveCollapsedPLT(haveCollapsedPLT) {} 14 | virtual void visit(Program *program); 15 | virtual void visit(Module *module); 16 | virtual void visit(DataRegionList *dataRegionList) { recurse(dataRegionList); } 17 | virtual void visit(DataRegion *dataRegion) { recurse(dataRegion); } 18 | virtual void visit(DataSection *dataSection) { recurse(dataSection); } 19 | virtual void visit(DataVariable *dataVariable); 20 | virtual void visit(PLTList *pltList) { recurse(pltList); } 21 | virtual void visit(PLTTrampoline *pltTrampoline); 22 | virtual void visit(InitFunctionList *initFunctionList); 23 | virtual void visit(InitFunction *initFunction); 24 | virtual void visit(Instruction *instruction); 25 | }; 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /src/pass/endbrenforce.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_ENDBR_ENFORCE_H 2 | #define EGALITO_PASS_ENDBR_ENFORCE_H 3 | 4 | #include "chunkpass.h" 5 | 6 | class EndbrEnforcePass : public ChunkPass { 7 | private: 8 | Function *violationTarget; 9 | public: 10 | EndbrEnforcePass() : violationTarget(nullptr) {} 11 | virtual void visit(Module *module); 12 | virtual void visit(Function *function); 13 | virtual void visit(Instruction *instruction); 14 | private: 15 | void makeEnforcementCode(Instruction *point); 16 | }; 17 | 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /src/pass/externalcalls.cpp: -------------------------------------------------------------------------------- 1 | #include "externalcalls.h" 2 | #include "instr/concrete.h" 3 | 4 | #undef DEBUG_GROUP 5 | #define DEBUG_GROUP dplt 6 | #include "log/log.h" 7 | 8 | void ExternalCalls::visit(Instruction *instruction) { 9 | auto semantic = instruction->getSemantic(); 10 | 11 | // look for instructions with Links 12 | if(auto v = dynamic_cast(semantic)) { 13 | auto link = v->getLink(); 14 | if(link && !link->getTarget()) { 15 | auto address = link->getTargetAddress(); 16 | auto pltEntry = CIter::spatial(pltList)->find(address); 17 | 18 | if(pltEntry) { 19 | LOG(1, "plt call at 0x" << std::hex << instruction->getAddress() 20 | << " to 0x" << address 21 | << " i.e. [" << pltEntry->getName() << "]"); 22 | v->setLink(new PLTLink(address, pltEntry)); 23 | delete link; 24 | } 25 | } 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/pass/externalcalls.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_EXTERNAL_CALLS_H 2 | #define EGALITO_PASS_EXTERNAL_CALLS_H 3 | 4 | #include "chunkpass.h" 5 | #include "elf/reloc.h" 6 | #include "chunk/plt.h" 7 | 8 | class ExternalCalls : public ChunkPass { 9 | private: 10 | PLTList *pltList; 11 | public: 12 | ExternalCalls(PLTList *pltList) : pltList(pltList) {} 13 | virtual void visit(Instruction *instruction); 14 | }; 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /src/pass/externalsymbollinks.cpp: -------------------------------------------------------------------------------- 1 | #include "externalsymbollinks.h" 2 | #include "chunk/link.h" 3 | #include "chunk/position.h" 4 | #include "elf/elfspace.h" 5 | #include "elf/elfmap.h" 6 | #include "log/log.h" 7 | #include "log/temp.h" 8 | 9 | void ExternalSymbolLinksPass::visit(Module *module) { 10 | for(auto dr : CIter::regions(module)) { 11 | for(auto ds : CIter::children(dr)) { 12 | for(auto dv : CIter::children(ds)) { 13 | if(dv->getDest()) continue; 14 | 15 | // If no target symbol, relocation type is probably not supported 16 | if(!dv->getTargetSymbol()) continue; 17 | 18 | auto externalSymbol = ExternalSymbolFactory(module) 19 | .makeExternalSymbol(dv->getTargetSymbol()); 20 | if(!dv->getIsCopy()) { 21 | auto link = new ExternalSymbolLink(externalSymbol); 22 | dv->setDest(link); 23 | } 24 | else { 25 | auto link = new CopyRelocLink(externalSymbol); 26 | dv->setDest(link); 27 | } 28 | } 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/pass/externalsymbollinks.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_EXTERNALSYMBOLLINKS_H 2 | #define EGALITO_PASS_EXTERNALSYMBOLLINKS_H 3 | 4 | #include "chunkpass.h" 5 | 6 | /** Find all links whose target is null, replace with ExternalSymbolLink. 7 | Used in mirrorgen when parsing only one Module. 8 | */ 9 | class ExternalSymbolLinksPass : public ChunkPass { 10 | public: 11 | virtual void visit(Module *module); 12 | }; 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /src/pass/fallthrough.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_FALLTHROUGH_H 2 | #define EGALITO_PASS_FALLTHROUGH_H 3 | 4 | #include "chunkpass.h" 5 | 6 | class FallThroughFunctionPass : public ChunkPass { 7 | public: 8 | FallThroughFunctionPass() {} 9 | virtual void visit(Function *function); 10 | }; 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /src/pass/findendbr.cpp: -------------------------------------------------------------------------------- 1 | #include "findendbr.h" 2 | #include "instr/concrete.h" 3 | #include "log/log.h" 4 | 5 | void FindEndbrPass::visit(Module *module) { 6 | LOG(9, "Searching for endbr in [" << module->getName() << "]"); 7 | recurse(module); 8 | } 9 | 10 | void FindEndbrPass::visit(Function *function) { 11 | currentFunction = function; 12 | recurse(function); 13 | if (brCount[function]) { 14 | LOG(9, "Number of endbr instructions in [" << function->getName() 15 | << "] is " << brCount[function]); 16 | } 17 | } 18 | 19 | void FindEndbrPass::visit(Instruction *instruction) { 20 | auto semantic = instruction->getSemantic(); 21 | if (auto v = dynamic_cast(semantic)) { 22 | #ifdef ARCH_X86_64 23 | if (v->getAssembly()->getId() == X86_INS_ENDBR64) { 24 | brCount[currentFunction]++; 25 | } 26 | #endif 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/pass/findendbr.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_FINDENDBR_H 2 | #define EGALITO_PASS_FINDENDBR_H 3 | 4 | #include 5 | #include "chunkpass.h" 6 | 7 | class FindEndbrPass : public ChunkPass { 8 | private: 9 | std::map brCount; 10 | Function *currentFunction; 11 | public: 12 | FindEndbrPass() : currentFunction(nullptr) {} 13 | virtual void visit(Module *module); 14 | virtual void visit(Function *function); 15 | virtual void visit(Instruction *instruction); 16 | }; 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /src/pass/findinitfuncs.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_FIND_INIT_FUNCS_H 2 | #define EGALITO_PASS_FIND_INIT_FUNCS_H 3 | 4 | #include "chunkpass.h" 5 | 6 | class FindInitFuncs : public ChunkPass { 7 | public: 8 | virtual void visit(Module *module); 9 | }; 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /src/pass/findsyscalls.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_FINDSYSCALLS_H 2 | #define EGALITO_PASS_FINDSYSCALLS_H 3 | 4 | #include 5 | #include 6 | 7 | #include "chunkpass.h" 8 | #include "log/registry.h" 9 | #include "log/temp.h" 10 | 11 | class UDState; 12 | 13 | class FindSyscalls : public ChunkPass { 14 | private: 15 | std::map> numberMap; 16 | std::set seen; 17 | public: 18 | virtual void visit(Function *function); 19 | 20 | const std::map> &getNumberMap() const 21 | { return numberMap; } 22 | private: 23 | bool isSyscallFunction(Function *function); 24 | bool getRegisterValue(UDState *state, int curreg, std::set &valueSet); 25 | }; 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /src/pass/fixdataregions.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_FIX_DATA_REGIONS_H 2 | #define EGALITO_PASS_FIX_DATA_REGIONS_H 3 | 4 | #include "chunkpass.h" 5 | 6 | class DataVariable; 7 | 8 | class FixDataRegionsPass : public ChunkPass { 9 | private: 10 | Program *program; 11 | Module *module; 12 | public: 13 | virtual void visit(Program *program); 14 | virtual void visit(Module *module); 15 | virtual void visit(DataRegionList *dataRegionList); 16 | virtual void visit(DataRegion *dataRegion); 17 | private: 18 | bool isForIFuncJumpSlot(DataVariable *var); 19 | }; 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /src/pass/fixenviron.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_FIX_ENVIRON_H 2 | #define EGALITO_PASS_FIX_ENVIRON_H 3 | 4 | #include "chunkpass.h" 5 | 6 | /** Add code to set __environ variable in _start, for uniongen only. 7 | This variable is normally set in _start for static executables. 8 | */ 9 | class FixEnvironPass : public ChunkPass { 10 | public: 11 | virtual void visit(Program *program); 12 | }; 13 | 14 | #endif 15 | -------------------------------------------------------------------------------- /src/pass/fixjumptables.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_FIX_JUMP_TABLES_H 2 | #define EGALITO_PASS_FIX_JUMP_TABLES_H 3 | 4 | #include "chunkpass.h" 5 | 6 | class FixJumpTablesPass : public ChunkPass { 7 | private: 8 | Module *module; 9 | public: 10 | FixJumpTablesPass(Module *module = nullptr) : module(module) {} 11 | 12 | virtual void visit(Module *module); 13 | virtual void visit(JumpTableList *jumpTableList); 14 | virtual void visit(JumpTable *jumpTable); 15 | }; 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /src/pass/handlecopyrelocs.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_HANDLECOPYRELOCS_H 2 | #define EGALITO_PASS_HANDLECOPYRELOCS_H 3 | 4 | #include "chunkpass.h" 5 | 6 | class Conductor; 7 | class Module; 8 | class Link; 9 | 10 | class HandleCopyRelocs : public ChunkPass { 11 | private: 12 | Conductor *conductor; 13 | public: 14 | HandleCopyRelocs(Conductor *conductor) : conductor(conductor) {} 15 | virtual void visit(Module *module); 16 | private: 17 | void copyAndDuplicate(Link *sourceLink, address_t destAddress, size_t size); 18 | }; 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /src/pass/handlerelocs.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_HANDLE_RELOCS_H 2 | #define EGALITO_PASS_HANDLE_RELOCS_H 3 | 4 | #include "chunkpass.h" 5 | #include "elf/reloc.h" 6 | 7 | class Module; 8 | 9 | class HandleRelocsPass : public ChunkPass { 10 | private: 11 | ElfMap *elf; 12 | RelocList *relocList; 13 | Module *module; 14 | bool resolveWeak; 15 | public: 16 | HandleRelocsPass(ElfMap *elf, RelocList *relocList, bool resolveWeak) 17 | : elf(elf), relocList(relocList), module(nullptr), 18 | resolveWeak(resolveWeak) {} 19 | virtual void visit(Module *module); 20 | private: 21 | void handleRelocation(Reloc *r, Instruction *instruction); 22 | void handleRelocation(Reloc *r, Instruction *instruction, 23 | Symbol *symbol); 24 | }; 25 | 26 | class HandleRelocsStrong : public HandleRelocsPass { 27 | public: 28 | HandleRelocsStrong(ElfMap *elf, RelocList *relocList) : 29 | HandleRelocsPass(elf, relocList, false) {} 30 | }; 31 | 32 | class HandleRelocsWeak : public HandleRelocsPass { 33 | public: 34 | HandleRelocsWeak(ElfMap *elf, RelocList *relocList) : 35 | HandleRelocsPass(elf, relocList, true) {} 36 | }; 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /src/pass/hijack.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_HIJACKPASS_H 2 | #define EGALITO_PASS_HIJACKPASS_H 3 | 4 | #include "pass/chunkpass.h" 5 | 6 | class HijackPass : public ChunkPass { 7 | private: 8 | Chunk *original; 9 | Chunk *wrapper; 10 | public: 11 | HijackPass(Conductor *conductor, const char *name); 12 | void visit(Module *module); 13 | private: 14 | void visit(Instruction *instruction); 15 | void visit(PLTTrampoline *trampoline); 16 | }; 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /src/pass/ifunclazy.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_IFUNCLAZY_H 2 | #define EGALITO_PASS_IFUNCLAZY_H 3 | 4 | #include "chunkpass.h" 5 | 6 | // relocation is not aware of the lazy selection 7 | 8 | class IFuncList; 9 | 10 | // this pass does not work in the following case (all conditions met): 11 | // - when the target has a plt to IFUNC 12 | // - when the target has a function pointer to IFUNC 13 | // In this case, gcc creates R_X86_64_GLOB_DAT, instead of R_X86_64_JUMP_SLOT. 14 | // In other words, if there is a .plt.got section. This section holds 15 | // special PLT trampolines that works, when ld has combined 16 | // a normal GOT entry and one needed by PLT. 17 | // 18 | // A workaround for this is to have a run-time constructor that 19 | // pre-resolves all IFUNCs (including the internal ones in glibc) 20 | // A proper fix would be to handle this PLT specially. 21 | // The current workaround is abuse CollapsePLTPass. 22 | class IFuncLazyPass : public ChunkPass { 23 | private: 24 | IFuncList *ifuncList; 25 | Module *module; 26 | public: 27 | IFuncLazyPass(IFuncList *ifuncList) : ifuncList(ifuncList) {} 28 | private: 29 | virtual void visit(Module *module); 30 | virtual void visit(PLTTrampoline *trampoline); 31 | }; 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /src/pass/ifuncplts.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_IFUNCPLTS_H 2 | #define EGALITO_PASS_IFUNCPLTS_H 3 | 4 | #include "chunkpass.h" 5 | 6 | /** Adds nop instruction before every instruction. */ 7 | class IFuncPLTs : public ChunkPass { 8 | public: 9 | virtual void visit(Module *module); 10 | virtual void visit(PLTList *pltList); 11 | virtual void visit(PLTTrampoline *trampoline); 12 | private: 13 | void freeChildren(Chunk *chunk, int level); 14 | }; 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /src/pass/inferlinks.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_INFER_LINKS_H 2 | #define EGALITO_PASS_INFER_LINKS_H 3 | 4 | #include "chunkpass.h" 5 | #include "elf/elfmap.h" 6 | 7 | class InferLinksPass : public ChunkPass { 8 | private: 9 | ElfMap *elf; 10 | Module *module; 11 | public: 12 | InferLinksPass(ElfMap *elf) : elf(elf), module(nullptr) {} 13 | virtual void visit(Module *module); 14 | virtual void visit(Instruction *instruction); 15 | }; 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /src/pass/injectbridge.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "injectbridge.h" 4 | #include "conductor/bridge.h" 5 | #include "elf/reloc.h" 6 | #include "chunk/dataregion.h" 7 | #include "chunk/link.h" 8 | #include "operation/mutator.h" 9 | #include "snippet/hook.h" 10 | #include "log/log.h" 11 | 12 | void InjectBridgePass::visit(Module *module) { 13 | auto bridge = LoaderBridge::getInstance(); 14 | 15 | for(auto reloc : *relocList) { 16 | auto sym = reloc->getSymbol(); 17 | if(!sym) continue; 18 | 19 | if(bridge->containsName(sym->getName())) { 20 | makeLinkToLoaderVariable(module, reloc); 21 | } 22 | } 23 | } 24 | 25 | void InjectBridgePass::makeLinkToLoaderVariable(Module *module, Reloc *reloc) { 26 | LOG(1, "[InjectBridge] assigning EgalitoLoaderLink for " 27 | << reloc->getSymbol()->getName()); 28 | 29 | auto link = new EgalitoLoaderLink(reloc->getSymbol()->getName()); 30 | 31 | auto address = reloc->getAddress() + module->getBaseAddress(); 32 | DataVariable::create(module, address, link, reloc->getSymbol()); 33 | } 34 | -------------------------------------------------------------------------------- /src/pass/injectbridge.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_INJECTBRIDGE_H 2 | #define EGALITO_PASS_INJECTBRIDGE_H 3 | 4 | #include "chunkpass.h" 5 | 6 | class RelocList; 7 | class Reloc; 8 | 9 | class InjectBridgePass : public ChunkPass { 10 | private: 11 | RelocList *relocList; 12 | public: 13 | InjectBridgePass(RelocList *relocList) : relocList(relocList) {} 14 | void visit(Module *module); 15 | private: 16 | void makeLinkToLoaderVariable(Module *module, Reloc *reloc); 17 | }; 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /src/pass/instrumentinstr.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_INSTRUMENTINSTR_PASS_H 2 | #define EGALITO_PASS_INSTRUMENTINSTR_PASS_H 3 | 4 | #include "pass/stackextend.h" 5 | 6 | class InstrumentInstructionPass : public ChunkPass { 7 | public: 8 | typedef bool (*predicate_t) (Function *function); 9 | private: 10 | Function *func; 11 | predicate_t predicate; 12 | public: 13 | InstrumentInstructionPass() : func(nullptr), predicate(nullptr) {} 14 | void setPredicate(predicate_t predicate) { this->predicate = predicate; } 15 | void setAdvice(Function *func) { this->func = func; } 16 | 17 | virtual void visit(Function *function); 18 | virtual void visit(Block *block); 19 | virtual void visit(Instruction *instruction); 20 | 21 | private: 22 | void addAdvice(Instruction *point, Function *advice, bool before); 23 | virtual bool shouldApply(Function *function) { 24 | return function != func 25 | && (predicate ? predicate(function) : true); } 26 | }; 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /src/pass/internalcalls.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_INTERNAL_CALLS_H 2 | #define EGALITO_INTERNAL_CALLS_H 3 | 4 | #include "chunkpass.h" 5 | 6 | class InternalCalls : public ChunkPass { 7 | private: 8 | FunctionList *functionList; 9 | public: 10 | InternalCalls() : functionList(nullptr) {} 11 | virtual void visit(Module *module); 12 | virtual void visit(Instruction *instruction); 13 | }; 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /src/pass/jitgsfixup.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_JIT_GS_FIXUP_H 2 | #define EGALITO_JIT_GS_FIXUP_H 3 | 4 | #include "chunkpass.h" 5 | 6 | class Conductor; 7 | class GSTable; 8 | class Module; 9 | 10 | class JitGSFixup : public ChunkPass { 11 | private: 12 | Conductor *conductor; 13 | GSTable *gsTable; 14 | Chunk *callback; 15 | public: 16 | JitGSFixup(Conductor *conductor, GSTable *gsTable); 17 | 18 | virtual void visit(Program *program); 19 | private: 20 | void addResetCalls(); 21 | void addAfterFirstSyscall(const char *name, Module *module, Chunk *target); 22 | void addAfterEverySyscall(const char *name, Module *module, Chunk *target); 23 | void addAfterSyscall(const char *name, Module *module, Chunk *target, 24 | bool firstOnly); 25 | void addAfter(Instruction *instruction, Block *block, Chunk *target); 26 | }; 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /src/pass/jitgssetup.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_JITGSSETUP_H 2 | #define EGALITO_PASS_JITGSSETUP_H 3 | 4 | #include "chunkpass.h" 5 | 6 | class ConductorSetup; 7 | class Conductor; 8 | class GSTable; 9 | 10 | class JitGSSetup : public ChunkPass { 11 | private: 12 | Conductor *conductor; 13 | GSTable *gsTable; 14 | public: 15 | JitGSSetup(Conductor *conductor, GSTable *gsTable) 16 | : conductor(conductor), gsTable(gsTable) {} 17 | virtual void visit(Program *program); 18 | private: 19 | void makeHardwiredGSEntries(Module *egalito); 20 | void makeResolverGSEntries(Module *egalito); 21 | void makeSupportGSEntries(Program *program); 22 | void makeResolvedEntry(const char *name, Module *module); 23 | void makeResolvedEntryForClass(const char *name, Module *module); 24 | void makeResolvedEntryForFunction(Function *function); 25 | //void makeResolvedEntryForPLT(std::string name, Program *program); 26 | void makeResolvedEntryForPLT(PLTTrampoline *plt); 27 | 28 | void makeRequiredEntries(); 29 | void makeRequiredEntriesFor(Chunk *chunk); 30 | }; 31 | 32 | #endif 33 | -------------------------------------------------------------------------------- /src/pass/jtoverestimate.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_J_T_OVERESTIMATE_H 2 | #define EGALITO_PASS_J_T_OVERESTIMATE_H 3 | 4 | #include "chunkpass.h" 5 | 6 | class JumpTableOverestimate : public ChunkPass { 7 | private: 8 | Module *module; 9 | std::map tableMap; 10 | public: 11 | virtual void visit(Module *module); 12 | virtual void visit(JumpTableList *jumpTableList); 13 | virtual void visit(JumpTable *jumpTable); 14 | private: 15 | void setEntries(JumpTable *jumpTable, int count); 16 | }; 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /src/pass/jumptablebounds.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_JUMP_TABLE_BOUNDS_H 2 | #define EGALITO_PASS_JUMP_TABLE_BOUNDS_H 3 | 4 | #include 5 | #include "chunkpass.h" 6 | 7 | /** Uses relocations and jump table beginning points to infer the number of 8 | entries in jump tables. Only works on modules compiled with -Wl,-q. Based 9 | on Shuffler's technique. 10 | */ 11 | class JumpTableBounds : public ChunkPass { 12 | private: 13 | Module *module; 14 | std::map tableMap; 15 | public: 16 | virtual void visit(Module *module); 17 | virtual void visit(JumpTableList *jumpTableList); 18 | virtual void visit(JumpTable *jumpTable); 19 | private: 20 | void setEntries(JumpTable *jumpTable, int count); 21 | }; 22 | 23 | #endif 24 | -------------------------------------------------------------------------------- /src/pass/jumptablepass.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_JUMP_TABLE_PASS_H 2 | #define EGALITO_PASS_JUMP_TABLE_PASS_H 3 | 4 | #include 5 | #include "chunkpass.h" 6 | 7 | /** Constructs jump table data structures in the given Module. */ 8 | class JumpTablePass : public ChunkPass { 9 | private: 10 | Module *module; 11 | std::map tableMap; 12 | public: 13 | JumpTablePass(Module *module = nullptr) : module(module) {} 14 | virtual void visit(Module *module); 15 | virtual void visit(JumpTableList *jumpTableList); 16 | 17 | /** Constructs JumpTableEntries for the given jumptable. 18 | Note: relies on this->module being set. 19 | */ 20 | size_t makeChildren(JumpTable *jumpTable, int count); 21 | 22 | private: 23 | void makeJumpTable(JumpTableList *jumpTableList, 24 | const std::vector &tables); 25 | void saveToFile() const; 26 | bool loadFromFile(JumpTableList *jumpTableList); 27 | }; 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /src/pass/ldsorefs.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_LDSOREFS_H 2 | #define EGALITO_PASS_LDSOREFS_H 3 | 4 | #include "chunkpass.h" 5 | 6 | class LdsoRefsPass : public ChunkPass { 7 | private: 8 | Function *emptyTarget; 9 | public: 10 | LdsoRefsPass() : emptyTarget(nullptr) {} 11 | 12 | virtual void visit(Program *program); 13 | virtual void visit(Module *module); 14 | virtual void visit(Function *function); 15 | virtual void visit(Instruction *instruction); 16 | }; 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /src/pass/logcalls.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_LOG_CALLS_H 2 | #define EGALITO_PASS_LOG_CALLS_H 3 | 4 | #include "chunkpass.h" 5 | #include "pass/instrumentcalls.h" 6 | 7 | class Conductor; 8 | 9 | // keeping the same name for now; we should really have one implementation 10 | class LogCallsPass : public ChunkPass { 11 | private: 12 | Function *loggingBegin, *loggingEnd; 13 | InstrumentCallsPass instrument; 14 | public: 15 | LogCallsPass(Conductor *conductor); 16 | virtual void visit(Function *function); 17 | }; 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /src/pass/loginstr.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_LOG_INSTR_H 2 | #define EGALITO_PASS_LOG_INSTR_H 3 | 4 | #include "chunkpass.h" 5 | #include "pass/instrumentinstr.h" 6 | 7 | class Conductor; 8 | 9 | // keeping the same name for now; we should really have one implementation 10 | class LogInstructionPass : public ChunkPass { 11 | private: 12 | Function *loggingFunc; 13 | InstrumentInstructionPass instrument; 14 | public: 15 | LogInstructionPass(Conductor *conductor); 16 | virtual void visit(Function *function); 17 | }; 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /src/pass/makecache.cpp: -------------------------------------------------------------------------------- 1 | #include "makecache.h" 2 | 3 | void MakeCachePass::visit(Function *function) { 4 | #ifdef ARCH_X86_64 5 | function->makeCache(); 6 | #endif 7 | } 8 | 9 | void MakeCachePass::visit(PLTTrampoline *trampoline) { 10 | #ifdef ARCH_X86_64 11 | trampoline->makeCache(); 12 | #endif 13 | } 14 | -------------------------------------------------------------------------------- /src/pass/makecache.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_MAKECACHE_H 2 | #define EGALITO_PASS_MAKECACHE_H 3 | 4 | #include "pass/chunkpass.h" 5 | 6 | class MakeCachePass : public ChunkPass { 7 | public: 8 | virtual void visit(Function *function); 9 | virtual void visit(PLTTrampoline *trampoline); 10 | }; 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /src/pass/nonreturn.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_NONRETURN_H 2 | #define EGALITO_PASS_NONRETURN_H 3 | 4 | #include 5 | #include "chunkpass.h" 6 | 7 | class ControlFlowInstruction; 8 | class UDState; 9 | 10 | class NonReturnFunction : public ChunkPass { 11 | private: 12 | const static std::vector knownList; 13 | std::set nonReturnList; 14 | 15 | public: 16 | NonReturnFunction() {} 17 | virtual void visit(FunctionList *functionList); 18 | virtual void visit(Function *function); 19 | private: 20 | bool neverReturns(Function *function); 21 | bool hasLinkToNeverReturn(ControlFlowInstruction *cfi); 22 | bool inList(Function *function); 23 | 24 | bool hasLinkToGNUError(ControlFlowInstruction *cfi); 25 | std::tuple getArg0Value(UDState *state); 26 | }; 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /src/pass/noppass.cpp: -------------------------------------------------------------------------------- 1 | #include "noppass.h" 2 | #include "disasm/disassemble.h" 3 | #include "instr/concrete.h" 4 | #include "operation/mutator.h" 5 | #include "log/log.h" 6 | 7 | void NopPass::visit(Block *block) { 8 | #ifdef ARCH_X86_64 9 | ChunkMutator mutator(block); 10 | uint32_t instructionIndex = 0; 11 | auto instructionCount = block->getChildren()->getIterable()->getCount(); 12 | 13 | if(instructionCount > 0) { 14 | while (instructionCount--) { 15 | auto instruction = block->getChildren()->getIterable()->get(instructionIndex); 16 | mutator.insertAfter(instruction, Disassemble::instruction({0x90})); 17 | // increment by 2 to avoid processing the nop instruction 18 | instructionIndex += 2; 19 | } 20 | } 21 | #endif 22 | } 23 | -------------------------------------------------------------------------------- /src/pass/noppass.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_NOP_PASS_H 2 | #define EGALITO_PASS_NOP_PASS_H 3 | 4 | #include "chunkpass.h" 5 | 6 | /** Adds nop instruction before every instruction. */ 7 | class NopPass : public ChunkPass { 8 | public: 9 | virtual void visit(Block *block); 10 | }; 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /src/pass/permutedata.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_PERMUTEDATA_H 2 | #define EGALITO_PASS_PERMUTEDATA_H 3 | 4 | #include "chunk/module.h" 5 | #include "chunkpass.h" 6 | 7 | class PermuteDataPass : public ChunkPass { 8 | private: 9 | // old data section, new data section 10 | DataSection *ds, *nds; 11 | // stores map of datavariables (in ds) to dvs (in nds) 12 | std::map dvmap; 13 | // stores map of offsets (in ds) to offsets (in nds) 14 | std::map newlayout; 15 | // set of variables that have to remain in place 16 | std::map immobileVariables; 17 | Module *curModule; 18 | GlobalVariable *lastVariable; 19 | public: 20 | virtual void visit(Module *module); 21 | virtual void visit(Instruction *instr); 22 | private: 23 | Link *updatedLink(Link *link); 24 | private: 25 | address_t newAddress(address_t address); 26 | address_t newOffset(address_t offset); 27 | }; 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /src/pass/populateplt.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_POPLUATEPLT_H 2 | #define EGALITO_PASS_POPLUATEPLT_H 3 | 4 | #include "chunkpass.h" 5 | 6 | class PopulatePLTPass : public ChunkPass { 7 | private: 8 | Conductor *conductor; 9 | Module *module; 10 | public: 11 | PopulatePLTPass(Conductor *conductor) : conductor(conductor) {} 12 | virtual void visit(Module *module); 13 | virtual void visit(PLTTrampoline *trampoline); 14 | private: 15 | void populateLazyTrampoline(PLTTrampoline *trampoline); 16 | void populateTrampoline(PLTTrampoline *trampoline); 17 | }; 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /src/pass/positiondump.cpp: -------------------------------------------------------------------------------- 1 | #include "positiondump.h" 2 | #include "log/log.h" 3 | 4 | void PositionDump::visit(Chunk *chunk, int indent) { 5 | for(int i = 0; i < indent; i ++) LOG0(1, " "); 6 | 7 | LOG0(1, chunk->getName() << " has "); 8 | auto pos = chunk->getPosition(); 9 | if(dynamic_cast(pos)) { 10 | LOG(1, "AbsolutePosition " << pos->get()); 11 | } 12 | else if(auto v = dynamic_cast(pos)) { 13 | LOG(1, "OffsetPosition at " 14 | << v->getDependency()->getName() 15 | << " + " << v->getOffset()); 16 | } 17 | else if(auto v = dynamic_cast(pos)) { 18 | LOG(1, "SubsequentPosition after " 19 | << v->getDependency()->getName() << ", i.e. after " 20 | << v->getDependency()->getPosition()->get()); 21 | } 22 | else { 23 | LOG(1, "???"); 24 | } 25 | 26 | if(chunk->getChildren()) { 27 | for(auto child : chunk->getChildren()->genericIterable()) { 28 | visit(child, indent + 1); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/pass/positiondump.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_POSITION_DUMP_H 2 | #define EGALITO_PASS_POSITION_DUMP_H 3 | 4 | #include "chunkpass.h" 5 | 6 | class PositionDump { 7 | public: 8 | void visit(Chunk *chunk, int indent = 1); 9 | }; 10 | 11 | #endif 12 | -------------------------------------------------------------------------------- /src/pass/profileinstrument.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_PROFILE_INSTRUMENT_H 2 | #define EGALITO_PASS_PROFILE_INSTRUMENT_H 3 | 4 | #include 5 | #include "chunkpass.h" 6 | #include "chunk/dataregion.h" 7 | #include "chunk/function.h" 8 | 9 | class ProfileInstrumentPass : public ChunkPass { 10 | public: 11 | virtual void visit(Function *function); 12 | private: 13 | std::pair createDataSection(Module *module); 14 | Link *addVariable(DataSection *section, Function *function); 15 | void appendFunctionName(DataSection *nameSection, const std::string &name); 16 | }; 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /src/pass/profilesave.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_PROFILE_SAVE_H 2 | #define EGALITO_PASS_PROFILE_SAVE_H 3 | 4 | #include "chunkpass.h" 5 | #include "chunk/dataregion.h" 6 | 7 | class ProfileSavePass : public ChunkPass { 8 | public: 9 | virtual void visit(Module *module); 10 | private: 11 | std::pair getDataSections(Module *module); 12 | Link *appendString(DataSection *nameSection, const std::string &name); 13 | }; 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /src/pass/promotejumps.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_PROMOTE_JUMPS_H 2 | #define EGALITO_PASS_PROMOTE_JUMPS_H 3 | 4 | #include "chunkpass.h" 5 | 6 | /** This whole pass is x86_64-specific. */ 7 | class PromoteJumpsPass : public ChunkPass { 8 | private: 9 | bool changed; 10 | public: 11 | virtual void visit(Module *module) { recurse(module->getFunctionList()); } 12 | virtual void visit(Function *function); 13 | virtual void visit(Instruction *instruction); 14 | 15 | template 16 | static bool fitsIn(address_t address); 17 | private: 18 | void promote(Instruction *instruction); 19 | static std::string getWiderOpcode(unsigned int id); 20 | }; 21 | 22 | template 23 | bool PromoteJumpsPass::fitsIn(address_t address) { 24 | NarrowType narrow = address; 25 | return static_cast(narrow) 26 | == static_cast(address); 27 | } 28 | 29 | #endif 30 | -------------------------------------------------------------------------------- /src/pass/relocheck.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_RELOCHECK_H 2 | #define EGALITO_PASS_RELOCHECK_H 3 | 4 | #include "chunkpass.h" 5 | #include "elf/reloc.h" 6 | 7 | class Module; 8 | class Instruction; 9 | 10 | class ReloCheckPass : public ChunkPass { 11 | public: 12 | virtual void visit(Module *module); 13 | virtual void visit(Instruction *instruction); 14 | private: 15 | void check(Reloc *r, Module *module); 16 | void checkDataVariable(Module *module); 17 | }; 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /src/pass/removepadding.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_REMOVEPADDING_H 2 | #define EGALITO_PASS_REMOVEPADDING_H 3 | 4 | #include "chunkpass.h" 5 | 6 | class Module; 7 | class Function; 8 | 9 | class RemovePadding : public ChunkPass { 10 | private: 11 | std::vector emptyFunctions; 12 | public: 13 | RemovePadding() {} 14 | virtual void visit(Module *module); 15 | virtual void visit(Function *function); 16 | private: 17 | void removeHead(Function *function); 18 | void removeTail(Function *function); 19 | }; 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /src/pass/reorderpush.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_REORDER_PUSH_H 2 | #define EGALITO_PASS_REORDER_PUSH_H 3 | 4 | #include 5 | #include "chunkpass.h" 6 | 7 | class Module; 8 | class Function; 9 | 10 | class ReorderPush : public ChunkPass { 11 | private: 12 | std::vector pushOrder; 13 | public: 14 | virtual void visit(Module *module); 15 | virtual void visit(Function *function); 16 | private: 17 | Instruction *pickNextInstruction(std::vector list, 18 | bool recordPushes, bool enforcePops); 19 | }; 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /src/pass/resolveexternallinks.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_RESOLVEEXTERNALLINKS_H 2 | #define EGALITO_PASS_RESOLVEEXTERNALLINKS_H 3 | 4 | #include "chunkpass.h" 5 | 6 | /** Re-resolve external links between modules, after all modules are loaded 7 | and more targets may be known. Used in parse2/parse3. 8 | */ 9 | class ResolveExternalLinksPass : public ChunkPass { 10 | private: 11 | Conductor *conductor; 12 | public: 13 | ResolveExternalLinksPass(Conductor *conductor) : conductor(conductor) {} 14 | virtual void visit(Module *module); 15 | }; 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /src/pass/resolveplt.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_RESOLVE_PLT_H 2 | #define EGALITO_PASS_RESOLVE_PLT_H 3 | 4 | #include "chunkpass.h" 5 | 6 | class Conductor; 7 | class ElfSpace; 8 | 9 | class ResolvePLTPass : public ChunkPass { 10 | private: 11 | Conductor *conductor; 12 | Module *module; 13 | public: 14 | ResolvePLTPass(Conductor *conductor) 15 | : conductor(conductor), module(nullptr) {} 16 | protected: 17 | virtual void visit(Module *module); 18 | virtual void visit(PLTList *pltList); 19 | virtual void visit(PLTTrampoline *pltTrampoline); 20 | }; 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /src/pass/resolvetls.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_RESOLVETLS_H 2 | #define EGALITO_PASS_RESOLVETLS_H 3 | 4 | #include "chunkpass.h" 5 | 6 | class Program; 7 | class Module; 8 | class TLSDataOffsetLink; 9 | 10 | class ResolveTLSPass : public ChunkPass { 11 | private: 12 | Program *program; 13 | Module *module; 14 | public: 15 | virtual void visit(Program *program); 16 | virtual void visit(Module *module); 17 | virtual void visit(DataRegion *dataRegion); 18 | private: 19 | void resolveTLSLink(TLSDataOffsetLink *link); 20 | }; 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /src/pass/retpoline.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_RETPOLINE_H 2 | #define EGALITO_PASS_RETPOLINE_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include "chunkpass.h" 8 | 9 | class RetpolinePass : public ChunkPass { 10 | private: 11 | std::map retpolineList; 12 | Module *module; 13 | public: 14 | RetpolinePass() : module(nullptr) {} 15 | virtual void visit(Module *module); 16 | protected: 17 | virtual void visit(Function *function); 18 | private: 19 | void log_instruction(Instruction *instr, const char *message); 20 | Function *makeOutlinedTrampoline(Module *module, Instruction *instr); 21 | std::vector makeMovInstruction(Instruction *instr); 22 | }; 23 | 24 | #endif 25 | -------------------------------------------------------------------------------- /src/pass/run.cpp: -------------------------------------------------------------------------------- 1 | #include "run.h" 2 | -------------------------------------------------------------------------------- /src/pass/run.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_RUN_H 2 | #define EGALITO_PASS_RUN_H 3 | 4 | #include "util/timing.h" 5 | 6 | #if 1 // enable pass profiling 7 | #define RUN_PASS(passConstructor, module) \ 8 | { \ 9 | EgalitoTiming timing(#passConstructor); \ 10 | auto pass = passConstructor; \ 11 | module->accept(&pass); \ 12 | } 13 | #else 14 | #define RUN_PASS(passConstructor, module) \ 15 | { \ 16 | auto pass = passConstructor; \ 17 | module->accept(&pass); \ 18 | } 19 | #endif 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /src/pass/shadowstack.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_SHADOW_STACK_H 2 | #define EGALITO_PASS_SHADOW_STACK_H 3 | 4 | #include "chunkpass.h" 5 | 6 | class ShadowStackPass : public ChunkPass { 7 | public: 8 | enum Mode { 9 | MODE_CONST, 10 | MODE_GS, 11 | }; 12 | private: 13 | Mode mode; 14 | Function *violationTarget; 15 | Function *entryPoint; 16 | public: 17 | ShadowStackPass(Mode mode = MODE_CONST) : mode(mode), 18 | violationTarget(nullptr), entryPoint(nullptr) {} 19 | virtual void visit(Program *program); 20 | virtual void visit(Module *module); 21 | virtual void visit(Function *function); 22 | virtual void visit(Instruction *instruction); 23 | private: 24 | void pushToShadowStack(Function *function); 25 | void pushToShadowStackConst(Function *function); 26 | void pushToShadowStackGS(Function *function); 27 | void popFromShadowStack(Instruction *instruction); 28 | void popFromShadowStackConst(Instruction *instruction); 29 | void popFromShadowStackGS(Instruction *instruction); 30 | }; 31 | 32 | 33 | #endif 34 | -------------------------------------------------------------------------------- /src/pass/splitbasicblock.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_SPLIT_BASIC_BLOCK_H 2 | #define EGALITO_PASS_SPLIT_BASIC_BLOCK_H 3 | 4 | #include 5 | #include "chunkpass.h" 6 | #include "elf/reloc.h" 7 | 8 | class SplitBasicBlock : public ChunkPass { 9 | private: 10 | std::set splitPoints; 11 | public: 12 | SplitBasicBlock() {} 13 | virtual void visit(Function *function); 14 | private: 15 | void considerSplittingFor(Function *function, NormalLink *link); 16 | }; 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /src/pass/splitfunction.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_SPLITFUNCTION_H 2 | #define EGALITO_PASS_SPLITFUNCTION_H 3 | 4 | #include "chunkpass.h" 5 | 6 | class FunctionList; 7 | class Function; 8 | 9 | class SplitFunction : public ChunkPass { 10 | private: 11 | // must be an ordered container 12 | std::vector> splitPoints; 13 | public: 14 | SplitFunction() {} 15 | virtual void visit(FunctionList *functionList); 16 | virtual void visit(Function *function); 17 | }; 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /src/pass/stackextend.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_STACKEXTEND_H 2 | #define EGALITO_PASS_STACKEXTEND_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include "chunkpass.h" 8 | #include "analysis/controlflow.h" 9 | #include "elf/reloc.h" 10 | 11 | class ControlFlowInstruction; 12 | class FrameType; 13 | 14 | class StackExtendPass : public ChunkPass { 15 | private: 16 | size_t extendSize; 17 | const std::vector saveList; 18 | 19 | public: 20 | StackExtendPass(size_t extendSize, const std::vector saveList={}) 21 | : extendSize(extendSize), saveList(saveList) {} 22 | 23 | virtual void visit(Module *module); 24 | virtual void visit(Function *function); 25 | virtual void visit(Block *block) {} 26 | virtual void visit(Instruction *instruction) {} 27 | private: 28 | virtual bool shouldApply(Function *function) { return true; } 29 | // AARCH64 30 | void addExtendStack(Function *function, FrameType *frame); 31 | void addShrinkStack(Function *function, FrameType *frame); 32 | // X86_64 33 | void extendStack(Function *function, FrameType *frame); 34 | void adjustOffset(Instruction *instruction); 35 | 36 | virtual void useStack(Function *function, FrameType *frame) {}; 37 | }; 38 | 39 | #endif 40 | -------------------------------------------------------------------------------- /src/pass/stackxor.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_STACKXOR_H 2 | #define EGALITO_PASS_STACKXOR_H 3 | 4 | #include "chunkpass.h" 5 | #include "chunk/concrete.h" 6 | 7 | class StackXOR : public ChunkPass { 8 | private: 9 | int xorOffset; 10 | public: 11 | StackXOR(int xorOffset) : xorOffset(xorOffset) {} 12 | virtual void visit(Function *function); 13 | virtual void visit(Block *block); 14 | virtual void visit(Instruction *instruction); 15 | private: 16 | void addInstructions(Block *block, Instruction *instruction, 17 | bool beforeJumpTo); 18 | }; 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /src/pass/syscallsandbox.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_SYSCALL_SANDBOX_H 2 | #define EGALITO_PASS_SYSCALL_SANDBOX_H 3 | 4 | #include "chunkpass.h" 5 | 6 | class SyscallSandbox : public ChunkPass { 7 | private: 8 | Program *program; 9 | public: 10 | SyscallSandbox(Program *program) : program(program) {} 11 | virtual void visit(Function *function); 12 | private: 13 | void addEnforcement(Function *function, Instruction *syscallInstr, Function*enforce); 14 | }; 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /src/pass/twocodealloc.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_TWOCODE_ALLOC_H 2 | #define EGALITO_PASS_TWOCODE_ALLOC_H 3 | 4 | #include 5 | #include "chunkpass.h" 6 | 7 | class GSTable; 8 | class IFuncList; 9 | 10 | class TwocodeAllocPass : public ChunkPass { 11 | private: 12 | GSTable *gsTable; 13 | DataSection *gsArray; 14 | Function *gsAllocFunc; 15 | 16 | public: 17 | TwocodeAllocPass(GSTable *gsTable, DataSection *gsArray) 18 | : gsTable(gsTable), gsArray(gsArray), gsAllocFunc(nullptr) {} 19 | 20 | virtual void visit(Program *program); 21 | private: 22 | void createAllocationFunction(Module *module); 23 | }; 24 | 25 | #endif 26 | -------------------------------------------------------------------------------- /src/pass/twocodemerge.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_TWOCODEMERGE_H 2 | #define EGALITO_PASS_TWOCODEMERGE_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include "chunkpass.h" 8 | #include "chunk/dataregion.h" 9 | #include "chunk/function.h" 10 | #include "chunk/gstable.h" 11 | 12 | class TwocodeMergePass : public ChunkPass { 13 | private: 14 | Module *otherModule; 15 | std::vector transformed; 16 | std::set regionsNeeded; 17 | public: 18 | TwocodeMergePass(Module *otherModule) : otherModule(otherModule) {} 19 | 20 | virtual void visit(Module *module); 21 | private: 22 | bool updateLinks(Module *module, Function *otherFunc); 23 | 24 | void copyFunctionsTo(Module *module); 25 | void copyRegionsTo(Module *module); 26 | }; 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /src/pass/twocodevars.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_TWOCODEVARS_H 2 | #define EGALITO_PASS_TWOCODEVARS_H 3 | 4 | #include 5 | #include "chunkpass.h" 6 | #include "chunk/dataregion.h" 7 | #include "chunk/function.h" 8 | #include "chunk/gstable.h" 9 | 10 | class TwocodeVarsPass : public ChunkPass { 11 | private: 12 | GSTable *gsTable; 13 | Module *otherModule; 14 | DataSection *gsSection; 15 | public: 16 | TwocodeVarsPass(GSTable *gsTable, Module *otherModule) : gsTable(gsTable), 17 | otherModule(otherModule), gsSection(nullptr) {} 18 | 19 | virtual void visit(Module *module); 20 | DataSection *getGSSection() const { return gsSection; } 21 | private: 22 | static void addBaseSymbol(DataSection *section, const char *symbolName); 23 | static void addGSValue(DataSection *section, GSTableEntry *entry); 24 | static void addVariable(DataSection *section, Chunk *target, const char *suffix); 25 | }; 26 | 27 | #endif 28 | -------------------------------------------------------------------------------- /src/pass/updatelink.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_PASS_UPDATELINK_H 2 | #define EGALITO_PASS_UPDATELINK_H 3 | 4 | #include "chunkpass.h" 5 | 6 | class Function; 7 | 8 | class UpdateLink : public ChunkPass { 9 | private: 10 | Function *sourceFunction; 11 | public: 12 | UpdateLink() {} 13 | virtual void visit(Function *function); 14 | virtual void visit(Instruction *instruction); 15 | virtual void visit(DataRegion *dataRegion); 16 | private: 17 | Link *makeUpdateLink(Link *link, Function *source); 18 | }; 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /src/runtime/managegs.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_RUNTIME_MANAGE_GS_H 2 | #define EGALITO_RUNTIME_MANAGE_GS_H 3 | 4 | #include "chunk/gstable.h" 5 | 6 | class ManageGS { 7 | public: 8 | static void init(GSTable *gsTable); 9 | static void allocateBuffer(GSTable *gsTable); 10 | static void setGS(GSTable *gsTable); 11 | 12 | static void setEntry(GSTable *gsTable, GSTableEntry::IndexType index, 13 | address_t value); 14 | 15 | static address_t getEntry(GSTableEntry::IndexType offset); 16 | 17 | static void resetEntries(GSTable *gsTable, Chunk *callback); 18 | static Chunk *resolve(GSTable *gsTable, GSTableEntry::IndexType index); 19 | }; 20 | 21 | #endif 22 | -------------------------------------------------------------------------------- /src/snippet/bss.S: -------------------------------------------------------------------------------- 1 | #ifdef ARCH_AARCH64 2 | .text 3 | .global egalito_clear_addon_bss 4 | egalito_clear_addon_bss: 5 | adrp x0, :got:__bss_start__ 6 | ldr x1, [x0, #:got_lo12:__bss_start__] 7 | adrp x0, :got:__bss_end__ 8 | ldr x2, [x0, #:got_lo12:__bss_end__] 9 | sub x3, x2, x1 10 | cbz x3, 2f 11 | 1: 12 | str xzr, [x1], #8 13 | sub x3, x3, #8 14 | cbnz x3, 1b 15 | 2: 16 | ret 17 | .type egalito_clear_addon_bss, STT_FUNC 18 | .size egalito_clear_addon_bss, .-egalito_clear_addon_bss 19 | #endif 20 | -------------------------------------------------------------------------------- /src/snippet/hook.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_SNIPPET_HOOK_H 2 | #define EGALITO_SNIPPET_HOOK_H 3 | 4 | #include 5 | 6 | #ifdef __cplusplus 7 | extern "C" { 8 | #endif 9 | 10 | extern void (*egalito_hook_function_entry_hook)(unsigned long address); 11 | extern void (*egalito_hook_function_exit_hook)(unsigned long address); 12 | extern void (*egalito_hook_instruction_hook)(unsigned long address); 13 | 14 | static inline void set_function_entry_hook(void (*f)(unsigned long address)) { 15 | #ifndef ARCH_RISCV 16 | egalito_hook_function_entry_hook = f; 17 | #else 18 | assert(0); // no hooking support on RISC-V yet 19 | #endif 20 | } 21 | 22 | static inline void set_function_exit_hook(void (*f)(unsigned long address)) { 23 | #ifndef ARCH_RISCV 24 | egalito_hook_function_exit_hook = f; 25 | #else 26 | assert(0); // no hooking support on RISC-V yet 27 | #endif 28 | } 29 | 30 | static inline void set_instruction_hook(void (*f)(unsigned long address)) { 31 | #ifndef ARCH_RISCV 32 | egalito_hook_instruction_hook = f; 33 | #else 34 | assert(0); // no hooking support on RISC-V yet 35 | #endif 36 | } 37 | 38 | #ifdef __cplusplus 39 | } 40 | #endif 41 | #endif 42 | -------------------------------------------------------------------------------- /src/snippet/logfunction.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_SNIPPET_LOGFUNCTION_H 2 | #define EGALITO_SNIPPET_LOGFUNCTION_H 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | extern void egalito_log_function_entry(unsigned long address); 9 | extern void egalito_log_function_exit(unsigned long address); 10 | 11 | #ifdef __cplusplus 12 | } 13 | #endif 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /src/snippet/start2-aarch64.S: -------------------------------------------------------------------------------- 1 | .global _start2 2 | .global egalito_initial_stack 3 | .global egalito_entry 4 | 5 | .section .bss 6 | .align 8 7 | egalito_initial_stack: 8 | .skip 8 9 | .type egalito_initial_stack, STT_OBJECT 10 | .weak egalito_initial_stack 11 | egalito_entry: 12 | .skip 8 13 | .type egalito_entry, STT_OBJECT 14 | .weak egalito_entry 15 | 16 | .section .text 17 | # This has to be called in the target context 18 | _start2: 19 | .cfi_startproc 20 | bl egalito_callInit 21 | 22 | adrp x1, :got:egalito_initial_stack 23 | ldr x1, [x1, #:got_lo12:egalito_initial_stack] 24 | ldr x1, [x1] 25 | mov sp, x1 26 | mov x0, #0 27 | adrp x1, :got:egalito_entry 28 | ldr x1, [x1, #:got_lo12:egalito_entry] 29 | ldr x1, [x1] 30 | br x1 31 | bl abort 32 | .cfi_endproc 33 | .type _start2, STT_FUNC 34 | .size _start2, .-_start2 35 | -------------------------------------------------------------------------------- /src/snippet/start2-x86_64.S: -------------------------------------------------------------------------------- 1 | .global _start2 2 | .global egalito_initial_stack 3 | .global egalito_entry 4 | 5 | .section .bss 6 | egalito_initial_stack: 7 | .skip 8 8 | .type egalito_initial_stack, STT_OBJECT 9 | .weak egalito_initial_stack 10 | egalito_entry: 11 | .skip 8 12 | .type egalito_entry, STT_OBJECT 13 | .weak egalito_entry 14 | 15 | .section .text 16 | /* This has to be called in the target context */ 17 | _start2: 18 | .cfi_startproc 19 | .cfi_undefined %rip 20 | push %rbx /* keep alignment */ 21 | call *egalito_callInit@gotpcrel(%rip) 22 | pop %rbx 23 | 24 | mov egalito_initial_stack@gotpcrel(%rip), %rax 25 | mov (%rax), %rsp /* restore %rsp */ 26 | xor %rdx, %rdx /* clear for now since loader is static */ 27 | 28 | mov egalito_entry@gotpcrel(%rip), %rbx 29 | jmp *(%rbx) 30 | hlt 31 | .cfi_endproc 32 | .type _start2, STT_FUNC 33 | .size _start2, .-_start2 34 | 35 | -------------------------------------------------------------------------------- /src/snippet/syscall-iface.s: -------------------------------------------------------------------------------- 1 | # For sandbox enforcement, we turn each syscall instruction into this sequence. 2 | # See pass/syscallsandbox.cpp. 3 | # Note: this file is not linked in, we just include it here for reference. 4 | # Note: we don't save %xmm0 etc because functions with syscalls don't use them. 5 | push %rdi 6 | mov %rsp, %rdi 7 | and $-0x10, %rsp 8 | push %rdi 9 | mov 0x8(%rsp),%rdi 10 | push %rsi 11 | push %rdx 12 | push %r10 13 | push %r8 14 | push %r9 15 | push %rcx 16 | mov %r10, %rcx 17 | push %rax 18 | nop ; call enforce 19 | mov %rax, %r11 20 | pop %rax 21 | pop %rcx 22 | pop %r9 23 | pop %r8 24 | pop %r10 25 | pop %rdx 26 | pop %rsi 27 | pop %rdi 28 | mov %rdi, %rsp 29 | pop %rdi 30 | test %r11, %r11 31 | jz skip 32 | syscall 33 | skip: 34 | nop 35 | -------------------------------------------------------------------------------- /src/transform/data.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_LOAD_DATA_H 2 | #define EGALITO_LOAD_DATA_H 3 | 4 | #include "types.h" 5 | 6 | class DataRegion; 7 | 8 | class DataLoader { 9 | public: 10 | #ifdef USE_LOADER 11 | /** Returns thread pointer for this platform's TLS. 12 | offset will be incremented by the size of the header. 13 | */ 14 | address_t allocateTLS(address_t base, size_t size, size_t *offset); 15 | #endif 16 | void loadRegion(DataRegion *region); 17 | address_t loadRegionTo(address_t address, DataRegion *region); 18 | }; 19 | 20 | #endif 21 | -------------------------------------------------------------------------------- /src/transform/slot.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_TRANSFORM_SLOT_H 2 | #define EGALITO_TRANSFORM_SLOT_H 3 | 4 | #include "types.h" 5 | 6 | class Slot { 7 | private: 8 | address_t address; 9 | size_t size; 10 | public: 11 | Slot(address_t address, size_t size) 12 | : address(address), size(size) {} 13 | address_t getAddress() const { return address; } 14 | size_t getSize() const { return size; } 15 | }; 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /src/types.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_TYPES_H 2 | #define EGALITO_TYPES_H 3 | 4 | #include // for uint64_t 5 | #include // for size_t 6 | 7 | #ifdef ARCH_ARM 8 | typedef uint32_t address_t; 9 | typedef int32_t diff_t; 10 | #else 11 | typedef uint64_t address_t; 12 | typedef int64_t diff_t; 13 | #endif 14 | typedef std::size_t size_t; 15 | 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /src/util/explicit_bzero.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "config.h" 3 | 4 | #ifndef HAVE_EXPLICIT_BZERO 5 | void explicit_bzero(void *s, size_t n) { 6 | volatile char *p = s; 7 | while(n--) *p++ = 0; 8 | } 9 | #endif 10 | -------------------------------------------------------------------------------- /src/util/explicit_bzero.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_UTIL_EXPLICIT_BZERO 2 | #define EGALITO_UTIL_EXPLICIT_BZERO 3 | 4 | #ifdef __cplusplus 5 | extern "C" { 6 | #endif 7 | 8 | #ifndef HAVE_EXPLICIT_BZERO 9 | extern void explicit_bzero(void *s, size_t n); 10 | #endif 11 | 12 | #ifdef __cplusplus 13 | } 14 | #endif 15 | #endif 16 | -------------------------------------------------------------------------------- /src/util/feature.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_UTIL_FEATURE_H 2 | #define EGALITO_UTIL_FEATURE_H 3 | 4 | static inline bool isFeatureEnabled(const char *name) { 5 | const char *variable = getenv(name); 6 | 7 | return variable && strtol(variable, nullptr, 0) != 0; 8 | } 9 | 10 | #endif 11 | -------------------------------------------------------------------------------- /src/util/range.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_UTIL_RANGE_H 2 | #define EGALITO_UTIL_RANGE_H 3 | 4 | #include 5 | #include "types.h" 6 | 7 | class Range { 8 | private: 9 | address_t _start; 10 | size_t _size; 11 | public: 12 | Range() : _start(0), _size(0) {} 13 | Range(address_t start, size_t size) : _start(start), _size(size) {} 14 | 15 | address_t getStart() const { return _start; } 16 | address_t getEnd() const { return _start + _size; } 17 | size_t getSize() const { return _size; } 18 | 19 | bool contains(address_t point) const; 20 | bool contains(const Range &other) const; 21 | bool overlaps(address_t point) const; 22 | bool overlaps(const Range &other) const; 23 | 24 | bool endsWith(address_t point) const; 25 | 26 | bool operator < (address_t point) const; 27 | bool operator < (const Range &other) const; 28 | bool operator == (const Range &other) const; 29 | bool operator != (const Range &other) const; 30 | 31 | static Range fromPoint(address_t point); 32 | static Range fromEndpoints(address_t start, address_t end); 33 | }; 34 | 35 | bool operator < (address_t point, const Range &range); 36 | std::ostream &operator << (std::ostream &stream, const Range &range); 37 | 38 | #endif 39 | -------------------------------------------------------------------------------- /src/util/timing.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "timing.h" 3 | 4 | #undef DEBUG_GROUP 5 | #define DEBUG_GROUP dtiming 6 | #include "log/log.h" 7 | 8 | #include "cminus/print.h" 9 | 10 | extern bool egalito_init_done; 11 | EgalitoTiming::EgalitoTiming(const char *message, unsigned long printThresholdMS) 12 | : message(message), printThresholdMS(printThresholdMS) { 13 | 14 | startTime = std::chrono::high_resolution_clock::now(); 15 | } 16 | 17 | EgalitoTiming::~EgalitoTiming() { 18 | auto endTime = std::chrono::high_resolution_clock::now(); 19 | auto duration = std::chrono::duration_cast 20 | (endTime - startTime).count(); 21 | 22 | if(static_cast(duration / 1000) >= printThresholdMS) { 23 | if(!egalito_init_done) { 24 | CLOG(1, "TIMING: %8.6fs for \"%s\"", duration / 1e6, message); 25 | } 26 | else { 27 | egalito_printf("timing: %d ms %d us for \"%s\"\n", 28 | (int)(duration/1000), (int)(duration%1000), message); 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/util/timing.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_UTIL_TIMING_H 2 | #define EGALITO_UTIL_TIMING_H 3 | 4 | #include 5 | 6 | class EgalitoTiming { 7 | private: 8 | std::chrono::high_resolution_clock::time_point startTime; 9 | const char *message; 10 | unsigned long printThresholdMS; 11 | public: 12 | EgalitoTiming(const char *message, unsigned long printThresholdMS = 0); 13 | ~EgalitoTiming(); 14 | }; 15 | 16 | #endif 17 | -------------------------------------------------------------------------------- /test/Makefile: -------------------------------------------------------------------------------- 1 | # Makefile for egalito test code 2 | 3 | include ../env.mk 4 | 5 | DIRS = framework unit scripts codegen 6 | .PHONY: all $(DIRS) 7 | all: unit 8 | 9 | unit: framework 10 | 11 | $(DIRS): 12 | $(MAKE) -C $@ 13 | -------------------------------------------------------------------------------- /test/README.txt: -------------------------------------------------------------------------------- 1 | Test levels: 2 | - fast 3 | - normal 4 | - full 5 | -------------------------------------------------------------------------------- /test/codegen/.gitignore: -------------------------------------------------------------------------------- 1 | /tmp 2 | -------------------------------------------------------------------------------- /test/codegen/Makefile: -------------------------------------------------------------------------------- 1 | P_ARCH := $(shell uname -m) 2 | 3 | define x86_only 4 | $(if $(filter x86_64,$(P_ARCH)),$1) 5 | endef 6 | 7 | define aarch64_only 8 | $(if $(filter aarch64,$(P_ARCH)),$1) 9 | endef 10 | 11 | define arch_dep 12 | $(if $(filter x86_64,$(P_ARCH)), $1 x86_64-debian, $1 aarch64-openSuSE) 13 | endef 14 | 15 | .PHONY: test 16 | test: 17 | ./run-build.sh -m hello 18 | ./run-build.sh -m jumptable 19 | ./run-system.sh -m /bin/ls 20 | ./run-system.sh -m /bin/cat 21 | ./run-system.sh -m /bin/gzip 22 | ./run-system.sh -m /bin/grep 23 | ./run-system.sh -m /usr/bin/env 24 | ./run-system.sh -m /usr/bin/make 25 | ./run-system.sh -m /usr/bin/dpkg 26 | ./run-system.sh -m /usr/bin/find 27 | -------------------------------------------------------------------------------- /test/codegen/run-basic.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | mkdir -p tmp 3 | 4 | mode=$1 5 | prog=$2 6 | if [ -z "$mode" -o -z "$prog" ]; then 7 | echo "Usage: $0 mode test-program" 1>&2 8 | echo "test failed!" 9 | exit 1 10 | fi 11 | 12 | rm -f tmp/$prog{,.log,.out} 13 | ../../app/etelf $mode ../binary/build/$prog tmp/$prog > tmp/$prog.log 2>&1 14 | ./tmp/$prog > tmp/$prog.out 2>&1 15 | 16 | if [ -z "$(diff $prog.expected tmp/$prog.out)" ]; then 17 | echo "test passed" 18 | else 19 | echo "test failed!" 20 | exit 1 21 | fi 22 | -------------------------------------------------------------------------------- /test/codegen/run-build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | mkdir -p tmp 3 | 4 | mode=$1 5 | prog=$2 6 | shift 7 | shift 8 | if [ -z "$mode" -o -z "$prog" ]; then 9 | echo "Usage: $0 mode test-program" 1>&2 10 | echo "test failed!" 11 | exit 1 12 | fi 13 | 14 | rm -f tmp/$prog{,.log,.out,.expected} 15 | ../binary/build/$prog $@ > tmp/$prog.expected 2>&1 16 | ../../app/etelf $mode ../binary/build/$prog tmp/$prog > tmp/$prog.log 2>&1 17 | ./tmp/$prog $@ > tmp/$prog.out 2>&1 18 | 19 | if [ -z "$(diff tmp/$prog.expected tmp/$prog.out)" ]; then 20 | echo "test passed" 21 | else 22 | echo "test failed!" 23 | exit 1 24 | fi 25 | -------------------------------------------------------------------------------- /test/codegen/run-system.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | mkdir -p tmp 3 | 4 | mode=$1 5 | prog=$2 6 | if [ -z "$mode" -o -z "$prog" ]; then 7 | echo "Usage: $0 mode test-program" 1>&2 8 | echo "test failed!" 9 | exit 1 10 | fi 11 | base=tmp/$(basename $prog) 12 | 13 | rm -f $base{,.log,.out} 14 | ../../app/etelf $mode $prog $base > $base.log 2>&1 15 | $base --help > $base.out 2>&1 16 | 17 | if [ "$?" -eq 0 -a "$(cat $base.out | wc -l)" -gt 0 ]; then 18 | echo "test passed" 19 | else 20 | echo "test failed!" 21 | exit 1 22 | fi 23 | -------------------------------------------------------------------------------- /test/docker/.gitignore: -------------------------------------------------------------------------------- 1 | /qemu-*-static 2 | -------------------------------------------------------------------------------- /test/docker/Dockerfile_aarch64: -------------------------------------------------------------------------------- 1 | FROM aarch64/debian:testing 2 | 3 | MAINTAINER Miguel Arroyo miguel@cs.columbia.edu version: 0.1 4 | 5 | COPY qemu-aarch64-static /usr/bin/qemu-aarch64-static 6 | 7 | RUN apt-get update && apt-get install -y \ 8 | build-essential \ 9 | gdb \ 10 | git \ 11 | gosu \ 12 | libc6-dbg \ 13 | libcapstone-dev \ 14 | libreadline-dev \ 15 | libboost-python-dev \ 16 | && apt-get clean && rm -rf /var/lib/apt/lists/* 17 | 18 | COPY scripts/entrypoint.sh /usr/local/bin/entrypoint.sh 19 | ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] 20 | 21 | CMD ["/bin/bash"] 22 | -------------------------------------------------------------------------------- /test/docker/Dockerfile_arm: -------------------------------------------------------------------------------- 1 | FROM armhf/debian:testing 2 | 3 | MAINTAINER Miguel Arroyo miguel@cs.columbia.edu version: 0.1 4 | 5 | COPY qemu-arm-static /usr/bin/qemu-arm-static 6 | 7 | RUN apt-get update && apt-get install -y \ 8 | build-essential \ 9 | gdb \ 10 | git \ 11 | gosu \ 12 | libc6-dbg \ 13 | libcapstone-dev \ 14 | libreadline-dev \ 15 | libboost-python-dev \ 16 | && apt-get clean && rm -rf /var/lib/apt/lists/* 17 | 18 | COPY scripts/entrypoint.sh /usr/local/bin/entrypoint.sh 19 | ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] 20 | 21 | CMD ["/bin/bash"] -------------------------------------------------------------------------------- /test/docker/Dockerfile_x86_64: -------------------------------------------------------------------------------- 1 | FROM debian:testing 2 | 3 | MAINTAINER Miguel Arroyo miguel@cs.columbia.edu version: 0.1 4 | 5 | RUN apt-get update && apt-get install -y \ 6 | build-essential \ 7 | lsb-release \ 8 | gdb \ 9 | git \ 10 | gosu \ 11 | libc6-dbg \ 12 | libcapstone-dev \ 13 | libreadline-dev \ 14 | libboost-python-dev \ 15 | && apt-get clean && rm -rf /var/lib/apt/lists/* 16 | 17 | COPY scripts/entrypoint.sh /usr/local/bin/entrypoint.sh 18 | ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] 19 | 20 | CMD ["/bin/bash"] 21 | -------------------------------------------------------------------------------- /test/docker/Dockerfile_x86_64-aarch64: -------------------------------------------------------------------------------- 1 | FROM debian:testing 2 | 3 | MAINTAINER Miguel Arroyo miguel@cs.columbia.edu version: 0.1 4 | 5 | #RUN echo "deb http://emdebian.org/tools/debian/ testing main" >> /etc/apt/sources.list 6 | 7 | RUN dpkg --add-architecture arm64 && apt-get update && apt-get install -y \ 8 | build-essential:amd64 \ 9 | lsb-release:amd64 \ 10 | git:amd64 \ 11 | gdb:amd64 \ 12 | gosu:amd64 \ 13 | wget:amd64 \ 14 | libc6-dbg:amd64 \ 15 | libncurses5:amd64 \ 16 | libpython2.7:amd64 \ 17 | qemu-user-static:amd64 \ 18 | libcapstone-dev:arm64 \ 19 | libreadline-dev:arm64 \ 20 | && apt-get clean && rm -rf /var/lib/apt/lists/* 21 | 22 | COPY scripts/entrypoint.sh /usr/local/bin/entrypoint.sh 23 | ENTRYPOINT ["/usr/local/bin/entrypoint.sh"] 24 | 25 | #Install Linaro Cross Compile Toolchain 26 | RUN cd / && \ 27 | wget https://releases.linaro.org/components/toolchain/binaries/latest/aarch64-linux-gnu/gcc-linaro-6.3.1-2017.02-x86_64_aarch64-linux-gnu.tar.xz && \ 28 | tar xvf gcc-linaro-6.3.1-2017.02-x86_64_aarch64-linux-gnu.tar.xz 29 | 30 | RUN mkdir -p /eg-deps && cp -r /usr/include/capstone /eg-deps && cp -r /usr/lib/libcapstone.* /eg-deps 31 | 32 | CMD ["/bin/bash"] 33 | -------------------------------------------------------------------------------- /test/docker/README.md: -------------------------------------------------------------------------------- 1 | # README 2 | This directory includes the Dockerfiles for egalito images. There is one for each supported architecture. 3 | When cross-compiling, QEMU is required. Depending on your distro you will need the corresponding `qemu-$ARCH-static` for which you are trying to cross-compile. 4 | 5 | ### Arch Link 6 | `yaourt -S qemu-user-static` 7 | 8 | ### Debian 9 | `apt-get install qemu-user-static` 10 | -------------------------------------------------------------------------------- /test/docker/scripts/entrypoint.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Add local user 4 | # Either use the LOCAL_USER_ID if passed in at runtime or 5 | # fallback 6 | 7 | USER_ID=${LOCAL_USER_ID:-9001} 8 | 9 | echo "Starting with UID : $USER_ID" 10 | useradd --shell /bin/bash -u $USER_ID -o -c "" -m user 11 | usermod -a -G dialout user 12 | export HOME=/home/user 13 | mkdir -p $HOME/.ccache 14 | chown -R $USER_ID $HOME/.ccache 15 | export PATH=/gcc-linaro-6.3.1-2017.02-x86_64_aarch64-linux-gnu/bin:$PATH 16 | echo "PATH=/gcc-linaro-6.3.1-2017.02-x86_64_aarch64-linux-gnu/bin:$PATH" >> $HOME/.bashrc 17 | 18 | exec gosu user "$@" 19 | -------------------------------------------------------------------------------- /test/example/.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | /build_x86_64 3 | /build_aarch64 4 | 5 | *.c 6 | *.o 7 | 8 | /hellocpp 9 | -------------------------------------------------------------------------------- /test/example/cfg.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char **argv) 4 | { 5 | if(argc & 1) { 6 | for(int i = 0; i < argc; i++) { 7 | printf("%ld\n", (long)argv[i]); 8 | } 9 | } 10 | 11 | return 0; 12 | } 13 | -------------------------------------------------------------------------------- /test/example/detectnull.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int f(); 4 | int main(); 5 | 6 | int f() { 7 | printf("%lx %lx\n", (unsigned long)f, (unsigned long)main); 8 | return 11; 9 | } 10 | int main() { 11 | int (*p)() = 0;//f; 12 | return p(); 13 | } 14 | -------------------------------------------------------------------------------- /test/example/detectnullfail.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void egalito_null_ptr_check_fail(void) { 5 | printf("egalito null ptr check failed at 0x%lx\n", 6 | (unsigned long)__builtin_return_address(0)); 7 | exit(1); 8 | } 9 | -------------------------------------------------------------------------------- /test/example/firmware.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | puts("Hello, World!"); 5 | return 0; 6 | } 7 | -------------------------------------------------------------------------------- /test/example/fp.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void f() {} 4 | 5 | int main() { 6 | void (*p)() = f; 7 | p(); 8 | return 0; 9 | } 10 | -------------------------------------------------------------------------------- /test/example/getenv.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main(int argc, char **argv, char **envp) { 5 | printf("note: envp is %lx\n", (unsigned long)envp); 6 | printf("note: *envp is %s\n", *envp); 7 | printf("getenv: PATH=%s\n", getenv("PATH")); 8 | puts("iterating through envp manually:"); 9 | for(char **env = envp; *env; env ++) { 10 | puts(*env); 11 | } 12 | return 0; 13 | } 14 | -------------------------------------------------------------------------------- /test/example/global2.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int var_data = 42; 4 | int var_bss; 5 | const int var_rodata = 55; 6 | 7 | int main() { 8 | printf("var_data = %d\n", var_data); 9 | printf("var_bss = %d\n", var_bss); 10 | printf("var_rodata = %d\n", var_rodata); 11 | var_data = 43; 12 | var_bss = 1; 13 | printf("var_data = %d\n", var_data); 14 | printf("var_bss = %d\n", var_bss); 15 | return 0; 16 | } 17 | -------------------------------------------------------------------------------- /test/example/hello-obj.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int global = 0; 4 | int global2 = 0; 5 | int global3 = 1; 6 | int global4 = 1; 7 | int global5; 8 | 9 | 10 | int foo() { 11 | global = 1; 12 | return 1; 13 | } 14 | 15 | int main() { 16 | puts("Hello, World!"); 17 | return 0; 18 | } 19 | -------------------------------------------------------------------------------- /test/example/hello.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | puts("Hello, World!"); 5 | return 0; 6 | } 7 | -------------------------------------------------------------------------------- /test/example/hellocpp.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | std::cout << "Hello, World!" << std::endl; 5 | return 0; 6 | } 7 | -------------------------------------------------------------------------------- /test/example/hi0-s.S: -------------------------------------------------------------------------------- 1 | .global my_write 2 | my_write: 3 | #ifdef ARCH_X86_64 4 | push %rcx 5 | push %r11 6 | mov $1, %rax # write 7 | syscall # other args in %rdi, %rsi, %rdx 8 | pop %r11 9 | pop %rcx 10 | retq 11 | #elif defined(ARCH_AARCH64) 12 | mov x8, 64 13 | svc 0 14 | ret 15 | #elif defined(ARCH_ARM) 16 | mov r7, #4 17 | svc #0 18 | bx lr 19 | #endif 20 | 21 | .type my_write, STT_FUNC 22 | .size my_write, .-my_write 23 | -------------------------------------------------------------------------------- /test/example/hi0.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void my_write(int, const char *, size_t); 5 | 6 | int main() { 7 | const char *message = "Hello, World!\n"; 8 | int length = 0; 9 | while(message[length]) length ++; 10 | 11 | //syscall(SYS_write, STDOUT_FILENO, message, length); 12 | my_write(STDOUT_FILENO, message, length); 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /test/example/hi2.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | void greet(void) { 4 | puts("Hello, World!"); 5 | } 6 | 7 | int main() { 8 | greet(); 9 | return 0; 10 | } 11 | -------------------------------------------------------------------------------- /test/example/hi5-s.S: -------------------------------------------------------------------------------- 1 | .global my_write 2 | .global my_exit 3 | my_write: 4 | #ifdef ARCH_X86_64 5 | push %rcx 6 | push %r11 7 | mov $1, %rax # write 8 | syscall # other args in %rdi, %rsi, %rdx 9 | pop %r11 10 | pop %rcx 11 | retq 12 | #elif defined(ARCH_AARCH64) 13 | mov x8, 64 14 | svc 0 15 | ret 16 | #elif defined(ARCH_ARM) 17 | mov r7, #4 18 | svc 0 19 | bx lr 20 | #endif 21 | 22 | .type my_write, STT_FUNC 23 | .size my_write, .-my_write 24 | 25 | my_exit: 26 | #ifdef ARCH_X86_64 27 | mov $60, %rax # exit 28 | syscall 29 | #elif defined(ARCH_AARCH64) 30 | mov x8, 93 31 | svc 0 32 | ret 33 | #elif defined(ARCH_ARM) 34 | mov r7, #1 35 | svc #0 36 | #endif 37 | 38 | .type my_exit, STT_FUNC 39 | .size my_exit, .-my_exit 40 | -------------------------------------------------------------------------------- /test/example/hi5.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | void my_write(int, const char *, size_t); 5 | void my_exit(int); 6 | 7 | void _start() { 8 | const char *message = "XXHello, World!\n"+2; 9 | int length = 0; 10 | while(message[length]) length ++; 11 | 12 | //syscall(SYS_write, STDOUT_FILENO, message, length); 13 | my_write(STDOUT_FILENO, message, length); 14 | my_exit(-1); 15 | } 16 | -------------------------------------------------------------------------------- /test/example/islower.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #ifdef ARCH_X86_64 5 | #include 6 | #include 7 | 8 | extern int arch_prctl(int code, unsigned long *addr); 9 | #endif 10 | 11 | int main() { 12 | #ifdef ARCH_X86_64 13 | unsigned long fs; 14 | if(arch_prctl(ARCH_GET_FS, &fs) == 0) { 15 | printf("fs @ 0x%08lx\n", fs); 16 | } 17 | else { 18 | printf("ARCH_GET_FS error\n"); 19 | } 20 | #endif 21 | 22 | printf("'a' should be lowercase: %d\n", islower('a')); 23 | printf("'A' should not be lowercase: %d\n", islower('A')); 24 | return 0; 25 | } 26 | -------------------------------------------------------------------------------- /test/example/jumptable.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main(int argc, char **argv) { 4 | int x = 0; 5 | switch(argc) { 6 | case 1: 7 | x += 37; break; 8 | case 2: 9 | x += 47; break; 10 | case 4: 11 | printf("%d\n", x); 12 | x += 67; break; 13 | case 5: 14 | x += 17; break; 15 | case 6: 16 | printf("%d\n", x); 17 | x += 27; break; 18 | case 16: 19 | printf("%d\n", x); 20 | x += 273; break; 21 | case 26: 22 | x += 272; break; 23 | case 36: 24 | printf("%d\n", x); 25 | x += 271; break; 26 | } 27 | printf("%d\n", x); 28 | return 0; 29 | } 30 | -------------------------------------------------------------------------------- /test/example/log.c: -------------------------------------------------------------------------------- 1 | 2 | static void entryAdvice(void) __attribute__((used)); 3 | static void exitAdvice(void) __attribute__((used)); 4 | 5 | static int entry_count, exit_count; 6 | 7 | void entryAdvice(void) { entry_count++; } 8 | void exitAdvice(void) { exit_count++; } 9 | 10 | int main(void) 11 | { 12 | 13 | return 0; 14 | } 15 | -------------------------------------------------------------------------------- /test/example/sandbox-stage3.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int main() { 5 | void *p = mmap(0, 0x1000, PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); 6 | //mprotect(p, 0x1000, PROT_WRITE); 7 | unsigned int *pp = (unsigned int *)p; 8 | pp[0] = 0xfa1e0ff3; // endbr64 9 | pp[1] = 0xfeeb; // infinite loop 10 | 11 | mprotect(p, 0x1000, PROT_EXEC); 12 | void (*ppp)(void) = (void (*)(void))p; 13 | ppp(); 14 | return 0; 15 | } 16 | -------------------------------------------------------------------------------- /test/example/sandbox-write.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | int egalito_sandbox_syscall_1(int fd, const void *buf, size_t count) { 5 | void* frame = __builtin_frame_address(0); 6 | unsigned int syscall = *(unsigned int *)((unsigned long)frame + 2*sizeof(unsigned long)); 7 | return count > 10; 8 | } 9 | 10 | int egalito_sandbox_syscall_default(int fd, const void *buf, size_t count) { 11 | void* frame = __builtin_frame_address(0); 12 | unsigned int syscall = *(unsigned int *)((unsigned long)frame + 2*sizeof(unsigned long)); 13 | 14 | // can't use printf 15 | //printf("[invoking syscall %d]\n", syscall); 16 | 17 | char buffer[128] = "[invoking syscall "; 18 | size_t len = 18; 19 | buffer[len++] = (syscall / 100) % 10 + '0'; 20 | buffer[len++] = (syscall / 10) % 10 + '0'; 21 | buffer[len++] = syscall % 10 + '0'; 22 | buffer[len++] = ']'; 23 | buffer[len++] = '\n'; 24 | buffer[len] = 0; 25 | write(STDOUT_FILENO, buffer, len); 26 | 27 | return 1; /* allow syscall */ 28 | } 29 | 30 | int main() { 31 | printf("short 1!\n"); 32 | fflush(stdout); 33 | printf("Hello World!\n"); 34 | fflush(stdout); 35 | printf("short 2!\n"); 36 | fflush(stdout); 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /test/example/stderr.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() { 4 | printf("printf\n"); 5 | printf("printf\n"); 6 | fprintf(stdout, "fprintf(stdout)\n"); 7 | fprintf(stdout, "fprintf(stdout)\n"); 8 | fprintf(stderr, "fprintf(stderr)\n"); 9 | fprintf(stderr, "fprintf(stderr)\n"); 10 | return 0; 11 | } 12 | -------------------------------------------------------------------------------- /test/framework/.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | /.symlinks 3 | /libframework.a 4 | /build_x86_64 5 | /build_aarch64 6 | -------------------------------------------------------------------------------- /test/framework/include.h: -------------------------------------------------------------------------------- 1 | #ifndef EGALITO_TEST_FRAMEWORK_INCLUDE_H 2 | #define EGALITO_TEST_FRAMEWORK_INCLUDE_H 3 | 4 | #include "catch.hpp" 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /test/framework/runner.cpp: -------------------------------------------------------------------------------- 1 | #define CATCH_CONFIG_MAIN 2 | #include "catch.hpp" 3 | 4 | // main() will be auto-generated in this file 5 | -------------------------------------------------------------------------------- /test/integration/.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | /.symlinks 3 | /runner 4 | /build_x86_64 5 | /build_aarch64 6 | -------------------------------------------------------------------------------- /test/script/Makefile: -------------------------------------------------------------------------------- 1 | P_ARCH := $(shell uname -m) 2 | 3 | define x86_only 4 | $(if $(filter x86_64,$(P_ARCH)),$1) 5 | endef 6 | 7 | define aarch64_only 8 | $(if $(filter aarch64,$(P_ARCH)),$1) 9 | endef 10 | 11 | define arch_dep 12 | $(if $(filter x86_64,$(P_ARCH)), $1 x86_64-debian, $1 aarch64-openSuSE) 13 | endef 14 | 15 | .PHONY: test 16 | test: 17 | ./hello.sh 18 | ./argv.sh 19 | ./islower.sh 20 | ./jumptable-rtl.sh 21 | $(call arch_dep,./jumptable-libc.sh) 22 | ./environ.sh 23 | ./codeform.sh 24 | ./dwarf-diff.sh 25 | ./codeform-dwarf-syms.sh 26 | ./codeform-s.sh 27 | ./verify-redzone.sh 28 | ./codeform-debloat.sh 29 | ./hello-process.sh 30 | ./hello-thread.sh 31 | ./nginx.sh 32 | ./nginx-thread.sh 33 | $(call x86_only,./coreutils.sh) 34 | ./cout.sh 35 | ./sandbox-stage3.sh 36 | 37 | jt: 38 | $(call arch_dep,./jumptable-libc.sh) 39 | -------------------------------------------------------------------------------- /test/script/a2f.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | 3 | import subprocess 4 | import re 5 | import sys 6 | import collections 7 | import bisect 8 | 9 | p = subprocess.Popen(["readelf", "-s", "bin-symbols.elf"], 10 | stdout=subprocess.PIPE) 11 | # 0: 00000000004005e4 80 FUNC GLOBAL DEFAULT 3 libc_exit_fini$new 12 | 13 | sizes = {} 14 | a = collections.OrderedDict() 15 | for line in p.stdout.readlines(): 16 | m = re.search('\d+:\s+(\w+)\s+(\w+)\s.+\s(\w+)\\$new', line) 17 | if m: 18 | sizes[int(m.group(1), 16)] = int(m.group(2)) 19 | a[int(m.group(1), 16)] = m.group(3) 20 | 21 | address = collections.OrderedDict(sorted(a.iteritems())) 22 | #for k,v in address.items(): 23 | # print(hex(k), v) 24 | # print(hex(k + sizes[k])) 25 | 26 | for line in sys.stdin: 27 | m = re.search('(\w+)\s+([><])\s([_\w]+)', line) 28 | if m: 29 | if m.group(2) == '>': print '-->', 30 | else: print '<--', 31 | a = int(m.group(3), 16) 32 | #print format(a, 'X'), 33 | ind = bisect.bisect_right(address.keys(), a) 34 | if ind: 35 | #print ind, 36 | print address.values()[ind - 1], format(a, 'x') 37 | -------------------------------------------------------------------------------- /test/script/add-nops.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | mkdir tmp 2>/dev/null 3 | 4 | LD_LIBRARY_PATH=../../src EGALITO_DEBUG=/dev/null:disasm=9 ../../app/etshell >tmp/add-nops.out </dev/null 11 | 12 | if [ "$?" = 0 ]; then 13 | echo test passed 14 | else 15 | echo test failed! 16 | fi 17 | -------------------------------------------------------------------------------- /test/script/argv.expected: -------------------------------------------------------------------------------- 1 | argv[0] = "../binary/build/argv" 2 | argv[1] = "one" 3 | argv[2] = "two" 4 | argv[3] = "(null)" 5 | -------------------------------------------------------------------------------- /test/script/argv.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | mkdir -p tmp 3 | 4 | ln -sf ../../src/libegalito.so 5 | LD_LIBRARY_PATH=../../src EGALITO_DEBUG=/dev/null ../../src/loader \ 6 | ../binary/build/argv one two \ 7 | >tmp/argv.out 2>&1 8 | rm libegalito.so 9 | 10 | if [ -z "$(diff argv.expected tmp/argv.out)" ]; then 11 | echo "test passed" 12 | else 13 | echo "test failed!" 14 | exit 1 15 | fi 16 | -------------------------------------------------------------------------------- /test/script/codeform-debloat.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | mkdir -p tmp 3 | 4 | DIR=../binary/target/codeform/dir 5 | 6 | rm -f tmp/codeform.htm 7 | ln -sf ../../src/libegalito.so 8 | EGALITO_DEBLOAT=1 ../../src/loader $DIR/codeform \ 9 | -o tmp/codeform.htm $DIR/rules/c_1_html $DIR/codeform.c \ 10 | >tmp/codeform-run.log 2>&1 11 | rm libegalito.so 12 | 13 | if [ -z "$(diff $DIR/../codeform-expected.html tmp/codeform.htm 2>&1)" ]; then 14 | echo "test passed" 15 | else 16 | echo "test failed!" 17 | exit 1 18 | fi 19 | -------------------------------------------------------------------------------- /test/script/codeform-dwarf-syms.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | mkdir -p tmp 3 | 4 | DIR=../binary/target/codeform/dir 5 | 6 | LD_LIBRARY_PATH=../../src ../../app/etshell >tmp/codeform.sym <tmp/codeform-s.sym < tmp/codeform-sym.1 16 | perl -ne '/0x([0-9a-f]+) 0x([0-9a-f]+)/ && print "0x$1 0x$2\n"' tmp/codeform-s.sym > tmp/codeform-sym.2 17 | 18 | diff tmp/codeform-sym.{1,2} 19 | if [ -z "$(diff tmp/codeform-sym.1 tmp/codeform-sym.2)" ]; then 20 | echo "test passed" 21 | else 22 | echo "test failed!" 23 | exit 1 24 | fi 25 | -------------------------------------------------------------------------------- /test/script/codeform-s.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | mkdir -p tmp 3 | 4 | DIR=../binary/target/codeform/dir 5 | 6 | rm -f tmp/codeform.htm 7 | ln -sf ../../src/libegalito.so 8 | LD_LIBRARY_PATH=../../src ../../src/loader $DIR/codeform-s \ 9 | -o tmp/codeform.htm $DIR/rules/c_1_html $DIR/codeform.c \ 10 | >tmp/codeform-run.log 2>&1 11 | rm libegalito.so 12 | 13 | if [ -z "$(diff $DIR/../codeform-expected.html tmp/codeform.htm 2>&1)" ]; then 14 | echo "test passed" 15 | else 16 | echo "test failed!" 17 | exit 1 18 | fi 19 | -------------------------------------------------------------------------------- /test/script/codeform.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | mkdir -p tmp 3 | 4 | DIR=../binary/target/codeform/dir 5 | 6 | rm -f tmp/codeform.htm 7 | ln -sf ../../src/libegalito.so 8 | LD_LIBRARY_PATH=../../src ../../src/loader $DIR/codeform \ 9 | -o tmp/codeform.htm $DIR/rules/c_1_html $DIR/codeform.c \ 10 | >tmp/codeform-run.log 2>&1 11 | rm libegalito.so 12 | 13 | if [ -z "$(diff $DIR/../codeform-expected.html tmp/codeform.htm 2>&1)" ]; then 14 | echo "test passed" 15 | else 16 | echo "test failed!" 17 | exit 1 18 | fi 19 | -------------------------------------------------------------------------------- /test/script/compare-syms.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | mkdir -p tmp 3 | 4 | if [ -z "$1" -o -z "$2" ]; then 5 | echo Usage: $0 exec1 exec2 6 | exit 7 | fi 8 | 9 | LD_LIBRARY_PATH=../../src ../../app/etshell >tmp/symbols.1 <tmp/symbols.2 < tmp/symbols.1b 19 | perl -ne '/0x([0-9a-f]+) 0x([0-9a-f]+)/ && print "0x$1 0x$2\n"' tmp/symbols.2 > tmp/symbols.2b 20 | 21 | wc -l tmp/symbols.1b ; wc -l tmp/symbols.2b 22 | diff tmp/symbols.{1,2}b 23 | -------------------------------------------------------------------------------- /test/script/coreutils-relocs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | mkdir -p tmp 3 | 4 | cp -p ../../src/libegalito.so . 5 | cp -p ../../src/loader . 6 | rm -f tmp/coreutils.out 7 | touch tmp/coreutils.out 8 | for file in ../binary/target/coreutils/install/bin/*; do 9 | if [[ ${file: -2} == "-q" ]]; then 10 | continue 11 | fi 12 | #echo checking $file 13 | echo $file >> tmp/coreutils-relocs.out 14 | ./relocheck.sh $file 15 | if [[ $? == 1 ]]; then 16 | echo "test failed!" 17 | exit 1 18 | fi 19 | #read -p "continue?" yn 20 | #case $yn in 21 | #n) exit;; 22 | #*) ;; 23 | #esac 24 | done 25 | rm libegalito.so 26 | rm loader 27 | echo "test passed" 28 | -------------------------------------------------------------------------------- /test/script/coreutils.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | mkdir -p tmp 3 | 4 | # this takes a long time, so make a copy 5 | rm -f libegalito.so 6 | rm -f loader 7 | cp -p ../../src/libegalito.so . 8 | cp -p ../../src/loader . 9 | rm -f tmp/coreutils.out 10 | touch tmp/coreutils.out 11 | for file in ../binary/target/coreutils/install/bin/*; do 12 | if [[ ${file: -2} == "-q" ]]; then 13 | continue 14 | fi 15 | echo $file >> tmp/coreutils.out 16 | EGALITO_DEBUG=/dev/null ./loader \ 17 | $file --help \ 18 | >tmp/`basename $file`.out 2>&1 19 | if [[ $? != 0 && $? != 1 ]]; then 20 | echo "test failed!" 21 | exit $? 22 | fi 23 | done 24 | rm libegalito.so 25 | rm loader 26 | echo "test passed" 27 | -------------------------------------------------------------------------------- /test/script/cout.expected: -------------------------------------------------------------------------------- 1 | foo 2 | foo 3 | -------------------------------------------------------------------------------- /test/script/cout.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | mkdir -p tmp 3 | 4 | ln -sf ../../src/libegalito.so 5 | LD_LIBRARY_PATH=../../src EGALITO_DEBUG=/dev/null ../../src/loader \ 6 | ../binary/build/cout 2>&1 \ 7 | | tail -n 2 >tmp/cout.out 8 | rm libegalito.so 9 | 10 | if [ -z "$(diff cout.expected tmp/cout.out)" ]; then 11 | echo "test passed" 12 | else 13 | echo "test failed!" 14 | exit 1 15 | fi 16 | -------------------------------------------------------------------------------- /test/script/detectnull.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | mkdir tmp 2>/dev/null 3 | 4 | LD_LIBRARY_PATH=../../src ../../app/etshell >/dev/null </dev/null 3 | 4 | for program in ../binary/build/hello ../binary/target/codeform/dir/codeform; do 5 | LD_LIBRARY_PATH=../../src EGALITO_DEBUG=/dev/null:dwarf=20 ../../app/etshell >tmp/dwarf-diff.egalito <tmp/dwarf-diff.objdump 12 | cat tmp/dwarf-diff.egalito | sed '1,3 d' | head -n -1 > tmp/dwarf-diff.egalito.2 13 | diff -B tmp/dwarf-diff.objdump tmp/dwarf-diff.egalito.2 14 | 15 | if [ "$?" != 0 ]; then 16 | echo test failed, $program 17 | exit 1 18 | fi 19 | done 20 | 21 | echo test passed 22 | -------------------------------------------------------------------------------- /test/script/environ.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | mkdir tmp 2>/dev/null 3 | 4 | ln -sf ../../src/libegalito.so 5 | LD_LIBRARY_PATH=../../src EGALITO_DEBUG=/dev/null ../../src/loader \ 6 | ../binary/build/environ \ 7 | >tmp/environ.out 2>&1 8 | rm libegalito.so 9 | 10 | grep -q 'done' tmp/environ.out 11 | if [ "$?" = 0 ]; then 12 | echo test passed 13 | else 14 | echo test failed! 15 | exit 1 16 | fi 17 | -------------------------------------------------------------------------------- /test/script/hello-process.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | mkdir -p tmp 3 | 4 | ln -sf ../../src/libegalito.so 5 | LD_LIBRARY_PATH=../../src EGALITO_DEBUG=/dev/null ../../src/loader \ 6 | ../binary/build/fork \ 7 | >tmp/fork.out 2>&1 8 | rm libegalito.so 9 | 10 | grep -q "\[parent\] Hello, World!" tmp/fork.out 11 | if [ "$?" != 0 ]; then 12 | echo test failed! 13 | exit 1 14 | fi 15 | 16 | grep -q "\[child\] Hello, World!" tmp/fork.out 17 | if [ "$?" != 0 ]; then 18 | echo test failed! 19 | exit 1 20 | fi 21 | echo test passed 22 | -------------------------------------------------------------------------------- /test/script/hello-q.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | mkdir -p tmp 3 | 4 | ln -sf ../../src/libegalito.so 5 | LD_LIBRARY_PATH=../../src EGALITO_DEBUG=/dev/null ../../src/loader \ 6 | ../binary/build/hello-q \ 7 | >tmp/hello-q.out 2>&1 8 | rm libegalito.so 9 | 10 | if [ -z "$(diff hello.expected tmp/hello-q.out)" ]; then 11 | echo "test passed" 12 | else 13 | echo "test failed!" 14 | exit 1 15 | fi 16 | -------------------------------------------------------------------------------- /test/script/hello-thread.expected: -------------------------------------------------------------------------------- 1 | will reach a barrier 2 | will reach a barrier 3 | Hello, World! 4 | Hello, World! 5 | joining 6 | -------------------------------------------------------------------------------- /test/script/hello-thread.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | mkdir -p tmp 3 | 4 | ln -sf ../../src/libegalito.so 5 | LD_LIBRARY_PATH=../../src EGALITO_DEBUG=/dev/null ../../src/loader \ 6 | ../binary/build/thread \ 7 | >tmp/thread.out 2>&1 8 | rm libegalito.so 9 | 10 | if [ -z "$(diff hello-thread.expected tmp/thread.out)" ]; then 11 | echo "test passed" 12 | else 13 | echo "test failed!" 14 | exit 1 15 | fi 16 | -------------------------------------------------------------------------------- /test/script/hello.expected: -------------------------------------------------------------------------------- 1 | Hello, World! 2 | -------------------------------------------------------------------------------- /test/script/hello.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | mkdir -p tmp 3 | 4 | ln -sf ../../src/libegalito.so 5 | LD_LIBRARY_PATH=../../src EGALITO_DEBUG=/dev/null ../../src/loader \ 6 | ../binary/build/hello \ 7 | >tmp/hello.out 2>&1 8 | rm libegalito.so 9 | 10 | if [ -z "$(diff hello.expected tmp/hello.out)" ]; then 11 | echo "test passed" 12 | else 13 | echo "test failed!" 14 | exit 1 15 | fi 16 | -------------------------------------------------------------------------------- /test/script/hi5.expected: -------------------------------------------------------------------------------- 1 | Hello, World! 2 | -------------------------------------------------------------------------------- /test/script/islower.expected: -------------------------------------------------------------------------------- 1 | 'a' should be lowercase: 512 2 | 'A' should not be lowercase: 0 3 | -------------------------------------------------------------------------------- /test/script/islower.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | mkdir -p tmp 3 | 4 | ln -sf ../../src/libegalito.so 5 | LD_LIBRARY_PATH=../../src EGALITO_DEBUG=/dev/null ../../src/loader \ 6 | ../binary/build/islower 2>&1 \ 7 | | tail -n 2 >tmp/islower.out 8 | rm libegalito.so 9 | 10 | if [ -z "$(diff islower.expected tmp/islower.out)" ]; then 11 | echo "test passed" 12 | else 13 | echo "test failed! this is usually because callInitFunctions isn't running" 14 | exit 1 15 | fi 16 | -------------------------------------------------------------------------------- /test/script/jumptable-libc-mktable.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | find ../binary/x86_64-debian/libc -name '*.c.*' | grep -v 'elf/dl-' \ 4 | | xargs ./jumptables.pl \ 5 | | ./filterinside.pl ../binary/x86_64-debian/libc/libc.so.6 \ 6 | | grep -Ev '\[_dl_start\]' \ 7 | | sed 's/.*in //' | sort > ../binary/x86_64-debian/libc/table-list.txt 8 | -------------------------------------------------------------------------------- /test/script/jumptable-libc.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | arch=$1 3 | 4 | mkdir tmp 2>/dev/null 5 | 6 | ../../app/etshell >tmp/jumptable-libc.out < tmp/jumptable-libc.2 14 | 15 | ./jumptable-diff.pl ../binary/$arch/libc/libc.so.6 \ 16 | tmp/jumptable-libc.1 tmp/jumptable-libc.2 | tee tmp/jumptable-libc.diff 17 | 18 | if [ -z "$(cat tmp/jumptable-libc.diff)" ]; then 19 | echo test passed 20 | else 21 | echo test failed! 22 | exit 1 23 | fi 24 | -------------------------------------------------------------------------------- /test/script/jumptable-rtl.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | mkdir tmp 2>/dev/null 3 | 4 | ../../app/etshell >tmp/jumptable-rtl.out < tmp/jumptable-rtl.1 11 | perl -ne 'print if(s/jump table in //)' tmp/jumptable-rtl.out | sed 's/ at.* with / has /' | sort > tmp/jumptable-rtl.2 12 | 13 | rm -f jumptable.c.finalrtl 14 | 15 | if [ -z "$(diff tmp/jumptable-rtl.1 tmp/jumptable-rtl.2)" ]; then 16 | echo test passed 17 | else 18 | echo test failed! 19 | exit 1 20 | fi 21 | -------------------------------------------------------------------------------- /test/script/nginx-jitshuffle.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | filename=${1:-index.html} 4 | source ../binary/target/nginx/wrkparam.sh 5 | 6 | command -v wrk > /dev/null 2>&1 || { echo >&2 "needs wrk -- skipping"; exit 0; } 7 | 8 | mkdir -p tmp 9 | ln -sf ../../src/libegalito.so 10 | 11 | pidfile=../binary/target/nginx/nginx/logs/nginx.pid 12 | rm -f $pidfile 13 | 14 | LANG=C EGALITO_DEBLOAT=1 EGALITO_USE_GS=1 EGALITO_USE_SHUFFLING=1 \ 15 | ../../src/loader ../binary/target/nginx/nginx/sbin/nginx -c ../conf/nginx.conf >tmp/nginx-jitshuffle.out 2>& 1 & 16 | 17 | count=50 18 | while [ ! -f $pidfile ]; do 19 | sleep 1; 20 | count=$((count-1)) 21 | if [[ "$count" -eq 0 ]]; then 22 | echo "test failed"; 23 | exit 1; 24 | fi 25 | done 26 | #cat $pidfile 27 | 28 | wrk $wrkparam http://localhost:8000/$filename > tmp/nginx-jitshuffle-wrk.out 29 | 30 | kill -QUIT $( cat $pidfile ) 31 | kill -KILL $( cat $pidfile ) 32 | killall loader 33 | rm -f $pidfile 34 | 35 | #kill -QUIT $( cat $pidfile ) 36 | 37 | #count=50 38 | #while [ -f $pidfile ]; do 39 | #sleep 1; 40 | #if [[ "$count" -eq 0 ]]; then 41 | #echo "test failed"; 42 | #exit 1; 43 | #fi 44 | #done 45 | 46 | rm libegalito.so 47 | echo "test passed" 48 | -------------------------------------------------------------------------------- /test/script/nginx-thread-jitshuffle.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | filename=${1:-index.html} 4 | source ../binary/target/nginx/wrkparam.sh 5 | 6 | command -v wrk > /dev/null 2>&1 || { echo >&2 "needs wrk -- skipping"; exit 0; } 7 | 8 | mkdir -p tmp 9 | ln -sf ../../src/libegalito.so 10 | 11 | pidfile=../binary/target/nginx/nginx/logs/nginx.pid 12 | rm -f $pidfile 13 | 14 | EGALITO_DEBLOAT=1 EGALITO_USE_GS=1 EGALITO_USE_SHUFFLING=1 \ 15 | ../../src/loader ../binary/target/nginx/nginx/sbin/nginx -c ../conf-aio/nginx.conf >tmp/nginx-thread-jitshuffle.out 2>& 1 & 16 | 17 | count=50 18 | while [ ! -f $pidfile ]; do 19 | sleep 1; 20 | count=$((count-1)) 21 | if [[ "$count" -eq 0 ]]; then 22 | echo "test failed"; 23 | exit 1; 24 | fi 25 | done 26 | #cat $pidfile 27 | 28 | wrk $wrkparam http://localhost:8000/$filename > tmp/nginx-thread-jitshuffle-wrk.out 29 | 30 | kill -QUIT $( cat $pidfile ) 31 | kill -KILL $( cat $pidfile ) 32 | killall loader 33 | rm -f $pidfile 34 | 35 | #kill -QUIT $( cat $pidfile ) 36 | 37 | #count=50 38 | #while [ -f $pidfile ]; do 39 | #sleep 1; 40 | #if [[ "$count" -eq 0 ]]; then 41 | #echo "test failed"; 42 | #exit 1; 43 | #fi 44 | #done 45 | 46 | rm libegalito.so 47 | echo "test passed" 48 | -------------------------------------------------------------------------------- /test/script/nginx-thread.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | filename=${1:-index.html} 4 | source ../binary/target/nginx/wrkparam.sh 5 | 6 | command -v wrk > /dev/null 2>&1 || { echo >&2 "needs wrk -- skipping"; exit 0; } 7 | 8 | mkdir -p tmp 9 | ln -sf ../../src/libegalito.so 10 | 11 | pidfile=../binary/target/nginx/nginx/logs/nginx.pid 12 | 13 | ../../src/loader ../binary/target/nginx/nginx/sbin/nginx -c ../conf-aio/nginx.conf >tmp/nginx-thread.out 2>& 1 & 14 | 15 | count=50 16 | while [ ! -f $pidfile ]; do 17 | sleep 1; 18 | count=$((count-1)) 19 | if [[ "$count" -eq 0 ]]; then 20 | echo "test failed"; 21 | exit 1; 22 | fi 23 | done 24 | #cat $pidfile 25 | 26 | wrk $wrkparam http://localhost:8000/$filename > tmp/nginx-thread-wrk.out 27 | 28 | kill -QUIT $( cat $pidfile ) 29 | 30 | count=50 31 | while [ -f $pidfile ]; do 32 | sleep 1; 33 | if [[ "$count" -eq 0 ]]; then 34 | echo "test failed"; 35 | exit 1; 36 | fi 37 | done 38 | 39 | rm libegalito.so 40 | echo "test passed" 41 | -------------------------------------------------------------------------------- /test/script/nginx.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | filename=${1:-index.html} 4 | source ../binary/target/nginx/wrkparam.sh 5 | 6 | command -v wrk > /dev/null 2>&1 || { echo >&2 "needs wrk -- skipping"; exit 0; } 7 | 8 | mkdir -p tmp 9 | ln -sf ../../src/libegalito.so 10 | 11 | pidfile=../binary/target/nginx/nginx/logs/nginx.pid 12 | 13 | ../../src/loader ../binary/target/nginx/nginx/sbin/nginx -c ../conf/nginx.conf >tmp/nginx.out 2>& 1 & 14 | 15 | count=50 16 | while [ ! -f $pidfile ]; do 17 | sleep 1; 18 | count=$((count-1)) 19 | if [[ "$count" -eq 0 ]]; then 20 | echo "test failed"; 21 | exit 1; 22 | fi 23 | done 24 | #cat $pidfile 25 | 26 | wrk $wrkparam http://localhost:8000/$filename > tmp/nginx-wrk.out 27 | 28 | kill -QUIT $( cat $pidfile ) 29 | 30 | count=50 31 | while [ -f $pidfile ]; do 32 | sleep 1; 33 | if [[ "$count" -eq 0 ]]; then 34 | echo "test failed"; 35 | exit 1; 36 | fi 37 | done 38 | 39 | rm libegalito.so 40 | echo "test passed" 41 | -------------------------------------------------------------------------------- /test/script/relocheck.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | program=${1:-../binary/build/hello} 3 | name=`basename $program` 4 | 5 | rm -f tmp/$name-relocs-unsorted.txt \ 6 | tmp/$name-relocs.txt \ 7 | tmp/$name-q-relocs.txt 8 | mkdir -p tmp 9 | EGALITO_DEBUG=/dev/null EGALITO_CHECK=1 ../../app/etshell \ 10 | 2>tmp/$name-relocs-unsorted.txt \ 11 | >tmp/$name.out << EOF 12 | parse $program 13 | dumplinks module-(executable) 14 | EOF 15 | 16 | cat tmp/$name-relocs-unsorted.txt | awk '{ print $1, $2 }' | \ 17 | sort -n | uniq > tmp/$name-relocs.txt 18 | 19 | ./relocs.pl $program-q | awk '{ print $1, $2 }' | sort -n | uniq > tmp/$name-q-relocs.txt 20 | 21 | #diff -y tmp/$name-q-relocs.txt tmp/$name-relocs.txt 22 | #diff tmp/$name-q-relocs.txt tmp/$name-relocs.txt 23 | ./relocs-diff.pl $program tmp/$name-q-relocs.txt tmp/$name-relocs.txt > tmp/$name-relocs.diff 24 | grep -q " relocation " tmp/$name-relocs.diff 25 | if [ "$?" != 0 ]; then 26 | echo test passed 27 | else 28 | echo test failed! 29 | exit 1 30 | fi 31 | -------------------------------------------------------------------------------- /test/script/sandbox-stage3.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | mkdir -p tmp 3 | 4 | rm -f tmp/sandbox-stage3 5 | EGALITO_DEBUG=/dev/null ../../app/etshell > tmp/sandbox-stage3.out </dev/null 3 | 4 | ln -sf ../../src/libegalito.so ./libegalito.so || true 5 | EGALITO_LOG_INSTRUCTION_PASS=1 EGALITO_DEBUG=/dev/null ../../src/loader \ 6 | ../binary/target/redzone/redzone > tmp/redzone-output.txt 7 | rm ./libegalito.so 8 | 9 | grep -q "\[redzone_output\] 153295" tmp/redzone-output.txt 10 | 11 | if [ "$?" = 0 ]; then 12 | echo test passed 13 | else 14 | echo test failed! 15 | exit 1 16 | fi 17 | -------------------------------------------------------------------------------- /test/unit/.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | /.symlinks 3 | /runner 4 | /build_x86_64 5 | /build_aarch64 6 | -------------------------------------------------------------------------------- /test/unit/elf/_elfmap.cpp: -------------------------------------------------------------------------------- 1 | #include "framework/include.h" 2 | #include "elf/elfmap.h" 3 | 4 | TEST_CASE("Elf Parser Dynamic", "[elf][dyn]") { 5 | ElfMap elf(TESTDIR "hello"); 6 | CHECK(elf.isDynamic()); 7 | } 8 | -------------------------------------------------------------------------------- /test/unit/elf/_symbol.cpp: -------------------------------------------------------------------------------- 1 | #include "framework/include.h" 2 | #include "elf/elfmap.h" 3 | #include "elf/elfspace.h" 4 | #include "elf/symbol.h" 5 | 6 | TEST_CASE("Build Symbol List", "[elf][symbollist]") { 7 | ElfMap *elf = new ElfMap(TESTDIR "hello"); 8 | ElfSpace *elfSpace = new ElfSpace(elf, "", ""); 9 | 10 | SymbolList *symbolList = SymbolList::buildSymbolList(elf); 11 | CHECK(symbolList->getCount() > 0); 12 | } 13 | 14 | #if defined(ARCH_ARM) 15 | TEST_CASE("Mapping Symbol List ", "[elf][mappingsym]") { 16 | ElfMap *elf = new ElfMap(TESTDIR "hi5"); 17 | 18 | SymbolList *symbolList = SymbolList::buildSymbolList(elf); 19 | MappingSymbolList *mappingSymbolList = MappingSymbolList::buildMappingSymbolList(symbolList); 20 | 21 | CHECK(mappingSymbolList->getCount() > 0); 22 | } 23 | #endif 24 | -------------------------------------------------------------------------------- /test/unit/log/_temp.cpp: -------------------------------------------------------------------------------- 1 | #include "framework/include.h" 2 | #include "log/registry.h" 3 | #include "log/temp.h" 4 | 5 | TEST_CASE("set temporary log level", "[log][fast][.]") { 6 | GroupRegistry::getInstance()->muteAllSettings(); 7 | 8 | SECTION("single case") { 9 | TemporaryLogLevel tll("chunk", 10); 10 | CHECK(GroupRegistry::getInstance()->getSetting("chunk") == 10); 11 | } 12 | 13 | SECTION("nested case") { 14 | TemporaryLogLevel tll("chunk", 10); 15 | { 16 | TemporaryLogLevel tll("chunk", 20); 17 | CHECK(GroupRegistry::getInstance()->getSetting("chunk") == 20); 18 | } 19 | CHECK(GroupRegistry::getInstance()->getSetting("chunk") == 10); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /test/unit/pass/_promotejumps.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "framework/include.h" 3 | #include "pass/promotejumps.h" 4 | 5 | TEST_CASE("jump displacement fits-in range test", "[pass][fast][x86_64]") { 6 | #ifdef ARCH_X86_64 7 | CHECK(sizeof(address_t) == 8); 8 | 9 | CHECK(PromoteJumpsPass::fitsIn(1)); 10 | CHECK(PromoteJumpsPass::fitsIn(-1)); 11 | CHECK(PromoteJumpsPass::fitsIn(CHAR_MAX)); 12 | CHECK(PromoteJumpsPass::fitsIn(CHAR_MIN)); 13 | CHECK(!PromoteJumpsPass::fitsIn(CHAR_MAX+1)); 14 | CHECK(!PromoteJumpsPass::fitsIn(CHAR_MIN-1)); 15 | 16 | CHECK(PromoteJumpsPass::fitsIn(1000)); 17 | CHECK(PromoteJumpsPass::fitsIn(-1000)); 18 | CHECK(PromoteJumpsPass::fitsIn(INT_MAX)); 19 | CHECK(PromoteJumpsPass::fitsIn(INT_MIN)); 20 | CHECK(!PromoteJumpsPass::fitsIn(INT_MAX+1L)); 21 | CHECK(!PromoteJumpsPass::fitsIn(INT_MIN-1L)); 22 | 23 | CHECK(PromoteJumpsPass::fitsIn(LONG_MAX)); 24 | CHECK(PromoteJumpsPass::fitsIn(LONG_MIN)); 25 | CHECK(PromoteJumpsPass::fitsIn(ULONG_MAX)); 26 | #endif 27 | } 28 | -------------------------------------------------------------------------------- /travis_aarch64_config.mk: -------------------------------------------------------------------------------- 1 | CROSS=aarch64-linux-gnu- 2 | CAPSTONE_INC=/eg-deps 3 | CAPSTONE_LIB=/eg-deps 4 | RTLD_CROSS=qemu-aarch64-static -L /usr/aarch64-linux-gnu 5 | --------------------------------------------------------------------------------