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:
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user