Skip to content

Commit

Permalink
Add support for AArch64 operands
Browse files Browse the repository at this point in the history
  • Loading branch information
romainthomas committed Dec 7, 2024
1 parent 8dc62e8 commit c1a7332
Show file tree
Hide file tree
Showing 42 changed files with 1,625 additions and 2 deletions.
10 changes: 10 additions & 0 deletions api/python/lief/assembly/aarch64/__init__.pyi
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import enum
from typing import Iterator, Optional, Union

from . import operands as operands
import lief


class Instruction(lief.assembly.Instruction):
@property
def opcode(self) -> OPCODE: ...

@property
def operands(self) -> Iterator[Optional[Operand]]: ...

class OPCODE(enum.Enum):
PHI = 0

Expand Down Expand Up @@ -16355,6 +16359,12 @@ class OPCODE(enum.Enum):

INSTRUCTION_LIST_END = 8172

class Operand:
@property
def to_string(self) -> str: ...

def __str__(self) -> str: ...

class REG(enum.Enum):
NoRegister = 0

Expand Down
48 changes: 48 additions & 0 deletions api/python/lief/assembly/aarch64/operands/__init__.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import enum
import lief.assembly.aarch64
from typing import Iterator, Optional, Union

import lief


class Immediate(lief.assembly.aarch64.Operand):
@property
def value(self) -> int: ...

class Memory(lief.assembly.aarch64.Operand):
class SHIFT(enum.Enum):
UNKNOWN = 0

LSL = 1

UXTX = 2

UXTW = 3

SXTX = 4

SXTW = 5

class shift_info_t:
@property
def type(self) -> Memory.SHIFT: ...

@property
def value(self) -> int: ...

@property
def base(self) -> lief.assembly.aarch64.REG: ...

@property
def offset(self) -> Optional[Union[lief.assembly.aarch64.REG, int]]: ...

@property
def shift(self) -> Memory.shift_info_t: ...

class PCRelative(lief.assembly.aarch64.Operand):
@property
def value(self) -> int: ...

class Register(lief.assembly.aarch64.Operand):
@property
def value(self) -> Optional[Union[lief.assembly.aarch64.REG, lief.assembly.aarch64.SYSREG]]: ...
2 changes: 1 addition & 1 deletion api/python/src/DyldSharedCache/pyDyldSharedCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -226,7 +226,7 @@ void create<dsc::DyldSharedCache>(nb::module_& m) {
R"doc(
Convert the given virtual address into an offset.
.. code-block:: warning
.. warning::
If the shared cache contains multiple subcaches,
this function needs to be called on the targeted subcache.
Expand Down
2 changes: 2 additions & 0 deletions api/python/src/asm/aarch64/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ target_sources(pyLIEF PRIVATE
init.cpp
pyInstruction.cpp
pyOpcode.cpp
pyOperand.cpp
pyRegister.cpp
)

add_subdirectory(operands)
2 changes: 2 additions & 0 deletions api/python/src/asm/aarch64/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ enum class OPCODE;
enum class REG;
enum class SYSREG;
class Instruction;
class Operand;
}

namespace LIEF::assembly::aarch64::py {
Expand All @@ -14,5 +15,6 @@ void init(nb::module_& m) {
create<REG>(mod);
create<SYSREG>(mod);
create<Instruction>(mod);
create<Operand>(mod);
}
}
6 changes: 6 additions & 0 deletions api/python/src/asm/aarch64/operands/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
target_sources(pyLIEF PRIVATE
pyImmediate.cpp
pyRegister.cpp
pyMemory.cpp
pyPCRelative.cpp
)
26 changes: 26 additions & 0 deletions api/python/src/asm/aarch64/operands/pyImmediate.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#include "asm/aarch64/init.hpp"
#include "LIEF/asm/aarch64/operands/Immediate.hpp"

namespace LIEF::assembly::aarch64::py {
template<>
void create<aarch64::operands::Immediate>(nb::module_& m) {
nb::class_<aarch64::operands::Immediate, aarch64::Operand> obj(m, "Immediate",
R"doc(
This class represents an immediate operand (i.e. a constant)
For instance:
.. code-block:: text
mov x0, #8;
|
+---> Immediate(8)
)doc"_doc
);

obj
.def_prop_ro("value", &operands::Immediate::value,
R"doc(The constant value wrapped by this operand)doc"_doc
)
;
}
}
101 changes: 101 additions & 0 deletions api/python/src/asm/aarch64/operands/pyMemory.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
#include <nanobind/nanobind.h>

#include "asm/aarch64/init.hpp"
#include "LIEF/asm/aarch64/operands/Memory.hpp"

namespace nanobind::detail {
template<>
struct type_caster<LIEF::assembly::aarch64::operands::Memory::offset_t> {
NB_TYPE_CASTER(LIEF::assembly::aarch64::operands::Memory::offset_t,
const_name("Optional[Union[lief.assembly.aarch64.REG, int]]"));

bool from_python(handle src, uint8_t, cleanup_list *) noexcept {
return false;
}

static handle from_cpp(LIEF::assembly::aarch64::operands::Memory::offset_t val,
rv_policy, cleanup_list *) noexcept
{
using namespace LIEF::assembly::aarch64;
using namespace LIEF::assembly::aarch64::operands;
switch (val.type) {
case Memory::offset_t::TYPE::REG:
return make_caster<REG>::from_cpp(val.reg, rv_policy::copy,
/*cleanup_list*/nullptr);

case Memory::offset_t::TYPE::DISP:
return make_caster<int64_t>::from_cpp(val.displacement, rv_policy::copy,
/*cleanup_list*/nullptr);
case Memory::offset_t::TYPE::NONE:
return nb::none();
}
return nb::none();
}
};
}


namespace LIEF::assembly::aarch64::py {
template<>
void create<aarch64::operands::Memory>(nb::module_& m) {
nb::class_<aarch64::operands::Memory, aarch64::Operand> obj(m, "Memory",
R"doc(
This class represents a memory operand.
.. code-block:: text
ldr x0, [x1, x2, lsl #3]
| | |
+------------+ | +--------+
| | |
v v v
Base Reg Offset Shift
)doc"_doc
);

nb::enum_<operands::Memory::SHIFT>(obj, "SHIFT")
.value("UNKNOWN", operands::Memory::SHIFT::UNKNOWN)
.value("LSL", operands::Memory::SHIFT::LSL)
.value("UXTX", operands::Memory::SHIFT::UXTX)
.value("UXTW", operands::Memory::SHIFT::UXTW)
.value("SXTX", operands::Memory::SHIFT::SXTX)
.value("SXTW", operands::Memory::SHIFT::SXTW)
;

nb::class_<operands::Memory::shift_info_t>(obj, "shift_info_t",
R"doc(This structure holds shift info (type + value))doc"_doc
)
.def_ro("type", &operands::Memory::shift_info_t::type)
.def_ro("value", &operands::Memory::shift_info_t::value)
;

obj
.def_prop_ro("base", &operands::Memory::base,
R"doc(
The base register.
For ``str x3, [x8, #8]`` it would return ``x8``.
)doc"_doc
)
.def_prop_ro("offset", &operands::Memory::offset,
R"doc(
The addressing offset.
It can be either:
- A register (e.g. ``ldr x0, [x1, x3]``)
- An offset (e.g. ``ldr x0, [x1, #8]``)
)doc"_doc
)
.def_prop_ro("shift", &operands::Memory::shift,
R"doc(
Shift information.
For instance, for ``ldr x1, [x2, x3, lsl #3]`` it would
return a :attr:`~.Memory.SHIFT.LSL` with a :attr:`~.Memory.shift_info_t.value`
set to ``3``.
)doc"_doc
)
;
}
}
28 changes: 28 additions & 0 deletions api/python/src/asm/aarch64/operands/pyPCRelative.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#include "asm/aarch64/init.hpp"
#include "LIEF/asm/aarch64/operands/PCRelative.hpp"

namespace LIEF::assembly::aarch64::py {
template<>
void create<aarch64::operands::PCRelative>(nb::module_& m) {
nb::class_<aarch64::operands::PCRelative, aarch64::Operand> obj(m, "PCRelative",
R"doc(
This class represents a PC-relative operand.
.. code-block:: text
ldr x0, #8
|
v
PC Relative operand
)doc"_doc
);

obj
.def_prop_ro("value", &aarch64::operands::PCRelative::value,
R"doc(
The effective value that is relative to the current ``pc`` register
)doc"_doc
)
;
}
}
66 changes: 66 additions & 0 deletions api/python/src/asm/aarch64/operands/pyRegister.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#include <nanobind/nanobind.h>

