This patch introduce decoding for binder ioctls including the command
and return protocol from BINDER_WRITE_READ.

* binder.c: New file.
* xlat/binder_driver_commands.in: New file.
* xlat/binder_driver_returns.in: New file.
* Makefile.am (strace_SOURCES): Add binder.c.
* ioctl.c (ioctl_decode): Call binder_ioctl for 'b' ioctl commands.
* defs.h (binder_ioctl): New prototype.
* configure.ac: Check binder header.

Signed-off-by: Antoine Damhet <antoine.dam...@lse.epita.fr>
Reviewed-by: Gabriel Laskar <gabr...@lse.epita.fr>
---
 Makefile.am                    |   1 +
 binder.c                       | 171 +++++++++++++++++++++++++++++++++++++++++
 configure.ac                   |  39 ++++++++++
 defs.h                         |   1 +
 ioctl.c                        |   4 +
 xlat/binder_driver_commands.in |  17 ++++
 xlat/binder_driver_returns.in  |  18 +++++
 7 files changed, 251 insertions(+)
 create mode 100644 binder.c
 create mode 100644 xlat/binder_driver_commands.in
 create mode 100644 xlat/binder_driver_returns.in

diff --git a/Makefile.am b/Makefile.am
index 77e0cc8..fb75e6d 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -78,6 +78,7 @@ strace_SOURCES =      \
        affinity.c      \
        aio.c           \
        alpha.c         \
+       binder.c        \
        bjm.c           \
        block.c         \
        bpf.c           \
