Skip to content

Commit

Permalink
Fix jumps and branches on a non-zero PC (#2479)
Browse files Browse the repository at this point in the history
* Fix ASAN shift runtime check

* Fix jumps and branches addresses when applying a PC address

* Add tests for branches and jumps
  • Loading branch information
wargio authored Sep 19, 2024
1 parent 10db5f4 commit e9b9b64
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 10 deletions.
6 changes: 3 additions & 3 deletions arch/Mips/MipsDisassembler.c
Original file line number Diff line number Diff line change
Expand Up @@ -1406,14 +1406,14 @@ static DecodeStatus readInstruction32(const uint8_t *Bytes, size_t BytesLen,
if (IsBigEndian) {
// Encoded as a big-endian 32-bit word in the stream.
*Insn = (Bytes[3] << 0) | (Bytes[2] << 8) | (Bytes[1] << 16) |
(Bytes[0] << 24);
((unsigned)Bytes[0] << 24);
} else {
if (IsMicroMips) {
*Insn = (Bytes[2] << 0) | (Bytes[3] << 8) |
(Bytes[0] << 16) | (Bytes[1] << 24);
(Bytes[0] << 16) | ((unsigned)Bytes[1] << 24);
} else {
*Insn = (Bytes[0] << 0) | (Bytes[1] << 8) |
(Bytes[2] << 16) | (Bytes[3] << 24);
(Bytes[2] << 16) | ((unsigned)Bytes[3] << 24);
}
}

Expand Down
5 changes: 4 additions & 1 deletion arch/Mips/MipsInstPrinter.c
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,10 @@ static void printJumpOperand(MCInst *MI, unsigned OpNo, SStream *O)
if (MCOperand_isReg(Op))
return printRegName(MI, O, MCOperand_getReg(Op));

printInt64(O, MCOperand_getImm(Op));
// only the upper bits are needed.
uint64_t Base = MI->address & ~0x0fffffffull;
uint64_t Target = MCOperand_getImm(Op);
printInt64(O, Base | Target);
}

static void printBranchOperand(MCInst *MI, uint64_t Address, unsigned OpNo, SStream *O)
Expand Down
22 changes: 18 additions & 4 deletions arch/Mips/MipsMapping.c
Original file line number Diff line number Diff line change
Expand Up @@ -296,12 +296,26 @@ static void Mips_set_detail_op_operand(MCInst *MI, unsigned OpNum)
printf("Operand type %d not handled!\n", op_type);
}

static void Mips_set_detail_op_jump(MCInst *MI, unsigned OpNum)
{
cs_op_type op_type = map_get_op_type(MI, OpNum) & ~CS_OP_MEM;
if (op_type == CS_OP_IMM) {
uint64_t Base = MI->address & ~0x0fffffffull;
uint64_t Target = Base | (uint64_t)MCInst_getOpVal(MI, OpNum);
Mips_set_detail_op_uimm(MI, OpNum, Target);
} else if (op_type == CS_OP_REG) {
Mips_set_detail_op_reg(MI, OpNum, MCInst_getOpVal(MI, OpNum),
false);
} else
printf("Operand type %d not handled!\n", op_type);
}

