123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371 |
- /* Copyright Yann Weber <asmsh@yannweb.net>
- 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 <https://www.gnu.org/licenses/>.
- */
- #include "shell_cmds.h"
-
- const asmsh_cmd_t *asmsh_cmd_match(const char *text, int tlen)
- {
- for(const asmsh_cmd_t *cmd=asmsh_CMDS; cmd->str; cmd++)
- {
- const int clen = strlen(cmd->str);
- if(cmd->sm && tlen >= cmd->sm && tlen < clen)
- {
- if(!strncmp(cmd->str, text, tlen))
- {
- return cmd;
- }
- continue;
- }
- else if(tlen != clen) { continue; }
- else
- {
- int cmp = strncmp(text, cmd->str, tlen);
- if(cmp < 0)
- {
- break;
- }
- else if(!cmp)
- {
- return cmd;
- }
- }
- }
- return NULL;
- }
-
-
- asmsh_cmd_args_t *asmsh_cmd_parse(const char *cmd)
- {
- asmsh_cmd_args_t *ret;
- int cmdlen, err, argno;
- const char *ptr, *arg;
-
- if(!cmd || !*cmd) { return NULL; }
- if (*cmd != '.') { return NULL; }
-
- if(!(ret = malloc(sizeof(*ret))))
- {
- asmsh_log_fatal("Unable to allocate command");
- return NULL;
- }
- bzero(ret, sizeof(*ret));
-
- cmdlen=0;
- for(ptr=cmd; *ptr && *ptr != ' ' && *ptr != '\t' && *ptr != '\n'; ptr++)
- {
- cmdlen++;
- }
- if(cmdlen > ASMSH_CMD_MAXLEN)
- {
- asmsh_log_error("Invalid command"); //TODO printf command
- err=EINVAL;
- goto err;
- }
- strncpy(ret->cmd, cmd, cmdlen);
- ret->cmd[cmdlen] = '\0';
- // lstrip white chars
- for(; *ptr && (*ptr == ' ' || *ptr == '\t' || *ptr == '\n'); ptr++);
- if(!*ptr)
- {
- // end of command
- ret->args[0] = NULL;
- return ret;
- }
- arg = ptr;
- argno=0;
- do
- {
- int arglen = 0;
- for(; *ptr && *ptr != ' ' && *ptr != '\t' && *ptr != '\n'; ptr++)
- {
- arglen++;
- }
- ret->args[argno] = strndup(arg, arglen);
- if(!ret->args[argno])
- {
- asmsh_log_error("strndup args failed");
- err=errno;
- goto err;
- }
- argno++;
- if(argno >= ASMSH_CMD_MAXARG)
- {
- //too many arguments
- asmsh_log_error("too many arguments");
- err=EINVAL;
- goto err;
- }
- // lstrip white chars
- for(; *ptr && (*ptr == ' ' || *ptr == '\t' || *ptr == '\n'); ptr++);
- arg=ptr;
- }while(*ptr);
-
- ret->argc = argno;
- ret->args[argno] = NULL;
- return ret;
- err:
- for(char **p=ret->args; *p; p++) { free(*p); }
- errno = err;
- free(ret);
- return NULL;
- }
-
-
- void asmsh_cmd_args_free(asmsh_cmd_args_t *args)
- {
- if(!args) { return; }
- for(char **a=args->args; *a; a++)
- {
- free(*a);
- }
- free(args);
- }
-
-
- int asmsh_cmd_bcode_(asmsh_t *sh, char *argbuf, int bufsz, int argc, char **args)
- {
- asmsh_bytecode_t bcode;
- char _buf[256], *buf;
- char code[256];
- const char *instr;
- int ret;
-
- if(!argbuf)
- {
- buf=_buf;
- bufsz=256;
- }
- else
- {
- buf=argbuf;
- }
-
- if(argc == 0)
- {
- if(sh->last_instr == NULL)
- {
- asmsh_log_error("No instruction compiled yet");
- return -1;
- }
- bcode = sh->last_bcode;
- instr = sh->last_instr;
- }
- else
- {
- char **arg;
- int sz = 0;
- for(arg=args;*arg;arg++)
- {
- sz+=snprintf(code+sz, 255-sz, "%s", *arg);
- if(*(arg+1))
- {
- code[sz] = ' ';
- sz++;
- }
- }
- code[sz]='\0';
- if(asmsh_asmc_compile(sh->cctx, code, &bcode) < 0)
- {
- return -1;
- }
- instr = code;
- }
-
- ret = snprintf(buf, bufsz, "%s = (%02db) ",
- instr, bcode.size);
- for(int i=0; i<sizeof(bcode.bytes); i++)
- {
- char repr[3] = "..";
- if(i<bcode.size)
- {
- snprintf(repr, 3, "%02x", bcode.bytes[i]);
- }
- repr[2]='\0';
- ret += snprintf(buf+ret, bufsz-ret, "%s%s%s",
- i&&(i%4==0)?" ":"",i==8?" ":"",
- repr);
- }
- buf[ret] = '\0';
- return 0;
- }
-
-
-
- int asmsh_cmd_quit(asmsh_t *sh, asmsh_cmd_args_t *args)
- {
- asmsh_cleanup(sh);
- return 1;
- }
-
-
- int asmsh_cmd_bcode(asmsh_t *sh, asmsh_cmd_args_t *args)
- {
- char str[256];
- int ret;
-
- ret = asmsh_cmd_bcode_(sh, str, 256, args->argc, args->args);
- if(ret)
- {
- return ret;
- }
- printf("%s\n", str);
- return 0;
- }
-
- int asmsh_cmd_maps(asmsh_t *sh, asmsh_cmd_args_t *args)
- {
- if(asmsh_env_update_maps(sh->env) < 0)
- {
- perror("Unable to update maps info");
- return -1;
- }
- printf("%12s-%-12s perm %-8s %-6s %-10s %s\n", "start", "stop", "offset", "device",
- "inode", "path");
- for(int i=0; i<sh->env->mmap.size; i++)
- {
- const child_mmap_t *m = &sh->env->mmap.maps[i];
- printf("%012llx-%012llx %c%c%c %08lx %02lx:%02lx %10lu %s\n",
- (unsigned long long int)m->start,
- (unsigned long long int)m->stop,
- m->perm & PROT_READ ?'r':'-',
- m->perm & PROT_WRITE?'w':'-',
- m->perm & PROT_EXEC ?'x':'-',
- m->offset,
- (m->device & 0xFF00)>>8,
- m->device & 0xFF,
- m->inode,
- m->pathname);
- }
- return 0;
- }
-
- int asmsh_cmd_print_regs(asmsh_t *sh, asmsh_cmd_args_t *args)
- {
- asmsh_env_t *env = sh->env;
- asmsh_env_update_regs(env);
- struct user_regs_struct *r = &env->regs;
-
- #define FLG(b, l) ( (r->eflags & (1<<b))?l:'-' )
-
- printf("rax: %016llx rbx: %016llx rcx: %016llx rdx: %016llx\n\
- rbp: %016llx rsi: %016llx rdi: %016llx rsp: %016llx\n\
- r8: %016llx r9: %016llx r10: %016llx r11: %016llx\n\
- r12: %016llx r13: %016llx r14: %016llx r15: %016llx\n\
- rip: %016llx flg: %016llx\n\
- cs: %04llx ds: %04llx es: %04llx fs:%04llx gs: %04llx ss:%04llx\n\
- flags: %c%c%c%c|%c%c%c\n\
- ODSZ|APC\n\
- ", r->rax, r->rbx, r->rcx, r->rdx,\
- r->rbp, r->rsi, r->rdi, r->rsp,\
- r->r8, r->r9, r->r10, r->r11,\
- r->r12, r->r13, r->r14, r->r15,\
- r->rip, r->eflags,\
- r->cs, r->ds, r->es, r->fs, r->gs, r->ss,
- FLG(11,'O'), FLG(10, 'D'), FLG(7, 'S'), FLG(6, 'Z'),
- FLG(4, 'A'), FLG(2, 'P'), FLG(0, 'C'));
-
- #undef FLG
- return 0;
- }
-
-
- int asmsh_cmd_step(asmsh_t *sh, asmsh_cmd_args_t *args)
- {
- int ret, status;
- ret = asmsh_env_step(sh->env, &status);
-
- if(ret > 1)
- {
- return status;
- }
- return ret;
- }
-
-
- int asmsh_cmd_syscalls(asmsh_t *sh, asmsh_cmd_args_t *args)
- {
- const int sz = sizeof(syscall_infos)/sizeof(*syscall_infos);
- int printed;
- char buf[512];
-
- printed = 0;
- for(int i=0; i<sz; i++)
- {
- int ret = snprintf(buf, 512, "%3d 0x%03x %20s ",
- syscall_infos[i].nr,
- syscall_infos[i].nr,
- syscall_infos[i].name);
- buf[ret] = '\0';
- printed += ret;
- if(printed > 80)
- {
- printf("\n");
- printed = ret;
- }
- printf(buf);
- }
- printf("\n");
- return 0;
- }
-
- int asmsh_cmd_reset(asmsh_t *sh, asmsh_cmd_args_t *args)
- {
- char *childpath = sh->child_path?strdup(sh->child_path):NULL;
- asmsh_cleanup(sh);
- int ret = asmsh_init(sh, childpath)<0?2:0;
- if(childpath) { free(childpath); }
- return ret;
- }
-
- // Display CPU flag resister values
- int asmsh_cmd_flags(asmsh_t *sh, asmsh_cmd_args_t *args)
- {
- printf("Flags :\n");
- #define printFLG(name, b) printf(" (%2d)%16s : %d\n", b, name,\
- (sh->env->regs.eflags & (1<<b))?1:0);
- printFLG("Overflow", 11);
- printFLG("Direction", 10);
- printFLG("Sign", 7);
- printFLG("Zero", 6);
- printFLG("Auxiliary carry", 4);
- printFLG("Parity", 2);
- printFLG("Carry", 0);
- #undef printFLG
- #define EFLG(b,n) ((sh->env->regs.eflags & (1<<b))?n:'-')
- printf("%c%c%c%c %c%c%c\n",
- EFLG(11,'O'), EFLG(10, 'D'), EFLG(7,'S'), EFLG(6,'Z'),
- EFLG(4,'A'), EFLG(2, 'P'), EFLG(0, 'C'));
- return 0;
- }
-
- // Print help (command list + help)
- int asmsh_cmd_help_(asmsh_t *sh, asmsh_cmd_args_t *args)
- {
- char buf[4096], abuf[64];
- int ret;
-
- ret = snprintf(buf, 4096, "Available commands :\n");
- for(const asmsh_cmd_t *cmd = asmsh_CMDS; cmd->str; cmd++)
- {
- snprintf(abuf, 64, "%s %s", cmd->sms, cmd->usage);
- ret += snprintf(buf+ret, 4096-ret, " %-18s : %s\n",
- abuf, cmd->desc);
- }
- dprintf(2, buf);
- return 0;
- }
-
-
|