Merge pull request #64 from Decompollaborate/develop

1.11.1
This commit is contained in:
Anghelo Carvajal 2024-07-12 11:50:25 -04:00 committed by GitHub
commit 4493e611ac
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 73 additions and 8 deletions

View File

@ -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

View File

@ -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"

View File

@ -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>.

View File

@ -198,6 +198,7 @@ namespace rabbitizer {
bool isLikelyHandwritten() const;
bool isNop() const;
bool isUnconditionalBranch() const;
bool isFunctionCall() const;
bool isReturn() const;
bool isJumptableJump() const;

View File

@ -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);

View File

@ -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)

View File

@ -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);

View File

@ -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"

View File

@ -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

View File

@ -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, ""),

View File

@ -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) }

View File

@ -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;
}

View File

@ -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.