Skip to content

Commit

Permalink
Aarch64 decompilation (#533)
Browse files Browse the repository at this point in the history
* Capstone2llvmirtool default basic modes for architectures

Run tool with reasonable Capstone basic modes for specified architecture.
Default values are as follows:
-a arm   : CS_MODE_ARM
-a arm64 : CS_MODE_ARM [looks like keystone doesn't like this]
-a mips  : CS_MODE_MIPS32
-a x86   : CS_MODE_32
-a ppc   : CS_MODE_32
-a <rest>: CS_MODE_LITTLE_ENDIAN

* Base for the ARM64 translator

- register maps(_reg2type)
- instructions map(_i2fm)
Modified ARM Translator unit, Work in progress.

* Fix the cs_reg_name

- register name could not be found because of the wrong cs_arch in constructor

* Add ARM64 support for capstone dependency

- capstone was configured without the ARM64 support, this caused
  cs_open to fail

* Temporary solution to call translate function

* Status register and program counter added to environment

- flags from status register added to arm64 env
- program counter added to arm64 env

* Methods store/load registers/operands skeletons + add instruction

- basic implementation of functions needed for loading and storing operands
- translateAdd is for testing purposes

* Store instruction base

- started implementation of MEM operand type
- Store register instruction translation method
e.g. retdec-capstone2llvmir -a arm64 -t 'str x0, [x1]'

* Operand shifts ported from ARM and MOV instruction tranlation

- MOV, MVN and MOVZ instructions
- operand shift functions moved and changed for ARM64
- instructions like 'movz x0, #3 LSL 16' work now

* Arm64 - tests ported from Arm

- test framework capstone2llvmirtranslator
- first INS_ADD test
- cmake compilation

* Basic MOV tests

- MOV, MOVZ

* Test for STR instruction and test header comments

* STP instruction + tests, pc in new enum, get op addr function

- Store pair instruction{pre-index, post-index, signed-offset}
- test for all cases except 32bit operands
- pc moved to its own enum
- generateGetOperandAddr to generate address from instruction operand

* LDR + STR, LDR tests from ARM, LDP stub

- LDR{pre-index, post-index, signed-offset} instruction implemented
- STR{pre-index, post-index, signed-offset} instruction implemented
- LDR tests ported from ARM
- LDP todo

* Implemented parent register handling

- Register parent map
- Storing registers
- Loading registers
- Headers

- Need more changes to conversions, I think 'mov w0, #3' zeroes out
  the upper 32bits of x0 register. But need to investigate further.

* LLVM data layout modified for ARM64

- taken from uname -a in qemu arm64 machine
Linux debian-aarch64 4.9.0-4-arm64 #1 SMP Debian
4.9.65-3+deb9u1 (2017-12-23) aarch64 GNU/Linux

* Removed useless debug output

* getCarryRegister for ARM64 fixed

* Store register ZEXT_TRUNC, 32bit tests baseline + tests

- when writing value to 32bit reg the 64bit, the value is zero
  extended to the vhole register
- parent register mapping enabled in tests
- 32bit version of tests

* Zero extension tests for ADD and MOV 32bit variants

* Implemented BL instruction

- added tests for label and imm branch

* Implemented RET instruction

- added tests

* Implemented LDP instruction

- added tests for instruction

* Implemeneted ADRP instruction

- real binary testing is needed
- without tests

* enable arm64 in decompiler.py and add arm64 architecture

in Architecture::setArch() ARM64 needs to be set before ARM
because "arm" from ARM matches the "arm aarch64" from ARM64

* Arm64 ABI implementation

* Arm64 decoder ported from Arm

* Arm64 imm operand shifts should not update flags by default.

- Added the option to switch this behaviour
- add one ADD test with shift

* Operand register extension generator + 64bit variant extension tests

- Arm supports the extension of operand e.g. 'add x0, x1, w2, SXTW'
  will sign-extend the w2 register to 64 bit and after that add the values
- test for 64bit variant implemented
- need to check the optional imm(shift VM outputs weird values)

* Arm64 Zero/Sign extension 32bit variant tests

* Implemented SUB instruction

- added tests for instruction

* Implemented BR instruction

- added tests for instruction

* Arm64 syscall id register is X8

* Specified call and return instruction ID for implemented instruction

- BL Branch link is hinting the function call
- RET is hinting the function return

* Fixed compilation after merge

- new methods added isOperandRegister, getOperandAccess
- loadOpTernaryop1op2 probably changed to loadOpBinaryOrTernaryOp1Op2
- made sure all unit tests passed
- TODO: implement new conventions from master

* Generate pseudoasm instruction when translation routine is not found

- Function to generate condition code

* Check preconditions in implemented arm64 instructions

* Changed register generation to match other modules.

* LDR instruction all 3 formats + tests

- register
- imm
- literal (label)

* Binaries can now be decompiled

- jumpTargetDryRun updated

* Generate condition codes for conditional instructions.

* ARM64: strb, strh instructions + tests

* Arm64: conditional and unconditional branch instruction + tests

- removed the generation of conditional code in translate instruction function,
  this is not necessary because condition is generated in body of given
  instruction and arm64 support only specific instruction to be conditional.

* Arm64: Instruction ret can have optional register operand + test

* Arm64: BLR instruction + test

* Arm64: CBNZ, CBZ instruction + test

* Arm64: TBNZ, TBZ implementation + tests

* Arm64: LDR different size variants, sign/zero extend + tests

* Arm64: LDPSW instruction + tests

- minor warning fix in STR instruction

* Arm64: ADC instruction + tests

- including flag setting for ADC and ADD instructions
- ADDS tests

* Arm64: ADCS 32bit tests for flags

* Arm64: ADR, ADRP instruction + tests

* Arm64: AND, ANDS instruction + tests

* Arm64: ASR instruction + tests

- ASRV variant

* Arm64: LSL, LSR, ROR instructions + tests

- all major shifts implemented

* Arm64: SUB, SBC flags + tests

- changed asserts to exceptions

* Arm64: CMP, CMN instructions + tests

* Arm64: CSEL instruction + tests

* Arm64: CSET, CSETM instruction + tests

* Arm64: MUL instruction + tests

* Arm64: MADD instruction + tests

- 32bit tests for MUL

* Arm64: MSUB instruction + tests

* Arm64: MNEG instruction + tests

* Arm64: NEG, NEGS instruction + tests

* Arm64: NGC, NGCS initial implementation + tests

- Check the carry flags + add tests

* Arm64: SDIV, UDIV instruction + tests

* Arm64: Fix correct semantics for SBC and NEG instructions

* Arm64: SMADDL, UMADDL instruction + tests

* Arm64: UMSUBL, SMSUBL instruction + tests

* Arm64: SMNEG, UMNEG instruction + tests

* Arm64: UMULL, SMULL, UMULH, SMULH instruction + tests

* Arm64: Conditional select operation instruction + tests

* Arm64: CINC, CINV, CNEG tests

* Arm64: EON, EOR instruction + tests

* Arm64: ORN, ORR instruction + tests

* Arm64: TST instruction + tests

- fixed the AND instruction to set carry and overflow flags to zero

* Arm64: EXTR instruction + tests

* Arm64: Extend instructions + tests

* Arm64: CCMN, CCMP instruction + tests

* Arm64: NOP instruction + tests

* Arm64: REV, RBIT, CLZ instructions + tests

* Arm64: BIC instruction + tests

* Arm64: Unpriviledged loads/stores instructions + tests

* Arm64: Load/Store exclusive instructions + tests

* ARM64: LDAXR instruction variants + tests

* Arm64: LDAR instruction variants + tests

* Arm64, llvmir-emul: don't lower bitreverse intrinsic

- updated tests to check if the correct intrinsic functions was
  called

* Arm64: FP environment + basic unary and binary operations + tests

* Arm64: FMIN, FMINNM, FMAX, FMAXNM instruction + tests

* Arm64: FCMP, FCCMP, FCVT, {U, S}CVTF instructions + tests

* Arm64: FCVTZS, FCVTZU instructions + tests

- let's start testing

* Arm64, bin2llvmir: Decoder should not analyse stack.

* Arm64: MOVK instruction + tests

* Arm64: MOVN instructions + tests

* Merge master with arm-prep

* Architecture: Change arm architectures to account for arm64

-> isArmOrThumb renamed to isArm32OrThumb
-> added isArm32 method
-> thumb is now set with a flag _thumbFlag

* Architecture: Removed the wrong architecture types

Now the enum eArch represents only general architecture and all
subtypes of architecture are checked to getBitSize() or _thumbFlag.

The function isArm() return true for every type of subarchitecture
e.g. {arm32, arm64 or thumb}

* Arm64: XZR loads zero and discards result when written

- Added some instruction IDs to branch types

* Arm64: STR and LDR instructions now determine correct register size

- For example 'str w0, [sp]' should store only 4bytes to stack pointer

* Arm64: Syscall optimalization and detection

Replace svc #0 with corresponding syscall decoded from previous assignments.

* Arm64: MOVI instructions + tests, Vector and half register

Generate Vector registers so in case the pseudo instructions with them
as operands is generated we don't crash. For the similar purpose I
changed the f16 in ARM64_REG_H* to i16 since half type in not
supported and we wan't to be able to at least generate pseudo instructions.

* Arm64: STR and LDR tests

Those tests target loading and storing floating point values.

* Arm64: Removed zero division semantics from llvmir

- Zero division is NOW undefined behaviour
- This caused problems in modulo idiom detection
- Also removed coresponding tests

* Arm64: FMOV instruction with immediate values

- Correctly handle imm values as operands of this instruction

* Revert "Arm64, bin2llvmir: Decoder should not analyse stack."

This reverts commit 7b88475.
This change caused other tests to fail.

* Arm64: Simplified and documented some code

- Removed unused code from decoder/arm64.cpp
- Fixed insnWrittesPcArm64 to work better
- Fixed Cond branch tests

* Arm64: Fixed documentation build
  • Loading branch information
MatejKastak authored and PeterMatula committed Mar 28, 2019
1 parent 91915c6 commit f07407f
Show file tree
Hide file tree
Showing 40 changed files with 12,920 additions and 74 deletions.
2 changes: 1 addition & 1 deletion deps/capstone/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -21,11 +21,11 @@ ExternalProject_Add(capstone-project
-DCAPSTONE_X86_ATT_DISABLE=OFF
# Enabled architectures.
-DCAPSTONE_ARM_SUPPORT=ON
-DCAPSTONE_ARM64_SUPPORT=ON
-DCAPSTONE_MIPS_SUPPORT=ON
-DCAPSTONE_PPC_SUPPORT=ON
-DCAPSTONE_X86_SUPPORT=ON
# Disabled architectures.
-DCAPSTONE_ARM64_SUPPORT=OFF
-DCAPSTONE_M68K_SUPPORT=OFF
-DCAPSTONE_SPARC_SUPPORT=OFF
-DCAPSTONE_SYSZ_SUPPORT=OFF
Expand Down
9 changes: 9 additions & 0 deletions include/retdec/bin2llvmir/optimizations/decoder/decoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,15 @@ class Decoder : public llvm::ModulePass
void patternsPseudoCall_arm(llvm::CallInst*& call, AsmInstruction& pAi);
cs_mode determineMode_arm(cs_insn* insn, utils::Address& target);

// ARM64 specific.
//
private:
std::size_t decodeJumpTargetDryRun_arm64(
const JumpTarget& jt,
ByteData bytes,
bool strict = false);
void patternsPseudoCall_arm64(llvm::CallInst*& call, AsmInstruction& pAi);

// MIPS specific.
//
private:
Expand Down
4 changes: 4 additions & 0 deletions include/retdec/bin2llvmir/optimizations/syscalls/syscalls.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ class SyscallFixer : public llvm::ModulePass
bool runArm_linux_32();
bool runArm_linux_32(AsmInstruction ai);

bool runArm64();
bool runArm64_linux_64();
bool runArm64_linux_64(AsmInstruction ai);

bool runMips();
bool runMips_linux();
bool runMips_linux(AsmInstruction ai);
Expand Down
35 changes: 35 additions & 0 deletions include/retdec/capstone2llvmir/arm64/arm64.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* @file include/retdec/capstone2llvmir/arm64/arm64.h
* @brief ARM64 specialization of translator's abstract public interface.
* @copyright (c) 2017 Avast Software, licensed under the MIT license
*/

#ifndef RETDEC_CAPSTONE2LLVMIR_ARM64_ARM64_H
#define RETDEC_CAPSTONE2LLVMIR_ARM64_ARM64_H

#include "retdec/capstone2llvmir/arm64/arm64_defs.h"
#include "retdec/capstone2llvmir/capstone2llvmir.h"

namespace retdec {
namespace capstone2llvmir {

/**
* ARM64 specialization of translator's abstract public interface.
*/
class Capstone2LlvmIrTranslatorArm64 : virtual public Capstone2LlvmIrTranslator
{
public:
virtual ~Capstone2LlvmIrTranslatorArm64() {};

public:
/**
* @return Capstone register that is parent to the specified Capstone
* register @p r. Register can be its own parent.
*/
virtual uint32_t getParentRegister(uint32_t r) const = 0;
};

} // namespace capstone2llvmir
} // namespace retdec

#endif /* RETDEC_CAPSTONE2LLVMIR_ARM64_ARM64_H */
21 changes: 21 additions & 0 deletions include/retdec/capstone2llvmir/arm64/arm64_defs.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
/**
* @file include/retdec/capstone2llvmir/arm64/arm64_defs.h
* @brief Additional (on top of Capstone) definitions for ARM64 translator.
* @copyright (c) 2017 Avast Software, licensed under the MIT license
*/

#ifndef RETDEC_CAPSTONE2LLVMIR_ARM64_ARM64_DEFS_H
#define RETDEC_CAPSTONE2LLVMIR_ARM64_ARM64_DEFS_H

#include <capstone/arm64.h>

enum arm64_reg_cpsr_flags
{
ARM64_REG_CPSR_N = ARM64_REG_ENDING + 1,
ARM64_REG_CPSR_Z,
ARM64_REG_CPSR_C,
ARM64_REG_CPSR_V,
ARM64_REG_PC,
};

#endif /* RETDEC_CAPSTONE2LLVMIR_ARM64_ARM64_DEFS_H */
1 change: 1 addition & 0 deletions include/retdec/capstone2llvmir/capstone2llvmir.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@

// These are additions to capstone - include them all here.
#include "retdec/capstone2llvmir/arm/arm_defs.h"
#include "retdec/capstone2llvmir/arm64/arm64_defs.h"
#include "retdec/capstone2llvmir/mips/mips_defs.h"
#include "retdec/capstone2llvmir/powerpc/powerpc_defs.h"
#include "retdec/capstone2llvmir/x86/x86_defs.h"
Expand Down
7 changes: 5 additions & 2 deletions include/retdec/config/architecture.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,10 @@ class Architecture
bool isPic32() const;
bool isMipsOrPic32() const;
bool isArm() const;
bool isArm32() const;
bool isArm64() const;
bool isThumb() const;
bool isArmOrThumb() const;
bool isArm32OrThumb() const;
bool isX86() const;
bool isX86_16() const;
bool isX86_32() const;
Expand All @@ -51,6 +52,8 @@ class Architecture
void setIsPic32();
void setIsArm();
void setIsThumb();
void setIsArm32();
void setIsArm64();
void setIsX86();
void setIsPpc();
void setIsEndianLittle();
Expand Down Expand Up @@ -84,7 +87,6 @@ class Architecture
MIPS,
PIC32,
ARM,
THUMB,
X86,
PPC,
};
Expand All @@ -97,6 +99,7 @@ class Architecture
private:
std::string _name;
unsigned _bitSize = 32;
bool _thumbFlag = false;
eEndian _endian = E_UNKNOWN;
eArch _arch = eArch::UNKNOWN;
};
Expand Down
13 changes: 8 additions & 5 deletions scripts/retdec-decompiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ def parse_args(args):
parser.add_argument('-a', '--arch',
dest='arch',
metavar='ARCH',
choices=['mips', 'pic32', 'arm', 'thumb', 'powerpc', 'x86', 'x86-64'],
help='Specify target architecture [mips|pic32|arm|thumb|powerpc|x86|x86-64].'
choices=['mips', 'pic32', 'arm', 'thumb', 'arm64', 'powerpc', 'x86', 'x86-64'],
help='Specify target architecture [mips|pic32|arm|thumb|arm64|powerpc|x86|x86-64].'
' Required if it cannot be autodetected from the input (e.g. raw mode, Intel HEX).')

parser.add_argument('-e', '--endian',
Expand Down Expand Up @@ -882,7 +882,10 @@ def decompile(self):
arch_full = arch_full.lower()

# Strip comments in parentheses and all trailing whitespace
self.arch = arch_full.split(' ')[0]
if 'aarch64' in arch_full:
self.arch = 'arm64'
else:
self.arch = arch_full.split(' ')[0]

# Get object file format.
self.format, _, _ = CmdRunner.run_cmd([config.CONFIGTOOL, self.config_file, '--read', '--format'], buffer_output=True)
Expand All @@ -905,7 +908,7 @@ def decompile(self):

ords_dir = ''
# Check whether the correct target architecture was specified.
if self.arch in ['arm', 'thumb']:
if self.arch in ['arm', 'thumb', 'arm64']:
ords_dir = config.ARM_ORDS_DIR
elif self.arch in ['x86', 'x86-64']:
ords_dir = config.X86_ORDS_DIR
Expand All @@ -917,7 +920,7 @@ def decompile(self):

self._cleanup()
utils.print_error('Unsupported target architecture \'%s\'. Supported architectures: '
'Intel x86, Intel x86-64, ARM, ARM + Thumb, MIPS, PIC32, PowerPC.' % self.arch)
'Intel x86, Intel x86-64, ARM, ARM + Thumb, ARM64, MIPS, PIC32, PowerPC.' % self.arch)
return 1

# Check file class (e.g. 'ELF32', 'ELF64'). At present, we can only decompile 32-bit files.
Expand Down
2 changes: 2 additions & 0 deletions src/bin2llvmir/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ set(BIN2LLVMIR_SOURCES
optimizations/cond_branch_opt/cond_branch_opt.cpp
optimizations/constants/constants.cpp
optimizations/decoder/arm.cpp
optimizations/decoder/arm64.cpp
optimizations/decoder/bbs.cpp
optimizations/decoder/decoder_ranges.cpp
optimizations/decoder/decoder_init.cpp
Expand Down Expand Up @@ -65,6 +66,7 @@ set(BIN2LLVMIR_SOURCES
optimizations/stack_pointer_ops/stack_pointer_ops.cpp
optimizations/value_protect/value_protect.cpp
optimizations/syscalls/arm.cpp
optimizations/syscalls/arm64.cpp
optimizations/syscalls/mips.cpp
optimizations/syscalls/syscalls.cpp
optimizations/syscalls/x86.cpp
Expand Down
111 changes: 111 additions & 0 deletions src/bin2llvmir/optimizations/decoder/arm64.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
/**
* @file src/bin2llvmir/optimizations/decoder/arm64.cpp
* @brief Decoding methods specific to ARM64 architecture.
* @copyright (c) 2017 Avast Software, licensed under the MIT license
*/

#include "retdec/bin2llvmir/optimizations/decoder/decoder.h"
#include "retdec/bin2llvmir/utils/capstone.h"
#include "retdec/utils/string.h"

using namespace retdec::utils;
using namespace retdec::capstone2llvmir;
using namespace llvm;

namespace retdec {
namespace bin2llvmir {

bool insnWrittesPcArm64(csh& ce, cs_insn* insn)
{
// Aarch64 reference manual states:
// Software cannot write directly to the PC. It can only
// be updated on a branch, exception entry or exception return.

// Set of instructions that can modify PC
const std::set<unsigned int> branch_instructions = {
ARM64_INS_B,
ARM64_INS_CBNZ,
ARM64_INS_CBZ,
ARM64_INS_TBNZ,
ARM64_INS_TBZ,
ARM64_INS_BL,
ARM64_INS_BLR,
ARM64_INS_BR,
ARM64_INS_RET,
ARM64_INS_ERET,
};

return (branch_instructions.count(insn->id) != 0);
}

bool looksLikeArm64FunctionStart(cs_insn* insn)
{
// Create stack frame 'stp x29, x30, [sp, -48]!'
return insn->id == ARM64_INS_STP;
}

std::size_t Decoder::decodeJumpTargetDryRun_arm64(
const JumpTarget& jt,
ByteData bytes,
bool strict)
{

if (strict)
{
return true;
}

static csh ce = _c2l->getCapstoneEngine();

uint64_t addr = jt.getAddress();
std::size_t nops = 0;
bool first = true;
// bytes.first -> Code
// bytes.second -> Code size
// addr -> Address of first instruction
while (cs_disasm_iter(ce, &bytes.first, &bytes.second, &addr, _dryCsInsn))
{

if (strict && first && !looksLikeArm64FunctionStart(_dryCsInsn))
{
return true;
}

if (jt.getType() == JumpTarget::eType::LEFTOVER
&& (first || nops > 0)
&& _abi->isNopInstruction(_dryCsInsn))
{
nops += _dryCsInsn->size;
}
else if (jt.getType() == JumpTarget::eType::LEFTOVER
&& nops > 0)
{
return nops;
}

if (_c2l->isControlFlowInstruction(*_dryCsInsn)
|| insnWrittesPcArm64(ce, _dryCsInsn))
{
return false;
}

first = false;
}

if (nops > 0)
{
return nops;
}

// There is a BB right after, that is not a function start.
//
if (getBasicBlockAtAddress(addr) && getFunctionAtAddress(addr) == nullptr)
{
return false;
}

return true;
}

} // namespace bin2llvmir
} // namespace retdec
12 changes: 8 additions & 4 deletions src/bin2llvmir/optimizations/decoder/decoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -376,10 +376,14 @@ std::size_t Decoder::decodeJumpTargetDryRun(
{
return decodeJumpTargetDryRun_x86(jt, bytes, strict);
}
else if (_config->getConfig().architecture.isArmOrThumb())
else if (_config->getConfig().architecture.isArm32OrThumb())
{
return decodeJumpTargetDryRun_arm(jt, bytes, strict);
}
else if (_config->getConfig().architecture.isArm64())
{
return decodeJumpTargetDryRun_arm64(jt, bytes, strict);
}
else if (_config->getConfig().architecture.isMipsOrPic32())
{
return decodeJumpTargetDryRun_mips(jt, bytes, strict);
Expand All @@ -400,7 +404,7 @@ std::size_t Decoder::decodeJumpTargetDryRun(

cs_mode Decoder::determineMode(cs_insn* insn, utils::Address& target)
{
if (_config->getConfig().architecture.isArmOrThumb())
if (_config->getConfig().architecture.isArm32OrThumb())
{
return determineMode_arm(insn, target);
}
Expand Down Expand Up @@ -472,7 +476,7 @@ bool Decoder::getJumpTargetsFromInstruction(
CallInst*& pCall = tr.branchCall;
auto nextAddr = addr + tr.size;

if (_config->getConfig().architecture.isArmOrThumb())
if (_config->getConfig().architecture.isArm32OrThumb())
{
AsmInstruction ai(tr.llvmInsn);
patternsPseudoCall_arm(pCall, ai);
Expand Down Expand Up @@ -1554,7 +1558,7 @@ void Decoder::finalizePseudoCalls()
// TODO: what about other possible LR stores? e.g. see
// patternsPseudoCall_arm().
//
if (_config->getConfig().architecture.isArmOrThumb()
if (_config->getConfig().architecture.isArm32OrThumb()
&& icf)
if (auto* st = dyn_cast<StoreInst>(i))
{
Expand Down
10 changes: 8 additions & 2 deletions src/bin2llvmir/optimizations/decoder/decoder_init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,17 @@ void Decoder::initTranslator()
case 32: basicMode = CS_MODE_32; break;
}
}
else if (a.isArmOrThumb()
else if (a.isArm32OrThumb()
&& a.getBitSize() == 32)
{
arch = CS_ARCH_ARM;
basicMode = CS_MODE_ARM; // We start with ARM mode even for THUMB.
}
else if (a.isArm64())
{
arch = CS_ARCH_ARM64;
basicMode = CS_MODE_ARM;
}
else
{
throw std::runtime_error("Unsupported architecture.");
Expand Down Expand Up @@ -188,7 +193,8 @@ void Decoder::initRanges()

auto& arch = _config->getConfig().architecture;
unsigned a = 0;
a = arch.isArmOrThumb() ? 2 : a;
a = arch.isArm32OrThumb() ? 2 : a;
a = arch.isArm64() ? 4 : a;
a = arch.isMipsOrPic32() ? 4 : a;
a = arch.isPpc() ? 4 : a;
_ranges.setArchitectureInstructionAlignment(a);
Expand Down
6 changes: 5 additions & 1 deletion src/bin2llvmir/optimizations/decoder/ir_modifications.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,10 +165,14 @@ llvm::GlobalVariable* Decoder::getCallReturnObject()
{
return _abi->getRegister(PPC_REG_R3);
}
else if (_config->getConfig().architecture.isArmOrThumb())
else if (_config->getConfig().architecture.isArm32OrThumb())
{
return _abi->getRegister(ARM_REG_R0);
}
else if (_config->getConfig().architecture.isArm64())
{
return _config->getLlvmRegister("r0");
}

assert(false);
return nullptr;
Expand Down
Loading

0 comments on commit f07407f

Please sign in to comment.