A shell that runs x86_64 assembly
c
x86-64
Du kannst nicht mehr als 25 Themen auswählen Themen müssen mit entweder einem Buchstaben oder einer Ziffer beginnen. Sie können Bindestriche („-“) enthalten und bis zu 35 Zeichen lang sein.

shell_cmd_breakpoint.c 5.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230
  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. #include "shell_cmds.h"
  14. /** Add a breakpoint
  15. * @param asmsh_t* The shell
  16. * @param asmsh_cmd_args_t* The command arguments
  17. * @param int The first argument of the expression
  18. * @return -1 on error else 0
  19. */
  20. static int brk_add(asmsh_t *sh, asmsh_cmd_args_t *args, int expr_first);
  21. /** Remove a breakpoint
  22. * @param asmsh_t* The shell
  23. * @param asmsh_cmd_args_t* The command arguments
  24. * @param int The first argument of the expression
  25. * @return -1 on error else 0
  26. */
  27. static int brk_del(asmsh_t *sh, asmsh_cmd_args_t *args, int expr_first);
  28. /** Add a breakpoint after an instruction
  29. * @param asmsh_t* The shell
  30. * @param asmsh_cmd_args_t* The command arguments
  31. * @param int The first argument of the expression
  32. * @return -1 on error else 0
  33. */
  34. static int brk_after(asmsh_t *sh, asmsh_cmd_args_t *args, int first);
  35. /** List all breakpoints
  36. * @param asmsh_t* The shell
  37. * @param asmsh_cmd_args_t* The command arguments
  38. * @param int The first argument of the expression
  39. * @return -1 on error else 0
  40. * @todo add filters arguments
  41. */
  42. static int brk_ls(asmsh_t *sh, asmsh_cmd_args_t *args, int expr_first);
  43. /** Add a breakpoint and display a message about it
  44. * @param asmsh_t The shell
  45. * @param unsigned long The breakpoint address
  46. * @returns 0 if no error or if allready exist else -1
  47. */
  48. static int brk_add_or_err(asmsh_t *sh, unsigned long addr);
  49. void log_brk_usage()
  50. {
  51. asmsh_log_info("Available commands are :");
  52. asmsh_log_info("\tadd [addr_expr]");
  53. asmsh_log_info("\t\tAdd a new breakpoint (optionnal/implicit)");
  54. asmsh_log_info("\tdel|d addr_expr");
  55. asmsh_log_info("\t\tDelete a breakpoint");
  56. asmsh_log_info("\tafter|a INSTRUCTION");
  57. asmsh_log_info("\t\tAdd a new breakpoint after an instruction");
  58. asmsh_log_info("\tlist|ls|l");
  59. asmsh_log_info("\t\tList existing breakpoints");
  60. asmsh_log_addr_expr_usage();
  61. }
  62. int asmsh_cmd_breakpoint(asmsh_t *sh, asmsh_cmd_args_t *args)
  63. {
  64. int ret;
  65. if(args->argc == 0 || args->args[0][0] == '.' || \
  66. (args->args[0][0] >= '0' && args->args[0][0] <= '9'))
  67. {
  68. if((ret = brk_add(sh, args, 0)) < 0)
  69. {
  70. asmsh_log_addr_expr_usage();
  71. }
  72. return ret;
  73. }
  74. // At least 1 arg, 1st arg chr is not in [0-9] nor is '.'
  75. // Looking for specific commands argument
  76. if(strcmp(args->args[0], "a") == 0 || \
  77. strcmp(args->args[0], "after") == 0)
  78. {
  79. return brk_after(sh, args, 1);
  80. }
  81. else if(strcmp(args->args[0], "add") == 0)
  82. {
  83. if((ret = brk_add(sh, args, 1)) < 0)
  84. {
  85. asmsh_log_addr_expr_usage();
  86. }
  87. return ret;
  88. }
  89. else if(strcmp(args->args[0], "d") == 0 || \
  90. strcmp(args->args[0], "del") == 0 || \
  91. strcmp(args->args[0], "rm") == 0)
  92. {
  93. ret = brk_del(sh, args, 1);
  94. return ret;
  95. }
  96. else if(strcmp(args->args[0], "list") == 0 || \
  97. strcmp(args->args[0], "ls") == 0 || \
  98. strcmp(args->args[0], "l") == 0)
  99. {
  100. ret = brk_ls(sh, args, 1);
  101. return ret;
  102. }
  103. else
  104. {
  105. asmsh_log_error("Unrecognized action '%s'", args->args[0]);
  106. log_brk_usage();
  107. }
  108. return -1;
  109. }
  110. static int brk_after(asmsh_t *sh, asmsh_cmd_args_t *args, int first)
  111. {
  112. asmsh_bytecode_t bcode;
  113. size_t sz;
  114. sz = 0;
  115. for(int i=1; i<args->argc; i++)
  116. {
  117. sz += strlen(args->args[i]) + 1;
  118. }
  119. char instr[sz];
  120. char *iptr = instr;
  121. for(int i=1; i<args->argc; i++)
  122. {
  123. iptr += sprintf(iptr, "%s ", args->args[i]);
  124. }
  125. instr[sz-1] = '\0';
  126. if(asmsh_asmc_compile(sh->cctx, instr, &bcode) < 0 ||\
  127. asmsh_env_write_code(sh->env, &bcode) < 0)
  128. {
  129. asmsh_log_perror("Unable to add breakpoint");
  130. return -1;
  131. }
  132. if(brk_add_or_err(sh, sh->env->regs.rip + bcode.size) < 0)
  133. {
  134. return -1;
  135. }
  136. int status;
  137. int ret = asmsh_env_step(sh->env, &status);
  138. return ret;
  139. }
  140. static int brk_add(asmsh_t *sh, asmsh_cmd_args_t *args, int expr_first)
  141. {
  142. const unsigned long rip = sh->env->regs.rip;
  143. unsigned long addr;
  144. if(asmsh_cmd_parse_addr_expr(args, expr_first, rip, &addr) < 0)
  145. {
  146. return -1;
  147. }
  148. return brk_add_or_err(sh, addr);
  149. }
  150. static int brk_add_or_err(asmsh_t *sh, unsigned long addr)
  151. {
  152. int ret = asmsh_brk_add(&sh->env->brks, addr);
  153. if(ret < 0)
  154. {
  155. int err = errno;
  156. asmsh_log_error("Unable to set breakpoint @ %016lX : %s",
  157. addr, strerror(errno));
  158. errno = err;
  159. return -1;
  160. }
  161. else if(ret > 0)
  162. {
  163. asmsh_log_warning("Breakpoint @ %016lX allready set", addr);
  164. return 0;
  165. }
  166. asmsh_log_info("Set breakpoint @ %016lX", addr);
  167. return 0;
  168. }
  169. static int brk_del(asmsh_t *sh, asmsh_cmd_args_t *args, int expr_first)
  170. {
  171. const unsigned long rip = sh->env->regs.rip;
  172. unsigned long addr;
  173. if(asmsh_cmd_parse_addr_expr(args, expr_first, rip, &addr) < 0)
  174. {
  175. return -1;
  176. }
  177. int ret = asmsh_brk_del(&sh->env->brks, addr);
  178. if(ret < 0)
  179. {
  180. int err = errno;
  181. asmsh_log_error("Unable to remove breakpoint @ %016lX : %s",
  182. addr, strerror(errno));
  183. errno = err;
  184. return -1;
  185. }
  186. else if(ret > 0)
  187. {
  188. asmsh_log_warning("Breakpoint @ %016lX do not exists", addr);
  189. return -1;
  190. }
  191. asmsh_log_info("Removed breakpoint @ %016lX", addr);
  192. return 0;
  193. }
  194. static int brk_ls(asmsh_t *sh, asmsh_cmd_args_t *args, int expr_first)
  195. {
  196. for(size_t i=0; i<sh->env->brks.sz; i++)
  197. {
  198. printf("0x%016lx\n", sh->env->brks.addrs[i]);
  199. }
  200. printf("%ld breakpoints\n", sh->env->brks.sz);
  201. return 0;
  202. }