Skip to content

Commit

Permalink
Refactor of pebble parser
Browse files Browse the repository at this point in the history
  • Loading branch information
wargio authored and XVilka committed Nov 24, 2024
1 parent be24ca8 commit 1a3a845
Showing 1 changed file with 88 additions and 64 deletions.
152 changes: 88 additions & 64 deletions librz/bin/p/bin_pebble.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,71 +11,96 @@
#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;
}
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 /*<RzBinString *>*/ *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");
Expand All @@ -87,15 +112,16 @@ static RzBinInfo *info(RzBinFile *bf) {
return ret;
}

static RzPVector /*<RzBinSection *>*/ *sections(RzBinFile *bf) {
static RzPVector /*<RzBinSection *>*/ *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;
}
Expand All @@ -104,8 +130,8 @@ static RzPVector /*<RzBinSection *>*/ *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) {
Expand All @@ -118,7 +144,7 @@ static RzPVector /*<RzBinSection *>*/ *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) {
Expand Down Expand Up @@ -146,22 +172,22 @@ static RzPVector /*<RzBinSection *>*/ *sections(RzBinFile *bf) {
return ret;
}

static RzPVector /*<RzBinAddr *>*/ *entries(RzBinFile *bf) {
static RzPVector /*<RzBinAddr *>*/ *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;
}
Expand All @@ -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
Expand Down

0 comments on commit 1a3a845

Please sign in to comment.