This patch finishes the decoding of the content of
binder_driver_return_protocol and binder_driver_command_protocol.

* binder.c: Completed.
* xlat/binder_object_flags.in: New file.
* xlat/binder_transaction_flags.in: New file.

Signed-off-by: Antoine Damhet <antoine.dam...@lse.epita.fr>
Reviewed-by: Gabriel Laskar <gabr...@lse.epita.fr>
---
All the underlaying BINDER_WRITE_READ structures are now decoded.
I tested on aosp 6.0.1_r17 (x86_64) with BinderDemo (in the external
folder). The expected output with "strace -v -e ioctl binder" should be:
ioctl(4, BINDER_VERSION, {protocol_version=8}) = 0
ioctl(4, BINDER_SET_MAX_THREADS, [15])  = 0
ioctl(4, BINDER_WRITE_READ, {write_size=68, write_consumed=0, 
write_buffer=[[BC_TRANSACTION, {{handle=0}, cookie=0x0, code=1599098439, 
flags=TF_ACCEPT_FDS, sender_pid=0, sender_euid=0, data_size=0, offsets_size=0, 
data=[NULL]}]], read_size=256, read_consumed=0} => {write_size=68, 
write_consumed=68, read_size=256, read_consumed=76, read_buffer=[BR_NOOP, 
BR_TRANSACTION_COMPLETE, [BR_REPLY, {cookie=0x0, code=0, flags=0, sender_pid=0, 
sender_euid=1000, data_size=0, offsets_size=0, data=[""]}]]}) = 0
ioctl(4, BINDER_WRITE_READ, {write_size=96, write_consumed=0, 
write_buffer=[[BC_FREE_BUFFER, 0x7f19e93c2050], [BC_INCREFS, 0], [BC_ACQUIRE, 
0], [BC_TRANSACTION, {{handle=0}, cookie=0x0, code=3, flags=TF_ACCEPT_FDS, 
sender_pid=0, sender_euid=0, data_size=108, offsets_size=8, 
data=[{type=BINDER_TYPE_BINDER, flags=FLAT_BINDER_FLAG_ACCEPTS_FDS|7f, 
{binder=0x7f19e9651120}, cookie=0x7f19e964c128}]}]], read_size=256, 
read_consumed=0} => {write_size=96, write_consumed=96, read_size=256, 
read_consumed=116, read_buffer=[BR_NOOP, [BR_INCREFS, {ptr=0x7f19e9651120, 
cookie=0x7f19e964c128}], [BR_ACQUIRE, {ptr=0x7f19e9651120, 
cookie=0x7f19e964c128}], BR_TRANSACTION_COMPLETE, [BR_REPLY, {cookie=0x0, 
code=0, flags=0, sender_pid=0, sender_euid=1000, data_size=4, offsets_size=0, 
data=["\0\0\0\0"]}]]}) = 0
ioctl(4, BINDER_WRITE_READ, {write_size=56, write_consumed=0, 
write_buffer=[[BC_INCREFS_DONE, {ptr=0x7f19e9651120, cookie=0x7f19e964c128}], 
[BC_ACQUIRE_DONE, {ptr=0x7f19e9651120, cookie=0x7f19e964c128}], 
[BC_FREE_BUFFER, 0x7f19e93c2050], BC_ENTER_LOOPER], read_size=256, 
read_consumed=0}
 binder.c                         | 251 ++++++++++++++++++++++++++++++++++++---
 xlat/binder_transaction_flags.in |   8 ++
 xlat/binder_types.in             |   9 ++
 3 files changed, 252 insertions(+), 16 deletions(-)
 create mode 100644 xlat/binder_transaction_flags.in
 create mode 100644 xlat/binder_types.in

diff --git a/binder.c b/binder.c
index 8781374..d0d7ee5 100644
--- a/binder.c
+++ b/binder.c
@@ -15,6 +15,233 @@
 
 #include "xlat/binder_driver_commands.h"
 #include "xlat/binder_driver_returns.h"
+#include "xlat/binder_transaction_flags.h"
+#include "xlat/binder_types.h"
+
+static void
+decode_flat_binder_object(struct flat_binder_object *obj)
+{
+       tprints("{type=");
+       printxval(binder_types, obj->type, "BINDER_TYPE_???");
+       tprints(", flags=");
+
+       if (obj->flags & FLAT_BINDER_FLAG_ACCEPTS_FDS)
+               tprints("FLAT_BINDER_FLAG_ACCEPTS_FDS|");
+       tprintf("%" PRIx32, FLAT_BINDER_FLAG_PRIORITY_MASK & obj->flags);
+
+       switch (obj->type) {
+       case BINDER_TYPE_HANDLE:
+       case BINDER_TYPE_WEAK_HANDLE:
+       case BINDER_TYPE_FD:
+               tprintf(", {handle=%" PRIu32 "}", obj->handle);
+               break;
+       case BINDER_TYPE_BINDER:
+       case BINDER_TYPE_WEAK_BINDER:
+               tprintf(", {binder=0x%" PRIx64 "}", (uint64_t)obj->binder);
+               break;
+       default:
+               break;
+       }
+
+       tprintf(", cookie=0x%" PRIx64 "}", (uint64_t)obj->cookie);
+}
+
+static int
+decode_binder_transaction_buffer(struct tcb *tcp, struct 
binder_transaction_data *tr)
+{
+       binder_size_t *off = malloc(tr->offsets_size);
+       if (!off)
+               return 1;
+
+       if (umoven(tcp, tr->data.ptr.offsets, tr->offsets_size, off)) {
+               free(off);
+               return 1;
+       }
+
+       char *buf = malloc(tr->data_size);
+       if (!buf) {
+               free(off);
+               return 1;
+       }
+
+       if (umoven(tcp, tr->data.ptr.buffer, tr->data_size, buf)) {
+               free(off);
+               free(buf);
+               return 1;
+       }
+
+       binder_size_t *end = (void *)((char *)off + tr->offsets_size);
+       binder_size_t *i = off;
+
+       goto print_one_transaction;
+       for (; i < end; ++i) {
+               tprints(", ");
+print_one_transaction:
+               decode_flat_binder_object((struct flat_binder_object *)(buf + 
*i));
+       }
+
+       free(off);
+       free(buf);
+       return 0;
+}
+
+static int
+decode_binder_transaction(struct tcb *tcp, struct binder_transaction_data *tr,
+               int reply, int command)
+{
+       tprints("{");
+       if (!reply) {
+               if (command)
+                       tprintf("{handle=%" PRIu32 "}, ", tr->target.handle);
+               else
+                       tprintf("{ptr=0x%" PRIx64 "}, ",
+                                       (uint64_t)tr->target.ptr);
+       }
+
+       tprintf("cookie=0x%" PRIx64 ", code=%" PRIu32 ", flags=",
+                       (uint64_t)tr->cookie, tr->code);
+       printflags(binder_transaction_flags, tr->flags, "TF_???");
+       tprintf(", sender_pid=%d, sender_euid=%d, data_size=%" PRIu64
+                       ", offsets_size=%" PRIu64,
+                       tr->sender_pid, tr->sender_euid,
+                       (uint64_t)tr->data_size, (uint64_t)tr->offsets_size);
+
+       tprints(", data=[");
+       int err = 0;
+
+       if (!tr->offsets_size)
+               printstr(tcp, tr->data.ptr.buffer, tr->data_size);
+       else
+               err = decode_binder_transaction_buffer(tcp, tr);
+
+       tprints("]}");
+       return err;
+}
+
+static void
+decode_binder_ptr_cookie(struct binder_ptr_cookie *ptr)
+{
+       tprintf("{ptr=0x%" PRIx64 ", cookie=0x%" PRIx64 "}",
+                       (uint64_t)ptr->ptr, (uint64_t)ptr->cookie);
+}
+
+static void
+decode_binder_pri_desc(struct binder_pri_desc *desc)
+{
+       tprintf("{priority=%" PRId32 ", desc=%" PRIu32 "}",
+                       desc->priority, desc->desc);
+}
+
+static void
+decode_binder_handle_cookie(struct binder_handle_cookie *handle)
+{
+       tprintf("{handle=%" PRIu32 ", cookie=0x%" PRIx64 "}",
+                       handle->handle, (uint64_t)handle->cookie);
+}
+
+static void
+decode_binder_pri_ptr_cookie(struct binder_pri_ptr_cookie *ptr)
+{
+       tprintf("{priority=%" PRId32 ", ptr=0x%" PRIx64
+                       ", cookie=0x%" PRIx64 "}",
+                       ptr->priority, (uint64_t)ptr->ptr,
+                       (uint64_t)ptr->cookie);
+}
+
+static int
+decode_binder_commands_parameters(struct tcb *tcp, uint32_t type, char *data)
+{
+       int err = 0;
+
+       tprints("[");
+       printxval(binder_driver_commands, type, "BC_???");
+       tprints(", ");
+
+       switch (type) {
+       case BC_TRANSACTION:
+               err = decode_binder_transaction(tcp,
+                               (struct binder_transaction_data *)data, 0, 1);
+               break;
+       case BC_REPLY:
+               err = decode_binder_transaction(tcp,
+                               (struct binder_transaction_data *)data, 1, 1);
+               break;
+       case BC_ACQUIRE_RESULT:
+               tprintf("%" PRId32, *(int32_t *)data);
+               break;
+       case BC_FREE_BUFFER:
+       case BC_DEAD_BINDER_DONE:
+               tprintf("%p", (void *)(*(binder_uintptr_t *)data));
+               break;
+       case BC_INCREFS:
+       case BC_ACQUIRE:
+       case BC_RELEASE:
+       case BC_DECREFS:
+               tprintf("%" PRIu32, *(uint32_t *)data);
+               break;
+       case BC_INCREFS_DONE:
+       case BC_ACQUIRE_DONE:
+               decode_binder_ptr_cookie((struct binder_ptr_cookie *)data);
+               break;
+       case BC_ATTEMPT_ACQUIRE:
+               decode_binder_pri_desc((struct binder_pri_desc *)data);
+               break;
+       case BC_REQUEST_DEATH_NOTIFICATION:
+       case BC_CLEAR_DEATH_NOTIFICATION:
+               decode_binder_handle_cookie((struct binder_handle_cookie 
*)data);
+               break;
+       default:
+               print_quoted_string(data, _IOC_SIZE(type), 0);
+               break;
+       }
+
+       tprints("]");
+       return err;
+}
+
+static int
+decode_binder_returns_parameters(struct tcb *tcp, uint32_t type, char *data)
+{
+       int err = 0;
+
+       tprints("[");
+       printxval(binder_driver_returns, type, "BR_???");
+       tprints(", ");
+
+       switch (type) {
+       case BR_TRANSACTION:
+               err = decode_binder_transaction(tcp,
+                               (struct binder_transaction_data *)data, 0, 0);
+               break;
+       case BR_REPLY:
+               err = decode_binder_transaction(tcp,
+                               (struct binder_transaction_data *)data, 1, 0);
+               break;
+       case BR_ACQUIRE_RESULT:
+       case BR_ERROR:
+               tprintf("%" PRId32, *(int32_t *)data);
+               break;
+       case BR_INCREFS:
+       case BR_ACQUIRE:
+       case BR_RELEASE:
+       case BR_DECREFS:
+               decode_binder_ptr_cookie((struct binder_ptr_cookie *)data);
+               break;
+       case BR_ATTEMPT_ACQUIRE:
+               decode_binder_pri_ptr_cookie((struct binder_pri_ptr_cookie 
*)data);
+               break;
+       case BR_DEAD_BINDER:
+       case BR_CLEAR_DEATH_NOTIFICATION_DONE:
+               tprintf("%p", (void *)(*(binder_uintptr_t *)data));
+               break;
+       default:
+               print_quoted_string(data, _IOC_SIZE(type), 0);
+               break;
+       }
+
+       tprints("]");
+       return err;
+}
 
 static int
 decode_binder_returns(struct tcb *tcp, struct binder_write_read *wr)
@@ -48,14 +275,10 @@ decode_binder_returns(struct tcb *tcp, struct 
binder_write_read *wr)
 
 print_one_read_buffer:
                type = *(uint32_t *)(buffer + pos);
-               if (_IOC_SIZE(type) > 0) {
-                       tprints("[");
-                       printxval(binder_driver_returns, type, "BR_???");
-                       tprints(", ");
-                       print_quoted_string(buffer + pos + sizeof(type),
-                                       _IOC_SIZE(type), 0);
-                       tprints("]");
-               } else
+               if (_IOC_SIZE(type) > 0)
+                       decode_binder_returns_parameters(tcp, type,
+                                       buffer + pos + sizeof(uint32_t));
+               else
                        printxval(binder_driver_returns, type, "BR_???");
                pos += sizeof(uint32_t) + _IOC_SIZE(type);
        }
