com.github.unidbg.ios.objc.ObjcImpl Maven / Gradle / Ivy
The newest version!
package com.github.unidbg.ios.objc;
import com.github.unidbg.Emulator;
import com.github.unidbg.Module;
import com.github.unidbg.Symbol;
import com.github.unidbg.ios.struct.objc.ObjcClass;
import com.github.unidbg.ios.struct.objc.ObjcObject;
import com.github.unidbg.memory.MemoryBlock;
import com.github.unidbg.pointer.UnidbgPointer;
import com.sun.jna.Pointer;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
class ObjcImpl extends ObjC {
private final Emulator> emulator;
private final Symbol _objc_msgSend;
private final Symbol _objc_getMetaClass;
private final Symbol _objc_getClass;
private final Symbol _objc_lookUpClass;
private final Symbol _sel_registerName;
private final Symbol _class_getMethodImplementation;
private final Symbol _class_respondsToSelector;
private final Symbol _object_setInstanceVariable;
private final Symbol _object_getInstanceVariable;
public ObjcImpl(Emulator> emulator) {
this.emulator = emulator;
Module module = emulator.getMemory().findModule("libobjc.A.dylib");
if (module == null) {
throw new IllegalStateException("libobjc.A.dylib NOT loaded");
}
_objc_msgSend = module.findSymbolByName("_objc_msgSend", false);
if (_objc_msgSend == null) {
throw new IllegalStateException("_objc_msgSend is null");
}
_objc_getMetaClass = module.findSymbolByName("_objc_getMetaClass", false);
if (_objc_getMetaClass == null) {
throw new IllegalStateException("_objc_getMetaClass is null");
}
_objc_getClass = module.findSymbolByName("_objc_getClass", false);
if (_objc_getClass == null) {
throw new IllegalStateException("_objc_getClass is null");
}
_objc_lookUpClass = module.findSymbolByName("_objc_lookUpClass", false);
if (_objc_lookUpClass == null) {
throw new IllegalStateException("_objc_lookUpClass is null");
}
_sel_registerName = module.findSymbolByName("_sel_registerName", false);
if (_sel_registerName == null) {
throw new IllegalStateException("_sel_registerName is null");
}
_class_getMethodImplementation = module.findSymbolByName("_class_getMethodImplementation", false);
if (_class_getMethodImplementation == null) {
throw new IllegalStateException("_class_getMethodImplementation is null");
}
_class_respondsToSelector = module.findSymbolByName("_class_respondsToSelector", false);
if (_class_respondsToSelector == null) {
throw new IllegalStateException("_class_respondsToSelector is null");
}
_object_setInstanceVariable = module.findSymbolByName("_object_setInstanceVariable", false);
if (_object_setInstanceVariable == null) {
throw new IllegalStateException("_object_setInstanceVariable is null");
}
_object_getInstanceVariable = module.findSymbolByName("_object_getInstanceVariable", false);
if (_object_getInstanceVariable == null) {
throw new IllegalStateException("_object_getInstanceVariable is null");
}
}
@Override
public void setInstanceVariable(Emulator> emulator, ObjcObject obj, String name, Object value) {
if (value instanceof Float) {
float f = (Float) value;
ByteBuffer buffer = ByteBuffer.allocate(8);
buffer.order(ByteOrder.LITTLE_ENDIAN);
buffer.putFloat(f);
buffer.flip();
value = buffer.getLong();
} else if (value instanceof Double) {
double d = (Double) value;
ByteBuffer buffer = ByteBuffer.allocate(8);
buffer.order(ByteOrder.LITTLE_ENDIAN);
buffer.putDouble(d);
buffer.flip();
value = buffer.getLong();
}
_object_setInstanceVariable.call(emulator, obj, name, value);
}
@Override
public UnidbgPointer getInstanceVariable(Emulator> emulator, ObjcObject obj, String name) {
MemoryBlock block = null;
try {
block = emulator.getMemory().malloc(16, true);
UnidbgPointer pointer = block.getPointer();
_object_getInstanceVariable.call(emulator, obj, name, pointer);
return pointer.getPointer(0);
} finally {
if (block != null) {
block.free();
}
}
}
@Override
public ObjcClass getMetaClass(String className) {
Number number = _objc_getMetaClass.call(emulator, className);
Pointer pointer = UnidbgPointer.pointer(emulator, number);
if (pointer == null) {
throw new IllegalArgumentException(className + " NOT found");
}
return ObjcClass.create(emulator, pointer);
}
@Override
public ObjcClass getClass(String className) {
Number number = _objc_getClass.call(emulator, className);
Pointer pointer = UnidbgPointer.pointer(emulator, number);
if (pointer == null) {
throw new IllegalArgumentException(className + " NOT found");
}
return ObjcClass.create(emulator, pointer);
}
@Override
public ObjcClass lookUpClass(String className) {
Number number = _objc_lookUpClass.call(emulator, className);
Pointer pointer = UnidbgPointer.pointer(emulator, number);
return pointer == null ? null : ObjcClass.create(emulator, pointer);
}
@Override
public Pointer registerName(String selectorName) {
Number number = _sel_registerName.call(emulator, selectorName);
Pointer pointer = UnidbgPointer.pointer(emulator, number);
if (pointer == null) {
throw new IllegalStateException(selectorName);
}
return pointer;
}
@Override
public boolean respondsToSelector(ObjcClass objcClass, String selectorName) {
Pointer selector = registerName(selectorName);
Number number = _class_respondsToSelector.call(emulator, objcClass, selector);
return number.intValue() == 1;
}
@Override
public UnidbgPointer getMethodImplementation(ObjcClass objcClass, String selectorName) {
Pointer selector = registerName(selectorName);
Number number = _class_getMethodImplementation.call(emulator, objcClass, selector);
UnidbgPointer pointer = UnidbgPointer.pointer(emulator, number);
if (pointer == null) {
throw new IllegalStateException(selectorName);
}
return pointer;
}
@Override
public Number msgSend(Emulator> emulator, Object... args) {
return _objc_msgSend.call(emulator, args);
}
private ObjcClass cNSString;
private ObjcClass cNSData;
@Override
public NSString newString(String str) {
if (str == null) {
return null;
}
if (cNSString == null) {
cNSString = getClass("NSString");
}
ObjcObject obj = cNSString.callObjc("stringWithUTF8String:", str);
return NSString.create(obj);
}
@Override
public NSData newData(byte[] bytes) {
if (bytes == null) {
return null;
}
if (cNSData == null) {
cNSData = getClass("NSData");
}
ObjcObject obj = cNSData.callObjc("dataWithBytes:length:", bytes, bytes.length);
return NSData.create(obj);
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy