static void print_name (FILE* stream, JCF* jcf, int name_index) { if (JPOOL_TAG (jcf, name_index) != CONSTANT_Utf8) fprintf (stream, "<not a UTF8 constant>"); else jcf_print_utf8 (stream, JPOOL_UTF_DATA (jcf,name_index), JPOOL_UTF_LENGTH (jcf, name_index)); }
static int utf8_equal_string (JCF *jcf, int index, const char * value) { if (CPOOL_INDEX_IN_RANGE (&jcf->cpool, index) && JPOOL_TAG (jcf, index) == CONSTANT_Utf8) { int len = strlen (value); if (JPOOL_UTF_LENGTH (jcf, index) == len && memcmp (JPOOL_UTF_DATA (jcf, index), value, len) == 0) return 1; } return 0; }
static void print_signature (FILE* stream, JCF *jcf, int signature_index, int options) { if (JPOOL_TAG (jcf, signature_index) != CONSTANT_Utf8) print_constant_terse (out, jcf, signature_index, CONSTANT_Utf8); else { const unsigned char *str = JPOOL_UTF_DATA (jcf, signature_index); int length = JPOOL_UTF_LENGTH (jcf, signature_index); const unsigned char *limit; limit = str + length; if (str >= limit) fprintf (stream, "<empty signature string>"); else { if (options & PRINT_SIGNATURE_RESULT_ONLY) { while (str < limit && *str++ != ')') ; } if (options & PRINT_SIGNATURE_ARGS_ONLY) { str++; fputc ('(', stream); while (str < limit && *str != ')') { print_signature_type (stream, &str, limit); if (*str != ')') fputs (", ", stream); } fputc (')', stream); } else { print_signature_type (stream, &str, limit); if (str < limit) { fprintf (stream, "<junk:"); jcf_print_utf8 (stream, str, limit - str); fputc ('>', stream); } } } } }
/* Go through all available attribute (ATTRIBUTE_NUMER) and try to identify PEEKED_NAME. Return 1 if PEEKED_NAME was found, 0 otherwise. JCF is restored to its initial position before returning. */ #ifdef NEED_PEEK_ATTRIBUTE /* Not everyone uses this function */ static int peek_attribute (JCF *jcf, int attribute_number, const char *peeked_name, int peeked_name_length) { int to_return = 0; long absolute_offset = (long)JCF_TELL (jcf); int i; for (i = 0; !to_return && i < attribute_number; i++) { uint16 attribute_name = (JCF_FILL (jcf, 6), JCF_readu2 (jcf)); uint32 attribute_length = JCF_readu4 (jcf); int name_length; const unsigned char *name_data; JCF_FILL (jcf, (long) attribute_length); if (attribute_name <= 0 || attribute_name >= JPOOL_SIZE(jcf) || JPOOL_TAG (jcf, attribute_name) != CONSTANT_Utf8) continue; name_length = JPOOL_UTF_LENGTH (jcf, attribute_name); name_data = JPOOL_UTF_DATA (jcf, attribute_name); if (name_length == peeked_name_length && ! memcmp (name_data, peeked_name, peeked_name_length)) { to_return = 1; break; } JCF_SKIP (jcf, attribute_length); } JCF_SEEK (jcf, absolute_offset); return to_return; }
static void print_constant (FILE *out, JCF *jcf, int index, int verbosity) { int j, n; jlong num; const char *str; int kind = JPOOL_TAG (jcf, index); switch (kind) { case CONSTANT_Class: n = JPOOL_USHORT1 (jcf, index); if (verbosity > 0) { if (verbosity > 1) fprintf (out, "Class name: %d=", n); else fprintf (out, "Class "); } if (! CPOOL_INDEX_IN_RANGE (&jcf->cpool, n)) fprintf (out, "<out of range>"); else if (verbosity < 2 && JPOOL_TAG (jcf, n) == CONSTANT_Utf8) { int len = JPOOL_UTF_LENGTH (jcf, n); jcf_print_utf8_replace (out, JPOOL_UTF_DATA(jcf,n), len, '/', '.'); } else print_constant_terse (out, jcf, n, CONSTANT_Utf8); break; case CONSTANT_Fieldref: str = "Field"; goto field_or_method; case CONSTANT_Methodref: str = "Method"; goto field_or_method; case CONSTANT_InterfaceMethodref: str = "InterfaceMethod"; goto field_or_method; field_or_method: { uint16 tclass = JPOOL_USHORT1 (jcf, index); uint16 name_and_type = JPOOL_USHORT2 (jcf, index); if (verbosity == 2) fprintf (out, "%sref class: %d=", str, tclass); else if (verbosity > 0) fprintf (out, "%s ", str); print_constant_terse (out, jcf, tclass, CONSTANT_Class); if (verbosity < 2) fprintf (out, "."); else fprintf (out, " name_and_type: %d=<", name_and_type); print_constant_terse (out, jcf, name_and_type, CONSTANT_NameAndType); if (verbosity == 2) fputc ('>', out); } break; case CONSTANT_String: j = JPOOL_USHORT1 (jcf, index); if (verbosity > 0) { if (verbosity > 1) fprintf (out, "String %d=", j); else fprintf (out, "String "); } print_constant_terse (out, jcf, j, CONSTANT_Utf8); break; case CONSTANT_Integer: if (verbosity > 0) fprintf (out, "Integer "); num = JPOOL_INT (jcf, index); goto integer; case CONSTANT_Long: if (verbosity > 0) fprintf (out, "Long "); num = JPOOL_LONG (jcf, index); goto integer; integer: { char buffer[25]; format_int (buffer, num, 10); fprintf (out, "%s", buffer); if (verbosity > 1) { format_uint (buffer, (uint64)num, 16); fprintf (out, "=0x%s", buffer); } } break; case CONSTANT_Float: { jfloat fnum = JPOOL_FLOAT (jcf, index); if (verbosity > 0) fputs ("Float ", out); if (fnum.negative) putc ('-', out); if (JFLOAT_FINITE (fnum)) { int dummy; int exponent = fnum.exponent - JFLOAT_EXP_BIAS; double f; uint32 mantissa = fnum.mantissa; if (fnum.exponent == 0) /* Denormal. */ exponent++; else /* Normal; add the implicit bit. */ mantissa |= ((uint32)1 << 23); f = frexp (mantissa, &dummy); f = ldexp (f, exponent + 1); fprintf (out, "%.10g", f); } else { if (fnum.mantissa == 0) fputs ("Inf", out); else if (fnum.mantissa & JFLOAT_QNAN_MASK) fprintf (out, "QNaN(%u)", (fnum.mantissa & ~JFLOAT_QNAN_MASK)); else fprintf (out, "SNaN(%u)", (fnum.mantissa & ~JFLOAT_QNAN_MASK)); } if (verbosity > 1) fprintf (out, ", bits = 0x%08lx", (long) JPOOL_UINT (jcf, index)); break; } case CONSTANT_Double: { jdouble dnum = JPOOL_DOUBLE (jcf, index); if (verbosity > 0) fputs ("Double ", out); if (dnum.negative) putc ('-', out); if (JDOUBLE_FINITE (dnum)) { int dummy; int exponent = dnum.exponent - JDOUBLE_EXP_BIAS; double d; uint64 mantissa = ((((uint64) dnum.mantissa0) << 32) + dnum.mantissa1); if (dnum.exponent == 0) /* Denormal. */ exponent++; else /* Normal; add the implicit bit. */ mantissa |= ((uint64)1 << 52); d = frexp (mantissa, &dummy); d = ldexp (d, exponent + 1); fprintf (out, "%.20g", d); } else { uint64 mantissa = dnum.mantissa0 & ~JDOUBLE_QNAN_MASK; mantissa = (mantissa << 32) + dnum.mantissa1; if (dnum.mantissa0 == 0 && dnum.mantissa1 == 0) fputs ("Inf", out); else if (dnum.mantissa0 & JDOUBLE_QNAN_MASK) fprintf (out, "QNaN(%llu)", (unsigned long long)mantissa); else fprintf (out, "SNaN(%llu)", (unsigned long long)mantissa); } if (verbosity > 1) { int32 hi, lo; hi = JPOOL_UINT (jcf, index); lo = JPOOL_UINT (jcf, index + 1); fprintf (out, ", bits = 0x%08lx%08lx", (long) hi, (long) lo); } break; } case CONSTANT_NameAndType: { uint16 name = JPOOL_USHORT1 (jcf, index); uint16 sig = JPOOL_USHORT2 (jcf, index); if (verbosity > 0) { if (verbosity > 1) fprintf (out, "NameAndType name: %d=", name); else fprintf (out, "NameAndType "); } print_name (out, jcf, name); if (verbosity <= 1) fputc (' ', out); else fprintf (out, ", signature: %d=", sig); print_signature (out, jcf, sig, 0); } break; case CONSTANT_Utf8: { const unsigned char *str = JPOOL_UTF_DATA (jcf, index); int length = JPOOL_UTF_LENGTH (jcf, index); if (verbosity > 0) { /* Print as 8-bit bytes. */ fputs ("Utf8: \"", out); while (--length >= 0) jcf_print_char (out, *str++); } else { /* Print as Unicode. */ fputc ('\"', out); jcf_print_utf8 (out, str, length); } fputc ('\"', out); } break; default: fprintf (out, "(Unknown constant type %d)", kind); } }
static int get_attribute (JCF *jcf, int index, jv_attr_type attr_type ATTRIBUTE_UNUSED) { uint16 attribute_name = (JCF_FILL (jcf, 6), JCF_readu2 (jcf)); uint32 attribute_length = JCF_readu4 (jcf); uint32 start_pos = JCF_TELL(jcf); int name_length; const unsigned char *name_data; JCF_FILL (jcf, (long) attribute_length); if (attribute_name <= 0 || attribute_name >= JPOOL_SIZE(jcf)) return -2; if (JPOOL_TAG (jcf, attribute_name) != CONSTANT_Utf8) return -2; name_length = JPOOL_UTF_LENGTH (jcf, attribute_name); name_data = JPOOL_UTF_DATA (jcf, attribute_name); #define MATCH_ATTRIBUTE(S) \ (name_length == sizeof (S)-1 && memcmp (name_data, S, sizeof (S)-1) == 0) #ifdef IGNORE_ATTRIBUTE if (IGNORE_ATTRIBUTE (jcf, attribute_name, attribute_length)) { JCF_SKIP (jcf, attribute_length); } else #endif #ifdef HANDLE_SOURCEFILE if (MATCH_ATTRIBUTE ("SourceFile")) { uint16 sourcefile_index = JCF_readu2 (jcf); HANDLE_SOURCEFILE(sourcefile_index); } else #endif #ifdef HANDLE_CONSTANTVALUE if (MATCH_ATTRIBUTE ("ConstantValue")) { uint16 constantvalue_index = JCF_readu2 (jcf); if (constantvalue_index <= 0 || constantvalue_index >= JPOOL_SIZE(jcf)) return -2; HANDLE_CONSTANTVALUE(constantvalue_index); } else #endif #ifdef HANDLE_CODE_ATTRIBUTE if (MATCH_ATTRIBUTE ("Code")) { uint16 j; uint16 max_stack ATTRIBUTE_UNUSED = JCF_readu2 (jcf); uint16 max_locals ATTRIBUTE_UNUSED = JCF_readu2 (jcf); uint32 code_length = JCF_readu4 (jcf); uint16 exception_table_length, attributes_count; if (code_length + 12 > attribute_length) return -1; HANDLE_CODE_ATTRIBUTE(max_stack, max_locals, code_length); JCF_SKIP (jcf, code_length); exception_table_length = JCF_readu2 (jcf); if (code_length + 8 * exception_table_length + 12 > attribute_length) return -1; #ifdef HANDLE_EXCEPTION_TABLE HANDLE_EXCEPTION_TABLE (jcf->read_ptr, exception_table_length); #endif JCF_SKIP (jcf, 2 * 4 * exception_table_length); attributes_count = JCF_readu2 (jcf); for (j = 0; j < attributes_count; j++) { int code = get_attribute (jcf, index, JV_METHOD_ATTR); if (code != 0) return code; } } else #endif /* HANDLE_CODE_ATTRIBUTE */ #ifdef HANDLE_EXCEPTIONS_ATTRIBUTE if (MATCH_ATTRIBUTE ("Exceptions")) { uint16 count = JCF_readu2 (jcf); HANDLE_EXCEPTIONS_ATTRIBUTE (count); } else #endif #ifdef HANDLE_LINENUMBERTABLE_ATTRIBUTE if (MATCH_ATTRIBUTE ("LineNumberTable")) { uint16 count = JCF_readu2 (jcf); HANDLE_LINENUMBERTABLE_ATTRIBUTE (count); } else #endif #ifdef HANDLE_LOCALVARIABLETABLE_ATTRIBUTE if (MATCH_ATTRIBUTE ("LocalVariableTable")) { uint16 count = JCF_readu2 (jcf); HANDLE_LOCALVARIABLETABLE_ATTRIBUTE (count); } else #endif #ifdef HANDLE_LOCALVARIABLETYPETABLE_ATTRIBUTE if (MATCH_ATTRIBUTE ("LocalVariableTypeTable")) { uint16 count = JCF_readu2 (jcf); HANDLE_LOCALVARIABLETYPETABLE_ATTRIBUTE (count); } else #endif #ifdef HANDLE_INNERCLASSES_ATTRIBUTE if (MATCH_ATTRIBUTE ("InnerClasses")) { uint16 count = JCF_readu2 (jcf); HANDLE_INNERCLASSES_ATTRIBUTE (count); } else #endif #ifdef HANDLE_SYNTHETIC_ATTRIBUTE if (MATCH_ATTRIBUTE ("Synthetic")) { HANDLE_SYNTHETIC_ATTRIBUTE (); } else #endif #ifdef HANDLE_GCJCOMPILED_ATTRIBUTE if (MATCH_ATTRIBUTE ("gnu.gcj.gcj-compiled")) { HANDLE_GCJCOMPILED_ATTRIBUTE (); } else #endif #ifdef HANDLE_DEPRECATED_ATTRIBUTE if (MATCH_ATTRIBUTE ("Deprecated")) { HANDLE_DEPRECATED_ATTRIBUTE (); } else #endif #ifdef HANDLE_SOURCEDEBUGEXTENSION_ATTRIBUTE if (MATCH_ATTRIBUTE ("SourceDebugExtension")) /* JSR 45 */ { HANDLE_SOURCEDEBUGEXTENSION_ATTRIBUTE (attribute_length); } else #endif #ifdef HANDLE_ENCLOSINGMETHOD_ATTRIBUTE if (MATCH_ATTRIBUTE ("EnclosingMethod")) { HANDLE_ENCLOSINGMETHOD_ATTRIBUTE (); } else #endif #ifdef HANDLE_SIGNATURE_ATTRIBUTE if (MATCH_ATTRIBUTE ("Signature")) { HANDLE_SIGNATURE_ATTRIBUTE (); } else #endif #ifdef HANDLE_RUNTIMEVISIBLEANNOTATIONS_ATTRIBUTE if (MATCH_ATTRIBUTE ("RuntimeVisibleAnnotations")) { HANDLE_RUNTIMEVISIBLEANNOTATIONS_ATTRIBUTE (); } else #endif #ifdef HANDLE_RUNTIMEINVISIBLEANNOTATIONS_ATTRIBUTE if (MATCH_ATTRIBUTE ("RuntimeInvisibleAnnotations")) { HANDLE_RUNTIMEINVISIBLEANNOTATIONS_ATTRIBUTE (); } else #endif #ifdef HANDLE_RUNTIMEVISIBLEPARAMETERANNOTATIONS_ATTRIBUTE if (MATCH_ATTRIBUTE ("RuntimeVisibleParameterAnnotations")) { HANDLE_RUNTIMEVISIBLEPARAMETERANNOTATIONS_ATTRIBUTE (); } else #endif #ifdef HANDLE_RUNTIMEINVISIBLEPARAMETERANNOTATIONS_ATTRIBUTE if (MATCH_ATTRIBUTE ("RuntimeInvisibleParameterAnnotations")) { HANDLE_RUNTIMEINVISIBLEPARAMETERANNOTATIONS_ATTRIBUTE (); } else #endif #ifdef HANDLE_ANNOTATIONDEFAULT_ATTRIBUTE if (MATCH_ATTRIBUTE ("AnnotationDefault")) { HANDLE_ANNOTATIONDEFAULT_ATTRIBUTE (); } else #endif if (MATCH_ATTRIBUTE ("BootstrapMethods")) { #ifdef HANDLE_BOOTSTRAP_METHODS_ATTRIBUTE HANDLE_BOOTSTRAP_METHODS_ATTRIBUTE(); #else JCF_SKIP (jcf, attribute_length); #endif } else { #ifdef PROCESS_OTHER_ATTRIBUTE PROCESS_OTHER_ATTRIBUTE(jcf, attribute_name, attribute_length); #else JCF_SKIP (jcf, attribute_length); #endif } if ((long) (start_pos + attribute_length) != JCF_TELL(jcf)) return -1; return 0; }
static int get_attribute (JCF *jcf) { uint16 attribute_name = (JCF_FILL (jcf, 6), JCF_readu2 (jcf)); uint32 attribute_length = JCF_readu4 (jcf); uint32 start_pos = JCF_TELL(jcf); int name_length; const unsigned char *name_data; JCF_FILL (jcf, (long) attribute_length); if (attribute_name <= 0 || attribute_name >= JPOOL_SIZE(jcf)) return -2; if (JPOOL_TAG (jcf, attribute_name) != CONSTANT_Utf8) return -2; name_length = JPOOL_UTF_LENGTH (jcf, attribute_name); name_data = JPOOL_UTF_DATA (jcf, attribute_name); #define MATCH_ATTRIBUTE(S) \ (name_length == sizeof (S)-1 && memcmp (name_data, S, sizeof (S)-1) == 0) #ifdef IGNORE_ATTRIBUTE if (IGNORE_ATTRIBUTE (jcf, attribute_name, attribute_length)) { JCF_SKIP (jcf, attribute_length); } else #endif #ifdef HANDLE_SOURCEFILE if (MATCH_ATTRIBUTE ("SourceFile")) { uint16 sourcefile_index = JCF_readu2 (jcf); HANDLE_SOURCEFILE(sourcefile_index); } else #endif #ifdef HANDLE_CONSTANTVALUE if (MATCH_ATTRIBUTE ("ConstantValue")) { uint16 constantvalue_index = JCF_readu2 (jcf); if (constantvalue_index <= 0 || constantvalue_index >= JPOOL_SIZE(jcf)) return -2; HANDLE_CONSTANTVALUE(constantvalue_index); } else #endif #ifdef HANDLE_CODE_ATTRIBUTE if (MATCH_ATTRIBUTE ("Code")) { uint16 j; uint16 max_stack ATTRIBUTE_UNUSED = JCF_readu2 (jcf); uint16 max_locals ATTRIBUTE_UNUSED = JCF_readu2 (jcf); uint32 code_length = JCF_readu4 (jcf); uint16 exception_table_length, attributes_count; if (code_length + 12 > attribute_length) return -1; HANDLE_CODE_ATTRIBUTE(max_stack, max_locals, code_length); JCF_SKIP (jcf, code_length); exception_table_length = JCF_readu2 (jcf); if (code_length + 8 * exception_table_length + 12 > attribute_length) return -1; #ifdef HANDLE_EXCEPTION_TABLE HANDLE_EXCEPTION_TABLE (jcf->read_ptr, exception_table_length); #endif JCF_SKIP (jcf, 2 * 4 * exception_table_length); attributes_count = JCF_readu2 (jcf); for (j = 0; j < attributes_count; j++) { int code = get_attribute (jcf); if (code != 0) return code; } } else #endif /* HANDLE_CODE_ATTRIBUTE */ #ifdef HANDLE_EXCEPTIONS_ATTRIBUTE if (MATCH_ATTRIBUTE ("Exceptions")) { uint16 count = JCF_readu2 (jcf); HANDLE_EXCEPTIONS_ATTRIBUTE (count); } else #endif #ifdef HANDLE_LINENUMBERTABLE_ATTRIBUTE if (MATCH_ATTRIBUTE ("LineNumberTable")) { uint16 count = JCF_readu2 (jcf); HANDLE_LINENUMBERTABLE_ATTRIBUTE (count); } else #endif #ifdef HANDLE_LOCALVARIABLETABLE_ATTRIBUTE if (MATCH_ATTRIBUTE ("LocalVariableTable")) { uint16 count = JCF_readu2 (jcf); HANDLE_LOCALVARIABLETABLE_ATTRIBUTE (count); } else #endif #ifdef HANDLE_INNERCLASSES_ATTRIBUTE if (MATCH_ATTRIBUTE ("InnerClasses")) { uint16 count = JCF_readu2 (jcf); HANDLE_INNERCLASSES_ATTRIBUTE (count); } else #endif #ifdef HANDLE_SYNTHETIC_ATTRIBUTE if (MATCH_ATTRIBUTE ("Synthetic")) { HANDLE_SYNTHETIC_ATTRIBUTE (); } else #endif #ifdef HANDLE_GCJCOMPILED_ATTRIBUTE if (MATCH_ATTRIBUTE ("gnu.gcj.gcj-compiled")) { HANDLE_GCJCOMPILED_ATTRIBUTE (); } else #endif #ifdef HANDLE_DEPRECATED_ATTRIBUTE if (MATCH_ATTRIBUTE ("Deprecated")) { HANDLE_DEPRECATED_ATTRIBUTE (); } else #endif { #ifdef PROCESS_OTHER_ATTRIBUTE PROCESS_OTHER_ATTRIBUTE(jcf, attribute_name, attribute_length); #else JCF_SKIP (jcf, attribute_length); #endif } if ((long) (start_pos + attribute_length) != JCF_TELL(jcf)) return -1; return 0; }