Do not access device maps.
It's possible that a device map has memory controlled by a single entry
device driver. Thus, you can deadlock if a process is touching that
device memory and we try to unwind it and also touch that device memory.
Simply skip any attempts to step through, or get function names from
device memory maps.
Bug: 36130325
Test: Ran new unit tests, ran bionic unit tests, ran art ThreadStress.
Change-Id: Ibc62d7ec8106c619ee08968f05e04aea55d7cbfa
diff --git a/libbacktrace/UnwindCurrent.cpp b/libbacktrace/UnwindCurrent.cpp
index 4862d9d..3c509e6 100644
--- a/libbacktrace/UnwindCurrent.cpp
+++ b/libbacktrace/UnwindCurrent.cpp
@@ -127,7 +127,7 @@
if (num_ignore_frames == 0) {
// GetFunctionName is an expensive call, only do it if we are
// keeping the frame.
- frame->func_name = GetFunctionName(frame->pc, &frame->func_offset);
+ frame->func_name = GetFunctionName(frame->pc, &frame->func_offset, &frame->map);
if (num_frames > 0) {
// Set the stack size for the previous frame.
backtrace_frame_data_t* prev = &frames_.at(num_frames-1);
@@ -143,6 +143,16 @@
frames_.resize(0);
}
}
+ // If the pc is in a device map, then don't try to step.
+ if (frame->map.flags & PROT_DEVICE_MAP) {
+ break;
+ }
+ // Verify the sp is not in a device map too.
+ backtrace_map_t map;
+ FillInMap(frame->sp, &map);
+ if (map.flags & PROT_DEVICE_MAP) {
+ break;
+ }
ret = unw_step (cursor.get());
} while (ret > 0 && num_frames < MAX_BACKTRACE_FRAMES);