jasonmolenda created this revision. jasonmolenda added a reviewer: kastiglione. jasonmolenda added a project: LLDB. Herald added subscribers: JDevlieghere, kristof.beyls. Herald added a project: All. jasonmolenda requested review of this revision. Herald added a subscriber: lldb-commits.
A common crash is calling through a null function pointer and trying to execute an instruction at address 0. lldb's backtracer special cases this, but the macOS crash tracer algorithm does not; crash reports will have a stack frame at 0 and then skip the calling stack frame, assuming a stack frame was set up. On arm64, the caller function is likely available in $lr, so let's insert a stack frame with that return pc value. Also fix a little bug where register names without a "prefix" would get "None" prepended, so "Nonepc", "Nonelr" etc. rdar://92631787 Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D125042 Files: lldb/examples/python/crashlog.py Index: lldb/examples/python/crashlog.py =================================================================== --- lldb/examples/python/crashlog.py +++ lldb/examples/python/crashlog.py @@ -516,6 +516,22 @@ image_addr = self.get_used_image(image_id)['base'] pc = image_addr + frame_offset thread.frames.append(self.crashlog.Frame(idx, pc, frame_offset)) + + # on arm64 systems, if jump through a null function pointer, + # we end up at address 0 and the crash reporter unwinder + # misses the frame that actually faulted. + # But $lr can tell us where the last BL/BLR instruction used + # was at, so insert that address as the caller stack frame. + if idx == 0 and pc == 0 and "lr" in thread.registers: + pc = thread.registers["lr"] + for image in self.data['usedImages']: + text_lo = image['base'] + text_hi = text_lo + image['size'] + if text_lo <= pc < text_hi: + idx += 1 + frame_offset = pc - text_lo + thread.frames.append(self.crashlog.Frame(idx, pc, frame_offset)) + idx += 1 def parse_threads(self, json_threads): @@ -551,7 +567,7 @@ continue try: value = int(state['value']) - registers["{}{}".format(prefix,key)] = value + registers["{}{}".format(prefix or '',key)] = value except (KeyError, ValueError, TypeError): pass return registers
Index: lldb/examples/python/crashlog.py =================================================================== --- lldb/examples/python/crashlog.py +++ lldb/examples/python/crashlog.py @@ -516,6 +516,22 @@ image_addr = self.get_used_image(image_id)['base'] pc = image_addr + frame_offset thread.frames.append(self.crashlog.Frame(idx, pc, frame_offset)) + + # on arm64 systems, if jump through a null function pointer, + # we end up at address 0 and the crash reporter unwinder + # misses the frame that actually faulted. + # But $lr can tell us where the last BL/BLR instruction used + # was at, so insert that address as the caller stack frame. + if idx == 0 and pc == 0 and "lr" in thread.registers: + pc = thread.registers["lr"] + for image in self.data['usedImages']: + text_lo = image['base'] + text_hi = text_lo + image['size'] + if text_lo <= pc < text_hi: + idx += 1 + frame_offset = pc - text_lo + thread.frames.append(self.crashlog.Frame(idx, pc, frame_offset)) + idx += 1 def parse_threads(self, json_threads): @@ -551,7 +567,7 @@ continue try: value = int(state['value']) - registers["{}{}".format(prefix,key)] = value + registers["{}{}".format(prefix or '',key)] = value except (KeyError, ValueError, TypeError): pass return registers
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits