Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tricore: fix runtime errors of integer overflow #2204

Merged
merged 1 commit into from
Nov 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
189 changes: 108 additions & 81 deletions arch/TriCore/TriCoreInstPrinter.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,11 @@
#ifdef CAPSTONE_HAS_TRICORE

#include <platform.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "../../MCInst.h"
#include "../../MCRegisterInfo.h"
#include "../../Mapping.h"
#include "../../MathExtras.h"
#include "../../SStream.h"
#include "../../utils.h"

#include "TriCoreMapping.h"
#include "TriCoreLinkage.h"

Expand All @@ -44,9 +39,41 @@ static void printOperand(MCInst *MI, int OpNum, SStream *O);

#include "TriCoreGenRegisterInfo.inc"

static bool fill_mem(MCInst *MI, unsigned int reg, int32_t disp);
static uint32_t to_u32(int64_t x)
{
if (x > UINT32_MAX || x < -(int64_t)(UINT32_MAX)) {
abort();
}
return (uint32_t)x;
}

static inline unsigned int get_msb(uint64_t value)
{
unsigned int msb = 0;
while (value > 0) {
value >>= 1; // Shift bits to the right
msb++; // Increment the position of the MSB
}
return msb;
}

static inline int64_t sign_ext64(int64_t imm, unsigned n)
{
n = get_msb(imm) > n ? get_msb(imm) : n;
int64_t mask = 1 << (n - 1);
return (imm ^ mask) - mask;
}

static inline int32_t sign_ext32(int32_t imm, unsigned n)
{
n = get_msb(imm) > n ? get_msb(imm) : n;
int32_t mask = 1 << (n - 1);
return (imm ^ mask) - mask;
}

static bool fill_mem(MCInst *MI, unsigned int reg, int64_t disp);

static inline void set_mem(cs_tricore_op *op, uint8_t base, int32_t disp)
static inline void set_mem(cs_tricore_op *op, uint8_t base, int64_t disp)
{
op->type |= TRICORE_OP_MEM;
op->mem.base = base;
Expand All @@ -63,7 +90,7 @@ static inline void fill_reg(MCInst *MI, uint32_t reg)
TriCore_inc_op_count(MI);
}

static inline void fill_imm(MCInst *MI, int32_t imm)
static inline void fill_imm(MCInst *MI, int64_t imm)
{
if (!detail_is_set(MI))
return;
Expand All @@ -80,7 +107,7 @@ static inline void fill_imm(MCInst *MI, int32_t imm)
tricore->op_count++;
}

static bool fill_mem(MCInst *MI, unsigned int reg, int32_t disp)
static bool fill_mem(MCInst *MI, unsigned int reg, int64_t disp)
{
if (!detail_is_set(MI))
return false;
Expand Down Expand Up @@ -166,42 +193,24 @@ static void printOperand(MCInst *MI, int OpNum, SStream *O)
fill_reg(MI, reg);
} else if (MCOperand_isImm(Op)) {
int64_t Imm = MCOperand_getImm(Op);
printInt64Bang(O, Imm);
fill_imm(MI, (int32_t)Imm);
printUInt32Bang(O, to_u32(Imm));
fill_imm(MI, Imm);
}
}

static inline unsigned int get_msb(unsigned int value)
{
unsigned int msb = 0;
while (value > 0) {
value >>= 1; // Shift bits to the right
msb++; // Increment the position of the MSB
}
return msb;
}

static inline int32_t sign_ext_n(int32_t imm, unsigned n)
{
n = get_msb(imm) > n ? get_msb(imm) : n;
int32_t mask = 1 << (n - 1);
int32_t sign_extended = (imm ^ mask) - mask;
return sign_extended;
}

static void print_sign_ext(MCInst *MI, int OpNum, SStream *O, unsigned n)
{
MCOperand *MO = MCInst_getOperand(MI, OpNum);
if (MCOperand_isImm(MO)) {
int32_t imm = (int32_t)MCOperand_getImm(MO);
imm = sign_ext_n(imm, n);
printInt32Bang(O, imm);
fill_imm(MI, imm);
int64_t imm = MCOperand_getImm(MO);
int32_t res = sign_ext32(to_u32(imm), n);
printInt32Bang(O, res);
fill_imm(MI, res);
} else
printOperand(MI, OpNum, O);
}

static void off4_fixup(MCInst *MI, uint64_t *off4)
static void off4_fixup(MCInst *MI, int64_t *off4)
{
switch (MCInst_getOpcode(MI)) {
case TRICORE_LD_A_slro:
Expand All @@ -212,27 +221,27 @@ static void off4_fixup(MCInst *MI, uint64_t *off4)
case TRICORE_ST_A_ssro:
case TRICORE_ST_W_sro:
case TRICORE_ST_W_ssro: {
*off4 *= 4;
*off4 = *off4 * 4;
break;
}
case TRICORE_LD_H_sro:
case TRICORE_LD_H_slro:
case TRICORE_ST_H_sro:
case TRICORE_ST_H_ssro: {
*off4 *= 2;
*off4 = *off4 * 2;
break;
}
}
}

