Add getHwBinderKernelReferences

Add a wrapper for the new BINDER_GET_NODE_DEBUG_INFO ioctl for use by
libmemunreachable.

Test: memunreachable_binder_test
Bug: 28275695
Change-Id: I66337691d4e00a81159a8ca4856c8f5c5cf493ee
Merged-In: I66337691d4e00a81159a8ca4856c8f5c5cf493ee
(cherry picked from commit 85966ba503e89311ad92c1047b6067020f347488)
diff --git a/ProcessState.cpp b/ProcessState.cpp
index 322b68f..16bbd4d 100644
--- a/ProcessState.cpp
+++ b/ProcessState.cpp
@@ -18,12 +18,12 @@
 
 #include <hwbinder/ProcessState.h>
 
-#include <utils/Atomic.h>
 #include <hwbinder/BpHwBinder.h>
 #include <hwbinder/IPCThreadState.h>
+#include <hwbinder/binder_kernel.h>
+#include <utils/Atomic.h>
 #include <utils/Log.h>
 #include <utils/String8.h>
-#include <utils/String8.h>
 #include <utils/threads.h>
 
 #include <private/binder/binder_module.h>
@@ -75,6 +75,11 @@
     return gProcess;
 }
 
+sp<ProcessState> ProcessState::selfOrNull() {
+    Mutex::Autolock _l(gProcessMutex);
+    return gProcess;
+}
+
 void ProcessState::setContextObject(const sp<IBinder>& object)
 {
     setContextObject(object, String16("default"));
@@ -163,6 +168,34 @@
     return mManagesContexts;
 }
 
+// Get references to userspace objects held by the kernel binder driver
+// Writes up to count elements into buf, and returns the total number
+// of references the kernel has, which may be larger than count.
+// buf may be NULL if count is 0.  The pointers returned by this method
+// should only be used for debugging and not dereferenced, they may
+// already be invalid.
+ssize_t ProcessState::getKernelReferences(size_t buf_count, uintptr_t* buf) {
+    binder_node_debug_info info = {};
+
+    uintptr_t* end = buf ? buf + buf_count : NULL;
+    size_t count = 0;
+
+    do {
+        status_t result = ioctl(mDriverFD, BINDER_GET_NODE_DEBUG_INFO, &info);
+        if (result < 0) {
+            return -1;
+        }
+        if (info.ptr != 0) {
+            if (buf && buf < end) *buf++ = info.ptr;
+            count++;
+            if (buf && buf < end) *buf++ = info.cookie;
+            count++;
+        }
+    } while (info.ptr != 0);
+
+    return count;
+}
+
 ProcessState::handle_entry* ProcessState::lookupHandleLocked(int32_t handle)
 {
     const size_t N=mHandleToObject.size();