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> --- 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 ------------------------------------------------------------------------------ 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. http://sdm.link/zohomanageengine _______________________________________________ Strace-devel mailing list Strace-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/strace-devel