diff --git a/binder.c b/binder.c
new file mode 100644
index 0000000..a614c82
--- /dev/null
+++ b/binder.c
@@ -0,0 +1,171 @@
+#include "defs.h"
+
+#if defined(HAVE_LINUX_ANDROID_BINDER_H) || defined(__ANDROID__)
+
+#include <linux/ioctl.h>
+
+/*
+ * The driver can support either 32 or 64 bit but not both at the same time.
+ */
+#if SIZEOF_LONG == 4
+# define BINDER_IPC_32BIT
+#endif
+#ifdef HAVE_LINUX_ANDROID_BINDER_H
+# include <linux/android/binder.h>
+#else
+# include <linux/binder.h>
+#endif
+
+#include "xlat/binder_driver_commands.h"
+#include "xlat/binder_driver_returns.h"
+
+static int
+decode_binder_commands_buffer(struct tcb *tcp, uintptr_t buffer, size_t pos,
+               size_t size, const struct xlat *x, const char *str)
+{
+       if (size < sizeof(uint32_t)) {
+               printaddr(buffer);
+               return 0;
+       }
+
+       if (abbrev(tcp)) {
+               tprints("[...]");
+               return 0;
+       }
+
+       uint32_t type;
+       int first_time = 1;
+       tprints("[");
+
+       while (pos + sizeof(uint32_t) <= size) {
+               if (umove(tcp, buffer + pos, &type)) {
+                       tprints("]");
+                       return 1;
+               }
+
+               if (!first_time)
+                       tprints(", ");
+               else
+                       first_time = 0;
+
+               if (_IOC_SIZE(type) > 0
+                               && pos + sizeof(type) + _IOC_SIZE(type) <= 
size) {
+                       tprints("{");
+                       printxval(x, type, str);
+                       tprints(", ");
+                       printstr(tcp, buffer + pos + sizeof(type),
+                                       _IOC_SIZE(type));
+                       tprints("}");
+               } else
+                       printxval(x, type, str);
+
+               if (SIZE_MAX - sizeof(uint32_t) + _IOC_SIZE(type) >= pos)
+                       pos += sizeof(uint32_t) + _IOC_SIZE(type);
+               else
+                       break;
+       }
+
+       tprints("]");
+       return 0;
+}
+
+static int
+decode_binder_write_read(struct tcb *tcp, const long addr)
+{
+       struct binder_write_read wr;
+
+       if (entering(tcp)) {
+               tprints(", ");
+               if (umove_or_printaddr(tcp, addr, &wr))
+                       return RVAL_DECODED | 1;
+
+               tprintf("{write_size=%" PRIu64 ", write_consumed=%" PRIu64
+                               ", write_buffer=",
+                               (uint64_t)wr.write_size,
+                               (uint64_t)wr.write_consumed);
+               if (decode_binder_commands_buffer(tcp, wr.write_buffer,
+                                       wr.write_consumed, wr.write_size,
+                                       binder_driver_commands, "BC_???")) {
+                       tprints("}");
+                       return RVAL_DECODED | 1;
+               }
+
+               tprintf(", read_size=%" PRIu64 ", read_consumed=%" PRIu64 "}",
+                               (uint64_t)wr.read_size,
+                               (uint64_t)wr.read_consumed);
+               return 0;
+       }
+
+       if (syserror(tcp) || umove(tcp, addr, &wr))
+               return RVAL_DECODED | 1;
+
+       tprints(" => ");
+
+       tprintf("{write_size=%" PRIu64 ", write_consumed=%" PRIu64
+                       ", read_size=%" PRIu64 ", read_consumed=%" PRIu64
+                       ", read_buffer=",
+                       (uint64_t)wr.write_size,
+                       (uint64_t)wr.write_consumed,
+                       (uint64_t)wr.read_size,
+                       (uint64_t)wr.read_consumed);
+       if (decode_binder_commands_buffer(tcp, wr.read_buffer, 0,
+                               wr.read_consumed,
+                               binder_driver_returns, "BR_???")) {
+               tprints("}");
+               return RVAL_DECODED | 1;
+       }
+
+       tprints("}");
+       return RVAL_DECODED | 1;
+}
+
+int
+decode_binder_version(struct tcb *tcp, long addr)
+{
+       struct binder_version version;
+
+       tprints(", ");
+       if (umove_or_printaddr(tcp, addr, &version))
+               return RVAL_DECODED | 1;
+
+       tprintf("{protocol_version=%" PRId32 "}", version.protocol_version);
+       return RVAL_DECODED | 1;
+}
+
+int
+binder_ioctl(struct tcb *tcp, const unsigned int code, long arg)
+{
+       if (!verbose(tcp))
+               return RVAL_DECODED;
+
+       if (code == BINDER_WRITE_READ)
+               return decode_binder_write_read(tcp, arg);
+
+       if (entering(tcp)) {
+               switch (code) {
+               case BINDER_SET_IDLE_TIMEOUT:
+                       tprints(", ");
+                       printnum_int64(tcp, arg, "%lld");
+                       return RVAL_DECODED | 1;
+               case BINDER_SET_MAX_THREADS:
+                       tprints(", ");
+                       printnum_int(tcp, arg, "%u");
+                       return RVAL_DECODED | 1;
+               case BINDER_SET_IDLE_PRIORITY:
+               case BINDER_SET_CONTEXT_MGR:
+               case BINDER_THREAD_EXIT:
+                       tprints(", ");
+                       printnum_int(tcp, arg, "%d");
+                       return RVAL_DECODED | 1;
+               default:
+                       break;
+               }
+       } else {
+               if (code == BINDER_VERSION)
+                       return decode_binder_version(tcp, arg);
+       }
+
+       return 0;
+}
+
+#endif /* !(HAVE_LINUX_ANDROID_BINDER_H || __ANDROID__) */
diff --git a/configure.ac b/configure.ac
index 9afda73..0d77998 100644
--- a/configure.ac
+++ b/configure.ac
@@ -434,6 +434,45 @@ AC_CHECK_HEADERS([linux/bpf.h], [
        fi
 ])
 
