Rewrite of zImage bin parser & new structured data methods (#5893)
This commit is contained in:
parent
dcb4acf661
commit
dfdd062f14
8 changed files with 951 additions and 156 deletions
|
|
@ -1,27 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2009-2015 ninjahacker <wardjm@gmail.com>
|
||||
// SPDX-License-Identifier: LGPL-3.0-only
|
||||
|
||||
#include <rz_types.h>
|
||||
#include <rz_util.h>
|
||||
#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;
|
||||
}
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
// SPDX-FileCopyrightText: 2009-2015 ninjahacker <wardjm@gmail.com>
|
||||
// SPDX-License-Identifier: LGPL-3.0-only
|
||||
|
||||
#ifndef ZIMG_H
|
||||
#define ZIMG_H
|
||||
|
||||
#include <rz_types.h>
|
||||
#include <rz_util.h>
|
||||
#include <rz_lib.h>
|
||||
#include <rz_bin.h>
|
||||
|
||||
#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
|
||||
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -1,39 +1,461 @@
|
|||
// SPDX-FileCopyrightText: 2011-2019 ninjahacker <wardjm@gmail.com>
|
||||
// SPDX-FileCopyrightText: 2026 deroad <deroad@kumo.xn--q9jyb4c>
|
||||
// SPDX-License-Identifier: LGPL-3.0-only
|
||||
|
||||
#include <rz_types.h>
|
||||
#include <rz_util.h>
|
||||
#include <rz_lib.h>
|
||||
#include <rz_bin.h>
|
||||
#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;
|
||||
|
||||
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;
|
||||
}
|
||||
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;
|
||||
|
||||
static ut64 baddr(RzBinFile *bf) {
|
||||
return 0;
|
||||
}
|
||||
typedef enum zimage_arch {
|
||||
ZIMAGE_ARCH_ARM32_LE = 0,
|
||||
ZIMAGE_ARCH_ARM32_BE,
|
||||
ZIMAGE_ARCH_RISCV,
|
||||
} zimage_arch_t;
|
||||
|
||||
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)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
static RzBinInfo *info(RzBinFile *bf) {
|
||||
h->version_major = riscv_version >> 16;
|
||||
h->version_minor = riscv_version & 0xffff;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 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 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 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 /*<RzBinAddr *>*/ *zimage_entries(RzBinFile *bf) {
|
||||
zImage *zo = bf->o->bin_obj;
|
||||
|
||||
RzBinAddr *ptr = NULL;
|
||||
|
||||
RzPVector /*<RzBinAddr *>*/ *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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -1,20 +1,26 @@
|
|||
NAME=Test 32-bit arm
|
||||
NAME=ARM32 LE zImage 3.16-4.14
|
||||
FILE=bins/zimg/arm32
|
||||
CMDS=<<EOF
|
||||
iI
|
||||
echo ---
|
||||
iH
|
||||
echo ---
|
||||
oml
|
||||
echo ---
|
||||
pd 16
|
||||
echo ---
|
||||
pxw 16 @ 0x24
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
arch arm
|
||||
cpu N/A
|
||||
cpu arm
|
||||
features N/A
|
||||
baddr 0x00000000
|
||||
binsz 0x00000400
|
||||
bintype zimg
|
||||
bits 32
|
||||
retguard false
|
||||
class Compressed Linux Kernel
|
||||
class Linux zImage Kernel (3.16-4.14)
|
||||
compiler N/A
|
||||
dbg_file N/A
|
||||
endian LE
|
||||
|
|
@ -23,7 +29,7 @@ guid N/A
|
|||
intrp N/A
|
||||
laddr 0x00000000
|
||||
lang C
|
||||
machine ARM
|
||||
machine ARM32 LE
|
||||
maxopsz 4
|
||||
minopsz 4
|
||||
os linux
|
||||
|
|
@ -44,24 +50,230 @@ PIE false
|
|||
RELROCS false
|
||||
NX false
|
||||
---
|
||||
zimg:
|
||||
size: 1024
|
||||
kernel:
|
||||
kernel_start: 0x16f2818
|
||||
kernel_end: 0x0
|
||||
kernel_size: 18446744073685489640
|
||||
magic:
|
||||
magic0: 0xe1a00000
|
||||
magic1: 0xe1a00000
|
||||
arm_magic: 0xea000003
|
||||
zImage:
|
||||
machine: "ARM32 LE"
|
||||
kernel: "3.16-4.14"
|
||||
arm32_magic: 0x16f2818
|
||||
kernel_start: 0x0
|
||||
kernel_end: 0x343448
|
||||
endianness_flag: 0x4030201
|
||||
|
||||
EOF
|
||||
RUN
|
||||
|
||||
NAME=zimg maps
|
||||
FILE=bins/zimg/arm32
|
||||
CMDS=oml
|
||||
EXPECT=<<EOF
|
||||
---
|
||||
1 fd: 3 +0x00000000 0x00000000 * 0x000003ff r-x
|
||||
---
|
||||
;-- entry0:
|
||||
0x00000000 mov r0, r0
|
||||
0x00000004 mov r0, r0
|
||||
0x00000008 mov r0, r0
|
||||
0x0000000c mov r0, r0
|
||||
0x00000010 mov r0, r0
|
||||
0x00000014 mov r0, r0
|
||||
0x00000018 mov r0, r0
|
||||
0x0000001c mov r0, r0
|
||||
,=< 0x00000020 b 0x34
|
||||
| 0x00000024 invalid
|
||||
| 0x00000028 andeq r0, r0, r0
|
||||
| 0x0000002c eorseq r3, r4, r8, asr 8
|
||||
| 0x00000030 streq r0, [r3], -0x201
|
||||
`-> 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=<<EOF
|
||||
iI
|
||||
echo ---
|
||||
iH
|
||||
echo ---
|
||||
oml
|
||||
echo ---
|
||||
pd 16
|
||||
echo ---
|
||||
pxw 16 @ 0x24
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
arch arm
|
||||
cpu arm
|
||||
features N/A
|
||||
baddr 0x00000000
|
||||
binsz 0x00000200
|
||||
bintype zimg
|
||||
bits 32
|
||||
retguard false
|
||||
class Linux zImage Kernel (2.6-3.16)
|
||||
compiler N/A
|
||||
dbg_file N/A
|
||||
endian LE
|
||||
hdr.csum N/A
|
||||
guid N/A
|
||||
intrp N/A
|
||||
laddr 0x00000000
|
||||
lang C
|
||||
machine ARM32 LE
|
||||
maxopsz 4
|
||||
minopsz 4
|
||||
os linux
|
||||
cc N/A
|
||||
pcalign 4
|
||||
rpath N/A
|
||||
subsys linux
|
||||
stripped false
|
||||
crypto false
|
||||
havecode true
|
||||
va false
|
||||
sanitiz false
|
||||
static true
|
||||
linenum false
|
||||
lsyms false
|
||||
canary false
|
||||
PIE false
|
||||
RELROCS false
|
||||
NX false
|
||||
---
|
||||
zImage:
|
||||
machine: "ARM32 LE"
|
||||
kernel: "2.6-3.16"
|
||||
arm32_magic: 0x16f2818
|
||||
kernel_start: 0x0
|
||||
kernel_end: 0x5abcd0
|
||||
|
||||
---
|
||||
1 fd: 3 +0x00000000 0x00000000 * 0x000001ff r-x
|
||||
---
|
||||
;-- entry0:
|
||||
0x00000000 mov r0, r0
|
||||
0x00000004 mov r0, r0
|
||||
0x00000008 mov r0, r0
|
||||
0x0000000c mov r0, r0
|
||||
0x00000010 mov r0, r0
|
||||
0x00000014 mov r0, r0
|
||||
0x00000018 mov r0, r0
|
||||
0x0000001c mov r0, r0
|
||||
,=< 0x00000020 b 0x30
|
||||
| 0x00000024 invalid
|
||||
| 0x00000028 andeq r0, r0, r0
|
||||
| 0x0000002c ldrsbeq fp, [sl], -0xc0
|
||||
`-> 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=<<EOF
|
||||
iI
|
||||
echo ---
|
||||
iH
|
||||
echo ---
|
||||
oml
|
||||
echo ---
|
||||
pd 32
|
||||
echo ---
|
||||
pxq 64 @ 0x8
|
||||
EOF
|
||||
EXPECT=<<EOF
|
||||
arch riscv
|
||||
cpu rv64
|
||||
features N/A
|
||||
baddr 0x00200000
|
||||
binsz 0x00000200
|
||||
bintype zimg
|
||||
bits 64
|
||||
retguard false
|
||||
class Linux zImage Kernel (5.2+)
|
||||
compiler N/A
|
||||
dbg_file N/A
|
||||
endian LE
|
||||
hdr.csum N/A
|
||||
guid N/A
|
||||
intrp N/A
|
||||
laddr 0x00000000
|
||||
lang C
|
||||
machine RISC-V
|
||||
maxopsz 6
|
||||
minopsz 4
|
||||
os linux
|
||||
cc N/A
|
||||
pcalign 2
|
||||
rpath N/A
|
||||
subsys linux
|
||||
stripped false
|
||||
crypto false
|
||||
havecode true
|
||||
va false
|
||||
sanitiz false
|
||||
static true
|
||||
linenum false
|
||||
lsyms false
|
||||
canary false
|
||||
PIE false
|
||||
RELROCS false
|
||||
NX false
|
||||
---
|
||||
zImage:
|
||||
machine: "RISC-V"
|
||||
kernel: "5.2+"
|
||||
image_load: 0x200000
|
||||
kernel_size: 0x92416c
|
||||
head_flags: 0x0
|
||||
version:
|
||||
major: 0
|
||||
minor: 2
|
||||
padding0: 0x0
|
||||
padding1: 0x0
|
||||
riscv_magic1: "52 49 53 43 56 00 00 00 |RISCV... |"
|
||||
riscv_magic2: "52 53 43 05 |RSC. |"
|
||||
|
||||
---
|
||||
1 fd: 3 +0x00000000 0x00000000 * 0x000001ff r-x
|
||||
---
|
||||
;-- entry0:
|
||||
,=< 0x00000000 j 0x40
|
||||
| 0x00000002 illegal
|
||||
| 0x00000004 illegal
|
||||
| 0x00000006 nop
|
||||
| 0x00000008 illegal
|
||||
| 0x0000000a addi s0, sp, 8
|
||||
| 0x0000000c illegal
|
||||
| 0x0000000e illegal
|
||||
| 0x00000010 lw a1, 68(a0)
|
||||
| 0x00000012 slli ra, ra, 0x4
|
||||
| 0x00000014 illegal
|
||||
| 0x00000016 illegal
|
||||
| 0x00000018 illegal
|
||||
| 0x0000001a illegal
|
||||
| 0x0000001c illegal
|
||||
| 0x0000001e illegal
|
||||
| 0x00000020 invalid
|
||||
| 0x00000022 illegal
|
||||
| 0x00000024 illegal
|
||||
| 0x00000026 illegal
|
||||
| 0x00000028 illegal
|
||||
| 0x0000002a illegal
|
||||
| 0x0000002c illegal
|
||||
| 0x0000002e illegal
|
||||
| ;-- str.RISCV:
|
||||
| 0x00000030 .string "RISCV" ; len=6
|
||||
| 0x00000036 illegal
|
||||
| 0x00000038 lw t1, 52(sp)
|
||||
| 0x0000003a fmadd.s fa0, ft0, ft0, ft0, rne
|
||||
| 0x0000003e illegal
|
||||
`-> 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
|
||||
|
|
|
|||
Loading…
Reference in a new issue