static void Mips_set_detail_op_branch(MCInst *MI, unsigned OpNum)
{
cs_op_type op_type = map_get_op_type(MI, OpNum) & ~CS_OP_MEM;
if (op_type == CS_OP_IMM) {
uint64_t Target = (uint64_t)MCInst_getOpVal(MI, OpNum);
Mips_set_detail_op_uimm(MI, OpNum, Target + MI->address);
uint64_t Target = MI->address + MCInst_getOpVal(MI, OpNum);
Mips_set_detail_op_uimm(MI, OpNum, Target);
} else if (op_type == CS_OP_REG) {
Mips_set_detail_op_reg(MI, OpNum, MCInst_getOpVal(MI, OpNum),
false);
Expand Down Expand Up @@ -374,9 +388,9 @@ void Mips_add_cs_detail(MCInst *MI, mips_op_group op_group, va_list args)
// this is only used by nanoMips.
return Mips_set_detail_op_mem_nanomips(MI, OpNum);
case Mips_OP_GROUP_BranchOperand:
/* fall-thru */
case Mips_OP_GROUP_JumpOperand:
return Mips_set_detail_op_branch(MI, OpNum);
case Mips_OP_GROUP_JumpOperand:
return Mips_set_detail_op_jump(MI, OpNum);
case Mips_OP_GROUP_Operand:
return Mips_set_detail_op_operand(MI, OpNum);
case Mips_OP_GROUP_UImm_1_0:
Expand Down
98 changes: 96 additions & 2 deletions tests/issues/issues.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4958,8 +4958,102 @@ test_cases:
insns:
- asm_text: "jalrc $t9"

-
input:
- input:
name: "Mips32 jumps with base offset"
bytes: [ 0x40, 0x04, 0x04, 0x08 ]
arch: "CS_ARCH_MIPS"
options: [ CS_MODE_LITTLE_ENDIAN, CS_MODE_MIPS5, CS_OPT_DETAIL ]
address: 0x8060b53c
expected:
insns:
# 8060b53c: 40040408 j 0x80101100
- asm_text: "j 0x80101100"
details:
mips:
operands:
- type: MIPS_OP_IMM
imm: 0x80101100

- input:
name: "Mips32 jumps with base offset (lower limit)"
bytes: [ 0x40, 0x04, 0x04, 0x08 ]
arch: "CS_ARCH_MIPS"
options: [ CS_MODE_LITTLE_ENDIAN, CS_MODE_MIPS5, CS_OPT_DETAIL ]
address: 0xFF000000
expected:
insns:
# ff000000: 40040408 j 0xf0101100
- asm_text: "j 0xf0101100"
details:
mips:
operands:
- type: MIPS_OP_IMM
imm: 0xf0101100

- input:
name: "Mips64 jumps with base offset"
bytes: [ 0x40, 0x04, 0x04, 0x08 ]
arch: "CS_ARCH_MIPS"
options: [ CS_MODE_LITTLE_ENDIAN, CS_MODE_MIPS64R5, CS_OPT_DETAIL ]
address: 0x8060b53c
expected:
insns:
# 8060b53c: 40040408 j 0x80101100
- asm_text: "j 0x80101100"
details:
mips:
operands:
- type: MIPS_OP_IMM
imm: 0x80101100

- input:
name: "Mips64 jumps with base offset (lower limit)"
bytes: [ 0x40, 0x04, 0x04, 0x08 ]
arch: "CS_ARCH_MIPS"
options: [ CS_MODE_LITTLE_ENDIAN, CS_MODE_MIPS64R5, CS_OPT_DETAIL ]
address: 0xFF000000
expected:
insns:
# ff000000: 40040408 j 0xf0101100
- asm_text: "j 0xf0101100"
details:
mips:
operands:
- type: MIPS_OP_IMM
imm: 0xf0101100

- input:
name: "micromips beqz16"
bytes: [ 0x8d, 0x7f ]
arch: "CS_ARCH_MIPS"
options: [ CS_MODE_BIG_ENDIAN, CS_MODE_MICRO, CS_MODE_MIPS32R3, CS_OPT_DETAIL ]
address: 0x80600000
expected:
insns:
- asm_text: "beqz16 $v0, 0x805ffffe"
details:
mips:
operands:
- type: MIPS_OP_REG
reg: v0
- type: MIPS_OP_IMM
imm: 0x805ffffe

- input:
name: "micromips b16"
bytes: [ 0xcf, 0xff ]
arch: "CS_ARCH_MIPS"
options: [ CS_MODE_BIG_ENDIAN, CS_MODE_MICRO, CS_MODE_MIPS32R3, CS_OPT_DETAIL ]
address: 0x80600000
expected:
insns:
- asm_text: "b16 0x805ffffe"
details:
mips:
operands:
- type: MIPS_OP_IMM
imm: 0x805ffffe
- input:
name: "issue 2471 -- max operands overflow"
bytes: [ 0xff, 0x00, 0x08, 0xc0 ]
arch: "CS_ARCH_AARCH64"
Expand Down

0 comments on commit e9b9b64

Please sign in to comment.