Commit message: Fix #10498 - Fix crash in fuzzed java files (#10511)
CVE: CVE-2018-14017
CWE: CWE-125
Vulnerability description: The r_bin_java_annotation_new function in shlr/java/class.c in radare2 2.7.0 allows remote attackers to cause a denial of service (heap-based buffer over-read and application crash) via a crafted .class file because of missing input validation in r_bin_java_line_number_table_attr_new.

Project: radare2
File: class.c

R_API ut8 *r_bin_java_get_attr_buf(RBinJavaObj *bin, ut64 sz, const ut64 offset, const ut8 *buf, const ut64 len) {
	ut8 *attr_buf = NULL;
	int pending = len - offset;
	const ut8 *a_buf = offset + buf;
	attr_buf = (ut8 *) calloc (pending + 1, 1);
	if (attr_buf == NULL) {
		eprintf ("Unable to allocate enough bytes (0x%04"PFMT64x
			") to read in the attribute.\n", sz);
		return attr_buf;
	}
	memcpy (attr_buf, a_buf, pending); // sz+1);
	return attr_buf;
}

Project: radare2
File: class.c

R_API RBinJavaAttrInfo *r_bin_java_source_debug_attr_new(ut8 *buffer, ut64 sz, ut64 buf_offset) {
	ut64 offset = 6;
	RBinJavaAttrInfo *attr = r_bin_java_default_attr_new (buffer, sz, buf_offset);
	if (!attr) {
		return NULL;
	}
	attr->type = R_BIN_JAVA_ATTR_TYPE_SOURCE_DEBUG_EXTENTSION_ATTR;
	if (attr->length == 0) {
		eprintf ("r_bin_java_source_debug_attr_new: Attempting to allocate 0 bytes for debug_extension.\n");
		attr->info.debug_extensions.debug_extension = NULL;
		return attr;
	} else if ((attr->length + offset) > sz) {
		eprintf ("r_bin_java_source_debug_attr_new: Expected %d byte(s) got %"
			PFMT64d " bytes for debug_extension.\n", attr->length, (offset + sz));
	}
	attr->info.debug_extensions.debug_extension = (ut8 *) malloc (attr->length);
	if (attr->info.debug_extensions.debug_extension && (attr->length > (sz - offset))) {
		memcpy (attr->info.debug_extensions.debug_extension, buffer + offset, sz - offset);
	} else if (attr->info.debug_extensions.debug_extension) {
		memcpy (attr->info.debug_extensions.debug_extension, buffer + offset, attr->length);
	} else {
		eprintf ("r_bin_java_source_debug_attr_new: Unable to allocate the data for the debug_extension.\n");
	}
	offset += attr->length;
	attr->size = offset;
	return attr;
}

Project: radare2
File: class.c

R_API RBinJavaAttrInfo *r_bin_java_read_next_attr_from_buffer(ut8 *buffer, st64 sz, st64 buf_offset) {
	RBinJavaAttrInfo *attr = NULL;
	ut64 offset = 0;
	ut16 name_idx;
	st64 nsz;

	if (!buffer || ((int) sz) < 4 || buf_offset < 0) {
		eprintf ("r_bin_Java_read_next_attr_from_buffer: invalid buffer size %d\n", (int) sz);
		return NULL;
	}
	name_idx = R_BIN_JAVA_USHORT (buffer, offset);
	offset += 2;
	nsz = R_BIN_JAVA_UINT (buffer, offset);
	offset += 4;

	char *name = r_bin_java_get_utf8_from_bin_cp_list (R_BIN_JAVA_GLOBAL_BIN, name_idx);
	if (!name) {
		name = strdup ("unknown");
	}
	IFDBG eprintf("r_bin_java_read_next_attr: name_idx = %d is %s\n", name_idx, name);
	RBinJavaAttrMetas *type_info = r_bin_java_get_attr_type_by_name (name);
	if (type_info) {
		IFDBG eprintf("Typeinfo: %s, was %s\n", type_info->name, name);
		// printf ("SZ %d %d %d\n", nsz, sz, buf_offset);
		if (nsz > sz) {
			free (name);
			return NULL;
		}
		if ((attr = type_info->allocs->new_obj (buffer, nsz, buf_offset))) {
			attr->metas->ord = (R_BIN_JAVA_GLOBAL_BIN->attr_idx++);
		}
	} else {
		eprintf ("r_bin_java_read_next_attr_from_buffer: Cannot find type_info for %s\n", name);
	}
	free (name);
	return attr;
}

Project: radare2
File: class.c

R_API int is_class_interface(RBinJavaObj *bin, RBinJavaCPTypeObj *cp_obj) {
	RBinJavaInterfaceInfo *ifobj;
	RListIter *iter;
	int res = false;
	r_list_foreach (bin->interfaces_list, iter, ifobj) {
		if (ifobj) {
			res = cp_obj == ifobj->cp_class;
			if (res) {
				break;
			}
		}
	}
	return res;
}

Project: radare2
File: class.c

R_API char *r_bin_java_resolve_cp_idx_to_string(RBinJavaObj *BIN_OBJ, int idx) {
	RBinJavaCPTypeObj *item = NULL;
	char *value = NULL;
	if (BIN_OBJ && BIN_OBJ->cp_count < 1) {
		return NULL;
	}
	item = (RBinJavaCPTypeObj *) r_bin_java_get_item_from_bin_cp_list (BIN_OBJ, idx);
	if (item) {
		value = ((RBinJavaCPTypeMetas *)
		item->metas->type_info)->
		allocs->stringify_obj (item);
	}
	return value;
}

Project: radare2
File: class.c

R_API void U(r_bin_java_stack_frame_default_free)(void *s) {
	RBinJavaStackMapFrame *stack_frame = s;
	if (stack_frame) {
		free (stack_frame->metas);
		free (stack_frame);
	}
}

Project: radare2
File: class.c

