Debugger: Fix udis86 usage for resolving target address.

DisassemblerX86{64}:
- Fix problematic usage of udis86 that was broken during an update.
  Rather than calling the appropriate udis86 function to retrieve the
  operand, we were accessing it directly on the ud struct, which was
  fully filled in implicitly in previous versions of the library. However,
  in the updated version of udis86, the operands are only lazily decoded on
  request, and as such this data was invalid, leading to us not resolving
  target addresses properly. This primarily affected determining the location
  of return values.
This commit is contained in:
Rene Gollent
2016-03-19 16:30:49 -04:00
parent 6e97df31a0
commit 06c2f877e6
2 changed files with 32 additions and 28 deletions
@@ -1,6 +1,7 @@
/*
* Copyright 2009-2012, Ingo Weinhold, [email protected].
* Copyright 2008, François Revol, [email protected]
* Copyright 2016, Rene Gollent, [email protected].
* Distributed under the terms of the MIT License.
*/
@@ -185,36 +186,37 @@ DisassemblerX86::GetInstructionTargetAddress(CpuState* state) const
return 0;
target_addr_t targetAddress = 0;
switch (fUdisData->operand[0].type) {
const struct ud_operand* op = ud_insn_opr(fUdisData, 0);
switch (op->type) {
case UD_OP_REG:
{
targetAddress = x86State->IntRegisterValue(
RegisterNumberFromUdisIndex(fUdisData->operand[0].base));
targetAddress += fUdisData->operand[0].offset;
RegisterNumberFromUdisIndex(op->base));
targetAddress += op->offset;
}
break;
case UD_OP_MEM:
{
targetAddress = x86State->IntRegisterValue(
RegisterNumberFromUdisIndex(fUdisData->operand[0].base));
RegisterNumberFromUdisIndex(op->base));
targetAddress += x86State->IntRegisterValue(
RegisterNumberFromUdisIndex(fUdisData->operand[0].index))
* fUdisData->operand[0].scale;
if (fUdisData->operand[0].offset != 0)
targetAddress += fUdisData->operand[0].lval.sdword;
RegisterNumberFromUdisIndex(op->index))
* op->scale;
if (op->offset != 0)
targetAddress += op->lval.sdword;
}
break;
case UD_OP_JIMM:
{
targetAddress = ud_insn_off(fUdisData)
+ fUdisData->operand[0].lval.sdword + ud_insn_len(fUdisData);
+ op->lval.sdword + ud_insn_len(fUdisData);
}
break;
case UD_OP_IMM:
case UD_OP_CONST:
{
targetAddress = fUdisData->operand[0].lval.udword;
targetAddress = op->lval.udword;
}
break;
@@ -2,6 +2,7 @@
* Copyright 2012, Alex Smith, [email protected].
* Copyright 2009-2012, Ingo Weinhold, [email protected].
* Copyright 2008, François Revol, [email protected]
* Copyright 2016, Rene Gollent, [email protected].
* Distributed under the terms of the MIT License.
*/
@@ -196,34 +197,35 @@ DisassemblerX8664::GetInstructionTargetAddress(CpuState* state) const
return 0;
target_addr_t targetAddress = 0;
switch (fUdisData->operand[0].type) {
const struct ud_operand* op = ud_insn_opr(fUdisData, 0);
switch (op->type) {
case UD_OP_REG:
{
targetAddress = x64State->IntRegisterValue(
RegisterNumberFromUdisIndex(fUdisData->operand[0].base));
targetAddress += fUdisData->operand[0].offset;
RegisterNumberFromUdisIndex(op->base));
targetAddress += op->offset;
}
break;
case UD_OP_MEM:
{
targetAddress = x64State->IntRegisterValue(
RegisterNumberFromUdisIndex(fUdisData->operand[0].base));
RegisterNumberFromUdisIndex(op->base));
targetAddress += x64State->IntRegisterValue(
RegisterNumberFromUdisIndex(fUdisData->operand[0].index))
* fUdisData->operand[0].scale;
RegisterNumberFromUdisIndex(op->index))
* op->scale;
off_t offset = 0;
switch (fUdisData->operand[0].offset) {
switch (op->offset) {
case 8:
offset = fUdisData->operand[0].lval.sbyte;
offset = op->lval.sbyte;
break;
case 16:
offset = fUdisData->operand[0].lval.sword;
offset = op->lval.sword;
break;
case 32:
offset = fUdisData->operand[0].lval.sdword;
offset = op->lval.sdword;
break;
case 64:
offset = fUdisData->operand[0].lval.sqword;
offset = op->lval.sqword;
break;
}
targetAddress += offset;
@@ -232,20 +234,20 @@ DisassemblerX8664::GetInstructionTargetAddress(CpuState* state) const
case UD_OP_JIMM:
{
targetAddress = ud_insn_off(fUdisData) + ud_insn_len(fUdisData);
if (fUdisData->operand[0].size == 32)
targetAddress += fUdisData->operand[0].lval.sdword;
if (op->size == 32)
targetAddress += op->lval.sdword;
else
targetAddress += fUdisData->operand[0].lval.sqword;
targetAddress += op->lval.sqword;
}
break;
case UD_OP_IMM:
case UD_OP_CONST:
{
if (fUdisData->operand[0].size == 32)
targetAddress = fUdisData->operand[0].lval.udword;
else if (fUdisData->operand[0].size == 64)
targetAddress = fUdisData->operand[0].lval.uqword;
if (op->size == 32)
targetAddress = op->lval.udword;
else if (op->size == 64)
targetAddress = op->lval.uqword;
}
break;