├── clemency ├── .gitkeep ├── syscall │ └── d │ │ └── linux-clcy-64 ├── anal │ ├── d │ │ └── cc-clcy-64 │ └── anal_clcy.c ├── asm │ ├── asm_clcy.c │ └── d │ │ └── clcy ├── include │ ├── clemency.h │ ├── disasm.h │ ├── opfield-inc.h │ └── opcode-inc.h ├── Makefile ├── parse │ └── parse_clcy.c ├── core │ └── core_clcy.c ├── io │ └── io_clcy.c ├── debug │ └── debug_clcy.c ├── disasm.c └── bin │ └── bin_clcy.c ├── DEF CON 25 CTF Finals service binaries ├── half ├── rubix ├── babyecho ├── legitbbs ├── quarter ├── trackerd ├── babysfirst ├── internet3 └── picturemgr ├── .gitignore └── README.md /clemency/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /DEF CON 25 CTF Finals service binaries/half: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaskRay/r2cLEMENCy/HEAD/DEF CON 25 CTF Finals service binaries/half -------------------------------------------------------------------------------- /DEF CON 25 CTF Finals service binaries/rubix: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaskRay/r2cLEMENCy/HEAD/DEF CON 25 CTF Finals service binaries/rubix -------------------------------------------------------------------------------- /DEF CON 25 CTF Finals service binaries/babyecho: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaskRay/r2cLEMENCy/HEAD/DEF CON 25 CTF Finals service binaries/babyecho -------------------------------------------------------------------------------- /DEF CON 25 CTF Finals service binaries/legitbbs: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaskRay/r2cLEMENCy/HEAD/DEF CON 25 CTF Finals service binaries/legitbbs -------------------------------------------------------------------------------- /DEF CON 25 CTF Finals service binaries/quarter: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaskRay/r2cLEMENCy/HEAD/DEF CON 25 CTF Finals service binaries/quarter -------------------------------------------------------------------------------- /DEF CON 25 CTF Finals service binaries/trackerd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaskRay/r2cLEMENCy/HEAD/DEF CON 25 CTF Finals service binaries/trackerd -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.swo 3 | *.swp 4 | *.un~ 5 | *.dylib 6 | *.sdb 7 | *.so 8 | .ycm_extra_conf.py 9 | .dir-locals.el 10 | *dSYM 11 | tags 12 | -------------------------------------------------------------------------------- /DEF CON 25 CTF Finals service binaries/babysfirst: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaskRay/r2cLEMENCy/HEAD/DEF CON 25 CTF Finals service binaries/babysfirst -------------------------------------------------------------------------------- /DEF CON 25 CTF Finals service binaries/internet3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaskRay/r2cLEMENCy/HEAD/DEF CON 25 CTF Finals service binaries/internet3 -------------------------------------------------------------------------------- /DEF CON 25 CTF Finals service binaries/picturemgr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MaskRay/r2cLEMENCy/HEAD/DEF CON 25 CTF Finals service binaries/picturemgr -------------------------------------------------------------------------------- /clemency/syscall/d/linux-clcy-64: -------------------------------------------------------------------------------- 1 | _=0 2 | # I_rnd 3 | rnd=0,129 4 | # I_rndm 5 | rndm=0,130 6 | # I_rmp 7 | rmp=0,131 8 | # I_smp 9 | smp=0,132 10 | -------------------------------------------------------------------------------- /clemency/anal/d/cc-clcy-64: -------------------------------------------------------------------------------- 1 | default.cc=clcy 2 | 3 | clcy=cc 4 | cc.clcy.name=clcy 5 | cc.clcy.arg1=r0 6 | cc.clcy.arg2=r1 7 | cc.clcy.arg3=r2 8 | cc.clcy.arg4=r3 9 | cc.clcy.arg5=r4 10 | cc.clcy.arg6=r5 11 | cc.clcy.arg7=r6 12 | cc.clcy.arg8=r7 13 | cc.clcy.arg9=r8 14 | cc.clcy.ret=r0 -------------------------------------------------------------------------------- /clemency/asm/asm_clcy.c: -------------------------------------------------------------------------------- 1 | /* radare - LGPL - Copyright 2017 - xvilka, MaskRay */ 2 | #include 3 | 4 | #include "../include/disasm.h" 5 | 6 | static int _assemble(RAsm *a, RAsmOp *op, const char *src) { 7 | return assemble (a->pc, op, src); 8 | } 9 | 10 | static int _disassemble(RAsm *a, RAsmOp *op, const ut8 *src, int len) { 11 | return disassemble (a->pc, op, src, len, false); 12 | } 13 | 14 | static RAsmPlugin r_asm_plugin_clcy = { 15 | .name = "clcy", 16 | .desc = "cLEMENCy asm", 17 | .arch = "clcy", 18 | .license = "LGPL3", 19 | .bits = 64, // in accordance with r_anal_plugin_clcy 20 | .disassemble = _disassemble, 21 | .assemble = _assemble, 22 | }; 23 | 24 | RLibStruct radare_plugin = { 25 | .type = R_LIB_TYPE_ASM, 26 | .data = &r_asm_plugin_clcy, 27 | .version = R2_VERSION, 28 | }; 29 | -------------------------------------------------------------------------------- /clemency/include/clemency.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #define MASK_9 0x1ff 4 | #define MASK_18 0x3ffff 5 | #define MASK_27 0x7ffffff 6 | #define MASK_54 0x3fffffffffffffull 7 | #define BIT_26 (1L << 26) 8 | #define BIT_53 (1L << 53) 9 | #define PGSIZE 1024 10 | #define REG_ST 29 11 | 12 | enum { 13 | I_invalid = 0, 14 | #define INS(X, OPC) I_##X, 15 | #include "opcode-inc.h" 16 | #undef FORMAT 17 | #undef INS 18 | #undef INS_1 19 | #undef INS_2 20 | #undef INS_3 21 | #undef INS_4 22 | I__count 23 | }; 24 | 25 | enum { 26 | CC_n, 27 | CC_e, 28 | CC_l, 29 | CC_le, 30 | CC_g, 31 | CC_ge, 32 | CC_no, 33 | CC_o, 34 | CC_ns, 35 | CC_s, 36 | CC_sl, 37 | CC_sle, 38 | CC_sg, 39 | CC_sge, 40 | CC_invalid, 41 | CC_always, 42 | }; 43 | 44 | typedef struct { 45 | ut64 code, opcode; 46 | int id, size; 47 | ut32 pc, funct; 48 | st32 imm; 49 | ut16 cc, reg_count; 50 | ut8 adj_rb, arith_signed, is_imm, mem_flags, rA, rB, rC, rw, uf; 51 | } inst_t; 52 | 53 | extern const char *conditions[16]; 54 | extern const char *regs[32]; 55 | -------------------------------------------------------------------------------- /clemency/include/disasm.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "clemency.h" 4 | 5 | bool decode_R(inst_t *inst, const ut16 *src, int len); 6 | bool decode_R_IMM(inst_t *inst, const ut16 *src, int len); 7 | bool decode_U(inst_t *inst, const ut16 *src, int len); 8 | bool decode_BIN_R(inst_t *inst, const ut16 *src, int len); 9 | bool decode_BIN_R_IMM(inst_t *inst, const ut16 *src, int len); 10 | bool decode_MOV_LOW_HI(inst_t *inst, const ut16 *src, int len); 11 | bool decode_MOV_LOW_SIGNED(inst_t *inst, const ut16 *src, int len); 12 | bool decode_B_CC_OFF(inst_t *inst, const ut16 *src, int len); 13 | bool decode_B_CC_R(inst_t *inst, const ut16 *src, int len); 14 | bool decode_B_OFF(inst_t *inst, const ut16 *src, int len); 15 | bool decode_B_LOC(inst_t *inst, const ut16 *src, int len); 16 | bool decode_N(inst_t *inst, const ut16 *src, int len); 17 | bool decode_FLAGS_INTS(inst_t *inst, const ut16 *src, int len); 18 | bool decode_U_EXTEND(inst_t *inst, const ut16 *src, int len); 19 | bool decode_RANDOM(inst_t *inst, const ut16 *src, int len); 20 | bool decode_M(inst_t *inst, const ut16 *src, int len); 21 | bool decode_MP(inst_t *inst, const ut16 *src, int len); 22 | 23 | int parse_reg(const char **src); 24 | int assemble(ut64 pc, RAsmOp *op, const char *src); 25 | int disassemble(ut64 pc, RAsmOp *op, const ut8 *src, int len, bool pseudo); 26 | -------------------------------------------------------------------------------- /clemency/Makefile: -------------------------------------------------------------------------------- 1 | R2_LIBS := r_anal r_asm r_bin r_core r_io r_parse 2 | R2_CFLAGS ?= $(shell pkg-config --cflags $(R2_LIBS)) 3 | R2_LDFLAGS ?= $(shell pkg-config --libs $(R2_LIBS)) 4 | R2PM_PLUGDIR ?= $(shell r2 -H RHOMEDIR)/plugins 5 | R2PM_SHAREDIR ?= $(dir $(shell r2 -H MAGICPATH)) 6 | 7 | INSTALL := install 8 | LIBEXT ?= $(shell r2 -H LIBEXT) 9 | SDB ?= @echo 'Please set SDB to the path of `sdb` executable e.g. radare2/shlr/sdb/sdb' \# 10 | 11 | CFLAGS += -g -fPIC -std=gnu11 12 | LDFLAGS += -shared 13 | 14 | SO := anal/anal_clcy.$(LIBEXT) asm/asm_clcy.$(LIBEXT) bin/bin_clcy.$(LIBEXT) \ 15 | core/core_clcy.$(LIBEXT) io/io_clcy.$(LIBEXT) parse/parse_clcy.$(LIBEXT) #debug/debug_clcy.$(LIBEXT) 16 | 17 | DEPS := $(SO) anal/d/cc-clcy-64.sdb asm/d/clcy.sdb syscall/d/linux-clcy-64.sdb 18 | 19 | all: $(DEPS) 20 | 21 | info: 22 | @$(foreach i,R2_LIBS R2_CFLAGS R2_LDFLAGS R2PM_PLUGDIR R2PM_SHAREDIR,echo $(i)=$($i);) 23 | 24 | run: $(DEPS) 25 | r2 -a clcy $(RUNFLAGS) clcy://../third_party/clemency/hello.bin 26 | 27 | %.o: %.c include/*.h 28 | $(COMPILE.c) $(R2_CFLAGS) $(R2_LDFLAGS) $< -o $@ 29 | 30 | %.$(LIBEXT): %.o 31 | $(LINK.c) $(R2_CFLAGS) $(R2_LDFLAGS) $^ $(LDLIBS) -o $@ 32 | 33 | anal/anal_clcy.$(LIBEXT): disasm.o 34 | asm/asm_clcy.$(LIBEXT): disasm.o 35 | parse/parse_clcy.$(LIBEXT): disasm.o 36 | 37 | %.sdb: % 38 | $(SDB) $@ = < $^ 39 | 40 | clean: 41 | $(RM) $(DEPS) disasm.o 42 | 43 | $(R2PM_PLUGDIR): 44 | mkdir $@ 45 | 46 | install: $(DEPS) | $(R2PM_PLUGDIR) 47 | $(INSTALL) $(SO) $(R2PM_PLUGDIR)/ 48 | $(INSTALL) anal/d/cc-clcy-64.sdb $(R2PM_SHAREDIR)/fcnsign/ 49 | $(INSTALL) asm/d/clcy.sdb $(R2PM_SHAREDIR)/opcodes/ 50 | $(INSTALL) syscall/d/linux-clcy-64.sdb $(R2PM_SHAREDIR)/syscall/ 51 | 52 | symstall: $(DEPS) | $(R2PM_PLUGDIR) 53 | ln -sfr $(SO) $(R2PM_PLUGDIR)/ 54 | ln -sfr anal/d/cc-clcy-64.sdb $(R2PM_SHAREDIR)/fcnsign/ 55 | ln -sfr asm/d/clcy.sdb $(R2PM_SHAREDIR)/opcodes/ 56 | ln -sfr syscall/d/linux-clcy-64.sdb $(R2PM_SHAREDIR)/syscall/ 57 | 58 | uninstall: 59 | $(RM) $(foreach i,$(SO),${R2PM_PLUGDIR}/$(notdir $i)) $(R2PM_SHAREDIR)/fcnsign/cc-clcy-64.sdb $(R2PM_SHAREDIR)/opcodes/clcy.sdb $(R2PM_SHAREDIR)/syscall/linux-clcy-64.sdb 60 | 61 | .PHONY: all clean install run symstall uninstall 62 | -------------------------------------------------------------------------------- /clemency/include/opfield-inc.h: -------------------------------------------------------------------------------- 1 | #define FORM_R \ 2 | FIELD(opcode, 0, 7) \ 3 | FIELD(rA, 7, 5) \ 4 | FIELD(rB, 12, 5) \ 5 | FIELD(rC, 17, 5) \ 6 | FIELD(funct, 22, 2) \ 7 | FIELD(arith_signed, 24, 1) \ 8 | FIELD(is_imm, 25, 1) \ 9 | FIELD(uf, 26, 1) \ 10 | 11 | #define FORM_R_IMM \ 12 | FIELD(opcode, 0, 7) \ 13 | FIELD(rA, 7, 5) \ 14 | FIELD(rB, 12, 5) \ 15 | FIELD(imm, 17, 7) \ 16 | FIELD(arith_signed, 24, 1) \ 17 | FIELD(is_imm, 25, 1) \ 18 | FIELD(uf, 26, 1) \ 19 | 20 | #define FORM_U \ 21 | FIELD(opcode, 0, 9) \ 22 | FIELD(rA, 9, 5) \ 23 | FIELD(rB, 14, 5) \ 24 | FIELD(funct, 19, 7) \ 25 | FIELD(uf, 26, 1) \ 26 | 27 | #define FORM_BIN_R \ 28 | FIELD(opcode, 0, 8) \ 29 | FIELD(rA, 8, 5) \ 30 | FIELD(rB, 13, 5) \ 31 | 32 | #define FORM_BIN_R_IMM \ 33 | FIELD(opcode, 0, 8) \ 34 | FIELD(rA, 8, 5) \ 35 | FIELD(imm, 13, 14) \ 36 | 37 | #define FORM_MOV_LOW_HI \ 38 | FIELD(opcode, 0, 5) \ 39 | FIELD(rA, 5, 5) \ 40 | FIELD(imm, 10, 17) \ 41 | 42 | #define FORM_MOV_LOW_SIGNED \ 43 | FIELD(opcode, 0, 5) \ 44 | FIELD(rA, 5, 5) \ 45 | FIELD(imm, 10, 17) \ 46 | 47 | #define FORM_B_CC_OFF \ 48 | FIELD(opcode, 0, 6) \ 49 | FIELD(cc, 6, 4) \ 50 | FIELD(imm, 10, 17) \ 51 | 52 | #define FORM_B_CC_R \ 53 | FIELD(opcode, 0, 6) \ 54 | FIELD(cc, 6, 4) \ 55 | FIELD(rA, 10, 5) \ 56 | FIELD(funct, 15, 3) \ 57 | 58 | #define FORM_B_OFF \ 59 | FIELD(opcode, 0, 9) \ 60 | FIELD(imm, 9, 27) \ 61 | 62 | #define FORM_B_LOC \ 63 | FIELD(opcode, 0, 9) \ 64 | FIELD(imm, 9, 27) \ 65 | 66 | #define FORM_N \ 67 | FIELD(opcode, 0, 18) \ 68 | 69 | #define FORM_FLAGS_INTS \ 70 | FIELD(opcode, 0, 12) \ 71 | FIELD(rA, 12, 5) \ 72 | FIELD(funct, 17, 1) \ 73 | 74 | #define FORM_U_EXTEND \ 75 | FIELD(opcode, 0, 12) \ 76 | FIELD(rA, 12, 5) \ 77 | FIELD(rB, 17, 5) \ 78 | FIELD(funct, 22, 5) \ 79 | 80 | #define FORM_RANDOM \ 81 | FIELD(opcode, 0, 9) \ 82 | FIELD(rA, 9, 5) \ 83 | FIELD(funct, 14, 12) \ 84 | FIELD(uf, 26, 1) \ 85 | 86 | #define FORM_M \ 87 | FIELD(opcode, 0, 7) \ 88 | FIELD(rA, 7, 5) \ 89 | FIELD(rB, 12, 5) \ 90 | FIELD(reg_count, 17, 5) \ 91 | FIELD(adj_rb, 22, 2) \ 92 | FIELD(imm, 24, 27) \ 93 | FIELD(funct, 51, 3) \ 94 | 95 | #define FORM_MP \ 96 | FIELD(opcode, 0, 7) \ 97 | FIELD(rA, 7, 5) \ 98 | FIELD(rB, 12, 5) \ 99 | FIELD(rw, 17, 1) \ 100 | FIELD(mem_flags, 18, 2) \ 101 | FIELD(funct, 20, 7) \ 102 | 103 | -------------------------------------------------------------------------------- /clemency/parse/parse_clcy.c: -------------------------------------------------------------------------------- 1 | /* radare - LGPL - Copyright 2017 - MaskRay */ 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "../include/disasm.h" 11 | 12 | static int _parse(RParse *p, const char *src, char *dst) { 13 | RCore *core = p->user; 14 | RAsmOp op; 15 | int len; 16 | // `assemble` could be saved if we had access to metadata of previous call to `assemble` 17 | if ((len = assemble (core->assembler->pc, &op, src)) > 0 && 18 | disassemble (core->assembler->pc, &op, op.buf, len, true) > 0) { 19 | strcpy (dst, op.buf_asm); 20 | } else { 21 | strcpy (dst, src); 22 | } 23 | return true; 24 | } 25 | 26 | static bool _varsub(RParse *p, RAnalFunction *f, ut64 addr, int oplen, char *src, char *dst, int len) { 27 | RList *spargs = NULL, *bpargs = NULL, *regargs = NULL; 28 | RListIter *iter; 29 | RAnalVar *var; 30 | char *str = strdup (src), *sub, *replace; 31 | bool ret = true; 32 | if (!str) { 33 | goto err; 34 | } 35 | if (p->relsub) { 36 | // TODO Support asm.relsub 37 | } 38 | 39 | regargs = p->varlist (p->anal, f, 'r'); 40 | bpargs = p->varlist (p->anal, f, 'b'); 41 | spargs = p->varlist (p->anal, f, 's'); 42 | 43 | // Stack register variable st+%#x 44 | r_list_foreach (spargs, iter, var) { 45 | if (var->delta >= 0) { 46 | sub = r_str_newf ("[st+%#x", var->delta); 47 | } else { 48 | sub = r_str_newf ("[st-%#x", -var->delta); 49 | } 50 | if (!sub) { 51 | goto err; 52 | } 53 | if (strstr (str, sub)) { 54 | replace = r_str_newf ("[st %c %s", var->delta >= 0 ? '+' : '-', var->name); 55 | str = r_str_replace (str, sub, replace, 0); 56 | free (replace); 57 | } 58 | free (sub); 59 | } 60 | 61 | // Frame register variable r28+%#x 62 | r_list_foreach (bpargs, iter, var) { 63 | if (var->delta >= 0) { 64 | sub = r_str_newf ("[r28+%#x", var->delta); 65 | } else { 66 | sub = r_str_newf ("[r28-%#x", -var->delta); 67 | } 68 | if (!sub) { 69 | goto err; 70 | } 71 | if (strstr (str, sub)) { 72 | replace = r_str_newf ("[r28 %c %s", var->delta >= 0 ? '+' : '-', var->name); 73 | str = r_str_replace (str, sub, replace, 0); 74 | free (replace); 75 | } 76 | free (sub); 77 | } 78 | 79 | r_list_foreach (regargs, iter, var) { 80 | RRegItem *r = r_reg_index_get (p->anal->reg, var->delta); 81 | if (r && r->name && strstr (str, r->name)) { 82 | str = r_str_replace (str, r->name, var->name, 1); 83 | } 84 | } 85 | 86 | if (strlen (str) >= len) { 87 | goto err; 88 | } 89 | r_str_ncpy (dst, str, len); 90 | 91 | out: 92 | r_list_free (spargs); 93 | r_list_free (bpargs); 94 | r_list_free (regargs); 95 | free (str); 96 | return ret; 97 | 98 | err: 99 | ret = false; 100 | goto out; 101 | } 102 | 103 | RParsePlugin r_parse_plugin_clcy = { 104 | .name = "clcy", 105 | .desc = "cLEMENCy pseudo syntax", 106 | .parse = _parse, 107 | .varsub = _varsub, 108 | }; 109 | 110 | RLibStruct radare_plugin = { 111 | .type = R_LIB_TYPE_PARSE, 112 | .data = &r_parse_plugin_clcy, 113 | .version = R2_VERSION, 114 | }; 115 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # r2cLEMENCy 2 | 3 | DEF CON 25 CTF Finals, organized by Legitimate Business Syndicate, used a brand new architecture called [cLEMENCy](https://github.com/legitbs/cLEMENCy). It features many bizarre designs: 4 | 5 | * 9-bit bytes (referred as nytes) 6 | * 27-bit general-purpose registers 7 | * Middle-endian 8 | + A word of 2 nytes is represented as `a[1] << 9 | a[0]` 9 | + A word of 3 nytes is represented as `a[1] << 27 | a[2] << 18 | a[0]` 10 | * Variable length instructions (18,27,36,54 bits) which are serialized in middle-endian. Opcodes are between 5 bits and 18 bits. 11 | 12 | Memory mappings: 13 | 14 | ``` 15 | [0000000,4000000) Main Program Memory 16 | [4000000,400001e) Clock IO 17 | [4010000,4011000) Flag IO 18 | [5000000,5002000) Data Received 19 | [5002000,5002003) Data Received Size 20 | [5010000,5012000) Data Sent 21 | [5012000,5012003) Data Sent Size 22 | [5100000,5104000) NFO file 23 | [7ffff00,7ffff1c) Interrupt Pointers 24 | [7ffff80,8000000) Processor Identification and Features 25 | ``` 26 | 27 | This repository contains a bunch of radare2 plugins for cLEMENCy. 28 | 29 | ## Building 30 | 31 | This repository can be built either standalone or as a subdirectory of radare2-extras. 32 | 33 | ### Standalone 34 | 35 | Specify `PKG_CONFIG_PATH` if you install radare2 to a user directory. 36 | 37 | ```zsh 38 | # cd clemency 39 | PKG_CONFIG_PATH=~/.config/radare2/prefix/lib/pkgconfig make 40 | ``` 41 | 42 | ### Subdirectory of radare2-extras 43 | 44 | ```zsh 45 | (cd .. # cd radare2-extras 46 | ./configure --prefix=~/.config/radare2/prefix # generates options.mk 47 | ) 48 | make 49 | ``` 50 | 51 | `make info` to see used environment variables. 52 | 53 | ## Installation 54 | 55 | * `make symstall`: install symlinks to `R2PM_PLUGDIR` and `R2PM_SHAREDIR` 56 | * `make install`: install files 57 | 58 | ## Usage 59 | 60 | [DEF CON CTF 2017 Final Scores and Data Dumps](https://blog.legitbs.net/2017/07/def-con-ctf-2017-final-scores-and-data.html) 61 | 62 | `DEF CON 25 CTF Finals service binaries/` contains service binaries used in DEF CON CTF Finals. 63 | 64 | ```zsh 65 | r2 -e asm.parser=clcy -e asm.midflags=1 -a clcy clcy:///tmp/babyecho 66 | ``` 67 | 68 | ## Components 69 | 70 | * `io/io_clcy.c`: expands 9-bit to 16-bit and unexpands 16-bit when closing 71 | * `core/core_clcy.c`: hexdump commands tailored to 9-bit 72 | * `bin/bin_clcy.c`: creates sections for cLEMENCy memory mappings, and sets up the NFO section 73 | * `asm/asm_clcy.c`: disassembler and assembler. `include/opcode-inc.h` is taken from https://github.com/pwning/defcon25-public by Plaid Parliament of Pwning 74 | * `anal/anal_clcy.c`: instruction classifier and ESIL translator 75 | * `parse/parse_clcy.c`: C-like pseudo disassembler and variable substituter 76 | 77 | ![](https://ptpb.pw/XeC6.jpg) 78 | 79 | ## Features 80 | 81 | `io_clcy` 82 | 83 | * Expand 9-bit to 16-bit 84 | 85 | `bin_clcy` 86 | 87 | * Loader: `om` 88 | 89 | `core_clcy` 90 | 91 | * 9-bit hexdump: `_px` `_pw` `_pt` 92 | 93 | `asm_clcy` 94 | 95 | * Disassembler: `pd` 96 | * Instruction descriptions: `e asm.describe=1` 97 | * Assembler: `e io.cache=1; wa ldt r1, [r0+0x57, 5]` 98 | 99 | `anal_clcy` 100 | 101 | * Instruction analyzer 102 | * ESIL translator: `e asm.emu=1` 103 | 104 | `parse_clcy` 105 | 106 | * C-like pseudo disassembler: `aa; pdc` 107 | -------------------------------------------------------------------------------- /clemency/core/core_clcy.c: -------------------------------------------------------------------------------- 1 | /* radare - LGPL - Copyright 2017 - pancake */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | 11 | #include "../include/clemency.h" 12 | 13 | static void clcy_help(RCore *core) { 14 | eprintf ("cLEMENCy command:\n"); 15 | eprintf ("_x 9bit hexdump\n"); 16 | eprintf ("_xw 18bit hexdump\n"); 17 | eprintf ("_xt 27bit hexdump\n"); 18 | } 19 | 20 | static void hexdump_9byte(RCore *core, const char *arg, int len) { 21 | ut32 tbs = core->blocksize; 22 | if (len != tbs && !r_core_block_size (core, len)) 23 | return; 24 | ut16 *buf = malloc (len); 25 | r_io_read_at (core->io, core->offset, (ut8 *)buf, len); 26 | for (int i = 0; (i + 1) * 2 <= len; i++) { 27 | if (i % 16 == 0) { 28 | if (i) r_cons_newline (); 29 | r_cons_printf ("0x%08"PFMT64x":", core->offset + i); 30 | } 31 | r_cons_printf (" %03x", buf[i]); 32 | } 33 | r_cons_newline (); 34 | free (buf); 35 | if (len != tbs) 36 | r_core_block_size (core, tbs); 37 | } 38 | 39 | static void hexdump_18word(RCore *core, const char *arg, int len) { 40 | ut32 tbs = core->blocksize; 41 | if (len != tbs && !r_core_block_size (core, len)) 42 | return; 43 | ut16 *buf = malloc (len); 44 | r_io_read_at (core->io, core->offset, (ut8 *)buf, len); 45 | for (int i = 0; (i + 1) * 4 <= len; i++) { 46 | if (i % 8 == 0) { 47 | if (i) r_cons_newline (); 48 | r_cons_printf ("0x%08"PFMT64x":", core->offset + i * 2); 49 | } 50 | r_cons_printf (" %05x", buf[i*2+1] << 9 | buf[i*2]); 51 | } 52 | r_cons_newline (); 53 | free (buf); 54 | if (len != tbs) 55 | r_core_block_size (core, tbs); 56 | } 57 | 58 | static void hexdump_27tri(RCore *core, const char *arg, int len) { 59 | ut32 tbs = core->blocksize; 60 | if (len != tbs && !r_core_block_size (core, len)) 61 | return; 62 | ut16 *buf = malloc (len); 63 | r_io_read_at (core->io, core->offset, (ut8 *)buf, len); 64 | for (int i = 0; (i + 1) * 6 <= len; i++) { 65 | if (i % 8 == 0) { 66 | if (i) r_cons_newline (); 67 | r_cons_printf ("0x%08"PFMT64x":", core->offset + i * 3); 68 | } 69 | r_cons_printf (" %07x", buf[i*3+1] << 18 | buf[i*3] << 9 | buf[i*3+2]); 70 | } 71 | r_cons_newline (); 72 | free (buf); 73 | if (len != tbs) 74 | r_core_block_size (core, tbs); 75 | } 76 | 77 | static int r_cmd_clcy(void *user, const char *input) { 78 | RCore *core = (RCore *)user; 79 | if (input[0] == '_') { 80 | switch (input[1]) { 81 | case 'x': // "_x" 82 | switch (input[2]) { 83 | case '\0': 84 | case ' ': 85 | r_core_cmdf (core, "_p %s", input[1] ? input + 2 : ""); 86 | break; 87 | case 't': 88 | r_core_cmdf (core, "_pt %s", input[2] ? input + 3 : ""); 89 | break; 90 | case 'w': 91 | r_core_cmdf (core, "_pw %s", input[2] ? input + 3 : ""); 92 | break; 93 | default: 94 | clcy_help (core); 95 | break; 96 | } 97 | break; 98 | case 'p': // "_p" 99 | switch (input[2]) { 100 | case '\0': 101 | case ' ': 102 | case 'x': { 103 | int l = input[3] == ' ' ? (int) r_num_math (core->num, input + 4) * 2 104 | : core->blocksize; 105 | hexdump_9byte (core, input, l); 106 | break; 107 | } 108 | case 't': { 109 | int l = input[3] == ' ' ? (int) r_num_math (core->num, input + 4) * 6 110 | : core->blocksize; 111 | hexdump_27tri (core, input, l); 112 | break; 113 | } 114 | case 'w': { 115 | int l = input[3] == ' ' ? (int) r_num_math (core->num, input + 4) * 4 116 | : core->blocksize; 117 | hexdump_18word (core, input, l); 118 | break; 119 | } 120 | default: 121 | clcy_help (core); 122 | break; 123 | } 124 | break; 125 | default: 126 | clcy_help (core); 127 | break; 128 | } 129 | return true; 130 | } 131 | return false; 132 | } 133 | 134 | RCorePlugin r_core_plugin_clcy = { 135 | .name = "clcy", 136 | .desc = "cLEMENCy core", 137 | .license = "LGPL3", 138 | .call = r_cmd_clcy, 139 | }; 140 | 141 | RLibStruct radare_plugin = { 142 | .type = R_LIB_TYPE_CORE, 143 | .data = &r_core_plugin_clcy, 144 | .version = R2_VERSION 145 | }; 146 | -------------------------------------------------------------------------------- /clemency/io/io_clcy.c: -------------------------------------------------------------------------------- 1 | /* radare - LGPL - Copyright 2017 - pancake, MaskRay */ 2 | #include 3 | #include 4 | 5 | #include 6 | #include 7 | 8 | typedef struct r_io_mmo_t { 9 | char *filename; 10 | ut16 *buf; 11 | ut64 size; 12 | int fd; 13 | int flags; 14 | int mode; 15 | bool dirty; 16 | } RIOMMapFileObj; 17 | 18 | extern RIOPlugin r_io_plugin_clcy; 19 | 20 | static bool _check_default(const char *filename) { 21 | return !strncmp (filename, "clcy://", 7); 22 | } 23 | 24 | static bool _check(RIO *io, const char *filename, bool many) { 25 | return _check_default (filename); 26 | } 27 | 28 | static int _close(RIODesc *fd) { 29 | if (!fd || !fd->data) return -1; 30 | RIOMMapFileObj *mmo = fd->data; 31 | if (mmo->dirty) { 32 | ut64 x = 0, l = 0, n_buf = 0, i; 33 | bool ok = true; 34 | for (i = 0; i < mmo->size; i++) { 35 | if (mmo->buf[i] >= 512) { 36 | ok = false; 37 | eprintf ("io_clcy: 16-bit at offset %"PFMT64x" >= 512", i); 38 | break; 39 | } 40 | x = x << 9 | mmo->buf[i]; 41 | l += 9; 42 | while (l >= 8) { 43 | l -= 8; 44 | ((ut8 *)mmo->buf)[n_buf++] = x >> l; 45 | x &= (1LL << l) - 1; 46 | } 47 | } 48 | if (ok) { 49 | ssize_t t; 50 | if (l) 51 | ((ut8 *)mmo->buf)[n_buf++] = x << 8-l; 52 | if (lseek (mmo->fd, 0, SEEK_SET) == -1) { 53 | eprintf ("io_clcy lseek: %s\n", strerror (errno)); 54 | } else if ((t = write (mmo->fd, mmo->buf, n_buf)) != n_buf) { 55 | eprintf ("io_clcy: written %zd bytes, %s\n", t, strerror (errno)); 56 | } else if (ftruncate (mmo->fd, n_buf) == -1) { 57 | eprintf ("io_clcy ftruncate: %s\n", strerror (errno)); 58 | } 59 | } 60 | } 61 | close (mmo->fd); 62 | free (mmo->buf); 63 | free (mmo->filename); 64 | free (mmo); 65 | fd->data = NULL; 66 | return 0; 67 | } 68 | 69 | static int _extend(RIO *io, RIODesc *fd, ut64 extend) { 70 | RIOMMapFileObj *mmo = fd->data; 71 | ut64 addr = io->off, size = mmo->size; 72 | ut16 *buf = realloc (mmo->buf, (size + extend) * 2); 73 | if (!buf) return -1; 74 | mmo->buf = buf; 75 | memmove (&mmo->buf[addr + extend], &mmo->buf[addr], (size - addr) * 2); 76 | memset (&mmo->buf[addr], 0, extend * 2); 77 | mmo->size += extend; 78 | mmo->dirty = true; 79 | return extend; 80 | } 81 | 82 | static ut64 _lseek(RIO *io, RIODesc *fd, ut64 offset, int whence) { 83 | RIOMMapFileObj *mmo = fd->data; 84 | ut64 seek_val; 85 | switch (whence) { 86 | case SEEK_SET: seek_val = R_MIN (mmo->size, offset); break; 87 | case SEEK_CUR: seek_val = R_MIN (mmo->size, io->off + offset); break; 88 | case SEEK_END: 89 | if ((st64)offset <= 0) { 90 | seek_val = mmo->size + offset; 91 | } 92 | break; 93 | } 94 | return io->off = seek_val; 95 | } 96 | 97 | static RIODesc *_open(RIO *io, const char *filename, int flags, int mode) { 98 | if (!_check_default (filename)) return NULL; 99 | filename += 7; 100 | RIOMMapFileObj *mmo; 101 | ut8 *buf; 102 | off_t len; 103 | int fd; 104 | 105 | if ((fd = r_sandbox_open (filename, flags & R_IO_WRITE ? O_CREAT | O_RDWR : O_RDONLY, mode)) < 0) { 106 | return NULL; 107 | } 108 | if ((len = lseek (fd, 0, SEEK_END)) < 0) { 109 | goto out_sandbox; 110 | } 111 | buf = len > 0 ? mmap (NULL, len, PROT_READ, MAP_SHARED, fd, 0) : NULL; 112 | if (buf == (ut8 *)-1) { 113 | goto out_sandbox; 114 | } 115 | 116 | if (!(mmo = R_NEW (RIOMMapFileObj))) { 117 | goto out_mmo; 118 | } 119 | if (!(mmo->filename = strdup (filename))) { 120 | goto out_mmo; 121 | } 122 | mmo->fd = fd; 123 | mmo->flags = flags; 124 | mmo->mode = mode; 125 | if (len >= 2) { 126 | mmo->size = len * 8 / 9; 127 | if (!(mmo->buf = malloc (mmo->size * 2))) { 128 | goto out_mmo; 129 | } 130 | } else 131 | mmo->buf = NULL; 132 | mmo->dirty = false; 133 | 134 | ut64 x = 0, l = 0, n_buf = 0, i; 135 | for (i = 0; i < len; i++) { 136 | x = x << 8 | buf[i]; 137 | l += 8; 138 | if (l >= 9) { 139 | l -= 9; 140 | mmo->buf[n_buf++] = x >> l; 141 | x &= (1L << l) - 1; 142 | } 143 | } 144 | io->addrbytes = 2; 145 | return r_io_desc_new (io, &r_io_plugin_clcy, mmo->filename, flags, mode, mmo); 146 | 147 | out_mmo: 148 | if (mmo) { 149 | free (mmo->filename); 150 | free (mmo); 151 | } 152 | if (buf) 153 | munmap (buf, len); 154 | out_sandbox: 155 | r_sandbox_close (fd); 156 | return NULL; 157 | } 158 | 159 | static int _read(RIO *io, RIODesc *fd, ut8 *buf, int len) { 160 | RIOMMapFileObj *mmo = fd->data; 161 | if (len <= (mmo->size - io->off) * 2) 162 | memcpy (buf, &mmo->buf[io->off], len); 163 | else { 164 | memcpy (buf, &mmo->buf[io->off], (mmo->size - io->off) * 2); 165 | memset (&buf[(mmo->size - io->off) * 2], 0xff, io->off * 2 + len - mmo->size * 2); 166 | } 167 | return len; 168 | } 169 | 170 | static bool _resize(RIO *io, RIODesc *fd, ut64 size) { 171 | RIOMMapFileObj *mmo = fd->data; 172 | if (size > mmo->size) { 173 | ut16 *buf = realloc (mmo->buf, size * 2); 174 | if (!buf) return false; 175 | mmo->buf = buf; 176 | memset (&buf[mmo->size], 0, (size - mmo->size) * 2); 177 | } 178 | mmo->size = size; 179 | mmo->dirty = true; 180 | return true; 181 | } 182 | 183 | static int _write(RIO *io, RIODesc *fd, const ut8 *buf, int len) { 184 | RIOMMapFileObj *mmo = fd->data; 185 | if (io->off * 2 + len > mmo->size * 2) return -1; 186 | mmo->dirty = true; 187 | memcpy (mmo->buf + io->off * 2, buf, len); 188 | return len; 189 | } 190 | 191 | RIOPlugin r_io_plugin_clcy = { 192 | .name = "clcy", 193 | .desc = "cLEMENCy io", 194 | .license = "LGPL3", 195 | .check = _check, 196 | .close = _close, 197 | .extend = _extend, 198 | .lseek = _lseek, 199 | .open = _open, 200 | .read = _read, 201 | .resize = _resize, 202 | .write = _write, 203 | }; 204 | 205 | RLibStruct radare_plugin = { 206 | .type = R_LIB_TYPE_IO, 207 | .data = &r_io_plugin_clcy, 208 | .version = R2_VERSION, 209 | }; 210 | -------------------------------------------------------------------------------- /clemency/include/opcode-inc.h: -------------------------------------------------------------------------------- 1 | // Default macros. You can safely ignore these. 2 | #ifndef FORMAT 3 | #define FORMAT(x) 4 | #endif 5 | #ifndef INS 6 | #define INS(x,y) 7 | #endif 8 | #ifndef INS_1 9 | #define INS_1(w,x,y,z) INS(w,x) 10 | #endif 11 | #ifndef INS_2 12 | #define INS_2(w,x,y1,z1,y2,z2) INS_1(w,x,y1,z1) 13 | #endif 14 | #ifndef INS_3 15 | #define INS_3(w,x,y1,z1,y2,z2,y3,z3) INS_2(w,x,y1,z1,y2,z2) 16 | #endif 17 | #ifndef INS_4 18 | #define INS_4(w,x,y1,z1,y2,z2,y3,z3,y4,z4) INS_3(w,x,y1,z1,y2,z2,y3,z3) 19 | #endif 20 | 21 | // TODO Instruction definitions 22 | FORMAT( R ) 23 | INS_3( ad, 0b0000000, funct, 0, arith_signed, 0, is_imm, 0 ) 24 | INS_3( adc, 0b0100000, funct, 0, arith_signed, 0, is_imm, 0 ) 25 | INS_3( adcm, 0b0100010, funct, 0, arith_signed, 0, is_imm, 0 ) 26 | INS_3( adf, 0b0000001, funct, 0, arith_signed, 0, is_imm, 0 ) 27 | INS_3( adfm, 0b0000011, funct, 0, arith_signed, 0, is_imm, 0 ) 28 | INS_3( adm, 0b0000010, funct, 0, arith_signed, 0, is_imm, 0 ) 29 | INS_3( an, 0b0010100, funct, 0, arith_signed, 0, is_imm, 0 ) 30 | INS_3( anm, 0b0010110, funct, 0, arith_signed, 0, is_imm, 0 ) 31 | INS_4( dmt, 0b0110100, funct, 0, arith_signed, 0, is_imm, 0, uf, 0 ) 32 | INS_3( dv, 0b0001100, funct, 0, arith_signed, 0, is_imm, 0 ) 33 | INS_3( dvs, 0b0001100, funct, 0, arith_signed, 1, is_imm, 0 ) 34 | INS_3( dvf, 0b0001100, funct, 0, arith_signed, 0, is_imm, 0 ) 35 | INS_3( dvfm, 0b0001111, funct, 0, arith_signed, 0, is_imm, 0 ) 36 | INS_3( dvm, 0b0001110, funct, 0, arith_signed, 0, is_imm, 0 ) 37 | INS_3( dvsm, 0b0001110, funct, 0, arith_signed, 1, is_imm, 0 ) 38 | INS_3( md, 0b0010000, funct, 0, arith_signed, 0, is_imm, 0 ) 39 | INS_3( mds, 0b0010000, funct, 0, arith_signed, 1, is_imm, 0 ) 40 | INS_3( mdf, 0b0010001, funct, 0, arith_signed, 0, is_imm, 0 ) 41 | INS_3( mdfm, 0b0010011, funct, 0, arith_signed, 0, is_imm, 0 ) 42 | INS_3( mdm, 0b0010010, funct, 0, arith_signed, 0, is_imm, 0 ) 43 | INS_3( mdsm, 0b0010010, funct, 0, arith_signed, 1, is_imm, 0 ) 44 | 45 | FORMAT( R_IMM ) 46 | INS_2( adci, 0b0100000, arith_signed, 0, is_imm, 1 ) 47 | INS_2( adcim, 0b0100010, arith_signed, 0, is_imm, 1 ) 48 | INS_2( adi, 0b0000000, arith_signed, 0, is_imm, 1 ) 49 | INS_2( adim, 0b0000010, arith_signed, 0, is_imm, 1 ) 50 | INS_2( ani, 0b0010100, arith_signed, 0, is_imm, 1 ) 51 | INS_2( dvi, 0b0001100, arith_signed, 0, is_imm, 1 ) 52 | INS_2( dvis, 0b0001100, arith_signed, 1, is_imm, 1 ) 53 | INS_2( dvim, 0b0001110, arith_signed, 0, is_imm, 1 ) 54 | INS_2( dvism, 0b0001110, arith_signed, 1, is_imm, 1 ) 55 | INS_3( mdi, 0b0010000, funct, 0, arith_signed, 0, is_imm, 1 ) 56 | INS_3( mdis, 0b0010000, funct, 0, arith_signed, 1, is_imm, 1 ) 57 | INS_3( mdim, 0b0010010, funct, 0, arith_signed, 0, is_imm, 1 ) 58 | INS_3( mdism, 0b0010010, funct, 0, arith_signed, 1, is_imm, 1 ) 59 | 60 | FORMAT( B_CC_OFF ) 61 | INS( b, 0b110000 ) 62 | INS( c, 0b110101 ) 63 | 64 | FORMAT( B_CC_R ) 65 | INS_1( br, 0b110010, funct, 0 ) 66 | INS_1( cr, 0b110111, funct, 0 ) 67 | 68 | FORMAT( B_OFF ) 69 | INS( brr, 0b111000000 ) 70 | INS( car, 0b111001000 ) 71 | 72 | FORMAT( B_LOC ) 73 | INS( bra, 0b111000100 ) 74 | INS( caa, 0b111001100 ) 75 | 76 | FORMAT( BIN_R ) 77 | INS( cm, 0b10111000 ) 78 | INS( cmf, 0b10111010 ) 79 | INS( cmfm, 0b10111110 ) 80 | INS( cmm, 0b10111100 ) 81 | 82 | FORMAT( BIN_R_IMM ) 83 | INS( cmi, 0b10111001 ) 84 | INS( cmim, 0b10111101 ) 85 | 86 | FORMAT( MOV_LOW_HI ) 87 | INS( mh, 0b10001 ) 88 | INS( ml, 0b10010 ) 89 | 90 | FORMAT( MOV_LOW_SIGNED ) 91 | INS( ms, 0b10011 ) 92 | 93 | FORMAT( U ) 94 | INS_2( fti, 0b101000101, funct, 0, uf, 0) 95 | INS_2( ftim, 0b101000111, funct, 0, uf, 0) 96 | INS_2( itf, 0b101000100, funct, 0, uf, 0) 97 | INS_2( itfm, 0b101000110, funct, 0, uf, 0) 98 | 99 | FORMAT( R ) 100 | INS_3( mu, 0b0001000, funct, 0, arith_signed, 0, is_imm, 0 ) 101 | INS_3( muf, 0b0001001, funct, 0, arith_signed, 0, is_imm, 0 ) 102 | INS_3( mufm, 0b0001011, funct, 0, arith_signed, 0, is_imm, 0 ) 103 | INS_3( mum, 0b0001010, funct, 0, arith_signed, 0, is_imm, 0 ) 104 | INS_3( mus, 0b0001000, funct, 0, arith_signed, 1, is_imm, 0 ) 105 | INS_3( musm, 0b0001010, funct, 0, arith_signed, 1, is_imm, 0 ) 106 | INS_3( or, 0b0011000, funct, 0, arith_signed, 0, is_imm, 0 ) 107 | INS_3( orm, 0b0011010, funct, 0, arith_signed, 0, is_imm, 0 ) 108 | INS_3( rl, 0b0110000, funct, 0, arith_signed, 0, is_imm, 0 ) 109 | INS_3( rlm, 0b0110010, funct, 0, arith_signed, 0, is_imm, 0 ) 110 | INS_3( rr, 0b0110001, funct, 0, arith_signed, 0, is_imm, 0 ) 111 | INS_3( rrm, 0b0110011, funct, 0, arith_signed, 0, is_imm, 0 ) 112 | INS_3( sa, 0b0101101, funct, 0, arith_signed, 0, is_imm, 0 ) 113 | INS_3( sam, 0b0101111, funct, 0, arith_signed, 0, is_imm, 0 ) 114 | INS_3( sb, 0b0000100, funct, 0, arith_signed, 0, is_imm, 0 ) 115 | INS_3( sbc, 0b0100100, funct, 0, arith_signed, 0, is_imm, 0 ) 116 | INS_3( sbcm, 0b0100110, funct, 0, arith_signed, 0, is_imm, 0 ) 117 | INS_3( sbf, 0b0000101, funct, 0, arith_signed, 0, is_imm, 0 ) 118 | INS_3( sbfm, 0b0000111, funct, 0, arith_signed, 0, is_imm, 0 ) 119 | INS_3( sbm, 0b0000110, funct, 0, arith_signed, 0, is_imm, 0 ) 120 | INS_3( sl, 0b0101000, funct, 0, arith_signed, 0, is_imm, 0 ) 121 | INS_3( slm, 0b0101010, funct, 0, arith_signed, 0, is_imm, 0 ) 122 | INS_3( sr, 0b0101001, funct, 0, arith_signed, 0, is_imm, 0 ) 123 | INS_3( srm, 0b0101011, funct, 0, arith_signed, 0, is_imm, 0 ) 124 | INS_3( xr, 0b0011100, funct, 0, arith_signed, 0, is_imm, 0 ) 125 | INS_3( xrm, 0b0011110, funct, 0, arith_signed, 0, is_imm, 0 ) 126 | 127 | FORMAT( R_IMM ) 128 | INS_2( mui, 0b0001000, arith_signed, 0, is_imm, 1 ) 129 | INS_2( muim, 0b0001010, arith_signed, 0, is_imm, 1 ) 130 | INS_2( muis, 0b0001000, arith_signed, 1, is_imm, 1 ) 131 | INS_2( muism, 0b0001010, arith_signed, 1, is_imm, 1 ) 132 | INS_2( ori, 0b0011000, arith_signed, 0, is_imm, 1 ) 133 | INS_2( rli, 0b1000000, arith_signed, 0, is_imm, 0 ) 134 | INS_2( rlim, 0b1000010, arith_signed, 0, is_imm, 0 ) 135 | INS_2( rri, 0b1000001, arith_signed, 0, is_imm, 0 ) 136 | INS_2( rrim, 0b1000011, arith_signed, 0, is_imm, 0 ) 137 | INS_2( sai, 0b0111101, arith_signed, 0, is_imm, 0 ) 138 | INS_2( saim, 0b0111111, arith_signed, 0, is_imm, 0 ) 139 | INS_2( sbi, 0b0000100, arith_signed, 0, is_imm, 1 ) 140 | INS_2( sbci, 0b0100100, arith_signed, 0, is_imm, 1 ) 141 | INS_2( sbcim, 0b0100110, arith_signed, 0, is_imm, 1 ) 142 | INS_2( sbim, 0b0000110, arith_signed, 0, is_imm, 1 ) 143 | INS_2( sli, 0b0111000, arith_signed, 0, is_imm, 0 ) 144 | INS_2( slim, 0b0111010, arith_signed, 0, is_imm, 0 ) 145 | INS_2( sri, 0b0111001, arith_signed, 0, is_imm, 0 ) 146 | INS_2( srim, 0b0111011, arith_signed, 0, is_imm, 0 ) 147 | INS_2( xri, 0b0011100, arith_signed, 0, is_imm, 1 ) 148 | 149 | FORMAT( U ) 150 | INS_1( bf, 0b101001100, funct, 0b1000000 ) 151 | INS_1( bfm, 0b101001110, funct, 0b1000000 ) 152 | INS_1( ng, 0b101001100, funct, 0b0000000 ) 153 | INS_1( ngf, 0b101001101, funct, 0b0000000 ) 154 | INS_1( ngfm, 0b101001111, funct, 0b0000000 ) 155 | INS_1( ngm, 0b101001110, funct, 0b0000000 ) 156 | INS_1( nt, 0b101001100, funct, 0b0100000 ) 157 | INS_1( ntm, 0b101001110, funct, 0b0100000 ) 158 | 159 | FORMAT( U_EXTEND ) 160 | INS_1( ses, 0b101000000111, funct, 0 ) 161 | INS_1( sew, 0b101000001000, funct, 0 ) 162 | INS_1( zes, 0b101000001001, funct, 0 ) 163 | INS_1( zew, 0b101000001010, funct, 0 ) 164 | 165 | FORMAT( N ) 166 | INS( re, 0b101000000000000000 ) 167 | INS( dbrk, 0b111111111111111111 ) 168 | INS( ht, 0b101000000011000000 ) 169 | INS( ir, 0b101000000001000000 ) 170 | INS( wt, 0b101000000010000000 ) 171 | 172 | FORMAT( FLAGS_INTS ) 173 | INS_1( rf, 0b101000001100, funct, 0 ) 174 | INS_1( sf, 0b101000001011, funct, 0 ) 175 | INS_1( ei, 0b101000000100, funct, 0 ) 176 | INS_1( di, 0b101000000101, funct, 0 ) 177 | 178 | FORMAT( M ) 179 | INS_1( ldt, 0b1010110, funct, 0) 180 | INS_1( lds, 0b1010100, funct, 0) 181 | INS_1( ldw, 0b1010101, funct, 0) 182 | INS_1( stt, 0b1011010, funct, 0) 183 | INS_1( sts, 0b1011000, funct, 0) 184 | INS_1( stw, 0b1011001, funct, 0) 185 | 186 | FORMAT( RANDOM ) 187 | INS_1( rnd, 0b101001100, funct, 0b000001100000 ) 188 | INS_1( rndm, 0b101001110, funct, 0b000001100000 ) 189 | 190 | FORMAT( MP ) 191 | INS_3( rmp, 0b1010010, rw, 0, mem_flags, 0, funct, 0) 192 | INS_2( smp, 0b1010010, rw, 1, funct, 0) 193 | 194 | // Unset the macros. You can safely ignore these. 195 | #undef FORMAT 196 | #undef INS 197 | #undef INS_1 198 | #undef INS_2 199 | #undef INS_3 200 | #undef INS_4 201 | -------------------------------------------------------------------------------- /clemency/asm/d/clcy: -------------------------------------------------------------------------------- 1 | ad=Add 2 | ad.=Add (uf) 3 | adc=Add With Carry 4 | adc.=Add With Carry (uf) 5 | adci=Add Immediate With Carry 6 | adci.=Add Immediate With Carry (uf) 7 | adcim=Add Immediate Multi Reg With Carry 8 | adcim.=Add Immediate Multi Reg With Carry (uf) 9 | adcm=Add Multi Reg With Carry 10 | adcm.=Add Multi Reg With Carry (uf) 11 | adf=Add Floating Point 12 | adf.=Add Floating Point (uf) 13 | adfm=Add Floating Point Multi Reg 14 | adfm.=Add Floating Point Multi Reg (uf) 15 | adi=Add Immediate 16 | adi.=Add Immediate (uf) 17 | adim=Add Immediate Multi Reg 18 | adim.=Add Immediate Multi Reg (uf) 19 | adm=Add Multi Reg 20 | adm.=Add Multi Reg (uf) 21 | an=And 22 | an.=And (uf) 23 | ani=And Immediate 24 | ani.=And Immediate (uf) 25 | anm=And Multi Reg 26 | anm.=And Multi Reg (uf) 27 | b=Branch 28 | bn=Branch if != 29 | be=Branch if == 30 | bl=Branch if unsigned < 31 | ble=Branch if unsigned <= 32 | bg=Branch if unsigned > 33 | bge=Branch if unsigned >= 34 | bno=Branch if OF == 0 35 | bo=Branch if OF == 1 36 | bns=Branch if SF == 0 37 | bs=Branch if SF == 1 38 | bsl=Branch if signed < 39 | bsle=Branch if signed <= 40 | bsg=Branch if signed > 41 | bsge=Branch if signed >= 42 | bf=Bit Flip 43 | bfm=Bit Flip Multi Reg 44 | br=Branch Register 45 | brn=Branch Register if != 46 | bre=Branch Register if == 47 | brl=Branch Register if unsigned < 48 | brle=Branch Register if unsigned <= 49 | brg=Branch Register if unsigned > 50 | brge=Branch Register if unsigned >= 51 | brno=Branch Register if OF == 0 52 | bro=Branch Register if OF == 1 53 | brns=Branch Register if SF == 0 54 | brs=Branch Register if SF == 1 55 | brsl=Branch Register if signed < 56 | brsle=Branch Register if signed <= 57 | brsg=Branch Register if signed > 58 | brsge=Branch Register if signed >= 59 | bra=Branch Absolute 60 | brr=Branch Relative 61 | c=Call 62 | cn=Call if != 63 | ce=Call if == 64 | cl=Call if unsigned < 65 | cle=Call if unsigned <= 66 | cg=Call if unsigned > 67 | cge=Call if unsigned >= 68 | cno=Call if OF == 0 69 | co=Call if OF == 1 70 | cns=Call if SF == 0 71 | cs=Call if SF == 1 72 | csl=Call if signed < 73 | csle=Call if signed <= 74 | csg=Call if signed > 75 | csge=Call if signed >= 76 | caa=Call Absolute 77 | car=Call Relative 78 | cm=Compare 79 | cmf=Compare Floating Point 80 | cmfm=Compare Floating Point Multi Reg 81 | cmi=Compare Immediate 82 | cmim=Compare Immediate Multi Reg 83 | cmm=Compare Multi Reg 84 | cr=Call Register 85 | crn=Call Register if != 86 | cre=Call Register if == 87 | crl=Call Register if unsigned < 88 | crle=Call Register if unsigned <= 89 | crg=Call Register if unsigned > 90 | crge=Call Register if unsigned >= 91 | crno=Call Register if OF == 0 92 | cro=Call Register if OF == 1 93 | crns=Call Register if SF == 0 94 | crs=Call Register if SF == 1 95 | crsl=Call Register if signed < 96 | crsle=Call Register if signed <= 97 | crsg=Call Register if signed > 98 | crsge=Call Register if signed >= 99 | dbrk=Debug Break 100 | di=Disable Interrupts 101 | dmt=Direct Memory Transfer 102 | dmt.=Direct Memory Transfer (uf) 103 | dv=Divide 104 | dv.=Divide (uf) 105 | dvf=Divide Floating Point 106 | dvf.=Divide Floating Point (uf) 107 | dvfm=Divide Floating Point Multi Reg 108 | dvfm.=Divide Floating Point Multi Reg (uf) 109 | dvi=Divide Immediate 110 | dvi.=Divide Immediate (uf) 111 | dvim=Divide Immediate Multi Reg 112 | dvim.=Divide Immediate Multi Reg (uf) 113 | dvis=Divide Immediate Signed 114 | dvis.=Divide Immediate Signed (uf) 115 | dvm=Divide Multi Reg 116 | dvm.=Divide Multi Reg (uf) 117 | dvs=Divide Signed 118 | dvs.=Divide Signed (uf) 119 | dvsm=Divide Signed Multi Reg 120 | dvsm.=Divide Signed Multi Reg (uf) 121 | ei=Enable Interrupts 122 | fti=Float to Integer 123 | fti.=Float to Integer (uf) 124 | ftim=Float to Integer Multi Reg 125 | ftim.=Float to Integer Multi Reg (uf) 126 | ht=Halt 127 | ir=Interrupt Return 128 | itf=Integer to Float 129 | itf.=Integer to Float (uf) 130 | itfm=Integer to Float Multi Reg 131 | itfm.=Integer to Float Multi Reg (uf) 132 | lds=Load Single 133 | ldsd=Load Single 134 | ldsi=Load Single 135 | ldt=Load Tri 136 | ldtd=Load Tri 137 | ldti=Load Tri 138 | ldw=Load Word 139 | ldwd=Load Word 140 | ldwi=Load Word 141 | md=Modulus 142 | md.=Modulus (uf) 143 | mdf=Modulus Floating Point 144 | mdf.=Modulus Floating Point (uf) 145 | mdfm=Modulus Floating Point Multi Reg 146 | mdfm.=Modulus Floating Point Multi Reg (uf) 147 | mdi=Modulus Immediate 148 | mdi.=Modulus Immediate (uf) 149 | mdim=Modulus Immediate Multi Reg 150 | mdim.=Modulus Immediate Multi Reg (uf) 151 | mdis=Modulus Immediate Signed 152 | mdis.=Modulus Immediate Signed (uf) 153 | mdm=Modulus Multi Reg 154 | mdm.=Modulus Multi Reg (uf) 155 | mds=Modulus Signed 156 | mds.=Modulus Signed (uf) 157 | mdsm=Modulus Signed Multi Reg 158 | mdsm.=Modulus Signed Multi Reg (uf) 159 | mh=Move High 160 | ml=Move Low 161 | ms=Move Low Signed 162 | mu=Multiply 163 | mu.=Multiply (uf) 164 | muf=Multiply Floating Point 165 | muf.=Multiply Floating Point (uf) 166 | mufm=Multiply Floating Point Multi Reg 167 | mufm.=Multiply Floating Point Multi Reg (uf) 168 | mui=Multiply Immediate 169 | mui.=Multiply Immediate (uf) 170 | muim=Multiply Immediate Multi Reg 171 | muim.=Multiply Immediate Multi Reg (uf) 172 | muis=Multiply Immediate Signed 173 | muis.=Multiply Immediate Signed (uf) 174 | mum=Multiply Multi Reg 175 | mum.=Multiply Multi Reg (uf) 176 | mus=Multiply Signed 177 | mus.=Multiply Signed (uf) 178 | musm=Multiply Signed Multi Reg 179 | musm.=Multiply Signed Multi Reg (uf) 180 | ng=Negate 181 | ngf=Negate Floating Point 182 | ngfm=Negate Floating Point Multi Reg 183 | ngm=Negate Multi Reg 184 | nt=Not 185 | ntm=Not Multi Reg 186 | or=Or 187 | or.=Or (uf) 188 | ori=Or Immediate 189 | ori.=Or Immediate (uf) 190 | orm=Or Multi Reg 191 | orm.=Or Multi Reg (uf) 192 | re=Return 193 | rf=Read Flags 194 | rl=Rotate Left 195 | rl.=Rotate Left (uf) 196 | rli=Rotate Left Immediate 197 | rli.=Rotate Left Immediate (uf) 198 | rlim=Rotate Left Immediate Multi Reg 199 | rlim.=Rotate Left Immediate Multi Reg (uf) 200 | rlm=Rotate Left Multi Reg 201 | rlm.=Rotate Left Multi Reg (uf) 202 | rmp=Read Memory Protection 203 | rnd=Random 204 | rnd.=Random (uf) 205 | rndm=Random Multi Reg 206 | rndm.=Random Multi Reg (uf) 207 | rr=Rotate Right 208 | rr.=Rotate Right (uf) 209 | rri=Rotate Right Immediate 210 | rri.=Rotate Right Immediate (uf) 211 | rrim=Rotate Right Immediate Multi Reg 212 | rrim.=Rotate Right Immediate Multi Reg (uf) 213 | rrm=Rotate Right Multi Reg 214 | rrm.=Rotate Right Multi Reg (uf) 215 | sa=Shift Arithemetic Right 216 | sa.=Shift Arithemetic Right (uf) 217 | sai=Shift Arithemetic Right Immediate 218 | sai.=Shift Arithemetic Right Immediate (uf) 219 | sam=Shift Arithemetic Right Multi Reg 220 | sam.=Shift Arithemetic Right Multi Reg (uf) 221 | sb=Subtract 222 | sb.=Subtract (uf) 223 | sbc=Subtract With Carry 224 | sbc.=Subtract With Carry (uf) 225 | sbci=Subtract Immediate With Carry 226 | sbci.=Subtract Immediate With Carry (uf) 227 | sbcm=Subtract Multi Reg With Carry 228 | sbcm.=Subtract Multi Reg With Carry (uf) 229 | sbf=Subtract Floating Point 230 | sbf.=Subtract Floating Point (uf) 231 | sbfm=Subtract Floating Point Multi Reg 232 | sbfm.=Subtract Floating Point Multi Reg (uf) 233 | sbi=Subtract Immediate 234 | sbi.=Subtract Immediate (uf) 235 | sbim=Subtract Immediate Multi Reg 236 | sbim.=Subtract Immediate Multi Reg (uf) 237 | sbm=Subtract Multi Reg 238 | sbm.=Subtract Multi Reg (uf) 239 | ses=Sign Extend Single 240 | sew=Sign Extend Word 241 | sf=Set Flags 242 | sl=Shift Left 243 | sl.=Shift Left (uf) 244 | sli=Shift Left Immediate 245 | sli.=Shift Left Immediate (uf) 246 | slim=Shift Left Immediate Multi Reg 247 | slim.=Shift Left Immediate Multi Reg (uf) 248 | slm=Shift Left Multi Reg 249 | slm.=Shift Left Multi Reg (uf) 250 | smp=Set Memory Protection 251 | sr=Shift Right 252 | sr.=Shift Right (uf) 253 | sri=Shift Right Immediate 254 | sri.=Shift Right Immediate (uf) 255 | srim=Shift Right Immediate Multi Reg 256 | srim.=Shift Right Immediate Multi Reg (uf) 257 | srm=Shift Right Multi Reg 258 | srm.=Shift Right Multi Reg (uf) 259 | sts=Store Single 260 | stsd=Store Single 261 | stsi=Store Single 262 | stt=Store Tri 263 | sttd=Store Tri 264 | stti=Store Tri 265 | stw=Store Word 266 | stwd=Store Word 267 | stwi=Store Word 268 | wt=Wait 269 | xr=Xor 270 | xr.=Xor (uf) 271 | xri=Xor Immediate 272 | xri.=Xor Immediate (uf) 273 | xrm=Xor Multi Reg 274 | xrm.=Xor Multi Reg (uf) 275 | zes=Zero Extend Single 276 | zew=Zero Extend Word 277 | -------------------------------------------------------------------------------- /clemency/debug/debug_clcy.c: -------------------------------------------------------------------------------- 1 | /* radare - LGPL - Copyright 2017 - pancake */ 2 | 3 | #include 4 | #include 5 | 6 | #include "../io/clcy.c" 7 | 8 | #define UNKNOWN -1 9 | #define UNSUPPORTED 0 10 | #define SUPPORTED 1 11 | 12 | // static libgdbr_t *desc = NULL; 13 | static void *desc = NULL; 14 | static ut8* reg_buf = NULL; 15 | static int buf_size = 0; 16 | static int support_sw_bp = UNKNOWN; 17 | static int support_hw_bp = UNKNOWN; 18 | 19 | static int r_debug_clcy_attach(RDebug *dbg, int pid); 20 | static void check_connection (RDebug *dbg) { 21 | if (!desc) { 22 | r_debug_clcy_attach (dbg, -1); 23 | } 24 | } 25 | 26 | static int r_debug_clcy_step(RDebug *dbg) { 27 | RIODesc *d = dbg->iob.io->desc; 28 | RIOClcy *riom = d->data; 29 | eprintf ("LETs go step\n"); 30 | char * res = runcmd (riom->rs, "t"); 31 | eprintf ("STEP %s\n", res); 32 | free (res); 33 | // gdbr_step (desc, -1); // TODO handle thread specific step? 34 | return true; 35 | } 36 | 37 | static RList* r_debug_clcy_threads(RDebug *dbg, int pid) { 38 | /* 39 | RList *list; 40 | if ((list = gdbr_threads_list (desc, pid))) { 41 | list->free = (RListFree) &r_debug_pid_free; 42 | } 43 | return list; 44 | */ 45 | return NULL; 46 | } 47 | 48 | static int r_debug_clcy_reg_read(RDebug *dbg, int type, ut8 *buf, int size) { 49 | memset (buf, 0, size); 50 | return size; 51 | /* 52 | int copy_size; 53 | int buflen = 0; 54 | check_connection (dbg); 55 | gdbr_read_registers (desc); 56 | if (!desc) { 57 | return -1; 58 | } 59 | // read the len of the current area 60 | free (r_reg_get_bytes (dbg->reg, type, &buflen)); 61 | if (size < desc->data_len) { 62 | eprintf ("r_debug_clcy_reg_read: small buffer %d vs %d\n", 63 | (int)size, (int)desc->data_len); 64 | // return -1; 65 | } 66 | copy_size = R_MIN (desc->data_len, size); 67 | buflen = R_MAX (desc->data_len, buflen); 68 | if (reg_buf) { 69 | // if (buf_size < copy_size) { //desc->data_len) { 70 | if (buflen > buf_size) { //copy_size) { 71 | ut8* new_buf = realloc (reg_buf, buflen); 72 | if (!new_buf) { 73 | return -1; 74 | } 75 | reg_buf = new_buf; 76 | buf_size = buflen; 77 | } 78 | } else { 79 | reg_buf = calloc (buflen, 1); 80 | if (!reg_buf) { 81 | return -1; 82 | } 83 | buf_size = buflen; 84 | } 85 | memset ((void*)(volatile void*)buf, 0, size); 86 | memcpy ((void*)(volatile void*)buf, desc->data, R_MIN (copy_size, size)); 87 | memset ((void*)(volatile void*)reg_buf, 0, buflen); 88 | memcpy ((void*)(volatile void*)reg_buf, desc->data, copy_size); 89 | #if 0 90 | int i; 91 | //for(i=0;i<168;i++) { 92 | for(i=0;idata[i]); 95 | } 96 | printf("\n"); 97 | #endif 98 | */ 99 | } 100 | 101 | static RList *r_debug_clcy_map_get(RDebug* dbg) { //TODO 102 | return 0; 103 | #if 0 104 | check_connection (dbg); 105 | if (desc->pid <= 0) { 106 | return NULL; 107 | } 108 | RList *retlist = NULL; 109 | 110 | // Get file from GDB 111 | char path[128]; 112 | ut8 *buf; 113 | int ret; 114 | // TODO don't hardcode buffer size, get from remote target 115 | // (I think gdb doesn't do that, it just keeps reading till EOF) 116 | // fstat info can get file size, but it doesn't work for /proc/pid/maps 117 | ut64 buflen = 16384; 118 | // If /proc/%d/maps is not valid for gdbserver, we return NULL, as of now 119 | snprintf (path, sizeof (path) - 1, "/proc/%d/maps", desc->pid); 120 | if (gdbr_open_file (desc, path, O_RDONLY, S_IRUSR | S_IWUSR | S_IXUSR) < 0) { 121 | return NULL; 122 | } 123 | if (!(buf = malloc (buflen))) { 124 | gdbr_close_file (desc); 125 | return NULL; 126 | } 127 | if ((ret = gdbr_read_file (desc, buf, buflen - 1)) <= 0) { 128 | gdbr_close_file (desc); 129 | free (buf); 130 | return NULL; 131 | } 132 | buf[ret] = '\0'; 133 | 134 | // Get map list 135 | int unk = 0, perm, i; 136 | char *ptr, *pos_1; 137 | size_t line_len; 138 | char name[1024], region1[100], region2[100], perms[5]; 139 | RDebugMap *map = NULL; 140 | region1[0] = region2[0] = '0'; 141 | region1[1] = region2[1] = 'x'; 142 | if (!(ptr = strtok ((char*) buf, "\n"))) { 143 | gdbr_close_file (desc); 144 | free (buf); 145 | return NULL; 146 | } 147 | if (!(retlist = r_list_new ())) { 148 | gdbr_close_file (desc); 149 | free (buf); 150 | return NULL; 151 | } 152 | while (ptr) { 153 | ut64 map_start, map_end, offset; 154 | bool map_is_shared = false; 155 | line_len = strlen (ptr); 156 | // maps files should not have empty lines 157 | if (line_len == 0) { 158 | break; 159 | } 160 | // We assume Linux target, for now, so - 161 | // 7ffff7dda000-7ffff7dfd000 r-xp 00000000 08:05 265428 /usr/lib/ld-2.25.so 162 | ret = sscanf (ptr, "%s %s %"PFMT64x" %*s %*s %[^\n]", ®ion1[2], 163 | perms, &offset, name); 164 | if (ret == 3) { 165 | name[0] = '\0'; 166 | } else if (ret != 4) { 167 | eprintf ("%s: Unable to parse \"%s\"\nContent:\n%s\n", __func__, path, buf); 168 | gdbr_close_file (desc); 169 | free (buf); 170 | r_list_free (retlist); 171 | return NULL; 172 | } 173 | if (!(pos_1 = strchr (®ion1[2], '-'))) { 174 | ptr = strtok (NULL, "\n"); 175 | continue; 176 | } 177 | strncpy (®ion2[2], pos_1 + 1, sizeof (region2) - 2 - 1); 178 | if (!*name) { 179 | snprintf (name, sizeof (name), "unk%d", unk++); 180 | } 181 | perm = 0; 182 | for (i = 0; perms[i] && i < 5; i++) { 183 | switch (perms[i]) { 184 | case 'r': perm |= R_IO_READ; break; 185 | case 'w': perm |= R_IO_WRITE; break; 186 | case 'x': perm |= R_IO_EXEC; break; 187 | case 'p': map_is_shared = false; break; 188 | case 's': map_is_shared = true; break; 189 | } 190 | } 191 | map_start = r_num_get (NULL, region1); 192 | map_end = r_num_get (NULL, region2); 193 | if (map_start == map_end || map_end == 0) { 194 | eprintf ("%s: ignoring invalid map size: %s - %s\n", 195 | __func__, region1, region2); 196 | ptr = strtok (NULL, "\n"); 197 | continue; 198 | } 199 | if (!(map = r_debug_map_new (name, map_start, map_end, perm, 0))) { 200 | break; 201 | } 202 | map->offset = offset; 203 | map->shared = map_is_shared; 204 | map->file = strdup (name); 205 | r_list_append (retlist, map); 206 | ptr = strtok (NULL, "\n"); 207 | } 208 | gdbr_close_file (desc); 209 | free (buf); 210 | return retlist; 211 | #endif 212 | } 213 | 214 | static int r_debug_clcy_reg_write(RDebug *dbg, int type, const ut8 *buf, int size) { 215 | eprintf ("write\n"); 216 | return -1; 217 | #if 0 218 | check_connection (dbg); 219 | if (!reg_buf) { 220 | // we cannot write registers before we once read them 221 | return -1; 222 | } 223 | int buflen = 0; 224 | int bits = dbg->anal->bits; 225 | const char *pcname = r_reg_get_name (dbg->anal->reg, R_REG_NAME_PC); 226 | RRegItem *reg = r_reg_get (dbg->anal->reg, pcname, 0); 227 | if (reg) { 228 | if (dbg->anal->bits != reg->size) 229 | bits = reg->size; 230 | } 231 | free (r_reg_get_bytes (dbg->reg, type, &buflen)); 232 | // some implementations of the gdb protocol are acting weird. 233 | // so winedbg is not able to write registers through the packet 234 | // and also it does not return the whole gdb register profile after 235 | // calling 236 | // so this workaround resizes the small register profile buffer 237 | // to the whole set and fills the rest with 0 238 | if (buf_size < buflen) { 239 | ut8* new_buf = realloc (reg_buf, buflen * sizeof (ut8)); 240 | if (!new_buf) { 241 | return -1; 242 | } 243 | reg_buf = new_buf; 244 | memset (new_buf + buf_size, 0, buflen - buf_size); 245 | } 246 | 247 | RRegItem* current = NULL; 248 | for (;;) { 249 | current = r_reg_next_diff (dbg->reg, type, reg_buf, buflen, current, bits); 250 | if (!current) break; 251 | ut64 val = r_reg_get_value (dbg->reg, current); 252 | int bytes = bits / 8; 253 | gdbr_write_reg (desc, current->name, (char*)&val, bytes); 254 | } 255 | return true; 256 | #endif 257 | } 258 | 259 | static int r_debug_clcy_continue(RDebug *dbg, int pid, int tid, int sig) { 260 | // check_connection (dbg); 261 | //gdbr_continue (desc, pid, tid, sig); 262 | return true; 263 | } 264 | 265 | static RDebugReasonType r_debug_clcy_wait(RDebug *dbg, int pid) { 266 | eprintf ("wait\n"); 267 | #if 0 268 | check_connection (dbg); 269 | if (!desc->stop_reason.is_valid) { 270 | if (gdbr_stop_reason (desc) < 0) { 271 | dbg->reason.type = R_DEBUG_REASON_UNKNOWN; 272 | return R_DEBUG_REASON_UNKNOWN; 273 | } 274 | } 275 | desc->stop_reason.is_valid = false; 276 | if (desc->stop_reason.thread.present) { 277 | dbg->reason.tid = desc->stop_reason.thread.tid; 278 | } 279 | dbg->reason.signum = desc->stop_reason.signum; 280 | dbg->reason.type = desc->stop_reason.reason; 281 | #endif 282 | return 0; //desc->stop_reason.reason; 283 | } 284 | 285 | static int r_debug_clcy_attach(RDebug *dbg, int pid) { 286 | RIODesc *d = dbg->iob.io->desc; 287 | RIOClcy *riom = d->data; 288 | char * res = runcmd (riom->rs, "t"); 289 | eprintf ("attach %s\n", res); 290 | free (res); 291 | return true; 292 | } 293 | 294 | static int r_debug_clcy_detach(RDebug *dbg, int pid) { 295 | // return gdbr_detach_pid (desc, pid); 296 | return true; 297 | } 298 | 299 | static const char *r_debug_clcy_reg_profile(RDebug *dbg) { 300 | int arch = r_sys_arch_id (dbg->arch); 301 | int bits = dbg->anal->bits; 302 | return strdup ( 303 | "=PC pc\n" 304 | "=SP st\n" 305 | "=BP st\n" 306 | "=A0 r0\n" 307 | "=A1 r1\n" 308 | "=A2 r2\n" 309 | "=A3 r3\n" 310 | "gpr r0 .27 0 0\n" 311 | "gpr r1 .27 4 0\n" 312 | "gpr r2 .27 8 0\n" 313 | "gpr r3 .27 12 0\n" 314 | "gpr r4 .27 16 0\n" 315 | "gpr r5 .27 20 0\n" 316 | "gpr r6 .27 24 0\n" 317 | "gpr r7 .27 28 0\n" 318 | "gpr r8 .27 32 0\n" 319 | "gpr r9 .27 36 0\n" 320 | "gpr r10 .27 40 0\n" 321 | "gpr r11 .27 44 0\n" 322 | "gpr r12 .27 48 0\n" 323 | "gpr r13 .27 52 0\n" 324 | "gpr r14 .27 56 0\n" 325 | "gpr r15 .27 60 0\n" 326 | "gpr r16 .27 64 0\n" 327 | "gpr r17 .27 68 0\n" 328 | "gpr r18 .27 72 0\n" 329 | "gpr r19 .27 76 0\n" 330 | "gpr r20 .27 80 0\n" 331 | "gpr r21 .27 84 0\n" 332 | "gpr r22 .27 88 0\n" 333 | "gpr r23 .27 92 0\n" 334 | "gpr r24 .27 96 0\n" 335 | "gpr r25 .27 100 0\n" 336 | "gpr r26 .27 104 0\n" 337 | "gpr r27 .27 108 0\n" 338 | "gpr r28 .27 112 0\n" 339 | "gpr st .27 116 0\n" 340 | "gpr ra .27 120 0\n" 341 | "gpr pc .27 124 0\n" 342 | "gpr fl .27 128 0\n" 343 | ); 344 | } 345 | 346 | static int r_debug_clcy_breakpoint (RBreakpointItem *bp, int set, void *user) { 347 | #if 0 348 | int ret; 349 | if (!bp) { 350 | return false; 351 | } 352 | // TODO handle rwx and conditions 353 | if (set) 354 | ret = bp->hw? 355 | gdbr_set_hwbp (desc, bp->addr, ""): 356 | gdbr_set_bp (desc, bp->addr, ""); 357 | else 358 | ret = bp->hw? 359 | gdbr_remove_hwbp (desc, bp->addr): 360 | gdbr_remove_bp (desc, bp->addr); 361 | return !ret; 362 | #endif 363 | // runcmd ("b"); 364 | return false; 365 | } 366 | 367 | static bool r_debug_clcy_kill(RDebug *dbg, int pid, int tid, int sig) { 368 | dbg->reason.type = 0; 369 | return true; 370 | } 371 | 372 | static RDebugInfo* r_debug_clcy_info(RDebug *dbg, const char *arg) { 373 | RDebugInfo *rdi; 374 | if (!(rdi = R_NEW0 (RDebugInfo))) { 375 | return NULL; 376 | } 377 | RList *th_list; 378 | bool list_alloc = false; 379 | if (dbg->threads) { 380 | th_list = dbg->threads; 381 | } else { 382 | th_list = r_debug_clcy_threads (dbg, dbg->pid); 383 | list_alloc = true; 384 | } 385 | RDebugPid *th; 386 | RListIter *it; 387 | bool found = false; 388 | r_list_foreach (th_list, it, th) { 389 | if (th->pid == dbg->pid) { 390 | found = true; 391 | break; 392 | } 393 | } 394 | rdi->pid = dbg->pid; 395 | rdi->tid = dbg->tid; 396 | // rdi->exe = gdbr_exec_file_read (desc, dbg->pid); 397 | rdi->status = found ? th->status : R_DBG_PROC_STOP; 398 | rdi->uid = found ? th->uid : -1; 399 | rdi->gid = found ? th->gid : -1; 400 | #if 0 401 | if (gdbr_stop_reason (desc) >= 0) { 402 | eprintf ("signal: %d\n", desc->stop_reason.signum); 403 | rdi->signum = desc->stop_reason.signum; 404 | } 405 | #endif 406 | if (list_alloc) { 407 | r_list_free (th_list); 408 | } 409 | return rdi; 410 | } 411 | 412 | RDebugPlugin r_debug_plugin_clcy = { 413 | .name = "clcy", 414 | /* TODO: Add support for more architectures here */ 415 | .license = "LGPL3", 416 | .arch = "clcy", 417 | .bits = 27, 418 | .step = r_debug_clcy_step, 419 | .cont = r_debug_clcy_continue, 420 | 421 | .attach = &r_debug_clcy_attach, 422 | .detach = &r_debug_clcy_detach, 423 | .threads = &r_debug_clcy_threads, 424 | .canstep = 1, 425 | .wait = &r_debug_clcy_wait, 426 | .map_get = r_debug_clcy_map_get, 427 | .breakpoint = &r_debug_clcy_breakpoint, 428 | 429 | .reg_read = &r_debug_clcy_reg_read, 430 | .reg_write = &r_debug_clcy_reg_write, 431 | .reg_profile = (void *)r_debug_clcy_reg_profile, 432 | 433 | .kill = &r_debug_clcy_kill, 434 | .info = &r_debug_clcy_info, 435 | //.bp_write = &r_debug_clcy_bp_write, 436 | //.bp_read = &r_debug_clcy_bp_read, 437 | }; 438 | 439 | #ifndef CORELIB 440 | RLibStruct radare_plugin = { 441 | .type = R_LIB_TYPE_DBG, 442 | .data = &r_debug_plugin_clcy, 443 | .version = R2_VERSION 444 | }; 445 | #endif 446 | -------------------------------------------------------------------------------- /clemency/disasm.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "include/disasm.h" 4 | #include "include/opfield-inc.h" 5 | 6 | #define SIGN_EXTEND(name, count) do { inst->name = ((st32)inst->name << (32 - count)) >> (32 - count); } while (0) 7 | 8 | static bool g_pseudo; 9 | 10 | const char *conditions[16] = { 11 | "n", "e", "l", "le", "g", "ge", "no", "o", 12 | "ns", "s", "sl", "sle", "sg", "sge", NULL, "" 13 | }; 14 | 15 | const char *regs[32] = { 16 | "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", 17 | "r9", "r10", "r11", "r12", "r13", "r14", "r15", "r16", 18 | "r17", "r18", "r19", "r20", "r21", "r22", "r23", "r24", 19 | "r25", "r26", "r27", "r28", "st", "ra", "pc" 20 | }; 21 | 22 | static const char *mnemonics[] = { 23 | "invalid", 24 | #define INS(ins, opcode) #ins, 25 | #include "include/opcode-inc.h" 26 | #undef FORMAT 27 | #undef INS 28 | #undef INS_1 29 | #undef INS_2 30 | #undef INS_3 31 | #undef INS_4 32 | }; 33 | 34 | static ut64 read_18(const ut16 *src) { 35 | return (ut64)src[1] << 9 | src[0]; 36 | } 37 | 38 | static ut64 read_27(const ut16 *src) { 39 | return (ut64)src[1] << 18 | (ut64)src[0] << 9 | src[2]; 40 | } 41 | 42 | static ut64 read_36(const ut16 *src) { 43 | return (ut64)src[1] << 27 | (ut64)src[0] << 18 | (ut64)src[2] << 9 | src[3]; 44 | } 45 | 46 | static ut64 read_54(const ut16 *src) { 47 | return (ut64)src[1] << 45 | (ut64)src[0] << 36 | (ut64)src[2] << 27 | (ut64)src[4] << 18 | (ut64)src[3] << 9 | src[5]; 48 | } 49 | 50 | #define DEFINE_DECODE(type, bits) \ 51 | bool decode_##type(inst_t *inst, const ut16 *src, int len) \ 52 | { \ 53 | int bit_size = bits; \ 54 | if ((inst->size = bits / 9) > len) return false; \ 55 | inst->code = read_##bits (src); \ 56 | FORM_##type; \ 57 | return true; \ 58 | } 59 | 60 | #define FIELD(name, offset, count) inst->name = (inst->code >> bit_size-count-offset) & ((1 << count) - 1); 61 | 62 | DEFINE_DECODE (R, 27) 63 | DEFINE_DECODE (R_IMM, 27) 64 | DEFINE_DECODE (U, 27) 65 | DEFINE_DECODE (BIN_R, 18) 66 | DEFINE_DECODE (BIN_R_IMM, 27) 67 | DEFINE_DECODE (MOV_LOW_HI, 27) 68 | DEFINE_DECODE (B_CC_R, 18) 69 | DEFINE_DECODE (B_LOC, 36) 70 | DEFINE_DECODE (N, 18) 71 | DEFINE_DECODE (FLAGS_INTS, 18) 72 | DEFINE_DECODE (U_EXTEND, 27) 73 | DEFINE_DECODE (RANDOM, 27) 74 | DEFINE_DECODE (MP, 27) 75 | 76 | #undef DEFINE_DECODE 77 | 78 | bool decode_MOV_LOW_SIGNED(inst_t *inst, const ut16 *src, int len) 79 | { 80 | int bit_size = 27; 81 | if ((inst->size = 3) > len) return false; 82 | inst->code = read_27 (src); 83 | FORM_MOV_LOW_SIGNED; 84 | SIGN_EXTEND(imm, 17); 85 | return true; 86 | } 87 | 88 | bool decode_B_CC_OFF(inst_t *inst, const ut16 *src, int len) 89 | { 90 | int bit_size = 27; 91 | if ((inst->size = 3) > len) return false; 92 | inst->code = read_27 (src); 93 | FORM_B_CC_OFF; 94 | SIGN_EXTEND (imm, 17); 95 | return true; 96 | } 97 | 98 | bool decode_B_OFF(inst_t *inst, const ut16 *src, int len) 99 | { 100 | int bit_size = 36; 101 | if ((inst->size = 4) > len) return false; 102 | inst->code = read_36 (src); 103 | FORM_B_OFF; 104 | SIGN_EXTEND (imm, 27); 105 | return true; 106 | } 107 | 108 | bool decode_M(inst_t *inst, const ut16 *src, int len) 109 | { 110 | int bit_size = 54; 111 | if ((inst->size = 6) > len) return false; 112 | inst->code = read_54 (src); 113 | FORM_M; 114 | SIGN_EXTEND (imm, 27); 115 | inst->reg_count++; 116 | return true; 117 | } 118 | 119 | #undef FIELD 120 | 121 | int parse_reg(const char **src) { 122 | static const char *specials[] = {"st", "ra", "pc"}; 123 | char *s = (char *)*src; 124 | for (int i = 0; i < 3; i++) 125 | if (!strncasecmp (s, specials[i], 2) && !isalnum (s[2])) { 126 | *src += 2; 127 | return 29 + i; 128 | } 129 | if (tolower (*s) == 'r') { 130 | errno = 0; 131 | int r = strtol (s+1, &s, 10); 132 | if (errno || s == *src+1) return -1; 133 | *src = s; 134 | return r; 135 | } 136 | return -1; 137 | } 138 | 139 | static void pprint_R(RAsmOp *op, const inst_t *inst) { 140 | const char *rA = regs[inst->rA], *infix = NULL; 141 | if (g_pseudo) { 142 | switch (inst->id) { 143 | case I_ad: infix = "+"; break; 144 | case I_sb: infix = "-"; break; 145 | case I_mu: infix = "*"; break; 146 | case I_dv: infix = "/"; break; 147 | case I_or: infix = "|"; break; 148 | case I_an: infix = "&"; break; 149 | case I_xr: infix = "^"; break; 150 | } 151 | } 152 | if (infix) { 153 | snprintf (op->buf_asm, sizeof op->buf_asm, "%s =%s %s %s %s", rA, inst->uf ? "." : "", regs[inst->rB], infix, regs[inst->rC]); 154 | } else { 155 | snprintf (op->buf_asm, sizeof op->buf_asm, "%s%s %s, %s, %s", mnemonics[inst->id], inst->uf ? "." : "", rA, regs[inst->rB], regs[inst->rC]); 156 | } 157 | } 158 | 159 | static void pprint_R_IMM(RAsmOp *op, const inst_t *inst) { 160 | const char *rA = regs[inst->rA], *infix = NULL; 161 | if (g_pseudo) { 162 | switch (inst->id) { 163 | case I_adi: infix = "+"; break; 164 | case I_sbi: infix = "-"; break; 165 | case I_mui: infix = "*"; break; 166 | case I_muis: infix = "*s"; break; 167 | case I_dvi: infix = "/"; break; 168 | case I_dvis: infix = "/s"; break; 169 | case I_rli: infix = "<buf_asm, sizeof op->buf_asm, "%s =%s %s %s %#" PRIx32, rA, inst->uf ? "." : "", regs[inst->rB], infix, inst->imm); 177 | } else { 178 | snprintf (op->buf_asm, sizeof op->buf_asm, "%s%s %s, %s, %#" PRIx32, mnemonics[inst->id], inst->uf ? "." : "", rA, regs[inst->rB], inst->imm); 179 | } 180 | } 181 | 182 | static void pprint_U(RAsmOp *op, const inst_t *inst) { 183 | snprintf (op->buf_asm, sizeof op->buf_asm, "%s%s %s, %s", mnemonics[inst->id], inst->uf ? "." : "", regs[inst->rA], regs[inst->rB]); 184 | } 185 | 186 | static void pprint_BIN_R(RAsmOp *op, const inst_t *inst) { 187 | snprintf (op->buf_asm, sizeof op->buf_asm, "%s %s, %s", mnemonics[inst->id], regs[inst->rA], regs[inst->rB]); 188 | } 189 | 190 | static void pprint_BIN_R_IMM(RAsmOp *op, const inst_t *inst) { 191 | snprintf (op->buf_asm, sizeof op->buf_asm, "%s %s, 0x%" PRIx32, mnemonics[inst->id], regs[inst->rA], inst->imm); 192 | } 193 | 194 | static void pprint_MOV_LOW_HI(RAsmOp *op, const inst_t *inst) { 195 | const char *rA = regs[inst->rA]; 196 | if (!g_pseudo) { 197 | snprintf (op->buf_asm, sizeof op->buf_asm, "%s %s, 0x%" PRIx32, mnemonics[inst->id], regs[inst->rA], inst->imm); 198 | } else if (inst->id == I_mh) { 199 | snprintf (op->buf_asm, sizeof op->buf_asm, "%s = %s & 0x3ff | %#" PRIx32 " << 10" , rA, rA, inst->imm); 200 | } else if (inst->id == I_ml) { 201 | snprintf (op->buf_asm, sizeof op->buf_asm, "%s = %#" PRIx32, rA, inst->imm); 202 | } else { 203 | abort (); 204 | } 205 | } 206 | 207 | static void pprint_MOV_LOW_SIGNED(RAsmOp *op, const inst_t *inst) { 208 | // clemency-emu displays this as 17-bit 209 | snprintf (op->buf_asm, sizeof op->buf_asm, "%s %s, 0x%" PRIx32, mnemonics[inst->id], regs[inst->rA], inst->imm & MASK_27); 210 | } 211 | 212 | static void pprint_B_CC_OFF(RAsmOp *op, const inst_t *inst) { 213 | if (!conditions[inst->cc]) 214 | strcpy (op->buf_asm, mnemonics[I_invalid]); 215 | else 216 | snprintf (op->buf_asm, sizeof op->buf_asm, "%s%s 0x%" PRIx32, mnemonics[inst->id], conditions[inst->cc], inst->pc + inst->imm & MASK_27); 217 | } 218 | 219 | static void pprint_B_CC_R(RAsmOp *op, const inst_t *inst) { 220 | if (!conditions[inst->cc]) 221 | strcpy (op->buf_asm, mnemonics[I_invalid]); 222 | else 223 | snprintf (op->buf_asm, sizeof op->buf_asm, "%s%s %s", mnemonics[inst->id], conditions[inst->cc], regs[inst->rA]); 224 | } 225 | 226 | static void pprint_B_OFF(RAsmOp *op, const inst_t *inst) { 227 | snprintf (op->buf_asm, sizeof op->buf_asm, "%s 0x%" PRIx32, mnemonics[inst->id], inst->pc + inst->imm & MASK_27); 228 | } 229 | 230 | static void pprint_B_LOC(RAsmOp *op, const inst_t *inst) { 231 | snprintf (op->buf_asm, sizeof op->buf_asm, "%s 0x%" PRIx32, mnemonics[inst->id], inst->imm); 232 | } 233 | 234 | static void pprint_N(RAsmOp *op, const inst_t *inst) { 235 | snprintf (op->buf_asm, sizeof op->buf_asm, "%s", mnemonics[inst->id]); 236 | } 237 | 238 | static void pprint_FLAGS_INTS(RAsmOp *op, const inst_t *inst) { 239 | snprintf (op->buf_asm, sizeof op->buf_asm, "%s %s", mnemonics[inst->id], regs[inst->rA]); 240 | } 241 | 242 | static void pprint_U_EXTEND(RAsmOp *op, const inst_t *inst) { 243 | snprintf (op->buf_asm, sizeof op->buf_asm, "%s %s, %s", mnemonics[inst->id], regs[inst->rA], regs[inst->rB]); 244 | } 245 | 246 | static void pprint_RANDOM(RAsmOp *op, const inst_t *inst) { 247 | snprintf (op->buf_asm, sizeof op->buf_asm, "%s%s %s", mnemonics[inst->id], inst->uf ? "." : "", regs[inst->rA]); 248 | } 249 | 250 | static void pprint_M(RAsmOp *op, const inst_t *inst) { 251 | static const char *adj[] = {"", "i", "d"}; 252 | if (inst->adj_rb >= R_ARRAY_SIZE (adj)) 253 | strcpy (op->buf_asm, mnemonics[I_invalid]); 254 | else { 255 | if (inst->imm >= 0) 256 | snprintf (op->buf_asm, sizeof op->buf_asm, "%s%s %s, [%s+0x%" PRIx32 ", %" PRIi16 "]", mnemonics[inst->id], adj[inst->adj_rb], regs[inst->rA], regs[inst->rB], inst->imm, inst->reg_count); 257 | else 258 | snprintf (op->buf_asm, sizeof op->buf_asm, "%s%s %s, [%s-0x%" PRIx32 ", %" PRIi16 "]", mnemonics[inst->id], adj[inst->adj_rb], regs[inst->rA], regs[inst->rB], -inst->imm, inst->reg_count); 259 | } 260 | } 261 | 262 | static void pprint_MP(RAsmOp *op, const inst_t *inst) { 263 | static const char *protections[] = {"", "R", "RW", "RE"}; 264 | snprintf (op->buf_asm, sizeof op->buf_asm, "%s %s, %s, %s", mnemonics[inst->id], regs[inst->rA], regs[inst->rB], protections[inst->mem_flags]); 265 | } 266 | 267 | int disassemble(ut64 pc, RAsmOp *op, const ut8 *src, int len, bool pseudo) { 268 | inst_t inst = {.pc = pc}; 269 | void (*pprint)(RAsmOp *op, const inst_t *inst); 270 | bool ok; 271 | g_pseudo = pseudo; 272 | 273 | #define FORMAT(fmt) ok = decode_##fmt (&inst, (const ut16*)src, len/2); pprint = pprint_##fmt; 274 | #define INS(x,opc) do { if (ok && inst.opcode == opc) { inst.id = I_##x; pprint (op, &inst); return op->size = inst.size; } } while (0); 275 | #define INS_1(x,opc,f1,v1) do { if (ok && inst.opcode == opc && inst.f1 == v1) { inst.id = I_##x; pprint (op, &inst); return op->size = inst.size; } } while (0); 276 | #define INS_2(x,opc,f1,v1,f2,v2) do { if (ok && inst.opcode == opc && inst.f1 == v1 && inst.f2 == v2) { inst.id = I_##x; pprint (op, &inst); return op->size = inst.size; } } while (0); 277 | #define INS_3(x,opc,f1,v1,f2,v2,f3,v3) do { if (ok && inst.opcode == opc && inst.f1 == v1 && inst.f2 == v2 && inst.f3 == v3) { inst.id = I_##x; pprint (op, &inst); return op->size = inst.size; } } while (0); 278 | #define INS_4(x,opc,f1,v1,f2,v2,f3,v3,f4,v4) do { if (ok && inst.opcode == opc && inst.f1 == v1 && inst.f2 == v2 && inst.f3 == v3 && inst.f4 == v4) { inst.id = I_##x; pprint (op, &inst); return op->size = inst.size; } } while (0); 279 | #include "include/opcode-inc.h" 280 | #undef FORMAT 281 | #undef INS 282 | #undef INS_1 283 | #undef INS_2 284 | #undef INS_3 285 | #undef INS_4 286 | 287 | strcpy (op->buf_asm, mnemonics[I_invalid]); 288 | return op->size = 1; 289 | } 290 | 291 | //***** Assembler *****/ 292 | 293 | static int parse_cc(inst_t *inst, const char **src) { 294 | for (int i = 0; i < R_ARRAY_SIZE (conditions); i++) 295 | if (conditions[i]) { 296 | int l = strlen (conditions[i]); 297 | if (!strncasecmp (*src, conditions[i], l) && !isalnum ((*src)[l])) { 298 | *src += l; 299 | inst->cc = i; 300 | return 0; 301 | } 302 | } 303 | return -1; 304 | } 305 | 306 | static int parse_char(inst_t *inst, const char **src, char c) { 307 | while (isspace (**src)) ++*src; 308 | if (*(*src)++ != c) return -1; 309 | while (isspace (**src)) ++*src; 310 | return 0; 311 | } 312 | 313 | static int parse_comma(inst_t *inst, const char **src) { 314 | return parse_char (inst, src, ','); 315 | } 316 | 317 | static int parse_end(const char **src) { 318 | while (isspace (**src)) ++*src; 319 | return **src ? -1 : 0; 320 | } 321 | 322 | static int parse_imm_st(inst_t *inst, const char **src, int bits) { 323 | char *s = (char *)*src; 324 | errno = 0; 325 | inst->imm = strtol (s, &s, 0); 326 | if (errno || s == *src || !(-1 << bits-1 <= inst->imm && inst->imm < 1 << bits-1)) return -1; 327 | *src = s; 328 | return 0; 329 | } 330 | 331 | static int parse_imm_ut(inst_t *inst, const char **src, int bits) { 332 | char *s = (char *)*src; 333 | errno = 0; 334 | inst->imm = strtol (s, &s, 0); 335 | if (errno || s == *src || !(0 <= inst->imm && inst->imm < 1 << bits)) return -1; 336 | *src = s; 337 | return 0; 338 | } 339 | 340 | static int parse_rA(inst_t *inst, const char **src) { 341 | inst->rA = parse_reg (src); 342 | return 0 <= inst->rA < 32 ? 0 : -1; 343 | } 344 | 345 | static int parse_rB(inst_t *inst, const char **src) { 346 | inst->rB = parse_reg (src); 347 | return 0 <= inst->rB < 32 ? 0 : -1; 348 | } 349 | 350 | static int parse_rC(inst_t *inst, const char **src) { 351 | inst->rC = parse_reg (src); 352 | return 0 <= inst->rC < 32 ? 0 : -1; 353 | } 354 | 355 | static int parse_space(inst_t *inst, const char **src) { 356 | const char *s = *src; 357 | while (isspace (*s)) s++; 358 | if (s == *src) return -1; 359 | *src = s; 360 | return 0; 361 | } 362 | 363 | static int parse_uf(inst_t *inst, const char **src) { 364 | if (**src == '.') { 365 | inst->uf = 1; 366 | ++*src; 367 | } else { 368 | inst->uf = 0; 369 | } 370 | return 0; 371 | } 372 | 373 | #define FIELD(name, offset, count) | ((ut64)inst->name << bit_size-count-offset) 374 | 375 | static int assemble_R(inst_t *inst, const char **src) { 376 | int bit_size = 27; 377 | if (parse_uf (inst, src)) return 1; 378 | if (parse_space (inst, src)) return 1; 379 | if (parse_rA (inst, src)) return 1; 380 | if (parse_comma (inst, src)) return -1; 381 | if (parse_rB (inst, src)) return 2; 382 | if (parse_comma (inst, src)) return -2; 383 | if (parse_rC (inst, src)) return 3; 384 | if (parse_end (src)) return 3; 385 | inst->size = 3; 386 | inst->code = 0 FORM_R; 387 | return 0; 388 | } 389 | 390 | static int assemble_R_IMM(inst_t *inst, const char **src) { 391 | int bit_size = 27; 392 | if (parse_uf (inst, src)) return 1; 393 | if (parse_space (inst, src)) return 1; 394 | if (parse_rA (inst, src)) return 1; 395 | if (parse_comma (inst, src)) return -1; 396 | if (parse_rB (inst, src)) return 2; 397 | if (parse_comma (inst, src)) return -2; 398 | if (parse_imm_st (inst, src, 28)) return 3; // TODO differentiate st/ut e.g. dvi/dvis 399 | inst->imm &= MASK_27; 400 | if (parse_end (src)) return 3; 401 | inst->size = 3; 402 | inst->code = 0 FORM_R_IMM; 403 | return 0; 404 | } 405 | 406 | static int assemble_U(inst_t *inst, const char **src) { 407 | int bit_size = 27; 408 | if (parse_uf (inst, src)) return 1; 409 | if (parse_space (inst, src)) return 1; 410 | if (parse_rA (inst, src)) return 1; 411 | if (parse_comma (inst, src)) return -1; 412 | if (parse_rB (inst, src)) return 2; 413 | if (parse_end (src)) return 2; 414 | inst->size = 3; 415 | inst->code = 0 FORM_U; 416 | return 0; 417 | } 418 | 419 | static int assemble_BIN_R(inst_t *inst, const char **src) { 420 | int bit_size = 18; 421 | if (parse_space (inst, src)) return 1; 422 | if (parse_rA (inst, src)) return 1; 423 | if (parse_comma (inst, src)) return -1; 424 | if (parse_rB (inst, src)) return 2; 425 | if (parse_end (src)) return 2; 426 | inst->size = 2; 427 | inst->code = 0 FORM_BIN_R; 428 | return 0; 429 | } 430 | 431 | static int assemble_BIN_R_IMM(inst_t *inst, const char **src) { 432 | int bit_size = 27; 433 | if (parse_space (inst, src)) return 1; 434 | if (parse_rA (inst, src)) return 1; 435 | if (parse_comma (inst, src)) return -1; 436 | if (parse_imm_st (inst, src, 14)) return 2; 437 | inst->imm &= (1 << 14) - 1; 438 | if (parse_end (src)) return 2; 439 | inst->size = 3; 440 | inst->code = 0 FORM_BIN_R_IMM; 441 | return 0; 442 | } 443 | 444 | static int assemble_MOV_LOW_HI(inst_t *inst, const char **src) { 445 | int bit_size = 27; 446 | if (parse_space (inst, src)) return 1; 447 | if (parse_rA (inst, src)) return 1; 448 | if (parse_comma (inst, src)) return -1; 449 | if (parse_imm_ut (inst, src, 17)) return 2; 450 | if (parse_end (src)) return 2; 451 | inst->size = 3; 452 | inst->code = 0 FORM_MOV_LOW_HI; 453 | return 0; 454 | } 455 | 456 | static int assemble_MOV_LOW_SIGNED(inst_t *inst, const char **src) { 457 | int bit_size = 27; 458 | if (parse_space (inst, src)) return 1; 459 | if (parse_rA (inst, src)) return 1; 460 | if (parse_comma (inst, src)) return -1; 461 | if (parse_imm_st (inst, src, 17)) return 2; 462 | inst->imm &= (1 << 17) - 1; 463 | if (parse_end (src)) return 2; 464 | inst->size = 3; 465 | inst->code = 0 FORM_MOV_LOW_HI; 466 | return 0; 467 | } 468 | 469 | static int assemble_B_CC_OFF(inst_t *inst, const char **src) { 470 | int bit_size = 27; 471 | if (parse_cc (inst, src)) return 1; 472 | if (parse_space (inst, src)) return 1; 473 | if (parse_imm_ut (inst, src, 17)) return 1; 474 | inst->imm = inst->imm - inst->pc & (1 << 17) - 1; 475 | if (parse_end (src)) return 1; 476 | inst->size = 3; 477 | inst->code = 0 FORM_B_CC_OFF; 478 | return 0; 479 | } 480 | 481 | static int assemble_B_CC_R(inst_t *inst, const char **src) { 482 | int bit_size = 18; 483 | if (parse_cc (inst, src)) return 1; 484 | if (parse_space (inst, src)) return 1; 485 | if (parse_rA (inst, src)) return 1; 486 | if (parse_end (src)) return 1; 487 | inst->size = 2; 488 | inst->code = 0 FORM_B_CC_R; 489 | return 0; 490 | } 491 | 492 | static int assemble_B_OFF(inst_t *inst, const char **src) { 493 | int bit_size = 36; 494 | if (parse_space (inst, src)) return 1; 495 | if (parse_imm_ut (inst, src, 27)) return 1; 496 | inst->imm = inst->imm - inst->pc & MASK_27; 497 | if (parse_end (src)) return 1; 498 | inst->size = 4; 499 | inst->code = 0 FORM_B_OFF; 500 | return 0; 501 | } 502 | 503 | static int assemble_B_LOC(inst_t *inst, const char **src) { 504 | int bit_size = 36; 505 | if (parse_cc (inst, src)) return 1; 506 | if (parse_imm_ut (inst, src, 27)) return 1; 507 | if (parse_end (src)) return 1; 508 | inst->size = 4; 509 | inst->code = 0 FORM_B_LOC; 510 | return 0; 511 | } 512 | 513 | static int assemble_N(inst_t *inst, const char **src) { 514 | int bit_size = 18; 515 | if (parse_end (src)) return 1; 516 | inst->size = 2; 517 | inst->code = 0 FORM_N; 518 | return 0; 519 | } 520 | 521 | static int assemble_FLAGS_INTS(inst_t *inst, const char **src) { 522 | int bit_size = 18; 523 | if (parse_space (inst, src)) return 1; 524 | if (parse_rA (inst, src)) return 1; 525 | if (parse_end (src)) return 1; 526 | inst->size = 2; 527 | inst->code = 0 FORM_FLAGS_INTS; 528 | return 0; 529 | } 530 | 531 | static int assemble_U_EXTEND(inst_t *inst, const char **src) { 532 | int bit_size = 27; 533 | if (parse_space (inst, src)) return 1; 534 | if (parse_rA (inst, src)) return 1; 535 | if (parse_comma (inst, src)) return -1; 536 | if (parse_rB (inst, src)) return 2; 537 | if (parse_end (src)) return 2; 538 | inst->size = 3; 539 | inst->code = 0 FORM_U_EXTEND; 540 | return 0; 541 | } 542 | 543 | static int assemble_RANDOM(inst_t *inst, const char **src) { 544 | int bit_size = 27; 545 | if (parse_uf (inst, src)) return 1; 546 | if (parse_space (inst, src)) return 1; 547 | if (parse_rA (inst, src)) return 1; 548 | if (parse_end (src)) return 1; 549 | inst->size = 3; 550 | inst->code = 0 FORM_RANDOM; 551 | return 0; 552 | } 553 | 554 | static int assemble_M(inst_t *inst, const char **src) { 555 | int bit_size = 54; 556 | if (**src == 'i') { 557 | ++*src; 558 | inst->adj_rb = 1; 559 | } else if (**src == 'd') { 560 | ++*src; 561 | inst->adj_rb = 2; 562 | } else { 563 | inst->adj_rb = 0; 564 | } 565 | if (parse_space (inst, src)) return 1; 566 | if (parse_rA (inst, src)) return 1; 567 | if (parse_comma (inst, src)) return 1; 568 | if (parse_char (inst, src, '[')) return 1; 569 | if (parse_rB (inst, src)) return 2; 570 | if (**src == ',') 571 | inst->imm = 0; 572 | else { 573 | if (parse_imm_st (inst, src, 27)) return 3; 574 | inst->imm &= MASK_27; 575 | } 576 | if (parse_comma (inst, src)) return -3; 577 | char *s = (char *)*src; 578 | errno = 0; 579 | inst->reg_count = strtol (s, &s, 0); 580 | if (errno || !(0 < inst->reg_count && inst->reg_count <= 32)) return 4; 581 | *src = s; 582 | inst->reg_count--; 583 | if (parse_char (inst, src, ']')) return 4; 584 | if (parse_end (src)) return 4; 585 | inst->size = 6; 586 | inst->code = 0 FORM_M; 587 | return 0; 588 | } 589 | 590 | static int assemble_MP(inst_t *inst, const char **src) { 591 | int bit_size = 27; 592 | if (parse_space (inst, src)) return 1; 593 | if (parse_rA (inst, src)) return 1; 594 | if (parse_comma (inst, src)) return 1; 595 | if (parse_rB (inst, src)) return 2; 596 | if (parse_comma (inst, src)) return 1; 597 | char *s = (char *)*src; 598 | if (tolower (s[0]) == 'r') { 599 | if (tolower (s[1]) == 'w') { 600 | inst->mem_flags = 2; 601 | s += 2; 602 | } else if (tolower (s[1]) == 'e') { 603 | inst->mem_flags = 3; 604 | s += 2; 605 | } else { 606 | inst->mem_flags = 1; 607 | s++; 608 | } 609 | } else if ('0' <= s[0] && s[0] <= '4') { 610 | inst->mem_flags = s[0] - '0'; 611 | s++; 612 | } else { 613 | inst->mem_flags = 0; 614 | } 615 | *src = s; 616 | if (parse_end (src)) return 3; 617 | inst->size = 3; 618 | inst->code = 0 FORM_MP; 619 | return 0; 620 | } 621 | 622 | #undef FIELD 623 | 624 | int assemble(ut64 pc, RAsmOp *op, const char *src) { 625 | static const char *bc[] = {"br", "b", "cr", "c"}; 626 | static const char *adj[] = {"lds", "ldt", "ldw", "sts", "stt", "stw"}; 627 | 628 | char buf[4096]; 629 | int mnemlen = 0; 630 | snprintf (buf, sizeof buf, "%s", src); 631 | for (int i = 0; i < R_ARRAY_SIZE (bc); i++) { 632 | int l = strlen (bc[i]), ll; 633 | if (!strncasecmp (buf, bc[i], l)) { 634 | for (int j = 0; j < R_ARRAY_SIZE (conditions); j++) 635 | if (conditions[j] && (ll = strlen (conditions[j]), !strncasecmp (buf+l, conditions[j], ll) && !isalnum (buf[l+ll]))) { 636 | mnemlen = l; 637 | break; 638 | } 639 | break; 640 | } 641 | } 642 | if (!mnemlen) { 643 | for (int i = 0; i < R_ARRAY_SIZE (adj); i++) { 644 | if (!strncasecmp (buf, adj[i], 3)) { 645 | mnemlen = 3; 646 | break; 647 | } 648 | } 649 | } 650 | if (!mnemlen) { 651 | while (buf[mnemlen] && buf[mnemlen] != '.' && !isspace (buf[mnemlen])) { 652 | mnemlen++; 653 | } 654 | } 655 | 656 | int (*assem)(inst_t *inst, const char **src); 657 | inst_t inst; 658 | char saved = buf[mnemlen]; 659 | buf[mnemlen] = '\0'; 660 | inst.pc = pc; 661 | 662 | #define FORMAT(fmt) assem = assemble_##fmt; 663 | #define INS(x,opc) if (!strcmp (buf, #x)) { buf[mnemlen] = saved; src = buf+mnemlen; inst.opcode = opc; break; } 664 | #define INS_1(x,opc,f1,v1) inst.f1 = v1; INS(x, opc) 665 | #define INS_2(x,opc,f1,v1,f2,v2) inst.f1 = v1; inst.f2 = v2; INS(x, opc) 666 | #define INS_3(x,opc,f1,v1,f2,v2,f3,v3) inst.f1 = v1; inst.f2 = v2; inst.f3 = v3; INS(x, opc) 667 | #define INS_4(x,opc,f1,v1,f2,v2,f3,v3,f4,v4) inst.f1 = v1; inst.f2 = v2; inst.f3 = v3; inst.f4 = v4; INS(x, opc) 668 | do { 669 | #include "include/opcode-inc.h" 670 | #undef FORMAT 671 | #undef INS 672 | #undef INS_1 673 | #undef INS_2 674 | #undef INS_3 675 | #undef INS_4 676 | return -1; 677 | } while (0); 678 | 679 | if (assem (&inst, &src)) return -1; 680 | for (int i = 0; i < inst.size; i++) { 681 | ut64 t = inst.code >> (inst.size-1-i)*9; 682 | op->buf[i * 2] = t & 255; 683 | op->buf[i * 2 + 1] = t >> 8 & 1; 684 | } 685 | // middle-endian swap 686 | for (int i = 0; i + 1 < inst.size; i += 3) { 687 | char t0 = op->buf[i * 2], t1 = op->buf[i * 2 + 1]; 688 | op->buf[i * 2] = op->buf[i * 2 + 2]; 689 | op->buf[i * 2 + 1] = op->buf[i * 2 + 3]; 690 | op->buf[i * 2 + 2] = t0; 691 | op->buf[i * 2 + 3] = t1; 692 | } 693 | return inst.size * 2; 694 | } 695 | -------------------------------------------------------------------------------- /clemency/anal/anal_clcy.c: -------------------------------------------------------------------------------- 1 | /* radare2 - LGPL - Copyright 2017 - xvilka */ 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "../include/clemency.h" 11 | #include "../include/disasm.h" 12 | 13 | #define CC_SWITCH(...) \ 14 | switch (inst.cc) { \ 15 | case CC_n: r_strbuf_setf (&op->esil, "zf,!" __VA_ARGS__); break; \ 16 | case CC_e: r_strbuf_setf (&op->esil, "zf" __VA_ARGS__); break; \ 17 | case CC_l: /* I think zf is redundant */ r_strbuf_setf (&op->esil, "cf" __VA_ARGS__); break; \ 18 | case CC_le: r_strbuf_setf (&op->esil, "zf,cf,|" __VA_ARGS__); break; \ 19 | case CC_g: r_strbuf_setf (&op->esil, "zf,cf,|,!" __VA_ARGS__); break; \ 20 | case CC_ge: /* I think zf is redundant */ r_strbuf_setf (&op->esil, "cf,!" __VA_ARGS__); break; \ 21 | case CC_no: r_strbuf_setf (&op->esil, "of,!" __VA_ARGS__); break; \ 22 | case CC_o: r_strbuf_setf (&op->esil, "of" __VA_ARGS__); break; \ 23 | case CC_ns: r_strbuf_setf (&op->esil, "sf,!" __VA_ARGS__); break; \ 24 | case CC_s: r_strbuf_setf (&op->esil, "sf" __VA_ARGS__); break; \ 25 | case CC_sl: r_strbuf_setf (&op->esil, "of,sf,==,!" __VA_ARGS__); break; \ 26 | case CC_sle: r_strbuf_setf (&op->esil, "zf,of,sf,==,!,|" __VA_ARGS__); break; \ 27 | case CC_sg: r_strbuf_setf (&op->esil, "zf,!,of,sf,==,&" __VA_ARGS__); break; \ 28 | case CC_sge: r_strbuf_setf (&op->esil, "of,sf,==" __VA_ARGS__); break; \ 29 | case CC_invalid: op->type = R_ANAL_OP_TYPE_ILL; break; \ 30 | case CC_always: r_strbuf_setf (&op->esil, "1" __VA_ARGS__); break; \ 31 | } 32 | 33 | static ut64 get_reg_id(const char *name) { 34 | char *p = (char *)name; 35 | return parse_reg(&name); 36 | } 37 | 38 | static ut64 read_fl(RAnalEsil *esil) { 39 | ut64 fl; 40 | r_anal_esil_get_parm (esil, "fl", &fl); 41 | return fl; 42 | } 43 | 44 | static ut64 read_reg(RAnalEsil *esil, int reg) { 45 | ut64 l; 46 | r_anal_esil_get_parm (esil, regs[reg], &l); 47 | return l; 48 | } 49 | 50 | static ut64 read_reg_pair(RAnalEsil *esil, int reg) { 51 | return read_reg (esil, reg) << 27 | read_reg (esil, reg+1 & 31); 52 | } 53 | 54 | static void write_fl(RAnalEsil *esil, ut64 v) { 55 | r_anal_esil_reg_write (esil, "fl", v & MASK_27); 56 | } 57 | 58 | static void write_reg(RAnalEsil *esil, int reg, ut64 v) { 59 | r_anal_esil_reg_write (esil, regs[reg], v & MASK_27); 60 | } 61 | 62 | static void write_reg_pair(RAnalEsil *esil, int reg, ut64 v) { 63 | write_reg (esil, reg, v >> 27 & MASK_27); 64 | write_reg (esil, reg + 1 & 31, v & MASK_27); 65 | } 66 | 67 | static int esil_pop_int(RAnalEsil *esil) { 68 | char *p = r_anal_esil_pop (esil); 69 | int ret = r_num_get (NULL, p); 70 | free (p); 71 | return ret; 72 | } 73 | 74 | static int clcy_custom_load(RAnalEsil *esil) { 75 | int nytes = esil_pop_int (esil), adj_rb = esil_pop_int (esil), 76 | iA = esil_pop_int (esil), iB = esil_pop_int (esil), 77 | offset = esil_pop_int (esil), reg_count = esil_pop_int (esil), 78 | rB = read_reg (esil, iB), temp = rB, tempPC = read_reg (esil, 31); 79 | ut16 buf[reg_count * nytes], *p = buf; 80 | if (adj_rb == 2) 81 | temp -= reg_count * nytes; 82 | if (!r_anal_esil_mem_read (esil, temp + offset & MASK_27, (ut8 *)buf, sizeof buf)) 83 | return 0; 84 | for (int i = 0; i < reg_count; i++) { 85 | switch (nytes) { 86 | case 1: write_reg (esil, iA, p[0]); break; 87 | case 2: write_reg (esil, iA, p[1] << 9 | p[0]); break; 88 | case 3: write_reg (esil, iA, p[1] << 18 | p[0] << 9 | p[2]); break; 89 | } 90 | iA = iA + 1 & 31; 91 | p += nytes; 92 | } 93 | if (adj_rb == 1) 94 | write_reg (esil, iB, rB + reg_count * nytes); 95 | else if (adj_rb == 2) 96 | write_reg (esil, iB, temp); 97 | write_reg (esil, 31, tempPC); 98 | return 1; 99 | } 100 | 101 | static int clcy_custom_store(RAnalEsil *esil) { 102 | int nytes = esil_pop_int (esil), adj_rb = esil_pop_int (esil), 103 | iA = esil_pop_int (esil), iB = esil_pop_int (esil), 104 | offset = esil_pop_int (esil), reg_count = esil_pop_int (esil), 105 | rB = read_reg (esil, iB), temp = rB; 106 | ut16 buf[reg_count * nytes], *p = buf; 107 | if (adj_rb == 2) 108 | temp -= reg_count * nytes; 109 | for (int i = 0; i < reg_count; i++) { 110 | ut64 t = read_reg (esil, iA); 111 | switch (nytes) { 112 | case 1: p[0] = t & MASK_9; break; 113 | case 2: p[1] = t >> 9 & MASK_9; p[0] = t & MASK_9; break; 114 | case 3: p[1] = t >> 18 & MASK_9; p[0] = t >> 9 & MASK_9; p[2] = t & MASK_9; break; 115 | } 116 | iA = iA + 1 & 31; 117 | p += nytes; 118 | } 119 | if (!r_anal_esil_mem_write (esil, temp + offset & MASK_27, (ut8 *)buf, sizeof buf)) 120 | esil->trap = 1; 121 | if (adj_rb == 1) 122 | write_reg (esil, iB, rB + reg_count * nytes); 123 | else if (adj_rb == 2) 124 | write_reg (esil, iB, temp); 125 | return 1; 126 | } 127 | 128 | static RAnalOp *_op; 129 | 130 | static int clcy_custom_binop(RAnalEsil *esil) { 131 | bool carry = false, uf = false, mf; 132 | ut64 a, b, c, msb; 133 | char *op = r_anal_esil_pop (esil), *op1 = op + 1; 134 | char *rA = r_anal_esil_pop (esil); 135 | char *rB = r_anal_esil_pop (esil); 136 | char *rC = r_anal_esil_pop (esil); 137 | char f = '+'; 138 | bool immC = !isalpha (rC[0]); 139 | int t, iA = get_reg_id (rA), iB = get_reg_id (rB), iC = immC ? -1 : get_reg_id (rC); 140 | // .: update flags 141 | if (*op1 == '.') 142 | uf = true, op1++; 143 | // c: carry 144 | if (*op1 == 'c') 145 | carry = true, op1++; 146 | // m: multi reg 147 | if (*op1 == 'm') { 148 | mf = true; 149 | msb = BIT_53; 150 | op1++; 151 | b = read_reg_pair (esil, iB); 152 | c = immC ? r_num_get (NULL, rC) : read_reg_pair (esil, iC); 153 | } else { 154 | mf = false; 155 | msb = BIT_26; 156 | b = read_reg (esil, iB); 157 | c = immC ? r_num_get (NULL, rC) : read_reg (esil, iC); 158 | } 159 | switch (*op1) { 160 | case '+': 161 | a = b + c; 162 | if (carry && read_fl (esil) & 2) a++; 163 | if (iA == REG_ST) { 164 | if (iA == iB && immC) { 165 | _op->stackop = R_ANAL_STACK_INC; 166 | _op->stackptr = -c; 167 | } 168 | } 169 | break; 170 | case '-': 171 | a = b - c; 172 | if (carry && read_fl (esil) & 2) a--; 173 | f = '-'; 174 | if (iA == REG_ST) { 175 | if (iA == iB && immC) { 176 | _op->stackop = R_ANAL_STACK_INC; 177 | _op->stackptr = c; 178 | } 179 | } 180 | break; 181 | case '*': 182 | f = '*'; 183 | if (op1[1] == '*') { // signed multiply 184 | if (mf) a = ((st64)b << 10 >> 10) * ((st64)c << 10 >> 10); 185 | else a = ((st32)b << 5 >> 5) * ((st32)c << 5 >> 5); 186 | } else { // unsigned multiply 187 | a = b * c; 188 | } 189 | break; 190 | case '/': 191 | f = '/'; 192 | if (!c) { 193 | esil->trap = R_ANAL_TRAP_DIVBYZERO; 194 | esil->trap_code = 0; 195 | } else if (op1[1] == '/') { // signed divide 196 | if (mf) a = ((st64)b << 10 >> 10) / ((st64)c << 10 >> 10); 197 | else a = ((st32)b << 5 >> 5) / ((st32)c << 5 >> 5); 198 | } else { // unsigned divide 199 | a = b / c; 200 | } 201 | break; 202 | case '&': a = b & c; break; 203 | case '|': a = b | c; break; 204 | case '^': a = b ^ c; break; 205 | case '<': a = b << c; break; 206 | case '>': 207 | if (op1[1] == '>' && op1[2] == '>') { // arithmetic shift right 208 | if (mf) a = (st64)b << 10 >> 10 >> c; 209 | else a = (st32)b << 5 >> 5 >> c; 210 | } else // logical shift right 211 | a = b >> c; 212 | break; 213 | case 'r': 214 | if (op1[1] == '<') { // rotate left 215 | if (mf) a = ((ut64)b << c % 54 | (ut32)b >> (54 - c % 54)) & MASK_54; 216 | else a = ((ut32)b << c % 27 | (ut32)b >> (27 - c % 27)) & MASK_27; 217 | } else { // rotate right 218 | if (mf) a = ((ut64)b >> c % 54 | (ut32)b << (54 - c % 54)) & MASK_54; 219 | else a = ((ut32)b >> c % 27 | (ut32)b << (27 - c % 27)) & MASK_27; 220 | } 221 | break; 222 | } 223 | if (mf) 224 | write_reg_pair (esil, iA, a); 225 | else 226 | write_reg (esil, iA, a); 227 | if (uf) { 228 | ut64 flags = read_fl (esil) & ~15 | !a | (a & msb ? 8 : 0); 229 | // Carry & Overflow 230 | switch (f) { 231 | case '+': 232 | case '*': 233 | if (f == '+' && a & msb << 1) 234 | flags |= 2; 235 | if ((b & msb) == (c & msb) && (b & msb) != (a & msb)) 236 | flags |= 4 | (f == '*' ? 2 : 0); 237 | break; 238 | case '-': 239 | case '/': 240 | if (f == '-' && a & msb << 1) 241 | flags |= 2; 242 | if ((b & msb) != (c & msb) && (b & msb) != (a & msb)) 243 | flags |= 4 | (f == '/' ? 2 : 0); 244 | break; 245 | } 246 | write_fl (esil, flags); 247 | } 248 | free (rC); 249 | free (rB); 250 | free (rA); 251 | free (op); 252 | return 1; 253 | } 254 | 255 | static int clcy_custom_compare(RAnalEsil *esil) { 256 | ut64 a, b, r, msb; 257 | char *op = r_anal_esil_pop (esil), 258 | *rA = r_anal_esil_pop (esil), *rB = r_anal_esil_pop (esil); 259 | bool immB = !isalpha (rB[0]); 260 | int iA = get_reg_id (rA), iB = immB ? -1 : get_reg_id (rB); 261 | if (op[1] == 'm') { 262 | msb = BIT_53; 263 | a = read_reg_pair (esil, iA); 264 | b = immB ? r_num_get (NULL, rB) : read_reg_pair (esil, iB); 265 | } else { 266 | msb = BIT_26; 267 | a = read_reg (esil, iA); 268 | b = immB ? r_num_get (NULL, rB) : read_reg (esil, iB); 269 | } 270 | r = a - b; 271 | write_fl (esil, read_fl (esil) & ~15 272 | | !r 273 | | (r & msb << 1 ? 2 : 0) 274 | | ((r & msb) != (r & msb) ? 4 : 0) 275 | | (r & msb ? 8 : 0)); 276 | free (rB); 277 | free (rA); 278 | free (op); 279 | return 1; 280 | } 281 | 282 | static int clcy_custom_dmt(RAnalEsil *esil) { 283 | int iA = esil_pop_int (esil), iB = esil_pop_int (esil), iC = esil_pop_int (esil), 284 | a = read_reg (esil, iA), b = read_reg (esil, iB), c = read_reg (esil, iC), len; 285 | if (0 < c && c <= 16) { 286 | ut8 *buf = malloc (c * 2); 287 | if (!buf) return 0; 288 | len = r_anal_esil_mem_read (esil, b, buf, c * 2); 289 | r_anal_esil_mem_write (esil, a, buf, len); 290 | } 291 | return 1; 292 | } 293 | 294 | static int clcy_custom_smp(RAnalEsil *esil) { 295 | int iA = esil_pop_int (esil), iB = esil_pop_int (esil), flags = esil_pop_int (esil), 296 | a = read_reg (esil, iA); 297 | if (a & PGSIZE - 1) { 298 | write_fl (esil, read_fl (esil) & ~1); // zf = 0 299 | write_reg (esil, iA, 0); 300 | return 1; 301 | } 302 | if (a + read_reg (esil, iB) * PGSIZE > MASK_27) { 303 | write_fl (esil, read_fl (esil) & ~1); // zf = 0 304 | write_reg (esil, iA, 1); 305 | return 1; 306 | } 307 | write_fl (esil, read_fl (esil) | 1); // zf = 1 308 | return 1; 309 | } 310 | 311 | static int clcy_custom_unop(RAnalEsil *esil) { 312 | bool uf = false, mf; 313 | ut64 a, b, msb; 314 | char *op = r_anal_esil_pop (esil), *op1 = op + 1; 315 | char *rA = r_anal_esil_pop (esil); 316 | char *rB = r_anal_esil_pop (esil); 317 | int iA = get_reg_id (rA), iB = get_reg_id (rB); 318 | if (*op1 == '.') 319 | uf = true, op1++; 320 | if (*op1 == 'm') { 321 | mf = true; 322 | msb = BIT_53; 323 | op1++; 324 | b = read_reg_pair (esil, iB); 325 | } else { 326 | mf = false; 327 | msb = BIT_26; 328 | b = read_reg (esil, iB); 329 | } 330 | switch (*op1) { 331 | case '!': a = !b; break; 332 | case '~': a = ~b; break; 333 | case '-': a = -b; break; 334 | } 335 | if (mf) 336 | write_reg_pair (esil, iA, a); 337 | else 338 | write_reg (esil, iA, a); 339 | if (uf) 340 | write_fl (esil, read_fl (esil) & ~15 341 | | !a 342 | | (a & msb << 1 ? 2 : 0) 343 | | ((b & msb) != (a & msb) ? 4 : 0) 344 | | (a & msb ? 8 : 0)); 345 | free (rB); 346 | free (rA); 347 | free (op); 348 | return 1; 349 | } 350 | 351 | static int clcy_custom_carryop(RAnalEsil *esil) { 352 | return 1; 353 | } 354 | 355 | static int reg_read(RAnalEsil *esil, const char *regname, ut64 *num) { 356 | RRegItem *reg = r_reg_get (esil->anal->reg, regname, -1); 357 | if (reg) { 358 | if (num) 359 | *num = r_reg_get_value (esil->anal->reg, reg); 360 | return 1; 361 | } 362 | return 0; 363 | } 364 | 365 | static int reg_write(RAnalEsil *esil, const char *regname, ut64 num) { 366 | RRegItem *reg = r_reg_get (esil->anal->reg, regname, -1); 367 | if (reg) { 368 | if (num) 369 | r_reg_set_value (esil->anal->reg, reg,num); 370 | return 1; 371 | } 372 | return 0; 373 | 374 | } 375 | 376 | static int clcy_op(RAnal *anal, RAnalOp *op, ut64 addr, const ut8 *src, int len) { 377 | inst_t inst = {.pc = addr}; 378 | 379 | #define FORMAT(fmt) ok = decode_##fmt (&inst, (const ut16*)src, len/2); 380 | #define INS(x,opc) if (ok && inst.opcode == opc) { inst.id = I_##x; break; } 381 | #define INS_1(x,opc,f1,v1) if (ok && inst.opcode == opc && inst.f1 == v1) { inst.id = I_##x; break; } 382 | #define INS_2(x,opc,f1,v1,f2,v2) if (ok && inst.opcode == opc && inst.f1 == v1 && inst.f2 == v2) { inst.id = I_##x; break; } 383 | #define INS_3(x,opc,f1,v1,f2,v2,f3,v3) if (ok && inst.opcode == opc && inst.f1 == v1 && inst.f2 == v2 && inst.f3 == v3) { inst.id = I_##x; break; } 384 | #define INS_4(x,opc,f1,v1,f2,v2,f3,v3,f4,v4) if (ok && inst.opcode == opc && inst.f1 == v1 && inst.f2 == v2 && inst.f3 == v3 && inst.f4 == v4) { inst.id = I_##x; break; } 385 | bool ok, found = true; 386 | do { 387 | #include "../include/opcode-inc.h" 388 | #undef FORMAT 389 | #undef INS 390 | #undef INS_1 391 | #undef INS_2 392 | #undef INS_3 393 | #undef INS_4 394 | found = false; 395 | } while (0); 396 | 397 | #define TYPE(inst_, type_) case I_##inst_: op->type = R_ANAL_OP_TYPE_##type_; break 398 | #define TYPE_E(inst_, type_, ...) case I_##inst_: op->type = R_ANAL_OP_TYPE_##type_; r_strbuf_setf (&op->esil, __VA_ARGS__); break 399 | ZERO_FILL (*op); 400 | 401 | const char *rA = regs[inst.rA], *rB = regs[inst.rB], *rC = regs[inst.rC], 402 | *if_uf = inst.uf ? "." : ""; 403 | int imm = (int)inst.imm; // st32 -> int to avoid PRIi32 404 | op->type = R_ANAL_OP_TYPE_NULL; 405 | op->jump = op->fail = -1; 406 | op->ptr = op->val = -1; 407 | op->addr = addr; 408 | _op = op; 409 | 410 | if (found) { 411 | op->size = inst.size; 412 | switch (inst.id) { 413 | case I_b: 414 | op->type = R_ANAL_OP_TYPE_JMP | (inst.cc == CC_always ? 0 : R_ANAL_OP_TYPE_COND); 415 | op->jump = addr + imm & MASK_27; 416 | op->fail = addr + op->size; 417 | CC_SWITCH (",?{,%d,pc,=,}", op->jump); 418 | break; 419 | case I_br: 420 | op->type = R_ANAL_OP_TYPE_RCALL | (inst.cc == CC_always ? 0 : R_ANAL_OP_TYPE_COND); 421 | op->jump = -1; 422 | op->fail = addr + op->size; 423 | op->reg = regs[inst.rA]; 424 | CC_SWITCH (",?{,%s,pc,=,}", op->reg); 425 | break; 426 | case I_bra: 427 | op->type = R_ANAL_OP_TYPE_JMP; 428 | op->jump = imm; 429 | op->fail = addr + op->size; 430 | r_strbuf_setf (&op->esil, "%d,pc,=", op->jump); 431 | break; 432 | case I_brr: 433 | op->type = R_ANAL_OP_TYPE_JMP; 434 | op->jump = addr + imm & MASK_27; 435 | op->fail = addr + op->size; 436 | r_strbuf_setf (&op->esil, "%d,pc,=", op->jump); 437 | break; 438 | case I_c: 439 | op->type = R_ANAL_OP_TYPE_CALL | (inst.cc == CC_always ? 0 : R_ANAL_OP_TYPE_COND); 440 | op->jump = addr + imm & MASK_27; 441 | op->fail = addr + op->size; 442 | CC_SWITCH (",?{,pc,ra,=,%d,pc,=,}", op->jump); 443 | break; 444 | case I_caa: 445 | op->type = R_ANAL_OP_TYPE_CALL; 446 | op->jump = imm; 447 | op->fail = addr + op->size; 448 | r_strbuf_setf (&op->esil, "pc,ra,=,%d,pc,=", op->jump); 449 | break; 450 | case I_car: 451 | op->type = R_ANAL_OP_TYPE_CALL; 452 | op->jump = addr + imm & MASK_27; 453 | op->fail = addr + op->size; 454 | r_strbuf_setf (&op->esil, "pc,ra,=,%d,pc,=", op->jump); 455 | break; 456 | case I_cr: 457 | op->type = R_ANAL_OP_TYPE_RCALL | (inst.cc == CC_always ? 0 : R_ANAL_OP_TYPE_COND); 458 | op->jump = -1; 459 | op->fail = addr + op->size; 460 | op->reg = regs[inst.rA]; 461 | CC_SWITCH (",?{,pc,ra,=,%s,pc,=,}", op->reg); 462 | break; 463 | case I_lds: 464 | case I_ldt: 465 | case I_ldw: { 466 | int t = inst.id == I_lds ? 1 : inst.id == I_ldw ? 2 : 3; 467 | op->type = R_ANAL_OP_TYPE_LOAD; 468 | op->refptr = t; 469 | if (inst.rB == REG_ST && inst.adj_rb) { 470 | op->stackop = R_ANAL_STACK_INC; 471 | if (inst.adj_rb == 1) 472 | op->stackptr = -inst.reg_count * t; 473 | else if (inst.adj_rb == 2) 474 | op->stackptr = inst.reg_count * t; 475 | } 476 | // anal/fcn.c:r_anal_fcn_fill_args uses "0x..,st,+" like patterns to detect access of local variable/argument 477 | // The first 4 commands are used to cheat r_anal_fcn_fill_args 478 | r_strbuf_setf (&op->esil, "%#x,%s,%c,POP, %d,%d,%d,%d,%d,%d,load", 479 | abs (imm), rB, imm < 0 ? '-' : '+', 480 | inst.reg_count, imm, inst.rB, inst.rA, inst.adj_rb, t); 481 | break; 482 | } 483 | case I_sts: 484 | case I_stt: 485 | case I_stw: { 486 | int t = inst.id == I_sts ? 1 : inst.id == I_stw ? 2 : 3; 487 | op->type = R_ANAL_OP_TYPE_STORE; 488 | if (inst.rB == REG_ST && inst.adj_rb) { 489 | op->stackop = R_ANAL_STACK_INC; 490 | if (inst.adj_rb == 1) 491 | op->stackptr = -inst.reg_count * t; 492 | else if (inst.adj_rb == 2) 493 | op->stackptr = inst.reg_count * t; 494 | } 495 | // See the comment above for case I_ldw: 496 | r_strbuf_setf (&op->esil, "%#x,%s,%c,POP, %d,%d,%d,%d,%d,%d,store", 497 | abs (imm), rB, imm < 0 ? '-' : '+', 498 | inst.reg_count, imm, inst.rB, inst.rA, inst.adj_rb, t); 499 | break; 500 | } 501 | TYPE_E (ad, ADD, "%s,%s,%s,'%s+,binop", rC, rB, rA, if_uf); 502 | TYPE_E (adc, ADD, "%s,%s,%s,'%sc+,binop", rC, rB, rA, if_uf); 503 | TYPE_E (adci, ADD, "%d,%s,%s,'%sc+,binop", imm, rB, rA, if_uf); 504 | TYPE_E (adcim, ADD, "%d,%s,%s,'%scm+,binop", imm, rB, rA, if_uf); 505 | TYPE_E (adcm, ADD, "%s,%s,%s,'%scm+,binop", rC, rB, rA, if_uf); 506 | TYPE (adf, ADD); 507 | TYPE (adfm, ADD); 508 | TYPE_E (adi, ADD, "%d,%s,%s,'%s+,binop", imm, rB, rA, if_uf); 509 | TYPE_E (adim, ADD, "%d,%s,%s,'%sm+,binop", imm, rB, rA, if_uf); 510 | TYPE_E (adm, ADD, "%s,%s,%s,'%sm+,binop", rC, rB, rA, if_uf); 511 | TYPE_E (an, AND, "%s,%s,%s,'%s&,binop", rC, rB, rA, if_uf); 512 | TYPE_E (ani, AND, "%d,%s,%s,'%s&,binop", imm, rB, rA, if_uf); 513 | TYPE_E (anm, AND, "%s,%s,%s,'%sm&,binop", rC, rB, rA, if_uf); 514 | TYPE_E (bf, XOR, "%s,%s,'%s~,unop", rB, rA, if_uf); 515 | TYPE_E (bfm, XOR, "%s,%s,'%sm~,unop", rB, rA, if_uf); 516 | TYPE_E (cm, CMP, "%s,%s,',compare", rB, rA); 517 | TYPE (cmf, CMP); 518 | TYPE (cmfm, CMP); 519 | TYPE_E (cmi, CMP, "%d,%s,',compare", imm, rA); 520 | TYPE_E (cmim, CMP, "%d,%s,'m,compare", imm, rA); 521 | TYPE_E (cmm, CMP, "%s,%s,'m,compare", rB, rA); 522 | TYPE_E (dbrk, TRAP, "0,%d,$", R_ANAL_TRAP_BREAKPOINT); 523 | TYPE_E (di, MOV, "0x1ff0,4,0x7ffffff,%s,^,<<,&,0x7ffe00f,fl,&,|,fl,=", rA); 524 | TYPE_E (dmt, MOV, "%d,%d,%d,dmt", inst.rC, inst.rB, inst.rA); 525 | TYPE_E (dv, DIV, "%s,%s,%s,'%s/,binop", rC, rB, rA, if_uf); 526 | TYPE (dvf, DIV); 527 | TYPE (dvfm, DIV); 528 | TYPE_E (dvi, DIV, "%d,%s,%s,'%s/,binop", imm, rB, rA, if_uf); 529 | TYPE_E (dvim, DIV, "%d,%s,%s,'%sm/,binop", imm, rB, rA, if_uf); 530 | TYPE_E (dvis, DIV, "%d,%s,%s,'%s//,binop", imm, rB, rA, if_uf); 531 | TYPE_E (dvism, DIV, "%d,%s,%s,'%sm//,binop", imm, rB, rA, if_uf); 532 | TYPE_E (dvm, DIV, "%s,%s,%s,'%sm/,binop", rC, rB, rA, if_uf); 533 | TYPE_E (dvs, DIV, "%s,%s,%s,'%s//,binop", rC, rB, rA, if_uf); 534 | TYPE_E (dvsm, DIV, "%s,%s,%s,'%sm//,binop", rC, rB, rA, if_uf); 535 | TYPE_E (ei, MOV, "0x1ff0,4,%s,<<,&,0x7ffe00f,fl,&,|,fl,=", rA); 536 | TYPE (fti, MOV); 537 | TYPE (ftim, MOV); 538 | TYPE_E (ht, TRAP, "0,%d,$", R_ANAL_TRAP_HALT); 539 | TYPE (ir, RET); 540 | TYPE (itf, MOV); 541 | TYPE (itfm, MOV); 542 | TYPE_E (md, MOD, "%s,%s,%s,'%s%%,binop", rC, rB, rA, if_uf); 543 | TYPE (mdf, MOD); 544 | TYPE (mdfm, MOD); 545 | TYPE_E (mdi, MOD, "%d,%s,%s,'%s%%,binop", imm, rB, rA, if_uf); 546 | TYPE_E (mdim, MOD, "%d,%s,%s,'%sm%%,binop", imm, rB, rA, if_uf); 547 | TYPE_E (mdis, MOD, "%d,%s,%s,'%s%%%%,binop", imm, rB, rA, if_uf); 548 | TYPE_E (mdism, MOD, "%d,%s,%s,'%sm%%%%,binop", imm, rB, rA, if_uf); 549 | TYPE_E (mdm, MOD, "%s,%s,%s,'%sm%%,binop", rC, rB, rA, if_uf); 550 | TYPE_E (mds, MOD, "%s,%s,%s,'%s%%%%,binop", rC, rB, rA, if_uf); 551 | TYPE_E (mdsm, MOD, "%s,%s,%s,'%sm%%%%,binop", rC, rB, rA, if_uf); 552 | TYPE_E (mh, MOV, "0x3ff,%s,&,10,%d,<<,|,%s,=,", rA, imm, rA); 553 | TYPE_E (ml, MOV, "%d,%s,=", imm, rA); 554 | TYPE_E (ms, MOV, "%d,%d,&,%s,=", MASK_27, imm, rA); 555 | TYPE_E (mu, MUL, "%s,%s,%s,'%s*,binop", rC, rB, rA, if_uf); 556 | TYPE (muf, MUL); 557 | TYPE (mufm, MUL); 558 | TYPE_E (mui, MUL, "%d,%s,%s,'%s*,binop", imm, rB, rA, if_uf); 559 | TYPE_E (muim, MUL, "%d,%s,%s,'%sm*,binop", imm, rB, rA, if_uf); 560 | TYPE_E (muis, MUL, "%d,%s,%s,'%s**,binop", imm, rB, rA, if_uf); 561 | TYPE_E (muism, MUL, "%d,%s,%s,'%sm**,binop", imm, rB, rA, if_uf); 562 | TYPE_E (mum, MUL, "%s,%s,%s,'%sm*,binop", rC, rB, rA, if_uf); 563 | TYPE_E (mus, MUL, "%s,%s,%s,'%s**,binop", rC, rB, rA, if_uf); 564 | TYPE_E (musm, MUL, "%s,%s,%s,'%sm**,binop", rC, rB, rA, if_uf); 565 | TYPE_E (ng, SUB, "%s,%s,'%s-,unop", rB, rA, if_uf); 566 | TYPE (ngf, SUB); 567 | TYPE (ngfm, SUB); 568 | TYPE_E (ngm, SUB, "%s,%s,'%sm-,unop", rB, rA, if_uf); 569 | TYPE_E (nt, NOT, "%s,%s,'%s!,unop", rB, rA, if_uf); 570 | TYPE_E (ntm, NOT, "%s,%s,'%sm!,unop", rB, rA, if_uf); 571 | TYPE_E (or, OR, "%s,%s,%s,'%s|,binop", rC, rB, rA, if_uf); 572 | TYPE_E (ori, OR, "%d,%s,%s,'%s|,binop", imm, rB, rA, if_uf); 573 | TYPE_E (orm, OR, "%s,%s,%s,'%sm|,binop", rC, rB, rA, if_uf); 574 | TYPE_E (re, RET, "ra,pc,="); 575 | TYPE_E (rf, MOV, "fl,%s,=", rA); 576 | TYPE_E (rl, ROL, "%s,%s,%s,'%sr<<,binop", rC, rB, rA, if_uf); 577 | TYPE_E (rli, ROL, "%d,%s,%s,'%sr<<,binop", imm, rB, rA, if_uf); 578 | TYPE_E (rlim, ROL, "%d,%s,%s,'%smr<<,binop", imm, rB, rA, if_uf); 579 | TYPE_E (rlm, ROL, "%s,%s,%s,'%smr<<,binop", rC, rB, rA, if_uf); 580 | TYPE_E (rmp, SWI, "%d,$", I_rmp); 581 | TYPE_E (rnd, SWI, "%d,$", I_rnd); 582 | TYPE_E (rndm, SWI, "%d,$", I_rndm); 583 | TYPE_E (rr, ROR, "%s,%s,%s,'%sr>>,binop", rC, rB, rA, if_uf); 584 | TYPE_E (rri, ROR, "%d,%s,%s,'%sr>>,binop", imm, rB, rA, if_uf); 585 | TYPE_E (rrim, ROR, "%d,%s,%s,'%smr>>,binop", imm, rB, rA, if_uf); 586 | TYPE_E (rrm, ROR, "%s,%s,%s,'%smr>>,binop", rC, rB, rA, if_uf); 587 | TYPE_E (sa, SAR, "%s,%s,%s,'%s>>>,binop", rC, rB, rA, if_uf); 588 | TYPE_E (sai, SAR, "%d,%s,%s,'%s>>>,binop", imm, rB, rA, if_uf); 589 | TYPE_E (saim, SAR, "%d,%s,%s,'%sm>>>,binop", imm, rB, rA, if_uf); 590 | TYPE_E (sam, SAR, "%s,%s,%s,'%sm>>>,binop", rC, rB, rA, if_uf); 591 | TYPE_E (sb, SUB, "%s,%s,%s,'%s-,binop", rC, rB, rA, if_uf); 592 | TYPE_E (sbc, SUB, "%s,%s,%s,'%sc-,binop", rC, rB, rA, if_uf); 593 | TYPE_E (sbci, SUB, "%d,%s,%s,'%sc-,binop", imm, rB, rA, if_uf); 594 | TYPE_E (sbcim, SUB, "%d,%s,%s,'%scm-,binop", imm, rB, rA, if_uf); 595 | TYPE_E (sbcm, SUB, "%s,%s,%s,'%scm-,binop", rC, rB, rA, if_uf); 596 | TYPE (sbf, SUB); 597 | TYPE (sbfm, SUB); 598 | TYPE_E (sbi, SUB, "%d,%s,%s,'%s-,binop", imm, rB, rA, if_uf); 599 | TYPE_E (sbim, SUB, "%d,%s,%s,'%sm-,binop", imm, rB, rA, if_uf); 600 | TYPE_E (sbm, SUB, "%s,%s,%s,'%sm-,binop", rC, rB, rA, if_uf); 601 | TYPE_E (ses, CPL, "%d,55,55,%s,<<,>>>>,&,%s,=", MASK_27, rB, rA); 602 | TYPE_E (sew, CPL, "%d,46,46,%s,<<,>>>>,&,%s,=", MASK_27, rB, rA); 603 | TYPE_E (sf, MOV, "%s,fl,=", rA); 604 | TYPE_E (sl, SHL, "%s,%s,%s,'%s<<,binop", rC, rB, rA, if_uf); 605 | TYPE_E (sli, SHL, "%d,%s,%s,'%s<<,binop", imm, rB, rA, if_uf); 606 | TYPE_E (slim, SHL, "%d,%s,%s,'%sm<<,binop", imm, rB, rA, if_uf); 607 | TYPE_E (slm, SHL, "%s,%s,%s,'%sm<<,binop", rC, rB, rA, if_uf); 608 | TYPE_E (smp, SWI, "%d,%d,%d,smp", inst.mem_flags, inst.rB, inst.rA); 609 | TYPE_E (sr, SHR, "%s,%s,%s,'%s>>,binop", rC, rB, rA, if_uf); 610 | TYPE_E (sri, SHR, "%d,%s,%s,'%s>>,binop", imm, rB, rA, if_uf); 611 | TYPE_E (srim, SHR, "%d,%s,%s,'%sm>>,binop", imm, rB, rA, if_uf); 612 | TYPE_E (srm, SHR, "%s,%s,%s,'%sm>>,binop", rC, rB, rA, if_uf); 613 | TYPE_E (xr, XOR, "%s,%s,%s,'%s^,binop", rC, rB, rA, if_uf); 614 | TYPE_E (xri, XOR, "%d,%s,%s,'%s^,binop", imm, rB, rA, if_uf); 615 | TYPE_E (xrm, XOR, "%s,%s,%s,'%sm^,binop", rC, rB, rA, if_uf); 616 | TYPE_E (zes, CPL, "%d,%s,&,%s,=", MASK_9, rB, rA); 617 | TYPE_E (zew, CPL, "%d,%s,&,%s,=", MASK_18, rB, rA); 618 | } 619 | } else { 620 | op->size = 1; 621 | } 622 | return op->size; 623 | } 624 | 625 | static int indicememoria = 0; 626 | static ut32 idxInputText = 0; 627 | static char texto[] ="packers_and_vms_and_xors_oh_my\n"; 628 | 629 | static int esil_clcy_intr (RAnalEsil *esil, int intr) { 630 | ut64 valor1; 631 | if (!esil) 632 | return false; 633 | if (intr==0) { 634 | reg_read(esil,"r_00",&valor1); 635 | eprintf("%c\n",(ut32)valor1); 636 | } else if (intr==0x4) { 637 | eprintf("Leido %c\n",texto[idxInputText]); 638 | reg_write(esil,"r_00",(ut64)((char) texto[idxInputText++])); 639 | } 640 | else if (intr==0x11) { 641 | ut64 basedata=0; 642 | reg_read(esil,"r_00",&valor1); 643 | reg_read(esil,"r_data",&basedata); 644 | int v1=indicememoria; 645 | indicememoria+= valor1; 646 | 647 | reg_write(esil,"r_00",(ut64) basedata+v1); 648 | } 649 | else 650 | eprintf ("INTERRUPT 0x%02x \n", intr); 651 | return true; 652 | } 653 | 654 | static int set_reg_profile(RAnal *anal) { 655 | // esil does not support 27-bit registers, thus padding them to 32-bit. 656 | const char *p = \ 657 | "#r0 return value\n" 658 | "=PC pc\n" 659 | "=SP st\n" 660 | "=BP r28\n" 661 | "=A0 r0\n" 662 | "=A1 r1\n" 663 | "=A2 r2\n" 664 | "=A3 r3\n" 665 | "=A4 r4\n" 666 | "=A5 r5\n" 667 | "=A6 r6\n" 668 | "=A7 r7\n" 669 | "=A8 r8\n" 670 | "gpr r0 .32 0 0\n" 671 | "gpr r1 .32 4 0\n" 672 | "gpr r2 .32 8 0\n" 673 | "gpr r3 .32 12 0\n" 674 | "gpr r4 .32 16 0\n" 675 | "gpr r5 .32 20 0\n" 676 | "gpr r6 .32 24 0\n" 677 | "gpr r7 .32 28 0\n" 678 | "gpr r8 .32 32 0\n" 679 | "gpr r9 .32 36 0\n" 680 | "gpr r10 .32 40 0\n" 681 | "gpr r11 .32 44 0\n" 682 | "gpr r12 .32 48 0\n" 683 | "gpr r13 .32 52 0\n" 684 | "gpr r14 .32 56 0\n" 685 | "gpr r15 .32 60 0\n" 686 | "gpr r16 .32 64 0\n" 687 | "gpr r17 .32 68 0\n" 688 | "gpr r18 .32 72 0\n" 689 | "gpr r19 .32 76 0\n" 690 | "gpr r20 .32 80 0\n" 691 | "gpr r21 .32 84 0\n" 692 | "gpr r22 .32 88 0\n" 693 | "gpr r23 .32 92 0\n" 694 | "gpr r24 .32 96 0\n" 695 | "gpr r25 .32 100 0\n" 696 | "gpr r26 .32 104 0\n" 697 | "gpr r27 .32 108 0\n" 698 | "gpr r28 .32 112 0\n" 699 | "gpr st .32 116 0\n" 700 | "gpr ra .32 120 0\n" 701 | "gpr pc .32 124 0\n" 702 | "flg fl .32 128 0 zcos\n" 703 | "flg zf .1 128.0 0\n" 704 | "flg cf .1 128.1 0\n" 705 | "flg of .1 128.2 0\n" 706 | "flg sf .1 128.3 0\n"; 707 | 708 | return r_reg_set_profile_string (anal->reg, p); 709 | } 710 | 711 | static int esil_clcy_init (RAnalEsil *esil) { 712 | r_anal_esil_set_op (esil, "binop", clcy_custom_binop); 713 | r_anal_esil_set_op (esil, "compare", clcy_custom_compare); 714 | r_anal_esil_set_op (esil, "dmt", clcy_custom_dmt); 715 | r_anal_esil_set_op (esil, "load", clcy_custom_load); 716 | r_anal_esil_set_op (esil, "smp", clcy_custom_smp); 717 | r_anal_esil_set_op (esil, "store", clcy_custom_store); 718 | r_anal_esil_set_op (esil, "unop", clcy_custom_unop); 719 | return true; 720 | } 721 | 722 | static int esil_clcy_fini (RAnalEsil *esil) { 723 | return true; 724 | } 725 | 726 | static RAnalPlugin r_anal_plugin_clcy = { 727 | .name = "clcy", 728 | .desc = "cLEMENCy analysis", 729 | .license = "LGPL3", 730 | .arch = "clcy", 731 | .bits = 64, // we use 64-bit integers in esil to emulate 27-bit and 54-bit 732 | .esil_init = esil_clcy_init, 733 | .esil_fini = esil_clcy_fini, 734 | .esil_intr = esil_clcy_intr, 735 | .esil = true, 736 | .op = &clcy_op, 737 | .set_reg_profile = set_reg_profile, 738 | }; 739 | 740 | RLibStruct radare_plugin = { 741 | .type = R_LIB_TYPE_ANAL, 742 | .data = &r_anal_plugin_clcy, 743 | .version = R2_VERSION, 744 | }; 745 | -------------------------------------------------------------------------------- /clemency/bin/bin_clcy.c: -------------------------------------------------------------------------------- 1 | /* radare - LGPL - Copyright 2017 - MaskRay */ 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #define NFO_VADDR 0x5100000 9 | 10 | // All DEFCON 25 CTF Finals executables have the pattern of cLEMENCy neatcc 11 | static const ut16 MAGIC[] = { 12 | 0x0040, 0x0158, 0x0040, 0x0001, 0x0000, 0x00b8, 0x0003, 0x0148 13 | }; 14 | 15 | // Extracted from clemency_nfo.c 16 | static const ut8 CLEMENCY_NFO[] = { 17 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 18 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 19 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 20 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 21 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 22 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2c, 0x4a, 0x61, 0x70, 0x39, 23 | 0x4c, 0x62, 0x5c, 0x2c, 0x72, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 24 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 25 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 26 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 27 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 28 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 29 | 0x20, 0x5a, 0x5f, 0x3a, 0x70, 0x3b, 0x4c, 0x34, 0x27, 0x39, 0x49, 0x43, 30 | 0x7e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 31 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 32 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 33 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 34 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 35 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x64, 0x31, 0x3b, 36 | 0x38, 0x25, 0x73, 0x7d, 0x3c, 0x21, 0x3d, 0x29, 0x55, 0x78, 0x2a, 0x0a, 37 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 38 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 39 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 40 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 41 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 42 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x4e, 0x6e, 0x2a, 0x27, 0x42, 0x5c, 43 | 0x79, 0x6b, 0x2a, 0x5f, 0x65, 0x6f, 0x22, 0x70, 0x0a, 0x20, 0x20, 0x20, 44 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 45 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 46 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 47 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 48 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 49 | 0x20, 0x4b, 0x54, 0x25, 0x82, 0xce, 0x97, 0x2d, 0x3b, 0x42, 0x36, 0x5d, 50 | 0x20, 0x50, 0x35, 0x73, 0x3a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 51 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 52 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 53 | 0x20, 0x20, 0x20, 0x27, 0x26, 0x65, 0x24, 0x4c, 0x43, 0x5c, 0x27, 0x20, 54 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 55 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x69, 0x2d, 56 | 0x35, 0xb0, 0x5d, 0x31, 0x61, 0x54, 0x4c, 0x42, 0x43, 0x20, 0x50, 0x15, 57 | 0xa5, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 58 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 59 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x29, 60 | 0x64, 0x3a, 0x24, 0x4a, 0x70, 0x52, 0xfb, 0x55, 0x42, 0x59, 0x66, 0x20, 61 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 62 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x2c, 0x7b, 0x58, 0x5d, 0x39, 0x51, 0x52, 63 | 0x28, 0x41, 0x24, 0x7a, 0xff, 0x4c, 0x26, 0x51, 0x0a, 0x20, 0x20, 0x20, 64 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 65 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 66 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x7a, 0x6d, 0xbe, 0x43, 0xb7, 0x68, 67 | 0x72, 0x33, 0x59, 0x7c, 0x71, 0x4f, 0x7e, 0x20, 0x20, 0x20, 0x20, 0x20, 68 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x25, 69 | 0x5f, 0x33, 0x7a, 0x62, 0x23, 0x78, 0x4b, 0x66, 0x47, 0x6b, 0x33, 0x5d, 70 | 0x6e, 0x31, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 71 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 72 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7d, 73 | 0x65, 0x48, 0x5e, 0x4d, 0xa9, 0x27, 0xe9, 0x78, 0x9f, 0xe7, 0x36, 0x50, 74 | 0x3d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 75 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x58, 0x3a, 0x53, 0x6e, 0x32, 0x7d, 0x36, 76 | 0x72, 0x3f, 0x59, 0x48, 0x3e, 0x54, 0x69, 0x0a, 0x20, 0x20, 0x20, 0x20, 77 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 78 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 79 | 0x20, 0x20, 0x20, 0x4b, 0xef, 0x40, 0x2b, 0x60, 0x31, 0x7e, 0x72, 0x59, 80 | 0x70, 0xc4, 0x59, 0x6b, 0x25, 0xf7, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 81 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4b, 0x78, 0x65, 82 | 0x6d, 0x58, 0x22, 0x71, 0x38, 0x30, 0x61, 0x27, 0x4d, 0x46, 0x7e, 0x0a, 83 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 84 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 85 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x38, 0x9a, 0x47, 0x62, 0x26, 86 | 0x26, 0x98, 0x77, 0x34, 0x71, 0x56, 0xaf, 0x74, 0x58, 0x20, 0x20, 0x20, 87 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 88 | 0xdc, 0x55, 0x34, 0x7a, 0x2e, 0x3d, 0x29, 0x56, 0x8f, 0x48, 0x5d, 0x4a, 89 | 0x3f, 0x3f, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 90 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 91 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6b, 0x6b, 0x73, 92 | 0x31, 0xc8, 0x66, 0x32, 0x77, 0x32, 0x72, 0x35, 0x48, 0x20, 0x50, 0x0f, 93 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 94 | 0xe8, 0x4f, 0x42, 0x2d, 0x88, 0x62, 0x51, 0x6d, 0x66, 0xb6, 0x41, 0x7b, 95 | 0x20, 0x50, 0x26, 0x50, 0x7a, 0x71, 0x61, 0x51, 0x58, 0x78, 0x73, 0x7d, 96 | 0x56, 0x38, 0x5b, 0x3c, 0x7b, 0x56, 0x40, 0x27, 0x71, 0x5c, 0x5c, 0x60, 97 | 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 98 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 99 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x7c, 0x48, 0x6e, 0x6e, 0x51, 0x39, 100 | 0x3f, 0x77, 0x52, 0x35, 0xc8, 0x57, 0x72, 0x57, 0x22, 0x48, 0x43, 0x6b, 101 | 0x20, 0x50, 0x37, 0x25, 0x3f, 0xe6, 0xf6, 0x5c, 0x34, 0x6e, 0x46, 0x25, 102 | 0x4a, 0x65, 0x60, 0x59, 0x25, 0x37, 0x2d, 0xd8, 0x40, 0x57, 0x2a, 0x2a, 103 | 0x6c, 0x42, 0x43, 0x20, 0x50, 0x3c, 0x63, 0x21, 0x3f, 0x50, 0x36, 0x5f, 104 | 0x71, 0x45, 0x36, 0x3c, 0x36, 0x41, 0x57, 0x0a, 0x20, 0x20, 0x20, 0x20, 105 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 106 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 107 | 0x46, 0x62, 0x21, 0x6b, 0x21, 0xab, 0x44, 0x57, 0x64, 0x25, 0x82, 0xc8, 108 | 0x72, 0x25, 0x26, 0x72, 0x2d, 0xf5, 0x20, 0x50, 0x33, 0x65, 0x36, 0x48, 109 | 0x24, 0x72, 0x63, 0x70, 0x5d, 0x26, 0x75, 0x2e, 0x65, 0x58, 0x37, 0x5c, 110 | 0x2d, 0xf0, 0x5b, 0x37, 0x24, 0x29, 0x46, 0x72, 0xdf, 0x20, 0x50, 0x14, 111 | 0x5a, 0x3b, 0x2a, 0x79, 0x32, 0x6c, 0x38, 0x59, 0x52, 0x6f, 0x50, 0xaa, 112 | 0x6a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 113 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xf2, 0x48, 114 | 0x36, 0x26, 0x45, 0x50, 0x4f, 0x67, 0x29, 0x98, 0x7a, 0x97, 0x32, 0xc3, 115 | 0x9a, 0x70, 0x62, 0x20, 0x50, 0x27, 0x23, 0x42, 0x6e, 0x5c, 0x79, 0x64, 116 | 0x79, 0x75, 0x64, 0x26, 0x6f, 0x64, 0xa2, 0x41, 0x4c, 0x35, 0xb0, 0x4c, 117 | 0x52, 0xf6, 0x77, 0x72, 0x2a, 0x8e, 0x20, 0x50, 0x01, 0x5c, 0xdd, 0x3b, 118 | 0x32, 0x6c, 0x42, 0xa5, 0x9c, 0x30, 0x3f, 0x5b, 0xd8, 0x5d, 0x77, 0x0a, 119 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 120 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x43, 0x53, 0x47, 0x6a, 0x3b, 121 | 0x6b, 0x47, 0x63, 0x31, 0x88, 0x60, 0x62, 0x28, 0x58, 0x24, 0x41, 0xb3, 122 | 0x20, 0x50, 0x34, 0x62, 0x2e, 0x62, 0x63, 0xba, 0x31, 0x3a, 0x75, 0x44, 123 | 0x3e, 0x6a, 0x6d, 0x5a, 0x4f, 0x33, 0x35, 0xc8, 0x50, 0x77, 0x2a, 0x31, 124 | 0x4c, 0x86, 0x6b, 0x20, 0x50, 0x21, 0x53, 0x61, 0x2f, 0x65, 0xd2, 0x4a, 125 | 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 126 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x72, 0x6f, 0x3b, 0x48, 127 | 0x72, 0x27, 0x70, 0x21, 0x82, 0xc7, 0x77, 0x29, 0x25, 0x32, 0x65, 0xe6, 128 | 0x20, 0x50, 0x1d, 0x24, 0x4f, 0x69, 0x62, 0x40, 0x5e, 0x4b, 0x67, 0x2f, 129 | 0x4f, 0x79, 0x5d, 0x4c, 0x69, 0x4e, 0x2d, 0xb8, 0x71, 0x72, 0xce, 0xa1, 130 | 0x48, 0x47, 0x4b, 0x20, 0x50, 0x23, 0x3d, 0x38, 0x6f, 0x0a, 0x20, 0x20, 131 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 132 | 0x20, 0x20, 0x20, 0x20, 0x20, 0xf9, 0x61, 0x58, 0x47, 0x31, 0xa1, 0x61, 133 | 0x7e, 0x7f, 0x29, 0x35, 0xa0, 0x61, 0xb2, 0x2a, 0x40, 0x58, 0x43, 0x33, 134 | 0x20, 0x50, 0x32, 0x3f, 0x7c, 0x6f, 0x57, 0xfb, 0x47, 0x4c, 0x9d, 0x3b, 135 | 0x20, 0x20, 0x20, 0x20, 0x71, 0x69, 0x3f, 0x68, 0x34, 0x2e, 0x43, 0x5e, 136 | 0xa4, 0x3a, 0x45, 0x4e, 0x65, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 137 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x43, 0x3e, 0x20, 0x5a, 0x96, 138 | 0x32, 0x52, 0x76, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 139 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 140 | 0x5a, 0x74, 0x43, 0x33, 0x3b, 0x3c, 0x2e, 0x5b, 0x77, 0x35, 0x25, 0x31, 141 | 0x4b, 0x6f, 0x78, 0x28, 0x6a, 0xb1, 0x3d, 0x20, 0x20, 0x20, 0x20, 0x20, 142 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x61, 0x44, 143 | 0x35, 0x90, 0x44, 0x73, 0xe3, 0x33, 0x58, 0x41, 0x7b, 0x20, 0x50, 0x2a, 144 | 0x24, 0x42, 0x71, 0x57, 0x36, 0x5b, 0x34, 0x72, 0x93, 0x68, 0x3d, 0x3c, 145 | 0x40, 0x21, 0x72, 0x47, 0x50, 0x75, 0x7b, 0xfd, 0x4f, 0x34, 0x0a, 0x20, 146 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 147 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0xd6, 0x5a, 0x95, 148 | 0x5f, 0x59, 0x56, 0x35, 0xd8, 0x73, 0xb7, 0x32, 0x43, 0x66, 0x57, 0x32, 149 | 0x20, 0x50, 0x34, 0x50, 0x25, 0x41, 0xab, 0x77, 0x92, 0x91, 0x2b, 0x6c, 150 | 0x34, 0x23, 0x2d, 0x48, 0x53, 0x69, 0x35, 0xa0, 0x5a, 0xa2, 0x25, 0xda, 151 | 0x62, 0x20, 0x90, 0x20, 0x50, 0x18, 0x35, 0x7d, 0x76, 0x2f, 0xac, 0x55, 152 | 0x54, 0x65, 0x6c, 0x7a, 0x27, 0x67, 0x90, 0x2d, 0x27, 0x5f, 0x74, 0x6f, 153 | 0x61, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 154 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 155 | 0x20, 0x20, 0x20, 0x61, 0x5a, 0x54, 0x7a, 0xed, 0x40, 0x29, 0x80, 0x46, 156 | 0x77, 0x3c, 0x4e, 0x42, 0x74, 0xb2, 0x20, 0x50, 0x17, 0x3f, 0xbe, 0x52, 157 | 0x70, 0x5c, 0x67, 0x2e, 0x53, 0x24, 0x7d, 0x33, 0x3f, 0x63, 0x47, 0x6d, 158 | 0x31, 0xb0, 0x60, 0x72, 0x53, 0xa2, 0x72, 0x6b, 0xad, 0x20, 0x50, 0x3b, 159 | 0x31, 0x6c, 0x50, 0x79, 0x3b, 0x5b, 0x43, 0x67, 0x3b, 0x7c, 0x57, 0x0a, 160 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 161 | 0x20, 0x20, 0xcf, 0x2d, 0x4e, 0x8f, 0x49, 0x4d, 0x50, 0x35, 0xc0, 0x72, 162 | 0x52, 0x5b, 0x5f, 0x22, 0x30, 0x76, 0x20, 0x50, 0x21, 0x48, 0x3a, 0x5a, 163 | 0x5e, 0x6c, 0x37, 0x5d, 0x41, 0x21, 0x7b, 0x4c, 0x2a, 0x77, 0xcb, 0x35, 164 | 0x35, 0xd0, 0x6c, 0x73, 0x49, 0xa0, 0x52, 0x37, 0x27, 0x20, 0x50, 0x2a, 165 | 0x3c, 0x2c, 0xd6, 0xf5, 0x48, 0x3a, 0x50, 0x23, 0xdf, 0x58, 0x32, 0x0a, 166 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 167 | 0x20, 0x2c, 0x23, 0x2c, 0x71, 0x7e, 0x62, 0x51, 0x58, 0x31, 0xe0, 0x4c, 168 | 0xf3, 0x8e, 0x21, 0x52, 0x3a, 0x35, 0x20, 0x50, 0x29, 0x38, 0x37, 0x6e, 169 | 0x21, 0x44, 0x2d, 0x6f, 0x3a, 0x62, 0x33, 0x2c, 0x5a, 0x2f, 0x7b, 0x5e, 170 | 0x25, 0x82, 0xd8, 0x93, 0x6d, 0x41, 0x2e, 0x5b, 0x27, 0x20, 0x50, 0x2d, 171 | 0x7e, 0x27, 0x77, 0x55, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x43, 172 | 0x3d, 0x6d, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x49, 0x53, 0x3a, 173 | 0x37, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 174 | 0x20, 0x20, 0x61, 0x65, 0x3d, 0x48, 0x35, 0xa0, 0x58, 0xf1, 0x65, 0x34, 175 | 0x3a, 0x60, 0x2a, 0x20, 0x50, 0x1f, 0x5c, 0x41, 0x4c, 0x56, 0x24, 0x56, 176 | 0x56, 0x39, 0x28, 0x44, 0x6e, 0x38, 0x2c, 0x2f, 0x46, 0x2d, 0x98, 0x42, 177 | 0xb7, 0x26, 0x23, 0xc6, 0x99, 0x81, 0x20, 0x50, 0x1e, 0x68, 0x27, 0xf8, 178 | 0x34, 0x6a, 0x56, 0x51, 0xf6, 0x30, 0x3c, 0x7e, 0xf0, 0x3b, 0x20, 0x20, 179 | 0x69, 0x66, 0x49, 0x50, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x48, 180 | 0x4c, 0x7a, 0x2f, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 181 | 0x20, 0x20, 0x20, 0x20, 0x30, 0x35, 0xd4, 0x4d, 0x3b, 0x22, 0xff, 0x5a, 182 | 0x31, 0xe8, 0x4f, 0x24, 0x36, 0x58, 0x4e, 0x4a, 0xe1, 0x20, 0x50, 0x27, 183 | 0x75, 0x6e, 0x6a, 0x66, 0x46, 0x73, 0x6d, 0x3d, 0x4c, 0x36, 0x2a, 0x4b, 184 | 0x3d, 0x57, 0x61, 0x35, 0x80, 0x5c, 0x37, 0x20, 0x31, 0x5a, 0x54, 0x4a, 185 | 0x20, 0x50, 0x2c, 0x58, 0x4c, 0x25, 0x51, 0x7a, 0x59, 0x20, 0x78, 0x20, 186 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 187 | 0x20, 0x75, 0x6d, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 188 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x67, 0x48, 0x5b, 0x4a, 0x35, 0xa8, 0x74, 189 | 0x53, 0x58, 0x24, 0x7e, 0xe7, 0x54, 0x20, 0x50, 0x38, 0x49, 0x5a, 0x23, 190 | 0x72, 0x6d, 0x26, 0x7c, 0x36, 0x42, 0x3b, 0xe8, 0x62, 0x26, 0x7c, 0x4e, 191 | 0x46, 0x29, 0x73, 0x47, 0x62, 0x4f, 0x31, 0x3f, 0x4c, 0x37, 0x7d, 0x6e, 192 | 0x91, 0x46, 0x67, 0x37, 0x59, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 193 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2e, 0x94, 0x9c, 0x35, 0x7b, 0xc7, 194 | 0x58, 0x3c, 0x5d, 0x59, 0x43, 0x74, 0x29, 0x38, 0x6b, 0x72, 0x3f, 0x5c, 195 | 0x66, 0x6b, 0x2c, 0x6d, 0x49, 0xfb, 0xe0, 0x74, 0x5d, 0x75, 0x42, 0x20, 196 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x58, 0x7e, 0x7a, 0x47, 197 | 0x67, 0x33, 0x6c, 0xb9, 0x64, 0x42, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 198 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x6f, 0x58, 0x28, 0x2c, 0x70, 199 | 0x45, 0x72, 0x67, 0x45, 0x7c, 0x69, 0x53, 0x7d, 0x5c, 0x39, 0x46, 0x47, 200 | 0x7d, 0x3c, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 201 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x66, 0x7c, 0x4e, 0x25, 202 | 0x76, 0x30, 0x51, 0x92, 0x3e, 0x5a, 0x40, 0x0a, 0x20, 0x20, 0x20, 0x20, 203 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 204 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x32, 0x47, 0x95, 0x45, 0xaf, 0x7c, 0x44, 205 | 0x76, 0x70, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 206 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x57, 0x3d, 0x6d, 207 | 0x49, 0x5e, 0x2e, 0x63, 0x50, 0x6c, 0x69, 0x0a, 0x20, 0x20, 0x20, 0x20, 208 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 209 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x62, 0x2a, 0xc5, 0x49, 0x4d, 0x57, 0x5c, 210 | 0xfb, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 211 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x29, 0x9f, 0xc4, 0x2b, 212 | 0x4f, 0x3e, 0x55, 0x61, 0xff, 0x60, 0x5b, 0x0a, 0x20, 0x20, 0x20, 0x20, 213 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 214 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x75, 0x73, 0x61, 0x76, 0x48, 0x20, 215 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 216 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x56, 0x43, 0x5e, 0x7f, 217 | 0x6c, 0x22, 0xe9, 0x75, 0x3e, 0x4e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 218 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 219 | 0x20, 0x20, 0x20, 0x20, 0x2b, 0x28, 0x25, 0x48, 0x43, 0x20, 0x20, 0x20, 220 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 221 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x37, 0xcf, 0x52, 0x6f, 0x7b, 0x44, 222 | 0x2e, 0x93, 0x54, 0x44, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 223 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 224 | 0x20, 0x73, 0x77, 0x3e, 0x79, 0x5f, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 225 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 226 | 0x20, 0x20, 0x20, 0x20, 0x5a, 0x32, 0x46, 0x2e, 0x73, 0x38, 0x26, 0x56, 227 | 0x47, 0x6e, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 228 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 229 | 0x61, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 230 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 231 | 0x20, 0x24, 0x7f, 0x6f, 0x24, 0x2a, 0x3e, 0x3a, 0x50, 0x30, 0x0a, 0x20, 232 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 233 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 234 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 235 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x77, 0x71, 0x4e, 236 | 0x53, 0x55, 0x70, 0x7b, 0x27, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 237 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 238 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 239 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 240 | 0x20, 0x20, 0x20, 0xef, 0x60, 0x29, 0x65, 0xd0, 0x49, 0xae, 0x0a, 0x0a, 241 | 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 242 | 0x20, 0x20, 0x2d, 0x2d, 0x3d, 0x2d, 0x2d, 0x3d, 0x2d, 0x2d, 0x3d, 0x2d, 243 | 0x2d, 0x3d, 0x2d, 0x2d, 0x3d, 0x2d, 0x2d, 0x52, 0x65, 0x6c, 0x65, 0x61, 244 | 0x73, 0x65, 0x20, 0x4e, 0x6f, 0x74, 0x65, 0x73, 0x2d, 0x2d, 0x3d, 0x2d, 245 | 0x2d, 0x3d, 0x2d, 0x2d, 0x3d, 0x2d, 0x2d, 0x3d, 0x2d, 0x2d, 0x3d, 0x2d, 246 | 0x2d, 0x0a, 0x0a, 0x4e, 0x61, 0x6d, 0x65, 0x3a, 0x20, 0x63, 0x4c, 0x45, 247 | 0x4d, 0x45, 0x4e, 0x43, 0x79, 0x20, 0x45, 0x6d, 0x75, 0x6c, 0x61, 0x74, 248 | 0x6f, 0x72, 0x0a, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x20, 0x64, 249 | 0x61, 0x74, 0x65, 0x3a, 0x20, 0x32, 0x30, 0x31, 0x37, 0x2d, 0x30, 0x37, 250 | 0x2d, 0x32, 0x37, 0x0a, 0x0a, 0x2d, 0x2d, 0x2d, 0x4e, 0x6f, 0x74, 0x65, 251 | 0x73, 0x2d, 0x2d, 0x2d, 0x0a, 0x45, 0x6d, 0x75, 0x6c, 0x61, 0x74, 0x6f, 252 | 0x72, 0x20, 0x66, 0x6f, 0x72, 0x20, 0x44, 0x45, 0x46, 0x20, 0x43, 0x4f, 253 | 0x4e, 0x20, 0x43, 0x54, 0x46, 0x20, 0x32, 0x30, 0x31, 0x37, 0x2c, 0x20, 254 | 0x6c, 0x69, 0x66, 0x74, 0x65, 0x64, 0x20, 0x66, 0x72, 0x6f, 0x6d, 0x20, 255 | 0x4c, 0x69, 0x67, 0x68, 0x74, 0x6e, 0x69, 0x6e, 0x67, 0x27, 0x73, 0x20, 256 | 0x6c, 0x61, 0x70, 0x74, 0x6f, 0x70, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x70, 257 | 0x61, 0x74, 0x63, 0x68, 0x65, 0x64, 0x20, 0x74, 0x6f, 0x20, 0x69, 0x6e, 258 | 0x63, 0x6c, 0x75, 0x64, 0x65, 0x0a, 0x74, 0x68, 0x69, 0x73, 0x20, 0x4e, 259 | 0x46, 0x4f, 0x20, 0x61, 0x74, 0x20, 0x30, 0x78, 0x35, 0x31, 0x30, 0x30, 260 | 0x30, 0x30, 0x30, 0x2c, 0x20, 0x64, 0x6f, 0x6e, 0x27, 0x74, 0x20, 0x77, 261 | 0x6f, 0x72, 0x72, 0x79, 0x2c, 0x20, 0x77, 0x65, 0x20, 0x68, 0x69, 0x6a, 262 | 0x61, 0x63, 0x6b, 0x65, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x67, 0x61, 263 | 0x6d, 0x65, 0x20, 0x6f, 0x6e, 0x65, 0x20, 0x74, 0x6f, 0x6f, 0x2e, 0x20, 264 | 0x48, 0x61, 0x73, 0x20, 0x61, 0x20, 0x62, 0x75, 0x69, 0x6c, 0x74, 0x20, 265 | 0x69, 0x6e, 0x0a, 0x64, 0x65, 0x62, 0x75, 0x67, 0x67, 0x65, 0x72, 0x20, 266 | 0x61, 0x6e, 0x64, 0x20, 0x64, 0x69, 0x73, 0x61, 0x73, 0x73, 0x65, 0x6d, 267 | 0x62, 0x6c, 0x65, 0x72, 0x2e, 0x20, 0x44, 0x65, 0x62, 0x75, 0x67, 0x67, 268 | 0x65, 0x72, 0x20, 0x61, 0x70, 0x70, 0x65, 0x61, 0x72, 0x73, 0x20, 0x74, 269 | 0x6f, 0x20, 0x61, 0x63, 0x63, 0x65, 0x70, 0x74, 0x20, 0x62, 0x61, 0x73, 270 | 0x69, 0x63, 0x20, 0x6d, 0x61, 0x74, 0x68, 0x20, 0x6f, 0x70, 0x65, 0x72, 271 | 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x20, 0x61, 0x6e, 0x64, 0x0a, 0x66, 272 | 0x75, 0x6e, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x20, 0x6e, 0x61, 0x6d, 0x65, 273 | 0x20, 0x75, 0x73, 0x61, 0x67, 0x65, 0x20, 0x69, 0x66, 0x20, 0x6e, 0x6f, 274 | 0x20, 0x73, 0x70, 0x61, 0x63, 0x65, 0x73, 0x20, 0x61, 0x72, 0x65, 0x20, 275 | 0x69, 0x6e, 0x63, 0x6c, 0x75, 0x64, 0x65, 0x64, 0x2c, 0x20, 0x5b, 0x5d, 276 | 0x20, 0x66, 0x6f, 0x72, 0x20, 0x64, 0x65, 0x72, 0x65, 0x66, 0x65, 0x72, 277 | 0x65, 0x6e, 0x63, 0x65, 0x73, 0x2e, 0x0a, 0x0a, 0x53, 0x75, 0x70, 0x70, 278 | 0x6f, 0x72, 0x74, 0x73, 0x20, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x20, 279 | 0x6d, 0x61, 0x70, 0x20, 0x66, 0x69, 0x6c, 0x65, 0x73, 0x2c, 0x20, 0x6e, 280 | 0x6f, 0x74, 0x20, 0x64, 0x6f, 0x63, 0x75, 0x6d, 0x65, 0x6e, 0x74, 0x65, 281 | 0x64, 0x20, 0x62, 0x75, 0x74, 0x20, 0x6c, 0x69, 0x6e, 0x65, 0x73, 0x20, 282 | 0x6c, 0x6f, 0x6f, 0x6b, 0x20, 0x6c, 0x69, 0x6b, 0x65, 0x20, 0x62, 0x65, 283 | 0x6c, 0x6f, 0x77, 0x0a, 0x31, 0x3a, 0x20, 0x5f, 0x73, 0x74, 0x61, 0x72, 284 | 0x74, 0x20, 0x40, 0x20, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x20, 285 | 0x30, 0x0a, 0x32, 0x3a, 0x20, 0x6d, 0x61, 0x69, 0x6e, 0x20, 0x40, 0x20, 286 | 0x30, 0x30, 0x31, 0x61, 0x34, 0x30, 0x38, 0x20, 0x32, 0x35, 0x39, 0x32, 287 | 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 288 | 0x20, 0x20, 0x2d, 0x2d, 0x3d, 0x2d, 0x2d, 0x3d, 0x2d, 0x4c, 0x65, 0x67, 289 | 0x69, 0x74, 0x69, 0x6d, 0x61, 0x74, 0x65, 0x20, 0x42, 0x75, 0x73, 0x69, 290 | 0x6e, 0x65, 0x73, 0x73, 0x20, 0x53, 0x79, 0x6e, 0x64, 0x69, 0x63, 0x61, 291 | 0x74, 0x65, 0x20, 0x43, 0x72, 0x65, 0x77, 0x2d, 0x3d, 0x2d, 0x2d, 0x3d, 292 | 0x2d, 0x2d, 0x0a, 0x0a, 0x44, 0x65, 0x61, 0x64, 0x77, 0x6f, 0x6f, 0x64, 293 | 0x20, 0x20, 0x20, 0x20, 0x46, 0x75, 0x7a, 0x79, 0x6c, 0x6c, 0x20, 0x20, 294 | 0x20, 0x20, 0x20, 0x20, 0x47, 0x79, 0x6e, 0x6f, 0x70, 0x68, 0x61, 0x67, 295 | 0x65, 0x20, 0x20, 0x20, 0x20, 0x48, 0x4a, 0x0a, 0x48, 0x6f, 0x6a, 0x75, 296 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x4a, 0x79, 0x6d, 0x62, 297 | 0x6f, 0x6c, 0x69, 0x61, 0x20, 0x20, 0x20, 0x20, 0x4c, 0x69, 0x67, 0x68, 298 | 0x74, 0x6e, 0x69, 0x6e, 0x67, 0x20, 0x20, 0x20, 0x20, 0x53, 0x65, 0x6c, 299 | 0x69, 0x72, 0x0a, 0x53, 0x69, 0x72, 0x67, 0x6f, 0x6f, 0x6e, 0x20, 0x20, 300 | 0x20, 0x20, 0x20, 0x54, 0x68, 0x69, 0x6e, 0x67, 0x32, 0x20, 0x20, 0x20, 301 | 0x20, 0x20, 0x20, 0x56, 0x69, 0x74, 0x6f, 0x0a, 0x0a, 0x20, 0x20, 0x20, 302 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x3d, 303 | 0x2d, 0x2d, 0x3d, 0x2d, 0x2d, 0x3d, 0x2d, 0x2d, 0x3d, 0x2d, 0x2d, 0x3d, 304 | 0x2d, 0x2d, 0x3d, 0x2d, 0x2d, 0x43, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 305 | 0x2d, 0x2d, 0x3d, 0x2d, 0x2d, 0x3d, 0x2d, 0x2d, 0x3d, 0x2d, 0x2d, 0x3d, 306 | 0x2d, 0x2d, 0x3d, 0x2d, 0x2d, 0x3d, 0x2d, 0x2d, 0x0a, 0x0a, 0x56, 0x69, 307 | 0x61, 0x20, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x3a, 0x20, 0x20, 0x20, 0x2e, 308 | 0x2e, 0x2e, 0x40, 0x6c, 0x65, 0x67, 0x69, 0x74, 0x62, 0x73, 0x2e, 0x6e, 309 | 0x65, 0x74, 0x0a, 0x56, 0x69, 0x61, 0x20, 0x57, 0x65, 0x62, 0x3a, 0x20, 310 | 0x20, 0x20, 0x20, 0x20, 0x77, 0x77, 0x77, 0x2e, 0x6c, 0x65, 0x67, 0x69, 311 | 0x74, 0x62, 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x0a, 0x56, 0x69, 0x61, 0x20, 312 | 0x54, 0x77, 0x69, 0x74, 0x74, 0x65, 0x72, 0x3a, 0x20, 0x23, 0x6c, 0x65, 313 | 0x67, 0x69, 0x74, 0x62, 0x73, 0x5f, 0x63, 0x74, 0x66, 0x0a, 0x0a, 0x20, 314 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x2d, 315 | 0x2d, 0x3d, 0x2d, 0x2d, 0x3d, 0x2d, 0x2d, 0x3d, 0x2d, 0x2d, 0x3d, 0x2d, 316 | 0x2d, 0x3d, 0x2d, 0x2d, 0x3d, 0x2d, 0x2d, 0x3d, 0x47, 0x72, 0x65, 0x65, 317 | 0x74, 0x7a, 0x3d, 0x2d, 0x2d, 0x3d, 0x2d, 0x2d, 0x3d, 0x2d, 0x2d, 0x3d, 318 | 0x2d, 0x2d, 0x3d, 0x2d, 0x2d, 0x3d, 0x2d, 0x2d, 0x3d, 0x2d, 0x2d, 0x0a, 319 | 0x0a, 0x44, 0x61, 0x72, 0x6b, 0x20, 0x54, 0x61, 0x6e, 0x67, 0x65, 0x6e, 320 | 0x74, 0x20, 0x20, 0x20, 0x20, 0x47, 0x72, 0x69, 0x66, 0x74, 0x65, 0x72, 321 | 0x20, 0x20, 0x20, 0x20, 0x53, 0x74, 0x72, 0x79, 0x64, 0x65, 0x20, 0x20, 322 | 0x20, 0x20, 0x48, 0x61, 0x78, 0x0a, 0x53, 0x6f, 0x65, 0x6e, 0x20, 0x20, 323 | 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x41, 0x61, 324 | 0x73, 0x6b, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x50, 0x68, 0x6f, 325 | 0x65, 0x6e, 0x69, 0x78, 0x20, 0x4b, 0x69, 0x61, 0x6e, 0x61, 0x0a, 0x4e, 326 | 0x65, 0x69, 0x6c, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 327 | 0x20, 0x20, 0x20, 0x4e, 0x69, 0x6b, 0x69, 0x74, 0x61, 0x20, 0x20, 0x20, 328 | 0x20, 0x20, 0x50, 0x79, 0x72, 0x30, 0x0a, 0x43, 0x73, 0x65, 0x61, 0x67, 329 | 0x6c, 0x65, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x72, 330 | 0x65, 0x73, 0x74, 0x20, 0x6f, 0x66, 0x20, 0x74, 0x68, 0x65, 0x20, 0x64, 331 | 0x64, 0x74, 0x65, 0x6b, 0x20, 0x63, 0x72, 0x65, 0x77, 0x0a, 0x56, 0x69, 332 | 0x73, 0x69, 0x20, 0x61, 0x6e, 0x64, 0x20, 0x74, 0x68, 0x65, 0x20, 0x6b, 333 | 0x65, 0x6e, 0x73, 0x68, 0x6f, 0x74, 0x6f, 0x20, 0x67, 0x72, 0x6f, 0x75, 334 | 0x70, 0x0a, 0x0a, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 335 | 0x20, 0x20, 0x20, 0x2d, 0x2d, 0x3d, 0x2d, 0x2d, 0x3d, 0x2d, 0x2d, 0x3d, 336 | 0x2d, 0x2d, 0x3d, 0x2d, 0x2d, 0x3d, 0x2d, 0x2d, 0x3d, 0x2d, 0x2d, 0x3d, 337 | 0x2d, 0x2d, 0x3d, 0x2d, 0x2d, 0x3d, 0x2d, 0x2d, 0x3d, 0x2d, 0x2d, 0x3d, 338 | 0x2d, 0x2d, 0x3d, 0x2d, 0x2d, 0x3d, 0x2d, 0x2d, 0x3d, 0x2d, 0x2d, 0x3d, 339 | 0x2d, 0x2d, 0x0a 340 | }; 341 | 342 | // [0x0000000, 0x4000000): Main Program Memory 343 | static ut64 _baddr(RBinFile *arch) { 344 | return 0LL; 345 | } 346 | 347 | static bool _check_bytes(const ut8 *buf, ut64 len) { 348 | return len >= sizeof MAGIC && memcmp (buf, MAGIC, sizeof MAGIC) == 0; 349 | } 350 | 351 | static RBuffer *_create(RBin *_bin, const ut8 *code, int codelen, const ut8 *_data, int _datalen) { 352 | RBuffer *buf = r_buf_new (); 353 | if (buf) { 354 | r_buf_append_bytes (buf, code, codelen); 355 | } 356 | return buf; 357 | } 358 | 359 | static int _destroy(RBinFile *arch) { 360 | return true; 361 | } 362 | 363 | static RBinInfo *_info(RBinFile *arch) { 364 | RBinInfo *ret = R_NEW0 (RBinInfo); 365 | if (!ret) { 366 | return NULL; 367 | } 368 | ret->lang = ""; 369 | ret->file = arch->file ? strdup (arch->file) : NULL; 370 | ret->type = NULL; 371 | ret->has_pi = 0; // no PIC/PIE 372 | ret->has_canary = 0; 373 | ret->bits = 64; // in accordance with r_anal_plugin_clcy, use 64-bit esil registers to emulate 54-bit pair registers 374 | ret->big_endian = 0; // used by r_asm_set_big_endian(). Actually middle-endian, but anyway we have custom assembler 375 | ret->has_va = 1; // Keep io.va = 1 376 | ret->has_nx = 1; // displayed in bin_info() 377 | ret->dbg_info = 0; // displayed in bin_info() 378 | return ret; 379 | } 380 | 381 | static bool _load(RBinFile *arch) { 382 | return true; 383 | } 384 | 385 | // Initialize the NFO section 386 | static RList *_patch_relocs(RBin *b) { 387 | ut64 len = sizeof CLEMENCY_NFO * 8 / 9; 388 | ut16 *buf = malloc (len * 2); 389 | if (!buf) { 390 | return NULL; 391 | } 392 | ut64 x = 0, l = 0, n_buf = 0, i; 393 | for (i = 0; i < sizeof CLEMENCY_NFO; i++) { 394 | x = x << 8 | CLEMENCY_NFO[i]; 395 | l += 8; 396 | if (l >= 9) { 397 | l -= 9; 398 | buf[n_buf++] = x >> l; 399 | x &= (1L << l) - 1; 400 | } 401 | } 402 | 403 | RIOSection sec = {.name = "NFO", .size = n_buf * 2, .vsize = 0x4000, .flags = R_IO_READ | R_IO_EXEC}; 404 | (void)r_io_create_mem_map (b->iob.io, &sec, NFO_VADDR, false, true); 405 | (void)r_io_write_at (b->iob.io, NFO_VADDR, (const ut8 *)buf, len * 2); 406 | free (buf); 407 | return NULL; 408 | } 409 | 410 | static RList *_sections(RBinFile *arch) { 411 | static const struct { 412 | const char *name; 413 | ut64 vaddr; 414 | ut64 vsize; 415 | int srwx; 416 | } sections[] = { 417 | {"Main Program Memory", 0, 0x4000000, 5}, 418 | {"Clock IO", 0x4000000, 0x1e, 6}, 419 | {"Flag IO", 0x4010000, 0x1000, 4}, 420 | {"Data Received", 0x5000000, 0x2000, 6}, 421 | {"Data Received Size", 0x5002000, 0x2, 6}, 422 | {"Data Sent", 0x5010000, 0x2000, 6}, 423 | {"Data Sent Size", 0x5012000, 0x2, 6}, 424 | //{"NFO", NFO_VADDR, 0x4000, 5}, // hidden section from clemency_nfo.c, created in _patch_relocs 425 | //{"Shared Memory", 0x6000000, 0x800000, 6}, 426 | //{"NVRAM Memory", 0x6800000, 0x800000, 6}, 427 | {"Interrupt Pointers", 0x7ffff00, 0x1c, 6}, 428 | //{"Processor Identification and Features", 0x7ffff80, 0x80, 4}, 429 | }; 430 | RList *ret = r_list_newf (free); 431 | RBinSection *sec; 432 | ut64 sz = r_buf_size (arch->buf); 433 | int i; 434 | if (ret) { 435 | for (i = 0; i < R_ARRAY_SIZE (sections); i++) { 436 | if (i || sz) { 437 | if (!(sec = R_NEW0 (RBinSection))) { 438 | break; 439 | } 440 | sec->add = true; 441 | r_str_ncpy (sec->name, sections[i].name, sizeof sec->name); 442 | sec->paddr = 0; 443 | sec->size = i ? 0 : sz; 444 | sec->vaddr = sections[i].vaddr; 445 | sec->vsize = sections[i].vsize; 446 | sec->srwx = sections[i].srwx; 447 | if (!r_list_append (ret, sec)) { 448 | break; 449 | } 450 | } 451 | } 452 | } 453 | return ret; 454 | } 455 | 456 | RBinPlugin r_bin_plugin_clcy = { 457 | .name = "clcy", 458 | .desc = "cLEMENCy bin plugin", 459 | .license = "LGPL3", 460 | .baddr = _baddr, 461 | .check_bytes = _check_bytes, 462 | .create = _create, 463 | .destroy = _destroy, 464 | .info = _info, 465 | .load = _load, 466 | .minstrlen = 0, 467 | .patch_relocs = _patch_relocs, 468 | .sections = _sections, 469 | }; 470 | 471 | RLibStruct radare_plugin = { 472 | .type = R_LIB_TYPE_BIN, 473 | .data = &r_bin_plugin_clcy, 474 | .version = R2_VERSION, 475 | }; 476 | --------------------------------------------------------------------------------