+AC_CHECK_HEADERS([linux/android/binder.h], [[ #include <sys/types.h>
+#include <linux/android/binder.h>])
+       AC_CHECK_DECLS(m4_normalize([BC_TRANSACTION,
+               BC_REPLY,
+               BC_ACQUIRE_RESULT,
+               BC_FREE_BUFFER,
+               BC_INCREFS,
+               BC_ACQUIRE,
+               BC_RELEASE,
+               BC_DECREFS,
+               BC_INCREFS_DONE,
+               BC_ACQUIRE_DONE,
+               BC_ATTEMPT_ACQUIRE,
+               BC_REGISTER_LOOPER,
+               BC_ENTER_LOOPER,
+               BC_EXIT_LOOPER,
+               BC_REQUEST_DEATH_NOTIFICATION,
+               BC_CLEAR_DEATH_NOTIFICATION,
+               BC_DEAD_BINDER_DONE,
+               BR_ERROR,
+               BR_OK,
+               BR_TRANSACTION,
+               BR_REPLY,
+               BR_ACQUIRE_RESULT,
+               BR_DEAD_REPLY,
+               BR_TRANSACTION_COMPLETE,
+               BR_INCREFS,
+               BR_ACQUIRE,
+               BR_RELEASE,
+               BR_DECREFS,
+               BR_ATTEMPT_ACQUIRE,
+               BR_NOOP,
+               BR_SPAWN_LOOPER,
+               BR_FINISHED,
+               BR_DEAD_BINDER,
+               BR_CLEAR_DEATH_NOTIFICATION_DONE,
+               BR_FAILED_REPLY]),,,[ #include <sys/types.h>
+#include <linux/android/binder.h>])])
+
 AC_CHECK_TYPES([struct statfs], [
        AC_CHECK_MEMBERS([struct statfs.f_frsize],,, [#include <linux/types.h>
 #include <asm/statfs.h>])
diff --git a/defs.h b/defs.h
index 99447e6..367a6e9 100644
--- a/defs.h
+++ b/defs.h
@@ -682,6 +682,7 @@ struct strace_statfs;
 extern void print_struct_statfs(struct tcb *tcp, long);
 extern void print_struct_statfs64(struct tcb *tcp, long, unsigned long);
 
+extern int binder_ioctl(struct tcb *, const unsigned int, long);
 extern int file_ioctl(struct tcb *, const unsigned int, long);
 extern int fs_x_ioctl(struct tcb *, const unsigned int, long);
 extern int loop_ioctl(struct tcb *, const unsigned int, long);
diff --git a/ioctl.c b/ioctl.c
index e4b20d9..54aa9a7 100644
--- a/ioctl.c
+++ b/ioctl.c
@@ -282,6 +282,10 @@ ioctl_decode(struct tcb *tcp)
        case 0x94:
                return btrfs_ioctl(tcp, code, arg);
 #endif
+#if defined(HAVE_LINUX_ANDROID_BINDER_H) || defined(__ANDROID__)
+       case 'b':
+               return binder_ioctl(tcp, code, arg);
+#endif
        default:
                break;
        }
diff --git a/xlat/binder_driver_commands.in b/xlat/binder_driver_commands.in
new file mode 100644
index 0000000..84d481c
--- /dev/null
+++ b/xlat/binder_driver_commands.in
@@ -0,0 +1,17 @@
+BC_TRANSACTION
+BC_REPLY
+BC_ACQUIRE_RESULT
+BC_FREE_BUFFER
+BC_INCREFS
+BC_ACQUIRE
+BC_RELEASE
+BC_DECREFS
+BC_INCREFS_DONE
+BC_ACQUIRE_DONE
+BC_ATTEMPT_ACQUIRE
+BC_REGISTER_LOOPER
+BC_ENTER_LOOPER
+BC_EXIT_LOOPER
+BC_REQUEST_DEATH_NOTIFICATION
+BC_CLEAR_DEATH_NOTIFICATION
+BC_DEAD_BINDER_DONE
diff --git a/xlat/binder_driver_returns.in b/xlat/binder_driver_returns.in
new file mode 100644
index 0000000..dc4c4c1
--- /dev/null
+++ b/xlat/binder_driver_returns.in
@@ -0,0 +1,18 @@
+BR_ERROR
+BR_OK
+BR_TRANSACTION
+BR_REPLY
+BR_ACQUIRE_RESULT
+BR_DEAD_REPLY
+BR_TRANSACTION_COMPLETE
+BR_INCREFS
+BR_ACQUIRE
+BR_RELEASE
+BR_DECREFS
+BR_ATTEMPT_ACQUIRE
+BR_NOOP
+BR_SPAWN_LOOPER
+BR_FINISHED
+BR_DEAD_BINDER
+BR_CLEAR_DEATH_NOTIFICATION_DONE
+BR_FAILED_REPLY
-- 
2.8.3


------------------------------------------------------------------------------
Attend Shape: An AT&T Tech Expo July 15-16. Meet us at AT&T Park in San
Francisco, CA to explore cutting-edge tech and listen to tech luminaries
present their vision of the future. This family event has something for
everyone, including kids. Get more information and register today.
http://sdm.link/attshape
_______________________________________________
Strace-devel mailing list
Strace-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/strace-devel

Reply via email to