mirror of
https://github.com/Decompollaborate/rabbitizer.git
synced 2024-12-26 00:16:28 +00:00
commit
4493e611ac
16
CHANGELOG.md
16
CHANGELOG.md
@ -7,6 +7,21 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
## [1.11.1] - 2024-07-12
|
||||
|
||||
### Added
|
||||
|
||||
- `Instruction.isFunctionCall`: Checks if the given instruciton is a function
|
||||
call.
|
||||
- If `config.toolchainTweaks_treatJAsUnconditionalBranch` is turned off then
|
||||
`j` instructions will be considered as function calls too. Useful for tail
|
||||
call optimizations.
|
||||
|
||||
### Fixed
|
||||
|
||||
- Fix registers not being cleared after a `j` tail call, which was messing with
|
||||
the pointer pairing logic.
|
||||
|
||||
## [1.11.0] - 2024-05-22
|
||||
|
||||
### Added
|
||||
@ -618,6 +633,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- First version
|
||||
|
||||
[unreleased]: https://github.com/Decompollaborate/rabbitizer/compare/master...develop
|
||||
[1.11.1]: https://github.com/Decompollaborate/rabbitizer/compare/1.11.0...1.11.1
|
||||
[1.11.0]: https://github.com/Decompollaborate/rabbitizer/compare/1.10.0...1.11.0
|
||||
[1.10.0]: https://github.com/Decompollaborate/rabbitizer/compare/1.9.5...1.10.0
|
||||
[1.9.5]: https://github.com/Decompollaborate/rabbitizer/compare/1.9.4...1.9.5
|
||||
|
@ -4,7 +4,7 @@
|
||||
[package]
|
||||
name = "rabbitizer"
|
||||
# Version should be synced with include/common/RabbitizerVersion.h
|
||||
version = "1.11.0"
|
||||
version = "1.11.1"
|
||||
edition = "2021"
|
||||
authors = ["Anghelo Carvajal <angheloalf95@gmail.com>"]
|
||||
description = "MIPS instruction decoder"
|
||||
|
@ -69,7 +69,7 @@ If you use a `requirements.txt` file in your repository, then you can add this
|
||||
library with the following line:
|
||||
|
||||
```txt
|
||||
rabbitizer>=1.11.0,<2.0.0
|
||||
rabbitizer>=1.11.1,<2.0.0
|
||||
```
|
||||
|
||||
### Development version
|
||||
@ -109,7 +109,7 @@ cargo add rabbitizer
|
||||
Or you can add it manually to your `Cargo.toml`:
|
||||
|
||||
```toml
|
||||
rabbitizer = "1.11.0"
|
||||
rabbitizer = "1.11.1"
|
||||
```
|
||||
|
||||
See this crate at <https://crates.io/crates/rabbitizer>.
|
||||
|
@ -198,6 +198,7 @@ namespace rabbitizer {
|
||||
bool isLikelyHandwritten() const;
|
||||
bool isNop() const;
|
||||
bool isUnconditionalBranch() const;
|
||||
bool isFunctionCall() const;
|
||||
|
||||
bool isReturn() const;
|
||||
bool isJumptableJump() const;
|
||||
|
@ -787,6 +787,9 @@ bool InstructionBase::isNop() const {
|
||||
bool InstructionBase::isUnconditionalBranch() const {
|
||||
return RabbitizerInstruction_isUnconditionalBranch(&this->instr);
|
||||
}
|
||||
bool InstructionBase::isFunctionCall() const {
|
||||
return RabbitizerInstruction_isFunctionCall(&this->instr);
|
||||
}
|
||||
|
||||
bool InstructionBase::isReturn() const {
|
||||
return RabbitizerInstruction_isReturn(&this->instr);
|
||||
|
@ -14,7 +14,7 @@ extern "C" {
|
||||
// Header version
|
||||
#define RAB_VERSION_MAJOR 1
|
||||
#define RAB_VERSION_MINOR 11
|
||||
#define RAB_VERSION_PATCH 0
|
||||
#define RAB_VERSION_PATCH 1
|
||||
|
||||
#define RAB_VERSION_STR RAB_STRINGIFY(RAB_VERSION_MAJOR) "." RAB_STRINGIFY(RAB_VERSION_MINOR) "." RAB_STRINGIFY(RAB_VERSION_PATCH)
|
||||
|
||||
|
@ -241,6 +241,8 @@ NODISCARD NON_NULL(1) PURE
|
||||
bool RabbitizerInstruction_isNop(const RabbitizerInstruction *self);
|
||||
NODISCARD NON_NULL(1) PURE
|
||||
bool RabbitizerInstruction_isUnconditionalBranch(const RabbitizerInstruction *self);
|
||||
NODISCARD NON_NULL(1) PURE
|
||||
bool RabbitizerInstruction_isFunctionCall(const RabbitizerInstruction *self);
|
||||
|
||||
NODISCARD NON_NULL(1) PURE
|
||||
bool RabbitizerInstruction_isReturn(const RabbitizerInstruction *self);
|
||||
|
@ -4,7 +4,7 @@
|
||||
[project]
|
||||
name = "rabbitizer"
|
||||
# Version should be synced with include/common/RabbitizerVersion.h
|
||||
version = "1.11.0"
|
||||
version = "1.11.1"
|
||||
description = "MIPS instruction decoder"
|
||||
# license = "MIT"
|
||||
readme = "README.md"
|
||||
|
@ -181,7 +181,7 @@ class Instruction:
|
||||
def isNop(self) -> bool:
|
||||
"""Check if the instruction is literally the `nop` instruction."""
|
||||
def isUnconditionalBranch(self) -> bool:
|
||||
"""Check if the instruction is an instruction that will always (unconditionally).
|
||||
"""Check if the instruction is an instruction that will always branch unconditionally.
|
||||
|
||||
This is always true for the `b` instruction.
|
||||
|
||||
@ -190,6 +190,17 @@ class Instruction:
|
||||
can be configured with the `config.toolchainTweaks_treatJAsUnconditionalBranch`
|
||||
option.
|
||||
"""
|
||||
def isFunctionCall(self) -> bool:
|
||||
"""Check if this is an instruction used for function calls.
|
||||
|
||||
This is always true for "and link" instructions.
|
||||
|
||||
Some compilers use the `j` instruction for tail call optimizations, meaning
|
||||
we may require to give special treatment to this instruction if we are
|
||||
analyzing code emitted by one of those compilers, like clearing registers
|
||||
after a tail call. This can be configured by turning off the
|
||||
`config.toolchainTweaks_treatJAsUnconditionalBranch` option.
|
||||
"""
|
||||
|
||||
def isReturn(self) -> bool:
|
||||
"""Check if the instruction and its register is the one usually used for
|
||||
|
@ -386,6 +386,7 @@ DEF_METHOD_BOOL(isImplemented)
|
||||
DEF_METHOD_BOOL(isLikelyHandwritten)
|
||||
DEF_METHOD_BOOL(isNop)
|
||||
DEF_METHOD_BOOL(isUnconditionalBranch)
|
||||
DEF_METHOD_BOOL(isFunctionCall)
|
||||
|
||||
DEF_METHOD_BOOL(isReturn)
|
||||
DEF_METHOD_BOOL(isJumptableJump)
|
||||
@ -650,6 +651,7 @@ static PyMethodDef rabbitizer_type_Instruction_methods[] = {
|
||||
METHOD_NO_ARGS(isLikelyHandwritten, ""),
|
||||
METHOD_NO_ARGS(isNop, ""),
|
||||
METHOD_NO_ARGS(isUnconditionalBranch, ""),
|
||||
METHOD_NO_ARGS(isFunctionCall, ""),
|
||||
|
||||
METHOD_NO_ARGS(isReturn, ""),
|
||||
METHOD_NO_ARGS(isJumptableJump, ""),
|
||||
|
@ -84,6 +84,7 @@ extern "C" {
|
||||
fn RabbitizerInstruction_isLikelyHandwritten(self_: *const Instruction) -> bool;
|
||||
fn RabbitizerInstruction_isNop(self_: *const Instruction) -> bool;
|
||||
fn RabbitizerInstruction_isUnconditionalBranch(self_: *const Instruction) -> bool;
|
||||
fn RabbitizerInstruction_isFunctionCall(self_: *const Instruction) -> bool;
|
||||
fn RabbitizerInstruction_isReturn(self_: *const Instruction) -> bool;
|
||||
fn RabbitizerInstruction_isJumptableJump(self_: *const Instruction) -> bool;
|
||||
|
||||
@ -546,6 +547,9 @@ impl Instruction {
|
||||
pub fn is_unconditional_branch(&self) -> bool {
|
||||
unsafe { RabbitizerInstruction_isUnconditionalBranch(self) }
|
||||
}
|
||||
pub fn is_function_call(&self) -> bool {
|
||||
unsafe { RabbitizerInstruction_isFunctionCall(self) }
|
||||
}
|
||||
|
||||
pub fn is_return(&self) -> bool {
|
||||
unsafe { RabbitizerInstruction_isReturn(self) }
|
||||
|
@ -147,7 +147,7 @@ void RabbitizerRegistersTracker_overwriteRegisters(RabbitizerRegistersTracker *s
|
||||
void RabbitizerRegistersTracker_unsetRegistersAfterFuncCall(RabbitizerRegistersTracker *self,
|
||||
UNUSED const RabbitizerInstruction *instr,
|
||||
const RabbitizerInstruction *prevInstr) {
|
||||
if (!RabbitizerInstrDescriptor_doesLink(prevInstr->descriptor)) {
|
||||
if (!RabbitizerInstruction_isFunctionCall(prevInstr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -52,7 +52,7 @@ bool RabbitizerInstruction_isNop(const RabbitizerInstruction *self) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the instruction is an instruction that will always (unconditionally).
|
||||
* Check if the instruction is an instruction that will always branch unconditionally.
|
||||
*
|
||||
* This is always true for the `b` instruction.
|
||||
*
|
||||
@ -81,6 +81,32 @@ bool RabbitizerInstruction_isUnconditionalBranch(const RabbitizerInstruction *se
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if this is an instruction used for function calls.
|
||||
*
|
||||
* This is always true for "and link" instructions.
|
||||
*
|
||||
* Some compilers use the `j` instruction for tail call optimizations, meaning
|
||||
* we may require to give special treatment to this instruction if we are
|
||||
* analyzing code emitted by one of those compilers, like clearing registers
|
||||
* after a tail call. This can be configured by turning off the
|
||||
* `config.toolchainTweaks_treatJAsUnconditionalBranch` option.
|
||||
*/
|
||||
bool RabbitizerInstruction_isFunctionCall(const RabbitizerInstruction *self) {
|
||||
if (RabbitizerInstrDescriptor_doesLink(self->descriptor)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (self->uniqueId) {
|
||||
case RABBITIZER_INSTR_ID_cpu_j:
|
||||
case RABBITIZER_INSTR_ID_rsp_j:
|
||||
return !RabbitizerConfig_Cfg.toolchainTweaks.treatJAsUnconditionalBranch;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the instruction and its register is the one usually used for
|
||||
* returning from a function.
|
||||
|
Loading…
Reference in New Issue
Block a user