From dfdd062f148f4dd52a41ff248b56f33e3da8d05c Mon Sep 17 00:00:00 2001 From: Giovanni <561184+wargio@users.noreply.github.com> Date: Mon, 9 Feb 2026 19:00:42 +0800 Subject: [PATCH] Rewrite of zImage bin parser & new structured data methods (#5893) --- librz/bin/format/zimg/zimg.c | 27 - librz/bin/format/zimg/zimg.h | 44 -- librz/bin/meson.build | 1 - librz/bin/p/bin_zimg.c | 612 +++++++++++++++++++-- librz/include/rz_util/rz_structured_data.h | 12 + librz/util/structured_data.c | 151 ++++- test/db/cmd/cmd_list | 6 +- test/db/formats/zimg | 254 ++++++++- 8 files changed, 951 insertions(+), 156 deletions(-) delete mode 100644 librz/bin/format/zimg/zimg.c delete mode 100644 librz/bin/format/zimg/zimg.h diff --git a/librz/bin/format/zimg/zimg.c b/librz/bin/format/zimg/zimg.c deleted file mode 100644 index 1b6c04e053..0000000000 --- a/librz/bin/format/zimg/zimg.c +++ /dev/null @@ -1,27 +0,0 @@ -// SPDX-FileCopyrightText: 2009-2015 ninjahacker -// SPDX-License-Identifier: LGPL-3.0-only - -#include -#include -#include "zimg.h" - -struct rz_bin_zimg_obj_t *rz_bin_zimg_new_buf(RzBuffer *buf) { - struct rz_bin_zimg_obj_t *bin = RZ_NEW0(struct rz_bin_zimg_obj_t); - if (!bin) { - goto fail; - } - bin->size = rz_buf_size(buf); - bin->b = rz_buf_ref(buf); - if (rz_buf_size(bin->b) < sizeof(struct zimg_header_t)) { - goto fail; - } - rz_buf_read_at(bin->b, 0, (ut8 *)&bin->header, sizeof(bin->header)); - return bin; - -fail: - if (bin) { - rz_buf_free(bin->b); - free(bin); - } - return NULL; -} diff --git a/librz/bin/format/zimg/zimg.h b/librz/bin/format/zimg/zimg.h deleted file mode 100644 index 11911115e4..0000000000 --- a/librz/bin/format/zimg/zimg.h +++ /dev/null @@ -1,44 +0,0 @@ -// SPDX-FileCopyrightText: 2009-2015 ninjahacker -// SPDX-License-Identifier: LGPL-3.0-only - -#ifndef ZIMG_H -#define ZIMG_H - -#include -#include -#include -#include - -#define RZ_BIN_ZIMG_MAXSTR 256 - -struct zimg_header_t { - ut8 magic[8]; - ut32 filler[6]; - ut8 arm_magic[4]; - ut32 kernel_start; - ut32 kernel_end; -}; - -typedef struct rz_bin_zimg_obj_t { - int size; - const char *file; - RzBuffer *b; - struct zimg_header_t header; - ut32 *strings; - ut64 code_from; - ut64 code_to; - Sdb *kv; -} RzBinZimgObj; - -struct rz_bin_zimg_str_t { - char str[RZ_BIN_ZIMG_MAXSTR]; - ut64 offset; - ut64 ordinal; - int size; - int last; -}; - -struct rz_bin_zimg_obj_t *rz_bin_zimg_new_buf(RzBuffer *buf); -struct rz_bin_zimg_str_t *rz_bin_zimg_get_strings(struct rz_bin_zimg_obj_t *bin); - -#endif diff --git a/librz/bin/meson.build b/librz/bin/meson.build index 8962f709d6..759d9a5403 100644 --- a/librz/bin/meson.build +++ b/librz/bin/meson.build @@ -271,7 +271,6 @@ rz_bin_sources = [ 'format/pyc/pyc_magic.c', 'format/te/te.c', 'format/wasm/wasm.c', - 'format/zimg/zimg.c', 'pdb/cab_extract.c', 'pdb/dbi.c', diff --git a/librz/bin/p/bin_zimg.c b/librz/bin/p/bin_zimg.c index 5f0b7a1701..7849a19972 100644 --- a/librz/bin/p/bin_zimg.c +++ b/librz/bin/p/bin_zimg.c @@ -1,39 +1,461 @@ -// SPDX-FileCopyrightText: 2011-2019 ninjahacker +// SPDX-FileCopyrightText: 2026 deroad // SPDX-License-Identifier: LGPL-3.0-only #include #include #include #include -#include "zimg/zimg.h" -static Sdb *get_sdb(RzBinFile *bf) { - rz_return_val_if_fail(bf && bf->o, false); - struct rz_bin_zimg_obj_t *bin = (struct rz_bin_zimg_obj_t *)bf->o->bin_obj; - return bin ? bin->kv : NULL; +typedef struct zimage_arm32_s { + ut32 arm32_magic; ///< 0x016f2818 + ut32 kernel_start; + ut32 kernel_end; + ut32 endianness_flag; + ut32 magic_table_flag; + ut32 magic_table; +} zimage_arm32_t; + +typedef struct zimage_riscv_s { + ut64 image_load; ///< base address + ut64 kernel_size; + ut64 head_flags; ///< usually 0 + ut16 version_major; + ut16 version_minor; + ut32 padding0; ///< should be 0 + ut64 padding1; ///< should be 0 + ut8 riscv_magic1[8]; ///< "RISCV\0\0\0" + ut8 riscv_magic2[4]; ///< "RSC\x05" + ut32 pe_header_offset; ///< from offset 0 +} zimage_riscv_t; + +typedef enum zimage_arch { + ZIMAGE_ARCH_ARM32_LE = 0, + ZIMAGE_ARCH_ARM32_BE, + ZIMAGE_ARCH_RISCV, +} zimage_arch_t; + +typedef struct zimage_s { + zimage_arch_t arch; + const char *kernel; + union { + zimage_arm32_t arm32; + zimage_riscv_t riscv; + } info; +} zImage; + +typedef bool (*zimage_parser_t)(zImage *image, RzBuffer *buf, ut64 off, bool big_endian); + +typedef struct zimage_signature_s { + const ut8 *bytes; + size_t size; + ut64 offset; +} zimage_signature_t; + +typedef struct zimage_marker_s { + const zimage_arch_t arch; + const bool big_endian; + const char *kernel; + const zimage_parser_t parser; + const zimage_signature_t *signatures; + const size_t n_signatures; +} zimage_marker_t; + +/** + * Reference: https://github.com/torvalds/linux/blob/05f7e89ab9731565d8a62e3b5d1ec206485eeb0b/arch/riscv/kernel/head.S#L28 + * + * #ifdef CONFIG_EFI + * li s4, -13 // encoding: [0x4d,0x5a] (compat) + * j 64 // encoding: [0x81,0xa0] (compat) + * #else + * j 64 // encoding: [0x81,0xa0] (compat) + * // encoding: [0x6f,0x00,0x00,0x04] (non-compat) + * .word 0 + * #endif + * .balign 8 + * #ifdef CONFIG_RISCV_M_MODE + * // Image load offset (0MB) from start of RAM for M-mode + * .dword 0 + * #else + * #if __riscv_xlen == 64 + * // Image load offset(2MB) from start of RAM + * .dword 0x200000 + * #else + * // Image load offset(4MB) from start of RAM + * .dword 0x400000 + * #endif + * #endif + * // Effective size of kernel image + * .dword _end - _start + * .dword __HEAD_FLAGS // likely 0 + * .word RISCV_HEADER_VERSION // (RISCV_HEADER_VERSION_MAJOR << 16 | RISCV_HEADER_VERSION_MINOR) + * .word 0 + * .dword 0 + * .ascii RISCV_IMAGE_MAGIC // "RISCV\0\0\0" + * .balign 4 + * .ascii RISCV_IMAGE_MAGIC2 // "RSC\x05" + * #ifdef CONFIG_EFI + * .word pe_head_start - _start + * pe_head_start: + * __EFI_PE_HEADER // "MZ" + * #else + * .word 0 + * #endif + */ + +#define RISCV_ZIMAGE_MAGIC1_VALUE "RISCV\0\0\0" +#define RISCV_ZIMAGE_MAGIC2_VALUE "RSC\x05" +#define RISCV_ZIMAGE_INFO_OFFSET 0x08 +#define RISCV_ZIMAGE_MAGIC_OFFSET 0x30 + +// clang-format off +const ut8 marker_riscv_efi_compact[4] = { 0x4d, 0x5a, 0x81, 0xa0 }; +const ut8 marker_riscv_compact[6] = { 0x81, 0xa0, 0, 0, 0, 0 }; +const ut8 marker_riscv_non_compact[8] = { 0x6f, 0x00, 0x00, 0x04, 0, 0, 0, 0 }; +const ut8 marker_riscv_magic[12] = { 'R', 'I', 'S', 'C', 'V', 0, 0, 0, 'R', 'S', 'C', 5 }; + +static const zimage_signature_t zimage_signature_riscv_efi_compact_5_9[] = { + { marker_riscv_efi_compact, sizeof (marker_riscv_efi_compact), 0 }, + { marker_riscv_magic, sizeof (marker_riscv_magic), RISCV_ZIMAGE_MAGIC_OFFSET }, +}; + +static const zimage_signature_t zimage_signature_riscv_compact_5_2[] = { + { marker_riscv_compact, sizeof (marker_riscv_compact), 0 }, + { marker_riscv_magic, sizeof (marker_riscv_magic), RISCV_ZIMAGE_MAGIC_OFFSET }, +}; + +static const zimage_signature_t zimage_signature_riscv_non_compact_5_2[] = { + { marker_riscv_non_compact, sizeof (marker_riscv_non_compact), 0 }, + { marker_riscv_magic, sizeof (marker_riscv_magic), RISCV_ZIMAGE_MAGIC_OFFSET }, +}; + +static const zimage_signature_t zimage_signature_riscv_compact_4_14[] = { + { marker_riscv_compact, sizeof (marker_riscv_compact), 0 }, +}; + +static const zimage_signature_t zimage_signature_riscv_non_compact_4_14[] = { + { marker_riscv_non_compact, sizeof (marker_riscv_non_compact), 0 }, +}; +// clang-format on + +static bool zimage_parse_riscv(zImage *image, RzBuffer *buf, ut64 off, bool big_endian) { + zimage_riscv_t *h = &image->info.riscv; + off += RISCV_ZIMAGE_INFO_OFFSET; + ut32 riscv_version = 0; + + bool ok = rz_buf_read_ble64_offset(buf, &off, &h->image_load, big_endian) && + rz_buf_read_ble64_offset(buf, &off, &h->kernel_size, big_endian) && + rz_buf_read_ble64_offset(buf, &off, &h->head_flags, big_endian) && + rz_buf_read_ble32_offset(buf, &off, &riscv_version, big_endian) && + rz_buf_read_ble32_offset(buf, &off, &h->padding0, big_endian) && + rz_buf_read_ble64_offset(buf, &off, &h->padding1, big_endian) && + rz_buf_read_offset(buf, &off, h->riscv_magic1, sizeof(h->riscv_magic1)) && + rz_buf_read_offset(buf, &off, h->riscv_magic2, sizeof(h->riscv_magic2)) && + rz_buf_read_ble32_offset(buf, &off, &h->pe_header_offset, big_endian); + + if (!ok) { + return false; + } + + h->version_major = riscv_version >> 16; + h->version_minor = riscv_version & 0xffff; + return true; } -static bool load_buffer(RzBinFile *bf, RzBinObject *obj, RzBuffer *b, Sdb *sdb) { - obj->bin_obj = rz_bin_zimg_new_buf(b); - return obj->bin_obj != NULL; +/** + * Reference: https://github.com/torvalds/linux/blob/05f7e89ab9731565d8a62e3b5d1ec206485eeb0b/arch/arm/boot/compressed/head.S#L188 + * + * .rept 7 + * __nop + * .endr + * #ifndef CONFIG_THUMB2_KERNEL + * __nop + * #else + * AR_CLASS( sub pc, pc, #3 ) @ A/R: switch to Thumb2 mode + * M_CLASS( nop.w ) @ M: already in Thumb2 mode + * .thumb + * #endif + * + * W(b) 1f + * + * .word _magic_sig @ Magic numbers to help the loader + * .word _magic_start @ absolute load/run zImage address + * .word _magic_end @ zImage end address + * .word 0x04030201 @ endianness flag + * .word 0x45454545 @ another magic number to indicate + * .word _magic_table @ additional data table + * __EFI_HEADER + * + * + * Additional values. + * + * _magic_sig = ZIMAGE_MAGIC(0x016f2818); + * _magic_start = ZIMAGE_MAGIC(_start); + * _magic_end = ZIMAGE_MAGIC(_edata); + * _magic_table = ZIMAGE_MAGIC(_table_start - _start); + */ + +#define ARM_ZIMAGE_MAGIC_VALUE 0x016f2818 +#define ARM_ZIMAGE_ENDIANNESS_VALUE 0x04030201 +#define ARM_ZIMAGE_MAGIC_TABLE_VALUE 0x45454545 +#define ARM_ZIMAGE_INFO_OFFSET 0x24 +#define ARM_ZIMAGE_ENDIANNESS_OFFSET 0x30 +#define ARM_ZIMAGE_MAGIC_TABLE_OFFSET 0x34 + +// clang-format off +const ut8 marker_arm32_mov_le[8] = { 0x00, 0x00, 0xa0, 0xe1, 0x00, 0x00, 0xa0, 0xe1 }; +const ut8 marker_arm32_magic_le[4] = { 0x18, 0x28, 0x6f, 0x01 }; +const ut8 marker_arm32_endianness_le[4] = { 1, 2, 3, 4 }; +const ut8 marker_arm32_mov_be[8] = { 0xe1, 0xa0, 0x00, 0x00, 0xe1, 0xa0, 0x00, 0x00 }; +const ut8 marker_arm32_magic_be[4] = { 0x01, 0x6f, 0x28, 0x18 }; +const ut8 marker_arm32_endianness_be[4] = { 4, 3, 2, 1 }; +const ut8 marker_arm32_magic_table[4] = { 0x45, 0x45, 0x45, 0x45 }; + +static const zimage_signature_t zimage_signature_arm32_le_4_14_plus[] = { + { marker_arm32_mov_le, sizeof (marker_arm32_mov_le), 0 }, + { marker_arm32_magic_le, sizeof (marker_arm32_magic_le), ARM_ZIMAGE_INFO_OFFSET }, + { marker_arm32_endianness_le, sizeof (marker_arm32_endianness_le), ARM_ZIMAGE_ENDIANNESS_OFFSET }, + { marker_arm32_magic_table, sizeof (marker_arm32_magic_table), ARM_ZIMAGE_MAGIC_TABLE_OFFSET }, +}; + +static const zimage_signature_t zimage_signature_arm32_le_3_16_4_14[] = { + { marker_arm32_mov_le, sizeof (marker_arm32_mov_le), 0 }, + { marker_arm32_magic_le, sizeof (marker_arm32_magic_le), ARM_ZIMAGE_INFO_OFFSET }, + { marker_arm32_endianness_le, sizeof (marker_arm32_endianness_le), ARM_ZIMAGE_ENDIANNESS_OFFSET }, +}; + +static const zimage_signature_t zimage_signature_arm32_le_pre3_16[] = { + { marker_arm32_mov_le, sizeof (marker_arm32_mov_le), 0 }, + { marker_arm32_magic_le, sizeof (marker_arm32_magic_le), ARM_ZIMAGE_INFO_OFFSET }, +}; + +static const zimage_signature_t zimage_signature_arm32_be_4_14_plus[] = { + { marker_arm32_mov_be, sizeof (marker_arm32_mov_be), 0 }, + { marker_arm32_magic_be, sizeof (marker_arm32_magic_be), ARM_ZIMAGE_INFO_OFFSET }, + { marker_arm32_endianness_be, sizeof (marker_arm32_endianness_be), ARM_ZIMAGE_ENDIANNESS_OFFSET }, + { marker_arm32_magic_table, sizeof (marker_arm32_magic_table), ARM_ZIMAGE_MAGIC_TABLE_OFFSET }, +}; + +static const zimage_signature_t zimage_signature_arm32_be_3_16_4_14[] = { + { marker_arm32_mov_be, sizeof (marker_arm32_mov_be), 0 }, + { marker_arm32_magic_be, sizeof (marker_arm32_magic_be), ARM_ZIMAGE_INFO_OFFSET }, + { marker_arm32_endianness_be, sizeof (marker_arm32_endianness_be), ARM_ZIMAGE_ENDIANNESS_OFFSET }, +}; + +static const zimage_signature_t zimage_signature_arm32_be_pre3_16[] = { + { marker_arm32_mov_be, sizeof (marker_arm32_mov_be), 0 }, + { marker_arm32_magic_be, sizeof (marker_arm32_magic_be), ARM_ZIMAGE_INFO_OFFSET }, +}; + +/* + if (h->magic_table_flag == ARM_ZIMAGE_MAGIC_TABLE_VALUE) { + return rz_str_dup("Linux zImage Kernel (4.14 or newer)"); + } else if (zo->endianness_flag == ARM_ZIMAGE_ENDIANNESS_VALUE) { + return rz_str_dup("Linux zImage Kernel (3.16 - 4.14)"); + } + return rz_str_dup("Linux zImage Kernel (3.16 or older)"); +*/ + +// clang-format on + +static bool zimage_parse_arm32(zImage *image, RzBuffer *buf, ut64 off, bool big_endian) { + zimage_arm32_t *h = &image->info.arm32; + + off += ARM_ZIMAGE_INFO_OFFSET; + return rz_buf_read_ble32_offset(buf, &off, &h->arm32_magic, big_endian) && + rz_buf_read_ble32_offset(buf, &off, &h->kernel_start, big_endian) && + rz_buf_read_ble32_offset(buf, &off, &h->kernel_end, big_endian) && + rz_buf_read_ble32_offset(buf, &off, &h->endianness_flag, big_endian) && + rz_buf_read_ble32_offset(buf, &off, &h->magic_table_flag, big_endian) && + rz_buf_read_ble32_offset(buf, &off, &h->magic_table, big_endian); } -static ut64 baddr(RzBinFile *bf) { - return 0; +static const zimage_marker_t zimage_markers[] = { + // clang-format off + { ZIMAGE_ARCH_ARM32_LE, false, "4.14+" , zimage_parse_arm32, zimage_signature_arm32_le_4_14_plus, RZ_ARRAY_SIZE(zimage_signature_arm32_le_4_14_plus) }, + { ZIMAGE_ARCH_ARM32_LE, false, "3.16-4.14", zimage_parse_arm32, zimage_signature_arm32_le_3_16_4_14, RZ_ARRAY_SIZE(zimage_signature_arm32_le_3_16_4_14) }, + { ZIMAGE_ARCH_ARM32_LE, false, "2.6-3.16" , zimage_parse_arm32, zimage_signature_arm32_le_pre3_16, RZ_ARRAY_SIZE(zimage_signature_arm32_le_pre3_16) }, + { ZIMAGE_ARCH_ARM32_BE, true, "4.14+" , zimage_parse_arm32, zimage_signature_arm32_be_4_14_plus, RZ_ARRAY_SIZE(zimage_signature_arm32_be_4_14_plus) }, + { ZIMAGE_ARCH_ARM32_BE, true, "3.16-4.14", zimage_parse_arm32, zimage_signature_arm32_be_3_16_4_14, RZ_ARRAY_SIZE(zimage_signature_arm32_be_3_16_4_14) }, + { ZIMAGE_ARCH_ARM32_BE, true, "2.6-3.16" , zimage_parse_arm32, zimage_signature_arm32_be_pre3_16, RZ_ARRAY_SIZE(zimage_signature_arm32_be_pre3_16) }, + { ZIMAGE_ARCH_RISCV , false, "5.9+" , zimage_parse_riscv, zimage_signature_riscv_efi_compact_5_9 , RZ_ARRAY_SIZE(zimage_signature_riscv_efi_compact_5_9) }, + { ZIMAGE_ARCH_RISCV , false, "5.2+" , zimage_parse_riscv, zimage_signature_riscv_compact_5_2 , RZ_ARRAY_SIZE(zimage_signature_riscv_compact_5_2) }, + { ZIMAGE_ARCH_RISCV , false, "5.2+" , zimage_parse_riscv, zimage_signature_riscv_non_compact_5_2 , RZ_ARRAY_SIZE(zimage_signature_riscv_non_compact_5_2) }, + { ZIMAGE_ARCH_RISCV , false, "4.14-5.2" , zimage_parse_riscv, zimage_signature_riscv_compact_4_14 , RZ_ARRAY_SIZE(zimage_signature_riscv_compact_4_14) }, + { ZIMAGE_ARCH_RISCV , false, "4.14-5.2" , zimage_parse_riscv, zimage_signature_riscv_non_compact_4_14, RZ_ARRAY_SIZE(zimage_signature_riscv_non_compact_4_14) }, + // clang-format on +}; + +static bool zimage_signature_check(RzBuffer *b, const zimage_signature_t *sig) { + ut8 bytes[16] = { 0 }; + rz_return_val_if_fail(sig->size < sizeof(bytes), false); + + if (!rz_buf_read_at(b, sig->offset, bytes, sig->size)) { + return false; + } + + return !memcmp(bytes, sig->bytes, sig->size); } -static bool check_buffer(RzBuffer *b) { - ut8 zimghdr[8]; - if (rz_buf_read_at(b, 0, zimghdr, sizeof(zimghdr))) { - // Checking ARM zImage kernel - if (!memcmp(zimghdr, "\x00\x00\xa0\xe1\x00\x00\xa0\xe1", 8)) { +static bool zimage_marker_check(RzBuffer *b, const zimage_marker_t *marker) { + for (size_t i = 0; i < marker->n_signatures; ++i) { + if (!zimage_signature_check(b, &marker->signatures[i])) { + return false; + } + } + return true; +} + +static bool zimage_check_buffer(RzBuffer *b) { + for (size_t i = 0; i < RZ_ARRAY_SIZE(zimage_markers); ++i) { + const zimage_marker_t *marker = &zimage_markers[i]; + if (zimage_marker_check(b, marker)) { return true; } } + return false; } -static RzBinInfo *info(RzBinFile *bf) { +static bool zimage_load_buffer(RzBinFile *bf, RzBinObject *obj, RzBuffer *b, Sdb *sdb) { + const zimage_marker_t *marker = NULL; + for (size_t i = 0; i < RZ_ARRAY_SIZE(zimage_markers); ++i) { + marker = &zimage_markers[i]; + if (zimage_marker_check(b, marker)) { + break; + } + marker = NULL; + } + + if (!marker) { + // should never happen. + return false; + } + + zImage *image = RZ_NEW0(zImage); + if (!image || !marker->parser(image, b, 0, marker->big_endian)) { + free(image); + return false; + } + + image->arch = marker->arch; + image->kernel = marker->kernel; + obj->bin_obj = image; + return true; +} + +static ut64 zimage_kernel_base_address(const zImage *zo) { + if (zo->arch == ZIMAGE_ARCH_RISCV) { + return zo->info.riscv.image_load; + } + return 0; +} + +static char *zimage_arch(const zImage *zo) { + switch (zo->arch) { + case ZIMAGE_ARCH_ARM32_LE: + return rz_str_dup("arm"); + case ZIMAGE_ARCH_ARM32_BE: + return rz_str_dup("arm"); + case ZIMAGE_ARCH_RISCV: + return rz_str_dup("riscv"); + default: + return rz_str_dup("unknown"); + } +} + +static char *zimage_machine(const zImage *zo) { + switch (zo->arch) { + case ZIMAGE_ARCH_ARM32_LE: + return rz_str_dup("ARM32 LE"); + case ZIMAGE_ARCH_ARM32_BE: + return rz_str_dup("ARM32 BE"); + case ZIMAGE_ARCH_RISCV: + return rz_str_dup("RISC-V"); + default: + return rz_str_dup("unknown"); + } +} + +static ut32 zimage_riscv_bits(const zImage *zo) { + const zimage_riscv_t *h = &zo->info.riscv; + switch (h->image_load) { + case 0x200000: + /* _riscv_xlen == 64 */ + return 64; + case 0x400000: + /* this could be _riscv_xlen == 128, but nobody supports it. */ + return 32; + case 0: /* RISCV_M_MODE: no-mmu */ + return 32; + default: + // we keep this for any non-standard values. + return 32; + } +} + +static char *zimage_riscv_cpu(const zImage *zo) { + const zimage_riscv_t *h = &zo->info.riscv; + switch (h->image_load) { + case 0x200000: + /* _riscv_xlen == 64 */ + return rz_str_dup("rv64"); + case 0x400000: + /* this could be _riscv_xlen == 128, but nobody supports it. */ + return rz_str_dup("rv32"); + case 0: /* RISCV_M_MODE: no-mmu */ + return rz_str_dup("rv32+c"); + default: + // we keep this for any non-standard values. + return rz_str_dup("rv32"); + } +} + +static char *zimage_cpu(const zImage *zo) { + switch (zo->arch) { + case ZIMAGE_ARCH_ARM32_LE: + /* fall-thru */ + case ZIMAGE_ARCH_ARM32_BE: + return rz_str_dup("arm"); + case ZIMAGE_ARCH_RISCV: + return zimage_riscv_cpu(zo); + default: + return NULL; + } +} + +static ut32 zimage_bits(const zImage *zo) { + switch (zo->arch) { + case ZIMAGE_ARCH_ARM32_LE: + /* fall-thru */ + case ZIMAGE_ARCH_ARM32_BE: + return 32; + case ZIMAGE_ARCH_RISCV: + return zimage_riscv_bits(zo); + default: + rz_warn_if_reached(); + return 32; + } +} + +static bool zimage_big_endian(const zImage *zo) { + switch (zo->arch) { + case ZIMAGE_ARCH_ARM32_BE: + return true; + default: + return false; + } +} + +static char *zimage_detect_kernel(const zImage *zo) { + if (RZ_STR_ISNOTEMPTY(zo->kernel)) { + return rz_str_newf("Linux zImage Kernel (%s)", zo->kernel); + } + return rz_str_dup("Linux zImage Kernel"); +} + +static RzBinInfo *zimage_info(RzBinFile *bf) { + zImage *zo = bf->o->bin_obj; + RzBinInfo *ret = RZ_NEW0(RzBinInfo); if (!ret) { return NULL; @@ -41,77 +463,149 @@ static RzBinInfo *info(RzBinFile *bf) { ret->file = rz_str_dup(bf->file); ret->type = rz_str_dup("Linux zImage Kernel"); ret->has_va = false; - ret->bclass = rz_str_dup("Compressed Linux Kernel"); + ret->bclass = zimage_detect_kernel(zo); ret->rclass = rz_str_dup("zimg"); ret->os = rz_str_dup("linux"); ret->subsystem = rz_str_dup("linux"); - ret->machine = rz_str_dup("ARM"); // TODO: can be other cpus - ret->arch = rz_str_dup("arm"); + ret->machine = zimage_machine(zo); + ret->arch = zimage_arch(zo); + ret->cpu = zimage_cpu(zo); ret->lang = "C"; - ret->bits = 32; - ret->big_endian = 0; - ret->dbg_info = 0; // 1 | 4 | 8; /* Stripped | LineNums | Syms */ + ret->bits = zimage_bits(zo); + ret->big_endian = zimage_big_endian(zo); + ret->dbg_info = 0; + return ret; } -static RzStructuredData *zimg_structure(RzBinFile *bf) { +static ut64 zimage_baddr(RzBinFile *bf) { + const zImage *zo = bf->o->bin_obj; + return zimage_kernel_base_address(zo); +} + +static RzBinAddr *zimage_bin_addr(RzBinSpecialSymbol type, ut64 offset, zImage *zo) { + RzBinAddr *ba = RZ_NEW0(RzBinAddr); + if (!ba) { + return NULL; + } + + ba->type = type; + ba->paddr = ba->hpaddr = offset; + ba->vaddr = ba->hvaddr = zimage_kernel_base_address(zo) + offset; + ba->bits = zimage_bits(zo); + return ba; +} + +static RzPVector /**/ *zimage_entries(RzBinFile *bf) { + zImage *zo = bf->o->bin_obj; + + RzBinAddr *ptr = NULL; + + RzPVector /**/ *ret = rz_pvector_new(free); + if (!ret) { + return NULL; + } + + // ipl3 always includes the header, but ipl2 will jump after the ROM header. + ptr = zimage_bin_addr(RZ_BIN_SPECIAL_SYMBOL_ENTRY, 0, zo); + if (!ptr) { + rz_pvector_free(ret); + return NULL; + } + rz_pvector_push(ret, ptr); + + return ret; +} + +static void zimage_structure_arm32(zImage *image, RzStructuredData *root) { + zimage_arm32_t *zo = &image->info.arm32; + + rz_structured_data_map_add_unsigned(root, "arm32_magic", zo->arm32_magic, true); + rz_structured_data_map_add_unsigned(root, "kernel_start", zo->kernel_start, true); + rz_structured_data_map_add_unsigned(root, "kernel_end", zo->kernel_end, true); + + if (zo->endianness_flag == ARM_ZIMAGE_ENDIANNESS_VALUE) { + rz_structured_data_map_add_unsigned(root, "endianness_flag", zo->endianness_flag, true); + } + + if (zo->magic_table_flag == ARM_ZIMAGE_MAGIC_TABLE_VALUE) { + rz_structured_data_map_add_unsigned(root, "magic_table_flag", zo->magic_table_flag, true); + rz_structured_data_map_add_unsigned(root, "magic_table", zo->magic_table, true); + } +} + +static void zimage_structure_riscv(zImage *image, RzStructuredData *root) { + zimage_riscv_t *zo = &image->info.riscv; + + rz_structured_data_map_add_unsigned(root, "image_load", zo->image_load, true); + rz_structured_data_map_add_unsigned(root, "kernel_size", zo->kernel_size, true); + rz_structured_data_map_add_unsigned(root, "head_flags", zo->head_flags, true); + + RzStructuredData *version = rz_structured_data_map_add_map(root, "version"); + if (version) { + rz_structured_data_map_add_unsigned(version, "major", zo->version_major, false); + rz_structured_data_map_add_unsigned(version, "minor", zo->version_minor, false); + } + + rz_structured_data_map_add_unsigned(root, "padding0", zo->padding0, true); + rz_structured_data_map_add_unsigned(root, "padding1", zo->padding1, true); + + rz_structured_data_map_add_bytes(root, "riscv_magic1", zo->riscv_magic1, sizeof(zo->riscv_magic1), RZ_STRUCTURED_DATA_FORMAT_HEXDUMP); + rz_structured_data_map_add_bytes(root, "riscv_magic2", zo->riscv_magic2, sizeof(zo->riscv_magic2), RZ_STRUCTURED_DATA_FORMAT_HEXDUMP); + + if (zo->pe_header_offset) { + rz_structured_data_map_add_unsigned(root, "pe_header_offset", zo->pe_header_offset, true); + } +} + +static RzStructuredData *zimage_structure(RzBinFile *bf) { rz_return_val_if_fail(bf && bf->o && bf->o->bin_obj, NULL); - RzBinZimgObj *zo = bf->o->bin_obj; + zImage *image = bf->o->bin_obj; RzStructuredData *info = rz_structured_data_new_map(); if (!info) { return NULL; } - RzStructuredData *zimg = rz_structured_data_map_add_map(info, "zimg"); - if (!zimg) { + RzStructuredData *root = rz_structured_data_map_add_map(info, "zImage"); + if (!root) { rz_structured_data_free(info); return NULL; } - rz_structured_data_map_add_unsigned(zimg, "size", zo->size, false); + rz_structured_data_map_add_string(root, "machine", zimage_machine(image)); + if (RZ_STR_ISNOTEMPTY(image->kernel)) { + rz_structured_data_map_add_string(root, "kernel", image->kernel); + } - RzStructuredData *kernel = rz_structured_data_map_add_map(zimg, "kernel"); - if (!kernel) { + switch (image->arch) { + case ZIMAGE_ARCH_ARM32_LE: + /* fall-thru */ + case ZIMAGE_ARCH_ARM32_BE: + zimage_structure_arm32(image, root); + break; + case ZIMAGE_ARCH_RISCV: + zimage_structure_riscv(image, root); + break; + default: rz_structured_data_free(info); return NULL; } - RzStructuredData *magic = rz_structured_data_map_add_map(zimg, "magic"); - if (!magic) { - rz_structured_data_free(info); - return NULL; - } - - ut32 magic0 = rz_read_le32(&zo->header.magic[0]); - ut32 magic1 = rz_read_le32(&zo->header.magic[4]); - ut32 arm_magic = rz_read_le32(zo->header.arm_magic); - - rz_structured_data_map_add_unsigned(magic, "magic0", magic0, true); - rz_structured_data_map_add_unsigned(magic, "magic1", magic1, true); - rz_structured_data_map_add_unsigned(magic, "arm_magic", arm_magic, true); - - ut64 kernel_start = zo->header.kernel_start; - ut64 kernel_end = zo->header.kernel_end; - - rz_structured_data_map_add_unsigned(kernel, "kernel_start", kernel_start, true); - rz_structured_data_map_add_unsigned(kernel, "kernel_end", kernel_end, true); - rz_structured_data_map_add_unsigned(kernel, "kernel_size", kernel_end - kernel_start, false); - return info; } RzBinPlugin rz_bin_plugin_zimg = { .name = "zimg", - .desc = "ZIMG format binary", + .desc = "zImage format binary", .license = "LGPL3", - .author = "ninjahacker", - .get_sdb = &get_sdb, - .load_buffer = &load_buffer, - .check_buffer = &check_buffer, - .baddr = &baddr, - .info = &info, - .bin_structure = &zimg_structure + .author = "deroad", + .load_buffer = &zimage_load_buffer, + .check_buffer = &zimage_check_buffer, + .baddr = &zimage_baddr, + .info = &zimage_info, + .entries = &zimage_entries, + .bin_structure = &zimage_structure }; #ifndef RZ_PLUGIN_INCORE diff --git a/librz/include/rz_util/rz_structured_data.h b/librz/include/rz_util/rz_structured_data.h index 0aadf99741..2df0c7c7a3 100644 --- a/librz/include/rz_util/rz_structured_data.h +++ b/librz/include/rz_util/rz_structured_data.h @@ -16,6 +16,14 @@ typedef enum rz_structured_data_block_t { RZ_STRUCTURED_DATA_BLOCK_ARRAY = 1, } RzStructuredDataBlock; +typedef enum rz_structured_data_format_t { + RZ_STRUCTURED_DATA_FORMAT_DEFAULT = 0, ///< Bytes are printed as hexadecimal one after each other. + RZ_STRUCTURED_DATA_FORMAT_COLON, ///< Bytes are printed as hexadecimal but separated by colons (`:`) + RZ_STRUCTURED_DATA_FORMAT_HEXDUMP, ///< Bytes are printed as a hexdump (16 bytes per line) + /// size + RZ_STRUCTURED_DATA_FORMAT_ENUM_MAX +} RzStructuredDataFormat; + typedef struct rz_structured_data_t RzStructuredData; typedef void (*RzStructuredDataIteratorNew)(RZ_NULLABLE void *user, RzStructuredDataBlock block, size_t n_elems); @@ -51,6 +59,8 @@ RZ_API bool rz_structured_data_map_add_signed(RZ_NONNULL RzStructuredData *paren RZ_API bool rz_structured_data_map_add_double(RZ_NONNULL RzStructuredData *parent, RZ_NONNULL const char *key, double d); RZ_API bool rz_structured_data_map_add_boolean(RZ_NONNULL RzStructuredData *parent, RZ_NONNULL const char *key, bool b); RZ_API bool rz_structured_data_map_add_string(RZ_NONNULL RzStructuredData *parent, RZ_NONNULL const char *key, RZ_NONNULL const char *v); +RZ_API bool rz_structured_data_map_add_string_n(RZ_NONNULL RzStructuredData *parent, RZ_NONNULL const char *key, RZ_NONNULL const char *v, size_t v_size); +RZ_API bool rz_structured_data_map_add_bytes(RZ_NONNULL RzStructuredData *parent, RZ_NONNULL const char *key, RZ_NONNULL const ut8 *v, size_t v_size, RzStructuredDataFormat fmt); /* primitive types for arrays */ RZ_API RZ_BORROW RzStructuredData *rz_structured_data_array_add_map(RZ_NONNULL RzStructuredData *parent); @@ -61,6 +71,8 @@ RZ_API bool rz_structured_data_array_add_signed(RZ_NONNULL RzStructuredData *par RZ_API bool rz_structured_data_array_add_double(RZ_NONNULL RzStructuredData *parent, double d); RZ_API bool rz_structured_data_array_add_boolean(RZ_NONNULL RzStructuredData *parent, bool b); RZ_API bool rz_structured_data_array_add_string(RZ_NONNULL RzStructuredData *parent, RZ_NONNULL const char *v); +RZ_API bool rz_structured_data_array_add_string_n(RZ_NONNULL RzStructuredData *parent, RZ_NONNULL const char *v, size_t v_size); +RZ_API bool rz_structured_data_array_add_bytes(RZ_NONNULL RzStructuredData *parent, RZ_NONNULL const ut8 *v, size_t v_size, RzStructuredDataFormat fmt); RZ_API void rz_structured_data_iterate(RZ_NONNULL const RzStructuredData *sd, RZ_NONNULL const RzStructuredDataIterator *iterator, RZ_NULLABLE void *user); RZ_API void rz_structured_data_to_pj(RZ_NONNULL const RzStructuredData *sd, RZ_NONNULL PJ *pj); diff --git a/librz/util/structured_data.c b/librz/util/structured_data.c index 2ae5955a84..651140ba6b 100644 --- a/librz/util/structured_data.c +++ b/librz/util/structured_data.c @@ -182,6 +182,67 @@ static bool structured_data_array_add(RZ_NONNULL RzStructuredData *parent, RZ_NO return true; } +static char *structured_data_hexdump_padded(const ut8 *buffer, const size_t length) { + size_t i = 0, j = 0; + char readable[20] = { 0 }; + RzStrBuf sb = { 0 }; + rz_strbuf_init(&sb); + + for (i = 0, j = 0; i < length; i++, j++) { + const ut8 c = buffer[i]; + if (i > 0 && (i % 16) == 0) { + rz_strbuf_appendf(&sb, "|%-16s|\n", readable); + memset(readable, 0, sizeof(readable)); + j = 0; + } + rz_strbuf_appendf(&sb, "%02x ", c); + readable[j] = IS_PRINTABLE(c) ? c : '.'; + } + + while ((i % 16) != 0) { + rz_strbuf_append_n(&sb, " ", 3); + i++; + } + + rz_strbuf_appendf(&sb, "|%-16s|", readable); + return rz_strbuf_drain_nofree(&sb); +} + +static char *structured_data_hex_colon_padded(const ut8 *buffer, size_t length) { + const char *hex = "0123456789abcdef"; + const size_t size = 3 * length; + char *output = malloc(size); + if (!output) { + return NULL; + } + + for (size_t i = 0, j = 0; i < length && j < size; i++, j += 3) { + const ut8 c = buffer[i]; + output[j + 0] = hex[c >> 4]; + output[j + 1] = hex[c & 0xf]; + output[j + 2] = ':'; + } + + // always overwrite the last byte with null char. + output[size - 1] = '\0'; + return output; +} + +static char *structured_data_bytes_to_string(const ut8 *buffer, const size_t length, RzStructuredDataFormat fmt) { + if (length < 1) { + return strdup(""); + } + + switch (fmt) { + case RZ_STRUCTURED_DATA_FORMAT_COLON: + return structured_data_hex_colon_padded(buffer, length); + case RZ_STRUCTURED_DATA_FORMAT_HEXDUMP: + return structured_data_hexdump_padded(buffer, length); + default /* RZ_STRUCTURED_DATA_FORMAT_DEFAULT */: + return rz_hex_bin2strdup(buffer, length); + } +} + /** * \brief Creates a new RzStructuredData initialized as a map * @@ -339,6 +400,51 @@ RZ_API bool rz_structured_data_map_add_string(RZ_NONNULL RzStructuredData *paren return structured_data_map_add(parent, key, child); } +/** + * \brief Adds a null terminated string type child (with a max size of n) to a parent and assigns it a map key + * + * \param parent Where to add the child RzStructuredData + * \param[in] key The key to assign the child RzStructuredData + * \param s The string value to assign to the child + * \param s_len The max size of the string value + * + * \return On success returns true, otherwise false. + */ +RZ_API bool rz_structured_data_map_add_string_n(RZ_NONNULL RzStructuredData *parent, RZ_NONNULL const char *key, RZ_NONNULL const char *s, size_t s_len) { + rz_return_val_if_fail(parent && parent->type == STRUCTURED_DATA_TYPE_MAP && key && s, false); + + char *copy = rz_str_ndup(s, s_len); + if (!copy) { + return false; + } + + RzStructuredData *child = structured_data_new_string(copy); + return structured_data_map_add(parent, key, child); +} + +/** + * \brief Generates a hexdump of the bytes and assignes the string type child to a map parent + * + * \param parent Where to add the child RzStructuredData + * \param[in] key The key to assign the child RzStructuredData + * \param v The bytes value to hexdump and assign to the child + * \param v_size The max size of the bytes value + * \param fmt The format to use when dumping the bytes + * + * \return On success returns true, otherwise false. + */ +RZ_API bool rz_structured_data_map_add_bytes(RZ_NONNULL RzStructuredData *parent, RZ_NONNULL const char *key, RZ_NONNULL const ut8 *v, size_t v_size, RzStructuredDataFormat fmt) { + rz_return_val_if_fail(parent && parent->type == STRUCTURED_DATA_TYPE_MAP && key && v && fmt < RZ_STRUCTURED_DATA_FORMAT_ENUM_MAX, false); + + char *copy = structured_data_bytes_to_string(v, v_size, fmt); + if (!copy) { + return false; + } + + RzStructuredData *child = structured_data_new_string(copy); + return structured_data_map_add(parent, key, child); +} + /** * \brief Returns a child, map type, RzStructuredData that has been added to the given parent * @@ -454,7 +560,7 @@ RZ_API bool rz_structured_data_array_add_boolean(RZ_NONNULL RzStructuredData *pa * \brief Adds a null terminated string type child to an array type parent * * \param parent Where to add the child RzStructuredData - * \param n The value to assign to the child + * \param s The string value to assign to the child * * \return On success returns true, otherwise false. */ @@ -470,6 +576,49 @@ RZ_API bool rz_structured_data_array_add_string(RZ_NONNULL RzStructuredData *par return structured_data_array_add(parent, child); } +/** + * \brief Adds a null terminated string type child (with a max size of n) to an array type parent + * + * \param parent Where to add the child RzStructuredData + * \param s The string value to assign to the child + * \param s_len The size of the string value + * + * \return On success returns true, otherwise false. + */ +RZ_API bool rz_structured_data_array_add_string_n(RZ_NONNULL RzStructuredData *parent, RZ_NONNULL const char *s, size_t s_len) { + rz_return_val_if_fail(parent && parent->type == STRUCTURED_DATA_TYPE_ARRAY && s, false); + + char *copy = rz_str_ndup(s, s_len); + if (!copy) { + return false; + } + + RzStructuredData *child = structured_data_new_string(copy); + return structured_data_array_add(parent, child); +} + +/** + * \brief Generates a hexdump of the bytes and assignes the string type child to an array type parent + * + * \param parent Where to add the child RzStructuredData + * \param v The bytes value to hexdump and assign to the child + * \param v_size The max size of the bytes value + * \param fmt The format to use when dumping the bytes + * + * \return On success returns true, otherwise false. + */ +RZ_API bool rz_structured_data_array_add_bytes(RZ_NONNULL RzStructuredData *parent, RZ_NONNULL const ut8 *v, size_t v_size, RzStructuredDataFormat fmt) { + rz_return_val_if_fail(parent && parent->type == STRUCTURED_DATA_TYPE_ARRAY && v && fmt < RZ_STRUCTURED_DATA_FORMAT_ENUM_MAX, false); + + char *copy = structured_data_bytes_to_string(v, v_size, fmt); + if (!copy) { + return false; + } + + RzStructuredData *child = structured_data_new_string(copy); + return structured_data_array_add(parent, child); +} + static void structured_data_iterate_over(StructuredDataIterOver *sdio, const RzStructuredData *sd); static void structured_data_iterate_over_map(StructuredDataIterOver *sdio, const RzStructuredData *sd) { diff --git a/test/db/cmd/cmd_list b/test/db/cmd/cmd_list index 7cf6bf8539..4afe1fa8a3 100644 --- a/test/db/cmd/cmd_list +++ b/test/db/cmd/cmd_list @@ -234,10 +234,10 @@ vsf LGPL3 riq VICE snapshot file wasm MIT pancake WebAssembly xbe LGPL3 LemonBoy Microsoft Xbox XBE (Xbox Executable) z64 LGPL3 lowlyw Nintendo 64 Big-Endian binary -zimg LGPL3 ninjahacker ZIMG format binary +zimg LGPL3 deroad zImage format binary .fatmach0 LGPL3 Fat Mach-O binary extractor .sep64 LGPL3 64-bit SEP binary extractor -[{"name":"any","description":"Dummy format binary","license":"LGPL3","author":"nibble"},{"name":"art","description":"Android Runtime","license":"LGPL3","author":"pancake"},{"name":"avr","description":"ATmel AVR usermode","license":"LGPL3","author":"deroad"},{"name":"bf","description":"Brainfuck","license":"LGPL3","author":"pancake"},{"name":"bflt","description":"bFLT uClinux binary","license":"LGPL3","author":"Oscar Salvador"},{"name":"bios","description":"BIOS binary","license":"LGPL","author":"pancake"},{"name":"bootimg","description":"Android Boot Image","license":"LGPL3","author":"pancake"},{"name":"cgc","description":"CGC (Cyber Grand Challenge)","license":"LGPL3","author":"ret2libc"},{"name":"coff","description":"COFF (Common Object File Format)","license":"LGPL3","author":"Fedor Sakharov"},{"name":"dex","description":"DEX (Dalvik Executable)","license":"LGPL3","author":"deroad"},{"name":"dmp64","description":"Windows x64 Crash Dump","license":"LGPL3","author":"abcSup"},{"name":"dol","description":"Nintendo Dolphin binary","license":"BSD","author":"pancake"},{"name":"dyldcache","description":"Apple DYLD Cache","license":"LGPL3","author":"pancake"},{"name":"elf","description":"ELF (Executable and Linkable Format)","license":"LGPL3","author":"nibble"},{"name":"elf64","description":"ELF64 (64-bit Executable and Linkable Format)","license":"LGPL3","author":"nibble"},{"name":"gns1","description":"Apple C4000 baseband firmware (GNS1.bin)","license":"LGPL3","author":"Zapper9982"},{"name":"java","description":"Java binary","license":"LGPL3","author":"deroad"},{"name":"kernelcache","description":"Apple Kernelcache","license":"LGPL3","author":"mrmacete"},{"name":"le","description":"LE/LX","license":"LGPL3","author":"GustavoLCR"},{"name":"luac","description":"Lua compiled binary","license":"LGPL3","author":"Heersin"},{"name":"mach0","description":"Mach-O (Mach Object)","license":"LGPL3","author":"pancake"},{"name":"mach064","description":"Mach-O 64-bit","license":"LGPL3","author":"nibble"},{"name":"mbn","description":"MBN/SBL bootloader binary","license":"LGPL3","author":"pancake"},{"name":"mdmp","description":"Windows MiniDump","license":"LGPL3","author":"Davis"},{"name":"mdt","description":"Qualcomm Peripheral Image Loader (32bit only)","license":"LGPL3","author":"Rot127"},{"name":"menuet","description":"Menuet/KolibriOS binary","license":"LGPL3","author":"pancake"},{"name":"mz","description":"MZ (DOS MZ Executable)","license":"MIT","author":"nodepad"},{"name":"ne","description":"NE (New Executable)","license":"LGPL3","author":"GustavoLCR"},{"name":"nes","description":"Nintendo NES","license":"MIT","author":"maijin"},{"name":"nin3ds","description":"Nintendo 3DS Firmware","license":"LGPL3","author":"a0rtega"},{"name":"ninds","description":"Nintendo DS binary","license":"LGPL3","author":"a0rtega"},{"name":"ningb","description":"Nintendo Game Boy","license":"LGPL3","author":"condret"},{"name":"ningba","description":"Nintendo Game Boy Advance","license":"LGPL3","author":"condret"},{"name":"nro","description":"Nintendo Switch NRO","license":"MIT","author":"pancake"},{"name":"nso","description":"Nintendo Switch NSO","license":"MIT","author":"rkx1209"},{"name":"omf","description":"OMF (Object Module Format)","license":"LGPL3","author":"ampotos"},{"name":"p9","description":"Plan9 binary","license":"LGPL3","author":"pancake"},{"name":"pe","description":"PE (Portable Executable)","license":"LGPL3","author":"nibble"},{"name":"pe64","description":"PE64 (PE32+) binary","license":"LGPL3","author":"nibble"},{"name":"pebble","description":"Pebble Watch App","license":"LGPL","author":"pancake"},{"name":"prg","description":"C64 PRG (Commodore 64)","license":"LGPL3","author":"thestr4ng3r"},{"name":"psxexe","description":"Sony PlayStation 1 executable","license":"LGPL3","author":"Dax89"},{"name":"pyc","description":"Python byte-compiled","license":"LGPL3","author":"c0riolis"},{"name":"qnx","description":"QNX executable","license":"LGPL3","author":"deepakchethan"},{"name":"sfc","description":"Super NES / Super Famicom ROM","license":"LGPL3","author":"usrshare"},{"name":"smd","description":"SEGA Genesis / MegaDrive ROM","license":"LGPL3","author":"pancake"},{"name":"sms","description":"SEGA MasterSystem / GameGear ROM","license":"LGPL3","author":"shengdi"},{"name":"spc700","description":"SNES SPC700 sound data","license":"LGPL3","author":"maijin"},{"name":"symbols","description":"Apple Symbols file","license":"MIT","author":"pancake"},{"name":"te","description":"TE (Terse Executable)","license":"LGPL3","author":"xvilka"},{"name":"vsf","description":"VICE snapshot file","license":"LGPL3","author":"riq"},{"name":"wasm","description":"WebAssembly","license":"MIT","author":"pancake"},{"name":"xbe","description":"Microsoft Xbox XBE (Xbox Executable)","license":"LGPL3","author":"LemonBoy"},{"name":"z64","description":"Nintendo 64 Big-Endian binary","license":"LGPL3","author":"lowlyw"},{"name":"zimg","description":"ZIMG format binary","license":"LGPL3","author":"ninjahacker"},{"name":"xtr.fatmach0","description":"Fat Mach-O binary extractor","license":"LGPL3"},{"name":"xtr.sep64","description":"64-bit SEP binary extractor","license":"LGPL3"}] +[{"name":"any","description":"Dummy format binary","license":"LGPL3","author":"nibble"},{"name":"art","description":"Android Runtime","license":"LGPL3","author":"pancake"},{"name":"avr","description":"ATmel AVR usermode","license":"LGPL3","author":"deroad"},{"name":"bf","description":"Brainfuck","license":"LGPL3","author":"pancake"},{"name":"bflt","description":"bFLT uClinux binary","license":"LGPL3","author":"Oscar Salvador"},{"name":"bios","description":"BIOS binary","license":"LGPL","author":"pancake"},{"name":"bootimg","description":"Android Boot Image","license":"LGPL3","author":"pancake"},{"name":"cgc","description":"CGC (Cyber Grand Challenge)","license":"LGPL3","author":"ret2libc"},{"name":"coff","description":"COFF (Common Object File Format)","license":"LGPL3","author":"Fedor Sakharov"},{"name":"dex","description":"DEX (Dalvik Executable)","license":"LGPL3","author":"deroad"},{"name":"dmp64","description":"Windows x64 Crash Dump","license":"LGPL3","author":"abcSup"},{"name":"dol","description":"Nintendo Dolphin binary","license":"BSD","author":"pancake"},{"name":"dyldcache","description":"Apple DYLD Cache","license":"LGPL3","author":"pancake"},{"name":"elf","description":"ELF (Executable and Linkable Format)","license":"LGPL3","author":"nibble"},{"name":"elf64","description":"ELF64 (64-bit Executable and Linkable Format)","license":"LGPL3","author":"nibble"},{"name":"gns1","description":"Apple C4000 baseband firmware (GNS1.bin)","license":"LGPL3","author":"Zapper9982"},{"name":"java","description":"Java binary","license":"LGPL3","author":"deroad"},{"name":"kernelcache","description":"Apple Kernelcache","license":"LGPL3","author":"mrmacete"},{"name":"le","description":"LE/LX","license":"LGPL3","author":"GustavoLCR"},{"name":"luac","description":"Lua compiled binary","license":"LGPL3","author":"Heersin"},{"name":"mach0","description":"Mach-O (Mach Object)","license":"LGPL3","author":"pancake"},{"name":"mach064","description":"Mach-O 64-bit","license":"LGPL3","author":"nibble"},{"name":"mbn","description":"MBN/SBL bootloader binary","license":"LGPL3","author":"pancake"},{"name":"mdmp","description":"Windows MiniDump","license":"LGPL3","author":"Davis"},{"name":"mdt","description":"Qualcomm Peripheral Image Loader (32bit only)","license":"LGPL3","author":"Rot127"},{"name":"menuet","description":"Menuet/KolibriOS binary","license":"LGPL3","author":"pancake"},{"name":"mz","description":"MZ (DOS MZ Executable)","license":"MIT","author":"nodepad"},{"name":"ne","description":"NE (New Executable)","license":"LGPL3","author":"GustavoLCR"},{"name":"nes","description":"Nintendo NES","license":"MIT","author":"maijin"},{"name":"nin3ds","description":"Nintendo 3DS Firmware","license":"LGPL3","author":"a0rtega"},{"name":"ninds","description":"Nintendo DS binary","license":"LGPL3","author":"a0rtega"},{"name":"ningb","description":"Nintendo Game Boy","license":"LGPL3","author":"condret"},{"name":"ningba","description":"Nintendo Game Boy Advance","license":"LGPL3","author":"condret"},{"name":"nro","description":"Nintendo Switch NRO","license":"MIT","author":"pancake"},{"name":"nso","description":"Nintendo Switch NSO","license":"MIT","author":"rkx1209"},{"name":"omf","description":"OMF (Object Module Format)","license":"LGPL3","author":"ampotos"},{"name":"p9","description":"Plan9 binary","license":"LGPL3","author":"pancake"},{"name":"pe","description":"PE (Portable Executable)","license":"LGPL3","author":"nibble"},{"name":"pe64","description":"PE64 (PE32+) binary","license":"LGPL3","author":"nibble"},{"name":"pebble","description":"Pebble Watch App","license":"LGPL","author":"pancake"},{"name":"prg","description":"C64 PRG (Commodore 64)","license":"LGPL3","author":"thestr4ng3r"},{"name":"psxexe","description":"Sony PlayStation 1 executable","license":"LGPL3","author":"Dax89"},{"name":"pyc","description":"Python byte-compiled","license":"LGPL3","author":"c0riolis"},{"name":"qnx","description":"QNX executable","license":"LGPL3","author":"deepakchethan"},{"name":"sfc","description":"Super NES / Super Famicom ROM","license":"LGPL3","author":"usrshare"},{"name":"smd","description":"SEGA Genesis / MegaDrive ROM","license":"LGPL3","author":"pancake"},{"name":"sms","description":"SEGA MasterSystem / GameGear ROM","license":"LGPL3","author":"shengdi"},{"name":"spc700","description":"SNES SPC700 sound data","license":"LGPL3","author":"maijin"},{"name":"symbols","description":"Apple Symbols file","license":"MIT","author":"pancake"},{"name":"te","description":"TE (Terse Executable)","license":"LGPL3","author":"xvilka"},{"name":"vsf","description":"VICE snapshot file","license":"LGPL3","author":"riq"},{"name":"wasm","description":"WebAssembly","license":"MIT","author":"pancake"},{"name":"xbe","description":"Microsoft Xbox XBE (Xbox Executable)","license":"LGPL3","author":"LemonBoy"},{"name":"z64","description":"Nintendo 64 Big-Endian binary","license":"LGPL3","author":"lowlyw"},{"name":"zimg","description":"zImage format binary","license":"LGPL3","author":"deroad"},{"name":"xtr.fatmach0","description":"Fat Mach-O binary extractor","license":"LGPL3"},{"name":"xtr.sep64","description":"64-bit SEP binary extractor","license":"LGPL3"}] name license author description version ------------------------------------------------------------------------------------------ any LGPL3 nibble Dummy format binary @@ -294,7 +294,7 @@ vsf LGPL3 riq VICE snapshot file wasm MIT pancake WebAssembly xbe LGPL3 LemonBoy Microsoft Xbox XBE (Xbox Executable) z64 LGPL3 lowlyw Nintendo 64 Big-Endian binary -zimg LGPL3 ninjahacker ZIMG format binary +zimg LGPL3 deroad zImage format binary xtr.fatmach0 LGPL3 Fat Mach-O binary extractor xtr.sep64 LGPL3 64-bit SEP binary extractor any diff --git a/test/db/formats/zimg b/test/db/formats/zimg index 8cda1c8406..bbefe6a829 100644 --- a/test/db/formats/zimg +++ b/test/db/formats/zimg @@ -1,20 +1,26 @@ -NAME=Test 32-bit arm +NAME=ARM32 LE zImage 3.16-4.14 FILE=bins/zimg/arm32 CMDS=< 0x00000034 mrs sb, apsr + 0x00000038 bl 0x3700 + 0x0000003c mov r7, r1 +--- +0x00000024 0x016f2818 0x00000000 0x00343448 0x04030201 .(o.....H44..... +EOF +RUN + +NAME=ARM32 LE zImage 3.14 +FILE=bins/zimg/zImage.3.14.arm32le +CMDS=< 0x00000030 mrs sb, apsr + 0x00000034 bl 0x1480 + 0x00000038 mov r7, r1 + 0x0000003c mov r8, r2 +--- +0x00000024 0x016f2818 0x00000000 0x005abcd0 0xe10f9000 .(o.......Z..... +EOF +RUN + +NAME=rv64 zImage 5.4 +FILE=bins/zimg/zImage.5.4.rv64 +CMDS=< 0x00000040 csrw sie, zero + 0x00000044 csrw sip, zero + 0x00000048 auipc gp, 0x8e2 +--- +0x00000008 0x0000000000200000 0x000000000092416c .. .....lA...... +0x00000018 0x0000000000000000 0x0000000000000002 ................ +0x00000028 0x0000000000000000 0x0000005643534952 ........RISCV... +0x00000038 0x0000000005435352 0x1440107310401073 RSC.....s.@.s.@. EOF RUN