Beispiel #1
0
/* 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;
}
#endif

#ifdef NEED_SKIP_ATTRIBUTE	/* Not everyone uses this function */
static void
skip_attribute (JCF *jcf, int number_of_attribute)
{
  while (number_of_attribute--)
    {
      JCF_u4 N;
      JCF_FILL (jcf, 6);
      (void) JCF_readu2 (jcf);
      N = JCF_readu4 (jcf);
      JCF_SKIP (jcf, N);
    }
}
Beispiel #2
0
/* 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;
}
Beispiel #3
0
int
main (int argc, char** argv)
{
  JCF jcf[1];
  int argi, opt;

  /* Unlock the stdio streams.  */
  unlock_std_streams ();

  gcc_init_libintl ();

  if (argc <= 1)
    {
      fprintf (stderr, _("jcf-dump: no classes specified\n"));
      usage ();
    }

  jcf_path_init ();

  /* We use getopt_long_only to allow single `-' long options.  For
     some of our options this is more natural.  */
  while ((opt = getopt_long_only (argc, argv, "o:I:vc", options, NULL)) != -1)
    {
      switch (opt)
	{
	case 0:
	  /* Already handled.  */
	  break;

        case 'o':
	  output_file = optarg;
	  break;

	case 'I':
	  jcf_path_include_arg (optarg);
	  break;

	case 'v':
	  verbose++;
	  break;

	case 'c':
	  flag_disassemble_methods = 1;
	  break;

	case OPT_classpath:
	  jcf_path_classpath_arg (optarg);
	  break;

	case OPT_bootclasspath:
	  jcf_path_bootclasspath_arg (optarg);
	  break;

	case OPT_extdirs:
	  jcf_path_extdirs_arg (optarg);
	  break;

	case OPT_HELP:
	  help ();
	  break;

	case OPT_VERSION:
	  version ();
	  break;

	case OPT_JAVAP:
	  flag_javap_compatible++;
	  flag_print_constant_pool = 0;
	  flag_print_attributes = 0;
	  break;

	default:
	  usage ();
	}
    }

  if (verbose && ! flag_javap_compatible)
    flag_print_constant_pool = 1;

  if (optind == argc)
    {
      fprintf (stderr, _("jcf-dump: no classes specified\n"));
      usage ();
    }

  jcf_path_seal (verbose);

  if (flag_print_main)
    {
      flag_print_fields = 0;
      flag_print_methods = 0;
      flag_print_constant_pool = 0;
      flag_print_attributes = 0;
      flag_print_class_info = 0;
    }

  if (output_file)
    {
      out = fopen (output_file, "w");
      if (! out)
	{
	  fprintf (stderr, _("Cannot open '%s' for output.\n"), output_file);
	  return FATAL_EXIT_CODE;
	}
    }
  else
    out = stdout;

  if (optind >= argc)
    {
      fprintf (out, "Reading .class from <standard input>.\n");
      open_class ("<stdio>", jcf, 0, NULL);
      process_class (jcf);
    }
  else
    {
      for (argi = optind; argi < argc; argi++)
	{
	  char *arg = argv[argi];
	  const char *class_filename = find_class (arg, strlen (arg), jcf, 0);
	  if (class_filename == NULL)
	    class_filename = find_classfile (arg, jcf, NULL);
	  if (class_filename == NULL)
	    {
	      perror ("Could not find class");
	      return FATAL_EXIT_CODE;
	    }
	  JCF_FILL (jcf, 4);
	  if (GET_u4 (jcf->read_ptr) == ZIPMAGIC)
	    {
	      long compressed_size, member_size;
	      int compression_method, filename_length, extra_length;
	      int general_purpose_bits;
	      const char *filename;
	      int total_length;
	      if (flag_print_class_info)
		fprintf (out, "Reading classes from archive %s.\n",
			 class_filename);
	      for (;;)
		{
		  int skip = 0;
		  jcf_filbuf_t save_filbuf = jcf->filbuf;
		  long magic = JCF_readu4_le (jcf);
		  if (magic == 0x02014b50 || magic == 0x06054b50)
		    break;  /* got to central directory */
		  if (magic != 0x04034b50) /* ZIPMAGIC (little-endian) */
		    {
		      fprintf (stderr, _("bad format of .zip/.jar archive\n"));
		      return FATAL_EXIT_CODE;
		    }
		  JCF_FILL (jcf, 26);
		  JCF_SKIP (jcf, 2);
		  general_purpose_bits = JCF_readu2_le (jcf);
		  compression_method = JCF_readu2_le (jcf);
		  JCF_SKIP (jcf, 8);
		  compressed_size = JCF_readu4_le (jcf);
		  member_size = JCF_readu4_le (jcf);
		  filename_length = JCF_readu2_le (jcf);
		  extra_length = JCF_readu2_le (jcf);
		  total_length = filename_length + extra_length
		    + compressed_size;
		  if (jcf->read_end - jcf->read_ptr < total_length)
		    jcf_trim_old_input (jcf);
		  JCF_FILL (jcf, total_length);
		  filename = (const char *) jcf->read_ptr;
		  JCF_SKIP (jcf, filename_length);
		  JCF_SKIP (jcf, extra_length);
		  if (filename_length > 0
		      && filename[filename_length-1] == '/')
		    {
		      if (flag_print_class_info)
			fprintf (out, "[Skipping directory %.*s]\n",
				 filename_length, filename);
		      skip = 1;
		    }
		  else if (compression_method != 0)
		    {
		      if (flag_print_class_info)
			fprintf (out, "[Skipping compressed file %.*s]\n",
				 filename_length, filename);
		      skip = 1;
		    }
		  else if (member_size < 4
			   || GET_u4 (jcf->read_ptr) != 0xcafebabe)
		    {
		      if (flag_print_class_info)
			fprintf (out, "[Skipping non-.class member %.*s]\n",
				 filename_length, filename);
		      skip = 1;
		    }
		  else
		    {
		      if (flag_print_class_info)
			fprintf (out, "Reading class member: %.*s.\n",
				 filename_length, filename);
		    }
		  if (skip)
		    {
		      JCF_SKIP (jcf, compressed_size);
		    }
		  else
		    {
		      unsigned char *save_end;
		      jcf->filbuf = jcf_unexpected_eof;
		      save_end = jcf->read_end;
		      jcf->read_end = jcf->read_ptr + compressed_size;
		      process_class (jcf);
		      jcf->filbuf = save_filbuf;
		      jcf->read_end = save_end;
		    }
		}
	    }
	  else
	    {
	      if (flag_print_class_info)
		fprintf (out, "Reading .class from %s.\n", class_filename);
	      process_class (jcf);
	    }
	  JCF_FINISH(jcf);
	}
    }

  return SUCCESS_EXIT_CODE;
}
Beispiel #4
0
/* Read and handle the constant pool.

   Return 0 if OK.
   Return -2 if a bad cross-reference (index of other constant) was seen.
*/
static int
jcf_parse_constant_pool (JCF* jcf)
{
  int i, n;
  JPOOL_SIZE (jcf) = (JCF_FILL (jcf, 2), JCF_readu2 (jcf));
  jcf->cpool.tags = (uint8 *) ggc_alloc_atomic (JPOOL_SIZE (jcf));
  jcf->cpool.data = ggc_alloc_cpool_entry (sizeof (jword) * JPOOL_SIZE (jcf));
  jcf->cpool.tags[0] = 0;
#ifdef HANDLE_START_CONSTANT_POOL
  HANDLE_START_CONSTANT_POOL (JPOOL_SIZE (jcf));
#endif
  for (i = 1; i < (int) JPOOL_SIZE (jcf); i++)
    {
      int constant_kind;
       
      /* Make sure at least 9 bytes are available.  This is enough
	 for all fixed-sized constant pool entries (so we don't need many
	 more JCF_FILL calls below), but is is small enough that
	 we are guaranteed to not hit EOF (in a valid .class file). */
      JCF_FILL (jcf, 9);
      constant_kind = JCF_readu (jcf);
      jcf->cpool.tags[i] = constant_kind;
      switch (constant_kind)
	{
	case CONSTANT_String:
	case CONSTANT_Class:
	  jcf->cpool.data[i].w = JCF_readu2 (jcf);
	  break;
	case CONSTANT_Fieldref:
	case CONSTANT_Methodref:
	case CONSTANT_InterfaceMethodref:
	case CONSTANT_NameAndType:
	  jcf->cpool.data[i].w = JCF_readu2 (jcf);
	  jcf->cpool.data[i].w |= JCF_readu2 (jcf) << 16;
	  break;
	case CONSTANT_Integer:
	case CONSTANT_Float:
	  jcf->cpool.data[i].w = JCF_readu4 (jcf);
	  break;
	case CONSTANT_Long:
	case CONSTANT_Double:
	  jcf->cpool.data[i].w = JCF_readu4 (jcf);
	  i++; /* These take up two spots in the constant pool */
	  jcf->cpool.tags[i] = 0;
	  jcf->cpool.data[i].w = JCF_readu4 (jcf);
	  break;
	case CONSTANT_Utf8:
	  n = JCF_readu2 (jcf);
	  JCF_FILL (jcf, n);
#ifdef HANDLE_CONSTANT_Utf8
	  HANDLE_CONSTANT_Utf8(jcf, i, n);
#else
	  jcf->cpool.data[i].w = JCF_TELL(jcf) - 2;
	  JCF_SKIP (jcf, n);
#endif
	  break;
	case CONSTANT_MethodHandle:
	  jcf->cpool.data[i].w = JCF_readu (jcf);
	  jcf->cpool.data[i].w |= JCF_readu2 (jcf) << 16;
	  break;
	case CONSTANT_MethodType:
	  jcf->cpool.data[i].w = JCF_readu2 (jcf);
	  break;
	case CONSTANT_InvokeDynamic:
	  jcf->cpool.data[i].w = JCF_readu2 (jcf);
	  jcf->cpool.data[i].w |= JCF_readu2 (jcf) << 16;
	  break;
	default:
	  return i;
	}
    }
  return 0;
}
Beispiel #5
0
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;
}