rizin/librz/bin/p/bin_java.c

230 lines
5.4 KiB
C

// SPDX-FileCopyrightText: 2021-2023 RizinOrg <info@rizin.re>
// SPDX-FileCopyrightText: 2021-2023 deroad <wargio@libero.it>
// SPDX-License-Identifier: LGPL-3.0-only
#include <rz_types.h>
#include <rz_util.h>
#include <rz_lib.h>
#include <rz_bin.h>
#include "../format/java/class_bin.h"
#include "../../asm/arch/java/const.h"
#define rz_bin_file_get_java_class(bf) ((RzBinJavaClass *)bf->o->bin_obj)
static RzBinInfo *info(RzBinFile *bf) {
RzBinJavaClass *jclass = rz_bin_file_get_java_class(bf);
if (!jclass) {
return NULL;
}
RzBinInfo *binfo = RZ_NEW0(RzBinInfo);
if (!binfo) {
return NULL;
}
binfo->lang = rz_bin_java_class_language(jclass);
binfo->file = strdup(bf->file);
binfo->type = strdup("JAVA CLASS");
binfo->bclass = rz_bin_java_class_version(jclass);
binfo->has_va = false;
binfo->rclass = strdup("class");
binfo->os = strdup("any");
binfo->subsystem = strdup("any");
binfo->machine = strdup("jvm");
binfo->arch = strdup("java");
binfo->bits = 32;
binfo->big_endian = true;
binfo->dbg_info = rz_bin_java_class_debug_info(jclass);
return binfo;
}
static bool load_buffer(RzBinFile *bf, RzBinObject *obj, RzBuffer *buf, Sdb *sdb) {
RzBinJavaClass *jclass = rz_bin_java_class_new(buf, obj->opts.loadaddr, sdb);
if (!jclass) {
return false;
}
obj->bin_obj = jclass;
return true;
}
static void destroy(RzBinFile *bf) {
rz_bin_java_class_free(rz_bin_file_get_java_class(bf));
}
static bool check_buffer(RzBuffer *b) {
if (rz_buf_size(b) > 32) {
ut8 buf[4];
rz_buf_read_at(b, 0, buf, sizeof(buf));
return !memcmp(buf, "\xca\xfe\xba\xbe", 4);
}
return false;
}
static ut64 baddr(RzBinFile *bf) {
return 0;
}
static Sdb *get_sdb(RzBinFile *bf) {
return bf->sdb;
}
static RzPVector /*<RzBinClass *>*/ *classes(RzBinFile *bf) {
RzBinJavaClass *jclass = rz_bin_file_get_java_class(bf);
if (!jclass) {
return NULL;
}
return rz_bin_java_class_as_classes(jclass);
}
static RzPVector /*<RzBinImport *>*/ *imports(RzBinFile *bf) {
RzBinJavaClass *jclass = rz_bin_file_get_java_class(bf);
if (!jclass) {
return NULL;
}
return rz_bin_java_class_const_pool_as_imports(jclass);
}
static RzPVector /*<RzBinSection *>*/ *sections(RzBinFile *bf) {
RzBinJavaClass *jclass = rz_bin_file_get_java_class(bf);
if (!jclass) {
return NULL;
}
return rz_bin_java_class_as_sections(jclass);
}
static RzPVector /*<RzBinSymbol *>*/ *symbols(RzBinFile *bf) {
RzList *tmp;
RzBinJavaClass *jclass = rz_bin_file_get_java_class(bf);
if (!jclass) {
return NULL;
}
// read from list and save to pvector
RzPVector *ret = rz_pvector_new((RzPVectorFree)rz_bin_symbol_free);
RzListIter *iter;
RzBinSymbol *sym;
RzList *list = rz_bin_java_class_methods_as_symbols(jclass);
if (!list) {
return NULL;
}
rz_list_foreach (list, iter, sym) {
rz_pvector_push(ret, sym);
}
tmp = rz_bin_java_class_fields_as_symbols(jclass);
rz_list_foreach (tmp, iter, sym) {
rz_pvector_push(ret, sym);
}
tmp->length = 0;
tmp->head = tmp->tail = NULL;
rz_list_free(tmp);
tmp = rz_bin_java_class_const_pool_as_symbols(jclass);
rz_list_foreach (tmp, iter, sym) {
rz_pvector_push(ret, sym);
}
tmp->length = 0;
tmp->head = tmp->tail = NULL;
rz_list_free(tmp);
return ret;
}
static RzPVector /*<char *>*/ *libs(RzBinFile *bf) {
RzBinJavaClass *jclass = rz_bin_file_get_java_class(bf);
if (!jclass) {
return NULL;
}
return rz_bin_java_class_as_libraries(jclass);
}
static RzBinAddr *binsym(RzBinFile *bf, RzBinSpecialSymbol sym) {
RzBinJavaClass *jclass = rz_bin_file_get_java_class(bf);
if (!jclass) {
return NULL;
}
return rz_bin_java_class_resolve_symbol(jclass, sym);
}
static RzList /*<RzBinAddr *>*/ *entrypoints(RzBinFile *bf) {
RzBinJavaClass *jclass = rz_bin_file_get_java_class(bf);
if (!jclass) {
return NULL;
}
return rz_bin_java_class_entrypoints(jclass);
}
static RzPVector /*<RzBinString *>*/ *strings(RzBinFile *bf) {
RzBinJavaClass *jclass = rz_bin_file_get_java_class(bf);
if (!jclass) {
return NULL;
}
return rz_bin_java_class_strings(jclass);
}
static int demangle_type(const char *str) {
return RZ_BIN_LANGUAGE_JAVA;
}
static char *enrich_asm(RzBinFile *bf, const char *asm_str, int asm_len) {
RzBinJavaClass *jclass = rz_bin_file_get_java_class(bf);
if (!jclass) {
return NULL;
}
for (int i = 0; i < asm_len; ++i) {
if (!strncmp(asm_str + i, JAVA_ASM_CONSTANT_POOL_STR, strlen(JAVA_ASM_CONSTANT_POOL_STR))) {
const char *snum = asm_str + i + strlen(JAVA_ASM_CONSTANT_POOL_STR);
if (!IS_DIGIT(*snum)) {
rz_warn_if_reached();
continue;
}
int index = atoi(snum);
char *tmp = rz_bin_java_class_const_pool_resolve_index(jclass, index);
if (!tmp) {
rz_warn_if_reached();
return NULL;
}
char *result = rz_str_newf("%.*s%s", i, asm_str, tmp);
free(tmp);
return result;
}
}
return NULL;
}
RzBinPlugin rz_bin_plugin_java = {
.name = "java",
.desc = "java bin plugin",
.license = "LGPL3",
.get_sdb = &get_sdb,
.load_buffer = &load_buffer,
.destroy = &destroy,
.check_buffer = &check_buffer,
.baddr = &baddr,
.binsym = &binsym,
.entries = &entrypoints,
.maps = &rz_bin_maps_of_file_sections,
.sections = sections,
.symbols = &symbols,
.imports = &imports,
.strings = &strings,
.enrich_asm = &enrich_asm,
.info = &info,
.libs = libs,
.classes = classes,
.demangle_type = demangle_type,
.minstrlen = 3,
};
#ifndef RZ_PLUGIN_INCORE
RZ_API RzLibStruct rizin_plugin = {
.type = RZ_LIB_TYPE_BIN,
.data = &rz_bin_plugin_java,
.version = RZ_VERSION
};
#endif