1 /*
2 * Copyright (c) 2016 GitHub, Inc.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #include <cmath>
17 #include <unordered_map>
18 #include <regex>
19
20 #include "syms.h"
21 #include "usdt.h"
22 #include "vendor/tinyformat.hpp"
23
24 #include "bcc_elf.h"
25 #include "bcc_syms.h"
26
27 namespace USDT {
28
Argument()29 Argument::Argument() {}
~Argument()30 Argument::~Argument() {}
31
ctype() const32 std::string Argument::ctype() const {
33 const int s = arg_size() * 8;
34 return (s < 0) ? tfm::format("int%d_t", -s) : tfm::format("uint%d_t", s);
35 }
36
37 static const char *type_names[][4] = {
38 { "int8_t", "int16_t", "int32_t", "int64_t" },
39 { "uint8_t", "uint16_t", "uint32_t", "uint64_t" },
40 };
41
ctype_name() const42 const char *Argument::ctype_name() const {
43 const int s = arg_size();
44 const int r = log2(abs(s));
45 return s < 0 ? type_names[0][r] : type_names[1][r];
46 }
47
get_global_address(uint64_t * address,const std::string & binpath,const optional<int> & pid) const48 bool Argument::get_global_address(uint64_t *address, const std::string &binpath,
49 const optional<int> &pid) const {
50 if (pid) {
51 static struct bcc_symbol_option default_option = {
52 .use_debug_file = 1,
53 .check_debug_file_crc = 1,
54 .lazy_symbolize = 1,
55 .use_symbol_type = BCC_SYM_ALL_TYPES
56 };
57 return ProcSyms(*pid, &default_option)
58 .resolve_name(binpath.c_str(), deref_ident_->c_str(), address);
59 }
60
61 if (!bcc_elf_is_shared_obj(binpath.c_str())) {
62 struct bcc_symbol sym;
63 if (bcc_resolve_symname(binpath.c_str(), deref_ident_->c_str(), 0x0, -1, nullptr, &sym) == 0) {
64 *address = sym.offset;
65 if (sym.module)
66 ::free(const_cast<char*>(sym.module));
67 return true;
68 }
69 }
70
71 return false;
72 }
73
assign_to_local(std::ostream & stream,const std::string & local_name,const std::string & binpath,const optional<int> & pid) const74 bool Argument::assign_to_local(std::ostream &stream,
75 const std::string &local_name,
76 const std::string &binpath,
77 const optional<int> &pid) const {
78 if (constant_) {
79 tfm::format(stream, "%s = %lld;", local_name, *constant_);
80 return true;
81 }
82
83 if (!deref_offset_) {
84 if(base_register_name_->substr(0,3) == "xmm") {
85 // TODO: When we can read xmm registers from BPF, update this to read
86 // the actual value
87 tfm::format(stream, "%s = 0;", local_name);
88 } else {
89 tfm::format(stream, "%s = ctx->%s;", local_name, *base_register_name_);
90 }
91 // Put a compiler barrier to prevent optimization
92 // like llvm SimplifyCFG SinkThenElseCodeToEnd
93 // Volatile marking is not sufficient to prevent such optimization.
94 tfm::format(stream, " %s", COMPILER_BARRIER);
95 return true;
96 }
97
98 if (deref_offset_ && !deref_ident_) {
99 tfm::format(stream, "{ u64 __addr = ctx->%s + %d",
100 *base_register_name_, *deref_offset_);
101 if (index_register_name_) {
102 int scale = scale_.value_or(1);
103 tfm::format(stream, " + (ctx->%s * %d);", *index_register_name_, scale);
104 } else {
105 tfm::format(stream, ";");
106 }
107 // Theoretically, llvm SimplifyCFG SinkThenElseCodeToEnd may still
108 // sink bpf_probe_read call, so put a barrier here to prevent sinking
109 // of ctx->#fields.
110 tfm::format(stream, " %s ", COMPILER_BARRIER);
111 tfm::format(stream,
112 "%s __res = 0x0; "
113 "bpf_probe_read_user(&__res, sizeof(__res), (void *)__addr); "
114 "%s = __res; }",
115 ctype(), local_name);
116 return true;
117 }
118
119 if (deref_offset_ && deref_ident_ && *base_register_name_ == "ip") {
120 uint64_t global_address;
121 if (!get_global_address(&global_address, binpath, pid))
122 return false;
123
124 tfm::format(stream,
125 "{ u64 __addr = 0x%xull + %d; %s __res = 0x0; "
126 "bpf_probe_read_user(&__res, sizeof(__res), (void *)__addr); "
127 "%s = __res; }",
128 global_address, *deref_offset_, ctype(), local_name);
129 return true;
130 }
131
132 return false;
133 }
134
print_error(ssize_t pos)135 void ArgumentParser::print_error(ssize_t pos) {
136 fprintf(stderr, "Parse error:\n %s\n", arg_);
137 for (ssize_t i = 0; i < pos + 4; ++i) fputc('-', stderr);
138 fputc('^', stderr);
139 fputc('\n', stderr);
140 }
141
skip_whitespace_from(size_t pos)142 void ArgumentParser::skip_whitespace_from(size_t pos) {
143 while (isspace(arg_[pos])) pos++;
144 cur_pos_ = pos;
145 }
146
skip_until_whitespace_from(size_t pos)147 void ArgumentParser::skip_until_whitespace_from(size_t pos) {
148 while (arg_[pos] != '\0' && !isspace(arg_[pos]))
149 pos++;
150 cur_pos_ = pos;
151 }
152
parse_register(ssize_t pos,ssize_t & new_pos,std::string & reg_name)153 bool ArgumentParser_aarch64::parse_register(ssize_t pos, ssize_t &new_pos,
154 std::string ®_name) {
155 if (arg_[pos] == 'x') {
156 optional<int> reg_num;
157 new_pos = parse_number(pos + 1, ®_num);
158 if (new_pos == pos + 1 || *reg_num < 0 || *reg_num > 31)
159 return error_return(pos + 1, pos + 1);
160
161 if (*reg_num == 31) {
162 reg_name = "sp";
163 } else {
164 reg_name = "regs[" + std::to_string(reg_num.value()) + "]";
165 }
166
167 return true;
168 } else if (arg_[pos] == 's' && arg_[pos + 1] == 'p') {
169 reg_name = "sp";
170 new_pos = pos + 2;
171 return true;
172 } else {
173 return error_return(pos, pos);
174 }
175 }
176
parse_size(ssize_t pos,ssize_t & new_pos,optional<int> * arg_size)177 bool ArgumentParser_aarch64::parse_size(ssize_t pos, ssize_t &new_pos,
178 optional<int> *arg_size) {
179 int abs_arg_size;
180
181 new_pos = parse_number(pos, arg_size);
182 if (new_pos == pos)
183 return error_return(pos, pos);
184
185 abs_arg_size = abs(arg_size->value());
186 if (abs_arg_size != 1 && abs_arg_size != 2 && abs_arg_size != 4 &&
187 abs_arg_size != 8)
188 return error_return(pos, pos);
189 return true;
190 }
191
parse_mem(ssize_t pos,ssize_t & new_pos,Argument * dest)192 bool ArgumentParser_aarch64::parse_mem(ssize_t pos, ssize_t &new_pos,
193 Argument *dest) {
194 std::string base_reg_name, index_reg_name;
195
196 if (parse_register(pos, new_pos, base_reg_name) == false)
197 return false;
198 dest->base_register_name_ = base_reg_name;
199
200 if (arg_[new_pos] == ',') {
201 pos = new_pos + 1;
202 new_pos = parse_number(pos, &dest->deref_offset_);
203 if (new_pos == pos) {
204 // offset isn't a number, so it should be a reg,
205 // which looks like: -1@[x0, x1], rather than -1@[x0, 24]
206 skip_whitespace_from(pos);
207 pos = cur_pos_;
208 if (parse_register(pos, new_pos, index_reg_name) == false)
209 return error_return(pos, pos);
210 dest->index_register_name_ = index_reg_name;
211 dest->scale_ = 1;
212 dest->deref_offset_ = 0;
213 }
214 }
215 if (arg_[new_pos] != ']')
216 return error_return(new_pos, new_pos);
217 new_pos++;
218 return true;
219 }
220
parse(Argument * dest)221 bool ArgumentParser_aarch64::parse(Argument *dest) {
222 if (done())
223 return false;
224
225 // Support the following argument patterns:
226 // [-]<size>@<value>, [-]<size>@<reg>, [-]<size>@[<reg>], or
227 // [-]<size>@[<reg>,<offset>]
228 // [-]<size>@[<reg>,<index_reg>]
229 ssize_t cur_pos = cur_pos_, new_pos;
230 optional<int> arg_size;
231
232 // Parse [-]<size>
233 if (parse_size(cur_pos, new_pos, &arg_size) == false)
234 return false;
235 dest->arg_size_ = arg_size;
236
237 // Make sure '@' present
238 if (arg_[new_pos] != '@')
239 return error_return(new_pos, new_pos);
240 cur_pos = new_pos + 1;
241
242 if (arg_[cur_pos] == 'x' || arg_[cur_pos] == 's') {
243 // Parse ...@<reg>
244 std::string reg_name;
245 if (parse_register(cur_pos, new_pos, reg_name) == false)
246 return false;
247
248 cur_pos_ = new_pos;
249 dest->base_register_name_ = reg_name;
250 } else if (arg_[cur_pos] == '[') {
251 // Parse ...@[<reg>], ...@[<reg,<offset>] and ...@[<reg>,<index_reg>]
252 if (parse_mem(cur_pos + 1, new_pos, dest) == false)
253 return false;
254 cur_pos_ = new_pos;
255 } else {
256 // Parse ...@<value>
257 optional<long long> val;
258 new_pos = parse_number(cur_pos, &val);
259 if (cur_pos == new_pos)
260 return error_return(cur_pos, cur_pos);
261 cur_pos_ = new_pos;
262 dest->constant_ = val;
263 }
264
265 skip_whitespace_from(cur_pos_);
266 return true;
267 }
268
parse_register(ssize_t pos,ssize_t & new_pos,std::string & reg_name)269 bool ArgumentParser_loongarch64::parse_register(ssize_t pos, ssize_t &new_pos,
270 std::string ®_name) {
271 if (arg_[pos] == '$' && arg_[pos + 1] == 'r') {
272 optional<int> reg_num;
273 new_pos = parse_number(pos + 2, ®_num);
274 if (new_pos == pos + 2 || *reg_num < 0 || *reg_num > 31)
275 return error_return(pos + 2, pos + 2);
276
277 if (*reg_num == 3) {
278 reg_name = "sp";
279 } else {
280 reg_name = "regs[" + std::to_string(reg_num.value()) + "]";
281 }
282 return true;
283 } else if (arg_[pos] == 's' && arg_[pos + 1] == 'p') {
284 reg_name = "sp";
285 new_pos = pos + 2;
286 return true;
287 } else {
288 return error_return(pos, pos);
289 }
290 }
291
parse_size(ssize_t pos,ssize_t & new_pos,optional<int> * arg_size)292 bool ArgumentParser_loongarch64::parse_size(ssize_t pos, ssize_t &new_pos,
293 optional<int> *arg_size) {
294 int abs_arg_size;
295
296 new_pos = parse_number(pos, arg_size);
297 if (new_pos == pos)
298 return error_return(pos, pos);
299
300 abs_arg_size = abs(arg_size->value());
301 if (abs_arg_size != 1 && abs_arg_size != 2 && abs_arg_size != 4 &&
302 abs_arg_size != 8)
303 return error_return(pos, pos);
304 return true;
305 }
306
parse_mem(ssize_t pos,ssize_t & new_pos,Argument * dest)307 bool ArgumentParser_loongarch64::parse_mem(ssize_t pos, ssize_t &new_pos,
308 Argument *dest) {
309 std::string base_reg_name, index_reg_name;
310
311 if (parse_register(pos, new_pos, base_reg_name) == false)
312 return false;
313 dest->base_register_name_ = base_reg_name;
314
315 if (arg_[new_pos] == ',') {
316 pos = new_pos + 1;
317 new_pos = parse_number(pos, &dest->deref_offset_);
318 if (new_pos == pos) {
319 // offset isn't a number, so it should be a reg,
320 // which looks like: -1@[$r0, $r1], rather than -1@[$r0, 24]
321 skip_whitespace_from(pos);
322 pos = cur_pos_;
323 if (parse_register(pos, new_pos, index_reg_name) == false)
324 return error_return(pos, pos);
325 dest->index_register_name_ = index_reg_name;
326 dest->scale_ = 1;
327 dest->deref_offset_ = 0;
328 }
329 }
330 if (arg_[new_pos] != ']')
331 return error_return(new_pos, new_pos);
332 new_pos++;
333 return true;
334 }
335
parse(Argument * dest)336 bool ArgumentParser_loongarch64::parse(Argument *dest) {
337 if (done())
338 return false;
339
340 // Support the following argument patterns:
341 // [-]<size>@<value>, [-]<size>@<reg>, [-]<size>@[<reg>], or
342 // [-]<size>@[<reg>,<offset>]
343 // [-]<size>@[<reg>,<index_reg>]
344 ssize_t cur_pos = cur_pos_, new_pos;
345 optional<int> arg_size;
346
347 // Parse [-]<size>
348 if (parse_size(cur_pos, new_pos, &arg_size) == false)
349 return false;
350 dest->arg_size_ = arg_size;
351
352 // Make sure '@' present
353 if (arg_[new_pos] != '@')
354 return error_return(new_pos, new_pos);
355 cur_pos = new_pos + 1;
356
357 if (arg_[cur_pos] == '$' || arg_[cur_pos] == 's') {
358 // Parse ...@<reg>
359 std::string reg_name;
360 if (parse_register(cur_pos, new_pos, reg_name) == false)
361 return false;
362
363 cur_pos_ = new_pos;
364 dest->base_register_name_ = reg_name;
365 } else if (arg_[cur_pos] == '[') {
366 // Parse ...@[<reg>], ...@[<reg,<offset>] and ...@[<reg>,<index_reg>]
367 if (parse_mem(cur_pos + 1, new_pos, dest) == false)
368 return false;
369 cur_pos_ = new_pos;
370 } else {
371 // Parse ...@<value>
372 optional<long long> val;
373 new_pos = parse_number(cur_pos, &val);
374 if (cur_pos == new_pos)
375 return error_return(cur_pos, cur_pos);
376 cur_pos_ = new_pos;
377 dest->constant_ = val;
378 }
379
380 skip_whitespace_from(cur_pos_);
381 return true;
382 }
383
parse(Argument * dest)384 bool ArgumentParser_powerpc64::parse(Argument *dest) {
385 if (done())
386 return false;
387
388 bool matched;
389 std::smatch matches;
390 std::string arg_str(&arg_[cur_pos_]);
391 std::regex arg_n_regex("^(\\-?[1248])\\@");
392 // Operands with constants of form iNUM or i-NUM
393 std::regex arg_op_regex_const("^i(\\-?[0-9]+)( +|$)");
394 // Operands with register only of form REG or %rREG
395 std::regex arg_op_regex_reg("^(?:%r)?([1-2]?[0-9]|3[0-1])( +|$)");
396 // Operands with a base register and an offset of form
397 // NUM(REG) or -NUM(REG) or NUM(%rREG) or -NUM(%rREG)
398 std::regex arg_op_regex_breg_off(
399 "^(\\-?[0-9]+)\\((?:%r)?([1-2]?[0-9]|3[0-1])\\)( +|$)");
400 // Operands with a base register and an index register
401 // of form REG,REG or %rREG,%rREG
402 std::regex arg_op_regex_breg_ireg(
403 "^(?:%r)?([1-2]?[0-9]|3[0-1])\\,(?:%r)?([1-2]?[0-9]|3[0-1])( +|$)");
404
405 matched = std::regex_search(arg_str, matches, arg_n_regex);
406 if (matched) {
407 dest->arg_size_ = stoi(matches.str(1));
408 cur_pos_ += matches.length(0);
409 arg_str = &arg_[cur_pos_];
410
411 if (std::regex_search(arg_str, matches, arg_op_regex_const)) {
412 dest->constant_ = (long long)stoull(matches.str(1));
413 } else if (std::regex_search(arg_str, matches, arg_op_regex_reg)) {
414 dest->base_register_name_ = "gpr[" + matches.str(1) + "]";
415 } else if (std::regex_search(arg_str, matches, arg_op_regex_breg_off)) {
416 dest->deref_offset_ = stoi(matches.str(1));
417 dest->base_register_name_ = "gpr[" + matches.str(2) + "]";
418 } else if (std::regex_search(arg_str, matches, arg_op_regex_breg_ireg)) {
419 dest->deref_offset_ = 0; // In powerpc64, such operands contain a base
420 // register and an index register which are
421 // part of an indexed load/store operation.
422 // Even if no offset value is present, this
423 // is required by Argument::assign_to_local()
424 // in order to generate code for reading the
425 // argument. So, this is set to zero.
426 dest->base_register_name_ = "gpr[" + matches.str(1) + "]";
427 dest->index_register_name_ = "gpr[" + matches.str(2) + "]";
428 dest->scale_ = abs(*dest->arg_size_);
429 } else {
430 matched = false;
431 }
432 }
433
434 if (!matched) {
435 print_error(cur_pos_);
436 skip_until_whitespace_from(cur_pos_);
437 skip_whitespace_from(cur_pos_);
438 return false;
439 }
440
441 cur_pos_ += matches.length(0);
442 skip_whitespace_from(cur_pos_);
443 return true;
444 }
445
parse(Argument * dest)446 bool ArgumentParser_s390x::parse(Argument *dest) {
447 if (done())
448 return false;
449
450 bool matched;
451 std::cmatch matches;
452 #define S390X_IMM "(-?[0-9]+)"
453 std::regex arg_n_regex("^" S390X_IMM "@");
454 // <imm>
455 std::regex arg_op_regex_imm("^" S390X_IMM "(?: +|$)");
456 // %r<N>
457 #define S390X_REG "%r([0-9]|1[0-5])"
458 std::regex arg_op_regex_reg("^" S390X_REG "(?: +|$)");
459 // <disp>(%r<N>,%r<N>)
460 std::regex arg_op_regex_mem("^" S390X_IMM "?\\(" S390X_REG
461 "(?:," S390X_REG ")?\\)(?: +|$)");
462 #undef S390X_IMM
463 #undef S390X_REG
464
465 matched = std::regex_search(arg_ + cur_pos_, matches, arg_n_regex);
466 if (matched) {
467 dest->arg_size_ = stoi(matches.str(1));
468 cur_pos_ += matches.length(0);
469
470 if (std::regex_search(arg_ + cur_pos_, matches, arg_op_regex_imm)) {
471 dest->constant_ = (long long)stoull(matches.str(1));
472 } else if (std::regex_search(arg_ + cur_pos_, matches, arg_op_regex_reg)) {
473 dest->base_register_name_ = "gprs[" + matches.str(1) + "]";
474 } else if (std::regex_search(arg_ + cur_pos_, matches, arg_op_regex_mem)) {
475 if (matches.length(1) > 0) {
476 dest->deref_offset_ = stoi(matches.str(1));
477 }
478 dest->base_register_name_ = "gprs[" + matches.str(2) + "]";
479 if (matches.length(3) > 0) {
480 dest->index_register_name_ = "gprs[" + matches.str(3) + "]";
481 }
482 } else {
483 matched = false;
484 }
485 }
486
487 if (!matched) {
488 print_error(cur_pos_);
489 skip_until_whitespace_from(cur_pos_);
490 skip_whitespace_from(cur_pos_);
491 return false;
492 }
493
494 cur_pos_ += matches.length(0);
495 skip_whitespace_from(cur_pos_);
496 return true;
497 }
498
parse_identifier(ssize_t pos,optional<std::string> * result)499 ssize_t ArgumentParser_x64::parse_identifier(ssize_t pos,
500 optional<std::string> *result) {
501 if (isalpha(arg_[pos]) || arg_[pos] == '_') {
502 ssize_t start = pos++;
503 while (isalnum(arg_[pos]) || arg_[pos] == '_') pos++;
504 if (pos - start)
505 result->emplace(arg_ + start, pos - start);
506 }
507 return pos;
508 }
509
parse_register(ssize_t pos,std::string & name,int & size)510 ssize_t ArgumentParser_x64::parse_register(ssize_t pos, std::string &name,
511 int &size) {
512 ssize_t start = ++pos;
513 if (arg_[start - 1] != '%')
514 return -start;
515
516 while (isalnum(arg_[pos])) pos++;
517
518 std::string regname(arg_ + start, pos - start);
519 if (!normalize_register(®name, &size))
520 return -start;
521
522 name = regname;
523 return pos;
524 }
525
parse_base_register(ssize_t pos,Argument * dest)526 ssize_t ArgumentParser_x64::parse_base_register(ssize_t pos, Argument *dest) {
527 int size;
528 std::string name;
529 ssize_t res = parse_register(pos, name, size);
530 if (res < 0)
531 return res;
532
533 dest->base_register_name_ = name;
534 if (!dest->arg_size_)
535 dest->arg_size_ = size;
536
537 return res;
538 }
539
parse_index_register(ssize_t pos,Argument * dest)540 ssize_t ArgumentParser_x64::parse_index_register(ssize_t pos, Argument *dest) {
541 int size;
542 std::string name;
543 ssize_t res = parse_register(pos, name, size);
544 if (res < 0)
545 return res;
546
547 dest->index_register_name_ = name;
548
549 return res;
550 }
551
parse_scale(ssize_t pos,Argument * dest)552 ssize_t ArgumentParser_x64::parse_scale(ssize_t pos, Argument *dest) {
553 return parse_number(pos, &dest->scale_);
554 }
555
parse_expr(ssize_t pos,Argument * dest)556 ssize_t ArgumentParser_x64::parse_expr(ssize_t pos, Argument *dest) {
557 if (arg_[pos] == '$')
558 return parse_number(pos + 1, &dest->constant_);
559
560 if (arg_[pos] == '%')
561 return parse_base_register(pos, dest);
562
563 if (isdigit(arg_[pos]) || arg_[pos] == '-') {
564 pos = parse_number(pos, &dest->deref_offset_);
565 if (arg_[pos] == '+') {
566 pos = parse_identifier(pos + 1, &dest->deref_ident_);
567 if (!dest->deref_ident_)
568 return -pos;
569 }
570 } else {
571 dest->deref_offset_ = 0;
572 pos = parse_identifier(pos, &dest->deref_ident_);
573 if (arg_[pos] == '+' || arg_[pos] == '-') {
574 pos = parse_number(pos, &dest->deref_offset_);
575 }
576 }
577
578 if (arg_[pos] != '(')
579 return -pos;
580
581 pos = parse_base_register(pos + 1, dest);
582 if (pos < 0)
583 return pos;
584
585 if (arg_[pos] == ',') {
586 pos = parse_index_register(pos + 1, dest);
587 if (pos < 0)
588 return pos;
589
590 if (arg_[pos] == ',') {
591 pos = parse_scale(pos + 1, dest);
592 if (pos < 0)
593 return pos;
594 }
595 }
596
597 return (arg_[pos] == ')') ? pos + 1 : -pos;
598 }
599
parse_1(ssize_t pos,Argument * dest)600 ssize_t ArgumentParser_x64::parse_1(ssize_t pos, Argument *dest) {
601 if (isdigit(arg_[pos]) || arg_[pos] == '-') {
602 optional<int> asize;
603 ssize_t m = parse_number(pos, &asize);
604 if (arg_[m] == '@' && asize) {
605 dest->arg_size_ = asize;
606 return parse_expr(m + 1, dest);
607 }
608 }
609 return parse_expr(pos, dest);
610 }
611
parse(Argument * dest)612 bool ArgumentParser_x64::parse(Argument *dest) {
613 if (done())
614 return false;
615
616 ssize_t res = parse_1(cur_pos_, dest);
617 if (res < 0)
618 return error_return(-res, -res + 1);
619 if (!isspace(arg_[res]) && arg_[res] != '\0')
620 return error_return(res, res);
621 skip_whitespace_from(res);
622 return true;
623 }
624
625 const std::unordered_map<std::string, ArgumentParser_x64::RegInfo>
626 ArgumentParser_x64::registers_ = {
627 {"rax", {X64_REG_A, 8}}, {"eax", {X64_REG_A, 4}},
628 {"ax", {X64_REG_A, 2}}, {"al", {X64_REG_A, 1}},
629
630 {"rbx", {X64_REG_B, 8}}, {"ebx", {X64_REG_B, 4}},
631 {"bx", {X64_REG_B, 2}}, {"bl", {X64_REG_B, 1}},
632
633 {"rcx", {X64_REG_C, 8}}, {"ecx", {X64_REG_C, 4}},
634 {"cx", {X64_REG_C, 2}}, {"cl", {X64_REG_C, 1}},
635
636 {"rdx", {X64_REG_D, 8}}, {"edx", {X64_REG_D, 4}},
637 {"dx", {X64_REG_D, 2}}, {"dl", {X64_REG_D, 1}},
638
639 {"rsi", {X64_REG_SI, 8}}, {"esi", {X64_REG_SI, 4}},
640 {"si", {X64_REG_SI, 2}}, {"sil", {X64_REG_SI, 1}},
641
642 {"rdi", {X64_REG_DI, 8}}, {"edi", {X64_REG_DI, 4}},
643 {"di", {X64_REG_DI, 2}}, {"dil", {X64_REG_DI, 1}},
644
645 {"rbp", {X64_REG_BP, 8}}, {"ebp", {X64_REG_BP, 4}},
646 {"bp", {X64_REG_BP, 2}}, {"bpl", {X64_REG_BP, 1}},
647
648 {"rsp", {X64_REG_SP, 8}}, {"esp", {X64_REG_SP, 4}},
649 {"sp", {X64_REG_SP, 2}}, {"spl", {X64_REG_SP, 1}},
650
651 {"r8", {X64_REG_8, 8}}, {"r8d", {X64_REG_8, 4}},
652 {"r8w", {X64_REG_8, 2}}, {"r8b", {X64_REG_8, 1}},
653
654 {"r9", {X64_REG_9, 8}}, {"r9d", {X64_REG_9, 4}},
655 {"r9w", {X64_REG_9, 2}}, {"r9b", {X64_REG_9, 1}},
656
657 {"r10", {X64_REG_10, 8}}, {"r10d", {X64_REG_10, 4}},
658 {"r10w", {X64_REG_10, 2}}, {"r10b", {X64_REG_10, 1}},
659
660 {"r11", {X64_REG_11, 8}}, {"r11d", {X64_REG_11, 4}},
661 {"r11w", {X64_REG_11, 2}}, {"r11b", {X64_REG_11, 1}},
662
663 {"r12", {X64_REG_12, 8}}, {"r12d", {X64_REG_12, 4}},
664 {"r12w", {X64_REG_12, 2}}, {"r12b", {X64_REG_12, 1}},
665
666 {"r13", {X64_REG_13, 8}}, {"r13d", {X64_REG_13, 4}},
667 {"r13w", {X64_REG_13, 2}}, {"r13b", {X64_REG_13, 1}},
668
669 {"r14", {X64_REG_14, 8}}, {"r14d", {X64_REG_14, 4}},
670 {"r14w", {X64_REG_14, 2}}, {"r14b", {X64_REG_14, 1}},
671
672 {"r15", {X64_REG_15, 8}}, {"r15d", {X64_REG_15, 4}},
673 {"r15w", {X64_REG_15, 2}}, {"r15b", {X64_REG_15, 1}},
674
675 {"rip", {X64_REG_RIP, 8}},
676
677 {"xmm0", {X64_REG_XMM0, 16}},
678 {"xmm1", {X64_REG_XMM1, 16}},
679 {"xmm2", {X64_REG_XMM2, 16}},
680 {"xmm3", {X64_REG_XMM3, 16}},
681 {"xmm4", {X64_REG_XMM4, 16}},
682 {"xmm5", {X64_REG_XMM5, 16}},
683 {"xmm6", {X64_REG_XMM6, 16}},
684 {"xmm7", {X64_REG_XMM7, 16}},
685 {"xmm8", {X64_REG_XMM8, 16}},
686 {"xmm9", {X64_REG_XMM9, 16}},
687 {"xmm10", {X64_REG_XMM10, 16}},
688 {"xmm11", {X64_REG_XMM11, 16}},
689 {"xmm12", {X64_REG_XMM12, 16}},
690 {"xmm13", {X64_REG_XMM13, 16}},
691 {"xmm14", {X64_REG_XMM14, 16}},
692 {"xmm15", {X64_REG_XMM15, 16}},
693 };
694
reg_to_name(std::string * norm,Register reg)695 void ArgumentParser_x64::reg_to_name(std::string *norm, Register reg) {
696 switch (reg) {
697 case X64_REG_A:
698 *norm = "ax";
699 break;
700 case X64_REG_B:
701 *norm = "bx";
702 break;
703 case X64_REG_C:
704 *norm = "cx";
705 break;
706 case X64_REG_D:
707 *norm = "dx";
708 break;
709
710 case X64_REG_SI:
711 *norm = "si";
712 break;
713 case X64_REG_DI:
714 *norm = "di";
715 break;
716 case X64_REG_BP:
717 *norm = "bp";
718 break;
719 case X64_REG_SP:
720 *norm = "sp";
721 break;
722
723 case X64_REG_8:
724 *norm = "r8";
725 break;
726 case X64_REG_9:
727 *norm = "r9";
728 break;
729 case X64_REG_10:
730 *norm = "r10";
731 break;
732 case X64_REG_11:
733 *norm = "r11";
734 break;
735 case X64_REG_12:
736 *norm = "r12";
737 break;
738 case X64_REG_13:
739 *norm = "r13";
740 break;
741 case X64_REG_14:
742 *norm = "r14";
743 break;
744 case X64_REG_15:
745 *norm = "r15";
746 break;
747
748 case X64_REG_RIP:
749 *norm = "ip";
750 break;
751
752 case X64_REG_XMM0:
753 *norm = "xmm0";
754 break;
755 case X64_REG_XMM1:
756 *norm = "xmm1";
757 break;
758 case X64_REG_XMM2:
759 *norm = "xmm2";
760 break;
761 case X64_REG_XMM3:
762 *norm = "xmm3";
763 break;
764 case X64_REG_XMM4:
765 *norm = "xmm4";
766 break;
767 case X64_REG_XMM5:
768 *norm = "xmm5";
769 break;
770 case X64_REG_XMM6:
771 *norm = "xmm6";
772 break;
773 case X64_REG_XMM7:
774 *norm = "xmm7";
775 break;
776 case X64_REG_XMM8:
777 *norm = "xmm8";
778 break;
779 case X64_REG_XMM9:
780 *norm = "xmm9";
781 break;
782 case X64_REG_XMM10:
783 *norm = "xmm10";
784 break;
785 case X64_REG_XMM11:
786 *norm = "xmm11";
787 break;
788 case X64_REG_XMM12:
789 *norm = "xmm12";
790 break;
791 case X64_REG_XMM13:
792 *norm = "xmm13";
793 break;
794 case X64_REG_XMM14:
795 *norm = "xmm14";
796 break;
797 case X64_REG_XMM15:
798 *norm = "xmm15";
799 break;
800
801 }
802 }
803
normalize_register(std::string * reg,int * reg_size)804 bool ArgumentParser_x64::normalize_register(std::string *reg, int *reg_size) {
805 auto it = registers_.find(*reg);
806 if (it == registers_.end())
807 return false;
808
809 *reg_size = it->second.size;
810 reg_to_name(reg, it->second.reg);
811 return true;
812 }
813 }
814