Browse Source

Starts implementing asmsh commands

Yann Weber 1 year ago
parent
commit
22e6614238
7 changed files with 299 additions and 36 deletions
  1. 2
    1
      Makefile.am
  2. 0
    28
      asmsh.c
  3. 1
    1
      compile.c
  4. 26
    6
      shell.c
  5. 3
    0
      shell.h
  6. 102
    0
      shell_cmds.c
  7. 165
    0
      shell_cmds.h

+ 2
- 1
Makefile.am View File

@@ -1,6 +1,7 @@
1 1
 bin_PROGRAMS = asmsh child
2 2
 
3
-libcheck_asmsh_a_SOURCES = mmap_parse.c asm_env.c compile.c logger.c completion.c shell.c
3
+libcheck_asmsh_a_SOURCES = mmap_parse.c asm_env.c compile.c logger.c \
4
+			   completion.c shell.c shell_cmds.c
4 5
 
5 6
 asmsh_SOURCES = asmsh.c $(libcheck_asmsh_a_SOURCES)
6 7
 child_SOURCES = child.s

+ 0
- 28
asmsh.c View File

@@ -9,33 +9,6 @@
9 9
 #include "shell.h"
10 10
 #include "completion.h"
11 11
 
12
-static void print_regs(asmsh_env_t *env)
13
-{
14
-	asmsh_env_update_regs(env);
15
-	struct user_regs_struct *r = &env->regs;
16
-	
17
-#define FLG(b, l) ( (r->eflags & (1<<b))?l:'-' )
18
-
19
-	printf("rax: %016lx rbx: %016lx rcx: %016lx rdx: %016lx\n\
20
-rbp: %016lx rsi: %016lx rdi: %016lx rsp: %016lx\n\
21
- r8: %016lx  r9: %016lx r10: %016lx r11: %016lx\n\
22
-r12: %016lx r13: %016lx r14: %016lx r15: %016lx\n\
23
-rip: %016lx flg: %016lx\n\
24
-cs: %04x ds: %04x es: %04x fs:%04x gs: %04x ss:%04x\n\
25
-flags: %c%c%c%c|%c%c%c\n\
26
-       ODSZ|APC\n\
27
-",	r->rax, r->rbx, r->rcx, r->rdx,\
28
-	r->rbp, r->rsi, r->rdi, r->rsp,\
29
-	r->r8, r->r9, r->r10, r->r11,\
30
-	r->r12, r->r13, r->r14, r->r15,\
31
-	r->rip, r->eflags,\
32
-	r->cs, r->ds, r->es, r->fs, r->gs, r->ss,
33
-	FLG(11,'O'), FLG(10, 'D'), FLG(7, 'S'), FLG(6, 'Z'),
34
-	FLG(4, 'A'), FLG(2, 'P'), FLG(0, 'C'));
35
-
36
-#undef FLG
37
-}
38
-
39 12
 int main(int argc, char *argv[], char *envp[])
40 13
 {
41 14
 	asmsh_logger_t *logger;
@@ -62,7 +35,6 @@ int main(int argc, char *argv[], char *envp[])
62 35
 
63 36
 	while(1)
64 37
 	{
65
-		print_regs(sh.env);
66 38
 		snprintf(prompt, sizeof(prompt)-1,
67 39
 				"asmsh@%p > ",
68 40
 				sh.env->regs.rip);

+ 1
- 1
compile.c View File

@@ -544,7 +544,7 @@ int asmh_asmc_bytecode_from_obj(const char *objfile, asmsh_bytecode_t *bytecode)
544 544
 
545 545
 	if(bytecode_sz == 0)
546 546
 	{
547
-		dprintf(2, "Null bytecode size");
547
+		asmsh_log_error("Null bytecode size");
548 548
 		err = ENODATA;
549 549
 		goto err;
550 550
 	}

+ 26
- 6
shell.c View File

@@ -14,6 +14,7 @@ int asmsh_init(asmsh_t *sh, const char *child_path)
14 14
 		asmsh_env_free(sh->env);
15 15
 		goto err;
16 16
 	}
17
+	sh->child_path = strdup(child_path); // TODO check error
17 18
 	return 0;
18 19
 err:
19 20
 	bzero(sh, sizeof(asmsh_t));
@@ -32,6 +33,14 @@ void asmsh_cleanup(asmsh_t *sh)
32 33
 	{
33 34
 		asmsh_env_free(sh->env);
34 35
 	}
36
+	if(sh->child_path)
37
+	{
38
+		free(sh->child_path);
39
+	}
40
+	if(sh->last_instr)
41
+	{
42
+		free(sh->last_instr);
43
+	}
35 44
 	bzero(sh, sizeof(asmsh_t));
36 45
 }
37 46
 
@@ -81,6 +90,7 @@ static int _compile_step(asmsh_t *sh, const char *cmd)
81 90
 	sh->last_bcode = bcode;
82 91
 	if(sh->last_instr) { free(sh->last_instr); }
83 92
 	sh->last_instr = strdup(cmd);
93
+
84 94
 char buf[256];
85 95
 int _ret;
86 96
 _ret = snprintf(buf, 255, "'%s' = 0x", cmd);
@@ -116,15 +126,25 @@ asmsh_log_info(buf);
116 126
 static int _handle_command(asmsh_t *sh, const char *cmd)
117 127
 {
118 128
 	const int clen = strlen(cmd);
129
+	const asmsh_cmd_t *match;
130
+	int ret;
119 131
 
120
-	if(clen <= 1)
132
+	asmsh_cmd_args_t *args;
133
+
134
+	args = asmsh_cmd_parse(cmd);
135
+	if(!args)
121 136
 	{
122
-		asmsh_log_error("No command given");
123
-		return 0;
137
+		asmsh_log_error("Parse error"); // TODO better error
138
+		return -1;
124 139
 	}
125
-	if(strncmp(cmd, ".quit", clen) == 0)
140
+
141
+	match = asmsh_cmd_match(args->cmd, strlen(args->cmd));
142
+	if(!match)
126 143
 	{
127
-		asmsh_cleanup(sh);
128
-		return 1;
144
+		asmsh_log_error("Unknow command");
145
+		return -1;
129 146
 	}
147
+	ret = match->cmd(sh, args);
148
+	asmsh_cmd_args_free(args);
149
+	return ret;
130 150
 }

+ 3
- 0
shell.h View File

@@ -16,6 +16,7 @@ struct asmsh_s
16 16
 	asmsh_asmc_ctx_t *cctx;
17 17
 	asmsh_env_t *env;
18 18
 
19
+	char *child_path;
19 20
 	char *last_instr;
20 21
 	asmsh_bytecode_t last_bcode;
21 22
 
@@ -27,4 +28,6 @@ void asmsh_cleanup(asmsh_t *sh);
27 28
 /** @return <0 on error 0 on ok 1 on exit */
28 29
 int asmsh_exec(asmsh_t *sh, const char *cmd);
29 30
 
31
+#include "shell_cmds.h"
32
+
30 33
 #endif

+ 102
- 0
shell_cmds.c View File

@@ -0,0 +1,102 @@
1
+#include "shell_cmds.h"
2
+
3
+const asmsh_cmd_t *asmsh_cmd_match(const char *text, int tlen)
4
+{
5
+	for(const asmsh_cmd_t *cmd=asmsh_CMDS; cmd->str; cmd++)
6
+	{
7
+		const int clen = strlen(cmd->str);
8
+		if(cmd->sm && tlen >= cmd->sm && tlen < clen)
9
+		{
10
+			if(!strncmp(cmd->str, text, tlen))
11
+			{
12
+				return cmd;
13
+			}
14
+			continue;
15
+		}
16
+		else if(tlen != clen) { continue; }
17
+		else
18
+		{
19
+			int cmp = strncmp(text, cmd->str, tlen);
20
+			if(cmp < 0)
21
+			{
22
+				break;
23
+			}
24
+			else if(!cmp)
25
+			{
26
+				return cmd;
27
+			}
28
+		}
29
+	}
30
+	return NULL;
31
+}
32
+
33
+
34
+asmsh_cmd_args_t *asmsh_cmd_parse(const char *cmd)
35
+{
36
+	asmsh_cmd_args_t *ret;
37
+	int cmdlen, err, argno;
38
+	const char *ptr, *arg;
39
+
40
+	if(!cmd || !*cmd || *cmd != '.') { return NULL; }
41
+
42
+	if(!(ret = malloc(sizeof(*ret))))
43
+	{
44
+		asmsh_log_fatal("Unable to allocate command");
45
+		return NULL;
46
+	}
47
+	bzero(ret, sizeof(*ret));
48
+
49
+	cmdlen=0;
50
+	for(ptr=cmd; *ptr && *ptr != ' ' && *ptr != '\t' && *ptr != '\n'; ptr++)
51
+	{
52
+		cmdlen++;
53
+	}
54
+	if(cmdlen > ASMSH_CMD_MAXLEN)
55
+	{
56
+		asmsh_log_error("Invalid command"); //TODO printf command
57
+		err=EINVAL;
58
+		goto err;
59
+	}
60
+	strncpy(ret->cmd, cmd, cmdlen);
61
+	ret->cmd[cmdlen] = '\0';
62
+	// lstrip white chars
63
+	for(ptr; *ptr && *ptr == ' ' && *ptr == '\t' && *ptr == '\n'; ptr++);
64
+	if(!*ptr)
65
+	{
66
+		// end of command
67
+		ret->args[0] = NULL;
68
+		return ret;
69
+	}
70
+	arg = ptr;
71
+	argno=0;
72
+	do
73
+	{
74
+		int arglen = 0;
75
+		for(ptr; *ptr && *ptr != ' '&& *ptr != '\t' && *ptr != '\n'; ptr++)
76
+		{
77
+			arglen++;
78
+		}
79
+		ret->args[argno] = strndup(arg, arglen);
80
+		if(!ret->args[argno])
81
+		{
82
+			err=errno;
83
+			goto err;
84
+		}
85
+		argno++;
86
+		if(argno >= ASMSH_CMD_MAXARG)
87
+		{
88
+			//too many arguments
89
+			err=EINVAL;
90
+			goto err;
91
+		}
92
+		// lstrip white chars
93
+		for(ptr; *ptr && *ptr == ' ' && *ptr == '\t' && *ptr == '\n'; ptr++);
94
+	}while(*ptr);
95
+
96
+	ret->args[argno] = NULL;
97
+	return ret;
98
+err:
99
+	for(char **p=ret->args; *p; p++) { free(*p); }
100
+	errno = err;
101
+	free(ret);
102
+}