@@ -97,14 +320,10 @@ decode_binder_commands(struct tcb *tcp, struct 
binder_write_read *wr)
 
 print_one_write_buffer:
                type = *(uint32_t *)(buffer + pos);
-               if (_IOC_SIZE(type) > 0) {
-                       tprints("[");
-                       printxval(binder_driver_commands, type, "BC_???");
-                       tprints(", ");
-                       print_quoted_string(buffer + pos + sizeof(type),
-                                       _IOC_SIZE(type), 0);
-                       tprints("]");
-               } else
+               if (_IOC_SIZE(type) > 0)
+                       decode_binder_commands_parameters(tcp, type,
+                                       buffer + pos + sizeof(uint32_t));
+               else
                        printxval(binder_driver_commands, type, "BC_???");
                pos += sizeof(uint32_t) + _IOC_SIZE(type);
        }
diff --git a/xlat/binder_transaction_flags.in b/xlat/binder_transaction_flags.in
new file mode 100644
index 0000000..eb36ea1
--- /dev/null
+++ b/xlat/binder_transaction_flags.in
@@ -0,0 +1,8 @@
+/*
+ * These values are defined as an enum in linux/android/binder.h and must be
+ * defined here because xlat is unable to fetch them.
+ */
+TF_ONE_WAY 0x01
+TF_ROOT_OBJECT 0x04
+TF_STATUS_CODE 0x08
+TF_ACCEPT_FDS 0x10
diff --git a/xlat/binder_types.in b/xlat/binder_types.in
new file mode 100644
index 0000000..fd30544
--- /dev/null
+++ b/xlat/binder_types.in
@@ -0,0 +1,9 @@
+/*
+ * These values are defined as an enum in linux/android/binder.h and must be
+ * defined here because xlat is unable to fetch them.
+ */
+BINDER_TYPE_BINDER B_PACK_CHARS('s', 'b', '*', B_TYPE_LARGE)
+BINDER_TYPE_WEAK_BINDER B_PACK_CHARS('w', 'b', '*', B_TYPE_LARGE)
+BINDER_TYPE_HANDLE B_PACK_CHARS('s', 'h', '*', B_TYPE_LARGE)
+BINDER_TYPE_WEAK_HANDLE B_PACK_CHARS('w', 'h', '*', B_TYPE_LARGE)
+BINDER_TYPE_FD B_PACK_CHARS('f', 'd', '*', B_TYPE_LARGE)
-- 
2.8.3


------------------------------------------------------------------------------
What NetFlow Analyzer can do for you? Monitors network bandwidth and traffic
patterns at an interface-level. Reveals which users, apps, and protocols are 
consuming the most bandwidth. Provides multi-vendor support for NetFlow, 
J-Flow, sFlow and other flows. Make informed decisions using capacity 
planning reports. https://ad.doubleclick.net/ddm/clk/305295220;132659582;e
_______________________________________________
Strace-devel mailing list
Strace-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/strace-devel

Reply via email to