bool ExploitabilityLinux::CalculateAddress()

in src/processor/exploitability_linux.cc [278:394]


bool ExploitabilityLinux::CalculateAddress(const string &address_expression,
                                           const DumpContext &context,
                                           uint64_t *write_address) {
  // The destination should be the format reg+a or reg-a, where reg
  // is a register and a is a hexadecimal constant. Although more complex
  // expressions can make valid instructions, objdump's disassembly outputs
  // it in this simpler format.
  // TODO(liuandrew): Handle more complex formats, should they arise.

  if (!write_address) {
    BPLOG(ERROR) << "Null parameter.";
    return false;
  }

  // Clone parameter into a non-const string.
  string expression = address_expression;

  // Parse out the constant that is added to the address (if it exists).
  size_t delim = expression.find('+');
  bool positive_add_constant = true;
  // Check if constant is subtracted instead of added.
  if (delim == string::npos) {
    positive_add_constant = false;
    delim = expression.find('-');
  }
  uint32_t add_constant = 0;
  // Save constant and remove it from the expression.
  if (delim != string::npos) {
    if (!sscanf(expression.substr(delim + 1).c_str(), "%x", &add_constant)) {
      BPLOG(ERROR) << "Failed to scan constant.";
      return false;
    }
    expression = expression.substr(0, delim);
  }

  // Set the the write address to the corresponding register.
  // TODO(liuandrew): Add support for partial registers, such as
  // the rax/eax/ax/ah/al chain.
  switch (context.GetContextCPU()) {
    case MD_CONTEXT_X86:
      if (!expression.compare("eax")) {
        *write_address = context.GetContextX86()->eax;
      } else if (!expression.compare("ebx")) {
        *write_address = context.GetContextX86()->ebx;
      } else if (!expression.compare("ecx")) {
        *write_address = context.GetContextX86()->ecx;
      } else if (!expression.compare("edx")) {
        *write_address = context.GetContextX86()->edx;
      } else if (!expression.compare("edi")) {
        *write_address = context.GetContextX86()->edi;
      } else if (!expression.compare("esi")) {
        *write_address = context.GetContextX86()->esi;
      } else if (!expression.compare("ebp")) {
        *write_address = context.GetContextX86()->ebp;
      } else if (!expression.compare("esp")) {
        *write_address = context.GetContextX86()->esp;
      } else if (!expression.compare("eip")) {
        *write_address = context.GetContextX86()->eip;
      } else {
        BPLOG(ERROR) << "Unsupported register";
        return false;
      }
      break;
    case MD_CONTEXT_AMD64:
      if (!expression.compare("rax")) {
        *write_address = context.GetContextAMD64()->rax;
      } else if (!expression.compare("rbx")) {
        *write_address = context.GetContextAMD64()->rbx;
      } else if (!expression.compare("rcx")) {
        *write_address = context.GetContextAMD64()->rcx;
      } else if (!expression.compare("rdx")) {
        *write_address = context.GetContextAMD64()->rdx;
      } else if (!expression.compare("rdi")) {
        *write_address = context.GetContextAMD64()->rdi;
      } else if (!expression.compare("rsi")) {
        *write_address = context.GetContextAMD64()->rsi;
      } else if (!expression.compare("rbp")) {
        *write_address = context.GetContextAMD64()->rbp;
      } else if (!expression.compare("rsp")) {
        *write_address = context.GetContextAMD64()->rsp;
      } else if (!expression.compare("rip")) {
        *write_address = context.GetContextAMD64()->rip;
      } else if (!expression.compare("r8")) {
        *write_address = context.GetContextAMD64()->r8;
      } else if (!expression.compare("r9")) {
        *write_address = context.GetContextAMD64()->r9;
      } else if (!expression.compare("r10")) {
        *write_address = context.GetContextAMD64()->r10;
      } else if (!expression.compare("r11")) {
        *write_address = context.GetContextAMD64()->r11;
      } else if (!expression.compare("r12")) {
        *write_address = context.GetContextAMD64()->r12;
      } else if (!expression.compare("r13")) {
        *write_address = context.GetContextAMD64()->r13;
      } else if (!expression.compare("r14")) {
        *write_address = context.GetContextAMD64()->r14;
      } else if (!expression.compare("r15")) {
        *write_address = context.GetContextAMD64()->r15;
      } else {
        BPLOG(ERROR) << "Unsupported register";
        return false;
      }
      break;
    default:
      // This should not occur since the same switch condition
      // should have terminated this method.
      return false;
      break;
  }

  // Add or subtract constant from write address (if applicable).
  *write_address =
      positive_add_constant ?
      *write_address + add_constant : *write_address - add_constant;

  return true;
}