static void const8_fixup(MCInst *MI, uint64_t *const8)
static void const8_fixup(MCInst *MI, int64_t *const8)
{
switch (MCInst_getOpcode(MI)) {
case TRICORE_LD_A_sc:
case TRICORE_ST_A_sc:
case TRICORE_ST_W_sc:
case TRICORE_LD_W_sc: {
*const8 *= 4;
*const8 = *const8 * 4;
break;
}
}
Expand All @@ -242,9 +251,9 @@ static void print_zero_ext(MCInst *MI, int OpNum, SStream *O, unsigned n)
{
MCOperand *MO = MCInst_getOperand(MI, OpNum);
if (MCOperand_isImm(MO)) {
uint64_t imm = MCOperand_getImm(MO);
int64_t imm = MCOperand_getImm(MO);
for (unsigned i = n + 1; i < 32; ++i) {
imm &= ~(1 << i);
imm &= ~(1LL << i);
}
if (n == 4) {
off4_fixup(MI, &imm);
Expand All @@ -253,7 +262,7 @@ static void print_zero_ext(MCInst *MI, int OpNum, SStream *O, unsigned n)
const8_fixup(MI, &imm);
}

printInt64Bang(O, imm);
printUInt32Bang(O, to_u32(imm));
fill_imm(MI, imm);
} else
printOperand(MI, OpNum, O);
Expand All @@ -263,41 +272,47 @@ static void printOff18Imm(MCInst *MI, int OpNum, SStream *O)
{
MCOperand *MO = MCInst_getOperand(MI, OpNum);
if (MCOperand_isImm(MO)) {
uint32_t imm = (uint32_t)MCOperand_getImm(MO);
imm = ((imm & 0x3C000) << 14) | (imm & 0x3fff);
printUInt32Bang(O, imm);
fill_imm(MI, (int32_t)imm);
int64_t imm = MCOperand_getImm(MO);
imm = ((to_u32(imm) & 0x3C000) << 14) | (to_u32(imm) & 0x3fff);
printUInt32Bang(O, to_u32(imm));
fill_imm(MI, imm);
} else
printOperand(MI, OpNum, O);
}

// PC + sext(2 * disp)
#define DISP1(N) ((int64_t)(MI->address) + sign_ext64(disp * 2, N))
// PC + sext(disp) * 2
#define DISP2(N) ((int64_t)(MI->address) + sign_ext64(disp, N) * 2)

static void printDisp24Imm(MCInst *MI, int OpNum, SStream *O)
{
MCOperand *MO = MCInst_getOperand(MI, OpNum);
if (MCOperand_isImm(MO)) {
uint32_t disp = MCOperand_getImm(MO);
int64_t disp = MCOperand_getImm(MO);
int64_t res = 0;
switch (MCInst_getOpcode(MI)) {
case TRICORE_CALL_b:
case TRICORE_FCALL_b: {
disp = (int32_t)MI->address + sign_ext_n(disp * 2, 24);
res = DISP1(24);
break;
}
case TRICORE_CALLA_b:
case TRICORE_FCALLA_b:
case TRICORE_JA_b:
case TRICORE_JLA_b:
// = {disp24[23:20], 7’b0000000, disp24[19:0], 1’b0};
disp = ((disp & 0xf00000) << 28) |
((disp & 0xfffff) << 1);
res = ((to_u32(disp) & 0xf00000) << 28) |
((to_u32(disp) & 0xfffff) << 1);
break;
case TRICORE_J_b:
case TRICORE_JL_b:
disp = (int32_t)MI->address + sign_ext_n(disp, 24) * 2;
res = DISP2(24);
break;
}

printUInt32Bang(O, disp);
fill_imm(MI, disp);
printUInt32Bang(O, to_u32(res));
fill_imm(MI, res);
} else
printOperand(MI, OpNum, O);
}
Expand All @@ -306,8 +321,13 @@ static void printDisp15Imm(MCInst *MI, int OpNum, SStream *O)
{
MCOperand *MO = MCInst_getOperand(MI, OpNum);
if (MCOperand_isImm(MO)) {
uint32_t disp = MCOperand_getImm(MO);
int64_t disp = MCOperand_getImm(MO);
int64_t res = 0;
switch (MCInst_getOpcode(MI)) {
case TRICORE_LOOP_brr:
case TRICORE_LOOPU_brr:
res = DISP1(15);
break;
case TRICORE_JEQ_brc:
case TRICORE_JEQ_brr:
case TRICORE_JEQ_A_brr:
Expand All @@ -330,19 +350,15 @@ static void printDisp15Imm(MCInst *MI, int OpNum, SStream *O)
case TRICORE_JNZ_T_brn:
case TRICORE_JZ_A_brr:
case TRICORE_JZ_T_brn:
disp = (int32_t)MI->address + sign_ext_n(disp, 15) * 2;
break;
case TRICORE_LOOP_brr:
case TRICORE_LOOPU_brr:
disp = (int32_t)MI->address + sign_ext_n(disp * 2, 15);
res = DISP2(15);
break;
default:
// handle other cases, if any
break;
}

printUInt32Bang(O, disp);
fill_imm(MI, disp);
printUInt32Bang(O, to_u32(res));
fill_imm(MI, res);
} else
printOperand(MI, OpNum, O);
}
Expand All @@ -351,23 +367,24 @@ static void printDisp8Imm(MCInst *MI, int OpNum, SStream *O)
{
MCOperand *MO = MCInst_getOperand(MI, OpNum);
if (MCOperand_isImm(MO)) {
uint32_t disp = MCOperand_getImm(MO);
int64_t disp = MCOperand_getImm(MO);
int64_t res = 0;
switch (MCInst_getOpcode(MI)) {
case TRICORE_CALL_sb:
disp = (int32_t)MI->address + sign_ext_n(2 * disp, 8);
disp = DISP1(8);
break;
case TRICORE_J_sb:
case TRICORE_JNZ_sb:
case TRICORE_JZ_sb:
disp = (int32_t)MI->address + sign_ext_n(disp, 8) * 2;
res = DISP2(8);
break;
default:
// handle other cases, if any
break;
}

printUInt32Bang(O, disp);
fill_imm(MI, disp);
printUInt32Bang(O, to_u32(res));
fill_imm(MI, res);
} else
printOperand(MI, OpNum, O);
}
Expand All @@ -376,7 +393,8 @@ static void printDisp4Imm(MCInst *MI, int OpNum, SStream *O)
{
MCOperand *MO = MCInst_getOperand(MI, OpNum);
if (MCOperand_isImm(MO)) {
uint32_t disp = MCOperand_getImm(MO);
int64_t disp = MCOperand_getImm(MO);
int64_t res = 0;
switch (MCInst_getOpcode(MI)) {
case TRICORE_JEQ_sbc1:
case TRICORE_JEQ_sbr1:
Expand All @@ -392,27 +410,29 @@ static void printDisp4Imm(MCInst *MI, int OpNum, SStream *O)
case TRICORE_JZ_sbr:
case TRICORE_JZ_A_sbr:
case TRICORE_JZ_T_sbrn:
disp = (int32_t)MI->address + disp * 2;
// PC + zero_ext(disp4) * 2;
res = (int64_t)(MI->address) + disp * 2;
break;
case TRICORE_JEQ_sbc2:
case TRICORE_JEQ_sbr2:
case TRICORE_JNE_sbc2:
case TRICORE_JNE_sbr2:
disp = (int32_t)MI->address + (disp + 16) * 2;
// PC + zero_ext(disp4 + 16) * 2;
res = (int64_t)(MI->address) + ((disp + 16) * 2);
break;
case TRICORE_LOOP_sbr:
// {27b’111111111111111111111111111, disp4, 0};
disp = (int32_t)MI->address +
((0b111111111111111111111111111 << 5) |
(disp << 1));
// PC + {27b’111111111111111111111111111, disp4, 0};
res = (int64_t)(MI->address) +
((0b111111111111111111111111111LL << 5) |
(to_u32(disp) << 1));
break;
default:
// handle other cases, if any
break;
}

printUInt32Bang(O, disp);
fill_imm(MI, disp);
printUInt32Bang(O, to_u32(res));
fill_imm(MI, res);
} else
printOperand(MI, OpNum, O);
}
Expand All @@ -432,14 +452,21 @@ static void printDisp4Imm(MCInst *MI, int OpNum, SStream *O)
// clang-format off

printSExtImm_(16)

printSExtImm_(10)

printSExtImm_(9)

printSExtImm_(4)

printZExtImm_(16)

printZExtImm_(9)

printZExtImm_(8)

printZExtImm_(4)

printZExtImm_(2);

// clang-format on
Expand All @@ -448,12 +475,12 @@ static void printOExtImm_4(MCInst *MI, int OpNum, SStream *O)
{
MCOperand *MO = MCInst_getOperand(MI, OpNum);
if (MCOperand_isImm(MO)) {
uint32_t imm = MCOperand_getImm(MO);
// {27b’111111111111111111111111111, disp4, 0};
imm = 0b11111111111111111111111111100000 | (imm << 1);

printInt32Bang(O, imm);
fill_imm(MI, imm);
int64_t disp = MCOperand_getImm(MO);
int64_t res = (int64_t)(MI->address) +
((0b111111111111111111111111111 << 5) |
(to_u32(disp) << 1));
Copy link
Collaborator

@Rot127 Rot127 Nov 27, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Run clang-format please, this has spaces in it.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've already run clang-format, even though I'm using version 17.0.1.

printUInt32Bang(O, to_u32(res));
fill_imm(MI, res);
} else
printOperand(MI, OpNum, O);
}
Expand Down
Loading