/* Copyright Yann Weber This file is part of asmsh. asmsh is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or any later version. asmsh is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with asmsh. If not, see . */ #ifndef ASMSH_COMPLETION_H #define ASMSH_COMPLETION_H #include "config.h" #include #include #include #include #if HAVE_LIBREADLINE == 1 #include #include #endif #define ASHCOMP_NOARG 0x00 #define ASHCOMP_REG8 0x01 #define ASHCOMP_REG16 0x02 #define ASHCOMP_REG32 0x04 #define ASHCOMP_REG64 0x08 #define ASHCOMP_REGALL 0x0F #define ASHCOMP_SEGREG 0x10 #define ASHCOMP_IMM 0x20 #define ASHCOMP_ADDR 0x40 #define ASHCOMP_XMM 0x100 #define ASHCOMP_XMM2 0x200 #define ASHCOMP_YMM 0x400 #define ASHCOMP_XALL 0x700 typedef struct asmsh_completion_s asmsh_completion_t; typedef struct asmsh_compinstr_s asmsh_compinstr_t; typedef unsigned int flag_t; struct asmsh_compinstr_s { const char *mnemo; flag_t arg1; flag_t arg2; }; struct asmsh_completion_s { flag_t regs; }; char **asmsh_completion(const char *buf, const char *text, int start, int end); #if HAVE_LIBREADLINE == 1 static char **_asmsh_completion_res; static char **_asmsh_completion_cur; static int _asmsh_completion_st[2]; static char *asmsh_rl_completion_gen(const char *text, int state) { if(!state) { _asmsh_completion_res = asmsh_completion(rl_line_buffer, text, _asmsh_completion_st[0], _asmsh_completion_st[1]); _asmsh_completion_cur = _asmsh_completion_res; if(!_asmsh_completion_res) { return NULL; } } char *res = *_asmsh_completion_cur; if(!*_asmsh_completion_cur) { free(_asmsh_completion_res); } else { *_asmsh_completion_cur = NULL; _asmsh_completion_cur++; } return res; } extern int rl_attempted_completion_over; extern const char* rl_special_prefixes; extern const char* rl_basic_word_break_characters; static char **asmsh_rl_completion(const char *text, int start, int end) { rl_attempted_completion_over = 1; _asmsh_completion_st[0]=start; _asmsh_completion_st[1]=end; return rl_completion_matches(text, asmsh_rl_completion_gen); } #endif /** Return all possible instructions given a start */ char **asmsh_compl_instr(const char *start); char **asmsh_compl_arg(const char *buf, const char *text, int start); static const char * const M_conds[] = {"o","no","b","c","nae","ae","nb","nc","e","z","ne","nz","be","na","a","nbe","s","ns","p","pe","np","po","l","nge","ge","nl","le","ng","g","nle", NULL}; static const char M_sizes[] = "bwdq"; /* Upper case letters are flags pointing to * more complex completion (like conditions) * C -> CMOVcc cc conditions * S -> a size descriptor or nothing */ static const asmsh_compinstr_t x86_64_instr[] = { {"aaa", 0, 0}, {"aad", ASHCOMP_IMM, 0}, {"aam", ASHCOMP_IMM, 0}, {"aas", 0, 0}, {"adc", 0xff, 0xff}, {"add", 0xff, 0xff}, {"and", 0xff, 0xff}, {"andn", 0xff, 0xff}, {"bextr", 0xff, 0xff}, {"blcfill", 0xff, 0xff}, {"blci", 0xff, 0xff}, {"blcic", 0xff, 0xff}, {"blcmsk", 0xff, 0xff}, {"blcs", 0xff, 0xff}, {"blsfill", 0xff, 0xff}, {"blsi", 0xff, 0xff}, {"blsic", 0xff, 0xff}, {"blsmsk", 0xff, 0xff}, {"blsr", 0xff, 0xff}, {"bound", 0x6|0x40, 0x6|0x40}, {"bsf", 0xff, 0xff}, {"bsr", 0xff, 0xff}, {"bswap", ASHCOMP_REG32 | ASHCOMP_REG64, 0}, {"bt", 0xff, 0}, {"btc", 0xff, 0}, {"btr", 0xff, 0}, {"bts", 0xff, 0}, {"call", 0xff, 0}, {"cbw", 0, 0}, {"cdq", 0, 0}, {"cdqe", 0, 0}, {"clc", 0, 0}, {"cld", 0, 0}, {"clflush", 0, 0}, {"cli", 0, 0}, {"cmc", 0, 0}, {"cmovC", 0xff, 0xff}, {"cmp", 0xff, 0xff}, {"cmpsS", 0, 0}, {"cmpxchg", 0xff, 0xff}, {"cmpxchg16b", 0xff, 0xff}, {"cmpxchg8b", 0xff, 0xff}, {"cpuid", 0, 0}, {"cqo", 0, 0}, {"crc32", 0xff, 0xff}, {"cwd", 0, 0}, {"daa", 0, 0}, {"das", 0, 0}, {"dec", 0xff, 0}, {"div", 0xff, 0}, {"enter", 0xff, 0xff}, {"idiv", 0xff, 0}, {"imul", 0xff, 0}, {"in", ASHCOMP_IMM, 0}, {"inc", 0xff, 0}, {"ins", 0, 0}, {"insd", 0, 0}, {"insw", 0, 0}, {"int", ASHCOMP_IMM, 0}, {"into", 0, 0}, {"iret", 0, 0}, {"iretd", 0, 0}, {"jC", 0xff, 0}, {"jmp", 0xff, 0}, {"lahf", 0, 0}, {"lds", ASHCOMP_REGALL, ASHCOMP_ADDR}, {"lea", ASHCOMP_REGALL, ASHCOMP_ADDR}, {"leave", 0xff, 0xff}, {"lfence", 0, 0}, {"lfs", ASHCOMP_REGALL, ASHCOMP_ADDR}, {"lgs", ASHCOMP_REGALL, ASHCOMP_ADDR}, {"lodsS", 0, 0}, {"loopC", 0xff, 0}, {"lss", ASHCOMP_REGALL, ASHCOMP_ADDR}, {"lzcnt", 0xff, 0xff}, {"mfence", 0, 0}, {"movS", 0xff, 0xff}, {"movbe", 0xff, 0xff}, {"movd", 0xff, 0xff}, {"movmskpd", ASHCOMP_REGALL, ASHCOMP_XALL}, {"movmsksps", ASHCOMP_REGALL, ASHCOMP_XALL}, {"movnti", 0xff, 0xff}, {"movsS", 0, 0}, {"movsx", 0xff, 0xff}, {"movzx", 0xff, 0xff}, {"mul", 0xff, 0}, {"neg", 0xff, 0}, {"nop", 0, 0}, {"not", 0xff, 0xff}, {"or", 0xff, 0xff}, {"out", ASHCOMP_IMM, 0}, {"outs", 0, 0}, {"outsb", 0, 0}, {"outsd", 0, 0}, {"outsw", 0, 0}, {"pop", ASHCOMP_REGALL, 0}, {"popS", ASHCOMP_IMM, 0}, {"popa", 0xff, 0}, {"popad", 0xff, 0}, {"popcnt", 0xff, 0xff}, {"popfd", 0, 0}, {"popfq", 0, 0}, {"prefetch", ASHCOMP_ADDR, 0}, {"prefetch0", ASHCOMP_ADDR, 0}, {"prefetch1", ASHCOMP_ADDR, 0}, {"prefetch2", ASHCOMP_ADDR, 0}, {"prefetchw", ASHCOMP_ADDR, 0}, {"push", ASHCOMP_REGALL, 0}, {"pushS", ASHCOMP_IMM, 0}, {"pusha", 0xff, 0}, {"pushad", 0xff, 0}, {"pushf", 0, 0}, {"pushfd", 0, 0}, {"pushfq", 0, 0}, {"rcl", 0xff, 0}, {"rcr", 0xff, 0}, {"ret", 0xff, 0}, {"rol", 0xff, 0}, {"ror", 0xff, 0}, {"sahf", 0, 0}, {"sal", 0xff, 0}, {"sar", 0xff, 0}, {"sbb", 0xff, 0xff}, {"scasS", 0, 0}, {"setC", 0xff, 0}, {"sfence", 0, 0}, {"shl", 0xff, 0}, {"shld", 0xff, 0}, {"shr", 0xff, 0}, {"shrd", 0xff, 0}, {"stc", 0, 0}, {"std", 0, 0}, {"sti", 0, 0}, {"stosS", 0, 0}, {"sub", 0xff, 0}, {"syscall", 0, 0}, {"sysenter", 0, 0}, {"sysexit", 0, 0}, {"t1mskc", 0xff, 0xff}, {"test", 0xff, 0xff}, {"tzcnt", 0xff, 0xff}, {"tzmsk", 0xff, 0xff}, {"vmovmksps", ASHCOMP_REGALL, ASHCOMP_XALL}, {"vmovmskpd", ASHCOMP_REGALL, ASHCOMP_XALL}, {"xadd", 0xff, 0xff}, {"xchg", 0xff, 0xff}, {"xlat", 0, 0}, {"xor", 0xff, 0xff}, {NULL,0,0} }; static const char * const asmsh_sym_regs64[] = { "%rax", "%rbx", "%rcx", "%rdx", "%rbp", "%rsi", "%rdi", "%rsp", "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15", NULL }; static const char * const asmsh_sym_regs32[] = { "%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi", "%ebp", "%esp", NULL }; static const char * const asmsh_sym_regs16[] = { "%ax", "%bx", "%cx", "%dx", "%si", "%di", "%bp", "%sp", NULL }; static const char * const asmsh_sym_regs8[] = { "%ah", "%al", "%bh", "%bl", "%ch", "%cl", "%dh", "%dl", NULL }; static const char * const asmsh_sym_regsseg[] = { "%cs", "%ds", "%es", "%fs", "%gs", "%ss", NULL }; static const char * const asmsh_sym_imm[] = { "$", "$0x", "$0o", NULL }; static const char * const asmsh_sym_xmm[] = { "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7", NULL }; static const char * const asmsh_sym_xmm2[] = { "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14", "%xmm15", NULL }; static const char * const asmsh_sym_ymm[] = { "%ymm0", "%ymm1", "%ymm2", "%ymm3", "%ymm4", "%ymm5", "%ymm6", "%ymm7", NULL }; typedef struct { const int flag; const char * const * const regs; } asmsh_symtable_elt_t; static const asmsh_symtable_elt_t asmsh_symtable[] = { { ASHCOMP_REG8, asmsh_sym_regs8}, { ASHCOMP_REG16, asmsh_sym_regs16}, { ASHCOMP_REG32, asmsh_sym_regs32}, { ASHCOMP_REG64, asmsh_sym_regs64}, { ASHCOMP_SEGREG, asmsh_sym_regsseg}, { ASHCOMP_IMM, asmsh_sym_imm}, { ASHCOMP_XMM, asmsh_sym_xmm}, { ASHCOMP_XMM2, asmsh_sym_xmm2}, { ASHCOMP_YMM, asmsh_sym_ymm}, { 0, NULL }, }; #endif