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