R_API void r_bin_java_print_stack_map_frame_summary(RBinJavaStackMapFrame *obj) {
	RListIter *iter, *iter_tmp;
	RList *ptrList;
	RBinJavaVerificationObj *ver_obj;
	if (obj == NULL) {
		eprintf ("Attempting to print an invalid RBinJavaStackMapFrame*  .\n");
		return;
	}
	Eprintf ("Stack Map Frame Information\n");
	Eprintf ("  Tag Value = 0x%02x Name: %s\n", obj->tag, ((RBinJavaStackMapFrameMetas *) obj->metas->type_info)->name);
	Eprintf ("  Offset: 0x%08"PFMT64x "\n", obj->file_offset);
	Eprintf ("  Local Variable Count = 0x%04x\n", obj->number_of_locals);
	Eprintf ("  Stack Items Count = 0x%04x\n", obj->number_of_stack_items);
	Eprintf ("  Local Variables:\n");
	ptrList = obj->local_items;
	r_list_foreach_safe (ptrList, iter, iter_tmp, ver_obj) {
		r_bin_java_print_verification_info_summary (ver_obj);
	}
	Eprintf ("  Stack Items:\n");
	ptrList = obj->stack_items;
	r_list_foreach_safe (ptrList, iter, iter_tmp, ver_obj) {
		r_bin_java_print_verification_info_summary (ver_obj);
	}
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_stack_map_table_attr_calc_size(RBinJavaAttrInfo *attr) {
	ut64 size = 0;
	RListIter *iter, *iter_tmp;
	RBinJavaStackMapFrame *sf;
	if (attr) {
		// attr = r_bin_java_default_attr_new (buffer, sz, buf_offset);
		size += 6;
		// IFDBG r_bin_java_print_source_code_file_attr_summary(attr);
		// Current spec does not call for variable sizes.
		// attr->info.stack_map_table_attr.number_of_entries = R_BIN_JAVA_USHORT (buffer, offset);
		size += 2;
		r_list_foreach_safe (attr->info.stack_map_table_attr.stack_map_frame_entries, iter, iter_tmp, sf) {
			size += r_bin_java_stack_map_frame_calc_size (sf);
		}
	}
	return size;
}

Project: radare2
File: class.c

R_API void r_bin_java_fmtype_free(void /*RBinJavaField*/ *f) {
	RBinJavaField *fm_type = f;
	if (!fm_type) {
		return;
	}
	free (fm_type->descriptor);
	free (fm_type->name);
	free (fm_type->flags_str);
	free (fm_type->class_name);
	free (fm_type->metas);
	r_list_free (fm_type->attributes);
	free (fm_type);
}

Project: radare2
File: class.c

R_API void r_bin_java_synthetic_attr_free(void /*RBinJavaAttrInfo*/ *a) {
	RBinJavaAttrInfo *attr = a;
	if (attr) {
		free (attr->name);
		free (attr->metas);
		free (attr);
	}
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_parse_attrs(RBinJavaObj *bin, const ut64 offset, const ut8 *buf, const ut64 len) {
	int i = 0;
	ut64 adv = 0;
	const ut8 *a_buf = buf + offset;
	if (offset + 2 >= len) {
		// Check if we can read that USHORT
		return UT64_MAX;
	}
	r_list_free (bin->attrs_list);
	bin->attrs_list = r_list_newf (r_bin_java_attribute_free);
	bin->attrs_offset = offset;
	bin->attrs_count = R_BIN_JAVA_USHORT (a_buf, adv);
	adv += 2;
	if (bin->attrs_count > 0) {
		for (i = 0; i < bin->attrs_count; i++, bin->attr_idx++) {
			RBinJavaAttrInfo *attr = r_bin_java_read_next_attr (bin, offset + adv, buf, len);
			if (!attr) {
				// eprintf ("[X] r_bin_java: Error unable to parse remainder of classfile after Attribute: %d.\n", i);
				break;
			}
			r_list_append (bin->attrs_list, attr);
			adv += attr->size;
			if (adv + offset >= len) {
				// eprintf ("[X] r_bin_java: Error unable to parse remainder of classfile after Attribute: %d.\n", i);
				break;
			}
		}
	}
	bin->attrs_size = adv;
	return adv;
}

Project: radare2
File: class.c

R_API void r_bin_java_source_code_file_attr_free(void /*RBinJavaAttrInfo*/ *a) {
	RBinJavaAttrInfo *attr = a;
	if (attr) {
		free (attr->name);
		free (attr->metas);
		free (attr);
	}
}

Project: radare2
File: class.c

R_API RBinJavaStackMapFrame *r_bin_java_build_stack_frame_from_local_variable_table(RBinJavaObj *bin, RBinJavaAttrInfo *attr) {
	RBinJavaStackMapFrame *sf = r_bin_java_default_stack_frame ();
	RBinJavaLocalVariableAttribute *lvattr = NULL;
	RBinJavaVerificationObj *type_item;
	RListIter *iter = NULL;
	ut32 value_cnt = 0;
	ut8 value;
	if (!sf || !bin || !attr || attr->type != R_BIN_JAVA_ATTR_TYPE_LOCAL_VARIABLE_TABLE_ATTR) {
		eprintf ("Attempting to create a stack_map frame from a bad attribute.\n");
		return sf;
	}
	sf->number_of_locals = attr->info.local_variable_table_attr.table_length;
	r_list_foreach (attr->info.local_variable_table_attr.local_variable_table, iter, lvattr) {
		ut32 pos = 0;
		// knock the array Types
		while (lvattr->descriptor[pos] == '[') {
			pos++;
		}
		value = lvattr->descriptor[pos];
		// IFDBG eprintf ("Found the following type value: %c at pos %d in %s\n", value, pos, lvattr->descriptor);
		switch (value) {
		case 'I':
		case 'Z':
		case 'S':
		case 'B':
		case 'C':
			type_item = r_bin_java_verification_info_from_type (bin, R_BIN_JAVA_STACKMAP_INTEGER, 0);
			break;
		case 'F':
			type_item = r_bin_java_verification_info_from_type (bin, R_BIN_JAVA_STACKMAP_FLOAT, 0);
			break;
		case 'D':
			type_item = r_bin_java_verification_info_from_type (bin, R_BIN_JAVA_STACKMAP_DOUBLE, 0);
			break;
		case 'J':
			type_item = r_bin_java_verification_info_from_type (bin, R_BIN_JAVA_STACKMAP_LONG, 0);
			break;
		case 'L':
			// TODO: FIXME write something that will iterate over the CP Pool and find the
			// CONSTANT_Class_info referencing this
		{
			ut16 idx = r_bin_java_find_cp_class_ref_from_name_idx (bin, lvattr->name_idx);
			type_item = r_bin_java_verification_info_from_type (bin, R_BIN_JAVA_STACKMAP_OBJECT, idx);
		}
		break;
		default:
			eprintf ("r_bin_java_build_stack_frame_from_local_variable_table: "
				"not sure how to handle: name: %s, type: %s\n", lvattr->name, lvattr->descriptor);
			type_item = r_bin_java_verification_info_from_type (bin, R_BIN_JAVA_STACKMAP_NULL, 0);
		}
		if (type_item) {
			r_list_append (sf->local_items, (void *) type_item);
		}
		value_cnt++;
	}
	if (value_cnt != attr->info.local_variable_table_attr.table_length) {
		IFDBG eprintf("r_bin_java_build_stack_frame_from_local_variable_table: "
		"Number of locals not accurate.  Expected %d but got %d",
		attr->info.local_variable_table_attr.table_length, value_cnt);
	}
	return sf;
}

Project: radare2
File: class.c

R_API int r_bin_java_check_reset_cp_obj(RBinJavaCPTypeObj *cp_obj, ut8 tag) {
	bool res = false;
	if (tag < R_BIN_JAVA_CP_METAS_SZ) {
		if (tag != cp_obj->tag) {
			if (cp_obj->tag == R_BIN_JAVA_CP_UTF8) {
				free (cp_obj->info.cp_utf8.bytes);
				cp_obj->info.cp_utf8.bytes = NULL;
				cp_obj->info.cp_utf8.length = 0;
				free (cp_obj->name);
				cp_obj->name = NULL;
				res = true;
			}
			cp_obj->tag = tag;
			cp_obj->metas->type_info = (void *) &R_BIN_JAVA_CP_METAS[tag];
			cp_obj->name = strdup (R_BIN_JAVA_CP_METAS[tag].name);
			res = true;
		} else {
			eprintf ("Invalid tag\n");
		}
	} else {
		eprintf ("Invalid tag '%d'.\n", tag);
	}
	return res;
}

Project: radare2
File: class.c

R_API ut8 r_bin_java_does_cp_idx_ref_field(RBinJavaObj *BIN_OBJ, int idx) {
	RBinJavaField *fm_type = NULL;
	RListIter *iter;
	ut8 res = 0;
	r_list_foreach (BIN_OBJ->fields_list, iter, fm_type) {
		if (fm_type->field_ref_cp_obj->metas->ord == idx) {
			res = 1;
			break;
		}
	}
	return res;
}

Project: radare2
File: class.c

R_API int U(r_bin_java_is_method_private)(RBinJavaObj * bin_obj, ut64 addr) {
	return r_bin_java_is_fm_type_private (r_bin_java_get_method_code_attribute_with_addr (bin_obj, addr));
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_annotation_calc_size(RBinJavaAnnotation *annotation) {
	ut64 sz = 0;
	RListIter *iter, *iter_tmp;
	RBinJavaElementValuePair *ev_pairs = NULL;
	if (!annotation) {
		// TODO eprintf allocation fail
		return sz;
	}
	// annotation->type_idx = R_BIN_JAVA_USHORT (buffer, offset);
	sz += 2;
	// annotation->num_element_value_pairs = R_BIN_JAVA_USHORT (buffer, offset);
	sz += 2;
	r_list_foreach_safe (annotation->element_value_pairs, iter, iter_tmp, ev_pairs) {
		if (ev_pairs) {
			sz += r_bin_java_element_pair_calc_size (ev_pairs);
		}
	}
	return sz;
}

Project: radare2
File: class.c

R_API double r_bin_java_raw_to_double(const ut8 *raw, ut64 offset) {
	ut64 bits = R_BIN_JAVA_LONG (raw, offset);
	int s = ((bits >> 63) == 0) ? 1 : -1;
	int e = (int) ((bits >> 52) & 0x7ffL);
	long m = (e == 0) ?
	(bits & 0xfffffffffffffLL) << 1 :
	(bits & 0xfffffffffffffLL) | 0x10000000000000LL;
	double res = 0.0;
	IFDBG eprintf("Convert Long to Double: %08"PFMT64x "\n", bits);
	if (bits == 0x7ff0000000000000LL) {
		return INFINITY;
	}
	if (bits == 0xfff0000000000000LL) {
		return -INFINITY;
	}
	if (0x7ff0000000000001LL <= bits && bits <= 0x7fffffffffffffffLL) {
		return NAN;
	}
	if (0xfff0000000000001LL <= bits && bits <= 0xffffffffffffffffLL) {
		return NAN;
	}
	res = s * m * my_pow (2, e - 1075);// XXXX TODO Get double to work correctly here
	IFDBG eprintf("	High-bytes = %02x %02x %02x %02x\n", raw[0], raw[1], raw[2], raw[3]);
	IFDBG eprintf("	Low-bytes = %02x %02x %02x %02x\n", raw[4], raw[5], raw[6], raw[7]);
	IFDBG eprintf("Convert Long to Double s: %d, m: 0x%08lx, e: 0x%08x, res: %f\n", s, m, e, res);
	return res;
}

Project: radare2
File: class.c

R_API void r_bin_java_print_synthetic_attr_summary(RBinJavaAttrInfo *attr) {
	if (attr == NULL) {
		eprintf ("Attempting to print an invalid RBinJavaAttrInfo *Synthetic.\n");
		return;
	}
	Eprintf ("Synthetic Attribute Information:\n");
	Eprintf ("  Attribute Offset: 0x%08"PFMT64x "\n", attr->file_offset);
	Eprintf ("  Attribute Name Index: %d (%s)\n", attr->name_idx, attr->name);
	Eprintf ("  Attribute Length: %d\n", attr->length);
	Eprintf ("  Attribute Index: %d\n", attr->info.source_file_attr.sourcefile_idx);
}

Project: radare2
File: class.c

R_API RBinJavaAttrInfo *r_bin_java_synthetic_attr_new(ut8 *buffer, ut64 sz, ut64 buf_offset) {
	ut64 offset = 0;
	RBinJavaAttrInfo *attr = r_bin_java_default_attr_new (buffer, sz, buf_offset);
	if (!attr) {
		return NULL;
	}
	offset += 6;
	attr->type = R_BIN_JAVA_ATTR_TYPE_SYNTHETIC_ATTR;
	attr->size = offset;
	return attr;
}

Project: radare2
File: class.c

R_API ut8 *U(r_bin_java_cp_get_method_ref)(RBinJavaObj * bin, ut32 * out_sz, ut16 class_idx, ut16 name_and_type_idx) {
	return r_bin_java_cp_get_fm_ref (bin, out_sz, R_BIN_JAVA_CP_METHODREF, class_idx, name_and_type_idx);
}

Project: radare2
File: class.c

R_API void U(r_bin_java_stack_frame_do_nothing_new)(RBinJavaObj * bin, RBinJavaStackMapFrame * stack_frame, ut64 offset) {}

Project: radare2
File: class.c

R_API void r_bin_java_print_invokedynamic_cp_summary(RBinJavaCPTypeObj *obj) {
	if (obj == NULL) {
		eprintf ("Attempting to print an invalid RBinJavaCPTypeObj*  RBinJavaCPTypeInvokeDynamic.\n");
		return;
	}
	eprintf ("InvokeDynamic ConstantPool Type (%d) ", obj->metas->ord);
	eprintf ("	Offset: 0x%08"PFMT64x"", obj->file_offset);
	eprintf ("	Bootstrap Method Attr Index = (0x%02x)\n", obj->info.cp_invoke_dynamic.bootstrap_method_attr_index);
	eprintf ("	Bootstrap Name and Type Index = (0x%02x)\n", obj->info.cp_invoke_dynamic.name_and_type_index);
}

Project: radare2
File: class.c

R_API void r_bin_java_print_method_summary(RBinJavaField *field) {
	RBinJavaAttrInfo *attr;
	RListIter *iter, *iter_tmp;
	if (field == NULL) {
		eprintf ("Attempting to print an invalid RBinJavaField* Method.\n");
		return;
	}
	Eprintf ("Method Summary Information:\n");
	Eprintf ("  File Offset: 0x%08"PFMT64x "\n", field->file_offset);
	Eprintf ("  Name Index: %d (%s)\n", field->name_idx, field->name);
	Eprintf ("  Descriptor Index: %d (%s)\n", field->descriptor_idx, field->descriptor);
	Eprintf ("  Access Flags: 0x%02x (%s)\n", field->flags, field->flags_str);
	Eprintf ("  Method Attributes Count: %d\n", field->attr_count);
	Eprintf ("  Method Attributes:\n");
	r_list_foreach_safe (field->attributes, iter, iter_tmp, attr) {
		r_bin_java_print_attr_summary (attr);
	}
}

Project: radare2
File: class.c

R_API void r_bin_java_reset_bin_info(RBinJavaObj *bin) {
	free (bin->cf2.flags_str);
	free (bin->cf2.this_class_name);
	r_list_free (bin->imports_list);
	r_list_free (bin->methods_list);
	r_list_free (bin->fields_list);
	r_list_free (bin->attrs_list);
	r_list_free (bin->cp_list);
	r_list_free (bin->interfaces_list);
	memset (bin, 0, sizeof (RBinJavaObj));
	bin->cf2.flags_str = strdup ("unknown");
	bin->cf2.this_class_name = strdup ("unknown");
	bin->imports_list = r_list_newf (free);
	bin->methods_list = r_list_newf (r_bin_java_fmtype_free);
	bin->fields_list = r_list_newf (r_bin_java_fmtype_free);
	bin->attrs_list = r_list_newf (r_bin_java_attribute_free);
	bin->cp_list = r_list_newf (r_bin_java_constant_pool);
	bin->interfaces_list = r_list_newf (r_bin_java_interface_free);
}

Project: radare2
File: class.c

R_API void U(copy_type_info_to_stack_frame_list_up_to_idx)(RList * type_list, RList * sf_list, ut64 idx) {
	RListIter *iter, *iter_tmp;
	RBinJavaVerificationObj *ver_obj, *new_ver_obj;
	ut32 pos = 0;
	if (type_list == NULL) {
		return;
	}
	if (sf_list == NULL) {
		return;
	}
	r_list_foreach_safe (type_list, iter, iter_tmp, ver_obj) {
		new_ver_obj = (RBinJavaVerificationObj *) malloc (sizeof (RBinJavaVerificationObj));
		// FIXME: how to handle failed memory allocation?
		if (new_ver_obj && ver_obj) {
			memcpy (new_ver_obj, ver_obj, sizeof (RBinJavaVerificationObj));
			if (!r_list_append (sf_list, (void *) new_ver_obj)) {
				R_FREE (new_ver_obj);
			}
		} else {
			R_FREE (new_ver_obj);
		}
		pos++;
		if (pos == idx) {
			break;
		}
	}
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_do_nothing_calc_size(RBinJavaCPTypeObj *obj) {
	return 0;
}

Project: radare2
File: class.c

R_API ut8 *r_bin_java_cp_append_classref_and_name(RBinJavaObj *bin, ut32 *out_sz, const char *classname, const ut32 classname_len) {
	ut16 use_name_idx = bin->cp_idx + 1;
	ut8 *bytes = NULL, *name_bytes = NULL;
	name_bytes = r_bin_java_cp_get_utf8 (R_BIN_JAVA_CP_UTF8, out_sz, (const ut8 *) classname, classname_len);
	if (*out_sz > 0 && name_bytes) {
		ut8 *idx_addr = (ut8 *) &use_name_idx;
		bytes = malloc (*out_sz + 3);
		memcpy (bytes, name_bytes, *out_sz);
		bytes[*out_sz + 0] = R_BIN_JAVA_CP_CLASS;
		bytes[*out_sz + 1] = idx_addr[1];
		bytes[*out_sz + 2] = idx_addr[0];
		*out_sz += 3;
	}
	free (name_bytes);
	return bytes;
}

Project: radare2
File: class.c

R_API RBinJavaCPTypeObj *r_bin_java_clone_cp_item(RBinJavaCPTypeObj *obj) {
	RBinJavaCPTypeObj *clone_obj = NULL;
	if (obj == NULL) {
		return clone_obj;
	}
	clone_obj = R_NEW0 (RBinJavaCPTypeObj);
	if (clone_obj) {
		memcpy (clone_obj, obj, sizeof (RBinJavaCPTypeObj));
		clone_obj->metas = (RBinJavaMetaInfo *) R_NEW0 (RBinJavaMetaInfo);
		clone_obj->metas->type_info = (void *) &R_BIN_JAVA_CP_METAS[clone_obj->tag];
		clone_obj->name = strdup (obj->name? obj->name: "unk");
		if (obj->tag == R_BIN_JAVA_CP_UTF8) {
			clone_obj->info.cp_utf8.bytes = (ut8 *) malloc (obj->info.cp_utf8.length + 1);
			if (clone_obj->info.cp_utf8.bytes) {
				memcpy (clone_obj->info.cp_utf8.bytes, obj->info.cp_utf8.bytes, clone_obj->info.cp_utf8.length);
			} else {
				// TODO: eprintf allocation error
			}
		}
	}
	return clone_obj;
}

Project: radare2
File: class.c

R_API RBinJavaElementValuePair *r_bin_java_element_pair_new(ut8 *buffer, ut64 sz, ut64 buf_offset) {
	RBinJavaElementValuePair *ev_pair = NULL;
	ut64 offset = 0;
	if (!buffer) {
		return NULL;
	}
	ev_pair = R_NEW0 (RBinJavaElementValuePair);
	if (!ev_pair) {
		// TODO eprintf ev_pair failed to allocate
		return NULL;
	}
	// TODO: What is the signifigance of ev_pair element
	ev_pair->element_name_idx = R_BIN_JAVA_USHORT (buffer, offset);
	offset += 2;
	ev_pair->file_offset = buf_offset;
	ev_pair->name = r_bin_java_get_utf8_from_bin_cp_list (R_BIN_JAVA_GLOBAL_BIN, ev_pair->element_name_idx);
	if (ev_pair->name == NULL) {
		// TODO: eprintf unable to find the name for the given index
		eprintf ("ElementValue Name is invalid.\n");
		ev_pair->name = strdup ("UNKNOWN");
	}
	ev_pair->value = r_bin_java_element_value_new (buffer + offset, sz - offset, buf_offset + offset);
	offset += ev_pair->value->size;
	ev_pair->size = offset;
	return ev_pair;
}

Project: radare2
File: class.c

R_API void r_bin_java_annotation_array_free(void /*RBinJavaAnnotationsArray*/ *a) {
	RBinJavaAnnotationsArray *annotation_array = a;
	RListIter *iter = NULL, *iter_tmp = NULL;
	RBinJavaAnnotation *annotation;
	if (annotation_array->annotations == NULL) {
		// TODO eprintf
		return;
	}
	r_list_foreach_safe (annotation_array->annotations, iter, iter_tmp, annotation) {
		if (annotation) {
			r_bin_java_annotation_free (annotation);
		}
		// r_list_delete (annotation_array->annotations, iter);
	}
	r_list_free (annotation_array->annotations);
	free (annotation_array);
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_unknown_cp_calc_size(RBinJavaCPTypeObj *obj) {
	return 1LL;
}

Project: radare2
File: class.c

R_API RBinJavaCPTypeObj *r_bin_java_get_item_from_bin_cp_list(RBinJavaObj *bin, ut64 idx) {
	/*
	Search through the Constant Pool list for the given CP Index.
	If the idx not found by directly going to the list index,
	the list will be walked and then the IDX will be checked.
	rvalue: RBinJavaObj* (user does NOT free).
	*/
	if (bin == NULL) {
		return NULL;
	}
	if (idx > bin->cp_count || idx == 0) {
		return r_bin_java_get_java_null_cp ();
	}
	return r_bin_java_get_item_from_cp_item_list (bin->cp_list, idx);
}

Project: radare2
File: class.c

R_API RBinJavaField *r_bin_java_get_method_code_attribute_with_addr(RBinJavaObj *bin, ut64 addr) {
	RListIter *iter = NULL, *iter_tmp = NULL;
	RBinJavaField *fm_type, *res = NULL;
	if (bin == NULL && R_BIN_JAVA_GLOBAL_BIN) {
		bin = R_BIN_JAVA_GLOBAL_BIN;
	} else if (bin == NULL) {
		eprintf ("Attempting to analyse function when the R_BIN_JAVA_GLOBAL_BIN has not been set.\n");
		return NULL;
	}
	r_list_foreach_safe (bin->methods_list, iter, iter_tmp, fm_type) {
		ut64 offset = r_bin_java_get_method_code_offset (fm_type) + bin->loadaddr,
		size = r_bin_java_get_method_code_size (fm_type);
		if (addr >= offset && addr <= size + offset) {
			res = fm_type;
		}
	}
	return res;
}

Project: radare2
File: class.c

R_API RList *r_bin_java_extract_all_bin_type_values(RBinJavaObj *bin_obj) {
	RListIter *fm_type_iter;
	RList *all_types = r_list_new ();
	RBinJavaField *fm_type;
	// get all field types
	r_list_foreach (bin_obj->fields_list, fm_type_iter, fm_type) {
		char *desc = NULL;
		if (!extract_type_value (fm_type->descriptor, &desc)) {
			return NULL;
		}
		IFDBG eprintf("Adding field type: %s\n", desc);
		r_list_append (all_types, desc);
	}
	// get all method types
	r_list_foreach (bin_obj->methods_list, fm_type_iter, fm_type) {
		RList *the_list = r_bin_java_extract_type_values (fm_type->descriptor);
		RListIter *desc_iter;
		char *str;
		r_list_foreach (the_list, desc_iter, str) {
			if (str && *str != '(' && *str != ')') {
				r_list_append (all_types, strdup (str));
				IFDBG eprintf("Adding method type: %s\n", str);
			}
		}
		r_list_free (the_list);
	}
	return all_types;
}

Project: radare2
File: class.c

R_API void r_bin_java_exceptions_attr_free(void /*RBinJavaAttrInfo*/ *a) {
	RBinJavaAttrInfo *attr = a;
	if (attr) {
		free (attr->name);
		free (attr->metas);
		free (attr->info.exceptions_attr.exception_idx_table);
		free (attr);
	}
}

Project: radare2
File: class.c

R_API int U(r_bin_java_float_cp_set)(RBinJavaObj * bin, ut16 idx, float val) {
	RBinJavaCPTypeObj *cp_obj = r_bin_java_get_item_from_bin_cp_list (bin, idx);
	if (!cp_obj) {
		return false;
	}
	ut8 bytes[4] = {
		0
	};
	if (cp_obj->tag != R_BIN_JAVA_CP_INTEGER && cp_obj->tag != R_BIN_JAVA_CP_FLOAT) {
		eprintf ("Not supporting the overwrite of CP Objects with one of a different size.\n");
		return false;
	}
	r_bin_java_check_reset_cp_obj (cp_obj, R_BIN_JAVA_CP_FLOAT);
	cp_obj->tag = R_BIN_JAVA_CP_FLOAT;
	memcpy (bytes, (const char *) &val, 4);
	float *foo = (float*) bytes;
	val = *foo; //(float)R_BIN_JAVA_UINT (bytes, 0);
	memcpy (&cp_obj->info.cp_float.bytes.raw, (const char *) &val, 4);
	return true;
}

Project: radare2
File: class.c

R_API char *r_bin_java_get_method_definition(RBinJavaField *fm_type) {
	return r_bin_java_unmangle (fm_type->flags_str, fm_type->name, fm_type->descriptor);
}

Project: radare2
File: class.c

R_API void r_bin_java_element_value_free(void /*RBinJavaElementValue*/ *e) {
	RBinJavaElementValue *element_value = e;
	RListIter *iter = NULL, *iter_tmp = NULL;
	RBinJavaCPTypeObj *obj = NULL;
	RBinJavaElementValue *ev_element = NULL;
	if (element_value) {
		free (element_value->metas);
		element_value->metas = NULL;
		switch (element_value->tag) {
		case R_BIN_JAVA_EV_TAG_BYTE:
		case R_BIN_JAVA_EV_TAG_CHAR:
		case R_BIN_JAVA_EV_TAG_DOUBLE:
		case R_BIN_JAVA_EV_TAG_FLOAT:
		case R_BIN_JAVA_EV_TAG_INT:
		case R_BIN_JAVA_EV_TAG_LONG:
		case R_BIN_JAVA_EV_TAG_SHORT:
		case R_BIN_JAVA_EV_TAG_BOOLEAN:
		case R_BIN_JAVA_EV_TAG_STRING:
			// Delete the CP Type Object
			obj = element_value->value.const_value.const_value_cp_obj;
			((RBinJavaCPTypeMetas *) obj->metas->type_info)->allocs->delete_obj (obj);
			break;
		case R_BIN_JAVA_EV_TAG_ENUM:
			// Delete the CP Type Objects
			obj = element_value->value.enum_const_value.const_name_cp_obj;
			((RBinJavaCPTypeMetas *) obj->metas->type_info)->allocs->delete_obj (obj);
			obj = element_value->value.enum_const_value.type_name_cp_obj;
			((RBinJavaCPTypeMetas *) obj->metas->type_info)->allocs->delete_obj (obj);
			break;
		case R_BIN_JAVA_EV_TAG_CLASS:
			// Delete the CP Type Object
			obj = element_value->value.class_value.class_info_cp_obj;
			((RBinJavaCPTypeMetas *) obj->metas->type_info)->allocs->delete_obj (obj);
			break;
		case R_BIN_JAVA_EV_TAG_ARRAY:
			// Delete the Element Value array List
			r_list_foreach_safe (element_value->value.array_value.values, iter, iter_tmp, ev_element) {
				if (ev_element) {
					r_bin_java_element_value_free (ev_element);
				} else {
					// TODO eprintf ev_pairs value was NULL
				}
				// r_list_delete (element_value->value.array_value.values, iter);
				ev_element = NULL;
			}
			r_list_free (element_value->value.array_value.values);
			break;
		case R_BIN_JAVA_EV_TAG_ANNOTATION:
			// Delete the Annotations List
			r_list_free (element_value->value.annotation_value.element_value_pairs);
			break;
		default:
			// eprintf unable to free the tag
			break;
		}
		free (element_value);
	}
}

Project: radare2
File: class.c

R_API ut16 r_bin_java_calculate_method_access_value(const char *access_flags_str) {
	return calculate_access_value (access_flags_str, METHOD_ACCESS_FLAGS);
}

Project: radare2
File: class.c

R_API int r_bin_java_new_bin(RBinJavaObj *bin, ut64 loadaddr, Sdb *kv, const ut8 *buf, ut64 len) {
	R_BIN_JAVA_GLOBAL_BIN = bin;
	bin->lines.count = 0;
	bin->loadaddr = loadaddr;
	r_bin_java_get_java_null_cp ();
	bin->id = r_num_rand (UT32_MAX);
	bin->kv = kv ? kv : sdb_new (NULL, NULL, 0);
	bin->AllJavaBinObjs = NULL;
	return r_bin_java_load_bin (bin, buf, len);
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_string_cp_calc_size(RBinJavaCPTypeObj *obj) {
	ut64 size = 0;
	// tag
	size += 1;
	// obj->info.cp_string.string_idx = R_BIN_JAVA_USHORT (buffer, 1);
	size += 2;
	return size;
}

Project: radare2
File: class.c

R_API void r_bin_java_print_fieldref_cp_summary(RBinJavaCPTypeObj *obj) {
	if (obj == NULL) {
		eprintf ("Attempting to print an invalid RBinJavaCPTypeObj*  FieldRef.\n");
		return;
	}
	eprintf ("FieldRef ConstantPool Type (%d) ", obj->metas->ord);
	eprintf ("	Offset: 0x%08"PFMT64x"", obj->file_offset);
	eprintf ("	Class Index = %d\n", obj->info.cp_field.class_idx);
	eprintf ("	Name and type Index = %d\n", obj->info.cp_field.name_and_type_idx);
}

Project: radare2
File: class.c

R_API RList *U(r_bin_java_get_ret_from_bin)(RBinJavaObj * bin_obj, ut64 addr) {
	RBinJavaField *fm_type = r_bin_java_get_method_code_attribute_with_addr (bin_obj, addr);
	return fm_type ? r_bin_java_get_ret (fm_type) : NULL;
}

Project: radare2
File: class.c

R_API RList *r_bin_java_get_method_definitions(RBinJavaObj *bin) {
	RBinJavaField *fm_type = NULL;
	RList *the_list = r_list_new ();
	if (!the_list) {
		return NULL;
	}
	RListIter *iter = NULL;
	if (!bin) {
		return the_list;
	}
	r_list_foreach (bin->methods_list, iter, fm_type) {
		char *method_proto = r_bin_java_get_method_definition (fm_type);
		// eprintf ("Method prototype: %s\n", method_proto);
		r_list_append (the_list, method_proto);
	}
	return the_list;
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_parse_fields(RBinJavaObj *bin, const ut64 offset, const ut8 *buf, const ut64 len) {
	int i = 0;
	ut64 adv = 0;
	RBinJavaField *field;
	const ut8 *fm_buf = buf + offset;
	r_list_free (bin->fields_list);
	bin->fields_list = r_list_newf (r_bin_java_fmtype_free);
	bin->fields_offset = offset;
	if (offset + 2 >= len) {
		return UT64_MAX;
	}
	bin->fields_count = R_BIN_JAVA_USHORT (fm_buf, 0);
	adv += 2;
	IFDBG eprintf("Fields count: %d 0x%"PFMT64x "\n", bin->fields_count, bin->fields_offset);
	if (bin->fields_count > 0) {
		for (i = 0; i < bin->fields_count; i++, bin->field_idx++) {
			field = r_bin_java_read_next_field (bin, offset + adv, buf, len);
			if (field) {
				adv += field->size;
				r_list_append (bin->fields_list, field);
				IFDBG r_bin_java_print_field_summary(field);
				if (adv + offset > len) {
					eprintf ("[X] r_bin_java: Error unable to parse remainder of classfile after Field: %d.\n", i);
					break;
				}
			} else {
				IFDBG eprintf("Failed to read Field %d\n", i);
			}
		}
	}
	bin->fields_size = adv;
	return adv;
}

Project: radare2
File: class.c

R_API void r_bin_java_deprecated_attr_free(void /*RBinJavaAttrInfo*/ *a) {
	RBinJavaAttrInfo *attr = a;
	if (attr) {
		free (attr->name);
		free (attr->metas);
		free (attr);
	}
}

Project: radare2
File: class.c

R_API void r_bin_java_print_enclosing_methods_attr_summary(RBinJavaAttrInfo *attr) {
	if (!attr) {
		eprintf ("Attempting to print an invalid RBinJavaAttrInfo *Deperecated.\n");
		return;
	}
	Eprintf ("Enclosing Method Attribute Information:\n");
	Eprintf ("  Attribute Offset: 0x%08"PFMT64x "\n", attr->file_offset);
	Eprintf ("  Attribute Name Index: %d (%s)\n", attr->name_idx, attr->name);
	Eprintf ("  Attribute Length: %d\n", attr->length);
	Eprintf ("  Class Info Index : 0x%02x\n", attr->info.enclosing_method_attr.class_idx);
	Eprintf ("  Method Name and Type Index : 0x%02x\n", attr->info.enclosing_method_attr.method_idx);
	Eprintf ("  Class Name : %s\n", attr->info.enclosing_method_attr.class_name);
	Eprintf ("  Method Name and Desc : %s %s\n", attr->info.enclosing_method_attr.method_name, attr->info.enclosing_method_attr.method_descriptor);
}

Project: radare2
File: class.c

R_API RBinJavaCPTypeObj *r_bin_java_get_java_null_cp() {
	if (R_BIN_JAVA_NULL_TYPE_INITTED) {
		return &R_BIN_JAVA_NULL_TYPE;
	}
	memset (&R_BIN_JAVA_NULL_TYPE, 0, sizeof (R_BIN_JAVA_NULL_TYPE));
	R_BIN_JAVA_NULL_TYPE.metas = R_NEW0 (RBinJavaMetaInfo);
	if (!R_BIN_JAVA_NULL_TYPE.metas) {
		return NULL;
	}
	memset (R_BIN_JAVA_NULL_TYPE.metas, 0, sizeof (RBinJavaMetaInfo));
	R_BIN_JAVA_NULL_TYPE.metas->type_info = &R_BIN_JAVA_CP_METAS[0];
	R_BIN_JAVA_NULL_TYPE.metas->ord = 0;
	R_BIN_JAVA_NULL_TYPE.file_offset = 0;
	R_BIN_JAVA_NULL_TYPE_INITTED = true;
	return &R_BIN_JAVA_NULL_TYPE;
}

Project: radare2
File: class.c

R_API void r_bin_java_bootstrap_method_argument_free(void /*RBinJavaBootStrapArgument*/ *b) {
	RBinJavaBootStrapArgument *bsm_arg = b;
	if (bsm_arg) {
		if (bsm_arg->argument_info_cp_obj) {
			((RBinJavaCPTypeMetas *) bsm_arg->argument_info_cp_obj)->allocs->delete_obj (bsm_arg->argument_info_cp_obj);
			bsm_arg->argument_info_cp_obj = NULL;
		}
		free (bsm_arg);
	}
}

Project: radare2
File: class.c

R_API void r_bin_java_print_constant_value_attr_summary(RBinJavaAttrInfo *attr) {
	if (!attr) {
		eprintf ("Attempting to print an invalid RBinJavaAttrInfo *ConstantValue.\n");
		return;
	}
	Eprintf ("Constant Value Attribute Information:\n");
	Eprintf ("  Attribute Offset: 0x%08"PFMT64x "\n", attr->file_offset);
	Eprintf ("  Attribute Name Index: %d (%s)\n", attr->name_idx, attr->name);
	Eprintf ("  Attribute Length: %d\n", attr->length);
	Eprintf ("  ConstantValue Index: %d\n", attr->info.constant_value_attr.constantvalue_idx);
}

Project: radare2
File: class.c

R_API void r_bin_java_print_rtv_annotations_attr_summary(RBinJavaAttrInfo *attr) {
	if (attr && attr->type == R_BIN_JAVA_ATTR_TYPE_RUNTIME_VISIBLE_ANNOTATION_ATTR) {
		Eprintf ("Runtime Visible Annotations Attribute Information:\n");
		Eprintf ("   Attribute Offset: 0x%08"PFMT64x "\n", attr->file_offset);
		Eprintf ("   Attribute Name Index: %d (%s)\n", attr->name_idx, attr->name);
		Eprintf ("   Attribute Length: %d\n", attr->length);
		r_bin_java_print_annotation_array_summary (&attr->info.annotation_array);
	}
}

Project: radare2
File: class.c

R_API char *r_bin_java_get_item_desc_from_bin_cp_list(RBinJavaObj *bin, RBinJavaCPTypeObj *obj) {
	/*
	Given a constant poool object Class, FieldRef, MethodRef, or InterfaceMethodRef
	return the actual descriptor string.
	@param cp_list: RList of RBinJavaCPTypeObj *
	@param obj object to look up the name for
	@rvalue char* (user frees) or NULL
	*/
	if (bin == NULL) {
		return NULL;
	}
	return r_bin_java_get_item_desc_from_cp_item_list (bin->cp_list, obj, MAX_CPITEMS);
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_code_attr_calc_size(RBinJavaAttrInfo *attr) {
	RListIter *iter;
	// RListIter *iter_tmp;
	ut64 size = 0;
	if (attr) {
		// attr = r_bin_java_default_attr_new (buffer, sz, buf_offset);
		size += 6;
		// attr->info.code_attr.max_stack = R_BIN_JAVA_USHORT (buffer, 0);
		size += 2;
		// attr->info.code_attr.max_locals = R_BIN_JAVA_USHORT (buffer, 2);
		size += 2;
		// attr->info.code_attr.code_length = R_BIN_JAVA_UINT (buffer, 4);
		size += 2;
		if (attr->info.code_attr.code) {
			size += attr->info.code_attr.code_length;
		}
		// attr->info.code_attr.exception_table_length =  R_BIN_JAVA_USHORT (buffer, offset);
		size += 2;
		// RBinJavaExceptionEntry *exc_entry;
		// r_list_foreach_safe (attr->info.code_attr.exception_table, iter, iter_tmp, exc_entry) {
		r_list_foreach_iter (attr->info.code_attr.exception_table, iter) {
			// exc_entry->start_pc = R_BIN_JAVA_USHORT (buffer,offset);
			size += 2;
			// exc_entry->end_pc = R_BIN_JAVA_USHORT (buffer,offset);
			size += 2;
			// exc_entry->handler_pc = R_BIN_JAVA_USHORT (buffer,offset);
			size += 2;
			// exc_entry->catch_type = R_BIN_JAVA_USHORT (buffer, offset);
			size += 2;
		}
		// attr->info.code_attr.attributes_count = R_BIN_JAVA_USHORT (buffer, offset);
		size += 2;
		// RBinJavaAttrInfo *_attr;
		if (attr->info.code_attr.attributes_count > 0) {
			// r_list_foreach_safe (attr->info.code_attr.attributes, iter, iter_tmp, _attr) {
			r_list_foreach_iter (attr->info.code_attr.attributes, iter) {
				size += r_bin_java_attr_calc_size (attr);
			}
		}
	}
	return size;
}

Project: radare2
File: class.c

R_API RBinJavaCPTypeObj *r_bin_java_do_nothing_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz) {
	return (RBinJavaCPTypeObj *) NULL;
}

Project: radare2
File: class.c

R_API char *r_bin_java_get_item_name_from_cp_item_list(RList *cp_list, RBinJavaCPTypeObj *obj, int depth) {
	/*
	Given a constant poool object Class, FieldRef, MethodRef, or InterfaceMethodRef
	return the actual descriptor string.
	@param cp_list: RList of RBinJavaCPTypeObj *
	@param obj object to look up the name for
	@rvalue ut8* (user frees) or NULL
	*/
	if (obj == NULL || cp_list == NULL || depth < 0) {
		return NULL;
	}
	switch (obj->tag) {
	case R_BIN_JAVA_CP_NAMEANDTYPE:
		return r_bin_java_get_utf8_from_cp_item_list (
			cp_list, obj->info.cp_name_and_type.name_idx);
	case R_BIN_JAVA_CP_CLASS:
		return r_bin_java_get_utf8_from_cp_item_list (
			cp_list, obj->info.cp_class.name_idx);
	// XXX - Probably not good form, but they are the same memory structure
	case R_BIN_JAVA_CP_FIELDREF:
	case R_BIN_JAVA_CP_INTERFACEMETHOD_REF:
	case R_BIN_JAVA_CP_METHODREF:
		obj = r_bin_java_get_item_from_cp_item_list (
			cp_list, obj->info.cp_method.name_and_type_idx);
		return r_bin_java_get_item_name_from_cp_item_list (
			cp_list, obj, depth - 1);
	default:
		return NULL;
	case 0:
		IFDBG eprintf("Invalid 0 tag in the constant pool\n");
		return NULL;
	}
	return NULL;
}

Project: radare2
File: class.c

R_API void r_bin_java_print_bootstrap_method_summary(RBinJavaBootStrapMethod *bsm) {
	RBinJavaBootStrapArgument *bsm_arg = NULL;
	RListIter *iter = NULL, *iter_tmp = NULL;
	if (bsm == NULL) {
		eprintf ("Attempting to print an invalid RBinJavaBootStrapArgument *.\n");
		return;
	}
	eprintf ("Bootstrap Method Information:\n");
	eprintf ("	Offset: 0x%08"PFMT64x"", bsm->file_offset);
	eprintf ("	Method Reference Index = (0x%02x)\n", bsm->bootstrap_method_ref);
	eprintf ("	Number of Method Arguments = (0x%02x)\n", bsm->num_bootstrap_arguments);
	if (bsm->bootstrap_arguments) {
		r_list_foreach_safe (bsm->bootstrap_arguments, iter, iter_tmp, bsm_arg) {
			if (bsm_arg) {
				r_bin_java_print_bootstrap_method_argument_summary (bsm_arg);
			}
		}
	} else {
		eprintf ("	Bootstrap Method Argument: NONE \n");
	}
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_source_code_file_attr_calc_size(RBinJavaAttrInfo *attr) {
	return attr ? 8 : 0;
}

Project: radare2
File: class.c

R_API char *r_bin_java_get_field_name(RBinJavaObj *bin_obj, ut32 idx) {
	char *name = NULL;
	if (idx < r_list_length (bin_obj->fields_list)) {
		RBinJavaField *fm_type = r_list_get_n (bin_obj->fields_list, idx);
		name = strdup (fm_type->name);
	}
	return name;
}

Project: radare2
File: class.c

R_API char *r_bin_java_resolve(RBinJavaObj *BIN_OBJ, int idx, ut8 space_bn_name_type) {
	// TODO XXX FIXME add a size parameter to the str when it is passed in
	RBinJavaCPTypeObj *item = NULL, *item2 = NULL;
	char *class_str = NULL,
	*name_str = NULL,
	*desc_str = NULL,
	*string_str = NULL,
	*empty = "",
	*cp_name = NULL,
	*str = NULL;
	if (BIN_OBJ && BIN_OBJ->cp_count < 1) {
		// r_bin_java_new_bin(BIN_OBJ);
		return NULL;
	}
	item = (RBinJavaCPTypeObj *) r_bin_java_get_item_from_bin_cp_list (BIN_OBJ, idx);
	if (item) {
		cp_name = ((RBinJavaCPTypeMetas *) item->metas->type_info)->name;
		IFDBG eprintf("java_resolve Resolved: (%d) %s\n", idx, cp_name);
	} else {
		str = malloc (512);
		if (str) {
			snprintf (str, 512, "(%d) INVALID CP_OBJ", idx);
		}
		return str;
	}
	cp_name = ((RBinJavaCPTypeMetas *) item->metas->type_info)->name;
	if (strcmp (cp_name, "Class") == 0) {
		item2 = (RBinJavaCPTypeObj *) r_bin_java_get_item_from_bin_cp_list (BIN_OBJ, idx);
		// str = r_bin_java_get_name_from_bin_cp_list (BIN_OBJ, idx-1);
		class_str = empty;
		class_str = r_bin_java_get_item_name_from_bin_cp_list (BIN_OBJ, item);
		if (!class_str) {
			class_str = empty;
		}
		name_str = r_bin_java_get_item_name_from_bin_cp_list (BIN_OBJ, item2);
		if (!name_str) {
			name_str = empty;
		}
		desc_str = r_bin_java_get_item_desc_from_bin_cp_list (BIN_OBJ, item2);
		if (!desc_str) {
			desc_str = empty;
		}
		str = r_str_newf ("%s%s%s", name_str,
			space_bn_name_type ? " " : "", desc_str);
		if (class_str != empty) {
			free (class_str);
		}
		if (name_str != empty) {
			free (name_str);
		}
		if (desc_str != empty) {
			free (desc_str);
		}
	} else if (!strcmp (cp_name, "MethodRef") ||
	!strcmp (cp_name, "FieldRef") ||
	!strcmp (cp_name, "InterfaceMethodRef")) {
		/*
		*  The MethodRef, FieldRef, and InterfaceMethodRef structures
		*/
		class_str = r_bin_java_get_name_from_bin_cp_list (BIN_OBJ, item->info.cp_method.class_idx);
		if (!class_str) {
			class_str = empty;
		}
		name_str = r_bin_java_get_item_name_from_bin_cp_list (BIN_OBJ, item);
		if (!name_str) {
			name_str = empty;
		}
		desc_str = r_bin_java_get_item_desc_from_bin_cp_list (BIN_OBJ, item);
		if (!desc_str) {
			desc_str = empty;
		}
		str = r_str_newf ("%s/%s%s%s", class_str, name_str,
			space_bn_name_type ? " " : "", desc_str);
		if (class_str != empty) {
			free (class_str);
		}
		if (name_str != empty) {
			free (name_str);
		}
		if (desc_str != empty) {
			free (desc_str);
		}
	} else if (!strcmp (cp_name, "String")) {
		string_str = r_bin_java_get_utf8_from_bin_cp_list (BIN_OBJ, item->info.cp_string.string_idx);
		str = NULL;
		IFDBG eprintf("java_resolve String got: (%d) %s\n", item->info.cp_string.string_idx, string_str);
		if (!string_str) {
			string_str = empty;
		}
		str = r_str_newf ("\"%s\"", string_str);
		IFDBG eprintf("java_resolve String return: %s\n", str);
		if (string_str != empty) {
			free (string_str);
		}

	} else if (!strcmp (cp_name, "Utf8")) {
		char *tmp_str = convert_string ((const char *) item->info.cp_utf8.bytes, item->info.cp_utf8.length);
		ut32 tmp_str_len = tmp_str ? strlen (tmp_str) + 4 : 0;
		if (tmp_str) {
			str = malloc (tmp_str_len + 4);
			snprintf (str, tmp_str_len + 4, "\"%s\"", tmp_str);
		}
		free (tmp_str);
	} else if (!strcmp (cp_name, "Long")) {
		str = r_str_newf ("0x%"PFMT64x, r_bin_java_raw_to_long (item->info.cp_long.bytes.raw, 0));
	} else if (!strcmp (cp_name, "Double")) {
		str = r_str_newf ("%f", r_bin_java_raw_to_double (item->info.cp_double.bytes.raw, 0));
	} else if (!strcmp (cp_name, "Integer")) {
		str = r_str_newf ("0x%08x", R_BIN_JAVA_UINT (item->info.cp_integer.bytes.raw, 0));
	} else if (!strcmp (cp_name, "Float")) {
		str = r_str_newf ("%f", R_BIN_JAVA_FLOAT (item->info.cp_float.bytes.raw, 0));
	} else if (!strcmp (cp_name, "NameAndType")) {
		name_str = r_bin_java_get_item_name_from_bin_cp_list (BIN_OBJ, item);
		if (!name_str) {
			name_str = empty;
		}
		desc_str = r_bin_java_get_item_desc_from_bin_cp_list (BIN_OBJ, item);
		if (!desc_str) {
			desc_str = empty;
		}
		str = r_str_newf ("%s%s%s", name_str, space_bn_name_type ? " " : "", desc_str);
		if (name_str != empty) {
			free (name_str);
		}
		if (desc_str != empty) {
			free (desc_str);
		}
	} else {
		str = strdup ("(null)");
	}
	return str;
}

Project: radare2
File: class.c

R_API char *r_bin_java_get_this_class_name(RBinJavaObj *bin) {
	return (bin->cf2.this_class_name ? strdup (bin->cf2.this_class_name) : strdup ("unknown"));
}

Project: radare2
File: class.c

R_API RBinJavaAttrInfo *r_bin_java_unknown_attr_new(ut8 *buffer, ut64 sz, ut64 buf_offset) {
	return r_bin_java_default_attr_new (buffer, sz, buf_offset);
}

Project: radare2
File: class.c

R_API RBinJavaStackMapFrameMetas *r_bin_java_determine_stack_frame_type(ut8 tag) {
	ut8 type_value = 0;
	if (tag < 64) {
		type_value = R_BIN_JAVA_STACK_FRAME_SAME;
	} else if (63 < tag && tag < 128) {
		type_value = R_BIN_JAVA_STACK_FRAME_SAME_LOCALS_1;
	} else if (247 < tag && tag < 251) {
		type_value = R_BIN_JAVA_STACK_FRAME_CHOP;
	} else if (tag == 251) {
		type_value = R_BIN_JAVA_STACK_FRAME_SAME_FRAME_EXTENDED;
	} else if (251 < tag && tag < 255) {
		type_value = R_BIN_JAVA_STACK_FRAME_APPEND;
	} else if (tag == 255) {
		type_value = R_BIN_JAVA_STACK_FRAME_FULL_FRAME;
	} else {
		type_value = R_BIN_JAVA_STACK_FRAME_RESERVED;
	}
	return &R_BIN_JAVA_STACK_MAP_FRAME_METAS[type_value];
}

Project: radare2
File: class.c

R_API void r_bin_java_print_methodtype_cp_summary(RBinJavaCPTypeObj *obj) {
	if (obj == NULL) {
		eprintf ("Attempting to print an invalid RBinJavaCPTypeObj*  RBinJavaCPTypeMethodType.\n");
		return;
	}
	Eprintf ("MethodType ConstantPool Type (%d) ", obj->metas->ord);
	Eprintf ("  Offset: 0x%08"PFMT64x "", obj->file_offset);
	Eprintf ("  Descriptor Index = 0x%02x\n", obj->info.cp_method_type.descriptor_index);
}

Project: radare2
File: class.c

R_API void r_bin_java_classes_free(void /*RBinClass*/ *k) {
	RBinClass *klass = k;
	if (klass) {
		r_list_free (klass->methods);
		r_list_free (klass->fields);
		free (klass->name);
		free (klass->super);
		free (klass->visibility_str);
		free (klass);
	}
}

Project: radare2
File: class.c

R_API void r_bin_java_inner_classes_attr_entry_free(void /*RBinJavaClassesAttribute*/ *a) {
	RBinJavaClassesAttribute *attr = a;
	if (attr) {
		free (attr->name);
		free (attr->flags_str);
		free (attr);
	}
}

Project: radare2
File: class.c

R_API DsoJsonObj *r_bin_java_get_fm_type_definition_json(RBinJavaObj *bin, RBinJavaField *fm_type, int is_method) {
	ut64 addr = UT64_MAX;
	char *prototype = NULL, *fq_name = NULL;
	bool is_native = ((fm_type->flags & R_BIN_JAVA_METHOD_ACC_NATIVE) != 0);
	bool is_static = ((fm_type->flags & R_BIN_JAVA_METHOD_ACC_STATIC) != 0);
	bool is_synthetic = ((fm_type->flags & R_BIN_JAVA_METHOD_ACC_SYNTHETIC) != 0);
	bool is_private = ((fm_type->flags & R_BIN_JAVA_METHOD_ACC_PRIVATE) != 0);
	bool is_public = ((fm_type->flags & R_BIN_JAVA_METHOD_ACC_PUBLIC) != 0);
	bool is_protected = ((fm_type->flags & R_BIN_JAVA_METHOD_ACC_PROTECTED) != 0);
	bool is_super = ((fm_type->flags & R_BIN_JAVA_CLASS_ACC_SUPER) != 0);

	DsoJsonObj *fm_type_dict = dso_json_dict_new ();
	dso_json_dict_insert_str_key_num (fm_type_dict, "access_flags", fm_type->flags);
	dso_json_dict_insert_str_key_num (fm_type_dict, "is_method", is_method);
	dso_json_dict_insert_str_key_num (fm_type_dict, "is_native", is_native);
	dso_json_dict_insert_str_key_num (fm_type_dict, "is_synthetic", is_synthetic);
	dso_json_dict_insert_str_key_num (fm_type_dict, "is_private", is_private);
	dso_json_dict_insert_str_key_num (fm_type_dict, "is_public", is_public);
	dso_json_dict_insert_str_key_num (fm_type_dict, "is_static", is_static);
	dso_json_dict_insert_str_key_num (fm_type_dict, "is_protected", is_protected);
	dso_json_dict_insert_str_key_num (fm_type_dict, "is_super", is_super);

	addr = r_bin_java_get_method_code_offset (fm_type);
	if (addr == 0) {
		addr = fm_type->file_offset;
	}
	addr += bin->loadaddr;

	dso_json_dict_insert_str_key_num (fm_type_dict, "addr", addr);
	dso_json_dict_insert_str_key_num (fm_type_dict, "offset", fm_type->file_offset + bin->loadaddr);
	dso_json_dict_insert_str_key_str (fm_type_dict, "class_name", fm_type->class_name);
	dso_json_dict_insert_str_key_str (fm_type_dict, "signature", fm_type->descriptor);
	dso_json_dict_insert_str_key_str (fm_type_dict, "name", fm_type->name);

	if (is_method) {
		fq_name = r_bin_java_create_method_fq_str (fm_type->class_name, fm_type->name, fm_type->descriptor);
	} else {
		fq_name = r_bin_java_create_field_fq_str (fm_type->class_name, fm_type->name, fm_type->descriptor);
	}
	dso_json_dict_insert_str_key_str (fm_type_dict, "fq_name", fq_name);

	prototype = r_bin_java_unmangle (fm_type->flags_str, fm_type->name, fm_type->descriptor);
	dso_json_dict_insert_str_key_str (fm_type_dict, "prototype", prototype);
	free (prototype);
	free (fq_name);
	return fm_type_dict;
}

Project: radare2
File: class.c

R_API void r_bin_java_element_pair_free(void /*RBinJavaElementValuePair*/ *e) {
	RBinJavaElementValuePair *ev_pair = e;
	if (ev_pair) {
		free (ev_pair->name);
		r_bin_java_element_value_free (ev_pair->value);
		free (ev_pair);
	}
	ev_pair = NULL;
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_local_variable_table_attr_calc_size(RBinJavaAttrInfo *attr) {
	ut64 size = 0;
	// ut64 offset = 0;
	RListIter *iter;
	// RBinJavaLocalVariableAttribute *lvattr;
	if (!attr) {
		return 0LL;
	}
	size += 6;
	// attr->info.local_variable_table_attr.table_length = R_BIN_JAVA_USHORT (buffer, offset);
	size += 2;
	// r_list_foreach (attr->info.local_variable_table_attr.local_variable_table, iter, lvattr) {
	r_list_foreach_iter (attr->info.local_variable_table_attr.local_variable_table, iter) {
		// lvattr->start_pc = R_BIN_JAVA_USHORT (buffer, offset);
		size += 2;
		// lvattr->length = R_BIN_JAVA_USHORT (buffer, offset);
		size += 2;
		// lvattr->name_idx = R_BIN_JAVA_USHORT (buffer, offset);
		size += 2;
		// lvattr->descriptor_idx = R_BIN_JAVA_USHORT (buffer, offset);
		size += 2;
		// lvattr->index = R_BIN_JAVA_USHORT (buffer, offset);
		size += 2;
	}
	return size;
}

Project: radare2
File: class.c

R_API void r_bin_java_print_field_summary(RBinJavaField *field) {
	RBinJavaAttrInfo *attr;
	RListIter *iter, *iter_tmp;
	if (field) {
		if (field->type == R_BIN_JAVA_FIELD_TYPE_METHOD) {
			r_bin_java_print_method_summary (field);
		} else {
#if 0
			r_bin_java_print_interface_summary (field);
			return;
		} * /
#endif
			Eprintf ("Field Summary Information:\n");
			Eprintf ("  File Offset: 0x%08"PFMT64x "\n", field->file_offset);
			Eprintf ("  Name Index: %d (%s)\n", field->name_idx, field->name);
			Eprintf ("  Descriptor Index: %d (%s)\n", field->descriptor_idx, field->descriptor);
			Eprintf ("  Access Flags: 0x%02x (%s)\n", field->flags, field->flags_str);
			Eprintf ("  Field Attributes Count: %d\n", field->attr_count);
			Eprintf ("  Field Attributes:\n");
			r_list_foreach_safe (field->attributes, iter, iter_tmp, attr) {
				r_bin_java_print_attr_summary (attr);
			}
		}
	} else {

Project: radare2
File: class.c

R_API ut8 r_bin_java_does_cp_idx_ref_method(RBinJavaObj *BIN_OBJ, int idx) {
	RBinJavaField *fm_type = NULL;
	RListIter *iter;
	ut8 res = 0;
	r_list_foreach (BIN_OBJ->methods_list, iter, fm_type) {
		if (fm_type->field_ref_cp_obj->metas->ord == idx) {
			res = 1;
			break;
		}
	}
	return res;
}

Project: radare2
File: class.c

R_API RBinJavaElementValueMetas *r_bin_java_get_ev_meta_from_tag(ut8 tag) {
	ut16 i = 0;
	RBinJavaElementValueMetas *res = &R_BIN_JAVA_ELEMENT_VALUE_METAS[13];
	for (i = 0; i < R_BIN_JAVA_ELEMENT_VALUE_METAS_SZ; i++) {
		if (tag == R_BIN_JAVA_ELEMENT_VALUE_METAS[i].tag) {
			res = &R_BIN_JAVA_ELEMENT_VALUE_METAS[i];
			break;
		}
	}
	return res;
}

Project: radare2
File: class.c

R_API void r_bin_java_print_attr_summary(RBinJavaAttrInfo *attr) {
	if (attr == NULL) {
		eprintf ("Attempting to print an invalid RBinJavaAttrInfo *.\n");
		return;
	}
	((RBinJavaAttrMetas *) attr->metas->type_info)->allocs->print_summary (attr);
}

Project: radare2
File: class.c

R_API ut16 r_bin_java_calculate_class_access_value(const char *access_flags_str) {
	return calculate_access_value (access_flags_str, CLASS_ACCESS_FLAGS);
}

Project: radare2
File: class.c

R_API void r_bin_java_obj_free(void /*RBinJavaCPTypeObj*/ *o) {
	RBinJavaCPTypeObj *obj = o;
	((RBinJavaCPTypeMetas *) obj->metas->type_info)->allocs->delete_obj (obj);
}

Project: radare2
File: class.c

R_API ut8 *r_bin_java_cp_get_utf8(ut8 tag, ut32 *out_sz, const ut8 *buf, const ut64 len) {
	ut8 *buffer = NULL;
	ut16 sz = 0;
	ut16 t = (ut16) len;
	if (len > 0 && len > (ut16) - 1) {
		*out_sz = 0;
		return NULL;
	}
	sz = R_BIN_JAVA_USHORT (((ut8 *) (ut16 *) &t), 0);
	*out_sz = 3 + t; // tag + sz + bytes
	buffer = malloc (*out_sz + 3);
	if (!buffer) {
		return NULL;
	}
	// XXX - excess bytes are created to ensure null for string operations.
	memset (buffer, 0, *out_sz + 3);
	buffer[0] = tag;
	memcpy (buffer + 1, (const char *) &sz, 2);
	memcpy (buffer + 3, buf, *out_sz - 3);
	return buffer;
}

Project: radare2
File: class.c

R_API char *r_bin_java_resolve_b64_encode(RBinJavaObj *BIN_OBJ, ut16 idx) {
	RBinJavaCPTypeObj *item = NULL, *item2 = NULL;
	char *class_str = NULL,
	*name_str = NULL,
	*desc_str = NULL,
	*string_str = NULL,
	*empty = "",
	*cp_name = NULL,
	*str = NULL, *out = NULL;
	int memory_alloc = 0;
	if (BIN_OBJ && BIN_OBJ->cp_count < 1) {
		// r_bin_java_new_bin(BIN_OBJ);
		return NULL;
	}
	item = (RBinJavaCPTypeObj *) r_bin_java_get_item_from_bin_cp_list (BIN_OBJ, idx);
	if (item) {
		cp_name = ((RBinJavaCPTypeMetas *) item->metas->type_info)->name;
		IFDBG eprintf("java_resolve Resolved: (%d) %s\n", idx, cp_name);
	} else {
		return NULL;
	}
	cp_name = ((RBinJavaCPTypeMetas *) item->metas->type_info)->name;
	if (!strcmp (cp_name, "Class")) {
		item2 = (RBinJavaCPTypeObj *) r_bin_java_get_item_from_bin_cp_list (BIN_OBJ, idx);
		// str = r_bin_java_get_name_from_bin_cp_list (BIN_OBJ, idx-1);
		class_str = empty;
		class_str = r_bin_java_get_item_name_from_bin_cp_list (BIN_OBJ, item);
		if (!class_str) {
			class_str = empty;
		}
		name_str = r_bin_java_get_item_name_from_bin_cp_list (BIN_OBJ, item2);
		if (!name_str) {
			name_str = empty;
		}
		desc_str = r_bin_java_get_item_desc_from_bin_cp_list (BIN_OBJ, item2);
		if (!desc_str) {
			desc_str = empty;
		}
		memory_alloc = strlen (class_str) + strlen (name_str) + strlen (desc_str) + 3;
		if (memory_alloc) {
			str = malloc (memory_alloc);
			snprintf (str, memory_alloc, "%s%s", name_str, desc_str);
			out = (char *) malloc (memory_alloc);
			memset (out, 0, memory_alloc);
			r_base64_encode (out, (const ut8 *) str, strlen (str));
			free (str);
			str = out;
		}
		if (class_str != empty) {
			free (class_str);
		}
		if (name_str != empty) {
			free (name_str);
		}
		if (desc_str != empty) {
			free (desc_str);
		}
	} else if (strcmp (cp_name, "MethodRef") == 0 ||
	strcmp (cp_name, "FieldRef") == 0 ||
	strcmp (cp_name, "InterfaceMethodRef") == 0) {
		/*
		*  The MethodRef, FieldRef, and InterfaceMethodRef structures
		*/
		class_str = r_bin_java_get_name_from_bin_cp_list (BIN_OBJ, item->info.cp_method.class_idx);
		if (!class_str) {
			class_str = empty;
		}
		name_str = r_bin_java_get_item_name_from_bin_cp_list (BIN_OBJ, item);
		if (!name_str) {
			name_str = empty;
		}
		desc_str = r_bin_java_get_item_desc_from_bin_cp_list (BIN_OBJ, item);
		if (!desc_str) {
			desc_str = empty;
		}
		memory_alloc = strlen (class_str) + strlen (name_str) + strlen (desc_str) + 3;
		if (memory_alloc) {
			str = malloc (memory_alloc);
			snprintf (str, memory_alloc, "%s/%s%s", class_str, name_str, desc_str);
			out = malloc (memory_alloc);
			memset (out, 0, memory_alloc);
			r_base64_encode (out, (const ut8 *) str, strlen (str));
			free (str);
			str = out;
		}
		if (class_str != empty) {
			free (class_str);
		}
		if (name_str != empty) {
			free (name_str);
		}
		if (desc_str != empty) {
			free (desc_str);
		}
	} else if (strcmp (cp_name, "String") == 0) {
		ut32 length = r_bin_java_get_utf8_len_from_bin_cp_list (BIN_OBJ, item->info.cp_string.string_idx);
		string_str = r_bin_java_get_utf8_from_bin_cp_list (BIN_OBJ, item->info.cp_string.string_idx);
		str = NULL;
		IFDBG eprintf("java_resolve String got: (%d) %s\n", item->info.cp_string.string_idx, string_str);
		if (!string_str) {
			string_str = empty;
			length = strlen (empty);
		}
		memory_alloc = length + 3;
		if (memory_alloc) {
			str = malloc (memory_alloc);
			snprintf (str, memory_alloc, "\"%s\"", string_str);
			out = malloc (memory_alloc);
			memset (out, 0, memory_alloc);
			r_base64_encode (out, (const ut8 *) str, strlen (str));
			free (str);
			str = out;
		}
		IFDBG eprintf("java_resolve String return: %s\n", str);
		if (string_str != empty) {
			free (string_str);
		}
	} else if (strcmp (cp_name, "Utf8") == 0) {
		ut64 sz = item->info.cp_utf8.length ? item->info.cp_utf8.length + 10 : 10;
		str = malloc (sz);
		memset (str, 0, sz);
		if (sz > 10) {
			r_base64_encode (str, item->info.cp_utf8.bytes, item->info.cp_utf8.length);
		}
	} else if (strcmp (cp_name, "Long") == 0) {
		str = malloc (34);
		out = malloc (34);
		memset (out, 0, 34);
		if (str) {
			snprintf (str, 34, "0x%"PFMT64x, r_bin_java_raw_to_long (item->info.cp_long.bytes.raw, 0));
			r_base64_encode (out, (const ut8 *) str, strlen (str));
			free (str);
			str = out;
		}
	} else if (strcmp (cp_name, "Double") == 0) {
		str = malloc (1000);
		out = malloc (1000);
		memset (out, 0, 1000);
		if (str) {
			snprintf (str, 1000, "%f", r_bin_java_raw_to_double (item->info.cp_double.bytes.raw, 0));
			r_base64_encode (out, (const ut8 *) str, strlen (str));
			free (str);
			str = out;
		}
	} else if (strcmp (cp_name, "Integer") == 0) {
		str = calloc (34, 1);
		out = calloc (34, 1);
		if (str) {
			snprintf (str, 34, "0x%08x", R_BIN_JAVA_UINT (item->info.cp_integer.bytes.raw, 0));
			r_base64_encode (out, (const ut8 *) str, strlen (str));
			free (str);
			str = out;
		}
	} else if (strcmp (cp_name, "Float") == 0) {
		str = malloc (34);
		out = malloc (34);
		memset (out, 0, 34);
		if (str) {
			snprintf (str, 34, "%f", R_BIN_JAVA_FLOAT (item->info.cp_float.bytes.raw, 0));
			r_base64_encode (out, (const ut8 *) str, strlen (str));
			free (str);
			str = out;
		}
	} else if (!strcmp (cp_name, "NameAndType")) {
		name_str = r_bin_java_get_item_name_from_bin_cp_list (BIN_OBJ, item);
		if (!name_str) {
			name_str = empty;
		}
		desc_str = r_bin_java_get_item_desc_from_bin_cp_list (BIN_OBJ, item);
		if (!desc_str) {
			desc_str = empty;
		}
		memory_alloc = strlen (name_str) + strlen (desc_str) + 3;
		if (memory_alloc) {
			str = malloc (memory_alloc);
			snprintf (str, memory_alloc, "%s %s", name_str, desc_str);
			out = malloc (memory_alloc);
			memset (out, 0, memory_alloc);
			r_base64_encode (out, (const ut8 *) str, strlen (str));
			free (str);
			str = out;
		}
		if (name_str != empty) {
			free (name_str);
		}
		if (desc_str != empty) {
			free (desc_str);
		}
	} else {
		str = malloc (16);
		memset (str, 0, 16);
		if (str) {
			r_base64_encode (str, (const ut8 *) "(null)", 6);
		}
	}
	return str;
}

Project: radare2
File: class.c

R_API void r_bin_java_print_utf8_cp_summary(RBinJavaCPTypeObj *obj) {
	if (obj == NULL) {
		eprintf ("Attempting to print an invalid RBinJavaCPTypeObj*  Utf8.\n");
		return;
	}
	char *str = convert_string ((const char *) obj->info.cp_utf8.bytes, obj->info.cp_utf8.length);
	eprintf ("UTF8 ConstantPool Type (%d) ", obj->metas->ord);
	eprintf ("	Offset: 0x%08"PFMT64x"", obj->file_offset);
	eprintf ("	length = %d\n", obj->info.cp_utf8.length);
	eprintf ("	utf8 = %s\n", str);
	free (str);
}

Project: radare2
File: class.c

R_API void r_bin_java_print_unknown_cp_summary(RBinJavaCPTypeObj *obj) {
	eprintf ("NULL ConstantPool Type.\n");
}

Project: radare2
File: class.c

R_API RList *r_bin_java_get_method_offsets(RBinJavaObj *bin) {
	RBinJavaField *fm_type = NULL;
	RList *the_list = r_list_new ();
	RListIter *iter = NULL;
	ut64 *paddr = NULL;
	if (!bin) {
		return the_list;
	}
	the_list->free = free;
	r_list_foreach (bin->methods_list, iter, fm_type) {
		paddr = R_NEW0 (ut64);
		*paddr = fm_type->file_offset + bin->loadaddr;
		r_list_append (the_list, paddr);
	}
	return the_list;
}

Project: radare2
File: class.c

R_API ut8 r_bin_java_quick_check(ut8 expected_tag, ut8 actual_tag, ut32 actual_len, const char *name) {
	ut8 res = 0;
	if (expected_tag > R_BIN_JAVA_CP_METAS_SZ) {
		eprintf ("Invalid tag '%d' expected 0x%02x for %s.\n", actual_tag, expected_tag, name);
		res = 1;
	} else if (expected_tag != actual_tag)  {
		eprintf ("Invalid tag '%d' expected 0x%02x for %s.\n", actual_tag, expected_tag, name);
		res = 1;
	} else if (actual_len < R_BIN_JAVA_CP_METAS[expected_tag].len)  {
		eprintf ("Unable to parse '%d' expected sz=0x%02x got 0x%02x for %s.\n",
			actual_tag, R_BIN_JAVA_CP_METAS[expected_tag].len, actual_len, name);
		res = 2;
	}
	return res;
}

Project: radare2
File: class.c

R_API RList *r_bin_java_find_cp_const_by_val_long(RBinJavaObj *bin_obj, const ut8 *bytes, ut32 len) {
	RList *res = r_list_newf (free);
	ut32 *v = NULL;
	RListIter *iter;
	RBinJavaCPTypeObj *cp_obj;
	eprintf ("Looking for 0x%08x\n", R_BIN_JAVA_UINT (bytes, 0));
	r_list_foreach (bin_obj->cp_list, iter, cp_obj) {
		if (cp_obj->tag == R_BIN_JAVA_CP_LONG) {
			if (len == 8 && r_bin_java_raw_to_long (cp_obj->info.cp_long.bytes.raw, 0) == r_bin_java_raw_to_long (bytes, 0)) {
				// TODO: we can safely store a ut32 inside the list without having to allocate it
				v = malloc (sizeof (ut32));
				if (!v) {
					r_list_free (res);
					return NULL;
				}
				*v = cp_obj->idx;
				r_list_append (res, v);
			}
		}
	}
	return res;
}

Project: radare2
File: class.c

R_API char *r_bin_java_print_methodtype_cp_stringify(RBinJavaCPTypeObj *obj) {
	ut32 size = 255, consumed = 0;
	char *value = malloc (size);
	if (value) {
		memset (value, 0, size);
		consumed = snprintf (value, size, "%d.0x%04"PFMT64x ".%s.%d",
			obj->metas->ord, obj->file_offset + obj->loadaddr, ((RBinJavaCPTypeMetas *) obj->metas->type_info)->name,
			obj->info.cp_method_type.descriptor_index);
		if (consumed >= size - 1) {
			free (value);
			size += size >> 1;
			value = malloc (size);
			if (value) {
				memset (value, 0, size);
				consumed = snprintf (value, size, "%d.0x%04"PFMT64x ".%s.%d",
					obj->metas->ord, obj->file_offset + obj->loadaddr, ((RBinJavaCPTypeMetas *) obj->metas->type_info)->name,
					obj->info.cp_method_type.descriptor_index);
			}
		}
	}
	return value;
}

Project: radare2
File: class.c

R_API char *r_bin_java_get_version(RBinJavaObj *bin) {
	return r_str_newf ("0x%02x%02x 0x%02x%02x",
		bin->cf.major[1], bin->cf.major[0],
		bin->cf.minor[1], bin->cf.minor[0]);
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_fieldref_cp_calc_size(RBinJavaCPTypeObj *obj) {
	ut64 size = 0;
	// tag
	size += 1;
	// obj->info.cp_field.class_idx = R_BIN_JAVA_USHORT (buffer, 1);
	size += 2;
	// obj->info.cp_field.name_and_type_idx = R_BIN_JAVA_USHORT (buffer, 3);
	size += 2;
	return size;
}

Project: radare2
File: class.c

R_API void U(deinit_java_type_null)() {
	free (R_BIN_JAVA_NULL_TYPE.metas);
}

Project: radare2
File: class.c

R_API char *r_bin_java_print_methodhandle_cp_stringify(RBinJavaCPTypeObj *obj) {
	ut32 size = 255, consumed = 0;
	char *value = malloc (size);
	ut8 ref_kind = obj->info.cp_method_handle.reference_kind;
	if (value) {
		memset (value, 0, size);
		consumed = snprintf (value, size, "%d.0x%04"PFMT64x ".%s.%s.%d",
			obj->metas->ord, obj->file_offset + obj->loadaddr, ((RBinJavaCPTypeMetas *) obj->metas->type_info)->name,
			R_BIN_JAVA_REF_METAS[ref_kind].name, obj->info.cp_method_handle.reference_index);
		if (consumed >= size - 1) {
			free (value);
			size += size >> 1;
			value = malloc (size);
			if (value) {
				memset (value, 0, size);
				consumed = snprintf (value, size, "%d.0x%04"PFMT64x ".%s.%s.%d",
					obj->metas->ord, obj->file_offset + obj->loadaddr, ((RBinJavaCPTypeMetas *) obj->metas->type_info)->name,
					R_BIN_JAVA_REF_METAS[ref_kind].name, obj->info.cp_method_handle.reference_index);
			}
		}
	}
	return value;
}

Project: radare2
File: class.c

R_API int U(r_bin_java_is_method_protected)(RBinJavaObj * bin_obj, ut64 addr) {
	return r_bin_java_is_fm_type_protected (
		r_bin_java_get_method_code_attribute_with_addr (bin_obj, addr));
}

Project: radare2
File: class.c

R_API void r_bin_java_line_number_table_attr_free(void /*RBinJavaAttrInfo*/ *a) {
	RBinJavaAttrInfo *attr = a;
	if (attr) {
		free (attr->name);
		free (attr->metas);
		r_list_free (attr->info.line_number_table_attr.line_number_table);
		free (attr);
	}
}

Project: radare2
File: class.c

R_API RList *U(r_bin_java_get_fields)(RBinJavaObj * bin) {
	RListIter *iter = NULL, *iter_tmp = NULL;
	RList *fields = r_list_new ();
	RBinJavaField *fm_type;
	RBinField *field;
	r_list_foreach_safe (bin->fields_list, iter, iter_tmp, fm_type) {
		field = r_bin_java_create_new_rbinfield_from_field (fm_type, bin->loadaddr);
		if (field) {
			r_list_append (fields, field);
		}
	}
	return fields;
}

Project: radare2
File: class.c

R_API void r_bin_java_print_element_pair_summary(RBinJavaElementValuePair *ev_pair) {
	if (!ev_pair) {
		eprintf ("Attempting to print an invalid RBinJavaElementValuePair *pair.\n");
		return;
	}
	Eprintf ("Element Value Pair information:\n");
	Eprintf ("  EV Pair File Offset: 0x%08"PFMT64x "\n", ev_pair->file_offset);
	Eprintf ("  EV Pair Element Name index: 0x%02x\n", ev_pair->element_name_idx);
	Eprintf ("  EV Pair Element Name: %s\n", ev_pair->name);
	Eprintf ("  EV Pair Element Value:\n");
	r_bin_java_print_element_value_summary (ev_pair->value);
}

Project: radare2
File: class.c

R_API const RList *r_bin_java_get_methods_list(RBinJavaObj *bin) {
	if (bin) {
		return bin->methods_list;
	}
	if (R_BIN_JAVA_GLOBAL_BIN) {
		return R_BIN_JAVA_GLOBAL_BIN->methods_list;
	}
	return NULL;
}

Project: radare2
File: class.c

R_API ut32 r_bin_java_cp_get_size(RBinJavaObj *bin, ut16 idx) {
	RBinJavaCPTypeObj *cp_obj = r_bin_java_get_item_from_bin_cp_list (bin, idx);
	switch (cp_obj->tag) {
	case R_BIN_JAVA_CP_INTEGER:
	case R_BIN_JAVA_CP_FLOAT:
		return 1 + 4;
	case R_BIN_JAVA_CP_LONG:
	case R_BIN_JAVA_CP_DOUBLE:
		return 1 + 8;
	case R_BIN_JAVA_CP_UTF8:
		return 1 + 2 + cp_obj->info.cp_utf8.length;
	}
	return 0;
}

Project: radare2
File: class.c

R_API void r_bin_java_local_variable_table_attr_entry_free(void /*RBinJavaLocalVariableAttribute*/ *a) {
	RBinJavaLocalVariableAttribute *lvattr = a;
	if (lvattr) {
		free (lvattr->descriptor);
		free (lvattr->name);
		free (lvattr);
	}
}

Project: radare2
File: class.c

R_API RBinJavaObj *r_bin_java_new(const char *file, ut64 loadaddr, Sdb *kv) {
	ut8 *buf;
	RBinJavaObj *bin = R_NEW0 (RBinJavaObj);
	if (!bin) {
		return NULL;
	}
	bin->file = strdup (file);
	if (!(buf = (ut8 *) r_file_slurp (file, &bin->size))) {
		return r_bin_java_free (bin);
	}
	if (!r_bin_java_new_bin (bin, loadaddr, kv, buf, bin->size)) {
		r_bin_java_free (bin);
		bin = NULL;
	}
	free (buf);
	return bin;
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_line_number_table_attr_calc_size(RBinJavaAttrInfo *attr) {
	ut64 size = 6;
	// RBinJavaLineNumberAttribute *lnattr;
	RListIter *iter;
	// RListIter *iter_tmp;
	if (!attr) {
		return 0LL;
	}
	// r_list_foreach_safe (attr->info.line_number_table_attr.line_number_table, iter, iter_tmp, lnattr) {
	r_list_foreach_iter (attr->info.line_number_table_attr.line_number_table, iter) {
		// lnattr->start_pc = R_BIN_JAVA_USHORT (buffer, offset);
		size += 2;
		// lnattr->line_number = R_BIN_JAVA_USHORT (buffer, offset);
		size += 2;
	}
	return size;
}

Project: radare2
File: class.c

R_API RList *retrieve_all_class_access_string_and_value() {
	return retrieve_all_access_string_and_value (CLASS_ACCESS_FLAGS);
}

Project: radare2
File: class.c

R_API void r_bin_java_print_line_number_attr_summary(RBinJavaLineNumberAttribute *lnattr) {
	if (!lnattr) {
		eprintf ("Attempting to print an invalid RBinJavaLineNumberAttribute *.\n");
		return;
	}
	Eprintf ("  Line Number Attribute Offset: 0x%08"PFMT64x "\n", lnattr->file_offset);
	Eprintf ("  Line Number Attribute StartPC: %d\n", lnattr->start_pc);
	Eprintf ("  Line Number Attribute LineNumber: %d\n", lnattr->line_number);
}

Project: radare2
File: class.c

R_API void r_bin_java_print_local_variable_table_attr_summary(RBinJavaAttrInfo *attr) {
	RBinJavaLocalVariableAttribute *lvattr;
	RListIter *iter, *iter_tmp;
	if (attr == NULL) {
		eprintf ("Attempting to print an invalid RBinJavaAttrInfo *LocalVariableTable.\n");
		return;
	}
	Eprintf ("Local Variable Table Attribute Information:\n");
	Eprintf ("  Attribute Offset: 0x%08"PFMT64x "\n", attr->file_offset);
	Eprintf ("  Attribute Name Index: %d (%s)\n", attr->name_idx, attr->name);
	Eprintf ("  Attribute Length: %d\n", attr->length);
	r_list_foreach_safe (attr->info.local_variable_table_attr.local_variable_table, iter, iter_tmp, lvattr) {
		r_bin_java_print_local_variable_attr_summary (lvattr);
	}
}

Project: radare2
File: class.c

R_API RList *r_bin_java_get_method_exception_table_with_addr(RBinJavaObj *bin, ut64 addr) {
	RListIter *iter = NULL, *iter_tmp = NULL;
	RBinJavaField *fm_type, *res = NULL;
	if (!bin && R_BIN_JAVA_GLOBAL_BIN) {
		bin = R_BIN_JAVA_GLOBAL_BIN;
	}
	if (!bin) {
		eprintf ("Attempting to analyse function when the R_BIN_JAVA_GLOBAL_BIN has not been set.\n");
		return NULL;
	}
	r_list_foreach_safe (bin->methods_list, iter, iter_tmp, fm_type) {
		ut64 offset = r_bin_java_get_method_code_offset (fm_type) + bin->loadaddr,
		size = r_bin_java_get_method_code_size (fm_type);
		if (addr >= offset && addr <= size + offset) {
			res = fm_type;
		}
	}
	if (res) {
		RBinJavaAttrInfo *code_attr = r_bin_java_get_method_code_attribute (res);
		return code_attr->info.code_attr.exception_table;
	}
	return NULL;
}

Project: radare2
File: class.c

R_API RBinJavaAttrInfo *r_bin_java_bootstrap_methods_attr_new(ut8 *buffer, ut64 sz, ut64 buf_offset) {
	ut32 i = 0;
	RBinJavaBootStrapMethod *bsm = NULL;
	ut64 offset = 0;
	RBinJavaAttrInfo *attr = r_bin_java_default_attr_new (buffer, sz, buf_offset);
	offset += 6;
	if (attr) {
		attr->type = R_BIN_JAVA_ATTR_TYPE_BOOTSTRAP_METHODS_ATTR;
		attr->info.bootstrap_methods_attr.num_bootstrap_methods = R_BIN_JAVA_USHORT (buffer, offset);
		offset += 2;
		attr->info.bootstrap_methods_attr.bootstrap_methods = r_list_newf (r_bin_java_bootstrap_method_free);
		for (i = 0; i < attr->info.bootstrap_methods_attr.num_bootstrap_methods; i++) {
			// bsm = r_bin_java_bootstrap_method_new (bin, bin->b->cur);
			bsm = r_bin_java_bootstrap_method_new (buffer + offset, sz - offset, buf_offset + offset);
			if (bsm) {
				offset += bsm->size;
				r_list_append (attr->info.bootstrap_methods_attr.bootstrap_methods, (void *) bsm);
			} else {
				// TODO eprintf Failed to read the %d boot strap method.
			}
		}
		attr->size = offset;
	}
	return attr;
}

Project: radare2
File: class.c

R_API RList *r_bin_java_get_args(RBinJavaField *fm_type) {
	RList *the_list = r_bin_java_extract_type_values (fm_type->descriptor);
	RList *arg_list = r_list_new ();
	ut8 in_args = 0;
	RListIter *desc_iter;
	char *str;
	r_list_foreach (the_list, desc_iter, str) {
		if (str && *str == '(') {
			in_args = 1;
			continue;
		}
		if (str && *str == ')') {
			break;
		}
		if (in_args) {
			r_list_append (arg_list, strdup (str));
		}
	}
	r_list_free (the_list);
	return arg_list;
}

Project: radare2
File: class.c

R_API void r_bin_java_print_rti_annotations_attr_summary(RBinJavaAttrInfo *attr) {
	if (attr && attr->type == R_BIN_JAVA_ATTR_TYPE_RUNTIME_INVISIBLE_ANNOTATION_ATTR) {
		Eprintf ("Runtime Invisible Annotations Attribute Information:\n");
		Eprintf ("   Attribute Offset: 0x%08"PFMT64x "\n", attr->file_offset);
		Eprintf ("   Attribute Name Index: %d (%s)\n", attr->name_idx, attr->name);
		Eprintf ("   Attribute Length: %d\n", attr->length);
		r_bin_java_print_annotation_array_summary (&attr->info.annotation_array);
	}
}

Project: radare2
File: class.c

R_API void U(add_method_infos_to_sdb)(RBinJavaObj * bin) {
	/*
	*** Experimental and May Change ***
	Add Mehtod information to an Array
	the key for this info variable depenedent on addr, method ordinal, etc.
	Key 1, mapping to method key:
	java.<file_offset> = <method_key>
	Key 2, basic code information
	<method_key>.code = [<addr>, <size>]
	Key 3, method description
	<method_key>.info = [<access str>, <class_name>, <name>, <signature>,]
	key 4, method meta
	<method_key>.meta = [<file_offset>, ?]
	// TODO in key 3 add <class_name>?
	e.g. <access str>.<name>.<signature>
	Note: method name not used because of collisions with operator overloading
	also take note that code offset and the method offset are not the same
	values.
	*/
	RListIter *iter = NULL, *iter_tmp = NULL;
	RBinJavaField *fm_type;
	ut32 key_size = 255,
	value_buffer_size = 1024,
	class_name_inheap = 1;
	char *method_key = NULL,
	*method_key_value = NULL,
	*value_buffer = NULL;
	char *class_name = r_bin_java_get_this_class_name (bin);
	ut64 baddr = bin->loadaddr;
	if (class_name == NULL) {
		class_name = "unknown";
		class_name_inheap = 0;
	}
	key_size += strlen (class_name);
	value_buffer_size += strlen (class_name);
	method_key = malloc (key_size);
	value_buffer = malloc (value_buffer_size);
	method_key_value = malloc (key_size);
	snprintf (method_key, key_size, "%s.methods", class_name);
	method_key[key_size - 1] = 0;
	r_list_foreach_safe (bin->methods_list, iter, iter_tmp, fm_type) {
		char number_buffer[80];
		ut64 file_offset = fm_type->file_offset + baddr;
		snprintf (number_buffer, sizeof (number_buffer), "0x%04"PFMT64x, file_offset);
		sdb_array_push (bin->kv, method_key, number_buffer, 0);
	}
	r_list_foreach_safe (bin->methods_list, iter, iter_tmp, fm_type) {
		ut64 code_offset = r_bin_java_get_method_code_offset (fm_type) + baddr,
		code_size = r_bin_java_get_method_code_size (fm_type),
		method_offset = fm_type->file_offset + baddr;
		// generate method specific key & value
		snprintf (method_key, key_size, "%s.0x%04"PFMT64x, class_name, code_offset);
		method_key[key_size - 1] = 0;
		snprintf (method_key_value, key_size, "%s.0x%04"PFMT64x ".method", class_name, method_offset);
		method_key_value[key_size - 1] = 0;
		IFDBG eprintf("Adding %s to sdb_array: %s\n", method_key_value, method_key);
		sdb_set (bin->kv, method_key, method_key_value, 0);
		// generate code key and values
		snprintf (method_key, key_size, "%s.code", method_key_value);
		method_key[key_size - 1] = 0;
		snprintf (value_buffer, value_buffer_size, "0x%04"PFMT64x, code_offset);
		value_buffer[value_buffer_size - 1] = 0;
		sdb_array_push (bin->kv, method_key, value_buffer, 0);
		snprintf (value_buffer, value_buffer_size, "0x%04"PFMT64x, code_size);
		value_buffer[value_buffer_size - 1] = 0;
		sdb_array_push (bin->kv, method_key, value_buffer, 0);
		// generate info key, and place values in method info array
		snprintf (method_key, key_size, "%s.info", method_key_value);
		method_key[key_size - 1] = 0;
		snprintf (value_buffer, value_buffer_size, "%s", fm_type->flags_str);
		value_buffer[value_buffer_size - 1] = 0;
		IFDBG eprintf("Adding %s to sdb_array: %s\n", value_buffer, method_key);
		sdb_array_push (bin->kv, method_key, value_buffer, 0);
		snprintf (value_buffer, value_buffer_size, "%s", fm_type->class_name);
		value_buffer[value_buffer_size - 1] = 0;
		IFDBG eprintf("Adding %s to sdb_array: %s\n", value_buffer, method_key);
		sdb_array_push (bin->kv, method_key, value_buffer, 0);
		snprintf (value_buffer, value_buffer_size, "%s", fm_type->name);
		value_buffer[value_buffer_size - 1] = 0;
		IFDBG eprintf("Adding %s to sdb_array: %s\n", value_buffer, method_key);
		sdb_array_push (bin->kv, method_key, value_buffer, 0);
		snprintf (value_buffer, value_buffer_size, "%s", fm_type->descriptor);
		value_buffer[value_buffer_size - 1] = 0;
		IFDBG eprintf("Adding %s to sdb_array: %s\n", value_buffer, method_key);
		sdb_array_push (bin->kv, method_key, value_buffer, 0);
	}
	free (method_key);
	free (method_key_value);
	free (value_buffer);
	if (class_name_inheap) {
		free (class_name);
	}
}

Project: radare2
File: class.c

R_API char *retrieve_class_method_access_string(ut16 flags) {
	return retrieve_access_string (flags, CLASS_ACCESS_FLAGS);
}

Project: radare2
File: class.c

R_API RBinJavaCPTypeObj *r_bin_java_double_cp_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz) {
	ut8 tag = buffer[0];
	RBinJavaCPTypeObj *obj = NULL;
	int quick_check = 0;
	quick_check = r_bin_java_quick_check (R_BIN_JAVA_CP_DOUBLE, tag, sz, "Double");
	if (quick_check > 0) {
		return (RBinJavaCPTypeObj *) obj;
	}
	obj = (RBinJavaCPTypeObj *) malloc (sizeof (RBinJavaCPTypeObj));
	if (obj) {
		memset (obj, 0, sizeof (RBinJavaCPTypeObj));
		obj->tag = tag;
		obj->metas = R_NEW0 (RBinJavaMetaInfo);
		obj->metas->type_info = (void *) &R_BIN_JAVA_CP_METAS[tag];
		obj->name = r_str_dup (NULL, (const char *) R_BIN_JAVA_CP_METAS[tag].name);
		memset (&obj->info.cp_double.bytes, 0, sizeof (obj->info.cp_double.bytes));
		memcpy (&obj->info.cp_double.bytes, buffer + 1, 8);
	}
	return obj;
}

Project: radare2
File: class.c

R_API ut8 *r_bin_java_cp_get_2_ut16(RBinJavaObj *bin, ut32 *out_sz, ut8 tag, ut16 ut16_one, ut16 ut16_two) {
	ut8 *bytes = malloc (7);
	if (!bytes) {
		return NULL;
	}
	ut8 *idx_addr = NULL;
	bytes[*out_sz] = tag;
	*out_sz += 1;
	idx_addr = (ut8 *) &ut16_one;
	bytes[*out_sz + 1] = idx_addr[1];
	bytes[*out_sz + 2] = idx_addr[0];
	*out_sz += 3;
	idx_addr = (ut8 *) &ut16_two;
	bytes[*out_sz + 1] = idx_addr[1];
	bytes[*out_sz + 2] = idx_addr[0];
	*out_sz += 3;
	return bytes;
}

Project: radare2
File: class.c

R_API void r_bin_java_print_inner_classes_attr_summary(RBinJavaAttrInfo *attr) {
	RBinJavaClassesAttribute *icattr;
	RListIter *iter, *iter_tmp;
	if (!attr) {
		eprintf ("Attempting to print an invalid RBinJavaAttrInfo *InnerClasses.\n");
		return;
	}
	Eprintf ("Inner Classes Attribute Information:\n");
	Eprintf ("  Attribute Offset: 0x%08"PFMT64x "\n", attr->file_offset);
	Eprintf ("  Attribute Name Index: %d (%s)\n", attr->name_idx, attr->name);
	Eprintf ("  Attribute Length: %d\n", attr->length);
	r_list_foreach_safe (attr->info.inner_classes_attr.classes, iter, iter_tmp, icattr) {
		r_bin_java_print_classes_attr_summary (icattr);
	}
}

Project: radare2
File: class.c

R_API char *r_bin_java_print_long_cp_stringify(RBinJavaCPTypeObj *obj) {
	ut32 size = 255, consumed = 0;
	char *value = malloc (size);
	if (value) {
		memset (value, 0, size);
		consumed = snprintf (value, size, "%d.0x%04"PFMT64x ".%s.0x%08"PFMT64x "",
			obj->metas->ord,
			obj->file_offset,
			((RBinJavaCPTypeMetas *) obj->metas->type_info)->name,
			r_bin_java_raw_to_long (obj->info.cp_long.bytes.raw, 0));
		if (consumed >= size - 1) {
			free (value);
			size += size >> 1;
			value = malloc (size);
			if (value) {
				memset (value, 0, size);
				consumed = snprintf (value, size, "%d.0x%04"PFMT64x ".%s.0x%08"PFMT64x "",
					obj->metas->ord,
					obj->file_offset,
					((RBinJavaCPTypeMetas *) obj->metas->type_info)->name,
					r_bin_java_raw_to_long (obj->info.cp_long.bytes.raw, 0));
			}
		}
	}
	return value;
}

Project: radare2
File: class.c

R_API RList *r_bin_java_extract_type_values(const char *arg_str) {
	RList *list_args = r_list_new ();
	if (!list_args) {
		return NULL;
	}
	char *str = NULL;
	const char *str_cur_pos = NULL;
	ut32 len = 0;
	if (!arg_str) {
		return list_args;
	}
	str_cur_pos = arg_str;
	list_args->free = free;
	while (str_cur_pos && *str_cur_pos) {
		// handle the end of an object
		len = extract_type_value (str_cur_pos, &str);
		if (len < 1) {
			r_list_free (list_args);
			return NULL;
		}
		str_cur_pos += len;
		r_list_append (list_args, str);
		str = NULL;
	}
	return list_args;
}

Project: radare2
File: class.c

R_API void r_bin_java_set_imports(RBinJavaObj *bin) {
	RListIter *iter = NULL;
	RBinJavaCPTypeObj *obj = NULL;
	r_list_free (bin->imports_list);
	bin->imports_list = r_list_newf (free);
	r_list_foreach (bin->cp_list, iter, obj) {
		const char *type = NULL;
		switch (obj->tag) {
		case R_BIN_JAVA_CP_METHODREF: type = "METHOD"; break;
		case R_BIN_JAVA_CP_INTERFACEMETHOD_REF: type = "FIELD"; break;
		case R_BIN_JAVA_CP_FIELDREF: type = "INTERFACE_METHOD"; break;
		default: type = NULL; break;
		}
		if (type) {
			r_bin_add_import (bin, obj, type);
		}
	}
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_unknown_attr_calc_size(RBinJavaAttrInfo *attr) {
	return attr ? 6 : 0;
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_exceptions_attr_calc_size(RBinJavaAttrInfo *attr) {
	ut64 size = 0, i = 0;
	if (attr) {
		size += 6;
		for (i = 0; i < attr->info.exceptions_attr.number_of_exceptions; i++) {
			// attr->info.exceptions_attr.exception_idx_table[i] = R_BIN_JAVA_USHORT (buffer, offset);
			size += 2;
		}
	}
	return size;
}

Project: radare2
File: class.c

R_API char *r_bin_java_create_field_fq_str(const char *klass, const char *name, const char *signature) {
	if (!klass) {
		klass = "null_class";
	}
	if (!name) {
		name = "null_name";
	}
	if (!signature) {
		signature = "null_signature";
	}
	return r_str_newf ("%s %s.%s", signature, klass, name);
}

Project: radare2
File: class.c

R_API RList *r_bin_java_get_field_definitions(RBinJavaObj *bin) {
	RBinJavaField *fm_type = NULL;
	RList *the_list = r_list_new ();
	if (!the_list) {
		return NULL;
	}
	RListIter *iter = NULL;
	if (!bin) {
		return the_list;
	}
	r_list_foreach (bin->fields_list, iter, fm_type) {
		char *field_def = r_bin_java_get_field_definition (fm_type);
		// eprintf ("Field def: %s, %s, %s, %s\n", fm_type->name, fm_type->descriptor, fm_type->flags_str, field_def);
		r_list_append (the_list, field_def);
	}
	return the_list;
}

Project: radare2
File: class.c

R_API char *r_bin_java_print_interfacemethodref_cp_stringify(RBinJavaCPTypeObj *obj) {
	ut32 size = 255, consumed = 0;
	char *value = malloc (size);
	if (value) {
		memset (value, 0, size);
		consumed = snprintf (value, size, "%d.0x%04"PFMT64x ".%s.%d.%d",
			obj->metas->ord, obj->file_offset + obj->loadaddr, ((RBinJavaCPTypeMetas *) obj->metas->type_info)->name,
			obj->info.cp_interface.class_idx, obj->info.cp_interface.name_and_type_idx);
		if (consumed >= size - 1) {
			free (value);
			size += size >> 1;
			value = malloc (size);
			if (value) {
				memset (value, 0, size);
				consumed = snprintf (value, size, "%d.0x%04"PFMT64x ".%s.%d.%d",
					obj->metas->ord, obj->file_offset + obj->loadaddr, ((RBinJavaCPTypeMetas *) obj->metas->type_info)->name,
					obj->info.cp_interface.class_idx, obj->info.cp_interface.name_and_type_idx);
			}
		}
	}
	return value;
}

Project: radare2
File: class.c

R_API RList *r_bin_java_find_cp_const_by_val_utf8(RBinJavaObj *bin_obj, const ut8 *bytes, ut32 len) {
	RList *res = r_list_newf (free);
	ut32 *v = NULL;
	RListIter *iter;
	RBinJavaCPTypeObj *cp_obj;
	IFDBG eprintf("In UTF-8 Looking for %s\n", bytes);
	r_list_foreach (bin_obj->cp_list, iter, cp_obj) {
		if (cp_obj->tag == R_BIN_JAVA_CP_UTF8) {
			IFDBG eprintf("In UTF-8 Looking @ %s\n", cp_obj->info.cp_utf8.bytes);
			IFDBG eprintf("UTF-8 len = %d and memcmp = %d\n", cp_obj->info.cp_utf8.length, memcmp (bytes, cp_obj->info.cp_utf8.bytes, len));
			if (len == cp_obj->info.cp_utf8.length && !memcmp (bytes, cp_obj->info.cp_utf8.bytes, len)) {
				v = malloc (sizeof (ut32));
				if (!v) {
					r_list_free (res);
					return NULL;
				}
				*v = cp_obj->metas->ord;
				IFDBG eprintf("Found a match adding idx: %d\n", *v);
				r_list_append (res, v);
			}
		}
	}
	return res;
}

Project: radare2
File: class.c

R_API RBinSymbol *r_bin_java_create_new_symbol_from_cp_idx(ut32 cp_idx, ut64 baddr) {
	RBinSymbol *sym = NULL;
	RBinJavaCPTypeObj *obj = r_bin_java_get_item_from_bin_cp_list (
		R_BIN_JAVA_GLOBAL_BIN, cp_idx);
	if (obj) {
		switch (obj->tag) {
		case R_BIN_JAVA_CP_METHODREF:
		case R_BIN_JAVA_CP_FIELDREF:
		case R_BIN_JAVA_CP_INTERFACEMETHOD_REF:
			sym = r_bin_java_create_new_symbol_from_ref (obj, baddr);
			break;
		case R_BIN_JAVA_CP_INVOKEDYNAMIC:
			sym = r_bin_java_create_new_symbol_from_invoke_dynamic (obj, baddr);
			break;
		default:
			break;
		}
	}
	return sym;
}

Project: radare2
File: class.c

R_API void r_bin_java_annotation_default_attr_free(void /*RBinJavaAttrInfo*/ *a) {
	RBinJavaAttrInfo *attr = a;
	RBinJavaElementValue *element_value = NULL, *ev_element = NULL;
	RBinJavaCPTypeObj *obj = NULL;
	RListIter *iter = NULL, *iter_tmp = NULL;
	if (attr == NULL || attr->type != R_BIN_JAVA_ATTR_TYPE_ANNOTATION_DEFAULT_ATTR) {
		return;
	}
	element_value = (attr->info.annotation_default_attr.default_value);
	switch (element_value->tag) {
	case R_BIN_JAVA_EV_TAG_BYTE:
	case R_BIN_JAVA_EV_TAG_CHAR:
	case R_BIN_JAVA_EV_TAG_DOUBLE:
	case R_BIN_JAVA_EV_TAG_FLOAT:
	case R_BIN_JAVA_EV_TAG_INT:
	case R_BIN_JAVA_EV_TAG_LONG:
	case R_BIN_JAVA_EV_TAG_SHORT:
	case R_BIN_JAVA_EV_TAG_BOOLEAN:
	case R_BIN_JAVA_EV_TAG_STRING:
		// Delete the CP Type Object
		obj = element_value->value.const_value.const_value_cp_obj;
		((RBinJavaCPTypeMetas *) obj->metas->type_info)->allocs->delete_obj (obj);
		break;
	case R_BIN_JAVA_EV_TAG_ENUM:
		// Delete the CP Type Objects
		obj = element_value->value.enum_const_value.const_name_cp_obj;
		((RBinJavaCPTypeMetas *) obj->metas->type_info)->allocs->delete_obj (obj);
		obj = element_value->value.enum_const_value.type_name_cp_obj;
		((RBinJavaCPTypeMetas *) obj->metas->type_info)->allocs->delete_obj (obj);
		break;
	case R_BIN_JAVA_EV_TAG_CLASS:
		// Delete the CP Type Object
		obj = element_value->value.class_value.class_info_cp_obj;
		((RBinJavaCPTypeMetas *) obj->metas->type_info)->allocs->delete_obj (obj);
		break;
	case R_BIN_JAVA_EV_TAG_ARRAY:
		// Delete the Element Value array List
		r_list_foreach_safe (element_value->value.array_value.values, iter, iter_tmp, ev_element) {
			r_bin_java_element_value_free (ev_element);
			// r_list_delete (element_value->value.array_value.values, iter);
			ev_element = NULL;
		}
		r_list_free (element_value->value.array_value.values);
		break;
	case R_BIN_JAVA_EV_TAG_ANNOTATION:
		// Delete the Annotations List
		r_list_free (element_value->value.annotation_value.element_value_pairs);
		break;
	default:
		// eprintf unable to free the tag
		break;
	}
	if (attr) {
		free (attr->name);
		free (attr->metas);
		free (attr);
	}
}

Project: radare2
File: class.c

R_API void r_bin_java_print_annotation_summary(RBinJavaAnnotation *annotation) {
	RListIter *iter = NULL, *iter_tmp = NULL;
	RBinJavaElementValuePair *ev_pair = NULL;
	if (!annotation) {
		// TODO eprintf invalid annotation
		return;
	}
	Eprintf ("  Annotation Type Index: 0x%02x\n", annotation->type_idx);
	Eprintf ("  Annotation Number of EV Pairs: 0x%04x\n", annotation->num_element_value_pairs);
	Eprintf ("  Annotation EV Pair Values:\n");
	if (annotation->element_value_pairs) {
		r_list_foreach_safe (annotation->element_value_pairs, iter, iter_tmp, ev_pair) {
			r_bin_java_print_element_pair_summary (ev_pair);
		}
	}
}

Project: radare2
File: class.c

R_API void r_bin_java_verification_info_free(void /*RBinJavaVerificationObj*/ *o) {
	RBinJavaVerificationObj *obj = o;
	// eprintf ("Freeing verification object\n");
	if (obj) {
		free (obj->name);
		free (obj);
	}
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_constant_value_attr_calc_size(RBinJavaAttrInfo *attr) {
	return attr ? 8 : 0;
}

Project: radare2
File: class.c

R_API void U(copy_type_info_to_stack_frame_list)(RList * type_list, RList * sf_list) {
	RListIter *iter, *iter_tmp;
	RBinJavaVerificationObj *ver_obj, *new_ver_obj;
	if (type_list == NULL) {
		return;
	}
	if (sf_list == NULL) {
		return;
	}
	r_list_foreach_safe (type_list, iter, iter_tmp, ver_obj) {
		new_ver_obj = (RBinJavaVerificationObj *) malloc (sizeof (RBinJavaVerificationObj));
		// FIXME: how to handle failed memory allocation?
		if (new_ver_obj && ver_obj) {
			memcpy (new_ver_obj, ver_obj, sizeof (RBinJavaVerificationObj));
			if (!r_list_append (sf_list, (void *) new_ver_obj)) {
				R_FREE (new_ver_obj);
			}
		} else {
			R_FREE (new_ver_obj);
		}
	}
}

Project: radare2
File: class.c

R_API RBinField *r_bin_java_allocate_rbinfield() {
	RBinField *t = (RBinField *) malloc (sizeof (RBinField));
	if (t) {
		memset (t, 0, sizeof (RBinField));
	}
	return t;
}

Project: radare2
File: class.c

R_API void r_bin_java_print_classref_cp_summary(RBinJavaCPTypeObj *obj) {
	if (obj == NULL) {
		eprintf ("Attempting to print an invalid RBinJavaCPTypeObj*  ClassRef.\n");
		return;
	}
	eprintf ("ClassRef ConstantPool Type (%d) ", obj->metas->ord);
	eprintf ("	Offset: 0x%08"PFMT64x"", obj->file_offset);
	eprintf ("	Name Index = %d\n", obj->info.cp_class.name_idx);
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_read_class_file2(RBinJavaObj *bin, const ut64 offset, const ut8 *obuf, ut64 len) {
	const ut8 *cf2_buf = obuf + offset;
	RBinJavaCPTypeObj *this_class_cp_obj = NULL;
	IFDBG eprintf("\n0x%"PFMT64x " Offset before reading the cf2 structure\n", offset);
	/*
	Reading the following fields:
	ut16 access_flags;
	ut16 this_class;
	ut16 super_class;
	*/
	if (cf2_buf + 6 > obuf + len) {
		return 0;
	}
	bin->cf2.cf2_size = 6;
	bin->cf2.access_flags = R_BIN_JAVA_USHORT (cf2_buf, 0);
	bin->cf2.this_class = R_BIN_JAVA_USHORT (cf2_buf, 2);
	bin->cf2.super_class = R_BIN_JAVA_USHORT (cf2_buf, 4);
	free (bin->cf2.flags_str);
	free (bin->cf2.this_class_name);
	bin->cf2.flags_str = retrieve_class_method_access_string (bin->cf2.access_flags);
	this_class_cp_obj = r_bin_java_get_item_from_bin_cp_list (bin, bin->cf2.this_class);
	bin->cf2.this_class_name = r_bin_java_get_item_name_from_bin_cp_list (bin, this_class_cp_obj);
	IFDBG eprintf("This class flags are: %s\n", bin->cf2.flags_str);
	return bin->cf2.cf2_size;
}

Project: radare2
File: class.c

R_API void r_bin_java_rtvp_annotations_attr_free(void /*RBinJavaAttrInfo*/ *a) {
	RBinJavaAttrInfo *attr = a;
	if (attr) {
		if (attr->type == R_BIN_JAVA_ATTR_TYPE_RUNTIME_VISIBLE_PARAMETER_ANNOTATION_ATTR) {
			r_list_free (attr->info.rtvp_annotations_attr.parameter_annotations);
		}
		free (attr->name);
		free (attr->metas);
		free (attr);
	}
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_deprecated_attr_calc_size(RBinJavaAttrInfo *attr) {
	return attr ? 6 : 0;
}

Project: radare2
File: class.c

R_API RBinJavaElementValue *r_bin_java_element_value_new(ut8 *buffer, ut64 sz, ut64 buf_offset) {
	ut32 i = 0;
	ut64 offset = 0;
	RBinJavaElementValue *element_value = R_NEW0 (RBinJavaElementValue);
	if (!element_value) {
		return NULL;
	}
	RBinJavaElementValuePair *ev_pairs = NULL;
	element_value->metas = R_NEW0 (RBinJavaMetaInfo);
	if (!element_value->metas) {
		R_FREE (element_value);
		return NULL;
	}
	element_value->file_offset = buf_offset;
	element_value->tag = buffer[offset];
	element_value->size += 1;
	offset += 1;
	element_value->metas->type_info = (void *) r_bin_java_get_ev_meta_from_tag (element_value->tag);
	switch (element_value->tag) {
	case R_BIN_JAVA_EV_TAG_BYTE:
	case R_BIN_JAVA_EV_TAG_CHAR:
	case R_BIN_JAVA_EV_TAG_DOUBLE:
	case R_BIN_JAVA_EV_TAG_FLOAT:
	case R_BIN_JAVA_EV_TAG_INT:
	case R_BIN_JAVA_EV_TAG_LONG:
	case R_BIN_JAVA_EV_TAG_SHORT:
	case R_BIN_JAVA_EV_TAG_BOOLEAN:
	case R_BIN_JAVA_EV_TAG_STRING:
		// look up value in bin->cp_list
		// (ut16) read and set const_value.const_value_idx
		element_value->value.const_value.const_value_idx = R_BIN_JAVA_USHORT (buffer, offset);
		element_value->size += 2;
		offset += 2;
		// look-up, deep copy, and set const_value.const_value_cp_obj
		element_value->value.const_value.const_value_cp_obj = r_bin_java_clone_cp_idx (R_BIN_JAVA_GLOBAL_BIN, element_value->value.const_value.const_value_idx);
		break;
	case R_BIN_JAVA_EV_TAG_ENUM:
		// (ut16) read and set enum_const_value.type_name_idx
		element_value->value.enum_const_value.type_name_idx = R_BIN_JAVA_USHORT (buffer, offset);
		element_value->size += 2;
		offset += 2;
		// (ut16) read and set enum_const_value.const_name_idx
		element_value->value.enum_const_value.const_name_idx = R_BIN_JAVA_USHORT (buffer, offset);
		element_value->size += 2;
		offset += 2;
		// look up type_name_index in bin->cp_list
		// look-up, deep copy, and set enum_const_value.const_name_cp_obj
		element_value->value.enum_const_value.const_name_cp_obj = r_bin_java_clone_cp_idx (R_BIN_JAVA_GLOBAL_BIN, element_value->value.enum_const_value.const_name_idx);
		// look-up, deep copy, and set enum_const_value.type_name_cp_obj
		element_value->value.enum_const_value.type_name_cp_obj = r_bin_java_clone_cp_idx (R_BIN_JAVA_GLOBAL_BIN, element_value->value.enum_const_value.type_name_idx);
		break;
	case R_BIN_JAVA_EV_TAG_CLASS:
		// (ut16) read and set class_value.class_info_idx
		element_value->value.class_value.class_info_idx = R_BIN_JAVA_USHORT (buffer, offset);
		element_value->size += 2;
		offset += 2;
		// look up type_name_index in bin->cp_list
		// look-up, deep copy, and set class_value.class_info_cp_obj
		element_value->value.class_value.class_info_cp_obj = r_bin_java_clone_cp_idx (R_BIN_JAVA_GLOBAL_BIN, element_value->value.class_value.class_info_idx);
		break;
	case R_BIN_JAVA_EV_TAG_ARRAY:
		// (ut16) read and set array_value.num_values
		element_value->value.array_value.num_values = R_BIN_JAVA_USHORT (buffer, offset);
		element_value->size += 2;
		offset += 2;
		element_value->value.array_value.values = r_list_new ();
		for (i = 0; i < element_value->value.array_value.num_values; i++) {
			if (offset >= sz) {
				break;
			}
			RBinJavaElementValue *ev_element = r_bin_java_element_value_new (buffer + offset, sz - offset, buf_offset + offset);
			if (ev_element) {
				element_value->size += ev_element->size;
				offset += ev_element->size;
			}
			// read array_value.num_values, and append to array_value.values
			r_list_append (element_value->value.array_value.values, (void *) ev_element);
			if (ev_element == NULL) {
				// TODO: eprintf error when reading element value
			}
		}
		break;
	case R_BIN_JAVA_EV_TAG_ANNOTATION:
		// annotation new is not used here.
		// (ut16) read and set annotation_value.type_idx;
		element_value->value.annotation_value.type_idx = R_BIN_JAVA_USHORT (buffer, offset);
		element_value->size += 2;
		offset += 2;
		// (ut16) read and set annotation_value.num_element_value_pairs;
		element_value->value.annotation_value.num_element_value_pairs = R_BIN_JAVA_USHORT (buffer, offset);
		element_value->size += 2;
		offset += 2;
		element_value->value.annotation_value.element_value_pairs = r_list_newf (r_bin_java_element_pair_free);
		// read annotation_value.num_element_value_pairs, and append to annotation_value.element_value_pairs
		for (i = 0; i < element_value->value.annotation_value.num_element_value_pairs; i++) {
			if (offset > sz) {
				break;
			}
			ev_pairs = r_bin_java_element_pair_new (buffer + offset, sz - offset, buf_offset + offset);
			if (ev_pairs) {
				element_value->size += ev_pairs->size;
				offset += ev_pairs->size;
			}
			if (ev_pairs == NULL) {
				// TODO: eprintf error when reading element pair
			}
			r_list_append (element_value->value.annotation_value.element_value_pairs, (void *) ev_pairs);
		}
		break;
	default:
		// eprintf unable to handle tag
		break;
	}
	return element_value;
}

Project: radare2
File: class.c

R_API RBinJavaCPTypeObj *r_bin_java_unknown_cp_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz) {
	ut8 tag = buffer[0];
	RBinJavaCPTypeObj *obj = NULL;
	obj = (RBinJavaCPTypeObj *) malloc (sizeof (RBinJavaCPTypeObj));
	if (obj) {
		memset (obj, 0, sizeof (RBinJavaCPTypeObj));
		obj->tag = tag;
		obj->metas = R_NEW0 (RBinJavaMetaInfo);
		obj->metas->type_info = (void *) &R_BIN_JAVA_CP_METAS[R_BIN_JAVA_CP_UNKNOWN];
	}
	return obj;
}

Project: radare2
File: class.c

R_API void r_bin_java_signature_attr_free(void /*RBinJavaAttrInfo*/ *a) {
	RBinJavaAttrInfo *attr = a;
	if (attr) {
		free (attr->name);
		free (attr->metas);
		free (attr->info.signature_attr.signature);
		free (attr);
	}
}

Project: radare2
File: class.c

R_API void r_bin_java_stack_frame_free(void /*RBinJavaStackMapFrame*/ *o) {
	RBinJavaStackMapFrame *obj = o;
	if (obj) {
		r_list_free (obj->local_items);
		r_list_free (obj->stack_items);
		free (obj->metas);
		free (obj);
	}
}

Project: radare2
File: class.c

R_API char *r_bin_java_create_method_fq_str(const char *klass, const char *name, const char *signature) {
	if (!klass) {
		klass = "null_class";
	}
	if (!name) {
		name = "null_name";
	}
	if (!signature) {
		signature = "null_signature";
	}
	return r_str_newf ("%s.%s.%s", klass, name, signature);
}

Project: radare2
File: class.c

R_API char *r_bin_java_get_field_definition(RBinJavaField *fm_type) {
	return r_bin_java_unmangle (fm_type->flags_str, fm_type->name, fm_type->descriptor);
}

Project: radare2
File: class.c

R_API char *r_bin_java_print_integer_cp_stringify(RBinJavaCPTypeObj *obj) {
	ut32 size = 255, consumed = 0;
	char *value = malloc (size);
	if (value) {
		memset (value, 0, size);
		consumed = snprintf (value, size, "%d.0x%04"PFMT64x ".%s.0x%08x",
			obj->metas->ord, obj->file_offset + obj->loadaddr, ((RBinJavaCPTypeMetas *) obj->metas->type_info)->name,
			R_BIN_JAVA_UINT (obj->info.cp_integer.bytes.raw, 0));
		if (consumed >= size - 1) {
			free (value);
			size += size >> 1;
			value = malloc (size);
			if (value) {
				memset (value, 0, size);
				consumed = snprintf (value, size, "%d.0x%04"PFMT64x ".%s.0x%08x",
					obj->metas->ord, obj->file_offset + obj->loadaddr, ((RBinJavaCPTypeMetas *) obj->metas->type_info)->name,
					R_BIN_JAVA_UINT (obj->info.cp_integer.bytes.raw, 0));
			}
		}
	}
	return value;
}

Project: radare2
File: class.c

R_API RBinJavaField *r_bin_java_read_next_method(RBinJavaObj *bin, const ut64 offset, const ut8 *buf, const ut64 len) {
	ut32 i, idx;
	const ut8 *f_buf = buf + offset;
	ut64 adv = 0;
	RBinJavaCPTypeObj *item = NULL;
	RBinJavaField *method;
	if (bin == NULL) {
		return NULL;
	}
	if (offset + 8 >= len) {
		return NULL;
	}
	method = (RBinJavaField *) R_NEW0 (RBinJavaField);
	if (method == NULL) {
		eprintf ("Unable to allocate memory for method information\n");
		return NULL;
	}
	method->metas = (RBinJavaMetaInfo *) R_NEW0 (RBinJavaMetaInfo);
	if (method->metas == NULL) {
		eprintf ("Unable to allocate memory for meta information\n");
		free (method);
		return NULL;
	}
	method->file_offset = offset;
	method->flags = R_BIN_JAVA_USHORT (f_buf, 0);
	method->flags_str = retrieve_method_access_string (method->flags);
	// need to subtract 1 for the idx
	method->name_idx = R_BIN_JAVA_USHORT (f_buf, 2);
	method->descriptor_idx = R_BIN_JAVA_USHORT (f_buf, 4);
	method->attr_count = R_BIN_JAVA_USHORT (f_buf, 6);
	method->attributes = r_list_newf (r_bin_java_attribute_free);
	method->type = R_BIN_JAVA_FIELD_TYPE_METHOD;
	method->metas->ord = bin->method_idx;
	adv += 8;
	idx = method->name_idx;
	item = r_bin_java_get_item_from_bin_cp_list (bin, idx);
	method->name = r_bin_java_get_utf8_from_bin_cp_list (bin, (ut32) (method->name_idx));
	IFDBG eprintf("Method name_idx: %d, which is: ord: %d, name: %s, value: %s\n", idx, item->metas->ord, ((RBinJavaCPTypeMetas *)item->metas->type_info)->name, method->name);
	if (method->name == NULL) {
		method->name = (char *) malloc (21);
		snprintf ((char *) method->name, 20, "sym.method_%08x", method->metas->ord);
		IFDBG eprintf("r_bin_java_read_next_method: Unable to find the name for 0x%02x index.\n", method->name_idx);
	}
	idx = method->descriptor_idx;
	item = r_bin_java_get_item_from_bin_cp_list (bin, idx);
	method->descriptor = r_bin_java_get_utf8_from_bin_cp_list (bin, (ut32) method->descriptor_idx);
	IFDBG eprintf("Method descriptor_idx: %d, which is: ord: %d, name: %s, value: %s\n", idx, item->metas->ord, ((RBinJavaCPTypeMetas *)item->metas->type_info)->name, method->descriptor);
	if (method->descriptor == NULL) {
		method->descriptor = r_str_dup (NULL, "NULL");
		IFDBG eprintf("r_bin_java_read_next_method: Unable to find the descriptor for 0x%02x index.\n", method->descriptor_idx);
	}
	IFDBG eprintf("Looking for a NameAndType CP with name_idx: %d descriptor_idx: %d\n", method->name_idx, method->descriptor_idx);
	method->field_ref_cp_obj = r_bin_java_find_cp_ref_info_from_name_and_type (bin, method->name_idx, method->descriptor_idx);
	if (method->field_ref_cp_obj) {
		IFDBG eprintf("Found the obj.\n");
		item = r_bin_java_get_item_from_bin_cp_list (bin, method->field_ref_cp_obj->info.cp_method.class_idx);
		IFDBG eprintf("Method class reference value: %d, which is: ord: %d, name: %s\n", method->field_ref_cp_obj->info.cp_method.class_idx, item->metas->ord, ((RBinJavaCPTypeMetas *)item->metas->type_info)->name);
		method->class_name = r_bin_java_get_item_name_from_bin_cp_list (bin, item);
		IFDBG eprintf("Method requesting ref_cp_obj the following which is: ord: %d, name: %s\n", method->field_ref_cp_obj->metas->ord, ((RBinJavaCPTypeMetas *)method->field_ref_cp_obj->metas->type_info)->name);
		IFDBG eprintf("MethodRef class name resolves to: %s\n", method->class_name);
		if (method->class_name == NULL) {
			method->class_name = r_str_dup (NULL, "NULL");
		}
	} else {
		// XXX - default to this class?
		method->field_ref_cp_obj = r_bin_java_get_item_from_bin_cp_list (bin, bin->cf2.this_class);
		method->class_name = r_bin_java_get_item_name_from_bin_cp_list (bin, method->field_ref_cp_obj);
	}
	IFDBG eprintf("Parsing %s(%s)\n", method->name, method->descriptor);
	if (method->attr_count > 0) {
		method->attr_offset = adv + offset;
		RBinJavaAttrInfo *attr = NULL;
		for (i = 0; i < method->attr_count; i++) {
			attr = r_bin_java_read_next_attr (bin, adv + offset, buf, len);
			if (!attr) {
				eprintf ("[X] r_bin_java: Error unable to parse remainder of classfile after Method Attribute: %d.\n", i);
				break;
			}
			if ((r_bin_java_get_attr_type_by_name (attr->name))->type == R_BIN_JAVA_ATTR_TYPE_CODE_ATTR) {
				// This is necessary for determing the appropriate number of bytes when readin
				// uoffset, ustack, ulocalvar values
				bin->cur_method_code_length = attr->info.code_attr.code_length;
				bin->offset_sz = 2;// (attr->info.code_attr.code_length > 65535) ? 4 : 2;
				bin->ustack_sz = 2;// (attr->info.code_attr.max_stack > 65535) ? 4 : 2;
				bin->ulocalvar_sz = 2;// (attr->info.code_attr.max_locals > 65535) ? 4 : 2;
			}
			IFDBG eprintf("Parsing @ 0x%"PFMT64x " (%s) = 0x%"PFMT64x " bytes\n", attr->file_offset, attr->name, attr->size);
			r_list_append (method->attributes, attr);
			adv += attr->size;
			if (adv + offset >= len) {
				eprintf ("[X] r_bin_java: Error unable to parse remainder of classfile after Method Attribute: %d.\n", i);
				break;
			}
		}
	}
	method->size = adv;
	// reset after parsing the method attributes
	IFDBG eprintf("Parsing @ 0x%"PFMT64x " %s(%s) = 0x%"PFMT64x " bytes\n", method->file_offset, method->name, method->descriptor, method->size);
	return method;
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_inner_classes_attr_calc_size(RBinJavaAttrInfo *attr) {
	RBinJavaClassesAttribute *icattr = NULL;
	RListIter *iter;
	ut64 size = 6;
	if (!attr) {
		return 0;
	}
	r_list_foreach (attr->info.inner_classes_attr.classes, iter, icattr) {
		size += r_bin_java_inner_class_attr_calc_size (icattr);
	}
	return size;
}

Project: radare2
File: class.c

R_API void r_bin_java_print_float_cp_summary(RBinJavaCPTypeObj *obj) {
	ut8 *b = NULL;
	if (obj == NULL) {
		eprintf ("Attempting to print an invalid RBinJavaCPTypeObj*  Double.\n");
		return;
	}
	b = obj->info.cp_float.bytes.raw;
	Eprintf ("Float ConstantPool Type (%d) ", obj->metas->ord);
	Eprintf ("  Offset: 0x%08"PFMT64x "", obj->file_offset);
	Eprintf ("  Bytes = %02x %02x %02x %02x\n", b[0], b[1], b[2], b[3]);
	Eprintf ("  Float = %f\n", R_BIN_JAVA_FLOAT (obj->info.cp_float.bytes.raw, 0));
}

Project: radare2
File: class.c

R_API RList *r_bin_java_find_cp_const_by_val_int(RBinJavaObj *bin_obj, const ut8 *bytes, ut32 len) {
	RList *res = r_list_newf (free);
	ut32 *v = NULL;
	RListIter *iter;
	RBinJavaCPTypeObj *cp_obj;
	eprintf ("Looking for 0x%08x\n", (ut32) R_BIN_JAVA_UINT (bytes, 0));
	r_list_foreach (bin_obj->cp_list, iter, cp_obj) {
		if (cp_obj->tag == R_BIN_JAVA_CP_INTEGER) {
			if (len == 4 && R_BIN_JAVA_UINT (bytes, 0) == R_BIN_JAVA_UINT (cp_obj->info.cp_integer.bytes.raw, 0)) {
				v = malloc (sizeof (ut32));
				if (!v) {
					r_list_free (res);
					return NULL;
				}
				*v = cp_obj->idx;
				r_list_append (res, v);
			}
		}
	}
	return res;
}

Project: radare2
File: class.c

R_API int r_bin_java_load_bin(RBinJavaObj *bin, const ut8 *buf, ut64 buf_sz) {
	ut64 adv = 0;
	R_BIN_JAVA_GLOBAL_BIN = bin;
	if (!bin) {
		return false;
	}
	r_bin_java_reset_bin_info (bin);
	memcpy ((ut8 *) &bin->cf, buf, 10);
	if (memcmp (bin->cf.cafebabe, "\xCA\xFE\xBA\xBE", 4)) {
		eprintf ("r_bin_java_new_bin: Invalid header (%02x %02x %02x %02x)\n",
			bin->cf.cafebabe[0], bin->cf.cafebabe[1],
			bin->cf.cafebabe[2], bin->cf.cafebabe[3]);
		return false;
	}
	if (bin->cf.major[0] == bin->cf.major[1] && bin->cf.major[0] == 0) {
		eprintf ("Java CLASS with MACH0 header?\n");
		return false;
	}
	adv += 8;
	// -2 so that the cp_count will be parsed
	adv += r_bin_java_parse_cp_pool (bin, adv, buf, buf_sz);
	if (adv > buf_sz) {
		eprintf ("[X] r_bin_java: Error unable to parse remainder of classfile after Constant Pool.\n");
		return true;
	}
	adv += r_bin_java_read_class_file2 (bin, adv, buf, buf_sz);
	if (adv > buf_sz) {
		eprintf ("[X] r_bin_java: Error unable to parse remainder of classfile after class file info.\n");
		return true;
	}
	IFDBG eprintf("This class: %d %s\n", bin->cf2.this_class, bin->cf2.this_class_name);
	IFDBG eprintf("0x%"PFMT64x " Access flags: 0x%04x\n", adv, bin->cf2.access_flags);
	adv += r_bin_java_parse_interfaces (bin, adv, buf, buf_sz);
	if (adv > buf_sz) {
		eprintf ("[X] r_bin_java: Error unable to parse remainder of classfile after Interfaces.\n");
		return true;
	}
	adv += r_bin_java_parse_fields (bin, adv, buf, buf_sz);
	if (adv > buf_sz) {
		eprintf ("[X] r_bin_java: Error unable to parse remainder of classfile after Fields.\n");
		return true;
	}
	adv += r_bin_java_parse_methods (bin, adv, buf, buf_sz);
	if (adv > buf_sz) {
		eprintf ("[X] r_bin_java: Error unable to parse remainder of classfile after Methods.\n");
		return true;
	}
	adv += r_bin_java_parse_attrs (bin, adv, buf, buf_sz);
	bin->calc_size = adv;
	// if (adv > buf_sz) {
	// eprintf ("[X] r_bin_java: Error unable to parse remainder of classfile after Attributes.\n");
	// return true;
	// }

	// add_cp_objs_to_sdb(bin);
	// add_method_infos_to_sdb(bin);
	// add_field_infos_to_sdb(bin);
	return true;
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_enclosing_methods_attr_calc_size(RBinJavaAttrInfo *attr) {
	ut64 size = 0;
	if (attr) {
		size += 6;
		// attr->info.enclosing_method_attr.class_idx = R_BIN_JAVA_USHORT (buffer, offset);
		size += 2;
		// attr->info.enclosing_method_attr.method_idx = R_BIN_JAVA_USHORT (buffer, offset);
		size += 2;
	}
	return size;
}

Project: radare2
File: class.c

R_API void r_bin_java_print_local_variable_type_table_attr_summary(RBinJavaAttrInfo *attr) {
	RBinJavaLocalVariableTypeAttribute *lvtattr;
	RListIter *iter, *iter_tmp;
	if (!attr) {
		eprintf ("Attempting to print an invalid RBinJavaAttrInfo *LocalVariableTable.\n");
		return;
	}
	eprintf ("Local Variable Type Table Attribute Information:\n");
	eprintf ("   Attribute Offset: 0x%08"PFMT64x "\n", attr->file_offset);
	eprintf ("   Attribute Name Index: %d (%s)\n", attr->name_idx, attr->name);
	eprintf ("   Attribute Length: %d\n", attr->length);
	r_list_foreach_safe (attr->info.local_variable_type_table_attr.local_variable_table, iter, iter_tmp, lvtattr) {
		r_bin_java_print_local_variable_type_attr_summary (lvtattr);
	}
}

Project: radare2
File: class.c

R_API RBinJavaStackMapFrame *r_bin_java_stack_map_frame_new(ut8 *buffer, ut64 sz, RBinJavaStackMapFrame *p_frame, ut64 buf_offset) {
	RBinJavaStackMapFrame *stack_frame = r_bin_java_default_stack_frame ();
	RBinJavaVerificationObj *se = NULL;
	ut64 offset = 0;
	if (!stack_frame) {
		return NULL;
	}
	stack_frame->tag = buffer[offset];
	offset += 1;
	stack_frame->metas->type_info = (void *) r_bin_java_determine_stack_frame_type (stack_frame->tag);
	stack_frame->type = ((RBinJavaStackMapFrameMetas *) stack_frame->metas->type_info)->type;
	stack_frame->file_offset = buf_offset;
	stack_frame->p_stack_frame = p_frame;
	switch (stack_frame->type) {
	case R_BIN_JAVA_STACK_FRAME_SAME:
		// Maybe?  1. Copy the previous frames locals and set the locals count.
		// copy_type_info_to_stack_frame_list_up_to_idx (p_frame->local_items, stack_frame->local_items, idx);
		if (p_frame) {
			stack_frame->number_of_locals = p_frame->number_of_locals;
		} else {
			IFINT eprintf("><?><\n");
			IFDBG eprintf("Unable to set previous stackframe with the number of locals (current info.code_attr.implicit_frame was probably not set :/)");
		}
		IFDBG eprintf("r_bin_java_stack_map_frame_new: TODO Stack Frame Same Locals Condition is untested, so there may be issues.\n");
		break;
	case R_BIN_JAVA_STACK_FRAME_SAME_LOCALS_1:
		// 1. Read the stack type
		stack_frame->number_of_stack_items = 1;
		if (offset > sz) {
			r_bin_java_stack_frame_free (stack_frame);
			return NULL;
		}
		se = r_bin_java_read_from_buffer_verification_info_new (buffer + offset, sz - offset, buf_offset + offset);
		IFDBG eprintf("r_bin_java_stack_map_frame_new: Parsed R_BIN_JAVA_STACK_FRAME_SAME_LOCALS_1.\n");
		if (se) {
			offset += se->size;
		} else {
			eprintf ("r_bin_java_stack_map_frame_new: Unable to parse the Stack Items for the stack frame.\n");
			r_bin_java_stack_frame_free (stack_frame);
			return NULL;
		}
		r_list_append (stack_frame->stack_items, (void *) se);
		// Maybe?  3. Copy the previous frames locals and set the locals count.
		// copy_type_info_to_stack_frame_list_up_to_idx (p_frame->local_items, stack_frame->local_items, idx);
		if (p_frame) {
			stack_frame->number_of_locals = p_frame->number_of_locals;
		} else {
			IFDBG eprintf("Unable to set previous stackframe with the number of locals (current info.code_attr.implicit_frame was probably not set :/)");
		}
		IFDBG eprintf("r_bin_java_stack_map_frame_new: TODO Stack Frame Same Locals 1 Stack Element Condition is untested, so there may be issues.\n");
		break;
	case R_BIN_JAVA_STACK_FRAME_CHOP:
		// 1. Calculate the max index we want to copy from the list of the
		// previous frames locals
		IFDBG eprintf("r_bin_java_stack_map_frame_new: Parsing R_BIN_JAVA_STACK_FRAME_CHOP.\n");
		// ut16 k = 251 - stack_frame->tag;
		/*,
		idx = p_frame->number_of_locals - k;
		*/
		// 2.  read the uoffset value
		stack_frame->offset_delta = R_BIN_JAVA_USHORT (buffer, offset);
		offset += 2;
		// Maybe? 3. Copy the previous frames locals and set the locals count.
		// copy_type_info_to_stack_frame_list_up_to_idx (p_frame->local_items, stack_frame->local_items, idx);
		if (p_frame) {
			stack_frame->number_of_locals = p_frame->number_of_locals;
		} else {
			IFINT eprintf("><?><\n");
			IFDBG eprintf("Unable to set previous stackframe with the number of locals (current info.code_attr.implicit_frame was probably not set :/)");
		}
		IFDBG eprintf("r_bin_java_stack_map_frame_new: TODO Stack Frame Chop Condition is untested, so there may be issues.\n");
		break;
	case R_BIN_JAVA_STACK_FRAME_SAME_FRAME_EXTENDED:
		IFDBG eprintf("r_bin_java_stack_map_frame_new: Parsing R_BIN_JAVA_STACK_FRAME_SAME_FRAME_EXTENDED.\n");
		// 1. Read the uoffset
		stack_frame->offset_delta = R_BIN_JAVA_USHORT (buffer, offset);
		offset += 2;
		// 2. Read the stack element type
		stack_frame->number_of_stack_items = 1;
		se = r_bin_java_read_from_buffer_verification_info_new (buffer + offset, sz - offset, buf_offset + offset);
		if (se) {
			offset += se->size;
		} else {
			eprintf ("r_bin_java_stack_map_frame_new: Unable to parse the Stack Items for the stack frame.\n");
			r_bin_java_stack_frame_free (stack_frame);
			return NULL;
		}
		r_list_append (stack_frame->stack_items, (void *) se);
		// Maybe? 3. Copy the previous frames locals to the current locals
		// copy_type_info_to_stack_frame_list_up_to_idx (p_frame->local_items, stack_frame->local_items, idx);
		if (p_frame) {
			stack_frame->number_of_locals = p_frame->number_of_locals;
		} else {
			IFINT eprintf("><?><\n");
			IFDBG eprintf("Unable to set previous stackframe with the number of locals (current info.code_attr.implicit_frame was probably not set :/)");
		}
		IFDBG eprintf("r_bin_java_stack_map_frame_new: TODO Stack Frame Same Locals Frame Stack 1 Extended Condition is untested, so there may be issues.\n");
		break;
	case R_BIN_JAVA_STACK_FRAME_APPEND:
		IFDBG eprintf("r_bin_java_stack_map_frame_new: Parsing R_BIN_JAVA_STACK_FRAME_APPEND.\n");
		// 1. Calculate the max index we want to copy from the list of the
		// previous frames locals
		ut16 k = stack_frame->tag - 251,
		i = 0;
		// 2. Read the uoffset
		stack_frame->offset_delta = R_BIN_JAVA_USHORT (buffer, offset);
		offset += 2;
		// Maybe? 3. Copy the previous frames locals to the current locals
		// copy_type_info_to_stack_frame_list_up_to_idx (p_frame->local_items, stack_frame->local_items, idx);
		// 4. Read off the rest of the appended locals types
		for (i = 0; i < k; i++) {
			IFDBG eprintf("r_bin_java_stack_map_frame_new: Parsing verifying the k'th frame: %d of %d.\n", i, k);
			se = r_bin_java_read_from_buffer_verification_info_new (buffer + offset, sz - offset, buf_offset + offset);
			IFDBG eprintf("r_bin_java_stack_map_frame_new: Completed Parsing\n");
			if (se) {
				offset += se->size;
			} else {
				eprintf ("r_bin_java_stack_map_frame_new: Unable to parse the locals for the stack frame.\n");
				r_bin_java_stack_frame_free (stack_frame);
				return NULL;
			}
			r_list_append (stack_frame->local_items, (void *) se);
		}
		IFDBG eprintf("r_bin_java_stack_map_frame_new: Breaking out of loop");
		IFDBG eprintf("p_frame: %p\n", p_frame);
		if (p_frame) {
			stack_frame->number_of_locals = p_frame->number_of_locals + k;
		} else {
			IFINT eprintf("><?><\n");
			IFDBG eprintf("Unable to set previous stackframe with the number of locals (current info.code_attr.implicit_frame was probably not set :/)");
		}
		IFDBG eprintf("r_bin_java_stack_map_frame_new: TODO Stack Frame Same Locals Frame Stack 1 Extended Condition is untested, so there may be issues.\n");
		break;
	case R_BIN_JAVA_STACK_FRAME_FULL_FRAME:
		IFDBG eprintf("r_bin_java_stack_map_frame_new: Parsing R_BIN_JAVA_STACK_FRAME_FULL_FRAME.\n");
		stack_frame->offset_delta = R_BIN_JAVA_USHORT (buffer, offset);
		offset += 2;
		// IFDBG eprintf ("r_bin_java_stack_map_frame_new: Code Size > 65535, read(%d byte(s)), offset = 0x%08x.\n", var_sz, stack_frame->offset_delta);
		// Read the number of variables based on the max # local variable
		stack_frame->number_of_locals = R_BIN_JAVA_USHORT (buffer, offset);
		offset += 2;
		// IFDBG eprintf ("r_bin_java_stack_map_frame_new: Max ulocalvar > 65535, read(%d byte(s)), number_of_locals = 0x%08x.\n", var_sz, stack_frame->number_of_locals);
		IFDBG r_bin_java_print_stack_map_frame_summary(stack_frame);
		// read the number of locals off the stack
		for (i = 0; i < stack_frame->number_of_locals; i++) {
			se = r_bin_java_read_from_buffer_verification_info_new (buffer + offset, sz - offset, buf_offset + offset);
			if (se) {
				offset += se->size;
				// r_list_append (stack_frame->local_items, (void *) se);
			} else {
				eprintf ("r_bin_java_stack_map_frame_new: Unable to parse the locals for the stack frame.\n");
				r_bin_java_stack_frame_free (stack_frame);
				return NULL;
			}
			r_list_append (stack_frame->local_items, (void *) se);
		}
		// Read the number of stack items based on the max size of stack
		stack_frame->number_of_stack_items = R_BIN_JAVA_USHORT (buffer, offset);
		offset += 2;
		// IFDBG eprintf ("r_bin_java_stack_map_frame_new: Max ustack items > 65535, read(%d byte(s)), number_of_locals = 0x%08x.\n", var_sz, stack_frame->number_of_stack_items);
		// read the stack items
		for (i = 0; i < stack_frame->number_of_stack_items; i++) {
			se = r_bin_java_read_from_buffer_verification_info_new (buffer + offset, sz - offset, buf_offset + offset);
			if (se) {
				offset += se->size;
				// r_list_append (stack_frame->stack_items, (void *) se);
			} else {
				eprintf ("r_bin_java_stack_map_frame_new: Unable to parse the stack items for the stack frame.\n");
				r_bin_java_stack_frame_free (stack_frame);
				return NULL;
			}
			r_list_append (stack_frame->local_items, (void *) se);
		}
		break;
	default:
		eprintf ("java: Unknown type\n");
		break;
	}
	// IFDBG eprintf ("Created a stack frame at offset(0x%08"PFMT64x") of size: %d\n", buf_offset, stack_frame->size);//r_bin_java_print_stack_map_frame_summary(stack_frame);
	stack_frame->size = offset;
	// IFDBG r_bin_java_print_stack_map_frame_summary(stack_frame);
	return stack_frame;
}

Project: radare2
File: class.c

R_API void r_bin_java_print_classes_attr_summary(RBinJavaClassesAttribute *icattr) {
	if (!icattr) {
		eprintf ("Attempting to print an invalid RBinJavaClassesAttribute* (InnerClasses element).\n");
		return;
	}
	eprintf ("   Inner Classes Class Attribute Offset: 0x%08"PFMT64x "\n", icattr->file_offset);
	eprintf ("   Inner Classes Class Attribute Class Name (%d): %s\n", icattr->inner_name_idx, icattr->name);
	eprintf ("   Inner Classes Class Attribute Class inner_class_info_idx: %d\n", icattr->inner_class_info_idx);
	eprintf ("   Inner Classes Class Attribute Class inner_class_access_flags: 0x%02x %s\n", icattr->inner_class_access_flags, icattr->flags_str);
	eprintf ("   Inner Classes Class Attribute Class outer_class_info_idx: %d\n", icattr->outer_class_info_idx);
	eprintf ("   Inner Classes Class Field Information:\n");
	r_bin_java_print_field_summary (icattr->clint_field);
	eprintf ("   Inner Classes Class Field Information:\n");
	r_bin_java_print_field_summary (icattr->clint_field);
	eprintf ("   Inner Classes Class Attr Info Information:\n");
	r_bin_java_print_attr_summary (icattr->clint_attr);
}

Project: radare2
File: class.c

R_API int r_bin_java_valid_class(const ut8 *buf, ut64 buf_sz) {
	RBinJavaObj *bin = R_NEW0 (RBinJavaObj), *cur_bin = R_BIN_JAVA_GLOBAL_BIN;
	if (!bin) {
		return false;
	}
	int res = r_bin_java_load_bin (bin, buf, buf_sz);
	if (bin->calc_size == buf_sz) {
		res = true;
	}
	r_bin_java_free (bin);
	R_BIN_JAVA_GLOBAL_BIN = cur_bin;
	return res;
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_bootstrap_method_calc_size(RBinJavaBootStrapMethod *bsm) {
	RListIter *iter, *iter_tmp;
	RBinJavaBootStrapArgument *bsm_arg = NULL;
	ut64 size = 0;
	if (bsm) {
		size += 6;
		// bsm->bootstrap_method_ref = R_BIN_JAVA_USHORT (buffer, offset);
		size += 2;
		// bsm->num_bootstrap_arguments = R_BIN_JAVA_USHORT (buffer, offset);
		size += 2;
		r_list_foreach_safe (bsm->bootstrap_arguments, iter, iter_tmp, bsm_arg) {
			if (bsm_arg) {
				size += r_bin_java_bootstrap_arg_calc_size (bsm_arg);
			} else {
				// TODO eprintf Failed to read the %d boot strap method.
			}
		}
	}
	return size;
}

Project: radare2
File: class.c

R_API RBinJavaAttrInfo *r_bin_java_local_variable_type_table_attr_new(ut8 *buffer, ut64 sz, ut64 buf_offset) {
	RBinJavaLocalVariableTypeAttribute *lvattr;
	ut64 offset = 6;
	ut32 i = 0;
	RBinJavaAttrInfo *attr = r_bin_java_default_attr_new (buffer, sz, 0);
	if (!attr) {
		return NULL;
	}
	attr->type = R_BIN_JAVA_ATTR_TYPE_LOCAL_VARIABLE_TYPE_TABLE_ATTR;
	attr->info.local_variable_type_table_attr.table_length = R_BIN_JAVA_USHORT (buffer, offset);
	offset += 2;
	attr->info.local_variable_type_table_attr.local_variable_table = r_list_newf (r_bin_java_local_variable_type_table_attr_entry_free);
	for (i = 0; i < attr->info.local_variable_type_table_attr.table_length; i++) {
		ut64 curpos = buf_offset + offset;
		lvattr = R_NEW0 (RBinJavaLocalVariableTypeAttribute);
		if (!lvattr) {
			perror ("calloc");
			break;
		}
		if (offset + 10 > sz) {
			eprintf ("oob");
			break;
		}
		lvattr->start_pc = R_BIN_JAVA_USHORT (buffer, offset);
		offset += 2;
		lvattr->length = R_BIN_JAVA_USHORT (buffer, offset);
		offset += 2;
		lvattr->name_idx = R_BIN_JAVA_USHORT (buffer, offset);
		offset += 2;
		lvattr->signature_idx = R_BIN_JAVA_USHORT (buffer, offset);
		offset += 2;
		lvattr->index = R_BIN_JAVA_USHORT (buffer, offset);
		offset += 2;
		lvattr->file_offset = curpos;
		lvattr->name = r_bin_java_get_utf8_from_bin_cp_list (R_BIN_JAVA_GLOBAL_BIN, lvattr->name_idx);
		lvattr->size = 10;
		if (!lvattr->name) {
			lvattr->name = strdup ("NULL");
			eprintf ("r_bin_java_local_variable_type_table_attr_new: Unable to find the name for %d index.\n", lvattr->name_idx);
		}
		lvattr->signature = r_bin_java_get_utf8_from_bin_cp_list (R_BIN_JAVA_GLOBAL_BIN, lvattr->signature_idx);
		if (!lvattr->signature) {
			lvattr->signature = strdup ("NULL");
			eprintf ("r_bin_java_local_variable_type_table_attr_new: Unable to find the descriptor for %d index.\n", lvattr->signature_idx);
		}
		r_list_append (attr->info.local_variable_type_table_attr.local_variable_table, lvattr);
	}
	// IFDBG r_bin_java_print_local_variable_type_table_attr_summary(attr);
	attr->size = offset;
	return attr;
}

Project: radare2
File: class.c

R_API ut8 *r_bin_java_cp_get_fm_ref(RBinJavaObj *bin, ut32 *out_sz, ut8 tag, ut16 class_idx, ut16 name_and_type_idx) {
	return r_bin_java_cp_get_2_ut16 (bin, out_sz, tag, class_idx, name_and_type_idx);
}

Project: radare2
File: class.c

R_API RBinJavaAttrInfo *r_bin_java_code_attr_new(ut8 *buffer, ut64 sz, ut64 buf_offset) {
	RBinJavaAttrInfo *attr = NULL, *_attr = NULL;
	ut32 k = 0, curpos;
	ut64 offset = 0;
	attr = r_bin_java_default_attr_new (buffer, sz, buf_offset);
	if (!attr) {
		return NULL;
	}
	if (sz < 16 || sz > buf_offset) {// sz > buf_offset) {
		free (attr);
		return NULL;
	}
	offset += 6;
	attr->type = R_BIN_JAVA_ATTR_TYPE_CODE_ATTR;
	attr->info.code_attr.max_stack = R_BIN_JAVA_USHORT (buffer, offset);
	offset += 2;
	attr->info.code_attr.max_locals = R_BIN_JAVA_USHORT (buffer, offset);
	offset += 2;
	attr->info.code_attr.code_length = R_BIN_JAVA_UINT (buffer, offset);
	offset += 4;
	// BUG: possible unsigned integer overflow here
	attr->info.code_attr.code_offset = buf_offset + offset;
	attr->info.code_attr.code = (ut8 *) malloc (attr->info.code_attr.code_length);
	if (!attr->info.code_attr.code) {
		eprintf ("Handling Code Attributes: Unable to allocate memory "
			"(%u bytes) for a code.\n", attr->info.code_attr.code_length);
		return attr;
	}
	R_BIN_JAVA_GLOBAL_BIN->current_code_attr = attr;
	{
		int len = attr->info.code_attr.code_length;
		memset (attr->info.code_attr.code, 0, len);
		if (offset + len >= sz) {
			len = sz;
			return attr;
		}
		memcpy (attr->info.code_attr.code, buffer + offset, len);
		offset += len;
	}
	attr->info.code_attr.exception_table_length = R_BIN_JAVA_USHORT (buffer, offset);
	offset += 2;
	attr->info.code_attr.exception_table = r_list_newf (free);
	for (k = 0; k < attr->info.code_attr.exception_table_length; k++) {
		curpos = buf_offset + offset;
		if (curpos + 8 > sz) {
			return attr;
		}
		RBinJavaExceptionEntry *e = R_NEW0 (RBinJavaExceptionEntry);
		if (!e) {
			free (attr);
			return NULL;
		}
		e->file_offset = curpos;
		e->start_pc = R_BIN_JAVA_USHORT (buffer, offset);
		offset += 2;
		e->end_pc = R_BIN_JAVA_USHORT (buffer, offset);
		offset += 2;
		e->handler_pc = R_BIN_JAVA_USHORT (buffer, offset);
		offset += 2;
		e->catch_type = R_BIN_JAVA_USHORT (buffer, offset);
		offset += 2;
		r_list_append (attr->info.code_attr.exception_table, e);
		e->size = 8;
	}
	attr->info.code_attr.attributes_count = R_BIN_JAVA_USHORT (buffer, offset);
	offset += 2;
	// IFDBG eprintf ("	code Attributes_count: %d\n", attr->info.code_attr.attributes_count);
	// XXX - attr->info.code_attr.attributes is not freed because one of the code attributes is improperly parsed.
	attr->info.code_attr.attributes = r_list_newf (r_bin_java_attribute_free);
	if (attr->info.code_attr.attributes_count > 0) {
		for (k = 0; k < attr->info.code_attr.attributes_count; k++) {
			int size = (offset < sz) ? sz - offset : 0;
			if (size > sz || size <= 0) {
				break;
			}
			_attr = r_bin_java_read_next_attr_from_buffer (buffer + offset, size, buf_offset + offset);
			if (!_attr) {
				eprintf ("[X] r_bin_java_code_attr_new: Error unable to parse remainder of classfile after Method's Code Attribute: %d.\n", k);
				break;
			}
			IFDBG eprintf("Parsing @ 0x%"PFMT64x " (%s) = 0x%"PFMT64x " bytes, %p\n", _attr->file_offset, _attr->name, _attr->size, _attr);
			offset += _attr->size;
			r_list_append (attr->info.code_attr.attributes, _attr);
			if (_attr->type == R_BIN_JAVA_ATTR_TYPE_LOCAL_VARIABLE_TABLE_ATTR) {
				IFDBG eprintf("Parsed the LocalVariableTable, preparing the implicit mthod frame.\n");
				// r_bin_java_print_attr_summary(_attr);
				attr->info.code_attr.implicit_frame = r_bin_java_build_stack_frame_from_local_variable_table (R_BIN_JAVA_GLOBAL_BIN, _attr);
				attr->info.code_attr.implicit_frame->file_offset = buf_offset;
				IFDBG r_bin_java_print_stack_map_frame_summary(attr->info.code_attr.implicit_frame);
				// r_list_append (attr->info.code_attr.attributes, attr->info.code_attr.implicit_frame);
			}
			// if (offset > sz) {
			// eprintf ("[X] r_bin_java: Error unable to parse remainder of classfile after Attribute: %d.\n", k);
			// break;
			// }

		}
	}
	if (attr->info.code_attr.implicit_frame == NULL) {
		// build a default implicit_frame
		attr->info.code_attr.implicit_frame = r_bin_java_default_stack_frame ();
		// r_list_append (attr->info.code_attr.attributes, attr->info.code_attr.implicit_frame);
	}
	attr->size = offset;
	return attr;
}

Project: radare2
File: class.c

R_API RBinJavaCPTypeObj *r_bin_java_integer_cp_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz) {
	ut8 tag = buffer[0];
	RBinJavaCPTypeObj *obj = NULL;
	int quick_check = 0;
	quick_check = r_bin_java_quick_check (R_BIN_JAVA_CP_INTEGER, tag, sz, "Integer");
	if (quick_check > 0) {
		return obj;
	}
	obj = (RBinJavaCPTypeObj *) R_NEW0 (RBinJavaCPTypeObj);
	if (obj) {
		obj->tag = tag;
		obj->metas = R_NEW0 (RBinJavaMetaInfo);
		obj->metas->type_info = (void *) &R_BIN_JAVA_CP_METAS[tag];
		obj->name = r_str_dup (NULL, (const char *) R_BIN_JAVA_CP_METAS[tag].name);
		memset (&obj->info.cp_integer.bytes, 0, sizeof (obj->info.cp_integer.bytes));
		memcpy (&obj->info.cp_integer.bytes.raw, buffer + 1, 4);

	}
	return obj;
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_rtv_annotations_attr_calc_size(RBinJavaAttrInfo *attr) {
	ut64 size = 0;
	if (attr == NULL) {
		// TODO eprintf allocation fail
		return size;
	}
	size += (6 + r_bin_java_annotation_array_calc_size (&(attr->info.annotation_array)));
	return size;
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_float_cp_calc_size(RBinJavaCPTypeObj *obj) {
	ut64 size = 0;
	// tag
	size += 1;
	// obj->info.cp_string.string_idx = R_BIN_JAVA_USHORT (buffer, 1);
	size += 4;
	return size;
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_rtvp_annotations_attr_calc_size(RBinJavaAttrInfo *attr) {
	ut64 size = 0;
	RListIter *iter = NULL, *iter_tmp = NULL;
	RBinJavaAnnotationsArray *annotation_array;
	if (!attr) {
		return size;
	}
	size += (6 + 1);
	r_list_foreach_safe (attr->info.rtvp_annotations_attr.parameter_annotations,
		iter, iter_tmp, annotation_array) {
		if (annotation_array) {
			size += r_bin_java_annotation_array_calc_size (
				annotation_array);
		}
	}
	return size;
}

Project: radare2
File: class.c

R_API RList *r_bin_java_get_field_offsets(RBinJavaObj *bin) {
	RBinJavaField *fm_type = NULL;
	RList *the_list = r_list_new ();
	if (!the_list) {
		return NULL;
	}
	RListIter *iter = NULL;
	ut64 *paddr = NULL;
	if (!bin) {
		return the_list;
	}
	the_list->free = free;
	r_list_foreach (bin->fields_list, iter, fm_type) {
		paddr = malloc (sizeof(ut64));
		if (!paddr) {
			r_list_free (the_list);
			return NULL;
		}
		*paddr = fm_type->file_offset + bin->loadaddr;
		// eprintf ("Field def: %s, %s, %s, %s\n", fm_type->name, fm_type->descriptor, fm_type->flags_str, field_def);
		r_list_append (the_list, paddr);
	}
	return the_list;
}

Project: radare2
File: class.c

R_API RBinJavaAttrInfo *r_bin_java_inner_classes_attr_new(ut8 *buffer, ut64 sz, ut64 buf_offset) {
	RBinJavaClassesAttribute *icattr;
	RBinJavaAttrInfo *attr = NULL;
	RBinJavaCPTypeObj *obj;
	ut32 i = 0;
	ut64 offset = 0, curpos;
	attr = r_bin_java_default_attr_new (buffer, sz, buf_offset);
	offset += 6;
	if (attr == NULL) {
		// TODO eprintf
		return attr;
	}
	attr->type = R_BIN_JAVA_ATTR_TYPE_INNER_CLASSES_ATTR;
	attr->info.inner_classes_attr.number_of_classes = R_BIN_JAVA_USHORT (buffer, offset);
	offset += 2;
	attr->info.inner_classes_attr.classes = r_list_newf (r_bin_java_inner_classes_attr_entry_free);
	for (i = 0; i < attr->info.inner_classes_attr.number_of_classes; i++) {
		curpos = buf_offset + offset;
		if (offset + 8 > sz) {
			eprintf ("Invalid amount of inner classes\n");
			break;
		}
		icattr = R_NEW0 (RBinJavaClassesAttribute);
		if (!icattr) {
			break;
		}
		icattr->inner_class_info_idx = R_BIN_JAVA_USHORT (buffer, offset);
		offset += 2;
		icattr->outer_class_info_idx = R_BIN_JAVA_USHORT (buffer, offset);
		offset += 2;
		icattr->inner_name_idx = R_BIN_JAVA_USHORT (buffer, offset);
		offset += 2;
		icattr->inner_class_access_flags = R_BIN_JAVA_USHORT (buffer, offset);
		offset += 2;
		icattr->flags_str = retrieve_class_method_access_string (icattr->inner_class_access_flags);
		icattr->file_offset = curpos;
		icattr->size = 8;

		obj = r_bin_java_get_item_from_bin_cp_list (R_BIN_JAVA_GLOBAL_BIN, icattr->inner_name_idx);
		if (obj == NULL) {
			eprintf ("BINCPLIS IS HULL %d\n", icattr->inner_name_idx);
		}
		icattr->name = r_bin_java_get_item_name_from_bin_cp_list (R_BIN_JAVA_GLOBAL_BIN, obj);
		if (!icattr->name) {
			obj = r_bin_java_get_item_from_bin_cp_list (R_BIN_JAVA_GLOBAL_BIN, icattr->inner_class_info_idx);
			if (!obj) {
				eprintf ("BINCPLIST IS NULL %d\n", icattr->inner_class_info_idx);
			}
			icattr->name = r_bin_java_get_item_name_from_bin_cp_list (R_BIN_JAVA_GLOBAL_BIN, obj);
			if (!icattr->name) {
				icattr->name = r_str_dup (NULL, "NULL");
				eprintf ("r_bin_java_inner_classes_attr: Unable to find the name for %d index.\n", icattr->inner_name_idx);
				break;
			}
		}

		IFDBG eprintf("r_bin_java_inner_classes_attr: Inner class name %d is %s.\n", icattr->inner_name_idx, icattr->name);
		r_list_append (attr->info.inner_classes_attr.classes, (void *) icattr);
	}
	attr->size = offset;
	// IFDBG r_bin_java_print_inner_classes_attr_summary(attr);
	return attr;
}

Project: radare2
File: class.c

R_API RList *r_bin_java_get_import_definitions(RBinJavaObj *bin) {
	RList *the_list = r_bin_java_get_lib_names (bin);
	RListIter *iter = NULL;
	char *new_str;
	if (!bin || !the_list) {
		return the_list;
	}
	r_list_foreach (the_list, iter, new_str) {
		while (*new_str) {
			if (*new_str == '/') {
				*new_str = '.';
			}
			new_str++;
		}
	}
	return the_list;
}

Project: radare2
File: class.c

R_API char *r_bin_java_resolve_with_space(RBinJavaObj *obj, int idx) {
	return r_bin_java_resolve (obj, idx, 1);
}

Project: radare2
File: class.c

R_API char *r_bin_java_print_unknown_cp_stringify(RBinJavaCPTypeObj *obj) {
	ut32 size = 255;
	char *value = malloc (size);
	if (value) {
		memset (value, 0, size);
		snprintf (value, size, "%d.0x%04"PFMT64x ".%s",
			obj->metas->ord, obj->file_offset + obj->loadaddr, ((RBinJavaCPTypeMetas *) obj->metas->type_info)->name);
	}
	return value;
}

Project: radare2
File: class.c

R_API DsoJsonObj *r_bin_java_get_method_json_definitions(RBinJavaObj *bin) {
	RBinJavaField *fm_type = NULL;
	RListIter *iter = NULL;
	DsoJsonObj *json_list = dso_json_list_new ();
	if (!bin) {
		return json_list;
	}
	r_list_foreach (bin->methods_list, iter, fm_type) {
		DsoJsonObj *method_proto = r_bin_java_get_method_json_definition (bin, fm_type);
		// eprintf ("Method json: %s\n", method_proto);
		dso_json_list_append (json_list, method_proto);
	}
	return json_list;
}

Project: radare2
File: class.c

R_API char *r_bin_java_print_methodref_cp_stringify(RBinJavaCPTypeObj *obj) {
	ut32 size = 255, consumed = 0;
	char *value = malloc (size);
	if (value) {
		memset (value, 0, size);
		consumed = snprintf (value, size, "%d.0x%04"PFMT64x ".%s.%d.%d",
			obj->metas->ord, obj->file_offset + obj->loadaddr, ((RBinJavaCPTypeMetas *) obj->metas->type_info)->name,
			obj->info.cp_method.class_idx,
			obj->info.cp_method.name_and_type_idx);
		if (consumed >= size - 1) {
			free (value);
			size += size >> 1;
			value = malloc (size);
			if (value) {
				memset (value, 0, size);
				consumed = snprintf (value, size, "%d.0x%04"PFMT64x ".%s.%d.%d",
					obj->metas->ord, obj->file_offset + obj->loadaddr, ((RBinJavaCPTypeMetas *) obj->metas->type_info)->name,
					obj->info.cp_method.class_idx,
					obj->info.cp_method.name_and_type_idx);
			}
		}
	}
	return value;
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_get_method_code_size(RBinJavaField *fm_type) {
	RListIter *attr_iter = NULL, *attr_iter_tmp = NULL;
	RBinJavaAttrInfo *attr = NULL;
	ut64 sz = 0;
	r_list_foreach_safe (fm_type->attributes, attr_iter, attr_iter_tmp, attr) {
		if (attr->type == R_BIN_JAVA_ATTR_TYPE_CODE_ATTR) {
			sz = attr->info.code_attr.code_length;
			break;
		}
	}
	return sz;
}

Project: radare2
File: class.c

R_API ut8 *r_bin_java_cp_get_4bytes(ut8 tag, ut32 *out_sz, const ut8 *buf, const ut64 len) {
	ut8 *buffer = malloc (5);
	if (!buffer) {
		return NULL;
	}
	ut32 val = 0;
	if (!buffer || len < 4) {
		if (out_sz) {
			*out_sz = 0;
		}
		free (buffer);
		return NULL;
	}
	buffer[0] = tag;
	val = R_BIN_JAVA_UINT (buf, 0);
	memcpy (buffer + 1, (const char *) &val, 4);
	*out_sz = 5;
	return buffer;
}

Project: radare2
File: class.c

R_API DsoJsonObj *r_bin_java_get_class_info_json(RBinJavaObj *bin) {
	RList *classes = r_bin_java_get_classes (bin);
	DsoJsonObj *interfaces_list = dso_json_list_new ();
	DsoJsonObj *class_info_dict = dso_json_dict_new ();
	RBinClass *class_ = r_list_get_n (classes, 0);

	if (class_) {
		int dummy = 0;
		RListIter *iter;
		RBinClass *class_v = NULL;
		// add access flags like in methods
		bool is_public = ((class_->visibility & R_BIN_JAVA_CLASS_ACC_PUBLIC) != 0);
		bool is_final = ((class_->visibility & R_BIN_JAVA_CLASS_ACC_FINAL) != 0);
		bool is_super = ((class_->visibility & R_BIN_JAVA_CLASS_ACC_SUPER) != 0);
		bool is_interface = ((class_->visibility & R_BIN_JAVA_CLASS_ACC_INTERFACE) != 0);
		bool is_abstract = ((class_->visibility & R_BIN_JAVA_CLASS_ACC_ABSTRACT) != 0);
		bool is_synthetic = ((class_->visibility & R_BIN_JAVA_CLASS_ACC_SYNTHETIC) != 0);
		bool is_annotation = ((class_->visibility & R_BIN_JAVA_CLASS_ACC_ANNOTATION) != 0);
		bool is_enum = ((class_->visibility & R_BIN_JAVA_CLASS_ACC_ENUM) != 0);

		dso_json_dict_insert_str_key_num (class_info_dict, "access_flags", class_->visibility);
		dso_json_dict_insert_str_key_num (class_info_dict, "is_public", is_public);
		dso_json_dict_insert_str_key_num (class_info_dict, "is_final", is_final);
		dso_json_dict_insert_str_key_num (class_info_dict, "is_super", is_super);
		dso_json_dict_insert_str_key_num (class_info_dict, "is_interface", is_interface);
		dso_json_dict_insert_str_key_num (class_info_dict, "is_abstract", is_abstract);
		dso_json_dict_insert_str_key_num (class_info_dict, "is_synthetic", is_synthetic);
		dso_json_dict_insert_str_key_num (class_info_dict, "is_annotation", is_annotation);
		dso_json_dict_insert_str_key_num (class_info_dict, "is_enum", is_enum);
		dso_json_dict_insert_str_key_str (class_info_dict, "name", class_->name);

		if (!class_->super) {
			DsoJsonObj *str = dso_json_str_new ();
			dso_json_dict_insert_str_key_obj (class_info_dict, "super", str);
			dso_json_str_free (str);
		} else {
			dso_json_dict_insert_str_key_str (class_info_dict, "super", class_->super);
		}

		r_list_foreach (classes, iter, class_v) {
			if (!dummy) {
				dummy++;
				continue;
			}
			// enumerate all interface classes and append them to the interfaces
			if ((class_v->visibility & R_BIN_JAVA_CLASS_ACC_INTERFACE) != 0) {
				dso_json_list_append_str (interfaces_list, class_v->name);
			}
		}
	}
	dso_json_dict_insert_str_key_obj (class_info_dict, "interfaces", interfaces_list);
	r_list_free (classes);
	// dso_json_list_free (interfaces_list);
	dso_json_obj_del (interfaces_list);
	return class_info_dict;
}

Project: radare2
File: class.c

R_API RBinJavaAttrInfo *r_bin_java_stack_map_table_attr_new(ut8 *buffer, ut64 sz, ut64 buf_offset) {
	ut32 i = 0;
	ut64 offset = 0;
	RBinJavaStackMapFrame *stack_frame = NULL, *new_stack_frame = NULL;
	RBinJavaAttrInfo *attr = r_bin_java_default_attr_new (buffer, sz, buf_offset);
	offset += 6;
	IFDBG eprintf("r_bin_java_stack_map_table_attr_new: New stack map allocated.\n");
	if (!attr) {
		return NULL;
	}
	attr->info.stack_map_table_attr.stack_map_frame_entries = r_list_newf (r_bin_java_stack_frame_free);
	// IFDBG r_bin_java_print_source_code_file_attr_summary(attr);
	// Current spec does not call for variable sizes.
	attr->info.stack_map_table_attr.number_of_entries = R_BIN_JAVA_USHORT (buffer, offset);
	offset += 2;
	IFDBG eprintf("r_bin_java_stack_map_table_attr_new: Processing stack map, summary is:\n");
	IFDBG r_bin_java_print_stack_map_table_attr_summary(attr);
	for (i = 0; i < attr->info.stack_map_table_attr.number_of_entries; i++) {
		// read next stack frame
		IFDBG eprintf("Reading StackMap Entry #%d @ 0x%08"PFMT64x "\n", i, buf_offset + offset);
		if (stack_frame == NULL && R_BIN_JAVA_GLOBAL_BIN && R_BIN_JAVA_GLOBAL_BIN->current_code_attr) {
			IFDBG eprintf("Setting an implicit frame at #%d @ 0x%08"PFMT64x "\n", i, buf_offset + offset);
			stack_frame = R_BIN_JAVA_GLOBAL_BIN->current_code_attr->info.code_attr.implicit_frame;
		}
		IFDBG eprintf("Reading StackMap Entry #%d @ 0x%08"PFMT64x ", current stack_frame: %p\n", i, buf_offset + offset, stack_frame);
		if (offset > sz) {
			r_bin_java_stack_map_table_attr_free (attr);
			return NULL;
		}
		new_stack_frame = r_bin_java_stack_map_frame_new (buffer + offset, sz - offset, stack_frame, buf_offset + offset);
		if (new_stack_frame) {
			offset += new_stack_frame->size;
			// append stack frame to the list
			r_list_append (attr->info.stack_map_table_attr.stack_map_frame_entries, (void *) new_stack_frame);
			stack_frame = new_stack_frame;
		} else {
			eprintf ("r_bin_java_stack_map_table_attr_new: Unable to parse the stack frame for the stack map table.\n");
			r_bin_java_stack_map_table_attr_free (attr);
			attr = NULL;
			break;
		}
	}
	if (attr) {
		attr->size = offset;
	}
	return attr;
}

Project: radare2
File: class.c

R_API ut32 r_bin_java_get_utf8_len_from_bin_cp_list(RBinJavaObj *bin, ut64 idx) {
	/*
	Search through the Constant Pool list for the given CP Index.
	If the idx not found by directly going to the list index,
	the list will be walked and then the IDX will be checked.
	rvalue: new char* for caller to free.
	*/
	if (bin == NULL) {
		return 0;
	}
	return r_bin_java_get_utf8_len_from_cp_item_list (bin->cp_list, idx);
}

Project: radare2
File: class.c

R_API ut8 *U(r_bin_java_cp_append_field_ref)(RBinJavaObj * bin, ut32 * out_sz, ut16 cn_idx, ut16 fn_idx, ut16 ft_idx) {
	return r_bin_java_cp_get_fref_bytes (bin, out_sz, R_BIN_JAVA_CP_FIELDREF, cn_idx, fn_idx, ft_idx);
}

Project: radare2
File: class.c

R_API RBinJavaCPTypeObj *r_bin_java_methodhandle_cp_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz) {
	ut8 tag = buffer[0];
	int quick_check = r_bin_java_quick_check (R_BIN_JAVA_CP_METHODHANDLE, tag, sz, "RBinJavaCPTypeMethodHandle");
	if (quick_check > 0) {
		return NULL;
	}
	RBinJavaCPTypeObj *obj = R_NEW0 (RBinJavaCPTypeObj);
	if (obj) {
		obj->metas = R_NEW0 (RBinJavaMetaInfo);
		obj->metas->type_info = (void *) &R_BIN_JAVA_CP_METAS[tag];
		obj->name = r_str_dup (NULL, (const char *) R_BIN_JAVA_CP_METAS[tag].name);;
		obj->tag = tag;
		obj->info.cp_method_handle.reference_kind = buffer[1];
		obj->info.cp_method_handle.reference_index = R_BIN_JAVA_USHORT (buffer, 2);
	}
	return obj;
}

Project: radare2
File: class.c

R_API int sdb_iterate_build_list(void *user, const char *k, const char *v) {
	RList *bin_objs_list = (RList *) user;
	size_t value = (size_t) sdb_atoi (v);
	RBinJavaObj *bin_obj = NULL;
	IFDBG eprintf("Found %s == %"PFMT64x " bin_objs db\n", k, (ut64) value);
	if (value != 0 && value != (size_t) -1) {
		bin_obj = (RBinJavaObj *) value;
		r_list_append (bin_objs_list, bin_obj);
	}
	return true;
}

Project: radare2
File: class.c

R_API ut32 r_bin_java_get_field_count(RBinJavaObj *bin_obj) {
	return r_list_length (bin_obj->fields_list);
}

Project: radare2
File: class.c

R_API RBinJavaCPTypeObj *r_bin_java_find_cp_ref_info_from_name_and_type(RBinJavaObj *bin, ut16 name_idx, ut16 descriptor_idx) {
	RBinJavaCPTypeObj *obj = r_bin_java_find_cp_name_and_type_info (bin, name_idx, descriptor_idx);
	if (obj) {
		return r_bin_java_find_cp_ref_info (bin, obj->metas->ord);
	}
	return NULL;
}

Project: radare2
File: class.c

R_API RList *r_bin_java_find_cp_const_by_val(RBinJavaObj *bin_obj, const ut8 *bytes, ut32 len, const char t) {
	switch (t) {
	case R_BIN_JAVA_CP_UTF8: return r_bin_java_find_cp_const_by_val_utf8 (bin_obj, bytes, len);
	case R_BIN_JAVA_CP_INTEGER: return r_bin_java_find_cp_const_by_val_int (bin_obj, bytes, len);
	case R_BIN_JAVA_CP_FLOAT: return r_bin_java_find_cp_const_by_val_float (bin_obj, bytes, len);
	case R_BIN_JAVA_CP_LONG: return r_bin_java_find_cp_const_by_val_long (bin_obj, bytes, len);
	case R_BIN_JAVA_CP_DOUBLE: return r_bin_java_find_cp_const_by_val_double (bin_obj, bytes, len);
	case R_BIN_JAVA_CP_UNKNOWN:
	default:
		eprintf ("Failed to perform the search for: %s\n", bytes);
		return r_list_new ();
	}
}

Project: radare2
File: class.c

R_API DsoJsonObj *r_bin_java_get_import_json_definitions(RBinJavaObj *bin) {
	RList *the_list;
	DsoJsonObj *json_list = dso_json_list_new ();
	RListIter *iter = NULL;
	char *new_str;

	if (!bin || !(the_list = r_bin_java_get_lib_names (bin))) {
		return json_list;
	}

	r_list_foreach (the_list, iter, new_str) {
		char *tmp = new_str;
		// eprintf ("Processing string: %s\n", new_str);
		while (*tmp) {
			if (*tmp == '/') {
				*tmp = '.';
			}
			tmp++;
		}
		// eprintf ("adding string: %s\n", new_str);
		dso_json_list_append_str (json_list, new_str);
	}
	r_list_free (the_list);
	return json_list;
}

Project: radare2
File: class.c

R_API ut8 *U(r_bin_java_cp_append_ref_cname_fname_ftype)(RBinJavaObj * bin, ut32 * out_sz, ut8 tag, const char *cname, const ut32 c_len, const char *fname, const ut32 f_len, const char *tname, const ut32 t_len) {
	ut32 cn_len = 0, fn_len = 0, ft_len = 0, total_len;
	ut16 cn_idx = 0, fn_idx = 0, ft_idx = 0;
	ut8 *bytes = NULL, *cn_bytes = NULL, *fn_bytes = NULL, *ft_bytes = NULL, *cref_bytes = NULL, *fref_bytes = NULL, *fnt_bytes = NULL;
	*out_sz = 0;
	cn_bytes = r_bin_java_cp_get_utf8 (R_BIN_JAVA_CP_UTF8, &cn_len, (const ut8 *) cname, c_len);
	cn_idx = bin->cp_idx + 1;
	if (cn_bytes) {
		fn_bytes = r_bin_java_cp_get_utf8 (R_BIN_JAVA_CP_UTF8, &fn_len, (const ut8 *) fname, f_len);
		fn_idx = bin->cp_idx + 2;
	}
	if (fn_bytes) {
		ft_bytes = r_bin_java_cp_get_utf8 (R_BIN_JAVA_CP_UTF8, &ft_len, (const ut8 *) tname, t_len);
		ft_idx = bin->cp_idx + 3;
	}
	if (cn_bytes && fn_bytes && ft_bytes) {
		ut32 cref_len = 0, fnt_len = 0, fref_len = 0;
		ut32 cref_idx = 0, fnt_idx = 0;
		cref_bytes = r_bin_java_cp_get_classref (bin, &cref_len, NULL, 0, cn_idx);
		cref_idx = bin->cp_idx + 3;
		fnt_bytes = r_bin_java_cp_get_name_type (bin, &fnt_len, fn_idx, ft_idx);
		fnt_idx = bin->cp_idx + 4;
		fref_bytes = r_bin_java_cp_get_2_ut16 (bin, &fref_len, tag, cref_idx, fnt_idx);
		if (cref_bytes && fref_bytes && fnt_bytes) {
			total_len = cn_len + fn_len + ft_len + cref_len + fnt_len + fref_len + 2;
			if (total_len < cn_len) {
				goto beach;
			}
			bytes = calloc (1, total_len);
			// class name bytes
			if (*out_sz + cn_len >= total_len) {
				goto beach;
			}
			memcpy (bytes, cn_bytes + *out_sz, cn_len);
			*out_sz += cn_len;
			// field name bytes
			if (*out_sz + fn_len >= total_len) {
				goto beach;
			}
			memcpy (bytes, fn_bytes + *out_sz, fn_len);
			*out_sz += fn_len;
			// field type bytes
			if (*out_sz + ft_len >= total_len) {
				goto beach;
			}
			memcpy (bytes, ft_bytes + *out_sz, ft_len);
			*out_sz += ft_len;
			// class ref bytes
			if (*out_sz + cref_len >= total_len) {
				goto beach;
			}
			memcpy (bytes, cref_bytes + *out_sz, cref_len);
			*out_sz += fn_len;
			// field name and type bytes
			if (*out_sz + fnt_len >= total_len) {
				goto beach;
			}
			memcpy (bytes, fnt_bytes + *out_sz, fnt_len);
			*out_sz += fnt_len;
			// field ref bytes
			if (*out_sz + fref_len >= total_len) {
				goto beach;
			}
			memcpy (bytes, fref_bytes + *out_sz, fref_len);
			*out_sz += fref_len;
		}
	}
beach:
	free (cn_bytes);
	free (ft_bytes);
	free (fn_bytes);
	free (fnt_bytes);
	free (fref_bytes);
	free (cref_bytes);
	return bytes;
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_integer_cp_calc_size(RBinJavaCPTypeObj *obj) {
	ut64 size = 0;
	// tag
	size += 1;
	// obj->info.cp_string.string_idx = R_BIN_JAVA_USHORT (buffer, 1);
	size += 4;
	return size;
}

Project: radare2
File: class.c

R_API char *retrieve_method_access_string(ut16 flags) {
	return retrieve_access_string (flags, METHOD_ACCESS_FLAGS);
}

Project: radare2
File: class.c

R_API ut32 U(r_bin_java_swap_uint)(ut32 x) {
	const ut32 Byte0 = x & 0x000000FF;
	const ut32 Byte1 = x & 0x0000FF00;
	const ut32 Byte2 = x & 0x00FF0000;
	const ut32 Byte3 = x & 0xFF000000;
	return (Byte0 << 24) | (Byte1 << 8) | (Byte2 >> 8) | (Byte3 >> 24);
}

Project: radare2
File: class.c

R_API DsoJsonObj *r_bin_java_get_bin_obj_json(RBinJavaObj *bin) {
	DsoJsonObj *imports_list = r_bin_java_get_import_json_definitions (bin);
	DsoJsonObj *fields_list = r_bin_java_get_field_json_definitions (bin);
	DsoJsonObj *methods_list = r_bin_java_get_method_json_definitions (bin);
	// interfaces_list = r_bin_java_get_interface_json_definitions (bin);
	DsoJsonObj *class_dict = r_bin_java_get_class_info_json (bin);
	char *res = dso_json_obj_to_str (methods_list);
	// eprintf ("Resulting methods json: \n%s\n", res);
	free (res);
	dso_json_dict_insert_str_key_obj (class_dict, "methods", methods_list);
	// dso_json_list_free (methods_list);
	dso_json_obj_del (methods_list);

	res = dso_json_obj_to_str (fields_list);
	// eprintf ("Resulting fields json: \n%s\n", res);
	free (res);
	dso_json_dict_insert_str_key_obj (class_dict, "fields", fields_list);
	// dso_json_list_free (fields_list);
	dso_json_obj_del (fields_list);

	res = dso_json_obj_to_str (imports_list);
	// eprintf ("Resulting imports json: \n%s\n", res);
	free (res);
	dso_json_dict_insert_str_key_obj (class_dict, "imports", imports_list);
	// dso_json_list_free (imports_list);
	dso_json_obj_del (imports_list);

	// res = dso_json_obj_to_str (interfaces_list);
	// eprintf ("Resulting interfaces json: \n%s\n", res);
	// free (res);
	// dso_json_dict_insert_str_key_obj (class_dict, "interfaces", interfaces_list);

	res = dso_json_obj_to_str (class_dict);
	// eprintf ("Resulting class info json: \n%s\n", res);
	free (res);
	// dso_json_obj_del (class_dict);
	return class_dict;
}

Project: radare2
File: class.c

R_API void r_bin_java_do_nothing_free(void /*RBinJavaCPTypeObj*/ *obj) {
	return;
}

Project: radare2
File: class.c

R_API char *r_bin_java_get_utf8_from_cp_item_list(RList *cp_list, ut64 idx) {
	/*
	Search through the Constant Pool list for the given CP Index.
	If the idx not found by directly going to the list index,
	the list will be walked and then the IDX will be checked.
	rvalue: new char* for caller to free.
	*/
	char *value = NULL;
	RListIter *iter;
	RBinJavaCPTypeObj *item = NULL;
	if (cp_list == NULL) {
		return NULL;
	}
	item = (RBinJavaCPTypeObj *) r_list_get_n (cp_list, idx);
	if (item && item->tag == R_BIN_JAVA_CP_UTF8 && item->metas->ord == idx) {
		value = convert_string ((const char *) item->info.cp_utf8.bytes, item->info.cp_utf8.length);
	}
	if (value == NULL) {
		r_list_foreach (cp_list, iter, item) {
			if (item && (item->tag == R_BIN_JAVA_CP_UTF8) && item->metas->ord == idx) {
				value = convert_string ((const char *) item->info.cp_utf8.bytes, item->info.cp_utf8.length);
				break;
			}
		}
	}
	return value;
}

Project: radare2
File: class.c

R_API RList *retrieve_all_access_string_and_value(RBinJavaAccessFlags *access_flags) {
	const char *fmt = "%s = 0x%04x";
	RList *result = r_list_new ();
	if (!result) {
		return NULL;
	}
	result->free = free;
	int i = 0;
	for (i = 0; access_flags[i].str != NULL; i++) {
		char *str = malloc (50);
		if (!str) {
			r_list_free (result);
			return NULL;
		}
		snprintf (str, 49, fmt, access_flags[i].str, access_flags[i].value);
		r_list_append (result, str);
	}
	return result;
}

Project: radare2
File: class.c

R_API void r_bin_java_interface_free(void /*RBinJavaInterfaceInfo*/ *o) {
	RBinJavaInterfaceInfo *obj = o;
	if (obj) {
		free (obj->name);
		free (obj);
	}
}

Project: radare2
File: class.c

R_API RBinJavaAttrInfo *r_bin_java_constant_value_attr_new(ut8 *buffer, ut64 sz, ut64 buf_offset) {
	ut64 offset = 6;
	RBinJavaAttrInfo *attr = r_bin_java_default_attr_new (buffer, sz, buf_offset);
	if (attr) {
		attr->type = R_BIN_JAVA_ATTR_TYPE_CONST_VALUE_ATTR;
		attr->info.constant_value_attr.constantvalue_idx = R_BIN_JAVA_USHORT (buffer, offset);
		offset += 2;
		attr->size = offset;
	}
	// IFDBG r_bin_java_print_constant_value_attr_summary(attr);
	return attr;
}

Project: radare2
File: class.c

R_API void r_bin_java_utf8_info_free(void /* RBinJavaCPTypeObj*/ *o) {
	RBinJavaCPTypeObj *obj = o;
	if (obj) {
		free (obj->name);
		free (obj->metas);
		free (obj->info.cp_utf8.bytes);
		free (obj);
	}
}

Project: radare2
File: class.c

R_API RList *r_bin_java_get_imports(RBinJavaObj *bin) {
	RList *ret = r_list_newf (free);
	RBinImport *import = NULL;
	RListIter *iter;
	r_list_foreach (bin->imports_list, iter, import) {
		RBinImport *n_import = R_NEW0 (RBinImport);
		if (!n_import) {
			r_list_free (ret);
			return NULL;
		}
		memcpy (n_import, import, sizeof (RBinImport));
		r_list_append (ret, n_import);
	}
	return ret;
}

Project: radare2
File: class.c

R_API char *r_bin_java_print_float_cp_stringify(RBinJavaCPTypeObj *obj) {
	ut32 size = 255, consumed = 0;
	char *value = malloc (size);
	if (value) {
		memset (value, 0, size);
		consumed = snprintf (value, size, "%d.0x%04"PFMT64x ".%s.%f",
			obj->metas->ord, obj->file_offset + obj->loadaddr, ((RBinJavaCPTypeMetas *) obj->metas->type_info)->name,
			R_BIN_JAVA_FLOAT (obj->info.cp_float.bytes.raw, 0));
		if (consumed >= size - 1) {
			free (value);
			size += size >> 1;
			value = malloc (size);
			if (value) {
				memset (value, 0, size);
				consumed = snprintf (value, size, "%d.0x%04"PFMT64x ".%s.%f",
					obj->metas->ord, obj->file_offset + obj->loadaddr, ((RBinJavaCPTypeMetas *) obj->metas->type_info)->name,
					R_BIN_JAVA_FLOAT (obj->info.cp_float.bytes.raw, 0));
			}
		}
	}
	return value;
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_annotation_array_calc_size(RBinJavaAnnotationsArray *annotation_array) {
	ut64 size = 0;
	RListIter *iter = NULL, *iter_tmp = NULL;
	RBinJavaAnnotation *annotation;
	if (annotation_array->annotations == NULL) {
		// TODO eprintf
		return size;
	}
	// annotation_array->num_annotations = R_BIN_JAVA_USHORT (buffer, offset);
	size += 2;
	r_list_foreach_safe (annotation_array->annotations, iter, iter_tmp, annotation) {
		size += r_bin_java_annotation_calc_size (annotation);
	}
	return size;
}

Project: radare2
File: class.c

R_API void r_bin_java_print_deprecated_attr_summary(RBinJavaAttrInfo *attr) {
	if (!attr) {
		eprintf ("Attempting to print an invalid RBinJavaAttrInfo *Deperecated.\n");
		return;
	}
	Eprintf ("Deperecated Attribute Information:\n");
	Eprintf ("  Attribute Offset: 0x%08"PFMT64x "\n", attr->file_offset);
	Eprintf ("  Attribute Name Index: %d (%s)\n", attr->name_idx, attr->name);
	Eprintf ("  Attribute Length: %d\n", attr->length);
}

Project: radare2
File: class.c

R_API void r_bin_java_print_rtvp_annotations_attr_summary(RBinJavaAttrInfo *attr) {
	RBinJavaAnnotationsArray *annotation_array = NULL;
	RListIter *iter = NULL, *iter_tmp = NULL;
	if (attr && attr->type == R_BIN_JAVA_ATTR_TYPE_RUNTIME_VISIBLE_PARAMETER_ANNOTATION_ATTR) {
		eprintf ("Runtime Visible Parameter Annotations Attribute Information:\n");
		eprintf ("  Attribute Offset: 0x%08"PFMT64x "\n", attr->file_offset);
		eprintf ("  Attribute Name Index: %d (%s)\n", attr->name_idx, attr->name);
		eprintf ("  Attribute Length: %d\n", attr->length);
		eprintf ("  Number of Runtime Invisible Parameters: %d\n", attr->info.rtvp_annotations_attr.num_parameters);
		r_list_foreach_safe (attr->info.rtvp_annotations_attr.parameter_annotations, iter, iter_tmp, annotation_array) {
			r_bin_java_print_annotation_array_summary (annotation_array);
		}
	}
}

Project: radare2
File: class.c

R_API RBinJavaAttrInfo *r_bin_java_rtvp_annotations_attr_new(ut8 *buffer, ut64 sz, ut64 buf_offset) {
	ut32 i = 0;
	RBinJavaAttrInfo *attr = NULL;
	ut64 offset = 0;
	attr = r_bin_java_default_attr_new (buffer, sz, buf_offset);
	offset += 6;
	RBinJavaAnnotationsArray *annotation_array;
	if (attr) {
		attr->type = R_BIN_JAVA_ATTR_TYPE_RUNTIME_VISIBLE_PARAMETER_ANNOTATION_ATTR;
		attr->info.rtvp_annotations_attr.num_parameters = buffer[offset];
		offset += 1;
		attr->info.rtvp_annotations_attr.parameter_annotations = r_list_newf (r_bin_java_annotation_array_free);
		for (i = 0; i < attr->info.rtvp_annotations_attr.num_parameters; i++) {
			annotation_array = r_bin_java_annotation_array_new (buffer + offset, sz - offset, buf_offset + offset);
			if (annotation_array == NULL) {}
			if (annotation_array) {
				offset += annotation_array->size;
			}
			r_list_append (attr->info.rtvp_annotations_attr.parameter_annotations, (void *) annotation_array);
		}
		attr->size = offset;
	}
	return attr;
}

Project: radare2
File: class.c

R_API char *r_bin_java_get_item_name_from_bin_cp_list(RBinJavaObj *bin, RBinJavaCPTypeObj *obj) {
	char *res = NULL;
	/*
	Given a constant poool object Class, FieldRef, MethodRef, or InterfaceMethodRef
	return the actual descriptor string.
	@param cp_list: RList of RBinJavaCPTypeObj *
	@param obj object to look up the name for
	@rvalue char* (user frees) or NULL
	*/
	if (bin && obj) {
		res = r_bin_java_get_item_name_from_cp_item_list (
			bin->cp_list, obj, MAX_CPITEMS);
	}
	return res;
}

Project: radare2
File: class.c

R_API char *r_bin_java_print_name_and_type_cp_stringify(RBinJavaCPTypeObj *obj) {
	ut32 size = 255, consumed = 0;
	char *value = malloc (size);
	if (value) {
		memset (value, 0, size);
		consumed = snprintf (value, size, "%d.0x%04"PFMT64x ".%s.%d.%d",
			obj->metas->ord, obj->file_offset + obj->loadaddr, ((RBinJavaCPTypeMetas *) obj->metas->type_info)->name,
			obj->info.cp_name_and_type.name_idx,
			obj->info.cp_name_and_type.descriptor_idx);
		if (consumed >= size - 1) {
			free (value);
			size += size >> 1;
			value = malloc (size);
			if (value) {
				memset (value, 0, size);
				consumed = snprintf (value, size, "%d.0x%04"PFMT64x ".%s.%d.%d",
					obj->metas->ord, obj->file_offset + obj->loadaddr, ((RBinJavaCPTypeMetas *) obj->metas->type_info)->name,
					obj->info.cp_name_and_type.name_idx,
					obj->info.cp_name_and_type.descriptor_idx);
			}
		}
	}
	return value;
}

Project: radare2
File: class.c

R_API void r_bin_java_constant_value_attr_free(void /*RBinJavaAttrInfo*/ *a) {
	RBinJavaAttrInfo *attr = a;
	if (attr) {
		free (attr->name);
		free (attr->metas);
		free (attr);
	}
}

Project: radare2
File: class.c

R_API RBinJavaAttrInfo *r_bin_java_local_variable_table_attr_new(ut8 *buffer, ut64 sz, ut64 buf_offset) {
	RBinJavaLocalVariableAttribute *lvattr;
	ut64 curpos = 0, offset = 6;
	RBinJavaAttrInfo *attr;
	ut32 i = 0;
	if (!buffer || sz < 1) {
		return NULL;
	}
	attr = r_bin_java_default_attr_new (buffer, sz, buf_offset);
	if (!attr) {
		return NULL;
	}
	attr->type = R_BIN_JAVA_ATTR_TYPE_LOCAL_VARIABLE_TABLE_ATTR;
	attr->info.local_variable_table_attr.table_length = R_BIN_JAVA_USHORT (buffer, offset);
	offset += 2;
	attr->info.local_variable_table_attr.local_variable_table =\
		r_list_newf (r_bin_java_local_variable_table_attr_entry_free);
	for (i = 0; i < attr->info.local_variable_table_attr.table_length; i++) {
		if (offset + 10 > sz) {
			break;
		}
		curpos = buf_offset + offset;
		lvattr = R_NEW0 (RBinJavaLocalVariableAttribute);
		lvattr->start_pc = R_BIN_JAVA_USHORT (buffer, offset);
		offset += 2;
		lvattr->length = R_BIN_JAVA_USHORT (buffer, offset);
		offset += 2;
		lvattr->name_idx = R_BIN_JAVA_USHORT (buffer, offset);
		offset += 2;
		lvattr->descriptor_idx = R_BIN_JAVA_USHORT (buffer, offset);
		offset += 2;
		lvattr->index = R_BIN_JAVA_USHORT (buffer, offset);
		offset += 2;
		lvattr->file_offset = curpos;
		lvattr->name = r_bin_java_get_utf8_from_bin_cp_list (R_BIN_JAVA_GLOBAL_BIN, lvattr->name_idx);
		lvattr->size = 10;
		if (!lvattr->name) {
			lvattr->name = strdup ("NULL");
			eprintf ("r_bin_java_local_variable_table_attr_new: Unable to find the name for %d index.\n", lvattr->name_idx);
		}
		lvattr->descriptor = r_bin_java_get_utf8_from_bin_cp_list (R_BIN_JAVA_GLOBAL_BIN, lvattr->descriptor_idx);
		if (!lvattr->descriptor) {
			lvattr->descriptor = strdup ("NULL");
			eprintf ("r_bin_java_local_variable_table_attr_new: Unable to find the descriptor for %d index.\n", lvattr->descriptor_idx);
		}
		r_list_append (attr->info.local_variable_table_attr.local_variable_table, lvattr);
	}
	attr->size = offset;
	// IFDBG r_bin_java_print_local_variable_table_attr_summary(attr);
	return attr;
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_stack_map_frame_calc_size(RBinJavaStackMapFrame *sf) {
	ut64 size = 0;
	RListIter *iter, *iter_tmp;
	RBinJavaVerificationObj *se;
	if (sf) {
		// sf->tag = buffer[offset];
		size += 1;
		switch (sf->type) {
		case R_BIN_JAVA_STACK_FRAME_SAME:
			// Nothing to read
			break;
		case R_BIN_JAVA_STACK_FRAME_SAME_LOCALS_1:
			r_list_foreach_safe (sf->stack_items, iter, iter_tmp, se) {
				size += rbin_java_verification_info_calc_size (se);
			}
			break;
		case R_BIN_JAVA_STACK_FRAME_CHOP:
			// sf->offset_delta = R_BIN_JAVA_USHORT (buffer, offset);
			size += 2;
			break;
		case R_BIN_JAVA_STACK_FRAME_SAME_FRAME_EXTENDED:
			// sf->offset_delta = R_BIN_JAVA_USHORT (buffer, offset);
			size += 2;
			r_list_foreach_safe (sf->stack_items, iter, iter_tmp, se) {
				size += rbin_java_verification_info_calc_size (se);
			}
			break;
		case R_BIN_JAVA_STACK_FRAME_APPEND:
			// sf->offset_delta = R_BIN_JAVA_USHORT (buffer, offset);
			size += 2;
			r_list_foreach_safe (sf->stack_items, iter, iter_tmp, se) {
				size += rbin_java_verification_info_calc_size (se);
			}
			break;
		case R_BIN_JAVA_STACK_FRAME_FULL_FRAME:
			// sf->offset_delta = R_BIN_JAVA_USHORT (buffer, offset);
			size += 2;
			// sf->number_of_locals = R_BIN_JAVA_USHORT (buffer, offset);
			size += 2;
			r_list_foreach_safe (sf->local_items, iter, iter_tmp, se) {
				size += rbin_java_verification_info_calc_size (se);
			}
			// sf->number_of_stack_items = R_BIN_JAVA_USHORT (buffer, offset);
			size += 2;
			r_list_foreach_safe (sf->stack_items, iter, iter_tmp, se) {
				size += rbin_java_verification_info_calc_size (se);
			}
			break;
		default:
			eprintf ("Unknown type\n");
			break;
		}
	}
	return size;
}

Project: radare2
File: class.c

R_API void r_bin_java_source_debug_attr_free(void /*RBinJavaAttrInfo*/ *a) {
	RBinJavaAttrInfo *attr = a;
	if (attr) {
		free (attr->name);
		free (attr->metas);
		free (attr->info.debug_extensions.debug_extension);
		free (attr);
	}
}

Project: radare2
File: class.c

R_API void r_bin_java_print_bootstrap_methods_attr_summary(RBinJavaAttrInfo *attr) {
	RListIter *iter, *iter_tmp;
	RBinJavaBootStrapMethod *obj = NULL;
	if (attr == NULL || attr->type == R_BIN_JAVA_ATTR_TYPE_BOOTSTRAP_METHODS_ATTR) {
		eprintf ("Unable to print attribue summary for RBinJavaAttrInfo *RBinJavaBootstrapMethodsAttr");
		return;
	}
	eprintf ("Bootstrap Methods Attribute Information Information:\n");
	eprintf ("	Attribute Offset: 0x%08"PFMT64x"", attr->file_offset);
	eprintf ("	Length: 0x%08x", attr->length);
	eprintf ("	Number of Method Arguments = (0x%02x)\n", attr->info.bootstrap_methods_attr.num_bootstrap_methods);
	if (attr->info.bootstrap_methods_attr.bootstrap_methods) {
		r_list_foreach_safe (attr->info.bootstrap_methods_attr.bootstrap_methods, iter, iter_tmp, obj) {
			if (obj) {
				r_bin_java_print_bootstrap_method_summary (obj);
			}
		}
	} else {
		eprintf ("	Bootstrap Methods: NONE \n");
	}
}

Project: radare2
File: class.c

R_API void r_bin_java_print_annotation_array_summary(RBinJavaAnnotationsArray *annotation_array) {
	RListIter *iter = NULL, *iter_tmp = NULL;
	RBinJavaAnnotation *annotation;
	if (annotation_array->annotations == NULL) {
		// TODO eprintf
		return;
	}
	eprintf ("   Annotation Array Information:\n");
	eprintf ("   Number of Annotation Array Elements: %d\n", annotation_array->num_annotations);
	r_list_foreach_safe (annotation_array->annotations, iter, iter_tmp, annotation) {
		r_bin_java_print_annotation_summary (annotation);
	}
}

Project: radare2
File: class.c

R_API RBinJavaAttrInfo *r_bin_java_source_code_file_attr_new(ut8 *buffer, ut64 sz, ut64 buf_offset) {
	if (!sz) {
		return NULL;
	}
	ut64 offset = 0;
	RBinJavaAttrInfo *attr = r_bin_java_default_attr_new (buffer, sz, buf_offset);
	offset += 6;
	if (!attr) {
		return NULL;
	}
	attr->type = R_BIN_JAVA_ATTR_TYPE_SOURCE_FILE_ATTR;
	// if (buffer + offset > buffer + sz) return NULL;
	attr->info.source_file_attr.sourcefile_idx = R_BIN_JAVA_USHORT (buffer, offset);
	offset += 2;
	attr->size = offset;
	// IFDBG r_bin_java_print_source_code_file_attr_summary(attr);
	return attr;
}

Project: radare2
File: class.c

R_API void r_bin_java_print_unknown_attr_summary(RBinJavaAttrInfo *attr) {
	if (attr == NULL) {
		eprintf ("Attempting to print an invalid RBinJavaAttrInfo *Unknown.\n");
		return;
	}
	Eprintf ("Unknown Attribute Information:\n");
	Eprintf ("  Attribute Offset: 0x%08"PFMT64x "\n", attr->file_offset);
	Eprintf ("  Attribute Name Index: %d (%s)\n", attr->name_idx, attr->name);
	Eprintf ("  Attribute Length: %d\n", attr->length);
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_calc_class_size(ut8 *bytes, ut64 size) {
	RBinJavaObj *bin = R_NEW0 (RBinJavaObj);
	if (!bin) {
		return false;
	}
	RBinJavaObj *cur_bin = R_BIN_JAVA_GLOBAL_BIN;
	ut64 bin_size = UT64_MAX;
	if (bin) {
		if (r_bin_java_load_bin (bin, bytes, size)) {
			bin_size = bin->calc_size;
		}
		r_bin_java_free (bin);
		R_BIN_JAVA_GLOBAL_BIN = cur_bin;
	}
	return bin_size;
}

Project: radare2
File: class.c

R_API int r_bin_java_resolve_cp_idx_print_summary(RBinJavaObj *BIN_OBJ, int idx) {
	RBinJavaCPTypeObj *item = NULL;
	if (BIN_OBJ && BIN_OBJ->cp_count < 1) {
		return false;
	}
	item = (RBinJavaCPTypeObj *) r_bin_java_get_item_from_bin_cp_list (BIN_OBJ, idx);
	if (item) {
		((RBinJavaCPTypeMetas *)
		item->metas->type_info)->
		allocs->print_summary (item);
	} else {
		eprintf ("Error: Invalid CP Object.\n");
	}
	return item ? true : false;
}

Project: radare2
File: class.c

R_API RBinJavaBootStrapMethod *r_bin_java_bootstrap_method_new(ut8 *buffer, ut64 sz, ut64 buf_offset) {
	RBinJavaBootStrapMethod *bsm = NULL;
	RBinJavaBootStrapArgument *bsm_arg = NULL;
	ut32 i = 0;
	ut64 offset = 0;
	bsm = (RBinJavaBootStrapMethod *) malloc (sizeof (RBinJavaBootStrapMethod));
	if (bsm == NULL) {
		// TODO eprintf failed to allocate bytes for bootstrap_method.
		return bsm;
	}
	memset (bsm, 0, sizeof (RBinJavaBootStrapMethod));
	bsm->file_offset = buf_offset;
	bsm->bootstrap_method_ref = R_BIN_JAVA_USHORT (buffer, offset);
	offset += 2;
	bsm->num_bootstrap_arguments = R_BIN_JAVA_USHORT (buffer, offset);
	offset += 2;
	bsm->bootstrap_arguments = r_list_new ();
	for (i = 0; i < bsm->num_bootstrap_arguments; i++) {
		// bsm_arg = r_bin_java_bootstrap_method_argument_new (bin, bin->b->cur);
		bsm_arg = r_bin_java_bootstrap_method_argument_new (buffer + offset, sz - offset, buf_offset + offset);
		if (bsm_arg) {
			offset += bsm_arg->size;
			r_list_append (bsm->bootstrap_arguments, (void *) bsm_arg);
		} else {
			// TODO eprintf Failed to read the %d boot strap method.
		}
	}
	bsm->size = offset;
	return bsm;
}

Project: radare2
File: class.c

R_API RList *U(r_bin_java_get_args_from_bin)(RBinJavaObj * bin_obj, ut64 addr) {
	RBinJavaField *fm_type = r_bin_java_get_method_code_attribute_with_addr (bin_obj, addr);
	return fm_type ? r_bin_java_get_args (fm_type) : NULL;
}

Project: radare2
File: class.c

R_API void r_bin_java_print_line_number_table_attr_summary(RBinJavaAttrInfo *attr) {
	RBinJavaLineNumberAttribute *lnattr;
	RListIter *iter, *iter_tmp;
	if (!attr) {
		eprintf ("Attempting to print an invalid RBinJavaAttrInfo *LineNumberTable.\n");
		return;
	}
	Eprintf ("Line Number Table Attribute Information:\n");
	Eprintf ("  Attribute Offset: 0x%08"PFMT64x "\n", attr->file_offset);
	Eprintf ("  Attribute Name Index: %d (%s)\n", attr->name_idx, attr->name);
	Eprintf ("  Attribute Length: %d\n", attr->length);
	r_list_foreach_safe (attr->info.line_number_table_attr.line_number_table, iter, iter_tmp, lnattr) {
		r_bin_java_print_line_number_attr_summary (lnattr);
	}
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_source_debug_attr_calc_size(RBinJavaAttrInfo *attr) {
	ut64 size = 6;
	if (!attr) {
		return 0LL;
	}
	if (attr->info.debug_extensions.debug_extension) {
		size += attr->length;
	}
	return size;
}

Project: radare2
File: class.c

R_API char *get_type_value_str(const char *arg_str, ut8 array_cnt) {
	ut32 str_len = array_cnt ? (array_cnt + 1) * 2 + strlen (arg_str) : strlen (arg_str);
	char *str = malloc (str_len + 1);
	ut32 bytes_written = snprintf (str, str_len + 1, "%s", arg_str);
	while (array_cnt > 0) {
		bytes_written = snprintf (str + bytes_written, str_len - bytes_written, "[]");
		array_cnt--;
	}
	return str;
}

Project: radare2
File: class.c

R_API RBinJavaAttrInfo *r_bin_java_get_attr_from_field(RBinJavaField *field, R_BIN_JAVA_ATTR_TYPE attr_type, ut32 pos) {
	/*
	Search through the Attribute list for the given type starting at position pos.
	rvalue: NULL or the first occurrence of attr_type after pos
	*/
	RBinJavaAttrInfo *attr = NULL, *item;
	RListIter *iter;
	ut32 i = 0;
	if (field) {
		r_list_foreach (field->attributes, iter, item) {
			// Note the increment happens after the comparison
			if ((i++) >= pos) {
				if (item && (item->type == attr_type)) {
					attr = item;
					break;
				}
			}
		}
	}
	return attr;
}

Project: radare2
File: class.c

R_API char *r_bin_java_get_name_from_bin_cp_list(RBinJavaObj *bin, ut64 idx) {
	/*
	Search through the Constant Pool list for the given CP Index.
	If the idx not found by directly going to the list index,
	the list will be walked and then the IDX will be checked.
	rvalue: new char* for caller to free.
	*/
	if (bin == NULL) {
		return NULL;
	}
	return r_bin_java_get_name_from_cp_item_list (bin->cp_list, idx);
}

Project: radare2
File: class.c

R_API char *r_bin_java_resolve_cp_idx_type(RBinJavaObj *BIN_OBJ, int idx) {
	RBinJavaCPTypeObj *item = NULL;
	char *str = NULL;
	if (BIN_OBJ && BIN_OBJ->cp_count < 1) {
		// r_bin_java_new_bin(BIN_OBJ);
		return NULL;
	}
	item = (RBinJavaCPTypeObj *) r_bin_java_get_item_from_bin_cp_list (BIN_OBJ, idx);
	if (item) {
		str = strdup (((RBinJavaCPTypeMetas *) item->metas->type_info)->name);
	} else {
		str = strdup ("INVALID");
	}
	return str;
}

Project: radare2
File: class.c

R_API ut16 r_bin_java_find_cp_class_ref_from_name_idx(RBinJavaObj *bin, ut16 name_idx) {
	ut16 pos, len = (ut16) r_list_length (bin->cp_list);
	RBinJavaCPTypeObj *item;
	for (pos = 0; pos < len; pos++) {
		item = (RBinJavaCPTypeObj *) r_list_get_n (bin->cp_list, pos);
		if (item && item->tag == R_BIN_JAVA_CP_CLASS && item->info.cp_class.name_idx == name_idx) {
			break;
		}
	}
	return (pos != len) ? pos : 0;
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_raw_to_long(const ut8 *raw, ut64 offset) {
	return R_BIN_JAVA_LONG (raw, offset);
}

Project: radare2
File: class.c

R_API RBinJavaCPTypeObj *r_bin_java_long_cp_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz) {
	ut8 tag = buffer[0];
	RBinJavaCPTypeObj *obj = NULL;
	int quick_check = 0;
	quick_check = r_bin_java_quick_check (R_BIN_JAVA_CP_LONG, tag, sz, "Long");
	if (quick_check > 0) {
		return obj;
	}
	obj = (RBinJavaCPTypeObj *) malloc (sizeof (RBinJavaCPTypeObj));
	if (obj) {
		memset (obj, 0, sizeof (RBinJavaCPTypeObj));
		obj->tag = tag;
		obj->metas = R_NEW0 (RBinJavaMetaInfo);
		obj->metas->type_info = (void *) &R_BIN_JAVA_CP_METAS[tag];
		obj->name = r_str_dup (NULL, (const char *) R_BIN_JAVA_CP_METAS[tag].name);
		memset (&obj->info.cp_long.bytes, 0, sizeof (obj->info.cp_long.bytes));
		memcpy (&(obj->info.cp_long.bytes), buffer + 1, 8);

	}
	return obj;
}

Project: radare2
File: class.c

R_API int r_bin_java_is_fm_type_protected(RBinJavaField *fm_type) {
	if (fm_type && fm_type->type == R_BIN_JAVA_FIELD_TYPE_METHOD) {
		return fm_type->flags & R_BIN_JAVA_METHOD_ACC_PROTECTED;
	}
	if (fm_type && fm_type->type == R_BIN_JAVA_FIELD_TYPE_FIELD) {
		return fm_type->flags & R_BIN_JAVA_FIELD_ACC_PROTECTED;
	}
	return 0;
}

Project: radare2
File: class.c

R_API RList *r_bin_java_get_symbols(RBinJavaObj *bin) {
	RListIter *iter = NULL, *iter_tmp = NULL;
	RList *imports, *symbols = r_list_newf (free);
	RBinSymbol *sym = NULL;
	RBinImport *imp;
	RBinJavaField *fm_type;
	r_list_foreach_safe (bin->methods_list, iter, iter_tmp, fm_type) {
		sym = r_bin_java_create_new_symbol_from_field (fm_type, bin->loadaddr);
		if (sym) {
			r_list_append (symbols, (void *) sym);
		}
		sym = r_bin_java_create_new_symbol_from_fm_type_meta (fm_type, bin->loadaddr);
		if (sym) {
			r_list_append (symbols, (void *) sym);
		}
	}
	r_list_foreach_safe (bin->fields_list, iter, iter_tmp, fm_type) {
		sym = r_bin_java_create_new_symbol_from_field (fm_type, bin->loadaddr);
		if (sym) {
			r_list_append (symbols, (void *) sym);
		}
		sym = r_bin_java_create_new_symbol_from_fm_type_meta (fm_type, bin->loadaddr);
		if (sym) {
			r_list_append (symbols, (void *) sym);
		}
	}
	bin->lang = "java";
	imports = r_bin_java_get_imports (bin);
	r_list_foreach (imports, iter, imp) {
		sym = R_NEW0 (RBinSymbol);
		if (!sym) {
			break;
		}
		if (imp->classname && !strncmp (imp->classname, "kotlin/jvm", 10)) {
			bin->lang = "kotlin";
		}
		sym->name = r_str_newf ("imp.%s", imp->name);
		if (!sym->name) {
			free (sym);
			break;
		}
		sym->type = r_str_const ("import");
		if (!sym->type) {
			free (sym);
			break;
		}
		sym->vaddr = sym->paddr = imp->ordinal;
		sym->ordinal = imp->ordinal;
		r_list_append (symbols, (void *) sym);
	}
	r_list_free (imports);
	return symbols;
}

Project: radare2
File: class.c

R_API RBinJavaAttrInfo *r_bin_java_line_number_table_attr_new(ut8 *buffer, ut64 sz, ut64 buf_offset) {
	ut32 i = 0;
	ut64 curpos, offset = 0;
	RBinJavaLineNumberAttribute *lnattr;
	RBinJavaAttrInfo *attr = r_bin_java_default_attr_new (buffer, sz, buf_offset);
	if (!attr) {
		return NULL;
	}
	offset += 6;
	attr->type = R_BIN_JAVA_ATTR_TYPE_LINE_NUMBER_TABLE_ATTR;
	attr->info.line_number_table_attr.line_number_table_length = R_BIN_JAVA_USHORT (buffer, offset);
	offset += 2;
	attr->info.line_number_table_attr.line_number_table = r_list_newf (free);

	ut32 linenum_len = attr->info.line_number_table_attr.line_number_table_length;
	RList *linenum_list = attr->info.line_number_table_attr.line_number_table;
	for (i = 0; i < linenum_len; i++) {
		curpos = buf_offset + offset;
		// printf ("%llx %llx \n", curpos, sz);
		// XXX if (curpos + 8 >= sz) break;
		lnattr = R_NEW0 (RBinJavaLineNumberAttribute);
		if (!lnattr) {
			break;
		}
		// wtf it works
		if (offset - 2 > sz) {
			break;
		}
		lnattr->start_pc = R_BIN_JAVA_USHORT (buffer, offset);
		offset += 2;
		lnattr->line_number = R_BIN_JAVA_USHORT (buffer, offset);
		offset += 2;
		lnattr->file_offset = curpos;
		lnattr->size = 4;
		r_list_append (linenum_list, lnattr);
	}
	attr->size = offset;
	return attr;
}

Project: radare2
File: class.c

R_API char *r_bin_java_build_obj_key(RBinJavaObj *bin) {
	char *jvcname = NULL;
	char *cname = r_bin_java_get_this_class_name (bin);
	ut32 class_name_len = cname ? strlen (cname) : strlen ("_unknown_");
	jvcname = malloc (class_name_len + 8 + 30);
	if (cname) {
		snprintf (jvcname, class_name_len + 30, "%d.%s.class", bin->id, cname);
		free (cname);
	} else {
		snprintf (jvcname, class_name_len + 30, "%d._unknown_.class", bin->id);
	}
	return jvcname;
}

Project: radare2
File: class.c

R_API RBinJavaAttrInfo *r_bin_java_rti_annotations_attr_new(ut8 *buffer, ut64 sz, ut64 buf_offset) {
	ut32 i = 0;
	RBinJavaAttrInfo *attr = NULL;
	ut64 offset = 0;
	attr = r_bin_java_default_attr_new (buffer, sz, buf_offset);
	offset += 6;
	if (attr) {
		attr->type = R_BIN_JAVA_ATTR_TYPE_RUNTIME_INVISIBLE_ANNOTATION_ATTR;
		attr->info.annotation_array.num_annotations = R_BIN_JAVA_USHORT (buffer, offset);
		offset += 2;
		attr->info.annotation_array.annotations = r_list_newf (r_bin_java_annotation_free);
		for (i = 0; i < attr->info.rtv_annotations_attr.num_annotations; i++) {
			RBinJavaAnnotation *annotation = r_bin_java_annotation_new (buffer + offset, sz - offset, buf_offset + offset);
			if (annotation) {
				offset += annotation->size;
			}
			r_list_append (attr->info.annotation_array.annotations, (void *) annotation);
		}
		attr->size = offset;
	}
	return attr;
}

Project: radare2
File: class.c

static char *convert_string(const char *bytes, ut32 len) {
	ut32 idx = 0, pos = 0;
	ut32 str_sz = 32 * len + 1;
	char *cpy_buffer = len > 0 ? malloc (str_sz) : NULL;
	if (!cpy_buffer) {
		return cpy_buffer;
	}
	// 4x is the increase from byte to \xHH where HH represents hexed byte
	memset (cpy_buffer, 0, str_sz);
	while (idx < len && pos < len) {
		if (dso_json_char_needs_hexing (bytes[idx])) {
			if (pos + 2 < len) {
				free (cpy_buffer);
				return NULL;
			}
			sprintf (cpy_buffer + pos, "\\x%02x", bytes[idx]);
			pos += 4;
		} else {
			cpy_buffer[pos] = bytes[idx];
			pos++;
		}
		idx++;
	}
	return cpy_buffer;
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_get_method_end(RBinJavaObj *bin, RBinJavaField *fm_type) {
	return r_bin_java_get_method_code_offset (fm_type) + bin->loadaddr +
	+r_bin_java_get_method_code_size (fm_type);
}

Project: radare2
File: class.c

R_API void r_bin_java_stack_map_table_attr_free(void /*RBinJavaAttrInfo*/ *a) {
	RBinJavaAttrInfo *attr = a;
	if (attr) {
		free (attr->name);
		free (attr->metas);
		r_list_free (attr->info.stack_map_table_attr.stack_map_frame_entries);
		free (attr);
	}
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_annotation_default_attr_calc_size(RBinJavaAttrInfo *attr) {
	ut64 size = 0;
	if (attr) {
		// attr = r_bin_java_default_attr_new (buffer, sz, buf_offset);
		size += 6;
		// attr->info.annotation_default_attr.default_value = r_bin_java_element_value_new (buffer+offset, sz-offset, buf_offset+offset);
		size += r_bin_java_element_value_calc_size (attr->info.annotation_default_attr.default_value);
	}
	return size;
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_find_method_offset(RBinJavaObj *bin, const char *method_name) {
	RListIter *attr_iter = NULL, *attr_iter_tmp = NULL;
	RBinJavaField *method = NULL;
	ut64 offset = -1;
	r_list_foreach_safe (bin->methods_list, attr_iter, attr_iter_tmp, method) {
		if (method && !strcmp ((const char *) method->name, method_name)) {
			offset = r_bin_java_get_method_code_offset (method) + bin->loadaddr;
			break;
		}
	}
	return offset;
}

Project: radare2
File: class.c

R_API int U(r_bin_java_long_cp_set)(RBinJavaObj * bin, ut16 idx, ut64 val) {
	RBinJavaCPTypeObj *cp_obj = r_bin_java_get_item_from_bin_cp_list (bin, idx);
	if (!cp_obj) {
		return false;
	}
	ut8 bytes[8] = {
		0
	};
	if (cp_obj->tag != R_BIN_JAVA_CP_LONG && cp_obj->tag != R_BIN_JAVA_CP_DOUBLE) {
		eprintf ("Not supporting the overwrite of CP Objects with one of a different size.\n");
		return false;
	}
	r_bin_java_check_reset_cp_obj (cp_obj, R_BIN_JAVA_CP_LONG);
	cp_obj->tag = R_BIN_JAVA_CP_LONG;
	memcpy (bytes, (const char *) &val, 8);
	val = r_bin_java_raw_to_long (bytes, 0);
	memcpy (&cp_obj->info.cp_long.bytes.raw, (const char *) &val, 8);
	return true;
}

Project: radare2
File: class.c

R_API RBinJavaCPTypeObj *r_bin_java_methodref_cp_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz) {
	ut8 tag = buffer[0];
	RBinJavaCPTypeObj *obj = NULL;
	int quick_check = 0;
	quick_check = r_bin_java_quick_check (R_BIN_JAVA_CP_METHODREF, tag, sz, "MethodRef");
	if (quick_check > 0) {
		return obj;
	}
	obj = (RBinJavaCPTypeObj *) malloc (sizeof (RBinJavaCPTypeObj));
	if (obj) {
		memset (obj, 0, sizeof (RBinJavaCPTypeObj));
		obj->tag = tag;
		obj->metas = R_NEW0 (RBinJavaMetaInfo);
		obj->metas->type_info = (void *) &R_BIN_JAVA_CP_METAS[tag];
		obj->info.cp_method.class_idx = R_BIN_JAVA_USHORT (buffer, 1);
		obj->info.cp_method.name_and_type_idx = R_BIN_JAVA_USHORT (buffer, 3);
	}
	return obj;
}

Project: radare2
File: class.c

R_API RBinJavaAttrInfo *r_bin_java_annotation_default_attr_new(ut8 *buffer, ut64 sz, ut64 buf_offset) {
	ut64 offset = 0;
	RBinJavaAttrInfo *attr = NULL;
	attr = r_bin_java_default_attr_new (buffer, sz, buf_offset);
	offset += 6;
	if (attr) {
		attr->type = R_BIN_JAVA_ATTR_TYPE_ANNOTATION_DEFAULT_ATTR;
		attr->info.annotation_default_attr.default_value = r_bin_java_element_value_new (buffer + offset, sz - offset, buf_offset + offset);
		if (attr->info.annotation_default_attr.default_value) {
			offset += attr->info.annotation_default_attr.default_value->size;
		}
	}
	r_bin_java_print_annotation_default_attr_summary (attr);
	return attr;
}

Project: radare2
File: class.c

R_API void U(add_field_infos_to_sdb)(RBinJavaObj * bin) {
	/*
	*** Experimental and May Change ***
	Add field information to an Array
	the key for this info variable depenedent on addr, method ordinal, etc.
	Key 1, mapping to method key:
	java.<file_offset> = <field_key>
	Key 3, method description
	<field_key>.info = [<access str>, <class_name>, <name>, <signature>]
	key 4, method meta
	<field_key>.meta = [<file_offset>, ?]
	*/
	RListIter *iter = NULL, *iter_tmp = NULL;
	RBinJavaField *fm_type;
	ut32 key_size = 255,
	value_buffer_size = 1024,
	class_name_inheap = 1;
	char *field_key = NULL,
	*field_key_value = NULL,
	*value_buffer = NULL;
	char *class_name = r_bin_java_get_this_class_name (bin);
	if (class_name == NULL) {
		class_name = "unknown";
		class_name_inheap = 0;
	}
	key_size += strlen (class_name);
	value_buffer_size += strlen (class_name);
	field_key = malloc (key_size);
	value_buffer = malloc (value_buffer_size);
	field_key_value = malloc (key_size);
	snprintf (field_key, key_size, "%s.methods", class_name);
	field_key[key_size - 1] = 0;
	r_list_foreach_safe (bin->fields_list, iter, iter_tmp, fm_type) {
		char number_buffer[80];
		ut64 file_offset = fm_type->file_offset + bin->loadaddr;
		snprintf (number_buffer, sizeof (number_buffer), "0x%04"PFMT64x, file_offset);
		IFDBG eprintf("Inserting: []%s = %s\n", field_key, number_buffer);
		sdb_array_push (bin->kv, field_key, number_buffer, 0);
	}
	r_list_foreach_safe (bin->fields_list, iter, iter_tmp, fm_type) {
		ut64 field_offset = fm_type->file_offset + bin->loadaddr;
		// generate method specific key & value
		snprintf (field_key, key_size, "%s.0x%04"PFMT64x, class_name, field_offset);
		field_key[key_size - 1] = 0;
		snprintf (field_key_value, key_size, "%s.0x%04"PFMT64x ".field", class_name, field_offset);
		field_key_value[key_size - 1] = 0;
		sdb_set (bin->kv, field_key, field_key_value, 0);
		IFDBG eprintf("Inserting: %s = %s\n", field_key, field_key_value);
		// generate info key, and place values in method info array
		snprintf (field_key, key_size, "%s.info", field_key_value);
		field_key[key_size - 1] = 0;
		snprintf (value_buffer, value_buffer_size, "%s", fm_type->flags_str);
		value_buffer[value_buffer_size - 1] = 0;
		sdb_array_push (bin->kv, field_key, value_buffer, 0);
		IFDBG eprintf("Inserting: []%s = %s\n", field_key, value_buffer);
		snprintf (value_buffer, value_buffer_size, "%s", fm_type->class_name);
		value_buffer[value_buffer_size - 1] = 0;
		sdb_array_push (bin->kv, field_key, value_buffer, 0);
		IFDBG eprintf("Inserting: []%s = %s\n", field_key, value_buffer);
		snprintf (value_buffer, value_buffer_size, "%s", fm_type->name);
		value_buffer[value_buffer_size - 1] = 0;
		sdb_array_push (bin->kv, field_key, value_buffer, 0);
		IFDBG eprintf("Inserting: []%s = %s\n", field_key, value_buffer);
		snprintf (value_buffer, value_buffer_size, "%s", fm_type->descriptor);
		value_buffer[value_buffer_size - 1] = 0;
		sdb_array_push (bin->kv, field_key, value_buffer, 0);
		IFDBG eprintf("Inserting: []%s = %s\n", field_key, value_buffer);
	}
	free (field_key);
	free (field_key_value);
	free (value_buffer);
	if (class_name_inheap) {
		free (class_name);
	}
}

Project: radare2
File: class.c

R_API void r_bin_java_local_variable_type_table_attr_entry_free(void /*RBinJavaLocalVariableTypeAttribute*/ *a) {
	RBinJavaLocalVariableTypeAttribute *attr = a;
	if (attr) {
		free (attr->name);
		free (attr->signature);
		free (attr);
	}
}

Project: radare2
File: class.c

R_API void r_bin_java_print_source_debug_attr_summary(RBinJavaAttrInfo *attr) {
	ut32 i = 0;
	if (attr == NULL) {
		eprintf ("Attempting to print an invalid RBinJavaSourceDebugExtensionAttr *.\n");
		return;
	}
	Eprintf ("Source Debug Extension Attribute Information:\n");
	Eprintf ("  Attribute Offset: 0x%08"PFMT64x "\n", attr->file_offset);
	Eprintf ("  Attribute Name Index: %d (%s)\n", attr->name_idx, attr->name);
	Eprintf ("  Extension Length: %d\n", attr->length);
	Eprintf ("  Source Debug Extension value: \n");
	for (i = 0; i < attr->length; i++) {
		Eprintf ("%c", attr->info.debug_extensions.debug_extension[i]);
	}
	Eprintf ("\n  Source Debug Extension End\n");
}

Project: radare2
File: class.c

R_API char *r_bin_java_unmangle_without_flags(const char *name, const char *descriptor) {
	return r_bin_java_unmangle (NULL, name, descriptor);
}

Project: radare2
File: class.c

R_API DsoJsonObj *r_bin_java_get_field_json_definitions(RBinJavaObj *bin) {
	RBinJavaField *fm_type = NULL;
	RListIter *iter = NULL;
	DsoJsonObj *json_list = dso_json_list_new ();
	if (!bin) {
		return json_list;
	}
	r_list_foreach (bin->fields_list, iter, fm_type) {
		DsoJsonObj *field_proto = r_bin_java_get_field_json_definition (bin, fm_type);
		// eprintf ("Field json: %s\n", field_proto);
		dso_json_list_append (json_list, field_proto);
	}
	return json_list;
}

Project: radare2
File: class.c

R_API void *r_bin_java_free(RBinJavaObj *bin) {
	char *bin_obj_key = NULL;
	if (!bin) {
		return NULL;
	}
	// Delete the bin object from the data base.
	bin_obj_key = r_bin_java_build_obj_key (bin);
	// if (bin->AllJavaBinObjs && sdb_exists (bin->AllJavaBinObjs, bin_obj_key)) {
	// sdb_unset (bin->AllJavaBinObjs, bin_obj_key, 0);
	// }
	free (bin_obj_key);
	r_list_free (bin->imports_list);
	// XXX - Need to remove all keys belonging to this class from
	// the share meta information sdb.
	// TODO e.g. iterate over bin->kv and delete all obj, func, etc. keys
	// sdb_free (bin->kv);
	// free up the constant pool list
	r_list_free (bin->cp_list);
	// free up the fields list
	r_list_free (bin->fields_list);
	// free up methods list
	r_list_free (bin->methods_list);
	// free up interfaces list
	r_list_free (bin->interfaces_list);
	r_list_free (bin->attrs_list);
	// TODO: XXX if a class list of all inner classes
	// are formed then this will need to be updated
	free (bin->cf2.flags_str);
	free (bin->cf2.this_class_name);
	if (bin == R_BIN_JAVA_GLOBAL_BIN) {
		R_BIN_JAVA_GLOBAL_BIN = NULL;
	}
	free (bin->file);
	free (bin);
	return NULL;
}

Project: radare2
File: class.c

R_API void r_bin_java_print_methodhandle_cp_summary(RBinJavaCPTypeObj *obj) {
	ut8 ref_kind;
	if (obj == NULL) {
		eprintf ("Attempting to print an invalid RBinJavaCPTypeObj*  RBinJavaCPTypeMethodHandle.\n");
		return;
	}
	ref_kind = obj->info.cp_method_handle.reference_kind;
	eprintf ("MethodHandle ConstantPool Type (%d) ", obj->metas->ord);
	eprintf ("	Offset: 0x%08"PFMT64x"", obj->file_offset);
	eprintf ("	Reference Kind = (0x%02x) %s\n", ref_kind, R_BIN_JAVA_REF_METAS[ref_kind].name);
	eprintf ("	Reference Index = %d\n", obj->info.cp_method_handle.reference_index);
}

Project: radare2
File: class.c

R_API void r_bin_java_enclosing_methods_attr_free(void /*RBinJavaAttrInfo*/ *a) {
	RBinJavaAttrInfo *attr = a;
	if (attr) {
		free (attr->name);
		free (attr->metas);
		free (attr->info.enclosing_method_attr.class_name);
		free (attr->info.enclosing_method_attr.method_name);
		free (attr->info.enclosing_method_attr.method_descriptor);
		free (attr);
	}
}

Project: radare2
File: class.c

R_API void U(r_bin_java_stack_frame_do_nothing_free)(void /*RBinJavaStackMapFrame*/ *stack_frame) {}

Project: radare2
File: class.c

R_API ut8 *r_bin_java_cp_get_name_type(RBinJavaObj *bin, ut32 *out_sz, ut16 name_idx, ut16 type_idx) {
	return r_bin_java_cp_get_2_ut16 (bin, out_sz, R_BIN_JAVA_CP_NAMEANDTYPE, name_idx, type_idx);
}

Project: radare2
File: class.c

R_API RBinJavaCPTypeObj *r_bin_java_get_item_from_cp_item_list(RList *cp_list, ut64 idx) {
	/*
	Search through the Constant Pool list for the given CP Index.
	rvalue: RBinJavaObj *
	*/
	RBinJavaCPTypeObj *item = NULL;
	if (cp_list == NULL) {
		return NULL;
	}
	item = (RBinJavaCPTypeObj *) r_list_get_n (cp_list, idx);
	return item;
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_parse_methods(RBinJavaObj *bin, const ut64 offset, const ut8 *buf, const ut64 len) {
	int i = 0;
	ut64 adv = 0;
	RBinJavaField *method;
	const ut8 *fm_buf = buf + offset;
	r_list_free (bin->methods_list);
	bin->methods_list = r_list_newf (r_bin_java_fmtype_free);

	if (offset + 2 >= len) {
		return 0LL;
	}
	bin->methods_offset = offset;
	bin->methods_count = R_BIN_JAVA_USHORT (fm_buf, 0);
	adv += 2;
	IFDBG eprintf("Methods count: %d 0x%"PFMT64x "\n", bin->methods_count, bin->methods_offset);
	bin->main = NULL;
	bin->entrypoint = NULL;
	bin->main_code_attr = NULL;
	bin->entrypoint_code_attr = NULL;
	for (i = 0; i < bin->methods_count; i++, bin->method_idx++) {
		method = r_bin_java_read_next_method (bin, offset + adv, buf, len);
		if (method) {
			adv += method->size;
			r_list_append (bin->methods_list, method);
		}
		// Update Main, Init, or Class Init
		if (method && !strcmp ((const char *) method->name, "main")) {
			bin->main = method;
			// get main code attr
			bin->main_code_attr = r_bin_java_get_attr_from_field (method, R_BIN_JAVA_ATTR_TYPE_CODE_ATTR, 0);
		} else if (method && (!strcmp ((const char *) method->name, "<init>") || !strcmp ((const char *) method->name, "init")))   {
			IFDBG eprintf("FOund an init function.\n");
			bin->entrypoint = method;
			bin->entrypoint_code_attr = r_bin_java_get_attr_from_field (method, R_BIN_JAVA_ATTR_TYPE_CODE_ATTR, 0);
		} else if (method && (!strcmp ((const char *) method->name, "<cinit>") || !strcmp ((const char *) method->name, "cinit")))   {
			bin->cf2.this_class_entrypoint = method;
			bin->cf2.this_class_entrypoint_code_attr = r_bin_java_get_attr_from_field (method, R_BIN_JAVA_ATTR_TYPE_CODE_ATTR, 0);
		}
		if (adv + offset > len) {
			eprintf ("[X] r_bin_java: Error unable to parse remainder of classfile after Method: %d.\n", i);
			break;
		}
		IFDBG r_bin_java_print_field_summary(method);
	}
	bin->methods_size = adv;
	return adv;
}

Project: radare2
File: class.c

R_API void r_bin_java_print_name_and_type_cp_summary(RBinJavaCPTypeObj *obj) {
	if (obj == NULL) {
		eprintf ("Attempting to print an invalid RBinJavaCPTypeObj*  Name_And_Type.\n");
		return;
	}
	Eprintf ("Name_And_Type ConstantPool Type (%d) ", obj->metas->ord);
	Eprintf ("  Offset: 0x%08"PFMT64x "", obj->file_offset);
	Eprintf ("  name_idx = (%d)\n", obj->info.cp_name_and_type.name_idx);
	Eprintf ("  descriptor_idx = (%d)\n", obj->info.cp_name_and_type.descriptor_idx);
}

Project: radare2
File: class.c

R_API RList *r_bin_java_get_lib_names(RBinJavaObj *bin) {
	RList *lib_names = r_list_newf (free);
	RListIter *iter;
	RBinJavaCPTypeObj *cp_obj = NULL;
	if (!bin) {
		return lib_names;
	}
	r_list_foreach (bin->cp_list, iter, cp_obj) {
		if (cp_obj && cp_obj->tag == R_BIN_JAVA_CP_CLASS &&
		(bin->cf2.this_class != cp_obj->info.cp_class.name_idx || !is_class_interface (bin, cp_obj))) {
			char *name = r_bin_java_get_item_name_from_bin_cp_list (bin, cp_obj);
			r_list_append (lib_names, name);
		}
	}
	return lib_names;
}

Project: radare2
File: class.c

R_API int U(r_bin_java_is_method_static)(RBinJavaObj * bin_obj, ut64 addr) {
	RBinJavaField *fm_type = r_bin_java_get_method_code_attribute_with_addr (bin_obj, addr);
	return fm_type && fm_type->flags & R_BIN_JAVA_METHOD_ACC_STATIC;
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_bootstrap_arg_calc_size(RBinJavaBootStrapArgument *bsm_arg) {
	ut64 size = 0;
	if (bsm_arg) {
		// bsm_arg->argument_info_idx = R_BIN_JAVA_USHORT (buffer, offset);
		size += 2;
	}
	return size;
}

Project: radare2
File: class.c

R_API char *r_bin_java_get_name_from_cp_item_list(RList *cp_list, ut64 idx) {
	/*
	Given a constant poool object Class, FieldRef, MethodRef, or InterfaceMethodRef
	return the actual descriptor string.
	@param cp_list: RList of RBinJavaCPTypeObj *
	@param obj object to look up the name for
	@rvalue ut8* (user frees) or NULL
	*/
	RBinJavaCPTypeObj *obj = r_bin_java_get_item_from_cp_item_list (
		cp_list, idx);
	if (obj && cp_list) {
		return r_bin_java_get_item_name_from_cp_item_list (
			cp_list, obj, MAX_CPITEMS);
	}
	return NULL;
}

Project: radare2
File: class.c

R_API ut8 *r_bin_java_cp_get_classref(RBinJavaObj *bin, ut32 *out_sz, const char *classname, const ut32 classname_len, const ut16 name_idx) {
	ut16 use_name_idx = -1;
	ut8 *bytes = NULL;
	if (name_idx == (ut16) - 1 && classname && *classname && classname_len > 0) {
		// find class_name_idx by class name
		RList *results = r_bin_java_find_cp_const_by_val_utf8 (bin, (const ut8 *) classname, classname_len);
		if (r_list_length (results) == 1) {
			use_name_idx = (ut16) * ((ut32 *) r_list_get_n (results, 0));
		}
		r_list_free (results);
	} else if (name_idx != (ut16) - 1 && name_idx != 0) {
		use_name_idx = name_idx;
	}
	if (use_name_idx == (ut16) - 1 && classname && *classname && classname_len > 0) {
		bytes = r_bin_java_cp_append_classref_and_name (bin, out_sz, classname, classname_len);
	} else if (use_name_idx != (ut16) - 1) {
		ut8 *idx_addr = (ut8 *) &use_name_idx;
		bytes = malloc (3);
		if (!bytes) {
			return NULL;
		}
		bytes[0] = R_BIN_JAVA_CP_CLASS;
		bytes[1] = idx_addr[1];
		bytes[2] = idx_addr[0];
		*out_sz += 3;
	}
	return bytes;
}

Project: radare2
File: class.c

R_API void r_bin_java_attribute_free(void /*RBinJavaAttrInfo*/ *a) {
	RBinJavaAttrInfo *attr = a;
	if (attr) {
		IFDBG eprintf("Deleting attr %s, %p\n", attr->name, attr);
		((RBinJavaAttrMetas *) attr->metas->type_info)->allocs->delete_obj (attr);
		// free (attr->metas);
		// free (attr);
	}
}

Project: radare2
File: class.c

R_API int r_bin_java_print_method_idx_summary(RBinJavaObj *bin_obj, ut32 idx) {
	int res = false;
	if (idx < r_list_length (bin_obj->methods_list)) {
		RBinJavaField *fm_type = r_list_get_n (bin_obj->methods_list, idx);
		r_bin_java_print_method_summary (fm_type);
		res = true;
	}
	return res;
}

Project: radare2
File: class.c

R_API void r_bin_java_constant_pool(void /*RBinJavaCPTypeObj*/ *o) {
	RBinJavaCPTypeObj *obj = o;
	if (obj != &R_BIN_JAVA_NULL_TYPE) {
		((RBinJavaCPTypeMetas *) obj->metas->type_info)->allocs->delete_obj (obj);
	}
}

Project: radare2
File: class.c

R_API RBinJavaCPTypeObj *r_bin_java_get_item_from_cp(RBinJavaObj *bin, int i) {
	if (i < 1 || i > bin->cf.cp_count) {
		return &R_BIN_JAVA_NULL_TYPE;
	}
	RBinJavaCPTypeObj *obj = (RBinJavaCPTypeObj *) r_list_get_n (bin->cp_list, i);
	return obj ? obj : &R_BIN_JAVA_NULL_TYPE;
}

Project: radare2
File: class.c

R_API RList *r_bin_java_get_bin_obj_list_thru_obj(RBinJavaObj *bin_obj) {
	RList *the_list;
	Sdb *sdb;
	if (!bin_obj) {
		return NULL;
	}
	sdb = bin_obj->AllJavaBinObjs;
	if (!sdb) {
		return NULL;
	}
	the_list = r_list_new ();
	if (!the_list) {
		return NULL;
	}
	sdb_foreach (sdb, sdb_iterate_build_list, (void *) the_list);
	return the_list;
}

Project: radare2
File: class.c

R_API char *r_bin_java_print_fieldref_cp_stringify(RBinJavaCPTypeObj *obj) {
	ut32 size = 255, consumed = 0;
	char *value = malloc (size);
	if (value) {
		memset (value, 0, size);
		consumed = snprintf (value, size, "%d.0x%04"PFMT64x ".%s.%d.%d",
			obj->metas->ord, obj->file_offset + obj->loadaddr, ((RBinJavaCPTypeMetas *) obj->metas->type_info)->name,
			obj->info.cp_field.class_idx,
			obj->info.cp_field.name_and_type_idx);
		if (consumed >= size - 1) {
			free (value);
			size += size >> 1;
			value = malloc (size);
			if (value) {
				memset (value, 0, size);
				consumed = snprintf (value, size, "%d.0x%04"PFMT64x ".%s.%d.%d",
					obj->metas->ord, obj->file_offset + obj->loadaddr, ((RBinJavaCPTypeMetas *) obj->metas->type_info)->name,
					obj->info.cp_field.class_idx,
					obj->info.cp_field.name_and_type_idx);
			}
		}
	}
	return value;
}

Project: radare2
File: class.c

R_API RBinJavaAttrInfo *r_bin_java_rtip_annotations_attr_new(ut8 *buffer, ut64 sz, ut64 buf_offset) {
	ut32 i = 0;
	RBinJavaAttrInfo *attr = NULL;
	ut64 offset = 0;
	attr = r_bin_java_default_attr_new (buffer, sz, buf_offset);
	offset += 6;
	RBinJavaAnnotationsArray *annotation_array;
	if (attr) {
		attr->type = R_BIN_JAVA_ATTR_TYPE_RUNTIME_INVISIBLE_PARAMETER_ANNOTATION_ATTR;
		attr->info.rtip_annotations_attr.num_parameters = buffer[offset];
		offset += 1;
		attr->info.rtip_annotations_attr.parameter_annotations = r_list_newf (r_bin_java_annotation_array_free);
		for (i = 0; i < attr->info.rtip_annotations_attr.num_parameters; i++) {
			annotation_array = r_bin_java_annotation_array_new (buffer + offset, sz - offset, buf_offset + offset);
			if (annotation_array == NULL) {}
			if (annotation_array) {
				offset += annotation_array->size;
			}
			r_list_append (attr->info.rtip_annotations_attr.parameter_annotations, (void *) annotation_array);
		}
		attr->size = offset;
	}
	return attr;
}

Project: radare2
File: class.c

R_API RBinJavaCPTypeObj *r_bin_java_methodtype_cp_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz) {
	ut8 tag = buffer[0];
	int quick_check = r_bin_java_quick_check (R_BIN_JAVA_CP_METHODTYPE, tag, sz, "RBinJavaCPTypeMethodType");
	if (quick_check > 0) {
		return NULL;
	}
	RBinJavaCPTypeObj *obj = R_NEW0 (RBinJavaCPTypeObj);
	if (obj) {
		obj->metas = R_NEW0 (RBinJavaMetaInfo);
		obj->metas->type_info = (void *) &R_BIN_JAVA_CP_METAS[tag];
		obj->name = r_str_dup (NULL, (const char *) R_BIN_JAVA_CP_METAS[tag].name);;
		obj->tag = tag;
		obj->info.cp_method_type.descriptor_index = R_BIN_JAVA_USHORT (buffer, 1);
	}
	return obj;
}

Project: radare2
File: class.c

R_API RBinJavaAttrInfo *r_bin_java_rtv_annotations_attr_new(ut8 *buffer, ut64 sz, ut64 buf_offset) {
	ut32 i = 0;
	RBinJavaAttrInfo *attr = NULL;
	ut64 offset = 0;
	attr = r_bin_java_default_attr_new (buffer, sz, buf_offset);
	offset += 6;
	if (attr) {
		attr->type = R_BIN_JAVA_ATTR_TYPE_RUNTIME_VISIBLE_ANNOTATION_ATTR;
		attr->info.annotation_array.num_annotations = R_BIN_JAVA_USHORT (buffer, offset);
		offset += 2;
		attr->info.annotation_array.annotations = r_list_newf (r_bin_java_annotation_free);
		for (i = 0; i < attr->info.annotation_array.num_annotations; i++) {
			int len = sz - offset;
			if (len < 1) {
				break;
			}
			RBinJavaAnnotation *annotation = r_bin_java_annotation_new (buffer + offset, len, buf_offset + offset);
			if (annotation) {
				offset += annotation->size;
				r_list_append (attr->info.annotation_array.annotations, (void *) annotation);
			}
		}
		attr->size = offset;
	}
	return attr;
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_get_method_code_offset(RBinJavaField *fm_type) {
	RListIter *attr_iter = NULL, *attr_iter_tmp = NULL;
	RBinJavaAttrInfo *attr = NULL;
	ut64 offset = 0;
	r_list_foreach_safe (fm_type->attributes, attr_iter, attr_iter_tmp, attr) {
		if (attr->type == R_BIN_JAVA_ATTR_TYPE_CODE_ATTR) {
			offset = attr->info.code_attr.code_offset;
			break;
		}
	}
	return offset;
}

Project: radare2
File: class.c

R_API ut8 *r_bin_java_cp_get_bytes(ut8 tag, ut32 *out_sz, const ut8 *buf, const ut64 len) {
	if (!out_sz) {
		return NULL;
	}
	if (out_sz) {
		*out_sz = 0;
	}
	switch (tag) {
	case R_BIN_JAVA_CP_INTEGER:
	case R_BIN_JAVA_CP_FLOAT:
		return r_bin_java_cp_get_4bytes (tag, out_sz, buf, len);
	case R_BIN_JAVA_CP_LONG:
	case R_BIN_JAVA_CP_DOUBLE:
		return r_bin_java_cp_get_8bytes (tag, out_sz, buf, len);
	case R_BIN_JAVA_CP_UTF8:
		return r_bin_java_cp_get_utf8 (tag, out_sz, buf, len);
	}
	return NULL;
}

Project: radare2
File: class.c

R_API RBinJavaAttrInfo *r_bin_java_read_next_attr(RBinJavaObj *bin, const ut64 offset, const ut8 *buf, const ut64 buf_len) {
	RBinJavaAttrInfo *attr = NULL;
	ut32 sz = 0;
	ut8 *buffer = NULL;
	const ut8 *a_buf = offset + buf;
	ut8 attr_idx_len = 6;
	if (offset + 6 > buf_len) {
		eprintf ("[X] r_bin_java: Error unable to parse remainder of classfile in Attribute offset "
			"(0x%"PFMT64x ") > len  of remaining bytes (0x%"PFMT64x ").\n", offset, buf_len);
		return NULL;
	}
	// ut16 attr_idx, ut32 length of attr.
	sz = R_BIN_JAVA_UINT (a_buf, 2) + attr_idx_len; // r_bin_java_read_int (bin, buf_offset+2) + attr_idx_len;
	if (sz + offset > buf_len) {
		eprintf ("[X] r_bin_java: Error unable to parse remainder of classfile in Attribute len "
			"(0x%x) + offset (0x%"PFMT64x ") exceeds length of buffer (0x%"PFMT64x ").\n",
			sz, offset, buf_len);
		return NULL;
	}
	// when reading the attr bytes, need to also
	// include the initial 6 bytes, which
	// are not included in the attribute length
	// ,
	// sz, buf_offset, buf_offset+sz);
	buffer = r_bin_java_get_attr_buf (bin, sz, offset, buf, buf_len);
	// printf ("%d %d %d\n", sz, buf_len, offset);
	if (offset < buf_len) {
		attr = r_bin_java_read_next_attr_from_buffer (buffer, buf_len - offset, offset);
		free (buffer);

		if (!attr) {
			return NULL;
		}
		attr->size = sz;
	} else {
		eprintf ("IS OOB\n");
	}
	return attr;
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_name_and_type_cp_calc_size(RBinJavaCPTypeObj *obj) {
	ut64 size = 0;
	if (obj) {
		size += 1;
		// obj->info.cp_name_and_type.name_idx = R_BIN_JAVA_USHORT (buffer, 1);
		size += 2;
		// obj->info.cp_name_and_type.descriptor_idx = R_BIN_JAVA_USHORT (buffer, 3);
		size += 2;
	}
	return size;
}

Project: radare2
File: class.c

R_API RList *r_bin_java_get_interface_names(RBinJavaObj *bin) {
	RList *interfaces_names = r_list_new ();
	RListIter *iter;
	RBinJavaInterfaceInfo *ifobj;
	r_list_foreach (bin->interfaces_list, iter, ifobj) {
		if (ifobj && ifobj->name) {
			r_list_append (interfaces_names, strdup (ifobj->name));
		}
	}
	return interfaces_names;
}

Project: radare2
File: class.c

R_API void r_bin_java_default_free(void /* RBinJavaCPTypeObj*/ *o) {
	RBinJavaCPTypeObj *obj = o;
	if (obj) {
		free (obj->metas);
		free (obj->name);
		free (obj->value);
		free (obj);
	}
}

Project: radare2
File: class.c

R_API void r_bin_java_print_null_cp_summary(RBinJavaCPTypeObj *obj) {
	eprintf ("Unknown ConstantPool Type Tag: 0x%04x .\n", obj->tag);
}

Project: radare2
File: class.c

R_API char *r_bin_java_get_desc_from_bin_cp_list(RBinJavaObj *bin, ut64 idx) {
	/*
	Search through the Constant Pool list for the given CP Index.
	If the idx not found by directly going to the list index,
	the list will be walked and then the IDX will be checked.
	rvalue: new char* for caller to free.
	*/
	if (bin == NULL) {
		return NULL;
	}
	return r_bin_java_get_desc_from_cp_item_list (bin->cp_list, idx);
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_synthetic_attr_calc_size(RBinJavaAttrInfo *attr) {
	return attr ? 12 : 6;
}

Project: radare2
File: class.c

R_API void r_bin_java_print_local_variable_attr_summary(RBinJavaLocalVariableAttribute *lvattr) {
	if (!lvattr) {
		eprintf ("Attempting to print an invalid RBinJavaLocalVariableAttribute *.\n");
		return;
	}
	Eprintf ("  Local Variable Attribute offset: 0x%08"PFMT64x "\n", lvattr->file_offset);
	Eprintf ("  Local Variable Attribute start_pc: %d\n", lvattr->start_pc);
	Eprintf ("  Local Variable Attribute Length: %d\n", lvattr->length);
	Eprintf ("  Local Variable Attribute name_idx: %d\n", lvattr->name_idx);
	Eprintf ("  Local Variable Attribute name: %s\n", lvattr->name);
	Eprintf ("  Local Variable Attribute descriptor_idx: %d\n", lvattr->descriptor_idx);
	Eprintf ("  Local Variable Attribute descriptor: %s\n", lvattr->descriptor);
	Eprintf ("  Local Variable Attribute index: %d\n", lvattr->index);
}

Project: radare2
File: class.c

R_API void r_bin_java_local_variable_type_table_attr_free(void /*RBinJavaAttrInfo*/ *a) {
	RBinJavaAttrInfo *attr = a;
	if (attr) {
		free (attr->name);
		free (attr->metas);
		r_list_free (attr->info.local_variable_type_table_attr.local_variable_table);
		free (attr);
	}
}

Project: radare2
File: class.c

R_API RBinJavaCPTypeObj *r_bin_java_clone_cp_idx(RBinJavaObj *bin, ut32 idx) {
	RBinJavaCPTypeObj *obj = NULL;
	if (bin) {
		obj = r_bin_java_get_item_from_bin_cp_list (bin, idx);
	}
	return r_bin_java_clone_cp_item (obj);
}

Project: radare2
File: class.c

R_API ut64 r_bin_java_methodref_cp_calc_size(RBinJavaCPTypeObj *obj) {
	ut64 size = 0;
	// tag
	size += 1;
	// obj->info.cp_method.class_idx = R_BIN_JAVA_USHORT (buffer, 1);
	size += 2;
	// obj->info.cp_method.name_and_type_idx = R_BIN_JAVA_USHORT (buffer, 3);
	size += 2;
	return size;
}