[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