def match_frames(page_faults, frames, foreign_frames): log.info("Matching frames for each fault") frame_map = build_frame_va_map(frames) foreign_frame_map = build_frame_va_map(foreign_frames) unresolved = 0 foreign_resolved = 0 results = [] for fault in page_faults: va = get_fault_va(fault) pa = get_fault_pa(fault) va_page = page_align(va) pa_page = page_align(pa) frame = select_frame(frame_map[va_page], pa_page) if frame is None: frame = select_frame(foreign_frame_map[va_page], pa_page) if frame is None: unresolved += 1 else: foreign_resolved += 1 log.info("%#016x -> %s", va_page, frame['FrameFile'] if frame else "?") if frame: results.append((va_page, frame['FrameFile'])) log.info("Failed to resolve %d faults. Let's hope they're not related to code", unresolved) log.info("Resolved %d from external CR3", foreign_resolved) return results
def debug_faults(page_faults): faulted_pages = sorted(set(page_align((get_fault_va(fault))) for fault in page_faults)) ranges = [] current = [] for a, b in zip(faulted_pages, faulted_pages[1:]): current.append(a) if (b - a) == 0x1000: continue else: ranges.append(current) current = [] for chunk in ranges: beg = chunk[0] end = chunk[-1] + 0xfff length = (end + 1 - beg) / 0x1000 log.debug("%#016x - %#016x (%d pages)", beg, end, length)
def select_frame(frames, phys_addr): for frame in frames: if phys_addr == page_align(get_trap_pa(frame)): return frame return None
def build_frame_va_map(frames): frame_map = defaultdict(list) for frame in frames: addr = page_align(get_frame_va(frame)) frame_map[addr].append(frame) return frame_map