| /* |
| * Copyright (c) 2016 GitHub, Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| #include <cmath> |
| #include <unordered_map> |
| #include <regex> |
| |
| #include "syms.h" |
| #include "usdt.h" |
| #include "vendor/tinyformat.hpp" |
| |
| #include "bcc_elf.h" |
| #include "bcc_syms.h" |
| |
| namespace USDT { |
| |
| Argument::Argument() {} |
| Argument::~Argument() {} |
| |
| std::string Argument::ctype() const { |
| const int s = arg_size() * 8; |
| return (s < 0) ? tfm::format("int%d_t", -s) : tfm::format("uint%d_t", s); |
| } |
| |
| static const char *type_names[][4] = { |
| { "int8_t", "int16_t", "int32_t", "int64_t" }, |
| { "uint8_t", "uint16_t", "uint32_t", "uint64_t" }, |
| }; |
| |
| const char *Argument::ctype_name() const { |
| const int s = arg_size(); |
| const int r = log2(abs(s)); |
| return s < 0 ? type_names[0][r] : type_names[1][r]; |
| } |
| |
| bool Argument::get_global_address(uint64_t *address, const std::string &binpath, |
| const optional<int> &pid) const { |
| if (pid) { |
| static struct bcc_symbol_option default_option = { |
| .use_debug_file = 1, |
| .check_debug_file_crc = 1, |
| .lazy_symbolize = 1, |
| .use_symbol_type = BCC_SYM_ALL_TYPES |
| }; |
| return ProcSyms(*pid, &default_option) |
| .resolve_name(binpath.c_str(), deref_ident_->c_str(), address); |
| } |
| |
| if (!bcc_elf_is_shared_obj(binpath.c_str())) { |
| struct bcc_symbol sym; |
| if (bcc_resolve_symname(binpath.c_str(), deref_ident_->c_str(), 0x0, -1, nullptr, &sym) == 0) { |
| *address = sym.offset; |
| if (sym.module) |
| ::free(const_cast<char*>(sym.module)); |
| return true; |
| } |
| } |
| |
| return false; |
| } |
| |
| bool Argument::assign_to_local(std::ostream &stream, |
| const std::string &local_name, |
| const std::string &binpath, |
| const optional<int> &pid) const { |
| if (constant_) { |
| tfm::format(stream, "%s = %lld;", local_name, *constant_); |
| return true; |
| } |
| |
| if (!deref_offset_) { |
| if(base_register_name_->substr(0,3) == "xmm") { |
| // TODO: When we can read xmm registers from BPF, update this to read |
| // the actual value |
| tfm::format(stream, "%s = 0;", local_name); |
| } else { |
| tfm::format(stream, "%s = ctx->%s;", local_name, *base_register_name_); |
| } |
| // Put a compiler barrier to prevent optimization |
| // like llvm SimplifyCFG SinkThenElseCodeToEnd |
| // Volatile marking is not sufficient to prevent such optimization. |
| tfm::format(stream, " %s", COMPILER_BARRIER); |
| return true; |
| } |
| |
| if (deref_offset_ && !deref_ident_) { |
| tfm::format(stream, "{ u64 __addr = ctx->%s + %d", |
| *base_register_name_, *deref_offset_); |
| if (index_register_name_) { |
| int scale = scale_.value_or(1); |
| tfm::format(stream, " + (ctx->%s * %d);", *index_register_name_, scale); |
| } else { |
| tfm::format(stream, ";"); |
| } |
| // Theoretically, llvm SimplifyCFG SinkThenElseCodeToEnd may still |
| // sink bpf_probe_read call, so put a barrier here to prevent sinking |
| // of ctx->#fields. |
| tfm::format(stream, " %s ", COMPILER_BARRIER); |
| tfm::format(stream, |
| "%s __res = 0x0; " |
| "bpf_probe_read_user(&__res, sizeof(__res), (void *)__addr); " |
| "%s = __res; }", |
| ctype(), local_name); |
| return true; |
| } |
| |
| if (deref_offset_ && deref_ident_ && *base_register_name_ == "ip") { |
| uint64_t global_address; |
| if (!get_global_address(&global_address, binpath, pid)) |
| return false; |
| |
| tfm::format(stream, |
| "{ u64 __addr = 0x%xull + %d; %s __res = 0x0; " |
| "bpf_probe_read_user(&__res, sizeof(__res), (void *)__addr); " |
| "%s = __res; }", |
| global_address, *deref_offset_, ctype(), local_name); |
| return true; |
| } |
| |
| return false; |
| } |
| |
| void ArgumentParser::print_error(ssize_t pos) { |
| fprintf(stderr, "Parse error:\n %s\n", arg_); |
| for (ssize_t i = 0; i < pos + 4; ++i) fputc('-', stderr); |
| fputc('^', stderr); |
| fputc('\n', stderr); |
| } |
| |
| void ArgumentParser::skip_whitespace_from(size_t pos) { |
| while (isspace(arg_[pos])) pos++; |
| cur_pos_ = pos; |
| } |
| |
| void ArgumentParser::skip_until_whitespace_from(size_t pos) { |
| while (arg_[pos] != '\0' && !isspace(arg_[pos])) |
| pos++; |
| cur_pos_ = pos; |
| } |
| |
| bool ArgumentParser_aarch64::parse_register(ssize_t pos, ssize_t &new_pos, |
| std::string ®_name) { |
| if (arg_[pos] == 'x') { |
| optional<int> reg_num; |
| new_pos = parse_number(pos + 1, ®_num); |
| if (new_pos == pos + 1 || *reg_num < 0 || *reg_num > 31) |
| return error_return(pos + 1, pos + 1); |
| |
| if (*reg_num == 31) { |
| reg_name = "sp"; |
| } else { |
| reg_name = "regs[" + std::to_string(reg_num.value()) + "]"; |
| } |
| |
| return true; |
| } else if (arg_[pos] == 's' && arg_[pos + 1] == 'p') { |
| reg_name = "sp"; |
| new_pos = pos + 2; |
| return true; |
| } else { |
| return error_return(pos, pos); |
| } |
| } |
| |
| bool ArgumentParser_aarch64::parse_size(ssize_t pos, ssize_t &new_pos, |
| optional<int> *arg_size) { |
| int abs_arg_size; |
| |
| new_pos = parse_number(pos, arg_size); |
| if (new_pos == pos) |
| return error_return(pos, pos); |
| |
| abs_arg_size = abs(arg_size->value()); |
| if (abs_arg_size != 1 && abs_arg_size != 2 && abs_arg_size != 4 && |
| abs_arg_size != 8) |
| return error_return(pos, pos); |
| return true; |
| } |
| |
| bool ArgumentParser_aarch64::parse_mem(ssize_t pos, ssize_t &new_pos, |
| Argument *dest) { |
| std::string base_reg_name, index_reg_name; |
| |
| if (parse_register(pos, new_pos, base_reg_name) == false) |
| return false; |
| dest->base_register_name_ = base_reg_name; |
| |
| if (arg_[new_pos] == ',') { |
| pos = new_pos + 1; |
| new_pos = parse_number(pos, &dest->deref_offset_); |
| if (new_pos == pos) { |
| // offset isn't a number, so it should be a reg, |
| // which looks like: -1@[x0, x1], rather than -1@[x0, 24] |
| skip_whitespace_from(pos); |
| pos = cur_pos_; |
| if (parse_register(pos, new_pos, index_reg_name) == false) |
| return error_return(pos, pos); |
| dest->index_register_name_ = index_reg_name; |
| dest->scale_ = 1; |
| dest->deref_offset_ = 0; |
| } |
| } |
| if (arg_[new_pos] != ']') |
| return error_return(new_pos, new_pos); |
| new_pos++; |
| return true; |
| } |
| |
| bool ArgumentParser_aarch64::parse(Argument *dest) { |
| if (done()) |
| return false; |
| |
| // Support the following argument patterns: |
| // [-]<size>@<value>, [-]<size>@<reg>, [-]<size>@[<reg>], or |
| // [-]<size>@[<reg>,<offset>] |
| // [-]<size>@[<reg>,<index_reg>] |
| ssize_t cur_pos = cur_pos_, new_pos; |
| optional<int> arg_size; |
| |
| // Parse [-]<size> |
| if (parse_size(cur_pos, new_pos, &arg_size) == false) |
| return false; |
| dest->arg_size_ = arg_size; |
| |
| // Make sure '@' present |
| if (arg_[new_pos] != '@') |
| return error_return(new_pos, new_pos); |
| cur_pos = new_pos + 1; |
| |
| if (arg_[cur_pos] == 'x' || arg_[cur_pos] == 's') { |
| // Parse ...@<reg> |
| std::string reg_name; |
| if (parse_register(cur_pos, new_pos, reg_name) == false) |
| return false; |
| |
| cur_pos_ = new_pos; |
| dest->base_register_name_ = reg_name; |
| } else if (arg_[cur_pos] == '[') { |
| // Parse ...@[<reg>], ...@[<reg,<offset>] and ...@[<reg>,<index_reg>] |
| if (parse_mem(cur_pos + 1, new_pos, dest) == false) |
| return false; |
| cur_pos_ = new_pos; |
| } else { |
| // Parse ...@<value> |
| optional<long long> val; |
| new_pos = parse_number(cur_pos, &val); |
| if (cur_pos == new_pos) |
| return error_return(cur_pos, cur_pos); |
| cur_pos_ = new_pos; |
| dest->constant_ = val; |
| } |
| |
| skip_whitespace_from(cur_pos_); |
| return true; |
| } |
| |
| bool ArgumentParser_loongarch64::parse_register(ssize_t pos, ssize_t &new_pos, |
| std::string ®_name) { |
| if (arg_[pos] == '$' && arg_[pos + 1] == 'r') { |
| optional<int> reg_num; |
| new_pos = parse_number(pos + 2, ®_num); |
| if (new_pos == pos + 2 || *reg_num < 0 || *reg_num > 31) |
| return error_return(pos + 2, pos + 2); |
| |
| if (*reg_num == 3) { |
| reg_name = "sp"; |
| } else { |
| reg_name = "regs[" + std::to_string(reg_num.value()) + "]"; |
| } |
| return true; |
| } else if (arg_[pos] == 's' && arg_[pos + 1] == 'p') { |
| reg_name = "sp"; |
| new_pos = pos + 2; |
| return true; |
| } else { |
| return error_return(pos, pos); |
| } |
| } |
| |
| bool ArgumentParser_loongarch64::parse_size(ssize_t pos, ssize_t &new_pos, |
| optional<int> *arg_size) { |
| int abs_arg_size; |
| |
| new_pos = parse_number(pos, arg_size); |
| if (new_pos == pos) |
| return error_return(pos, pos); |
| |
| abs_arg_size = abs(arg_size->value()); |
| if (abs_arg_size != 1 && abs_arg_size != 2 && abs_arg_size != 4 && |
| abs_arg_size != 8) |
| return error_return(pos, pos); |
| return true; |
| } |
| |
| bool ArgumentParser_loongarch64::parse_mem(ssize_t pos, ssize_t &new_pos, |
| Argument *dest) { |
| std::string base_reg_name, index_reg_name; |
| |
| if (parse_register(pos, new_pos, base_reg_name) == false) |
| return false; |
| dest->base_register_name_ = base_reg_name; |
| |
| if (arg_[new_pos] == ',') { |
| pos = new_pos + 1; |
| new_pos = parse_number(pos, &dest->deref_offset_); |
| if (new_pos == pos) { |
| // offset isn't a number, so it should be a reg, |
| // which looks like: -1@[$r0, $r1], rather than -1@[$r0, 24] |
| skip_whitespace_from(pos); |
| pos = cur_pos_; |
| if (parse_register(pos, new_pos, index_reg_name) == false) |
| return error_return(pos, pos); |
| dest->index_register_name_ = index_reg_name; |
| dest->scale_ = 1; |
| dest->deref_offset_ = 0; |
| } |
| } |
| if (arg_[new_pos] != ']') |
| return error_return(new_pos, new_pos); |
| new_pos++; |
| return true; |
| } |
| |
| bool ArgumentParser_loongarch64::parse(Argument *dest) { |
| if (done()) |
| return false; |
| |
| // Support the following argument patterns: |
| // [-]<size>@<value>, [-]<size>@<reg>, [-]<size>@[<reg>], or |
| // [-]<size>@[<reg>,<offset>] |
| // [-]<size>@[<reg>,<index_reg>] |
| ssize_t cur_pos = cur_pos_, new_pos; |
| optional<int> arg_size; |
| |
| // Parse [-]<size> |
| if (parse_size(cur_pos, new_pos, &arg_size) == false) |
| return false; |
| dest->arg_size_ = arg_size; |
| |
| // Make sure '@' present |
| if (arg_[new_pos] != '@') |
| return error_return(new_pos, new_pos); |
| cur_pos = new_pos + 1; |
| |
| if (arg_[cur_pos] == '$' || arg_[cur_pos] == 's') { |
| // Parse ...@<reg> |
| std::string reg_name; |
| if (parse_register(cur_pos, new_pos, reg_name) == false) |
| return false; |
| |
| cur_pos_ = new_pos; |
| dest->base_register_name_ = reg_name; |
| } else if (arg_[cur_pos] == '[') { |
| // Parse ...@[<reg>], ...@[<reg,<offset>] and ...@[<reg>,<index_reg>] |
| if (parse_mem(cur_pos + 1, new_pos, dest) == false) |
| return false; |
| cur_pos_ = new_pos; |
| } else { |
| // Parse ...@<value> |
| optional<long long> val; |
| new_pos = parse_number(cur_pos, &val); |
| if (cur_pos == new_pos) |
| return error_return(cur_pos, cur_pos); |
| cur_pos_ = new_pos; |
| dest->constant_ = val; |
| } |
| |
| skip_whitespace_from(cur_pos_); |
| return true; |
| } |
| |
| bool ArgumentParser_powerpc64::parse(Argument *dest) { |
| if (done()) |
| return false; |
| |
| bool matched; |
| std::smatch matches; |
| std::string arg_str(&arg_[cur_pos_]); |
| std::regex arg_n_regex("^(\\-?[1248])\\@"); |
| // Operands with constants of form iNUM or i-NUM |
| std::regex arg_op_regex_const("^i(\\-?[0-9]+)( +|$)"); |
| // Operands with register only of form REG or %rREG |
| std::regex arg_op_regex_reg("^(?:%r)?([1-2]?[0-9]|3[0-1])( +|$)"); |
| // Operands with a base register and an offset of form |
| // NUM(REG) or -NUM(REG) or NUM(%rREG) or -NUM(%rREG) |
| std::regex arg_op_regex_breg_off( |
| "^(\\-?[0-9]+)\\((?:%r)?([1-2]?[0-9]|3[0-1])\\)( +|$)"); |
| // Operands with a base register and an index register |
| // of form REG,REG or %rREG,%rREG |
| std::regex arg_op_regex_breg_ireg( |
| "^(?:%r)?([1-2]?[0-9]|3[0-1])\\,(?:%r)?([1-2]?[0-9]|3[0-1])( +|$)"); |
| |
| matched = std::regex_search(arg_str, matches, arg_n_regex); |
| if (matched) { |
| dest->arg_size_ = stoi(matches.str(1)); |
| cur_pos_ += matches.length(0); |
| arg_str = &arg_[cur_pos_]; |
| |
| if (std::regex_search(arg_str, matches, arg_op_regex_const)) { |
| dest->constant_ = (long long)stoull(matches.str(1)); |
| } else if (std::regex_search(arg_str, matches, arg_op_regex_reg)) { |
| dest->base_register_name_ = "gpr[" + matches.str(1) + "]"; |
| } else if (std::regex_search(arg_str, matches, arg_op_regex_breg_off)) { |
| dest->deref_offset_ = stoi(matches.str(1)); |
| dest->base_register_name_ = "gpr[" + matches.str(2) + "]"; |
| } else if (std::regex_search(arg_str, matches, arg_op_regex_breg_ireg)) { |
| dest->deref_offset_ = 0; // In powerpc64, such operands contain a base |
| // register and an index register which are |
| // part of an indexed load/store operation. |
| // Even if no offset value is present, this |
| // is required by Argument::assign_to_local() |
| // in order to generate code for reading the |
| // argument. So, this is set to zero. |
| dest->base_register_name_ = "gpr[" + matches.str(1) + "]"; |
| dest->index_register_name_ = "gpr[" + matches.str(2) + "]"; |
| dest->scale_ = abs(*dest->arg_size_); |
| } else { |
| matched = false; |
| } |
| } |
| |
| if (!matched) { |
| print_error(cur_pos_); |
| skip_until_whitespace_from(cur_pos_); |
| skip_whitespace_from(cur_pos_); |
| return false; |
| } |
| |
| cur_pos_ += matches.length(0); |
| skip_whitespace_from(cur_pos_); |
| return true; |
| } |
| |
| bool ArgumentParser_s390x::parse(Argument *dest) { |
| if (done()) |
| return false; |
| |
| bool matched; |
| std::cmatch matches; |
| #define S390X_IMM "(-?[0-9]+)" |
| std::regex arg_n_regex("^" S390X_IMM "@"); |
| // <imm> |
| std::regex arg_op_regex_imm("^" S390X_IMM "(?: +|$)"); |
| // %r<N> |
| #define S390X_REG "%r([0-9]|1[0-5])" |
| std::regex arg_op_regex_reg("^" S390X_REG "(?: +|$)"); |
| // <disp>(%r<N>,%r<N>) |
| std::regex arg_op_regex_mem("^" S390X_IMM "?\\(" S390X_REG |
| "(?:," S390X_REG ")?\\)(?: +|$)"); |
| #undef S390X_IMM |
| #undef S390X_REG |
| |
| matched = std::regex_search(arg_ + cur_pos_, matches, arg_n_regex); |
| if (matched) { |
| dest->arg_size_ = stoi(matches.str(1)); |
| cur_pos_ += matches.length(0); |
| |
| if (std::regex_search(arg_ + cur_pos_, matches, arg_op_regex_imm)) { |
| dest->constant_ = (long long)stoull(matches.str(1)); |
| } else if (std::regex_search(arg_ + cur_pos_, matches, arg_op_regex_reg)) { |
| dest->base_register_name_ = "gprs[" + matches.str(1) + "]"; |
| } else if (std::regex_search(arg_ + cur_pos_, matches, arg_op_regex_mem)) { |
| if (matches.length(1) > 0) { |
| dest->deref_offset_ = stoi(matches.str(1)); |
| } |
| dest->base_register_name_ = "gprs[" + matches.str(2) + "]"; |
| if (matches.length(3) > 0) { |
| dest->index_register_name_ = "gprs[" + matches.str(3) + "]"; |
| } |
| } else { |
| matched = false; |
| } |
| } |
| |
| if (!matched) { |
| print_error(cur_pos_); |
| skip_until_whitespace_from(cur_pos_); |
| skip_whitespace_from(cur_pos_); |
| return false; |
| } |
| |
| cur_pos_ += matches.length(0); |
| skip_whitespace_from(cur_pos_); |
| return true; |
| } |
| |
| ssize_t ArgumentParser_x64::parse_identifier(ssize_t pos, |
| optional<std::string> *result) { |
| if (isalpha(arg_[pos]) || arg_[pos] == '_') { |
| ssize_t start = pos++; |
| while (isalnum(arg_[pos]) || arg_[pos] == '_') pos++; |
| if (pos - start) |
| result->emplace(arg_ + start, pos - start); |
| } |
| return pos; |
| } |
| |
| ssize_t ArgumentParser_x64::parse_register(ssize_t pos, std::string &name, |
| int &size) { |
| ssize_t start = ++pos; |
| if (arg_[start - 1] != '%') |
| return -start; |
| |
| while (isalnum(arg_[pos])) pos++; |
| |
| std::string regname(arg_ + start, pos - start); |
| if (!normalize_register(®name, &size)) |
| return -start; |
| |
| name = regname; |
| return pos; |
| } |
| |
| ssize_t ArgumentParser_x64::parse_base_register(ssize_t pos, Argument *dest) { |
| int size; |
| std::string name; |
| ssize_t res = parse_register(pos, name, size); |
| if (res < 0) |
| return res; |
| |
| dest->base_register_name_ = name; |
| if (!dest->arg_size_) |
| dest->arg_size_ = size; |
| |
| return res; |
| } |
| |
| ssize_t ArgumentParser_x64::parse_index_register(ssize_t pos, Argument *dest) { |
| int size; |
| std::string name; |
| ssize_t res = parse_register(pos, name, size); |
| if (res < 0) |
| return res; |
| |
| dest->index_register_name_ = name; |
| |
| return res; |
| } |
| |
| ssize_t ArgumentParser_x64::parse_scale(ssize_t pos, Argument *dest) { |
| return parse_number(pos, &dest->scale_); |
| } |
| |
| ssize_t ArgumentParser_x64::parse_expr(ssize_t pos, Argument *dest) { |
| if (arg_[pos] == '$') |
| return parse_number(pos + 1, &dest->constant_); |
| |
| if (arg_[pos] == '%') |
| return parse_base_register(pos, dest); |
| |
| if (isdigit(arg_[pos]) || arg_[pos] == '-') { |
| pos = parse_number(pos, &dest->deref_offset_); |
| if (arg_[pos] == '+') { |
| pos = parse_identifier(pos + 1, &dest->deref_ident_); |
| if (!dest->deref_ident_) |
| return -pos; |
| } |
| } else { |
| dest->deref_offset_ = 0; |
| pos = parse_identifier(pos, &dest->deref_ident_); |
| if (arg_[pos] == '+' || arg_[pos] == '-') { |
| pos = parse_number(pos, &dest->deref_offset_); |
| } |
| } |
| |
| if (arg_[pos] != '(') |
| return -pos; |
| |
| pos = parse_base_register(pos + 1, dest); |
| if (pos < 0) |
| return pos; |
| |
| if (arg_[pos] == ',') { |
| pos = parse_index_register(pos + 1, dest); |
| if (pos < 0) |
| return pos; |
| |
| if (arg_[pos] == ',') { |
| pos = parse_scale(pos + 1, dest); |
| if (pos < 0) |
| return pos; |
| } |
| } |
| |
| return (arg_[pos] == ')') ? pos + 1 : -pos; |
| } |
| |
| ssize_t ArgumentParser_x64::parse_1(ssize_t pos, Argument *dest) { |
| if (isdigit(arg_[pos]) || arg_[pos] == '-') { |
| optional<int> asize; |
| ssize_t m = parse_number(pos, &asize); |
| if (arg_[m] == '@' && asize) { |
| dest->arg_size_ = asize; |
| return parse_expr(m + 1, dest); |
| } |
| } |
| return parse_expr(pos, dest); |
| } |
| |
| bool ArgumentParser_x64::parse(Argument *dest) { |
| if (done()) |
| return false; |
| |
| ssize_t res = parse_1(cur_pos_, dest); |
| if (res < 0) |
| return error_return(-res, -res + 1); |
| if (!isspace(arg_[res]) && arg_[res] != '\0') |
| return error_return(res, res); |
| skip_whitespace_from(res); |
| return true; |
| } |
| |
| const std::unordered_map<std::string, ArgumentParser_x64::RegInfo> |
| ArgumentParser_x64::registers_ = { |
| {"rax", {X64_REG_A, 8}}, {"eax", {X64_REG_A, 4}}, |
| {"ax", {X64_REG_A, 2}}, {"al", {X64_REG_A, 1}}, |
| |
| {"rbx", {X64_REG_B, 8}}, {"ebx", {X64_REG_B, 4}}, |
| {"bx", {X64_REG_B, 2}}, {"bl", {X64_REG_B, 1}}, |
| |
| {"rcx", {X64_REG_C, 8}}, {"ecx", {X64_REG_C, 4}}, |
| {"cx", {X64_REG_C, 2}}, {"cl", {X64_REG_C, 1}}, |
| |
| {"rdx", {X64_REG_D, 8}}, {"edx", {X64_REG_D, 4}}, |
| {"dx", {X64_REG_D, 2}}, {"dl", {X64_REG_D, 1}}, |
| |
| {"rsi", {X64_REG_SI, 8}}, {"esi", {X64_REG_SI, 4}}, |
| {"si", {X64_REG_SI, 2}}, {"sil", {X64_REG_SI, 1}}, |
| |
| {"rdi", {X64_REG_DI, 8}}, {"edi", {X64_REG_DI, 4}}, |
| {"di", {X64_REG_DI, 2}}, {"dil", {X64_REG_DI, 1}}, |
| |
| {"rbp", {X64_REG_BP, 8}}, {"ebp", {X64_REG_BP, 4}}, |
| {"bp", {X64_REG_BP, 2}}, {"bpl", {X64_REG_BP, 1}}, |
| |
| {"rsp", {X64_REG_SP, 8}}, {"esp", {X64_REG_SP, 4}}, |
| {"sp", {X64_REG_SP, 2}}, {"spl", {X64_REG_SP, 1}}, |
| |
| {"r8", {X64_REG_8, 8}}, {"r8d", {X64_REG_8, 4}}, |
| {"r8w", {X64_REG_8, 2}}, {"r8b", {X64_REG_8, 1}}, |
| |
| {"r9", {X64_REG_9, 8}}, {"r9d", {X64_REG_9, 4}}, |
| {"r9w", {X64_REG_9, 2}}, {"r9b", {X64_REG_9, 1}}, |
| |
| {"r10", {X64_REG_10, 8}}, {"r10d", {X64_REG_10, 4}}, |
| {"r10w", {X64_REG_10, 2}}, {"r10b", {X64_REG_10, 1}}, |
| |
| {"r11", {X64_REG_11, 8}}, {"r11d", {X64_REG_11, 4}}, |
| {"r11w", {X64_REG_11, 2}}, {"r11b", {X64_REG_11, 1}}, |
| |
| {"r12", {X64_REG_12, 8}}, {"r12d", {X64_REG_12, 4}}, |
| {"r12w", {X64_REG_12, 2}}, {"r12b", {X64_REG_12, 1}}, |
| |
| {"r13", {X64_REG_13, 8}}, {"r13d", {X64_REG_13, 4}}, |
| {"r13w", {X64_REG_13, 2}}, {"r13b", {X64_REG_13, 1}}, |
| |
| {"r14", {X64_REG_14, 8}}, {"r14d", {X64_REG_14, 4}}, |
| {"r14w", {X64_REG_14, 2}}, {"r14b", {X64_REG_14, 1}}, |
| |
| {"r15", {X64_REG_15, 8}}, {"r15d", {X64_REG_15, 4}}, |
| {"r15w", {X64_REG_15, 2}}, {"r15b", {X64_REG_15, 1}}, |
| |
| {"rip", {X64_REG_RIP, 8}}, |
| |
| {"xmm0", {X64_REG_XMM0, 16}}, |
| {"xmm1", {X64_REG_XMM1, 16}}, |
| {"xmm2", {X64_REG_XMM2, 16}}, |
| {"xmm3", {X64_REG_XMM3, 16}}, |
| {"xmm4", {X64_REG_XMM4, 16}}, |
| {"xmm5", {X64_REG_XMM5, 16}}, |
| {"xmm6", {X64_REG_XMM6, 16}}, |
| {"xmm7", {X64_REG_XMM7, 16}}, |
| {"xmm8", {X64_REG_XMM8, 16}}, |
| {"xmm9", {X64_REG_XMM9, 16}}, |
| {"xmm10", {X64_REG_XMM10, 16}}, |
| {"xmm11", {X64_REG_XMM11, 16}}, |
| {"xmm12", {X64_REG_XMM12, 16}}, |
| {"xmm13", {X64_REG_XMM13, 16}}, |
| {"xmm14", {X64_REG_XMM14, 16}}, |
| {"xmm15", {X64_REG_XMM15, 16}}, |
| }; |
| |
| void ArgumentParser_x64::reg_to_name(std::string *norm, Register reg) { |
| switch (reg) { |
| case X64_REG_A: |
| *norm = "ax"; |
| break; |
| case X64_REG_B: |
| *norm = "bx"; |
| break; |
| case X64_REG_C: |
| *norm = "cx"; |
| break; |
| case X64_REG_D: |
| *norm = "dx"; |
| break; |
| |
| case X64_REG_SI: |
| *norm = "si"; |
| break; |
| case X64_REG_DI: |
| *norm = "di"; |
| break; |
| case X64_REG_BP: |
| *norm = "bp"; |
| break; |
| case X64_REG_SP: |
| *norm = "sp"; |
| break; |
| |
| case X64_REG_8: |
| *norm = "r8"; |
| break; |
| case X64_REG_9: |
| *norm = "r9"; |
| break; |
| case X64_REG_10: |
| *norm = "r10"; |
| break; |
| case X64_REG_11: |
| *norm = "r11"; |
| break; |
| case X64_REG_12: |
| *norm = "r12"; |
| break; |
| case X64_REG_13: |
| *norm = "r13"; |
| break; |
| case X64_REG_14: |
| *norm = "r14"; |
| break; |
| case X64_REG_15: |
| *norm = "r15"; |
| break; |
| |
| case X64_REG_RIP: |
| *norm = "ip"; |
| break; |
| |
| case X64_REG_XMM0: |
| *norm = "xmm0"; |
| break; |
| case X64_REG_XMM1: |
| *norm = "xmm1"; |
| break; |
| case X64_REG_XMM2: |
| *norm = "xmm2"; |
| break; |
| case X64_REG_XMM3: |
| *norm = "xmm3"; |
| break; |
| case X64_REG_XMM4: |
| *norm = "xmm4"; |
| break; |
| case X64_REG_XMM5: |
| *norm = "xmm5"; |
| break; |
| case X64_REG_XMM6: |
| *norm = "xmm6"; |
| break; |
| case X64_REG_XMM7: |
| *norm = "xmm7"; |
| break; |
| case X64_REG_XMM8: |
| *norm = "xmm8"; |
| break; |
| case X64_REG_XMM9: |
| *norm = "xmm9"; |
| break; |
| case X64_REG_XMM10: |
| *norm = "xmm10"; |
| break; |
| case X64_REG_XMM11: |
| *norm = "xmm11"; |
| break; |
| case X64_REG_XMM12: |
| *norm = "xmm12"; |
| break; |
| case X64_REG_XMM13: |
| *norm = "xmm13"; |
| break; |
| case X64_REG_XMM14: |
| *norm = "xmm14"; |
| break; |
| case X64_REG_XMM15: |
| *norm = "xmm15"; |
| break; |
| |
| } |
| } |
| |
| bool ArgumentParser_x64::normalize_register(std::string *reg, int *reg_size) { |
| auto it = registers_.find(*reg); |
| if (it == registers_.end()) |
| return false; |
| |
| *reg_size = it->second.size; |
| reg_to_name(reg, it->second.reg); |
| return true; |
| } |
| } |