Skip to content

Commit e9b9b64

Browse files
authored
Fix jumps and branches on a non-zero PC (#2479)
* Fix ASAN shift runtime check * Fix jumps and branches addresses when applying a PC address * Add tests for branches and jumps
1 parent 10db5f4 commit e9b9b64

File tree

4 files changed

+121
-10
lines changed

4 files changed

+121
-10
lines changed

arch/Mips/MipsDisassembler.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1406,14 +1406,14 @@ static DecodeStatus readInstruction32(const uint8_t *Bytes, size_t BytesLen,
14061406
if (IsBigEndian) {
14071407
// Encoded as a big-endian 32-bit word in the stream.
14081408
*Insn = (Bytes[3] << 0) | (Bytes[2] << 8) | (Bytes[1] << 16) |
1409-
(Bytes[0] << 24);
1409+
((unsigned)Bytes[0] << 24);
14101410
} else {
14111411
if (IsMicroMips) {
14121412
*Insn = (Bytes[2] << 0) | (Bytes[3] << 8) |
1413-
(Bytes[0] << 16) | (Bytes[1] << 24);
1413+
(Bytes[0] << 16) | ((unsigned)Bytes[1] << 24);
14141414
} else {
14151415
*Insn = (Bytes[0] << 0) | (Bytes[1] << 8) |
1416-
(Bytes[2] << 16) | (Bytes[3] << 24);
1416+
(Bytes[2] << 16) | ((unsigned)Bytes[3] << 24);
14171417
}
14181418
}
14191419

arch/Mips/MipsInstPrinter.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,10 @@ static void printJumpOperand(MCInst *MI, unsigned OpNo, SStream *O)
204204
if (MCOperand_isReg(Op))
205205
return printRegName(MI, O, MCOperand_getReg(Op));
206206

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

210213
static void printBranchOperand(MCInst *MI, uint64_t Address, unsigned OpNo, SStream *O)

arch/Mips/MipsMapping.c

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -296,12 +296,26 @@ static void Mips_set_detail_op_operand(MCInst *MI, unsigned OpNum)
296296
printf("Operand type %d not handled!\n", op_type);
297297
}
298298

299+
static void Mips_set_detail_op_jump(MCInst *MI, unsigned OpNum)
300+
{
301+
cs_op_type op_type = map_get_op_type(MI, OpNum) & ~CS_OP_MEM;
302+
if (op_type == CS_OP_IMM) {
303+
uint64_t Base = MI->address & ~0x0fffffffull;
304+
uint64_t Target = Base | (uint64_t)MCInst_getOpVal(MI, OpNum);
305+
Mips_set_detail_op_uimm(MI, OpNum, Target);
306+
} else if (op_type == CS_OP_REG) {
307+
Mips_set_detail_op_reg(MI, OpNum, MCInst_getOpVal(MI, OpNum),
308+
false);
309+
} else
310+
printf("Operand type %d not handled!\n", op_type);
311+
}
312+
299313
static void Mips_set_detail_op_branch(MCInst *MI, unsigned OpNum)
300314
{
301315
cs_op_type op_type = map_get_op_type(MI, OpNum) & ~CS_OP_MEM;
302316
if (op_type == CS_OP_IMM) {
303-
uint64_t Target = (uint64_t)MCInst_getOpVal(MI, OpNum);
304-
Mips_set_detail_op_uimm(MI, OpNum, Target + MI->address);
317+
uint64_t Target = MI->address + MCInst_getOpVal(MI, OpNum);
318+
Mips_set_detail_op_uimm(MI, OpNum, Target);
305319
} else if (op_type == CS_OP_REG) {
306320
Mips_set_detail_op_reg(MI, OpNum, MCInst_getOpVal(MI, OpNum),
307321
false);
@@ -374,9 +388,9 @@ void Mips_add_cs_detail(MCInst *MI, mips_op_group op_group, va_list args)
374388
// this is only used by nanoMips.
375389
return Mips_set_detail_op_mem_nanomips(MI, OpNum);
376390
case Mips_OP_GROUP_BranchOperand:
377-
/* fall-thru */
378-
case Mips_OP_GROUP_JumpOperand:
379391
return Mips_set_detail_op_branch(MI, OpNum);
392+
case Mips_OP_GROUP_JumpOperand:
393+
return Mips_set_detail_op_jump(MI, OpNum);
380394
case Mips_OP_GROUP_Operand:
381395
return Mips_set_detail_op_operand(MI, OpNum);
382396
case Mips_OP_GROUP_UImm_1_0:

tests/issues/issues.yaml

Lines changed: 96 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4958,8 +4958,102 @@ test_cases:
49584958
insns:
49594959
- asm_text: "jalrc $t9"
49604960

4961-
-
4962-
input:
4961+
- input:
4962+
name: "Mips32 jumps with base offset"
4963+
bytes: [ 0x40, 0x04, 0x04, 0x08 ]
4964+
arch: "CS_ARCH_MIPS"
4965+
options: [ CS_MODE_LITTLE_ENDIAN, CS_MODE_MIPS5, CS_OPT_DETAIL ]
4966+
address: 0x8060b53c
4967+
expected:
4968+
insns:
4969+
# 8060b53c: 40040408 j 0x80101100
4970+
- asm_text: "j 0x80101100"
4971+
details:
4972+
mips:
4973+
operands:
4974+
- type: MIPS_OP_IMM
4975+
imm: 0x80101100
4976+
4977+
- input:
4978+
name: "Mips32 jumps with base offset (lower limit)"
4979+
bytes: [ 0x40, 0x04, 0x04, 0x08 ]
4980+
arch: "CS_ARCH_MIPS"
4981+
options: [ CS_MODE_LITTLE_ENDIAN, CS_MODE_MIPS5, CS_OPT_DETAIL ]
4982+
address: 0xFF000000
4983+
expected:
4984+
insns:
4985+
# ff000000: 40040408 j 0xf0101100
4986+
- asm_text: "j 0xf0101100"
4987+
details:
4988+
mips:
4989+
operands:
4990+
- type: MIPS_OP_IMM
4991+
imm: 0xf0101100
4992+
4993+
- input:
4994+
name: "Mips64 jumps with base offset"
4995+
bytes: [ 0x40, 0x04, 0x04, 0x08 ]
4996+
arch: "CS_ARCH_MIPS"
4997+
options: [ CS_MODE_LITTLE_ENDIAN, CS_MODE_MIPS64R5, CS_OPT_DETAIL ]
4998+
address: 0x8060b53c
4999+
expected:
5000+
insns:
5001+
# 8060b53c: 40040408 j 0x80101100
5002+
- asm_text: "j 0x80101100"
5003+
details:
5004+
mips:
5005+
operands:
5006+
- type: MIPS_OP_IMM
5007+
imm: 0x80101100
5008+
5009+
- input:
5010+
name: "Mips64 jumps with base offset (lower limit)"
5011+
bytes: [ 0x40, 0x04, 0x04, 0x08 ]
5012+
arch: "CS_ARCH_MIPS"
5013+
options: [ CS_MODE_LITTLE_ENDIAN, CS_MODE_MIPS64R5, CS_OPT_DETAIL ]
5014+
address: 0xFF000000
5015+
expected:
5016+
insns:
5017+
# ff000000: 40040408 j 0xf0101100
5018+
- asm_text: "j 0xf0101100"
5019+
details:
5020+
mips:
5021+
operands:
5022+
- type: MIPS_OP_IMM
5023+
imm: 0xf0101100
5024+
5025+
- input:
5026+
name: "micromips beqz16"
5027+
bytes: [ 0x8d, 0x7f ]
5028+
arch: "CS_ARCH_MIPS"
5029+
options: [ CS_MODE_BIG_ENDIAN, CS_MODE_MICRO, CS_MODE_MIPS32R3, CS_OPT_DETAIL ]
5030+
address: 0x80600000
5031+
expected:
5032+
insns:
5033+
- asm_text: "beqz16 $v0, 0x805ffffe"
5034+
details:
5035+
mips:
5036+
operands:
5037+
- type: MIPS_OP_REG
5038+
reg: v0
5039+
- type: MIPS_OP_IMM
5040+
imm: 0x805ffffe
5041+
5042+
- input:
5043+
name: "micromips b16"
5044+
bytes: [ 0xcf, 0xff ]
5045+
arch: "CS_ARCH_MIPS"
5046+
options: [ CS_MODE_BIG_ENDIAN, CS_MODE_MICRO, CS_MODE_MIPS32R3, CS_OPT_DETAIL ]
5047+
address: 0x80600000
5048+
expected:
5049+
insns:
5050+
- asm_text: "b16 0x805ffffe"
5051+
details:
5052+
mips:
5053+
operands:
5054+
- type: MIPS_OP_IMM
5055+
imm: 0x805ffffe
5056+
- input:
49635057
name: "issue 2471 -- max operands overflow"
49645058
bytes: [ 0xff, 0x00, 0x08, 0xc0 ]
49655059
arch: "CS_ARCH_AARCH64"

0 commit comments

Comments
 (0)