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.

shell_cmds.h 5.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  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_SHELL_CMDS_H
  14. #define ASMSH_SHELL_CMDS_H
  15. #include "config.h"
  16. #include <errno.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #include <unistd.h>
  20. #include "logger.h"
  21. #define ASMSH_CMD_MAXLEN 31
  22. #define ASMSH_CMD_MAXARG 15
  23. typedef struct asmsh_cmd_s asmsh_cmd_t;
  24. typedef struct asmsh_cmd_args_s asmsh_cmd_args_t;
  25. #include "shell.h"
  26. /** @return <0 on recoverable error 0 on ok, 1+status on exit */
  27. typedef int (asmsh_cmd_f)(asmsh_t*, asmsh_cmd_args_t*);
  28. /** Represent a single command */
  29. struct asmsh_cmd_s
  30. {
  31. /** The command (with the leading '.') */
  32. const char *str;
  33. /** The command function pointer */
  34. asmsh_cmd_f *cmd;
  35. /**If non-zero indicate the minimum of chars to
  36. * match. ".quit" while have 2 to match starting
  37. * from ".q"
  38. */
  39. unsigned char sm;
  40. /* Help information */
  41. /** Small command name (like .h(elp) )*/
  42. const char *sms;
  43. /** Command usage */
  44. const char *usage;
  45. /** Command description */
  46. const char *desc;
  47. };
  48. /** A command arguments with command name & NULL terminated array of args */
  49. struct asmsh_cmd_args_s
  50. {
  51. char cmd[ASMSH_CMD_MAXLEN+1];
  52. int argc;
  53. char *args[ASMSH_CMD_MAXARG+1];
  54. };
  55. /**@param const char* the text to match
  56. * @param int the len of the text to match
  57. * @return a ptr or NULL
  58. */
  59. const asmsh_cmd_t *asmsh_cmd_match(const char *cmd, int stop);
  60. /** @return NULL on error or ptr on new cmd args */
  61. asmsh_cmd_args_t *asmsh_cmd_parse(const char *cmd);
  62. static void asmsh_cmd_args_free(asmsh_cmd_args_t *args)
  63. {
  64. if(!args) { return; }
  65. for(char **a=args->args; *a; a++)
  66. {
  67. free(*a);
  68. }
  69. free(args);
  70. }
  71. const char *asmsh_cmd_help(asmsh_t *sh);
  72. /*
  73. * Commands declaration
  74. *
  75. * A command can return 0 if no errors, -X for a recoverable error
  76. * 1 for exit with status 0, 1+S for exit with status S
  77. */
  78. // Quit the shell
  79. static int _quit(asmsh_t *sh, asmsh_cmd_args_t *args)
  80. {
  81. asmsh_cleanup(sh);
  82. return 1;
  83. }
  84. // Print an instruction bytecode
  85. int asmsh_cmd_bcode(asmsh_t *sh, char *buf, int bufsz, int argc, char **args);
  86. static int _bcode(asmsh_t *sh, asmsh_cmd_args_t *args)
  87. {
  88. char str[256];
  89. int ret;
  90. ret = asmsh_cmd_bcode(sh, str, 256, args->argc, args->args);
  91. if(ret)
  92. {
  93. return ret;
  94. }
  95. printf("%s\n", str);
  96. return 0;
  97. }
  98. // Print the registers
  99. static int _print_regs(asmsh_t *sh, asmsh_cmd_args_t *args)
  100. {
  101. asmsh_env_t *env = sh->env;
  102. asmsh_env_update_regs(env);
  103. struct user_regs_struct *r = &env->regs;
  104. #define FLG(b, l) ( (r->eflags & (1<<b))?l:'-' )
  105. printf("rax: %016lx rbx: %016lx rcx: %016lx rdx: %016lx\n\
  106. rbp: %016lx rsi: %016lx rdi: %016lx rsp: %016lx\n\
  107. r8: %016lx r9: %016lx r10: %016lx r11: %016lx\n\
  108. r12: %016lx r13: %016lx r14: %016lx r15: %016lx\n\
  109. rip: %016lx flg: %016lx\n\
  110. cs: %04x ds: %04x es: %04x fs:%04x gs: %04x ss:%04x\n\
  111. flags: %c%c%c%c|%c%c%c\n\
  112. ODSZ|APC\n\
  113. ", r->rax, r->rbx, r->rcx, r->rdx,\
  114. r->rbp, r->rsi, r->rdi, r->rsp,\
  115. r->r8, r->r9, r->r10, r->r11,\
  116. r->r12, r->r13, r->r14, r->r15,\
  117. r->rip, r->eflags,\
  118. r->cs, r->ds, r->es, r->fs, r->gs, r->ss,
  119. FLG(11,'O'), FLG(10, 'D'), FLG(7, 'S'), FLG(6, 'Z'),
  120. FLG(4, 'A'), FLG(2, 'P'), FLG(0, 'C'));
  121. #undef FLG
  122. return 0;
  123. }
  124. // Reset the shell (restart the child etc)
  125. static int _reset(asmsh_t *sh, asmsh_cmd_args_t *args)
  126. {
  127. char *childpath = strdup(sh->child_path);
  128. asmsh_cleanup(sh);
  129. asmsh_init(sh, childpath);
  130. free(childpath);
  131. }
  132. // Display CPU flag resister values
  133. static int _flags(asmsh_t *sh, asmsh_cmd_args_t *args)
  134. {
  135. printf("Flags :\n");
  136. #define printFLG(name, b) printf(" (%2d)%16s : %d\n", b, name,\
  137. (sh->env->regs.eflags & (1<<b))?1:0);
  138. printFLG("Overflow", 11);
  139. printFLG("Direction", 10);
  140. printFLG("Sign", 7);
  141. printFLG("Zero", 6);
  142. printFLG("Auxiliary carry", 4);
  143. printFLG("Parity", 2);
  144. printFLG("Carry", 0);
  145. #undef printFLG
  146. #define EFLG(b,n) ((sh->env->regs.eflags & (1<<b))?n:'-')
  147. printf("%c%c%c%c %c%c%c\n",
  148. EFLG(11,'O'), EFLG(10, 'D'), EFLG(7,'S'), EFLG(6,'Z'),
  149. EFLG(4,'A'), EFLG(2, 'P'), EFLG(0, 'C'));
  150. return 0;
  151. }
  152. // Declared because referenced in command list but not implemented
  153. // because the _help function needs a reference to the command list
  154. static int _help(asmsh_t *sh, asmsh_cmd_args_t *args);
  155. /*
  156. * The list of shell commands
  157. */
  158. static const asmsh_cmd_t asmsh_CMDS[] = {
  159. {".bytecode", _bcode, 2,
  160. ".b(ytecode)", "",
  161. "display last instruction bytecode"},
  162. {".flags", _flags, 2,
  163. ".f(lags)", "",
  164. "display CPU flags"},
  165. {".help", _help, 2,
  166. ".h(elp)","[cmd]",
  167. "display this help or the help of specified command"},
  168. {".quit", _quit, 2,
  169. ".q(uit)","",
  170. "quit asmsh"},
  171. {".regs", _print_regs, 1,
  172. ".(regs)", "",
  173. "display registers value"},
  174. {".reset", _reset, 0,
  175. ".reset", "",
  176. "reset the shell"},
  177. {NULL, NULL, 0},
  178. };
  179. // Print help (command list + help)
  180. static int _help(asmsh_t *sh, asmsh_cmd_args_t *args)
  181. {
  182. char buf[4096], abuf[64];
  183. int ret, pret;
  184. ret = snprintf(buf, 4096, "Available commands :\n");
  185. pret = ret;
  186. for(const asmsh_cmd_t *cmd = asmsh_CMDS; cmd->str; cmd++)
  187. {
  188. snprintf(abuf, 64, "%s %s", cmd->sms, cmd->usage);
  189. ret += snprintf(buf+ret, 4096-ret, " %-18s : %s\n",
  190. abuf, cmd->desc);
  191. }
  192. dprintf(2, buf);
  193. return 0;
  194. }
  195. #endif