A shell that runs x86_64 assembly
c
x86-64
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

completion.h 8.0KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. /* Copyright Yann Weber <asmsh@yannweb.net>
  2. This file is part of asmsh.
  3. asmsh is free software: you can redistribute it and/or modify it under the
  4. terms of the GNU General Public License as published by the Free Software
  5. Foundation, either version 3 of the License, or any later version.
  6. asmsh is distributed in the hope that it will be useful, but WITHOUT ANY
  7. WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
  8. FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
  9. details.
  10. You should have received a copy of the GNU General Public License along
  11. with asmsh. If not, see <https://www.gnu.org/licenses/>.
  12. */
  13. #ifndef ASMSH_COMPLETION_H
  14. #define ASMSH_COMPLETION_H
  15. #include "config.h"
  16. #include <errno.h>
  17. #include <stdlib.h>
  18. #include <stdio.h>
  19. #include <string.h>
  20. #if HAVE_LIBREADLINE == 1
  21. #include <readline/readline.h>
  22. #include <readline/history.h>
  23. #endif
  24. #define ASHCOMP_NOARG 0x00
  25. #define ASHCOMP_REG8 0x01
  26. #define ASHCOMP_REG16 0x02
  27. #define ASHCOMP_REG32 0x04
  28. #define ASHCOMP_REG64 0x08
  29. #define ASHCOMP_REGALL 0x0F
  30. #define ASHCOMP_SEGREG 0x10
  31. #define ASHCOMP_IMM 0x20
  32. #define ASHCOMP_ADDR 0x40
  33. #define ASHCOMP_XMM 0x100
  34. #define ASHCOMP_XMM2 0x200
  35. #define ASHCOMP_YMM 0x400
  36. #define ASHCOMP_XALL 0x700
  37. typedef struct asmsh_completion_s asmsh_completion_t;
  38. typedef struct asmsh_compinstr_s asmsh_compinstr_t;
  39. typedef unsigned int flag_t;
  40. struct asmsh_compinstr_s
  41. {
  42. const char *mnemo;
  43. flag_t arg1;
  44. flag_t arg2;
  45. };
  46. struct asmsh_completion_s
  47. {
  48. flag_t regs;
  49. };
  50. char **asmsh_completion(const char *buf, const char *text, int start, int end);
  51. #if HAVE_LIBREADLINE == 1
  52. static char **_asmsh_completion_res;
  53. static char **_asmsh_completion_cur;
  54. static int _asmsh_completion_st[2];
  55. static char *asmsh_rl_completion_gen(const char *text, int state)
  56. {
  57. if(!state)
  58. {
  59. _asmsh_completion_res = asmsh_completion(rl_line_buffer,
  60. text,
  61. _asmsh_completion_st[0],
  62. _asmsh_completion_st[1]);
  63. _asmsh_completion_cur = _asmsh_completion_res;
  64. if(!_asmsh_completion_res)
  65. {
  66. return NULL;
  67. }
  68. }
  69. char *res = *_asmsh_completion_cur;
  70. if(!*_asmsh_completion_cur)
  71. {
  72. free(_asmsh_completion_res);
  73. }
  74. else
  75. {
  76. *_asmsh_completion_cur = NULL;
  77. _asmsh_completion_cur++;
  78. }
  79. return res;
  80. }
  81. extern int rl_attempted_completion_over;
  82. extern const char* rl_special_prefixes;
  83. extern const char* rl_basic_word_break_characters;
  84. static char **asmsh_rl_completion(const char *text, int start, int end)
  85. {
  86. rl_attempted_completion_over = 1;
  87. _asmsh_completion_st[0]=start;
  88. _asmsh_completion_st[1]=end;
  89. return rl_completion_matches(text, asmsh_rl_completion_gen);
  90. }
  91. #endif
  92. /** Return all possible instructions given a start */
  93. char **asmsh_compl_instr(const char *start);
  94. char **asmsh_compl_arg(const char *buf, const char *text, int start);
  95. 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};
  96. static const char M_sizes[] = "bwdq";
  97. /* Upper case letters are flags pointing to
  98. * more complex completion (like conditions)
  99. * C -> CMOVcc cc conditions
  100. * S -> a size descriptor or nothing
  101. */
  102. static const asmsh_compinstr_t x86_64_instr[] = {
  103. {"aaa", 0, 0},
  104. {"aad", ASHCOMP_IMM, 0},
  105. {"aam", ASHCOMP_IMM, 0},
  106. {"aas", 0, 0},
  107. {"adc", 0xff, 0xff},
  108. {"add", 0xff, 0xff},
  109. {"and", 0xff, 0xff},
  110. {"andn", 0xff, 0xff},
  111. {"bextr", 0xff, 0xff},
  112. {"blcfill", 0xff, 0xff},
  113. {"blci", 0xff, 0xff},
  114. {"blcic", 0xff, 0xff},
  115. {"blcmsk", 0xff, 0xff},
  116. {"blcs", 0xff, 0xff},
  117. {"blsfill", 0xff, 0xff},
  118. {"blsi", 0xff, 0xff},
  119. {"blsic", 0xff, 0xff},
  120. {"blsmsk", 0xff, 0xff},
  121. {"blsr", 0xff, 0xff},
  122. {"bound", 0x6|0x40, 0x6|0x40},
  123. {"bsf", 0xff, 0xff},
  124. {"bsr", 0xff, 0xff},
  125. {"bswap", ASHCOMP_REG32 | ASHCOMP_REG64, 0},
  126. {"bt", 0xff, 0},
  127. {"btc", 0xff, 0},
  128. {"btr", 0xff, 0},
  129. {"bts", 0xff, 0},
  130. {"call", 0xff, 0},
  131. {"cbw", 0, 0},
  132. {"cdq", 0, 0},
  133. {"cdqe", 0, 0},
  134. {"clc", 0, 0},
  135. {"cld", 0, 0},
  136. {"clflush", 0, 0},
  137. {"cli", 0, 0},
  138. {"cmc", 0, 0},
  139. {"cmovC", 0xff, 0xff},
  140. {"cmp", 0xff, 0xff},
  141. {"cmpsS", 0, 0},
  142. {"cmpxchg", 0xff, 0xff},
  143. {"cmpxchg16b", 0xff, 0xff},
  144. {"cmpxchg8b", 0xff, 0xff},
  145. {"cpuid", 0, 0},
  146. {"cqo", 0, 0},
  147. {"crc32", 0xff, 0xff},
  148. {"cwd", 0, 0},
  149. {"daa", 0, 0},
  150. {"das", 0, 0},
  151. {"dec", 0xff, 0},
  152. {"div", 0xff, 0},
  153. {"enter", 0xff, 0xff},
  154. {"idiv", 0xff, 0},
  155. {"imul", 0xff, 0},
  156. {"in", ASHCOMP_IMM, 0},
  157. {"inc", 0xff, 0},
  158. {"ins", 0, 0},
  159. {"insd", 0, 0},
  160. {"insw", 0, 0},
  161. {"int", ASHCOMP_IMM, 0},
  162. {"into", 0, 0},
  163. {"iret", 0, 0},
  164. {"iretd", 0, 0},
  165. {"jC", 0xff, 0},
  166. {"jmp", 0xff, 0},
  167. {"lahf", 0, 0},
  168. {"lds", ASHCOMP_REGALL, ASHCOMP_ADDR},
  169. {"lea", ASHCOMP_REGALL, ASHCOMP_ADDR},
  170. {"leave", 0xff, 0xff},
  171. {"lfence", 0, 0},
  172. {"lfs", ASHCOMP_REGALL, ASHCOMP_ADDR},
  173. {"lgs", ASHCOMP_REGALL, ASHCOMP_ADDR},
  174. {"lodsS", 0, 0},
  175. {"loopC", 0xff, 0},
  176. {"lss", ASHCOMP_REGALL, ASHCOMP_ADDR},
  177. {"lzcnt", 0xff, 0xff},
  178. {"mfence", 0, 0},
  179. {"movS", 0xff, 0xff},
  180. {"movbe", 0xff, 0xff},
  181. {"movd", 0xff, 0xff},
  182. {"movmskpd", ASHCOMP_REGALL, ASHCOMP_XALL},
  183. {"movmsksps", ASHCOMP_REGALL, ASHCOMP_XALL},
  184. {"movnti", 0xff, 0xff},
  185. {"movsS", 0, 0},
  186. {"movsx", 0xff, 0xff},
  187. {"movzx", 0xff, 0xff},
  188. {"mul", 0xff, 0},
  189. {"neg", 0xff, 0},
  190. {"nop", 0, 0},
  191. {"not", 0xff, 0xff},
  192. {"or", 0xff, 0xff},
  193. {"out", ASHCOMP_IMM, 0},
  194. {"outs", 0, 0},
  195. {"outsb", 0, 0},
  196. {"outsd", 0, 0},
  197. {"outsw", 0, 0},
  198. {"pop", ASHCOMP_REGALL, 0},
  199. {"popS", ASHCOMP_IMM, 0},
  200. {"popa", 0xff, 0},
  201. {"popad", 0xff, 0},
  202. {"popcnt", 0xff, 0xff},
  203. {"popfd", 0, 0},
  204. {"popfq", 0, 0},
  205. {"prefetch", ASHCOMP_ADDR, 0},
  206. {"prefetch0", ASHCOMP_ADDR, 0},
  207. {"prefetch1", ASHCOMP_ADDR, 0},
  208. {"prefetch2", ASHCOMP_ADDR, 0},
  209. {"prefetchw", ASHCOMP_ADDR, 0},
  210. {"push", ASHCOMP_REGALL, 0},
  211. {"pushS", ASHCOMP_IMM, 0},
  212. {"pusha", 0xff, 0},
  213. {"pushad", 0xff, 0},
  214. {"pushf", 0, 0},
  215. {"pushfd", 0, 0},
  216. {"pushfq", 0, 0},
  217. {"rcl", 0xff, 0},
  218. {"rcr", 0xff, 0},
  219. {"ret", 0xff, 0},
  220. {"rol", 0xff, 0},
  221. {"ror", 0xff, 0},
  222. {"sahf", 0, 0},
  223. {"sal", 0xff, 0},
  224. {"sar", 0xff, 0},
  225. {"sbb", 0xff, 0xff},
  226. {"scasS", 0, 0},
  227. {"setC", 0xff, 0},
  228. {"sfence", 0, 0},
  229. {"shl", 0xff, 0},
  230. {"shld", 0xff, 0},
  231. {"shr", 0xff, 0},
  232. {"shrd", 0xff, 0},
  233. {"stc", 0, 0},
  234. {"std", 0, 0},
  235. {"sti", 0, 0},
  236. {"stosS", 0, 0},
  237. {"sub", 0xff, 0},
  238. {"syscall", 0, 0},
  239. {"sysenter", 0, 0},
  240. {"sysexit", 0, 0},
  241. {"t1mskc", 0xff, 0xff},
  242. {"test", 0xff, 0xff},
  243. {"tzcnt", 0xff, 0xff},
  244. {"tzmsk", 0xff, 0xff},
  245. {"vmovmksps", ASHCOMP_REGALL, ASHCOMP_XALL},
  246. {"vmovmskpd", ASHCOMP_REGALL, ASHCOMP_XALL},
  247. {"xadd", 0xff, 0xff},
  248. {"xchg", 0xff, 0xff},
  249. {"xlat", 0, 0},
  250. {"xor", 0xff, 0xff},
  251. {NULL,0,0}
  252. };
  253. static const char * const asmsh_sym_regs64[] = {
  254. "%rax", "%rbx", "%rcx", "%rdx", "%rbp", "%rsi", "%rdi", "%rsp",
  255. "%r8", "%r9", "%r10", "%r11", "%r12", "%r13", "%r14", "%r15",
  256. NULL
  257. };
  258. static const char * const asmsh_sym_regs32[] = {
  259. "%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi", "%ebp", "%esp",
  260. NULL
  261. };
  262. static const char * const asmsh_sym_regs16[] = {
  263. "%ax", "%bx", "%cx", "%dx", "%si", "%di", "%bp", "%sp",
  264. NULL
  265. };
  266. static const char * const asmsh_sym_regs8[] = {
  267. "%ah", "%al", "%bh", "%bl", "%ch", "%cl", "%dh", "%dl",
  268. NULL
  269. };
  270. static const char * const asmsh_sym_regsseg[] = {
  271. "%cs", "%ds", "%es", "%fs", "%gs", "%ss",
  272. NULL
  273. };
  274. static const char * const asmsh_sym_imm[] = {
  275. "$", "$0x", "$0o",
  276. NULL
  277. };
  278. static const char * const asmsh_sym_xmm[] = {
  279. "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7",
  280. NULL
  281. };
  282. static const char * const asmsh_sym_xmm2[] = {
  283. "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14", "%xmm15",
  284. NULL
  285. };
  286. static const char * const asmsh_sym_ymm[] = {
  287. "%ymm0", "%ymm1", "%ymm2", "%ymm3", "%ymm4", "%ymm5", "%ymm6", "%ymm7",
  288. NULL
  289. };
  290. typedef struct {
  291. const int flag;
  292. const char * const * const regs;
  293. } asmsh_symtable_elt_t;
  294. static const asmsh_symtable_elt_t asmsh_symtable[] = {
  295. { ASHCOMP_REG8, asmsh_sym_regs8},
  296. { ASHCOMP_REG16, asmsh_sym_regs16},
  297. { ASHCOMP_REG32, asmsh_sym_regs32},
  298. { ASHCOMP_REG64, asmsh_sym_regs64},
  299. { ASHCOMP_SEGREG, asmsh_sym_regsseg},
  300. { ASHCOMP_IMM, asmsh_sym_imm},
  301. { ASHCOMP_XMM, asmsh_sym_xmm},
  302. { ASHCOMP_XMM2, asmsh_sym_xmm2},
  303. { ASHCOMP_YMM, asmsh_sym_ymm},
  304. { 0, NULL },
  305. };
  306. #endif