[PATCH v2 2/3] Add decoding for binder command/return protocol
Antoine Damhet
antoine.damhet at lse.epita.fr
Sat Jun 18 17:13:55 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>
---
binder.c | 283 +++++++++++++++++++++++++++++++++++++--
configure.ac | 7 +-
xlat/binder_transaction_flags.in | 4 +
xlat/binder_types.in | 5 +
4 files changed, 286 insertions(+), 13 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 5997e85..9eb4930 100644
--- a/binder.c
+++ b/binder.c
@@ -18,10 +18,272 @@
#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 bool
+print_flat_binder_object(struct tcb *tcp, void *offset, size_t elem_size,
+ void *buffer)
+{
+ (void)elem_size;
+ binder_size_t *i = offset;
+ struct flat_binder_object obj;
+
+ if (umove(tcp, (uintptr_t)buffer + *i, &obj))
+ return false;
+
+ decode_flat_binder_object(&obj);
+ return true;
+}
+
+static int
+decode_binder_transaction_buffer(struct tcb *tcp, struct binder_transaction_data *tr)
+{
+ binder_size_t sz;
+
+ return !print_array(tcp,
+ tr->data.ptr.offsets,
+ tr->offsets_size / sizeof(binder_size_t),
+ &sz,
+ sizeof(binder_size_t),
+ umoven_or_printaddr,
+ print_flat_binder_object,
+ (void *)tr->data.ptr.buffer);
+}
+
+static int
+decode_binder_transaction(struct tcb *tcp, uintptr_t addr, int reply,
+ int command)
+{
+ struct binder_transaction_data tr;
+
+ if (umove(tcp, addr, &tr))
+ return 1;
+
+ 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 tcb *tcp, uintptr_t addr)
+{
+ struct binder_ptr_cookie ptr;
+
+ if (!umove(tcp, addr, &ptr))
+ tprintf("{ptr=0x%" PRIx64 ", cookie=0x%" PRIx64 "}",
+ (uint64_t)ptr.ptr, (uint64_t)ptr.cookie);
+}
+
+static void
+decode_binder_pri_desc(struct tcb *tcp, uintptr_t addr)
+{
+ struct binder_pri_desc desc;
+
+ if (!umove(tcp, addr, &desc))
+ tprintf("{priority=%" PRId32 ", desc=%" PRIu32 "}",
+ desc.priority, desc.desc);
+}
+
+static void
+decode_binder_handle_cookie(struct tcb *tcp, uintptr_t addr)
+{
+ struct binder_handle_cookie handle;
+
+ if (!umove(tcp, addr, &handle))
+ tprintf("{handle=%" PRIu32 ", cookie=0x%" PRIx64 "}",
+ handle.handle, (uint64_t)handle.cookie);
+}
+
+static void
+decode_binder_pri_ptr_cookie(struct tcb *tcp, uintptr_t addr)
+{
+ struct binder_pri_ptr_cookie ptr;
+
+ if (!umove(tcp, addr, &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, uintptr_t addr)
+{
+ int err = 0;
+
+ tprints("[");
+ printxval(binder_driver_commands, type, "BC_???");
+ tprints(", ");
+
+ switch (type) {
+ case BC_TRANSACTION:
+ err = decode_binder_transaction(tcp, addr, 0, 1);
+ break;
+ case BC_REPLY:
+ err = decode_binder_transaction(tcp, addr, 1, 1);
+ break;
+ case BC_ACQUIRE_RESULT: {
+ int32_t i;
+
+ if (umove(tcp, addr, &i))
+ err = 1;
+ else
+ tprintf("%" PRId32, i);
+ }
+ break;
+ case BC_FREE_BUFFER:
+ case BC_DEAD_BINDER_DONE: {
+ binder_uintptr_t ptr;
+
+ if (umove(tcp, addr, &ptr))
+ err = 1;
+ else
+ tprintf("0x%" PRIx64, (uint64_t)ptr);
+ }
+ break;
+ case BC_INCREFS:
+ case BC_ACQUIRE:
+ case BC_RELEASE:
+ case BC_DECREFS: {
+ uint32_t i;
+
+ if (umove(tcp, addr, &i))
+ err = 1;
+ else
+ tprintf("%" PRIu32, i);
+ }
+ break;
+ case BC_INCREFS_DONE:
+ case BC_ACQUIRE_DONE:
+ decode_binder_ptr_cookie(tcp, addr);
+ break;
+ case BC_ATTEMPT_ACQUIRE:
+ decode_binder_pri_desc(tcp, addr);
+ break;
+ case BC_REQUEST_DEATH_NOTIFICATION:
+ case BC_CLEAR_DEATH_NOTIFICATION:
+ decode_binder_handle_cookie(tcp, addr);
+ break;
+ default:
+ printstr(tcp, addr, _IOC_SIZE(type));
+ break;
+ }
+
+ tprints("]");
+ return err;
+}
+
+static int
+decode_binder_returns_parameters(struct tcb *tcp, uint32_t type, uintptr_t addr)
+{
+ int err = 0;
+
+ tprints("[");
+ printxval(binder_driver_returns, type, "BR_???");
+ tprints(", ");
+
+ switch (type) {
+ case BR_TRANSACTION:
+ err = decode_binder_transaction(tcp, addr, 0, 0);
+ break;
+ case BR_REPLY:
+ err = decode_binder_transaction(tcp, addr, 1, 0);
+ break;
+ case BR_ACQUIRE_RESULT:
+ case BR_ERROR: {
+ int32_t i;
+
+ if (umove(tcp, addr, &i))
+ err = 1;
+ else
+ tprintf("%" PRId32, i);
+ }
+ break;
+ case BR_INCREFS:
+ case BR_ACQUIRE:
+ case BR_RELEASE:
+ case BR_DECREFS:
+ decode_binder_ptr_cookie(tcp, addr);
+ break;
+ case BR_ATTEMPT_ACQUIRE:
+ decode_binder_pri_ptr_cookie(tcp, addr);
+ break;
+ case BR_DEAD_BINDER:
+ case BR_CLEAR_DEATH_NOTIFICATION_DONE: {
+ binder_uintptr_t ptr;
+
+ if (umove(tcp, addr, &ptr))
+ err = 1;
+ else
+ tprintf("0x%" PRIx64, (uint64_t)ptr);
+ }
+ break;
+ default:
+ printstr(tcp, addr, _IOC_SIZE(type));
+ break;
+ }
+
+ tprints("]");
+ return err;
+}
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)
+ size_t size, const struct xlat *x, const char *str,
+ int (*const decode_func)(struct tcb *, uint32_t, uintptr_t))
{
if (size < sizeof(uint32_t)) {
tprints("[]");
@@ -43,15 +305,10 @@ decode_binder_commands_buffer(struct tcb *tcp, uintptr_t buffer, size_t pos,
print_one_commands_buffer:
if (umove(tcp, buffer + pos, &type))
return 1;
- if (_IOC_SIZE(type) > 0) {
- tprints("[");
- printxval(x, type, str);
- tprints(", ");
- if (pos + sizeof(type) + _IOC_SIZE(type) <= size)
- printstr(tcp, buffer + pos + sizeof(type),
- _IOC_SIZE(type));
- tprints("]");
- } else
+ if (_IOC_SIZE(type) > 0
+ && pos + sizeof(type) + _IOC_SIZE(type) <= size)
+ decode_func(tcp, type, buffer + pos + sizeof(uint32_t));
+ else
printxval(x, type, str);
pos += sizeof(uint32_t) + _IOC_SIZE(type);
}
@@ -76,7 +333,8 @@ decode_binder_write_read(struct tcb *tcp, const long addr)
(uint64_t)wr.write_consumed);
if (decode_binder_commands_buffer(tcp, wr.write_buffer,
wr.write_consumed, wr.write_size,
- binder_driver_commands, "BC_???")) {
+ binder_driver_commands, "BC_???",
+ decode_binder_commands_parameters)) {
tprints("}");
return RVAL_DECODED | 1;
}
@@ -101,7 +359,8 @@ decode_binder_write_read(struct tcb *tcp, const long addr)
(uint64_t)wr.read_consumed);
if (decode_binder_commands_buffer(tcp, wr.read_buffer, 0,
wr.read_consumed,
- binder_driver_returns, "BR_???")) {
+ binder_driver_returns, "BR_???",
+ decode_binder_returns_parameters)) {
tprints("}");
return RVAL_DECODED | 1;
}
diff --git a/configure.ac b/configure.ac
index b919449..1797d0a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -455,7 +455,12 @@ AC_CHECK_HEADERS([linux/android/binder.h], [[ #include <sys/types.h>
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>
+ BR_FAILED_REPLY,
+ TF_ONE_WAY, TF_ROOT_OBJECT, TF_STATUS_CODE,
+ TF_ACCEPT_FDS,
+ BINDER_TYPE_BINDER, BINDER_TYPE_WEAK_BINDER,
+ BINDER_TYPE_HANDLE, BINDER_TYPE_WEAK_HANDLE,
+ BINDER_TYPE_FD]),,,[ #include <sys/types.h>
#include <linux/android/binder.h>])])
AC_CHECK_TYPES([struct statfs], [
diff --git a/xlat/binder_transaction_flags.in b/xlat/binder_transaction_flags.in
new file mode 100644
index 0000000..101242d
--- /dev/null
+++ b/xlat/binder_transaction_flags.in
@@ -0,0 +1,4 @@
+TF_ONE_WAY
+TF_ROOT_OBJECT
+TF_STATUS_CODE
+TF_ACCEPT_FDS
diff --git a/xlat/binder_types.in b/xlat/binder_types.in
new file mode 100644
index 0000000..3a9b24f
--- /dev/null
+++ b/xlat/binder_types.in
@@ -0,0 +1,5 @@
+BINDER_TYPE_BINDER
+BINDER_TYPE_WEAK_BINDER
+BINDER_TYPE_HANDLE
+BINDER_TYPE_WEAK_HANDLE
+BINDER_TYPE_FD
--
2.8.3
More information about the Strace-devel
mailing list