1 /* Apache 2.0 - Copyright 2007-2018 - pancake and dso
2    class.c rewrite: Adam Pridgen <dso@rice.edu || adam.pridgen@thecoverofnight.com>
3  */
4 #include <stdio.h>
5 #include <string.h>
6 #include <stdlib.h>
7 #include <stdarg.h>
8 #include <r_types.h>
9 #include <r_util.h>
10 #include <r_bin.h>
11 #include <math.h>
12 #include <sdb.h>
13 #include "class.h"
14 #include "dsojson.h"
15 
16 static PrintfCallback Eprintf =(PrintfCallback) printf;
17 #ifdef IFDBG
18 #undef IFDBG
19 #endif
20 #define DO_THE_DBG 0
21 #define IFDBG  if (DO_THE_DBG)
22 #define IFINT  if (0)
23 
24 #define MAX_CPITEMS 8192
25 
26 R_API char *U(r_bin_java_unmangle_method)(const char *flags, const char *name, const char *params, const char *r_value);
27 R_API int r_bin_java_is_fm_type_private(RBinJavaField *fm_type);
28 R_API int r_bin_java_is_fm_type_protected(RBinJavaField *fm_type);
29 R_API ut32 U(r_bin_java_swap_uint)(ut32 x);
30 
31 // R_API const char * r_bin_java_get_this_class_name(RBinJavaObj *bin);
32 R_API void U(add_cp_objs_to_sdb)(RBinJavaObj * bin);
33 R_API void U(add_field_infos_to_sdb)(RBinJavaObj * bin);
34 R_API void U(add_method_infos_to_sdb)(RBinJavaObj * bin);
35 R_API RList *retrieve_all_access_string_and_value(RBinJavaAccessFlags *access_flags);
36 R_API char *retrieve_access_string(ut16 flags, RBinJavaAccessFlags *access_flags);
37 R_API ut16 calculate_access_value(const char *access_flags_str, RBinJavaAccessFlags *access_flags);
38 R_API int r_bin_java_new_bin(RBinJavaObj *bin, ut64 loadaddr, Sdb *kv, const ut8 *buf, ut64 len);
39 R_API int extract_type_value(const char *arg_str, char **output);
40 R_API int r_bin_java_check_reset_cp_obj(RBinJavaCPTypeObj *cp_obj, ut8 tag);
41 R_API ut8 *r_bin_java_cp_get_4bytes(ut8 tag, ut32 *out_sz, const ut8 *buf, const ut64 len);
42 R_API ut8 *r_bin_java_cp_get_8bytes(ut8 tag, ut32 *out_sz, const ut8 *buf, const ut64 len);
43 R_API ut8 *r_bin_java_cp_get_utf8(ut8 tag, ut32 *out_sz, const ut8 *buf, const ut64 len);
44 
45 R_API RBinJavaCPTypeObj *r_bin_java_get_item_from_bin_cp_list(RBinJavaObj *bin, ut64 idx);
46 R_API RBinJavaCPTypeObj *r_bin_java_get_item_from_cp_item_list(RList *cp_list, ut64 idx);
47 // Allocs for objects
48 R_API RBinJavaCPTypeObj *r_bin_java_class_cp_new(RBinJavaObj *bin, ut8 *buffer, ut64 offset);
49 R_API RBinJavaCPTypeObj *r_bin_java_fieldref_cp_new(RBinJavaObj *bin, ut8 *buffer, ut64 offset);
50 R_API RBinJavaCPTypeObj *r_bin_java_methodref_cp_new(RBinJavaObj *bin, ut8 *buffer, ut64 offset);
51 R_API RBinJavaCPTypeObj *r_bin_java_interfacemethodref_cp_new(RBinJavaObj *bin, ut8 *buffer, ut64 offset);
52 R_API RBinJavaCPTypeObj *r_bin_java_name_and_type_cp_new(RBinJavaObj *bin, ut8 *buffer, ut64 offset);
53 R_API RBinJavaCPTypeObj *r_bin_java_string_cp_new(RBinJavaObj *bin, ut8 *buffer, ut64 offset);
54 R_API RBinJavaCPTypeObj *r_bin_java_integer_cp_new(RBinJavaObj *bin, ut8 *buffer, ut64 offset);
55 R_API RBinJavaCPTypeObj *r_bin_java_float_cp_new(RBinJavaObj *bin, ut8 *buffer, ut64 offset);
56 R_API RBinJavaCPTypeObj *r_bin_java_long_cp_new(RBinJavaObj *bin, ut8 *buffer, ut64 offset);
57 R_API RBinJavaCPTypeObj *r_bin_java_double_cp_new(RBinJavaObj *bin, ut8 *buffer, ut64 offset);
58 R_API RBinJavaCPTypeObj *r_bin_java_utf8_cp_new(RBinJavaObj *bin, ut8 *buffer, ut64 offset);
59 R_API RBinJavaCPTypeObj *r_bin_java_do_nothing_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz);
60 R_API RBinJavaCPTypeObj *r_bin_java_clone_cp_item(RBinJavaCPTypeObj *obj);
61 R_API RBinJavaCPTypeObj *r_bin_java_clone_cp_idx(RBinJavaObj *bin, ut32 idx);
62 R_API RBinJavaCPTypeObj *r_bin_java_methodhandle_cp_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz);
63 R_API RBinJavaCPTypeObj *r_bin_java_methodtype_cp_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz);
64 R_API RBinJavaCPTypeObj *r_bin_java_invokedynamic_cp_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz);
65 // Deallocs for type objects
66 R_API void r_bin_java_default_free(void /*RBinJavaCPTypeObj*/ *obj);
67 R_API void r_bin_java_obj_free(void /*RBinJavaCPTypeObj*/ *obj);
68 R_API void r_bin_java_utf8_info_free(void /*RBinJavaCPTypeObj*/ *obj);
69 R_API void r_bin_java_do_nothing_free(void /*RBinJavaCPTypeObj*/ *obj);
70 R_API void r_bin_java_fmtype_free(void /*RBinJavaField*/ *fm_type);
71 // handle freeing the lists
72 // handle the reading of the various field
73 R_API RBinJavaAttrInfo *r_bin_java_read_next_attr(RBinJavaObj *bin, const ut64 offset, const ut8 *buf, const ut64 len);
74 R_API RBinJavaCPTypeObj *r_bin_java_read_next_constant_pool_item(RBinJavaObj *bin, const ut64 offset, const ut8 *buf, ut64 len);
75 R_API RBinJavaAttrMetas *r_bin_java_get_attr_type_by_name(const char *name);
76 R_API RBinJavaCPTypeObj *r_bin_java_get_java_null_cp(void);
77 R_API ut64 r_bin_java_read_class_file2(RBinJavaObj *bin, const ut64 offset, const ut8 *buf, ut64 len);
78 R_API RBinJavaAttrInfo *r_bin_java_get_attr_from_field(RBinJavaField *field, R_BIN_JAVA_ATTR_TYPE attr_type, ut32 pos);
79 R_API RBinJavaField *r_bin_java_read_next_field(RBinJavaObj *bin, const ut64 offset, const ut8 *buffer, const ut64 len);
80 R_API RBinJavaField *r_bin_java_read_next_method(RBinJavaObj *bin, const ut64 offset, const ut8 *buffer, const ut64 len);
81 R_API void r_bin_java_print_utf8_cp_summary(RBinJavaCPTypeObj *obj);
82 R_API void r_bin_java_print_name_and_type_cp_summary(RBinJavaCPTypeObj *obj);
83 R_API void r_bin_java_print_double_cp_summary(RBinJavaCPTypeObj *obj);
84 R_API void r_bin_java_print_long_cp_summary(RBinJavaCPTypeObj *obj);
85 R_API void r_bin_java_print_float_cp_summary(RBinJavaCPTypeObj *obj);
86 R_API void r_bin_java_print_integer_cp_summary(RBinJavaCPTypeObj *obj);
87 R_API void r_bin_java_print_string_cp_summary(RBinJavaCPTypeObj *obj);
88 R_API void r_bin_java_print_classref_cp_summary(RBinJavaCPTypeObj *obj);
89 R_API void r_bin_java_print_fieldref_cp_summary(RBinJavaCPTypeObj *obj);
90 R_API void r_bin_java_print_methodref_cp_summary(RBinJavaCPTypeObj *obj);
91 R_API void r_bin_java_print_interfacemethodref_cp_summary(RBinJavaCPTypeObj *obj);
92 R_API void r_bin_java_print_unknown_cp_summary(RBinJavaCPTypeObj *obj);
93 R_API void r_bin_java_print_null_cp_summary(RBinJavaCPTypeObj *obj);
94 R_API void r_bin_java_print_unknown_attr_summary(RBinJavaAttrInfo *attr);
95 R_API void r_bin_java_print_methodhandle_cp_summary(RBinJavaCPTypeObj *obj);
96 R_API void r_bin_java_print_methodtype_cp_summary(RBinJavaCPTypeObj *obj);
97 R_API void r_bin_java_print_invokedynamic_cp_summary(RBinJavaCPTypeObj *obj);
98 R_API RBinJavaCPTypeObj *r_bin_java_unknown_cp_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz);
99 R_API RBinJavaInterfaceInfo *r_bin_java_interface_new(RBinJavaObj *bin, const ut8 *buf, ut64 sz);
100 R_API RBinJavaInterfaceInfo *r_bin_java_read_next_interface_item(RBinJavaObj *bin, const ut64 offset, const ut8 *buf, ut64 len);
101 R_API void r_bin_java_interface_free(void /*RBinJavaInterfaceInfo*/ *obj);
102 R_API void r_bin_java_stack_frame_free(void /*RBinJavaStackMapFrame*/ *obj);
103 R_API void r_bin_java_stack_map_table_attr_free(void /*RBinJavaAttrInfo*/ *attr);
104 R_API void r_bin_java_verification_info_free(void /*RBinJavaVerificationObj*/ *obj);
105 R_API void r_bin_java_print_stack_map_table_attr_summary(RBinJavaAttrInfo *obj);
106 R_API void r_bin_java_print_stack_map_frame_summary(RBinJavaStackMapFrame *obj);
107 R_API void r_bin_java_print_verification_info_summary(RBinJavaVerificationObj *obj);
108 R_API RBinJavaStackMapFrame *r_bin_java_build_stack_frame_from_local_variable_table(RBinJavaObj *bin, RBinJavaAttrInfo *attr);
109 R_API void U(r_bin_java_print_stack_map_append_frame_summary)(RBinJavaStackMapFrame * obj);
110 R_API void U(r_bin_java_stack_frame_default_free)(void /*RBinJavaStackMapFrame*/ *stack_frame);
111 R_API void U(r_bin_java_stack_frame_do_nothing_free)(void /*RBinJavaStackMapFrame*/ *stack_frame);
112 R_API void U(r_bin_java_stack_frame_do_nothing_new)(RBinJavaObj * bin, RBinJavaStackMapFrame * stack_frame, ut64 offset);
113 R_API RBinJavaStackMapFrame *r_bin_java_stack_map_frame_new(ut8 *buffer, ut64 sz, RBinJavaStackMapFrame *p_frame, ut64 buf_offset);
114 // R_API RBinJavaStackMapFrame* r_bin_java_stack_map_frame_new (ut8* buffer, ut64 sz, ut64 buf_offset);
115 R_API RBinJavaElementValue *r_bin_java_element_value_new(ut8 *buffer, ut64 sz, ut64 buf_offset);
116 // R_API RBinJavaVerificationObj* r_bin_java_read_next_verification_info_new(ut8* buffer, ut64 sz, ut64 buf_offset);
117 R_API RBinJavaAnnotation *r_bin_java_annotation_new(ut8 *buffer, ut64 sz, ut64 buf_offset);
118 R_API RBinJavaElementValuePair *r_bin_java_element_pair_new(ut8 *buffer, ut64 sz, ut64 buf_offset);
119 R_API RBinJavaElementValue *r_bin_java_element_value_new(ut8 *buffer, ut64 sz, ut64 buf_offset);
120 // R_API RBinJavaBootStrapArgument* r_bin_java_bootstrap_method_argument_new(ut8* buffer, ut64 sz, ut64 buf_offset);
121 R_API RBinJavaBootStrapMethod *r_bin_java_bootstrap_method_new(ut8 *buffer, ut64 sz, ut64 buf_offset);
122 R_API RBinJavaAnnotationsArray *r_bin_java_annotation_array_new(ut8 *buffer, ut64 sz, ut64 buf_offset);
123 R_API RBinJavaElementValueMetas *r_bin_java_get_ev_meta_from_tag(ut8 tag);
124 R_API RBinJavaCPTypeMetas *U(r_bin_java_get_cp_meta_from_tag)(ut8 tag);
125 R_API void r_bin_java_inner_classes_attr_entry_free(void /*RBinJavaClassesAttribute*/ *attr);
126 R_API void r_bin_java_annotation_default_attr_free(void /*RBinJavaAttrInfo*/ *attr);
127 R_API void r_bin_java_enclosing_methods_attr_free(void /*RBinJavaAttrInfo*/ *attr);
128 R_API void r_bin_java_local_variable_type_table_attr_entry_free(void /*RBinJavaLocalVariableTypeAttribute*/ *lvattr);
129 R_API void r_bin_java_local_variable_type_table_attr_free(void /*RBinJavaAttrInfo*/ *attr);
130 R_API void r_bin_java_signature_attr_free(void /*RBinJavaAttrInfo*/ *attr);
131 R_API void r_bin_java_source_debug_attr_free(void /*RBinJavaAttrInfo*/ *attr);
132 R_API void r_bin_java_element_value_free(void /*RBinJavaElementValue*/ *element_value);
133 R_API void r_bin_java_element_pair_free(void /*RBinJavaElementValuePair*/ *evp);
134 R_API void r_bin_java_annotation_free(void /*RBinJavaAnnotation*/ *annotation);
135 R_API void r_bin_java_rtv_annotations_attr_free(void /*RBinJavaAttrInfo*/ *attr);
136 R_API void r_bin_java_rti_annotations_attr_free(void /*RBinJavaAttrInfo*/ *attr);
137 R_API void r_bin_java_annotation_array_free(void /*RBinJavaAnnotationsArray*/ *annotation_array);
138 R_API void r_bin_java_bootstrap_methods_attr_free(void /*RBinJavaAttrInfo*/ *attr);
139 R_API void r_bin_java_bootstrap_method_free(void /*RBinJavaBootStrapMethod*/ *bsm);
140 R_API void r_bin_java_bootstrap_method_argument_free(void /*RBinJavaBootStrapArgument*/ *bsm_arg);
141 R_API void r_bin_java_rtvp_annotations_attr_free(void /*RBinJavaAttrInfo*/ *attr);
142 R_API void r_bin_java_rtip_annotations_attr_free(void /*RBinJavaAttrInfo*/ *attr);
143 R_API void r_bin_java_unknown_attr_free(void /*RBinJavaAttrInfo*/ *attr);
144 R_API void r_bin_java_code_attr_free(void /*RBinJavaAttrInfo*/ *attr);
145 R_API void r_bin_java_constant_value_attr_free(void /*RBinJavaAttrInfo*/ *attr);
146 R_API void r_bin_java_deprecated_attr_free(void /*RBinJavaAttrInfo*/ *attr);
147 R_API void r_bin_java_exceptions_attr_free(void /*RBinJavaAttrInfo*/ *attr);
148 R_API void r_bin_java_inner_classes_attr_free(void /*RBinJavaAttrInfo*/ *attr);
149 R_API void r_bin_java_line_number_table_attr_free(void /*RBinJavaAttrInfo*/ *attr);
150 R_API void r_bin_java_local_variable_table_attr_free(void /*RBinJavaAttrInfo*/ *attr);
151 R_API void r_bin_java_source_code_file_attr_free(void /*RBinJavaAttrInfo*/ *attr);
152 R_API void r_bin_java_synthetic_attr_free(void /*RBinJavaAttrInfo*/ *attr);
153 
154 R_API void r_bin_java_print_annotation_default_attr_summary(RBinJavaAttrInfo *attr);
155 R_API void r_bin_java_print_enclosing_methods_attr_summary(RBinJavaAttrInfo *attr);
156 R_API void r_bin_java_print_local_variable_type_attr_summary(RBinJavaLocalVariableTypeAttribute *lvattr);
157 R_API void r_bin_java_print_local_variable_type_table_attr_summary(RBinJavaAttrInfo *attr);
158 R_API void r_bin_java_print_signature_attr_summary(RBinJavaAttrInfo *attr);
159 R_API void r_bin_java_print_source_debug_attr_summary(RBinJavaAttrInfo *attr);
160 R_API void r_bin_java_print_element_value_summary(RBinJavaElementValue *element_value);
161 R_API void r_bin_java_print_annotation_summary(RBinJavaAnnotation *annotation);
162 R_API void r_bin_java_print_element_pair_summary(RBinJavaElementValuePair *evp);
163 R_API void r_bin_java_print_bootstrap_methods_attr_summary(RBinJavaAttrInfo *attr);
164 // R_API void r_bin_java_bootstrap_method_summary(RBinJavaBootStrapMethod *bsm);
165 // R_API void r_bin_java_bootstrap_method_argument_summary(RBinJavaBootStrapArgument *bsm_arg);
166 R_API void r_bin_java_print_rtv_annotations_attr_summary(RBinJavaAttrInfo *attr);
167 R_API void r_bin_java_print_rti_annotations_attr_summary(RBinJavaAttrInfo *attr);
168 R_API void r_bin_java_print_annotation_array_summary(RBinJavaAnnotationsArray *annotation_array);
169 R_API void r_bin_java_print_rtvp_annotations_attr_summary(RBinJavaAttrInfo *attr);
170 R_API void r_bin_java_print_rtip_annotations_attr_summary(RBinJavaAttrInfo *attr);
171 R_API void r_bin_java_attribute_free(void /*RBinJavaAttrInfo*/ *attr);
172 R_API void r_bin_java_constant_pool(void /*RBinJavaCPTypeObj*/ *obj);
173 R_API void r_bin_java_print_field_summary(RBinJavaField *field);
174 // R_API void r_bin_java_print_interface_summary(RBinJavaField *field);
175 R_API void r_bin_java_print_method_summary(RBinJavaField *field);
176 R_API void r_bin_java_print_code_exceptions_attr_summary(RBinJavaExceptionEntry *exc_entry);
177 R_API void r_bin_java_print_code_attr_summary(RBinJavaAttrInfo *attr);
178 R_API void r_bin_java_print_constant_value_attr_summary(RBinJavaAttrInfo *attr);
179 R_API void r_bin_java_print_deprecated_attr_summary(RBinJavaAttrInfo *attr);
180 R_API void r_bin_java_print_exceptions_attr_summary(RBinJavaAttrInfo *attr);
181 R_API void r_bin_java_print_classes_attr_summary(RBinJavaClassesAttribute *icattr);
182 R_API void r_bin_java_print_inner_classes_attr_summary(RBinJavaAttrInfo *attr);
183 R_API void r_bin_java_print_line_number_table_attr_summary(RBinJavaAttrInfo *attr);
184 R_API void r_bin_java_print_local_variable_attr_summary(RBinJavaLocalVariableAttribute *lvattr);
185 R_API void r_bin_java_print_local_variable_table_attr_summary(RBinJavaAttrInfo *attr);
186 R_API void r_bin_java_print_source_code_file_attr_summary(RBinJavaAttrInfo *attr);
187 R_API void r_bin_java_print_synthetic_attr_summary(RBinJavaAttrInfo *attr);
188 R_API void r_bin_java_print_attr_summary(RBinJavaAttrInfo *attr);
189 R_API RBinJavaAttrInfo *r_bin_java_read_next_attr_from_buffer(RBinJavaObj *bin, ut8 *buffer, st64 sz, st64 buf_offset);
190 R_API RBinJavaAttrInfo *r_bin_java_unknown_attr_new(RBinJavaObj *bin, ut8 *buf, ut64 sz, ut64 buf_offset);
191 R_API RBinJavaAttrInfo *r_bin_java_annotation_default_attr_new(RBinJavaObj *bin, ut8 *buf, ut64 sz, ut64 buf_offset);
192 R_API RBinJavaAttrInfo *r_bin_java_enclosing_methods_attr_new(RBinJavaObj *bin, ut8 *buf, ut64 sz, ut64 buf_offset);
193 R_API RBinJavaAttrInfo *r_bin_java_local_variable_type_table_attr_new(RBinJavaObj *bin, ut8 *buf, ut64 sz, ut64 buf_offset);
194 R_API RBinJavaAttrInfo *r_bin_java_signature_attr_new(RBinJavaObj *bin, ut8 *buf, ut64 sz, ut64 buf_offset);
195 R_API RBinJavaAttrInfo *r_bin_java_source_debug_attr_new(RBinJavaObj *bin, ut8 *buf, ut64 sz, ut64 buf_offset);
196 R_API RBinJavaAttrInfo *r_bin_java_bootstrap_methods_attr_new(RBinJavaObj *bin, ut8 *buf, ut64 sz, ut64 buf_offset);
197 R_API RBinJavaAttrInfo *r_bin_java_rtv_annotations_attr_new(RBinJavaObj *bin, ut8 *buf, ut64 sz, ut64 buf_offset);
198 R_API RBinJavaAttrInfo *r_bin_java_rti_annotations_attr_new(RBinJavaObj *bin, ut8 *buf, ut64 sz, ut64 buf_offset);
199 R_API RBinJavaAttrInfo *r_bin_java_rtvp_annotations_attr_new(RBinJavaObj *bin, ut8 *buf, ut64 sz, ut64 buf_offset);
200 R_API RBinJavaAttrInfo *r_bin_java_rtip_annotations_attr_new(RBinJavaObj *bin, ut8 *buf, ut64 sz, ut64 buf_offset);
201 R_API RBinJavaAttrInfo *r_bin_java_code_attr_new(RBinJavaObj *bin, ut8 *buf, ut64 sz, ut64 buf_offset);
202 R_API RBinJavaAttrInfo *r_bin_java_constant_value_attr_new(RBinJavaObj *bin, ut8 *buf, ut64 sz, ut64 buf_offset);
203 R_API RBinJavaAttrInfo *r_bin_java_deprecated_attr_new(RBinJavaObj *bin, ut8 *buf, ut64 sz, ut64 buf_offset);
204 R_API RBinJavaAttrInfo *r_bin_java_exceptions_attr_new(RBinJavaObj *bin, ut8 *buf, ut64 sz, ut64 buf_offset);
205 R_API RBinJavaAttrInfo *r_bin_java_inner_classes_attr_new(RBinJavaObj *bin, ut8 *buf, ut64 sz, ut64 buf_offset);
206 R_API RBinJavaAttrInfo *r_bin_java_line_number_table_attr_new(RBinJavaObj *bin, ut8 *buf, ut64 sz, ut64 buf_offset);
207 R_API RBinJavaAttrInfo *r_bin_java_local_variable_table_attr_new(RBinJavaObj *bin, ut8 *buf, ut64 sz, ut64 buf_offset);
208 R_API RBinJavaAttrInfo *r_bin_java_source_code_file_attr_new(RBinJavaObj *bin, ut8 *buf, ut64 sz, ut64 buf_offset);
209 R_API RBinJavaAttrInfo *r_bin_java_stack_map_table_attr_new(RBinJavaObj *bin, ut8 *buf, ut64 sz, ut64 buf_offset);
210 R_API RBinJavaAttrInfo *r_bin_java_synthetic_attr_new(RBinJavaObj *bin, ut8 *buf, ut64 sz, ut64 buf_offset);
211 R_API ut64 r_bin_java_unknown_attr_calc_size(RBinJavaAttrInfo *attr);
212 R_API ut64 r_bin_java_annotation_default_attr_calc_size(RBinJavaAttrInfo *attr);
213 R_API ut64 r_bin_java_enclosing_methods_attr_calc_size(RBinJavaAttrInfo *attr);
214 R_API ut64 r_bin_java_local_variable_type_table_attr_calc_size(RBinJavaAttrInfo *attr);
215 R_API ut64 r_bin_java_signature_attr_calc_size(RBinJavaAttrInfo *attr);
216 R_API ut64 r_bin_java_source_debug_attr_calc_size(RBinJavaAttrInfo *attr);
217 R_API ut64 r_bin_java_bootstrap_methods_attr_calc_size(RBinJavaAttrInfo *attr);
218 R_API ut64 r_bin_java_rtv_annotations_attr_calc_size(RBinJavaAttrInfo *attr);
219 R_API ut64 r_bin_java_rti_annotations_attr_calc_size(RBinJavaAttrInfo *attr);
220 R_API ut64 r_bin_java_rtvp_annotations_attr_calc_size(RBinJavaAttrInfo *attr);
221 R_API ut64 r_bin_java_rtip_annotations_attr_calc_size(RBinJavaAttrInfo *attr);
222 R_API ut64 r_bin_java_code_attr_calc_size(RBinJavaAttrInfo *attr);
223 R_API ut64 r_bin_java_constant_value_attr_calc_size(RBinJavaAttrInfo *attr);
224 R_API ut64 r_bin_java_deprecated_attr_calc_size(RBinJavaAttrInfo *attr);
225 R_API ut64 r_bin_java_exceptions_attr_calc_size(RBinJavaAttrInfo *attr);
226 R_API ut64 r_bin_java_inner_classes_attr_calc_size(RBinJavaAttrInfo *attr);
227 R_API ut64 r_bin_java_line_number_table_attr_calc_size(RBinJavaAttrInfo *attr);
228 R_API ut64 r_bin_java_local_variable_table_attr_calc_size(RBinJavaAttrInfo *attr);
229 R_API ut64 r_bin_java_source_code_file_attr_calc_size(RBinJavaAttrInfo *attr);
230 R_API ut64 r_bin_java_stack_map_table_attr_calc_size(RBinJavaAttrInfo *attr);
231 R_API ut64 r_bin_java_synthetic_attr_calc_size(RBinJavaAttrInfo *attr);
232 R_API ut64 r_bin_java_bootstrap_method_calc_size(RBinJavaBootStrapMethod *bsm);
233 R_API ut64 r_bin_java_element_pair_calc_size(RBinJavaElementValuePair *evp);
234 R_API ut64 r_bin_java_element_value_calc_size(RBinJavaElementValue *element_value);
235 
236 R_API ut64 r_bin_java_unknown_cp_calc_size(RBinJavaCPTypeObj *obj);
237 R_API ut64 r_bin_java_class_cp_calc_size(RBinJavaCPTypeObj *obj);
238 R_API ut64 r_bin_java_fieldref_cp_calc_size(RBinJavaCPTypeObj *obj);
239 R_API ut64 r_bin_java_methodref_cp_calc_size(RBinJavaCPTypeObj *obj);
240 R_API ut64 r_bin_java_interfacemethodref_cp_calc_size(RBinJavaCPTypeObj *obj);
241 R_API ut64 r_bin_java_name_and_type_cp_calc_size(RBinJavaCPTypeObj *obj);
242 R_API ut64 r_bin_java_string_cp_calc_size(RBinJavaCPTypeObj *obj);
243 R_API ut64 r_bin_java_integer_cp_calc_size(RBinJavaCPTypeObj *obj);
244 R_API ut64 r_bin_java_float_cp_calc_size(RBinJavaCPTypeObj *obj);
245 R_API ut64 r_bin_java_long_cp_calc_size(RBinJavaCPTypeObj *obj);
246 R_API ut64 r_bin_java_double_cp_calc_size(RBinJavaCPTypeObj *obj);
247 R_API ut64 r_bin_java_utf8_cp_calc_size(RBinJavaCPTypeObj *obj);
248 R_API ut64 r_bin_java_do_nothing_calc_size(RBinJavaCPTypeObj *obj);
249 R_API ut64 r_bin_java_methodhandle_cp_calc_size(RBinJavaCPTypeObj *obj);
250 R_API ut64 r_bin_java_methodtype_cp_calc_size(RBinJavaCPTypeObj *obj);
251 R_API ut64 r_bin_java_invokedynamic_cp_calc_size(RBinJavaCPTypeObj *obj);
252 R_API RBinJavaStackMapFrame *r_bin_java_default_stack_frame(void);
253 
254 R_API RList *r_bin_java_find_cp_const_by_val_float(RBinJavaObj *bin_obj, const ut8 *bytes, ut32 len);
255 R_API RList *r_bin_java_find_cp_const_by_val_double(RBinJavaObj *bin_obj, const ut8 *bytes, ut32 len);
256 R_API RList *r_bin_java_find_cp_const_by_val_int(RBinJavaObj *bin_obj, const ut8 *bytes, ut32 len);
257 R_API RList *r_bin_java_find_cp_const_by_val_long(RBinJavaObj *bin_obj, const ut8 *bytes, ut32 len);
258 R_API RList *r_bin_java_find_cp_const_by_val_utf8(RBinJavaObj *bin_obj, const ut8 *bytes, ut32 len);
259 R_API ut8 *r_bin_java_cp_append_classref_and_name(RBinJavaObj *bin, ut32 *out_sz, const char *classname, const ut32 classname_len);
260 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);
261 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);
262 R_API ut8 *U(r_bin_java_cp_get_method_ref)(RBinJavaObj * bin, ut32 * out_sz, ut16 class_idx, ut16 name_and_type_idx);
263 R_API ut8 *U(r_bin_java_cp_get_field_ref)(RBinJavaObj * bin, ut32 * out_sz, ut16 class_idx, ut16 name_and_type_idx);
264 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);
265 R_API ut8 *r_bin_java_cp_get_2_ut16(RBinJavaObj *bin, ut32 *out_sz, ut8 tag, ut16 ut16_one, ut16 ut16_two);
266 R_API ut8 *r_bin_java_cp_get_name_type(RBinJavaObj *bin, ut32 *out_sz, ut16 name_idx, ut16 type_idx);
267 
convert_string(const char * bytes,ut32 len)268 static char *convert_string(const char *bytes, ut32 len) {
269 	ut32 idx = 0, pos = 0;
270 	ut32 str_sz = 32 * len + 1;
271 	char *cpy_buffer = len > 0 ? malloc (str_sz) : NULL;
272 	if (!cpy_buffer) {
273 		return cpy_buffer;
274 	}
275 	// 4x is the increase from byte to \xHH where HH represents hexed byte
276 	memset (cpy_buffer, 0, str_sz);
277 	while (idx < len && pos < len) {
278 		if (dso_json_char_needs_hexing (bytes[idx])) {
279 			if (pos + 2 < len) {
280 				free (cpy_buffer);
281 				return NULL;
282 			}
283 			sprintf (cpy_buffer + pos, "\\x%02x", bytes[idx]);
284 			pos += 4;
285 		} else {
286 			cpy_buffer[pos] = bytes[idx];
287 			pos++;
288 		}
289 		idx++;
290 	}
291 	return cpy_buffer;
292 }
293 
294 // taken from LLVM Code Byte Swap
295 // TODO: move into r_util
U(r_bin_java_swap_uint)296 R_API ut32 U(r_bin_java_swap_uint)(ut32 x) {
297 	const ut32 Byte0 = x & 0x000000FF;
298 	const ut32 Byte1 = x & 0x0000FF00;
299 	const ut32 Byte2 = x & 0x00FF0000;
300 	const ut32 Byte3 = x & 0xFF000000;
301 	return (Byte0 << 24) | (Byte1 << 8) | (Byte2 >> 8) | (Byte3 >> 24);
302 }
303 
304 static bool R_BIN_JAVA_NULL_TYPE_INITTED = false;
305 // XXX - this is a global variable used while parsing the class file
306 // this variable should DIE.
307 static RBinJavaObj *R_BIN_JAVA_GLOBAL_BIN = NULL;
308 static RBinJavaAccessFlags FIELD_ACCESS_FLAGS[] = {
309 	{ "public", R_BIN_JAVA_FIELD_ACC_PUBLIC, 6 },
310 	{ "private", R_BIN_JAVA_FIELD_ACC_PRIVATE, 7 },
311 	{ "protected", R_BIN_JAVA_FIELD_ACC_PROTECTED, 9 },
312 	{ "static", R_BIN_JAVA_FIELD_ACC_STATIC, 6 },
313 	{ "final", R_BIN_JAVA_FIELD_ACC_FINAL, 5 },
314 	{ "undefined.0x0020", 0x0020, 16 },
315 	{ "volatile", R_BIN_JAVA_FIELD_ACC_VOLATILE, 8 },
316 	{ "transient", R_BIN_JAVA_FIELD_ACC_TRANSIENT, 9 },
317 	{ "undefined.0x0100", 0x0100, 16 },
318 	{ "undefined.0x0200", 0x0200, 16 },
319 	{ "undefined.0x0400", 0x0400, 16 },
320 	{ "undefined.0x0800", 0x0800, 16 },
321 	{ "synthetic", R_BIN_JAVA_FIELD_ACC_SYNTHETIC, 9 },
322 	{ "undefined.0x2000", 0x2000, 16 },
323 	{ "enum", R_BIN_JAVA_FIELD_ACC_ENUM, 16 },
324 	{ "undefined.0x8000", 0x8000, 16 },
325 	{ NULL, 0, 0 }
326 };
327 static RBinJavaAccessFlags METHOD_ACCESS_FLAGS[] = {
328 	{ "public", R_BIN_JAVA_METHOD_ACC_PUBLIC, 6 },
329 	{ "private", R_BIN_JAVA_METHOD_ACC_PRIVATE, 7 },
330 	{ "protected", R_BIN_JAVA_METHOD_ACC_PROTECTED, 9 },
331 	{ "static", R_BIN_JAVA_METHOD_ACC_STATIC, 6 },
332 	{ "final", R_BIN_JAVA_METHOD_ACC_FINAL, 5 },
333 	{ "synchronized", R_BIN_JAVA_METHOD_ACC_SYNCHRONIZED, 12 },
334 	{ "bridge", R_BIN_JAVA_METHOD_ACC_BRIDGE, 6 },
335 	{ "varargs", R_BIN_JAVA_METHOD_ACC_VARARGS, 7 },
336 	{ "native", R_BIN_JAVA_METHOD_ACC_NATIVE, 6 },
337 	{ "interface", R_BIN_JAVA_METHOD_ACC_INTERFACE, 9 },
338 	{ "abstract", R_BIN_JAVA_METHOD_ACC_ABSTRACT, 8 },
339 	{ "strict", R_BIN_JAVA_METHOD_ACC_STRICT, 6 },
340 	{ "synthetic", R_BIN_JAVA_METHOD_ACC_SYNTHETIC, 9 },
341 	{ "annotation", R_BIN_JAVA_METHOD_ACC_ANNOTATION, 10 },
342 	{ "enum", R_BIN_JAVA_METHOD_ACC_ENUM, 4 },
343 	{ "undefined.0x8000", 0x8000, 16 },
344 	{ NULL, 0, 0 }
345 };
346 // XXX - Fix these there are some incorrect ongs
347 static RBinJavaAccessFlags CLASS_ACCESS_FLAGS[] = {
348 	{ "public", R_BIN_JAVA_CLASS_ACC_PUBLIC, 6 },
349 	{ "undefined.0x0002", 0x0002, 16 },
350 	{ "undefined.0x0004", 0x0004, 16 },
351 	{ "undefined.0x0008", 0x0008, 16 },
352 	{ "final", R_BIN_JAVA_CLASS_ACC_FINAL, 5 },
353 	{ "super", R_BIN_JAVA_CLASS_ACC_SUPER, 5 },
354 	{ "undefined.0x0040", 0x0040, 16 },
355 	{ "undefined.0x0080", 0x0080, 16 },
356 	{ "undefined.0x0100", 0x0100, 16 },
357 	{ "interface", R_BIN_JAVA_CLASS_ACC_INTERFACE, 9 },
358 	{ "abstract", R_BIN_JAVA_CLASS_ACC_ABSTRACT, 8 },
359 	{ "undefined.0x0800", 0x0800, 16 },
360 	{ "synthetic", R_BIN_JAVA_CLASS_ACC_SYNTHETIC, 9 },
361 	{ "annotation", R_BIN_JAVA_CLASS_ACC_ANNOTATION, 10 },
362 	{ "enum", R_BIN_JAVA_CLASS_ACC_ENUM, 4 },
363 	{ "undefined.0x8000", 0x8000, 16 },
364 	{ NULL, 0, 0 }
365 };
366 static RBinJavaRefMetas R_BIN_JAVA_REF_METAS[] = {
367 	{ "Unknown", R_BIN_JAVA_REF_UNKNOWN },
368 	{ "GetField", R_BIN_JAVA_REF_GETFIELD },
369 	{ "GetStatic", R_BIN_JAVA_REF_GETSTATIC },
370 	{ "PutField", R_BIN_JAVA_REF_PUTFIELD },
371 	{ "PutStatic", R_BIN_JAVA_REF_PUTSTATIC },
372 	{ "InvokeVirtual", R_BIN_JAVA_REF_INVOKEVIRTUAL },
373 	{ "InvokeStatic", R_BIN_JAVA_REF_INVOKESTATIC },
374 	{ "InvokeSpecial", R_BIN_JAVA_REF_INVOKESPECIAL },
375 	{ "NewInvokeSpecial", R_BIN_JAVA_REF_NEWINVOKESPECIAL },
376 	{ "InvokeInterface", R_BIN_JAVA_REF_INVOKEINTERFACE }
377 };
378 static ut16 R_BIN_JAVA_ELEMENT_VALUE_METAS_SZ = 14;
379 static RBinJavaElementValueMetas R_BIN_JAVA_ELEMENT_VALUE_METAS[] = {
380 	{ "Byte", R_BIN_JAVA_EV_TAG_BYTE, NULL },
381 	{ "Char", R_BIN_JAVA_EV_TAG_CHAR, NULL },
382 	{ "Double", R_BIN_JAVA_EV_TAG_DOUBLE, NULL },
383 	{ "Float", R_BIN_JAVA_EV_TAG_FLOAT, NULL },
384 	{ "Integer", R_BIN_JAVA_EV_TAG_INT, NULL },
385 	{ "Long", R_BIN_JAVA_EV_TAG_LONG, NULL },
386 	{ "Short", R_BIN_JAVA_EV_TAG_SHORT, NULL },
387 	{ "Boolean", R_BIN_JAVA_EV_TAG_BOOLEAN, NULL },
388 	{ "Array of ", R_BIN_JAVA_EV_TAG_ARRAY, NULL },
389 	{ "String", R_BIN_JAVA_EV_TAG_STRING, NULL },
390 	{ "Enum", R_BIN_JAVA_EV_TAG_ENUM, NULL },
391 	{ "Class", R_BIN_JAVA_EV_TAG_CLASS, NULL },
392 	{ "Annotation", R_BIN_JAVA_EV_TAG_ANNOTATION, NULL },
393 	{ "Unknown", R_BIN_JAVA_EV_TAG_UNKNOWN, NULL },
394 };
395 static RBinJavaVerificationMetas R_BIN_JAVA_VERIFICATION_METAS[] = {
396 	{ "Top", R_BIN_JAVA_STACKMAP_TOP },
397 	{ "Integer", R_BIN_JAVA_STACKMAP_INTEGER },
398 	{ "Float", R_BIN_JAVA_STACKMAP_FLOAT },
399 	{ "Double", R_BIN_JAVA_STACKMAP_DOUBLE },
400 	{ "Long", R_BIN_JAVA_STACKMAP_LONG },
401 	{ "NULL", R_BIN_JAVA_STACKMAP_NULL },
402 	{ "This", R_BIN_JAVA_STACKMAP_THIS },
403 	{ "Object", R_BIN_JAVA_STACKMAP_OBJECT },
404 	{ "Uninitialized", R_BIN_JAVA_STACKMAP_UNINIT },
405 	{ "Unknown", R_BIN_JAVA_STACKMAP_UNKNOWN }
406 };
407 static RBinJavaStackMapFrameMetas R_BIN_JAVA_STACK_MAP_FRAME_METAS[] = {
408 	{ "ImplicitStackFrame", R_BIN_JAVA_STACK_FRAME_IMPLICIT, NULL },
409 	{ "Same", R_BIN_JAVA_STACK_FRAME_SAME, NULL },
410 	{ "SameLocals1StackItem", R_BIN_JAVA_STACK_FRAME_SAME_LOCALS_1, NULL },
411 	{ "Chop", R_BIN_JAVA_STACK_FRAME_CHOP, NULL },
412 	{ "SameFrameExtended", R_BIN_JAVA_STACK_FRAME_SAME_FRAME_EXTENDED, NULL },
413 	{ "Append", R_BIN_JAVA_STACK_FRAME_APPEND, NULL },
414 	{ "FullFrame", R_BIN_JAVA_STACK_FRAME_FULL_FRAME, NULL },
415 	{ "Reserved", R_BIN_JAVA_STACK_FRAME_RESERVED, NULL }
416 };
417 
418 static RBinJavaCPTypeObjectAllocs R_BIN_ALLOCS_CONSTANTS[] = {
419 	{ r_bin_java_do_nothing_new, r_bin_java_do_nothing_free, r_bin_java_print_null_cp_summary, r_bin_java_do_nothing_calc_size, r_bin_java_print_null_cp_stringify },
420 	{ r_bin_java_utf8_cp_new, r_bin_java_utf8_info_free, r_bin_java_print_utf8_cp_summary, r_bin_java_utf8_cp_calc_size, r_bin_java_print_utf8_cp_stringify },
421 	{ r_bin_java_unknown_cp_new, r_bin_java_default_free, r_bin_java_print_unknown_cp_summary, r_bin_java_unknown_cp_calc_size, r_bin_java_print_unknown_cp_stringify },
422 	{ r_bin_java_integer_cp_new, r_bin_java_default_free, r_bin_java_print_integer_cp_summary, r_bin_java_integer_cp_calc_size, r_bin_java_print_integer_cp_stringify },
423 	{ r_bin_java_float_cp_new, r_bin_java_default_free, r_bin_java_print_float_cp_summary, r_bin_java_float_cp_calc_size, r_bin_java_print_float_cp_stringify },
424 	{ r_bin_java_long_cp_new, r_bin_java_default_free, r_bin_java_print_long_cp_summary, r_bin_java_long_cp_calc_size, r_bin_java_print_long_cp_stringify },
425 	{ r_bin_java_double_cp_new, r_bin_java_default_free, r_bin_java_print_double_cp_summary, r_bin_java_double_cp_calc_size, r_bin_java_print_double_cp_stringify },
426 	{ r_bin_java_class_cp_new, r_bin_java_default_free, r_bin_java_print_classref_cp_summary, r_bin_java_class_cp_calc_size, r_bin_java_print_classref_cp_stringify },
427 	{ r_bin_java_string_cp_new, r_bin_java_default_free, r_bin_java_print_string_cp_summary, r_bin_java_string_cp_calc_size, r_bin_java_print_string_cp_stringify },
428 	{ r_bin_java_fieldref_cp_new, r_bin_java_default_free, r_bin_java_print_fieldref_cp_summary, r_bin_java_fieldref_cp_calc_size, r_bin_java_print_fieldref_cp_stringify },
429 	{ r_bin_java_methodref_cp_new, r_bin_java_default_free, r_bin_java_print_methodref_cp_summary, r_bin_java_methodref_cp_calc_size, r_bin_java_print_methodref_cp_stringify },
430 	{ r_bin_java_interfacemethodref_cp_new, r_bin_java_default_free, r_bin_java_print_interfacemethodref_cp_summary, r_bin_java_interfacemethodref_cp_calc_size, r_bin_java_print_interfacemethodref_cp_stringify },
431 	{ r_bin_java_name_and_type_cp_new, r_bin_java_default_free, r_bin_java_print_name_and_type_cp_summary, r_bin_java_name_and_type_cp_calc_size, r_bin_java_print_name_and_type_cp_stringify },
432 	{ NULL, NULL, NULL, NULL, NULL },
433 	{ NULL, NULL, NULL, NULL, NULL },
434 	{ r_bin_java_methodhandle_cp_new, r_bin_java_default_free, r_bin_java_print_methodhandle_cp_summary, r_bin_java_methodhandle_cp_calc_size, r_bin_java_print_methodhandle_cp_stringify },
435 	{ r_bin_java_methodtype_cp_new, r_bin_java_default_free, r_bin_java_print_methodtype_cp_summary, r_bin_java_methodtype_cp_calc_size, r_bin_java_print_methodtype_cp_stringify },
436 	{ NULL, NULL, NULL, NULL, NULL },
437 	{ r_bin_java_invokedynamic_cp_new, r_bin_java_default_free, r_bin_java_print_invokedynamic_cp_summary, r_bin_java_invokedynamic_cp_calc_size, r_bin_java_print_invokedynamic_cp_stringify },
438 };
439 static RBinJavaCPTypeObj R_BIN_JAVA_NULL_TYPE;
440 static ut8 R_BIN_JAVA_CP_METAS_SZ = 12;
441 static RBinJavaCPTypeMetas R_BIN_JAVA_CP_METAS[] = {
442 	// Each field has a name pointer and a tag field
443 	{ "NULL", R_BIN_JAVA_CP_NULL, 0, &R_BIN_ALLOCS_CONSTANTS[0] },
444 	{ "Utf8", R_BIN_JAVA_CP_UTF8, 3, &R_BIN_ALLOCS_CONSTANTS[1] },  // 2 bytes = length, N bytes string (containts a pointer in the field)
445 	{ "Unknown", R_BIN_JAVA_CP_UNKNOWN, 0, &R_BIN_ALLOCS_CONSTANTS[2] },
446 	{ "Integer", R_BIN_JAVA_CP_INTEGER, 5, &R_BIN_ALLOCS_CONSTANTS[3] },  // 4 bytes
447 	{ "Float", R_BIN_JAVA_CP_FLOAT, 5, &R_BIN_ALLOCS_CONSTANTS[4] },  // 4 bytes
448 	{ "Long", R_BIN_JAVA_CP_LONG, 9, &R_BIN_ALLOCS_CONSTANTS[5] }, // 4 high 4 low
449 	{ "Double", R_BIN_JAVA_CP_DOUBLE, 9, &R_BIN_ALLOCS_CONSTANTS[6] }, // 4 high 4 low
450 	{ "Class", R_BIN_JAVA_CP_CLASS, 3, &R_BIN_ALLOCS_CONSTANTS[7] }, // 2 name_idx
451 	{ "String", R_BIN_JAVA_CP_STRING, 3, &R_BIN_ALLOCS_CONSTANTS[8] }, // 2 string_idx
452 	{ "FieldRef", R_BIN_JAVA_CP_FIELDREF, 5, &R_BIN_ALLOCS_CONSTANTS[9] }, // 2 class idx, 2 name/type_idx
453 	{ "MethodRef", R_BIN_JAVA_CP_METHODREF, 5, &R_BIN_ALLOCS_CONSTANTS[10] }, // 2 class idx, 2 name/type_idx
454 	{ "InterfaceMethodRef", R_BIN_JAVA_CP_INTERFACEMETHOD_REF, 5, &R_BIN_ALLOCS_CONSTANTS[11] },  // 2 class idx, 2 name/type_idx
455 	{ "NameAndType", R_BIN_JAVA_CP_NAMEANDTYPE, 5, &R_BIN_ALLOCS_CONSTANTS[12] }, // 4 high 4 low
456 	{ "Unknown", R_BIN_JAVA_CP_UNKNOWN, 0, &R_BIN_ALLOCS_CONSTANTS[2] },
457 	{ "Unknown", R_BIN_JAVA_CP_UNKNOWN, 0, &R_BIN_ALLOCS_CONSTANTS[2] },
458 	{ "MethodHandle", R_BIN_JAVA_CP_METHODHANDLE, 4, &R_BIN_ALLOCS_CONSTANTS[15] }, // 4 high 4 low
459 	{ "MethodType", R_BIN_JAVA_CP_METHODTYPE, 3, &R_BIN_ALLOCS_CONSTANTS[16] }, // 4 high 4 low
460 	{ "Unknown", R_BIN_JAVA_CP_UNKNOWN, 0, &R_BIN_ALLOCS_CONSTANTS[2] },
461 	{ "InvokeDynamic", R_BIN_JAVA_CP_INVOKEDYNAMIC, 5, &R_BIN_ALLOCS_CONSTANTS[18] }, // 4 high 4 low
462 };
463 static RBinJavaAttrInfoObjectAllocs RBIN_JAVA_ATTRS_ALLOCS[] = {
464 	{ r_bin_java_annotation_default_attr_new, r_bin_java_annotation_default_attr_free, r_bin_java_print_annotation_default_attr_summary, r_bin_java_annotation_default_attr_calc_size },
465 	{ r_bin_java_bootstrap_methods_attr_new, r_bin_java_bootstrap_methods_attr_free, r_bin_java_print_bootstrap_methods_attr_summary, r_bin_java_bootstrap_methods_attr_calc_size },
466 	{ r_bin_java_code_attr_new, r_bin_java_code_attr_free, r_bin_java_print_code_attr_summary, r_bin_java_code_attr_calc_size },
467 	{ r_bin_java_constant_value_attr_new, r_bin_java_constant_value_attr_free, r_bin_java_print_constant_value_attr_summary, r_bin_java_constant_value_attr_calc_size },
468 	{ r_bin_java_deprecated_attr_new, r_bin_java_deprecated_attr_free, r_bin_java_print_deprecated_attr_summary, r_bin_java_deprecated_attr_calc_size },
469 	{ r_bin_java_enclosing_methods_attr_new, r_bin_java_enclosing_methods_attr_free, r_bin_java_print_enclosing_methods_attr_summary, r_bin_java_enclosing_methods_attr_calc_size },
470 	{ r_bin_java_exceptions_attr_new, r_bin_java_exceptions_attr_free, r_bin_java_print_exceptions_attr_summary, r_bin_java_exceptions_attr_calc_size },
471 	{ r_bin_java_inner_classes_attr_new, r_bin_java_inner_classes_attr_free, r_bin_java_print_inner_classes_attr_summary, r_bin_java_inner_classes_attr_calc_size },
472 	{ r_bin_java_line_number_table_attr_new, r_bin_java_line_number_table_attr_free, r_bin_java_print_line_number_table_attr_summary, r_bin_java_line_number_table_attr_calc_size },
473 	{ r_bin_java_local_variable_table_attr_new, r_bin_java_local_variable_table_attr_free, r_bin_java_print_local_variable_table_attr_summary, r_bin_java_local_variable_table_attr_calc_size },
474 	{ r_bin_java_local_variable_type_table_attr_new, r_bin_java_local_variable_type_table_attr_free, r_bin_java_print_local_variable_type_table_attr_summary, r_bin_java_local_variable_type_table_attr_calc_size },
475 	{ r_bin_java_rti_annotations_attr_new, r_bin_java_rti_annotations_attr_free, r_bin_java_print_rti_annotations_attr_summary, r_bin_java_rti_annotations_attr_calc_size },
476 	{ r_bin_java_rtip_annotations_attr_new, r_bin_java_rtip_annotations_attr_free, r_bin_java_print_rtip_annotations_attr_summary, r_bin_java_rtip_annotations_attr_calc_size },
477 	{ r_bin_java_rtv_annotations_attr_new, r_bin_java_rtv_annotations_attr_free, r_bin_java_print_rtv_annotations_attr_summary, r_bin_java_rtv_annotations_attr_calc_size },
478 	{ r_bin_java_rtvp_annotations_attr_new, r_bin_java_rtvp_annotations_attr_free, r_bin_java_print_rtvp_annotations_attr_summary, r_bin_java_rtvp_annotations_attr_calc_size },
479 	{ r_bin_java_signature_attr_new, r_bin_java_signature_attr_free, r_bin_java_print_signature_attr_summary, r_bin_java_signature_attr_calc_size },
480 	{ r_bin_java_source_debug_attr_new, r_bin_java_source_debug_attr_free, r_bin_java_print_source_debug_attr_summary, r_bin_java_source_debug_attr_calc_size },
481 	{ r_bin_java_source_code_file_attr_new, r_bin_java_source_code_file_attr_free, r_bin_java_print_source_code_file_attr_summary, r_bin_java_source_code_file_attr_calc_size },
482 	{ r_bin_java_stack_map_table_attr_new, r_bin_java_stack_map_table_attr_free, r_bin_java_print_stack_map_table_attr_summary, r_bin_java_stack_map_table_attr_calc_size },
483 	{ r_bin_java_synthetic_attr_new, r_bin_java_synthetic_attr_free, r_bin_java_print_synthetic_attr_summary, r_bin_java_synthetic_attr_calc_size },
484 	{ r_bin_java_unknown_attr_new, r_bin_java_unknown_attr_free, r_bin_java_print_unknown_attr_summary, r_bin_java_unknown_attr_calc_size }
485 };
486 // R_API ut32 RBIN_JAVA_ATTRS_METAS_SZ = 21;
487 static ut32 RBIN_JAVA_ATTRS_METAS_SZ = 20;
488 static RBinJavaAttrMetas RBIN_JAVA_ATTRS_METAS[] = {
489 	{ "AnnotationDefault", R_BIN_JAVA_ATTR_TYPE_ANNOTATION_DEFAULT_ATTR, &RBIN_JAVA_ATTRS_ALLOCS[0] },
490 	{ "BootstrapMethods", R_BIN_JAVA_ATTR_TYPE_BOOTSTRAP_METHODS_ATTR, &RBIN_JAVA_ATTRS_ALLOCS[1] },
491 	{ "Code", R_BIN_JAVA_ATTR_TYPE_CODE_ATTR, &RBIN_JAVA_ATTRS_ALLOCS[2] },
492 	{ "ConstantValue", R_BIN_JAVA_ATTR_TYPE_CONST_VALUE_ATTR, &RBIN_JAVA_ATTRS_ALLOCS[3] },
493 	{ "Deperecated", R_BIN_JAVA_ATTR_TYPE_DEPRECATED_ATTR, &RBIN_JAVA_ATTRS_ALLOCS[4] },
494 	{ "EnclosingMethod", R_BIN_JAVA_ATTR_TYPE_ENCLOSING_METHOD_ATTR, &RBIN_JAVA_ATTRS_ALLOCS[5] },
495 	{ "Exceptions", R_BIN_JAVA_ATTR_TYPE_EXCEPTIONS_ATTR, &RBIN_JAVA_ATTRS_ALLOCS[6] },
496 	{ "InnerClasses", R_BIN_JAVA_ATTR_TYPE_INNER_CLASSES_ATTR, &RBIN_JAVA_ATTRS_ALLOCS[7] },
497 	{ "LineNumberTable", R_BIN_JAVA_ATTR_TYPE_LINE_NUMBER_TABLE_ATTR, &RBIN_JAVA_ATTRS_ALLOCS[8] },
498 	{ "LocalVariableTable", R_BIN_JAVA_ATTR_TYPE_LOCAL_VARIABLE_TABLE_ATTR, &RBIN_JAVA_ATTRS_ALLOCS[9] },
499 	{ "LocalVariableTypeTable", R_BIN_JAVA_ATTR_TYPE_LOCAL_VARIABLE_TYPE_TABLE_ATTR, &RBIN_JAVA_ATTRS_ALLOCS[10] },
500 	{ "RuntimeInvisibleAnnotations", R_BIN_JAVA_ATTR_TYPE_RUNTIME_INVISIBLE_ANNOTATION_ATTR, &RBIN_JAVA_ATTRS_ALLOCS[11] },
501 	{ "RuntimeInvisibleParameterAnnotations", R_BIN_JAVA_ATTR_TYPE_RUNTIME_INVISIBLE_PARAMETER_ANNOTATION_ATTR, &RBIN_JAVA_ATTRS_ALLOCS[12] },
502 	{ "RuntimeVisibleAnnotations", R_BIN_JAVA_ATTR_TYPE_RUNTIME_VISIBLE_ANNOTATION_ATTR, &RBIN_JAVA_ATTRS_ALLOCS[13] },
503 	{ "RuntimeVisibleParameterAnnotations", R_BIN_JAVA_ATTR_TYPE_RUNTIME_VISIBLE_PARAMETER_ANNOTATION_ATTR, &RBIN_JAVA_ATTRS_ALLOCS[14] },
504 	{ "Signature", R_BIN_JAVA_ATTR_TYPE_SIGNATURE_ATTR, &RBIN_JAVA_ATTRS_ALLOCS[15] },
505 	{ "SourceDebugExtension", R_BIN_JAVA_ATTR_TYPE_SOURCE_DEBUG_EXTENTSION_ATTR, &RBIN_JAVA_ATTRS_ALLOCS[16] },
506 	{ "SourceFile", R_BIN_JAVA_ATTR_TYPE_SOURCE_FILE_ATTR, &RBIN_JAVA_ATTRS_ALLOCS[17] },
507 	{ "StackMapTable", R_BIN_JAVA_ATTR_TYPE_STACK_MAP_TABLE_ATTR, &RBIN_JAVA_ATTRS_ALLOCS[18] },
508 	// { "StackMap", R_BIN_JAVA_ATTR_TYPE_STACK_MAP_TABLE_ATTR, &RBIN_JAVA_ATTRS_ALLOCS[18]},
509 	{ "Synthetic", R_BIN_JAVA_ATTR_TYPE_SYNTHETIC_ATTR, &RBIN_JAVA_ATTRS_ALLOCS[19] },
510 	{ "Unknown", R_BIN_JAVA_ATTR_TYPE_UNKNOWN_ATTR, &RBIN_JAVA_ATTRS_ALLOCS[20] }
511 };
512 
r_bin_java_is_old_format(RBinJavaObj * bin)513 R_API bool r_bin_java_is_old_format(RBinJavaObj *bin) {
514 	return bin->cf.major[1] == 45 && bin->cf.minor[1] <= 2;
515 }
516 
r_bin_java_reset_bin_info(RBinJavaObj * bin)517 R_API void r_bin_java_reset_bin_info(RBinJavaObj *bin) {
518 	free (bin->cf2.flags_str);
519 	free (bin->cf2.this_class_name);
520 	r_list_free (bin->imports_list);
521 	r_list_free (bin->methods_list);
522 	r_list_free (bin->fields_list);
523 	r_list_free (bin->attrs_list);
524 	r_list_free (bin->cp_list);
525 	r_list_free (bin->interfaces_list);
526 	r_str_constpool_fini (&bin->constpool);
527 	memset (bin, 0, sizeof (RBinJavaObj));
528 	r_str_constpool_init (&bin->constpool);
529 	bin->cf2.flags_str = strdup ("unknown");
530 	bin->cf2.this_class_name = strdup ("unknown");
531 	bin->imports_list = r_list_newf (free);
532 	bin->methods_list = r_list_newf (r_bin_java_fmtype_free);
533 	bin->fields_list = r_list_newf (r_bin_java_fmtype_free);
534 	bin->attrs_list = r_list_newf (r_bin_java_attribute_free);
535 	bin->cp_list = r_list_newf (r_bin_java_constant_pool);
536 	bin->interfaces_list = r_list_newf (r_bin_java_interface_free);
537 }
538 
r_bin_java_unmangle_method(const char * flags,const char * name,const char * params,const char * r_value)539 R_API char *r_bin_java_unmangle_method(const char *flags, const char *name, const char *params, const char *r_value) {
540 	RList *the_list = params ? r_bin_java_extract_type_values (params) : r_list_new ();
541 	RListIter *iter = NULL;
542 	// second case removes leading space if no flags are given
543 	const char *fmt = flags ? "%s %s %s (%s)" : "%s%s %s (%s)";
544 	char *str = NULL, *f_val_str = NULL, *r_val_str = NULL, *prototype = NULL, *p_val_str = NULL;
545 	ut32 params_idx = 0, params_len = 0, prototype_len = 0;
546 	if (!extract_type_value (r_value, &r_val_str)) {
547 		r_list_free (the_list);
548 		return NULL;
549 	}
550 	if (!r_val_str) {
551 		r_val_str = strdup ("UNKNOWN");
552 	}
553 	f_val_str = strdup (r_str_get (flags));
554 	r_list_foreach (the_list, iter, str) {
555 		params_len += strlen (str);
556 		if (params_idx > 0) {
557 			params_len += 2;
558 		}
559 		params_idx++;
560 	}
561 	if (params_len > 0) {
562 		ut32 offset = 0;
563 		params_len += 1;
564 		p_val_str = malloc (params_len);
565 		r_list_foreach (the_list, iter, str) {
566 			if (offset != 0) {
567 				offset += snprintf (p_val_str + offset, params_len - offset, ", %s", str);
568 			} else {
569 				offset += snprintf (p_val_str + offset, params_len - offset, "%s", str);
570 			}
571 		}
572 	} else {
573 		p_val_str = strdup ("");
574 	}
575 
576 	prototype_len += (flags ? strlen (flags) + 1 : 0); // space vs no space
577 	prototype_len += strlen (name) + 1; // name + space
578 	prototype_len += strlen (r_val_str) + 1; // r_value + space
579 	prototype_len += strlen (p_val_str) + 3; // space + l_paren + params + r_paren
580 	prototype_len += 1; // null
581 	prototype = malloc (prototype_len);
582 	/// TODO enable this function and start using it to demangle strings
583 	snprintf (prototype, prototype_len, fmt, f_val_str, r_val_str, name, p_val_str);
584 	free (f_val_str);
585 	free (r_val_str);
586 	free (p_val_str);
587 	r_list_free (the_list);
588 	return prototype;
589 }
590 
r_bin_java_unmangle(const char * flags,const char * name,const char * descriptor)591 R_API char *r_bin_java_unmangle(const char *flags, const char *name, const char *descriptor) {
592 	ut32 l_paren_pos = -1, r_paren_pos = -1;
593 	char *result = NULL;
594 	ut32 desc_len = descriptor && *descriptor ? strlen (descriptor) : 0,
595 	name_len = name && *name ? strlen (name) : 0,
596 	flags_len = flags && *flags ? strlen (flags) : 0,
597 	i = 0;
598 	if (desc_len == 0 || name == 0) {
599 		return NULL;
600 	}
601 	for (i = 0; i < desc_len; i++) {
602 		if (descriptor[i] == '(') {
603 			l_paren_pos = i;
604 		} else if (l_paren_pos != (ut32) - 1 && descriptor[i] == ')') {
605 			r_paren_pos = i;
606 			break;
607 		}
608 	}
609 	// handle field case;
610 	if (l_paren_pos == (ut32) - 1 && r_paren_pos == (ut32) - 1) {
611 		char *unmangle_field_desc = NULL;
612 		ut32 len = extract_type_value (descriptor, &unmangle_field_desc);
613 		if (len == 0) {
614 			eprintf ("Warning: attempting to unmangle invalid type descriptor.\n");
615 			free (unmangle_field_desc);
616 			return result;
617 		}
618 		if (flags_len > 0) {
619 			len += (flags_len + name_len + 5); // space and null
620 			result = malloc (len);
621 			snprintf (result, len, "%s %s %s", flags, unmangle_field_desc, name);
622 		} else {
623 			len += (name_len + 5); // space and null
624 			result = malloc (len);
625 			snprintf (result, len, "%s %s", unmangle_field_desc, name);
626 		}
627 		free (unmangle_field_desc);
628 	} else if (l_paren_pos != (ut32) - 1 &&
629 	r_paren_pos != (ut32) - 1 &&
630 	l_paren_pos < r_paren_pos) {
631 		// params_len account for l_paren + 1 and null
632 		ut32 params_len = r_paren_pos - (l_paren_pos + 1) != 0 ? r_paren_pos - (l_paren_pos + 1) + 1 : 0;
633 		char *params = params_len ? malloc (params_len) : NULL;
634 		const char *rvalue = descriptor + r_paren_pos + 1;
635 		if (params) {
636 			snprintf (params, params_len, "%s", descriptor + l_paren_pos + 1);
637 		}
638 		result = r_bin_java_unmangle_method (flags, name, params, rvalue);
639 		free (params);
640 	}
641 	return result;
642 }
643 
r_bin_java_get_bin_obj_json(RBinJavaObj * bin)644 R_API DsoJsonObj *r_bin_java_get_bin_obj_json(RBinJavaObj *bin) {
645 	DsoJsonObj *imports_list = r_bin_java_get_import_json_definitions (bin);
646 	DsoJsonObj *fields_list = r_bin_java_get_field_json_definitions (bin);
647 	DsoJsonObj *methods_list = r_bin_java_get_method_json_definitions (bin);
648 	// interfaces_list = r_bin_java_get_interface_json_definitions (bin);
649 	DsoJsonObj *class_dict = r_bin_java_get_class_info_json (bin);
650 	char *res = dso_json_obj_to_str (methods_list);
651 	// eprintf ("Resulting methods json: \n%s\n", res);
652 	free (res);
653 	if (dso_json_dict_insert_str_key_obj (class_dict, "methods", methods_list)) {
654 		// dso_json_list_free (methods_list);
655 		dso_json_obj_del (methods_list);
656 	}
657 
658 	res = dso_json_obj_to_str (fields_list);
659 	// eprintf ("Resulting fields json: \n%s\n", res);
660 	free (res);
661 	if (dso_json_dict_insert_str_key_obj (class_dict, "fields", fields_list)) {
662 		// dso_json_list_free (fields_list);
663 		dso_json_obj_del (fields_list);
664 	}
665 
666 	res = dso_json_obj_to_str (imports_list);
667 	// eprintf ("Resulting imports json: \n%s\n", res);
668 	free (res);
669 	if (dso_json_dict_insert_str_key_obj (class_dict, "imports", imports_list)) {
670 		// dso_json_list_free (imports_list);
671 		dso_json_obj_del (imports_list);
672 	}
673 
674 	// res = dso_json_obj_to_str (interfaces_list);
675 	// eprintf ("Resulting interfaces json: \n%s\n", res);
676 	// free (res);
677 	// dso_json_dict_insert_str_key_obj (class_dict, "interfaces", interfaces_list);
678 
679 	res = dso_json_obj_to_str (class_dict);
680 	// eprintf ("Resulting class info json: \n%s\n", res);
681 	free (res);
682 	// dso_json_obj_del (class_dict);
683 	return class_dict;
684 }
685 
r_bin_java_get_import_json_definitions(RBinJavaObj * bin)686 R_API DsoJsonObj *r_bin_java_get_import_json_definitions(RBinJavaObj *bin) {
687 	RList *the_list;
688 	DsoJsonObj *json_list = dso_json_list_new ();
689 	RListIter *iter = NULL;
690 	char *new_str;
691 
692 	if (!bin || !(the_list = r_bin_java_get_lib_names (bin))) {
693 		return json_list;
694 	}
695 
696 	r_list_foreach (the_list, iter, new_str) {
697 		char *tmp = new_str;
698 		// eprintf ("Processing string: %s\n", new_str);
699 		while (*tmp) {
700 			if (*tmp == '/') {
701 				*tmp = '.';
702 			}
703 			tmp++;
704 		}
705 		// eprintf ("adding string: %s\n", new_str);
706 		dso_json_list_append_str (json_list, new_str);
707 	}
708 	r_list_free (the_list);
709 	return json_list;
710 }
711 
r_bin_java_get_class_info_json(RBinJavaObj * bin)712 R_API DsoJsonObj *r_bin_java_get_class_info_json(RBinJavaObj *bin) {
713 	RList *classes = r_bin_java_get_classes (bin);
714 	DsoJsonObj *interfaces_list = dso_json_list_new ();
715 	DsoJsonObj *class_info_dict = dso_json_dict_new ();
716 	RBinClass *class_ = r_list_get_n (classes, 0);
717 
718 	if (class_) {
719 		int dummy = 0;
720 		RListIter *iter;
721 		RBinClass *class_v = NULL;
722 		// add access flags like in methods
723 		bool is_public = ((class_->visibility & R_BIN_JAVA_CLASS_ACC_PUBLIC) != 0);
724 		bool is_final = ((class_->visibility & R_BIN_JAVA_CLASS_ACC_FINAL) != 0);
725 		bool is_super = ((class_->visibility & R_BIN_JAVA_CLASS_ACC_SUPER) != 0);
726 		bool is_interface = ((class_->visibility & R_BIN_JAVA_CLASS_ACC_INTERFACE) != 0);
727 		bool is_abstract = ((class_->visibility & R_BIN_JAVA_CLASS_ACC_ABSTRACT) != 0);
728 		bool is_synthetic = ((class_->visibility & R_BIN_JAVA_CLASS_ACC_SYNTHETIC) != 0);
729 		bool is_annotation = ((class_->visibility & R_BIN_JAVA_CLASS_ACC_ANNOTATION) != 0);
730 		bool is_enum = ((class_->visibility & R_BIN_JAVA_CLASS_ACC_ENUM) != 0);
731 
732 		dso_json_dict_insert_str_key_num (class_info_dict, "access_flags", class_->visibility);
733 		dso_json_dict_insert_str_key_num (class_info_dict, "is_public", is_public);
734 		dso_json_dict_insert_str_key_num (class_info_dict, "is_final", is_final);
735 		dso_json_dict_insert_str_key_num (class_info_dict, "is_super", is_super);
736 		dso_json_dict_insert_str_key_num (class_info_dict, "is_interface", is_interface);
737 		dso_json_dict_insert_str_key_num (class_info_dict, "is_abstract", is_abstract);
738 		dso_json_dict_insert_str_key_num (class_info_dict, "is_synthetic", is_synthetic);
739 		dso_json_dict_insert_str_key_num (class_info_dict, "is_annotation", is_annotation);
740 		dso_json_dict_insert_str_key_num (class_info_dict, "is_enum", is_enum);
741 		dso_json_dict_insert_str_key_str (class_info_dict, "name", class_->name);
742 
743 		if (!class_->super) {
744 			DsoJsonObj *str = dso_json_str_new ();
745 			if (dso_json_dict_insert_str_key_obj (class_info_dict, "super", str)) {
746 				dso_json_str_free (str);
747 			}
748 		} else {
749 			dso_json_dict_insert_str_key_str (class_info_dict, "super", class_->super);
750 		}
751 
752 		r_list_foreach (classes, iter, class_v) {
753 			if (!dummy) {
754 				dummy++;
755 				continue;
756 			}
757 			// enumerate all interface classes and append them to the interfaces
758 			if ((class_v->visibility & R_BIN_JAVA_CLASS_ACC_INTERFACE) != 0) {
759 				dso_json_list_append_str (interfaces_list, class_v->name);
760 			}
761 		}
762 	}
763 	if (dso_json_dict_insert_str_key_obj (class_info_dict, "interfaces", interfaces_list)) {
764 		// dso_json_list_free (interfaces_list);
765 		dso_json_obj_del (interfaces_list);
766 	}
767 	r_list_free (classes);
768 	return class_info_dict;
769 }
770 
r_bin_java_get_interface_json_definitions(RBinJavaObj * bin)771 R_API DsoJsonObj *r_bin_java_get_interface_json_definitions(RBinJavaObj *bin) {
772 	RList *the_list;
773 	DsoJsonObj *json_list = dso_json_list_new ();
774 	RListIter *iter = NULL;
775 	char *new_str;
776 
777 	if (!bin || !(the_list = r_bin_java_get_interface_names (bin))) {
778 		return json_list;
779 	}
780 
781 	r_list_foreach (the_list, iter, new_str) {
782 		char *tmp = new_str;
783 		// eprintf ("Processing string: %s\n", new_str);
784 		while (*tmp) {
785 			if (*tmp == '/') {
786 				*tmp = '.';
787 			}
788 			tmp++;
789 		}
790 		// eprintf ("adding string: %s\n", new_str);
791 		dso_json_list_append_str (json_list, new_str);
792 	}
793 	r_list_free (the_list);
794 	return json_list;
795 }
796 
r_bin_java_get_method_json_definitions(RBinJavaObj * bin)797 R_API DsoJsonObj *r_bin_java_get_method_json_definitions(RBinJavaObj *bin) {
798 	RBinJavaField *fm_type = NULL;
799 	RListIter *iter = NULL;
800 	DsoJsonObj *json_list = dso_json_list_new ();
801 	if (!bin) {
802 		return json_list;
803 	}
804 	r_list_foreach (bin->methods_list, iter, fm_type) {
805 		DsoJsonObj *method_proto = r_bin_java_get_method_json_definition (bin, fm_type);
806 		// eprintf ("Method json: %s\n", method_proto);
807 		dso_json_list_append (json_list, method_proto);
808 	}
809 	return json_list;
810 }
811 
r_bin_java_get_field_json_definitions(RBinJavaObj * bin)812 R_API DsoJsonObj *r_bin_java_get_field_json_definitions(RBinJavaObj *bin) {
813 	RBinJavaField *fm_type = NULL;
814 	RListIter *iter = NULL;
815 	DsoJsonObj *json_list = dso_json_list_new ();
816 	if (!bin) {
817 		return json_list;
818 	}
819 	r_list_foreach (bin->fields_list, iter, fm_type) {
820 		DsoJsonObj *field_proto = r_bin_java_get_field_json_definition (bin, fm_type);
821 		// eprintf ("Field json: %s\n", field_proto);
822 		dso_json_list_append (json_list, field_proto);
823 	}
824 	return json_list;
825 }
826 
r_bin_java_create_method_fq_str(const char * klass,const char * name,const char * signature)827 R_API char *r_bin_java_create_method_fq_str(const char *klass, const char *name, const char *signature) {
828 	if (!klass) {
829 		klass = "null_class";
830 	}
831 	if (!name) {
832 		name = "null_name";
833 	}
834 	if (!signature) {
835 		signature = "null_signature";
836 	}
837 	return r_str_newf ("%s.%s.%s", klass, name, signature);
838 }
839 
r_bin_java_create_field_fq_str(const char * klass,const char * name,const char * signature)840 R_API char *r_bin_java_create_field_fq_str(const char *klass, const char *name, const char *signature) {
841 	if (!klass) {
842 		klass = "null_class";
843 	}
844 	if (!name) {
845 		name = "null_name";
846 	}
847 	if (!signature) {
848 		signature = "null_signature";
849 	}
850 	return r_str_newf ("%s %s.%s", signature, klass, name);
851 }
852 
r_bin_java_get_fm_type_definition_json(RBinJavaObj * bin,RBinJavaField * fm_type,int is_method)853 R_API DsoJsonObj *r_bin_java_get_fm_type_definition_json(RBinJavaObj *bin, RBinJavaField *fm_type, int is_method) {
854 	ut64 addr = UT64_MAX;
855 	char *prototype = NULL, *fq_name = NULL;
856 	bool is_native = ((fm_type->flags & R_BIN_JAVA_METHOD_ACC_NATIVE) != 0);
857 	bool is_static = ((fm_type->flags & R_BIN_JAVA_METHOD_ACC_STATIC) != 0);
858 	bool is_synthetic = ((fm_type->flags & R_BIN_JAVA_METHOD_ACC_SYNTHETIC) != 0);
859 	bool is_private = ((fm_type->flags & R_BIN_JAVA_METHOD_ACC_PRIVATE) != 0);
860 	bool is_public = ((fm_type->flags & R_BIN_JAVA_METHOD_ACC_PUBLIC) != 0);
861 	bool is_protected = ((fm_type->flags & R_BIN_JAVA_METHOD_ACC_PROTECTED) != 0);
862 	bool is_super = ((fm_type->flags & R_BIN_JAVA_CLASS_ACC_SUPER) != 0);
863 
864 	DsoJsonObj *fm_type_dict = dso_json_dict_new ();
865 	dso_json_dict_insert_str_key_num (fm_type_dict, "access_flags", fm_type->flags);
866 	dso_json_dict_insert_str_key_num (fm_type_dict, "is_method", is_method);
867 	dso_json_dict_insert_str_key_num (fm_type_dict, "is_native", is_native);
868 	dso_json_dict_insert_str_key_num (fm_type_dict, "is_synthetic", is_synthetic);
869 	dso_json_dict_insert_str_key_num (fm_type_dict, "is_private", is_private);
870 	dso_json_dict_insert_str_key_num (fm_type_dict, "is_public", is_public);
871 	dso_json_dict_insert_str_key_num (fm_type_dict, "is_static", is_static);
872 	dso_json_dict_insert_str_key_num (fm_type_dict, "is_protected", is_protected);
873 	dso_json_dict_insert_str_key_num (fm_type_dict, "is_super", is_super);
874 
875 	addr = r_bin_java_get_method_code_offset (fm_type);
876 	if (addr == 0) {
877 		addr = fm_type->file_offset;
878 	}
879 	addr += bin->loadaddr;
880 
881 	dso_json_dict_insert_str_key_num (fm_type_dict, "addr", addr);
882 	dso_json_dict_insert_str_key_num (fm_type_dict, "offset", fm_type->file_offset + bin->loadaddr);
883 	dso_json_dict_insert_str_key_str (fm_type_dict, "class_name", fm_type->class_name);
884 	dso_json_dict_insert_str_key_str (fm_type_dict, "signature", fm_type->descriptor);
885 	dso_json_dict_insert_str_key_str (fm_type_dict, "name", fm_type->name);
886 
887 	if (is_method) {
888 		fq_name = r_bin_java_create_method_fq_str (fm_type->class_name, fm_type->name, fm_type->descriptor);
889 	} else {
890 		fq_name = r_bin_java_create_field_fq_str (fm_type->class_name, fm_type->name, fm_type->descriptor);
891 	}
892 	dso_json_dict_insert_str_key_str (fm_type_dict, "fq_name", fq_name);
893 
894 	prototype = r_bin_java_unmangle (fm_type->flags_str, fm_type->name, fm_type->descriptor);
895 	dso_json_dict_insert_str_key_str (fm_type_dict, "prototype", prototype);
896 	free (prototype);
897 	free (fq_name);
898 	return fm_type_dict;
899 }
900 
r_bin_java_get_method_definition(RBinJavaField * fm_type)901 R_API char *r_bin_java_get_method_definition(RBinJavaField *fm_type) {
902 	return r_bin_java_unmangle (fm_type->flags_str, fm_type->name, fm_type->descriptor);
903 }
904 
r_bin_java_get_field_definition(RBinJavaField * fm_type)905 R_API char *r_bin_java_get_field_definition(RBinJavaField *fm_type) {
906 	return r_bin_java_unmangle (fm_type->flags_str, fm_type->name, fm_type->descriptor);
907 }
908 
r_bin_java_get_method_json_definition(RBinJavaObj * bin,RBinJavaField * fm_type)909 R_API DsoJsonObj *r_bin_java_get_method_json_definition(RBinJavaObj *bin, RBinJavaField *fm_type) {
910 	return r_bin_java_get_fm_type_definition_json (bin, fm_type, 1);
911 }
912 
r_bin_java_get_field_json_definition(RBinJavaObj * bin,RBinJavaField * fm_type)913 R_API DsoJsonObj *r_bin_java_get_field_json_definition(RBinJavaObj *bin, RBinJavaField *fm_type) {
914 	return r_bin_java_get_fm_type_definition_json (bin, fm_type, 0);
915 }
916 
r_bin_java_extract_reference_name(const char * input_str,char ** ref_str,ut8 array_cnt)917 R_API int r_bin_java_extract_reference_name(const char *input_str, char **ref_str, ut8 array_cnt) {
918 	char *new_str = NULL;
919 	ut32 str_len = array_cnt ? (array_cnt + 1) * 2 : 0;
920 	const char *str_pos = input_str;
921 	int consumed = 0, len = 0;
922 	if (!str_pos || *str_pos != 'L' || !*str_pos) {
923 		return -1;
924 	}
925 	consumed++;
926 	str_pos++;
927 	while (*str_pos && *str_pos != ';') {
928 		str_pos++;
929 		len++;
930 		consumed++;
931 	}
932 	str_pos = input_str + 1;
933 	free (*ref_str);
934 	str_len += len;
935 	*ref_str = malloc (str_len + 1);
936 	new_str = *ref_str;
937 	memcpy (new_str, str_pos, str_len);
938 	new_str[str_len] = 0;
939 	while (*new_str) {
940 		if (*new_str == '/') {
941 			*new_str = '.';
942 		}
943 		new_str++;
944 	}
945 	return len + 2;
946 }
947 
UNUSED_FUNCTION(r_bin_java_print_prototypes)948 R_API void UNUSED_FUNCTION(r_bin_java_print_prototypes)(RBinJavaObj * bin) {
949 	RList *the_list = r_bin_java_get_method_definitions (bin);
950 	RListIter *iter;
951 	char *str;
952 	r_list_foreach (the_list, iter, str) {
953 		eprintf ("%s;\n", str);
954 	}
955 	r_list_free (the_list);
956 }
957 
get_type_value_str(const char * arg_str,ut8 array_cnt)958 R_API char *get_type_value_str(const char *arg_str, ut8 array_cnt) {
959 	ut32 str_len = array_cnt ? (array_cnt + 1) * 2 + strlen (arg_str) : strlen (arg_str);
960 	char *str = malloc (str_len + 1);
961 	ut32 bytes_written = snprintf (str, str_len + 1, "%s", arg_str);
962 	while (array_cnt > 0) {
963 		strcpy (str + bytes_written, "[]");
964 		bytes_written += 2;
965 		array_cnt--;
966 	}
967 	return str;
968 }
969 
extract_type_value(const char * arg_str,char ** output)970 R_API int extract_type_value(const char *arg_str, char **output) {
971 	ut8 found_one = 0, array_cnt = 0;
972 	ut32 len = 0, consumed = 0;
973 	char *str = NULL;
974 	if (!arg_str || !output) {
975 		return 0;
976 	}
977 	if (output && *output && *output != NULL) {
978 		R_FREE (*output);
979 	}
980 	while (arg_str && *arg_str && !found_one) {
981 		len = 1;
982 		// handle the end of an object
983 		switch (*arg_str) {
984 		case 'V':
985 			str = get_type_value_str ("void", array_cnt);
986 			break;
987 		case 'J':
988 			str = get_type_value_str ("long", array_cnt);
989 			array_cnt = 0;
990 			break;
991 		case 'I':
992 			str = get_type_value_str ("int", array_cnt);
993 			array_cnt = 0;
994 			break;
995 		case 'D':
996 			str = get_type_value_str ("double", array_cnt);
997 			array_cnt = 0;
998 			break;
999 		case 'F':
1000 			str = get_type_value_str ("float", array_cnt);
1001 			array_cnt = 0;
1002 			break;
1003 		case 'B':
1004 			str = get_type_value_str ("byte", array_cnt);
1005 			array_cnt = 0;
1006 			break;
1007 		case 'C':
1008 			str = get_type_value_str ("char", array_cnt);
1009 			array_cnt = 0;
1010 			break;
1011 		case 'Z':
1012 			str = get_type_value_str ("boolean", array_cnt);
1013 			array_cnt = 0;
1014 			break;
1015 		case 'S':
1016 			str = get_type_value_str ("short", array_cnt);
1017 			array_cnt = 0;
1018 			break;
1019 		case '[':
1020 			array_cnt++;
1021 			break;
1022 		case 'L':
1023 			len = r_bin_java_extract_reference_name (arg_str, &str, array_cnt);
1024 			array_cnt = 0;
1025 			break;
1026 		case '(':
1027 			str = strdup ("(");
1028 			break;
1029 		case ')':
1030 			str = strdup (")");
1031 			break;
1032 		default:
1033 			return 0;
1034 		}
1035 		if (len < 1) {
1036 			break;
1037 		}
1038 		consumed += len;
1039 		arg_str += len;
1040 		if (str) {
1041 			*output = str;
1042 			break;
1043 		}
1044 	}
1045 	return consumed;
1046 }
1047 
r_bin_java_extract_type_values(const char * arg_str)1048 R_API RList *r_bin_java_extract_type_values(const char *arg_str) {
1049 	RList *list_args = r_list_new ();
1050 	if (!list_args) {
1051 		return NULL;
1052 	}
1053 	char *str = NULL;
1054 	const char *str_cur_pos = NULL;
1055 	ut32 len = 0;
1056 	if (!arg_str) {
1057 		return list_args;
1058 	}
1059 	str_cur_pos = arg_str;
1060 	list_args->free = free;
1061 	while (str_cur_pos && *str_cur_pos) {
1062 		// handle the end of an object
1063 		len = extract_type_value (str_cur_pos, &str);
1064 		if (len < 1) {
1065 			r_list_free (list_args);
1066 			return NULL;
1067 		}
1068 		str_cur_pos += len;
1069 		r_list_append (list_args, str);
1070 		str = NULL;
1071 	}
1072 	return list_args;
1073 }
1074 
r_bin_java_is_fm_type_private(RBinJavaField * fm_type)1075 R_API int r_bin_java_is_fm_type_private(RBinJavaField *fm_type) {
1076 	if (fm_type && fm_type->type == R_BIN_JAVA_FIELD_TYPE_METHOD) {
1077 		return fm_type->flags & R_BIN_JAVA_METHOD_ACC_PRIVATE;
1078 	}
1079 	if (fm_type && fm_type->type == R_BIN_JAVA_FIELD_TYPE_FIELD) {
1080 		return fm_type->flags & R_BIN_JAVA_FIELD_ACC_PRIVATE;
1081 	}
1082 	return 0;
1083 }
1084 
r_bin_java_is_fm_type_protected(RBinJavaField * fm_type)1085 R_API int r_bin_java_is_fm_type_protected(RBinJavaField *fm_type) {
1086 	if (fm_type && fm_type->type == R_BIN_JAVA_FIELD_TYPE_METHOD) {
1087 		return fm_type->flags & R_BIN_JAVA_METHOD_ACC_PROTECTED;
1088 	}
1089 	if (fm_type && fm_type->type == R_BIN_JAVA_FIELD_TYPE_FIELD) {
1090 		return fm_type->flags & R_BIN_JAVA_FIELD_ACC_PROTECTED;
1091 	}
1092 	return 0;
1093 }
1094 
r_bin_java_get_args(RBinJavaField * fm_type)1095 R_API RList *r_bin_java_get_args(RBinJavaField *fm_type) {
1096 	RList *the_list = r_bin_java_extract_type_values (fm_type->descriptor);
1097 	RList *arg_list = r_list_new ();
1098 	ut8 in_args = 0;
1099 	RListIter *desc_iter;
1100 	char *str;
1101 	r_list_foreach (the_list, desc_iter, str) {
1102 		if (str && *str == '(') {
1103 			in_args = 1;
1104 			continue;
1105 		}
1106 		if (str && *str == ')') {
1107 			break;
1108 		}
1109 		if (in_args && str) {
1110 			r_list_append (arg_list, strdup (str));
1111 		}
1112 	}
1113 	r_list_free (the_list);
1114 	return arg_list;
1115 }
1116 
r_bin_java_get_ret(RBinJavaField * fm_type)1117 R_API RList *r_bin_java_get_ret(RBinJavaField *fm_type) {
1118 	RList *the_list = r_bin_java_extract_type_values (fm_type->descriptor);
1119 	RList *ret_list = r_list_new ();
1120 	ut8 in_ret = 0;
1121 	RListIter *desc_iter;
1122 	char *str;
1123 	r_list_foreach (the_list, desc_iter, str) {
1124 		if (str && *str != ')') {
1125 			in_ret = 0;
1126 		}
1127 		if (in_ret) {
1128 			r_list_append (ret_list, strdup (str));
1129 		}
1130 	}
1131 	r_list_free (the_list);
1132 	return ret_list;
1133 }
1134 
r_bin_java_get_this_class_name(RBinJavaObj * bin)1135 R_API char *r_bin_java_get_this_class_name(RBinJavaObj *bin) {
1136 	return (bin->cf2.this_class_name ? strdup (bin->cf2.this_class_name) : strdup ("unknown"));
1137 }
1138 
calculate_access_value(const char * access_flags_str,RBinJavaAccessFlags * access_flags)1139 R_API ut16 calculate_access_value(const char *access_flags_str, RBinJavaAccessFlags *access_flags) {
1140 	ut16 result = 0;
1141 	ut16 size = strlen (access_flags_str) + 1;
1142 	char *p_flags, *my_flags = malloc (size);
1143 	RBinJavaAccessFlags *iter = NULL;
1144 	if (size < 5 || !my_flags) {
1145 		free (my_flags);
1146 		return result;
1147 	}
1148 	memcpy (my_flags, access_flags_str, size);
1149 	p_flags = strtok (my_flags, " ");
1150 	while (p_flags && access_flags) {
1151 		int idx = 0;
1152 		do {
1153 			iter = &access_flags[idx];
1154 			if (!iter || !iter->str) {
1155 				continue;
1156 			}
1157 			if (iter->len > 0 && iter->len != 16) {
1158 				if (!strncmp (iter->str, p_flags, iter->len)) {
1159 					result |= iter->value;
1160 				}
1161 			}
1162 			idx++;
1163 		} while (access_flags[idx].str != NULL);
1164 		p_flags = strtok (NULL, " ");
1165 	}
1166 	free (my_flags);
1167 	return result;
1168 }
1169 
retrieve_all_access_string_and_value(RBinJavaAccessFlags * access_flags)1170 R_API RList *retrieve_all_access_string_and_value(RBinJavaAccessFlags *access_flags) {
1171 	const char *fmt = "%s = 0x%04x";
1172 	RList *result = r_list_new ();
1173 	if (!result) {
1174 		return NULL;
1175 	}
1176 	result->free = free;
1177 	int i = 0;
1178 	for (i = 0; access_flags[i].str != NULL; i++) {
1179 		char *str = malloc (50);
1180 		if (!str) {
1181 			r_list_free (result);
1182 			return NULL;
1183 		}
1184 		snprintf (str, 49, fmt, access_flags[i].str, access_flags[i].value);
1185 		r_list_append (result, str);
1186 	}
1187 	return result;
1188 }
1189 
retrieve_access_string(ut16 flags,RBinJavaAccessFlags * access_flags)1190 R_API char *retrieve_access_string(ut16 flags, RBinJavaAccessFlags *access_flags) {
1191 	char *outbuffer = NULL, *cur_pos = NULL;
1192 	ut16 i;
1193 	ut16 max_str_len = 0;
1194 	for (i = 0; access_flags[i].str != NULL; i++) {
1195 		if (flags & access_flags[i].value) {
1196 			max_str_len += (strlen (access_flags[i].str) + 1);
1197 			if (max_str_len < strlen (access_flags[i].str)) {
1198 				return NULL;
1199 			}
1200 		}
1201 	}
1202 	max_str_len++;
1203 	outbuffer = (char *) malloc (max_str_len);
1204 	if (outbuffer) {
1205 		memset (outbuffer, 0, max_str_len);
1206 		cur_pos = outbuffer;
1207 		for (i = 0; access_flags[i].str != NULL; i++) {
1208 			if (flags & access_flags[i].value) {
1209 				ut8 len = strlen (access_flags[i].str);
1210 				const char *the_string = access_flags[i].str;
1211 				memcpy (cur_pos, the_string, len);
1212 				memcpy (cur_pos + len, " ", 1);
1213 				cur_pos += len + 1;
1214 			}
1215 		}
1216 		if (cur_pos != outbuffer) {
1217 			*(cur_pos - 1) = 0;
1218 		}
1219 	}
1220 	return outbuffer;
1221 }
1222 
retrieve_method_access_string(ut16 flags)1223 R_API char *retrieve_method_access_string(ut16 flags) {
1224 	return retrieve_access_string (flags, METHOD_ACCESS_FLAGS);
1225 }
1226 
retrieve_field_access_string(ut16 flags)1227 R_API char *retrieve_field_access_string(ut16 flags) {
1228 	return retrieve_access_string (flags, FIELD_ACCESS_FLAGS);
1229 }
1230 
retrieve_class_method_access_string(ut16 flags)1231 R_API char *retrieve_class_method_access_string(ut16 flags) {
1232 	return retrieve_access_string (flags, CLASS_ACCESS_FLAGS);
1233 }
1234 
r_bin_java_build_obj_key(RBinJavaObj * bin)1235 R_API char *r_bin_java_build_obj_key(RBinJavaObj *bin) {
1236 	char *jvcname = NULL;
1237 	char *cname = r_bin_java_get_this_class_name (bin);
1238 	ut32 class_name_len = cname ? strlen (cname) : strlen ("_unknown_");
1239 	jvcname = malloc (class_name_len + 8 + 30);
1240 	if (cname) {
1241 		snprintf (jvcname, class_name_len + 30, "%d.%s.class", bin->id, cname);
1242 		free (cname);
1243 	} else {
1244 		snprintf (jvcname, class_name_len + 30, "%d._unknown_.class", bin->id);
1245 	}
1246 	return jvcname;
1247 }
1248 
sdb_iterate_build_list(void * user,const char * k,const char * v)1249 R_API bool sdb_iterate_build_list(void *user, const char *k, const char *v) {
1250 	RList *bin_objs_list = (RList *) user;
1251 	size_t value = (size_t) sdb_atoi (v);
1252 	RBinJavaObj *bin_obj = NULL;
1253 	IFDBG eprintf("Found %s == %"PFMT64x " bin_objs db\n", k, (ut64) value);
1254 	if (value != 0 && value != (size_t) -1) {
1255 		bin_obj = (RBinJavaObj *) value;
1256 		r_list_append (bin_objs_list, bin_obj);
1257 	}
1258 	return true;
1259 }
1260 
r_bin_java_get_java_null_cp(void)1261 R_API RBinJavaCPTypeObj *r_bin_java_get_java_null_cp(void) {
1262 	if (R_BIN_JAVA_NULL_TYPE_INITTED) {
1263 		return &R_BIN_JAVA_NULL_TYPE;
1264 	}
1265 	memset (&R_BIN_JAVA_NULL_TYPE, 0, sizeof (R_BIN_JAVA_NULL_TYPE));
1266 	R_BIN_JAVA_NULL_TYPE.metas = R_NEW0 (RBinJavaMetaInfo);
1267 	if (!R_BIN_JAVA_NULL_TYPE.metas) {
1268 		return NULL;
1269 	}
1270 	memset (R_BIN_JAVA_NULL_TYPE.metas, 0, sizeof (RBinJavaMetaInfo));
1271 	R_BIN_JAVA_NULL_TYPE.metas->type_info = &R_BIN_JAVA_CP_METAS[0];
1272 	R_BIN_JAVA_NULL_TYPE.metas->ord = 0;
1273 	R_BIN_JAVA_NULL_TYPE.file_offset = 0;
1274 	R_BIN_JAVA_NULL_TYPE_INITTED = true;
1275 	return &R_BIN_JAVA_NULL_TYPE;
1276 }
1277 
r_bin_java_get_ev_meta_from_tag(ut8 tag)1278 R_API RBinJavaElementValueMetas *r_bin_java_get_ev_meta_from_tag(ut8 tag) {
1279 	ut16 i = 0;
1280 	RBinJavaElementValueMetas *res = &R_BIN_JAVA_ELEMENT_VALUE_METAS[13];
1281 	for (i = 0; i < R_BIN_JAVA_ELEMENT_VALUE_METAS_SZ; i++) {
1282 		if (tag == R_BIN_JAVA_ELEMENT_VALUE_METAS[i].tag) {
1283 			res = &R_BIN_JAVA_ELEMENT_VALUE_METAS[i];
1284 			break;
1285 		}
1286 	}
1287 	return res;
1288 }
1289 
r_bin_java_quick_check(ut8 expected_tag,ut8 actual_tag,ut32 actual_len,const char * name)1290 R_API ut8 r_bin_java_quick_check(ut8 expected_tag, ut8 actual_tag, ut32 actual_len, const char *name) {
1291 	ut8 res = 0;
1292 	if (expected_tag > R_BIN_JAVA_CP_METAS_SZ) {
1293 		eprintf ("Invalid tag '%d' expected 0x%02x for %s.\n", actual_tag, expected_tag, name);
1294 		res = 1;
1295 	} else if (expected_tag != actual_tag)  {
1296 		eprintf ("Invalid tag '%d' expected 0x%02x for %s.\n", actual_tag, expected_tag, name);
1297 		res = 1;
1298 	} else if (actual_len < R_BIN_JAVA_CP_METAS[expected_tag].len)  {
1299 		eprintf ("Unable to parse '%d' expected sz=0x%02x got 0x%02x for %s.\n",
1300 			actual_tag, R_BIN_JAVA_CP_METAS[expected_tag].len, actual_len, name);
1301 		res = 2;
1302 	}
1303 	return res;
1304 }
1305 
r_bin_java_raw_to_long(const ut8 * raw,ut64 offset)1306 R_API ut64 r_bin_java_raw_to_long(const ut8 *raw, ut64 offset) {
1307 	return R_BIN_JAVA_LONG (raw, offset);
1308 }
1309 // yanked from careercup, because i am lazy:
1310 // 1) dont want to figure out how make radare use math library
1311 // 2) dont feel like figuring it out when google does it in O(1).
my_pow(ut64 base,int exp)1312 R_API double my_pow(ut64 base, int exp) {
1313 	ut8 flag = 0;
1314 	ut64 res = 1;
1315 	if (exp < 0) {
1316 		flag = 1;
1317 		exp *= -1;
1318 	}
1319 	while (exp) {
1320 		if (exp & 1) {
1321 			res *= base;
1322 		}
1323 		exp >>= 1;
1324 		base *= base;
1325 		IFDBG eprintf("Result: %"PFMT64d ", base: %"PFMT64d ", exp: %d\n", res, base, exp);
1326 	}
1327 	if (flag == 0) {
1328 		return 1.0 * res;
1329 	}
1330 	return (1.0 / res);
1331 }
1332 
r_bin_java_raw_to_double(const ut8 * raw,ut64 offset)1333 R_API double r_bin_java_raw_to_double(const ut8 *raw, ut64 offset) {
1334 	ut64 bits = R_BIN_JAVA_LONG (raw, offset);
1335 	int s = ((bits >> 63) == 0) ? 1 : -1;
1336 	int e = (int) ((bits >> 52) & 0x7ffL);
1337 	long m = (e == 0) ?
1338 	(bits & 0xfffffffffffffLL) << 1 :
1339 	(bits & 0xfffffffffffffLL) | 0x10000000000000LL;
1340 	double res = 0.0;
1341 	IFDBG eprintf("Convert Long to Double: %08"PFMT64x "\n", bits);
1342 	if (bits == 0x7ff0000000000000LL) {
1343 		return INFINITY;
1344 	}
1345 	if (bits == 0xfff0000000000000LL) {
1346 		return -INFINITY;
1347 	}
1348 	if (0x7ff0000000000001LL <= bits && bits <= 0x7fffffffffffffffLL) {
1349 		return NAN;
1350 	}
1351 	if (0xfff0000000000001LL <= bits && bits <= 0xffffffffffffffffLL) {
1352 		return NAN;
1353 	}
1354 	res = s * m * my_pow (2, e - 1075);// XXXX TODO Get double to work correctly here
1355 	IFDBG eprintf("	High-bytes = %02x %02x %02x %02x\n", raw[0], raw[1], raw[2], raw[3]);
1356 	IFDBG eprintf("	Low-bytes = %02x %02x %02x %02x\n", raw[4], raw[5], raw[6], raw[7]);
1357 	IFDBG eprintf("Convert Long to Double s: %d, m: 0x%08lx, e: 0x%08x, res: %f\n", s, m, e, res);
1358 	return res;
1359 }
1360 
r_bin_java_read_next_method(RBinJavaObj * bin,const ut64 offset,const ut8 * buf,const ut64 len)1361 R_API RBinJavaField *r_bin_java_read_next_method(RBinJavaObj *bin, const ut64 offset, const ut8 *buf, const ut64 len) {
1362 	ut32 i, idx;
1363 	const ut8 *f_buf = buf + offset;
1364 	ut64 adv = 0;
1365 	RBinJavaCPTypeObj *item = NULL;
1366 	if (!bin || offset + 8 >= len) {
1367 		return NULL;
1368 	}
1369 	RBinJavaField *method = (RBinJavaField *) R_NEW0 (RBinJavaField);
1370 	if (!method) {
1371 		eprintf ("Unable to allocate memory for method information\n");
1372 		return NULL;
1373 	}
1374 	method->metas = (RBinJavaMetaInfo *) R_NEW0 (RBinJavaMetaInfo);
1375 	if (!method->metas) {
1376 		eprintf ("Unable to allocate memory for meta information\n");
1377 		free (method);
1378 		return NULL;
1379 	}
1380 	method->file_offset = offset;
1381 	method->flags = R_BIN_JAVA_USHORT (f_buf, 0);
1382 	method->flags_str = retrieve_method_access_string (method->flags);
1383 	// need to subtract 1 for the idx
1384 	method->name_idx = R_BIN_JAVA_USHORT (f_buf, 2);
1385 	method->descriptor_idx = R_BIN_JAVA_USHORT (f_buf, 4);
1386 	method->attr_count = R_BIN_JAVA_USHORT (f_buf, 6);
1387 	method->attributes = r_list_newf (r_bin_java_attribute_free);
1388 	method->type = R_BIN_JAVA_FIELD_TYPE_METHOD;
1389 	method->metas->ord = bin->method_idx;
1390 	adv += 8;
1391 	idx = method->name_idx;
1392 	item = r_bin_java_get_item_from_bin_cp_list (bin, idx);
1393 	method->name = r_bin_java_get_utf8_from_bin_cp_list (bin, (ut32) (method->name_idx));
1394 	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);
1395 	if (!method->name) {
1396 		method->name = (char *) malloc (21);
1397 		snprintf ((char *) method->name, 20, "sym.method_%08x", method->metas->ord);
1398 		IFDBG eprintf("r_bin_java_read_next_method: Unable to find the name for 0x%02x index.\n", method->name_idx);
1399 	}
1400 	idx = method->descriptor_idx;
1401 	item = r_bin_java_get_item_from_bin_cp_list (bin, idx);
1402 	method->descriptor = r_bin_java_get_utf8_from_bin_cp_list (bin, (ut32) method->descriptor_idx);
1403 	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);
1404 	if (!method->descriptor) {
1405 		method->descriptor = r_str_dup (NULL, "NULL");
1406 		IFDBG eprintf("r_bin_java_read_next_method: Unable to find the descriptor for 0x%02x index.\n", method->descriptor_idx);
1407 	}
1408 	IFDBG eprintf("Looking for a NameAndType CP with name_idx: %d descriptor_idx: %d\n", method->name_idx, method->descriptor_idx);
1409 	method->field_ref_cp_obj = r_bin_java_find_cp_ref_info_from_name_and_type (bin, method->name_idx, method->descriptor_idx);
1410 	if (method->field_ref_cp_obj) {
1411 		IFDBG eprintf("Found the obj.\n");
1412 		item = r_bin_java_get_item_from_bin_cp_list (bin, method->field_ref_cp_obj->info.cp_method.class_idx);
1413 		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);
1414 		method->class_name = r_bin_java_get_item_name_from_bin_cp_list (bin, item);
1415 		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);
1416 		IFDBG eprintf("MethodRef class name resolves to: %s\n", method->class_name);
1417 		if (!method->class_name) {
1418 			method->class_name = r_str_dup (NULL, "NULL");
1419 		}
1420 	} else {
1421 		// XXX - default to this class?
1422 		method->field_ref_cp_obj = r_bin_java_get_item_from_bin_cp_list (bin, bin->cf2.this_class);
1423 		method->class_name = r_bin_java_get_item_name_from_bin_cp_list (bin, method->field_ref_cp_obj);
1424 	}
1425 	IFDBG eprintf("Parsing %s(%s)\n", method->name, method->descriptor);
1426 	if (method->attr_count > 0) {
1427 		method->attr_offset = adv + offset;
1428 		RBinJavaAttrInfo *attr = NULL;
1429 		for (i = 0; i < method->attr_count; i++) {
1430 			attr = r_bin_java_read_next_attr (bin, adv + offset, buf, len);
1431 			if (!attr) {
1432 				eprintf ("[X] r_bin_java: Error unable to parse remainder of classfile after Method Attribute: %d.\n", i);
1433 				break;
1434 			}
1435 			if ((r_bin_java_get_attr_type_by_name (attr->name))->type == R_BIN_JAVA_ATTR_TYPE_CODE_ATTR) {
1436 				// This is necessary for determing the appropriate number of bytes when readin
1437 				// uoffset, ustack, ulocalvar values
1438 				bin->cur_method_code_length = attr->info.code_attr.code_length;
1439 				bin->offset_sz = 2;// (attr->info.code_attr.code_length > 65535) ? 4 : 2;
1440 				bin->ustack_sz = 2;// (attr->info.code_attr.max_stack > 65535) ? 4 : 2;
1441 				bin->ulocalvar_sz = 2;// (attr->info.code_attr.max_locals > 65535) ? 4 : 2;
1442 			}
1443 			IFDBG eprintf("Parsing @ 0x%"PFMT64x " (%s) = 0x%"PFMT64x " bytes\n", attr->file_offset, attr->name, attr->size);
1444 			r_list_append (method->attributes, attr);
1445 			adv += attr->size;
1446 			if (adv + offset >= len) {
1447 				eprintf ("[X] r_bin_java: Error unable to parse remainder of classfile after Method Attribute: %d.\n", i);
1448 				break;
1449 			}
1450 		}
1451 	}
1452 	method->size = adv;
1453 	// reset after parsing the method attributes
1454 	IFDBG eprintf("Parsing @ 0x%"PFMT64x " %s(%s) = 0x%"PFMT64x " bytes\n", method->file_offset, method->name, method->descriptor, method->size);
1455 	return method;
1456 }
1457 
r_bin_java_read_next_field(RBinJavaObj * bin,const ut64 offset,const ut8 * buffer,const ut64 len)1458 R_API RBinJavaField *r_bin_java_read_next_field(RBinJavaObj *bin, const ut64 offset, const ut8 *buffer, const ut64 len) {
1459 	RBinJavaAttrInfo *attr;
1460 	ut32 i, idx;
1461 	ut8 buf[8];
1462 	RBinJavaCPTypeObj *item = NULL;
1463 	const ut8 *f_buf = buffer + offset;
1464 	ut64 adv = 0;
1465 	if (!bin || offset + 8 >= len) {
1466 		return NULL;
1467 	}
1468 	RBinJavaField *field = (RBinJavaField *) R_NEW0 (RBinJavaField);
1469 	if (!field) {
1470 		eprintf ("Unable to allocate memory for field information\n");
1471 		return NULL;
1472 	}
1473 	field->metas = (RBinJavaMetaInfo *) R_NEW0 (RBinJavaMetaInfo);
1474 	if (!field->metas) {
1475 		eprintf ("Unable to allocate memory for meta information\n");
1476 		free (field);
1477 		return NULL;
1478 	}
1479 	memcpy (buf, f_buf, 8);
1480 	field->file_offset = offset;
1481 	field->flags = R_BIN_JAVA_USHORT (buf, 0);
1482 	field->flags_str = retrieve_field_access_string (field->flags);
1483 	field->name_idx = R_BIN_JAVA_USHORT (buf, 2);
1484 	field->descriptor_idx = R_BIN_JAVA_USHORT (buf, 4);
1485 	field->attr_count = R_BIN_JAVA_USHORT (buf, 6);
1486 	field->attributes = r_list_newf (r_bin_java_attribute_free);
1487 	field->type = R_BIN_JAVA_FIELD_TYPE_FIELD;
1488 	adv += 8;
1489 	field->metas->ord = bin->field_idx;
1490 
1491 	idx = field->name_idx;
1492 	item = r_bin_java_get_item_from_bin_cp_list (bin, idx);
1493 	field->name = r_bin_java_get_utf8_from_bin_cp_list (bin, (ut32) (field->name_idx));
1494 	IFDBG eprintf("Field name_idx: %d, which is: ord: %d, name: %s, value: %s\n", idx, item->metas->ord, ((RBinJavaCPTypeMetas *)item->metas->type_info)->name, field->name);
1495 	if (!field->name) {
1496 		field->name = (char *) malloc (21);
1497 		snprintf ((char *) field->name, 20, "sym.field_%08x", field->metas->ord);
1498 		IFDBG eprintf("r_bin_java_read_next_field: Unable to find the name for 0x%02x index.\n", field->name_idx);
1499 	}
1500 	idx = field->descriptor_idx;
1501 	item = r_bin_java_get_item_from_bin_cp_list (bin, idx);
1502 	field->descriptor = r_bin_java_get_utf8_from_bin_cp_list (bin, (ut32) field->descriptor_idx);
1503 	IFDBG eprintf("Field descriptor_idx: %d, which is: ord: %d, name: %s, value: %s\n", idx, item->metas->ord, ((RBinJavaCPTypeMetas *)item->metas->type_info)->name, field->descriptor);
1504 	if (!field->descriptor) {
1505 		field->descriptor = r_str_dup (NULL, "NULL");
1506 		IFDBG eprintf("r_bin_java_read_next_field: Unable to find the descriptor for 0x%02x index.\n", field->descriptor_idx);
1507 	}
1508 	IFDBG eprintf("Looking for a NameAndType CP with name_idx: %d descriptor_idx: %d\n", field->name_idx, field->descriptor_idx);
1509 	field->field_ref_cp_obj = r_bin_java_find_cp_ref_info_from_name_and_type (bin, field->name_idx, field->descriptor_idx);
1510 	if (field->field_ref_cp_obj) {
1511 		IFDBG eprintf("Found the obj.\n");
1512 		item = r_bin_java_get_item_from_bin_cp_list (bin, field->field_ref_cp_obj->info.cp_field.class_idx);
1513 		IFDBG eprintf("Field class reference value: %d, which is: ord: %d, name: %s\n", field->field_ref_cp_obj->info.cp_field.class_idx, item->metas->ord, ((RBinJavaCPTypeMetas *)item->metas->type_info)->name);
1514 		field->class_name = r_bin_java_get_item_name_from_bin_cp_list (bin, item);
1515 		IFDBG eprintf("Field requesting ref_cp_obj the following which is: ord: %d, name: %s\n", field->field_ref_cp_obj->metas->ord, ((RBinJavaCPTypeMetas *)field->field_ref_cp_obj->metas->type_info)->name);
1516 		IFDBG eprintf("FieldRef class name resolves to: %s\n", field->class_name);
1517 		if (!field->class_name) {
1518 			field->class_name = r_str_dup (NULL, "NULL");
1519 		}
1520 	} else {
1521 		// XXX - default to this class?
1522 		field->field_ref_cp_obj = r_bin_java_get_item_from_bin_cp_list (bin, bin->cf2.this_class);
1523 		field->class_name = r_bin_java_get_item_name_from_bin_cp_list (bin, field->field_ref_cp_obj);
1524 	}
1525 	IFDBG eprintf("Parsing %s(%s)", field->name, field->descriptor);
1526 	if (field->attr_count > 0) {
1527 		field->attr_offset = adv + offset;
1528 		for (i = 0; i < field->attr_count && offset + adv < len; i++) {
1529 			attr = r_bin_java_read_next_attr (bin, offset + adv, buffer, len);
1530 			if (!attr) {
1531 				eprintf ("[X] r_bin_java: Error unable to parse remainder of classfile after Field Attribute: %d.\n", i);
1532 				free (field->metas);
1533 				free (field);
1534 				return NULL;
1535 			}
1536 			if ((r_bin_java_get_attr_type_by_name (attr->name))->type == R_BIN_JAVA_ATTR_TYPE_CODE_ATTR) {
1537 				// This is necessary for determing the appropriate number of bytes when readin
1538 				// uoffset, ustack, ulocalvar values
1539 				bin->cur_method_code_length = attr->info.code_attr.code_length;
1540 				bin->offset_sz = 2;// (attr->info.code_attr.code_length > 65535) ? 4 : 2;
1541 				bin->ustack_sz = 2;// (attr->info.code_attr.max_stack > 65535) ? 4 : 2;
1542 				bin->ulocalvar_sz = 2;// (attr->info.code_attr.max_locals > 65535) ? 4 : 2;
1543 			}
1544 			r_list_append (field->attributes, attr);
1545 			adv += attr->size;
1546 			if (adv + offset >= len) {
1547 				eprintf ("[X] r_bin_java: Error unable to parse remainder of classfile after Field Attribute: %d.\n", i);
1548 				r_bin_java_fmtype_free (field);
1549 				return NULL;
1550 			}
1551 		}
1552 	}
1553 	field->size = adv;
1554 	return field;
1555 }
1556 
r_bin_java_clone_cp_idx(RBinJavaObj * bin,ut32 idx)1557 R_API RBinJavaCPTypeObj *r_bin_java_clone_cp_idx(RBinJavaObj *bin, ut32 idx) {
1558 	RBinJavaCPTypeObj *obj = NULL;
1559 	if (bin) {
1560 		obj = r_bin_java_get_item_from_bin_cp_list (bin, idx);
1561 	}
1562 	return r_bin_java_clone_cp_item (obj);
1563 }
1564 
r_bin_java_clone_cp_item(RBinJavaCPTypeObj * obj)1565 R_API RBinJavaCPTypeObj *r_bin_java_clone_cp_item(RBinJavaCPTypeObj *obj) {
1566 	RBinJavaCPTypeObj *clone_obj = NULL;
1567 	if (obj == NULL) {
1568 		return clone_obj;
1569 	}
1570 	clone_obj = R_NEW0 (RBinJavaCPTypeObj);
1571 	if (clone_obj) {
1572 		memcpy (clone_obj, obj, sizeof (RBinJavaCPTypeObj));
1573 		clone_obj->metas = (RBinJavaMetaInfo *) R_NEW0 (RBinJavaMetaInfo);
1574 		clone_obj->metas->type_info = (void *) &R_BIN_JAVA_CP_METAS[clone_obj->tag];
1575 		clone_obj->name = strdup (obj->name? obj->name: "unk");
1576 		if (obj->tag == R_BIN_JAVA_CP_UTF8) {
1577 			clone_obj->info.cp_utf8.bytes = (ut8 *) malloc (obj->info.cp_utf8.length + 1);
1578 			if (clone_obj->info.cp_utf8.bytes) {
1579 				memcpy (clone_obj->info.cp_utf8.bytes, obj->info.cp_utf8.bytes, clone_obj->info.cp_utf8.length);
1580 			} else {
1581 				// TODO: eprintf allocation error
1582 			}
1583 		}
1584 	}
1585 	return clone_obj;
1586 }
1587 
r_bin_java_read_next_constant_pool_item(RBinJavaObj * bin,const ut64 offset,const ut8 * buf,ut64 len)1588 R_API RBinJavaCPTypeObj *r_bin_java_read_next_constant_pool_item(RBinJavaObj *bin, const ut64 offset, const ut8 *buf, ut64 len) {
1589 	RBinJavaCPTypeMetas *java_constant_info = NULL;
1590 	ut8 tag = 0;
1591 	ut64 buf_sz = 0;
1592 	ut8 *cp_buf = NULL;
1593 	ut32 str_len = 0;
1594 	RBinJavaCPTypeObj *java_obj = NULL;
1595 	tag = buf[offset];
1596 	if (tag > R_BIN_JAVA_CP_METAS_SZ) {
1597 		eprintf ("Invalid tag '%d' at offset 0x%08"PFMT64x "\n", tag, (ut64) offset);
1598 		return NULL;
1599 #if 0
1600 		java_obj = r_bin_java_unknown_cp_new (bin, &tag, 1);
1601 		if (java_obj != NULL && java_obj->metas != NULL) {
1602 			java_obj->file_offset = offset;
1603 			java_obj->loadaddr = bin->loadaddr;
1604 		}
1605 		return NULL; // early error to avoid future overflows
1606 		// return java_obj;
1607 #endif
1608 	}
1609 	java_constant_info = &R_BIN_JAVA_CP_METAS[tag];
1610 	if (java_constant_info->tag == 0 || java_constant_info->tag == 2) {
1611 		return java_obj;
1612 	}
1613 	buf_sz += java_constant_info->len;
1614 	if (java_constant_info->tag == 1) {
1615 		if (offset + 32 < len) {
1616 			str_len = R_BIN_JAVA_USHORT (buf, offset + 1);
1617 			buf_sz += str_len;
1618 		} else {
1619 			return NULL;
1620 		}
1621 	}
1622 	cp_buf = calloc (buf_sz, 1);
1623 	if (!cp_buf) {
1624 		return java_obj;
1625 	}
1626 	if (offset + buf_sz < len) {
1627 		memcpy (cp_buf, (ut8 *) buf + offset, buf_sz);
1628 		IFDBG eprintf("Parsed the tag '%d':%s and create object from offset 0x%08"PFMT64x ".\n", tag, R_BIN_JAVA_CP_METAS[tag].name, offset);
1629 		java_obj = (*java_constant_info->allocs->new_obj)(bin, cp_buf, buf_sz);
1630 		if (java_obj != NULL && java_obj->metas != NULL) {
1631 			java_obj->file_offset = offset;
1632 			// IFDBG eprintf ("java_obj->file_offset = 0x%08"PFMT64x".\n",java_obj->file_offset);
1633 		} else if (!java_obj) {
1634 			eprintf ("Unable to parse the tag '%d' and create valid object.\n", tag);
1635 		} else if (!java_obj->metas) {
1636 			eprintf ("Unable to parse the tag '%d' and create valid object.\n", tag);
1637 		} else {
1638 			eprintf ("Failed to set the java_obj->metas-file_offset for '%d' offset is(0x%08"PFMT64x ").\n", tag, offset);
1639 		}
1640 	}
1641 	free (cp_buf);
1642 	return java_obj;
1643 }
1644 
r_bin_java_read_next_interface_item(RBinJavaObj * bin,const ut64 offset,const ut8 * buf,const ut64 len)1645 R_API RBinJavaInterfaceInfo *r_bin_java_read_next_interface_item(RBinJavaObj *bin, const ut64 offset, const ut8 *buf, const ut64 len) {
1646 	ut8 idx[2] = {
1647 		0
1648 	};
1649 	RBinJavaInterfaceInfo *ifobj;
1650 	const ut8 *if_buf = buf + offset;
1651 	if (offset + 2 >= len) {
1652 		return NULL;
1653 	}
1654 	memcpy (&idx, if_buf, 2);
1655 	ifobj = r_bin_java_interface_new (bin, if_buf, len - offset);
1656 	if (ifobj) {
1657 		ifobj->file_offset = offset;
1658 	}
1659 	return ifobj;
1660 }
1661 // R_API void addrow (RBinJavaObj *bin, int addr, int line) {
1662 // int n = bin->lines.count++;
1663 //// XXX. possible memleak
1664 // bin->lines.addr = realloc (bin->lines.addr, sizeof (int)*n+1);
1665 // bin->lines.addr[n] = addr;
1666 // bin->lines.line = realloc (bin->lines.line, sizeof (int)*n+1);
1667 // bin->lines.line[n] = line;
1668 // }
1669 // R_API struct r_bin_java_cp_item_t* r_bin_java_get_item_from_cp_CP(RBinJavaObj *bin, int i) {
1670 // return (i<0||i>bin->cf.cp_count)? &cp_null_item: &bin->cp_items[i];
1671 // }
1672 
r_bin_java_get_utf8_from_bin_cp_list(RBinJavaObj * bin,ut64 idx)1673 R_API char *r_bin_java_get_utf8_from_bin_cp_list(RBinJavaObj *bin, ut64 idx) {
1674 	/*
1675 	Search through the Constant Pool list for the given CP Index.
1676 	If the idx not found by directly going to the list index,
1677 	the list will be walked and then the IDX will be checked.
1678 	rvalue: new char* for caller to free.
1679 	*/
1680 	if (bin == NULL) {
1681 		return NULL;
1682 	}
1683 	return r_bin_java_get_utf8_from_cp_item_list (bin->cp_list, idx);
1684 }
1685 
r_bin_java_get_utf8_len_from_bin_cp_list(RBinJavaObj * bin,ut64 idx)1686 R_API ut32 r_bin_java_get_utf8_len_from_bin_cp_list(RBinJavaObj *bin, ut64 idx) {
1687 	/*
1688 	Search through the Constant Pool list for the given CP Index.
1689 	If the idx not found by directly going to the list index,
1690 	the list will be walked and then the IDX will be checked.
1691 	rvalue: new char* for caller to free.
1692 	*/
1693 	if (bin == NULL) {
1694 		return 0;
1695 	}
1696 	return r_bin_java_get_utf8_len_from_cp_item_list (bin->cp_list, idx);
1697 }
1698 
r_bin_java_get_name_from_bin_cp_list(RBinJavaObj * bin,ut64 idx)1699 R_API char *r_bin_java_get_name_from_bin_cp_list(RBinJavaObj *bin, ut64 idx) {
1700 	/*
1701 	Search through the Constant Pool list for the given CP Index.
1702 	If the idx not found by directly going to the list index,
1703 	the list will be walked and then the IDX will be checked.
1704 	rvalue: new char* for caller to free.
1705 	*/
1706 	if (bin == NULL) {
1707 		return NULL;
1708 	}
1709 	return r_bin_java_get_name_from_cp_item_list (bin->cp_list, idx);
1710 }
1711 
r_bin_java_get_desc_from_bin_cp_list(RBinJavaObj * bin,ut64 idx)1712 R_API char *r_bin_java_get_desc_from_bin_cp_list(RBinJavaObj *bin, ut64 idx) {
1713 	/*
1714 	Search through the Constant Pool list for the given CP Index.
1715 	If the idx not found by directly going to the list index,
1716 	the list will be walked and then the IDX will be checked.
1717 	rvalue: new char* for caller to free.
1718 	*/
1719 	if (bin == NULL) {
1720 		return NULL;
1721 	}
1722 	return r_bin_java_get_desc_from_cp_item_list (bin->cp_list, idx);
1723 }
1724 
r_bin_java_get_item_from_bin_cp_list(RBinJavaObj * bin,ut64 idx)1725 R_API RBinJavaCPTypeObj *r_bin_java_get_item_from_bin_cp_list(RBinJavaObj *bin, ut64 idx) {
1726 	/*
1727 	Search through the Constant Pool list for the given CP Index.
1728 	If the idx not found by directly going to the list index,
1729 	the list will be walked and then the IDX will be checked.
1730 	rvalue: RBinJavaObj* (user does NOT free).
1731 	*/
1732 	if (bin == NULL) {
1733 		return NULL;
1734 	}
1735 	if (idx > bin->cp_count || idx == 0) {
1736 		return r_bin_java_get_java_null_cp ();
1737 	}
1738 	return r_bin_java_get_item_from_cp_item_list (bin->cp_list, idx);
1739 }
1740 
r_bin_java_get_item_name_from_bin_cp_list(RBinJavaObj * bin,RBinJavaCPTypeObj * obj)1741 R_API char *r_bin_java_get_item_name_from_bin_cp_list(RBinJavaObj *bin, RBinJavaCPTypeObj *obj) {
1742 	char *res = NULL;
1743 	/*
1744 	Given a constant poool object Class, FieldRef, MethodRef, or InterfaceMethodRef
1745 	return the actual descriptor string.
1746 	@param cp_list: RList of RBinJavaCPTypeObj *
1747 	@param obj object to look up the name for
1748 	@rvalue char* (user frees) or NULL
1749 	*/
1750 	if (bin && obj) {
1751 		res = r_bin_java_get_item_name_from_cp_item_list (
1752 			bin->cp_list, obj, MAX_CPITEMS);
1753 	}
1754 	return res;
1755 }
1756 
r_bin_java_get_item_desc_from_bin_cp_list(RBinJavaObj * bin,RBinJavaCPTypeObj * obj)1757 R_API char *r_bin_java_get_item_desc_from_bin_cp_list(RBinJavaObj *bin, RBinJavaCPTypeObj *obj) {
1758 	/*
1759 	Given a constant poool object Class, FieldRef, MethodRef, or InterfaceMethodRef
1760 	return the actual descriptor string.
1761 	@param cp_list: RList of RBinJavaCPTypeObj *
1762 	@param obj object to look up the name for
1763 	@rvalue char* (user frees) or NULL
1764 	*/
1765 	return bin? r_bin_java_get_item_desc_from_cp_item_list (bin->cp_list, obj, MAX_CPITEMS): NULL;
1766 }
1767 
r_bin_java_get_utf8_from_cp_item_list(RList * cp_list,ut64 idx)1768 R_API char *r_bin_java_get_utf8_from_cp_item_list(RList *cp_list, ut64 idx) {
1769 	/*
1770 	Search through the Constant Pool list for the given CP Index.
1771 	If the idx not found by directly going to the list index,
1772 	the list will be walked and then the IDX will be checked.
1773 	rvalue: new char* for caller to free.
1774 	*/
1775 	char *value = NULL;
1776 	RListIter *iter;
1777 	if (!cp_list) {
1778 		return NULL;
1779 	}
1780 	RBinJavaCPTypeObj *item = (RBinJavaCPTypeObj *) r_list_get_n (cp_list, idx);
1781 	if (item && item->tag == R_BIN_JAVA_CP_UTF8 && item->metas->ord == idx) {
1782 		value = convert_string ((const char *) item->info.cp_utf8.bytes, item->info.cp_utf8.length);
1783 	}
1784 	if (!value) {
1785 		r_list_foreach (cp_list, iter, item) {
1786 			if (item && (item->tag == R_BIN_JAVA_CP_UTF8) && item->metas->ord == idx) {
1787 				value = convert_string ((const char *) item->info.cp_utf8.bytes, item->info.cp_utf8.length);
1788 				break;
1789 			}
1790 		}
1791 	}
1792 	return value;
1793 }
1794 
r_bin_java_get_utf8_len_from_cp_item_list(RList * cp_list,ut64 idx)1795 R_API ut32 r_bin_java_get_utf8_len_from_cp_item_list(RList *cp_list, ut64 idx) {
1796 	/*
1797 	Search through the Constant Pool list for the given CP Index.
1798 	If the idx not found by directly going to the list index,
1799 	the list will be walked and then the IDX will be checked.
1800 	rvalue: new ut32 .
1801 	*/
1802 	ut32 value = -1;
1803 	RListIter *iter;
1804 	if (!cp_list) {
1805 		return 0;
1806 	}
1807 	RBinJavaCPTypeObj *item = (RBinJavaCPTypeObj *) r_list_get_n (cp_list, idx);
1808 	if (item && (item->tag == R_BIN_JAVA_CP_UTF8) && item->metas->ord == idx) {
1809 		value = item->info.cp_utf8.length;
1810 	}
1811 	if (value == -1) {
1812 		r_list_foreach (cp_list, iter, item) {
1813 			if (item && (item->tag == R_BIN_JAVA_CP_UTF8) && item->metas->ord == idx) {
1814 				value = item->info.cp_utf8.length;
1815 				break;
1816 			}
1817 		}
1818 	}
1819 	return value;
1820 }
1821 
r_bin_java_get_item_from_cp_item_list(RList * cp_list,ut64 idx)1822 R_API RBinJavaCPTypeObj *r_bin_java_get_item_from_cp_item_list(RList *cp_list, ut64 idx) {
1823 	/*
1824 	Search through the Constant Pool list for the given CP Index.
1825 	rvalue: RBinJavaObj *
1826 	*/
1827 	RBinJavaCPTypeObj *item = NULL;
1828 	if (cp_list == NULL) {
1829 		return NULL;
1830 	}
1831 	item = (RBinJavaCPTypeObj *) r_list_get_n (cp_list, idx);
1832 	return item;
1833 }
1834 
r_bin_java_get_item_name_from_cp_item_list(RList * cp_list,RBinJavaCPTypeObj * obj,int depth)1835 R_API char *r_bin_java_get_item_name_from_cp_item_list(RList *cp_list, RBinJavaCPTypeObj *obj, int depth) {
1836 	/*
1837 	Given a constant poool object Class, FieldRef, MethodRef, or InterfaceMethodRef
1838 	return the actual descriptor string.
1839 	@param cp_list: RList of RBinJavaCPTypeObj *
1840 	@param obj object to look up the name for
1841 	@rvalue ut8* (user frees) or NULL
1842 	*/
1843 	if (obj == NULL || cp_list == NULL || depth < 0) {
1844 		return NULL;
1845 	}
1846 	switch (obj->tag) {
1847 	case R_BIN_JAVA_CP_NAMEANDTYPE:
1848 		return r_bin_java_get_utf8_from_cp_item_list (
1849 			cp_list, obj->info.cp_name_and_type.name_idx);
1850 	case R_BIN_JAVA_CP_CLASS:
1851 		return r_bin_java_get_utf8_from_cp_item_list (
1852 			cp_list, obj->info.cp_class.name_idx);
1853 	// XXX - Probably not good form, but they are the same memory structure
1854 	case R_BIN_JAVA_CP_FIELDREF:
1855 	case R_BIN_JAVA_CP_INTERFACEMETHOD_REF:
1856 	case R_BIN_JAVA_CP_METHODREF:
1857 		obj = r_bin_java_get_item_from_cp_item_list (
1858 			cp_list, obj->info.cp_method.name_and_type_idx);
1859 		return r_bin_java_get_item_name_from_cp_item_list (
1860 			cp_list, obj, depth - 1);
1861 	default:
1862 		return NULL;
1863 	case 0:
1864 		IFDBG eprintf("Invalid 0 tag in the constant pool\n");
1865 		return NULL;
1866 	}
1867 	return NULL;
1868 }
1869 
r_bin_java_get_name_from_cp_item_list(RList * cp_list,ut64 idx)1870 R_API char *r_bin_java_get_name_from_cp_item_list(RList *cp_list, ut64 idx) {
1871 	/*
1872 	Given a constant poool object Class, FieldRef, MethodRef, or InterfaceMethodRef
1873 	return the actual descriptor string.
1874 	@param cp_list: RList of RBinJavaCPTypeObj *
1875 	@param obj object to look up the name for
1876 	@rvalue ut8* (user frees) or NULL
1877 	*/
1878 	RBinJavaCPTypeObj *obj = r_bin_java_get_item_from_cp_item_list (
1879 		cp_list, idx);
1880 	if (obj && cp_list) {
1881 		return r_bin_java_get_item_name_from_cp_item_list (
1882 			cp_list, obj, MAX_CPITEMS);
1883 	}
1884 	return NULL;
1885 }
1886 
r_bin_java_get_item_desc_from_cp_item_list(RList * cp_list,RBinJavaCPTypeObj * obj,int depth)1887 R_API char *r_bin_java_get_item_desc_from_cp_item_list(RList *cp_list, RBinJavaCPTypeObj *obj, int depth) {
1888 	/*
1889 	Given a constant poool object FieldRef, MethodRef, or InterfaceMethodRef
1890 	return the actual descriptor string.
1891 	@rvalue ut8* (user frees) or NULL
1892 	*/
1893 	if (!obj || !cp_list || depth < 0) {
1894 		return NULL;
1895 	}
1896 	switch (obj->tag) {
1897 	case R_BIN_JAVA_CP_NAMEANDTYPE:
1898 		return r_bin_java_get_utf8_from_cp_item_list (cp_list,
1899 			obj->info.cp_name_and_type.descriptor_idx);
1900 	// XXX - Probably not good form, but they are the same memory structure
1901 	case R_BIN_JAVA_CP_FIELDREF:
1902 	case R_BIN_JAVA_CP_INTERFACEMETHOD_REF:
1903 	case R_BIN_JAVA_CP_METHODREF:
1904 		obj = r_bin_java_get_item_from_cp_item_list (cp_list,
1905 			obj->info.cp_method.name_and_type_idx);
1906 		return r_bin_java_get_item_desc_from_cp_item_list (
1907 			cp_list, obj, depth - 1);
1908 	default:
1909 		return NULL;
1910 	}
1911 	return NULL;
1912 }
1913 
r_bin_java_get_desc_from_cp_item_list(RList * cp_list,ut64 idx)1914 R_API char *r_bin_java_get_desc_from_cp_item_list(RList *cp_list, ut64 idx) {
1915 	/*
1916 	Given a constant poool object FieldRef, MethodRef, or InterfaceMethodRef
1917 	return the actual descriptor string.
1918 	@rvalue ut8* (user frees) or NULL
1919 	*/
1920 	RBinJavaCPTypeObj *obj = r_bin_java_get_item_from_cp_item_list (cp_list, idx);
1921 	if (cp_list == NULL) {
1922 		return NULL;
1923 	}
1924 	return r_bin_java_get_item_desc_from_cp_item_list (cp_list, obj, MAX_CPITEMS);
1925 }
1926 
r_bin_java_get_method_code_attribute(const RBinJavaField * method)1927 R_API RBinJavaAttrInfo *r_bin_java_get_method_code_attribute(const RBinJavaField *method) {
1928 	/*
1929 	Search through a methods attributes and return the code attr.
1930 	rvalue: RBinJavaAttrInfo* if found otherwise NULL.
1931 	*/
1932 	RBinJavaAttrInfo *res = NULL, *attr = NULL;
1933 	RListIter *iter;
1934 	if (method) {
1935 		r_list_foreach (method->attributes, iter, attr) {
1936 			if (attr && (attr->type == R_BIN_JAVA_ATTR_TYPE_CODE_ATTR)) {
1937 				res = attr;
1938 				break;
1939 			}
1940 		}
1941 	}
1942 	return res;
1943 }
1944 
r_bin_java_get_attr_from_field(RBinJavaField * field,R_BIN_JAVA_ATTR_TYPE attr_type,ut32 pos)1945 R_API RBinJavaAttrInfo *r_bin_java_get_attr_from_field(RBinJavaField *field, R_BIN_JAVA_ATTR_TYPE attr_type, ut32 pos) {
1946 	/*
1947 	Search through the Attribute list for the given type starting at position pos.
1948 	rvalue: NULL or the first occurrence of attr_type after pos
1949 	*/
1950 	RBinJavaAttrInfo *attr = NULL, *item;
1951 	RListIter *iter;
1952 	ut32 i = 0;
1953 	if (field) {
1954 		r_list_foreach (field->attributes, iter, item) {
1955 			// Note the increment happens after the comparison
1956 			if ((i++) >= pos) {
1957 				if (item && (item->type == attr_type)) {
1958 					attr = item;
1959 					break;
1960 				}
1961 			}
1962 		}
1963 	}
1964 	return attr;
1965 }
1966 
r_bin_java_get_attr_buf(RBinJavaObj * bin,ut64 sz,const ut64 offset,const ut8 * buf,const ut64 len)1967 R_API ut8 *r_bin_java_get_attr_buf(RBinJavaObj *bin, ut64 sz, const ut64 offset, const ut8 *buf, const ut64 len) {
1968 	ut8 *attr_buf = NULL;
1969 	int pending = len - offset;
1970 	const ut8 *a_buf = offset + buf;
1971 	attr_buf = (ut8 *) calloc (pending + 1, 1);
1972 	if (attr_buf == NULL) {
1973 		eprintf ("Unable to allocate enough bytes (0x%04"PFMT64x
1974 			") to read in the attribute.\n", sz);
1975 		return attr_buf;
1976 	}
1977 	memcpy (attr_buf, a_buf, pending); // sz+1);
1978 	return attr_buf;
1979 }
1980 
r_bin_java_default_attr_new(RBinJavaObj * bin,ut8 * buffer,ut64 sz,ut64 buf_offset)1981 R_API RBinJavaAttrInfo *r_bin_java_default_attr_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz, ut64 buf_offset) {
1982 	// NOTE: this function receives the buffer offset in the original buffer,
1983 	// but the buffer is already point to that particular offset.
1984 	// XXX - all the code that relies on this function should probably be modified
1985 	// so that the original buffer pointer is passed in and then the buffer+buf_offset
1986 	// points to the correct location.
1987 	RBinJavaAttrInfo *attr = R_NEW0 (RBinJavaAttrInfo);
1988 	if (!attr) {
1989 		return NULL;
1990 	}
1991 	RBinJavaAttrMetas *type_info = NULL;
1992 	attr->metas = R_NEW0 (RBinJavaMetaInfo);
1993 	if (attr->metas == NULL) {
1994 		free (attr);
1995 		return NULL;
1996 	}
1997 	attr->is_attr_in_old_format = r_bin_java_is_old_format(bin);
1998 	attr->file_offset = buf_offset;
1999 	attr->name_idx = R_BIN_JAVA_USHORT (buffer, 0);
2000 	attr->length = R_BIN_JAVA_UINT (buffer, 2);
2001 	attr->size = R_BIN_JAVA_UINT (buffer, 2) + 6;
2002 	attr->name = r_bin_java_get_utf8_from_bin_cp_list (R_BIN_JAVA_GLOBAL_BIN, attr->name_idx);
2003 	if (attr->name == NULL) {
2004 		// Something bad has happened
2005 		attr->name = r_str_dup (NULL, "NULL");
2006 		eprintf ("r_bin_java_default_attr_new: Unable to find the name for %d index.\n", attr->name_idx);
2007 	}
2008 	type_info = r_bin_java_get_attr_type_by_name (attr->name);
2009 	attr->metas->ord = (R_BIN_JAVA_GLOBAL_BIN->attr_idx++);
2010 	attr->metas->type_info = (void *) type_info;
2011 	// IFDBG eprintf ("	Addrs for type_info [tag=%d]: 0x%08"PFMT64x"\n", type_val, &attr->metas->type_info);
2012 	return attr;
2013 }
2014 
r_bin_java_get_attr_type_by_name(const char * name)2015 R_API RBinJavaAttrMetas *r_bin_java_get_attr_type_by_name(const char *name) {
2016 	// TODO: use sdb/hashtable here
2017 	int i;
2018 	for (i = 0; i < RBIN_JAVA_ATTRS_METAS_SZ; i++) {
2019 		if (!strcmp ((const char *) name, RBIN_JAVA_ATTRS_METAS[i].name)) {
2020 			return &RBIN_JAVA_ATTRS_METAS[i];
2021 		}
2022 	}
2023 	return &RBIN_JAVA_ATTRS_METAS[R_BIN_JAVA_ATTR_TYPE_UNKNOWN_ATTR];
2024 }
2025 
r_bin_java_read_next_attr(RBinJavaObj * bin,const ut64 offset,const ut8 * buf,const ut64 buf_len)2026 R_API RBinJavaAttrInfo *r_bin_java_read_next_attr(RBinJavaObj *bin, const ut64 offset, const ut8 *buf, const ut64 buf_len) {
2027 	RBinJavaAttrInfo *attr = NULL;
2028 	ut32 sz = 0;
2029 	ut8 *buffer = NULL;
2030 	const ut8 *a_buf = offset + buf;
2031 	ut8 attr_idx_len = 6;
2032 	if (offset + 6 > buf_len) {
2033 		eprintf ("[X] r_bin_java: Error unable to parse remainder of classfile in Attribute offset "
2034 			"(0x%"PFMT64x ") > len  of remaining bytes (0x%"PFMT64x ").\n", offset, buf_len);
2035 		return NULL;
2036 	}
2037 	// ut16 attr_idx, ut32 length of attr.
2038 	sz = R_BIN_JAVA_UINT (a_buf, 2) + attr_idx_len; // r_bin_java_read_int (bin, buf_offset+2) + attr_idx_len;
2039 	if (sz + offset > buf_len) {
2040 		eprintf ("[X] r_bin_java: Error unable to parse remainder of classfile in Attribute len "
2041 			"(0x%x) + offset (0x%"PFMT64x ") exceeds length of buffer (0x%"PFMT64x ").\n",
2042 			sz, offset, buf_len);
2043 		return NULL;
2044 	}
2045 	// when reading the attr bytes, need to also
2046 	// include the initial 6 bytes, which
2047 	// are not included in the attribute length
2048 	// ,
2049 	// sz, buf_offset, buf_offset+sz);
2050 	buffer = r_bin_java_get_attr_buf (bin, sz, offset, buf, buf_len);
2051 	// printf ("%d %d %d\n", sz, buf_len, offset);
2052 	if (offset < buf_len) {
2053 		attr = r_bin_java_read_next_attr_from_buffer (bin, buffer, buf_len - offset, offset);
2054 		free (buffer);
2055 
2056 		if (!attr) {
2057 			return NULL;
2058 		}
2059 		attr->size = sz;
2060 	} else {
2061 		free (buffer);
2062 		eprintf ("IS OOB\n");
2063 	}
2064 	return attr;
2065 }
2066 
r_bin_java_read_next_attr_from_buffer(RBinJavaObj * bin,ut8 * buffer,st64 sz,st64 buf_offset)2067 R_API RBinJavaAttrInfo *r_bin_java_read_next_attr_from_buffer(RBinJavaObj *bin, ut8 *buffer, st64 sz, st64 buf_offset) {
2068 	RBinJavaAttrInfo *attr = NULL;
2069 	ut64 offset = 0;
2070 	ut16 name_idx;
2071 	st64 nsz;
2072 
2073 	if (!buffer || ((int) sz) < 4 || buf_offset < 0) {
2074 		eprintf ("r_bin_Java_read_next_attr_from_buffer: invalid buffer size %d\n", (int) sz);
2075 		return NULL;
2076 	}
2077 	name_idx = R_BIN_JAVA_USHORT (buffer, offset);
2078 	offset += 2;
2079 	nsz = R_BIN_JAVA_UINT (buffer, offset);
2080 	// DEAD INCREMENT offset += 4;
2081 
2082 	char *name = r_bin_java_get_utf8_from_bin_cp_list (R_BIN_JAVA_GLOBAL_BIN, name_idx);
2083 	if (!name) {
2084 		name = strdup ("unknown");
2085 	}
2086 	IFDBG eprintf("r_bin_java_read_next_attr: name_idx = %d is %s\n", name_idx, name);
2087 	RBinJavaAttrMetas *type_info = r_bin_java_get_attr_type_by_name (name);
2088 	if (type_info) {
2089 		IFDBG eprintf("Typeinfo: %s, was %s\n", type_info->name, name);
2090 		// printf ("SZ %d %d %d\n", nsz, sz, buf_offset);
2091 		if (nsz > sz) {
2092 			free (name);
2093 			return NULL;
2094 		}
2095 		if ((attr = type_info->allocs->new_obj (bin, buffer, nsz, buf_offset))) {
2096 			attr->metas->ord = (R_BIN_JAVA_GLOBAL_BIN->attr_idx++);
2097 		}
2098 	} else {
2099 		eprintf ("r_bin_java_read_next_attr_from_buffer: Cannot find type_info for %s\n", name);
2100 	}
2101 	free (name);
2102 	return attr;
2103 }
2104 
r_bin_java_read_class_file2(RBinJavaObj * bin,const ut64 offset,const ut8 * obuf,ut64 len)2105 R_API ut64 r_bin_java_read_class_file2(RBinJavaObj *bin, const ut64 offset, const ut8 *obuf, ut64 len) {
2106 	const ut8 *cf2_buf = obuf + offset;
2107 	RBinJavaCPTypeObj *this_class_cp_obj = NULL;
2108 	IFDBG eprintf("\n0x%"PFMT64x " Offset before reading the cf2 structure\n", offset);
2109 	/*
2110 	Reading the following fields:
2111 	ut16 access_flags;
2112 	ut16 this_class;
2113 	ut16 super_class;
2114 	*/
2115 	if (cf2_buf + 6 > obuf + len) {
2116 		return 0;
2117 	}
2118 	bin->cf2.cf2_size = 6;
2119 	bin->cf2.access_flags = R_BIN_JAVA_USHORT (cf2_buf, 0);
2120 	bin->cf2.this_class = R_BIN_JAVA_USHORT (cf2_buf, 2);
2121 	bin->cf2.super_class = R_BIN_JAVA_USHORT (cf2_buf, 4);
2122 	free (bin->cf2.flags_str);
2123 	free (bin->cf2.this_class_name);
2124 	bin->cf2.flags_str = retrieve_class_method_access_string (bin->cf2.access_flags);
2125 	this_class_cp_obj = r_bin_java_get_item_from_bin_cp_list (bin, bin->cf2.this_class);
2126 	bin->cf2.this_class_name = r_bin_java_get_item_name_from_bin_cp_list (bin, this_class_cp_obj);
2127 	IFDBG eprintf("This class flags are: %s\n", bin->cf2.flags_str);
2128 	return bin->cf2.cf2_size;
2129 }
2130 
r_bin_java_parse_cp_pool(RBinJavaObj * bin,const ut64 offset,const ut8 * buf,const ut64 len)2131 R_API ut64 r_bin_java_parse_cp_pool(RBinJavaObj *bin, const ut64 offset, const ut8 *buf, const ut64 len) {
2132 	int ord = 0;
2133 	ut64 adv = 0;
2134 	RBinJavaCPTypeObj *obj = NULL;
2135 	const ut8 *cp_buf = buf + offset;
2136 	r_list_free (bin->cp_list);
2137 	bin->cp_list = r_list_newf (r_bin_java_constant_pool);
2138 	bin->cp_offset = offset;
2139 	memcpy ((char *) &bin->cp_count, cp_buf, 2);
2140 	bin->cp_count = R_BIN_JAVA_USHORT (cp_buf, 0) - 1;
2141 	adv += 2;
2142 	IFDBG eprintf("ConstantPoolCount %d\n", bin->cp_count);
2143 	r_list_append (bin->cp_list, r_bin_java_get_java_null_cp ());
2144 	for (ord = 1, bin->cp_idx = 0; bin->cp_idx < bin->cp_count && adv < len; ord++, bin->cp_idx++) {
2145 		obj = r_bin_java_read_next_constant_pool_item (bin, offset + adv, buf, len);
2146 		if (obj) {
2147 			// IFDBG eprintf ("SUCCESS Read ConstantPoolItem %d\n", i);
2148 			obj->metas->ord = ord;
2149 			obj->idx = ord;
2150 			r_list_append (bin->cp_list, obj);
2151 			if (obj->tag == R_BIN_JAVA_CP_LONG || obj->tag == R_BIN_JAVA_CP_DOUBLE) {
2152 				// i++;
2153 				ord++;
2154 				bin->cp_idx++;
2155 				r_list_append (bin->cp_list, &R_BIN_JAVA_NULL_TYPE);
2156 			}
2157 
2158 			IFDBG ((RBinJavaCPTypeMetas *) obj->metas->type_info)->allocs->print_summary (obj);
2159 			adv += ((RBinJavaCPTypeMetas *) obj->metas->type_info)->allocs->calc_size (obj);
2160 			if (offset + adv > len) {
2161 				eprintf ("[X] r_bin_java: Error unable to parse remainder of classfile after Constant Pool Object: %d.\n", ord);
2162 				break;
2163 			}
2164 		} else {
2165 			IFDBG eprintf("Failed to read ConstantPoolItem %d\n", bin->cp_idx);
2166 			break;
2167 		}
2168 	}
2169 	// Update the imports
2170 	r_bin_java_set_imports (bin);
2171 	bin->cp_size = adv;
2172 	return bin->cp_size;
2173 }
2174 
r_bin_java_parse_interfaces(RBinJavaObj * bin,const ut64 offset,const ut8 * buf,const ut64 len)2175 R_API ut64 r_bin_java_parse_interfaces(RBinJavaObj *bin, const ut64 offset, const ut8 *buf, const ut64 len) {
2176 	int i = 0;
2177 	ut64 adv = 0;
2178 	RBinJavaInterfaceInfo *interfaces_obj;
2179 	const ut8 *if_buf = buf + offset;
2180 	bin->cp_offset = offset;
2181 	bin->interfaces_offset = offset;
2182 	r_list_free (bin->interfaces_list);
2183 	bin->interfaces_list = r_list_newf (r_bin_java_interface_free);
2184 	if (offset + 2 > len) {
2185 		bin->interfaces_size = 0;
2186 		return 0;
2187 	}
2188 	bin->interfaces_count = R_BIN_JAVA_USHORT (if_buf, 0);
2189 	adv += 2;
2190 	IFDBG eprintf("Interfaces count: %d\n", bin->interfaces_count);
2191 	if (bin->interfaces_count > 0) {
2192 		for (i = 0; i < bin->interfaces_count; i++) {
2193 			interfaces_obj = r_bin_java_read_next_interface_item (bin, offset + adv, buf, len);
2194 			if (interfaces_obj) {
2195 				r_list_append (bin->interfaces_list, interfaces_obj);
2196 				adv += interfaces_obj->size;
2197 				if (offset + adv > len) {
2198 					eprintf ("[X] r_bin_java: Error unable to parse remainder of classfile after Interface: %d.\n", i);
2199 					break;
2200 				}
2201 			} else {
2202 				break;
2203 			}
2204 		}
2205 	}
2206 	bin->interfaces_size = adv;
2207 	return adv;
2208 }
2209 
r_bin_java_parse_fields(RBinJavaObj * bin,const ut64 offset,const ut8 * buf,const ut64 len)2210 R_API ut64 r_bin_java_parse_fields(RBinJavaObj *bin, const ut64 offset, const ut8 *buf, const ut64 len) {
2211 	int i = 0;
2212 	ut64 adv = 0;
2213 	RBinJavaField *field;
2214 	const ut8 *fm_buf = buf + offset;
2215 	r_list_free (bin->fields_list);
2216 	bin->fields_list = r_list_newf (r_bin_java_fmtype_free);
2217 	bin->fields_offset = offset;
2218 	if (offset + 2 >= len) {
2219 		return UT64_MAX;
2220 	}
2221 	bin->fields_count = R_BIN_JAVA_USHORT (fm_buf, 0);
2222 	adv += 2;
2223 	IFDBG eprintf("Fields count: %d 0x%"PFMT64x "\n", bin->fields_count, bin->fields_offset);
2224 	if (bin->fields_count > 0) {
2225 		for (i = 0; i < bin->fields_count; i++, bin->field_idx++) {
2226 			field = r_bin_java_read_next_field (bin, offset + adv, buf, len);
2227 			if (field) {
2228 				adv += field->size;
2229 				r_list_append (bin->fields_list, field);
2230 				IFDBG r_bin_java_print_field_summary(field);
2231 				if (adv + offset > len) {
2232 					eprintf ("[X] r_bin_java: Error unable to parse remainder of classfile after Field: %d.\n", i);
2233 					break;
2234 				}
2235 			} else {
2236 				IFDBG eprintf("Failed to read Field %d\n", i);
2237 				break;
2238 			}
2239 		}
2240 	}
2241 	bin->fields_size = adv;
2242 	return adv;
2243 }
2244 
r_bin_java_parse_attrs(RBinJavaObj * bin,const ut64 offset,const ut8 * buf,const ut64 len)2245 R_API ut64 r_bin_java_parse_attrs(RBinJavaObj *bin, const ut64 offset, const ut8 *buf, const ut64 len) {
2246 	int i = 0;
2247 	ut64 adv = 0;
2248 	const ut8 *a_buf = buf + offset;
2249 	if (offset + 2 >= len) {
2250 		// Check if we can read that USHORT
2251 		return UT64_MAX;
2252 	}
2253 	r_list_free (bin->attrs_list);
2254 	bin->attrs_list = r_list_newf (r_bin_java_attribute_free);
2255 	bin->attrs_offset = offset;
2256 	bin->attrs_count = R_BIN_JAVA_USHORT (a_buf, adv);
2257 	adv += 2;
2258 	if (bin->attrs_count > 0) {
2259 		for (i = 0; i < bin->attrs_count; i++, bin->attr_idx++) {
2260 			RBinJavaAttrInfo *attr = r_bin_java_read_next_attr (bin, offset + adv, buf, len);
2261 			if (!attr) {
2262 				// eprintf ("[X] r_bin_java: Error unable to parse remainder of classfile after Attribute: %d.\n", i);
2263 				break;
2264 			}
2265 			r_list_append (bin->attrs_list, attr);
2266 			adv += attr->size;
2267 			if (adv + offset >= len) {
2268 				// eprintf ("[X] r_bin_java: Error unable to parse remainder of classfile after Attribute: %d.\n", i);
2269 				break;
2270 			}
2271 		}
2272 	}
2273 	bin->attrs_size = adv;
2274 	return adv;
2275 }
2276 
r_bin_java_parse_methods(RBinJavaObj * bin,const ut64 offset,const ut8 * buf,const ut64 len)2277 R_API ut64 r_bin_java_parse_methods(RBinJavaObj *bin, const ut64 offset, const ut8 *buf, const ut64 len) {
2278 	int i = 0;
2279 	ut64 adv = 0;
2280 	RBinJavaField *method;
2281 	const ut8 *fm_buf = buf + offset;
2282 	r_list_free (bin->methods_list);
2283 	bin->methods_list = r_list_newf (r_bin_java_fmtype_free);
2284 
2285 	if (offset + 2 >= len) {
2286 		return 0LL;
2287 	}
2288 	bin->methods_offset = offset;
2289 	bin->methods_count = R_BIN_JAVA_USHORT (fm_buf, 0);
2290 	adv += 2;
2291 	IFDBG eprintf("Methods count: %d 0x%"PFMT64x "\n", bin->methods_count, bin->methods_offset);
2292 	bin->main = NULL;
2293 	bin->entrypoint = NULL;
2294 	bin->main_code_attr = NULL;
2295 	bin->entrypoint_code_attr = NULL;
2296 	for (i = 0; i < bin->methods_count; i++, bin->method_idx++) {
2297 		method = r_bin_java_read_next_method (bin, offset + adv, buf, len);
2298 		if (method) {
2299 			adv += method->size;
2300 			r_list_append (bin->methods_list, method);
2301 		}
2302 		// Update Main, Init, or Class Init
2303 		if (method && !strcmp ((const char *) method->name, "main")) {
2304 			bin->main = method;
2305 			// get main code attr
2306 			bin->main_code_attr = r_bin_java_get_attr_from_field (method, R_BIN_JAVA_ATTR_TYPE_CODE_ATTR, 0);
2307 		} else if (method && (!strcmp ((const char *) method->name, "<init>") || !strcmp ((const char *) method->name, "init")))   {
2308 			IFDBG eprintf("Found an init function.\n");
2309 			bin->entrypoint = method;
2310 			bin->entrypoint_code_attr = r_bin_java_get_attr_from_field (method, R_BIN_JAVA_ATTR_TYPE_CODE_ATTR, 0);
2311 		} else if (method && (!strcmp ((const char *) method->name, "<cinit>") || !strcmp ((const char *) method->name, "cinit")))   {
2312 			bin->cf2.this_class_entrypoint = method;
2313 			bin->cf2.this_class_entrypoint_code_attr = r_bin_java_get_attr_from_field (method, R_BIN_JAVA_ATTR_TYPE_CODE_ATTR, 0);
2314 		}
2315 		if (adv + offset > len) {
2316 			eprintf ("[X] r_bin_java: Error unable to parse remainder of classfile after Method: %d.\n", i);
2317 			break;
2318 		}
2319 		IFDBG r_bin_java_print_field_summary(method);
2320 	}
2321 	bin->methods_size = adv;
2322 	return adv;
2323 }
2324 
r_bin_java_new_bin(RBinJavaObj * bin,ut64 loadaddr,Sdb * kv,const ut8 * buf,ut64 len)2325 R_API int r_bin_java_new_bin(RBinJavaObj *bin, ut64 loadaddr, Sdb *kv, const ut8 *buf, ut64 len) {
2326 	R_BIN_JAVA_GLOBAL_BIN = bin;
2327 	if (!r_str_constpool_init (&bin->constpool)) {
2328 		return false;
2329 	}
2330 	bin->lines.count = 0;
2331 	bin->loadaddr = loadaddr;
2332 	r_bin_java_get_java_null_cp ();
2333 	bin->id = r_num_rand (UT32_MAX);
2334 	bin->kv = kv ? kv : sdb_new (NULL, NULL, 0);
2335 	bin->AllJavaBinObjs = NULL;
2336 	return r_bin_java_load_bin (bin, buf, len);
2337 }
2338 
r_bin_java_load_bin(RBinJavaObj * bin,const ut8 * buf,ut64 buf_sz)2339 R_API int r_bin_java_load_bin(RBinJavaObj *bin, const ut8 *buf, ut64 buf_sz) {
2340 	ut64 adv = 0;
2341 	R_BIN_JAVA_GLOBAL_BIN = bin;
2342 	if (!bin) {
2343 		return false;
2344 	}
2345 	r_bin_java_reset_bin_info (bin);
2346 	memcpy ((ut8 *) &bin->cf, buf, 10);
2347 	if (memcmp (bin->cf.cafebabe, "\xCA\xFE\xBA\xBE", 4)) {
2348 		eprintf ("r_bin_java_new_bin: Invalid header (%02x %02x %02x %02x)\n",
2349 			bin->cf.cafebabe[0], bin->cf.cafebabe[1],
2350 			bin->cf.cafebabe[2], bin->cf.cafebabe[3]);
2351 		return false;
2352 	}
2353 	if (bin->cf.major[0] == bin->cf.major[1] && bin->cf.major[0] == 0) {
2354 		eprintf ("Java CLASS with MACH0 header?\n");
2355 		return false;
2356 	}
2357 	adv += 8;
2358 	// -2 so that the cp_count will be parsed
2359 	adv += r_bin_java_parse_cp_pool (bin, adv, buf, buf_sz);
2360 	if (adv > buf_sz) {
2361 		eprintf ("[X] r_bin_java: Error unable to parse remainder of classfile after Constant Pool.\n");
2362 		return true;
2363 	}
2364 	adv += r_bin_java_read_class_file2 (bin, adv, buf, buf_sz);
2365 	if (adv > buf_sz) {
2366 		eprintf ("[X] r_bin_java: Error unable to parse remainder of classfile after class file info.\n");
2367 		return true;
2368 	}
2369 	IFDBG eprintf("This class: %d %s\n", bin->cf2.this_class, bin->cf2.this_class_name);
2370 	IFDBG eprintf("0x%"PFMT64x " Access flags: 0x%04x\n", adv, bin->cf2.access_flags);
2371 	adv += r_bin_java_parse_interfaces (bin, adv, buf, buf_sz);
2372 	if (adv > buf_sz) {
2373 		eprintf ("[X] r_bin_java: Error unable to parse remainder of classfile after Interfaces.\n");
2374 		return true;
2375 	}
2376 	adv += r_bin_java_parse_fields (bin, adv, buf, buf_sz);
2377 	if (adv > buf_sz) {
2378 		eprintf ("[X] r_bin_java: Error unable to parse remainder of classfile after Fields.\n");
2379 		return true;
2380 	}
2381 	adv += r_bin_java_parse_methods (bin, adv, buf, buf_sz);
2382 	if (adv > buf_sz) {
2383 		eprintf ("[X] r_bin_java: Error unable to parse remainder of classfile after Methods.\n");
2384 		return true;
2385 	}
2386 	adv += r_bin_java_parse_attrs (bin, adv, buf, buf_sz);
2387 	bin->calc_size = adv;
2388 	// if (adv > buf_sz) {
2389 	// eprintf ("[X] r_bin_java: Error unable to parse remainder of classfile after Attributes.\n");
2390 	// return true;
2391 	// }
2392 
2393 	// add_cp_objs_to_sdb(bin);
2394 	// add_method_infos_to_sdb(bin);
2395 	// add_field_infos_to_sdb(bin);
2396 	return true;
2397 }
2398 
r_bin_java_get_version(RBinJavaObj * bin)2399 R_API char *r_bin_java_get_version(RBinJavaObj *bin) {
2400 	return r_str_newf ("0x%02x%02x 0x%02x%02x",
2401 		bin->cf.major[1], bin->cf.major[0],
2402 		bin->cf.minor[1], bin->cf.minor[0]);
2403 }
2404 
r_bin_java_get_entrypoints(RBinJavaObj * bin)2405 R_API RList *r_bin_java_get_entrypoints(RBinJavaObj *bin) {
2406 	RListIter *iter = NULL, *iter_tmp = NULL;
2407 	RBinJavaField *fm_type;
2408 	RList *ret = r_list_newf (free);
2409 	if (!ret) {
2410 		return NULL;
2411 	}
2412 	r_list_foreach_safe (bin->methods_list, iter, iter_tmp, fm_type) {
2413 		if (!strcmp (fm_type->name, "main")
2414 		|| !strcmp (fm_type->name, "<init>")
2415 		|| !strcmp (fm_type->name, "<clinit>")
2416 		|| strstr (fm_type->flags_str, "static")) {
2417 			RBinAddr *addr = R_NEW0 (RBinAddr);
2418 			if (addr) {
2419 				addr->vaddr = addr->paddr = \
2420 					r_bin_java_get_method_code_offset (fm_type) + bin->loadaddr;
2421 				addr->hpaddr = fm_type->file_offset;
2422 				r_list_append (ret, addr);
2423 			}
2424 		}
2425 	}
2426 	return ret;
2427 }
2428 
r_bin_java_get_method_code_attribute_with_addr(RBinJavaObj * bin,ut64 addr)2429 R_API RBinJavaField *r_bin_java_get_method_code_attribute_with_addr(RBinJavaObj *bin, ut64 addr) {
2430 	RListIter *iter = NULL, *iter_tmp = NULL;
2431 	RBinJavaField *fm_type, *res = NULL;
2432 	if (bin == NULL && R_BIN_JAVA_GLOBAL_BIN) {
2433 		bin = R_BIN_JAVA_GLOBAL_BIN;
2434 	} else if (bin == NULL) {
2435 		eprintf ("Attempting to analyse function when the R_BIN_JAVA_GLOBAL_BIN has not been set.\n");
2436 		return NULL;
2437 	}
2438 	r_list_foreach_safe (bin->methods_list, iter, iter_tmp, fm_type) {
2439 		ut64 offset = r_bin_java_get_method_code_offset (fm_type) + bin->loadaddr,
2440 		size = r_bin_java_get_method_code_size (fm_type);
2441 		if (addr >= offset && addr <= size + offset) {
2442 			res = fm_type;
2443 		}
2444 	}
2445 	return res;
2446 }
2447 
r_bin_java_get_entrypoint(RBinJavaObj * bin,int sym)2448 R_API RBinAddr *r_bin_java_get_entrypoint(RBinJavaObj *bin, int sym) {
2449 	RBinAddr *ret = NULL;
2450 	ret = R_NEW0 (RBinAddr);
2451 	if (!ret) {
2452 		return NULL;
2453 	}
2454 	ret->paddr = UT64_MAX;
2455 	switch (sym) {
2456 	case R_BIN_SYM_ENTRY:
2457 	case R_BIN_SYM_INIT:
2458 		ret->paddr = r_bin_java_find_method_offset (bin, "<init>");
2459 		if (ret->paddr == UT64_MAX) {
2460 			ret->paddr = r_bin_java_find_method_offset (bin, "<cinit>");
2461 		}
2462 		break;
2463 	case R_BIN_SYM_FINI:
2464 		ret->paddr = UT64_MAX;
2465 		break;
2466 	case R_BIN_SYM_MAIN:
2467 		ret->paddr = r_bin_java_find_method_offset (bin, "main");
2468 		break;
2469 	default:
2470 		ret->paddr = -1;
2471 	}
2472 	if (ret->paddr != -1) {
2473 		ret->paddr += bin->loadaddr;
2474 	}
2475 	return ret;
2476 }
2477 
r_bin_java_get_method_code_size(RBinJavaField * fm_type)2478 R_API ut64 r_bin_java_get_method_code_size(RBinJavaField *fm_type) {
2479 	RListIter *attr_iter = NULL, *attr_iter_tmp = NULL;
2480 	RBinJavaAttrInfo *attr = NULL;
2481 	ut64 sz = 0;
2482 	r_list_foreach_safe (fm_type->attributes, attr_iter, attr_iter_tmp, attr) {
2483 		if (attr->type == R_BIN_JAVA_ATTR_TYPE_CODE_ATTR) {
2484 			sz = attr->info.code_attr.code_length;
2485 			break;
2486 		}
2487 	}
2488 	return sz;
2489 }
2490 
r_bin_java_find_method_offset(RBinJavaObj * bin,const char * method_name)2491 R_API ut64 r_bin_java_find_method_offset(RBinJavaObj *bin, const char *method_name) {
2492 	RListIter *attr_iter = NULL, *attr_iter_tmp = NULL;
2493 	RBinJavaField *method = NULL;
2494 	ut64 offset = -1;
2495 	r_list_foreach_safe (bin->methods_list, attr_iter, attr_iter_tmp, method) {
2496 		if (method && !strcmp ((const char *) method->name, method_name)) {
2497 			offset = r_bin_java_get_method_code_offset (method) + bin->loadaddr;
2498 			break;
2499 		}
2500 	}
2501 	return offset;
2502 }
2503 
r_bin_java_get_method_code_offset(RBinJavaField * fm_type)2504 R_API ut64 r_bin_java_get_method_code_offset(RBinJavaField *fm_type) {
2505 	RListIter *attr_iter = NULL, *attr_iter_tmp = NULL;
2506 	RBinJavaAttrInfo *attr = NULL;
2507 	ut64 offset = 0;
2508 	r_list_foreach_safe (fm_type->attributes, attr_iter, attr_iter_tmp, attr) {
2509 		if (attr->type == R_BIN_JAVA_ATTR_TYPE_CODE_ATTR) {
2510 			offset = attr->info.code_attr.code_offset;
2511 			break;
2512 		}
2513 	}
2514 	return offset;
2515 }
2516 
r_bin_java_allocate_rbinfield(void)2517 R_API RBinField *r_bin_java_allocate_rbinfield(void) {
2518 	RBinField *t = (RBinField *) malloc (sizeof (RBinField));
2519 	if (t) {
2520 		memset (t, 0, sizeof (RBinField));
2521 	}
2522 	return t;
2523 }
2524 
r_bin_java_create_new_rbinfield_from_field(RBinJavaField * fm_type,ut64 baddr)2525 R_API RBinField *r_bin_java_create_new_rbinfield_from_field(RBinJavaField *fm_type, ut64 baddr) {
2526 	RBinField *field = r_bin_java_allocate_rbinfield ();
2527 	if (field) {
2528 		field->name = strdup (fm_type->name);
2529 		field->paddr = fm_type->file_offset + baddr;
2530 		field->visibility = fm_type->flags;
2531 	}
2532 	return field;
2533 }
2534 
r_bin_java_create_new_symbol_from_field(RBinJavaField * fm_type,ut64 baddr)2535 R_API RBinSymbol *r_bin_java_create_new_symbol_from_field(RBinJavaField *fm_type, ut64 baddr) {
2536 	RBinSymbol *sym = R_NEW0 (RBinSymbol);
2537 	if (fm_type == NULL || fm_type->field_ref_cp_obj == NULL || fm_type->field_ref_cp_obj == &R_BIN_JAVA_NULL_TYPE) {
2538 		R_FREE (sym);
2539 	}
2540 	if (sym) {
2541 		sym->name = strdup (fm_type->name);
2542 		// strncpy (sym->type, fm_type->descriptor, R_BIN_SIZEOF_STRINGS);
2543 		if (fm_type->type == R_BIN_JAVA_FIELD_TYPE_METHOD) {
2544 			sym->type = R_BIN_TYPE_FUNC_STR;
2545 			sym->paddr = r_bin_java_get_method_code_offset (fm_type);
2546 			sym->vaddr = r_bin_java_get_method_code_offset (fm_type) + baddr;
2547 			sym->size = r_bin_java_get_method_code_size (fm_type);
2548 		} else {
2549 			sym->type = "FIELD";
2550 			sym->paddr = fm_type->file_offset;// r_bin_java_get_method_code_offset (fm_type);
2551 			sym->vaddr = fm_type->file_offset + baddr;
2552 			sym->size = fm_type->size;
2553 		}
2554 		if (r_bin_java_is_fm_type_protected (fm_type)) {
2555 			sym->bind = R_BIN_BIND_LOCAL_STR;
2556 		} else if (r_bin_java_is_fm_type_private (fm_type)) {
2557 			sym->bind = R_BIN_BIND_LOCAL_STR;
2558 		} else if (r_bin_java_is_fm_type_protected (fm_type)) {
2559 			sym->bind = R_BIN_BIND_GLOBAL_STR;
2560 		}
2561 		sym->forwarder = "NONE";
2562 		if (fm_type->class_name) {
2563 			sym->classname = strdup (fm_type->class_name);
2564 		} else {
2565 			sym->classname = strdup ("UNKNOWN"); // dupped names?
2566 		}
2567 		sym->ordinal = fm_type->metas->ord;
2568 		sym->visibility = fm_type->flags;
2569 		if (fm_type->flags_str) {
2570 			sym->visibility_str = strdup (fm_type->flags_str);
2571 		}
2572 	}
2573 	return sym;
2574 }
2575 
r_bin_java_create_new_symbol_from_fm_type_meta(RBinJavaField * fm_type,ut64 baddr)2576 R_API RBinSymbol *r_bin_java_create_new_symbol_from_fm_type_meta(RBinJavaField *fm_type, ut64 baddr) {
2577 	RBinSymbol *sym = R_NEW0 (RBinSymbol);
2578 	if (!sym || !fm_type || !fm_type->field_ref_cp_obj || fm_type->field_ref_cp_obj == &R_BIN_JAVA_NULL_TYPE) {
2579 		free (sym);
2580 		return NULL;
2581 	}
2582 	// ut32 new_name_len = strlen (fm_type->name) + strlen ("_meta") + 1;
2583 	// char *new_name = malloc (new_name_len);
2584 	sym->name = r_str_newf ("meta_%s", fm_type->name);
2585 	if (fm_type->type == R_BIN_JAVA_FIELD_TYPE_METHOD) {
2586 		sym->type = "FUNC_META";
2587 	} else {
2588 		sym->type = "FIELD_META";
2589 	}
2590 	if (r_bin_java_is_fm_type_protected (fm_type)) {
2591 		sym->bind = R_BIN_BIND_LOCAL_STR;
2592 	} else if (r_bin_java_is_fm_type_private (fm_type)) {
2593 		sym->bind = R_BIN_BIND_LOCAL_STR;
2594 	} else if (r_bin_java_is_fm_type_protected (fm_type)) {
2595 		sym->bind = R_BIN_BIND_GLOBAL_STR;
2596 	}
2597 	sym->forwarder = "NONE";
2598 	if (fm_type->class_name) {
2599 		sym->classname = strdup (fm_type->class_name);
2600 	} else {
2601 		sym->classname = strdup ("UNKNOWN");
2602 	}
2603 	sym->paddr = fm_type->file_offset;// r_bin_java_get_method_code_offset (fm_type);
2604 	sym->vaddr = fm_type->file_offset + baddr;
2605 	sym->ordinal = fm_type->metas->ord;
2606 	sym->size = fm_type->size;
2607 	sym->visibility = fm_type->flags;
2608 	if (fm_type->flags_str) {
2609 		sym->visibility_str = strdup (fm_type->flags_str);
2610 	}
2611 	return sym;
2612 }
2613 
r_bin_java_create_new_symbol_from_ref(RBinJavaObj * bin,RBinJavaCPTypeObj * obj,ut64 baddr)2614 R_API RBinSymbol *r_bin_java_create_new_symbol_from_ref(RBinJavaObj *bin, RBinJavaCPTypeObj *obj, ut64 baddr) {
2615 	RBinSymbol *sym = R_NEW0 (RBinSymbol);
2616 	if (!sym) {
2617 		return NULL;
2618 	}
2619 	char *class_name, *name, *type_name;
2620 	if (obj == NULL || (obj->tag != R_BIN_JAVA_CP_METHODREF &&
2621 	obj->tag != R_BIN_JAVA_CP_INTERFACEMETHOD_REF &&
2622 	obj->tag != R_BIN_JAVA_CP_FIELDREF)) {
2623 		R_FREE (sym);
2624 		return sym;
2625 	}
2626 	if (sym) {
2627 		class_name = r_bin_java_get_name_from_bin_cp_list (bin,
2628 			obj->info.cp_method.class_idx);
2629 		name = r_bin_java_get_name_from_bin_cp_list (bin,
2630 			obj->info.cp_method.name_and_type_idx);
2631 		type_name = r_bin_java_get_name_from_bin_cp_list (bin,
2632 			obj->info.cp_method.name_and_type_idx);
2633 		if (name) {
2634 			sym->name = name;
2635 			name = NULL;
2636 		}
2637 		if (type_name) {
2638 			sym->type = r_str_constpool_get (&bin->constpool, type_name);
2639 			R_FREE (type_name);
2640 		}
2641 		if (class_name) {
2642 			sym->classname = strdup (class_name);
2643 		}
2644 		sym->paddr = obj->file_offset + baddr;
2645 		sym->vaddr = obj->file_offset + baddr;
2646 		sym->ordinal = obj->metas->ord;
2647 		sym->size = 0;
2648 	}
2649 	return sym;
2650 }
2651 
2652 // TODO: vaddr+vsize break things if set
r_bin_java_get_sections(RBinJavaObj * bin)2653 R_API RList *r_bin_java_get_sections(RBinJavaObj *bin) {
2654 	RBinSection *section = NULL;
2655 	RList *sections = r_list_newf (free);
2656 	ut64 baddr = bin->loadaddr;
2657 	RBinJavaField *fm_type;
2658 	RListIter *iter = NULL;
2659 	if (bin->cp_count > 0) {
2660 		section = R_NEW0 (RBinSection);
2661 		if (section) {
2662 			section->name = strdup ("constant_pool");
2663 			section->paddr = bin->cp_offset + baddr;
2664 			section->size = bin->cp_size;
2665 #if 0
2666 			section->vsize = section->size;
2667 			section->vaddr = 0x10; // XXX // bin->cp_offset; //  + baddr;
2668 #endif
2669 			section->vaddr = baddr;
2670 			// section->vaddr = section->paddr;
2671 			// section->vsize = section->size;
2672 			section->perm = R_PERM_R;
2673 			section->add = true;
2674 			r_list_append (sections, section);
2675 		}
2676 		section = NULL;
2677 	}
2678 	if (bin->fields_count > 0) {
2679 		section = R_NEW0 (RBinSection);
2680 		if (section) {
2681 			section->name = strdup ("fields");
2682 			section->size = bin->fields_size;
2683 			section->paddr = bin->fields_offset + baddr;
2684 #if 0
2685 			section->vsize = section->size;
2686 			section->vaddr = section->paddr;
2687 #endif
2688 			section->perm = R_PERM_R;
2689 			section->add = true;
2690 			r_list_append (sections, section);
2691 			section = NULL;
2692 			r_list_foreach (bin->fields_list, iter, fm_type) {
2693 				if (fm_type->attr_offset == 0) {
2694 					continue;
2695 				}
2696 				section = R_NEW0 (RBinSection);
2697 				if (section) {
2698 					section->name = r_str_newf ("attrs.%s", fm_type->name);
2699 					section->size = fm_type->size - (fm_type->file_offset - fm_type->attr_offset);
2700 #if 0
2701 					section->vsize = section->size;
2702 					section->vaddr = section->paddr;
2703 #endif
2704 					section->paddr = fm_type->attr_offset + baddr;
2705 					section->perm = R_PERM_R;
2706 					section->add = true;
2707 					r_list_append (sections, section);
2708 				}
2709 			}
2710 		}
2711 	}
2712 	if (bin->methods_count > 0) {
2713 		section = R_NEW0 (RBinSection);
2714 		if (section) {
2715 			section->name = strdup ("methods");
2716 			section->paddr = bin->methods_offset + baddr;
2717 			section->size = bin->methods_size;
2718 			// section->vaddr = section->paddr;
2719 			// section->vsize = section->size;
2720 			section->perm = R_PERM_RX;
2721 			section->add = true;
2722 			r_list_append (sections, section);
2723 			section = NULL;
2724 			r_list_foreach (bin->methods_list, iter, fm_type) {
2725 				if (fm_type->attr_offset == 0) {
2726 					continue;
2727 				}
2728 				section = R_NEW0 (RBinSection);
2729 				if (section) {
2730 					section->name = r_str_newf ("attrs.%s", fm_type->name);
2731 					section->size = fm_type->size - (fm_type->file_offset - fm_type->attr_offset);
2732 					// section->vsize = section->size;
2733 					// section->vaddr = section->paddr;
2734 					section->paddr = fm_type->attr_offset + baddr;
2735 					section->perm = R_PERM_R | R_PERM_X;
2736 					section->add = true;
2737 					r_list_append (sections, section);
2738 				}
2739 			}
2740 		}
2741 	}
2742 	if (bin->interfaces_count > 0) {
2743 		section = R_NEW0 (RBinSection);
2744 		if (section) {
2745 			section->name = strdup ("interfaces");
2746 			section->paddr = bin->interfaces_offset + baddr;
2747 			section->size = bin->interfaces_size;
2748 			// section->vaddr = section->paddr;
2749 			// section->vsize = section->size;
2750 			section->perm = R_PERM_R;
2751 			section->add = true;
2752 			r_list_append (sections, section);
2753 		}
2754 		section = NULL;
2755 	}
2756 	if (bin->attrs_count > 0) {
2757 		section = R_NEW0 (RBinSection);
2758 		if (section) {
2759 			section->name = strdup ("attributes");
2760 			section->paddr = bin->attrs_offset + baddr;
2761 			section->size = bin->attrs_size;
2762 			// section->vaddr = section->paddr;
2763 			// section->vsize = section->size;
2764 			section->perm = R_PERM_R;
2765 			section->perm = R_PERM_R;
2766 			section->add = true;
2767 			r_list_append (sections, section);
2768 		}
2769 		section = NULL;
2770 	}
2771 	return sections;
2772 }
2773 
r_bin_java_enum_class_methods(RBinJavaObj * bin,ut16 class_idx)2774 R_API RList *r_bin_java_enum_class_methods(RBinJavaObj *bin, ut16 class_idx) {
2775 	RList *methods = r_list_newf (free);
2776 	RListIter *iter;
2777 	RBinJavaField *field;
2778 	r_list_foreach (bin->methods_list, iter, field) {
2779 		if (field->field_ref_cp_obj && 0) {
2780 			if ((field && field->field_ref_cp_obj->metas->ord == class_idx)) {
2781 				RBinSymbol *sym = r_bin_java_create_new_symbol_from_ref (
2782 						bin, field->field_ref_cp_obj, bin->loadaddr);
2783 				if (sym) {
2784 					r_list_append (methods, sym);
2785 				}
2786 			}
2787 		} else {
2788 			RBinSymbol *sym = R_NEW0 (RBinSymbol);
2789 			sym->name = strdup (field->name);
2790 			// func defintion
2791 			// sym->paddr = field->file_offset + bin->loadaddr;
2792 			// code implementation
2793 			sym->paddr = r_bin_java_get_method_code_offset (field);
2794 			sym->vaddr = sym->paddr; // + bin->loadaddr;
2795 			r_list_append (methods, sym);
2796 		}
2797 	}
2798 	return methods;
2799 }
2800 
r_bin_java_enum_class_fields(RBinJavaObj * bin,ut16 class_idx)2801 R_API RList *r_bin_java_enum_class_fields(RBinJavaObj *bin, ut16 class_idx) {
2802 	RList *fields = r_list_newf (free);
2803 	RListIter *iter;
2804 	RBinJavaField *fm_type;
2805 	RBinField *field = NULL;
2806 	r_list_foreach (bin->fields_list, iter, fm_type) {
2807 		if (fm_type) {
2808 			if (fm_type && fm_type->field_ref_cp_obj
2809 			&& fm_type->field_ref_cp_obj->metas->ord == class_idx) {
2810 				field = r_bin_java_create_new_rbinfield_from_field (fm_type, bin->loadaddr);
2811 				if (field) {
2812 					r_list_append (fields, field);
2813 				}
2814 			}
2815 		}
2816 	}
2817 	return fields;
2818 }
2819 
is_class_interface(RBinJavaObj * bin,RBinJavaCPTypeObj * cp_obj)2820 R_API int is_class_interface(RBinJavaObj *bin, RBinJavaCPTypeObj *cp_obj) {
2821 	RBinJavaInterfaceInfo *ifobj;
2822 	RListIter *iter;
2823 	int res = false;
2824 	r_list_foreach (bin->interfaces_list, iter, ifobj) {
2825 		if (ifobj) {
2826 			res = cp_obj == ifobj->cp_class;
2827 			if (res) {
2828 				break;
2829 			}
2830 		}
2831 	}
2832 	return res;
2833 }
2834 /*
2835    R_API RList * r_bin_java_get_interface_classes(RBinJavaObj * bin) {
2836         RList *interfaces_names = r_list_new ();
2837         RListIter *iter;
2838         RBinJavaInterfaceInfo *ifobj;
2839         r_list_foreach(bin->interfaces_list, iter, iinfo) {
2840                 RBinClass *class_ = R_NEW0 (RBinClass);
2841                 RBinJavaCPTypeObj *cp_obj = ;
2842                 if (ifobj && ifobj->name) {
2843                         ut8 * name = strdup(ifobj->name);
2844                         r_list_append(interfaces_names, name);
2845                 }
2846         }
2847         return interfaces_names;
2848    }
2849 */
2850 
r_bin_java_get_lib_names(RBinJavaObj * bin)2851 R_API RList *r_bin_java_get_lib_names(RBinJavaObj *bin) {
2852 	RList *lib_names = r_list_newf (free);
2853 	RListIter *iter;
2854 	RBinJavaCPTypeObj *cp_obj = NULL;
2855 	if (!bin) {
2856 		return lib_names;
2857 	}
2858 	r_list_foreach (bin->cp_list, iter, cp_obj) {
2859 		if (cp_obj && cp_obj->tag == R_BIN_JAVA_CP_CLASS &&
2860 		(bin->cf2.this_class != cp_obj->info.cp_class.name_idx || !is_class_interface (bin, cp_obj))) {
2861 			char *name = r_bin_java_get_item_name_from_bin_cp_list (bin, cp_obj);
2862 			if (name) {
2863 				r_list_append (lib_names, name);
2864 			}
2865 		}
2866 	}
2867 	return lib_names;
2868 }
2869 
r_bin_java_classes_free(void * k)2870 R_API void r_bin_java_classes_free(void /*RBinClass*/ *k) {
2871 	RBinClass *klass = k;
2872 	if (klass) {
2873 		r_list_free (klass->methods);
2874 		r_list_free (klass->fields);
2875 		free (klass->name);
2876 		free (klass->super);
2877 		free (klass->visibility_str);
2878 		free (klass);
2879 	}
2880 }
2881 
r_bin_java_get_classes(RBinJavaObj * bin)2882 R_API RList *r_bin_java_get_classes(RBinJavaObj *bin) {
2883 	RList *classes = r_list_newf (r_bin_java_classes_free);
2884 	RListIter *iter;
2885 	RBinJavaCPTypeObj *cp_obj = NULL;
2886 	RBinJavaCPTypeObj *this_class_cp_obj = r_bin_java_get_item_from_bin_cp_list (bin, bin->cf2.this_class);
2887 	ut32 idx = 0;
2888 	RBinClass *k = R_NEW0 (RBinClass);
2889 	if (!k) {
2890 		r_list_free (classes);
2891 		return NULL;
2892 	}
2893 	k->visibility = bin->cf2.access_flags;
2894 	if (bin->cf2.flags_str) {
2895 		k->visibility_str = strdup (bin->cf2.flags_str);
2896 	}
2897 	k->methods = r_bin_java_enum_class_methods (bin, bin->cf2.this_class);
2898 	k->fields = r_bin_java_enum_class_fields (bin, bin->cf2.this_class);
2899 	k->name = r_bin_java_get_this_class_name (bin);
2900 	k->super = r_bin_java_get_name_from_bin_cp_list (bin, bin->cf2.super_class);
2901 	k->index = (idx++);
2902 	r_list_append (classes, k);
2903 	r_list_foreach (bin->cp_list, iter, cp_obj) {
2904 		if (cp_obj && cp_obj->tag == R_BIN_JAVA_CP_CLASS
2905 		&& (this_class_cp_obj != cp_obj && is_class_interface (bin, cp_obj))) {
2906 			k = R_NEW0 (RBinClass);
2907 			if (!k) {
2908 				break;
2909 			}
2910 			k->methods = r_bin_java_enum_class_methods (bin, cp_obj->info.cp_class.name_idx);
2911 			k->fields = r_bin_java_enum_class_fields (bin, cp_obj->info.cp_class.name_idx);
2912 			k->index = idx;
2913 			k->name = r_bin_java_get_item_name_from_bin_cp_list (bin, cp_obj);
2914 			r_list_append (classes, k);
2915 			idx++;
2916 		}
2917 	}
2918 	return classes;
2919 }
2920 
r_bin_java_create_new_symbol_from_invoke_dynamic(RBinJavaCPTypeObj * obj,ut64 baddr)2921 R_API RBinSymbol *r_bin_java_create_new_symbol_from_invoke_dynamic(RBinJavaCPTypeObj *obj, ut64 baddr) {
2922 	if (!obj || (obj->tag != R_BIN_JAVA_CP_INVOKEDYNAMIC)) {
2923 		return NULL;
2924 	}
2925 	return r_bin_java_create_new_symbol_from_cp_idx (obj->info.cp_invoke_dynamic.name_and_type_index, baddr);
2926 }
2927 
r_bin_java_create_new_symbol_from_cp_idx(ut32 cp_idx,ut64 baddr)2928 R_API RBinSymbol *r_bin_java_create_new_symbol_from_cp_idx(ut32 cp_idx, ut64 baddr) {
2929 	RBinSymbol *sym = NULL;
2930 	RBinJavaCPTypeObj *obj = r_bin_java_get_item_from_bin_cp_list (
2931 		R_BIN_JAVA_GLOBAL_BIN, cp_idx);
2932 	if (obj) {
2933 		switch (obj->tag) {
2934 		case R_BIN_JAVA_CP_METHODREF:
2935 		case R_BIN_JAVA_CP_FIELDREF:
2936 		case R_BIN_JAVA_CP_INTERFACEMETHOD_REF:
2937 			sym = r_bin_java_create_new_symbol_from_ref (R_BIN_JAVA_GLOBAL_BIN, obj, baddr);
2938 			break;
2939 		case R_BIN_JAVA_CP_INVOKEDYNAMIC:
2940 			sym = r_bin_java_create_new_symbol_from_invoke_dynamic (obj, baddr);
2941 			break;
2942 		default:
2943 			break;
2944 		}
2945 	}
2946 	return sym;
2947 }
2948 
U(r_bin_java_get_fields)2949 R_API RList *U(r_bin_java_get_fields)(RBinJavaObj * bin) {
2950 	RListIter *iter = NULL, *iter_tmp = NULL;
2951 	RList *fields = r_list_new ();
2952 	RBinJavaField *fm_type;
2953 	RBinField *field;
2954 	r_list_foreach_safe (bin->fields_list, iter, iter_tmp, fm_type) {
2955 		field = r_bin_java_create_new_rbinfield_from_field (fm_type, bin->loadaddr);
2956 		if (field) {
2957 			r_list_append (fields, field);
2958 		}
2959 	}
2960 	return fields;
2961 }
2962 
r_bin_add_import(RBinJavaObj * bin,RBinJavaCPTypeObj * obj,const char * type)2963 R_API void r_bin_add_import(RBinJavaObj *bin, RBinJavaCPTypeObj *obj, const char *type) {
2964 	RBinImport *imp = R_NEW0 (RBinImport);
2965 	char *class_name = r_bin_java_get_name_from_bin_cp_list (bin, obj->info.cp_method.class_idx);
2966 	char *name = r_bin_java_get_name_from_bin_cp_list (bin, obj->info.cp_method.name_and_type_idx);
2967 	char *descriptor = r_bin_java_get_desc_from_bin_cp_list (bin, obj->info.cp_method.name_and_type_idx);
2968 	class_name = class_name ? class_name : strdup ("INVALID CLASS NAME INDEX");
2969 	name = name ? name : strdup ("InvalidNameIndex");
2970 	descriptor = descriptor ? descriptor : strdup ("INVALID DESCRIPTOR INDEX");
2971 	imp->classname = class_name;
2972 	imp->name = name;
2973 	imp->bind = "NONE";
2974 	imp->type = r_str_constpool_get (&bin->constpool, type);
2975 	imp->descriptor = descriptor;
2976 	imp->ordinal = obj->idx;
2977 	r_list_append (bin->imports_list, imp);
2978 }
2979 
r_bin_java_set_imports(RBinJavaObj * bin)2980 R_API void r_bin_java_set_imports(RBinJavaObj *bin) {
2981 	RListIter *iter = NULL;
2982 	RBinJavaCPTypeObj *obj = NULL;
2983 	r_list_free (bin->imports_list);
2984 	bin->imports_list = r_list_newf (free);
2985 	r_list_foreach (bin->cp_list, iter, obj) {
2986 		const char *type = NULL;
2987 		switch (obj->tag) {
2988 		case R_BIN_JAVA_CP_METHODREF: type = "METHOD"; break;
2989 		case R_BIN_JAVA_CP_INTERFACEMETHOD_REF: type = "FIELD"; break;
2990 		case R_BIN_JAVA_CP_FIELDREF: type = "INTERFACE_METHOD"; break;
2991 		default: type = NULL; break;
2992 		}
2993 		if (type) {
2994 			r_bin_add_import (bin, obj, type);
2995 		}
2996 	}
2997 }
2998 
r_bin_java_get_imports(RBinJavaObj * bin)2999 R_API RList *r_bin_java_get_imports(RBinJavaObj *bin) {
3000 	RList *ret = r_list_newf (free);
3001 	RBinImport *import = NULL;
3002 	RListIter *iter;
3003 	r_list_foreach (bin->imports_list, iter, import) {
3004 		RBinImport *n_import = R_NEW0 (RBinImport);
3005 		if (!n_import) {
3006 			r_list_free (ret);
3007 			return NULL;
3008 		}
3009 		memcpy (n_import, import, sizeof (RBinImport));
3010 		r_list_append (ret, n_import);
3011 	}
3012 	return ret;
3013 }
3014 
r_bin_java_get_symbols(RBinJavaObj * bin)3015 R_API RList *r_bin_java_get_symbols(RBinJavaObj *bin) {
3016 	RListIter *iter = NULL, *iter_tmp = NULL;
3017 	RList *imports, *symbols = r_list_newf (free);
3018 	RBinSymbol *sym = NULL;
3019 	RBinImport *imp;
3020 	RBinJavaField *fm_type;
3021 	r_list_foreach_safe (bin->methods_list, iter, iter_tmp, fm_type) {
3022 		sym = r_bin_java_create_new_symbol_from_field (fm_type, bin->loadaddr);
3023 		if (sym) {
3024 			r_list_append (symbols, (void *) sym);
3025 		}
3026 		sym = r_bin_java_create_new_symbol_from_fm_type_meta (fm_type, bin->loadaddr);
3027 		if (sym) {
3028 			r_list_append (symbols, (void *) sym);
3029 		}
3030 	}
3031 	r_list_foreach_safe (bin->fields_list, iter, iter_tmp, fm_type) {
3032 		sym = r_bin_java_create_new_symbol_from_field (fm_type, bin->loadaddr);
3033 		if (sym) {
3034 			r_list_append (symbols, (void *) sym);
3035 		}
3036 		sym = r_bin_java_create_new_symbol_from_fm_type_meta (fm_type, bin->loadaddr);
3037 		if (sym) {
3038 			r_list_append (symbols, (void *) sym);
3039 		}
3040 	}
3041 	bin->lang = "java";
3042 	if (bin->cf.major[1] >= 46) {
3043 		switch (bin->cf.major[1]) {
3044 			static char lang[32];
3045 			int langid;
3046 			case 46:
3047 			case 47:
3048 			case 48:
3049 				langid = 2 + (bin->cf.major[1] - 46);
3050 				snprintf (lang, sizeof (lang) - 1, "java 1.%d", langid);
3051 				bin->lang = lang;
3052 				break;
3053 			default:
3054 				langid = 5 + (bin->cf.major[1] - 49);
3055 				snprintf (lang, sizeof (lang) - 1, "java %d", langid);
3056 				bin->lang = lang;
3057 		}
3058 	}
3059 	imports = r_bin_java_get_imports (bin);
3060 	r_list_foreach (imports, iter, imp) {
3061 		sym = R_NEW0 (RBinSymbol);
3062 		if (!sym) {
3063 			break;
3064 		}
3065 		if (imp->classname && !strncmp (imp->classname, "kotlin/jvm", 10)) {
3066 			bin->lang = "kotlin";
3067 		}
3068 		sym->name = strdup (imp->name);
3069 		sym->is_imported = true;
3070 		if (!sym->name) {
3071 			free (sym);
3072 			break;
3073 		}
3074 		sym->type = "import";
3075 		if (!sym->type) {
3076 			free (sym);
3077 			break;
3078 		}
3079 		sym->vaddr = sym->paddr = imp->ordinal;
3080 		sym->ordinal = imp->ordinal;
3081 		r_list_append (symbols, (void *) sym);
3082 	}
3083 	r_list_free (imports);
3084 	return symbols;
3085 }
3086 
r_bin_java_get_strings(RBinJavaObj * bin)3087 R_API RList *r_bin_java_get_strings(RBinJavaObj *bin) {
3088 	RList *strings = r_list_newf (free);
3089 	RBinString *str = NULL;
3090 	RListIter *iter = NULL, *iter_tmp = NULL;
3091 	RBinJavaCPTypeObj *cp_obj = NULL;
3092 	r_list_foreach_safe (bin->cp_list, iter, iter_tmp, cp_obj) {
3093 		if (cp_obj && cp_obj->tag == R_BIN_JAVA_CP_UTF8) {
3094 			str = (RBinString *) R_NEW0 (RBinString);
3095 			if (str) {
3096 				str->paddr = cp_obj->file_offset + bin->loadaddr;
3097 				str->ordinal = cp_obj->metas->ord;
3098 				str->size = cp_obj->info.cp_utf8.length + 3;
3099 				str->length = cp_obj->info.cp_utf8.length;
3100 				if (str->size > 0) {
3101 					str->string = r_str_ndup ((const char *)
3102 						cp_obj->info.cp_utf8.bytes,
3103 						R_BIN_JAVA_MAXSTR);
3104 				}
3105 				r_list_append (strings, (void *) str);
3106 			}
3107 		}
3108 	}
3109 	return strings;
3110 }
3111 
r_bin_java_free(RBinJavaObj * bin)3112 R_API void *r_bin_java_free(RBinJavaObj *bin) {
3113 	char *bin_obj_key = NULL;
3114 	if (!bin) {
3115 		return NULL;
3116 	}
3117 	// Delete the bin object from the data base.
3118 	bin_obj_key = r_bin_java_build_obj_key (bin);
3119 	// if (bin->AllJavaBinObjs && sdb_exists (bin->AllJavaBinObjs, bin_obj_key)) {
3120 	// sdb_unset (bin->AllJavaBinObjs, bin_obj_key, 0);
3121 	// }
3122 	free (bin_obj_key);
3123 	r_list_free (bin->imports_list);
3124 	// XXX - Need to remove all keys belonging to this class from
3125 	// the share meta information sdb.
3126 	// TODO e.g. iterate over bin->kv and delete all obj, func, etc. keys
3127 	// sdb_free (bin->kv);
3128 	// free up the constant pool list
3129 	r_list_free (bin->cp_list);
3130 	// free up the fields list
3131 	r_list_free (bin->fields_list);
3132 	// free up methods list
3133 	r_list_free (bin->methods_list);
3134 	// free up interfaces list
3135 	r_list_free (bin->interfaces_list);
3136 	r_list_free (bin->attrs_list);
3137 	// TODO: XXX if a class list of all inner classes
3138 	// are formed then this will need to be updated
3139 	free (bin->cf2.flags_str);
3140 	free (bin->cf2.this_class_name);
3141 	if (bin == R_BIN_JAVA_GLOBAL_BIN) {
3142 		R_BIN_JAVA_GLOBAL_BIN = NULL;
3143 	}
3144 	free (bin->file);
3145 	r_str_constpool_fini (&bin->constpool);
3146 	free (bin);
3147 	return NULL;
3148 }
3149 
r_bin_java_new_buf(RBuffer * buf,ut64 loadaddr,Sdb * kv)3150 R_API RBinJavaObj *r_bin_java_new_buf(RBuffer *buf, ut64 loadaddr, Sdb *kv) {
3151 	RBinJavaObj *bin = R_NEW0 (RBinJavaObj);
3152 	if (!bin) {
3153 		return NULL;
3154 	}
3155 	ut64 tmpsz;
3156 	const ut8 *tmp = r_buf_data (buf, &tmpsz);
3157 	if (!r_bin_java_new_bin (bin, loadaddr, kv, tmp, tmpsz)) {
3158 		return r_bin_java_free (bin);
3159 	}
3160 	return bin;
3161 }
3162 
r_bin_java_attribute_free(void * a)3163 R_API void r_bin_java_attribute_free(void /*RBinJavaAttrInfo*/ *a) {
3164 	RBinJavaAttrInfo *attr = a;
3165 	if (attr) {
3166 		IFDBG eprintf("Deleting attr %s, %p\n", attr->name, attr);
3167 		if (attr && attr->metas && attr->metas->type_info) {
3168 			RBinJavaAttrMetas *a = attr->metas->type_info;
3169 			if (a && a->allocs && a->allocs->delete_obj) {
3170 				a->allocs->delete_obj (attr);
3171 			}
3172 		}
3173 		// free (attr->metas);
3174 		// free (attr);
3175 	}
3176 }
3177 
r_bin_java_constant_pool(void * o)3178 R_API void r_bin_java_constant_pool(void /*RBinJavaCPTypeObj*/ *o) {
3179 	RBinJavaCPTypeObj *obj = o;
3180 	if (obj != &R_BIN_JAVA_NULL_TYPE) {
3181 		((RBinJavaCPTypeMetas *) obj->metas->type_info)->allocs->delete_obj (obj);
3182 	}
3183 }
3184 
r_bin_java_fmtype_free(void * f)3185 R_API void r_bin_java_fmtype_free(void /*RBinJavaField*/ *f) {
3186 	RBinJavaField *fm_type = f;
3187 	if (!fm_type) {
3188 		return;
3189 	}
3190 	free (fm_type->descriptor);
3191 	free (fm_type->name);
3192 	free (fm_type->flags_str);
3193 	free (fm_type->class_name);
3194 	free (fm_type->metas);
3195 	r_list_free (fm_type->attributes);
3196 	free (fm_type);
3197 }
3198 // Start Free the various attribute types
r_bin_java_unknown_attr_free(void * a)3199 R_API void r_bin_java_unknown_attr_free(void /*RBinJavaAttrInfo*/ *a) {
3200 	RBinJavaAttrInfo *attr = a;
3201 	if (attr) {
3202 		free (attr->name);
3203 		free (attr->metas);
3204 		free (attr);
3205 	}
3206 }
3207 
r_bin_java_local_variable_table_attr_entry_free(void * a)3208 R_API void r_bin_java_local_variable_table_attr_entry_free(void /*RBinJavaLocalVariableAttribute*/ *a) {
3209 	RBinJavaLocalVariableAttribute *lvattr = a;
3210 	if (lvattr) {
3211 		free (lvattr->descriptor);
3212 		free (lvattr->name);
3213 		free (lvattr);
3214 	}
3215 }
3216 
r_bin_java_local_variable_table_attr_free(void * a)3217 R_API void r_bin_java_local_variable_table_attr_free(void /*RBinJavaAttrInfo*/ *a) {
3218 	RBinJavaAttrInfo *attr = a;
3219 	if (attr) {
3220 		free (attr->name);
3221 		free (attr->metas);
3222 		r_list_free (attr->info.local_variable_table_attr.local_variable_table);
3223 		free (attr);
3224 	}
3225 }
3226 
r_bin_java_local_variable_type_table_attr_entry_free(void * a)3227 R_API void r_bin_java_local_variable_type_table_attr_entry_free(void /*RBinJavaLocalVariableTypeAttribute*/ *a) {
3228 	RBinJavaLocalVariableTypeAttribute *attr = a;
3229 	if (attr) {
3230 		free (attr->name);
3231 		free (attr->signature);
3232 		free (attr);
3233 	}
3234 }
3235 
r_bin_java_local_variable_type_table_attr_free(void * a)3236 R_API void r_bin_java_local_variable_type_table_attr_free(void /*RBinJavaAttrInfo*/ *a) {
3237 	RBinJavaAttrInfo *attr = a;
3238 	if (attr) {
3239 		free (attr->name);
3240 		free (attr->metas);
3241 		r_list_free (attr->info.local_variable_type_table_attr.local_variable_table);
3242 		free (attr);
3243 	}
3244 }
3245 
r_bin_java_deprecated_attr_free(void * a)3246 R_API void r_bin_java_deprecated_attr_free(void /*RBinJavaAttrInfo*/ *a) {
3247 	RBinJavaAttrInfo *attr = a;
3248 	if (attr) {
3249 		free (attr->name);
3250 		free (attr->metas);
3251 		free (attr);
3252 	}
3253 }
3254 
r_bin_java_enclosing_methods_attr_free(void * a)3255 R_API void r_bin_java_enclosing_methods_attr_free(void /*RBinJavaAttrInfo*/ *a) {
3256 	RBinJavaAttrInfo *attr = a;
3257 	if (attr) {
3258 		free (attr->name);
3259 		free (attr->metas);
3260 		free (attr->info.enclosing_method_attr.class_name);
3261 		free (attr->info.enclosing_method_attr.method_name);
3262 		free (attr->info.enclosing_method_attr.method_descriptor);
3263 		free (attr);
3264 	}
3265 }
3266 
r_bin_java_synthetic_attr_free(void * a)3267 R_API void r_bin_java_synthetic_attr_free(void /*RBinJavaAttrInfo*/ *a) {
3268 	RBinJavaAttrInfo *attr = a;
3269 	if (attr) {
3270 		free (attr->name);
3271 		free (attr->metas);
3272 		free (attr);
3273 	}
3274 }
3275 
r_bin_java_constant_value_attr_free(void * a)3276 R_API void r_bin_java_constant_value_attr_free(void /*RBinJavaAttrInfo*/ *a) {
3277 	RBinJavaAttrInfo *attr = a;
3278 	if (attr) {
3279 		free (attr->name);
3280 		free (attr->metas);
3281 		free (attr);
3282 	}
3283 }
3284 
r_bin_java_line_number_table_attr_free(void * a)3285 R_API void r_bin_java_line_number_table_attr_free(void /*RBinJavaAttrInfo*/ *a) {
3286 	RBinJavaAttrInfo *attr = a;
3287 	if (attr) {
3288 		free (attr->name);
3289 		free (attr->metas);
3290 		r_list_free (attr->info.line_number_table_attr.line_number_table);
3291 		free (attr);
3292 	}
3293 }
3294 
r_bin_java_code_attr_free(void * a)3295 R_API void r_bin_java_code_attr_free(void /*RBinJavaAttrInfo*/ *a) {
3296 	RBinJavaAttrInfo *attr = a;
3297 	if (attr) {
3298 		// XXX - Intentional memory leak here.  When one of the
3299 		// Code attributes is parsed, the code (the r_bin_java)
3300 		// is not properly parsing the class file
3301 		r_bin_java_stack_frame_free (attr->info.code_attr.implicit_frame);
3302 		r_list_free (attr->info.code_attr.attributes);
3303 		free (attr->info.code_attr.code);
3304 		r_list_free (attr->info.code_attr.exception_table);
3305 		free (attr->name);
3306 		free (attr->metas);
3307 		free (attr);
3308 	}
3309 }
3310 
r_bin_java_exceptions_attr_free(void * a)3311 R_API void r_bin_java_exceptions_attr_free(void /*RBinJavaAttrInfo*/ *a) {
3312 	RBinJavaAttrInfo *attr = a;
3313 	if (attr) {
3314 		free (attr->name);
3315 		free (attr->metas);
3316 		free (attr->info.exceptions_attr.exception_idx_table);
3317 		free (attr);
3318 	}
3319 }
3320 
r_bin_java_inner_classes_attr_entry_free(void * a)3321 R_API void r_bin_java_inner_classes_attr_entry_free(void /*RBinJavaClassesAttribute*/ *a) {
3322 	RBinJavaClassesAttribute *attr = a;
3323 	if (attr) {
3324 		free (attr->name);
3325 		free (attr->flags_str);
3326 		free (attr);
3327 	}
3328 }
3329 
r_bin_java_inner_classes_attr_free(void * a)3330 R_API void r_bin_java_inner_classes_attr_free(void /*RBinJavaAttrInfo*/ *a) {
3331 	RBinJavaAttrInfo *attr = a;
3332 	if (attr) {
3333 		free (attr->name);
3334 		free (attr->metas);
3335 		r_list_free (attr->info.inner_classes_attr.classes);
3336 		free (attr);
3337 	}
3338 }
3339 
r_bin_java_signature_attr_free(void * a)3340 R_API void r_bin_java_signature_attr_free(void /*RBinJavaAttrInfo*/ *a) {
3341 	RBinJavaAttrInfo *attr = a;
3342 	if (attr) {
3343 		free (attr->name);
3344 		free (attr->metas);
3345 		free (attr->info.signature_attr.signature);
3346 		free (attr);
3347 	}
3348 }
3349 
r_bin_java_source_debug_attr_free(void * a)3350 R_API void r_bin_java_source_debug_attr_free(void /*RBinJavaAttrInfo*/ *a) {
3351 	RBinJavaAttrInfo *attr = a;
3352 	if (attr) {
3353 		free (attr->name);
3354 		free (attr->metas);
3355 		free (attr->info.debug_extensions.debug_extension);
3356 		free (attr);
3357 	}
3358 }
3359 
r_bin_java_source_code_file_attr_free(void * a)3360 R_API void r_bin_java_source_code_file_attr_free(void /*RBinJavaAttrInfo*/ *a) {
3361 	RBinJavaAttrInfo *attr = a;
3362 	if (attr) {
3363 		free (attr->name);
3364 		free (attr->metas);
3365 		free (attr);
3366 	}
3367 }
3368 
r_bin_java_stack_map_table_attr_free(void * a)3369 R_API void r_bin_java_stack_map_table_attr_free(void /*RBinJavaAttrInfo*/ *a) {
3370 	RBinJavaAttrInfo *attr = a;
3371 	if (attr) {
3372 		free (attr->name);
3373 		free (attr->metas);
3374 		r_list_free (attr->info.stack_map_table_attr.stack_map_frame_entries);
3375 		free (attr);
3376 	}
3377 }
3378 
r_bin_java_stack_frame_free(void * o)3379 R_API void r_bin_java_stack_frame_free(void /*RBinJavaStackMapFrame*/ *o) {
3380 	RBinJavaStackMapFrame *obj = o;
3381 	if (obj) {
3382 		r_list_free (obj->local_items);
3383 		r_list_free (obj->stack_items);
3384 		free (obj->metas);
3385 		free (obj);
3386 	}
3387 }
3388 
r_bin_java_verification_info_free(void * o)3389 R_API void r_bin_java_verification_info_free(void /*RBinJavaVerificationObj*/ *o) {
3390 	RBinJavaVerificationObj *obj = o;
3391 	// eprintf ("Freeing verification object\n");
3392 	if (obj) {
3393 		free (obj->name);
3394 		free (obj);
3395 	}
3396 }
3397 
r_bin_java_interface_free(void * o)3398 R_API void r_bin_java_interface_free(void /*RBinJavaInterfaceInfo*/ *o) {
3399 	RBinJavaInterfaceInfo *obj = o;
3400 	if (obj) {
3401 		free (obj->name);
3402 		free (obj);
3403 	}
3404 }
3405 // End Free the various attribute types
3406 // Start the various attibute types new
r_bin_java_attr_calc_size(RBinJavaAttrInfo * attr)3407 R_API ut64 r_bin_java_attr_calc_size(RBinJavaAttrInfo *attr) {
3408 	return attr ? ((RBinJavaAttrMetas *) attr->metas->type_info)->allocs->calc_size (attr) : 0;
3409 }
3410 
r_bin_java_unknown_attr_calc_size(RBinJavaAttrInfo * attr)3411 R_API ut64 r_bin_java_unknown_attr_calc_size(RBinJavaAttrInfo *attr) {
3412 	return attr ? 6 : 0;
3413 }
3414 
r_bin_java_unknown_attr_new(RBinJavaObj * bin,ut8 * buffer,ut64 sz,ut64 buf_offset)3415 R_API RBinJavaAttrInfo *r_bin_java_unknown_attr_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz, ut64 buf_offset) {
3416 	return r_bin_java_default_attr_new (bin, buffer, sz, buf_offset);
3417 }
3418 
r_bin_java_code_attr_calc_size(RBinJavaAttrInfo * attr)3419 R_API ut64 r_bin_java_code_attr_calc_size(RBinJavaAttrInfo *attr) {
3420 	RListIter *iter;
3421 	// RListIter *iter_tmp;
3422 	ut64 size = 0;
3423 	bool is_attr_in_old_format = attr->is_attr_in_old_format;
3424 	if (attr) {
3425 		// attr = r_bin_java_default_attr_new (buffer, sz, buf_offset);
3426 		size += is_attr_in_old_format ? 4 : 6;
3427 		// attr->info.code_attr.max_stack = R_BIN_JAVA_USHORT (buffer, 0);
3428 		size += is_attr_in_old_format ? 1 : 2;
3429 		// attr->info.code_attr.max_locals = R_BIN_JAVA_USHORT (buffer, 2);
3430 		size += is_attr_in_old_format ? 1 : 2;
3431 		// attr->info.code_attr.code_length = R_BIN_JAVA_UINT (buffer, 4);
3432 		size += is_attr_in_old_format ? 2 : 4;
3433 		if (attr->info.code_attr.code) {
3434 			size += attr->info.code_attr.code_length;
3435 		}
3436 		// attr->info.code_attr.exception_table_length =  R_BIN_JAVA_USHORT (buffer, offset);
3437 		size += 2;
3438 		// RBinJavaExceptionEntry *exc_entry;
3439 		// r_list_foreach_safe (attr->info.code_attr.exception_table, iter, iter_tmp, exc_entry) {
3440 		r_list_foreach_iter (attr->info.code_attr.exception_table, iter) {
3441 			// exc_entry->start_pc = R_BIN_JAVA_USHORT (buffer,offset);
3442 			size += 2;
3443 			// exc_entry->end_pc = R_BIN_JAVA_USHORT (buffer,offset);
3444 			size += 2;
3445 			// exc_entry->handler_pc = R_BIN_JAVA_USHORT (buffer,offset);
3446 			size += 2;
3447 			// exc_entry->catch_type = R_BIN_JAVA_USHORT (buffer, offset);
3448 			size += 2;
3449 		}
3450 		// attr->info.code_attr.attributes_count = R_BIN_JAVA_USHORT (buffer, offset);
3451 		size += 2;
3452 		// RBinJavaAttrInfo *_attr;
3453 		if (attr->info.code_attr.attributes_count > 0) {
3454 			// r_list_foreach_safe (attr->info.code_attr.attributes, iter, iter_tmp, _attr) {
3455 			r_list_foreach_iter (attr->info.code_attr.attributes, iter) {
3456 				size += r_bin_java_attr_calc_size (attr);
3457 			}
3458 		}
3459 	}
3460 	return size;
3461 }
3462 
r_bin_java_code_attr_new(RBinJavaObj * bin,ut8 * buffer,ut64 sz,ut64 buf_offset)3463 R_API RBinJavaAttrInfo *r_bin_java_code_attr_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz, ut64 buf_offset) {
3464 	RBinJavaAttrInfo *attr = NULL, *_attr = NULL;
3465 	ut32 k = 0, curpos;
3466 	ut64 offset = 0;
3467 	attr = r_bin_java_default_attr_new (bin, buffer, sz, buf_offset);
3468 	if (!attr) {
3469 		return NULL;
3470 	}
3471 	if (sz < 16 || sz > buf_offset) {// sz > buf_offset) {
3472 		free (attr);
3473 		return NULL;
3474 	}
3475 	offset += 6;
3476 	attr->type = R_BIN_JAVA_ATTR_TYPE_CODE_ATTR;
3477 	attr->info.code_attr.max_stack = attr->is_attr_in_old_format ? buffer[offset] : R_BIN_JAVA_USHORT (buffer, offset);
3478 	offset += attr->is_attr_in_old_format ? 1 : 2;
3479 	attr->info.code_attr.max_locals = attr->is_attr_in_old_format ? buffer[offset] : R_BIN_JAVA_USHORT (buffer, offset);
3480 	offset += attr->is_attr_in_old_format ? 1 : 2;
3481 	attr->info.code_attr.code_length = attr->is_attr_in_old_format ? R_BIN_JAVA_USHORT(buffer, offset) : R_BIN_JAVA_UINT (buffer, offset);
3482 	offset += attr->is_attr_in_old_format ? 2 : 4;
3483 	// BUG: possible unsigned integer overflow here
3484 	attr->info.code_attr.code_offset = buf_offset + offset;
3485 	attr->info.code_attr.code = (ut8 *) malloc (attr->info.code_attr.code_length);
3486 	if (!attr->info.code_attr.code) {
3487 		eprintf ("Handling Code Attributes: Unable to allocate memory "
3488 			"(%u bytes) for a code.\n", attr->info.code_attr.code_length);
3489 		return attr;
3490 	}
3491 	R_BIN_JAVA_GLOBAL_BIN->current_code_attr = attr;
3492 	{
3493 		int len = attr->info.code_attr.code_length;
3494 		memset (attr->info.code_attr.code, 0, len);
3495 		if (offset + len >= sz) {
3496 			return attr;
3497 		}
3498 		memcpy (attr->info.code_attr.code, buffer + offset, len);
3499 		offset += len;
3500 	}
3501 	attr->info.code_attr.exception_table_length = R_BIN_JAVA_USHORT (buffer, offset);
3502 	offset += 2;
3503 	attr->info.code_attr.exception_table = r_list_newf (free);
3504 	for (k = 0; k < attr->info.code_attr.exception_table_length; k++) {
3505 		curpos = buf_offset + offset;
3506 		if (curpos + 8 > sz) {
3507 			return attr;
3508 		}
3509 		RBinJavaExceptionEntry *e = R_NEW0 (RBinJavaExceptionEntry);
3510 		if (!e) {
3511 			free (attr);
3512 			return NULL;
3513 		}
3514 		e->file_offset = curpos;
3515 		e->start_pc = R_BIN_JAVA_USHORT (buffer, offset);
3516 		offset += 2;
3517 		e->end_pc = R_BIN_JAVA_USHORT (buffer, offset);
3518 		offset += 2;
3519 		e->handler_pc = R_BIN_JAVA_USHORT (buffer, offset);
3520 		offset += 2;
3521 		e->catch_type = R_BIN_JAVA_USHORT (buffer, offset);
3522 		offset += 2;
3523 		r_list_append (attr->info.code_attr.exception_table, e);
3524 		e->size = 8;
3525 	}
3526 	attr->info.code_attr.attributes_count = R_BIN_JAVA_USHORT (buffer, offset);
3527 	offset += 2;
3528 	// IFDBG eprintf ("	code Attributes_count: %d\n", attr->info.code_attr.attributes_count);
3529 	// XXX - attr->info.code_attr.attributes is not freed because one of the code attributes is improperly parsed.
3530 	attr->info.code_attr.attributes = r_list_newf (r_bin_java_attribute_free);
3531 	if (attr->info.code_attr.attributes_count > 0) {
3532 		for (k = 0; k < attr->info.code_attr.attributes_count; k++) {
3533 			int size = (offset < sz) ? sz - offset : 0;
3534 			if (size > sz || size <= 0) {
3535 				break;
3536 			}
3537 			_attr = r_bin_java_read_next_attr_from_buffer (bin, buffer + offset, size, buf_offset + offset);
3538 			if (!_attr) {
3539 				eprintf ("[X] r_bin_java_code_attr_new: Error unable to parse remainder of classfile after Method's Code Attribute: %d.\n", k);
3540 				break;
3541 			}
3542 			IFDBG eprintf("Parsing @ 0x%"PFMT64x " (%s) = 0x%"PFMT64x " bytes, %p\n", _attr->file_offset, _attr->name, _attr->size, _attr);
3543 			offset += _attr->size;
3544 			r_list_append (attr->info.code_attr.attributes, _attr);
3545 			if (_attr->type == R_BIN_JAVA_ATTR_TYPE_LOCAL_VARIABLE_TABLE_ATTR) {
3546 				IFDBG eprintf("Parsed the LocalVariableTable, preparing the implicit mthod frame.\n");
3547 				// r_bin_java_print_attr_summary(_attr);
3548 				attr->info.code_attr.implicit_frame = r_bin_java_build_stack_frame_from_local_variable_table (R_BIN_JAVA_GLOBAL_BIN, _attr);
3549 				attr->info.code_attr.implicit_frame->file_offset = buf_offset;
3550 				IFDBG r_bin_java_print_stack_map_frame_summary(attr->info.code_attr.implicit_frame);
3551 				// r_list_append (attr->info.code_attr.attributes, attr->info.code_attr.implicit_frame);
3552 			}
3553 			// if (offset > sz) {
3554 			// eprintf ("[X] r_bin_java: Error unable to parse remainder of classfile after Attribute: %d.\n", k);
3555 			// break;
3556 			// }
3557 
3558 		}
3559 	}
3560 	if (attr->info.code_attr.implicit_frame == NULL) {
3561 		// build a default implicit_frame
3562 		attr->info.code_attr.implicit_frame = r_bin_java_default_stack_frame ();
3563 		// r_list_append (attr->info.code_attr.attributes, attr->info.code_attr.implicit_frame);
3564 	}
3565 	attr->size = offset;
3566 	return attr;
3567 }
3568 
r_bin_java_constant_value_attr_new(RBinJavaObj * bin,ut8 * buffer,ut64 sz,ut64 buf_offset)3569 R_API RBinJavaAttrInfo *r_bin_java_constant_value_attr_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz, ut64 buf_offset) {
3570 	ut64 offset = 6;
3571 	RBinJavaAttrInfo *attr = r_bin_java_default_attr_new (bin, buffer, sz, buf_offset);
3572 	if (attr) {
3573 		attr->type = R_BIN_JAVA_ATTR_TYPE_CONST_VALUE_ATTR;
3574 		attr->info.constant_value_attr.constantvalue_idx = R_BIN_JAVA_USHORT (buffer, offset);
3575 		offset += 2;
3576 		attr->size = offset;
3577 	}
3578 	// IFDBG r_bin_java_print_constant_value_attr_summary(attr);
3579 	return attr;
3580 }
3581 
r_bin_java_constant_value_attr_calc_size(RBinJavaAttrInfo * attr)3582 R_API ut64 r_bin_java_constant_value_attr_calc_size(RBinJavaAttrInfo *attr) {
3583 	return attr ? 8 : 0;
3584 }
3585 
r_bin_java_deprecated_attr_new(RBinJavaObj * bin,ut8 * buffer,ut64 sz,ut64 buf_offset)3586 R_API RBinJavaAttrInfo *r_bin_java_deprecated_attr_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz, ut64 buf_offset) {
3587 	RBinJavaAttrInfo *attr = NULL;
3588 	ut64 offset = 0;
3589 	attr = r_bin_java_default_attr_new (bin, buffer, sz, buf_offset);
3590 	offset += 6;
3591 	if (attr) {
3592 		attr->type = R_BIN_JAVA_ATTR_TYPE_DEPRECATED_ATTR;
3593 		attr->size = offset;
3594 	}
3595 	// IFDBG r_bin_java_print_deprecated_attr_summary(attr);
3596 	return attr;
3597 }
3598 
r_bin_java_deprecated_attr_calc_size(RBinJavaAttrInfo * attr)3599 R_API ut64 r_bin_java_deprecated_attr_calc_size(RBinJavaAttrInfo *attr) {
3600 	return attr ? 6 : 0;
3601 }
3602 
r_bin_java_signature_attr_new(RBinJavaObj * bin,ut8 * buffer,ut64 sz,ut64 buf_offset)3603 R_API RBinJavaAttrInfo *r_bin_java_signature_attr_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz, ut64 buf_offset) {
3604 	ut64 offset = 6;
3605 	RBinJavaAttrInfo *attr = r_bin_java_default_attr_new (bin, buffer, sz, buf_offset);
3606 	if (!attr) {
3607 		return NULL;
3608 	}
3609 	attr->type = R_BIN_JAVA_ATTR_TYPE_SIGNATURE_ATTR;
3610 	// attr->info.source_file_attr.sourcefile_idx = R_BIN_JAVA_USHORT (buffer, offset);
3611 	// offset += 2;
3612 	attr->info.signature_attr.signature_idx = R_BIN_JAVA_USHORT (buffer, offset);
3613 	offset += 2;
3614 	attr->info.signature_attr.signature = r_bin_java_get_utf8_from_bin_cp_list (
3615 		R_BIN_JAVA_GLOBAL_BIN, attr->info.signature_attr.signature_idx);
3616 	if (!attr->info.signature_attr.signature) {
3617 		eprintf ("r_bin_java_signature_attr_new: Unable to resolve the "
3618 			"Signature UTF8 String Index: 0x%02x\n", attr->info.signature_attr.signature_idx);
3619 	}
3620 	attr->size = offset;
3621 	// IFDBG r_bin_java_print_source_code_file_attr_summary(attr);
3622 	return attr;
3623 }
3624 
r_bin_java_signature_attr_calc_size(RBinJavaAttrInfo * attr)3625 R_API ut64 r_bin_java_signature_attr_calc_size(RBinJavaAttrInfo *attr) {
3626 	ut64 size = 0;
3627 	if (attr == NULL) {
3628 		// TODO eprintf allocation fail
3629 		return size;
3630 	}
3631 	size += 6;
3632 	// attr->info.source_file_attr.sourcefile_idx = R_BIN_JAVA_USHORT (buffer, offset);
3633 	size += 2;
3634 	// attr->info.signature_attr.signature_idx = R_BIN_JAVA_USHORT (buffer, offset);
3635 	size += 2;
3636 	return size;
3637 }
3638 
r_bin_java_enclosing_methods_attr_new(RBinJavaObj * bin,ut8 * buffer,ut64 sz,ut64 buf_offset)3639 R_API RBinJavaAttrInfo *r_bin_java_enclosing_methods_attr_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz, ut64 buf_offset) {
3640 	ut64 offset = 6;
3641 	RBinJavaAttrInfo *attr = r_bin_java_default_attr_new (bin, buffer, sz, buf_offset);
3642 	if (!attr || sz < 10) {
3643 		free (attr);
3644 		return NULL;
3645 	}
3646 	attr->type = R_BIN_JAVA_ATTR_TYPE_ENCLOSING_METHOD_ATTR;
3647 	attr->info.enclosing_method_attr.class_idx = R_BIN_JAVA_USHORT (buffer, offset);
3648 	offset += 2;
3649 	attr->info.enclosing_method_attr.method_idx = R_BIN_JAVA_USHORT (buffer, offset);
3650 	offset += 2;
3651 	attr->info.enclosing_method_attr.class_name = r_bin_java_get_name_from_bin_cp_list (R_BIN_JAVA_GLOBAL_BIN, attr->info.enclosing_method_attr.class_idx);
3652 	if (attr->info.enclosing_method_attr.class_name == NULL) {
3653 		eprintf ("Could not resolve enclosing class name for the enclosed method.\n");
3654 	}
3655 	attr->info.enclosing_method_attr.method_name = r_bin_java_get_name_from_bin_cp_list (R_BIN_JAVA_GLOBAL_BIN, attr->info.enclosing_method_attr.method_idx);
3656 	if (attr->info.enclosing_method_attr.class_name == NULL) {
3657 		eprintf ("Could not resolve method descriptor for the enclosed method.\n");
3658 	}
3659 	attr->info.enclosing_method_attr.method_descriptor = r_bin_java_get_desc_from_bin_cp_list (R_BIN_JAVA_GLOBAL_BIN, attr->info.enclosing_method_attr.method_idx);
3660 	if (attr->info.enclosing_method_attr.method_name == NULL) {
3661 		eprintf ("Could not resolve method name for the enclosed method.\n");
3662 	}
3663 	attr->size = offset;
3664 	return attr;
3665 }
3666 
r_bin_java_enclosing_methods_attr_calc_size(RBinJavaAttrInfo * attr)3667 R_API ut64 r_bin_java_enclosing_methods_attr_calc_size(RBinJavaAttrInfo *attr) {
3668 	ut64 size = 0;
3669 	if (attr) {
3670 		size += 6;
3671 		// attr->info.enclosing_method_attr.class_idx = R_BIN_JAVA_USHORT (buffer, offset);
3672 		size += 2;
3673 		// attr->info.enclosing_method_attr.method_idx = R_BIN_JAVA_USHORT (buffer, offset);
3674 		size += 2;
3675 	}
3676 	return size;
3677 }
3678 
r_bin_java_exceptions_attr_new(RBinJavaObj * bin,ut8 * buffer,ut64 sz,ut64 buf_offset)3679 R_API RBinJavaAttrInfo *r_bin_java_exceptions_attr_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz, ut64 buf_offset) {
3680 	ut32 i = 0, offset = 0;
3681 	ut64 size;
3682 	RBinJavaAttrInfo *attr = NULL;
3683 	if (sz < 8) {
3684 		return NULL;
3685 	}
3686 	attr = r_bin_java_default_attr_new (bin, buffer, sz, buf_offset);
3687 	offset += 6;
3688 	if (!attr) {
3689 		return attr;
3690 	}
3691 	attr->type = R_BIN_JAVA_ATTR_TYPE_LINE_NUMBER_TABLE_ATTR;
3692 	attr->info.exceptions_attr.number_of_exceptions = R_BIN_JAVA_USHORT (buffer, offset);
3693 	offset += 2;
3694 	size = sizeof (ut16) * attr->info.exceptions_attr.number_of_exceptions;
3695 	if (size < attr->info.exceptions_attr.number_of_exceptions) {
3696 		free (attr);
3697 		return NULL;
3698 	}
3699 	attr->info.exceptions_attr.exception_idx_table = (ut16 *) malloc (size);
3700 	if (!attr->info.exceptions_attr.exception_idx_table) {
3701 		free (attr);
3702 		return NULL;
3703 	}
3704 	for (i = 0; i < attr->info.exceptions_attr.number_of_exceptions; i++) {
3705 		if (offset + 2 > sz) {
3706 			break;
3707 		}
3708 		attr->info.exceptions_attr.exception_idx_table[i] = R_BIN_JAVA_USHORT (buffer, offset);
3709 		offset += 2;
3710 	}
3711 	attr->size = offset;
3712 	// IFDBG r_bin_java_print_exceptions_attr_summary(attr);
3713 	return attr;
3714 }
3715 
r_bin_java_exceptions_attr_calc_size(RBinJavaAttrInfo * attr)3716 R_API ut64 r_bin_java_exceptions_attr_calc_size(RBinJavaAttrInfo *attr) {
3717 	ut64 size = 0, i = 0;
3718 	if (attr) {
3719 		size += 6;
3720 		for (i = 0; i < attr->info.exceptions_attr.number_of_exceptions; i++) {
3721 			// attr->info.exceptions_attr.exception_idx_table[i] = R_BIN_JAVA_USHORT (buffer, offset);
3722 			size += 2;
3723 		}
3724 	}
3725 	return size;
3726 }
3727 
r_bin_java_inner_classes_attr_new(RBinJavaObj * bin,ut8 * buffer,ut64 sz,ut64 buf_offset)3728 R_API RBinJavaAttrInfo *r_bin_java_inner_classes_attr_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz, ut64 buf_offset) {
3729 	RBinJavaClassesAttribute *icattr;
3730 	RBinJavaAttrInfo *attr = NULL;
3731 	RBinJavaCPTypeObj *obj;
3732 	ut32 i = 0;
3733 	ut64 offset = 0, curpos;
3734 	attr = r_bin_java_default_attr_new (bin, buffer, sz, buf_offset);
3735 	offset += 6;
3736 	if (attr == NULL) {
3737 		// TODO eprintf
3738 		return attr;
3739 	}
3740 	attr->type = R_BIN_JAVA_ATTR_TYPE_INNER_CLASSES_ATTR;
3741 	attr->info.inner_classes_attr.number_of_classes = R_BIN_JAVA_USHORT (buffer, offset);
3742 	offset += 2;
3743 	attr->info.inner_classes_attr.classes = r_list_newf (r_bin_java_inner_classes_attr_entry_free);
3744 	for (i = 0; i < attr->info.inner_classes_attr.number_of_classes; i++) {
3745 		curpos = buf_offset + offset;
3746 		if (offset + 8 > sz) {
3747 			eprintf ("Invalid amount of inner classes\n");
3748 			break;
3749 		}
3750 		icattr = R_NEW0 (RBinJavaClassesAttribute);
3751 		if (!icattr) {
3752 			break;
3753 		}
3754 		icattr->inner_class_info_idx = R_BIN_JAVA_USHORT (buffer, offset);
3755 		offset += 2;
3756 		icattr->outer_class_info_idx = R_BIN_JAVA_USHORT (buffer, offset);
3757 		offset += 2;
3758 		icattr->inner_name_idx = R_BIN_JAVA_USHORT (buffer, offset);
3759 		offset += 2;
3760 		icattr->inner_class_access_flags = R_BIN_JAVA_USHORT (buffer, offset);
3761 		offset += 2;
3762 		icattr->flags_str = retrieve_class_method_access_string (icattr->inner_class_access_flags);
3763 		icattr->file_offset = curpos;
3764 		icattr->size = 8;
3765 
3766 		obj = r_bin_java_get_item_from_bin_cp_list (R_BIN_JAVA_GLOBAL_BIN, icattr->inner_name_idx);
3767 		if (obj == NULL) {
3768 			eprintf ("BINCPLIS IS HULL %d\n", icattr->inner_name_idx);
3769 		}
3770 		icattr->name = r_bin_java_get_item_name_from_bin_cp_list (R_BIN_JAVA_GLOBAL_BIN, obj);
3771 		if (!icattr->name) {
3772 			obj = r_bin_java_get_item_from_bin_cp_list (R_BIN_JAVA_GLOBAL_BIN, icattr->inner_class_info_idx);
3773 			if (!obj) {
3774 				eprintf ("BINCPLIST IS NULL %d\n", icattr->inner_class_info_idx);
3775 			}
3776 			icattr->name = r_bin_java_get_item_name_from_bin_cp_list (R_BIN_JAVA_GLOBAL_BIN, obj);
3777 			if (!icattr->name) {
3778 				icattr->name = r_str_dup (NULL, "NULL");
3779 				eprintf ("r_bin_java_inner_classes_attr: Unable to find the name for %d index.\n", icattr->inner_name_idx);
3780 				free (icattr);
3781 				break;
3782 			}
3783 		}
3784 
3785 		IFDBG eprintf("r_bin_java_inner_classes_attr: Inner class name %d is %s.\n", icattr->inner_name_idx, icattr->name);
3786 		r_list_append (attr->info.inner_classes_attr.classes, (void *) icattr);
3787 	}
3788 	attr->size = offset;
3789 	// IFDBG r_bin_java_print_inner_classes_attr_summary(attr);
3790 	return attr;
3791 }
3792 
r_bin_java_inner_class_attr_calc_size(RBinJavaClassesAttribute * icattr)3793 R_API ut64 r_bin_java_inner_class_attr_calc_size(RBinJavaClassesAttribute *icattr) {
3794 	ut64 size = 0;
3795 	if (icattr) {
3796 		// icattr->inner_class_info_idx = R_BIN_JAVA_USHORT (buffer, offset);
3797 		size += 2;
3798 		// icattr->outer_class_info_idx = R_BIN_JAVA_USHORT (buffer, offset);
3799 		size += 2;
3800 		// icattr->inner_name_idx = R_BIN_JAVA_USHORT (buffer, offset);
3801 		size += 2;
3802 		// icattr->inner_class_access_flags = R_BIN_JAVA_USHORT (buffer, offset);
3803 		size += 2;
3804 	}
3805 	return size;
3806 }
3807 
r_bin_java_inner_classes_attr_calc_size(RBinJavaAttrInfo * attr)3808 R_API ut64 r_bin_java_inner_classes_attr_calc_size(RBinJavaAttrInfo *attr) {
3809 	RBinJavaClassesAttribute *icattr = NULL;
3810 	RListIter *iter;
3811 	ut64 size = 6;
3812 	if (!attr) {
3813 		return 0;
3814 	}
3815 	r_list_foreach (attr->info.inner_classes_attr.classes, iter, icattr) {
3816 		size += r_bin_java_inner_class_attr_calc_size (icattr);
3817 	}
3818 	return size;
3819 }
3820 
r_bin_java_line_number_table_attr_new(RBinJavaObj * bin,ut8 * buffer,ut64 sz,ut64 buf_offset)3821 R_API RBinJavaAttrInfo *r_bin_java_line_number_table_attr_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz, ut64 buf_offset) {
3822 	ut32 i = 0;
3823 	ut64 curpos, offset = 0;
3824 	RBinJavaLineNumberAttribute *lnattr;
3825 	if (sz < 6) {
3826 		return NULL;
3827 	}
3828 	RBinJavaAttrInfo *attr = r_bin_java_default_attr_new (bin, buffer, sz, buf_offset);
3829 	if (!attr) {
3830 		return NULL;
3831 	}
3832 	offset += 6;
3833 	attr->type = R_BIN_JAVA_ATTR_TYPE_LINE_NUMBER_TABLE_ATTR;
3834 	attr->info.line_number_table_attr.line_number_table_length = R_BIN_JAVA_USHORT (buffer, offset);
3835 	offset += 2;
3836 	attr->info.line_number_table_attr.line_number_table = r_list_newf (free);
3837 
3838 	ut32 linenum_len = attr->info.line_number_table_attr.line_number_table_length;
3839 	RList *linenum_list = attr->info.line_number_table_attr.line_number_table;
3840 	for (i = 0; i < linenum_len; i++) {
3841 		curpos = buf_offset + offset;
3842 		// printf ("%llx %llx \n", curpos, sz);
3843 		// XXX if (curpos + 8 >= sz) break;
3844 		lnattr = R_NEW0 (RBinJavaLineNumberAttribute);
3845 		if (!lnattr) {
3846 			break;
3847 		}
3848 		// wtf it works
3849 		if (offset - 2 > sz) {
3850 			R_FREE (lnattr);
3851 			break;
3852 		}
3853 		lnattr->start_pc = R_BIN_JAVA_USHORT (buffer, offset);
3854 		offset += 2;
3855 		lnattr->line_number = R_BIN_JAVA_USHORT (buffer, offset);
3856 		offset += 2;
3857 		lnattr->file_offset = curpos;
3858 		lnattr->size = 4;
3859 		r_list_append (linenum_list, lnattr);
3860 	}
3861 	attr->size = offset;
3862 	return attr;
3863 }
3864 
r_bin_java_line_number_table_attr_calc_size(RBinJavaAttrInfo * attr)3865 R_API ut64 r_bin_java_line_number_table_attr_calc_size(RBinJavaAttrInfo *attr) {
3866 	ut64 size = 6;
3867 	// RBinJavaLineNumberAttribute *lnattr;
3868 	RListIter *iter;
3869 	// RListIter *iter_tmp;
3870 	if (!attr) {
3871 		return 0LL;
3872 	}
3873 	// r_list_foreach_safe (attr->info.line_number_table_attr.line_number_table, iter, iter_tmp, lnattr) {
3874 	r_list_foreach_iter (attr->info.line_number_table_attr.line_number_table, iter) {
3875 		// lnattr->start_pc = R_BIN_JAVA_USHORT (buffer, offset);
3876 		size += 2;
3877 		// lnattr->line_number = R_BIN_JAVA_USHORT (buffer, offset);
3878 		size += 2;
3879 	}
3880 	return size;
3881 }
3882 
r_bin_java_source_debug_attr_new(RBinJavaObj * bin,ut8 * buffer,ut64 sz,ut64 buf_offset)3883 R_API RBinJavaAttrInfo *r_bin_java_source_debug_attr_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz, ut64 buf_offset) {
3884 	ut64 offset = 6;
3885 	RBinJavaAttrInfo *attr = r_bin_java_default_attr_new (bin, buffer, sz, buf_offset);
3886 	if (!attr) {
3887 		return NULL;
3888 	}
3889 	attr->type = R_BIN_JAVA_ATTR_TYPE_SOURCE_DEBUG_EXTENTSION_ATTR;
3890 	if (attr->length == 0) {
3891 		eprintf ("r_bin_java_source_debug_attr_new: Attempting to allocate 0 bytes for debug_extension.\n");
3892 		attr->info.debug_extensions.debug_extension = NULL;
3893 		return attr;
3894 	} else if ((attr->length + offset) > sz) {
3895 		eprintf ("r_bin_java_source_debug_attr_new: Expected %d byte(s) got %"
3896 			PFMT64d " bytes for debug_extension.\n", attr->length, (offset + sz));
3897 	}
3898 	attr->info.debug_extensions.debug_extension = (ut8 *) malloc (attr->length);
3899 	if (attr->info.debug_extensions.debug_extension && (attr->length > (sz - offset))) {
3900 		memcpy (attr->info.debug_extensions.debug_extension, buffer + offset, sz - offset);
3901 	} else if (attr->info.debug_extensions.debug_extension) {
3902 		memcpy (attr->info.debug_extensions.debug_extension, buffer + offset, attr->length);
3903 	} else {
3904 		eprintf ("r_bin_java_source_debug_attr_new: Unable to allocate the data for the debug_extension.\n");
3905 	}
3906 	offset += attr->length;
3907 	attr->size = offset;
3908 	return attr;
3909 }
3910 
r_bin_java_source_debug_attr_calc_size(RBinJavaAttrInfo * attr)3911 R_API ut64 r_bin_java_source_debug_attr_calc_size(RBinJavaAttrInfo *attr) {
3912 	ut64 size = 6;
3913 	if (!attr) {
3914 		return 0LL;
3915 	}
3916 	if (attr->info.debug_extensions.debug_extension) {
3917 		size += attr->length;
3918 	}
3919 	return size;
3920 }
3921 
r_bin_java_local_variable_table_attr_calc_size(RBinJavaAttrInfo * attr)3922 R_API ut64 r_bin_java_local_variable_table_attr_calc_size(RBinJavaAttrInfo *attr) {
3923 	ut64 size = 0;
3924 	// ut64 offset = 0;
3925 	RListIter *iter;
3926 	// RBinJavaLocalVariableAttribute *lvattr;
3927 	if (!attr) {
3928 		return 0LL;
3929 	}
3930 	size += 6;
3931 	// attr->info.local_variable_table_attr.table_length = R_BIN_JAVA_USHORT (buffer, offset);
3932 	size += 2;
3933 	// r_list_foreach (attr->info.local_variable_table_attr.local_variable_table, iter, lvattr) {
3934 	r_list_foreach_iter (attr->info.local_variable_table_attr.local_variable_table, iter) {
3935 		// lvattr->start_pc = R_BIN_JAVA_USHORT (buffer, offset);
3936 		size += 2;
3937 		// lvattr->length = R_BIN_JAVA_USHORT (buffer, offset);
3938 		size += 2;
3939 		// lvattr->name_idx = R_BIN_JAVA_USHORT (buffer, offset);
3940 		size += 2;
3941 		// lvattr->descriptor_idx = R_BIN_JAVA_USHORT (buffer, offset);
3942 		size += 2;
3943 		// lvattr->index = R_BIN_JAVA_USHORT (buffer, offset);
3944 		size += 2;
3945 	}
3946 	return size;
3947 }
3948 
r_bin_java_local_variable_table_attr_new(RBinJavaObj * bin,ut8 * buffer,ut64 sz,ut64 buf_offset)3949 R_API RBinJavaAttrInfo *r_bin_java_local_variable_table_attr_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz, ut64 buf_offset) {
3950 	RBinJavaLocalVariableAttribute *lvattr;
3951 	ut64 curpos = 0, offset = 6;
3952 	RBinJavaAttrInfo *attr;
3953 	ut32 i = 0;
3954 	if (!buffer || sz < 1) {
3955 		return NULL;
3956 	}
3957 	attr = r_bin_java_default_attr_new (bin, buffer, sz, buf_offset);
3958 	if (!attr) {
3959 		return NULL;
3960 	}
3961 	attr->type = R_BIN_JAVA_ATTR_TYPE_LOCAL_VARIABLE_TABLE_ATTR;
3962 	attr->info.local_variable_table_attr.table_length = R_BIN_JAVA_USHORT (buffer, offset);
3963 	offset += 2;
3964 	attr->info.local_variable_table_attr.local_variable_table =\
3965 		r_list_newf (r_bin_java_local_variable_table_attr_entry_free);
3966 	for (i = 0; i < attr->info.local_variable_table_attr.table_length; i++) {
3967 		if (offset + 10 > sz) {
3968 			break;
3969 		}
3970 		curpos = buf_offset + offset;
3971 		lvattr = R_NEW0 (RBinJavaLocalVariableAttribute);
3972 		lvattr->start_pc = R_BIN_JAVA_USHORT (buffer, offset);
3973 		offset += 2;
3974 		lvattr->length = R_BIN_JAVA_USHORT (buffer, offset);
3975 		offset += 2;
3976 		lvattr->name_idx = R_BIN_JAVA_USHORT (buffer, offset);
3977 		offset += 2;
3978 		lvattr->descriptor_idx = R_BIN_JAVA_USHORT (buffer, offset);
3979 		offset += 2;
3980 		lvattr->index = R_BIN_JAVA_USHORT (buffer, offset);
3981 		offset += 2;
3982 		lvattr->file_offset = curpos;
3983 		lvattr->name = r_bin_java_get_utf8_from_bin_cp_list (R_BIN_JAVA_GLOBAL_BIN, lvattr->name_idx);
3984 		lvattr->size = 10;
3985 		if (!lvattr->name) {
3986 			lvattr->name = strdup ("NULL");
3987 			eprintf ("r_bin_java_local_variable_table_attr_new: Unable to find the name for %d index.\n", lvattr->name_idx);
3988 		}
3989 		lvattr->descriptor = r_bin_java_get_utf8_from_bin_cp_list (R_BIN_JAVA_GLOBAL_BIN, lvattr->descriptor_idx);
3990 		if (!lvattr->descriptor) {
3991 			lvattr->descriptor = strdup ("NULL");
3992 			eprintf ("r_bin_java_local_variable_table_attr_new: Unable to find the descriptor for %d index.\n", lvattr->descriptor_idx);
3993 		}
3994 		r_list_append (attr->info.local_variable_table_attr.local_variable_table, lvattr);
3995 	}
3996 	attr->size = offset;
3997 	// IFDBG r_bin_java_print_local_variable_table_attr_summary(attr);
3998 	return attr;
3999 }
4000 
r_bin_java_local_variable_type_table_attr_calc_size(RBinJavaAttrInfo * attr)4001 R_API ut64 r_bin_java_local_variable_type_table_attr_calc_size(RBinJavaAttrInfo *attr) {
4002 	// RBinJavaLocalVariableTypeAttribute *lvattr;
4003 	RListIter *iter;
4004 	ut64 size = 0;
4005 	if (attr) {
4006 		RList *list = attr->info.local_variable_type_table_attr.local_variable_table;
4007 		size += 6;
4008 		// attr->info.local_variable_type_table_attr.table_length = R_BIN_JAVA_USHORT (buffer, offset);
4009 		size += 2;
4010 		// r_list_foreach (list, iter, lvattr) {
4011 		r_list_foreach_iter (list, iter) {
4012 			// lvattr->start_pc = R_BIN_JAVA_USHORT (buffer, offset);
4013 			size += 2;
4014 			// lvattr->length = R_BIN_JAVA_USHORT (buffer, offset);
4015 			size += 2;
4016 			// lvattr->name_idx = R_BIN_JAVA_USHORT (buffer, offset);
4017 			size += 2;
4018 			// lvattr->signature_idx = R_BIN_JAVA_USHORT (buffer, offset);
4019 			size += 2;
4020 			// lvattr->index = R_BIN_JAVA_USHORT (buffer, offset);
4021 			size += 2;
4022 		}
4023 	}
4024 	return size;
4025 }
4026 
r_bin_java_local_variable_type_table_attr_new(RBinJavaObj * bin,ut8 * buffer,ut64 sz,ut64 buf_offset)4027 R_API RBinJavaAttrInfo *r_bin_java_local_variable_type_table_attr_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz, ut64 buf_offset) {
4028 	RBinJavaLocalVariableTypeAttribute *lvattr;
4029 	ut64 offset = 6;
4030 	ut32 i = 0;
4031 	RBinJavaAttrInfo *attr = r_bin_java_default_attr_new (bin, buffer, sz, 0);
4032 	if (!attr) {
4033 		return NULL;
4034 	}
4035 	attr->type = R_BIN_JAVA_ATTR_TYPE_LOCAL_VARIABLE_TYPE_TABLE_ATTR;
4036 	attr->info.local_variable_type_table_attr.table_length = R_BIN_JAVA_USHORT (buffer, offset);
4037 	offset += 2;
4038 	attr->info.local_variable_type_table_attr.local_variable_table = r_list_newf (r_bin_java_local_variable_type_table_attr_entry_free);
4039 	for (i = 0; i < attr->info.local_variable_type_table_attr.table_length; i++) {
4040 		ut64 curpos = buf_offset + offset;
4041 		lvattr = R_NEW0 (RBinJavaLocalVariableTypeAttribute);
4042 		if (!lvattr) {
4043 			perror ("calloc");
4044 			break;
4045 		}
4046 		if (offset + 10 > sz) {
4047 			eprintf ("oob");
4048 			free (lvattr);
4049 			break;
4050 		}
4051 		lvattr->start_pc = R_BIN_JAVA_USHORT (buffer, offset);
4052 		offset += 2;
4053 		lvattr->length = R_BIN_JAVA_USHORT (buffer, offset);
4054 		offset += 2;
4055 		lvattr->name_idx = R_BIN_JAVA_USHORT (buffer, offset);
4056 		offset += 2;
4057 		lvattr->signature_idx = R_BIN_JAVA_USHORT (buffer, offset);
4058 		offset += 2;
4059 		lvattr->index = R_BIN_JAVA_USHORT (buffer, offset);
4060 		offset += 2;
4061 		lvattr->file_offset = curpos;
4062 		lvattr->name = r_bin_java_get_utf8_from_bin_cp_list (R_BIN_JAVA_GLOBAL_BIN, lvattr->name_idx);
4063 		lvattr->size = 10;
4064 		if (!lvattr->name) {
4065 			lvattr->name = strdup ("NULL");
4066 			eprintf ("r_bin_java_local_variable_type_table_attr_new: Unable to find the name for %d index.\n", lvattr->name_idx);
4067 		}
4068 		lvattr->signature = r_bin_java_get_utf8_from_bin_cp_list (R_BIN_JAVA_GLOBAL_BIN, lvattr->signature_idx);
4069 		if (!lvattr->signature) {
4070 			lvattr->signature = strdup ("NULL");
4071 			eprintf ("r_bin_java_local_variable_type_table_attr_new: Unable to find the descriptor for %d index.\n", lvattr->signature_idx);
4072 		}
4073 		r_list_append (attr->info.local_variable_type_table_attr.local_variable_table, lvattr);
4074 	}
4075 	// IFDBG r_bin_java_print_local_variable_type_table_attr_summary(attr);
4076 	attr->size = offset;
4077 	return attr;
4078 }
4079 
r_bin_java_source_code_file_attr_new(RBinJavaObj * bin,ut8 * buffer,ut64 sz,ut64 buf_offset)4080 R_API RBinJavaAttrInfo *r_bin_java_source_code_file_attr_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz, ut64 buf_offset) {
4081 	if (!sz) {
4082 		return NULL;
4083 	}
4084 	ut64 offset = 0;
4085 	RBinJavaAttrInfo *attr = r_bin_java_default_attr_new (bin, buffer, sz, buf_offset);
4086 	offset += 6;
4087 	if (!attr) {
4088 		return NULL;
4089 	}
4090 	attr->type = R_BIN_JAVA_ATTR_TYPE_SOURCE_FILE_ATTR;
4091 	// if (buffer + offset > buffer + sz) return NULL;
4092 	attr->info.source_file_attr.sourcefile_idx = R_BIN_JAVA_USHORT (buffer, offset);
4093 	offset += 2;
4094 	attr->size = offset;
4095 	// IFDBG r_bin_java_print_source_code_file_attr_summary(attr);
4096 	return attr;
4097 }
4098 
r_bin_java_source_code_file_attr_calc_size(RBinJavaAttrInfo * attr)4099 R_API ut64 r_bin_java_source_code_file_attr_calc_size(RBinJavaAttrInfo *attr) {
4100 	return attr ? 8 : 0;
4101 }
4102 
r_bin_java_synthetic_attr_new(RBinJavaObj * bin,ut8 * buffer,ut64 sz,ut64 buf_offset)4103 R_API RBinJavaAttrInfo *r_bin_java_synthetic_attr_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz, ut64 buf_offset) {
4104 	ut64 offset = 0;
4105 	RBinJavaAttrInfo *attr = r_bin_java_default_attr_new (bin, buffer, sz, buf_offset);
4106 	if (!attr) {
4107 		return NULL;
4108 	}
4109 	offset += 6;
4110 	attr->type = R_BIN_JAVA_ATTR_TYPE_SYNTHETIC_ATTR;
4111 	attr->size = offset;
4112 	return attr;
4113 }
4114 
r_bin_java_synthetic_attr_calc_size(RBinJavaAttrInfo * attr)4115 R_API ut64 r_bin_java_synthetic_attr_calc_size(RBinJavaAttrInfo *attr) {
4116 	return attr ? 12 : 6;
4117 }
4118 
r_bin_java_interface_new(RBinJavaObj * bin,const ut8 * buffer,ut64 sz)4119 R_API RBinJavaInterfaceInfo *r_bin_java_interface_new(RBinJavaObj *bin, const ut8 *buffer, ut64 sz) {
4120 	RBinJavaInterfaceInfo *ifobj = NULL;
4121 	ifobj = R_NEW0 (RBinJavaInterfaceInfo);
4122 	IFDBG eprintf("Parsing RBinJavaInterfaceInfo\n");
4123 	if (ifobj) {
4124 		if (buffer) {
4125 			ifobj->class_info_idx = R_BIN_JAVA_USHORT (buffer, 0);
4126 			ifobj->cp_class = r_bin_java_get_item_from_bin_cp_list (bin, ifobj->class_info_idx);
4127 			if (ifobj->cp_class) {
4128 				ifobj->name = r_bin_java_get_item_name_from_bin_cp_list (bin, ifobj->cp_class);
4129 			} else {
4130 				ifobj->name = r_str_dup (NULL, "NULL");
4131 			}
4132 			ifobj->size = 2;
4133 		} else {
4134 			ifobj->class_info_idx = 0;
4135 			ifobj->name = r_str_dup (NULL, "NULL");
4136 		}
4137 	}
4138 	return ifobj;
4139 }
4140 
r_bin_java_verification_info_from_type(RBinJavaObj * bin,R_BIN_JAVA_STACKMAP_TYPE type,ut32 value)4141 R_API RBinJavaVerificationObj *r_bin_java_verification_info_from_type(RBinJavaObj *bin, R_BIN_JAVA_STACKMAP_TYPE type, ut32 value) {
4142 	RBinJavaVerificationObj *se = R_NEW0 (RBinJavaVerificationObj);
4143 	if (!se) {
4144 		return NULL;
4145 	}
4146 	se->tag = type;
4147 	if (se->tag == R_BIN_JAVA_STACKMAP_OBJECT) {
4148 		se->info.obj_val_cp_idx = (ut16) value;
4149 	} else if (se->tag == R_BIN_JAVA_STACKMAP_UNINIT) {
4150 		/*if (bin->offset_sz == 4) {
4151 		se->info.uninit_offset = value;
4152 		} else {
4153 		se->info.uninit_offset = (ut16) value;
4154 		}*/
4155 		se->info.uninit_offset = (ut16) value;
4156 	}
4157 	return se;
4158 }
4159 
r_bin_java_read_from_buffer_verification_info_new(ut8 * buffer,ut64 sz,ut64 buf_offset)4160 R_API RBinJavaVerificationObj *r_bin_java_read_from_buffer_verification_info_new(ut8 *buffer, ut64 sz, ut64 buf_offset) {
4161 	ut64 offset = 0;
4162 	RBinJavaVerificationObj *se = R_NEW0 (RBinJavaVerificationObj);
4163 	if (!se) {
4164 		return NULL;
4165 	}
4166 	se->file_offset = buf_offset;
4167 	se->tag = buffer[offset];
4168 	offset += 1;
4169 	if (se->tag == R_BIN_JAVA_STACKMAP_OBJECT) {
4170 		se->info.obj_val_cp_idx = R_BIN_JAVA_USHORT (buffer, offset);
4171 		offset += 2;
4172 	} else if (se->tag == R_BIN_JAVA_STACKMAP_UNINIT) {
4173 		se->info.uninit_offset = R_BIN_JAVA_USHORT (buffer, offset);
4174 		offset += 2;
4175 	}
4176 	if (R_BIN_JAVA_STACKMAP_UNINIT < se->tag) {
4177 		r_bin_java_verification_info_free (se);
4178 		return NULL;
4179 	}
4180 	se->size = offset;
4181 	return se;
4182 }
4183 
rbin_java_verification_info_calc_size(RBinJavaVerificationObj * se)4184 R_API ut64 rbin_java_verification_info_calc_size(RBinJavaVerificationObj *se) {
4185 	ut64 sz = 1;
4186 	if (!se) {
4187 		return 0;
4188 	}
4189 	// r_buf_read_at (bin->b, offset, (ut8*)(&se->tag), 1)
4190 	switch (se->tag) {
4191 	case R_BIN_JAVA_STACKMAP_OBJECT:
4192 		// r_buf_read_at (bin->b, offset+1, (ut8*)buf, 2)
4193 		sz += 2;
4194 		break;
4195 	case R_BIN_JAVA_STACKMAP_UNINIT:
4196 		// r_buf_read_at (bin->b, offset+1, (ut8*)buf, 2)
4197 		sz += 2;
4198 		break;
4199 	}
4200 	return sz;
4201 }
4202 
r_bin_java_determine_stack_frame_type(ut8 tag)4203 R_API RBinJavaStackMapFrameMetas *r_bin_java_determine_stack_frame_type(ut8 tag) {
4204 	ut8 type_value = 0;
4205 	if (tag < 64) {
4206 		type_value = R_BIN_JAVA_STACK_FRAME_SAME;
4207 	} else if (tag < 128) {
4208 		type_value = R_BIN_JAVA_STACK_FRAME_SAME_LOCALS_1;
4209 	} else if (247 < tag && tag < 251) {
4210 		type_value = R_BIN_JAVA_STACK_FRAME_CHOP;
4211 	} else if (tag == 251) {
4212 		type_value = R_BIN_JAVA_STACK_FRAME_SAME_FRAME_EXTENDED;
4213 	} else if (251 < tag && tag < 255) {
4214 		type_value = R_BIN_JAVA_STACK_FRAME_APPEND;
4215 	} else if (tag == 255) {
4216 		type_value = R_BIN_JAVA_STACK_FRAME_FULL_FRAME;
4217 	} else {
4218 		type_value = R_BIN_JAVA_STACK_FRAME_RESERVED;
4219 	}
4220 	return &R_BIN_JAVA_STACK_MAP_FRAME_METAS[type_value];
4221 }
4222 
r_bin_java_stack_map_frame_calc_size(RBinJavaStackMapFrame * sf)4223 R_API ut64 r_bin_java_stack_map_frame_calc_size(RBinJavaStackMapFrame *sf) {
4224 	ut64 size = 0;
4225 	RListIter *iter, *iter_tmp;
4226 	RBinJavaVerificationObj *se;
4227 	if (sf) {
4228 		// sf->tag = buffer[offset];
4229 		size += 1;
4230 		switch (sf->type) {
4231 		case R_BIN_JAVA_STACK_FRAME_SAME:
4232 			// Nothing to read
4233 			break;
4234 		case R_BIN_JAVA_STACK_FRAME_SAME_LOCALS_1:
4235 			r_list_foreach_safe (sf->stack_items, iter, iter_tmp, se) {
4236 				size += rbin_java_verification_info_calc_size (se);
4237 			}
4238 			break;
4239 		case R_BIN_JAVA_STACK_FRAME_CHOP:
4240 			// sf->offset_delta = R_BIN_JAVA_USHORT (buffer, offset);
4241 			size += 2;
4242 			break;
4243 		case R_BIN_JAVA_STACK_FRAME_SAME_FRAME_EXTENDED:
4244 			// sf->offset_delta = R_BIN_JAVA_USHORT (buffer, offset);
4245 			size += 2;
4246 			r_list_foreach_safe (sf->stack_items, iter, iter_tmp, se) {
4247 				size += rbin_java_verification_info_calc_size (se);
4248 			}
4249 			break;
4250 		case R_BIN_JAVA_STACK_FRAME_APPEND:
4251 			// sf->offset_delta = R_BIN_JAVA_USHORT (buffer, offset);
4252 			size += 2;
4253 			r_list_foreach_safe (sf->stack_items, iter, iter_tmp, se) {
4254 				size += rbin_java_verification_info_calc_size (se);
4255 			}
4256 			break;
4257 		case R_BIN_JAVA_STACK_FRAME_FULL_FRAME:
4258 			// sf->offset_delta = R_BIN_JAVA_USHORT (buffer, offset);
4259 			size += 2;
4260 			// sf->number_of_locals = R_BIN_JAVA_USHORT (buffer, offset);
4261 			size += 2;
4262 			r_list_foreach_safe (sf->local_items, iter, iter_tmp, se) {
4263 				size += rbin_java_verification_info_calc_size (se);
4264 			}
4265 			// sf->number_of_stack_items = R_BIN_JAVA_USHORT (buffer, offset);
4266 			size += 2;
4267 			r_list_foreach_safe (sf->stack_items, iter, iter_tmp, se) {
4268 				size += rbin_java_verification_info_calc_size (se);
4269 			}
4270 			break;
4271 		default:
4272 			eprintf ("Unknown type\n");
4273 			break;
4274 		}
4275 	}
4276 	return size;
4277 }
4278 
r_bin_java_stack_map_frame_new(ut8 * buffer,ut64 sz,RBinJavaStackMapFrame * p_frame,ut64 buf_offset)4279 R_API RBinJavaStackMapFrame *r_bin_java_stack_map_frame_new(ut8 *buffer, ut64 sz, RBinJavaStackMapFrame *p_frame, ut64 buf_offset) {
4280 	RBinJavaStackMapFrame *stack_frame = r_bin_java_default_stack_frame ();
4281 	RBinJavaVerificationObj *se = NULL;
4282 	ut64 offset = 0;
4283 	if (!stack_frame) {
4284 		return NULL;
4285 	}
4286 	stack_frame->tag = buffer[offset];
4287 	offset += 1;
4288 	stack_frame->metas->type_info = (void *) r_bin_java_determine_stack_frame_type (stack_frame->tag);
4289 	stack_frame->type = ((RBinJavaStackMapFrameMetas *) stack_frame->metas->type_info)->type;
4290 	stack_frame->file_offset = buf_offset;
4291 	stack_frame->p_stack_frame = p_frame;
4292 	switch (stack_frame->type) {
4293 	case R_BIN_JAVA_STACK_FRAME_SAME:
4294 		// Maybe?  1. Copy the previous frames locals and set the locals count.
4295 		// copy_type_info_to_stack_frame_list_up_to_idx (p_frame->local_items, stack_frame->local_items, idx);
4296 		if (p_frame) {
4297 			stack_frame->number_of_locals = p_frame->number_of_locals;
4298 		} else {
4299 			IFINT eprintf("><?><\n");
4300 			IFDBG eprintf("Unable to set previous stackframe with the number of locals (current info.code_attr.implicit_frame was probably not set :/)");
4301 		}
4302 		IFDBG eprintf("r_bin_java_stack_map_frame_new: TODO Stack Frame Same Locals Condition is untested, so there may be issues.\n");
4303 		break;
4304 	case R_BIN_JAVA_STACK_FRAME_SAME_LOCALS_1:
4305 		// 1. Read the stack type
4306 		stack_frame->number_of_stack_items = 1;
4307 		if (offset > sz) {
4308 			r_bin_java_stack_frame_free (stack_frame);
4309 			return NULL;
4310 		}
4311 		se = r_bin_java_read_from_buffer_verification_info_new (buffer + offset, sz - offset, buf_offset + offset);
4312 		IFDBG eprintf("r_bin_java_stack_map_frame_new: Parsed R_BIN_JAVA_STACK_FRAME_SAME_LOCALS_1.\n");
4313 		if (se) {
4314 			offset += se->size;
4315 		} else {
4316 			eprintf ("r_bin_java_stack_map_frame_new: Unable to parse the Stack Items for the stack frame.\n");
4317 			r_bin_java_stack_frame_free (stack_frame);
4318 			return NULL;
4319 		}
4320 		r_list_append (stack_frame->stack_items, (void *) se);
4321 		// Maybe?  3. Copy the previous frames locals and set the locals count.
4322 		// copy_type_info_to_stack_frame_list_up_to_idx (p_frame->local_items, stack_frame->local_items, idx);
4323 		if (p_frame) {
4324 			stack_frame->number_of_locals = p_frame->number_of_locals;
4325 		} else {
4326 			IFDBG eprintf("Unable to set previous stackframe with the number of locals (current info.code_attr.implicit_frame was probably not set :/)");
4327 		}
4328 		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");
4329 		break;
4330 	case R_BIN_JAVA_STACK_FRAME_CHOP:
4331 		// 1. Calculate the max index we want to copy from the list of the
4332 		// previous frames locals
4333 		IFDBG eprintf("r_bin_java_stack_map_frame_new: Parsing R_BIN_JAVA_STACK_FRAME_CHOP.\n");
4334 		// ut16 k = 251 - stack_frame->tag;
4335 		/*,
4336 		idx = p_frame->number_of_locals - k;
4337 		*/
4338 		// 2.  read the uoffset value
4339 		stack_frame->offset_delta = R_BIN_JAVA_USHORT (buffer, offset);
4340 		offset += 2;
4341 		// Maybe? 3. Copy the previous frames locals and set the locals count.
4342 		// copy_type_info_to_stack_frame_list_up_to_idx (p_frame->local_items, stack_frame->local_items, idx);
4343 		if (p_frame) {
4344 			stack_frame->number_of_locals = p_frame->number_of_locals;
4345 		} else {
4346 			IFINT eprintf("><?><\n");
4347 			IFDBG eprintf("Unable to set previous stackframe with the number of locals (current info.code_attr.implicit_frame was probably not set :/)");
4348 		}
4349 		IFDBG eprintf("r_bin_java_stack_map_frame_new: TODO Stack Frame Chop Condition is untested, so there may be issues.\n");
4350 		break;
4351 	case R_BIN_JAVA_STACK_FRAME_SAME_FRAME_EXTENDED:
4352 		IFDBG eprintf("r_bin_java_stack_map_frame_new: Parsing R_BIN_JAVA_STACK_FRAME_SAME_FRAME_EXTENDED.\n");
4353 		// 1. Read the uoffset
4354 		stack_frame->offset_delta = R_BIN_JAVA_USHORT (buffer, offset);
4355 		offset += 2;
4356 		// 2. Read the stack element type
4357 		stack_frame->number_of_stack_items = 1;
4358 		se = r_bin_java_read_from_buffer_verification_info_new (buffer + offset, sz - offset, buf_offset + offset);
4359 		if (se) {
4360 			offset += se->size;
4361 		} else {
4362 			eprintf ("r_bin_java_stack_map_frame_new: Unable to parse the Stack Items for the stack frame.\n");
4363 			r_bin_java_stack_frame_free (stack_frame);
4364 			return NULL;
4365 		}
4366 		r_list_append (stack_frame->stack_items, (void *) se);
4367 		// Maybe? 3. Copy the previous frames locals to the current locals
4368 		// copy_type_info_to_stack_frame_list_up_to_idx (p_frame->local_items, stack_frame->local_items, idx);
4369 		if (p_frame) {
4370 			stack_frame->number_of_locals = p_frame->number_of_locals;
4371 		} else {
4372 			IFINT eprintf("><?><\n");
4373 			IFDBG eprintf("Unable to set previous stackframe with the number of locals (current info.code_attr.implicit_frame was probably not set :/)");
4374 		}
4375 		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");
4376 		break;
4377 	case R_BIN_JAVA_STACK_FRAME_APPEND:
4378 		IFDBG eprintf("r_bin_java_stack_map_frame_new: Parsing R_BIN_JAVA_STACK_FRAME_APPEND.\n");
4379 		// 1. Calculate the max index we want to copy from the list of the
4380 		// previous frames locals
4381 		ut16 k = stack_frame->tag - 251;
4382 		ut32 i = 0;
4383 		// 2. Read the uoffset
4384 		stack_frame->offset_delta = R_BIN_JAVA_USHORT (buffer, offset);
4385 		offset += 2;
4386 		// Maybe? 3. Copy the previous frames locals to the current locals
4387 		// copy_type_info_to_stack_frame_list_up_to_idx (p_frame->local_items, stack_frame->local_items, idx);
4388 		// 4. Read off the rest of the appended locals types
4389 		for (i = 0; i < k; i++) {
4390 			if (offset >= sz) {
4391 				break;
4392 			}
4393 			IFDBG eprintf("r_bin_java_stack_map_frame_new: Parsing verifying the k'th frame: %d of %d.\n", i, k);
4394 			se = r_bin_java_read_from_buffer_verification_info_new (buffer + offset, sz - offset, buf_offset + offset);
4395 			IFDBG eprintf("r_bin_java_stack_map_frame_new: Completed Parsing\n");
4396 			if (se) {
4397 				offset += se->size;
4398 			} else {
4399 				eprintf ("r_bin_java_stack_map_frame_new: Unable to parse the locals for the stack frame.\n");
4400 				r_bin_java_stack_frame_free (stack_frame);
4401 				return NULL;
4402 			}
4403 			r_list_append (stack_frame->local_items, (void *) se);
4404 		}
4405 		IFDBG eprintf("r_bin_java_stack_map_frame_new: Breaking out of loop");
4406 		IFDBG eprintf("p_frame: %p\n", p_frame);
4407 		if (p_frame) {
4408 			stack_frame->number_of_locals = p_frame->number_of_locals + k;
4409 		} else {
4410 			IFINT eprintf("><?><\n");
4411 			IFDBG eprintf("Unable to set previous stackframe with the number of locals (current info.code_attr.implicit_frame was probably not set :/)");
4412 		}
4413 		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");
4414 		break;
4415 	case R_BIN_JAVA_STACK_FRAME_FULL_FRAME:
4416 		IFDBG eprintf("r_bin_java_stack_map_frame_new: Parsing R_BIN_JAVA_STACK_FRAME_FULL_FRAME.\n");
4417 		stack_frame->offset_delta = R_BIN_JAVA_USHORT (buffer, offset);
4418 		offset += 2;
4419 		// 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);
4420 		// Read the number of variables based on the max # local variable
4421 		stack_frame->number_of_locals = R_BIN_JAVA_USHORT (buffer, offset);
4422 		offset += 2;
4423 		// 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);
4424 		IFDBG r_bin_java_print_stack_map_frame_summary(stack_frame);
4425 		// read the number of locals off the stack
4426 		for (i = 0; i < stack_frame->number_of_locals; i++) {
4427 			if (offset >= sz) {
4428 				break;
4429 			}
4430 			se = r_bin_java_read_from_buffer_verification_info_new (buffer + offset, sz - offset, buf_offset + offset);
4431 			if (se) {
4432 				offset += se->size;
4433 				// r_list_append (stack_frame->local_items, (void *) se);
4434 			} else {
4435 				eprintf ("r_bin_java_stack_map_frame_new: Unable to parse the locals for the stack frame.\n");
4436 				r_bin_java_stack_frame_free (stack_frame);
4437 				return NULL;
4438 			}
4439 			r_list_append (stack_frame->local_items, (void *) se);
4440 		}
4441 		// Read the number of stack items based on the max size of stack
4442 		stack_frame->number_of_stack_items = R_BIN_JAVA_USHORT (buffer, offset);
4443 		offset += 2;
4444 		// 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);
4445 		// read the stack items
4446 		for (i = 0; i < stack_frame->number_of_stack_items; i++) {
4447 			if (offset >= sz) {
4448 				break;
4449 			}
4450 			se = r_bin_java_read_from_buffer_verification_info_new (buffer + offset, sz - offset, buf_offset + offset);
4451 			if (se) {
4452 				offset += se->size;
4453 				// r_list_append (stack_frame->stack_items, (void *) se);
4454 			} else {
4455 				eprintf ("r_bin_java_stack_map_frame_new: Unable to parse the stack items for the stack frame.\n");
4456 				r_bin_java_stack_frame_free (stack_frame);
4457 				return NULL;
4458 			}
4459 			r_list_append (stack_frame->local_items, (void *) se);
4460 		}
4461 		break;
4462 	default:
4463 		eprintf ("java: Unknown type\n");
4464 		break;
4465 	}
4466 	// 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);
4467 	stack_frame->size = offset;
4468 	// IFDBG r_bin_java_print_stack_map_frame_summary(stack_frame);
4469 	return stack_frame;
4470 }
4471 
r_bin_java_find_cp_class_ref_from_name_idx(RBinJavaObj * bin,ut16 name_idx)4472 R_API ut16 r_bin_java_find_cp_class_ref_from_name_idx(RBinJavaObj *bin, ut16 name_idx) {
4473 	ut16 pos, len = (ut16) r_list_length (bin->cp_list);
4474 	RBinJavaCPTypeObj *item;
4475 	for (pos = 0; pos < len; pos++) {
4476 		item = (RBinJavaCPTypeObj *) r_list_get_n (bin->cp_list, pos);
4477 		if (item && item->tag == R_BIN_JAVA_CP_CLASS && item->info.cp_class.name_idx == name_idx) {
4478 			break;
4479 		}
4480 	}
4481 	return (pos != len) ? pos : 0;
4482 }
4483 
r_bin_java_default_stack_frame(void)4484 R_API RBinJavaStackMapFrame *r_bin_java_default_stack_frame(void) {
4485 	RBinJavaStackMapFrame *sf = R_NEW0 (RBinJavaStackMapFrame);
4486 	if (!sf) {
4487 		return NULL;
4488 	}
4489 	sf->metas = R_NEW0 (RBinJavaMetaInfo);
4490 	if (!sf->metas) {
4491 		free (sf);
4492 		return NULL;
4493 	}
4494 	sf->metas->type_info = (void *) &R_BIN_JAVA_STACK_MAP_FRAME_METAS[R_BIN_JAVA_STACK_FRAME_IMPLICIT];
4495 	sf->type = ((RBinJavaStackMapFrameMetas *) sf->metas->type_info)->type;
4496 	sf->local_items = r_list_newf (r_bin_java_verification_info_free);
4497 	sf->stack_items = r_list_newf (r_bin_java_verification_info_free);
4498 	sf->number_of_stack_items = 0;
4499 	sf->number_of_locals = 0;
4500 	return sf;
4501 }
4502 
r_bin_java_build_stack_frame_from_local_variable_table(RBinJavaObj * bin,RBinJavaAttrInfo * attr)4503 R_API RBinJavaStackMapFrame *r_bin_java_build_stack_frame_from_local_variable_table(RBinJavaObj *bin, RBinJavaAttrInfo *attr) {
4504 	RBinJavaStackMapFrame *sf = r_bin_java_default_stack_frame ();
4505 	RBinJavaLocalVariableAttribute *lvattr = NULL;
4506 	RBinJavaVerificationObj *type_item;
4507 	RListIter *iter = NULL;
4508 	ut32 value_cnt = 0;
4509 	ut8 value;
4510 	if (!sf || !bin || !attr || attr->type != R_BIN_JAVA_ATTR_TYPE_LOCAL_VARIABLE_TABLE_ATTR) {
4511 		eprintf ("Attempting to create a stack_map frame from a bad attribute.\n");
4512 		return sf;
4513 	}
4514 	sf->number_of_locals = attr->info.local_variable_table_attr.table_length;
4515 	r_list_foreach (attr->info.local_variable_table_attr.local_variable_table, iter, lvattr) {
4516 		ut32 pos = 0;
4517 		// knock the array Types
4518 		while (lvattr->descriptor[pos] == '[') {
4519 			pos++;
4520 		}
4521 		value = lvattr->descriptor[pos];
4522 		// IFDBG eprintf ("Found the following type value: %c at pos %d in %s\n", value, pos, lvattr->descriptor);
4523 		switch (value) {
4524 		case 'I':
4525 		case 'Z':
4526 		case 'S':
4527 		case 'B':
4528 		case 'C':
4529 			type_item = r_bin_java_verification_info_from_type (bin, R_BIN_JAVA_STACKMAP_INTEGER, 0);
4530 			break;
4531 		case 'F':
4532 			type_item = r_bin_java_verification_info_from_type (bin, R_BIN_JAVA_STACKMAP_FLOAT, 0);
4533 			break;
4534 		case 'D':
4535 			type_item = r_bin_java_verification_info_from_type (bin, R_BIN_JAVA_STACKMAP_DOUBLE, 0);
4536 			break;
4537 		case 'J':
4538 			type_item = r_bin_java_verification_info_from_type (bin, R_BIN_JAVA_STACKMAP_LONG, 0);
4539 			break;
4540 		case 'L':
4541 			// TODO: FIXME write something that will iterate over the CP Pool and find the
4542 			// CONSTANT_Class_info referencing this
4543 		{
4544 			ut16 idx = r_bin_java_find_cp_class_ref_from_name_idx (bin, lvattr->name_idx);
4545 			type_item = r_bin_java_verification_info_from_type (bin, R_BIN_JAVA_STACKMAP_OBJECT, idx);
4546 		}
4547 		break;
4548 		default:
4549 			eprintf ("r_bin_java_build_stack_frame_from_local_variable_table: "
4550 				"not sure how to handle: name: %s, type: %s\n", lvattr->name, lvattr->descriptor);
4551 			type_item = r_bin_java_verification_info_from_type (bin, R_BIN_JAVA_STACKMAP_NULL, 0);
4552 		}
4553 		if (type_item) {
4554 			r_list_append (sf->local_items, (void *) type_item);
4555 		}
4556 		value_cnt++;
4557 	}
4558 	if (value_cnt != attr->info.local_variable_table_attr.table_length) {
4559 		IFDBG eprintf("r_bin_java_build_stack_frame_from_local_variable_table: "
4560 		"Number of locals not accurate.  Expected %d but got %d",
4561 		attr->info.local_variable_table_attr.table_length, value_cnt);
4562 	}
4563 	return sf;
4564 }
4565 
r_bin_java_stack_map_table_attr_calc_size(RBinJavaAttrInfo * attr)4566 R_API ut64 r_bin_java_stack_map_table_attr_calc_size(RBinJavaAttrInfo *attr) {
4567 	ut64 size = 0;
4568 	RListIter *iter, *iter_tmp;
4569 	RBinJavaStackMapFrame *sf;
4570 	if (attr) {
4571 		// attr = r_bin_java_default_attr_new (buffer, sz, buf_offset);
4572 		size += 6;
4573 		// IFDBG r_bin_java_print_source_code_file_attr_summary(attr);
4574 		// Current spec does not call for variable sizes.
4575 		// attr->info.stack_map_table_attr.number_of_entries = R_BIN_JAVA_USHORT (buffer, offset);
4576 		size += 2;
4577 		r_list_foreach_safe (attr->info.stack_map_table_attr.stack_map_frame_entries, iter, iter_tmp, sf) {
4578 			size += r_bin_java_stack_map_frame_calc_size (sf);
4579 		}
4580 	}
4581 	return size;
4582 }
4583 
r_bin_java_stack_map_table_attr_new(RBinJavaObj * bin,ut8 * buffer,ut64 sz,ut64 buf_offset)4584 R_API RBinJavaAttrInfo *r_bin_java_stack_map_table_attr_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz, ut64 buf_offset) {
4585 	ut32 i = 0;
4586 	ut64 offset = 0;
4587 	RBinJavaStackMapFrame *stack_frame = NULL, *new_stack_frame = NULL;
4588 	if (sz < 10) {
4589 		return NULL;
4590 	}
4591 	RBinJavaAttrInfo *attr = r_bin_java_default_attr_new (bin, buffer, sz, buf_offset);
4592 	offset += 6;
4593 	IFDBG eprintf("r_bin_java_stack_map_table_attr_new: New stack map allocated.\n");
4594 	if (!attr) {
4595 		return NULL;
4596 	}
4597 	attr->info.stack_map_table_attr.stack_map_frame_entries = r_list_newf (r_bin_java_stack_frame_free);
4598 	// IFDBG r_bin_java_print_source_code_file_attr_summary(attr);
4599 	// Current spec does not call for variable sizes.
4600 	attr->info.stack_map_table_attr.number_of_entries = R_BIN_JAVA_USHORT (buffer, offset);
4601 	offset += 2;
4602 	IFDBG eprintf("r_bin_java_stack_map_table_attr_new: Processing stack map, summary is:\n");
4603 	IFDBG r_bin_java_print_stack_map_table_attr_summary(attr);
4604 	for (i = 0; i < attr->info.stack_map_table_attr.number_of_entries; i++) {
4605 		// read next stack frame
4606 		IFDBG eprintf("Reading StackMap Entry #%d @ 0x%08"PFMT64x "\n", i, buf_offset + offset);
4607 		if (stack_frame == NULL && R_BIN_JAVA_GLOBAL_BIN && R_BIN_JAVA_GLOBAL_BIN->current_code_attr) {
4608 			IFDBG eprintf("Setting an implicit frame at #%d @ 0x%08"PFMT64x "\n", i, buf_offset + offset);
4609 			stack_frame = R_BIN_JAVA_GLOBAL_BIN->current_code_attr->info.code_attr.implicit_frame;
4610 		}
4611 		IFDBG eprintf("Reading StackMap Entry #%d @ 0x%08"PFMT64x ", current stack_frame: %p\n", i, buf_offset + offset, stack_frame);
4612 		if (offset >= sz) {
4613 			r_bin_java_stack_map_table_attr_free (attr);
4614 			return NULL;
4615 		}
4616 		new_stack_frame = r_bin_java_stack_map_frame_new (buffer + offset, sz - offset, stack_frame, buf_offset + offset);
4617 		if (new_stack_frame) {
4618 			offset += new_stack_frame->size;
4619 			// append stack frame to the list
4620 			r_list_append (attr->info.stack_map_table_attr.stack_map_frame_entries, (void *) new_stack_frame);
4621 			stack_frame = new_stack_frame;
4622 		} else {
4623 			eprintf ("r_bin_java_stack_map_table_attr_new: Unable to parse the stack frame for the stack map table.\n");
4624 			r_bin_java_stack_map_table_attr_free (attr);
4625 			attr = NULL;
4626 			break;
4627 		}
4628 	}
4629 	if (attr) {
4630 		attr->size = offset;
4631 	}
4632 	return attr;
4633 }
4634 // End attribute types new
4635 // Start new Constant Pool Types
r_bin_java_do_nothing_new(RBinJavaObj * bin,ut8 * buffer,ut64 sz)4636 R_API RBinJavaCPTypeObj *r_bin_java_do_nothing_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz) {
4637 	return (RBinJavaCPTypeObj *) NULL;
4638 }
4639 
r_bin_java_do_nothing_calc_size(RBinJavaCPTypeObj * obj)4640 R_API ut64 r_bin_java_do_nothing_calc_size(RBinJavaCPTypeObj *obj) {
4641 	return 0;
4642 }
4643 
r_bin_java_do_nothing_free(void * obj)4644 R_API void r_bin_java_do_nothing_free(void /*RBinJavaCPTypeObj*/ *obj) {
4645 	return;
4646 }
4647 
r_bin_java_unknown_cp_new(RBinJavaObj * bin,ut8 * buffer,ut64 sz)4648 R_API RBinJavaCPTypeObj *r_bin_java_unknown_cp_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz) {
4649 	ut8 tag = buffer[0];
4650 	RBinJavaCPTypeObj *obj = NULL;
4651 	obj = (RBinJavaCPTypeObj *) malloc (sizeof (RBinJavaCPTypeObj));
4652 	if (obj) {
4653 		memset (obj, 0, sizeof (RBinJavaCPTypeObj));
4654 		obj->tag = tag;
4655 		obj->metas = R_NEW0 (RBinJavaMetaInfo);
4656 		obj->metas->type_info = (void *) &R_BIN_JAVA_CP_METAS[R_BIN_JAVA_CP_UNKNOWN];
4657 	}
4658 	return obj;
4659 }
4660 
r_bin_java_unknown_cp_calc_size(RBinJavaCPTypeObj * obj)4661 R_API ut64 r_bin_java_unknown_cp_calc_size(RBinJavaCPTypeObj *obj) {
4662 	return 1LL;
4663 }
4664 
r_bin_java_class_cp_new(RBinJavaObj * bin,ut8 * buffer,ut64 sz)4665 R_API RBinJavaCPTypeObj *r_bin_java_class_cp_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz) {
4666 	ut8 tag = buffer[0];
4667 	int quick_check = r_bin_java_quick_check (R_BIN_JAVA_CP_CLASS, tag, sz, "Class");
4668 	if (quick_check > 0) {
4669 		return NULL;
4670 	}
4671 	RBinJavaCPTypeObj *obj = R_NEW0 (RBinJavaCPTypeObj);
4672 	if (obj) {
4673 		obj->tag = tag;
4674 		obj->metas = R_NEW0 (RBinJavaMetaInfo);
4675 		obj->metas->type_info = (void *) &R_BIN_JAVA_CP_METAS[tag];
4676 		obj->info.cp_class.name_idx = R_BIN_JAVA_USHORT (buffer, 1);
4677 	}
4678 	return obj;
4679 }
4680 
r_bin_java_class_cp_calc_size(RBinJavaCPTypeObj * obj)4681 R_API ut64 r_bin_java_class_cp_calc_size(RBinJavaCPTypeObj *obj) {
4682 	ut64 size = 0;
4683 	// ut8 tag = buffer[0];
4684 	size += 1;
4685 	// obj->info.cp_class.name_idx = R_BIN_JAVA_USHORT (buffer, 1);
4686 	size += 2;
4687 	return size;
4688 }
4689 
r_bin_java_fieldref_cp_new(RBinJavaObj * bin,ut8 * buffer,ut64 sz)4690 R_API RBinJavaCPTypeObj *r_bin_java_fieldref_cp_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz) {
4691 	ut8 tag = buffer[0];
4692 	RBinJavaCPTypeObj *obj = NULL;
4693 	int quick_check = 0;
4694 	quick_check = r_bin_java_quick_check (R_BIN_JAVA_CP_FIELDREF, tag, sz, "FieldRef");
4695 	if (quick_check > 0) {
4696 		return obj;
4697 	}
4698 	obj = (RBinJavaCPTypeObj *) malloc (sizeof (RBinJavaCPTypeObj));
4699 	if (obj) {
4700 		memset (obj, 0, sizeof (RBinJavaCPTypeObj));
4701 		obj->tag = tag;
4702 		obj->metas = R_NEW0 (RBinJavaMetaInfo);
4703 		obj->metas->type_info = (void *) &R_BIN_JAVA_CP_METAS[tag];
4704 		obj->info.cp_field.class_idx = R_BIN_JAVA_USHORT (buffer, 1);
4705 		obj->info.cp_field.name_and_type_idx = R_BIN_JAVA_USHORT (buffer, 3);
4706 
4707 	}
4708 	return (RBinJavaCPTypeObj *) obj;
4709 }
4710 
r_bin_java_fieldref_cp_calc_size(RBinJavaCPTypeObj * obj)4711 R_API ut64 r_bin_java_fieldref_cp_calc_size(RBinJavaCPTypeObj *obj) {
4712 	ut64 size = 0;
4713 	// tag
4714 	size += 1;
4715 	// obj->info.cp_field.class_idx = R_BIN_JAVA_USHORT (buffer, 1);
4716 	size += 2;
4717 	// obj->info.cp_field.name_and_type_idx = R_BIN_JAVA_USHORT (buffer, 3);
4718 	size += 2;
4719 	return size;
4720 }
4721 
r_bin_java_methodref_cp_new(RBinJavaObj * bin,ut8 * buffer,ut64 sz)4722 R_API RBinJavaCPTypeObj *r_bin_java_methodref_cp_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz) {
4723 	ut8 tag = buffer[0];
4724 	RBinJavaCPTypeObj *obj = NULL;
4725 	int quick_check = 0;
4726 	quick_check = r_bin_java_quick_check (R_BIN_JAVA_CP_METHODREF, tag, sz, "MethodRef");
4727 	if (quick_check > 0) {
4728 		return obj;
4729 	}
4730 	obj = (RBinJavaCPTypeObj *) malloc (sizeof (RBinJavaCPTypeObj));
4731 	if (obj) {
4732 		memset (obj, 0, sizeof (RBinJavaCPTypeObj));
4733 		obj->tag = tag;
4734 		obj->metas = R_NEW0 (RBinJavaMetaInfo);
4735 		obj->metas->type_info = (void *) &R_BIN_JAVA_CP_METAS[tag];
4736 		obj->info.cp_method.class_idx = R_BIN_JAVA_USHORT (buffer, 1);
4737 		obj->info.cp_method.name_and_type_idx = R_BIN_JAVA_USHORT (buffer, 3);
4738 	}
4739 	return obj;
4740 }
4741 
r_bin_java_methodref_cp_calc_size(RBinJavaCPTypeObj * obj)4742 R_API ut64 r_bin_java_methodref_cp_calc_size(RBinJavaCPTypeObj *obj) {
4743 	ut64 size = 0;
4744 	// tag
4745 	size += 1;
4746 	// obj->info.cp_method.class_idx = R_BIN_JAVA_USHORT (buffer, 1);
4747 	size += 2;
4748 	// obj->info.cp_method.name_and_type_idx = R_BIN_JAVA_USHORT (buffer, 3);
4749 	size += 2;
4750 	return size;
4751 }
4752 
r_bin_java_interfacemethodref_cp_new(RBinJavaObj * bin,ut8 * buffer,ut64 sz)4753 R_API RBinJavaCPTypeObj *r_bin_java_interfacemethodref_cp_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz) {
4754 	ut8 tag = buffer[0];
4755 	int quick_check = r_bin_java_quick_check (R_BIN_JAVA_CP_INTERFACEMETHOD_REF, tag, sz, "InterfaceMethodRef");
4756 	if (quick_check > 0) {
4757 		return NULL;
4758 	}
4759 	RBinJavaCPTypeObj *obj = R_NEW0 (RBinJavaCPTypeObj);
4760 	if (obj) {
4761 		obj->tag = tag;
4762 		obj->metas = R_NEW0 (RBinJavaMetaInfo);
4763 		obj->metas->type_info = (void *) &R_BIN_JAVA_CP_METAS[tag];
4764 		obj->name = r_str_dup (NULL, (const char *) R_BIN_JAVA_CP_METAS[tag].name);
4765 		obj->info.cp_interface.class_idx = R_BIN_JAVA_USHORT (buffer, 1);
4766 		obj->info.cp_interface.name_and_type_idx = R_BIN_JAVA_USHORT (buffer, 3);
4767 
4768 	}
4769 	return obj;
4770 }
4771 
r_bin_java_interfacemethodref_cp_calc_size(RBinJavaCPTypeObj * obj)4772 R_API ut64 r_bin_java_interfacemethodref_cp_calc_size(RBinJavaCPTypeObj *obj) {
4773 	ut64 size = 0;
4774 	// tag
4775 	size += 1;
4776 	// obj->info.cp_interface.class_idx = R_BIN_JAVA_USHORT (buffer, 1);
4777 	size += 2;
4778 	// obj->info.cp_interface.name_and_type_idx = R_BIN_JAVA_USHORT (buffer, 3);
4779 	size += 2;
4780 	return size;
4781 }
4782 
r_bin_java_string_cp_new(RBinJavaObj * bin,ut8 * buffer,ut64 sz)4783 R_API RBinJavaCPTypeObj *r_bin_java_string_cp_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz) {
4784 	ut8 tag = buffer[0];
4785 	int quick_check = r_bin_java_quick_check (R_BIN_JAVA_CP_STRING, tag, sz, "String");
4786 	if (quick_check > 0) {
4787 		return NULL;
4788 	}
4789 	RBinJavaCPTypeObj *obj = R_NEW0 (RBinJavaCPTypeObj);
4790 	if (obj) {
4791 		obj->tag = tag;
4792 		obj->metas = R_NEW0 (RBinJavaMetaInfo);
4793 		obj->metas->type_info = (void *) &R_BIN_JAVA_CP_METAS[tag];
4794 		obj->name = r_str_dup (NULL, (const char *) R_BIN_JAVA_CP_METAS[tag].name);
4795 		obj->info.cp_string.string_idx = R_BIN_JAVA_USHORT (buffer, 1);
4796 	}
4797 	return obj;
4798 }
4799 
r_bin_java_string_cp_calc_size(RBinJavaCPTypeObj * obj)4800 R_API ut64 r_bin_java_string_cp_calc_size(RBinJavaCPTypeObj *obj) {
4801 	ut64 size = 0;
4802 	// tag
4803 	size += 1;
4804 	// obj->info.cp_string.string_idx = R_BIN_JAVA_USHORT (buffer, 1);
4805 	size += 2;
4806 	return size;
4807 }
4808 
r_bin_java_integer_cp_new(RBinJavaObj * bin,ut8 * buffer,ut64 sz)4809 R_API RBinJavaCPTypeObj *r_bin_java_integer_cp_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz) {
4810 	ut8 tag = buffer[0];
4811 	RBinJavaCPTypeObj *obj = NULL;
4812 	int quick_check = 0;
4813 	quick_check = r_bin_java_quick_check (R_BIN_JAVA_CP_INTEGER, tag, sz, "Integer");
4814 	if (quick_check > 0) {
4815 		return obj;
4816 	}
4817 	obj = (RBinJavaCPTypeObj *) R_NEW0 (RBinJavaCPTypeObj);
4818 	if (obj) {
4819 		obj->tag = tag;
4820 		obj->metas = R_NEW0 (RBinJavaMetaInfo);
4821 		obj->metas->type_info = (void *) &R_BIN_JAVA_CP_METAS[tag];
4822 		obj->name = r_str_dup (NULL, (const char *) R_BIN_JAVA_CP_METAS[tag].name);
4823 		memset (&obj->info.cp_integer.bytes, 0, sizeof (obj->info.cp_integer.bytes));
4824 		memcpy (&obj->info.cp_integer.bytes.raw, buffer + 1, 4);
4825 
4826 	}
4827 	return obj;
4828 }
4829 
r_bin_java_integer_cp_calc_size(RBinJavaCPTypeObj * obj)4830 R_API ut64 r_bin_java_integer_cp_calc_size(RBinJavaCPTypeObj *obj) {
4831 	ut64 size = 0;
4832 	// tag
4833 	size += 1;
4834 	// obj->info.cp_string.string_idx = R_BIN_JAVA_USHORT (buffer, 1);
4835 	size += 4;
4836 	return size;
4837 }
4838 
r_bin_java_float_cp_new(RBinJavaObj * bin,ut8 * buffer,ut64 sz)4839 R_API RBinJavaCPTypeObj *r_bin_java_float_cp_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz) {
4840 	ut8 tag = buffer[0];
4841 	RBinJavaCPTypeObj *obj = NULL;
4842 	int quick_check = 0;
4843 	quick_check = r_bin_java_quick_check (R_BIN_JAVA_CP_FLOAT, tag, sz, "Float");
4844 	if (quick_check > 0) {
4845 		return obj;
4846 	}
4847 	obj = (RBinJavaCPTypeObj *) calloc (1, sizeof (RBinJavaCPTypeObj));
4848 	if (obj) {
4849 		obj->tag = tag;
4850 		obj->metas = R_NEW0 (RBinJavaMetaInfo);
4851 		obj->metas->type_info = (void *) &R_BIN_JAVA_CP_METAS[tag];
4852 		obj->name = r_str_dup (NULL, (const char *) R_BIN_JAVA_CP_METAS[tag].name);
4853 		memset (&obj->info.cp_float.bytes, 0, sizeof (obj->info.cp_float.bytes));
4854 		memcpy (&obj->info.cp_float.bytes.raw, buffer, 4);
4855 	}
4856 	return (RBinJavaCPTypeObj *) obj;
4857 }
4858 
r_bin_java_float_cp_calc_size(RBinJavaCPTypeObj * obj)4859 R_API ut64 r_bin_java_float_cp_calc_size(RBinJavaCPTypeObj *obj) {
4860 	ut64 size = 0;
4861 	// tag
4862 	size += 1;
4863 	// obj->info.cp_string.string_idx = R_BIN_JAVA_USHORT (buffer, 1);
4864 	size += 4;
4865 	return size;
4866 }
4867 
r_bin_java_long_cp_new(RBinJavaObj * bin,ut8 * buffer,ut64 sz)4868 R_API RBinJavaCPTypeObj *r_bin_java_long_cp_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz) {
4869 	ut8 tag = buffer[0];
4870 	RBinJavaCPTypeObj *obj = NULL;
4871 	int quick_check = 0;
4872 	quick_check = r_bin_java_quick_check (R_BIN_JAVA_CP_LONG, tag, sz, "Long");
4873 	if (quick_check > 0) {
4874 		return obj;
4875 	}
4876 	obj = (RBinJavaCPTypeObj *) malloc (sizeof (RBinJavaCPTypeObj));
4877 	if (obj) {
4878 		memset (obj, 0, sizeof (RBinJavaCPTypeObj));
4879 		obj->tag = tag;
4880 		obj->metas = R_NEW0 (RBinJavaMetaInfo);
4881 		obj->metas->type_info = (void *) &R_BIN_JAVA_CP_METAS[tag];
4882 		obj->name = r_str_dup (NULL, (const char *) R_BIN_JAVA_CP_METAS[tag].name);
4883 		memset (&obj->info.cp_long.bytes, 0, sizeof (obj->info.cp_long.bytes));
4884 		memcpy (&(obj->info.cp_long.bytes), buffer + 1, 8);
4885 
4886 	}
4887 	return obj;
4888 }
4889 
r_bin_java_long_cp_calc_size(RBinJavaCPTypeObj * obj)4890 R_API ut64 r_bin_java_long_cp_calc_size(RBinJavaCPTypeObj *obj) {
4891 	ut64 size = 0;
4892 	// tag
4893 	size += 1;
4894 	// obj->info.cp_string.string_idx = R_BIN_JAVA_USHORT (buffer, 1);
4895 	size += 8;
4896 	return size;
4897 }
4898 
r_bin_java_double_cp_new(RBinJavaObj * bin,ut8 * buffer,ut64 sz)4899 R_API RBinJavaCPTypeObj *r_bin_java_double_cp_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz) {
4900 	ut8 tag = buffer[0];
4901 	RBinJavaCPTypeObj *obj = NULL;
4902 	int quick_check = 0;
4903 	quick_check = r_bin_java_quick_check (R_BIN_JAVA_CP_DOUBLE, tag, sz, "Double");
4904 	if (quick_check > 0) {
4905 		return (RBinJavaCPTypeObj *) obj;
4906 	}
4907 	obj = (RBinJavaCPTypeObj *) malloc (sizeof (RBinJavaCPTypeObj));
4908 	if (obj) {
4909 		memset (obj, 0, sizeof (RBinJavaCPTypeObj));
4910 		obj->tag = tag;
4911 		obj->metas = R_NEW0 (RBinJavaMetaInfo);
4912 		obj->metas->type_info = (void *) &R_BIN_JAVA_CP_METAS[tag];
4913 		obj->name = r_str_dup (NULL, (const char *) R_BIN_JAVA_CP_METAS[tag].name);
4914 		memset (&obj->info.cp_double.bytes, 0, sizeof (obj->info.cp_double.bytes));
4915 		memcpy (&obj->info.cp_double.bytes, buffer + 1, 8);
4916 	}
4917 	return obj;
4918 }
4919 
r_bin_java_double_cp_calc_size(RBinJavaCPTypeObj * obj)4920 R_API ut64 r_bin_java_double_cp_calc_size(RBinJavaCPTypeObj *obj) {
4921 	ut64 size = 0;
4922 	// tag
4923 	size += 1;
4924 	// obj->info.cp_string.string_idx = R_BIN_JAVA_USHORT (buffer, 1);
4925 	size += 8;
4926 	return size;
4927 }
4928 
r_bin_java_utf8_cp_new(RBinJavaObj * bin,ut8 * buffer,ut64 sz)4929 R_API RBinJavaCPTypeObj *r_bin_java_utf8_cp_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz) {
4930 	ut8 tag = buffer[0];
4931 	RBinJavaCPTypeObj *obj;
4932 	int quick_check = r_bin_java_quick_check (R_BIN_JAVA_CP_UTF8, tag, sz, "Utf8");
4933 	if (quick_check > 0) {
4934 		return NULL;
4935 	}
4936 	if ((obj = R_NEW0 (RBinJavaCPTypeObj))) {
4937 		obj->tag = tag;
4938 		obj->metas = R_NEW0 (RBinJavaMetaInfo);
4939 		obj->metas->type_info = (void *) &R_BIN_JAVA_CP_METAS[tag];
4940 		obj->name = r_str_dup (NULL, (const char *) R_BIN_JAVA_CP_METAS[tag].name);
4941 		obj->info.cp_utf8.length = R_BIN_JAVA_USHORT (buffer, 1);
4942 		obj->info.cp_utf8.bytes = (ut8 *) malloc (obj->info.cp_utf8.length + 1);
4943 		if (obj->info.cp_utf8.bytes) {
4944 			memset (obj->info.cp_utf8.bytes, 0, obj->info.cp_utf8.length + 1);
4945 			if (obj->info.cp_utf8.length < (sz - 3)) {
4946 				memcpy (obj->info.cp_utf8.bytes, buffer + 3, (sz - 3));
4947 				obj->info.cp_utf8.length = sz - 3;
4948 			} else {
4949 				memcpy (obj->info.cp_utf8.bytes, buffer + 3, obj->info.cp_utf8.length);
4950 			}
4951 			obj->value = obj->info.cp_utf8.bytes;
4952 		} else {
4953 			r_bin_java_obj_free (obj);
4954 			obj = NULL;
4955 		}
4956 	}
4957 	return obj;
4958 }
4959 
r_bin_java_utf8_cp_calc_size(RBinJavaCPTypeObj * obj)4960 R_API ut64 r_bin_java_utf8_cp_calc_size(RBinJavaCPTypeObj *obj) {
4961 	ut64 size = 0;
4962 	size += 1;
4963 	if (obj && R_BIN_JAVA_CP_UTF8 == obj->tag) {
4964 		size += 2;
4965 		size += obj->info.cp_utf8.length;
4966 	}
4967 	return size;
4968 }
4969 
r_bin_java_name_and_type_cp_new(RBinJavaObj * bin,ut8 * buffer,ut64 sz)4970 R_API RBinJavaCPTypeObj *r_bin_java_name_and_type_cp_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz) {
4971 	ut8 tag = buffer[0];
4972 	RBinJavaCPTypeObj *obj = NULL;
4973 	int quick_check = 0;
4974 	quick_check = r_bin_java_quick_check (R_BIN_JAVA_CP_NAMEANDTYPE, tag, sz, "RBinJavaCPTypeNameAndType");
4975 	if (quick_check > 0) {
4976 		return obj;
4977 	}
4978 	obj = R_NEW0 (RBinJavaCPTypeObj);
4979 	if (obj) {
4980 		obj->metas = R_NEW0 (RBinJavaMetaInfo);
4981 		obj->metas->type_info = (void *) &R_BIN_JAVA_CP_METAS[tag];
4982 		obj->name = r_str_dup (NULL, (const char *) R_BIN_JAVA_CP_METAS[tag].name);;
4983 		obj->tag = tag;
4984 		obj->info.cp_name_and_type.name_idx = R_BIN_JAVA_USHORT (buffer, 1);
4985 		obj->info.cp_name_and_type.descriptor_idx = R_BIN_JAVA_USHORT (buffer, 3);
4986 	}
4987 	return obj;
4988 }
4989 
r_bin_java_name_and_type_cp_calc_size(RBinJavaCPTypeObj * obj)4990 R_API ut64 r_bin_java_name_and_type_cp_calc_size(RBinJavaCPTypeObj *obj) {
4991 	ut64 size = 0;
4992 	if (obj) {
4993 		size += 1;
4994 		// obj->info.cp_name_and_type.name_idx = R_BIN_JAVA_USHORT (buffer, 1);
4995 		size += 2;
4996 		// obj->info.cp_name_and_type.descriptor_idx = R_BIN_JAVA_USHORT (buffer, 3);
4997 		size += 2;
4998 	}
4999 	return size;
5000 }
5001 
r_bin_java_methodtype_cp_new(RBinJavaObj * bin,ut8 * buffer,ut64 sz)5002 R_API RBinJavaCPTypeObj *r_bin_java_methodtype_cp_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz) {
5003 	ut8 tag = buffer[0];
5004 	int quick_check = r_bin_java_quick_check (R_BIN_JAVA_CP_METHODTYPE, tag, sz, "RBinJavaCPTypeMethodType");
5005 	if (quick_check > 0) {
5006 		return NULL;
5007 	}
5008 	RBinJavaCPTypeObj *obj = R_NEW0 (RBinJavaCPTypeObj);
5009 	if (obj) {
5010 		obj->metas = R_NEW0 (RBinJavaMetaInfo);
5011 		obj->metas->type_info = (void *) &R_BIN_JAVA_CP_METAS[tag];
5012 		obj->name = r_str_dup (NULL, (const char *) R_BIN_JAVA_CP_METAS[tag].name);;
5013 		obj->tag = tag;
5014 		obj->info.cp_method_type.descriptor_index = R_BIN_JAVA_USHORT (buffer, 1);
5015 	}
5016 	return obj;
5017 }
5018 
r_bin_java_methodtype_cp_calc_size(RBinJavaCPTypeObj * obj)5019 R_API ut64 r_bin_java_methodtype_cp_calc_size(RBinJavaCPTypeObj *obj) {
5020 	ut64 size = 0;
5021 	size += 1;
5022 	// obj->info.cp_method_type.descriptor_index = R_BIN_JAVA_USHORT (buffer, 1);
5023 	size += 2;
5024 	return size;
5025 }
5026 
r_bin_java_methodhandle_cp_new(RBinJavaObj * bin,ut8 * buffer,ut64 sz)5027 R_API RBinJavaCPTypeObj *r_bin_java_methodhandle_cp_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz) {
5028 	ut8 tag = buffer[0];
5029 	int quick_check = r_bin_java_quick_check (R_BIN_JAVA_CP_METHODHANDLE, tag, sz, "RBinJavaCPTypeMethodHandle");
5030 	if (quick_check > 0) {
5031 		return NULL;
5032 	}
5033 	RBinJavaCPTypeObj *obj = R_NEW0 (RBinJavaCPTypeObj);
5034 	if (obj) {
5035 		obj->metas = R_NEW0 (RBinJavaMetaInfo);
5036 		obj->metas->type_info = (void *) &R_BIN_JAVA_CP_METAS[tag];
5037 		obj->name = r_str_dup (NULL, (const char *) R_BIN_JAVA_CP_METAS[tag].name);;
5038 		obj->tag = tag;
5039 		obj->info.cp_method_handle.reference_kind = buffer[1];
5040 		obj->info.cp_method_handle.reference_index = R_BIN_JAVA_USHORT (buffer, 2);
5041 	}
5042 	return obj;
5043 }
5044 
r_bin_java_methodhandle_cp_calc_size(RBinJavaCPTypeObj * obj)5045 R_API ut64 r_bin_java_methodhandle_cp_calc_size(RBinJavaCPTypeObj *obj) {
5046 	ut64 size = 0;
5047 	size += 1;
5048 	// obj->info.cp_method_handle.reference_index =  R_BIN_JAVA_USHORT (buffer, 2);
5049 	size += 2;
5050 	return size;
5051 }
5052 
r_bin_java_invokedynamic_cp_new(RBinJavaObj * bin,ut8 * buffer,ut64 sz)5053 R_API RBinJavaCPTypeObj *r_bin_java_invokedynamic_cp_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz) {
5054 	ut8 tag = buffer[0];
5055 	RBinJavaCPTypeObj *obj;
5056 	int quick_check = r_bin_java_quick_check (R_BIN_JAVA_CP_INVOKEDYNAMIC, tag, sz, "RBinJavaCPTypeMethodHandle");
5057 	if (quick_check > 0) {
5058 		return NULL;
5059 	}
5060 	if ((obj = R_NEW0 (RBinJavaCPTypeObj))) {
5061 		obj->metas = R_NEW0 (RBinJavaMetaInfo);
5062 		obj->metas->type_info = (void *) &R_BIN_JAVA_CP_METAS[tag];
5063 		obj->name = r_str_dup (NULL, (const char *) R_BIN_JAVA_CP_METAS[tag].name);;
5064 		obj->tag = tag;
5065 		obj->info.cp_invoke_dynamic.bootstrap_method_attr_index = R_BIN_JAVA_USHORT (buffer, 1);
5066 		obj->info.cp_invoke_dynamic.name_and_type_index = R_BIN_JAVA_USHORT (buffer, 3);
5067 	}
5068 	return obj;
5069 }
5070 
r_bin_java_check_reset_cp_obj(RBinJavaCPTypeObj * cp_obj,ut8 tag)5071 R_API int r_bin_java_check_reset_cp_obj(RBinJavaCPTypeObj *cp_obj, ut8 tag) {
5072 	bool res = false;
5073 	if (tag < R_BIN_JAVA_CP_METAS_SZ) {
5074 		if (tag != cp_obj->tag) {
5075 			if (cp_obj->tag == R_BIN_JAVA_CP_UTF8) {
5076 				R_FREE (cp_obj->info.cp_utf8.bytes);
5077 				cp_obj->info.cp_utf8.length = 0;
5078 				R_FREE (cp_obj->name);
5079 			}
5080 			cp_obj->tag = tag;
5081 			cp_obj->metas->type_info = (void *) &R_BIN_JAVA_CP_METAS[tag];
5082 			cp_obj->name = strdup (R_BIN_JAVA_CP_METAS[tag].name);
5083 			res = true;
5084 		} else {
5085 			eprintf ("Invalid tag\n");
5086 		}
5087 	} else {
5088 		eprintf ("Invalid tag '%d'.\n", tag);
5089 	}
5090 	return res;
5091 }
5092 
r_bin_java_cp_get_4bytes(ut8 tag,ut32 * out_sz,const ut8 * buf,const ut64 len)5093 R_API ut8 *r_bin_java_cp_get_4bytes(ut8 tag, ut32 *out_sz, const ut8 *buf, const ut64 len) {
5094 	ut8 *buffer = malloc (5);
5095 	if (!buffer) {
5096 		return NULL;
5097 	}
5098 	ut32 val = 0;
5099 	if (!buffer || len < 4) {
5100 		if (out_sz) {
5101 			*out_sz = 0;
5102 		}
5103 		free (buffer);
5104 		return NULL;
5105 	}
5106 	buffer[0] = tag;
5107 	val = R_BIN_JAVA_UINT (buf, 0);
5108 	memcpy (buffer + 1, (const char *) &val, 4);
5109 	*out_sz = 5;
5110 	return buffer;
5111 }
5112 
r_bin_java_cp_get_8bytes(ut8 tag,ut32 * out_sz,const ut8 * buf,const ut64 len)5113 R_API ut8 *r_bin_java_cp_get_8bytes(ut8 tag, ut32 *out_sz, const ut8 *buf, const ut64 len) {
5114 	ut8 *buffer = malloc (10);
5115 	if (!buffer) {
5116 		return NULL;
5117 	}
5118 	ut64 val = 0;
5119 	if (len < 8) {
5120 		*out_sz = 0;
5121 		free (buffer);
5122 		return NULL;
5123 	}
5124 	buffer[0] = tag;
5125 	val = r_bin_java_raw_to_long (buf, 0);
5126 	memcpy (buffer + 1, (const char *) &val, 8);
5127 	*out_sz = 9;
5128 	return buffer;
5129 }
5130 
r_bin_java_cp_append_classref_and_name(RBinJavaObj * bin,ut32 * out_sz,const char * classname,const ut32 classname_len)5131 R_API ut8 *r_bin_java_cp_append_classref_and_name(RBinJavaObj *bin, ut32 *out_sz, const char *classname, const ut32 classname_len) {
5132 	ut16 use_name_idx = bin->cp_idx + 1;
5133 	ut8 *bytes = NULL, *name_bytes = NULL;
5134 	name_bytes = r_bin_java_cp_get_utf8 (R_BIN_JAVA_CP_UTF8, out_sz, (const ut8 *) classname, classname_len);
5135 	if (*out_sz > 0 && name_bytes) {
5136 		ut8 *idx_addr = (ut8 *) &use_name_idx;
5137 		bytes = malloc (*out_sz + 3);
5138 		memcpy (bytes, name_bytes, *out_sz);
5139 		bytes[*out_sz + 0] = R_BIN_JAVA_CP_CLASS;
5140 		bytes[*out_sz + 1] = idx_addr[1];
5141 		bytes[*out_sz + 2] = idx_addr[0];
5142 		*out_sz += 3;
5143 	}
5144 	free (name_bytes);
5145 	return bytes;
5146 }
5147 
r_bin_java_cp_get_fref_bytes(RBinJavaObj * bin,ut32 * out_sz,ut8 tag,ut16 cn_idx,ut16 fn_idx,ut16 ft_idx)5148 R_API ut8 *r_bin_java_cp_get_fref_bytes(RBinJavaObj *bin, ut32 *out_sz, ut8 tag, ut16 cn_idx, ut16 fn_idx, ut16 ft_idx) {
5149 	ut8 *bytes = NULL, *fnt_bytes = NULL;
5150 	RBinJavaCPTypeObj *ref_cp_obj = NULL;
5151 	ut16 fnt_idx = 0, cref_idx = 0;
5152 	ut32 fnt_len = 0;
5153 	ut16 ref_cp_obj_idx = r_bin_java_find_cp_class_ref_from_name_idx (bin, cn_idx);
5154 	if (!ref_cp_obj_idx) {
5155 		return NULL;
5156 	}
5157 	ref_cp_obj = r_bin_java_get_item_from_bin_cp_list (bin, ref_cp_obj_idx);
5158 	if (ref_cp_obj) {
5159 		cref_idx = ref_cp_obj->idx;
5160 	}
5161 	ref_cp_obj = r_bin_java_find_cp_name_and_type_info (bin, fn_idx, ft_idx);
5162 	if (ref_cp_obj) {
5163 		fnt_idx = ref_cp_obj->idx;
5164 	} else {
5165 		fnt_bytes = r_bin_java_cp_get_name_type (bin, &fnt_len, fn_idx, ft_idx);
5166 		fnt_idx = bin->cp_idx + 1;
5167 	}
5168 	if (cref_idx && fnt_idx) {
5169 		bytes = r_bin_java_cp_get_fm_ref (bin, out_sz, tag, cref_idx, fnt_idx);
5170 		if (fnt_bytes) {
5171 			ut8 *tbuf = malloc (fnt_len + *out_sz);
5172 			if (!tbuf) {
5173 				free (bytes);
5174 				free (fnt_bytes);
5175 				return NULL;
5176 			}
5177 			// copy the bytes to the new buffer
5178 			memcpy (tbuf, fnt_bytes, fnt_len);
5179 			memcpy (tbuf + fnt_len, bytes, *out_sz);
5180 			// update the values free old buffer
5181 			*out_sz += fnt_len;
5182 			free (bytes);
5183 			bytes = tbuf;
5184 		}
5185 	}
5186 	free (fnt_bytes);
5187 	return bytes;
5188 }
5189 
r_bin_java_cp_get_classref(RBinJavaObj * bin,ut32 * out_sz,const char * classname,const ut32 classname_len,const ut16 name_idx)5190 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) {
5191 	ut16 use_name_idx = -1;
5192 	ut8 *bytes = NULL;
5193 	if (name_idx == (ut16) - 1 && classname && *classname && classname_len > 0) {
5194 		// find class_name_idx by class name
5195 		RList *results = r_bin_java_find_cp_const_by_val_utf8 (bin, (const ut8 *) classname, classname_len);
5196 		if (r_list_length (results) == 1) {
5197 			use_name_idx = (ut16) * ((ut32 *) r_list_get_n (results, 0));
5198 		}
5199 		r_list_free (results);
5200 	} else if (name_idx != (ut16) - 1 && name_idx != 0) {
5201 		use_name_idx = name_idx;
5202 	}
5203 	if (use_name_idx == (ut16) - 1 && classname && *classname && classname_len > 0) {
5204 		bytes = r_bin_java_cp_append_classref_and_name (bin, out_sz, classname, classname_len);
5205 	} else if (use_name_idx != (ut16) - 1) {
5206 		ut8 *idx_addr = (ut8 *) &use_name_idx;
5207 		bytes = malloc (3);
5208 		if (!bytes) {
5209 			return NULL;
5210 		}
5211 		bytes[0] = R_BIN_JAVA_CP_CLASS;
5212 		bytes[1] = idx_addr[1];
5213 		bytes[2] = idx_addr[0];
5214 		*out_sz += 3;
5215 	}
5216 	return bytes;
5217 }
5218 
r_bin_java_cp_get_fm_ref(RBinJavaObj * bin,ut32 * out_sz,ut8 tag,ut16 class_idx,ut16 name_and_type_idx)5219 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) {
5220 	return r_bin_java_cp_get_2_ut16 (bin, out_sz, tag, class_idx, name_and_type_idx);
5221 }
5222 
r_bin_java_cp_get_2_ut16(RBinJavaObj * bin,ut32 * out_sz,ut8 tag,ut16 ut16_one,ut16 ut16_two)5223 R_API ut8 *r_bin_java_cp_get_2_ut16(RBinJavaObj *bin, ut32 *out_sz, ut8 tag, ut16 ut16_one, ut16 ut16_two) {
5224 	ut8 *bytes = malloc (7);
5225 	if (!bytes) {
5226 		return NULL;
5227 	}
5228 	ut8 *idx_addr = NULL;
5229 	bytes[*out_sz] = tag;
5230 	*out_sz += 1;
5231 	idx_addr = (ut8 *) &ut16_one;
5232 	bytes[*out_sz + 1] = idx_addr[1];
5233 	bytes[*out_sz + 2] = idx_addr[0];
5234 	*out_sz += 3;
5235 	idx_addr = (ut8 *) &ut16_two;
5236 	bytes[*out_sz + 1] = idx_addr[1];
5237 	bytes[*out_sz + 2] = idx_addr[0];
5238 	*out_sz += 3;
5239 	return bytes;
5240 }
5241 
r_bin_java_cp_get_name_type(RBinJavaObj * bin,ut32 * out_sz,ut16 name_idx,ut16 type_idx)5242 R_API ut8 *r_bin_java_cp_get_name_type(RBinJavaObj *bin, ut32 *out_sz, ut16 name_idx, ut16 type_idx) {
5243 	return r_bin_java_cp_get_2_ut16 (bin, out_sz, R_BIN_JAVA_CP_NAMEANDTYPE, name_idx, type_idx);
5244 }
5245 
r_bin_java_cp_get_utf8(ut8 tag,ut32 * out_sz,const ut8 * buf,const ut64 len)5246 R_API ut8 *r_bin_java_cp_get_utf8(ut8 tag, ut32 *out_sz, const ut8 *buf, const ut64 len) {
5247 	ut8 *buffer = NULL;
5248 	ut16 sz = 0;
5249 	ut16 t = (ut16) len;
5250 	if (len > 0 && len > (ut16) - 1) {
5251 		*out_sz = 0;
5252 		return NULL;
5253 	}
5254 	sz = R_BIN_JAVA_USHORT (((ut8 *) (ut16 *) &t), 0);
5255 	*out_sz = 3 + t; // tag + sz + bytes
5256 	buffer = malloc (*out_sz + 3);
5257 	if (!buffer) {
5258 		return NULL;
5259 	}
5260 	// XXX - excess bytes are created to ensure null for string operations.
5261 	memset (buffer, 0, *out_sz + 3);
5262 	buffer[0] = tag;
5263 	memcpy (buffer + 1, (const char *) &sz, 2);
5264 	memcpy (buffer + 3, buf, *out_sz - 3);
5265 	return buffer;
5266 }
5267 
r_bin_java_invokedynamic_cp_calc_size(RBinJavaCPTypeObj * obj)5268 R_API ut64 r_bin_java_invokedynamic_cp_calc_size(RBinJavaCPTypeObj *obj) {
5269 	ut64 size = 0;
5270 	size += 1;
5271 	// obj->info.cp_invoke_dynamic.bootstrap_method_attr_index = R_BIN_JAVA_USHORT (buffer, 1);
5272 	size += 2;
5273 	// obj->info.cp_invoke_dynamic.name_and_type_index = R_BIN_JAVA_USHORT (buffer, 3);
5274 	size += 2;
5275 	return size;
5276 }
5277 // End new Constant Pool types
5278 // Start free Constant Pool types
r_bin_java_default_free(void * o)5279 R_API void r_bin_java_default_free(void /* RBinJavaCPTypeObj*/ *o) {
5280 	RBinJavaCPTypeObj *obj = o;
5281 	if (obj) {
5282 		free (obj->metas);
5283 		free (obj->name);
5284 		free (obj->value);
5285 		free (obj);
5286 	}
5287 }
5288 
r_bin_java_utf8_info_free(void * o)5289 R_API void r_bin_java_utf8_info_free(void /* RBinJavaCPTypeObj*/ *o) {
5290 	RBinJavaCPTypeObj *obj = o;
5291 	if (obj) {
5292 		free (obj->name);
5293 		free (obj->metas);
5294 		free (obj->info.cp_utf8.bytes);
5295 		free (obj);
5296 	}
5297 }
5298 // Deallocs for type objects
r_bin_java_obj_free(void * o)5299 R_API void r_bin_java_obj_free(void /*RBinJavaCPTypeObj*/ *o) {
5300 	RBinJavaCPTypeObj *obj = o;
5301 	((RBinJavaCPTypeMetas *) obj->metas->type_info)->allocs->delete_obj (obj);
5302 }
5303 
r_bin_java_print_attr_summary(RBinJavaAttrInfo * attr)5304 R_API void r_bin_java_print_attr_summary(RBinJavaAttrInfo *attr) {
5305 	if (attr == NULL) {
5306 		eprintf ("Attempting to print an invalid RBinJavaAttrInfo *.\n");
5307 		return;
5308 	}
5309 	((RBinJavaAttrMetas *) attr->metas->type_info)->allocs->print_summary (attr);
5310 }
5311 
r_bin_java_print_source_debug_attr_summary(RBinJavaAttrInfo * attr)5312 R_API void r_bin_java_print_source_debug_attr_summary(RBinJavaAttrInfo *attr) {
5313 	ut32 i = 0;
5314 	if (attr == NULL) {
5315 		eprintf ("Attempting to print an invalid RBinJavaSourceDebugExtensionAttr *.\n");
5316 		return;
5317 	}
5318 	Eprintf ("Source Debug Extension Attribute Information:\n");
5319 	Eprintf ("  Attribute Offset: 0x%08"PFMT64x "\n", attr->file_offset);
5320 	Eprintf ("  Attribute Name Index: %d (%s)\n", attr->name_idx, attr->name);
5321 	Eprintf ("  Extension Length: %d\n", attr->length);
5322 	Eprintf ("  Source Debug Extension value: \n");
5323 	for (i = 0; i < attr->length; i++) {
5324 		Eprintf ("%c", attr->info.debug_extensions.debug_extension[i]);
5325 	}
5326 	Eprintf ("\n  Source Debug Extension End\n");
5327 }
5328 
r_bin_java_print_unknown_attr_summary(RBinJavaAttrInfo * attr)5329 R_API void r_bin_java_print_unknown_attr_summary(RBinJavaAttrInfo *attr) {
5330 	if (attr == NULL) {
5331 		eprintf ("Attempting to print an invalid RBinJavaAttrInfo *Unknown.\n");
5332 		return;
5333 	}
5334 	Eprintf ("Unknown Attribute Information:\n");
5335 	Eprintf ("  Attribute Offset: 0x%08"PFMT64x "\n", attr->file_offset);
5336 	Eprintf ("  Attribute Name Index: %d (%s)\n", attr->name_idx, attr->name);
5337 	Eprintf ("  Attribute Length: %d\n", attr->length);
5338 }
5339 
r_bin_java_print_code_exceptions_attr_summary(RBinJavaExceptionEntry * exc_entry)5340 R_API void r_bin_java_print_code_exceptions_attr_summary(RBinJavaExceptionEntry *exc_entry) {
5341 	if (exc_entry == NULL) {
5342 		eprintf ("Attempting to print an invalid RBinJavaExceptionEntry *.\n");
5343 		return;
5344 	}
5345 	Eprintf ("  Exception Table Entry Information\n");
5346 	Eprintf ("    offset:	0x%08"PFMT64x"\n", exc_entry->file_offset);
5347 	Eprintf ("    catch_type: %d\n", exc_entry->catch_type);
5348 	Eprintf ("    start_pc:   0x%04x\n", exc_entry->start_pc);
5349 	Eprintf ("    end_pc:	0x%04x\n", exc_entry->end_pc);
5350 	Eprintf ("    handler_pc: 0x%04x\n", exc_entry->handler_pc);
5351 }
5352 // End free Constant Pool types
r_bin_java_print_code_attr_summary(RBinJavaAttrInfo * attr)5353 R_API void r_bin_java_print_code_attr_summary(RBinJavaAttrInfo *attr) {
5354 	RListIter *iter = NULL, *iter_tmp = NULL;
5355 	RBinJavaExceptionEntry *exc_entry = NULL;
5356 	RBinJavaAttrInfo *_attr = NULL;
5357 	if (!attr) {
5358 		eprintf ("Attempting to print an invalid RBinJavaAttrInfo *Code.\n");
5359 		return;
5360 	}
5361 	Eprintf ("Code Attribute Information:\n");
5362 	Eprintf ("  Attribute Offset: 0x%08"PFMT64x "\n", attr->file_offset);
5363 	Eprintf ("  Attribute Name Index: %d (%s)\n", attr->name_idx, attr->name);
5364 	Eprintf ("  Attribute Length: %d, Attribute Count: %d\n", attr->length, attr->info.code_attr.attributes_count);
5365 	Eprintf ("    Max Stack: %d\n", attr->info.code_attr.max_stack);
5366 	Eprintf ("    Max Locals: %d\n", attr->info.code_attr.max_locals);
5367 	Eprintf ("    Code Length: %d\n", attr->info.code_attr.code_length);
5368 	Eprintf ("    Code At Offset: 0x%08"PFMT64x "\n", (ut64) attr->info.code_attr.code_offset);
5369 	Eprintf ("Code Attribute Exception Table Information:\n");
5370 	Eprintf ("  Exception Table Length: %d\n", attr->info.code_attr.exception_table_length);
5371 	if (attr->info.code_attr.exception_table) {
5372 		// Delete the attr entries
5373 		r_list_foreach_safe (attr->info.code_attr.exception_table, iter, iter_tmp, exc_entry) {
5374 			r_bin_java_print_code_exceptions_attr_summary (exc_entry);
5375 		}
5376 	}
5377 	Eprintf ("  Implicit Method Stack Frame:\n");
5378 	r_bin_java_print_stack_map_frame_summary (attr->info.code_attr.implicit_frame);
5379 	Eprintf ("Code Attribute Attributes Information:\n");
5380 	if (attr->info.code_attr.attributes && attr->info.code_attr.attributes_count > 0) {
5381 		Eprintf ("  Code Attribute Attributes Count: %d\n", attr->info.code_attr.attributes_count);
5382 		r_list_foreach_safe (attr->info.code_attr.attributes, iter, iter_tmp, _attr) {
5383 			r_bin_java_print_attr_summary (_attr);
5384 		}
5385 	}
5386 }
5387 
r_bin_java_print_constant_value_attr_summary(RBinJavaAttrInfo * attr)5388 R_API void r_bin_java_print_constant_value_attr_summary(RBinJavaAttrInfo *attr) {
5389 	if (!attr) {
5390 		eprintf ("Attempting to print an invalid RBinJavaAttrInfo *ConstantValue.\n");
5391 		return;
5392 	}
5393 	Eprintf ("Constant Value Attribute Information:\n");
5394 	Eprintf ("  Attribute Offset: 0x%08"PFMT64x "\n", attr->file_offset);
5395 	Eprintf ("  Attribute Name Index: %d (%s)\n", attr->name_idx, attr->name);
5396 	Eprintf ("  Attribute Length: %d\n", attr->length);
5397 	Eprintf ("  ConstantValue Index: %d\n", attr->info.constant_value_attr.constantvalue_idx);
5398 }
5399 
r_bin_java_print_deprecated_attr_summary(RBinJavaAttrInfo * attr)5400 R_API void r_bin_java_print_deprecated_attr_summary(RBinJavaAttrInfo *attr) {
5401 	if (!attr) {
5402 		eprintf ("Attempting to print an invalid RBinJavaAttrInfo *Deperecated.\n");
5403 		return;
5404 	}
5405 	Eprintf ("Deperecated Attribute Information:\n");
5406 	Eprintf ("  Attribute Offset: 0x%08"PFMT64x "\n", attr->file_offset);
5407 	Eprintf ("  Attribute Name Index: %d (%s)\n", attr->name_idx, attr->name);
5408 	Eprintf ("  Attribute Length: %d\n", attr->length);
5409 }
5410 
r_bin_java_print_enclosing_methods_attr_summary(RBinJavaAttrInfo * attr)5411 R_API void r_bin_java_print_enclosing_methods_attr_summary(RBinJavaAttrInfo *attr) {
5412 	if (!attr) {
5413 		eprintf ("Attempting to print an invalid RBinJavaAttrInfo *Deperecated.\n");
5414 		return;
5415 	}
5416 	Eprintf ("Enclosing Method Attribute Information:\n");
5417 	Eprintf ("  Attribute Offset: 0x%08"PFMT64x "\n", attr->file_offset);
5418 	Eprintf ("  Attribute Name Index: %d (%s)\n", attr->name_idx, attr->name);
5419 	Eprintf ("  Attribute Length: %d\n", attr->length);
5420 	Eprintf ("  Class Info Index : 0x%02x\n", attr->info.enclosing_method_attr.class_idx);
5421 	Eprintf ("  Method Name and Type Index : 0x%02x\n", attr->info.enclosing_method_attr.method_idx);
5422 	Eprintf ("  Class Name : %s\n", attr->info.enclosing_method_attr.class_name);
5423 	Eprintf ("  Method Name and Desc : %s %s\n", attr->info.enclosing_method_attr.method_name, attr->info.enclosing_method_attr.method_descriptor);
5424 }
5425 
r_bin_java_print_exceptions_attr_summary(RBinJavaAttrInfo * attr)5426 R_API void r_bin_java_print_exceptions_attr_summary(RBinJavaAttrInfo *attr) {
5427 	ut32 i = 0;
5428 	if (!attr) {
5429 		eprintf ("Attempting to print an invalid RBinJavaAttrInfo *Exceptions.\n");
5430 		return;
5431 	}
5432 	Eprintf ("Exceptions Attribute Information:\n");
5433 	Eprintf ("  Attribute Offset: 0x%08"PFMT64x "\n", attr->file_offset);
5434 	Eprintf ("  Attribute Name Index: %d (%s)\n", attr->name_idx, attr->name);
5435 	Eprintf ("  Attribute Length: %d\n", attr->length);
5436 	for (i = 0; i < attr->info.exceptions_attr.number_of_exceptions; i++) {
5437 		Eprintf ("  Exceptions Attribute Index[%d]: %d\n", i, attr->info.exceptions_attr.exception_idx_table[i]);
5438 	}
5439 }
5440 
r_bin_java_print_classes_attr_summary(RBinJavaClassesAttribute * icattr)5441 R_API void r_bin_java_print_classes_attr_summary(RBinJavaClassesAttribute *icattr) {
5442 	if (!icattr) {
5443 		eprintf ("Attempting to print an invalid RBinJavaClassesAttribute* (InnerClasses element).\n");
5444 		return;
5445 	}
5446 	eprintf ("   Inner Classes Class Attribute Offset: 0x%08"PFMT64x "\n", icattr->file_offset);
5447 	eprintf ("   Inner Classes Class Attribute Class Name (%d): %s\n", icattr->inner_name_idx, icattr->name);
5448 	eprintf ("   Inner Classes Class Attribute Class inner_class_info_idx: %d\n", icattr->inner_class_info_idx);
5449 	eprintf ("   Inner Classes Class Attribute Class inner_class_access_flags: 0x%02x %s\n", icattr->inner_class_access_flags, icattr->flags_str);
5450 	eprintf ("   Inner Classes Class Attribute Class outer_class_info_idx: %d\n", icattr->outer_class_info_idx);
5451 	eprintf ("   Inner Classes Class Field Information:\n");
5452 	r_bin_java_print_field_summary (icattr->clint_field);
5453 	eprintf ("   Inner Classes Class Field Information:\n");
5454 	r_bin_java_print_field_summary (icattr->clint_field);
5455 	eprintf ("   Inner Classes Class Attr Info Information:\n");
5456 	r_bin_java_print_attr_summary (icattr->clint_attr);
5457 }
5458 
r_bin_java_print_inner_classes_attr_summary(RBinJavaAttrInfo * attr)5459 R_API void r_bin_java_print_inner_classes_attr_summary(RBinJavaAttrInfo *attr) {
5460 	RBinJavaClassesAttribute *icattr;
5461 	RListIter *iter, *iter_tmp;
5462 	if (!attr) {
5463 		eprintf ("Attempting to print an invalid RBinJavaAttrInfo *InnerClasses.\n");
5464 		return;
5465 	}
5466 	Eprintf ("Inner Classes Attribute Information:\n");
5467 	Eprintf ("  Attribute Offset: 0x%08"PFMT64x "\n", attr->file_offset);
5468 	Eprintf ("  Attribute Name Index: %d (%s)\n", attr->name_idx, attr->name);
5469 	Eprintf ("  Attribute Length: %d\n", attr->length);
5470 	r_list_foreach_safe (attr->info.inner_classes_attr.classes, iter, iter_tmp, icattr) {
5471 		r_bin_java_print_classes_attr_summary (icattr);
5472 	}
5473 }
5474 
r_bin_java_print_line_number_attr_summary(RBinJavaLineNumberAttribute * lnattr)5475 R_API void r_bin_java_print_line_number_attr_summary(RBinJavaLineNumberAttribute *lnattr) {
5476 	if (!lnattr) {
5477 		eprintf ("Attempting to print an invalid RBinJavaLineNumberAttribute *.\n");
5478 		return;
5479 	}
5480 	Eprintf ("  Line Number Attribute Offset: 0x%08"PFMT64x "\n", lnattr->file_offset);
5481 	Eprintf ("  Line Number Attribute StartPC: %d\n", lnattr->start_pc);
5482 	Eprintf ("  Line Number Attribute LineNumber: %d\n", lnattr->line_number);
5483 }
5484 
r_bin_java_print_line_number_table_attr_summary(RBinJavaAttrInfo * attr)5485 R_API void r_bin_java_print_line_number_table_attr_summary(RBinJavaAttrInfo *attr) {
5486 	RBinJavaLineNumberAttribute *lnattr;
5487 	RListIter *iter, *iter_tmp;
5488 	if (!attr) {
5489 		eprintf ("Attempting to print an invalid RBinJavaAttrInfo *LineNumberTable.\n");
5490 		return;
5491 	}
5492 	Eprintf ("Line Number Table Attribute Information:\n");
5493 	Eprintf ("  Attribute Offset: 0x%08"PFMT64x "\n", attr->file_offset);
5494 	Eprintf ("  Attribute Name Index: %d (%s)\n", attr->name_idx, attr->name);
5495 	Eprintf ("  Attribute Length: %d\n", attr->length);
5496 	r_list_foreach_safe (attr->info.line_number_table_attr.line_number_table, iter, iter_tmp, lnattr) {
5497 		r_bin_java_print_line_number_attr_summary (lnattr);
5498 	}
5499 }
5500 
r_bin_java_print_local_variable_attr_summary(RBinJavaLocalVariableAttribute * lvattr)5501 R_API void r_bin_java_print_local_variable_attr_summary(RBinJavaLocalVariableAttribute *lvattr) {
5502 	if (!lvattr) {
5503 		eprintf ("Attempting to print an invalid RBinJavaLocalVariableAttribute *.\n");
5504 		return;
5505 	}
5506 	Eprintf ("  Local Variable Attribute offset: 0x%08"PFMT64x "\n", lvattr->file_offset);
5507 	Eprintf ("  Local Variable Attribute start_pc: %d\n", lvattr->start_pc);
5508 	Eprintf ("  Local Variable Attribute Length: %d\n", lvattr->length);
5509 	Eprintf ("  Local Variable Attribute name_idx: %d\n", lvattr->name_idx);
5510 	Eprintf ("  Local Variable Attribute name: %s\n", lvattr->name);
5511 	Eprintf ("  Local Variable Attribute descriptor_idx: %d\n", lvattr->descriptor_idx);
5512 	Eprintf ("  Local Variable Attribute descriptor: %s\n", lvattr->descriptor);
5513 	Eprintf ("  Local Variable Attribute index: %d\n", lvattr->index);
5514 }
5515 
r_bin_java_print_local_variable_table_attr_summary(RBinJavaAttrInfo * attr)5516 R_API void r_bin_java_print_local_variable_table_attr_summary(RBinJavaAttrInfo *attr) {
5517 	RBinJavaLocalVariableAttribute *lvattr;
5518 	RListIter *iter, *iter_tmp;
5519 	if (attr == NULL) {
5520 		eprintf ("Attempting to print an invalid RBinJavaAttrInfo *LocalVariableTable.\n");
5521 		return;
5522 	}
5523 	Eprintf ("Local Variable Table Attribute Information:\n");
5524 	Eprintf ("  Attribute Offset: 0x%08"PFMT64x "\n", attr->file_offset);
5525 	Eprintf ("  Attribute Name Index: %d (%s)\n", attr->name_idx, attr->name);
5526 	Eprintf ("  Attribute Length: %d\n", attr->length);
5527 	r_list_foreach_safe (attr->info.local_variable_table_attr.local_variable_table, iter, iter_tmp, lvattr) {
5528 		r_bin_java_print_local_variable_attr_summary (lvattr);
5529 	}
5530 }
5531 
r_bin_java_print_local_variable_type_attr_summary(RBinJavaLocalVariableTypeAttribute * lvattr)5532 R_API void r_bin_java_print_local_variable_type_attr_summary(RBinJavaLocalVariableTypeAttribute *lvattr) {
5533 	if (!lvattr) {
5534 		eprintf ("Attempting to print an invalid RBinJavaLocalVariableTypeAttribute *.\n");
5535 		return;
5536 	}
5537 	eprintf ("   Local Variable Type Attribute offset: 0x%08"PFMT64x "\n", lvattr->file_offset);
5538 	eprintf ("   Local Variable Type Attribute start_pc: %d\n", lvattr->start_pc);
5539 	eprintf ("   Local Variable Type Attribute Length: %d\n", lvattr->length);
5540 	eprintf ("   Local Variable Type Attribute name_idx: %d\n", lvattr->name_idx);
5541 	eprintf ("   Local Variable Type Attribute name: %s\n", lvattr->name);
5542 	eprintf ("   Local Variable Type Attribute signature_idx: %d\n", lvattr->signature_idx);
5543 	eprintf ("   Local Variable Type Attribute signature: %s\n", lvattr->signature);
5544 	eprintf ("   Local Variable Type Attribute index: %d\n", lvattr->index);
5545 }
5546 
r_bin_java_print_local_variable_type_table_attr_summary(RBinJavaAttrInfo * attr)5547 R_API void r_bin_java_print_local_variable_type_table_attr_summary(RBinJavaAttrInfo *attr) {
5548 	RBinJavaLocalVariableTypeAttribute *lvtattr;
5549 	RListIter *iter, *iter_tmp;
5550 	if (!attr) {
5551 		eprintf ("Attempting to print an invalid RBinJavaAttrInfo *LocalVariableTable.\n");
5552 		return;
5553 	}
5554 	eprintf ("Local Variable Type Table Attribute Information:\n");
5555 	eprintf ("   Attribute Offset: 0x%08"PFMT64x "\n", attr->file_offset);
5556 	eprintf ("   Attribute Name Index: %d (%s)\n", attr->name_idx, attr->name);
5557 	eprintf ("   Attribute Length: %d\n", attr->length);
5558 	r_list_foreach_safe (attr->info.local_variable_type_table_attr.local_variable_table, iter, iter_tmp, lvtattr) {
5559 		r_bin_java_print_local_variable_type_attr_summary (lvtattr);
5560 	}
5561 }
5562 
r_bin_java_print_signature_attr_summary(RBinJavaAttrInfo * attr)5563 R_API void r_bin_java_print_signature_attr_summary(RBinJavaAttrInfo *attr) {
5564 	if (!attr) {
5565 		eprintf ("Attempting to print an invalid RBinJavaAttrInfo *SignatureAttr.\n");
5566 		return;
5567 	}
5568 	Eprintf ("Signature Attribute Information:\n");
5569 	Eprintf ("  Attribute Offset: 0x%08"PFMT64x "\n", attr->file_offset);
5570 	Eprintf ("  Attribute Name Index: %d (%s)\n", attr->name_idx, attr->name);
5571 	Eprintf ("  Attribute Length: %d\n", attr->length);
5572 	Eprintf ("  Signature UTF8 Index: %d\n", attr->info.signature_attr.signature_idx);
5573 	Eprintf ("  Signature string: %s\n", attr->info.signature_attr.signature);
5574 }
5575 
r_bin_java_print_source_code_file_attr_summary(RBinJavaAttrInfo * attr)5576 R_API void r_bin_java_print_source_code_file_attr_summary(RBinJavaAttrInfo *attr) {
5577 	if (!attr) {
5578 		eprintf ("Attempting to print an invalid RBinJavaAttrInfo *SourceFile.\n");
5579 		return;
5580 	}
5581 	Eprintf ("Source File Attribute Information:\n");
5582 	Eprintf ("  Attribute Offset: 0x%08"PFMT64x "\n", attr->file_offset);
5583 	Eprintf ("  Attribute Name Index: %d (%s)\n", attr->name_idx, attr->name);
5584 	Eprintf ("  Attribute Length: %d\n", attr->length);
5585 	Eprintf ("  Source File Index: %d\n", attr->info.source_file_attr.sourcefile_idx);
5586 }
5587 
r_bin_java_print_synthetic_attr_summary(RBinJavaAttrInfo * attr)5588 R_API void r_bin_java_print_synthetic_attr_summary(RBinJavaAttrInfo *attr) {
5589 	if (attr == NULL) {
5590 		eprintf ("Attempting to print an invalid RBinJavaAttrInfo *Synthetic.\n");
5591 		return;
5592 	}
5593 	Eprintf ("Synthetic Attribute Information:\n");
5594 	Eprintf ("  Attribute Offset: 0x%08"PFMT64x "\n", attr->file_offset);
5595 	Eprintf ("  Attribute Name Index: %d (%s)\n", attr->name_idx, attr->name);
5596 	Eprintf ("  Attribute Length: %d\n", attr->length);
5597 	Eprintf ("  Attribute Index: %d\n", attr->info.source_file_attr.sourcefile_idx);
5598 }
5599 
r_bin_java_print_stack_map_table_attr_summary(RBinJavaAttrInfo * attr)5600 R_API void r_bin_java_print_stack_map_table_attr_summary(RBinJavaAttrInfo *attr) {
5601 	RListIter *iter, *iter_tmp;
5602 	RList *ptrList;
5603 	RBinJavaStackMapFrame *frame;
5604 	if (attr == NULL) {
5605 		eprintf ("Attempting to print an invalid RBinJavaStackMapTableAttr*  .\n");
5606 		return;
5607 	}
5608 	Eprintf ("StackMapTable Attribute Information:\n");
5609 	Eprintf ("  Attribute Offset: 0x%08"PFMT64x "\n", attr->file_offset);
5610 	Eprintf ("  Attribute Name Index: %d (%s)\n", attr->name_idx, attr->name);
5611 	Eprintf ("  Attribute Length: %d\n", attr->length);
5612 	Eprintf ("  StackMapTable Method Code Size: 0x%08x\n", attr->info.stack_map_table_attr.code_size);
5613 	Eprintf ("  StackMapTable Frame Entries: 0x%08x\n", attr->info.stack_map_table_attr.number_of_entries);
5614 	Eprintf ("  StackMapTable Frames:\n");
5615 	ptrList = attr->info.stack_map_table_attr.stack_map_frame_entries;
5616 	if (ptrList) {
5617 		r_list_foreach_safe (ptrList, iter, iter_tmp, frame) {
5618 			r_bin_java_print_stack_map_frame_summary (frame);
5619 		}
5620 	}
5621 }
5622 
r_bin_java_print_stack_map_frame_summary(RBinJavaStackMapFrame * obj)5623 R_API void r_bin_java_print_stack_map_frame_summary(RBinJavaStackMapFrame *obj) {
5624 	RListIter *iter, *iter_tmp;
5625 	RList *ptrList;
5626 	RBinJavaVerificationObj *ver_obj;
5627 	if (obj == NULL) {
5628 		eprintf ("Attempting to print an invalid RBinJavaStackMapFrame*  .\n");
5629 		return;
5630 	}
5631 	Eprintf ("Stack Map Frame Information\n");
5632 	Eprintf ("  Tag Value = 0x%02x Name: %s\n", obj->tag, ((RBinJavaStackMapFrameMetas *) obj->metas->type_info)->name);
5633 	Eprintf ("  Offset: 0x%08"PFMT64x "\n", obj->file_offset);
5634 	Eprintf ("  Local Variable Count = 0x%04x\n", obj->number_of_locals);
5635 	Eprintf ("  Stack Items Count = 0x%04x\n", obj->number_of_stack_items);
5636 	Eprintf ("  Local Variables:\n");
5637 	ptrList = obj->local_items;
5638 	r_list_foreach_safe (ptrList, iter, iter_tmp, ver_obj) {
5639 		r_bin_java_print_verification_info_summary (ver_obj);
5640 	}
5641 	Eprintf ("  Stack Items:\n");
5642 	ptrList = obj->stack_items;
5643 	r_list_foreach_safe (ptrList, iter, iter_tmp, ver_obj) {
5644 		r_bin_java_print_verification_info_summary (ver_obj);
5645 	}
5646 }
5647 
r_bin_java_print_verification_info_summary(RBinJavaVerificationObj * obj)5648 R_API void r_bin_java_print_verification_info_summary(RBinJavaVerificationObj *obj) {
5649 	ut8 tag_value = R_BIN_JAVA_STACKMAP_UNKNOWN;
5650 	if (obj == NULL) {
5651 		eprintf ("Attempting to print an invalid RBinJavaVerificationObj*  .\n");
5652 		return;
5653 	}
5654 	if (obj->tag < R_BIN_JAVA_STACKMAP_UNKNOWN) {
5655 		tag_value = obj->tag;
5656 	}
5657 	Eprintf ("Verification Information\n");
5658 	Eprintf ("  Offset: 0x%08"PFMT64x "", obj->file_offset);
5659 	Eprintf ("  Tag Value = 0x%02x\n", obj->tag);
5660 	Eprintf ("  Name = %s\n", R_BIN_JAVA_VERIFICATION_METAS[tag_value].name);
5661 	if (obj->tag == R_BIN_JAVA_STACKMAP_OBJECT) {
5662 		Eprintf ("  Object Constant Pool Index = 0x%x\n", obj->info.obj_val_cp_idx);
5663 	} else if (obj->tag == R_BIN_JAVA_STACKMAP_UNINIT) {
5664 		Eprintf ("  Uninitialized Object offset in code = 0x%x\n", obj->info.uninit_offset);
5665 	}
5666 }
5667 
r_bin_java_print_field_summary(RBinJavaField * field)5668 R_API void r_bin_java_print_field_summary(RBinJavaField *field) {
5669 	RBinJavaAttrInfo *attr;
5670 	RListIter *iter, *iter_tmp;
5671 	if (field) {
5672 		if (field->type == R_BIN_JAVA_FIELD_TYPE_METHOD) {
5673 			r_bin_java_print_method_summary (field);
5674 		} else {
5675 #if 0
5676 			r_bin_java_print_interface_summary (field);
5677 			return;
5678 		} * /
5679 #endif
5680 			Eprintf ("Field Summary Information:\n");
5681 			Eprintf ("  File Offset: 0x%08"PFMT64x "\n", field->file_offset);
5682 			Eprintf ("  Name Index: %d (%s)\n", field->name_idx, field->name);
5683 			Eprintf ("  Descriptor Index: %d (%s)\n", field->descriptor_idx, field->descriptor);
5684 			Eprintf ("  Access Flags: 0x%02x (%s)\n", field->flags, field->flags_str);
5685 			Eprintf ("  Field Attributes Count: %d\n", field->attr_count);
5686 			Eprintf ("  Field Attributes:\n");
5687 			r_list_foreach_safe (field->attributes, iter, iter_tmp, attr) {
5688 				r_bin_java_print_attr_summary (attr);
5689 			}
5690 		}
5691 	} else {
5692 		eprintf ("Attempting to print an invalid RBinJavaField* Field.\n");
5693 	}
5694 }
5695 
r_bin_java_print_method_summary(RBinJavaField * field)5696 R_API void r_bin_java_print_method_summary(RBinJavaField *field) {
5697 	RBinJavaAttrInfo *attr;
5698 	RListIter *iter, *iter_tmp;
5699 	if (field == NULL) {
5700 		eprintf ("Attempting to print an invalid RBinJavaField* Method.\n");
5701 		return;
5702 	}
5703 	Eprintf ("Method Summary Information:\n");
5704 	Eprintf ("  File Offset: 0x%08"PFMT64x "\n", field->file_offset);
5705 	Eprintf ("  Name Index: %d (%s)\n", field->name_idx, field->name);
5706 	Eprintf ("  Descriptor Index: %d (%s)\n", field->descriptor_idx, field->descriptor);
5707 	Eprintf ("  Access Flags: 0x%02x (%s)\n", field->flags, field->flags_str);
5708 	Eprintf ("  Method Attributes Count: %d\n", field->attr_count);
5709 	Eprintf ("  Method Attributes:\n");
5710 	r_list_foreach_safe (field->attributes, iter, iter_tmp, attr) {
5711 		r_bin_java_print_attr_summary (attr);
5712 	}
5713 }
5714 /*
5715    R_API void r_bin_java_print_interface_summary(ut16 idx) {//RBinJavaField *field) {
5716         RBinJavaAttrInfo *attr;
5717         RBinJavaCPTypeObj *class_info;
5718         RListIter *iter, *iter_tmp;
5719         if (field == NULL) {
5720                 eprintf ("Attempting to print an invalid RBinJavaField* Interface.\n");
5721                 return;
5722         }
5723         eprintf ("Interface Summary Information:\n");
5724         eprintf ("	File offset: 0x%08"PFMT64x"", field->file_offset);
5725         eprintf ("	Access Flags: %d\n", field->flags);
5726         eprintf ("	Name Index: %d (%s)\n", field->name_idx, field->name);
5727         eprintf ("	Descriptor Index: %d (%s)\n", field->descriptor_idx, field->descriptor);
5728         eprintf ("	Interface Attributes Count: %d\n", field->attr_count);
5729         eprintf ("	Interface Attributes:\n");
5730         r_list_foreach_safe (field->attributes, iter, iter_tmp, attr) {
5731                 r_bin_java_print_attr_summary(attr);
5732         }
5733    }
5734  */
r_bin_java_print_interfacemethodref_cp_summary(RBinJavaCPTypeObj * obj)5735 R_API void r_bin_java_print_interfacemethodref_cp_summary(RBinJavaCPTypeObj *obj) {
5736 	if (obj == NULL) {
5737 		eprintf ("Attempting to print an invalid RBinJavaCPTypeObj*  InterfaceMethodRef.\n");
5738 		return;
5739 	}
5740 	eprintf ("InterfaceMethodRef ConstantPool Type (%d) ", obj->metas->ord);
5741 	eprintf ("	Offset: 0x%08"PFMT64x"", obj->file_offset);
5742 	eprintf ("	Class Index = %d\n", obj->info.cp_interface.class_idx);
5743 	eprintf ("	Name and type Index = %d\n", obj->info.cp_interface.name_and_type_idx);
5744 }
5745 
r_bin_java_print_interfacemethodref_cp_stringify(RBinJavaCPTypeObj * obj)5746 R_API char *r_bin_java_print_interfacemethodref_cp_stringify(RBinJavaCPTypeObj *obj) {
5747 	ut32 size = 255, consumed = 0;
5748 	char *value = malloc (size);
5749 	if (value) {
5750 		memset (value, 0, size);
5751 		consumed = snprintf (value, size, "%d.0x%04"PFMT64x ".%s.%d.%d",
5752 			obj->metas->ord, obj->file_offset + obj->loadaddr, ((RBinJavaCPTypeMetas *) obj->metas->type_info)->name,
5753 			obj->info.cp_interface.class_idx, obj->info.cp_interface.name_and_type_idx);
5754 		if (consumed >= size - 1) {
5755 			free (value);
5756 			size += size >> 1;
5757 			value = malloc (size);
5758 			if (value) {
5759 				memset (value, 0, size);
5760 				(void)snprintf (value, size, "%d.0x%04"PFMT64x ".%s.%d.%d",
5761 					obj->metas->ord, obj->file_offset + obj->loadaddr, ((RBinJavaCPTypeMetas *) obj->metas->type_info)->name,
5762 					obj->info.cp_interface.class_idx, obj->info.cp_interface.name_and_type_idx);
5763 			}
5764 		}
5765 	}
5766 	return value;
5767 }
5768 
r_bin_java_print_methodhandle_cp_summary(RBinJavaCPTypeObj * obj)5769 R_API void r_bin_java_print_methodhandle_cp_summary(RBinJavaCPTypeObj *obj) {
5770 	ut8 ref_kind;
5771 	if (obj == NULL) {
5772 		eprintf ("Attempting to print an invalid RBinJavaCPTypeObj*  RBinJavaCPTypeMethodHandle.\n");
5773 		return;
5774 	}
5775 	ref_kind = obj->info.cp_method_handle.reference_kind;
5776 	eprintf ("MethodHandle ConstantPool Type (%d) ", obj->metas->ord);
5777 	eprintf ("	Offset: 0x%08"PFMT64x"", obj->file_offset);
5778 	eprintf ("	Reference Kind = (0x%02x) %s\n", ref_kind, R_BIN_JAVA_REF_METAS[ref_kind].name);
5779 	eprintf ("	Reference Index = %d\n", obj->info.cp_method_handle.reference_index);
5780 }
5781 
r_bin_java_print_methodhandle_cp_stringify(RBinJavaCPTypeObj * obj)5782 R_API char *r_bin_java_print_methodhandle_cp_stringify(RBinJavaCPTypeObj *obj) {
5783 	ut32 size = 255, consumed = 0;
5784 	char *value = malloc (size);
5785 	ut8 ref_kind = obj->info.cp_method_handle.reference_kind;
5786 	if (value) {
5787 		memset (value, 0, size);
5788 		consumed = snprintf (value, size, "%d.0x%04"PFMT64x ".%s.%s.%d",
5789 			obj->metas->ord, obj->file_offset + obj->loadaddr, ((RBinJavaCPTypeMetas *) obj->metas->type_info)->name,
5790 			R_BIN_JAVA_REF_METAS[ref_kind].name, obj->info.cp_method_handle.reference_index);
5791 		if (consumed >= size - 1) {
5792 			free (value);
5793 			size += size >> 1;
5794 			value = malloc (size);
5795 			if (value) {
5796 				memset (value, 0, size);
5797 				(void)snprintf (value, size, "%d.0x%04"PFMT64x ".%s.%s.%d",
5798 					obj->metas->ord, obj->file_offset + obj->loadaddr, ((RBinJavaCPTypeMetas *) obj->metas->type_info)->name,
5799 					R_BIN_JAVA_REF_METAS[ref_kind].name, obj->info.cp_method_handle.reference_index);
5800 			}
5801 		}
5802 	}
5803 	return value;
5804 }
5805 
r_bin_java_print_methodtype_cp_summary(RBinJavaCPTypeObj * obj)5806 R_API void r_bin_java_print_methodtype_cp_summary(RBinJavaCPTypeObj *obj) {
5807 	if (obj == NULL) {
5808 		eprintf ("Attempting to print an invalid RBinJavaCPTypeObj*  RBinJavaCPTypeMethodType.\n");
5809 		return;
5810 	}
5811 	Eprintf ("MethodType ConstantPool Type (%d) ", obj->metas->ord);
5812 	Eprintf ("  Offset: 0x%08"PFMT64x "", obj->file_offset);
5813 	Eprintf ("  Descriptor Index = 0x%02x\n", obj->info.cp_method_type.descriptor_index);
5814 }
5815 
r_bin_java_print_methodtype_cp_stringify(RBinJavaCPTypeObj * obj)5816 R_API char *r_bin_java_print_methodtype_cp_stringify(RBinJavaCPTypeObj *obj) {
5817 	ut32 size = 255, consumed = 0;
5818 	char *value = malloc (size);
5819 	if (value) {
5820 		memset (value, 0, size);
5821 		consumed = snprintf (value, size, "%d.0x%04"PFMT64x ".%s.%d",
5822 			obj->metas->ord, obj->file_offset + obj->loadaddr, ((RBinJavaCPTypeMetas *) obj->metas->type_info)->name,
5823 			obj->info.cp_method_type.descriptor_index);
5824 		if (consumed >= size - 1) {
5825 			free (value);
5826 			size += size >> 1;
5827 			value = malloc (size);
5828 			if (value) {
5829 				memset (value, 0, size);
5830 				(void)snprintf (value, size, "%d.0x%04"PFMT64x ".%s.%d",
5831 					obj->metas->ord, obj->file_offset + obj->loadaddr, ((RBinJavaCPTypeMetas *) obj->metas->type_info)->name,
5832 					obj->info.cp_method_type.descriptor_index);
5833 			}
5834 		}
5835 	}
5836 	return value;
5837 }
5838 
r_bin_java_print_invokedynamic_cp_summary(RBinJavaCPTypeObj * obj)5839 R_API void r_bin_java_print_invokedynamic_cp_summary(RBinJavaCPTypeObj *obj) {
5840 	if (obj == NULL) {
5841 		eprintf ("Attempting to print an invalid RBinJavaCPTypeObj*  RBinJavaCPTypeInvokeDynamic.\n");
5842 		return;
5843 	}
5844 	eprintf ("InvokeDynamic ConstantPool Type (%d) ", obj->metas->ord);
5845 	eprintf ("	Offset: 0x%08"PFMT64x"", obj->file_offset);
5846 	eprintf ("	Bootstrap Method Attr Index = (0x%02x)\n", obj->info.cp_invoke_dynamic.bootstrap_method_attr_index);
5847 	eprintf ("	Bootstrap Name and Type Index = (0x%02x)\n", obj->info.cp_invoke_dynamic.name_and_type_index);
5848 }
5849 
r_bin_java_print_invokedynamic_cp_stringify(RBinJavaCPTypeObj * obj)5850 R_API char *r_bin_java_print_invokedynamic_cp_stringify(RBinJavaCPTypeObj *obj) {
5851 	ut32 size = 255, consumed = 0;
5852 	char *value = malloc (size);
5853 	if (value) {
5854 		memset (value, 0, size);
5855 		consumed = snprintf (value, size, "%d.0x%04"PFMT64x ".%s.%d.%d",
5856 			obj->metas->ord, obj->file_offset + obj->loadaddr, ((RBinJavaCPTypeMetas *) obj->metas->type_info)->name,
5857 			obj->info.cp_invoke_dynamic.bootstrap_method_attr_index,
5858 			obj->info.cp_invoke_dynamic.name_and_type_index);
5859 		if (consumed >= size - 1) {
5860 			free (value);
5861 			size += size >> 1;
5862 			value = malloc (size);
5863 			if (value) {
5864 				memset (value, 0, size);
5865 				(void)snprintf (value, size, "%d.0x%04"PFMT64x ".%s.%d.%d",
5866 					obj->metas->ord, obj->file_offset + obj->loadaddr, ((RBinJavaCPTypeMetas *) obj->metas->type_info)->name,
5867 					obj->info.cp_invoke_dynamic.bootstrap_method_attr_index,
5868 					obj->info.cp_invoke_dynamic.name_and_type_index);
5869 			}
5870 		}
5871 	}
5872 	return value;
5873 }
5874 
r_bin_java_print_methodref_cp_summary(RBinJavaCPTypeObj * obj)5875 R_API void r_bin_java_print_methodref_cp_summary(RBinJavaCPTypeObj *obj) {
5876 	if (obj == NULL) {
5877 		eprintf ("Attempting to print an invalid RBinJavaCPTypeObj*  MethodRef.\n");
5878 		return;
5879 	}
5880 	eprintf ("MethodRef ConstantPool Type (%d) ", obj->metas->ord);
5881 	eprintf ("	Offset: 0x%08"PFMT64x"", obj->file_offset);
5882 	eprintf ("	Class Index = %d\n", obj->info.cp_method.class_idx);
5883 	eprintf ("	Name and type Index = %d\n", obj->info.cp_method.name_and_type_idx);
5884 }
5885 
r_bin_java_print_methodref_cp_stringify(RBinJavaCPTypeObj * obj)5886 R_API char *r_bin_java_print_methodref_cp_stringify(RBinJavaCPTypeObj *obj) {
5887 	ut32 size = 255, consumed = 0;
5888 	char *value = malloc (size);
5889 	if (value) {
5890 		memset (value, 0, size);
5891 		consumed = snprintf (value, size, "%d.0x%04"PFMT64x ".%s.%d.%d",
5892 			obj->metas->ord, obj->file_offset + obj->loadaddr, ((RBinJavaCPTypeMetas *) obj->metas->type_info)->name,
5893 			obj->info.cp_method.class_idx,
5894 			obj->info.cp_method.name_and_type_idx);
5895 		if (consumed >= size - 1) {
5896 			free (value);
5897 			size += size >> 1;
5898 			value = malloc (size);
5899 			if (value) {
5900 				memset (value, 0, size);
5901 				(void)snprintf (value, size, "%d.0x%04"PFMT64x ".%s.%d.%d",
5902 					obj->metas->ord, obj->file_offset + obj->loadaddr, ((RBinJavaCPTypeMetas *) obj->metas->type_info)->name,
5903 					obj->info.cp_method.class_idx,
5904 					obj->info.cp_method.name_and_type_idx);
5905 			}
5906 		}
5907 	}
5908 	return value;
5909 }
5910 
r_bin_java_print_fieldref_cp_summary(RBinJavaCPTypeObj * obj)5911 R_API void r_bin_java_print_fieldref_cp_summary(RBinJavaCPTypeObj *obj) {
5912 	if (obj == NULL) {
5913 		eprintf ("Attempting to print an invalid RBinJavaCPTypeObj*  FieldRef.\n");
5914 		return;
5915 	}
5916 	eprintf ("FieldRef ConstantPool Type (%d) ", obj->metas->ord);
5917 	eprintf ("	Offset: 0x%08"PFMT64x"", obj->file_offset);
5918 	eprintf ("	Class Index = %d\n", obj->info.cp_field.class_idx);
5919 	eprintf ("	Name and type Index = %d\n", obj->info.cp_field.name_and_type_idx);
5920 }
5921 
r_bin_java_print_fieldref_cp_stringify(RBinJavaCPTypeObj * obj)5922 R_API char *r_bin_java_print_fieldref_cp_stringify(RBinJavaCPTypeObj *obj) {
5923 	ut32 size = 255, consumed = 0;
5924 	char *value = malloc (size);
5925 	if (value) {
5926 		memset (value, 0, size);
5927 		consumed = snprintf (value, size, "%d.0x%04"PFMT64x ".%s.%d.%d",
5928 			obj->metas->ord, obj->file_offset + obj->loadaddr, ((RBinJavaCPTypeMetas *) obj->metas->type_info)->name,
5929 			obj->info.cp_field.class_idx,
5930 			obj->info.cp_field.name_and_type_idx);
5931 		if (consumed >= size - 1) {
5932 			free (value);
5933 			size += size >> 1;
5934 			value = malloc (size);
5935 			if (value) {
5936 				memset (value, 0, size);
5937 				(void)snprintf (value, size, "%d.0x%04"PFMT64x ".%s.%d.%d",
5938 					obj->metas->ord, obj->file_offset + obj->loadaddr, ((RBinJavaCPTypeMetas *) obj->metas->type_info)->name,
5939 					obj->info.cp_field.class_idx,
5940 					obj->info.cp_field.name_and_type_idx);
5941 			}
5942 		}
5943 	}
5944 	return value;
5945 }
5946 
r_bin_java_print_classref_cp_summary(RBinJavaCPTypeObj * obj)5947 R_API void r_bin_java_print_classref_cp_summary(RBinJavaCPTypeObj *obj) {
5948 	if (obj == NULL) {
5949 		eprintf ("Attempting to print an invalid RBinJavaCPTypeObj*  ClassRef.\n");
5950 		return;
5951 	}
5952 	eprintf ("ClassRef ConstantPool Type (%d) ", obj->metas->ord);
5953 	eprintf ("	Offset: 0x%08"PFMT64x"", obj->file_offset);
5954 	eprintf ("	Name Index = %d\n", obj->info.cp_class.name_idx);
5955 }
5956 
r_bin_java_print_classref_cp_stringify(RBinJavaCPTypeObj * obj)5957 R_API char *r_bin_java_print_classref_cp_stringify(RBinJavaCPTypeObj *obj) {
5958 	ut32 size = 255, consumed = 0;
5959 	char *value = malloc (size);
5960 	if (value) {
5961 		memset (value, 0, size);
5962 		consumed = snprintf (value, size, "%d.0x%04"PFMT64x ".%s.%d",
5963 			obj->metas->ord, obj->file_offset + obj->loadaddr, ((RBinJavaCPTypeMetas *) obj->metas->type_info)->name,
5964 			obj->info.cp_class.name_idx);
5965 		if (consumed >= size - 1) {
5966 			free (value);
5967 			size += size >> 1;
5968 			value = malloc (size);
5969 			if (value) {
5970 				memset (value, 0, size);
5971 				(void)snprintf (value, size, "%d.0x%04"PFMT64x ".%s.%d",
5972 					obj->metas->ord, obj->file_offset + obj->loadaddr, ((RBinJavaCPTypeMetas *) obj->metas->type_info)->name,
5973 					obj->info.cp_class.name_idx);
5974 			}
5975 		}
5976 	}
5977 	return value;
5978 }
5979 
r_bin_java_print_string_cp_summary(RBinJavaCPTypeObj * obj)5980 R_API void r_bin_java_print_string_cp_summary(RBinJavaCPTypeObj *obj) {
5981 	if (!obj) {
5982 		eprintf ("Attempting to print an invalid RBinJavaCPTypeObj*  String.\n");
5983 		return;
5984 	}
5985 	Eprintf ("String ConstantPool Type (%d) ", obj->metas->ord);
5986 	Eprintf ("  Offset: 0x%08"PFMT64x "", obj->file_offset);
5987 	Eprintf ("  String Index = %d\n", obj->info.cp_string.string_idx);
5988 }
5989 
r_bin_java_print_string_cp_stringify(RBinJavaCPTypeObj * obj)5990 R_API char *r_bin_java_print_string_cp_stringify(RBinJavaCPTypeObj *obj) {
5991 	ut32 size = 255, consumed = 0;
5992 	char *value = malloc (size);
5993 	if (value) {
5994 		memset (value, 0, size);
5995 		consumed = snprintf (value, size, "%d.0x%04"PFMT64x ".%s.%d",
5996 			obj->metas->ord, obj->file_offset + obj->loadaddr, ((RBinJavaCPTypeMetas *) obj->metas->type_info)->name,
5997 			obj->info.cp_string.string_idx);
5998 		if (consumed >= size - 1) {
5999 			free (value);
6000 			size += size >> 1;
6001 			value = malloc (size);
6002 			if (value) {
6003 				memset (value, 0, size);
6004 				(void)snprintf (value, size, "%d.0x%04"PFMT64x ".%s.%d",
6005 					obj->metas->ord, obj->file_offset,
6006 					((RBinJavaCPTypeMetas *) obj->metas->type_info)->name,
6007 					obj->info.cp_string.string_idx);
6008 			}
6009 		}
6010 	}
6011 	return value;
6012 }
6013 
r_bin_java_print_integer_cp_summary(RBinJavaCPTypeObj * obj)6014 R_API void r_bin_java_print_integer_cp_summary(RBinJavaCPTypeObj *obj) {
6015 	ut8 *b = NULL;
6016 	if (obj == NULL) {
6017 		eprintf ("Attempting to print an invalid RBinJavaCPTypeObj*  Integer.\n");
6018 		return;
6019 	}
6020 	b = obj->info.cp_integer.bytes.raw;
6021 	eprintf ("Integer ConstantPool Type (%d) ", obj->metas->ord);
6022 	eprintf ("	Offset: 0x%08"PFMT64x"", obj->file_offset);
6023 	eprintf ("	bytes = %02x %02x %02x %02x\n", b[0], b[1], b[2], b[3]);
6024 	eprintf ("	integer = %d\n", R_BIN_JAVA_UINT (obj->info.cp_integer.bytes.raw, 0));
6025 }
6026 
r_bin_java_print_integer_cp_stringify(RBinJavaCPTypeObj * obj)6027 R_API char *r_bin_java_print_integer_cp_stringify(RBinJavaCPTypeObj *obj) {
6028 	ut32 size = 255, consumed = 0;
6029 	char *value = malloc (size);
6030 	if (value) {
6031 		memset (value, 0, size);
6032 		consumed = snprintf (value, size, "%d.0x%04"PFMT64x ".%s.0x%08x",
6033 			obj->metas->ord, obj->file_offset + obj->loadaddr, ((RBinJavaCPTypeMetas *) obj->metas->type_info)->name,
6034 			R_BIN_JAVA_UINT (obj->info.cp_integer.bytes.raw, 0));
6035 		if (consumed >= size - 1) {
6036 			free (value);
6037 			size += size >> 1;
6038 			value = malloc (size);
6039 			if (value) {
6040 				memset (value, 0, size);
6041 				(void)snprintf (value, size, "%d.0x%04"PFMT64x ".%s.0x%08x",
6042 					obj->metas->ord, obj->file_offset + obj->loadaddr, ((RBinJavaCPTypeMetas *) obj->metas->type_info)->name,
6043 					R_BIN_JAVA_UINT (obj->info.cp_integer.bytes.raw, 0));
6044 			}
6045 		}
6046 	}
6047 	return value;
6048 }
6049 
r_bin_java_print_float_cp_summary(RBinJavaCPTypeObj * obj)6050 R_API void r_bin_java_print_float_cp_summary(RBinJavaCPTypeObj *obj) {
6051 	ut8 *b = NULL;
6052 	if (obj == NULL) {
6053 		eprintf ("Attempting to print an invalid RBinJavaCPTypeObj*  Double.\n");
6054 		return;
6055 	}
6056 	b = obj->info.cp_float.bytes.raw;
6057 	Eprintf ("Float ConstantPool Type (%d) ", obj->metas->ord);
6058 	Eprintf ("  Offset: 0x%08"PFMT64x "", obj->file_offset);
6059 	Eprintf ("  Bytes = %02x %02x %02x %02x\n", b[0], b[1], b[2], b[3]);
6060 	Eprintf ("  Float = %f\n", R_BIN_JAVA_FLOAT (obj->info.cp_float.bytes.raw, 0));
6061 }
6062 
r_bin_java_print_float_cp_stringify(RBinJavaCPTypeObj * obj)6063 R_API char *r_bin_java_print_float_cp_stringify(RBinJavaCPTypeObj *obj) {
6064 	ut32 size = 255, consumed = 0;
6065 	char *value = malloc (size);
6066 	if (value) {
6067 		memset (value, 0, size);
6068 		consumed = snprintf (value, size, "%d.0x%04"PFMT64x ".%s.%f",
6069 			obj->metas->ord, obj->file_offset + obj->loadaddr, ((RBinJavaCPTypeMetas *) obj->metas->type_info)->name,
6070 			R_BIN_JAVA_FLOAT (obj->info.cp_float.bytes.raw, 0));
6071 		if (consumed >= size - 1) {
6072 			free (value);
6073 			size += size >> 1;
6074 			value = malloc (size);
6075 			if (value) {
6076 				memset (value, 0, size);
6077 				(void)snprintf (value, size, "%d.0x%04"PFMT64x ".%s.%f",
6078 					obj->metas->ord, obj->file_offset + obj->loadaddr, ((RBinJavaCPTypeMetas *) obj->metas->type_info)->name,
6079 					R_BIN_JAVA_FLOAT (obj->info.cp_float.bytes.raw, 0));
6080 			}
6081 		}
6082 	}
6083 	return value;
6084 }
6085 
r_bin_java_print_long_cp_summary(RBinJavaCPTypeObj * obj)6086 R_API void r_bin_java_print_long_cp_summary(RBinJavaCPTypeObj *obj) {
6087 	ut8 *b = NULL;
6088 	if (obj == NULL) {
6089 		eprintf ("Attempting to print an invalid RBinJavaCPTypeObj*  Long.\n");
6090 		return;
6091 	}
6092 	b = obj->info.cp_long.bytes.raw;
6093 	Eprintf ("Long ConstantPool Type (%d) ", obj->metas->ord);
6094 	Eprintf ("  Offset: 0x%08"PFMT64x "", obj->file_offset);
6095 	Eprintf ("  High-Bytes = %02x %02x %02x %02x\n", b[0], b[1], b[2], b[3]);
6096 	Eprintf ("  Low-Bytes = %02x %02x %02x %02x\n", b[4], b[5], b[6], b[7]);
6097 	Eprintf ("  Long = %08"PFMT64x "\n", r_bin_java_raw_to_long (obj->info.cp_long.bytes.raw, 0));
6098 }
6099 
r_bin_java_print_long_cp_stringify(RBinJavaCPTypeObj * obj)6100 R_API char *r_bin_java_print_long_cp_stringify(RBinJavaCPTypeObj *obj) {
6101 	ut32 size = 255, consumed = 0;
6102 	char *value = malloc (size);
6103 	if (value) {
6104 		memset (value, 0, size);
6105 		consumed = snprintf (value, size, "%d.0x%04"PFMT64x ".%s.0x%08"PFMT64x "",
6106 			obj->metas->ord,
6107 			obj->file_offset,
6108 			((RBinJavaCPTypeMetas *) obj->metas->type_info)->name,
6109 			r_bin_java_raw_to_long (obj->info.cp_long.bytes.raw, 0));
6110 		if (consumed >= size - 1) {
6111 			free (value);
6112 			size += size >> 1;
6113 			value = malloc (size);
6114 			if (value) {
6115 				memset (value, 0, size);
6116 				(void)snprintf (value, size, "%d.0x%04"PFMT64x ".%s.0x%08"PFMT64x "",
6117 					obj->metas->ord,
6118 					obj->file_offset,
6119 					((RBinJavaCPTypeMetas *) obj->metas->type_info)->name,
6120 					r_bin_java_raw_to_long (obj->info.cp_long.bytes.raw, 0));
6121 			}
6122 		}
6123 	}
6124 	return value;
6125 }
6126 
r_bin_java_print_double_cp_summary(RBinJavaCPTypeObj * obj)6127 R_API void r_bin_java_print_double_cp_summary(RBinJavaCPTypeObj *obj) {
6128 	ut8 *b = NULL;
6129 	if (!obj) {
6130 		eprintf ("Attempting to print an invalid RBinJavaCPTypeObj*  Double.\n");
6131 		return;
6132 	}
6133 	b = obj->info.cp_double.bytes.raw;
6134 	Eprintf ("Double ConstantPool Type (%d) ", obj->metas->ord);
6135 	Eprintf ("  Offset: 0x%08"PFMT64x "", obj->file_offset);
6136 	Eprintf ("  High-Bytes = %02x %02x %02x %02x\n", b[0], b[1], b[2], b[3]);
6137 	Eprintf ("  Low-Bytes = %02x %02x %02x %02x\n", b[4], b[5], b[6], b[7]);
6138 	Eprintf ("  Double = %f\n", r_bin_java_raw_to_double (obj->info.cp_double.bytes.raw, 0));
6139 }
6140 
r_bin_java_print_double_cp_stringify(RBinJavaCPTypeObj * obj)6141 R_API char *r_bin_java_print_double_cp_stringify(RBinJavaCPTypeObj *obj) {
6142 	ut32 size = 255, consumed = 0;
6143 	char *value = malloc (size);
6144 	if (value) {
6145 		memset (value, 0, size);
6146 		consumed = snprintf (value, size, "%d.0x%04"PFMT64x ".%s.%f",
6147 			obj->metas->ord,
6148 			obj->file_offset,
6149 			((RBinJavaCPTypeMetas *) obj->metas->type_info)->name,
6150 			r_bin_java_raw_to_double (obj->info.cp_double.bytes.raw, 0));
6151 		if (consumed >= size - 1) {
6152 			free (value);
6153 			size += size >> 1;
6154 			value = malloc (size);
6155 			if (value) {
6156 				memset (value, 0, size);
6157 				(void)snprintf (value, size, "%d.0x%04"PFMT64x ".%s.%f",
6158 					obj->metas->ord,
6159 					obj->file_offset,
6160 					((RBinJavaCPTypeMetas *) obj->metas->type_info)->name,
6161 					r_bin_java_raw_to_double (obj->info.cp_double.bytes.raw, 0));
6162 			}
6163 		}
6164 	}
6165 	return value;
6166 }
6167 
r_bin_java_print_name_and_type_cp_summary(RBinJavaCPTypeObj * obj)6168 R_API void r_bin_java_print_name_and_type_cp_summary(RBinJavaCPTypeObj *obj) {
6169 	if (obj == NULL) {
6170 		eprintf ("Attempting to print an invalid RBinJavaCPTypeObj*  Name_And_Type.\n");
6171 		return;
6172 	}
6173 	Eprintf ("Name_And_Type ConstantPool Type (%d) ", obj->metas->ord);
6174 	Eprintf ("  Offset: 0x%08"PFMT64x "", obj->file_offset);
6175 	Eprintf ("  name_idx = (%d)\n", obj->info.cp_name_and_type.name_idx);
6176 	Eprintf ("  descriptor_idx = (%d)\n", obj->info.cp_name_and_type.descriptor_idx);
6177 }
6178 
r_bin_java_print_name_and_type_cp_stringify(RBinJavaCPTypeObj * obj)6179 R_API char *r_bin_java_print_name_and_type_cp_stringify(RBinJavaCPTypeObj *obj) {
6180 	ut32 size = 255, consumed = 0;
6181 	char *value = malloc (size);
6182 	if (value) {
6183 		memset (value, 0, size);
6184 		consumed = snprintf (value, size, "%d.0x%04"PFMT64x ".%s.%d.%d",
6185 			obj->metas->ord, obj->file_offset + obj->loadaddr, ((RBinJavaCPTypeMetas *) obj->metas->type_info)->name,
6186 			obj->info.cp_name_and_type.name_idx,
6187 			obj->info.cp_name_and_type.descriptor_idx);
6188 		if (consumed >= size - 1) {
6189 			free (value);
6190 			size += size >> 1;
6191 			value = malloc (size);
6192 			if (value) {
6193 				memset (value, 0, size);
6194 				(void)snprintf (value, size, "%d.0x%04"PFMT64x ".%s.%d.%d",
6195 					obj->metas->ord, obj->file_offset + obj->loadaddr, ((RBinJavaCPTypeMetas *) obj->metas->type_info)->name,
6196 					obj->info.cp_name_and_type.name_idx,
6197 					obj->info.cp_name_and_type.descriptor_idx);
6198 			}
6199 		}
6200 	}
6201 	return value;
6202 }
6203 
r_bin_java_print_utf8_cp_summary(RBinJavaCPTypeObj * obj)6204 R_API void r_bin_java_print_utf8_cp_summary(RBinJavaCPTypeObj *obj) {
6205 	if (obj == NULL) {
6206 		eprintf ("Attempting to print an invalid RBinJavaCPTypeObj*  Utf8.\n");
6207 		return;
6208 	}
6209 	char *str = convert_string ((const char *) obj->info.cp_utf8.bytes, obj->info.cp_utf8.length);
6210 	eprintf ("UTF8 ConstantPool Type (%d) ", obj->metas->ord);
6211 	eprintf ("	Offset: 0x%08"PFMT64x"", obj->file_offset);
6212 	eprintf ("	length = %d\n", obj->info.cp_utf8.length);
6213 	eprintf ("	utf8 = %s\n", str);
6214 	free (str);
6215 }
6216 
r_bin_java_print_utf8_cp_stringify(RBinJavaCPTypeObj * obj)6217 R_API char *r_bin_java_print_utf8_cp_stringify(RBinJavaCPTypeObj *obj) {
6218 	ut32 size = 255, consumed = 0;
6219 	char *utf8_str = r_hex_bin2strdup (obj->info.cp_utf8.bytes, obj->info.cp_utf8.length);
6220 	char *value = malloc (size + strlen (utf8_str));
6221 	if (value) {
6222 		memset (value, 0, size);
6223 		consumed = snprintf (value, size, "%d.0x%04"PFMT64x ".%s.%d.%s",
6224 			obj->metas->ord, obj->file_offset + obj->loadaddr, ((RBinJavaCPTypeMetas *) obj->metas->type_info)->name,
6225 			obj->info.cp_utf8.length,
6226 			utf8_str);
6227 		if (consumed >= size - 1) {
6228 			free (value);
6229 			size += size >> 1;
6230 			value = malloc (size + strlen (utf8_str));
6231 			if (value) {
6232 				memset (value, 0, size);
6233 				(void)snprintf (value, size, "%d.0x%04"PFMT64x ".%s.%d.%s",
6234 					obj->metas->ord, obj->file_offset + obj->loadaddr, ((RBinJavaCPTypeMetas *) obj->metas->type_info)->name,
6235 					obj->info.cp_utf8.length,
6236 					utf8_str);
6237 			}
6238 		}
6239 	}
6240 	free (utf8_str);
6241 	return value;
6242 }
6243 
r_bin_java_print_null_cp_summary(RBinJavaCPTypeObj * obj)6244 R_API void r_bin_java_print_null_cp_summary(RBinJavaCPTypeObj *obj) {
6245 	eprintf ("Unknown ConstantPool Type Tag: 0x%04x .\n", obj->tag);
6246 }
6247 
r_bin_java_print_null_cp_stringify(RBinJavaCPTypeObj * obj)6248 R_API char *r_bin_java_print_null_cp_stringify(RBinJavaCPTypeObj *obj) {
6249 	ut32 size = 255, consumed = 0;
6250 	char *value = malloc (size);
6251 	if (value) {
6252 		memset (value, 0, size);
6253 		consumed = snprintf (value, size, "%d.0x%04"PFMT64x ".%s",
6254 			obj->metas->ord, obj->file_offset + obj->loadaddr, ((RBinJavaCPTypeMetas *) obj->metas->type_info)->name);
6255 		if (consumed >= size - 1) {
6256 			free (value);
6257 			size += size >> 1;
6258 			value = malloc (size);
6259 			if (value) {
6260 				memset (value, 0, size);
6261 				(void)snprintf (value, size, "%d.0x%04"PFMT64x ".%s",
6262 					obj->metas->ord, obj->file_offset,
6263 					((RBinJavaCPTypeMetas *) obj->metas->type_info)->name);
6264 			}
6265 		}
6266 	}
6267 	return value;
6268 }
6269 
r_bin_java_print_unknown_cp_summary(RBinJavaCPTypeObj * obj)6270 R_API void r_bin_java_print_unknown_cp_summary(RBinJavaCPTypeObj *obj) {
6271 	eprintf ("NULL ConstantPool Type.\n");
6272 }
6273 
r_bin_java_print_unknown_cp_stringify(RBinJavaCPTypeObj * obj)6274 R_API char *r_bin_java_print_unknown_cp_stringify(RBinJavaCPTypeObj *obj) {
6275 	ut32 size = 255;
6276 	char *value = malloc (size);
6277 	if (value) {
6278 		memset (value, 0, size);
6279 		snprintf (value, size, "%d.0x%04"PFMT64x ".%s",
6280 			obj->metas->ord, obj->file_offset + obj->loadaddr, ((RBinJavaCPTypeMetas *) obj->metas->type_info)->name);
6281 	}
6282 	return value;
6283 }
6284 
r_bin_java_element_pair_new(ut8 * buffer,ut64 sz,ut64 buf_offset)6285 R_API RBinJavaElementValuePair *r_bin_java_element_pair_new(ut8 *buffer, ut64 sz, ut64 buf_offset) {
6286 	if (!buffer || sz < 4) {
6287 		return NULL;
6288 	}
6289 	RBinJavaElementValuePair *evp = R_NEW0 (RBinJavaElementValuePair);
6290 	if (!evp) {
6291 		return NULL;
6292 	}
6293 	// TODO: What is the signifigance of evp element
6294 	evp->element_name_idx = R_BIN_JAVA_USHORT (buffer, 0);
6295 	ut64 offset = 2;
6296 	evp->file_offset = buf_offset;
6297 	evp->name = r_bin_java_get_utf8_from_bin_cp_list (R_BIN_JAVA_GLOBAL_BIN, evp->element_name_idx);
6298 	if (!evp->name) {
6299 		// TODO: eprintf unable to find the name for the given index
6300 		eprintf ("ElementValue Name is invalid.\n");
6301 		evp->name = strdup ("UNKNOWN");
6302 	}
6303 	if (offset >= sz) {
6304 		free (evp);
6305 		return NULL;
6306 	}
6307 	evp->value = r_bin_java_element_value_new (buffer + offset, sz - offset, buf_offset + offset);
6308 	offset += evp->value->size;
6309 	if (offset >= sz) {
6310 		free (evp->value);
6311 		free (evp);
6312 		return NULL;
6313 	}
6314 	evp->size = offset;
6315 	return evp;
6316 }
6317 
r_bin_java_print_element_pair_summary(RBinJavaElementValuePair * evp)6318 R_API void r_bin_java_print_element_pair_summary(RBinJavaElementValuePair *evp) {
6319 	if (!evp) {
6320 		eprintf ("Attempting to print an invalid RBinJavaElementValuePair *pair.\n");
6321 		return;
6322 	}
6323 	Eprintf ("Element Value Pair information:\n");
6324 	Eprintf ("  EV Pair File Offset: 0x%08"PFMT64x "\n", evp->file_offset);
6325 	Eprintf ("  EV Pair Element Name index: 0x%02x\n", evp->element_name_idx);
6326 	Eprintf ("  EV Pair Element Name: %s\n", evp->name);
6327 	Eprintf ("  EV Pair Element Value:\n");
6328 	r_bin_java_print_element_value_summary (evp->value);
6329 }
6330 
r_bin_java_print_element_value_summary(RBinJavaElementValue * element_value)6331 R_API void r_bin_java_print_element_value_summary(RBinJavaElementValue *element_value) {
6332 	RBinJavaCPTypeObj *obj;
6333 	RBinJavaElementValue *ev_element = NULL;
6334 	RListIter *iter = NULL, *iter_tmp = NULL;
6335 	char *name;
6336 	if (!element_value) {
6337 		eprintf ("Attempting to print an invalid RBinJavaElementValuePair *pair.\n");
6338 		return;
6339 	}
6340 	name = ((RBinJavaElementValueMetas *) element_value->metas->type_info)->name;
6341 	eprintf ("Element Value information:\n");
6342 	eprintf ("   EV Pair File Offset: 0x%08"PFMT64x "\n", element_value->file_offset);
6343 	eprintf ("   EV Value Type (%d): %s\n", element_value->tag, name);
6344 	switch (element_value->tag) {
6345 	case R_BIN_JAVA_EV_TAG_BYTE:
6346 	case R_BIN_JAVA_EV_TAG_CHAR:
6347 	case R_BIN_JAVA_EV_TAG_DOUBLE:
6348 	case R_BIN_JAVA_EV_TAG_FLOAT:
6349 	case R_BIN_JAVA_EV_TAG_INT:
6350 	case R_BIN_JAVA_EV_TAG_LONG:
6351 	case R_BIN_JAVA_EV_TAG_SHORT:
6352 	case R_BIN_JAVA_EV_TAG_BOOLEAN:
6353 	case R_BIN_JAVA_EV_TAG_STRING:
6354 		eprintf ("   EV Value Constant Value index: 0x%02x\n", element_value->value.const_value.const_value_idx);
6355 		eprintf ("   EV Value Constant Value Information:\n");
6356 		obj = element_value->value.const_value.const_value_cp_obj;
6357 		if (obj && obj->metas && obj->metas->type_info) {
6358 			((RBinJavaCPTypeMetas *) obj->metas->type_info)->allocs->print_summary (obj);
6359 		}
6360 		break;
6361 	case R_BIN_JAVA_EV_TAG_ENUM:
6362 		eprintf ("   EV Value Enum Constant Value Const Name Index: 0x%02x\n", element_value->value.enum_const_value.const_name_idx);
6363 		eprintf ("   EV Value Enum Constant Value Type Name Index: 0x%02x\n", element_value->value.enum_const_value.type_name_idx);
6364 		eprintf ("   EV Value Enum Constant Value Const CP Information:\n");
6365 		obj = element_value->value.enum_const_value.const_name_cp_obj;
6366 		if (obj && obj->metas && obj->metas->type_info) {
6367 			((RBinJavaCPTypeMetas *) obj->metas->type_info)->allocs->print_summary (obj);
6368 		}
6369 		eprintf ("   EV Value Enum Constant Value Type CP Information:\n");
6370 		obj = element_value->value.enum_const_value.type_name_cp_obj;
6371 		if (obj && obj->metas && obj->metas->type_info) {
6372 			((RBinJavaCPTypeMetas *) obj->metas->type_info)->allocs->print_summary (obj);
6373 		}
6374 		break;
6375 	case R_BIN_JAVA_EV_TAG_CLASS:
6376 		eprintf ("   EV Value Class Info Index: 0x%02x\n", element_value->value.class_value.class_info_idx);
6377 		eprintf ("   EV Value Class Info CP Information:\n");
6378 		obj = element_value->value.class_value.class_info_cp_obj;
6379 		if (obj && obj->metas && obj->metas->type_info) {
6380 			((RBinJavaCPTypeMetas *) obj->metas->type_info)->allocs->print_summary (obj);
6381 		}
6382 		break;
6383 	case R_BIN_JAVA_EV_TAG_ARRAY:
6384 		eprintf ("   EV Value Array Value Number of Values: 0x%04x\n", element_value->value.array_value.num_values);
6385 		eprintf ("   EV Value Array Values\n");
6386 		r_list_foreach_safe (element_value->value.array_value.values, iter, iter_tmp, ev_element) {
6387 			r_bin_java_print_element_value_summary (ev_element);
6388 		}
6389 		break;
6390 	case R_BIN_JAVA_EV_TAG_ANNOTATION:
6391 		eprintf ("   EV Annotation Information:\n");
6392 		r_bin_java_print_annotation_summary (&element_value->value.annotation_value);
6393 		break;
6394 	default:
6395 		// eprintf unable to handle tag
6396 		break;
6397 	}
6398 }
6399 
r_bin_java_element_pair_free(void * e)6400 R_API void r_bin_java_element_pair_free(void /*RBinJavaElementValuePair*/ *e) {
6401 	RBinJavaElementValuePair *evp = e;
6402 	if (evp) {
6403 		free (evp->name);
6404 		r_bin_java_element_value_free (evp->value);
6405 		free (evp);
6406 	}
6407 	evp = NULL;
6408 }
6409 
r_bin_java_element_value_free(void * e)6410 R_API void r_bin_java_element_value_free(void /*RBinJavaElementValue*/ *e) {
6411 	RBinJavaElementValue *element_value = e;
6412 	RListIter *iter = NULL, *iter_tmp = NULL;
6413 	RBinJavaCPTypeObj *obj = NULL;
6414 	RBinJavaElementValue *ev_element = NULL;
6415 	if (element_value) {
6416 		R_FREE (element_value->metas);
6417 		switch (element_value->tag) {
6418 		case R_BIN_JAVA_EV_TAG_BYTE:
6419 		case R_BIN_JAVA_EV_TAG_CHAR:
6420 		case R_BIN_JAVA_EV_TAG_DOUBLE:
6421 		case R_BIN_JAVA_EV_TAG_FLOAT:
6422 		case R_BIN_JAVA_EV_TAG_INT:
6423 		case R_BIN_JAVA_EV_TAG_LONG:
6424 		case R_BIN_JAVA_EV_TAG_SHORT:
6425 		case R_BIN_JAVA_EV_TAG_BOOLEAN:
6426 		case R_BIN_JAVA_EV_TAG_STRING:
6427 			// Delete the CP Type Object
6428 			obj = element_value->value.const_value.const_value_cp_obj;
6429 			if (obj && obj->metas) {
6430 				((RBinJavaCPTypeMetas *) obj->metas->type_info)->allocs->delete_obj (obj);
6431 			}
6432 			break;
6433 		case R_BIN_JAVA_EV_TAG_ENUM:
6434 			// Delete the CP Type Objects
6435 			obj = element_value->value.enum_const_value.const_name_cp_obj;
6436 			if (obj && obj->metas) {
6437 				RBinJavaCPTypeMetas *ti = obj->metas->type_info;
6438 				if (ti && ti->allocs && ti->allocs->delete_obj) {
6439 					ti->allocs->delete_obj (obj);
6440 				}
6441 			}
6442 			obj = element_value->value.enum_const_value.type_name_cp_obj;
6443 			if (obj && obj->metas) {
6444 				RBinJavaCPTypeMetas *tm = obj->metas->type_info;
6445 				if (tm && tm->allocs && tm->allocs->delete_obj) {
6446 					tm->allocs->delete_obj (obj);
6447 				}
6448 			}
6449 			break;
6450 		case R_BIN_JAVA_EV_TAG_CLASS:
6451 			// Delete the CP Type Object
6452 			obj = element_value->value.class_value.class_info_cp_obj;
6453 			if (obj && obj->metas) {
6454 				((RBinJavaCPTypeMetas *) obj->metas->type_info)->allocs->delete_obj (obj);
6455 			}
6456 			break;
6457 		case R_BIN_JAVA_EV_TAG_ARRAY:
6458 			// Delete the Element Value array List
6459 			r_list_foreach_safe (element_value->value.array_value.values, iter, iter_tmp, ev_element) {
6460 				if (ev_element) {
6461 					r_bin_java_element_value_free (ev_element);
6462 				} else {
6463 					// TODO eprintf evps value was NULL
6464 				}
6465 				// r_list_delete (element_value->value.array_value.values, iter);
6466 				ev_element = NULL;
6467 			}
6468 			r_list_free (element_value->value.array_value.values);
6469 			break;
6470 		case R_BIN_JAVA_EV_TAG_ANNOTATION:
6471 			// Delete the Annotations List
6472 			r_list_free (element_value->value.annotation_value.element_value_pairs);
6473 			break;
6474 		default:
6475 			// eprintf unable to free the tag
6476 			break;
6477 		}
6478 		free (element_value);
6479 	}
6480 }
6481 
r_bin_java_annotation_default_attr_calc_size(RBinJavaAttrInfo * attr)6482 R_API ut64 r_bin_java_annotation_default_attr_calc_size(RBinJavaAttrInfo *attr) {
6483 	ut64 size = 0;
6484 	if (attr) {
6485 		// attr = r_bin_java_default_attr_new (buffer, sz, buf_offset);
6486 		size += 6;
6487 		// attr->info.annotation_default_attr.default_value = r_bin_java_element_value_new (buffer+offset, sz-offset, buf_offset+offset);
6488 		size += r_bin_java_element_value_calc_size (attr->info.annotation_default_attr.default_value);
6489 	}
6490 	return size;
6491 }
6492 
r_bin_java_annotation_default_attr_new(RBinJavaObj * bin,ut8 * buffer,ut64 sz,ut64 buf_offset)6493 R_API RBinJavaAttrInfo *r_bin_java_annotation_default_attr_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz, ut64 buf_offset) {
6494 	ut64 offset = 0;
6495 	RBinJavaAttrInfo *attr = NULL;
6496 	attr = r_bin_java_default_attr_new (bin, buffer, sz, buf_offset);
6497 	offset += 6;
6498 	if (attr && sz >= offset) {
6499 		attr->type = R_BIN_JAVA_ATTR_TYPE_ANNOTATION_DEFAULT_ATTR;
6500 		attr->info.annotation_default_attr.default_value = r_bin_java_element_value_new (buffer + offset, sz - offset, buf_offset + offset);
6501 		if (attr->info.annotation_default_attr.default_value) {
6502 			offset += attr->info.annotation_default_attr.default_value->size;
6503 		}
6504 	}
6505 	r_bin_java_print_annotation_default_attr_summary (attr);
6506 	return attr;
6507 }
6508 
delete_obj(RBinJavaCPTypeObj * obj)6509 static void delete_obj(RBinJavaCPTypeObj *obj) {
6510 	if (obj && obj->metas && obj->metas->type_info) {
6511 		RBinJavaCPTypeMetas *ti = obj->metas->type_info;
6512 		if (ti && ti->allocs && ti->allocs->delete_obj) {
6513 			ti->allocs->delete_obj (obj);
6514 		}
6515 	}
6516 }
6517 
r_bin_java_annotation_default_attr_free(void * a)6518 R_API void r_bin_java_annotation_default_attr_free(void /*RBinJavaAttrInfo*/ *a) {
6519 	RBinJavaAttrInfo *attr = a;
6520 	RBinJavaElementValue *ev_element = NULL;
6521 	RListIter *iter = NULL, *iter_tmp = NULL;
6522 	if (!attr || attr->type != R_BIN_JAVA_ATTR_TYPE_ANNOTATION_DEFAULT_ATTR) {
6523 		return;
6524 	}
6525 	RBinJavaElementValue *element_value = attr->info.annotation_default_attr.default_value;
6526 	if (!element_value) {
6527 		return;
6528 	}
6529 	switch (element_value->tag) {
6530 	case R_BIN_JAVA_EV_TAG_BYTE:
6531 	case R_BIN_JAVA_EV_TAG_CHAR:
6532 	case R_BIN_JAVA_EV_TAG_DOUBLE:
6533 	case R_BIN_JAVA_EV_TAG_FLOAT:
6534 	case R_BIN_JAVA_EV_TAG_INT:
6535 	case R_BIN_JAVA_EV_TAG_LONG:
6536 	case R_BIN_JAVA_EV_TAG_SHORT:
6537 	case R_BIN_JAVA_EV_TAG_BOOLEAN:
6538 	case R_BIN_JAVA_EV_TAG_STRING:
6539 		// Delete the CP Type Object
6540 		delete_obj (element_value->value.const_value.const_value_cp_obj);
6541 		break;
6542 	case R_BIN_JAVA_EV_TAG_ENUM:
6543 		// Delete the CP Type Objects
6544 		delete_obj (element_value->value.enum_const_value.const_name_cp_obj);
6545 		break;
6546 	case R_BIN_JAVA_EV_TAG_CLASS:
6547 		// Delete the CP Type Object
6548 		delete_obj (element_value->value.class_value.class_info_cp_obj);
6549 		break;
6550 	case R_BIN_JAVA_EV_TAG_ARRAY:
6551 		// Delete the Element Value array List
6552 		r_list_foreach_safe (element_value->value.array_value.values, iter, iter_tmp, ev_element) {
6553 			r_bin_java_element_value_free (ev_element);
6554 			// r_list_delete (element_value->value.array_value.values, iter);
6555 			ev_element = NULL;
6556 		}
6557 		r_list_free (element_value->value.array_value.values);
6558 		break;
6559 	case R_BIN_JAVA_EV_TAG_ANNOTATION:
6560 		// Delete the Annotations List
6561 		r_list_free (element_value->value.annotation_value.element_value_pairs);
6562 		break;
6563 	default:
6564 		// eprintf unable to free the tag
6565 		break;
6566 	}
6567 	if (attr) {
6568 		free (attr->name);
6569 		free (attr->metas);
6570 		free (attr);
6571 	}
6572 }
6573 
r_bin_java_annotation_new(ut8 * buffer,ut64 sz,ut64 buf_offset)6574 R_API RBinJavaAnnotation *r_bin_java_annotation_new(ut8 *buffer, ut64 sz, ut64 buf_offset) {
6575 	ut32 i = 0;
6576 	RBinJavaAnnotation *annotation = NULL;
6577 	RBinJavaElementValuePair *evps = NULL;
6578 	ut64 offset = 0;
6579 	annotation = R_NEW0 (RBinJavaAnnotation);
6580 	if (!annotation) {
6581 		return NULL;
6582 	}
6583 	// (ut16) read and set annotation_value.type_idx;
6584 	annotation->type_idx = R_BIN_JAVA_USHORT (buffer, offset);
6585 	offset += 2;
6586 	// (ut16) read and set annotation_value.num_element_value_pairs;
6587 	annotation->num_element_value_pairs = R_BIN_JAVA_USHORT (buffer, offset);
6588 	offset += 2;
6589 	annotation->element_value_pairs = r_list_newf (r_bin_java_element_pair_free);
6590 	// read annotation_value.num_element_value_pairs, and append to annotation_value.element_value_pairs
6591 	for (i = 0; i < annotation->num_element_value_pairs; i++) {
6592 		if (offset > sz) {
6593 			break;
6594 		}
6595 		evps = r_bin_java_element_pair_new (buffer + offset, sz - offset, buf_offset + offset);
6596 		if (evps) {
6597 			offset += evps->size;
6598 			r_list_append (annotation->element_value_pairs, (void *) evps);
6599 		}
6600 	}
6601 	annotation->size = offset;
6602 	return annotation;
6603 }
6604 
r_bin_java_annotation_calc_size(RBinJavaAnnotation * annotation)6605 R_API ut64 r_bin_java_annotation_calc_size(RBinJavaAnnotation *annotation) {
6606 	ut64 sz = 0;
6607 	RListIter *iter, *iter_tmp;
6608 	RBinJavaElementValuePair *evps = NULL;
6609 	if (!annotation) {
6610 		// TODO eprintf allocation fail
6611 		return sz;
6612 	}
6613 	// annotation->type_idx = R_BIN_JAVA_USHORT (buffer, offset);
6614 	sz += 2;
6615 	// annotation->num_element_value_pairs = R_BIN_JAVA_USHORT (buffer, offset);
6616 	sz += 2;
6617 	r_list_foreach_safe (annotation->element_value_pairs, iter, iter_tmp, evps) {
6618 		if (evps) {
6619 			sz += r_bin_java_element_pair_calc_size (evps);
6620 		}
6621 	}
6622 	return sz;
6623 }
6624 
r_bin_java_annotation_free(void * a)6625 R_API void r_bin_java_annotation_free(void /*RBinJavaAnnotation*/ *a) {
6626 	RBinJavaAnnotation *annotation = a;
6627 	if (annotation) {
6628 		r_list_free (annotation->element_value_pairs);
6629 		free (annotation);
6630 	}
6631 }
6632 
r_bin_java_print_annotation_summary(RBinJavaAnnotation * annotation)6633 R_API void r_bin_java_print_annotation_summary(RBinJavaAnnotation *annotation) {
6634 	RListIter *iter = NULL, *iter_tmp = NULL;
6635 	RBinJavaElementValuePair *evp = NULL;
6636 	if (!annotation) {
6637 		// TODO eprintf invalid annotation
6638 		return;
6639 	}
6640 	Eprintf ("  Annotation Type Index: 0x%02x\n", annotation->type_idx);
6641 	Eprintf ("  Annotation Number of EV Pairs: 0x%04x\n", annotation->num_element_value_pairs);
6642 	Eprintf ("  Annotation EV Pair Values:\n");
6643 	if (annotation->element_value_pairs) {
6644 		r_list_foreach_safe (annotation->element_value_pairs, iter, iter_tmp, evp) {
6645 			r_bin_java_print_element_pair_summary (evp);
6646 		}
6647 	}
6648 }
6649 
r_bin_java_element_pair_calc_size(RBinJavaElementValuePair * evp)6650 R_API ut64 r_bin_java_element_pair_calc_size(RBinJavaElementValuePair *evp) {
6651 	ut64 sz = 0;
6652 	if (evp == NULL) {
6653 		return sz;
6654 	}
6655 	// evp->element_name_idx = r_bin_java_read_short(bin, bin->b->cur);
6656 	sz += 2;
6657 	// evp->value = r_bin_java_element_value_new (bin, offset+2);
6658 	if (evp->value) {
6659 		sz += r_bin_java_element_value_calc_size (evp->value);
6660 	}
6661 	return sz;
6662 }
6663 
r_bin_java_element_value_calc_size(RBinJavaElementValue * element_value)6664 R_API ut64 r_bin_java_element_value_calc_size(RBinJavaElementValue *element_value) {
6665 	RListIter *iter, *iter_tmp;
6666 	RBinJavaElementValue *ev_element;
6667 	RBinJavaElementValuePair *evps;
6668 	ut64 sz = 0;
6669 	if (element_value == NULL) {
6670 		return sz;
6671 	}
6672 	// tag
6673 	sz += 1;
6674 	switch (element_value->tag) {
6675 	case R_BIN_JAVA_EV_TAG_BYTE:
6676 	case R_BIN_JAVA_EV_TAG_CHAR:
6677 	case R_BIN_JAVA_EV_TAG_DOUBLE:
6678 	case R_BIN_JAVA_EV_TAG_FLOAT:
6679 	case R_BIN_JAVA_EV_TAG_INT:
6680 	case R_BIN_JAVA_EV_TAG_LONG:
6681 	case R_BIN_JAVA_EV_TAG_SHORT:
6682 	case R_BIN_JAVA_EV_TAG_BOOLEAN:
6683 	case R_BIN_JAVA_EV_TAG_STRING:
6684 		// look up value in bin->cp_list
6685 		// (ut16) read and set const_value.const_value_idx
6686 		// element_value->value.const_value.const_value_idx = r_bin_java_read_short(bin, bin->b->cur);
6687 		sz += 2;
6688 		break;
6689 	case R_BIN_JAVA_EV_TAG_ENUM:
6690 		// (ut16) read and set enum_const_value.type_name_idx
6691 		// element_value->value.enum_const_value.type_name_idx = r_bin_java_read_short(bin, bin->b->cur);
6692 		sz += 2;
6693 		// (ut16) read and set enum_const_value.const_name_idx
6694 		// element_value->value.enum_const_value.const_name_idx = r_bin_java_read_short(bin, bin->b->cur);
6695 		sz += 2;
6696 		break;
6697 	case R_BIN_JAVA_EV_TAG_CLASS:
6698 		// (ut16) read and set class_value.class_info_idx
6699 		// element_value->value.class_value.class_info_idx = r_bin_java_read_short(bin, bin->b->cur);
6700 		sz += 2;
6701 		break;
6702 	case R_BIN_JAVA_EV_TAG_ARRAY:
6703 		// (ut16) read and set array_value.num_values
6704 		// element_value->value.array_value.num_values = r_bin_java_read_short(bin, bin->b->cur);
6705 		sz += 2;
6706 		r_list_foreach_safe (element_value->value.array_value.values, iter, iter_tmp, ev_element) {
6707 			if (ev_element) {
6708 				sz += r_bin_java_element_value_calc_size (ev_element);
6709 			}
6710 		}
6711 		break;
6712 	case R_BIN_JAVA_EV_TAG_ANNOTATION:
6713 		// annotation new is not used here.
6714 		// (ut16) read and set annotation_value.type_idx;
6715 		// element_value->value.annotation_value.type_idx = r_bin_java_read_short(bin, bin->b->cur);
6716 		sz += 2;
6717 		// (ut16) read and set annotation_value.num_element_value_pairs;
6718 		// element_value->value.annotation_value.num_element_value_pairs = r_bin_java_read_short(bin, bin->b->cur);
6719 		sz += 2;
6720 		element_value->value.annotation_value.element_value_pairs = r_list_newf (r_bin_java_element_pair_free);
6721 		r_list_foreach_safe (element_value->value.annotation_value.element_value_pairs, iter, iter_tmp, evps) {
6722 			if (evps) {
6723 				sz += r_bin_java_element_pair_calc_size (evps);
6724 			}
6725 		}
6726 		break;
6727 	default:
6728 		// eprintf unable to handle tag
6729 		break;
6730 	}
6731 	return sz;
6732 }
6733 
r_bin_java_element_value_new(ut8 * buffer,ut64 sz,ut64 buf_offset)6734 R_API RBinJavaElementValue *r_bin_java_element_value_new(ut8 *buffer, ut64 sz, ut64 buf_offset) {
6735 	ut32 i = 0;
6736 	ut64 offset = 0;
6737 	RBinJavaElementValue *element_value = R_NEW0 (RBinJavaElementValue);
6738 	if (!element_value) {
6739 		return NULL;
6740 	}
6741 	RBinJavaElementValuePair *evps = NULL;
6742 	element_value->metas = R_NEW0 (RBinJavaMetaInfo);
6743 	if (!element_value->metas) {
6744 		R_FREE (element_value);
6745 		return NULL;
6746 	}
6747 	element_value->file_offset = buf_offset;
6748 	element_value->tag = buffer[offset];
6749 	element_value->size += 1;
6750 	offset += 1;
6751 	element_value->metas->type_info = (void *) r_bin_java_get_ev_meta_from_tag (element_value->tag);
6752 	switch (element_value->tag) {
6753 	case R_BIN_JAVA_EV_TAG_BYTE:
6754 	case R_BIN_JAVA_EV_TAG_CHAR:
6755 	case R_BIN_JAVA_EV_TAG_DOUBLE:
6756 	case R_BIN_JAVA_EV_TAG_FLOAT:
6757 	case R_BIN_JAVA_EV_TAG_INT:
6758 	case R_BIN_JAVA_EV_TAG_LONG:
6759 	case R_BIN_JAVA_EV_TAG_SHORT:
6760 	case R_BIN_JAVA_EV_TAG_BOOLEAN:
6761 	case R_BIN_JAVA_EV_TAG_STRING:
6762 		// look up value in bin->cp_list
6763 		// (ut16) read and set const_value.const_value_idx
6764 		element_value->value.const_value.const_value_idx = R_BIN_JAVA_USHORT (buffer, offset);
6765 		element_value->size += 2;
6766 		// look-up, deep copy, and set const_value.const_value_cp_obj
6767 		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);
6768 		break;
6769 	case R_BIN_JAVA_EV_TAG_ENUM:
6770 		// (ut16) read and set enum_const_value.type_name_idx
6771 		element_value->value.enum_const_value.type_name_idx = R_BIN_JAVA_USHORT (buffer, offset);
6772 		element_value->size += 2;
6773 		offset += 2;
6774 		// (ut16) read and set enum_const_value.const_name_idx
6775 		element_value->value.enum_const_value.const_name_idx = R_BIN_JAVA_USHORT (buffer, offset);
6776 		element_value->size += 2;
6777 		offset += 2;
6778 		// look up type_name_index in bin->cp_list
6779 		// look-up, deep copy, and set enum_const_value.const_name_cp_obj
6780 		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);
6781 		// look-up, deep copy, and set enum_const_value.type_name_cp_obj
6782 		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);
6783 		break;
6784 	case R_BIN_JAVA_EV_TAG_CLASS:
6785 		// (ut16) read and set class_value.class_info_idx
6786 		element_value->value.class_value.class_info_idx = R_BIN_JAVA_USHORT (buffer, offset);
6787 		element_value->size += 2;
6788 		offset += 2;
6789 		// look up type_name_index in bin->cp_list
6790 		// look-up, deep copy, and set class_value.class_info_cp_obj
6791 		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);
6792 		break;
6793 	case R_BIN_JAVA_EV_TAG_ARRAY:
6794 		// (ut16) read and set array_value.num_values
6795 		element_value->value.array_value.num_values = R_BIN_JAVA_USHORT (buffer, offset);
6796 		element_value->size += 2;
6797 		offset += 2;
6798 		element_value->value.array_value.values = r_list_new ();
6799 		for (i = 0; i < element_value->value.array_value.num_values; i++) {
6800 			if (offset >= sz) {
6801 				break;
6802 			}
6803 			RBinJavaElementValue *ev_element = r_bin_java_element_value_new (buffer + offset, sz - offset, buf_offset + offset);
6804 			if (ev_element) {
6805 				element_value->size += ev_element->size;
6806 				offset += ev_element->size;
6807 				// read array_value.num_values, and append to array_value.values
6808 				r_list_append (element_value->value.array_value.values, (void *) ev_element);
6809 			}
6810 		}
6811 		break;
6812 	case R_BIN_JAVA_EV_TAG_ANNOTATION:
6813 		// annotation new is not used here.
6814 		// (ut16) read and set annotation_value.type_idx;
6815 		if (offset + 8 < sz) {
6816 			element_value->value.annotation_value.type_idx = R_BIN_JAVA_USHORT (buffer, offset);
6817 			element_value->size += 2;
6818 			offset += 2;
6819 			// (ut16) read and set annotation_value.num_element_value_pairs;
6820 			element_value->value.annotation_value.num_element_value_pairs = R_BIN_JAVA_USHORT (buffer, offset);
6821 			element_value->size += 2;
6822 			offset += 2;
6823 		}
6824 		element_value->value.annotation_value.element_value_pairs = r_list_newf (r_bin_java_element_pair_free);
6825 		// read annotation_value.num_element_value_pairs, and append to annotation_value.element_value_pairs
6826 		for (i = 0; i < element_value->value.annotation_value.num_element_value_pairs; i++) {
6827 			if (offset > sz) {
6828 				break;
6829 			}
6830 			evps = r_bin_java_element_pair_new (buffer + offset, sz - offset, buf_offset + offset);
6831 			if (evps) {
6832 				element_value->size += evps->size;
6833 				offset += evps->size;
6834 			}
6835 			if (evps == NULL) {
6836 				// TODO: eprintf error when reading element pair
6837 			}
6838 			r_list_append (element_value->value.annotation_value.element_value_pairs, (void *) evps);
6839 		}
6840 		break;
6841 	default:
6842 		// eprintf unable to handle tag
6843 		break;
6844 	}
6845 	return element_value;
6846 }
6847 
r_bin_java_bootstrap_method_argument_free(void * b)6848 R_API void r_bin_java_bootstrap_method_argument_free(void /*RBinJavaBootStrapArgument*/ *b) {
6849 	RBinJavaBootStrapArgument *bsm_arg = b;
6850 	if (bsm_arg) {
6851 		RBinJavaCPTypeMetas *tm = (RBinJavaCPTypeMetas*)bsm_arg->argument_info_cp_obj;
6852 		if (tm) {
6853 			if (tm && (size_t)(tm->allocs) > 1024 && tm->allocs->delete_obj) {
6854 				tm->allocs->delete_obj (tm);
6855 			}
6856 			bsm_arg->argument_info_cp_obj = NULL;
6857 		}
6858 		free (bsm_arg);
6859 	}
6860 }
6861 
r_bin_java_print_bootstrap_method_argument_summary(RBinJavaBootStrapArgument * bsm_arg)6862 R_API void r_bin_java_print_bootstrap_method_argument_summary(RBinJavaBootStrapArgument *bsm_arg) {
6863 	if (!bsm_arg) {
6864 		eprintf ("Attempting to print an invalid RBinJavaBootStrapArgument *.\n");
6865 		return;
6866 	}
6867 	eprintf ("Bootstrap Method Argument Information:\n");
6868 	eprintf ("	Offset: 0x%08"PFMT64x"", bsm_arg->file_offset);
6869 	eprintf ("	Name_And_Type Index = (0x%02x)\n", bsm_arg->argument_info_idx);
6870 	if (bsm_arg->argument_info_cp_obj) {
6871 		eprintf ("	Bootstrap Method Argument Type and Name Info:\n");
6872 		((RBinJavaCPTypeMetas *) bsm_arg->argument_info_cp_obj)->allocs->print_summary (bsm_arg->argument_info_cp_obj);
6873 	} else {
6874 		eprintf ("	Bootstrap Method Argument Type and Name Info: INVALID\n");
6875 	}
6876 }
6877 
r_bin_java_print_bootstrap_method_summary(RBinJavaBootStrapMethod * bsm)6878 R_API void r_bin_java_print_bootstrap_method_summary(RBinJavaBootStrapMethod *bsm) {
6879 	RBinJavaBootStrapArgument *bsm_arg = NULL;
6880 	RListIter *iter = NULL, *iter_tmp = NULL;
6881 	if (!bsm) {
6882 		eprintf ("Attempting to print an invalid RBinJavaBootStrapArgument *.\n");
6883 		return;
6884 	}
6885 	eprintf ("Bootstrap Method Information:\n");
6886 	eprintf ("	Offset: 0x%08"PFMT64x"", bsm->file_offset);
6887 	eprintf ("	Method Reference Index = (0x%02x)\n", bsm->bootstrap_method_ref);
6888 	eprintf ("	Number of Method Arguments = (0x%02x)\n", bsm->num_bootstrap_arguments);
6889 	if (bsm->bootstrap_arguments) {
6890 		r_list_foreach_safe (bsm->bootstrap_arguments, iter, iter_tmp, bsm_arg) {
6891 			if (bsm_arg) {
6892 				r_bin_java_print_bootstrap_method_argument_summary (bsm_arg);
6893 			}
6894 		}
6895 	} else {
6896 		eprintf ("	Bootstrap Method Argument: NONE \n");
6897 	}
6898 }
6899 
r_bin_java_bootstrap_method_argument_new(ut8 * buffer,ut64 sz,ut64 buf_offset)6900 R_API RBinJavaBootStrapArgument *r_bin_java_bootstrap_method_argument_new(ut8 *buffer, ut64 sz, ut64 buf_offset) {
6901 	ut64 offset = 0;
6902 	RBinJavaBootStrapArgument *bsm_arg = (RBinJavaBootStrapArgument *) malloc (sizeof (RBinJavaBootStrapArgument));
6903 	if (!bsm_arg) {
6904 		// TODO eprintf failed to allocate bytes for bootstrap_method.
6905 		return bsm_arg;
6906 	}
6907 	memset (bsm_arg, 0, sizeof (RBinJavaBootStrapArgument));
6908 	bsm_arg->file_offset = buf_offset;
6909 	bsm_arg->argument_info_idx = R_BIN_JAVA_USHORT (buffer, offset);
6910 	offset += 2;
6911 	bsm_arg->argument_info_cp_obj = r_bin_java_clone_cp_idx (R_BIN_JAVA_GLOBAL_BIN, bsm_arg->argument_info_idx);
6912 	bsm_arg->size = offset;
6913 	return bsm_arg;
6914 }
6915 
r_bin_java_bootstrap_method_free(void * b)6916 R_API void r_bin_java_bootstrap_method_free(void /*/RBinJavaBootStrapMethod*/ *b) {
6917 	RBinJavaBootStrapMethod *bsm = b;
6918 	RListIter *iter, *iter_tmp;
6919 	RBinJavaBootStrapArgument *obj = NULL;
6920 	if (bsm) {
6921 		if (bsm->bootstrap_arguments) {
6922 			r_list_foreach_safe (bsm->bootstrap_arguments, iter, iter_tmp, obj) {
6923 				if (obj) {
6924 					r_bin_java_bootstrap_method_argument_free (obj);
6925 				}
6926 				// r_list_delete (bsm->bootstrap_arguments, iter);
6927 			}
6928 			r_list_free (bsm->bootstrap_arguments);
6929 			bsm->bootstrap_arguments = NULL;
6930 		}
6931 		free (bsm);
6932 	}
6933 }
6934 
r_bin_java_bootstrap_method_new(ut8 * buffer,ut64 sz,ut64 buf_offset)6935 R_API RBinJavaBootStrapMethod *r_bin_java_bootstrap_method_new(ut8 *buffer, ut64 sz, ut64 buf_offset) {
6936 	RBinJavaBootStrapArgument *bsm_arg = NULL;
6937 	ut32 i = 0;
6938 	ut64 offset = 0;
6939 	RBinJavaBootStrapMethod *bsm = R_NEW0 (RBinJavaBootStrapMethod);
6940 	if (!bsm) {
6941 		// TODO eprintf failed to allocate bytes for bootstrap_method.
6942 		return bsm;
6943 	}
6944 	memset (bsm, 0, sizeof (RBinJavaBootStrapMethod));
6945 	bsm->file_offset = buf_offset;
6946 	bsm->bootstrap_method_ref = R_BIN_JAVA_USHORT (buffer, offset);
6947 	offset += 2;
6948 	bsm->num_bootstrap_arguments = R_BIN_JAVA_USHORT (buffer, offset);
6949 	offset += 2;
6950 	bsm->bootstrap_arguments = r_list_new ();
6951 	for (i = 0; i < bsm->num_bootstrap_arguments; i++) {
6952 		if (offset >= sz) {
6953 			break;
6954 		}
6955 		// bsm_arg = r_bin_java_bootstrap_method_argument_new (bin, bin->b->cur);
6956 		bsm_arg = r_bin_java_bootstrap_method_argument_new (buffer + offset, sz - offset, buf_offset + offset);
6957 		if (bsm_arg) {
6958 			offset += bsm_arg->size;
6959 			r_list_append (bsm->bootstrap_arguments, (void *) bsm_arg);
6960 		} else {
6961 			// TODO eprintf Failed to read the %d boot strap method.
6962 		}
6963 	}
6964 	bsm->size = offset;
6965 	return bsm;
6966 }
6967 
r_bin_java_print_bootstrap_methods_attr_summary(RBinJavaAttrInfo * attr)6968 R_API void r_bin_java_print_bootstrap_methods_attr_summary(RBinJavaAttrInfo *attr) {
6969 	RListIter *iter, *iter_tmp;
6970 	RBinJavaBootStrapMethod *obj = NULL;
6971 	if (!attr || attr->type == R_BIN_JAVA_ATTR_TYPE_BOOTSTRAP_METHODS_ATTR) {
6972 		eprintf ("Unable to print attribue summary for RBinJavaAttrInfo *RBinJavaBootstrapMethodsAttr");
6973 		return;
6974 	}
6975 	eprintf ("Bootstrap Methods Attribute Information Information:\n");
6976 	eprintf ("	Attribute Offset: 0x%08"PFMT64x"", attr->file_offset);
6977 	eprintf ("	Length: 0x%08x", attr->length);
6978 	eprintf ("	Number of Method Arguments = (0x%02x)\n", attr->info.bootstrap_methods_attr.num_bootstrap_methods);
6979 	if (attr->info.bootstrap_methods_attr.bootstrap_methods) {
6980 		r_list_foreach_safe (attr->info.bootstrap_methods_attr.bootstrap_methods, iter, iter_tmp, obj) {
6981 			if (obj) {
6982 				r_bin_java_print_bootstrap_method_summary (obj);
6983 			}
6984 		}
6985 	} else {
6986 		eprintf ("	Bootstrap Methods: NONE \n");
6987 	}
6988 }
6989 
r_bin_java_bootstrap_methods_attr_free(void * a)6990 R_API void r_bin_java_bootstrap_methods_attr_free(void /*RBinJavaAttrInfo*/ *a) {
6991 	RBinJavaAttrInfo *attr = a;
6992 	if (attr && attr->type == R_BIN_JAVA_ATTR_TYPE_BOOTSTRAP_METHODS_ATTR) {
6993 		free (attr->name);
6994 		free (attr->metas);
6995 		r_list_free (attr->info.bootstrap_methods_attr.bootstrap_methods);
6996 		free (attr);
6997 	}
6998 }
6999 
r_bin_java_bootstrap_methods_attr_calc_size(RBinJavaAttrInfo * attr)7000 R_API ut64 r_bin_java_bootstrap_methods_attr_calc_size(RBinJavaAttrInfo *attr) {
7001 	RListIter *iter, *iter_tmp;
7002 	RBinJavaBootStrapMethod *bsm = NULL;
7003 	ut64 size = 0;
7004 	if (attr) {
7005 		size += 6;
7006 		// attr->info.bootstrap_methods_attr.num_bootstrap_methods = R_BIN_JAVA_USHORT (buffer, offset);
7007 		size += 2;
7008 		r_list_foreach_safe (attr->info.bootstrap_methods_attr.bootstrap_methods, iter, iter_tmp, bsm) {
7009 			if (bsm) {
7010 				size += r_bin_java_bootstrap_method_calc_size (bsm);
7011 			} else {
7012 				// TODO eprintf Failed to read the %d boot strap method.
7013 			}
7014 		}
7015 	}
7016 	return size;
7017 }
7018 
r_bin_java_bootstrap_arg_calc_size(RBinJavaBootStrapArgument * bsm_arg)7019 R_API ut64 r_bin_java_bootstrap_arg_calc_size(RBinJavaBootStrapArgument *bsm_arg) {
7020 	ut64 size = 0;
7021 	if (bsm_arg) {
7022 		// bsm_arg->argument_info_idx = R_BIN_JAVA_USHORT (buffer, offset);
7023 		size += 2;
7024 	}
7025 	return size;
7026 }
7027 
r_bin_java_bootstrap_method_calc_size(RBinJavaBootStrapMethod * bsm)7028 R_API ut64 r_bin_java_bootstrap_method_calc_size(RBinJavaBootStrapMethod *bsm) {
7029 	RListIter *iter, *iter_tmp;
7030 	RBinJavaBootStrapArgument *bsm_arg = NULL;
7031 	ut64 size = 0;
7032 	if (bsm) {
7033 		size += 6;
7034 		// bsm->bootstrap_method_ref = R_BIN_JAVA_USHORT (buffer, offset);
7035 		size += 2;
7036 		// bsm->num_bootstrap_arguments = R_BIN_JAVA_USHORT (buffer, offset);
7037 		size += 2;
7038 		r_list_foreach_safe (bsm->bootstrap_arguments, iter, iter_tmp, bsm_arg) {
7039 			if (bsm_arg) {
7040 				size += r_bin_java_bootstrap_arg_calc_size (bsm_arg);
7041 			} else {
7042 				// TODO eprintf Failed to read the %d boot strap method.
7043 			}
7044 		}
7045 	}
7046 	return size;
7047 }
7048 
r_bin_java_bootstrap_methods_attr_new(RBinJavaObj * bin,ut8 * buffer,ut64 sz,ut64 buf_offset)7049 R_API RBinJavaAttrInfo *r_bin_java_bootstrap_methods_attr_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz, ut64 buf_offset) {
7050 	ut32 i = 0;
7051 	RBinJavaBootStrapMethod *bsm = NULL;
7052 	ut64 offset = 0;
7053 	RBinJavaAttrInfo *attr = r_bin_java_default_attr_new (bin, buffer, sz, buf_offset);
7054 	offset += 6;
7055 	if (attr) {
7056 		attr->type = R_BIN_JAVA_ATTR_TYPE_BOOTSTRAP_METHODS_ATTR;
7057 		attr->info.bootstrap_methods_attr.num_bootstrap_methods = R_BIN_JAVA_USHORT (buffer, offset);
7058 		offset += 2;
7059 		attr->info.bootstrap_methods_attr.bootstrap_methods = r_list_newf (r_bin_java_bootstrap_method_free);
7060 		for (i = 0; i < attr->info.bootstrap_methods_attr.num_bootstrap_methods; i++) {
7061 			// bsm = r_bin_java_bootstrap_method_new (bin, bin->b->cur);
7062 			if (offset >= sz) {
7063 				break;
7064 			}
7065 			bsm = r_bin_java_bootstrap_method_new (buffer + offset, sz - offset, buf_offset + offset);
7066 			if (bsm) {
7067 				offset += bsm->size;
7068 				r_list_append (attr->info.bootstrap_methods_attr.bootstrap_methods, (void *) bsm);
7069 			} else {
7070 				// TODO eprintf Failed to read the %d boot strap method.
7071 			}
7072 		}
7073 		attr->size = offset;
7074 	}
7075 	return attr;
7076 }
7077 
r_bin_java_print_annotation_default_attr_summary(RBinJavaAttrInfo * attr)7078 R_API void r_bin_java_print_annotation_default_attr_summary(RBinJavaAttrInfo *attr) {
7079 	if (attr && attr->type == R_BIN_JAVA_ATTR_TYPE_ANNOTATION_DEFAULT_ATTR) {
7080 		eprintf ("Annotation Default Attribute Information:\n");
7081 		eprintf ("   Attribute Offset: 0x%08"PFMT64x "\n", attr->file_offset);
7082 		eprintf ("   Attribute Name Index: %d (%s)\n", attr->name_idx, attr->name);
7083 		eprintf ("   Attribute Length: %d\n", attr->length);
7084 		r_bin_java_print_element_value_summary ((attr->info.annotation_default_attr.default_value));
7085 	} else {
7086 		// TODO: eprintf attr is invalid
7087 	}
7088 }
7089 
r_bin_java_annotation_array_free(void * a)7090 R_API void r_bin_java_annotation_array_free(void /*RBinJavaAnnotationsArray*/ *a) {
7091 	RBinJavaAnnotationsArray *annotation_array = a;
7092 	RListIter *iter = NULL, *iter_tmp = NULL;
7093 	RBinJavaAnnotation *annotation;
7094 	if (!annotation_array->annotations) {
7095 		// TODO eprintf
7096 		return;
7097 	}
7098 	r_list_foreach_safe (annotation_array->annotations, iter, iter_tmp, annotation) {
7099 		if (annotation) {
7100 			r_bin_java_annotation_free (annotation);
7101 		}
7102 		// r_list_delete (annotation_array->annotations, iter);
7103 	}
7104 	r_list_free (annotation_array->annotations);
7105 	free (annotation_array);
7106 }
7107 
r_bin_java_print_annotation_array_summary(RBinJavaAnnotationsArray * annotation_array)7108 R_API void r_bin_java_print_annotation_array_summary(RBinJavaAnnotationsArray *annotation_array) {
7109 	RListIter *iter = NULL, *iter_tmp = NULL;
7110 	RBinJavaAnnotation *annotation;
7111 	if (!annotation_array->annotations) {
7112 		// TODO eprintf
7113 		return;
7114 	}
7115 	eprintf ("   Annotation Array Information:\n");
7116 	eprintf ("   Number of Annotation Array Elements: %d\n", annotation_array->num_annotations);
7117 	r_list_foreach_safe (annotation_array->annotations, iter, iter_tmp, annotation) {
7118 		r_bin_java_print_annotation_summary (annotation);
7119 	}
7120 }
7121 
r_bin_java_annotation_array_new(ut8 * buffer,ut64 sz,ut64 buf_offset)7122 R_API RBinJavaAnnotationsArray *r_bin_java_annotation_array_new(ut8 *buffer, ut64 sz, ut64 buf_offset) {
7123 	RBinJavaAnnotation *annotation;
7124 	RBinJavaAnnotationsArray *annotation_array;
7125 	ut32 i;
7126 	ut64 offset = 0;
7127 	annotation_array = (RBinJavaAnnotationsArray *) malloc (sizeof (RBinJavaAnnotationsArray));
7128 	if (!annotation_array) {
7129 		// TODO eprintf
7130 		return NULL;
7131 	}
7132 	annotation_array->num_annotations = R_BIN_JAVA_USHORT (buffer, offset);
7133 	offset += 2;
7134 	annotation_array->annotations = r_list_new ();
7135 	for (i = 0; i < annotation_array->num_annotations; i++) {
7136 		if (offset > sz) {
7137 			break;
7138 		}
7139 		annotation = r_bin_java_annotation_new (buffer + offset, sz - offset, buf_offset + offset);
7140 		if (annotation) {
7141 			offset += annotation->size;
7142 			r_list_append (annotation_array->annotations, (void *) annotation);
7143 		}
7144 	}
7145 	annotation_array->size = offset;
7146 	return annotation_array;
7147 }
7148 
r_bin_java_rtv_annotations_attr_new(RBinJavaObj * bin,ut8 * buffer,ut64 sz,ut64 buf_offset)7149 R_API RBinJavaAttrInfo *r_bin_java_rtv_annotations_attr_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz, ut64 buf_offset) {
7150 	ut32 i = 0;
7151 	RBinJavaAttrInfo *attr = NULL;
7152 	ut64 offset = 0;
7153 	attr = r_bin_java_default_attr_new (bin, buffer, sz, buf_offset);
7154 	offset += 6;
7155 	if (attr) {
7156 		attr->type = R_BIN_JAVA_ATTR_TYPE_RUNTIME_VISIBLE_ANNOTATION_ATTR;
7157 		attr->info.annotation_array.num_annotations = R_BIN_JAVA_USHORT (buffer, offset);
7158 		offset += 2;
7159 		attr->info.annotation_array.annotations = r_list_newf (r_bin_java_annotation_free);
7160 		for (i = 0; i < attr->info.annotation_array.num_annotations; i++) {
7161 			if (offset >= sz) {
7162 				break;
7163 			}
7164 			RBinJavaAnnotation *annotation = r_bin_java_annotation_new (buffer + offset, sz - offset, buf_offset + offset);
7165 			if (annotation) {
7166 				offset += annotation->size;
7167 				r_list_append (attr->info.annotation_array.annotations, (void *) annotation);
7168 			}
7169 		}
7170 		attr->size = offset;
7171 	}
7172 	return attr;
7173 }
7174 
r_bin_java_annotation_array_calc_size(RBinJavaAnnotationsArray * annotation_array)7175 R_API ut64 r_bin_java_annotation_array_calc_size(RBinJavaAnnotationsArray *annotation_array) {
7176 	ut64 size = 0;
7177 	RListIter *iter = NULL, *iter_tmp = NULL;
7178 	RBinJavaAnnotation *annotation;
7179 	if (!annotation_array->annotations) {
7180 		// TODO eprintf
7181 		return size;
7182 	}
7183 	// annotation_array->num_annotations = R_BIN_JAVA_USHORT (buffer, offset);
7184 	size += 2;
7185 	r_list_foreach_safe (annotation_array->annotations, iter, iter_tmp, annotation) {
7186 		size += r_bin_java_annotation_calc_size (annotation);
7187 	}
7188 	return size;
7189 }
7190 
r_bin_java_rtv_annotations_attr_calc_size(RBinJavaAttrInfo * attr)7191 R_API ut64 r_bin_java_rtv_annotations_attr_calc_size(RBinJavaAttrInfo *attr) {
7192 	ut64 size = 0;
7193 	if (!attr) {
7194 		// TODO eprintf allocation fail
7195 		return size;
7196 	}
7197 	size += (6 + r_bin_java_annotation_array_calc_size (&(attr->info.annotation_array)));
7198 	return size;
7199 }
7200 
r_bin_java_rti_annotations_attr_new(RBinJavaObj * bin,ut8 * buffer,ut64 sz,ut64 buf_offset)7201 R_API RBinJavaAttrInfo *r_bin_java_rti_annotations_attr_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz, ut64 buf_offset) {
7202 	ut32 i = 0;
7203 	RBinJavaAttrInfo *attr = NULL;
7204 	ut64 offset = 0;
7205 	attr = r_bin_java_default_attr_new (bin, buffer, sz, buf_offset);
7206 	offset += 6;
7207 	if (attr) {
7208 		attr->type = R_BIN_JAVA_ATTR_TYPE_RUNTIME_INVISIBLE_ANNOTATION_ATTR;
7209 		attr->info.annotation_array.num_annotations = R_BIN_JAVA_USHORT (buffer, offset);
7210 		offset += 2;
7211 		attr->info.annotation_array.annotations = r_list_newf (r_bin_java_annotation_free);
7212 		for (i = 0; i < attr->info.rtv_annotations_attr.num_annotations; i++) {
7213 			if (offset >= sz) {
7214 				break;
7215 			}
7216 			RBinJavaAnnotation *annotation = r_bin_java_annotation_new (buffer + offset, sz - offset, buf_offset + offset);
7217 			if (annotation) {
7218 				offset += annotation->size;
7219 			}
7220 			r_list_append (attr->info.annotation_array.annotations, (void *) annotation);
7221 		}
7222 		attr->size = offset;
7223 	}
7224 	return attr;
7225 }
7226 
r_bin_java_rti_annotations_attr_calc_size(RBinJavaAttrInfo * attr)7227 R_API ut64 r_bin_java_rti_annotations_attr_calc_size(RBinJavaAttrInfo *attr) {
7228 	ut64 size = 0;
7229 	if (!attr) {
7230 		// TODO eprintf allocation fail
7231 		return size;
7232 	}
7233 	size += (6 + r_bin_java_annotation_array_calc_size (&(attr->info.annotation_array)));
7234 	return size;
7235 }
7236 
r_bin_java_rtv_annotations_attr_free(void * a)7237 R_API void r_bin_java_rtv_annotations_attr_free(void /*RBinJavaAttrInfo*/ *a) {
7238 	RBinJavaAttrInfo *attr = a;
7239 	if (attr && attr->type == R_BIN_JAVA_ATTR_TYPE_RUNTIME_VISIBLE_ANNOTATION_ATTR) {
7240 		r_list_free (attr->info.annotation_array.annotations);
7241 		free (attr->metas);
7242 		free (attr->name);
7243 		free (attr);
7244 	}
7245 }
7246 
r_bin_java_rti_annotations_attr_free(void * a)7247 R_API void r_bin_java_rti_annotations_attr_free(void /*RBinJavaAttrInfo*/ *a) {
7248 	RBinJavaAttrInfo *attr = a;
7249 	if (attr && attr->type == R_BIN_JAVA_ATTR_TYPE_RUNTIME_INVISIBLE_ANNOTATION_ATTR) {
7250 		r_list_free (attr->info.annotation_array.annotations);
7251 		free (attr->metas);
7252 		free (attr->name);
7253 		free (attr);
7254 	}
7255 }
7256 
r_bin_java_print_rtv_annotations_attr_summary(RBinJavaAttrInfo * attr)7257 R_API void r_bin_java_print_rtv_annotations_attr_summary(RBinJavaAttrInfo *attr) {
7258 	if (attr && attr->type == R_BIN_JAVA_ATTR_TYPE_RUNTIME_VISIBLE_ANNOTATION_ATTR) {
7259 		Eprintf ("Runtime Visible Annotations Attribute Information:\n");
7260 		Eprintf ("   Attribute Offset: 0x%08"PFMT64x "\n", attr->file_offset);
7261 		Eprintf ("   Attribute Name Index: %d (%s)\n", attr->name_idx, attr->name);
7262 		Eprintf ("   Attribute Length: %d\n", attr->length);
7263 		r_bin_java_print_annotation_array_summary (&attr->info.annotation_array);
7264 	}
7265 }
7266 
r_bin_java_print_rti_annotations_attr_summary(RBinJavaAttrInfo * attr)7267 R_API void r_bin_java_print_rti_annotations_attr_summary(RBinJavaAttrInfo *attr) {
7268 	if (attr && attr->type == R_BIN_JAVA_ATTR_TYPE_RUNTIME_INVISIBLE_ANNOTATION_ATTR) {
7269 		Eprintf ("Runtime Invisible Annotations Attribute Information:\n");
7270 		Eprintf ("   Attribute Offset: 0x%08"PFMT64x "\n", attr->file_offset);
7271 		Eprintf ("   Attribute Name Index: %d (%s)\n", attr->name_idx, attr->name);
7272 		Eprintf ("   Attribute Length: %d\n", attr->length);
7273 		r_bin_java_print_annotation_array_summary (&attr->info.annotation_array);
7274 	}
7275 }
7276 
r_bin_java_rtip_annotations_attr_calc_size(RBinJavaAttrInfo * attr)7277 R_API ut64 r_bin_java_rtip_annotations_attr_calc_size(RBinJavaAttrInfo *attr) {
7278 	ut64 size = 0;
7279 	RListIter *iter = NULL, *iter_tmp = NULL;
7280 	RBinJavaAnnotationsArray *annotation_array;
7281 	if (!attr) {
7282 		// TODO eprintf allocation fail
7283 		return size;
7284 	}
7285 	// attr->info.rtip_annotations_attr.num_parameters = buffer[offset];
7286 	size += (6 + 1);
7287 	r_list_foreach_safe (attr->info.rtip_annotations_attr.parameter_annotations, iter, iter_tmp, annotation_array) {
7288 		if (annotation_array) {
7289 			size += r_bin_java_annotation_array_calc_size (annotation_array);
7290 		}
7291 	}
7292 	return size;
7293 }
7294 
r_bin_java_rtip_annotations_attr_new(RBinJavaObj * bin,ut8 * buffer,ut64 sz,ut64 buf_offset)7295 R_API RBinJavaAttrInfo *r_bin_java_rtip_annotations_attr_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz, ut64 buf_offset) {
7296 	ut32 i = 0;
7297 	RBinJavaAttrInfo *attr = NULL;
7298 	ut64 offset = 0;
7299 	attr = r_bin_java_default_attr_new (bin, buffer, sz, buf_offset);
7300 	offset += 6;
7301 	if (attr) {
7302 		attr->type = R_BIN_JAVA_ATTR_TYPE_RUNTIME_INVISIBLE_PARAMETER_ANNOTATION_ATTR;
7303 		attr->info.rtip_annotations_attr.num_parameters = buffer[offset];
7304 		offset += 1;
7305 		attr->info.rtip_annotations_attr.parameter_annotations = r_list_newf (r_bin_java_annotation_array_free);
7306 		for (i = 0; i < attr->info.rtip_annotations_attr.num_parameters; i++) {
7307 			if (offset >= sz) {
7308 				break;
7309 			}
7310 			RBinJavaAnnotationsArray *annotation_array = r_bin_java_annotation_array_new (
7311 				buffer + offset, sz - offset, buf_offset + offset);
7312 			if (annotation_array) {
7313 				offset += annotation_array->size;
7314 				r_list_append (attr->info.rtip_annotations_attr.parameter_annotations, (void *) annotation_array);
7315 			}
7316 		}
7317 		attr->size = offset;
7318 	}
7319 	return attr;
7320 }
7321 
r_bin_java_rtvp_annotations_attr_new(RBinJavaObj * bin,ut8 * buffer,ut64 sz,ut64 buf_offset)7322 R_API RBinJavaAttrInfo *r_bin_java_rtvp_annotations_attr_new(RBinJavaObj *bin, ut8 *buffer, ut64 sz, ut64 buf_offset) {
7323 	ut32 i = 0;
7324 	RBinJavaAttrInfo *attr = NULL;
7325 	ut64 offset = 0;
7326 	attr = r_bin_java_default_attr_new (bin, buffer, sz, buf_offset);
7327 	offset += 6;
7328 	RBinJavaAnnotationsArray *annotation_array;
7329 	if (attr) {
7330 		attr->type = R_BIN_JAVA_ATTR_TYPE_RUNTIME_VISIBLE_PARAMETER_ANNOTATION_ATTR;
7331 		attr->info.rtvp_annotations_attr.num_parameters = buffer[offset];
7332 		offset += 1;
7333 		attr->info.rtvp_annotations_attr.parameter_annotations = r_list_newf (r_bin_java_annotation_array_free);
7334 		for (i = 0; i < attr->info.rtvp_annotations_attr.num_parameters; i++) {
7335 			if (offset > sz) {
7336 				break;
7337 			}
7338 			annotation_array = r_bin_java_annotation_array_new (buffer + offset, sz - offset, buf_offset + offset);
7339 			if (annotation_array) {
7340 				offset += annotation_array->size;
7341 			}
7342 			r_list_append (attr->info.rtvp_annotations_attr.parameter_annotations, (void *) annotation_array);
7343 		}
7344 		attr->size = offset;
7345 	}
7346 	return attr;
7347 }
7348 
r_bin_java_rtvp_annotations_attr_calc_size(RBinJavaAttrInfo * attr)7349 R_API ut64 r_bin_java_rtvp_annotations_attr_calc_size(RBinJavaAttrInfo *attr) {
7350 	ut64 size = 0;
7351 	RListIter *iter = NULL, *iter_tmp = NULL;
7352 	RBinJavaAnnotationsArray *annotation_array;
7353 	if (!attr) {
7354 		return size;
7355 	}
7356 	size += (6 + 1);
7357 	r_list_foreach_safe (attr->info.rtvp_annotations_attr.parameter_annotations,
7358 		iter, iter_tmp, annotation_array) {
7359 		if (annotation_array) {
7360 			size += r_bin_java_annotation_array_calc_size (
7361 				annotation_array);
7362 		}
7363 	}
7364 	return size;
7365 }
7366 
r_bin_java_rtvp_annotations_attr_free(void * a)7367 R_API void r_bin_java_rtvp_annotations_attr_free(void /*RBinJavaAttrInfo*/ *a) {
7368 	RBinJavaAttrInfo *attr = a;
7369 	if (attr) {
7370 		if (attr->type == R_BIN_JAVA_ATTR_TYPE_RUNTIME_VISIBLE_PARAMETER_ANNOTATION_ATTR) {
7371 			r_list_free (attr->info.rtvp_annotations_attr.parameter_annotations);
7372 		}
7373 		free (attr->name);
7374 		free (attr->metas);
7375 		free (attr);
7376 	}
7377 }
7378 
r_bin_java_rtip_annotations_attr_free(void * a)7379 R_API void r_bin_java_rtip_annotations_attr_free(void /*RBinJavaAttrInfo*/ *a) {
7380 	RBinJavaAttrInfo *attr = a;
7381 	if (attr) { // && attr->type == R_BIN_JAVA_ATTR_TYPE_RUNTIME_INVISIBLE_PARAMETER_ANNOTATION_ATTR) {
7382 		r_list_free (attr->info.rtip_annotations_attr.parameter_annotations);
7383 		free (attr->metas);
7384 		free (attr->name);
7385 		free (attr);
7386 	}
7387 }
7388 
r_bin_java_print_rtvp_annotations_attr_summary(RBinJavaAttrInfo * attr)7389 R_API void r_bin_java_print_rtvp_annotations_attr_summary(RBinJavaAttrInfo *attr) {
7390 	RBinJavaAnnotationsArray *annotation_array = NULL;
7391 	RListIter *iter = NULL, *iter_tmp = NULL;
7392 	if (attr && attr->type == R_BIN_JAVA_ATTR_TYPE_RUNTIME_VISIBLE_PARAMETER_ANNOTATION_ATTR) {
7393 		eprintf ("Runtime Visible Parameter Annotations Attribute Information:\n");
7394 		eprintf ("  Attribute Offset: 0x%08"PFMT64x "\n", attr->file_offset);
7395 		eprintf ("  Attribute Name Index: %d (%s)\n", attr->name_idx, attr->name);
7396 		eprintf ("  Attribute Length: %d\n", attr->length);
7397 		eprintf ("  Number of Runtime Invisible Parameters: %d\n", attr->info.rtvp_annotations_attr.num_parameters);
7398 		r_list_foreach_safe (attr->info.rtvp_annotations_attr.parameter_annotations, iter, iter_tmp, annotation_array) {
7399 			r_bin_java_print_annotation_array_summary (annotation_array);
7400 		}
7401 	}
7402 }
7403 
r_bin_java_print_rtip_annotations_attr_summary(RBinJavaAttrInfo * attr)7404 R_API void r_bin_java_print_rtip_annotations_attr_summary(RBinJavaAttrInfo *attr) {
7405 	RBinJavaAnnotationsArray *annotation_array = NULL;
7406 	RListIter *iter = NULL, *iter_tmp = NULL;
7407 	if (attr && attr->type == R_BIN_JAVA_ATTR_TYPE_RUNTIME_INVISIBLE_PARAMETER_ANNOTATION_ATTR) {
7408 		eprintf ("Runtime Invisible Parameter Annotations Attribute Information:\n");
7409 		eprintf ("  Attribute Offset: 0x%08"PFMT64x "\n", attr->file_offset);
7410 		eprintf ("  Attribute Name Index: %d (%s)\n", attr->name_idx, attr->name);
7411 		eprintf ("  Attribute Length: %d\n", attr->length);
7412 		eprintf ("  Number of Runtime Invisible Parameters: %d\n", attr->info.rtip_annotations_attr.num_parameters);
7413 		r_list_foreach_safe (attr->info.rtip_annotations_attr.parameter_annotations, iter, iter_tmp, annotation_array) {
7414 			r_bin_java_print_annotation_array_summary (annotation_array);
7415 		}
7416 	}
7417 }
7418 
r_bin_java_find_cp_name_and_type_info(RBinJavaObj * bin,ut16 name_idx,ut16 descriptor_idx)7419 R_API RBinJavaCPTypeObj *r_bin_java_find_cp_name_and_type_info(RBinJavaObj *bin, ut16 name_idx, ut16 descriptor_idx) {
7420 	RListIter *iter, *iter_tmp;
7421 	RBinJavaCPTypeObj *res = NULL, *obj = NULL;
7422 	IFDBG eprintf("Looking for name_idx: %d and descriptor_idx: %d\n", name_idx, descriptor_idx);
7423 	r_list_foreach_safe (bin->cp_list, iter, iter_tmp, obj) {
7424 		if (obj && obj->tag == R_BIN_JAVA_CP_NAMEANDTYPE) {
7425 			IFDBG eprintf("RBinJavaCPTypeNameAndType has name_idx: %d and descriptor_idx: %d\n",
7426 			obj->info.cp_name_and_type.name_idx, obj->info.cp_name_and_type.descriptor_idx);
7427 			if (obj->info.cp_name_and_type.name_idx == name_idx &&
7428 			obj->info.cp_name_and_type.descriptor_idx == descriptor_idx) {
7429 				res = obj;
7430 				break;
7431 			}
7432 		}
7433 	}
7434 	return res;
7435 }
7436 
r_bin_java_resolve_cp_idx_type(RBinJavaObj * BIN_OBJ,int idx)7437 R_API char *r_bin_java_resolve_cp_idx_type(RBinJavaObj *BIN_OBJ, int idx) {
7438 	RBinJavaCPTypeObj *item = NULL;
7439 	char *str = NULL;
7440 	if (BIN_OBJ && BIN_OBJ->cp_count < 1) {
7441 		// r_bin_java_new_bin(BIN_OBJ);
7442 		return NULL;
7443 	}
7444 	item = (RBinJavaCPTypeObj *) r_bin_java_get_item_from_bin_cp_list (BIN_OBJ, idx);
7445 	if (item) {
7446 		str = strdup (((RBinJavaCPTypeMetas *) item->metas->type_info)->name);
7447 	} else {
7448 		str = strdup ("INVALID");
7449 	}
7450 	return str;
7451 }
7452 
r_bin_java_find_cp_ref_info_from_name_and_type(RBinJavaObj * bin,ut16 name_idx,ut16 descriptor_idx)7453 R_API RBinJavaCPTypeObj *r_bin_java_find_cp_ref_info_from_name_and_type(RBinJavaObj *bin, ut16 name_idx, ut16 descriptor_idx) {
7454 	RBinJavaCPTypeObj *obj = r_bin_java_find_cp_name_and_type_info (bin, name_idx, descriptor_idx);
7455 	if (obj) {
7456 		return r_bin_java_find_cp_ref_info (bin, obj->metas->ord);
7457 	}
7458 	return NULL;
7459 }
7460 
r_bin_java_find_cp_ref_info(RBinJavaObj * bin,ut16 name_and_type_idx)7461 R_API RBinJavaCPTypeObj *r_bin_java_find_cp_ref_info(RBinJavaObj *bin, ut16 name_and_type_idx) {
7462 	RListIter *iter, *iter_tmp;
7463 	RBinJavaCPTypeObj *res = NULL, *obj = NULL;
7464 	r_list_foreach_safe (bin->cp_list, iter, iter_tmp, obj) {
7465 		if (obj->tag == R_BIN_JAVA_CP_FIELDREF &&
7466 		obj->info.cp_field.name_and_type_idx == name_and_type_idx) {
7467 			res = obj;
7468 			break;
7469 		} else if (obj->tag == R_BIN_JAVA_CP_METHODREF &&
7470 		obj->info.cp_method.name_and_type_idx == name_and_type_idx) {
7471 			res = obj;
7472 			break;
7473 		}
7474 	}
7475 	return res;
7476 }
7477 
r_bin_java_resolve(RBinJavaObj * BIN_OBJ,int idx,ut8 space_bn_name_type)7478 R_API char *r_bin_java_resolve(RBinJavaObj *BIN_OBJ, int idx, ut8 space_bn_name_type) {
7479 	// TODO XXX FIXME add a size parameter to the str when it is passed in
7480 	RBinJavaCPTypeObj *item = NULL, *item2 = NULL;
7481 	char *class_str = NULL,
7482 	*name_str = NULL,
7483 	*desc_str = NULL,
7484 	*string_str = NULL,
7485 	*empty = "",
7486 	*cp_name = NULL,
7487 	*str = NULL;
7488 	if (BIN_OBJ && BIN_OBJ->cp_count < 1) {
7489 		// r_bin_java_new_bin(BIN_OBJ);
7490 		return NULL;
7491 	}
7492 	item = (RBinJavaCPTypeObj *) r_bin_java_get_item_from_bin_cp_list (BIN_OBJ, idx);
7493 	if (item) {
7494 		cp_name = ((RBinJavaCPTypeMetas *) item->metas->type_info)->name;
7495 		IFDBG eprintf("java_resolve Resolved: (%d) %s\n", idx, cp_name);
7496 	} else {
7497 		str = malloc (512);
7498 		if (str) {
7499 			snprintf (str, 512, "(%d) INVALID CP_OBJ", idx);
7500 		}
7501 		return str;
7502 	}
7503 	if (strcmp (cp_name, "Class") == 0) {
7504 		item2 = (RBinJavaCPTypeObj *) r_bin_java_get_item_from_bin_cp_list (BIN_OBJ, idx);
7505 		// str = r_bin_java_get_name_from_bin_cp_list (BIN_OBJ, idx-1);
7506 		class_str = r_bin_java_get_item_name_from_bin_cp_list (BIN_OBJ, item);
7507 		if (!class_str) {
7508 			class_str = empty;
7509 		}
7510 		name_str = r_bin_java_get_item_name_from_bin_cp_list (BIN_OBJ, item2);
7511 		if (!name_str) {
7512 			name_str = empty;
7513 		}
7514 		desc_str = r_bin_java_get_item_desc_from_bin_cp_list (BIN_OBJ, item2);
7515 		if (!desc_str) {
7516 			desc_str = empty;
7517 		}
7518 		str = r_str_newf ("%s%s%s", name_str,
7519 			space_bn_name_type ? " " : "", desc_str);
7520 		if (class_str != empty) {
7521 			free (class_str);
7522 		}
7523 		if (name_str != empty) {
7524 			free (name_str);
7525 		}
7526 		if (desc_str != empty) {
7527 			free (desc_str);
7528 		}
7529 	} else if (!strcmp (cp_name, "MethodRef") ||
7530 	!strcmp (cp_name, "FieldRef") ||
7531 	!strcmp (cp_name, "InterfaceMethodRef")) {
7532 		/*
7533 		*  The MethodRef, FieldRef, and InterfaceMethodRef structures
7534 		*/
7535 		class_str = r_bin_java_get_name_from_bin_cp_list (BIN_OBJ, item->info.cp_method.class_idx);
7536 		if (!class_str) {
7537 			class_str = empty;
7538 		}
7539 		name_str = r_bin_java_get_item_name_from_bin_cp_list (BIN_OBJ, item);
7540 		if (!name_str) {
7541 			name_str = empty;
7542 		}
7543 		desc_str = r_bin_java_get_item_desc_from_bin_cp_list (BIN_OBJ, item);
7544 		if (!desc_str) {
7545 			desc_str = empty;
7546 		}
7547 		str = r_str_newf ("%s/%s%s%s", class_str, name_str,
7548 			space_bn_name_type ? " " : "", desc_str);
7549 		if (class_str != empty) {
7550 			free (class_str);
7551 		}
7552 		if (name_str != empty) {
7553 			free (name_str);
7554 		}
7555 		if (desc_str != empty) {
7556 			free (desc_str);
7557 		}
7558 	} else if (!strcmp (cp_name, "String")) {
7559 		string_str = r_bin_java_get_utf8_from_bin_cp_list (BIN_OBJ, item->info.cp_string.string_idx);
7560 		str = NULL;
7561 		IFDBG eprintf("java_resolve String got: (%d) %s\n", item->info.cp_string.string_idx, string_str);
7562 		if (!string_str) {
7563 			string_str = empty;
7564 		}
7565 		str = r_str_newf ("\"%s\"", string_str);
7566 		IFDBG eprintf("java_resolve String return: %s\n", str);
7567 		if (string_str != empty) {
7568 			free (string_str);
7569 		}
7570 
7571 	} else if (!strcmp (cp_name, "Utf8")) {
7572 		char *tmp_str = convert_string ((const char *) item->info.cp_utf8.bytes, item->info.cp_utf8.length);
7573 		ut32 tmp_str_len = tmp_str ? strlen (tmp_str) + 4 : 0;
7574 		if (tmp_str) {
7575 			str = malloc (tmp_str_len + 4);
7576 			snprintf (str, tmp_str_len + 4, "\"%s\"", tmp_str);
7577 		}
7578 		free (tmp_str);
7579 	} else if (!strcmp (cp_name, "Long")) {
7580 		str = r_str_newf ("0x%"PFMT64x, r_bin_java_raw_to_long (item->info.cp_long.bytes.raw, 0));
7581 	} else if (!strcmp (cp_name, "Double")) {
7582 		str = r_str_newf ("%f", r_bin_java_raw_to_double (item->info.cp_double.bytes.raw, 0));
7583 	} else if (!strcmp (cp_name, "Integer")) {
7584 		str = r_str_newf ("0x%08x", R_BIN_JAVA_UINT (item->info.cp_integer.bytes.raw, 0));
7585 	} else if (!strcmp (cp_name, "Float")) {
7586 		str = r_str_newf ("%f", R_BIN_JAVA_FLOAT (item->info.cp_float.bytes.raw, 0));
7587 	} else if (!strcmp (cp_name, "NameAndType")) {
7588 		name_str = r_bin_java_get_item_name_from_bin_cp_list (BIN_OBJ, item);
7589 		if (!name_str) {
7590 			name_str = empty;
7591 		}
7592 		desc_str = r_bin_java_get_item_desc_from_bin_cp_list (BIN_OBJ, item);
7593 		if (!desc_str) {
7594 			desc_str = empty;
7595 		}
7596 		str = r_str_newf ("%s%s%s", name_str, space_bn_name_type ? " " : "", desc_str);
7597 		if (name_str != empty) {
7598 			free (name_str);
7599 		}
7600 		if (desc_str != empty) {
7601 			free (desc_str);
7602 		}
7603 	} else {
7604 		str = strdup ("(null)");
7605 	}
7606 	return str;
7607 }
7608 
r_bin_java_does_cp_idx_ref_method(RBinJavaObj * BIN_OBJ,int idx)7609 R_API ut8 r_bin_java_does_cp_idx_ref_method(RBinJavaObj *BIN_OBJ, int idx) {
7610 	RBinJavaField *fm_type = NULL;
7611 	RListIter *iter;
7612 	ut8 res = 0;
7613 	r_list_foreach (BIN_OBJ->methods_list, iter, fm_type) {
7614 		if (fm_type->field_ref_cp_obj->metas->ord == idx) {
7615 			res = 1;
7616 			break;
7617 		}
7618 	}
7619 	return res;
7620 }
7621 
r_bin_java_does_cp_idx_ref_field(RBinJavaObj * BIN_OBJ,int idx)7622 R_API ut8 r_bin_java_does_cp_idx_ref_field(RBinJavaObj *BIN_OBJ, int idx) {
7623 	RBinJavaField *fm_type = NULL;
7624 	RListIter *iter;
7625 	ut8 res = 0;
7626 	r_list_foreach (BIN_OBJ->fields_list, iter, fm_type) {
7627 		if (fm_type->field_ref_cp_obj->metas->ord == idx) {
7628 			res = 1;
7629 			break;
7630 		}
7631 	}
7632 	return res;
7633 }
7634 
r_bin_java_get_method_name(RBinJavaObj * bin_obj,ut32 idx)7635 R_API char *r_bin_java_get_method_name(RBinJavaObj *bin_obj, ut32 idx) {
7636 	char *name = NULL;
7637 	if (idx < r_list_length (bin_obj->methods_list)) {
7638 		RBinJavaField *fm_type = r_list_get_n (bin_obj->methods_list, idx);
7639 		name = strdup (fm_type->name);
7640 	}
7641 	return name;
7642 }
7643 
r_bin_java_get_method_num_name(RBinJavaObj * bin_obj)7644 R_API RList *r_bin_java_get_method_num_name(RBinJavaObj *bin_obj) {
7645 	ut32 i = 0;
7646 	RListIter *iter = NULL;
7647 	RBinJavaField *fm_type;
7648 	RList *res = r_list_newf (free);
7649 	r_list_foreach (bin_obj->methods_list, iter, fm_type) {
7650 		ut32 len = strlen (fm_type->name) + 30;
7651 		char *str = malloc (len);
7652 		snprintf (str, len, "%d %s", i, fm_type->name);
7653 		++i;
7654 		r_list_append (res, str);
7655 	}
7656 	return res;
7657 }
7658 
7659 /*
7660    R_API int r_bin_java_does_cp_obj_ref_idx (RBinJavaObj *bin_obj, RBinJavaCPTypeObj *cp_obj, ut16 idx) {
7661         int res = false;
7662         RBinJavaCPTypeObj *t_obj = NULL;
7663         if (cp_obj) {
7664                 switch (cp_obj->tag) {
7665                         case R_BIN_JAVA_CP_NULL: break;
7666                         case R_BIN_JAVA_CP_UTF8: break;
7667                         case R_BIN_JAVA_CP_UNKNOWN: break;
7668                         case R_BIN_JAVA_CP_INTEGER: break;
7669                         case R_BIN_JAVA_CP_FLOAT: break;
7670                         case R_BIN_JAVA_CP_LONG: break;
7671                         case R_BIN_JAVA_CP_DOUBLE: break;
7672                         case R_BIN_JAVA_CP_CLASS:
7673                                 res = idx == cp_obj->info.cp_class.name_idx ? true : false;
7674                                 break;
7675                         case R_BIN_JAVA_CP_STRING:
7676                                 res = idx == cp_obj->info.cp_string.string_idx ? true : false;
7677                                 break;
7678                         case R_BIN_JAVA_CP_METHODREF: break;// check if idx is referenced here
7679                         case R_BIN_JAVA_CP_INTERFACEMETHOD_REF: break; // check if idx is referenced here
7680                         case R_BIN_JAVA_CP_FIELDREF:
7681                                 t_obj = r_bin_java_get_item_from_cp (bin_obj, cp_obj->info.cp_method.class_idx);
7682                                 res = r_bin_java_does_cp_obj_ref_idx (bin_obj, t_obj, idx);
7683                                 if (res == true) break;
7684                                 t_obj = r_bin_java_get_item_from_cp (bin_obj, cp_obj->info.cp_method.name_and_type_idx);
7685                                 res = r_bin_java_does_cp_obj_ref_idx (bin_obj, t_obj, idx);
7686                                 break;
7687                         case R_BIN_JAVA_CP_NAMEANDTYPE: break;// check if idx is referenced here
7688                                 obj->info.cp_name_and_type.name_idx
7689                         case R_BIN_JAVA_CP_METHODHANDLE: break;// check if idx is referenced here
7690                         case R_BIN_JAVA_CP_METHODTYPE: break;// check if idx is referenced here
7691                         case R_BIN_JAVA_CP_INVOKEDYNAMIC: break;// check if idx is referenced here
7692                 }
7693         }
7694    }
7695  */
r_bin_java_find_cp_const_by_val_long(RBinJavaObj * bin_obj,const ut8 * bytes,ut32 len)7696 R_API RList *r_bin_java_find_cp_const_by_val_long(RBinJavaObj *bin_obj, const ut8 *bytes, ut32 len) {
7697 	RList *res = r_list_newf (free);
7698 	ut32 *v = NULL;
7699 	RListIter *iter;
7700 	RBinJavaCPTypeObj *cp_obj;
7701 	eprintf ("Looking for 0x%08x\n", R_BIN_JAVA_UINT (bytes, 0));
7702 	r_list_foreach (bin_obj->cp_list, iter, cp_obj) {
7703 		if (cp_obj->tag == R_BIN_JAVA_CP_LONG) {
7704 			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)) {
7705 				// TODO: we can safely store a ut32 inside the list without having to allocate it
7706 				v = malloc (sizeof (ut32));
7707 				if (!v) {
7708 					r_list_free (res);
7709 					return NULL;
7710 				}
7711 				*v = cp_obj->idx;
7712 				r_list_append (res, v);
7713 			}
7714 		}
7715 	}
7716 	return res;
7717 }
7718 
r_bin_java_find_cp_const_by_val_double(RBinJavaObj * bin_obj,const ut8 * bytes,ut32 len)7719 R_API RList *r_bin_java_find_cp_const_by_val_double(RBinJavaObj *bin_obj, const ut8 *bytes, ut32 len) {
7720 	RList *res = r_list_newf (free);
7721 	ut32 *v = NULL;
7722 	RListIter *iter;
7723 	RBinJavaCPTypeObj *cp_obj;
7724 	eprintf ("Looking for %f\n", r_bin_java_raw_to_double (bytes, 0));
7725 	r_list_foreach (bin_obj->cp_list, iter, cp_obj) {
7726 		if (cp_obj->tag == R_BIN_JAVA_CP_DOUBLE) {
7727 			if (len == 8 && r_bin_java_raw_to_double (cp_obj->info.cp_long.bytes.raw, 0) == r_bin_java_raw_to_double (bytes, 0)) {
7728 				v = malloc (sizeof (ut32));
7729 				if (!v) {
7730 					r_list_free (res);
7731 					return NULL;
7732 				}
7733 				*v = cp_obj->idx;
7734 				r_list_append (res, v);
7735 			}
7736 		}
7737 	}
7738 	return res;
7739 }
7740 
r_bin_java_find_cp_const_by_val_float(RBinJavaObj * bin_obj,const ut8 * bytes,ut32 len)7741 R_API RList *r_bin_java_find_cp_const_by_val_float(RBinJavaObj *bin_obj, const ut8 *bytes, ut32 len) {
7742 	RList *res = r_list_newf (free);
7743 	ut32 *v = NULL;
7744 	RListIter *iter;
7745 	RBinJavaCPTypeObj *cp_obj;
7746 	eprintf ("Looking for %f\n", R_BIN_JAVA_FLOAT (bytes, 0));
7747 	r_list_foreach (bin_obj->cp_list, iter, cp_obj) {
7748 		if (cp_obj->tag == R_BIN_JAVA_CP_FLOAT) {
7749 			if (len == 4 && R_BIN_JAVA_FLOAT (cp_obj->info.cp_long.bytes.raw, 0) == R_BIN_JAVA_FLOAT (bytes, 0)) {
7750 				v = malloc (sizeof (ut32));
7751 				if (!v) {
7752 					r_list_free (res);
7753 					return NULL;
7754 				}
7755 				*v = cp_obj->idx;
7756 				r_list_append (res, v);
7757 			}
7758 		}
7759 	}
7760 	return res;
7761 }
7762 
r_bin_java_find_cp_const_by_val(RBinJavaObj * bin_obj,const ut8 * bytes,ut32 len,const char t)7763 R_API RList *r_bin_java_find_cp_const_by_val(RBinJavaObj *bin_obj, const ut8 *bytes, ut32 len, const char t) {
7764 	switch (t) {
7765 	case R_BIN_JAVA_CP_UTF8: return r_bin_java_find_cp_const_by_val_utf8 (bin_obj, bytes, len);
7766 	case R_BIN_JAVA_CP_INTEGER: return r_bin_java_find_cp_const_by_val_int (bin_obj, bytes, len);
7767 	case R_BIN_JAVA_CP_FLOAT: return r_bin_java_find_cp_const_by_val_float (bin_obj, bytes, len);
7768 	case R_BIN_JAVA_CP_LONG: return r_bin_java_find_cp_const_by_val_long (bin_obj, bytes, len);
7769 	case R_BIN_JAVA_CP_DOUBLE: return r_bin_java_find_cp_const_by_val_double (bin_obj, bytes, len);
7770 	case R_BIN_JAVA_CP_UNKNOWN:
7771 	default:
7772 		eprintf ("Failed to perform the search for: %s\n", bytes);
7773 		return r_list_new ();
7774 	}
7775 }
7776 
7777 // #if 0
7778 // Attempted to clean up these functions and remove them since they are "unused" but without
7779 // them there are some compile time warnings, because other projects actually depend on these
7780 // for some form of information.
U(add_cp_objs_to_sdb)7781 R_API void U(add_cp_objs_to_sdb)(RBinJavaObj * bin) {
7782 	/*
7783 	Add Constant Pool Serialized Object to an Array
7784 	the key for this info is:
7785 	Key:
7786 	java.<classname>.cp_obj
7787 	Each Value varies by type:
7788 	In general its:
7789 	<ordinal>.<file_offset>.<type_name>.[type specific stuff]
7790 	Example:
7791 	UTF-8:  <ordinal>.<file_offset>.<type_name>.<strlen>.<hexlified(str)>
7792 	Integer: <ordinal>.<file_offset>.<type_name>.<abs(int)>
7793 	Long: <ordinal>.<file_offset>.<type_name>.abs(long)>
7794 	FieldRef/MethodRef: <ordinal>.<file_offset>.<type_name>.<class_idx>.<name_and_type_idx>
7795 	*/
7796 	ut32 idx = 0, class_name_inheap = 1;
7797 	RBinJavaCPTypeObj *cp_obj = NULL;
7798 	char *key = NULL,
7799 	*value = NULL;
7800 	char str_cnt[40];
7801 	char *class_name = r_bin_java_get_this_class_name (bin);
7802 	ut32 key_buf_size = 0;
7803 	if (!class_name) {
7804 		class_name = "unknown";
7805 		class_name_inheap = 0;
7806 	}
7807 	// 4 - format, 8 number, 1 null byte, 7 "unknown"
7808 	key_buf_size = strlen (class_name) + 4 + 8 + 1;
7809 	key = malloc (key_buf_size);
7810 	if (key == NULL) {
7811 		if (class_name_inheap) {
7812 			free (class_name);
7813 		}
7814 		return;
7815 	}
7816 	snprintf (key, key_buf_size - 1, "%s.cp_count", class_name);
7817 	key[key_buf_size - 1] = 0;
7818 	snprintf (str_cnt, 39, "%d", bin->cp_count);
7819 	str_cnt[39] = 0;
7820 	sdb_set (bin->kv, key, value, 0);
7821 	// sdb_alist(bin->kv, key);
7822 	for (idx = 0; idx < bin->cp_count; idx++) {
7823 		snprintf (key, key_buf_size - 1, "%s.cp.%d", class_name, idx);
7824 		key[key_buf_size - 1] = 0;
7825 		cp_obj = (RBinJavaCPTypeObj *) r_bin_java_get_item_from_bin_cp_list (bin, idx);
7826 		IFDBG eprintf("Adding %s to the sdb.\n", key);
7827 		if (cp_obj) {
7828 			value = ((RBinJavaCPTypeMetas *)
7829 			cp_obj->metas->type_info)->
7830 			allocs->stringify_obj (cp_obj);
7831 			sdb_set (bin->kv, key, value, 0);
7832 			free (value);
7833 		}
7834 	}
7835 	if (class_name_inheap) {
7836 		free (class_name);
7837 	}
7838 	free (key);
7839 }
7840 
U(add_field_infos_to_sdb)7841 R_API void U(add_field_infos_to_sdb)(RBinJavaObj * bin) {
7842 	/*
7843 	*** Experimental and May Change ***
7844 	Add field information to an Array
7845 	the key for this info variable depenedent on addr, method ordinal, etc.
7846 	Key 1, mapping to method key:
7847 	java.<file_offset> = <field_key>
7848 	Key 3, method description
7849 	<field_key>.info = [<access str>, <class_name>, <name>, <signature>]
7850 	key 4, method meta
7851 	<field_key>.meta = [<file_offset>, ?]
7852 	*/
7853 	RListIter *iter = NULL, *iter_tmp = NULL;
7854 	RBinJavaField *fm_type;
7855 	ut32 key_size = 255,
7856 	value_buffer_size = 1024,
7857 	class_name_inheap = 1;
7858 	char *field_key = NULL,
7859 	*field_key_value = NULL,
7860 	*value_buffer = NULL;
7861 	char *class_name = r_bin_java_get_this_class_name (bin);
7862 	if (!class_name) {
7863 		class_name = "unknown";
7864 		class_name_inheap = 0;
7865 	}
7866 	key_size += strlen (class_name);
7867 	value_buffer_size += strlen (class_name);
7868 	field_key = malloc (key_size);
7869 	value_buffer = malloc (value_buffer_size);
7870 	field_key_value = malloc (key_size);
7871 	snprintf (field_key, key_size, "%s.methods", class_name);
7872 	field_key[key_size - 1] = 0;
7873 	r_list_foreach_safe (bin->fields_list, iter, iter_tmp, fm_type) {
7874 		char number_buffer[80];
7875 		ut64 file_offset = fm_type->file_offset + bin->loadaddr;
7876 		snprintf (number_buffer, sizeof (number_buffer), "0x%04"PFMT64x, file_offset);
7877 		IFDBG eprintf("Inserting: []%s = %s\n", field_key, number_buffer);
7878 		sdb_array_push (bin->kv, field_key, number_buffer, 0);
7879 	}
7880 	r_list_foreach_safe (bin->fields_list, iter, iter_tmp, fm_type) {
7881 		ut64 field_offset = fm_type->file_offset + bin->loadaddr;
7882 		// generate method specific key & value
7883 		snprintf (field_key, key_size, "%s.0x%04"PFMT64x, class_name, field_offset);
7884 		field_key[key_size - 1] = 0;
7885 		snprintf (field_key_value, key_size, "%s.0x%04"PFMT64x ".field", class_name, field_offset);
7886 		field_key_value[key_size - 1] = 0;
7887 		sdb_set (bin->kv, field_key, field_key_value, 0);
7888 		IFDBG eprintf("Inserting: %s = %s\n", field_key, field_key_value);
7889 		// generate info key, and place values in method info array
7890 		snprintf (field_key, key_size, "%s.info", field_key_value);
7891 		field_key[key_size - 1] = 0;
7892 		snprintf (value_buffer, value_buffer_size, "%s", fm_type->flags_str);
7893 		value_buffer[value_buffer_size - 1] = 0;
7894 		sdb_array_push (bin->kv, field_key, value_buffer, 0);
7895 		IFDBG eprintf("Inserting: []%s = %s\n", field_key, value_buffer);
7896 		snprintf (value_buffer, value_buffer_size, "%s", fm_type->class_name);
7897 		value_buffer[value_buffer_size - 1] = 0;
7898 		sdb_array_push (bin->kv, field_key, value_buffer, 0);
7899 		IFDBG eprintf("Inserting: []%s = %s\n", field_key, value_buffer);
7900 		snprintf (value_buffer, value_buffer_size, "%s", fm_type->name);
7901 		value_buffer[value_buffer_size - 1] = 0;
7902 		sdb_array_push (bin->kv, field_key, value_buffer, 0);
7903 		IFDBG eprintf("Inserting: []%s = %s\n", field_key, value_buffer);
7904 		snprintf (value_buffer, value_buffer_size, "%s", fm_type->descriptor);
7905 		value_buffer[value_buffer_size - 1] = 0;
7906 		sdb_array_push (bin->kv, field_key, value_buffer, 0);
7907 		IFDBG eprintf("Inserting: []%s = %s\n", field_key, value_buffer);
7908 	}
7909 	free (field_key);
7910 	free (field_key_value);
7911 	free (value_buffer);
7912 	if (class_name_inheap) {
7913 		free (class_name);
7914 	}
7915 }
7916 
U(add_method_infos_to_sdb)7917 R_API void U(add_method_infos_to_sdb)(RBinJavaObj * bin) {
7918 	/*
7919 	*** Experimental and May Change ***
7920 	Add Mehtod information to an Array
7921 	the key for this info variable depenedent on addr, method ordinal, etc.
7922 	Key 1, mapping to method key:
7923 	java.<file_offset> = <method_key>
7924 	Key 2, basic code information
7925 	<method_key>.code = [<addr>, <size>]
7926 	Key 3, method description
7927 	<method_key>.info = [<access str>, <class_name>, <name>, <signature>,]
7928 	key 4, method meta
7929 	<method_key>.meta = [<file_offset>, ?]
7930 	// TODO in key 3 add <class_name>?
7931 	e.g. <access str>.<name>.<signature>
7932 	Note: method name not used because of collisions with operator overloading
7933 	also take note that code offset and the method offset are not the same
7934 	values.
7935 	*/
7936 	RListIter *iter = NULL, *iter_tmp = NULL;
7937 	RBinJavaField *fm_type;
7938 	ut32 key_size = 255,
7939 	value_buffer_size = 1024,
7940 	class_name_inheap = 1;
7941 	char *method_key = NULL,
7942 	*method_key_value = NULL,
7943 	*value_buffer = NULL;
7944 	char *class_name = r_bin_java_get_this_class_name (bin);
7945 	ut64 baddr = bin->loadaddr;
7946 	if (!class_name) {
7947 		class_name = "unknown";
7948 		class_name_inheap = 0;
7949 	}
7950 	key_size += strlen (class_name);
7951 	value_buffer_size += strlen (class_name);
7952 	method_key = malloc (key_size);
7953 	value_buffer = malloc (value_buffer_size);
7954 	method_key_value = malloc (key_size);
7955 	snprintf (method_key, key_size, "%s.methods", class_name);
7956 	method_key[key_size - 1] = 0;
7957 	r_list_foreach_safe (bin->methods_list, iter, iter_tmp, fm_type) {
7958 		char number_buffer[80];
7959 		ut64 file_offset = fm_type->file_offset + baddr;
7960 		snprintf (number_buffer, sizeof (number_buffer), "0x%04"PFMT64x, file_offset);
7961 		sdb_array_push (bin->kv, method_key, number_buffer, 0);
7962 	}
7963 	r_list_foreach_safe (bin->methods_list, iter, iter_tmp, fm_type) {
7964 		ut64 code_offset = r_bin_java_get_method_code_offset (fm_type) + baddr,
7965 		code_size = r_bin_java_get_method_code_size (fm_type),
7966 		method_offset = fm_type->file_offset + baddr;
7967 		// generate method specific key & value
7968 		snprintf (method_key, key_size, "%s.0x%04"PFMT64x, class_name, code_offset);
7969 		method_key[key_size - 1] = 0;
7970 		snprintf (method_key_value, key_size, "%s.0x%04"PFMT64x ".method", class_name, method_offset);
7971 		method_key_value[key_size - 1] = 0;
7972 		IFDBG eprintf("Adding %s to sdb_array: %s\n", method_key_value, method_key);
7973 		sdb_set (bin->kv, method_key, method_key_value, 0);
7974 		// generate code key and values
7975 		snprintf (method_key, key_size, "%s.code", method_key_value);
7976 		method_key[key_size - 1] = 0;
7977 		snprintf (value_buffer, value_buffer_size, "0x%04"PFMT64x, code_offset);
7978 		value_buffer[value_buffer_size - 1] = 0;
7979 		sdb_array_push (bin->kv, method_key, value_buffer, 0);
7980 		snprintf (value_buffer, value_buffer_size, "0x%04"PFMT64x, code_size);
7981 		value_buffer[value_buffer_size - 1] = 0;
7982 		sdb_array_push (bin->kv, method_key, value_buffer, 0);
7983 		// generate info key, and place values in method info array
7984 		snprintf (method_key, key_size, "%s.info", method_key_value);
7985 		method_key[key_size - 1] = 0;
7986 		snprintf (value_buffer, value_buffer_size, "%s", fm_type->flags_str);
7987 		value_buffer[value_buffer_size - 1] = 0;
7988 		IFDBG eprintf("Adding %s to sdb_array: %s\n", value_buffer, method_key);
7989 		sdb_array_push (bin->kv, method_key, value_buffer, 0);
7990 		snprintf (value_buffer, value_buffer_size, "%s", fm_type->class_name);
7991 		value_buffer[value_buffer_size - 1] = 0;
7992 		IFDBG eprintf("Adding %s to sdb_array: %s\n", value_buffer, method_key);
7993 		sdb_array_push (bin->kv, method_key, value_buffer, 0);
7994 		snprintf (value_buffer, value_buffer_size, "%s", fm_type->name);
7995 		value_buffer[value_buffer_size - 1] = 0;
7996 		IFDBG eprintf("Adding %s to sdb_array: %s\n", value_buffer, method_key);
7997 		sdb_array_push (bin->kv, method_key, value_buffer, 0);
7998 		snprintf (value_buffer, value_buffer_size, "%s", fm_type->descriptor);
7999 		value_buffer[value_buffer_size - 1] = 0;
8000 		IFDBG eprintf("Adding %s to sdb_array: %s\n", value_buffer, method_key);
8001 		sdb_array_push (bin->kv, method_key, value_buffer, 0);
8002 	}
8003 	free (method_key);
8004 	free (method_key_value);
8005 	free (value_buffer);
8006 	if (class_name_inheap) {
8007 		free (class_name);
8008 	}
8009 }
8010 
U(r_bin_java_get_args_from_bin)8011 R_API RList *U(r_bin_java_get_args_from_bin)(RBinJavaObj * bin_obj, ut64 addr) {
8012 	RBinJavaField *fm_type = r_bin_java_get_method_code_attribute_with_addr (bin_obj, addr);
8013 	return fm_type ? r_bin_java_get_args (fm_type) : NULL;
8014 }
8015 
U(r_bin_java_get_ret_from_bin)8016 R_API RList *U(r_bin_java_get_ret_from_bin)(RBinJavaObj * bin_obj, ut64 addr) {
8017 	RBinJavaField *fm_type = r_bin_java_get_method_code_attribute_with_addr (bin_obj, addr);
8018 	return fm_type ? r_bin_java_get_ret (fm_type) : NULL;
8019 }
8020 
U(r_bin_java_get_fcn_name_from_bin)8021 R_API char *U(r_bin_java_get_fcn_name_from_bin)(RBinJavaObj * bin_obj, ut64 addr) {
8022 	RBinJavaField *fm_type = r_bin_java_get_method_code_attribute_with_addr (bin_obj, addr);
8023 	return fm_type && fm_type->name ? strdup (fm_type->name) : NULL;
8024 }
8025 
U(r_bin_java_is_method_static)8026 R_API int U(r_bin_java_is_method_static)(RBinJavaObj * bin_obj, ut64 addr) {
8027 	RBinJavaField *fm_type = r_bin_java_get_method_code_attribute_with_addr (bin_obj, addr);
8028 	return fm_type && fm_type->flags & R_BIN_JAVA_METHOD_ACC_STATIC;
8029 }
8030 
U(r_bin_java_is_method_private)8031 R_API int U(r_bin_java_is_method_private)(RBinJavaObj * bin_obj, ut64 addr) {
8032 	return r_bin_java_is_fm_type_private (r_bin_java_get_method_code_attribute_with_addr (bin_obj, addr));
8033 }
8034 
U(r_bin_java_is_method_protected)8035 R_API int U(r_bin_java_is_method_protected)(RBinJavaObj * bin_obj, ut64 addr) {
8036 	return r_bin_java_is_fm_type_protected (
8037 		r_bin_java_get_method_code_attribute_with_addr (bin_obj, addr));
8038 }
8039 
r_bin_java_print_method_idx_summary(RBinJavaObj * bin_obj,ut32 idx)8040 R_API int r_bin_java_print_method_idx_summary(RBinJavaObj *bin_obj, ut32 idx) {
8041 	int res = false;
8042 	if (idx < r_list_length (bin_obj->methods_list)) {
8043 		RBinJavaField *fm_type = r_list_get_n (bin_obj->methods_list, idx);
8044 		r_bin_java_print_method_summary (fm_type);
8045 		res = true;
8046 	}
8047 	return res;
8048 }
8049 
r_bin_java_get_method_count(RBinJavaObj * bin_obj)8050 R_API ut32 r_bin_java_get_method_count(RBinJavaObj *bin_obj) {
8051 	return r_list_length (bin_obj->methods_list);
8052 }
8053 
r_bin_java_get_interface_names(RBinJavaObj * bin)8054 R_API RList *r_bin_java_get_interface_names(RBinJavaObj *bin) {
8055 	RList *interfaces_names = r_list_new ();
8056 	RListIter *iter;
8057 	RBinJavaInterfaceInfo *ifobj;
8058 	r_list_foreach (bin->interfaces_list, iter, ifobj) {
8059 		if (ifobj && ifobj->name) {
8060 			r_list_append (interfaces_names, strdup (ifobj->name));
8061 		}
8062 	}
8063 	return interfaces_names;
8064 }
8065 
r_bin_java_get_main(RBinJavaObj * bin)8066 R_API ut64 r_bin_java_get_main(RBinJavaObj *bin) {
8067 	if (bin->main_code_attr) {
8068 		return bin->main_code_attr->info.code_attr.code_offset + bin->loadaddr;
8069 	}
8070 	return 0;
8071 }
8072 
r_bin_java_new(const char * file,ut64 loadaddr,Sdb * kv)8073 R_API RBinJavaObj *r_bin_java_new(const char *file, ut64 loadaddr, Sdb *kv) {
8074 	RBinJavaObj *bin = R_NEW0 (RBinJavaObj);
8075 	if (!bin) {
8076 		return NULL;
8077 	}
8078 	bin->file = strdup (file);
8079 	size_t sz;
8080 	ut8 *buf = (ut8 *)r_file_slurp (file, &sz);
8081 	bin->size = sz;
8082 	if (!buf) {
8083 		return r_bin_java_free (bin);
8084 	}
8085 	if (!r_bin_java_new_bin (bin, loadaddr, kv, buf, bin->size)) {
8086 		r_bin_java_free (bin);
8087 		bin = NULL;
8088 	}
8089 	free (buf);
8090 	return bin;
8091 }
8092 
r_bin_java_get_class_entrypoint(RBinJavaObj * bin)8093 R_API ut64 r_bin_java_get_class_entrypoint(RBinJavaObj *bin) {
8094 	if (bin->cf2.this_class_entrypoint_code_attr) {
8095 		return bin->cf2.this_class_entrypoint_code_attr->info.code_attr.code_offset;
8096 	}
8097 	return 0;
8098 }
8099 
r_bin_java_get_method_exception_table_with_addr(RBinJavaObj * bin,ut64 addr)8100 R_API RList *r_bin_java_get_method_exception_table_with_addr(RBinJavaObj *bin, ut64 addr) {
8101 	RListIter *iter = NULL, *iter_tmp = NULL;
8102 	RBinJavaField *fm_type, *res = NULL;
8103 	if (!bin && R_BIN_JAVA_GLOBAL_BIN) {
8104 		bin = R_BIN_JAVA_GLOBAL_BIN;
8105 	}
8106 	if (!bin) {
8107 		eprintf ("Attempting to analyse function when the R_BIN_JAVA_GLOBAL_BIN has not been set.\n");
8108 		return NULL;
8109 	}
8110 	r_list_foreach_safe (bin->methods_list, iter, iter_tmp, fm_type) {
8111 		ut64 offset = r_bin_java_get_method_code_offset (fm_type) + bin->loadaddr,
8112 		size = r_bin_java_get_method_code_size (fm_type);
8113 		if (addr >= offset && addr <= size + offset) {
8114 			res = fm_type;
8115 		}
8116 	}
8117 	if (res) {
8118 		RBinJavaAttrInfo *code_attr = r_bin_java_get_method_code_attribute (res);
8119 		return code_attr->info.code_attr.exception_table;
8120 	}
8121 	return NULL;
8122 }
8123 
r_bin_java_get_methods_list(RBinJavaObj * bin)8124 R_API const RList *r_bin_java_get_methods_list(RBinJavaObj *bin) {
8125 	if (bin) {
8126 		return bin->methods_list;
8127 	}
8128 	if (R_BIN_JAVA_GLOBAL_BIN) {
8129 		return R_BIN_JAVA_GLOBAL_BIN->methods_list;
8130 	}
8131 	return NULL;
8132 }
8133 
r_bin_java_get_bin_obj_list_thru_obj(RBinJavaObj * bin_obj)8134 R_API RList *r_bin_java_get_bin_obj_list_thru_obj(RBinJavaObj *bin_obj) {
8135 	RList *the_list;
8136 	Sdb *sdb;
8137 	if (!bin_obj) {
8138 		return NULL;
8139 	}
8140 	sdb = bin_obj->AllJavaBinObjs;
8141 	if (!sdb) {
8142 		return NULL;
8143 	}
8144 	the_list = r_list_new ();
8145 	if (!the_list) {
8146 		return NULL;
8147 	}
8148 	sdb_foreach (sdb, sdb_iterate_build_list, (void *) the_list);
8149 	return the_list;
8150 }
8151 
r_bin_java_extract_all_bin_type_values(RBinJavaObj * bin_obj)8152 R_API RList *r_bin_java_extract_all_bin_type_values(RBinJavaObj *bin_obj) {
8153 	RListIter *fm_type_iter;
8154 	RList *all_types = r_list_new ();
8155 	RBinJavaField *fm_type;
8156 	// get all field types
8157 	r_list_foreach (bin_obj->fields_list, fm_type_iter, fm_type) {
8158 		char *desc = NULL;
8159 		if (!extract_type_value (fm_type->descriptor, &desc)) {
8160 			return NULL;
8161 		}
8162 		IFDBG eprintf("Adding field type: %s\n", desc);
8163 		r_list_append (all_types, desc);
8164 	}
8165 	// get all method types
8166 	r_list_foreach (bin_obj->methods_list, fm_type_iter, fm_type) {
8167 		RList *the_list = r_bin_java_extract_type_values (fm_type->descriptor);
8168 		RListIter *desc_iter;
8169 		char *str;
8170 		r_list_foreach (the_list, desc_iter, str) {
8171 			if (str && *str != '(' && *str != ')') {
8172 				r_list_append (all_types, strdup (str));
8173 				IFDBG eprintf("Adding method type: %s\n", str);
8174 			}
8175 		}
8176 		r_list_free (the_list);
8177 	}
8178 	return all_types;
8179 }
8180 
r_bin_java_get_method_definitions(RBinJavaObj * bin)8181 R_API RList *r_bin_java_get_method_definitions(RBinJavaObj *bin) {
8182 	RBinJavaField *fm_type = NULL;
8183 	RList *the_list = r_list_new ();
8184 	if (!the_list) {
8185 		return NULL;
8186 	}
8187 	RListIter *iter = NULL;
8188 	if (!bin) {
8189 		return the_list;
8190 	}
8191 	r_list_foreach (bin->methods_list, iter, fm_type) {
8192 		char *method_proto = r_bin_java_get_method_definition (fm_type);
8193 		// eprintf ("Method prototype: %s\n", method_proto);
8194 		r_list_append (the_list, method_proto);
8195 	}
8196 	return the_list;
8197 }
8198 
r_bin_java_get_field_definitions(RBinJavaObj * bin)8199 R_API RList *r_bin_java_get_field_definitions(RBinJavaObj *bin) {
8200 	RBinJavaField *fm_type = NULL;
8201 	RList *the_list = r_list_new ();
8202 	if (!the_list) {
8203 		return NULL;
8204 	}
8205 	RListIter *iter = NULL;
8206 	if (!bin) {
8207 		return the_list;
8208 	}
8209 	r_list_foreach (bin->fields_list, iter, fm_type) {
8210 		char *field_def = r_bin_java_get_field_definition (fm_type);
8211 		// eprintf ("Field def: %s, %s, %s, %s\n", fm_type->name, fm_type->descriptor, fm_type->flags_str, field_def);
8212 		r_list_append (the_list, field_def);
8213 	}
8214 	return the_list;
8215 }
8216 
r_bin_java_get_import_definitions(RBinJavaObj * bin)8217 R_API RList *r_bin_java_get_import_definitions(RBinJavaObj *bin) {
8218 	RList *the_list = r_bin_java_get_lib_names (bin);
8219 	RListIter *iter = NULL;
8220 	char *new_str;
8221 	if (!bin || !the_list) {
8222 		return the_list;
8223 	}
8224 	r_list_foreach (the_list, iter, new_str) {
8225 		while (*new_str) {
8226 			if (*new_str == '/') {
8227 				*new_str = '.';
8228 			}
8229 			new_str++;
8230 		}
8231 	}
8232 	return the_list;
8233 }
8234 
r_bin_java_get_field_offsets(RBinJavaObj * bin)8235 R_API RList *r_bin_java_get_field_offsets(RBinJavaObj *bin) {
8236 	RBinJavaField *fm_type = NULL;
8237 	RList *the_list = r_list_new ();
8238 	if (!the_list) {
8239 		return NULL;
8240 	}
8241 	RListIter *iter = NULL;
8242 	ut64 *paddr = NULL;
8243 	if (!bin) {
8244 		return the_list;
8245 	}
8246 	the_list->free = free;
8247 	r_list_foreach (bin->fields_list, iter, fm_type) {
8248 		paddr = malloc (sizeof(ut64));
8249 		if (!paddr) {
8250 			r_list_free (the_list);
8251 			return NULL;
8252 		}
8253 		*paddr = fm_type->file_offset + bin->loadaddr;
8254 		// eprintf ("Field def: %s, %s, %s, %s\n", fm_type->name, fm_type->descriptor, fm_type->flags_str, field_def);
8255 		r_list_append (the_list, paddr);
8256 	}
8257 	return the_list;
8258 }
8259 
r_bin_java_get_method_offsets(RBinJavaObj * bin)8260 R_API RList *r_bin_java_get_method_offsets(RBinJavaObj *bin) {
8261 	RBinJavaField *fm_type = NULL;
8262 	RList *the_list = r_list_new ();
8263 	RListIter *iter = NULL;
8264 	ut64 *paddr = NULL;
8265 	if (!bin) {
8266 		return the_list;
8267 	}
8268 	the_list->free = free;
8269 	r_list_foreach (bin->methods_list, iter, fm_type) {
8270 		paddr = R_NEW0 (ut64);
8271 		*paddr = fm_type->file_offset + bin->loadaddr;
8272 		r_list_append (the_list, paddr);
8273 	}
8274 	return the_list;
8275 }
8276 
r_bin_java_calculate_field_access_value(const char * access_flags_str)8277 R_API ut16 r_bin_java_calculate_field_access_value(const char *access_flags_str) {
8278 	return calculate_access_value (access_flags_str, FIELD_ACCESS_FLAGS);
8279 }
8280 
r_bin_java_calculate_class_access_value(const char * access_flags_str)8281 R_API ut16 r_bin_java_calculate_class_access_value(const char *access_flags_str) {
8282 	return calculate_access_value (access_flags_str, CLASS_ACCESS_FLAGS);
8283 }
8284 
r_bin_java_calculate_method_access_value(const char * access_flags_str)8285 R_API ut16 r_bin_java_calculate_method_access_value(const char *access_flags_str) {
8286 	return calculate_access_value (access_flags_str, METHOD_ACCESS_FLAGS);
8287 }
8288 
retrieve_all_method_access_string_and_value(void)8289 R_API RList *retrieve_all_method_access_string_and_value(void) {
8290 	return retrieve_all_access_string_and_value (METHOD_ACCESS_FLAGS);
8291 }
8292 
retrieve_all_field_access_string_and_value(void)8293 R_API RList *retrieve_all_field_access_string_and_value(void) {
8294 	return retrieve_all_access_string_and_value (FIELD_ACCESS_FLAGS);
8295 }
8296 
retrieve_all_class_access_string_and_value(void)8297 R_API RList *retrieve_all_class_access_string_and_value(void) {
8298 	return retrieve_all_access_string_and_value (CLASS_ACCESS_FLAGS);
8299 }
8300 
r_bin_java_resolve_with_space(RBinJavaObj * obj,int idx)8301 R_API char *r_bin_java_resolve_with_space(RBinJavaObj *obj, int idx) {
8302 	return r_bin_java_resolve (obj, idx, 1);
8303 }
8304 
r_bin_java_resolve_without_space(RBinJavaObj * obj,int idx)8305 R_API char *r_bin_java_resolve_without_space(RBinJavaObj *obj, int idx) {
8306 	return r_bin_java_resolve (obj, idx, 0);
8307 }
8308 
r_bin_java_resolve_b64_encode(RBinJavaObj * BIN_OBJ,ut16 idx)8309 R_API char *r_bin_java_resolve_b64_encode(RBinJavaObj *BIN_OBJ, ut16 idx) {
8310 	RBinJavaCPTypeObj *item = NULL, *item2 = NULL;
8311 	char *class_str = NULL,
8312 	*name_str = NULL,
8313 	*desc_str = NULL,
8314 	*string_str = NULL,
8315 	*empty = "",
8316 	*cp_name = NULL,
8317 	*str = NULL, *out = NULL;
8318 	int memory_alloc = 0;
8319 	if (BIN_OBJ && BIN_OBJ->cp_count < 1) {
8320 		// r_bin_java_new_bin(BIN_OBJ);
8321 		return NULL;
8322 	}
8323 	item = (RBinJavaCPTypeObj *) r_bin_java_get_item_from_bin_cp_list (BIN_OBJ, idx);
8324 	if (item) {
8325 		cp_name = ((RBinJavaCPTypeMetas *) item->metas->type_info)->name;
8326 		IFDBG eprintf("java_resolve Resolved: (%d) %s\n", idx, cp_name);
8327 	} else {
8328 		return NULL;
8329 	}
8330 	if (!strcmp (cp_name, "Class")) {
8331 		item2 = (RBinJavaCPTypeObj *) r_bin_java_get_item_from_bin_cp_list (BIN_OBJ, idx);
8332 		// str = r_bin_java_get_name_from_bin_cp_list (BIN_OBJ, idx-1);
8333 		class_str = r_bin_java_get_item_name_from_bin_cp_list (BIN_OBJ, item);
8334 		if (!class_str) {
8335 			class_str = empty;
8336 		}
8337 		name_str = r_bin_java_get_item_name_from_bin_cp_list (BIN_OBJ, item2);
8338 		if (!name_str) {
8339 			name_str = empty;
8340 		}
8341 		desc_str = r_bin_java_get_item_desc_from_bin_cp_list (BIN_OBJ, item2);
8342 		if (!desc_str) {
8343 			desc_str = empty;
8344 		}
8345 		memory_alloc = strlen (class_str) + strlen (name_str) + strlen (desc_str) + 3;
8346 		if (memory_alloc) {
8347 			str = malloc (memory_alloc);
8348 			if (str) {
8349 				snprintf (str, memory_alloc, "%s%s", name_str, desc_str);
8350 				out = r_base64_encode_dyn ((const char *) str, strlen (str));
8351 				free (str);
8352 				str = out;
8353 			}
8354 		}
8355 		if (class_str != empty) {
8356 			free (class_str);
8357 		}
8358 		if (name_str != empty) {
8359 			free (name_str);
8360 		}
8361 		if (desc_str != empty) {
8362 			free (desc_str);
8363 		}
8364 	} else if (strcmp (cp_name, "MethodRef") == 0 ||
8365 	strcmp (cp_name, "FieldRef") == 0 ||
8366 	strcmp (cp_name, "InterfaceMethodRef") == 0) {
8367 		/*
8368 		*  The MethodRef, FieldRef, and InterfaceMethodRef structures
8369 		*/
8370 		class_str = r_bin_java_get_name_from_bin_cp_list (BIN_OBJ, item->info.cp_method.class_idx);
8371 		if (!class_str) {
8372 			class_str = empty;
8373 		}
8374 		name_str = r_bin_java_get_item_name_from_bin_cp_list (BIN_OBJ, item);
8375 		if (!name_str) {
8376 			name_str = empty;
8377 		}
8378 		desc_str = r_bin_java_get_item_desc_from_bin_cp_list (BIN_OBJ, item);
8379 		if (!desc_str) {
8380 			desc_str = empty;
8381 		}
8382 		memory_alloc = strlen (class_str) + strlen (name_str) + strlen (desc_str) + 3;
8383 		if (memory_alloc) {
8384 			str = malloc (memory_alloc);
8385 			if (str) {
8386 				snprintf (str, memory_alloc, "%s/%s%s", class_str, name_str, desc_str);
8387 				out = r_base64_encode_dyn ((const char *) str, strlen (str));
8388 				free (str);
8389 				str = out;
8390 			}
8391 		}
8392 		if (class_str != empty) {
8393 			free (class_str);
8394 		}
8395 		if (name_str != empty) {
8396 			free (name_str);
8397 		}
8398 		if (desc_str != empty) {
8399 			free (desc_str);
8400 		}
8401 	} else if (strcmp (cp_name, "String") == 0) {
8402 		ut32 length = r_bin_java_get_utf8_len_from_bin_cp_list (BIN_OBJ, item->info.cp_string.string_idx);
8403 		string_str = r_bin_java_get_utf8_from_bin_cp_list (BIN_OBJ, item->info.cp_string.string_idx);
8404 		str = NULL;
8405 		IFDBG eprintf("java_resolve String got: (%d) %s\n", item->info.cp_string.string_idx, string_str);
8406 		if (!string_str) {
8407 			string_str = empty;
8408 			length = strlen (empty);
8409 		}
8410 		memory_alloc = length + 3;
8411 		if (memory_alloc) {
8412 			str = malloc (memory_alloc);
8413 			if (str) {
8414 				snprintf (str, memory_alloc, "\"%s\"", string_str);
8415 				out = r_base64_encode_dyn ((const char *) str, strlen (str));
8416 				free (str);
8417 				str = out;
8418 			}
8419 		}
8420 		IFDBG eprintf("java_resolve String return: %s\n", str);
8421 		if (string_str != empty) {
8422 			free (string_str);
8423 		}
8424 	} else if (strcmp (cp_name, "Utf8") == 0) {
8425 		ut64 sz = item->info.cp_utf8.length ? item->info.cp_utf8.length + 10 : 10;
8426 		str = malloc (sz);
8427 		memset (str, 0, sz);
8428 		if (sz > 10) {
8429 			r_base64_encode (str, item->info.cp_utf8.bytes, item->info.cp_utf8.length);
8430 		}
8431 	} else if (strcmp (cp_name, "Long") == 0) {
8432 		str = malloc (34);
8433 		if (str) {
8434 			snprintf (str, 34, "0x%"PFMT64x, r_bin_java_raw_to_long (item->info.cp_long.bytes.raw, 0));
8435 			out = r_base64_encode_dyn ((const char *) str, strlen (str));
8436 			free (str);
8437 			str = out;
8438 		}
8439 	} else if (strcmp (cp_name, "Double") == 0) {
8440 		str = malloc (1000);
8441 		if (str) {
8442 			snprintf (str, 1000, "%f", r_bin_java_raw_to_double (item->info.cp_double.bytes.raw, 0));
8443 			out = r_base64_encode_dyn ((const char *) str, strlen (str));
8444 			free (str);
8445 			str = out;
8446 		}
8447 	} else if (strcmp (cp_name, "Integer") == 0) {
8448 		str = calloc (34, 1);
8449 		if (str) {
8450 			snprintf (str, 34, "0x%08x", R_BIN_JAVA_UINT (item->info.cp_integer.bytes.raw, 0));
8451 			out = r_base64_encode_dyn ((const char *) str, strlen (str));
8452 			free (str);
8453 			str = out;
8454 		}
8455 	} else if (strcmp (cp_name, "Float") == 0) {
8456 		str = malloc (34);
8457 		if (str) {
8458 			snprintf (str, 34, "%f", R_BIN_JAVA_FLOAT (item->info.cp_float.bytes.raw, 0));
8459 			out = r_base64_encode_dyn ((const char *) str, strlen (str));
8460 			free (str);
8461 			str = out;
8462 		}
8463 	} else if (!strcmp (cp_name, "NameAndType")) {
8464 		name_str = r_bin_java_get_item_name_from_bin_cp_list (BIN_OBJ, item);
8465 		if (!name_str) {
8466 			name_str = empty;
8467 		}
8468 		desc_str = r_bin_java_get_item_desc_from_bin_cp_list (BIN_OBJ, item);
8469 		if (!desc_str) {
8470 			desc_str = empty;
8471 		}
8472 		memory_alloc = strlen (name_str) + strlen (desc_str) + 3;
8473 		if (memory_alloc) {
8474 			str = malloc (memory_alloc);
8475 			if (str) {
8476 				snprintf (str, memory_alloc, "%s %s", name_str, desc_str);
8477 				out = r_base64_encode_dyn ((const char *) str, strlen (str));
8478 				free (str);
8479 				str = out;
8480 			}
8481 		}
8482 		if (name_str != empty) {
8483 			free (name_str);
8484 		}
8485 		if (desc_str != empty) {
8486 			free (desc_str);
8487 		}
8488 	} else {
8489 		str = r_base64_encode_dyn ((const char *) "(null)", 6);
8490 	}
8491 	return str;
8492 }
8493 
r_bin_java_resolve_cp_idx_address(RBinJavaObj * BIN_OBJ,int idx)8494 R_API ut64 r_bin_java_resolve_cp_idx_address(RBinJavaObj *BIN_OBJ, int idx) {
8495 	RBinJavaCPTypeObj *item = NULL;
8496 	ut64 addr = -1;
8497 	if (BIN_OBJ && BIN_OBJ->cp_count < 1) {
8498 		return -1;
8499 	}
8500 	item = (RBinJavaCPTypeObj *) r_bin_java_get_item_from_bin_cp_list (BIN_OBJ, idx);
8501 	if (item) {
8502 		addr = item->file_offset + item->loadaddr;
8503 	}
8504 	return addr;
8505 }
8506 
r_bin_java_resolve_cp_idx_to_string(RBinJavaObj * BIN_OBJ,int idx)8507 R_API char *r_bin_java_resolve_cp_idx_to_string(RBinJavaObj *BIN_OBJ, int idx) {
8508 	RBinJavaCPTypeObj *item = NULL;
8509 	char *value = NULL;
8510 	if (BIN_OBJ && BIN_OBJ->cp_count < 1) {
8511 		return NULL;
8512 	}
8513 	item = (RBinJavaCPTypeObj *) r_bin_java_get_item_from_bin_cp_list (BIN_OBJ, idx);
8514 	if (item) {
8515 		value = ((RBinJavaCPTypeMetas *)
8516 		item->metas->type_info)->
8517 		allocs->stringify_obj (item);
8518 	}
8519 	return value;
8520 }
8521 
r_bin_java_resolve_cp_idx_print_summary(RBinJavaObj * BIN_OBJ,int idx)8522 R_API int r_bin_java_resolve_cp_idx_print_summary(RBinJavaObj *BIN_OBJ, int idx) {
8523 	RBinJavaCPTypeObj *item = NULL;
8524 	if (BIN_OBJ && BIN_OBJ->cp_count < 1) {
8525 		return false;
8526 	}
8527 	item = (RBinJavaCPTypeObj *) r_bin_java_get_item_from_bin_cp_list (BIN_OBJ, idx);
8528 	if (item) {
8529 		((RBinJavaCPTypeMetas *)
8530 		item->metas->type_info)->
8531 		allocs->print_summary (item);
8532 	} else {
8533 		eprintf ("Error: Invalid CP Object.\n");
8534 	}
8535 	return item ? true : false;
8536 }
8537 
U(r_bin_java_resolve_to_const_value)8538 R_API ConstJavaValue *U(r_bin_java_resolve_to_const_value)(RBinJavaObj * BIN_OBJ, int idx) {
8539 	// TODO XXX FIXME add a size parameter to the str when it is passed in
8540 	RBinJavaCPTypeObj *item = NULL, *item2 = NULL;
8541 	ConstJavaValue *result = R_NEW0 (ConstJavaValue);
8542 	if (!result) {
8543 		return NULL;
8544 	}
8545 	char *class_str = NULL,
8546 	*name_str = NULL,
8547 	*desc_str = NULL,
8548 	*string_str = NULL,
8549 	*empty = "",
8550 	*cp_name = NULL;
8551 	result->type = "unknown";
8552 	if (BIN_OBJ && BIN_OBJ->cp_count < 1) {
8553 		// r_bin_java_new_bin(BIN_OBJ);
8554 		return result;
8555 	}
8556 	item = (RBinJavaCPTypeObj *) r_bin_java_get_item_from_bin_cp_list (BIN_OBJ, idx);
8557 	if (!item) {
8558 		return result;
8559 	}
8560 	cp_name = ((RBinJavaCPTypeMetas *) item->metas->type_info)->name;
8561 	IFDBG eprintf("java_resolve Resolved: (%d) %s\n", idx, cp_name);
8562 	if (strcmp (cp_name, "Class") == 0) {
8563 		item2 = (RBinJavaCPTypeObj *) r_bin_java_get_item_from_bin_cp_list (BIN_OBJ, idx);
8564 		// str = r_bin_java_get_name_from_bin_cp_list (BIN_OBJ, idx-1);
8565 		class_str = r_bin_java_get_item_name_from_bin_cp_list (BIN_OBJ, item);
8566 		if (!class_str) {
8567 			class_str = empty;
8568 		}
8569 		name_str = r_bin_java_get_item_name_from_bin_cp_list (BIN_OBJ, item2);
8570 		if (!name_str) {
8571 			name_str = empty;
8572 		}
8573 		desc_str = r_bin_java_get_item_desc_from_bin_cp_list (BIN_OBJ, item2);
8574 		if (!desc_str) {
8575 			desc_str = empty;
8576 		}
8577 		result->value._ref = R_NEW0 (_JavaRef);
8578 		result->type = "ref";
8579 		result->value._ref->class_name = strdup (class_str);
8580 		result->value._ref->name = strdup (name_str);
8581 		result->value._ref->desc = strdup (desc_str);
8582 		if (class_str != empty) {
8583 			free (class_str);
8584 		}
8585 		if (name_str != empty) {
8586 			free (name_str);
8587 		}
8588 		if (desc_str != empty) {
8589 			free (desc_str);
8590 		}
8591 	} else if (strcmp (cp_name, "MethodRef") == 0 ||
8592 	strcmp (cp_name, "FieldRef") == 0 ||
8593 	strcmp (cp_name, "InterfaceMethodRef") == 0) {
8594 		/*
8595 		*  The MethodRef, FieldRef, and InterfaceMethodRef structures
8596 		*/
8597 		class_str = r_bin_java_get_name_from_bin_cp_list (BIN_OBJ, item->info.cp_method.class_idx);
8598 		if (!class_str) {
8599 			class_str = empty;
8600 		}
8601 		name_str = r_bin_java_get_item_name_from_bin_cp_list (BIN_OBJ, item);
8602 		if (!name_str) {
8603 			name_str = empty;
8604 		}
8605 		desc_str = r_bin_java_get_item_desc_from_bin_cp_list (BIN_OBJ, item);
8606 		if (!desc_str) {
8607 			desc_str = empty;
8608 		}
8609 		result->value._ref = R_NEW0 (_JavaRef);
8610 		result->type = "ref";
8611 		result->value._ref->class_name = strdup (class_str);
8612 		result->value._ref->name = strdup (name_str);
8613 		result->value._ref->desc = strdup (desc_str);
8614 		if (class_str != empty) {
8615 			free (class_str);
8616 		}
8617 		if (name_str != empty) {
8618 			free (name_str);
8619 		}
8620 		if (desc_str != empty) {
8621 			free (desc_str);
8622 		}
8623 	} else if (strcmp (cp_name, "String") == 0) {
8624 		ut32 length = r_bin_java_get_utf8_len_from_bin_cp_list (BIN_OBJ, item->info.cp_string.string_idx);
8625 		string_str = r_bin_java_get_utf8_from_bin_cp_list (BIN_OBJ, item->info.cp_string.string_idx);
8626 		IFDBG eprintf("java_resolve String got: (%d) %s\n", item->info.cp_string.string_idx, string_str);
8627 		if (!string_str) {
8628 			string_str = empty;
8629 			length = strlen (empty);
8630 		}
8631 		result->type = "str";
8632 		result->value._str = R_NEW0 (struct  java_const_value_str_t);
8633 		result->value._str->len = length;
8634 		if (length > 0) {
8635 			result->value._str->str = r_str_ndup (string_str, length);
8636 		} else {
8637 			result->value._str->str = strdup ("");
8638 		}
8639 		if (string_str != empty) {
8640 			free (string_str);
8641 		}
8642 	} else if (strcmp (cp_name, "Utf8") == 0) {
8643 		result->type = "str";
8644 		result->value._str = R_NEW0 (struct java_const_value_str_t);
8645 		result->value._str->str = malloc (item->info.cp_utf8.length);
8646 		result->value._str->len = item->info.cp_utf8.length;
8647 		memcpy (result->value._str->str, item->info.cp_utf8.bytes, item->info.cp_utf8.length);
8648 	} else if (strcmp (cp_name, "Long") == 0) {
8649 		result->type = "long";
8650 		result->value._long = r_bin_java_raw_to_long (item->info.cp_long.bytes.raw, 0);
8651 	} else if (strcmp (cp_name, "Double") == 0) {
8652 		result->type = "double";
8653 		result->value._double = r_bin_java_raw_to_double (item->info.cp_double.bytes.raw, 0);
8654 	} else if (strcmp (cp_name, "Integer") == 0) {
8655 		result->type = "int";
8656 		result->value._int = R_BIN_JAVA_UINT (item->info.cp_integer.bytes.raw, 0);
8657 	} else if (strcmp (cp_name, "Float") == 0) {
8658 		result->type = "float";
8659 		result->value._float = R_BIN_JAVA_FLOAT (item->info.cp_float.bytes.raw, 0);
8660 	} else if (strcmp (cp_name, "NameAndType") == 0) {
8661 		result->value._ref = R_NEW0 (struct java_const_value_ref_t);
8662 		result->type = "ref";
8663 		name_str = r_bin_java_get_item_name_from_bin_cp_list (BIN_OBJ, item);
8664 		if (!name_str) {
8665 			name_str = empty;
8666 		}
8667 		desc_str = r_bin_java_get_item_desc_from_bin_cp_list (BIN_OBJ, item);
8668 		if (!desc_str) {
8669 			desc_str = empty;
8670 		}
8671 		result->value._ref->class_name = strdup (empty);
8672 		result->value._ref->name = strdup (name_str);
8673 		result->value._ref->desc = strdup (desc_str);
8674 		if (name_str != empty) {
8675 			free (name_str);
8676 		}
8677 		if (desc_str != empty) {
8678 			free (desc_str);
8679 		}
8680 		result->value._ref->is_method = r_bin_java_does_cp_idx_ref_method (BIN_OBJ, idx);
8681 		result->value._ref->is_field = r_bin_java_does_cp_idx_ref_field (BIN_OBJ, idx);
8682 	}
8683 	return result;
8684 }
8685 
U(r_bin_java_free_const_value)8686 R_API void U(r_bin_java_free_const_value)(ConstJavaValue * cp_value) {
8687 	char first_char = cp_value && cp_value->type ? *cp_value->type : 0,
8688 	second_char = cp_value && cp_value->type ? *(cp_value->type + 1) : 0;
8689 	switch (first_char) {
8690 	case 'r':
8691 		if (cp_value && cp_value->value._ref) {
8692 			free (cp_value->value._ref->class_name);
8693 			free (cp_value->value._ref->name);
8694 			free (cp_value->value._ref->desc);
8695 		}
8696 		break;
8697 	case 's':
8698 		if (second_char == 't' && cp_value->value._str) {
8699 			free (cp_value->value._str->str);
8700 		}
8701 		break;
8702 	}
8703 	free (cp_value);
8704 }
8705 
r_bin_java_get_field_name(RBinJavaObj * bin_obj,ut32 idx)8706 R_API char *r_bin_java_get_field_name(RBinJavaObj *bin_obj, ut32 idx) {
8707 	char *name = NULL;
8708 	if (idx < r_list_length (bin_obj->fields_list)) {
8709 		RBinJavaField *fm_type = r_list_get_n (bin_obj->fields_list, idx);
8710 		name = strdup (fm_type->name);
8711 	}
8712 	return name;
8713 }
8714 
r_bin_java_print_field_idx_summary(RBinJavaObj * bin_obj,ut32 idx)8715 R_API int r_bin_java_print_field_idx_summary(RBinJavaObj *bin_obj, ut32 idx) {
8716 	int res = false;
8717 	if (idx < r_list_length (bin_obj->fields_list)) {
8718 		RBinJavaField *fm_type = r_list_get_n (bin_obj->fields_list, idx);
8719 		r_bin_java_print_field_summary (fm_type);
8720 		res = true;
8721 	}
8722 	return res;
8723 }
8724 
r_bin_java_get_field_count(RBinJavaObj * bin_obj)8725 R_API ut32 r_bin_java_get_field_count(RBinJavaObj *bin_obj) {
8726 	return r_list_length (bin_obj->fields_list);
8727 }
8728 
r_bin_java_get_field_num_name(RBinJavaObj * bin_obj)8729 R_API RList *r_bin_java_get_field_num_name(RBinJavaObj *bin_obj) {
8730 	ut32 i = 0;
8731 	RBinJavaField *fm_type;
8732 	RListIter *iter = NULL;
8733 	RList *res = r_list_newf (free);
8734 	r_list_foreach (bin_obj->fields_list, iter, fm_type) {
8735 		ut32 len = strlen (fm_type->name) + 30;
8736 		char *str = malloc (len);
8737 		if (!str) {
8738 			r_list_free (res);
8739 			return NULL;
8740 		}
8741 		snprintf (str, len, "%d %s", i, fm_type->name);
8742 		++i;
8743 		r_list_append (res, str);
8744 	}
8745 	return res;
8746 }
r_bin_java_find_cp_const_by_val_utf8(RBinJavaObj * bin_obj,const ut8 * bytes,ut32 len)8747 R_API RList *r_bin_java_find_cp_const_by_val_utf8(RBinJavaObj *bin_obj, const ut8 *bytes, ut32 len) {
8748 	RList *res = r_list_newf (free);
8749 	ut32 *v = NULL;
8750 	RListIter *iter;
8751 	RBinJavaCPTypeObj *cp_obj;
8752 	IFDBG eprintf("In UTF-8 Looking for %s\n", bytes);
8753 	r_list_foreach (bin_obj->cp_list, iter, cp_obj) {
8754 		if (cp_obj->tag == R_BIN_JAVA_CP_UTF8) {
8755 			IFDBG eprintf("In UTF-8 Looking @ %s\n", cp_obj->info.cp_utf8.bytes);
8756 			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));
8757 			if (len == cp_obj->info.cp_utf8.length && !memcmp (bytes, cp_obj->info.cp_utf8.bytes, len)) {
8758 				v = malloc (sizeof (ut32));
8759 				if (!v) {
8760 					r_list_free (res);
8761 					return NULL;
8762 				}
8763 				*v = cp_obj->metas->ord;
8764 				IFDBG eprintf("Found a match adding idx: %d\n", *v);
8765 				r_list_append (res, v);
8766 			}
8767 		}
8768 	}
8769 	return res;
8770 }
r_bin_java_find_cp_const_by_val_int(RBinJavaObj * bin_obj,const ut8 * bytes,ut32 len)8771 R_API RList *r_bin_java_find_cp_const_by_val_int(RBinJavaObj *bin_obj, const ut8 *bytes, ut32 len) {
8772 	RList *res = r_list_newf (free);
8773 	ut32 *v = NULL;
8774 	RListIter *iter;
8775 	RBinJavaCPTypeObj *cp_obj;
8776 	eprintf ("Looking for 0x%08x\n", (ut32) R_BIN_JAVA_UINT (bytes, 0));
8777 	r_list_foreach (bin_obj->cp_list, iter, cp_obj) {
8778 		if (cp_obj->tag == R_BIN_JAVA_CP_INTEGER) {
8779 			if (len == 4 && R_BIN_JAVA_UINT (bytes, 0) == R_BIN_JAVA_UINT (cp_obj->info.cp_integer.bytes.raw, 0)) {
8780 				v = malloc (sizeof (ut32));
8781 				if (!v) {
8782 					r_list_free (res);
8783 					return NULL;
8784 				}
8785 				*v = cp_obj->idx;
8786 				r_list_append (res, v);
8787 			}
8788 		}
8789 	}
8790 	return res;
8791 }
8792 
r_bin_java_resolve_cp_idx_tag(RBinJavaObj * BIN_OBJ,int idx)8793 R_API char r_bin_java_resolve_cp_idx_tag(RBinJavaObj *BIN_OBJ, int idx) {
8794 	RBinJavaCPTypeObj *item = NULL;
8795 	if (BIN_OBJ && BIN_OBJ->cp_count < 1) {
8796 		// r_bin_java_new_bin(BIN_OBJ);
8797 		return R_BIN_JAVA_CP_UNKNOWN;
8798 	}
8799 	item = (RBinJavaCPTypeObj *) r_bin_java_get_item_from_bin_cp_list (BIN_OBJ, idx);
8800 	if (item) {
8801 		return item->tag;
8802 	}
8803 	return R_BIN_JAVA_CP_UNKNOWN;
8804 }
8805 
U(r_bin_java_integer_cp_set)8806 R_API int U(r_bin_java_integer_cp_set)(RBinJavaObj * bin, ut16 idx, ut32 val) {
8807 	RBinJavaCPTypeObj *cp_obj = r_bin_java_get_item_from_bin_cp_list (bin, idx);
8808 	if (!cp_obj) {
8809 		return false;
8810 	}
8811 	ut8 bytes[4] = {
8812 		0
8813 	};
8814 	if (cp_obj->tag != R_BIN_JAVA_CP_INTEGER && cp_obj->tag != R_BIN_JAVA_CP_FLOAT) {
8815 		eprintf ("Not supporting the overwrite of CP Objects with one of a different size.\n");
8816 		return false;
8817 	}
8818 	r_bin_java_check_reset_cp_obj (cp_obj, R_BIN_JAVA_CP_INTEGER);
8819 	cp_obj->tag = R_BIN_JAVA_CP_INTEGER;
8820 	memcpy (bytes, (const char *) &val, 4);
8821 	val = R_BIN_JAVA_UINT (bytes, 0);
8822 	memcpy (&cp_obj->info.cp_integer.bytes.raw, (const char *) &val, 4);
8823 	return true;
8824 }
8825 
U(r_bin_java_float_cp_set)8826 R_API int U(r_bin_java_float_cp_set)(RBinJavaObj * bin, ut16 idx, float val) {
8827 	RBinJavaCPTypeObj *cp_obj = r_bin_java_get_item_from_bin_cp_list (bin, idx);
8828 	if (!cp_obj) {
8829 		return false;
8830 	}
8831 	ut8 bytes[4] = {
8832 		0
8833 	};
8834 	if (cp_obj->tag != R_BIN_JAVA_CP_INTEGER && cp_obj->tag != R_BIN_JAVA_CP_FLOAT) {
8835 		eprintf ("Not supporting the overwrite of CP Objects with one of a different size.\n");
8836 		return false;
8837 	}
8838 	r_bin_java_check_reset_cp_obj (cp_obj, R_BIN_JAVA_CP_FLOAT);
8839 	cp_obj->tag = R_BIN_JAVA_CP_FLOAT;
8840 	memcpy (bytes, (const char *) &val, 4);
8841 	float *foo = (float*) bytes;
8842 	val = *foo; //(float)R_BIN_JAVA_UINT (bytes, 0);
8843 	memcpy (&cp_obj->info.cp_float.bytes.raw, (const char *) &val, 4);
8844 	return true;
8845 }
8846 
U(r_bin_java_long_cp_set)8847 R_API int U(r_bin_java_long_cp_set)(RBinJavaObj * bin, ut16 idx, ut64 val) {
8848 	RBinJavaCPTypeObj *cp_obj = r_bin_java_get_item_from_bin_cp_list (bin, idx);
8849 	if (!cp_obj) {
8850 		return false;
8851 	}
8852 	ut8 bytes[8] = {
8853 		0
8854 	};
8855 	if (cp_obj->tag != R_BIN_JAVA_CP_LONG && cp_obj->tag != R_BIN_JAVA_CP_DOUBLE) {
8856 		eprintf ("Not supporting the overwrite of CP Objects with one of a different size.\n");
8857 		return false;
8858 	}
8859 	r_bin_java_check_reset_cp_obj (cp_obj, R_BIN_JAVA_CP_LONG);
8860 	cp_obj->tag = R_BIN_JAVA_CP_LONG;
8861 	memcpy (bytes, (const char *) &val, 8);
8862 	val = r_bin_java_raw_to_long (bytes, 0);
8863 	memcpy (&cp_obj->info.cp_long.bytes.raw, (const char *) &val, 8);
8864 	return true;
8865 }
8866 
U(r_bin_java_double_cp_set)8867 R_API int U(r_bin_java_double_cp_set)(RBinJavaObj * bin, ut16 idx, ut32 val) {
8868 	RBinJavaCPTypeObj *cp_obj = r_bin_java_get_item_from_bin_cp_list (bin, idx);
8869 	if (!cp_obj) {
8870 		return false;
8871 	}
8872 	ut8 bytes[8] = {
8873 		0
8874 	};
8875 	if (cp_obj->tag != R_BIN_JAVA_CP_LONG && cp_obj->tag != R_BIN_JAVA_CP_DOUBLE) {
8876 		eprintf ("Not supporting the overwrite of CP Objects with one of a different size.\n");
8877 		return false;
8878 	}
8879 	r_bin_java_check_reset_cp_obj (cp_obj, R_BIN_JAVA_CP_DOUBLE);
8880 	cp_obj->tag = R_BIN_JAVA_CP_DOUBLE;
8881 	ut64 val64 = val;
8882 	memcpy (bytes, (const char *) &val64, 8);
8883 	val64 = r_bin_java_raw_to_long (bytes, 0);
8884 	memcpy (&cp_obj->info.cp_double.bytes.raw, (const char *) &val64, 8);
8885 	return true;
8886 }
8887 
U(r_bin_java_utf8_cp_set)8888 R_API int U(r_bin_java_utf8_cp_set)(RBinJavaObj * bin, ut16 idx, const ut8 * buffer, ut32 len) {
8889 	RBinJavaCPTypeObj *cp_obj = r_bin_java_get_item_from_bin_cp_list (bin, idx);
8890 	if (!cp_obj) {
8891 		return false;
8892 	}
8893 	eprintf ("Writing %d byte(s) (%s)\n", len, buffer);
8894 	// r_bin_java_check_reset_cp_obj(cp_obj, R_BIN_JAVA_CP_INTEGER);
8895 	if (cp_obj->tag != R_BIN_JAVA_CP_UTF8) {
8896 		eprintf ("Not supporting the overwrite of CP Objects with one of a different size.\n");
8897 		return false;
8898 	}
8899 	if (cp_obj->info.cp_utf8.length != len) {
8900 		eprintf ("Not supporting the resize, rewriting utf8 string up to %d byte(s).\n", cp_obj->info.cp_utf8.length);
8901 		if (cp_obj->info.cp_utf8.length > len) {
8902 			eprintf ("Remaining %d byte(s) will be filled with \\x00.\n", cp_obj->info.cp_utf8.length - len);
8903 		}
8904 	}
8905 	memcpy (cp_obj->info.cp_utf8.bytes, buffer, cp_obj->info.cp_utf8.length);
8906 	if (cp_obj->info.cp_utf8.length > len) {
8907 		memset (cp_obj->info.cp_utf8.bytes + len, 0, cp_obj->info.cp_utf8.length - len);
8908 	}
8909 	return true;
8910 }
8911 
r_bin_java_cp_get_bytes(ut8 tag,ut32 * out_sz,const ut8 * buf,const ut64 len)8912 R_API ut8 *r_bin_java_cp_get_bytes(ut8 tag, ut32 *out_sz, const ut8 *buf, const ut64 len) {
8913 	if (!out_sz) {
8914 		return NULL;
8915 	}
8916 	if (out_sz) {
8917 		*out_sz = 0;
8918 	}
8919 	switch (tag) {
8920 	case R_BIN_JAVA_CP_INTEGER:
8921 	case R_BIN_JAVA_CP_FLOAT:
8922 		return r_bin_java_cp_get_4bytes (tag, out_sz, buf, len);
8923 	case R_BIN_JAVA_CP_LONG:
8924 	case R_BIN_JAVA_CP_DOUBLE:
8925 		return r_bin_java_cp_get_8bytes (tag, out_sz, buf, len);
8926 	case R_BIN_JAVA_CP_UTF8:
8927 		return r_bin_java_cp_get_utf8 (tag, out_sz, buf, len);
8928 	}
8929 	return NULL;
8930 }
8931 
r_bin_java_cp_get_size(RBinJavaObj * bin,ut16 idx)8932 R_API ut32 r_bin_java_cp_get_size(RBinJavaObj *bin, ut16 idx) {
8933 	RBinJavaCPTypeObj *cp_obj = r_bin_java_get_item_from_bin_cp_list (bin, idx);
8934 	switch (cp_obj->tag) {
8935 	case R_BIN_JAVA_CP_INTEGER:
8936 	case R_BIN_JAVA_CP_FLOAT:
8937 		return 1 + 4;
8938 	case R_BIN_JAVA_CP_LONG:
8939 	case R_BIN_JAVA_CP_DOUBLE:
8940 		return 1 + 8;
8941 	case R_BIN_JAVA_CP_UTF8:
8942 		return 1 + 2 + cp_obj->info.cp_utf8.length;
8943 	}
8944 	return 0;
8945 }
8946 
r_bin_java_get_method_start(RBinJavaObj * bin,RBinJavaField * fm_type)8947 R_API ut64 r_bin_java_get_method_start(RBinJavaObj *bin, RBinJavaField *fm_type) {
8948 	return r_bin_java_get_method_code_offset (fm_type) + bin->loadaddr;
8949 }
8950 
r_bin_java_get_method_end(RBinJavaObj * bin,RBinJavaField * fm_type)8951 R_API ut64 r_bin_java_get_method_end(RBinJavaObj *bin, RBinJavaField *fm_type) {
8952 	return r_bin_java_get_method_code_offset (fm_type) + bin->loadaddr +
8953 	+r_bin_java_get_method_code_size (fm_type);
8954 }
8955 
U(r_bin_java_cp_append_method_ref)8956 R_API ut8 *U(r_bin_java_cp_append_method_ref)(RBinJavaObj * bin, ut32 * out_sz, ut16 cn_idx, ut16 fn_idx, ut16 ft_idx) {
8957 	return r_bin_java_cp_get_fref_bytes (bin, out_sz, R_BIN_JAVA_CP_METHODREF, cn_idx, fn_idx, ft_idx);
8958 }
8959 
U(r_bin_java_cp_append_field_ref)8960 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) {
8961 	return r_bin_java_cp_get_fref_bytes (bin, out_sz, R_BIN_JAVA_CP_FIELDREF, cn_idx, fn_idx, ft_idx);
8962 }
8963 
r_bin_java_unmangle_without_flags(const char * name,const char * descriptor)8964 R_API char *r_bin_java_unmangle_without_flags(const char *name, const char *descriptor) {
8965 	return r_bin_java_unmangle (NULL, name, descriptor);
8966 }
8967 
U(r_bin_java_print_stack_map_append_frame_summary)8968 R_API void U(r_bin_java_print_stack_map_append_frame_summary)(RBinJavaStackMapFrame * obj) {
8969 	RListIter *iter, *iter_tmp;
8970 	RList *ptrList;
8971 	RBinJavaVerificationObj *ver_obj;
8972 	Eprintf ("Stack Map Frame Information\n");
8973 	Eprintf ("  Tag Value = 0x%02x Name: %s\n", obj->tag, ((RBinJavaStackMapFrameMetas *) obj->metas->type_info)->name);
8974 	Eprintf ("  Offset: 0x%08"PFMT64x "\n", obj->file_offset);
8975 	Eprintf ("  Local Variable Count = 0x%04x\n", obj->number_of_locals);
8976 	Eprintf ("  Local Variables:\n");
8977 	ptrList = obj->local_items;
8978 	r_list_foreach_safe (ptrList, iter, iter_tmp, ver_obj) {
8979 		r_bin_java_print_verification_info_summary (ver_obj);
8980 	}
8981 	Eprintf ("  Stack Items Count = 0x%04x\n", obj->number_of_stack_items);
8982 	Eprintf ("  Stack Items:\n");
8983 	ptrList = obj->stack_items;
8984 	r_list_foreach_safe (ptrList, iter, iter_tmp, ver_obj) {
8985 		r_bin_java_print_verification_info_summary (ver_obj);
8986 	}
8987 }
8988 
U(r_bin_java_stack_frame_default_free)8989 R_API void U(r_bin_java_stack_frame_default_free)(void *s) {
8990 	RBinJavaStackMapFrame *stack_frame = s;
8991 	if (stack_frame) {
8992 		free (stack_frame->metas);
8993 		free (stack_frame);
8994 	}
8995 }
U(r_bin_java_stack_frame_do_nothing_free)8996 R_API void U(r_bin_java_stack_frame_do_nothing_free)(void /*RBinJavaStackMapFrame*/ *stack_frame) {}
U(r_bin_java_stack_frame_do_nothing_new)8997 R_API void U(r_bin_java_stack_frame_do_nothing_new)(RBinJavaObj * bin, RBinJavaStackMapFrame * stack_frame, ut64 offset) {}
U(r_bin_java_get_cp_meta_from_tag)8998 R_API RBinJavaCPTypeMetas *U(r_bin_java_get_cp_meta_from_tag)(ut8 tag) {
8999 	ut16 i = 0;
9000 	// set default to unknown.
9001 	RBinJavaCPTypeMetas *res = &R_BIN_JAVA_CP_METAS[2];
9002 	for (i = 0; i < R_BIN_JAVA_CP_METAS_SZ; i++) {
9003 		if (tag == R_BIN_JAVA_CP_METAS[i].tag) {
9004 			res = &R_BIN_JAVA_CP_METAS[i];
9005 			break;
9006 		}
9007 	}
9008 	return res;
9009 }
9010 
U(r_bin_java_cp_append_ref_cname_fname_ftype)9011 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) {
9012 	ut32 cn_len = 0, fn_len = 0, ft_len = 0, total_len;
9013 	ut16 cn_idx = 0, fn_idx = 0, ft_idx = 0;
9014 	ut8 *bytes = NULL, *cn_bytes = NULL, *fn_bytes = NULL, *ft_bytes = NULL, *cref_bytes = NULL, *fref_bytes = NULL, *fnt_bytes = NULL;
9015 	*out_sz = 0;
9016 	cn_bytes = r_bin_java_cp_get_utf8 (R_BIN_JAVA_CP_UTF8, &cn_len, (const ut8 *) cname, c_len);
9017 	cn_idx = bin->cp_idx + 1;
9018 	if (cn_bytes) {
9019 		fn_bytes = r_bin_java_cp_get_utf8 (R_BIN_JAVA_CP_UTF8, &fn_len, (const ut8 *) fname, f_len);
9020 		fn_idx = bin->cp_idx + 2;
9021 	}
9022 	if (fn_bytes) {
9023 		ft_bytes = r_bin_java_cp_get_utf8 (R_BIN_JAVA_CP_UTF8, &ft_len, (const ut8 *) tname, t_len);
9024 		ft_idx = bin->cp_idx + 3;
9025 	}
9026 	if (cn_bytes && fn_bytes && ft_bytes) {
9027 		ut32 cref_len = 0, fnt_len = 0, fref_len = 0;
9028 		ut32 cref_idx = 0, fnt_idx = 0;
9029 		cref_bytes = r_bin_java_cp_get_classref (bin, &cref_len, NULL, 0, cn_idx);
9030 		cref_idx = bin->cp_idx + 3;
9031 		fnt_bytes = r_bin_java_cp_get_name_type (bin, &fnt_len, fn_idx, ft_idx);
9032 		fnt_idx = bin->cp_idx + 4;
9033 		fref_bytes = r_bin_java_cp_get_2_ut16 (bin, &fref_len, tag, cref_idx, fnt_idx);
9034 		if (cref_bytes && fref_bytes && fnt_bytes) {
9035 			total_len = cn_len + fn_len + ft_len + cref_len + fnt_len + fref_len + 2;
9036 			if (total_len < cn_len) {
9037 				goto beach;
9038 			}
9039 			bytes = calloc (1, total_len);
9040 			// class name bytes
9041 			if (*out_sz + cn_len >= total_len) {
9042 				goto beach;
9043 			}
9044 			memcpy (bytes, cn_bytes + *out_sz, cn_len);
9045 			*out_sz += cn_len;
9046 			// field name bytes
9047 			if (*out_sz + fn_len >= total_len) {
9048 				goto beach;
9049 			}
9050 			memcpy (bytes, fn_bytes + *out_sz, fn_len);
9051 			*out_sz += fn_len;
9052 			// field type bytes
9053 			if (*out_sz + ft_len >= total_len) {
9054 				goto beach;
9055 			}
9056 			memcpy (bytes, ft_bytes + *out_sz, ft_len);
9057 			*out_sz += ft_len;
9058 			// class ref bytes
9059 			if (*out_sz + cref_len >= total_len) {
9060 				goto beach;
9061 			}
9062 			memcpy (bytes, cref_bytes + *out_sz, cref_len);
9063 			*out_sz += fn_len;
9064 			// field name and type bytes
9065 			if (*out_sz + fnt_len >= total_len) {
9066 				goto beach;
9067 			}
9068 			memcpy (bytes, fnt_bytes + *out_sz, fnt_len);
9069 			*out_sz += fnt_len;
9070 			// field ref bytes
9071 			if (*out_sz + fref_len >= total_len) {
9072 				goto beach;
9073 			}
9074 			memcpy (bytes, fref_bytes + *out_sz, fref_len);
9075 			*out_sz += fref_len;
9076 		}
9077 	}
9078 beach:
9079 	free (cn_bytes);
9080 	free (ft_bytes);
9081 	free (fn_bytes);
9082 	free (fnt_bytes);
9083 	free (fref_bytes);
9084 	free (cref_bytes);
9085 	return bytes;
9086 }
U(r_bin_java_cp_get_method_ref)9087 R_API ut8 *U(r_bin_java_cp_get_method_ref)(RBinJavaObj * bin, ut32 * out_sz, ut16 class_idx, ut16 name_and_type_idx) {
9088 	return r_bin_java_cp_get_fm_ref (bin, out_sz, R_BIN_JAVA_CP_METHODREF, class_idx, name_and_type_idx);
9089 }
U(r_bin_java_cp_get_field_ref)9090 R_API ut8 *U(r_bin_java_cp_get_field_ref)(RBinJavaObj * bin, ut32 * out_sz, ut16 class_idx, ut16 name_and_type_idx) {
9091 	return r_bin_java_cp_get_fm_ref (bin, out_sz, R_BIN_JAVA_CP_FIELDREF, class_idx, name_and_type_idx);
9092 }
9093 
U(deinit_java_type_null)9094 R_API void U(deinit_java_type_null)(void) {
9095 	free (R_BIN_JAVA_NULL_TYPE.metas);
9096 }
9097 
r_bin_java_get_item_from_cp(RBinJavaObj * bin,int i)9098 R_API RBinJavaCPTypeObj *r_bin_java_get_item_from_cp(RBinJavaObj *bin, int i) {
9099 	if (i < 1 || i > bin->cf.cp_count) {
9100 		return &R_BIN_JAVA_NULL_TYPE;
9101 	}
9102 	RBinJavaCPTypeObj *obj = (RBinJavaCPTypeObj *) r_list_get_n (bin->cp_list, i);
9103 	return obj ? obj : &R_BIN_JAVA_NULL_TYPE;
9104 }
9105 
U(copy_type_info_to_stack_frame_list)9106 R_API void U(copy_type_info_to_stack_frame_list)(RList * type_list, RList * sf_list) {
9107 	RListIter *iter, *iter_tmp;
9108 	RBinJavaVerificationObj *ver_obj, *new_ver_obj;
9109 	if (!type_list || !sf_list) {
9110 		return;
9111 	}
9112 	r_list_foreach_safe (type_list, iter, iter_tmp, ver_obj) {
9113 		new_ver_obj = (RBinJavaVerificationObj *) malloc (sizeof (RBinJavaVerificationObj));
9114 		// FIXME: how to handle failed memory allocation?
9115 		if (new_ver_obj && ver_obj) {
9116 			memcpy (new_ver_obj, ver_obj, sizeof (RBinJavaVerificationObj));
9117 			if (!r_list_append (sf_list, (void *) new_ver_obj)) {
9118 				R_FREE (new_ver_obj);
9119 			}
9120 		} else {
9121 			R_FREE (new_ver_obj);
9122 		}
9123 	}
9124 }
9125 
U(copy_type_info_to_stack_frame_list_up_to_idx)9126 R_API void U(copy_type_info_to_stack_frame_list_up_to_idx)(RList * type_list, RList * sf_list, ut64 idx) {
9127 	RListIter *iter, *iter_tmp;
9128 	RBinJavaVerificationObj *ver_obj, *new_ver_obj;
9129 	ut32 pos = 0;
9130 	if (!type_list || !sf_list) {
9131 		return;
9132 	}
9133 	r_list_foreach_safe (type_list, iter, iter_tmp, ver_obj) {
9134 		new_ver_obj = (RBinJavaVerificationObj *) malloc (sizeof (RBinJavaVerificationObj));
9135 		// FIXME: how to handle failed memory allocation?
9136 		if (new_ver_obj && ver_obj) {
9137 			memcpy (new_ver_obj, ver_obj, sizeof (RBinJavaVerificationObj));
9138 			if (!r_list_append (sf_list, (void *) new_ver_obj)) {
9139 				R_FREE (new_ver_obj);
9140 			}
9141 		} else {
9142 			R_FREE (new_ver_obj);
9143 		}
9144 		pos++;
9145 		if (pos == idx) {
9146 			break;
9147 		}
9148 	}
9149 }
9150 
r_bin_java_cp_get_idx_bytes(RBinJavaObj * bin,ut16 idx,ut32 * out_sz)9151 R_API ut8 *r_bin_java_cp_get_idx_bytes(RBinJavaObj *bin, ut16 idx, ut32 *out_sz) {
9152 	RBinJavaCPTypeObj *cp_obj = r_bin_java_get_item_from_bin_cp_list (bin, idx);
9153 	if (!cp_obj || !out_sz) {
9154 		return NULL;
9155 	}
9156 	if (out_sz) {
9157 		*out_sz = 0;
9158 	}
9159 	switch (cp_obj->tag) {
9160 	case R_BIN_JAVA_CP_INTEGER:
9161 	case R_BIN_JAVA_CP_FLOAT:
9162 		return r_bin_java_cp_get_4bytes (cp_obj->tag, out_sz, cp_obj->info.cp_integer.bytes.raw, 5);
9163 	case R_BIN_JAVA_CP_LONG:
9164 	case R_BIN_JAVA_CP_DOUBLE:
9165 		return r_bin_java_cp_get_4bytes (cp_obj->tag, out_sz, cp_obj->info.cp_long.bytes.raw, 9);
9166 	case R_BIN_JAVA_CP_UTF8:
9167 		// eprintf ("Getting idx: %d = %p (3+0x%"PFMT64x")\n", idx, cp_obj, cp_obj->info.cp_utf8.length);
9168 		if (cp_obj->info.cp_utf8.length > 0) {
9169 			return r_bin_java_cp_get_utf8 (cp_obj->tag, out_sz,
9170 				cp_obj->info.cp_utf8.bytes, cp_obj->info.cp_utf8.length);
9171 		}
9172 	}
9173 	return NULL;
9174 }
9175 
r_bin_java_valid_class(const ut8 * buf,ut64 buf_sz)9176 R_API int r_bin_java_valid_class(const ut8 *buf, ut64 buf_sz) {
9177 	RBinJavaObj *bin = R_NEW0 (RBinJavaObj), *cur_bin = R_BIN_JAVA_GLOBAL_BIN;
9178 	if (!bin) {
9179 		return false;
9180 	}
9181 	int res = r_bin_java_load_bin (bin, buf, buf_sz);
9182 	if (bin->calc_size == buf_sz) {
9183 		res = true;
9184 	}
9185 	r_bin_java_free (bin);
9186 	R_BIN_JAVA_GLOBAL_BIN = cur_bin;
9187 	return res;
9188 }
9189 
r_bin_java_calc_class_size(ut8 * bytes,ut64 size)9190 R_API ut64 r_bin_java_calc_class_size(ut8 *bytes, ut64 size) {
9191 	RBinJavaObj *bin = R_NEW0 (RBinJavaObj);
9192 	if (!bin) {
9193 		return false;
9194 	}
9195 	RBinJavaObj *cur_bin = R_BIN_JAVA_GLOBAL_BIN;
9196 	ut64 bin_size = UT64_MAX;
9197 	if (bin) {
9198 		if (r_bin_java_load_bin (bin, bytes, size)) {
9199 			bin_size = bin->calc_size;
9200 		}
9201 		r_bin_java_free (bin);
9202 		R_BIN_JAVA_GLOBAL_BIN = cur_bin;
9203 	}
9204 	return bin_size;
9205 }
9206 
U(r_bin_java_get_cp_idx_with_name)9207 R_API int U(r_bin_java_get_cp_idx_with_name)(RBinJavaObj * bin_obj, const char *name, ut32 len) {
9208 	RListIter *iter;
9209 	RBinJavaCPTypeObj *obj;
9210 	r_list_foreach (bin_obj->cp_list, iter, obj) {
9211 		if (obj->tag == R_BIN_JAVA_CP_UTF8) {
9212 			if (!strncmp (name, (const char *) obj->info.cp_utf8.bytes, len)) {
9213 				return obj->metas->ord;
9214 			}
9215 		}
9216 	}
9217 	return 0;
9218 }
9219 
r_bin_java_external_printf(PrintfCallback cb)9220 R_API void r_bin_java_external_printf(PrintfCallback cb) {
9221 	Eprintf = cb ? cb : (PrintfCallback) printf;
9222 }
9223