def read_closure(settings, interps, heaps, pointer): try: if isinstance(pointer, Argument) or isinstance(pointer, CaseArgument) or isinstance(pointer, Offset) and isinstance(pointer.base, CasePointer): return if settings.opts.verbose: print("Found closure:") print(" Pointer:", show.show_pretty_pointer(settings, pointer)) if isinstance(pointer, StaticValue) and show.name_is_library(show.get_name_for_address(settings, pointer.value)): if settings.opts.verbose: print(" Library defined!") print() return info_pointer = ptrutil.dereference(settings, pointer, heaps, []).untagged assert isinstance(info_pointer, StaticValue) info_address = info_pointer.value info_type = info.read_closure_type(settings, info_address) if info_type[:11] == 'constructor': num_ptrs = ptrutil.read_half_word(settings, settings.text_offset + info_address - settings.rt.halfword.size*4) num_non_ptrs = ptrutil.read_half_word(settings, settings.text_offset + info_address - settings.rt.halfword.size*3) args = [] arg_pointer = ptrutil.make_tagged(settings, pointer)._replace(tag = 0) for i in range(num_ptrs + num_non_ptrs): arg_pointer = ptrutil.pointer_offset(settings, arg_pointer, settings.rt.word.size); args.append(ptrutil.dereference(settings, arg_pointer.untagged, heaps, [])) arg_pattern = 'p' * num_ptrs + 'n' * num_non_ptrs interps[pointer] = Apply(func = Pointer(info_pointer), func_type = 'constructor', args = interp_args(args, arg_pattern), pattern = arg_pattern) if settings.opts.verbose: print() for arg in args[:num_ptrs]: read_closure(settings, interps, arg.untagged) return elif info_type[:8] == 'function': arg_pattern = info.read_arg_pattern(settings, info_address) else: arg_pattern = '' if settings.opts.verbose: print() interps[pointer] = Pointer(info_pointer) read_function_thunk(settings, interps, heaps, info_address, ptrutil.make_tagged(settings, pointer)._replace(tag = len(arg_pattern)), arg_pattern) except: e_type, e_obj, e_tb = sys.exc_info() print("Error when processing closure at", show.show_pretty_pointer(settings, pointer)) print(" Error:", e_obj) print(" Error Location:", e_tb.tb_lineno) print(" No Disassembly Available") print()
def read_closure(settings, worklist, heaps, pointer): try: info_pointer = ptrutil.dereference(settings, pointer, heaps, []).untagged assert isinstance(info_pointer, StaticValue) info_address = info_pointer.value info_type = info.read_closure_type(settings, info_address) if settings.opts.verbose: print(" Type:", info_type) if info_type[:11] == 'constructor': num_ptrs = ptrutil.read_half_word(settings, settings.text_offset + info_address - settings.rt.halfword.size*4) num_non_ptrs = ptrutil.read_half_word(settings, settings.text_offset + info_address - settings.rt.halfword.size*3) args = [] arg_pointer = ptrutil.make_tagged(settings, pointer)._replace(tag = 0) for i in range(num_ptrs + num_non_ptrs): arg_pointer = ptrutil.pointer_offset(settings, arg_pointer, settings.rt.word.size); args.append(ptrutil.dereference(settings, arg_pointer.untagged, heaps, [])) arg_pattern = 'p' * num_ptrs + 'n' * num_non_ptrs for arg in args[:num_ptrs]: worklist.append(ClosureWork(heaps = heaps, pointer = arg.untagged)) return Apply(func = Pointer(info_pointer), func_type = 'constructor', args = interp_args(args, arg_pattern), pattern = arg_pattern) elif info_type[:11] == 'indirection': tagged = ptrutil.make_tagged(settings, pointer)._replace(tag = 0) offset = ptrutil.pointer_offset(settings, tagged, settings.rt.word.size) new_ptr = ptrutil.dereference(settings, offset.untagged, heaps, []) if settings.opts.verbose: print() worklist.append(ClosureWork(heaps = heaps, pointer = new_ptr.untagged)) return Pointer(new_ptr.untagged) elif info_type[:8] == 'function': arg_pattern = info.read_arg_pattern(settings, info_address) else: arg_pattern = '' worklist.append(FunctionThunkWork(heaps = heaps, address = info_address, main_register = ptrutil.make_tagged(settings, pointer)._replace(tag = len(arg_pattern)), arg_pattern = arg_pattern)) return Pointer(info_pointer) except: e_type, e_obj, e_tb = sys.exc_info() print("Error when processing closure at", show.show_pretty_pointer(settings, pointer)) print(" Error:", e_obj) print(" Error Location:", e_tb.tb_lineno) print(" No Disassembly Available") print() return UnknownInterpretation()
def read_closure_type(settings, address): type_table = { 1: 'constructor', 2: 'constructor (1 ptr, 0 nonptr)', 3: 'constructor (0 ptr, 1 nonptr)', 4: 'constructor (2 ptr, 0 nonptr)', 5: 'constructor (1 ptr, 1 nonptr)', 6: 'constructor (0 ptr, 2 nonptr)', 7: 'constructor (static)', 8: 'constructor (no CAF, static)', 9: 'function', 10: 'function (1 ptr, 0 nonptr)', 11: 'function (0 ptr, 1 nonptr)', 12: 'function (2 ptr, 0 nonptr)', 13: 'function (1 ptr, 1 nonptr)', 14: 'function (0 ptr, 2 nonptr)', 15: 'function (static)', 16: 'thunk', 17: 'thunk (1 ptr, 0 nonptr)', 18: 'thunk (0 ptr, 1 nonptr)', 19: 'thunk (2 ptr, 0 nonptr)', 20: 'thunk (1 ptr, 1 nonptr)', 21: 'thunk (0 ptr, 2 nonptr)', 22: 'thunk (static)', 23: 'selector', 28: 'indirection', 29: 'indirection (permanent)', 30: 'indirection (static)' } type = ptrutil.read_half_word(settings, settings.text_offset + address - settings.rt.halfword.size*2) if type in type_table: return type_table[type] else: return 'unknown: ' + str(type)
def read_closure_type(settings, address): type_table = { 1: 'constructor', 2: 'constructor (1 ptr, 0 nonptr)', 3: 'constructor (0 ptr, 1 nonptr)', 4: 'constructor (2 ptr, 0 nonptr)', 5: 'constructor (1 ptr, 1 nonptr)', 6: 'constructor (0 ptr, 2 nonptr)', 7: 'constructor (static)', 8: 'constructor (no CAF, static)', 9: 'function', 10: 'function (1 ptr, 0 nonptr)', 11: 'function (0 ptr, 1 nonptr)', 12: 'function (2 ptr, 0 nonptr)', 13: 'function (1 ptr, 1 nonptr)', 14: 'function (0 ptr, 2 nonptr)', 15: 'function (static)', 16: 'thunk', 17: 'thunk (1 ptr, 0 nonptr)', 18: 'thunk (0 ptr, 1 nonptr)', 19: 'thunk (2 ptr, 0 nonptr)', 20: 'thunk (1 ptr, 1 nonptr)', 21: 'thunk (0 ptr, 2 nonptr)', 22: 'thunk (static)', 23: 'selector' } type = ptrutil.read_half_word(settings, settings.text_offset + address - settings.rt.halfword.size*2) if type in type_table: return type_table[type] else: return 'unknown: ' + str(type)
def read_closure_type(settings, address): type_table = { 1: "constructor", 2: "constructor (1 ptr, 0 nonptr)", 3: "constructor (0 ptr, 1 nonptr)", 4: "constructor (2 ptr, 0 nonptr)", 5: "constructor (1 ptr, 1 nonptr)", 6: "constructor (0 ptr, 2 nonptr)", 7: "constructor (static)", 8: "constructor (no CAF, static)", 9: "function", 10: "function (1 ptr, 0 nonptr)", 11: "function (0 ptr, 1 nonptr)", 12: "function (2 ptr, 0 nonptr)", 13: "function (1 ptr, 1 nonptr)", 14: "function (0 ptr, 2 nonptr)", 15: "function (static)", 16: "thunk", 17: "thunk (1 ptr, 0 nonptr)", 18: "thunk (0 ptr, 1 nonptr)", 19: "thunk (2 ptr, 0 nonptr)", 20: "thunk (1 ptr, 1 nonptr)", 21: "thunk (0 ptr, 2 nonptr)", 22: "thunk (static)", 23: "selector", 28: "indirection", 29: "indirection (permanent)", 30: "indirection (static)", } type = ptrutil.read_half_word(settings, settings.text_offset + address - settings.rt.halfword.size * 2) if type in type_table: return type_table[type] else: return "unknown: " + str(type)
def read_function_type(settings, address): type_table = { 3: '', 4: 'n', 5: 'p', 12: 'nn', 13: 'np', 14: 'pn', 15: 'pp', 16: 'nnn', 17: 'nnp', 18: 'npn', 19: 'npp', 20: 'pnn', 21: 'pnp', 22: 'ppn', 23: 'ppp', 24: 'pppp', 25: 'ppppp', 26: 'pppppp', 27: 'ppppppp', 28: 'pppppppp' } type = ptrutil.read_half_word(settings, settings.text_offset + address - settings.rt.halfword.size*6) if type >= 12 and settings.version < (7, 8, 0): # Introduction of vector arguments type += 3 if type in type_table: return type_table[type] elif type == 0: bitmap = ptrutil.read_word(settings, settings.text_offset + address - settings.rt.word.size*5) size = bitmap & (settings.word.size - 1) bits = bitmap >> settings.word.lg_size ret = '' for i in range(size): if bits % 2 == 0: ret += 'p' else: ret += 'n' bits //= 2 return ret else: # TODO: Read large bitmaps #assert False, "unknown function type" + str(type) + " at "+str(hex(address)) print("##################") print("##################") print("##################") return 'x'
def read_function_type(settings, address): type_table = { 3: '', 4: 'n', 5: 'p', 12: 'nn', 13: 'np', 14: 'pn', 15: 'pp', 16: 'nnn', 17: 'nnp', 18: 'npn', 19: 'npp', 20: 'pnn', 21: 'pnp', 22: 'ppn', 23: 'ppp', 24: 'pppp', 25: 'ppppp', 26: 'pppppp', 27: 'ppppppp', 28: 'pppppppp' } type = ptrutil.read_half_word(settings, settings.text_offset + address - settings.rt.halfword.size*6) if type >= 12 and settings.version < (7, 8, 0): # Introduction of vector arguments type += 3 if type in type_table: return type_table[type] elif type == 0: bitmap = ptrutil.read_word(settings, settings.text_offset + address - settings.rt.word.size*5) size = bitmap & (settings.word.size - 1) bits = bitmap >> settings.word.lg_size ret = '' for i in range(size): if bits % 2 == 0: ret += 'p' else: ret += 'n' bits //= 2 return ret else: # TODO: Read large bitmaps assert False, "unknown function type"
def read_num_args(settings, address): return ptrutil.read_half_word(settings, settings.text_offset + address - settings.rt.halfword.size*5)