Browse Source

First instruction completion implementation

+ strating args completion
Yann Weber 1 year ago
parent
commit
6cc8ab5e41
6 changed files with 632 additions and 19 deletions
  1. 1
    1
      Makefile.am
  2. 4
    2
      asm_env.c
  3. 24
    16
      asmsh.c
  4. 263
    0
      completion.c
  5. 292
    0
      completion.h
  6. 48
    0
      tests/tests_completion.c

+ 1
- 1
Makefile.am View File

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

+ 4
- 2
asm_env.c View File

@@ -157,7 +157,7 @@ int asmsh_env_step(asmsh_env_t *env, int *status)
157 157
 	}
158 158
 	if(status) { *status = env->status; }
159 159
 
160
-	if(!WIFSTOPPED(env->status))
160
+	if(!WIFSTOPPED(env->status) || env->status >> 8 != 5)
161 161
 	{
162 162
 		goto err_wstatus;
163 163
 	}
@@ -183,7 +183,9 @@ err_wstatus:
183 183
 	}
184 184
 	else if(WIFSTOPPED(env->status))
185 185
 	{
186
-		dprintf(2, "Child stopped by sig %d\n", WSTOPSIG(env->status));
186
+		dprintf(2, "Child stopped by %s(sig#%d)\n",
187
+				strsignal(WSTOPSIG(env->status)),
188
+				WSTOPSIG(env->status));
187 189
 	}
188 190
 	else
