def __read_superclasses_from_sections(section_it): ''' Read the superclasses from the specified section name Parameters ---------- section_it: iterator<tuple<int, string>> iterator over the sections where the superclass infos are stored Returns ------- dict<ObjcClass, ObjcClass> dict with object as key and the superclass as item ''' superclasses_dict = {} for (_, i) in section_it: CLASS_PARENT_MATCH = AsmRegEx.compiled_vre( AsmRegEx.RE_CLASS_PARENT).search(i) if CLASS_PARENT_MATCH is not None: clazzname = CLASS_PARENT_MATCH.group( AsmRegEx.RE_CLASS_PARENT_GR_CLASS) superclazz_name = CLASS_PARENT_MATCH.group( AsmRegEx.RE_CLASS_PARENT_GR_PARENT) superclasses_dict[ObjcClass(clazzname)] = ObjcClass( superclazz_name) return superclasses_dict
def __init__(self, name, category_on_class, superclass=None, is_static=False, is_frameworkclass=False, variables=None, methods=None): ObjcClass.__init__(self, name, superclass, is_static, is_frameworkclass, variables, methods) self.__category_on_class = category_on_class
def parse_objc_class_from_classref(self, asmline): classref_match = regexp.compiled_vre( regexp.RE_CLASSREF).search(asmline) if classref_match is not None: return ObjcClass( classref_match.group(regexp.RE_CLASSREF_GR_CLASSREF)) return None
def parse_objc_class_from_classref(self, asmline): ''' Create ObjcClass from classref ([ds:cls_NSAssertionHandler]) ''' classsref_match = regexp.compiled_vre( regexp.RE_CLASSREF).search(asmline) if classsref_match is not None: name = classsref_match.group(regexp.RE_CLASSREF_GR_CLASSREF) return ObjcClass(name, is_static=True) return None
def test_msg_send_eq(self): objc_class = ObjcClass('Foo') sels = [Selector('alloc'), Selector('init'), Selector('foo:', ['1'])] sels2 = [Selector('foo:', ['1'])] msg_send1 = MsgSend(objc_class, sels) msg_send2 = MethodImplementation(objc_class, sels2) res = msg_send1 == msg_send2 and msg_send2 == msg_send1 print '%s == %s and vice versa = %s' % (msg_send1, msg_send2, res) self.assertTrue(res, 'Node quality not correct! Method calls will not link to the corresponding method implementations and vice versa\n')
def setUp(self): TestCase.setUp(self) self.__category_class = CategoryClass('AnyHttpsCert', ObjcClass('NSURLRequest')) self.__category = MethodImplementation( self.category_class, [Selector('allowsAnyHTTPSCertificateForHost:')], is_static=True)
def parse_objc_class_from_classref(self, asmline): ''' Create ObjcClass from classref ([ds:objc_classref_Object1]) ''' classsref_match = regexp.compiled_vre( regexp.RE_CLASSREF).search(asmline) # is classref e.g. [ds:objc_classref_Object1] if classsref_match is not None: name = classsref_match.group(regexp.RE_CLASSREF_GR_CLASSREF) return ObjcClass(name, is_static=True) return None
def parse_ivar(self, asmline): '''Create a ObjcClass from e.g. "IVAR_0x291c" ''' ivar_match = regexp.compiled_vre(regexp.RE_IVAR).search(asmline) if ivar_match is not None: ivar_name = ivar_match.group(regexp.RE_IVAR_GR_NAME) var = Variable(ivar_name) ivar_class = ObjcClass('IVAR', variables=[var]) return IVar(ivar_class) return None
def parse_objc_class_from_framework_class(self, asmline): ''' Create ObjcClass from frameworkclass e.g. ([ds:bind__OBJC_CLASS_$_NSUserDefaults]) ''' frameworkclass_match = regexp.compiled_vre( regexp.RE_FRAMEWORKCLASS).search(asmline) # is frameworkclass e.g. [ds:bind__OBJC_CLASS_$_NSUserDefaults] if frameworkclass_match is not None: name = frameworkclass_match.group( regexp.RE_FRAMEWORKCLASS_GR_FCLASS) return ObjcClass(name, is_frameworkclass=True) return None
def parse_ivar(self, asmline): '''Create a ObjcClass from e.g. [ds:_OBJC_IVAR_$_AppDelegate.obj3] and set AppDelegate as the class with the attribute obj3 ''' ivar_match = regexp.compiled_vre(regexp.RE_IVAR).search(asmline) if ivar_match is not None: ivar_class = ivar_match.group(regexp.RE_IVAR_GR_CLASS) ivar_name = ivar_match.group(regexp.RE_IVAR_GR_IVAR) var = Variable(ivar_name) ivar_class = ObjcClass(ivar_class, variables=[var]) return IVar(ivar_class) return None
def test_filter_method_definition(self): ''' Test `md_filter_method_defintion` ''' selname = 'application:handleOpenURL:' sel = Selector(selname) msg_send = MsgSend(ObjcClass('AppDelegate'), [sel]) res = md_filter_method_defintion(msg_send, class_name=None, selector_name=selname, search_substring=True) print '%s has selector %s = %s' % (msg_send, sel, res) self.assertTrue(res, self.MSG % 'MethodDefFilterUtil')
def msg_send_from_destination(self, destination, selector): ''' Overwritten to accept other ints as destination. Currently annotation in Hopper is not so good, leading often to hex values (parsed to int) in the `destination_register`. ''' # temporary workaround to read a msgSend even if destination is integer (transformed from hex) # because Hopper is currently not annotating all destinations! msg_send = ObjectiveCRuntime.msg_send_from_destination( self, destination, selector) if msg_send is None: arm_fix = isinstance(destination, int) if selector is not None and arm_fix: msg_send = MsgSend(ObjcClass(str(destination)), [selector]) return msg_send
def test_filter_category(self): ''' Tests for the method `md_filter_category` ''' category_on_class_name = 'NSURLRequest' category_on_class = ObjcClass(category_on_class_name) category_name = 'AnyHttpsCert' cclass = CategoryClass(category_name, category_on_class=category_on_class) selector = Selector('allowsAnyHTTPSCertificateForHost') category_msg_send = MsgSend(cclass, [selector]) # test with all properties at once category_match = md_filter_category(category_msg_send, str(selector), category_on_class_name, category_name, search_substring=False) print '%s is category on %s with name %s and selector %s = %s' % ( category_msg_send, category_on_class_name, category_name, selector, category_match) category_match2 = md_filter_category(category_msg_send, str(selector), category_on_class_name, category_name=None, search_substring=False) print '%s is category on %s and selector %s = %s' % ( category_msg_send, category_on_class_name, selector, category_match2) # category_on test category_match3 = md_filter_category( category_msg_send, category_on=category_on_class_name) print '%s is category on %s = %s' % ( category_msg_send, category_on_class_name, category_match3) # category name test category_match4 = md_filter_category(category_msg_send, category_name=category_name) print '%s is category with name %s = %s' % ( category_msg_send, category_name, category_match4) # selector test category_match5 = md_filter_category(category_msg_send, selector=str(selector)) print '%s is category with selector %s = %s' % ( category_msg_send, str(selector), category_match5) self.assertTrue( all((category_match, category_match2, category_match3, category_match4, category_match5)), self.MSG % 'md_filter_category')
def parse_meth_impl(asmline): ''' Parse a method implementation like e.g. "methImpl_AppDelegate_applicationDidFinishLaunching_". For more details see `RE_METH_IMPL`. Returns ------- MethodImplementation ''' meth_impl_match = regexp.compiled_vre(regexp.RE_METH_IMPL).search(asmline) if meth_impl_match is not None: classname = meth_impl_match.group(regexp.RE_METH_IMPL_GR_CLASS) selectorname = meth_impl_match.group(regexp.RE_METH_IMPL_GR_SELECTOR) selector = Selector.selector_from_underscore_delimiter(selectorname) is_static = regexp.method_implementation_is_static(meth_impl_match.group(regexp.RE_METH_IMPL_GR_STATIC)) if classname is not None: objc_class = ObjcClass(classname, is_static = is_static) return MethodImplementation(objc_class, [selector], is_static) return None
def set_class_of_func(self, value): self.__class_of_func = value def __str__(self): return '%s.%s' % (self.get_class_of_func(), Function.__str__(self)) def __eq__(self, other): if isinstance(other, ClassFunc): return self is other or (Function.__eq__(self, other) and self.class_of_func == other.class_of_func) return False def __hash__(self): return hash((Function.__hash__(self), self.class_of_func)) class_of_func = property(get_class_of_func, set_class_of_func, None, "__class_of_func(ObjcClass) -- the class to which the function belongs.") ##################################################################################### # NSObjectInterface # ##################################################################################### def get_nsobject(self): return self.get_class_of_func() if __name__ == '__main__': class_of_func = ObjcClass('AppDelegate') function = 'function' args = ['1', '2', '3'] classfunc = ClassFunc(class_of_func, function, args) print classfunc
return '''%s(%s, category_on_class: %s\nsuperclass: %s, static: %s, frameworkclass: %s, \nvariables: %s, \nmethods: %s) ''' % ( self.__class__.__name__, self.get_objc_name(), self.get_category_on_class(), self.get_superclass().get_objc_name(), self.get_is_static(), self.get_is_frameworkclass(), self.get_variables(), self.get_methods()) def __static_str(self): is_static = self.is_static return '+' if is_static else '-' category_on_class = property( get_category_on_class, set_category_on_class, None, "category_on_class(ObjcClass) -- the class on which the category is added" ) ##################################################################################### # HopperAnnotationInterface # ##################################################################################### def hopper_str(self): return '%s(%s(%s))' % (self.__class__.__name__, self.get_category_on_class(), self.get_objc_name()) if __name__ == '__main__': category_on_class = ObjcClass('NSURLRequest') cclass = CategoryClass('AnyHttpsCert', category_on_class=category_on_class) print cclass
def __eq__(self, other): if isinstance(other, CategoryClass): return self is other or ObjcClass.__eq__( self, other) and (self.get_category_on_class()) == ( other.get_category_on_class()) return False
def __hash__(self): return hash((ObjcClass.__hash__(self), self.get_category_on_class()))
Returns a `MethodImplementation` where the class is a `CategoryClass`. ''' msg_send = None category_match = AsmRegEx.compiled_vre( AsmRegEx.RE_CATEGORY).search(asmline) if category_match is not None: category_on_class = category_match.group( AsmRegEx.RE_CATEGORY_ON_CLASS) classname = category_match.group(AsmRegEx.RE_CATEGORY_CLASS) category_is_static = category_match.group( AsmRegEx.RE_CATEGORY_STATIC_SYMBOL ) == AsmRegEx.RE_CATEGORY_SYMBOL_STATIC selectorname = category_match.group(AsmRegEx.RE_CATEGORY_SELECTOR) selector = Selector(selectorname) cclass = CategoryClass(classname, category_on_class) msg_send = MethodImplementation(cclass, [selector], is_static=category_is_static) return msg_send if __name__ == '__main__': from vizasm.model.objc.object.nsobject.objcclass.ObjcClass import ObjcClass method = MethodImplementation(ObjcClass('AppDelegate'), [Selector('applicationDidFinishLaunching:')], is_static=False) print method category_msg_send = MethodImplementation.create_from_asm_line( ' +[NSURLRequest(AnyHttpsCert) allowsAnyHTTPSCertificateForHost:]_100001c70:' ) print 'MsgSend from category: %s ' % (category_msg_send)
from vizasm.analysis.asm.cpu.x86.Cpu_x86 import Cpu_x86 from vizasm.analysis.asm.cpu.x86.Register_x86 import Register_x86 as reg cpu = Cpu_x86({}) pu = ParseUtil_x86(cpu, reg) imp_stub_x86 = pu.parse_imp( 'call imp___symbol_stub__objc_setProperty') stackvar = pu.parse_stackvar( '00002caf 8B4D14 mov ecx, dword [ss:ebp-0x48+arg_4]' ) cls_ref = pu.parse_objc_class_from_classref('[ds:cls_NSAssertionHandler]') cls_ref2 = pu.parse_objc_class_from_classref( 'dword [ds:eax-0x25e1+cls_Object1]') cpu.read_line('mov ecx, dword [ds:eax-0x25e1+cls_Object1]') var_assignment_without_ivar_ref = pu.parse_var_assignment_without_ivar_ref_from_asmline( 'dword [ds:ecx+0x8]') cpu.memory.registers.set_value_for_register( reg('eax'), MsgSend(ObjcClass('Object1'), [Selector('alloc'), Selector('init')])) var_assignment_with_ivar_ref = pu.parse_var_assignment_with_ivar_ref_from_asmline( 'mov dword [ds:ecx+0x8], eax') print imp_stub_x86 print cls_ref print cls_ref2 print stackvar print var_assignment_without_ivar_ref print var_assignment_with_ivar_ref print pu.parse_imp( '[ds:eax-0x221e+imp___nl_symbol_ptr__NSStreamSocketSecurityLevelKey]')
print pu.parse_assignment_split('str r0, [r4, r5]') print 'register: %s' % pu.parse_register( ' r2 ; XREF=0x31ae') print pu.parse_stack_push_via_stm('stm.w sp, {r3, r11}', cpu.stack_pointer_register()) print pu.parse_stack_push_via_stm('stm.w sp, {r2, r9}', cpu.stack_pointer_register().register) print pu.parse_stack_access('[sp, #0x8]') print pu.parse_stack_access('[sp]') print pu.parse_offset_addring_offset_needed('[r0, r4]') print pu.parse_offset_addressing('[r0]') # VarAssignment test cpu.memory.registers.set_value_for_register( reg('r5'), IVar(ObjcClass('SelfClass'), MsgSend(ObjcClass('Foo'), [Selector('alloc'), Selector('init')]))) cpu.memory.registers.set_value_for_register(reg('r0'), ObjcClass('Foo')) cpu.memory.registers.set_value_for_register(reg('r4'), ObjcClass('SelfClass')) print pu.parse_var_assignment_with_ivar_ref_from_asmline( 'str r0, [r4, r5]') print pu.parse_var_assignment_without_ivar_ref_from_asmline('[sp, r5]') print pu.parse_var_assignment_with_ivar_ref_from_asmline( 'str r0, [sp, r5]') print 'stack access: %s' % str(pu.parse_stack_access('[sp, #0x4]')) print 'stack access: %s' % str(pu.parse_stack_access('[sp], #0x4')) print 'stack access: %s' % str(pu.parse_stack_access('[sp]')) print pu.parse_add('add r7, sp, #0xc')
the `Selector` with which the `MsgSend` shall be created. Returns ------- MsgSend the created `MsgSend` ''' return MsgSend.create_from_msgsend(self, selector) selectors = property(get_selectors, set_selectors, None, "__selectors(list) -- the selector(s) to send to the class (default [])") msg_receiver = property(get_msg_receiver, set_msg_receiver, None, "__msg_receiver(ObjClass) -- the class to which the message(s) will be sent") if __name__ == '__main__': from vizasm.model.objc.function.MethodImplementation import MethodImplementation objcclass = ObjcClass('NSUserDefaults') sel1 = Selector('standardUserDefaults') sel2 = Selector('objectForKey:', ['aKey']) sel3 = Selector('setValueForKey:value:', ['aKey', 'value']) msg = MsgSend(objcclass, [sel1, sel2, sel3]) print msg msg2 = MsgSend(objcclass, [Selector('alloc'), Selector('init'), Selector('httpsConnection')]) print msg2 msg2 = MsgSend(objcclass, [Selector('new'), Selector('httpsConnection')]) print msg2 msg4 = MsgSend(objcclass, [Selector('alloc'), Selector('init')]) print msg4 msg3 = MsgSend.create_from_msgsend(msg, sel1) print msg3
ivar2 = pu.parse_ivar('[ds:_OBJC_IVAR_$_AppDelegate.obj3] ') d[ivar2] = 'test2' # this should not overwrite ivar2 but add an additional entry in the dict, cause ivar3 is not equal to ivar2 ivar3 = pu.parse_ivar('[ds:_OBJC_IVAR_$_AppDelegate.obj2] ') d[ivar3] = 'test3' print d print 'list equal test: should be true' x = [ivar] y = [ivar] print '[ivar] equals [ivar]: %s' % (x == y) print '[ivar] equals [ivar2]: %s' % (x == [ivar2]) print '\nivar without ref: %s' % (ivar) ivar.set_ivar_ref( MsgSend(ObjcClass('Object3'), [Selector('alloc'), Selector('init')])) print 'ivar with ref: %s' % (ivar) print 'StackVar' print pu.parse_stackvar('dword [ss:rbp-0x60+arg_0]') print pu.parse_stackvar('[ss:rbp-0x30+var_41]') ''' print 'ObjcClass' fclass = ObjcClass.create_from_asm_line('[ds:bind__OBJC_CLASS_$_NSUserDefaults]') fclass2 = ObjcClass.create_from_asm_line('[ds:bind__OBJC_CLASS_$_NSUserDefaults]') classref = ObjcClass.create_from_asm_line('[ds:objc_classref_Object1]') print 'fclass: %s' % (fclass) print 'classref: %s' % (classref) print fclass.__hash__() == fclass2.__hash__()
class MethodCall(object, AddMethodCallToGraphInterface): ''' The `Methodcall` stores messages a sender has sent. This model is uses for a method (sender) that sends several messages and is the output of the `Cpu`. If the sender is not present at creation, using None as argument for the sender creates a pseudo none sender. You can check if this sender is still present with the method has_no_sender(). Parameters ---------- __sender: FunctionInterface, optional (default is PSEUDO_NONE_SENDER) __calls: list<MethodCallItem>, optional (default is []) ''' PSEUDO_NONE_NAME = 'pseudo none' PSEUDO_NONE_SENDER = MsgSend(ObjcClass(PSEUDO_NONE_NAME), []) def __init__(self, sender = None, calls = None): object.__init__(self) if calls is None: calls = [] # fix for creation with None as sender if sender is None: sender = MethodCall.PSEUDO_NONE_SENDER self.__sender = sender self.__calls = calls def __len__(self): return len(self.get_calls()) def __eq__(self, other): if isinstance(other, MethodCall): return self is other or ((self.get_sender(), self.get_calls())) == ((other.sender(), other.get_msg())) return False def __ne__(self, other): return not self == other def __hash__(self): return hash((self.get_sender().__hash__(), tuple(self.get_calls()).__hash__())) def __iter__(self): return iter(sorted(self.calls)) def format_head(self): ''' Format the head (first line) of the `MethodCall`. No newline will be appended. ''' return 'Method: %s' % (self.get_sender()) def __str__(self): head = self.format_head() return '%s:\n%s\n%s' % (head, (len(head) + 1) * '-', ''.join(str(call) for call in self)) def __repr__(self): return '%s(%s: %s)' % (self.__class__.__name__, self.get_sender(), self.get_calls()) def get_sender(self): return self.__sender def get_calls(self): return self.__calls def set_sender(self, value): self.__sender = value def set_calls(self, value): self.__calls = value sender = property(get_sender, set_sender, None, "__sender(MsgSend, optional (default is PSEUDO_NONE_SENDER))") calls = property(get_calls, set_calls, None, "__calls:(list<MethodCallItem>, optional (default is []))") def add_methodcall(self, call, linenr, address = None): ''' Add a call. Parameters: ----------- call: Function or MsgSend linenr: int address: int ''' self.add_methodcallitem(MethodCallItem(call, linenr, address)) def add_methodcallitem(self, methodcallitem): ''' Add the `MethodCallItem`. Parameters: ----------- methodcallitem: MethodCallItem the `MethodCallItem` which shall be added ''' self.get_calls().append(methodcallitem) def idx_methodcallitem(self, linenr): ''' Return the index of the `MethodCallItem` with the given line number''' for i, methocallitem in enumerate(self.calls): if methocallitem.linenr == linenr: return i return None def has_no_sender(self): ''' Check if the `Methodcall` has a sender. If the `MethodCall` is initialized with None as sender, a pseudo none sender is created and used. ''' return self.get_sender() == MethodCall.PSEUDO_NONE_SENDER def is_empty(self): ''' Returns if the methodcall does not contain any calls ''' return len(self.get_calls()) == 0 def create_gephi_attr_dicts(self, asm_lines, filtered_methodcall = None): ''' Construct the attribute dictionary describing the graph style. Use the created dictionaries with the `add_to_graph` method. The attributes are: Calling Method: assembler code the method calls (filtered or not) Method: line number in the asm file address in the asm file surrounding lines Parameters ---------- asm_lines: string the assembler method as string filtered_methodcall: MethodCall, optional (default is None) the filtered `MethodCall` Returns ------- methodcall_sender_attr_dict: dict methodcall_calls_attr_list_dict: dict ''' method_lines_list = [str(methodcallitem) for methodcallitem in self.calls] if filtered_methodcall is None: filtered_methodcall = self # construct calls attribute dictionary methodcall_calls_attr_list_dict = [] cnt_surrounding_lines = setting_for_key(SETTINGS_CNT_SURROUNDING_LINES) if cnt_surrounding_lines >= 0: for i, methodcallitem in enumerate(filtered_methodcall.calls): # construct leading and trailing lines # index of the current line (filtered `MethodCall`) in the list of method lines current_line = str(filtered_methodcall.calls[i].call) linenr = methodcallitem.linenr idx_line = self.idx_methodcallitem(linenr) # idx_line = method_lines_list.index(current_line) lines_before, lines_after = Util.surrounding_elements_from_list(method_lines_list, idx_line, cnt_surrounding_lines) surrounding_lines = NodeAttributes.NPATTERN_SURROUND_LINES % (Util.strlist_to_str(lines_before), current_line, Util.strlist_to_str(lines_after)) methodcall_attr_dict = {NodeAttributes.NATTR_METHOD_SURROUNDING_LINES % cnt_surrounding_lines : surrounding_lines} methodcall_attr_dict.update(methodcallitem.get_gexf_viz_attr_dict()) methodcall_calls_attr_list_dict.append(methodcall_attr_dict) # add method signature to list of method lines method_lines_list.insert(0, filtered_methodcall.format_head() + ":\n") # construct sender attribute dictionary method_lines = Util.strlist_to_str(method_lines_list) methodcall_sender_attr_dict = {NodeAttributes.NATTR_METHOD : method_lines, NodeAttributes.NATTR_ASM_CODE : asm_lines} return (methodcall_sender_attr_dict, methodcall_calls_attr_list_dict) ##################################################################################### # AddToGraphInterface # ##################################################################################### def add_to_graph(self, graph, methodcall_sender_attr_dict = None, methodcall_calls_attr_list_dict = None, sender_methodcall_edge_attr_dict = None): ''' Add the `MethodCall` to the graph Parameters ---------- methodcall_sender_attr_dict: dict, optional (Default {}) methodcall_calls_attr_list_dict: dict, optional (Default {}) methodcall_calls_attr_list_dict: dict, optional (Default {}) ''' if methodcall_sender_attr_dict is None: methodcall_sender_attr_dict = {} if methodcall_calls_attr_list_dict is None: methodcall_calls_attr_list_dict = [] if sender_methodcall_edge_attr_dict is None: sender_methodcall_edge_attr_dict = {} if len(self) > 0: key = self.sender graph.add_node(key) graph.add_attributes(key, methodcall_sender_attr_dict) for idx, methodcallitem in enumerate(self): # only set the next attribute dictionary if list is not empty if methodcall_calls_attr_list_dict: methodcall_attr_dict = deepcopy(methodcall_calls_attr_list_dict[idx]) else: methodcall_attr_dict = {} edge_label = methodcallitem.call graph.add_node(edge_label) graph.add_edge(self.sender, edge_label, key = None, attr_dict = deepcopy(sender_methodcall_edge_attr_dict)) methodcall_attr_dict.update({NodeAttributes.NATTR_LINENUMBER : str(methodcallitem.linenr)}) methodcall_attr_dict.update({NodeAttributes.NATTR_ADDRESS : str(hex(methodcallitem.address))}) graph.add_attributes(edge_label, methodcall_attr_dict)
it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. VizAsm is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with VizAsm. If not, see <http://www.gnu.org/licenses/>. ''' from vizasm.model.objc.function.MsgSend import MsgSend class MethodSelectorArgument(MsgSend): ''' A `MethodSelectorArgument` is a `MsgSend` without any selectors and overwritten __str__ method.. It's used for the unknown arguments of a method implementations `Selector` ''' def __init__(self, msg_send_class): MsgSend.__init__(self, msg_send_class, []) def __str__(self): return str(self.msg_receiver) if __name__ == '__main__': from vizasm.model.objc.object.nsobject.objcclass.ObjcClass import ObjcClass print MethodSelectorArgument(ObjcClass('arg1'))