summaryrefslogtreecommitdiff
path: root/rust/src/llil/operation.rs
diff options
context:
space:
mode:
Diffstat (limited to 'rust/src/llil/operation.rs')
-rw-r--r--rust/src/llil/operation.rs825
1 files changed, 0 insertions, 825 deletions
diff --git a/rust/src/llil/operation.rs b/rust/src/llil/operation.rs
deleted file mode 100644
index b65dfa8c..00000000
--- a/rust/src/llil/operation.rs
+++ /dev/null
@@ -1,825 +0,0 @@
-// Copyright 2021-2024 Vector 35 Inc.
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-use binaryninjacore_sys::{BNGetLowLevelILByIndex, BNLowLevelILInstruction};
-
-use std::collections::BTreeMap;
-use std::marker::PhantomData;
-use std::mem;
-
-use super::*;
-
-pub struct Operation<'func, A, M, F, O>
-where
- A: 'func + Architecture,
- M: FunctionMutability,
- F: FunctionForm,
- O: OperationArguments,
-{
- pub(crate) function: &'func Function<A, M, F>,
- pub(crate) op: BNLowLevelILInstruction,
- _args: PhantomData<O>,
-}
-
-impl<'func, A, M, F, O> Operation<'func, A, M, F, O>
-where
- A: 'func + Architecture,
- M: FunctionMutability,
- F: FunctionForm,
- O: OperationArguments,
-{
- pub(crate) fn new(function: &'func Function<A, M, F>, op: BNLowLevelILInstruction) -> Self {
- Self {
- function,
- op,
- _args: PhantomData,
- }
- }
-
- pub fn address(&self) -> u64 {
- self.op.address
- }
-}
-
-impl<'func, A, M, O> Operation<'func, A, M, NonSSA<LiftedNonSSA>, O>
-where
- A: 'func + Architecture,
- M: FunctionMutability,
- O: OperationArguments,
-{
- pub fn flag_write(&self) -> Option<A::FlagWrite> {
- match self.op.flags {
- 0 => None,
- id => self.function.arch().flag_write_from_id(id),
- }
- }
-}
-
-// LLIL_NOP, LLIL_NORET, LLIL_BP, LLIL_UNDEF, LLIL_UNIMPL
-pub struct NoArgs;
-
-// LLIL_POP
-pub struct Pop;
-
-impl<'func, A, M, F> Operation<'func, A, M, F, Pop>
-where
- A: 'func + Architecture,
- M: FunctionMutability,
- F: FunctionForm,
-{
- pub fn size(&self) -> usize {
- self.op.size
- }
-}
-
-// LLIL_SYSCALL, LLIL_SYSCALL_SSA
-pub struct Syscall;
-
-// LLIL_INTRINSIC, LLIL_INTRINSIC_SSA
-pub struct Intrinsic;
-
-impl<'func, A, M, V> Operation<'func, A, M, NonSSA<V>, Intrinsic>
-where
- A: 'func + Architecture,
- M: FunctionMutability,
- V: NonSSAVariant,
-{
- // TODO: Support register and expression lists
- pub fn intrinsic(&self) -> Option<A::Intrinsic> {
- let raw_id = self.op.operands[2] as u32;
- self.function.arch().intrinsic_from_id(raw_id)
- }
-}
-
-// LLIL_SET_REG, LLIL_SET_REG_SSA, LLIL_SET_REG_PARTIAL_SSA
-pub struct SetReg;
-
-impl<'func, A, M, V> Operation<'func, A, M, NonSSA<V>, SetReg>
-where
- A: 'func + Architecture,
- M: FunctionMutability,
- V: NonSSAVariant,
-{
- pub fn size(&self) -> usize {
- self.op.size
- }
-
- pub fn dest_reg(&self) -> Register<A::Register> {
- let raw_id = self.op.operands[0] as u32;
-
- if raw_id >= 0x8000_0000 {
- Register::Temp(raw_id & 0x7fff_ffff)
- } else {
- self.function
- .arch()
- .register_from_id(raw_id)
- .map(Register::ArchReg)
- .unwrap_or_else(|| {
- error!(
- "got garbage register from LLIL_SET_REG @ 0x{:x}",
- self.op.address
- );
-
- Register::Temp(0)
- })
- }
- }
-
- pub fn source_expr(&self) -> Expression<'func, A, M, NonSSA<V>, ValueExpr> {
- Expression::new(self.function, self.op.operands[1] as usize)
- }
-}
-
-// LLIL_SET_REG_SPLIT, LLIL_SET_REG_SPLIT_SSA
-pub struct SetRegSplit;
-
-impl<'func, A, M, V> Operation<'func, A, M, NonSSA<V>, SetRegSplit>
-where
- A: 'func + Architecture,
- M: FunctionMutability,
- V: NonSSAVariant,
-{
- pub fn size(&self) -> usize {
- self.op.size
- }
-
- pub fn dest_reg_high(&self) -> Register<A::Register> {
- let raw_id = self.op.operands[0] as u32;
-
- if raw_id >= 0x8000_0000 {
- Register::Temp(raw_id & 0x7fff_ffff)
- } else {
- self.function
- .arch()
- .register_from_id(raw_id)
- .map(Register::ArchReg)
- .unwrap_or_else(|| {
- error!(
- "got garbage register from LLIL_SET_REG_SPLIT @ 0x{:x}",
- self.op.address
- );
-
- Register::Temp(0)
- })
- }
- }
-
- pub fn dest_reg_low(&self) -> Register<A::Register> {
- let raw_id = self.op.operands[1] as u32;
-
- if raw_id >= 0x8000_0000 {
- Register::Temp(raw_id & 0x7fff_ffff)
- } else {
- self.function
- .arch()
- .register_from_id(raw_id)
- .map(Register::ArchReg)
- .unwrap_or_else(|| {
- error!(
- "got garbage register from LLIL_SET_REG_SPLIT @ 0x{:x}",
- self.op.address
- );
-
- Register::Temp(0)
- })
- }
- }
-
- pub fn source_expr(&self) -> Expression<'func, A, M, NonSSA<V>, ValueExpr> {
- Expression::new(self.function, self.op.operands[2] as usize)
- }
-}
-
-// LLIL_SET_FLAG, LLIL_SET_FLAG_SSA
-pub struct SetFlag;
-
-impl<'func, A, M, V> Operation<'func, A, M, NonSSA<V>, SetFlag>
-where
- A: 'func + Architecture,
- M: FunctionMutability,
- V: NonSSAVariant,
-{
- pub fn source_expr(&self) -> Expression<'func, A, M, NonSSA<V>, ValueExpr> {
- Expression::new(self.function, self.op.operands[1] as usize)
- }
-}
-
-// LLIL_LOAD, LLIL_LOAD_SSA
-pub struct Load;
-
-impl<'func, A, M, V> Operation<'func, A, M, NonSSA<V>, Load>
-where
- A: 'func + Architecture,
- M: FunctionMutability,
- V: NonSSAVariant,
-{
- pub fn size(&self) -> usize {
- self.op.size
- }
-
- pub fn source_mem_expr(&self) -> Expression<'func, A, M, NonSSA<V>, ValueExpr> {
- Expression::new(self.function, self.op.operands[0] as usize)
- }
-}
-
-// LLIL_STORE, LLIL_STORE_SSA
-pub struct Store;
-
-impl<'func, A, M, V> Operation<'func, A, M, NonSSA<V>, Store>
-where
- A: 'func + Architecture,
- M: FunctionMutability,
- V: NonSSAVariant,
-{
- pub fn size(&self) -> usize {
- self.op.size
- }
-
- pub fn dest_mem_expr(&self) -> Expression<'func, A, M, NonSSA<V>, ValueExpr> {
- Expression::new(self.function, self.op.operands[0] as usize)
- }
-
- pub fn source_expr(&self) -> Expression<'func, A, M, NonSSA<V>, ValueExpr> {
- Expression::new(self.function, self.op.operands[1] as usize)
- }
-}
-
-// LLIL_REG, LLIL_REG_SSA, LLIL_REG_SSA_PARTIAL
-pub struct Reg;
-
-impl<'func, A, M, V> Operation<'func, A, M, NonSSA<V>, Reg>
-where
- A: 'func + Architecture,
- M: FunctionMutability,
- V: NonSSAVariant,
-{
- pub fn size(&self) -> usize {
- self.op.size
- }
-
- pub fn source_reg(&self) -> Register<A::Register> {
- let raw_id = self.op.operands[0] as u32;
-
- if raw_id >= 0x8000_0000 {
- Register::Temp(raw_id & 0x7fff_ffff)
- } else {
- self.function
- .arch()
- .register_from_id(raw_id)
- .map(Register::ArchReg)
- .unwrap_or_else(|| {
- error!(
- "got garbage register from LLIL_REG @ 0x{:x}",
- self.op.address
- );
-
- Register::Temp(0)
- })
- }
- }
-}
-
-// LLIL_REG_SPLIT
-pub struct RegSplit;
-
-impl<'func, A, M, V> Operation<'func, A, M, NonSSA<V>, RegSplit>
- where
- A: 'func + Architecture,
- M: FunctionMutability,
- V: NonSSAVariant,
-{
- pub fn size(&self) -> usize {
- self.op.size
- }
-
- pub fn low_reg(&self) -> Register<A::Register> {
- let raw_id = self.op.operands[0] as u32;
-
- if raw_id >= 0x8000_0000 {
- Register::Temp(raw_id & 0x7fff_ffff)
- } else {
- self.function
- .arch()
- .register_from_id(raw_id)
- .map(Register::ArchReg)
- .unwrap_or_else(|| {
- error!(
- "got garbage register from LLIL_REG @ 0x{:x}",
- self.op.address
- );
-
- Register::Temp(0)
- })
- }
- }
-
- pub fn high_reg(&self) -> Register<A::Register> {
- let raw_id = self.op.operands[1] as u32;
-
- if raw_id >= 0x8000_0000 {
- Register::Temp(raw_id & 0x7fff_ffff)
- } else {
- self.function
- .arch()
- .register_from_id(raw_id)
- .map(Register::ArchReg)
- .unwrap_or_else(|| {
- error!(
- "got garbage register from LLIL_REG @ 0x{:x}",
- self.op.address
- );
-
- Register::Temp(0)
- })
- }
- }
-}
-
-// LLIL_FLAG, LLIL_FLAG_SSA
-pub struct Flag;
-
-// LLIL_FLAG_BIT, LLIL_FLAG_BIT_SSA
-pub struct FlagBit;
-
-// LLIL_JUMP
-pub struct Jump;
-
-impl<'func, A, M, F> Operation<'func, A, M, F, Jump>
-where
- A: 'func + Architecture,
- M: FunctionMutability,
- F: FunctionForm,
-{
- pub fn target(&self) -> Expression<'func, A, M, F, ValueExpr> {
- Expression::new(self.function, self.op.operands[0] as usize)
- }
-}
-
-// LLIL_JUMP_TO
-pub struct JumpTo;
-
-struct TargetListIter<'func, A, M, F>
-where
- A: 'func + Architecture,
- M: FunctionMutability,
- F: FunctionForm,
-{
- function: &'func Function<A, M, F>,
- cursor: BNLowLevelILInstruction,
- cursor_operand: usize,
-}
-
-impl<'func, A, M, F> TargetListIter<'func, A, M, F>
-where
- A: 'func + Architecture,
- M: FunctionMutability,
- F: FunctionForm,
-{
- fn next(&mut self) -> u64 {
- if self.cursor_operand >= 3 {
- self.cursor = unsafe {
- BNGetLowLevelILByIndex(self.function.handle, self.cursor.operands[3] as usize)
- };
- self.cursor_operand = 0;
- }
- let result = self.cursor.operands[self.cursor_operand];
- self.cursor_operand += 1;
- result
- }
-}
-
-impl<'func, A, M, F> Operation<'func, A, M, F, JumpTo>
-where
- A: 'func + Architecture,
- M: FunctionMutability,
- F: FunctionForm,
-{
- pub fn target(&self) -> Expression<'func, A, M, F, ValueExpr> {
- Expression::new(self.function, self.op.operands[0] as usize)
- }
-
- pub fn target_list(&self) -> BTreeMap<u64, usize> {
- let mut result = BTreeMap::new();
- let count = self.op.operands[1] as usize / 2;
- let mut list = TargetListIter {
- function: self.function,
- cursor: unsafe {
- BNGetLowLevelILByIndex(self.function.handle, self.op.operands[2] as usize)
- },
- cursor_operand: 0,
- };
-
- for _ in 0..count {
- let value = list.next();
- let target = list.next() as usize;
- result.insert(value, target);
- }
-
- result
- }
-}
-
-// LLIL_CALL, LLIL_CALL_SSA
-pub struct Call;
-
-impl<'func, A, M, V> Operation<'func, A, M, NonSSA<V>, Call>
-where
- A: 'func + Architecture,
- M: FunctionMutability,
- V: NonSSAVariant,
-{
- pub fn target(&self) -> Expression<'func, A, M, NonSSA<V>, ValueExpr> {
- Expression::new(self.function, self.op.operands[0] as usize)
- }
-
- pub fn stack_adjust(&self) -> Option<u64> {
- use binaryninjacore_sys::BNLowLevelILOperation::LLIL_CALL_STACK_ADJUST;
-
- if self.op.operation == LLIL_CALL_STACK_ADJUST {
- Some(self.op.operands[1])
- } else {
- None
- }
- }
-}
-
-// LLIL_RET
-pub struct Ret;
-
-impl<'func, A, M, F> Operation<'func, A, M, F, Ret>
-where
- A: 'func + Architecture,
- M: FunctionMutability,
- F: FunctionForm,
-{
- pub fn target(&self) -> Expression<'func, A, M, F, ValueExpr> {
- Expression::new(self.function, self.op.operands[0] as usize)
- }
-}
-
-// LLIL_IF
-pub struct If;
-
-impl<'func, A, M, F> Operation<'func, A, M, F, If>
-where
- A: 'func + Architecture,
- M: FunctionMutability,
- F: FunctionForm,
-{
- pub fn condition(&self) -> Expression<'func, A, M, F, ValueExpr> {
- Expression::new(self.function, self.op.operands[0] as usize)
- }
-
- pub fn true_target(&self) -> Instruction<'func, A, M, F> {
- Instruction {
- function: self.function,
- instr_idx: self.op.operands[1] as usize,
- }
- }
-
- pub fn true_target_idx(&self) -> usize {
- self.op.operands[1] as usize
- }
-
- pub fn false_target(&self) -> Instruction<'func, A, M, F> {
- Instruction {
- function: self.function,
- instr_idx: self.op.operands[2] as usize,
- }
- }
-
- pub fn false_target_idx(&self) -> usize {
- self.op.operands[2] as usize
- }
-}
-
-// LLIL_GOTO
-pub struct Goto;
-
-impl<'func, A, M, F> Operation<'func, A, M, F, Goto>
-where
- A: 'func + Architecture,
- M: FunctionMutability,
- F: FunctionForm,
-{
- pub fn target(&self) -> Instruction<'func, A, M, F> {
- Instruction {
- function: self.function,
- instr_idx: self.op.operands[0] as usize,
- }
- }
-
- pub fn target_idx(&self) -> usize {
- self.op.operands[0] as usize
- }
-}
-
-// LLIL_FLAG_COND
-pub struct FlagCond;
-
-// LLIL_FLAG_GROUP
-pub struct FlagGroup;
-
-impl<'func, A, M> Operation<'func, A, M, NonSSA<LiftedNonSSA>, FlagGroup>
-where
- A: 'func + Architecture,
- M: FunctionMutability,
-{
- pub fn flag_group(&self) -> A::FlagGroup {
- let id = self.op.operands[0] as u32;
- self.function.arch().flag_group_from_id(id).unwrap()
- }
-}
-
-// LLIL_TRAP
-pub struct Trap;
-
-impl<'func, A, M, F> Operation<'func, A, M, F, Trap>
-where
- A: 'func + Architecture,
- M: FunctionMutability,
- F: FunctionForm,
-{
- pub fn vector(&self) -> u64 {
- self.op.operands[0]
- }
-}
-
-// LLIL_REG_PHI
-pub struct RegPhi;
-
-// LLIL_FLAG_PHI
-pub struct FlagPhi;
-
-// LLIL_MEM_PHI
-pub struct MemPhi;
-
-// LLIL_CONST, LLIL_CONST_PTR
-pub struct Const;
-
-impl<'func, A, M, F> Operation<'func, A, M, F, Const>
-where
- A: 'func + Architecture,
- M: FunctionMutability,
- F: FunctionForm,
-{
- pub fn size(&self) -> usize {
- self.op.size
- }
-
- pub fn value(&self) -> u64 {
- #[cfg(debug_assertions)]
- {
- let raw = self.op.operands[0] as i64;
-
- let is_safe = match raw.overflowing_shr(self.op.size as u32 * 8) {
- (_, true) => true,
- (res, false) => [-1, 0].contains(&res),
- };
-
- if !is_safe {
- error!(
- "il expr @ {:x} contains constant 0x{:x} as {} byte value (doesn't fit!)",
- self.op.address, self.op.operands[0], self.op.size
- );
- }
- }
-
- let mut mask = -1i64 as u64;
-
- if self.op.size < mem::size_of::<u64>() {
- mask <<= self.op.size * 8;
- mask = !mask;
- }
-
- self.op.operands[0] & mask
- }
-}
-
-// LLIL_EXTERN_PTR
-pub struct Extern;
-
-impl<'func, A, M, F> Operation<'func, A, M, F, Extern>
-where
- A: 'func + Architecture,
- M: FunctionMutability,
- F: FunctionForm,
-{
- pub fn size(&self) -> usize {
- self.op.size
- }
-
- pub fn value(&self) -> u64 {
- #[cfg(debug_assertions)]
- {
- let raw = self.op.operands[0] as i64;
-
- let is_safe = match raw.overflowing_shr(self.op.size as u32 * 8) {
- (_, true) => true,
- (res, false) => [-1, 0].contains(&res),
- };
-
- if !is_safe {
- error!(
- "il expr @ {:x} contains extern 0x{:x} as {} byte value (doesn't fit!)",
- self.op.address, self.op.operands[0], self.op.size
- );
- }
- }
-
- let mut mask = -1i64 as u64;
-
- if self.op.size < mem::size_of::<u64>() {
- mask <<= self.op.size * 8;
- mask = !mask;
- }
-
- self.op.operands[0] & mask
- }
-}
-
-// LLIL_ADD, LLIL_SUB, LLIL_AND, LLIL_OR
-// LLIL_XOR, LLIL_LSL, LLIL_LSR, LLIL_ASR
-// LLIL_ROL, LLIL_ROR, LLIL_MUL, LLIL_MULU_DP,
-// LLIL_MULS_DP, LLIL_DIVU, LLIL_DIVS, LLIL_MODU,
-// LLIL_MODS
-pub struct BinaryOp;
-
-impl<'func, A, M, F> Operation<'func, A, M, F, BinaryOp>
-where
- A: 'func + Architecture,
- M: FunctionMutability,
- F: FunctionForm,
-{
- pub fn size(&self) -> usize {
- self.op.size
- }
-
- pub fn left(&self) -> Expression<'func, A, M, F, ValueExpr> {
- Expression::new(self.function, self.op.operands[0] as usize)
- }
-
- pub fn right(&self) -> Expression<'func, A, M, F, ValueExpr> {
- Expression::new(self.function, self.op.operands[1] as usize)
- }
-}
-
-// LLIL_ADC, LLIL_SBB, LLIL_RLC, LLIL_RRC
-pub struct BinaryOpCarry;
-
-impl<'func, A, M, F> Operation<'func, A, M, F, BinaryOpCarry>
-where
- A: 'func + Architecture,
- M: FunctionMutability,
- F: FunctionForm,
-{
- pub fn size(&self) -> usize {
- self.op.size
- }
-
- pub fn left(&self) -> Expression<'func, A, M, F, ValueExpr> {
- Expression::new(self.function, self.op.operands[0] as usize)
- }
-
- pub fn right(&self) -> Expression<'func, A, M, F, ValueExpr> {
- Expression::new(self.function, self.op.operands[1] as usize)
- }
-
- pub fn carry(&self) -> Expression<'func, A, M, F, ValueExpr> {
- Expression::new(self.function, self.op.operands[2] as usize)
- }
-}
-
-// LLIL_DIVS_DP, LLIL_DIVU_DP, LLIL_MODU_DP, LLIL_MODS_DP
-pub struct DoublePrecDivOp;
-
-impl<'func, A, M, F> Operation<'func, A, M, F, DoublePrecDivOp>
-where
- A: 'func + Architecture,
- M: FunctionMutability,
- F: FunctionForm,
-{
- pub fn size(&self) -> usize {
- self.op.size
- }
-
- pub fn high(&self) -> Expression<'func, A, M, F, ValueExpr> {
- Expression::new(self.function, self.op.operands[0] as usize)
- }
-
- pub fn low(&self) -> Expression<'func, A, M, F, ValueExpr> {
- Expression::new(self.function, self.op.operands[1] as usize)
- }
-
- pub fn right(&self) -> Expression<'func, A, M, F, ValueExpr> {
- Expression::new(self.function, self.op.operands[2] as usize)
- }
-}
-
-// LLIL_PUSH, LLIL_NEG, LLIL_NOT, LLIL_SX,
-// LLIL_ZX, LLIL_LOW_PART, LLIL_BOOL_TO_INT, LLIL_UNIMPL_MEM
-pub struct UnaryOp;
-
-impl<'func, A, M, F> Operation<'func, A, M, F, UnaryOp>
-where
- A: 'func + Architecture,
- M: FunctionMutability,
- F: FunctionForm,
-{
- pub fn size(&self) -> usize {
- self.op.size
- }
-
- pub fn operand(&self) -> Expression<'func, A, M, F, ValueExpr> {
- Expression::new(self.function, self.op.operands[0] as usize)
- }
-}
-
-// LLIL_CMP_X
-pub struct Condition;
-
-impl<'func, A, M, F> Operation<'func, A, M, F, Condition>
-where
- A: 'func + Architecture,
- M: FunctionMutability,
- F: FunctionForm,
-{
- pub fn size(&self) -> usize {
- self.op.size
- }
-
- pub fn left(&self) -> Expression<'func, A, M, F, ValueExpr> {
- Expression::new(self.function, self.op.operands[0] as usize)
- }
-
- pub fn right(&self) -> Expression<'func, A, M, F, ValueExpr> {
- Expression::new(self.function, self.op.operands[1] as usize)
- }
-}
-
-// LLIL_UNIMPL_MEM
-pub struct UnimplMem;
-
-impl<'func, A, M, F> Operation<'func, A, M, F, UnimplMem>
-where
- A: 'func + Architecture,
- M: FunctionMutability,
- F: FunctionForm,
-{
- pub fn size(&self) -> usize {
- self.op.size
- }
-
- pub fn mem_expr(&self) -> Expression<'func, A, M, F, ValueExpr> {
- Expression::new(self.function, self.op.operands[0] as usize)
- }
-}
-
-// TODO TEST_BIT
-
-pub trait OperationArguments: 'static {}
-
-impl OperationArguments for NoArgs {}
-impl OperationArguments for Pop {}
-impl OperationArguments for Syscall {}
-impl OperationArguments for Intrinsic {}
-impl OperationArguments for SetReg {}
-impl OperationArguments for SetRegSplit {}
-impl OperationArguments for SetFlag {}
-impl OperationArguments for Load {}
-impl OperationArguments for Store {}
-impl OperationArguments for Reg {}
-impl OperationArguments for RegSplit {}
-impl OperationArguments for Flag {}
-impl OperationArguments for FlagBit {}
-impl OperationArguments for Jump {}
-impl OperationArguments for JumpTo {}
-impl OperationArguments for Call {}
-impl OperationArguments for Ret {}
-impl OperationArguments for If {}
-impl OperationArguments for Goto {}
-impl OperationArguments for FlagCond {}
-impl OperationArguments for FlagGroup {}
-impl OperationArguments for Trap {}
-impl OperationArguments for RegPhi {}
-impl OperationArguments for FlagPhi {}
-impl OperationArguments for MemPhi {}
-impl OperationArguments for Const {}
-impl OperationArguments for Extern {}
-impl OperationArguments for BinaryOp {}
-impl OperationArguments for BinaryOpCarry {}
-impl OperationArguments for DoublePrecDivOp {}
-impl OperationArguments for UnaryOp {}
-impl OperationArguments for Condition {}
-impl OperationArguments for UnimplMem {}