[PATCH 2/3] Add decoding for binder command/return protocol
Antoine Damhet
antoine.damhet at lse.epita.fr
Sat May 28 20:40:27 UTC 2016
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.damhet at lse.epita.fr>
Reviewed-by: Gabriel Laskar <gabriel at 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
More information about the Strace-devel
mailing list