Rizin
unix-like reverse engineering framework and cli tools
class_bin.c
Go to the documentation of this file.
1 // SPDX-FileCopyrightText: 2021 deroad <wargio@libero.it>
2 // SPDX-License-Identifier: LGPL-3.0-only
3 
4 #include "class_bin.h"
5 #include "class_private.h"
6 
7 #define ACCESS_FLAG_MASK_SRC (ACCESS_FLAG_PUBLIC | ACCESS_FLAG_PRIVATE | ACCESS_FLAG_PROTECTED | ACCESS_FLAG_STATIC | ACCESS_FLAG_FINAL)
8 
9 #define CLASS_ACCESS_FLAGS_SIZE 16
11  { ACCESS_FLAG_PUBLIC, /* */ "public" },
12  { ACCESS_FLAG_PRIVATE, /* */ "private" },
13  { ACCESS_FLAG_PROTECTED, /* */ "protected" },
14  { ACCESS_FLAG_STATIC, /* */ "static" },
15  { ACCESS_FLAG_FINAL, /* */ "final" },
16  { ACCESS_FLAG_SUPER, /* */ "super" },
17  { ACCESS_FLAG_BRIDGE, /* */ "bridge" },
18  { ACCESS_FLAG_VARARGS, /* */ "varargs" },
19  { ACCESS_FLAG_NATIVE, /* */ "native" },
20  { ACCESS_FLAG_INTERFACE, /* */ "interface" },
21  { ACCESS_FLAG_ABSTRACT, /* */ "abstract" },
22  { ACCESS_FLAG_STRICT, /* */ "strict" },
23  { ACCESS_FLAG_SYNTHETIC, /* */ "synthetic" },
24  { ACCESS_FLAG_ANNOTATION, "annotation" },
25  { ACCESS_FLAG_ENUM, /* */ "enum" },
26  { ACCESS_FLAG_MODULE, /* */ "module" },
27 };
28 
30  ut64 flags = 0;
31  if (access_flags & ACCESS_FLAG_PUBLIC) {
33  }
34  if (access_flags & ACCESS_FLAG_PRIVATE) {
36  }
37  if (access_flags & ACCESS_FLAG_PROTECTED) {
39  }
40  if (access_flags & ACCESS_FLAG_STATIC) {
42  }
43  if (access_flags & ACCESS_FLAG_FINAL) {
45  }
46  if (access_flags & ACCESS_FLAG_BRIDGE) {
48  }
49  if (access_flags & ACCESS_FLAG_VARARGS) {
51  }
52  if (access_flags & ACCESS_FLAG_NATIVE) {
54  }
55  if (access_flags & ACCESS_FLAG_ABSTRACT) {
57  }
58  if (access_flags & ACCESS_FLAG_STRICT) {
60  }
61  if (access_flags & ACCESS_FLAG_SYNTHETIC) {
63  }
64  return flags;
65 }
66 
68  if (bin->constant_pool && index < bin->constant_pool_count) {
69  return bin->constant_pool[index];
70  }
71  return NULL;
72 }
73 
75  const ConstPool *cpool = java_class_constant_pool_at(bin, index);
76  if (!cpool) {
77  return NULL;
78  }
79  return java_constant_pool_stringify(cpool);
80 }
81 
82 static ut32 sanitize_size(st64 buffer_size, ut64 count, ut32 min_struct_size) {
83  ut64 memory_size = count * min_struct_size;
84  return memory_size <= buffer_size ? count : 0;
85 }
86 
88  return bin->major_version < (45) || (bin->major_version == 45 && bin->minor_version < 3);
89 }
90 
91 static bool is_eob(RzBuffer *buf) {
93  st64 position = rz_buf_tell(buf);
94  return position >= size;
95 }
96 
98  // https://docs.oracle.com/javase/specs/jvms/se15/html/jvms-4.html#jvms-4.1
99  ut64 offset = 0;
101  if (buffer_size < 1) {
102  RZ_LOG_ERROR("java bin: invalid buffer size (size < 1)\n");
103  goto java_class_parse_bad;
104  }
105 
106  if (!rz_buf_read_be32(buf, &bin->magic) ||
107  !rz_buf_read_be16(buf, &bin->minor_version) ||
108  !rz_buf_read_be16(buf, &bin->major_version) ||
109  !rz_buf_read_be16(buf, &bin->constant_pool_count)) {
110  goto java_class_parse_bad;
111  }
112 
113  // Before version 1.0.2 it was called oak
114  // which uses a different file structure.
115  bool is_oak = java_class_is_oak(bin);
116 
117  bin->constant_pool_count = sanitize_size(buffer_size - rz_buf_tell(buf), bin->constant_pool_count, 3);
118  bin->constant_pool_offset = base + rz_buf_tell(buf);
119 
120  if (bin->constant_pool_count > 0) {
121  bin->constant_pool = RZ_NEWS0(ConstPool *, bin->constant_pool_count);
122  if (!bin->constant_pool) {
123  goto java_class_parse_bad;
124  }
125  for (ut32 i = 1; i < bin->constant_pool_count; ++i) {
126  offset = rz_buf_tell(buf) + base;
128  if (!cpool) {
129  RZ_LOG_ERROR("java bin: could not parse the constant pool value at offset %" PFMT64x "\n", offset);
130  break;
131  }
132  bin->constant_pool[i] = cpool;
134  if (i >= (bin->constant_pool_count - 1)) {
135  break;
136  }
137  i++;
138  bin->constant_pool[i] = java_constant_null_new(offset);
139  }
140  }
141  if (is_eob(buf)) {
143  goto java_class_parse_bad;
144  }
145  }
146 
147  if (!rz_buf_read_be16(buf, &bin->access_flags) ||
148  !rz_buf_read_be16(buf, &bin->this_class) ||
149  !rz_buf_read_be16(buf, &bin->super_class) ||
150  !rz_buf_read_be16(buf, &bin->interfaces_count)) {
151  goto java_class_parse_bad;
152  }
153 
154  bin->interfaces_count = sanitize_size(buffer_size - rz_buf_tell(buf), bin->interfaces_count, 2);
155  bin->interfaces_offset = base + rz_buf_tell(buf);
156 
157  if (bin->interfaces_count > 0) {
158  bin->interfaces = RZ_NEWS0(Interface *, bin->interfaces_count);
159  if (!bin->interfaces) {
160  goto java_class_parse_bad;
161  }
162  for (ut32 i = 0; i < bin->interfaces_count; ++i) {
163  offset = rz_buf_tell(buf) + base;
164  bin->interfaces[i] = java_interface_new(buf, offset);
165  }
166  if (is_eob(buf)) {
168  goto java_class_parse_bad;
169  }
170  }
171 
172  if (!rz_buf_read_be16(buf, &bin->fields_count)) {
173  goto java_class_parse_bad;
174  }
175 
176  bin->fields_count = sanitize_size(buffer_size - rz_buf_tell(buf), bin->fields_count, 8);
177  bin->fields_offset = base + rz_buf_tell(buf);
178 
179  if (bin->fields_count > 0) {
180  bin->fields = RZ_NEWS0(Field *, bin->fields_count);
181  if (!bin->fields) {
182  goto java_class_parse_bad;
183  }
184  for (ut32 i = 0; i < bin->fields_count; ++i) {
185  offset = rz_buf_tell(buf) + base;
186  bin->fields[i] = java_field_new(bin->constant_pool,
187  bin->constant_pool_count, buf, offset);
188  }
189  if (is_eob(buf)) {
191  goto java_class_parse_bad;
192  }
193  }
194 
195  if (!rz_buf_read_be16(buf, &bin->methods_count)) {
196  goto java_class_parse_bad;
197  }
198  bin->methods_count = sanitize_size(buffer_size - rz_buf_tell(buf), bin->methods_count, 8);
199  bin->methods_offset = base + rz_buf_tell(buf);
200 
201  if (bin->methods_count > 0) {
202  bin->methods = RZ_NEWS0(Method *, bin->methods_count);
203  if (!bin->methods) {
204  goto java_class_parse_bad;
205  }
206  for (ut32 i = 0; i < bin->methods_count; ++i) {
207  offset = rz_buf_tell(buf) + base;
208  bin->methods[i] = java_method_new(bin->constant_pool,
209  bin->constant_pool_count, buf, offset, is_oak);
210  }
211  if (is_eob(buf)) {
213  goto java_class_parse_bad;
214  }
215  }
216 
217  if (!rz_buf_read_be16(buf, &bin->attributes_count)) {
218  goto java_class_parse_bad;
219  }
220 
221  bin->attributes_count = sanitize_size(buffer_size - rz_buf_tell(buf), bin->attributes_count, 6);
222  bin->attributes_offset = base + rz_buf_tell(buf);
223 
224  if (bin->attributes_count > 0) {
225  bin->attributes = RZ_NEWS0(Attribute *, bin->attributes_count);
226  if (!bin->attributes) {
227  goto java_class_parse_bad;
228  }
229  for (ut32 i = 0; i < bin->attributes_count; ++i) {
230  offset = rz_buf_tell(buf) + base;
232  if (attr && java_attribute_resolve(bin->constant_pool, bin->constant_pool_count, attr, buf, false)) {
233  bin->attributes[i] = attr;
234  } else {
235  java_attribute_free(attr);
236  break;
237  }
238  }
239  }
240  bin->class_end_offset = base + rz_buf_tell(buf);
241  if (size) {
242  *size = rz_buf_tell(buf);
243  }
244  return true;
245 
246 java_class_parse_bad:
248  return false;
249 }
250 
252  char *tmp_val;
253  char tmp_key[256];
254 
255  sdb_num_set(kv, "java_class.offset", offset, 0);
256  sdb_num_set(kv, "java_class.size", size, 0);
257  sdb_num_set(kv, "java_class.magic", size, 0);
258  sdb_num_set(kv, "java_class.minor_version", size, 0);
259  sdb_num_set(kv, "java_class.major_version", size, 0);
260 
261  tmp_val = rz_bin_java_class_version(bin);
262  if (tmp_val) {
263  sdb_set(kv, "java_class.version", tmp_val, 0);
264  free(tmp_val);
265  }
266 
267  sdb_num_set(kv, "java_class.constant_pool_count", bin->constant_pool_count, 0);
268  for (ut32 i = 0; i < bin->constant_pool_count; ++i) {
269  ConstPool *cpool = bin->constant_pool[i];
270  if (!cpool) {
271  continue;
272  }
273  tmp_val = java_constant_pool_stringify(cpool);
274  if (tmp_val) {
275  snprintf(tmp_key, sizeof(tmp_key), "java_class.constant_pool_%d", i);
276  sdb_set(kv, tmp_key, tmp_val, 0);
277  free(tmp_val);
278  }
279  }
280 
281  sdb_num_set(kv, "java_class.fields_count", bin->fields_count, 0);
282  sdb_num_set(kv, "java_class.methods_count", bin->methods_count, 0);
283  sdb_num_set(kv, "java_class.attributes_count", bin->attributes_count, 0);
284 }
285 
292 
293  ut64 size;
294  if (!java_class_parse(bin, offset, kv, buf, &size)) {
295  return NULL;
296  }
297 
298  java_set_sdb(kv, bin, offset, size);
299 
300  return bin;
301 }
302 
307  if (!bin) {
308  return NULL;
309  }
310 #define is_version(bin, major, minor) ((bin)->major_version == (major) && (bin)->minor_version >= (minor))
311  if (bin->major_version < 45 ||
312  (bin->major_version == 45 && bin->minor_version < 3)) {
313  return strdup("Java SE 1.0.2"); // old format
314  } else if (is_version(bin, 45, 3)) {
315  return strdup("Java SE 1.1");
316  } else if (is_version(bin, 46, 0)) {
317  return strdup("Java SE 1.2");
318  } else if (is_version(bin, 47, 0)) {
319  return strdup("Java SE 1.3");
320  } else if (is_version(bin, 48, 0)) {
321  return strdup("Java SE 1.4");
322  } else if (is_version(bin, 49, 0)) {
323  return strdup("Java SE 1.5"); // enum, generics, annotations
324  } else if (is_version(bin, 50, 0)) {
325  return strdup("Java SE 1.6"); // stackmaps
326  } else if (is_version(bin, 51, 0)) {
327  return strdup("Java SE 1.7");
328  } else if (is_version(bin, 52, 0)) {
329  return strdup("Java SE 1.8"); // lambda, type annos, param names
330  } else if (is_version(bin, 53, 0)) {
331  return strdup("Java SE 1.9"); // modules, indy string concat
332  } else if (is_version(bin, 54, 0)) {
333  return strdup("Java SE 10");
334  } else if (is_version(bin, 55, 0)) {
335  return strdup("Java SE 11"); // constant dynamic, nest mates
336  } else if (is_version(bin, 56, 0)) {
337  return strdup("Java SE 12");
338  } else if (is_version(bin, 57, 0)) {
339  return strdup("Java SE 13");
340  } else if (is_version(bin, 58, 0)) {
341  return strdup("Java SE 14");
342  } else if (is_version(bin, 59, 0)) {
343  return strdup("Java SE 15");
344  } else if (is_version(bin, 60, 0)) {
345  return strdup("Java SE 16");
346  }
347 #undef is_version
348  return strdup("unknown");
349 }
350 
352  if (!bin) {
353  return 0;
354  }
355  if (bin->methods) {
356  for (ut32 i = 0; i < bin->methods_count; ++i) {
357  Method *method = bin->methods[i];
358  if (!method || method->attributes_count < 1) {
359  continue;
360  }
361  for (ut32 k = 0; k < method->attributes_count; ++k) {
362  Attribute *attr = method->attributes[k];
363  if (attr && attr->type == ATTRIBUTE_TYPE_CODE) {
364  AttributeCode *ac = (AttributeCode *)attr->info;
365  for (ut32 k = 0; k < ac->attributes_count; k++) {
366  Attribute *cattr = ac->attributes[k];
367  if (cattr && cattr->type == ATTRIBUTE_TYPE_LINENUMBERTABLE) {
369  }
370  }
371  }
372  }
373  }
374  }
375  return RZ_BIN_DBG_SYMS;
376 }
377 
380  const char *language = "java";
381  char *string = NULL;
382  if (bin->constant_pool) {
383  for (ut32 i = 0; i < bin->constant_pool_count; ++i) {
384  const ConstPool *cpool = bin->constant_pool[i];
385  if (!cpool || !java_constant_pool_is_string(cpool)) {
386  continue;
387  }
388  string = java_constant_pool_stringify(cpool);
389  if (string && !strncmp(string, "kotlin/jvm", 10)) {
390  language = "kotlin";
391  break;
392  } else if (string && !strncmp(string, "org/codehaus/groovy/runtime", 27)) {
393  language = "groovy";
394  break;
395  }
396  free(string);
397  string = NULL;
398  }
399  }
400  free(string);
401  return language;
402 }
403 
408  if (!bin) {
409  return;
410  }
411  if (bin->constant_pool) {
412  for (ut32 i = 0; i < bin->constant_pool_count; ++i) {
413  java_constant_pool_free(bin->constant_pool[i]);
414  }
415  free(bin->constant_pool);
416  }
417  if (bin->interfaces) {
418  for (ut32 i = 0; i < bin->interfaces_count; ++i) {
419  java_interface_free(bin->interfaces[i]);
420  }
421  free(bin->interfaces);
422  }
423  if (bin->fields) {
424  for (ut32 i = 0; i < bin->fields_count; ++i) {
425  java_field_free(bin->fields[i]);
426  }
427  free(bin->fields);
428  }
429  if (bin->methods) {
430  for (ut32 i = 0; i < bin->methods_count; ++i) {
431  java_method_free(bin->methods[i]);
432  }
433  free(bin->methods);
434  }
435  if (bin->attributes) {
436  for (ut32 i = 0; i < bin->attributes_count; ++i) {
437  java_attribute_free(bin->attributes[i]);
438  }
439  free(bin->attributes);
440  }
441  free(bin);
442 }
443 
448  ut16 index;
450  const ConstPool *cpool = java_class_constant_pool_at(bin, bin->this_class);
451 
452  if (!cpool || java_constant_pool_resolve(cpool, &index, NULL) != 1) {
453  RZ_LOG_ERROR("java bin: unknown class name at constant pool index %u\n", bin->this_class);
454  return strdup("unknown_class");
455  }
456 
458  char *class_name = rz_str_newf("L%s;", tmp);
459  free(tmp);
460  return class_name;
461 }
462 
467  ut16 index;
469  const ConstPool *cpool = java_class_constant_pool_at(bin, bin->super_class);
470  if (!cpool || java_constant_pool_resolve(cpool, &index, NULL) != 1) {
471  RZ_LOG_ERROR("java bin: unknown super name at constant pool index %u\n", bin->this_class);
472  return strdup("unknown_super");
473  }
475 }
476 
478  rz_return_val_if_fail(bin, 0xffffffff);
479  return bin->access_flags;
480 }
481 
487  RzStrBuf *sb = NULL;
488  ut16 access_flags = bin->access_flags & mask;
489 
490  for (ut32 i = 0; i < CLASS_ACCESS_FLAGS_SIZE; ++i) {
491  const AccessFlagsReadable *afr = &access_flags_list[i];
492  if (access_flags & afr->flag) {
493  if (!sb) {
494  sb = rz_strbuf_new(afr->readable);
495  if (!sb) {
496  return NULL;
497  }
498  } else {
499  rz_strbuf_appendf(sb, " %s", afr->readable);
500  }
501  }
502  }
503 
504  return sb ? rz_strbuf_drain(sb) : NULL;
505 }
506 
508  if (count > 9999) {
509  return 5;
510  } else if (count > 999) {
511  return 4;
512  } else if (count > 99) {
513  return 3;
514  }
515  return 2;
516 }
517 
522  rz_return_if_fail(bin && j);
523  char *tmp = NULL;
524 
525  pj_o(j);
526 
527  pj_ko(j, "version");
528  {
529  pj_kn(j, "minor", bin->minor_version);
530  pj_kn(j, "major", bin->major_version);
532  pj_ks(j, "version", tmp ? tmp : "");
533  free(tmp);
534  }
535  pj_end(j);
536 
537  pj_kn(j, "constant_pool_count", bin->constant_pool_count);
538  pj_k(j, "constant_pool");
540 
541  pj_kn(j, "access_flags_n", bin->access_flags);
543  pj_ks(j, "access_flags_s", tmp ? tmp : "");
544  free(tmp);
545 
546  pj_kn(j, "class_n", bin->this_class);
548  pj_ks(j, "class_s", tmp ? tmp : "");
549  free(tmp);
550 
551  pj_kn(j, "super_n", bin->super_class);
553  pj_ks(j, "super_s", tmp ? tmp : "");
554  free(tmp);
555 
556  pj_kn(j, "interfaces_count", bin->interfaces_count);
557  pj_k(j, "interfaces");
559 
560  pj_kn(j, "methods_count", bin->methods_count);
561  pj_k(j, "methods");
563 
564  pj_kn(j, "fields_count", bin->fields_count);
565  pj_k(j, "fields");
567 
568  pj_kn(j, "attributes_count", bin->attributes_count);
569  pj_ka(j, "attributes");
570  for (ut32 i = 0; i < bin->attributes_count; ++i) {
571  Attribute *attr = bin->attributes[i];
572  if (!attr) {
573  continue;
574  }
575  pj_o(j);
576  pj_kn(j, "offset", attr->offset);
577  pj_kn(j, "size", attr->attribute_length);
578  pj_kn(j, "name_n", attr->attribute_name_index);
580  pj_ks(j, "name_s", tmp ? tmp : "");
581  free(tmp);
582  pj_end(j);
583  }
584  pj_end(j);
585  pj_end(j);
586 }
587 
593  char number[16];
594  char *tmp = NULL;
595  int padding;
596 
598  rz_strbuf_appendf(sb, "Version: (%u.%u) %s\n", bin->major_version, bin->minor_version, tmp);
599  free(tmp);
600 
602  rz_strbuf_appendf(sb, "Flags: (0x%04x) %s\n", bin->access_flags, tmp);
603  free(tmp);
604 
606  rz_strbuf_appendf(sb, "Class: (#%u) %s\n", bin->this_class, tmp);
607  free(tmp);
608 
610  rz_strbuf_appendf(sb, "Super: (#%u) %s\n", bin->super_class, tmp);
611  free(tmp);
612 
617 
618  rz_strbuf_appendf(sb, "Attributes: %u\n", bin->attributes_count);
619  padding = calculate_padding_ut16(bin->attributes_count) + 1;
620  for (ut32 i = 0; i < bin->attributes_count; ++i) {
621  Attribute *attr = bin->attributes[i];
622  if (!attr) {
623  continue;
624  }
625  snprintf(number, sizeof(number), "#%u", i);
627  rz_strbuf_appendf(sb, " %-*s = #%-5u size: %-5u %s\n", padding, number, attr->attribute_name_index, attr->attribute_length, tmp);
628  free(tmp);
629  }
630 }
631 
632 static inline bool is_dual_index(const ConstPool *cpool) {
633  return cpool->tag == CONSTANT_POOL_FIELDREF ||
634  cpool->tag == CONSTANT_POOL_METHODREF ||
636  cpool->tag == CONSTANT_POOL_NAMEANDTYPE ||
637  cpool->tag == CONSTANT_POOL_DYNAMIC ||
639 }
640 
645  rz_return_val_if_fail(bin && index >= 0, NULL);
646  ut16 arg0, arg1;
647  char *tmp;
648  const ConstPool *cpool = java_class_constant_pool_at(bin, index);
649 
650  if (!cpool || !index) {
651  return NULL;
652  }
653  if (java_constant_pool_is_string(cpool) ||
655  return java_constant_pool_stringify(cpool);
656  } else if (cpool->tag == CONSTANT_POOL_CLASS) {
657  if (java_constant_pool_resolve(cpool, &arg0, NULL) != 1) {
658  RZ_LOG_ERROR("java bin: can't resolve constant pool index %u\n", index);
659  return NULL;
660  }
662  if (tmp[0] == '[' && tmp[1] == 'L') {
663  return tmp;
664  }
665  char *res = rz_str_newf("L%s;", tmp);
666  free(tmp);
667  return res;
668  } else if (cpool->tag == CONSTANT_POOL_STRING) {
669  if (java_constant_pool_resolve(cpool, &arg0, NULL) != 1) {
670  RZ_LOG_ERROR("java bin: can't resolve constant pool index %u\n", index);
671  return NULL;
672  }
674  tmp = rz_str_newf("\"%s\"", s0);
675  free(s0);
676  return tmp;
677  } else if (is_dual_index(cpool)) {
678  if (java_constant_pool_resolve(cpool, &arg0, &arg1) != 2) {
679  RZ_LOG_ERROR("java bin: can't resolve constant pool index %u\n", index);
680  return NULL;
681  }
682  char *s0 = arg0 ? rz_bin_java_class_const_pool_resolve_index(bin, arg0) : NULL;
684  if ((arg0 && !s0) || !s1) {
685  RZ_LOG_ERROR("java bin: can't resolve constant pool index %u\n", index);
686  free(s0);
687  free(s1);
688  return NULL;
689  }
690  if (!arg0) {
691  return s1;
692  }
693  if (s1[0] == '(') {
694  tmp = rz_str_newf("%s%s", s0, s1);
695  } else {
696  tmp = rz_str_newf("%s.%s", s0, s1);
697  }
698  free(s0);
699  free(s1);
700  return tmp;
701  }
702  return NULL;
703 }
704 
710 
711  char *dem = NULL;
712  char *tmp = NULL;
713  ut16 index;
714 
715  RzListIter *iter;
717  rz_list_foreach (list, iter, tmp) {
718  rz_str_replace_char(tmp, '/', '.');
719  rz_strbuf_appendf(sb, "import %s;\n", tmp);
720  }
721  if (rz_list_length(list) > 0) {
722  rz_strbuf_appendf(sb, "\n");
723  }
725 
726  rz_strbuf_append(sb, "class");
727 
729  if (tmp) {
730  rz_strbuf_appendf(sb, " %s", tmp);
731  free(tmp);
732  }
733 
735  dem = rz_demangler_java(tmp);
736  if (dem) {
737  rz_strbuf_appendf(sb, " %s", dem);
738  RZ_FREE(dem);
739  } else {
740  rz_strbuf_appendf(sb, " %s", tmp);
741  }
742 
743  free(tmp);
744 
745  if (bin->access_flags & ACCESS_FLAG_SUPER) {
747  if (strcmp(tmp, "java/lang/Object") != 0) {
748  rz_str_replace_char(tmp, '/', '.');
749  rz_strbuf_appendf(sb, " extends %s", tmp);
750  }
751  free(tmp);
752  }
753 
754  if (bin->interfaces_count > 0) {
755  rz_strbuf_append(sb, " implements ");
756  ut32 k = 0;
757  for (ut32 i = 0; i < bin->interfaces_count; ++i) {
758  if (!bin->interfaces[i]) {
759  continue;
760  }
761  const ConstPool *cpool = java_class_constant_pool_at(bin, bin->interfaces[i]->index);
762  if (!cpool || java_constant_pool_resolve(cpool, &index, NULL) != 1) {
763  RZ_LOG_ERROR("java bin: can't resolve constant pool index %u\n", bin->interfaces[i]->index);
764  break;
765  }
767  if ((dem = rz_demangler_java(tmp))) {
768  free(tmp);
769  tmp = dem;
770  }
771  if (k > 0) {
772  rz_strbuf_appendf(sb, ", %s", tmp);
773  } else {
775  }
776  free(tmp);
777  k++;
778  }
779  if (k < 1) {
780  rz_strbuf_append(sb, "?");
781  }
782  }
783 
784  rz_strbuf_append(sb, " {\n");
785 
786  if (bin->methods) {
787  for (ut32 i = 0; i < bin->methods_count; ++i) {
788  const Method *method = bin->methods[i];
789  if (!method) {
790  continue;
791  }
792  rz_strbuf_append(sb, " ");
793 
795  if (tmp) {
796  rz_strbuf_appendf(sb, "%s ", tmp);
797  free(tmp);
798  }
799 
801  if (!name) {
802  name = strdup("?");
803  }
805  if (!desc) {
806  desc = strdup("(?)V");
807  }
808 
809  if (desc[0] == '(') {
810  tmp = rz_str_newf("%s%s", name, desc);
811  } else {
812  tmp = strdup(name);
813  }
814  free(desc);
815  free(name);
816 
817  dem = rz_demangler_java(tmp);
818  if (!dem) {
820  } else {
821  rz_strbuf_append(sb, dem);
822  RZ_FREE(dem);
823  }
824  free(tmp);
825  rz_strbuf_append(sb, ";\n");
826  }
827  }
828 
829  if (bin->methods_count > 0 && bin->fields_count) {
830  rz_strbuf_append(sb, "\n");
831  }
832 
833  if (bin->fields) {
834  for (ut32 i = 0; i < bin->fields_count; ++i) {
835  const Field *field = bin->fields[i];
836  if (!field) {
837  continue;
838  }
839  rz_strbuf_append(sb, " ");
840 
842  if (tmp) {
843  rz_strbuf_appendf(sb, "%s ", tmp);
844  free(tmp);
845  }
846 
848  if (tmp) {
849  rz_str_replace_char(tmp, '/', '.');
850  rz_strbuf_appendf(sb, "%s ", tmp);
851  free(tmp);
852  }
853 
855  if (tmp) {
856  rz_str_replace_char(tmp, '/', '.');
858  free(tmp);
859  }
860  rz_strbuf_append(sb, "\n");
861  }
862  }
863 
864  rz_strbuf_append(sb, "}\n");
865 }
866 
872 
873  RzBinAddr *ret = RZ_NEW0(RzBinAddr);
874  if (!ret) {
875  return NULL;
876  }
877  ret->paddr = UT64_MAX;
878 
879  char *name = NULL;
880  if (bin->methods) {
881  for (ut32 i = 0; i < bin->methods_count; ++i) {
882  const Method *method = bin->methods[i];
883  if (!method) {
884  continue;
885  }
886 
888  if (!name) {
889  continue;
890  }
891 
893  if (strcmp(name, "<init>") != 0 && strcmp(name, "<clinit>") != 0) {
894  free(name);
895  continue;
896  }
897  } else if (resolve == RZ_BIN_SPECIAL_SYMBOL_MAIN) {
898  if (strcmp(name, "main") != 0) {
899  free(name);
900  continue;
901  }
902  }
903  free(name);
904  ut64 addr = UT64_MAX;
905  for (ut32 i = 0; i < method->attributes_count; ++i) {
906  Attribute *attr = method->attributes[i];
907  if (attr && attr->type == ATTRIBUTE_TYPE_CODE) {
908  AttributeCode *ac = (AttributeCode *)attr->info;
909  addr = ac->code_offset;
910  break;
911  }
912  }
913  if (addr == UT64_MAX) {
914  RZ_LOG_ERROR("java bin: can't resolve symbol address\n");
915  continue;
916  }
917  ret->paddr = addr;
918  break;
919  }
920  }
921  return ret;
922 }
923 
929 
931  if (!list) {
932  return NULL;
933  }
934 
935  char *name = NULL;
936  bool is_static;
937  if (bin->methods) {
938  for (ut32 i = 0; i < bin->methods_count; ++i) {
939  const Method *method = bin->methods[i];
940  if (!method) {
942  continue;
943  }
944  is_static = method->access_flags & METHOD_ACCESS_FLAG_STATIC;
945  if (!is_static) {
947  if (!name) {
948  continue;
949  }
950  if (strcmp(name, "main") != 0 && strcmp(name, "<init>") != 0 && strcmp(name, "<clinit>") != 0) {
951  free(name);
952  continue;
953  }
954  free(name);
955  }
956 
957  ut64 addr = UT64_MAX;
958  for (ut32 i = 0; i < method->attributes_count; ++i) {
959  Attribute *attr = method->attributes[i];
960  if (attr && attr->type == ATTRIBUTE_TYPE_CODE) {
961  AttributeCode *ac = (AttributeCode *)attr->info;
962  addr = ac->code_offset;
963  break;
964  }
965  }
966  if (addr == UT64_MAX) {
967  RZ_LOG_ERROR("java bin: can't resolve entrypoint address\n");
968  continue;
969  }
970 
971  RzBinAddr *entrypoint = RZ_NEW0(RzBinAddr);
972  if (!entrypoint) {
974  continue;
975  }
976  entrypoint->vaddr = entrypoint->paddr = addr;
977  rz_list_append(list, entrypoint);
978  }
979  }
980  return list;
981 }
982 
988 
990  if (!list) {
991  return NULL;
992  }
993 
994  char *string;
995  if (bin->constant_pool_count > 0) {
996  for (ut32 i = 1; i < bin->constant_pool_count; ++i) {
997  const ConstPool *cpool = bin->constant_pool[i];
998  if (!cpool || !java_constant_pool_is_string(cpool) || cpool->size < 1) {
999  continue;
1000  }
1001  string = java_constant_pool_stringify(cpool);
1002  if (!string) {
1003  RZ_LOG_ERROR("java bin: expecting a string, got NULL\n");
1004  continue;
1005  }
1006  RzBinString *bstr = RZ_NEW0(RzBinString);
1007  if (!bstr) {
1008  free(string);
1010  continue;
1011  }
1012  bstr->paddr = cpool->offset;
1013  bstr->ordinal = i;
1014  bstr->length = cpool->size;
1015  bstr->size = cpool->size;
1016  bstr->string = string;
1017  bstr->type = RZ_STRING_ENC_MUTF8;
1018  rz_list_append(list, bstr);
1019  }
1020  }
1021 
1022  for (ut32 i = 0; i < bin->attributes_count; ++i) {
1023  Attribute *attr = bin->attributes[i];
1024  if (attr && attr->type == ATTRIBUTE_TYPE_SOURCEDEBUGEXTENSION) {
1025  RzBinString *bstr = RZ_NEW0(RzBinString);
1026  if (!bstr) {
1028  continue;
1029  }
1030  bstr->paddr = attr->offset;
1031  bstr->ordinal = i;
1032  bstr->length = attr->attribute_length;
1033  bstr->size = attr->attribute_length;
1034  bstr->string = strdup(attr->info);
1035  bstr->type = RZ_STRING_ENC_UTF8;
1036  rz_list_append(list, bstr);
1037  }
1038  }
1039  return list;
1040 }
1041 
1042 static char *add_class_name_to_name(char *name, char *classname) {
1043  if (classname) {
1044  return rz_str_newf("%s.%s", classname, name);
1045  }
1046  return strdup(name);
1047 }
1048 
1054 
1056  if (!list) {
1057  return NULL;
1058  }
1059 
1060  char *method_name = NULL;
1061  if (bin->methods) {
1062  for (ut32 i = 0; i < bin->methods_count; ++i) {
1063  const Method *method = bin->methods[i];
1064  if (!method) {
1066  continue;
1067  }
1068  const ConstPool *cpool = java_class_constant_pool_at(bin, method->name_index);
1069  if (!cpool || !java_constant_pool_is_string(cpool)) {
1070  RZ_LOG_ERROR("java bin: can't resolve method with constant pool index %u\n", method->name_index);
1071  continue;
1072  }
1073  method_name = java_constant_pool_stringify(cpool);
1074  if (!method_name) {
1075  continue;
1076  }
1077  ut64 size = 0;
1078  ut64 addr = UT64_MAX;
1079  for (ut32 i = 0; i < method->attributes_count; ++i) {
1080  Attribute *attr = method->attributes[i];
1081  if (attr && attr->type == ATTRIBUTE_TYPE_CODE) {
1082  AttributeCode *ac = (AttributeCode *)attr->info;
1083  addr = ac->code_offset;
1084  size = attr->attribute_length;
1085  break;
1086  }
1087  }
1089  if (!symbol) {
1091  free(method_name);
1092  continue;
1093  }
1095  if (!desc) {
1096  desc = strdup("(?)V");
1097  }
1098 
1100  symbol->dname = rz_str_newf("%s%s", method_name, desc);
1101  symbol->name = add_class_name_to_name(method_name, symbol->classname);
1102  symbol->size = size;
1104  symbol->type = RZ_BIN_TYPE_FUNC_STR;
1105  symbol->ordinal = rz_list_length(list);
1106  symbol->visibility = method->access_flags;
1108  symbol->libname = rz_demangler_java(symbol->classname);
1110  free(desc);
1111  free(method_name);
1112  rz_list_append(list, symbol);
1113  }
1114  }
1115  return list;
1116 }
1117 
1122  rz_return_if_fail(bin && sb);
1123 
1124  rz_strbuf_appendf(sb, "Methods: %u\n", bin->methods_count);
1125  char number[16];
1126  char *flags, *name, *descr;
1127  if (bin->methods) {
1128  for (ut32 i = 0; i < bin->methods_count; ++i) {
1129  const Method *method = bin->methods[i];
1130  if (!method) {
1132  continue;
1133  }
1137 
1138  if (flags) {
1139  rz_strbuf_appendf(sb, " %s %s%s;\n", flags, name, descr);
1140  } else {
1141  rz_strbuf_appendf(sb, " %s%s;\n", name, descr);
1142  }
1143  rz_strbuf_appendf(sb, " name: %s\n", name);
1144  rz_strbuf_appendf(sb, " descriptor: %s\n", descr);
1145  rz_strbuf_appendf(sb, " flags: (0x%04x) %s\n", method->access_flags, flags ? flags : "");
1146 
1147  free(flags);
1148  free(name);
1149  free(descr);
1150  rz_strbuf_appendf(sb, " attributes: %u\n", method->attributes_count);
1151  int padding = calculate_padding_ut16(method->attributes_count) + 1;
1152  for (ut32 i = 0; i < method->attributes_count; ++i) {
1153  Attribute *attr = method->attributes[i];
1154  if (!attr) {
1155  continue;
1156  }
1157  snprintf(number, sizeof(number), "#%u", i);
1159  rz_strbuf_appendf(sb, " %-*s = #%-5u size: %-5u %s\n", padding, number, attr->attribute_name_index, attr->attribute_length, name);
1160  free(name);
1161  }
1162  }
1163  }
1164 }
1165 
1170  rz_return_if_fail(bin && j);
1171 
1172  pj_a(j);
1173 
1174  char *tmp;
1175  if (bin->methods) {
1176  for (ut32 i = 0; i < bin->methods_count; ++i) {
1177  const Method *method = bin->methods[i];
1178  if (!method) {
1180  continue;
1181  }
1182  pj_o(j); // {
1183  pj_kn(j, "offset", method->offset);
1184 
1185  pj_kn(j, "access_flags_n", method->access_flags);
1187  pj_ks(j, "access_flags_s", tmp ? tmp : "");
1188  free(tmp);
1189 
1190  pj_kn(j, "name_n", method->name_index);
1192  pj_ks(j, "name_s", tmp ? tmp : "");
1193  free(tmp);
1194 
1195  pj_kn(j, "descriptor_n", method->descriptor_index);
1197  pj_ks(j, "descriptor_s", tmp ? tmp : "");
1198  free(tmp);
1199 
1200  pj_kn(j, "attributes_count", method->attributes_count);
1201  pj_ka(j, "attributes"); // [
1202  for (ut32 i = 0; i < method->attributes_count; ++i) {
1203  Attribute *attr = method->attributes[i];
1204  if (!attr) {
1206  continue;
1207  }
1208  pj_o(j);
1209  pj_kn(j, "offset", attr->offset);
1210  pj_kn(j, "size", attr->attribute_length);
1211  pj_kn(j, "name_n", attr->attribute_name_index);
1213  pj_ks(j, "name_s", tmp ? tmp : "");
1214  free(tmp);
1215  pj_end(j);
1216  }
1217  pj_end(j); // ]
1218  pj_end(j); // }
1219  }
1220  }
1221  pj_end(j);
1222 }
1223 
1229 
1231  if (!list) {
1232  return NULL;
1233  }
1234 
1235  char *field_name = NULL;
1236  if (bin->fields) {
1237  for (ut32 i = 0; i < bin->fields_count; ++i) {
1238  const Field *field = bin->fields[i];
1239  if (!field) {
1241  continue;
1242  }
1243  const ConstPool *cpool = java_class_constant_pool_at(bin, field->name_index);
1244  if (!cpool || !java_constant_pool_is_string(cpool)) {
1245  RZ_LOG_ERROR("java bin: can't resolve field with constant pool index %u\n", field->name_index);
1246  continue;
1247  }
1249  if (!field_name) {
1250  continue;
1251  }
1252  RzBinSymbol *symbol = rz_bin_symbol_new(NULL, field->offset, field->offset);
1253  if (!symbol) {
1255  free(field_name);
1256  continue;
1257  }
1259  symbol->name = add_class_name_to_name(field_name, symbol->classname);
1260  symbol->size = 0;
1262  symbol->type = RZ_BIN_TYPE_OBJECT_STR;
1263  symbol->ordinal = i;
1264  symbol->visibility = field->access_flags;
1267  free(field_name);
1268  rz_list_append(list, symbol);
1269  }
1270  }
1271  return list;
1272 }
1273 
1279 
1281  if (!list) {
1282  return NULL;
1283  }
1284 
1285  char *name = NULL;
1286  if (bin->fields) {
1287  for (ut32 i = 0; i < bin->fields_count; ++i) {
1288  const Field *field = bin->fields[i];
1289  if (!field) {
1291  continue;
1292  }
1293  const ConstPool *cpool = java_class_constant_pool_at(bin, field->name_index);
1294  if (!cpool || !java_constant_pool_is_string(cpool)) {
1295  RZ_LOG_ERROR("java bin: can't resolve field with constant pool index %u\n", field->name_index);
1296  continue;
1297  }
1299  if (!name) {
1300  continue;
1301  }
1302  RzBinField *bf = rz_bin_field_new(field->offset, field->offset, 0, name, NULL, NULL, false);
1303  if (bf) {
1304  bf->visibility = field->access_flags;
1307  rz_list_append(list, bf);
1308  }
1309  free(name);
1310  }
1311  }
1312  return list;
1313 }
1314 
1319  rz_return_if_fail(bin && sb);
1320 
1321  rz_strbuf_appendf(sb, "Fields: %u\n", bin->fields_count);
1322  char number[16];
1323  char *flags, *name, *descr;
1324  if (bin->fields) {
1325  for (ut32 i = 0; i < bin->fields_count; ++i) {
1326  const Field *field = bin->fields[i];
1327  if (!field) {
1329  continue;
1330  }
1334 
1335  if (flags) {
1336  rz_strbuf_appendf(sb, " %s %s%s;\n", flags, name, descr);
1337  } else {
1338  rz_strbuf_appendf(sb, " %s%s;\n", name, descr);
1339  }
1340  rz_strbuf_appendf(sb, " name: %s\n", name);
1341  rz_strbuf_appendf(sb, " descriptor: %s\n", descr);
1342  rz_strbuf_appendf(sb, " flags: (0x%04x) %s\n", field->access_flags, flags);
1343 
1344  free(flags);
1345  free(name);
1346  free(descr);
1347  rz_strbuf_appendf(sb, " attributes: %u\n", field->attributes_count);
1348  int padding = calculate_padding_ut16(field->attributes_count) + 1;
1349  for (ut32 i = 0; i < field->attributes_count; ++i) {
1350  Attribute *attr = field->attributes[i];
1351  if (!attr) {
1352  continue;
1353  }
1354  snprintf(number, sizeof(number), "#%u", i);
1356  rz_strbuf_appendf(sb, " %*s = #%-5u size: %-5u %s\n", padding, number, attr->attribute_name_index, attr->attribute_length, name);
1357  free(name);
1358  }
1359  }
1360  }
1361 }
1362 
1367  rz_return_if_fail(bin && j);
1368 
1369  pj_a(j);
1370 
1371  char *tmp;
1372  if (bin->fields) {
1373  for (ut32 i = 0; i < bin->fields_count; ++i) {
1374  const Field *field = bin->fields[i];
1375  if (!field) {
1377  continue;
1378  }
1379  pj_o(j); // {
1380 
1381  pj_kn(j, "offset", field->offset);
1382 
1383  pj_kn(j, "access_flags_n", field->access_flags);
1385  pj_ks(j, "access_flags_s", tmp ? tmp : "");
1386  free(tmp);
1387 
1388  pj_kn(j, "name_n", field->name_index);
1390  pj_ks(j, "name_s", tmp ? tmp : "");
1391  free(tmp);
1392 
1393  pj_kn(j, "descriptor_n", field->descriptor_index);
1395  pj_ks(j, "descriptor_s", tmp ? tmp : "");
1396  free(tmp);
1397 
1398  pj_kn(j, "attributes_count", field->attributes_count);
1399  pj_ka(j, "attributes"); // [
1400  for (ut32 i = 0; i < field->attributes_count; ++i) {
1401  Attribute *attr = field->attributes[i];
1402  if (!attr) {
1403  continue;
1404  }
1405  pj_o(j);
1406  pj_kn(j, "offset", attr->offset);
1407  pj_kn(j, "size", attr->attribute_length);
1408  pj_kn(j, "name_n", attr->attribute_name_index);
1410  pj_ks(j, "name_s", tmp ? tmp : "");
1411  free(tmp);
1412  pj_end(j);
1413  }
1414  pj_end(j); // ]
1415  pj_end(j); // }
1416  }
1417  }
1418  pj_end(j);
1419 }
1420 
1421 static char *import_type(const ConstPool *cpool) {
1422  if (cpool->tag == CONSTANT_POOL_METHODREF) {
1423  return RZ_BIN_TYPE_METH_STR;
1424  } else if (cpool->tag == CONSTANT_POOL_FIELDREF) {
1425  return "FIELD";
1426  } else if (cpool->tag == CONSTANT_POOL_INTERFACEMETHODREF) {
1427  return "IMETH";
1428  }
1429  return RZ_BIN_TYPE_UNKNOWN_STR;
1430 }
1431 
1437 
1439  if (!list) {
1440  return NULL;
1441  }
1442  char *method_name, *classname;
1443  bool is_main;
1444  ut16 class_index, name_and_type_index, name_index, descriptor_index, class_name_index;
1445  if (bin->constant_pool) {
1446  for (ut32 i = 0; i < bin->constant_pool_count; ++i) {
1447  const ConstPool *cpool = bin->constant_pool[i];
1448  if (!cpool || !java_constant_pool_is_import(cpool)) {
1449  continue;
1450  }
1451  if (java_constant_pool_resolve(cpool, &class_index, &name_and_type_index) != 2) {
1452  RZ_LOG_ERROR("java bin: can't resolve symbol with constant pool index %u\n", i);
1453  break;
1454  }
1455  const ConstPool *nat = java_class_constant_pool_at(bin, name_and_type_index);
1456  if (!nat ||
1457  java_constant_pool_resolve(nat, &name_index, &descriptor_index) != 2) {
1458  RZ_LOG_ERROR("java bin: can't resolve symbol with constant pool index %u\n", i);
1459  break;
1460  }
1461  const ConstPool *pclass = java_class_constant_pool_at(bin, class_index);
1462  if (!pclass ||
1463  java_constant_pool_resolve(pclass, &class_name_index, NULL) != 1) {
1464  RZ_LOG_ERROR("java bin: can't resolve symbol with constant pool index %u\n", i);
1465  break;
1466  }
1467  RzBinSymbol *symbol = rz_bin_symbol_new(NULL, cpool->offset, cpool->offset);
1468  if (!symbol) {
1470  break;
1471  }
1472 
1473  char *desc = java_class_constant_pool_stringify_at(bin, descriptor_index);
1474  if (!desc) {
1475  desc = strdup("(?)V");
1476  }
1477 
1478  method_name = java_class_constant_pool_stringify_at(bin, name_index);
1479  if (!method_name) {
1480  method_name = strdup("unknown_method");
1481  }
1482  is_main = !strcmp(method_name, "main");
1483  classname = java_class_constant_pool_stringify_at(bin, class_name_index);
1484  symbol->name = add_class_name_to_name(method_name, symbol->classname);
1485  if (desc[0] == '(') {
1486  symbol->dname = rz_str_newf("%s%s", method_name, desc);
1487  } else {
1488  symbol->dname = strdup(method_name);
1489  }
1490  symbol->classname = rz_str_newf("L%s;", classname);
1491  symbol->libname = classname;
1492  rz_str_replace_ch(symbol->libname, '/', '.', 1);
1493  symbol->bind = RZ_BIN_BIND_IMPORT_STR;
1494  symbol->type = is_main ? RZ_BIN_TYPE_FUNC_STR : import_type(cpool);
1495  symbol->ordinal = i;
1496  symbol->is_imported = true;
1497  free(desc);
1498  free(method_name);
1499  rz_list_append(list, symbol);
1500  }
1501  }
1502 
1503  return list;
1504 }
1505 
1511 
1513  if (!imports) {
1514  return NULL;
1515  }
1516  bool is_main;
1517  ut16 class_index, name_and_type_index, name_index, descriptor_index, class_name_index;
1518  if (bin->constant_pool) {
1519  for (ut32 i = 0; i < bin->constant_pool_count; ++i) {
1520  const ConstPool *cpool = bin->constant_pool[i];
1521  if (!cpool || !java_constant_pool_is_import(cpool)) {
1522  continue;
1523  }
1524  if (java_constant_pool_resolve(cpool, &class_index, &name_and_type_index) != 2) {
1525  RZ_LOG_ERROR("java bin: can't resolve import with constant pool index %u\n", i);
1526  continue;
1527  }
1528  const ConstPool *nat = java_class_constant_pool_at(bin, name_and_type_index);
1529  if (!nat ||
1530  java_constant_pool_resolve(nat, &name_index, &descriptor_index) != 2) {
1531  RZ_LOG_ERROR("java bin: can't resolve import with constant pool index %u\n", i);
1532  continue;
1533  }
1534  const ConstPool *pclass = java_class_constant_pool_at(bin, class_index);
1535  if (!pclass ||
1536  java_constant_pool_resolve(pclass, &class_name_index, NULL) != 1) {
1537  RZ_LOG_ERROR("java bin: can't resolve import with constant pool index %u\n", i);
1538  continue;
1539  }
1540 
1541  char *object = java_class_constant_pool_stringify_at(bin, class_name_index);
1542  if (!object) {
1543  continue;
1544  }
1545 
1546  RzBinImport *import = RZ_NEW0(RzBinImport);
1547  if (!import) {
1549  continue;
1550  }
1551 
1552  char *class_name = (char *)rz_str_rchr(object, NULL, '/');
1553  if (class_name) {
1554  class_name[0] = 0;
1555  class_name++;
1556  }
1557  rz_str_replace_ch(object, '/', '.', 1);
1558 
1559  import->classname = strdup(class_name ? class_name : object);
1560  import->libname = class_name ? strdup(object) : NULL;
1561  import->name = java_class_constant_pool_stringify_at(bin, name_index);
1562  is_main = import->name && !strcmp(import->name, "main");
1563  import->bind = is_main ? RZ_BIN_BIND_GLOBAL_STR : NULL;
1564  import->type = is_main ? RZ_BIN_TYPE_FUNC_STR : import_type(cpool);
1565  import->descriptor = java_class_constant_pool_stringify_at(bin, descriptor_index);
1566  import->ordinal = i;
1567  free(object);
1568  rz_list_append(imports, import);
1569  }
1570  }
1571 
1572  if (bin->interfaces) {
1573  for (ut32 i = 0; i < bin->interfaces_count; ++i) {
1574  if (!bin->interfaces[i]) {
1575  continue;
1576  }
1577 
1578  RzBinImport *import = RZ_NEW0(RzBinImport);
1579  if (!import) {
1581  continue;
1582  }
1583  const ConstPool *cpool = java_class_constant_pool_at(bin, bin->interfaces[i]->index);
1584  if (!cpool || java_constant_pool_resolve(cpool, &class_index, NULL) != 1) {
1585  RZ_LOG_ERROR("java bin: can't resolve interface with constant pool index %u\n", i);
1586  rz_bin_import_free(import);
1587  continue;
1588  }
1589 
1590  import->classname = java_class_constant_pool_stringify_at(bin, class_index);
1591  import->name = strdup("*");
1592  import->bind = RZ_BIN_BIND_WEAK_STR;
1593  import->type = RZ_BIN_TYPE_IFACE_STR;
1594  import->ordinal = i;
1595  rz_list_append(imports, import);
1596  }
1597  }
1598 
1599  return imports;
1600 }
1601 
1606  rz_return_if_fail(bin && sb);
1607 
1608  char number[16];
1609  const char *tag;
1610  char *text, *rtext;
1611  rz_strbuf_appendf(sb, "Constant pool: %u\n", bin->constant_pool_count);
1612  if (bin->constant_pool) {
1613  int padding = calculate_padding_ut16(bin->constant_pool_count) + 1;
1614  for (ut32 i = 0; i < bin->constant_pool_count; ++i) {
1615  rtext = NULL;
1616  const ConstPool *cpool = bin->constant_pool[i];
1617  if (!cpool) {
1618  continue;
1619  }
1621  if (!tag) {
1622  RZ_LOG_ERROR("java bin: invalid tag name for constant pool at index %u\n", i);
1623  continue;
1624  }
1625  snprintf(number, sizeof(number), "#%u", i);
1627  if (i > 0 && !java_constant_pool_is_string(cpool) &&
1628  !java_constant_pool_is_number(cpool)) {
1630  }
1631  if (rtext) {
1632  char *dem = rz_demangler_java(rtext);
1633  if (dem) {
1634  free(rtext);
1635  rtext = dem;
1636  }
1637  rz_strbuf_appendf(sb, " %*s = %-19s %-14s // %s\n", padding, number, tag, text, rtext);
1638  } else {
1639  rz_strbuf_appendf(sb, " %*s = %-19s %s\n", padding, number, tag, text);
1640  }
1641  free(text);
1642  free(rtext);
1643  }
1644  }
1645 }
1646 
1651  rz_return_if_fail(bin && j);
1652  const char *tag;
1653  char *text, *rtext;
1654  pj_a(j);
1655  if (bin->constant_pool) {
1656  for (ut32 i = 0; i < bin->constant_pool_count; ++i) {
1657  rtext = NULL;
1658  const ConstPool *cpool = bin->constant_pool[i];
1659  if (!cpool) {
1660  continue;
1661  }
1663  if (!tag) {
1664  RZ_LOG_ERROR("java bin: invalid tag name for constant pool at index %u\n", i);
1665  continue;
1666  }
1668  pj_o(j);
1669  pj_kn(j, "index", i);
1670  pj_kn(j, "tag_n", cpool->tag);
1671  pj_ks(j, "tag_s", tag);
1672  pj_ks(j, "value", text ? text : "");
1673  if (i > 0 && !java_constant_pool_is_string(cpool) &&
1674  !java_constant_pool_is_number(cpool)) {
1676  pj_ks(j, "resolved", rtext ? rtext : "");
1677  }
1678  pj_end(j);
1679  free(text);
1680  free(rtext);
1681  }
1682  }
1683  pj_end(j);
1684 }
1685 
1686 static RzBinSection *new_section(const char *name, ut64 start, ut64 end, ut32 perm) {
1688  if (!section) {
1690  return NULL;
1691  }
1692  section->name = strdup(name);
1693  if (!section->name) {
1695  free(section);
1696  return NULL;
1697  }
1698  section->paddr = start;
1699  section->vaddr = start;
1700  section->size = end - start;
1701  section->vsize = section->size;
1702  section->perm = perm;
1703  return section;
1704 }
1705 
1706 static void section_free(void *u) {
1708 }
1709 
1710 static int compare_section_names(const void *a, const void *b) {
1711  RzBinSection *sec = (RzBinSection *)b;
1712  return strcmp((const char *)a, sec->name);
1713 }
1714 
1720 
1722  if (!sections) {
1723  return NULL;
1724  }
1725  ut32 iname;
1726  char *tmp;
1727  char secname[512];
1728  ut64 end_offset;
1729  if (bin->constant_pool) {
1731  new_section("class.constant_pool",
1732  bin->constant_pool_offset,
1733  bin->interfaces_offset,
1734  RZ_PERM_R));
1735  }
1736  if (bin->interfaces) {
1738  new_section("class.interfaces",
1739  bin->interfaces_offset,
1740  bin->fields_offset,
1741  RZ_PERM_R));
1742  }
1743  if (bin->fields) {
1744  for (ut32 i = 0; i < bin->fields_count; ++i) {
1745  Field *field = bin->fields[i];
1746  if (!field) {
1747  continue;
1748  }
1750  if (!tmp) {
1752  continue;
1753  }
1754  snprintf(secname, sizeof(secname), "class.fields.%s.attr", tmp);
1755  if ((i + 1) < bin->fields_count && bin->fields[i + 1]) {
1756  end_offset = bin->fields[i + 1]->offset;
1757  } else {
1758  end_offset = bin->methods_offset;
1759  }
1760  for (iname = 0; rz_list_find(sections, secname, compare_section_names); iname++) {
1761  snprintf(secname, sizeof(secname), "class.fields.%s_%d.attr", tmp, iname);
1762  }
1763  free(tmp);
1764  rz_list_append(sections, new_section(secname, field->offset, end_offset, RZ_PERM_R));
1765  }
1767  new_section("class.fields",
1768  bin->fields_offset,
1769  bin->methods_offset,
1770  RZ_PERM_R));
1771  }
1772  if (bin->methods) {
1774  new_section("class.methods",
1775  bin->methods_offset,
1776  bin->attributes_offset,
1777  RZ_PERM_R));
1778 
1779  for (ut32 i = 0; i < bin->methods_count; ++i) {
1780  Method *method = bin->methods[i];
1781  if (!method || method->attributes_count < 1) {
1782  continue;
1783  }
1785  if (!tmp) {
1787  continue;
1788  }
1789  snprintf(secname, sizeof(secname), "class.methods.%s.attr", tmp);
1790  for (iname = 0; rz_list_find(sections, secname, compare_section_names); iname++) {
1791  snprintf(secname, sizeof(secname), "class.methods.%s_%d.attr", tmp, iname);
1792  }
1793 
1794  if ((i + 1) < bin->methods_count && bin->methods[i + 1]) {
1795  end_offset = bin->methods[i + 1]->offset;
1796  } else {
1797  end_offset = bin->attributes_offset;
1798  }
1799  if (iname > 0) {
1800  snprintf(secname, sizeof(secname), "class.methods.%s_%d.attr", tmp, iname);
1801  } else {
1802  snprintf(secname, sizeof(secname), "class.methods.%s.attr", tmp);
1803  }
1804  rz_list_append(sections, new_section(secname, method->offset, end_offset, RZ_PERM_R));
1805 
1806  if (!method->attributes) {
1807  free(tmp);
1808  continue;
1809  }
1810 
1811  for (ut32 k = 0; k < method->attributes_count; ++k) {
1812  Attribute *attr = method->attributes[k];
1813  if (attr && attr->type == ATTRIBUTE_TYPE_CODE) {
1814  AttributeCode *ac = (AttributeCode *)attr->info;
1815  if (iname > 0) {
1816  snprintf(secname, sizeof(secname), "class.methods.%s_%d.attr.%d.code", tmp, iname, k);
1817  } else {
1818  snprintf(secname, sizeof(secname), "class.methods.%s.attr.%d.code", tmp, k);
1819  }
1820  ut64 size = ac->code_offset + attr->attribute_length;
1822  break;
1823  }
1824  }
1825  free(tmp);
1826  }
1827  }
1828  if (bin->attributes) {
1830  new_section("class.attr",
1831  bin->attributes_offset,
1832  bin->class_end_offset,
1833  RZ_PERM_R));
1834  }
1835 
1836  return sections;
1837 }
1838 
1839 static int compare_strings(const void *a, const void *b) {
1840  return strcmp((const char *)a, (const char *)b);
1841 }
1842 
1848 
1850  if (!list) {
1851  return NULL;
1852  }
1853  ut16 arg0, arg1;
1854  char *tmp;
1855 
1856  if (bin->constant_pool) {
1857  for (ut32 i = 0; i < bin->constant_pool_count; ++i) {
1858  tmp = NULL;
1859  const ConstPool *cpool = bin->constant_pool[i];
1860  if (!cpool) {
1861  continue;
1862  }
1863  if (cpool->tag == CONSTANT_POOL_CLASS) {
1864  if (java_constant_pool_resolve(cpool, &arg0, &arg1) != 1) {
1865  RZ_LOG_ERROR("java bin: can't resolve library with constant pool index %u\n", i);
1866  break;
1867  }
1868  // arg0 is name_index
1870  } else if (java_constant_pool_is_import(cpool)) {
1871  if (java_constant_pool_resolve(cpool, &arg0, &arg1) != 2) {
1872  RZ_LOG_ERROR("java bin: can't resolve library with constant pool index %u\n", i);
1873  break;
1874  }
1875  // arg0 is name_and_type_index
1876  const ConstPool *nat = java_class_constant_pool_at(bin, arg0);
1877  if (!nat ||
1878  java_constant_pool_resolve(nat, &arg0, &arg1) != 1) {
1879  RZ_LOG_ERROR("java bin: can't resolve library with constant pool index %u\n", i);
1880  break;
1881  }
1882  // arg0 is name_index
1884  }
1885  if (tmp && !rz_list_find(list, tmp, compare_strings)) {
1887  } else {
1888  free(tmp);
1889  }
1890  }
1891  }
1892  return list;
1893 }
1894 
1899  rz_return_if_fail(bin && sb);
1900 
1901  ut16 index;
1902  char number[16];
1903  char *tmp = NULL;
1904  rz_strbuf_appendf(sb, "Interfaces: %u\n", bin->interfaces_count);
1905  if (bin->interfaces) {
1906  int padding = calculate_padding_ut16(bin->constant_pool_count) + 1;
1907  for (ut32 i = 0; i < bin->interfaces_count; ++i) {
1908  if (!bin->interfaces[i]) {
1909  continue;
1910  }
1911  const ConstPool *cpool = java_class_constant_pool_at(bin, bin->interfaces[i]->index);
1912  if (!cpool || java_constant_pool_resolve(cpool, &index, NULL) != 1) {
1913  RZ_LOG_ERROR("java bin: can't resolve interface with constant pool index %u\n", i);
1914  break;
1915  }
1916  snprintf(number, sizeof(number), "#%u", i);
1918  rz_str_replace_char(tmp, '/', '.');
1919  rz_strbuf_appendf(sb, " %*s = #%-5u %s\n", padding, number, index, tmp);
1920  free(tmp);
1921  }
1922  }
1923 }
1924 
1929  rz_return_if_fail(bin && j);
1930  pj_a(j);
1931  char *tmp = NULL;
1932  ut16 index;
1933  if (bin->interfaces) {
1934  for (ut32 i = 0; i < bin->interfaces_count; ++i) {
1935  if (!bin->interfaces[i]) {
1936  continue;
1937  }
1938 
1939  const ConstPool *cpool = java_class_constant_pool_at(bin, bin->interfaces[i]->index);
1940  if (!cpool || java_constant_pool_resolve(cpool, &index, NULL) != 1) {
1941  RZ_LOG_ERROR("java bin: can't resolve interface with constant pool index %u\n", i);
1942  continue;
1943  }
1944  pj_o(j);
1945  pj_kn(j, "offset", bin->interfaces[i]->offset);
1946  pj_kn(j, "name_n", bin->interfaces[i]->index);
1948  rz_str_replace_char(tmp, '/', '.');
1949  pj_ks(j, "name_s", tmp ? tmp : "");
1950  free(tmp);
1951  pj_end(j);
1952  }
1953  }
1954  pj_end(j);
1955 }
#define mask()
lzma_index ** i
Definition: index.h:629
RZ_API RzBinSymbol * rz_bin_symbol_new(const char *name, ut64 paddr, ut64 vaddr)
Definition: bin.c:165
RZ_API void rz_bin_symbol_free(RzBinSymbol *sym)
Definition: bin.c:175
RZ_API void rz_bin_string_free(void *_str)
Definition: bin.c:192
RZ_API void rz_bin_field_free(RzBinField *field)
Definition: bin.c:950
RZ_API void rz_bin_import_free(RzBinImport *imp)
Definition: bin.c:137
RZ_API void rz_bin_section_free(RzBinSection *bs)
Definition: bin.c:1116
RZ_API RzBinField * rz_bin_field_new(ut64 paddr, ut64 vaddr, int size, const char *name, const char *comment, const char *format, bool format_named)
Definition: bin.c:935
static SblHeader sb
Definition: bin_mbn.c:26
RzList * imports(RzBinFile *bf)
Definition: bin_ne.c:106
RzList * sections(RzBinFile *bf)
Definition: bin_ne.c:110
const char * desc
Definition: bin_vsf.c:19
bool java_attribute_resolve(ConstPool **pool, ut32 poolsize, Attribute *attr, RzBuffer *buf, bool is_oak)
Attribute * java_attribute_new(RzBuffer *buf, ut64 offset)
void java_attribute_free(Attribute *attr)
@ ATTRIBUTE_TYPE_CODE
@ ATTRIBUTE_TYPE_LINENUMBERTABLE
@ ATTRIBUTE_TYPE_SOURCEDEBUGEXTENSION
RZ_API RZ_BORROW const char * rz_bin_java_class_language(RZ_NONNULL RzBinJavaClass *bin)
Definition: class_bin.c:378
RZ_API void rz_bin_java_class_const_pool_as_json(RZ_NONNULL RzBinJavaClass *bin, RZ_NONNULL PJ *j)
Returns the class const pool in json format via PJ arg.
Definition: class_bin.c:1650
static bool java_class_parse(RzBinJavaClass *bin, ut64 base, Sdb *kv, RzBuffer *buf, ut64 *size)
Definition: class_bin.c:97
RZ_API RZ_OWN RzList * rz_bin_java_class_fields_as_symbols(RZ_NONNULL RzBinJavaClass *bin)
Returns a RzList<RzBinSymbol*> containing the class fields.
Definition: class_bin.c:1227
static char * add_class_name_to_name(char *name, char *classname)
Definition: class_bin.c:1042
RZ_API RZ_OWN RzList * rz_bin_java_class_const_pool_as_symbols(RZ_NONNULL RzBinJavaClass *bin)
Returns a RzList<RzBinSymbol*> containing the class const pool.
Definition: class_bin.c:1435
RZ_API RZ_OWN RzList * rz_bin_java_class_methods_as_symbols(RZ_NONNULL RzBinJavaClass *bin)
Returns a RzList<RzBinSymbol*> containing the class methods.
Definition: class_bin.c:1052
RZ_API ut64 rz_bin_java_class_debug_info(RZ_NONNULL RzBinJavaClass *bin)
Definition: class_bin.c:351
static int calculate_padding_ut16(ut16 count)
Definition: class_bin.c:507
RZ_API RZ_OWN RzList * rz_bin_java_class_as_libraries(RZ_NONNULL RzBinJavaClass *bin)
Returns a RzList<char*> containing the class libraries.
Definition: class_bin.c:1846
RZ_API void rz_bin_java_class_interfaces_as_text(RZ_NONNULL RzBinJavaClass *bin, RZ_NONNULL RzStrBuf *sb)
Returns the class interfaces as text via RzStrBuf arg.
Definition: class_bin.c:1898
RZ_API RZ_OWN RzBinJavaClass * rz_bin_java_class_new(RZ_NONNULL RzBuffer *buf, ut64 offset, RZ_NONNULL Sdb *kv)
Parses the java class file and returns a RzBinJavaClass struct.
Definition: class_bin.c:289
RZ_API RZ_OWN RzList * rz_bin_java_class_strings(RZ_NONNULL RzBinJavaClass *bin)
Returns a RzList<RzBinString*> containing the strings.
Definition: class_bin.c:986
static RzBinSection * new_section(const char *name, ut64 start, ut64 end, ut32 perm)
Definition: class_bin.c:1686
static ut32 sanitize_size(st64 buffer_size, ut64 count, ut32 min_struct_size)
Definition: class_bin.c:82
static const AccessFlagsReadable access_flags_list[CLASS_ACCESS_FLAGS_SIZE]
Definition: class_bin.c:10
RZ_API void rz_bin_java_class_as_json(RZ_NONNULL RzBinJavaClass *bin, RZ_NONNULL PJ *j)
Returns the class info as json.
Definition: class_bin.c:521
RZ_API void rz_bin_java_class_fields_as_json(RZ_NONNULL RzBinJavaClass *bin, RZ_NONNULL PJ *j)
Returns the fields in json format via PJ arg.
Definition: class_bin.c:1366
RZ_API RZ_OWN RzList * rz_bin_java_class_const_pool_as_imports(RZ_NONNULL RzBinJavaClass *bin)
Returns a RzList<RzBinImport*> containing the class const pool.
Definition: class_bin.c:1509
RZ_API RZ_OWN RzList * rz_bin_java_class_as_sections(RZ_NONNULL RzBinJavaClass *bin)
Returns a RzList<RzBinSection*> containing the class sections.
Definition: class_bin.c:1718
static bool is_dual_index(const ConstPool *cpool)
Definition: class_bin.c:632
RZ_API RZ_OWN char * rz_bin_java_class_version(RZ_NONNULL RzBinJavaClass *bin)
Parses the java class file and returns a RzBinJavaClass struct.
Definition: class_bin.c:306
static ut64 java_access_flags_to_bin_flags(ut64 access_flags)
Definition: class_bin.c:29
static int compare_section_names(const void *a, const void *b)
Definition: class_bin.c:1710
static char * java_class_constant_pool_stringify_at(RzBinJavaClass *bin, ut32 index)
Definition: class_bin.c:74
static char * import_type(const ConstPool *cpool)
Definition: class_bin.c:1421
RZ_API RZ_OWN char * rz_bin_java_class_const_pool_resolve_index(RZ_NONNULL RzBinJavaClass *bin, st32 index)
Returns the string linked to the class const pool index.
Definition: class_bin.c:644
RZ_API void rz_bin_java_class_as_text(RZ_NONNULL RzBinJavaClass *bin, RZ_NONNULL RzStrBuf *sb)
Returns the class info as text.
Definition: class_bin.c:591
RZ_API RZ_OWN char * rz_bin_java_class_access_flags_readable(RZ_NONNULL RzBinJavaClass *bin, ut16 mask)
Returns the readable class access flags.
Definition: class_bin.c:485
RZ_API RZ_OWN RzList * rz_bin_java_class_entrypoints(RZ_NONNULL RzBinJavaClass *bin)
Returns a RzList<RzBinAddr*> containing the entrypoints.
Definition: class_bin.c:927
RZ_API RZ_OWN char * rz_bin_java_class_name(RZ_NONNULL RzBinJavaClass *bin)
Returns the class name.
Definition: class_bin.c:447
RZ_API RZ_OWN RzList * rz_bin_java_class_fields_as_binfields(RZ_NONNULL RzBinJavaClass *bin)
Returns a RzList<RzBinField*> containing the class fields.
Definition: class_bin.c:1277
RZ_API RZ_OWN char * rz_bin_java_class_super(RZ_NONNULL RzBinJavaClass *bin)
Returns the class super name.
Definition: class_bin.c:466
static bool java_class_is_oak(RzBinJavaClass *bin)
Definition: class_bin.c:87
RZ_API RZ_OWN RzBinAddr * rz_bin_java_class_resolve_symbol(RZ_NONNULL RzBinJavaClass *bin, RzBinSpecialSymbol resolve)
Resolves and returns the RzBinAddr struct linked to the input RzBinSpecialSymbol.
Definition: class_bin.c:870
static const ConstPool * java_class_constant_pool_at(RzBinJavaClass *bin, ut32 index)
Definition: class_bin.c:67
RZ_API void rz_bin_java_class_as_source_code(RZ_NONNULL RzBinJavaClass *bin, RZ_NONNULL RzStrBuf *sb)
Returns the class info as text source code.
Definition: class_bin.c:708
static bool is_eob(RzBuffer *buf)
Definition: class_bin.c:91
static void section_free(void *u)
Definition: class_bin.c:1706
#define ACCESS_FLAG_MASK_SRC
Definition: class_bin.c:7
RZ_API void rz_bin_java_class_const_pool_as_text(RZ_NONNULL RzBinJavaClass *bin, RZ_NONNULL RzStrBuf *sb)
Returns the class const pool in text format via RzStrBuf arg.
Definition: class_bin.c:1605
RZ_API void rz_bin_java_class_free(RZ_NULLABLE RzBinJavaClass *bin)
Frees a RzBinJavaClass pointer.
Definition: class_bin.c:407
static void java_set_sdb(Sdb *kv, RzBinJavaClass *bin, ut64 offset, ut64 size)
Definition: class_bin.c:251
RZ_API void rz_bin_java_class_interfaces_as_json(RZ_NONNULL RzBinJavaClass *bin, RZ_NONNULL PJ *j)
Returns the class interfaces as json via PJ arg.
Definition: class_bin.c:1928
static int compare_strings(const void *a, const void *b)
Definition: class_bin.c:1839
#define is_version(bin, major, minor)
RZ_API void rz_bin_java_class_methods_as_text(RZ_NONNULL RzBinJavaClass *bin, RZ_NONNULL RzStrBuf *sb)
Returns the methods in text format via RzStrBuf arg.
Definition: class_bin.c:1121
RZ_API ut32 rz_bin_java_class_access_flags(RZ_NONNULL RzBinJavaClass *bin)
Definition: class_bin.c:477
RZ_API void rz_bin_java_class_fields_as_text(RZ_NONNULL RzBinJavaClass *bin, RZ_NONNULL RzStrBuf *sb)
Returns the fields in text format via RzStrBuf arg.
Definition: class_bin.c:1318
#define CLASS_ACCESS_FLAGS_SIZE
Definition: class_bin.c:9
RZ_API void rz_bin_java_class_methods_as_json(RZ_NONNULL RzBinJavaClass *bin, RZ_NONNULL PJ *j)
Returns the methods in json format via PJ arg.
Definition: class_bin.c:1169
@ ACCESS_FLAG_SUPER
Definition: class_bin.h:23
#define ACCESS_FLAG_MASK_ALL
Definition: class_bin.h:36
bool java_constant_pool_requires_null(const ConstPool *cpool)
bool java_constant_pool_is_string(const ConstPool *cpool)
void java_constant_pool_free(ConstPool *cpool)
ut32 java_constant_pool_resolve(const ConstPool *cpool, ut16 *arg0, ut16 *arg1)
char * java_constant_pool_stringify(const ConstPool *cpool)
const char * java_constant_pool_tag_name(const ConstPool *cpool)
ConstPool * java_constant_pool_new(RzBuffer *buf, ut64 offset)
ConstPool * java_constant_null_new(ut64 offset)
bool java_constant_pool_is_number(const ConstPool *cpool)
bool java_constant_pool_is_import(const ConstPool *cpool)
@ CONSTANT_POOL_FIELDREF
@ CONSTANT_POOL_METHODREF
@ CONSTANT_POOL_INTERFACEMETHODREF
@ CONSTANT_POOL_NAMEANDTYPE
@ CONSTANT_POOL_DYNAMIC
@ CONSTANT_POOL_INVOKEDYNAMIC
@ CONSTANT_POOL_CLASS
@ CONSTANT_POOL_STRING
bool java_field_is_global(const Field *field)
Definition: class_field.c:91
Field * java_field_new(ConstPool **pool, ut32 poolsize, RzBuffer *buf, ut64 offset)
Definition: class_field.c:41
void java_field_free(Field *field)
Definition: class_field.c:78
char * java_field_access_flags_readable(const Field *field)
Definition: class_field.c:20
Interface * java_interface_new(RzBuffer *buf, ut64 offset)
#define java_interface_free(x)
Method * java_method_new(ConstPool **pool, ut32 poolsize, RzBuffer *buf, ut64 offset, bool is_oak)
Definition: class_method.c:54
bool java_method_is_global(const Method *method)
Definition: class_method.c:102
char * java_method_access_flags_readable(const Method *method)
Definition: class_method.c:26
void java_method_free(Method *method)
Definition: class_method.c:89
@ METHOD_ACCESS_FLAG_STATIC
Definition: class_method.h:15
#define RZ_API
#define NULL
Definition: cris-opc.c:27
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void count
Definition: sflib.h:98
static static sync static getppid static getegid const char static filename char static len const char char static bufsiz static mask static vfork const void static prot static getpgrp const char static swapflags static arg static fd static protocol static who struct sockaddr static addrlen static backlog struct timeval struct timezone static tz const struct iovec static count static mode const void const struct sockaddr static tolen const char static pathname void static offset struct stat static buf void long static basep static whence static length const void static len static semflg const void static shmflg const struct timespec struct timespec static rem const char static group const void start
Definition: sflib.h:133
uint16_t ut16
uint32_t ut32
const char * k
Definition: dsignal.c:11
@ ACCESS_FLAG_MODULE
Definition: dex.h:56
@ ACCESS_FLAG_SYNTHETIC
Definition: dex.h:53
@ ACCESS_FLAG_VARARGS
Definition: dex.h:48
@ ACCESS_FLAG_NATIVE
Definition: dex.h:49
@ ACCESS_FLAG_PRIVATE
Definition: dex.h:42
@ ACCESS_FLAG_ENUM
Definition: dex.h:55
@ ACCESS_FLAG_PROTECTED
Definition: dex.h:43
@ ACCESS_FLAG_STATIC
Definition: dex.h:44
@ ACCESS_FLAG_ANNOTATION
Definition: dex.h:54
@ ACCESS_FLAG_BRIDGE
Definition: dex.h:47
@ ACCESS_FLAG_STRICT
Definition: dex.h:52
@ ACCESS_FLAG_ABSTRACT
Definition: dex.h:51
@ ACCESS_FLAG_FINAL
Definition: dex.h:45
@ ACCESS_FLAG_INTERFACE
Definition: dex.h:50
@ ACCESS_FLAG_PUBLIC
Definition: dex.h:41
RZ_API void Ht_() free(HtName_(Ht) *ht)
Definition: ht_inc.c:130
voidpf void uLong size
Definition: ioapi.h:138
voidpf uLong offset
Definition: ioapi.h:144
voidpf void * buf
Definition: ioapi.h:138
snprintf
Definition: kernel.h:364
RZ_API RZ_OWN char * rz_demangler_java(RZ_NULLABLE const char *symbol)
Demangles java symbols.
Definition: demangler.c:38
static void list(RzEgg *egg)
Definition: rz-gg.c:52
RZ_API RZ_BORROW RzListIter * rz_list_find(RZ_NONNULL const RzList *list, const void *p, RZ_NONNULL RzListComparator cmp)
Returns RzListIter element which matches via the RzListComparator.
Definition: list.c:620
RZ_API RZ_OWN RzList * rz_list_newf(RzListFree f)
Returns a new initialized RzList pointer and sets the free method.
Definition: list.c:248
RZ_API ut32 rz_list_length(RZ_NONNULL const RzList *list)
Returns the length of the list.
Definition: list.c:109
RZ_API RZ_BORROW RzListIter * rz_list_append(RZ_NONNULL RzList *list, void *data)
Appends at the end of the list a new element.
Definition: list.c:288
RZ_API void rz_list_free(RZ_NONNULL RzList *list)
Empties the list and frees the list pointer.
Definition: list.c:137
return strdup("=SP r13\n" "=LR r14\n" "=PC r15\n" "=A0 r0\n" "=A1 r1\n" "=A2 r2\n" "=A3 r3\n" "=ZF zf\n" "=SF nf\n" "=OF vf\n" "=CF cf\n" "=SN or0\n" "gpr lr .32 56 0\n" "gpr pc .32 60 0\n" "gpr cpsr .32 64 0 ____tfiae_________________qvczn\n" "gpr or0 .32 68 0\n" "gpr tf .1 64.5 0 thumb\n" "gpr ef .1 64.9 0 endian\n" "gpr jf .1 64.24 0 java\n" "gpr qf .1 64.27 0 sticky_overflow\n" "gpr vf .1 64.28 0 overflow\n" "gpr cf .1 64.29 0 carry\n" "gpr zf .1 64.30 0 zero\n" "gpr nf .1 64.31 0 negative\n" "gpr itc .4 64.10 0 if_then_count\n" "gpr gef .4 64.16 0 great_or_equal\n" "gpr r0 .32 0 0\n" "gpr r1 .32 4 0\n" "gpr r2 .32 8 0\n" "gpr r3 .32 12 0\n" "gpr r4 .32 16 0\n" "gpr r5 .32 20 0\n" "gpr r6 .32 24 0\n" "gpr r7 .32 28 0\n" "gpr r8 .32 32 0\n" "gpr r9 .32 36 0\n" "gpr r10 .32 40 0\n" "gpr r11 .32 44 0\n" "gpr r12 .32 48 0\n" "gpr r13 .32 52 0\n" "gpr r14 .32 56 0\n" "gpr r15 .32 60 0\n" "gpr r16 .32 64 0\n" "gpr r17 .32 68 0\n")
RZ_API int sdb_num_set(Sdb *s, const char *key, ut64 v, ut32 cas)
Definition: num.c:25
const char * name
Definition: op.c:541
@ field_name
Definition: parser.c:1737
#define rz_warn_if_reached()
Definition: rz_assert.h:29
#define rz_return_if_fail(expr)
Definition: rz_assert.h:100
#define rz_return_val_if_fail(expr, val)
Definition: rz_assert.h:108
#define RZ_BIN_BIND_WEAK_STR
Definition: rz_bin.h:108
#define RZ_BIN_TYPE_OBJECT_STR
Definition: rz_bin.h:118
#define RZ_BIN_METH_PUBLIC
Definition: rz_bin.h:85
#define RZ_BIN_TYPE_METH_STR
Definition: rz_bin.h:122
#define RZ_BIN_METH_VARARGS
Definition: rz_bin.h:99
#define RZ_BIN_METH_SYNTHETIC
Definition: rz_bin.h:100
#define RZ_BIN_METH_STRICT
Definition: rz_bin.h:101
#define RZ_BIN_TYPE_IFACE_STR
Definition: rz_bin.h:121
RzBinSpecialSymbol
Definition: rz_bin.h:136
@ RZ_BIN_SPECIAL_SYMBOL_ENTRY
Definition: rz_bin.h:137
@ RZ_BIN_SPECIAL_SYMBOL_INIT
Definition: rz_bin.h:138
@ RZ_BIN_SPECIAL_SYMBOL_MAIN
Definition: rz_bin.h:139
#define RZ_BIN_DBG_SYMS
Definition: rz_bin.h:30
#define RZ_BIN_METH_ABSTRACT
Definition: rz_bin.h:95
#define RZ_BIN_METH_FINAL
Definition: rz_bin.h:91
#define RZ_BIN_BIND_LOCAL_STR
Definition: rz_bin.h:106
#define RZ_BIN_BIND_GLOBAL_STR
Definition: rz_bin.h:107
#define RZ_BIN_METH_BRIDGE
Definition: rz_bin.h:98
#define RZ_BIN_METH_STATIC
Definition: rz_bin.h:84
#define RZ_BIN_METH_PRIVATE
Definition: rz_bin.h:86
#define RZ_BIN_METH_PROTECTED
Definition: rz_bin.h:87
#define RZ_BIN_TYPE_FUNC_STR
Definition: rz_bin.h:119
#define RZ_BIN_METH_NATIVE
Definition: rz_bin.h:97
#define RZ_BIN_TYPE_UNKNOWN_STR
Definition: rz_bin.h:134
#define RZ_BIN_DBG_LINENUMS
Definition: rz_bin.h:29
#define RZ_BIN_BIND_IMPORT_STR
Definition: rz_bin.h:114
RZ_API ut64 rz_buf_tell(RZ_NONNULL RzBuffer *b)
Return the current cursor position.
Definition: buf.c:1238
#define rz_buf_read_be16(b, result)
Definition: rz_buf.h:280
#define rz_buf_read_be32(b, result)
Definition: rz_buf.h:281
RZ_API ut64 rz_buf_size(RZ_NONNULL RzBuffer *b)
Return the size of the buffer.
Definition: buf.c:1225
void(* RzListFree)(void *ptr)
Definition: rz_list.h:11
#define RZ_LOG_ERROR(fmtstr,...)
Definition: rz_log.h:58
RZ_API PJ * pj_ko(PJ *j, const char *k)
Definition: pj.c:156
RZ_API PJ * pj_ka(PJ *j, const char *k)
Definition: pj.c:163
RZ_API PJ * pj_k(PJ *j, const char *k)
Definition: pj.c:104
RZ_API PJ * pj_end(PJ *j)
Definition: pj.c:87
RZ_API PJ * pj_o(PJ *j)
Definition: pj.c:75
RZ_API PJ * pj_ks(PJ *j, const char *k, const char *v)
Definition: pj.c:170
RZ_API PJ * pj_kn(PJ *j, const char *k, ut64 n)
Definition: pj.c:121
RZ_API PJ * pj_a(PJ *j)
Definition: pj.c:81
RZ_API char * rz_str_newf(const char *fmt,...) RZ_PRINTF_CHECK(1
RZ_API const char * rz_str_rchr(const char *base, const char *p, int ch)
Definition: str.c:829
@ RZ_STRING_ENC_MUTF8
Definition: rz_str.h:22
@ RZ_STRING_ENC_UTF8
Definition: rz_str.h:21
RZ_API int rz_str_replace_ch(char *s, char a, char b, bool g)
Definition: str.c:139
RZ_API int rz_str_replace_char(char *s, int a, int b)
Definition: str.c:169
RZ_API RZ_OWN char * rz_strbuf_drain(RzStrBuf *sb)
Definition: strbuf.c:342
RZ_API bool rz_strbuf_append(RzStrBuf *sb, const char *s)
Definition: strbuf.c:222
RZ_API RzStrBuf * rz_strbuf_new(const char *s)
Definition: strbuf.c:8
RZ_API bool rz_strbuf_appendf(RzStrBuf *sb, const char *fmt,...) RZ_PRINTF_CHECK(2
#define RZ_PERM_R
Definition: rz_types.h:93
#define RZ_NULLABLE
Definition: rz_types.h:65
#define RZ_OWN
Definition: rz_types.h:62
#define RZ_NEW0(x)
Definition: rz_types.h:284
#define RZ_NONNULL
Definition: rz_types.h:64
#define RZ_PERM_X
Definition: rz_types.h:95
#define RZ_NEWS0(x, y)
Definition: rz_types.h:282
#define RZ_FREE(x)
Definition: rz_types.h:369
#define PFMT64x
Definition: rz_types.h:393
#define RZ_BORROW
Definition: rz_types.h:63
#define st64
Definition: rz_types_base.h:10
#define UT64_MAX
Definition: rz_types_base.h:86
#define st32
Definition: rz_types_base.h:12
RZ_API int sdb_set(Sdb *s, const char *key, const char *val, ut32 cas)
Definition: sdb.c:611
static struct sockaddr static addrlen static backlog const void static flags void flags
Definition: sfsocketcall.h:123
#define b(i)
Definition: sha256.c:42
#define s0(x)
Definition: sha256.c:59
#define a(i)
Definition: sha256.c:41
#define s1(x)
Definition: sha256.c:60
Definition: malloc.c:26
AttributeType type
Attribute ** attributes
Definition: class_field.h:29
ut16 access_flags
Definition: class_field.h:25
ut16 descriptor_index
Definition: class_field.h:27
ut16 attributes_count
Definition: class_field.h:28
ut16 name_index
Definition: class_field.h:26
Attribute ** attributes
Definition: class_method.h:35
ut16 attributes_count
Definition: class_method.h:34
ut16 descriptor_index
Definition: class_method.h:33
Definition: z80asm.h:102
Definition: rz_pj.h:12
ut64 vaddr
Definition: rz_bin.h:186
ut64 paddr
Definition: rz_bin.h:187
ut64 flags
Definition: rz_bin.h:773
ut32 visibility
Definition: rz_bin.h:766
char * type
Definition: rz_bin.h:768
char * name
Definition: rz_bin.h:619
ut32 ordinal
Definition: rz_bin.h:755
char * string
Definition: rz_bin.h:752
const char * bind
Definition: rz_bin.h:681
char * visibility_str
Definition: rz_bin.h:686
bool is_imported
Definition: rz_bin.h:684
const char * type
Definition: rz_bin.h:682
char * name
Definition: rz_bin.h:675
char * classname
Definition: rz_bin.h:678
ut32 ordinal
Definition: rz_bin.h:692
char * dname
Definition: rz_bin.h:676
ut64 method_flags
Definition: rz_bin.h:696
ut32 visibility
Definition: rz_bin.h:693
char * libname
Definition: rz_bin.h:677
Definition: sdb.h:63
uint32_t size
static const char * resolve(struct Type *t, const char *foo, const char **bar)
Definition: swift.c:91
if(dbg->bits==RZ_SYS_BITS_64)
Definition: windows-arm64.h:4
ut64(WINAPI *w32_GetEnabledXStateFeatures)()
static int addr
Definition: z80asm.c:58
#define buffer_size(buffer)