189 191
 	{

+ 24
- 16
asmsh.c View File

@@ -7,6 +7,7 @@
7 7
 
8 8
 #include "asm_env.h"
9 9
 #include "compile.h"
10
+#include "completion.h"
10 11
 
11 12
 static void print_regs(asmsh_env_t *env)
12 13
 {
@@ -35,6 +36,10 @@ flags: %c%c%c%c|%c%c%c\n\
35 36
 #undef FLG
36 37
 }
37 38
 
39
+/*
40
+static char *asm_startmatch_gen(const char *text, int state)
41
+{
42
+}
38 43
 
39 44
 static char *asm_match_generator(const char *text, int state)
40 45
 {
@@ -47,8 +52,17 @@ static char **asmsh_completion(const char *text, int start, int end)
47 52
 {
48 53
 	rl_attempted_completion_over = 1;
49 54
 	//dprintf(2,"\n'%s' '%s' %d %d\n", rl_line_buffer, text, start, end);
55
+	//if(start == 0)
56
+	//{
57
+	//	return rl_completion_matches(text, asm_startmatch_gen);
58
+	//}
59
+	//else
60
+	//{
61
+	//	return rl_completion_matches(text, asm_match_generator);
62
+	//}
50 63
 	return rl_completion_matches(text, asm_match_generator);
51 64
 }
65
+*/
52 66
 
53 67
 
54 68
 int main(int argc, char *argv[], char *envp[])
@@ -59,6 +73,8 @@ int main(int argc, char *argv[], char *envp[])
59 73
 
60 74
 	int ret, status;
61 75
 	char *cmd;
76
+	char prompt[64];
77
+	bzero(prompt, sizeof(prompt));
62 78
 
63 79
 	if(!(env = asmsh_env(CHILD_EXEC_PATH)))
64 80
 	{
@@ -70,12 +86,17 @@ int main(int argc, char *argv[], char *envp[])
70 86
 		perror("Unable to init compilation ctx");
71 87
 	}
72 88
 
73
-	rl_attempted_completion_function =  asmsh_completion;
89
+	rl_attempted_completion_function =  asmsh_rl_completion;
90
+
91
+	status = 0;
74 92
 
75 93
 	while(1)
76 94
 	{
77 95
 		print_regs(env);
78
-		cmd = readline("asmsh> ");
96
+		snprintf(prompt, sizeof(prompt)-1,
97
+				"asmsh@%p > ",
98
+				env->regs.rip, status >> 8);
99
+		cmd = readline(prompt);
79 100
 		if(!cmd)
80 101
 		{
81 102
 			break;
@@ -98,20 +119,7 @@ int main(int argc, char *argv[], char *envp[])
98 119
 		ret = asmsh_env_step(env, &status);
99 120
 		if(ret)
100 121
 		{
101
-			if(WIFEXITED(status))
102
-			{
103
-				printf("exited with status %d\n", WEXITSTATUS(status));
104
-			}
105
-			else if(WCOREDUMP(status))
106
-			{
107
-				printf("SEGFAULT");
108
-				goto err;
109
-			}
110
-			else
111
-			{
112
-				printf("Unknown status %d\n", status);
113
-				goto err;
114
-			}
122
+			dprintf(2, "Child is dead...\n");
115 123
 			break;
116 124
 		}
117 125
 		add_history(cmd);

+ 263
- 0
completion.c View File

@@ -0,0 +1,263 @@
1
+#include "completion.h"
2
+
3
+/// Replace uppper char leading macro if needed
4
+static int _completion_upper_macro(const char *macro, const char *start, char **ret, size_t *i);
5
+
6
+char **asmsh_completion(const char *buf, const char *text, int start, int end)
7
+{
8
+	if(end == 0)
9
+	{
10
+		// TODO catenate all !
11
+		return asmsh_compl_instr(text);
12
+	}
13
+	if(*buf != '.')
14
+	{
15
+		if(start == 0)
16
+		{
17
+			return asmsh_compl_instr(text);
18
+		}
19
+		return asmsh_compl_arg(buf, text, start);
20
+	}
21
+	// command completion handling
22
+}
23
+
24
+
25
+char **asmsh_compl_instr(const char *start)
26
+{
27
+	const size_t icount = sizeof(x86_64_instr)/sizeof(*x86_64_instr);
28
+	size_t i,j;
29
+	char **ret;
30
+	int start_len, cmp;
31
+	ret = malloc(icount * 2 * sizeof(char*));
32
+	bzero(ret, icount * sizeof(char*));
33
+	if(!ret)
34
+	{
35
+		perror("Unable to allocate completion result");
36
+		return NULL;
37
+	}
38
+	if(!start || !*start)
39
+	{
40
+		i=0;
41
+		for(j=0; j<icount; j++)
42
+		{
43
+			if(x86_64_instr[j].mnemo)
44
+			{
45
+				int mret = _completion_upper_macro(
46
+					x86_64_instr[j].mnemo,
47
+					"", ret, &i);
48
+				if(mret < 0)
49
+				{
50
+					goto err_strdup;
51
+				}
52
+				else if(mret == 0)
53
+				{
54
+					ret[i] = strdup(x86_64_instr[j].mnemo);
55
+					if(!ret[i])
56
+					{
57
+						goto err_strdup;
58
+					}
59
+					i++;
60
+				}
61
+			}
62
+			else
63
+			{
64
+				ret[i] = NULL;
65
+			}
66
+		}
67
+		return ret;
68
+	}
69
+	else
70
+	{
71
+		start_len = strlen(start);
72
+		i=0;
73
+		for(j=0; x86_64_instr[j].mnemo; j++)
74
+		{
75
+
76
+			int mret = _completion_upper_macro(
77
+					x86_64_instr[j].mnemo,
78
+					start, ret, &i);
79
+			if(mret < 0)
80
+			{
81
+				goto err_strdup;
82
+			}
83
+			else if(mret > 0)
84
+			{
85
+				continue; // handled by macro
86
+			}
87
+			// normal comparison
88
+			cmp = strncmp(start, x86_64_instr[j].mnemo, start_len);
89
+			if(cmp == 0)
90
+			{
91
+				ret[i]=strdup(x86_64_instr[j].mnemo);
92
+				if(!ret[i])
93
+				{
94
+					goto err_strdup;
95
+				}
96
+				i++;
97
+			}
98
+			else if (cmp < 0)
99
+			{
100
+				break;
101
+			}
102
+		}
103
+	}
104
+	return ret;
105
+
106
+err_strdup:
107
+	perror("Error while copying string for completion");
108
+	i--;
109
+	do
110
+	{
111
+		free(ret[i]);
112
+	}while(i>0);
113
+	free(ret);
114
+	return NULL;
115
+}
116
+
117
+
118
+
119
+char **asmsh_compl_arg(const char *buf, const char *text, int start)
120
+{
121
+	char **ret;
122
+
123
+	int match = -1;
124
+
125
+	for(int i=0; i<(sizeof(x86_64_instr)/sizeof(*x86_64_instr))-1; i++)
126
+	{
127
+		const char *instr = x86_64_instr[i].mnemo;
128
+		int ilen = strlen(instr);
129
+		int macro = 0;
130
+		if(instr[ilen-1] >= 'A' && instr[ilen-1] <= 'Z')
131
+		{
132
+			ilen--;
133
+			macro = 1;
134
+		}
135
+		int cmp = strncmp(buf, instr, ilen);
136
+		if(cmp < 0)
137
+		{
138
+			break;
139
+		}
140
+		else if(cmp > 0)
141
+		{
142
+			continue;
143
+		}
144
+		else if(!macro && (buf[ilen] != ' ' && buf[ilen] != '\t'))
145
+		{
146
+			continue; //not a full match
147
+		}
148
+		// match or approximate macro match
149
+		match = i;
150
+		break;
151
+	}
152
+	if(match < 0)
153
+	{
154
+		ret = malloc(sizeof(char*));
155
+		*ret = NULL;
156
+		return ret;
157
+	}
158
+	
159
+	return ret;
160
+}
161
+
162
+
163
+
164
+static int _completion_upper_macro(const char *macro, const char *start, char **ret, size_t *i)
165
+{
166
+	int stlen, len, oi, need_cmp;
167
+	char buf[32]; /* large enough */
168
+	char fmt[32];
169
+	oi = *i;
170
+	len = strlen(macro);
171
+	stlen = strlen(start);
172
+
173
+	switch(macro[len-1])
174
+	{
175
+		case 'C':
176
+		case 'S':
177
+			break;
178
+		default:
179
+			return 0;
180
+	}
181
+
182
+	need_cmp=1;
183
+	if(len > stlen)
184
+	{
185
+		if(strncmp(start, macro, stlen) == 0)
186
+		{
187
+			need_cmp = 0;
188
+		}
189
+		else
190
+		{
191
+			return 0;
192
+		}
193
+	}
194
+	else
195
+	{
196
+		if(strncmp(start, macro, len-1))
197
+		{
198
+			return 0;
199
+		}
200
+	}
201
+	
202
+	switch(macro[len-1])
203
+	{
204
+		case 'C':
205
+			memcpy(fmt, macro, len-1);
206
+			fmt[len-1]='%';
207
+			fmt[len]='s';
208
+			fmt[len+1]='\0';
209
+			for(const char * const *cc=M_conds; *cc; cc++)
210
+			{
211
+				int r = snprintf(buf, 31, fmt, *cc);
212
+				if(r < 0) { return -1; }
213
+				buf[r] = '\0';
214
+				if(!need_cmp || strncmp(start, buf, r<stlen?r:stlen) == 0)
215
+				{
216
+					ret[*i] = strdup(buf);
217
+					(*i)++;
218
+				}
219
+			}
220
+			break;
221
+		case 'S':
222
+			if(!need_cmp)
223
+			{
224
+				ret[*i] = strdup(macro);
225
+				ret[*i][len-1] = '\0';
226
+				(*i)++;
227
+				for(const char *s=M_sizes; *s; s++)
228
+				{
229
+					if(!(ret[*i] = strdup(macro)))
230
+					{
231
+						return -1;
232
+					}
233
+					ret[*i][len-1] = *s;
234
+					(*i)++;
235
+				}
236
+			}
237
+			else if(stlen == len-1)
238
+			{
239
+				ret[*i] = strdup(macro);
240
+				ret[*i][len-1] = '\0';
241
+				(*i)++;
242
+			}
243
+			else if(stlen == len)
244
+			{
245
+				for(const char *s=M_sizes; *s; s++)
246
+				{
247
+					if(*s == start[len-1])
248
+					{
249
+						if(!(ret[*i]=strdup(macro)))
250
+						{
251
+							return -1;
252
+						}
253
+						ret[*i][len-1]=*s;
254
+						(*i)++;
255
+						break;
256
+					}
257
+				}
258
+			}
259
+			break;
260
+	}
261
+	return 1;
262
+}
263
+

+ 292
- 0
completion.h View File

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

+ 48
- 0
tests/tests_completion.c View File

@@ -0,0 +1,48 @@
1
+#include "config.h"
2
+
3
+#include <check.h>
4
+#include <errno.h>
5
+#include <stdio.h>
6
+#include <unistd.h>
7
+
8
+#include "asmsh_check.h"
9
+#include "completion.h"
10
+
11
+const char *icompl_a[] = {"a", "aaa", "aad", "aam", "aas", "adc", "add", "and", "andn", NULL};
12
+const char *icompl_x[] = {"x", "xadd", "xchg", "xlat", "xor", NULL};
13
+const char *icompl_j[] = {"j", "jo", "jno", "jb", "jc", "jnae", "jae", "jnb", "jnc", "je", "jz", "jne", "jnz", "jbe", "jna", "ja", "jnbe", "js", "jns", "jp", "jpe", "jnp", "jpo", "jl", "jnge", "jge", "jnl", "jle", "jng", "jg", "jnle", "jmp", NULL};
14
+const char *icompl_xa[] = {"xr", NULL};
15
+const char *icompl_ro[] = {"ro", "rol", "ror", NULL};
16
+const char *icompl_movs[] = {"movs", "movs", "movsb", "movsw", "movsd", "movsq", "movsx", NULL};
17
+const char *icompl_movb[] = {"movb", "movb", "movbe", NULL};
18
+const char **icompl[] = {icompl_a, icompl_x, icompl_j, icompl_xa, icompl_ro, icompl_movs, icompl_movb};
19
+int icompl_sz = sizeof(icompl)/sizeof(*icompl);
20
+
21
+START_TEST(test_instr_completions)
22
+{
23
+	const char **curcomp = icompl[_i];
24
+	char **ret;
25
+	int i;
26
+	ret = asmsh_compl_instr(curcomp[0]);
27
+	ck_assert_ptr_nonnull(ret);
28
+
29
+	i=0;
30
+	while(1)
31
+	{
32
+		if(!ret[i] || !curcomp[i+1])
33
+		{
34
+			ck_assert_ptr_null(ret[i]);
35
+			ck_assert_ptr_null(curcomp[i+1]);
36
+			break;
37
+		}
38
+		ck_assert_str_eq(ret[i], curcomp[i+1]);
39
+		free(ret[i]);
40
+		i++;
41
+	}
42
+	free(ret);
43
+}
44
+END_TEST
45
+
46
+ASMSH_CHECK_START("testing completion", "Testing completion features")
47
+	ASMSH_ADD_LOOP_TEST(test_instr_completions, 0, icompl_sz);
48
+ASMSH_CHECK_END

Loading…
Cancel
Save