#include "asm/aarch64/init.hpp"
#include "LIEF/asm/aarch64/operands/Register.hpp"

namespace nanobind::detail {
template<>
struct type_caster<LIEF::assembly::aarch64::operands::Register::reg_t> {
NB_TYPE_CASTER(LIEF::assembly::aarch64::operands::Register::reg_t,
const_name("Optional[Union[lief.assembly.aarch64.REG, lief.assembly.aarch64.SYSREG]]"));

bool from_python(handle src, uint8_t, cleanup_list *) noexcept {
return false;
}

static handle from_cpp(LIEF::assembly::aarch64::operands::Register::reg_t val,
rv_policy, cleanup_list *) noexcept
{
using namespace LIEF::assembly::aarch64;
using namespace LIEF::assembly::aarch64::operands;
switch (val.type) {
case Register::reg_t::TYPE::REG:
return make_caster<REG>::from_cpp(val.reg, rv_policy::copy,
/*cleanup_list*/nullptr);

case Register::reg_t::TYPE::SYSREG:
return make_caster<SYSREG>::from_cpp(val.sysreg, rv_policy::copy,
/*cleanup_list*/nullptr);
case Register::reg_t::TYPE::NONE:
return nb::none();
}
return nb::none();
}
};
}

namespace LIEF::assembly::aarch64::py {
template<>
void create<aarch64::operands::Register>(nb::module_& m) {
nb::class_<aarch64::operands::Register, aarch64::Operand> obj(m, "Register",
R"doc(
This class represents a register operand.
.. code-block:: text
mrs x0, TPIDR_EL0
| |
+------+ +-------+
| |
v v
REG SYSREG
)doc"_doc
);

obj
.def_prop_ro("value", &operands::Register::value,
R"doc(
The effective register as either: a :class:`lief.assembly.aarch64.REG` or
a :class:`lief.assembly.aarch64.SYSREG`.
)doc"_doc
)
;


}
}
13 changes: 13 additions & 0 deletions api/python/src/asm/aarch64/pyInstruction.cpp
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
#include "LIEF/asm/aarch64/Instruction.hpp"
#include "LIEF/asm/aarch64/Operand.hpp"

#include <nanobind/make_iterator.h>

#include "asm/aarch64/init.hpp"

#include <nanobind/stl/unique_ptr.h>

namespace LIEF::assembly::aarch64::py {
template<>
void create<aarch64::Instruction>(nb::module_& m) {
Expand All @@ -15,6 +20,14 @@ void create<aarch64::Instruction>(nb::module_& m) {
.def_prop_ro("opcode", &Instruction::opcode,
R"doc(The instruction opcode as defined in LLVM)doc"_doc
)
.def_prop_ro("operands", [] (const aarch64::Instruction& self) {
auto ops = self.operands();
return nb::make_iterator<nb::rv_policy::reference_internal>(
nb::type<aarch64::Instruction>(), "operands_it", ops
);
}, nb::keep_alive<0, 1>(),
R"doc(Iterator over the operands of the current instruction)doc"_doc
)
;
}
}
Loading

0 comments on commit c1a7332

Please sign in to comment.