@@ -105,53 +105,119 @@ static bool _displ_operand_rule(RDLexer* lex, void* userdata) {
105105 return false;
106106 }
107107
108- if (!rd_lexer_next_expect (lex , RD_TOK_OPEN_SQUARE , & tok )) return false;
108+ if (!rd_lexer_try_consume (lex , RD_TOK_OPEN_SQUARE , & tok )) return false;
109109
110110 ZydisRegister base = ZYDIS_REGISTER_NONE , index = ZYDIS_REGISTER_NONE ;
111111 u8 scale = 1 ;
112112 i64 disp = 0 ;
113- bool have_disp = false;
113+ bool have_disp = false, first = true ;
114114
115- // optional base register: "[0x1000]" (absolute) is valid with none at all
116- if (rd_lexer_peek_expect (lex , RD_TOK_IDENTIFIER , & tok )) {
117- ZydisRegister reg = _x86_register_from_token (& tok );
115+ while (!rd_lexer_try_consume (lex , RD_TOK_CLOSE_SQUARE , & tok )) {
116+ bool minus = false;
118117
119- if (reg != ZYDIS_REGISTER_NONE ) {
120- rd_lexer_consume (lex );
121- base = reg ;
122- }
123- }
118+ if (!first ) {
119+ if (!rd_lexer_next (lex , & tok )) {
120+ RD_LOG_FAIL_TO (data -> buf , "unterminated memory operand" );
121+ return false;
122+ }
123+
124+ bool plus = tok .type == RD_TOK_PLUS ;
125+ minus = tok .type == RD_TOK_MINUS ;
124126
125- for (;;) {
126- if (!rd_lexer_next (lex , & tok )) return false;
127- if (tok .type == RD_TOK_CLOSE_SQUARE ) break ;
127+ if (!plus && !minus ) {
128+ RD_LOG_FAIL_TO (data -> buf , "expected '+' or '-'" );
129+ return false;
130+ }
131+ }
128132
129- bool plus = tok .type == RD_TOK_PLUS , minus = tok .type == RD_TOK_MINUS ;
130- if (!plus && !minus ) return false;
131- if (!rd_lexer_next (lex , & tok )) return false;
133+ if (!rd_lexer_next (lex , & tok )) {
134+ RD_LOG_FAIL_TO (data -> buf , "unterminated memory operand" );
135+ return false;
136+ }
132137
133- if (tok .type == RD_TOK_IDENTIFIER ) { // index register, optional "*scale"
138+ if (tok .type == RD_TOK_IDENTIFIER ) {
134139 ZydisRegister reg = _x86_register_from_token (& tok );
135- if (reg == ZYDIS_REGISTER_NONE ) return false;
136- index = reg ;
137140
138- if (rd_lexer_peek_expect (lex , RD_TOK_ASTERISK , & tok )) {
139- rd_lexer_consume (lex );
141+ if (reg != ZYDIS_REGISTER_NONE ) {
142+ u8 curr_scale = 1 ;
143+ bool scaled = rd_lexer_try_consume (lex , RD_TOK_ASTERISK , & tok );
140144
141- if (!rd_lexer_next_expect (lex , RD_TOK_NUMBER , & tok ))
145+ if (scaled && !rd_lexer_next_expect (lex , RD_TOK_NUMBER , & tok )) {
146+ RD_LOG_FAIL_TO (data -> buf , "expected scale value after '*'" );
147+ return false;
148+ }
149+
150+ if (scaled ) curr_scale = (u8 )tok .u_value ;
151+
152+ if (scaled || base != ZYDIS_REGISTER_NONE ) {
153+ if (index != ZYDIS_REGISTER_NONE ) {
154+ RD_LOG_FAIL_TO (data -> buf ,
155+ "only one index register is allowed" );
156+ return false;
157+ }
158+
159+ if (reg == ZYDIS_REGISTER_ESP || reg == ZYDIS_REGISTER_RSP ) {
160+ RD_LOG_FAIL_TO (
161+ data -> buf ,
162+ "ESP/RSP cannot be used as an index register" );
163+ return false;
164+ }
165+
166+ index = reg ;
167+ scale = curr_scale ;
168+ }
169+ else
170+ base = reg ;
171+ }
172+ else { // not a register, try as a symbol
173+ const char * name = rd_lexer_token_value (lex , & tok );
174+
175+ RDAddress addr ;
176+ if (!rd_get_address (data -> ctx , name , & addr )) {
177+ RD_LOG_FAIL_TO (
178+ data -> buf ,
179+ "unknown register or symbol '%s' in memory operand" ,
180+ name );
142181 return false;
182+ }
183+
184+ disp += minus ? - (i64 )addr
185+ : (i64 )addr ; // folds into the displacement
143186
144- scale = ( u8 ) tok . u_value ;
187+ have_disp = true ;
145188 }
146189 }
147190 else if (tok .type == RD_TOK_NUMBER ) {
191+ if (have_disp ) {
192+ RD_LOG_FAIL_TO (data -> buf , "only one displacement is allowed" );
193+ return false;
194+ }
195+
148196 disp = minus ? - (i64 )tok .u_value : (i64 )tok .u_value ;
149197 have_disp = true;
150198 }
151- else
199+ else {
200+ RD_LOG_FAIL_TO (data -> buf , "unexpected token in memory operand" );
152201 return false;
202+ }
203+
204+ first = false;
205+ }
206+
207+ if (base == ZYDIS_REGISTER_NONE && index == ZYDIS_REGISTER_NONE &&
208+ !have_disp ) {
209+ RD_LOG_FAIL_TO (data -> buf , "empty memory operand" );
210+ return false;
153211 }
154212
213+ ZydisEncoderOperand * zop = & data -> req .operands [data -> req .operand_count ++ ];
214+ zop -> type = ZYDIS_OPERAND_TYPE_MEMORY ;
215+ zop -> mem .base = base ;
216+ zop -> mem .index = index ;
217+ zop -> mem .scale = index != ZYDIS_REGISTER_NONE ? scale : 0 ;
218+ zop -> mem .displacement = disp ;
219+ zop -> mem .size = (ZyanU16 )size ;
220+
155221 return true;
156222}
157223
@@ -160,16 +226,14 @@ bool x86_encoder_parse(RDLexer* lex, const char* s, X86GrammarData* data) {
160226
161227 RDToken tok ;
162228 if (!rd_lexer_next_expect (lex , RD_TOK_IDENTIFIER , & tok )) {
163- RD_LOG_FAIL (
164- "%s" , rd_format_to (data -> err_buf , "expected mnemonic in '%s'" , s ));
229+ RD_LOG_FAIL_TO (data -> buf , "expected mnemonic in '%s'" , s );
165230 return false;
166231 }
167232
168233 ZydisMnemonic mnem = _x86_mnemonic_from_token (& tok );
169234 if (mnem == ZYDIS_MNEMONIC_INVALID ) {
170- RD_LOG_FAIL ("%s" , rd_format_to (data -> err_buf ,
171- "unknown mnemonic '%.*s' in '%s'" ,
172- (int )tok .length , tok .value , s ));
235+ RD_LOG_FAIL_TO (data -> buf , "unknown mnemonic '%.*s' in '%s'" ,
236+ (int )tok .length , tok .value , s );
173237 return false;
174238 }
175239
@@ -185,32 +249,28 @@ bool x86_encoder_parse(RDLexer* lex, const char* s, X86GrammarData* data) {
185249 RDToken peek ;
186250 if (rd_lexer_peek (lex , & peek )) {
187251 if (!rd_lexer_try_any (lex , OPERAND_ENTRIES , data )) {
188- RD_LOG_FAIL ("%s" , rd_format_to (data -> err_buf ,
189- "expected operand in '%s'" , s ));
252+ RD_LOG_FAIL_TO (data -> buf , "expected operand in '%s'" , s );
190253 return false;
191254 }
192255
193256 while (rd_lexer_peek_expect (lex , RD_TOK_COMMA , & tok )) {
194257 rd_lexer_consume (lex );
195258
196259 if (data -> req .operand_count >= ZYDIS_ENCODER_MAX_OPERANDS ) {
197- RD_LOG_FAIL ("%s" , rd_format_to (data -> err_buf ,
198- "too many operands in '%s'" , s ));
260+ RD_LOG_FAIL_TO (data -> buf , "too many operands in '%s'" , s );
199261 return false;
200262 }
201263
202264 if (!rd_lexer_try_any (lex , OPERAND_ENTRIES , data )) {
203- RD_LOG_FAIL ("%s" , rd_format_to (
204- data -> err_buf ,
205- "expected operand after ',' in '%s'" , s ));
265+ RD_LOG_FAIL_TO (data -> buf , "expected operand after ',' in '%s'" ,
266+ s );
206267 return false;
207268 }
208269 }
209270 }
210271
211272 if (!rd_lexer_at_end (lex )) {
212- RD_LOG_FAIL ("%s" , rd_format_to (data -> err_buf ,
213- "unexpected trailing input in '%s'" , s ));
273+ RD_LOG_FAIL_TO (data -> buf , "unexpected trailing input in '%s'" , s );
214274 return false;
215275 }
216276
@@ -230,11 +290,10 @@ bool x86_encoder_parse(RDLexer* lex, const char* s, X86GrammarData* data) {
230290 if (op -> type != ZYDIS_OPERAND_TYPE_MEMORY || op -> mem .size != 0 ) continue ;
231291
232292 if (!reg_size ) {
233- RD_LOG_FAIL ("%s" ,
234- rd_format_to (data -> err_buf ,
235- "ambiguous memory operand size in '%s'"
236- "specify byte/word/dword/qword ptr" ,
237- s ));
293+ RD_LOG_FAIL_TO (data -> buf ,
294+ "ambiguous memory operand size in '%s' "
295+ "specify byte/word/dword/qword ptr" ,
296+ s );
238297 return false;
239298 }
240299
0 commit comments