diff --git a/librz/bin/p/bin_pebble.c b/librz/bin/p/bin_pebble.c index b43b33f37f4..c20eb1b0ebb 100644 --- a/librz/bin/p/bin_pebble.c +++ b/librz/bin/p/bin_pebble.c @@ -11,34 +11,32 @@ #define APP_NAME_BYTES 32 #define COMPANY_NAME_BYTES 32 -RZ_PACKED( - typedef struct { - ut8 major; //!< "compatibility" version number - ut8 minor; - }) -Version; - -RZ_PACKED( - typedef struct { - char header[8]; //!< Sentinel value, should always be 'PBLAPP\0\0' - Version struct_version; //!< version of this structure's format - Version sdk_version; //!< version of the SDK used to build this app - Version app_version; //!< version of the app - ut16 size; //!< size of the app binary, including this metadata but not the reloc table - ut32 offset; //!< The entry point of this executable - ut32 crc; //!< CRC of the app data only, ie, not including this struct or the reloc table at the end - char name[APP_NAME_BYTES]; //!< Name to display on the menu - char company[COMPANY_NAME_BYTES]; //!< Name of the maker of this app - ut32 icon_resource_id; //!< Resource ID within this app's bank to use as a 32x32 icon - ut32 sym_table_addr; //!< The system will poke the sdk's symbol table address into this field on load - ut32 flags; //!< Bitwise OR of PebbleAppFlags - ut32 reloc_list_start; //!< The offset of the address relocation list - ut32 num_reloc_entries; //!< The number of entries in the address relocation list - ut8 uuid[16]; - }) -PebbleAppInfo; - -static bool check_buffer(RzBuffer *b) { +#define pebble_get_pai(bf) ((PebbleAppInfo *)bf->o->bin_obj) + +typedef struct { + ut8 major; //!< "compatibility" version number + ut8 minor; +} Version; + +typedef struct { + char header[8]; //!< Sentinel value, should always be 'PBLAPP\0\0' + Version struct_version; //!< version of this structure's format + Version sdk_version; //!< version of the SDK used to build this app + Version app_version; //!< version of the app + ut16 size; //!< size of the app binary, including this metadata but not the reloc table + ut32 offset; //!< The entry point of this executable + ut32 crc; //!< CRC of the app data only, ie, not including this struct or the reloc table at the end + char name[APP_NAME_BYTES]; //!< Name to display on the menu + char company[COMPANY_NAME_BYTES]; //!< Name of the maker of this app + ut32 icon_resource_id; //!< Resource ID within this app's bank to use as a 32x32 icon + ut32 sym_table_addr; //!< The system will poke the sdk's symbol table address into this field on load + ut32 flags; //!< Bitwise OR of PebbleAppFlags + ut32 reloc_list_start; //!< The offset of the address relocation list + ut32 num_reloc_entries; //!< The number of entries in the address relocation list + ut8 uuid[16]; +} PebbleAppInfo; + +static bool pebble_check_buffer(RzBuffer *b) { ut8 magic[8]; if (rz_buf_read_at(b, 0, magic, sizeof(magic)) != sizeof(magic)) { return false; @@ -46,36 +44,63 @@ static bool check_buffer(RzBuffer *b) { return !memcmp(magic, "PBLAPP\x00\x00", 8); } -static bool load_buffer(RzBinFile *bf, RzBinObject *obj, RzBuffer *b, Sdb *sdb) { - return check_buffer(b); +static inline bool parse_pebble_version(RzBuffer *buf, ut64 *offset, Version *v) { + return rz_buf_read8_offset(buf, offset, &v->major) && + rz_buf_read8_offset(buf, offset, &v->minor); } -static ut64 baddr(RzBinFile *bf) { - return 0LL; +static bool parse_pebble_app_info(RzBuffer *buf, PebbleAppInfo *pai) { + ut64 offset = 0; + return rz_buf_read_offset(buf, &offset, (ut8 *)pai->header, sizeof(pai->header)) && + parse_pebble_version(buf, &offset, &pai->struct_version) && + parse_pebble_version(buf, &offset, &pai->sdk_version) && + parse_pebble_version(buf, &offset, &pai->app_version) && + rz_buf_read_le16_offset(buf, &offset, &pai->size) && + rz_buf_read_le32_offset(buf, &offset, &pai->offset) && + rz_buf_read_le32_offset(buf, &offset, &pai->crc) && + rz_buf_read_offset(buf, &offset, (ut8 *)pai->name, sizeof(pai->name)) && + rz_buf_read_offset(buf, &offset, (ut8 *)pai->company, sizeof(pai->company)) && + rz_buf_read_le32_offset(buf, &offset, &pai->icon_resource_id) && + rz_buf_read_le32_offset(buf, &offset, &pai->sym_table_addr) && + rz_buf_read_le32_offset(buf, &offset, &pai->flags) && + rz_buf_read_le32_offset(buf, &offset, &pai->reloc_list_start) && + rz_buf_read_le32_offset(buf, &offset, &pai->num_reloc_entries) && + rz_buf_read_offset(buf, &offset, (ut8 *)pai->uuid, sizeof(pai->uuid)); } -/* accelerate binary load */ -static RzPVector /**/ *strings(RzBinFile *bf) { - return NULL; +static bool pebble_load_buffer(RzBinFile *bf, RzBinObject *obj, RzBuffer *b, Sdb *sdb) { + PebbleAppInfo *pai = RZ_NEW0(PebbleAppInfo); + if (!pai || + !parse_pebble_app_info(b, pai)) { + free(pai); + rz_warn_if_reached(); + return false; + } + obj->bin_obj = pai; + return true; } -static RzBinInfo *info(RzBinFile *bf) { +static ut64 pebble_baddr(RzBinFile *bf) { + return 0LL; +} + +static RzBinInfo *pebble_info(RzBinFile *bf) { RzBinInfo *ret = NULL; - PebbleAppInfo pai; - memset(&pai, 0, sizeof(pai)); - int reat = rz_buf_read_at(bf->buf, 0, (ut8 *)&pai, sizeof(pai)); - if (reat != sizeof(pai)) { - RZ_LOG_ERROR("Truncated Header\n"); + PebbleAppInfo *pai = pebble_get_pai(bf); + if (!pai) { + RZ_LOG_ERROR("Invalid PebbleAppInfo header\n"); return NULL; } if (!(ret = RZ_NEW0(RzBinInfo))) { + RZ_LOG_ERROR("Failed to allocate Pebble RzBinInfo\n"); return NULL; } + ret->lang = NULL; ret->file = rz_str_dup(bf->file); ret->type = rz_str_dup("pebble"); - ret->bclass = rz_str_ndup(pai.name, 32); - ret->rclass = rz_str_ndup(pai.company, 32); + ret->bclass = rz_str_ndup(pai->name, sizeof(pai->name)); + ret->rclass = rz_str_ndup(pai->company, sizeof(pai->company)); ret->os = rz_str_dup("rtos"); ret->subsystem = rz_str_dup("pebble"); ret->machine = rz_str_dup("watch"); @@ -87,15 +112,16 @@ static RzBinInfo *info(RzBinFile *bf) { return ret; } -static RzPVector /**/ *sections(RzBinFile *bf) { +static RzPVector /**/ *pebble_sections(RzBinFile *bf) { ut64 textsize = UT64_MAX; RzPVector *ret = NULL; RzBinSection *ptr = NULL; - PebbleAppInfo pai = { { 0 } }; - if (!rz_buf_read_at(bf->buf, 0, (ut8 *)&pai, sizeof(pai))) { - RZ_LOG_ERROR("Truncated Header\n"); + PebbleAppInfo *pai = pebble_get_pai(bf); + if (!pai) { + RZ_LOG_ERROR("Invalid PebbleAppInfo header\n"); return NULL; } + if (!(ret = rz_pvector_new(free))) { return NULL; } @@ -104,8 +130,8 @@ static RzPVector /**/ *sections(RzBinFile *bf) { return ret; } ptr->name = rz_str_dup("relocs"); - ptr->vsize = ptr->size = pai.num_reloc_entries * sizeof(ut32); - ptr->vaddr = ptr->paddr = pai.reloc_list_start; + ptr->vsize = ptr->size = ((ut64)pai->num_reloc_entries) * sizeof(ut32); + ptr->vaddr = ptr->paddr = pai->reloc_list_start; ptr->perm = RZ_PERM_RW; rz_pvector_push(ret, ptr); if (ptr->vaddr < textsize) { @@ -118,7 +144,7 @@ static RzPVector /**/ *sections(RzBinFile *bf) { } ptr->name = rz_str_dup("symtab"); ptr->vsize = ptr->size = 0; - ptr->vaddr = ptr->paddr = pai.sym_table_addr; + ptr->vaddr = ptr->paddr = pai->sym_table_addr; ptr->perm = RZ_PERM_R; rz_pvector_push(ret, ptr); if (ptr->vaddr < textsize) { @@ -146,22 +172,22 @@ static RzPVector /**/ *sections(RzBinFile *bf) { return ret; } -static RzPVector /**/ *entries(RzBinFile *bf) { +static RzPVector /**/ *pebble_entries(RzBinFile *bf) { RzBinAddr *ptr = NULL; RzPVector *ret; - PebbleAppInfo pai; - if (!rz_buf_read_at(bf->buf, 0, (ut8 *)&pai, sizeof(pai))) { - RZ_LOG_ERROR("Truncated Header\n"); + PebbleAppInfo *pai = pebble_get_pai(bf); + if (!pai) { + RZ_LOG_ERROR("Invalid PebbleAppInfo header\n"); return NULL; } + if (!(ret = rz_pvector_new(free))) { return NULL; } if (!(ptr = RZ_NEW0(RzBinAddr))) { return ret; } - ptr->paddr = pai.offset; - ptr->vaddr = pai.offset; + ptr->paddr = ptr->vaddr = pai->offset; rz_pvector_push(ret, ptr); return ret; } @@ -170,15 +196,13 @@ RzBinPlugin rz_bin_plugin_pebble = { .name = "pebble", .desc = "Pebble Watch App", .license = "LGPL", - .load_buffer = &load_buffer, - .check_buffer = &check_buffer, - .baddr = &baddr, - .entries = entries, + .load_buffer = &pebble_load_buffer, + .check_buffer = &pebble_check_buffer, + .baddr = &pebble_baddr, + .entries = pebble_entries, .maps = &rz_bin_maps_of_file_sections, - .sections = sections, - .strings = &strings, - .info = &info, - //.relocs = &relocs + .sections = pebble_sections, + .info = &pebble_info, }; #ifndef RZ_PLUGIN_INCORE