def test_disassemble_invalid_vst_1_64_raw_data(self): """Test disassembling invalid vst1.64 raw bytes with the API.""" # Create a target from the debugger. target = self.dbg.CreateTargetWithFileAndTargetTriple( "", "thumbv7-apple-macosx") self.assertTrue(target, VALID_TARGET) raw_bytes = bytearray([ 0xf0, 0xb5, 0x03, 0xaf, 0x2d, 0xe9, 0x00, 0x0d, 0xad, 0xf1, 0x40, 0x04, 0x24, 0xf0, 0x0f, 0x04, 0xa5, 0x46 ]) assembly = """ push {r4, r5, r6, r7, lr} add r7, sp, #0xc push.w {r8, r10, r11} sub.w r4, sp, #0x40 bic r4, r4, #0xf mov sp, r4 """ def split(s): return [x.strip() for x in s.strip().splitlines()] insts = target.GetInstructions(lldb.SBAddress(), raw_bytes) if self.TraceOn(): print() for i in insts: print("Disassembled %s" % str(i)) if sys.version_info.major >= 3: sio = StringIO() insts.Print(sio) self.assertEqual(split(assembly), split(sio.getvalue())) self.assertEqual(insts.GetSize(), len(split(assembly))) if sys.version_info.major >= 3: for i, asm in enumerate(split(assembly)): inst = insts.GetInstructionAtIndex(i) sio = StringIO() inst.Print(sio) self.assertEqual(asm, sio.getvalue().strip()) raw_bytes = bytearray([0x04, 0xf9, 0xed, 0x82]) insts = target.GetInstructions(lldb.SBAddress(), raw_bytes) inst = insts.GetInstructionAtIndex(0) if self.TraceOn(): print() print("Raw bytes: ", [hex(x) for x in raw_bytes]) print("Disassembled%s" % str(inst)) self.assertEqual(inst.GetMnemonic(target), "vst1.64")
def test_non_address_bit_memory_corefile(self): self.runCmd("target create --core corefile") self.expect("thread list", substrs=['stopped', 'stop reason = signal SIGSEGV']) # No caching (the program/corefile are the cache) and no writing # to memory. So just check that tagged/untagged addresses read # the same location. # These are known addresses in the corefile, since we won't have symbols. buf = 0x0000ffffa75a5000 buf_with_non_address = 0xff0bffffa75a5000 expected = ["4c 4c 44 42", "LLDB"] self.expect("memory read 0x{:x}".format(buf), substrs=expected) self.expect("memory read 0x{:x}".format(buf_with_non_address), substrs=expected) # This takes a more direct route to ReadMemory. As opposed to "memory read" # above that might fix the addresses up front for display reasons. self.expect("expression (char*)0x{:x}".format(buf), substrs=["LLDB"]) self.expect("expression (char*)0x{:x}".format(buf_with_non_address), substrs=["LLDB"]) def check_reads(addrs, method, num_bytes, expected): error = lldb.SBError() for addr in addrs: if num_bytes is None: got = method(addr, error) else: got = method(addr, num_bytes, error) self.assertTrue(error.Success()) self.assertEqual(expected, got) addr_buf = lldb.SBAddress() addr_buf.SetLoadAddress(buf, self.target()) addr_buf_with_non_address = lldb.SBAddress() addr_buf_with_non_address.SetLoadAddress(buf_with_non_address, self.target()) check_reads([addr_buf, addr_buf_with_non_address], self.target().ReadMemory, 4, b'LLDB') addrs = [buf, buf_with_non_address] check_reads(addrs, self.process().ReadMemory, 4, b'LLDB') check_reads(addrs, self.process().ReadCStringFromMemory, 5, "LLDB") check_reads(addrs, self.process().ReadUnsignedFromMemory, 4, 0x42444c4c) check_reads(addrs, self.process().ReadPointerFromMemory, None, 0x0000000042444c4c)
def task_get_ith_ipc_entry(target_task, index): """ Return the INDEX-th ipc_entry in TARGET_TASK's itk_space. params: target_task - lldb.SBValue index - int returns: ipc_entry - lldb.SBValue throws: IndexError - If index is out of bound. """ itk_space = target_task.GetChildMemberWithName('itk_space') is_table_size = itk_space.GetChildMemberWithName( 'is_table_size').GetValueAsUnsigned() is_table = itk_space.GetChildMemberWithName('is_table') if index >= is_table_size: raise IndexError("Index must be less than is_table_size.") if index <= 0: raise IndexError( "Index must be positive. 0 is reserved for sentinel node.") ith_ipc_entry_addr = is_table.GetValueAsUnsigned( ) + index * SIZE_OF_IPC_ENTRY ith_ipc_entry_sbaddr = lldb.SBAddress(ith_ipc_entry_addr, lldb.debugger.GetSelectedTarget()) ipc_entry_type = getsbtype("struct ipc_entry") ipc_entry = lldb.debugger.GetSelectedTarget().CreateValueFromAddress( 'ith_entry', ith_ipc_entry_sbaddr, ipc_entry_type) return ipc_entry
def dyld_arm64_resolve_dispatch(target, target_address): ''' target: SBTarget target_address : target call address bl <addr> @return : a symbol if error return empty string dyld_shared_cache of iOS alway dispatch an other module function by: libdispatch:__stubs:00000001800B2E28 ADRP X16, #0x193E1A460@PAGE libdispatch:__stubs:00000001800B2E2C ADD X16, X16, #0x193E1A460@PAGEOFF libdispatch:__stubs:00000001800B2E30 BR X16 out goal to resolve symbol for this address ''' instructions = target.ReadInstructions( lldb.SBAddress(target_address, target), 3, 'intel') if instructions.GetSize() == 0: return 0 if instructions[0].GetMnemonic(target) != 'adrp' or instructions[1].GetMnemonic(target) != 'add' or \ (instructions[2].GetMnemonic(target) != 'br' and instructions[2].GetOperands(target).startswith('x')): return 0 page_shift = int(instructions[0].GetOperands(target).split(',')[1]) target_page = (target_address + page_shift * 0x1000) & 0xFFFFFFFFFFFFF000 call_offset = int( instructions[1].GetOperands(target).split(',')[2].strip(' #'), 16) call_func_ptr = target_page + call_offset return call_func_ptr
def task_iterate_ipc_entry(target_task, disposition=None): """ Iterate over all ipc_entry in TARGET_TASK with port type DISPOSITION. params: target_task - lldb.SBValue disposition - bitmap If None, no restriction on port disposition yields: (ipc_entry, - lldb.SBValue cur_index) - int Entry's index into is_table """ ipc_space = target_task.GetChildMemberWithName('itk_space') is_table_size = ipc_space.GetChildMemberWithName( 'is_table_size').GetValueAsUnsigned() is_table = ipc_space.GetChildMemberWithName('is_table') cur_index = 0 while cur_index < is_table_size: ith_ipc_entry_addr = is_table.GetValueAsUnsigned( ) + cur_index * SIZE_OF_IPC_ENTRY ith_ipc_entry_sbaddr = lldb.SBAddress( ith_ipc_entry_addr, lldb.debugger.GetSelectedTarget()) ipc_entry_type = getsbtype("struct ipc_entry") ipc_entry = lldb.debugger.GetSelectedTarget().CreateValueFromAddress( 'ith_entry', ith_ipc_entry_sbaddr, ipc_entry_type) # First entry of is_table is a sentinel node with ie_bits 0xff000000 and thus will not be yielded if disposition == None or port_entry_contains_disposition( ipc_entry, disposition): yield (ipc_entry, cur_index) cur_index += 1
def backtrace_print_frame (target, frame_num, addr, fp): process = target.GetProcess() addr_for_printing = addr addr_width = process.GetAddressByteSize() * 2 if frame_num > 0: addr = addr - 1 sbaddr = lldb.SBAddress() try: sbaddr.SetLoadAddress(addr, target) module_description = "" if sbaddr.GetModule(): module_filename = "" module_uuid_str = sbaddr.GetModule().GetUUIDString() if module_uuid_str == None: module_uuid_str = "" if sbaddr.GetModule().GetFileSpec(): module_filename = sbaddr.GetModule().GetFileSpec().GetFilename() if module_filename == None: module_filename = "" if module_uuid_str != "" or module_filename != "": module_description = '{0!s} {1!s}'.format(module_filename, module_uuid_str) except Exception: print '%2d: pc==0x%-*x fp==0x%-*x' % (frame_num, addr_width, addr_for_printing, addr_width, fp) return sym_ctx = target.ResolveSymbolContextForAddress(sbaddr, lldb.eSymbolContextEverything) if sym_ctx.IsValid() and sym_ctx.GetSymbol().IsValid(): function_start = sym_ctx.GetSymbol().GetStartAddress().GetLoadAddress(target) offset = addr - function_start print '%2d: pc==0x%-*x fp==0x%-*x %s %s + %d' % (frame_num, addr_width, addr_for_printing, addr_width, fp, module_description, sym_ctx.GetSymbol().GetName(), offset) else: print '%2d: pc==0x%-*x fp==0x%-*x %s' % (frame_num, addr_width, addr_for_printing, addr_width, fp, module_description) return sbaddr.GetModule()
def test_disassemble_raw_data(self): """Test disassembling raw bytes with the API.""" # Create a target from the debugger. arch = self.getArchitecture() if re.match("mips*el", arch): target = self.dbg.CreateTargetWithFileAndTargetTriple("", "mipsel") raw_bytes = bytearray([0x21, 0xf0, 0xa0, 0x03]) elif re.match("mips", arch): target = self.dbg.CreateTargetWithFileAndTargetTriple("", "mips") raw_bytes = bytearray([0x03, 0xa0, 0xf0, 0x21]) else: target = self.dbg.CreateTargetWithFileAndTargetTriple("", "x86_64") raw_bytes = bytearray([0x48, 0x89, 0xe5]) self.assertTrue(target, VALID_TARGET) insts = target.GetInstructions(lldb.SBAddress(0, target), raw_bytes) inst = insts.GetInstructionAtIndex(0) if self.TraceOn(): print() print("Raw bytes: ", [hex(x) for x in raw_bytes]) print("Disassembled%s" % str(inst)) if re.match("mips", arch): self.assertTrue(inst.GetMnemonic(target) == "move") self.assertTrue( inst.GetOperands(target) == '$' + "fp, " + '$' + "sp") else: self.assertTrue(inst.GetMnemonic(target) == "movq") self.assertTrue( inst.GetOperands(target) == '%' + "rsp, " + '%' + "rbp")
def updated_content(self): thread = self.__thread if not thread.IsValid(): return 'Invalid thread. Has it finished its work?' target = thread.GetProcess().GetTarget() frame = thread.GetSelectedFrame() registerList = frame.GetRegisters() result = 'Frame registers:' for value in registerList: #print value result = result + ('\n%s (number of registers = %d):\n' % (value.GetName(), value.GetNumChildren())) for child in value: if child.GetValue() is not None: # Let's assume no register name is bigger than 10 chars, for now. # 18 chars are needed for 64 bit values: 0x0000000000000000 addr = lldb.SBAddress(child.GetValueAsUnsigned(), target) desc = lldbutil.get_description(addr) if re.match('0x[0-9A-Fa-f]+|^$', desc): desc = '' else: desc = '; ' + desc result = result + ( '%10.10s = %.18s%s\n' % (child.GetName(), child.GetValue(), desc)) return result
def test_read_memory(self): d = {'EXE': 'b.out'} self.build(dictionary=d) self.setTearDownCleanup(dictionary=d) target = self.create_simple_target('b.out') breakpoint = target.BreakpointCreateByLocation("main.c", self.line_main) self.assertTrue(breakpoint, VALID_BREAKPOINT) # Put debugger into synchronous mode so when we target.LaunchSimple returns # it will guaranteed to be at the breakpoint self.dbg.SetAsync(False) # Launch the process, and do not stop at the entry point. process = target.LaunchSimple(None, None, self.get_process_working_directory()) # find the file address in the .data section of the main # module data_section = self.find_data_section(target) sb_addr = lldb.SBAddress(data_section, 0) error = lldb.SBError() content = target.ReadMemory(sb_addr, 1, error) self.assertSuccess(error, "Make sure memory read succeeded") self.assertEqual(len(content), 1)
def dylan_object_summary(value, internal_dict): # In case we're looking at an object on the stack and not a # pointer to it. if not value.GetType().IsPointerType(): value = value.address_of wrapper_symbol_name = dylan_object_wrapper_symbol_name(value) if not wrapper_symbol_name: # We have no valid wrapper symbol, so just find the symbol # for the address and use that. This is probably not actually # a dylan_value. target = lldb.debugger.GetSelectedTarget() address = lldb.SBAddress(value.GetValueAsUnsigned(), target) return address.symbol.name summary_func = SUMMARY_DISPATCH_TABLE.get(wrapper_symbol_name, None) if summary_func: # Look this up now so that we know we're probably valid given that # we have a summary func. If not, we wrap it in try/except below # to catch possible errors. class_name = dylan_object_class_name(value) summary = summary_func(value, internal_dict) if summary is not None: return '{%s: %s}' % (class_name, summary) else: return '{%s}' % (class_name, ) else: try: return '{%s}' % (dylan_object_class_name(value), ) except: return '{uninitialized}'
def dump_page(debugger, command, result, internal_dict): if not ('RUBY_Qfalse' in globals()): lldb_init(debugger) target = debugger.GetSelectedTarget() process = target.GetProcess() thread = process.GetSelectedThread() frame = thread.GetSelectedFrame() tHeapPageP = target.FindFirstType("struct heap_page").GetPointerType() page = frame.EvaluateExpression(command) page = page.Cast(tHeapPageP) tRBasic = target.FindFirstType("struct RBasic") tRValue = target.FindFirstType("struct RVALUE") obj_address = page.GetChildMemberWithName('start').GetValueAsUnsigned() num_slots = page.GetChildMemberWithName('total_slots').unsigned ruby_type_map = ruby_types(debugger) for j in range(0, num_slots): offset = obj_address + (j * tRValue.GetByteSize()) obj_addr = lldb.SBAddress(offset, target) p = target.CreateValueFromAddress("object", obj_addr, tRBasic) dump_bits(target, result, page, offset, end=" ") flags = p.GetChildMemberWithName('flags').GetValueAsUnsigned() print("%s [%3d]: Addr: %0#x (flags: %0#x)" % (rb_type(flags, ruby_type_map), j, offset, flags), file=result)
def test_SBAddress(self): obj = lldb.SBAddress() if self.TraceOn(): print obj self.assertFalse(obj) # Do fuzz testing on the invalid obj, it should not crash lldb. import sb_address sb_address.fuzz_obj(obj)
def fuzz_obj(obj): obj.GetProcess() listener = lldb.SBListener() error = lldb.SBError() obj.Launch(listener, None, None, None, None, None, None, 0, True, error) obj.LaunchSimple(None, None, None) obj.AttachToProcessWithID(listener, 123, error) obj.AttachToProcessWithName(listener, 'lldb', False, error) obj.ConnectRemote(listener, "connect://to/here", None, error) obj.GetExecutable() obj.GetNumModules() obj.GetModuleAtIndex(0xffffffff) obj.GetDebugger() filespec = lldb.SBFileSpec() obj.FindModule(filespec) sc_list = obj.FindFunctions("the_func") sc_list = obj.FindFunctions("the_func", lldb.eFunctionNameTypeAny) obj.FindFirstType("dont_care") obj.FindTypes("dont_care") obj.FindFirstType(None) obj.GetInstructions(lldb.SBAddress(), bytearray()) obj.GetSourceManager() obj.FindGlobalVariables("my_global_var", 1) address = obj.ResolveLoadAddress(0xffff) obj.ResolveSymbolContextForAddress(address, 0) obj.BreakpointCreateByLocation("filename", 20) obj.BreakpointCreateByLocation(filespec, 20) obj.BreakpointCreateByName("func", None) obj.BreakpointCreateByRegex("func.", None) obj.BreakpointCreateByAddress(0xf0f0) obj.GetNumBreakpoints() obj.GetBreakpointAtIndex(0) obj.BreakpointDelete(0) obj.FindBreakpointByID(0) obj.EnableAllBreakpoints() obj.DisableAllBreakpoints() obj.DeleteAllBreakpoints() obj.GetNumWatchpoints() obj.GetWatchpointAtIndex(0) obj.DeleteWatchpoint(0) obj.FindWatchpointByID(0) obj.EnableAllWatchpoints() obj.DisableAllWatchpoints() obj.DeleteAllWatchpoints() obj.GetAddressByteSize() obj.GetByteOrder() obj.GetTriple() error = lldb.SBError() obj.WatchAddress(123, 8, True, True, error) obj.GetBroadcaster() obj.GetDescription(lldb.SBStream(), lldb.eDescriptionLevelBrief) obj.Clear() for module in obj.module_iter(): s = str(module) for bp in obj.breakpoint_iter(): s = str(bp) for wp in obj.watchpoint_iter(): s = str(wp)
def update(self): #*(void**)(_renderListsLastTouchedIterator.__ptr_ + 1) ptr = self.valobj.GetValueAsUnsigned() target = self.valobj.GetTarget() addr = lldb.SBAddress(ptr, target) ty = target.FindFirstType('void*') self.obj = self.valobj.CreateValueFromAddress('item', addr, ty) #self.obj = self.valobj.CreateValueFromExpression('item', '*(void**)"' + ptr + '"') return
def string(self, length): s = '' for i in range(0, length): target = lldb.debugger.GetSelectedTarget() sbaddr = lldb.SBAddress( self._sbvalue_object.GetValueAsUnsigned() + i, target) sberr = lldb.SBError() ss = str(target.ReadMemory(sbaddr, 1, sberr)) s += ss return s
def dump_page_internal(page, target, process, thread, frame, result, debugger, highlight=None): if not ('RUBY_Qfalse' in globals()): lldb_init(debugger) ruby_type_map = ruby_types(debugger) freelist = [] fl_start = page.GetChildMemberWithName('freelist').GetValueAsUnsigned() tRVALUE = target.FindFirstType("struct RVALUE") while fl_start > 0: freelist.append(fl_start) obj_addr = lldb.SBAddress(fl_start, target) obj = target.CreateValueFromAddress("object", obj_addr, tRVALUE) fl_start = obj.GetChildMemberWithName("as").GetChildMemberWithName( "free").GetChildMemberWithName("next").GetValueAsUnsigned() page_iter = HeapPageIter(page, target) if page_iter.is_valid(): for (page_index, obj_addr, obj) in page_iter: dump_bits(target, result, page, obj_addr, end=" ") flags = obj.GetChildMemberWithName('flags').GetValueAsUnsigned() flType = flags & RUBY_T_MASK flidx = ' ' if flType == RUBY_T_NONE: try: flidx = "%3d" % freelist.index(obj_addr) except ValueError: flidx = ' -1' if flType == RUBY_T_NONE: klass = obj.GetChildMemberWithName( 'klass').GetValueAsUnsigned() result_str = "%s idx: [%3d] freelist_idx: {%s} Addr: %0#x (flags: %0#x, next: %0#x)" % ( rb_type(flags, ruby_type_map), page_index, flidx, obj_addr, flags, klass) else: result_str = "%s idx: [%3d] freelist_idx: {%s} Addr: %0#x (flags: %0#x)" % ( rb_type(flags, ruby_type_map), page_index, flidx, obj_addr, flags) if highlight == obj_addr: result_str = ' '.join([result_str, "<<<<<"]) print(result_str, file=result) else: print("%s is not a valid heap page" % page, file=result)
def dylan_method_iep_function(value): def get_iep(value): if dylan_object_wrapper_subtype_mask(value) & 8192: return dylan_slot_element(value, KEYWORD_METHOD_IEP) else: return dylan_slot_element(value, METHOD_MEP) iep = get_iep(value) target = lldb.debugger.GetSelectedTarget() address = lldb.SBAddress(iep.GetValueAsUnsigned(), target) return address.GetFunction()
def iseq_extract_values(self, debugger, target, process, result, iseqs, n): tValueP = target.FindFirstType("VALUE") sizeofValueP = tValueP.GetByteSize() pc = iseqs.unsigned + (n * sizeofValueP) insn = target.CreateValueFromAddress("i", lldb.SBAddress(pc, target), tValueP) addr = insn.GetValueAsUnsigned() orig_insn = self.rb_vm_insn_addr2insn2(target, result, addr) name = self.insn_name(target, process, result, orig_insn) length = self.insn_len(target, orig_insn) op_str = self.insn_op_types(target, process, result, orig_insn) op_types = bytes(op_str, 'utf-8') if length != (len(op_types) + 1): print("error decoding iseqs", file=result) return -1 print("%0#14x %04d %s" % (pc, n, name), file=result, end="") if length == 1: print("", file=result) return length print("(", end="", file=result) for idx, op_type in enumerate(op_types): if idx == 0: print(" ", end="", file=result) else: print(", ", end="", file=result) opAddr = lldb.SBAddress( iseqs.unsigned + ((n + idx + 1) * sizeofValueP), target) opValue = target.CreateValueFromAddress("op", opAddr, tValueP) op = opValue.GetValueAsUnsigned() print(self.ISEQ_OPT_DISPATCH.get(op_type) % op, end="", file=result) print(" )", file=result) return length
def ImageLookupAddress(debugger, command, exe_ctx, result, internal_dict): target = exe_ctx.GetTarget() depth_p = target.FindFirstGlobalVariable(DEPTH) depth_p = int(depth_p.GetValue()) callstack_p = target.FindFirstGlobalVariable(CALLSTACK) for i in range(depth_p): addr = lldb.SBAddress(int(callstack_p.child[i].GetValue()), target) print() print(hex(addr.file_addr), addr) return
def __next__(self): if self.counter < self.num_slots: obj_addr_i = self.start + (self.counter * self.slot_size) obj_addr = lldb.SBAddress(obj_addr_i, self.target) slot_info = (self.counter, obj_addr_i, self.target.CreateValueFromAddress( "object", obj_addr, self.tRBasic)) self.counter += 1 return slot_info else: raise StopIteration
def dereference(self, pointer, target_id=0): """ Recursively dereference a pointer for display """ t = self.host.GetTargetAtIndex(target_id) error = lldb.SBError() addr = pointer chain = [] # recursively dereference for i in range(0, MAX_DEREF): ptr = t.process.ReadPointerFromMemory(addr, error) if error.Success(): if ptr in chain: chain.append(('circular', 'circular')) break chain.append(('pointer', addr)) addr = ptr else: break if len(chain) == 0: raise InvalidPointerError( "0x{:X} is not a valid pointer".format(pointer)) # get some info for the last pointer # first try to resolve a symbol context for the address p, addr = chain[-1] sbaddr = lldb.SBAddress(addr, t) ctx = t.ResolveSymbolContextForAddress( sbaddr, lldb.eSymbolContextEverything) if ctx.IsValid() and ctx.GetSymbol().IsValid(): # found a symbol, store some info and we're done for this pointer fstart = ctx.GetSymbol().GetStartAddress().GetLoadAddress(t) offset = addr - fstart chain.append( ('symbol', '{} + 0x{:X}'.format(ctx.GetSymbol().name, offset))) log.debug("symbol context: {}".format(str(chain[-1]))) else: # no symbol context found, see if it looks like a string log.debug("no symbol context") s = t.process.ReadCStringFromMemory(addr, 256, error) for i in range(0, len(s)): if ord(s[i]) >= 128: s = s[:i] break if len(s): chain.append(('string', s)) return chain
def disassemble_invalid_vst_1_64_raw_data(self): """Test disassembling invalid vst1.64 raw bytes with the API.""" # Create a target from the debugger. target = self.dbg.CreateTargetWithFileAndTargetTriple ("", "thumbv7") self.assertTrue(target, VALID_TARGET) raw_bytes = bytearray([0xf0, 0xb5, 0x03, 0xaf, 0x2d, 0xe9, 0x00, 0x0d, 0xad, 0xf1, 0x40, 0x04, 0x24, 0xf0, 0x0f, 0x04, 0xa5, 0x46]) insts = target.GetInstructions(lldb.SBAddress(), raw_bytes) if self.TraceOn(): print for i in insts: print "Disassembled%s" % str(i) # Remove the following return statement when the radar is fixed. return # rdar://problem/11034702 # VST1 (multiple single elements) encoding? # The disassembler should not crash! raw_bytes = bytearray([0x04, 0xf9, 0xed, 0x82]) insts = target.GetInstructions(lldb.SBAddress(), raw_bytes) inst = insts.GetInstructionAtIndex(0) if self.TraceOn(): print print "Raw bytes: ", [hex(x) for x in raw_bytes] print "Disassembled%s" % str(inst) self.assertTrue (inst.GetMnemonic(target) == "vst1.64")
def value(self): dict_offset = self.lldb_value.GetChildMemberWithName('ob_type') \ .GetChildMemberWithName('tp_dictoffset') \ .unsigned object_type = self.target.FindFirstType('PyObject') address = lldb.SBAddress( int(self.lldb_value.value, 16) + dict_offset, self.target) value = self.target.CreateValueFromAddress( 'value', address, object_type.GetPointerType()) # "data" is the real object used to store the contents of the class return next(v for k, v in PyDictObject(value).value.items() if k.value == 'data')
def source_location(self, target_id=0, address=None): if target_id is None: target_id=0 if address == None: pc_name, address = self.program_counter(target_id=target_id) t = self.host.GetTargetAtIndex(target_id or 0) sbaddr = lldb.SBAddress(address, t) ctx = t.ResolveSymbolContextForAddress(sbaddr, lldb.eSymbolContextEverything) if ctx.IsValid() and ctx.GetSymbol().IsValid(): line_entry = ctx.GetLineEntry() if line_entry.IsValid(): file_spec = line_entry.GetFileSpec() return (file_spec.__get_fullpath__(), line_entry.GetLine()) return None
def rb_ary_entry(target, ary, idx, result): tRArray = target.FindFirstType("struct RArray").GetPointerType() ary = ary.Cast(tRArray) flags = ary.GetValueForExpressionPath("->flags").GetValueAsUnsigned() if flags & RUBY_FL_USER1: ptr = ary.GetValueForExpressionPath("->as.ary") else: ptr = ary.GetValueForExpressionPath("->as.heap.ptr") ptr_addr = ptr.GetValueAsUnsigned() + (idx * ptr.GetType().GetByteSize()) return target.CreateValueFromAddress("ary_entry[%d]" % idx, lldb.SBAddress(ptr_addr, target), ptr.GetType().GetPointeeType())
def dylan_object_wrapper_symbol_name(value): # We don't want to get the actual wrapper value object here # as that creates circular loops with synthetics by creating # an object, which creates a synthetic which looks at the wrapper # symbol name, which if it accessed the wrapper value object # would create a new object and synthetic, etc. target = lldb.debugger.GetSelectedTarget() if value.GetValueAsUnsigned() == 0: return None try: wrapper_address = dylan_object_wrapper_address(value) except: return None address = lldb.SBAddress(wrapper_address, target) return address.symbol.name
def create_stackframes(self): if not self.has_crashed: return None if not self.backing_thread or not len(self.backing_thread.frames): return None for frame in self.backing_thread.frames: sym_addr = lldb.SBAddress() sym_addr.SetLoadAddress(frame.pc, self.target) if not sym_addr.IsValid(): continue self.frames.append({"idx": frame.index, "pc": frame.pc}) return self.frames
def build_addr2insn(self, target): tIntPtr = target.FindFirstType("intptr_t") size = target.EvaluateExpression('ruby_vminsn_type::VM_INSTRUCTION_SIZE').unsigned sizeOfIntPtr = tIntPtr.GetByteSize() addr_of_table = target.FindSymbols("vm_exec_core.insns_address_table")[0].GetSymbol().GetStartAddress().GetLoadAddress(target) my_dict = {} for insn in range(size): addr_in_table = addr_of_table + (insn * sizeOfIntPtr) addr = lldb.SBAddress(addr_in_table, target) machine_insn = target.CreateValueFromAddress("insn", addr, tIntPtr).GetValueAsUnsigned() my_dict[machine_insn] = insn return my_dict
def print_bt(self, ec): tRbExecutionContext_t = self.target.FindFirstType( "rb_execution_context_t") ec = ec.Cast(tRbExecutionContext_t.GetPointerType()) vm_stack = ec.GetValueForExpressionPath("->vm_stack") vm_stack_size = ec.GetValueForExpressionPath("->vm_stack_size") last_cfp_frame = ec.GetValueForExpressionPath("->cfp") cfp_type_p = last_cfp_frame.GetType() stack_top = vm_stack.GetValueAsUnsigned() + ( vm_stack_size.GetValueAsUnsigned() * vm_stack.GetType().GetByteSize()) cfp_frame_size = cfp_type_p.GetPointeeType().GetByteSize() start_cfp = stack_top # Skip dummy frames start_cfp -= cfp_frame_size start_cfp -= cfp_frame_size last_cfp = last_cfp_frame.GetValueAsUnsigned() size = ((start_cfp - last_cfp) / cfp_frame_size) + 1 print(self.fmt % ("rb_control_frame_t", "TYPE", ""), file=self.result) curr_addr = start_cfp while curr_addr >= last_cfp: cfp = self.target.CreateValueFromAddress( "cfp", lldb.SBAddress(curr_addr, self.target), cfp_type_p.GetPointeeType()) ep = cfp.GetValueForExpressionPath("->ep") iseq = cfp.GetValueForExpressionPath("->iseq") frame_type = ep.GetChildAtIndex( 0).GetValueAsUnsigned() & self.VM_FRAME_MAGIC_MASK if iseq.GetValueAsUnsigned(): pc = cfp.GetValueForExpressionPath("->pc") if pc.GetValueAsUnsigned(): self.dump_iseq_frame(cfp, iseq) else: if frame_type == self.VM_FRAME_MAGIC_CFUNC: self.dump_cfunc_frame(cfp) curr_addr -= cfp_frame_size
def symbolicate(self, load_addr, verbose=False): if not self.target: self.create_target() if self.target: live_process = False process = self.target.process if process: state = process.state if state > lldb.eStateUnloaded and state < lldb.eStateDetached: live_process = True # If we don't have a live process, we can attempt to find the image # that a load address belongs to and lazily load its module in the # target, but we shouldn't do any of this if we have a live process if not live_process: image = self.find_image_containing_load_addr(load_addr) if image: image.add_module(self.target) symbolicated_address = Address(self.target, load_addr) if symbolicated_address.symbolicate(verbose): if symbolicated_address.so_addr: symbolicated_addresses = list() symbolicated_addresses.append(symbolicated_address) # See if we were able to reconstruct anything? while True: inlined_parent_so_addr = lldb.SBAddress() inlined_parent_sym_ctx = symbolicated_address.sym_ctx.GetParentOfInlinedScope( symbolicated_address.so_addr, inlined_parent_so_addr) if not inlined_parent_sym_ctx: break if not inlined_parent_so_addr: break symbolicated_address = Address( self.target, inlined_parent_so_addr.GetLoadAddress(self.target)) symbolicated_address.sym_ctx = inlined_parent_sym_ctx symbolicated_address.so_addr = inlined_parent_so_addr symbolicated_address.symbolicate(verbose) # push the new frame onto the new frame stack symbolicated_addresses.append(symbolicated_address) if symbolicated_addresses: return symbolicated_addresses else: print('error: no target in Symbolicator') return None