+ 165
- 0
shell_cmds.h View File

@@ -0,0 +1,165 @@
1
+#ifndef ASMSH_SHELL_CMDS_H
2
+#define ASMSH_SHELL_CMDS_H
3
+#include "config.h"
4
+
5
+#include <errno.h>
6
+#include <stdlib.h>
7
+#include <string.h>
8
+#include <unistd.h>
9
+
10
+#include "logger.h"
11
+
12
+#define ASMSH_CMD_MAXLEN 31
13
+#define ASMSH_CMD_MAXARG 15
14
+
15
+typedef struct asmsh_cmd_s asmsh_cmd_t;
16
+typedef struct asmsh_cmd_args_s asmsh_cmd_args_t;
17
+#include "shell.h"
18
+
19
+/** @return <0 on recoverable error 0 on ok, 1+status on exit */
20
+typedef int (asmsh_cmd_f)(asmsh_t*, asmsh_cmd_args_t*);
21
+
22
+struct asmsh_cmd_s
23
+{
24
+	const char *str;
25
+	asmsh_cmd_f *cmd;
26
+	/**If non-zero indicate the minimum of chars to
27
+	 * match. ".quit" while have 2 to match starting
28
+	 * from ".q"
29
+	 */
30
+	unsigned char sm;
31
+
32
+	const char *sms;
33
+	const char *usage;
34
+	const char *desc;
35
+};
36
+
37
+struct asmsh_cmd_args_s
38
+{
39
+	char cmd[ASMSH_CMD_MAXLEN+1];
40
+	char *args[ASMSH_CMD_MAXARG+1];
41
+};
42
+
43
+static int _quit(asmsh_t *sh, asmsh_cmd_args_t *args)
44
+{
45
+	asmsh_cleanup(sh);
46
+	return 1;
47
+}
48
+
49
+static int _print_regs(asmsh_t *sh, asmsh_cmd_args_t *args)
50
+{
51
+	asmsh_env_t *env = sh->env;
52
+	asmsh_env_update_regs(env);
53
+	struct user_regs_struct *r = &env->regs;
54
+	
55
+#define FLG(b, l) ( (r->eflags & (1<<b))?l:'-' )
56
+
57
+	printf("rax: %016lx rbx: %016lx rcx: %016lx rdx: %016lx\n\
58
+rbp: %016lx rsi: %016lx rdi: %016lx rsp: %016lx\n\
59
+ r8: %016lx  r9: %016lx r10: %016lx r11: %016lx\n\
60
+r12: %016lx r13: %016lx r14: %016lx r15: %016lx\n\
61
+rip: %016lx flg: %016lx\n\
62
+cs: %04x ds: %04x es: %04x fs:%04x gs: %04x ss:%04x\n\
63
+flags: %c%c%c%c|%c%c%c\n\
64
+       ODSZ|APC\n\
65
+",	r->rax, r->rbx, r->rcx, r->rdx,\
66
+	r->rbp, r->rsi, r->rdi, r->rsp,\
67
+	r->r8, r->r9, r->r10, r->r11,\
68
+	r->r12, r->r13, r->r14, r->r15,\
69
+	r->rip, r->eflags,\
70
+	r->cs, r->ds, r->es, r->fs, r->gs, r->ss,
71
+	FLG(11,'O'), FLG(10, 'D'), FLG(7, 'S'), FLG(6, 'Z'),
72
+	FLG(4, 'A'), FLG(2, 'P'), FLG(0, 'C'));
73
+
74
+#undef FLG
75
+	return 0;
76
+}
77
+
78
+static int _reset(asmsh_t *sh, asmsh_cmd_args_t *args)
79
+{
80
+	char *childpath = strdup(sh->child_path);
81
+	asmsh_cleanup(sh);
82
+	asmsh_init(sh, childpath);
83
+	free(childpath);
84
+}
85
+
86
+static int _flags(asmsh_t *sh, asmsh_cmd_args_t *args)
87
+{
88
+	printf("Flags :\n");
89
+#define printFLG(name, b) printf(" (%2d)%16s : %d\n", b, name,\
90
+		(sh->env->regs.eflags & (1<<b))?1:0);
91
+	printFLG("Overflow", 11);
92
+	printFLG("Direction", 10);
93
+	printFLG("Sign", 7);
94
+	printFLG("Zero", 6);
95
+	printFLG("Auxiliary carry", 4);
96
+	printFLG("Parity", 2);
97
+	printFLG("Carry", 0);
98
+#undef printFLG
99
+#define EFLG(b,n) ((sh->env->regs.eflags & (1<<b))?n:'-')
100
+	printf("%c%c%c%c %c%c%c\n",
101
+			EFLG(11,'O'), EFLG(10, 'D'), EFLG(7,'S'), EFLG(6,'Z'),
102
+			EFLG(4,'A'), EFLG(2, 'P'), EFLG(0, 'C'));
103
+	return 0;
104
+}
105
+
106
+static int _help(asmsh_t *sh, asmsh_cmd_args_t *args);
107
+
108
+static const asmsh_cmd_t asmsh_CMDS[] = {
109
+	{".flags", _flags, 2,
110
+	 ".f(lags)", "",
111
+	 "display CPU flags"},
112
+	{".help", _help, 2,
113
+	 ".h(elp)","[cmd]",
114
+	 "display this help or the help of specified command"},
115
+	{".quit", _quit, 2,
116
+	 ".q(uit)","",
117
+	 "quit asmsh"},
118
+	{".regs", _print_regs, 1,
119
+	".(regs)", "",
120
+	"display registers value"},
121
+	{".reset", _reset, 0,
122
+	 ".reset", "",
123
+	 "reset the shell"},
124
+	{NULL, NULL, 0},
125
+};
126
+
127
+static int _help(asmsh_t *sh, asmsh_cmd_args_t *args)
128
+{
129
+	char buf[4096], abuf[64];
130
+	int ret, pret;
131
+
132
+	ret = snprintf(buf, 4096, "Available commands :\n");
133
+	pret = ret;
134
+	for(const asmsh_cmd_t *cmd = asmsh_CMDS; cmd->str; cmd++)
135
+	{
136
+		snprintf(abuf, 64, "%s %s", cmd->sms, cmd->usage);
137
+		ret += snprintf(buf+ret, 4096-ret, "  %-18s : %s\n", 
138
+				abuf, cmd->desc);
139
+	}
140
+	dprintf(2, buf);
141
+	return 0;
142
+}
143
+
144
+/**@param const char* the text to match
145
+ * @param int the len of the text to match
146
+ * @return a ptr or NULL
147
+ */
148
+const asmsh_cmd_t *asmsh_cmd_match(const char *cmd, int stop);
149
+
150
+/** @return NULL on error or ptr on new cmd args */
151
+asmsh_cmd_args_t *asmsh_cmd_parse(const char *cmd);
152
+static void asmsh_cmd_args_free(asmsh_cmd_args_t *args)
153
+{
154
+	if(!args) { return; }
155
+	for(char **a=args->args; *a; a++)
156
+	{
157
+		free(*a);
158
+	}
159
+	free(args);
160
+}
161
+
162
+
163
+const char *asmsh_cmd_help(asmsh_t *sh);
164
+
165
+#endif

Loading…
Cancel
Save