OSDN Git Service

Add getBinderKernelReferences
authorColin Cross <ccross@android.com>
Wed, 21 Jun 2017 00:48:33 +0000 (17:48 -0700)
committerColin Cross <ccross@android.com>
Wed, 12 Jul 2017 21:00:56 +0000 (14:00 -0700)
Add a wrapper for the new BINDER_GET_NODE_DEBUG_INFO ioctl for use by
libmemunreachable.

Test: memunreachable_binder_test
Bug: 28275695
Change-Id: Ic112584fa05071bd336974b3a18869077a69389b

libs/binder/Debug.cpp
libs/binder/ProcessState.cpp
libs/binder/include/binder/Debug.h
libs/binder/include/binder/ProcessState.h

index a8f2da5..4ac61a3 100644 (file)
@@ -15,6 +15,7 @@
  */
 
 #include <binder/Debug.h>
+#include <binder/ProcessState.h>
 
 #include <utils/misc.h>
 
@@ -294,5 +295,14 @@ void printHexData(int32_t indent, const void *buf, size_t length,
     }
 }
 
+ssize_t getBinderKernelReferences(size_t count, uintptr_t* buf) {
+    sp<ProcessState> proc = ProcessState::selfOrNull();
+    if (proc.get() == NULL) {
+        return 0;
+    }
+
+    return proc->getKernelReferences(count, buf);
+}
+
 }; // namespace android
 
index add5e74..11dd525 100644 (file)
@@ -90,6 +90,12 @@ sp<ProcessState> ProcessState::initWithDriver(const char* driver)
     return gProcess;
 }
 
+sp<ProcessState> ProcessState::selfOrNull()
+{
+    Mutex::Autolock _l(gProcessMutex);
+    return gProcess;
+}
+
 void ProcessState::setContextObject(const sp<IBinder>& object)
 {
     setContextObject(object, String16("default"));
@@ -176,6 +182,46 @@ bool ProcessState::becomeContextManager(context_check_func checkFunc, void* user
     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)
+{
+    // TODO: remove these when they are defined by bionic's binder.h
+    struct binder_node_debug_info {
+        binder_uintptr_t ptr;
+        binder_uintptr_t cookie;
+        __u32 has_strong_ref;
+        __u32 has_weak_ref;
+    };
+#define BINDER_GET_NODE_DEBUG_INFO _IOWR('b', 11, struct binder_node_debug_info)
+
+    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();
index f6a3355..be0266c 100644 (file)
 #define ANDROID_BINDER_DEBUG_H
 
 #include <stdint.h>
+#include <sys/cdefs.h>
 #include <sys/types.h>
 
 namespace android {
 // ---------------------------------------------------------------------------
 
-#ifdef __cplusplus
-extern "C" {
-#endif
+__BEGIN_DECLS
 
 const char* stringForIndent(int32_t indentLevel);
 
@@ -39,9 +38,10 @@ void printHexData(int32_t indent, const void *buf, size_t length,
     size_t alignment=0, bool cArrayStyle=false,
     debugPrintFunc func = 0, void* cookie = 0);
 
-#ifdef __cplusplus
-}
-#endif
+
+ssize_t getBinderKernelReferences(size_t count, uintptr_t* buf);
+
+__END_DECLS
 
 // ---------------------------------------------------------------------------
 }; // namespace android
index 1ef045d..f85c261 100644 (file)
@@ -35,6 +35,7 @@ class ProcessState : public virtual RefBase
 {
 public:
     static  sp<ProcessState>    self();
+    static  sp<ProcessState>    selfOrNull();
     /* initWithDriver() can be used to configure libbinder to use
      * a different binder driver dev node. It must be called *before*
      * any call to ProcessState::self(). /dev/binder remains the default.
@@ -71,6 +72,8 @@ public:
 
             String8             getDriverName();
 
+            ssize_t             getKernelReferences(size_t count, uintptr_t* buf);
+
 private:
     friend class IPCThreadState;