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;
}