Logo Search packages:      
Sourcecode: jclassinfo version File versions  Download package

attributes.c

/*
 * jclassinfo
 * Copyright (C) 2003  Nicos Panayides
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *
 * Nicos Panayides
 * anarxia@gmx.net
 *
 * $Id: attributes.c,v 1.7 2003/10/27 01:59:16 anarxia Exp $
 */

#include "config.h"
#include <stdlib.h>
#include <string.h>
#include <jclass/jclass.h>
#include "attributes.h"
#include "common.h"

void attribute_container_print(const AttributeContainer* attribute, 
      IntType int_type, int do_flag, const ConstantPool* constant_pool)
{
      int j;
      char* attr_name;
            
      if(attribute == NULL)
            return;
            
      attr_name = jclass_cp_get_constant_value(constant_pool, attribute->name_index, INT_IS_INT);
      
      if(attr_name == NULL)
            return;
      
      /* Covers Synthetic and deprecated */
      if(attribute->length == 0)
      {
            printf("[%s]", attr_name);
            free(attr_name);
            return;
      }
            
      if(!strcmp("SourceFile", attr_name))
      {
            SourceFileAttribute* sourcefile;
            sourcefile = jclass_sourcefile_attribute_new(attribute);
            sourcefile_attribute_print(sourcefile, constant_pool);
            jclass_sourcefile_attribute_free(sourcefile);
      }
      else if(!strcmp("InnerClasses", attr_name))
      {
            InnerClassesAttribute* innerclasses;
            innerclasses = jclass_innerclasses_attribute_new(attribute);
            innerclasses_attribute_print(innerclasses, constant_pool);
            jclass_innerclasses_attribute_free(innerclasses);
      }
      else if(!strcmp("ConstantValue", attr_name))
      {
            ConstantValueAttribute* constantvalue;
            constantvalue = jclass_constantvalue_attribute_new(attribute);
            constantvalue_attribute_print(constantvalue, int_type, constant_pool);
            jclass_constantvalue_attribute_free(constantvalue);
      }
      else if(!strcmp("Exceptions", attr_name))
      {
            ExceptionsAttribute* exceptions;
            exceptions = jclass_exceptions_attribute_new(attribute);
            exceptions_attribute_print(exceptions, constant_pool);
            jclass_exceptions_attribute_free(exceptions);
      }
      else if(!strcmp("Code", attr_name))
      {
            if(do_flag & (DISASM |METHOD_DEBUG_INFO|VERBOSE))
            {
                  CodeAttribute* code;
                  code = jclass_code_attribute_new(attribute);
                  code_attribute_print(code, do_flag, constant_pool);
                  jclass_code_attribute_free(code);
            }
      }
      else
      {
            printf("\n%s %u bytes, contents =", attr_name, attribute->length);
            for(j=0; j < attribute->length; j++)
                  printf(" %02X", attribute->contents[j]);
      }
      
      free(attr_name);
}

void constantvalue_attribute_print(const ConstantValueAttribute* attrib, 
      IntType int_type, const ConstantPool* constant_pool)
{
      char* cp_string;
            
      cp_string = jclass_cp_get_constant_value(constant_pool, 
                        attrib->cp_index, int_type);
            
      printf("= %s", cp_string);
      free(cp_string);
}

void sourcefile_attribute_print(const SourceFileAttribute* attrib,
      const ConstantPool* constant_pool)
{
      char* cp_string;
      
      cp_string = jclass_cp_get_constant_value(constant_pool,
            attrib->filename_index, INT_IS_INT);
            
      printf("Compiled from %s", cp_string);
      free(cp_string);
}

void exceptions_attribute_print(const ExceptionsAttribute* exceptions, 
      const ConstantPool* constant_pool)
{
      char* exception_name;
      int j;
      
      printf("throws");
      if (exceptions->no_exceptions > 0)
      {
            exception_name = jclass_cp_get_class_name(constant_pool, exceptions->exception_index[0], 0);
            printf(" %s", exception_name);
            free(exception_name);
      }
      
      for(j = 1; j < exceptions->no_exceptions; j++)
      {
            exception_name = jclass_cp_get_class_name(constant_pool, exceptions->exception_index[j], 0);
            printf(", %s", exception_name);
            free(exception_name);
      }
}

void innerclasses_attribute_print(const InnerClassesAttribute* attrib, 
      const ConstantPool* constant_pool)
{     
      uint16_t j;
      uint16_t name_index;
      
      char* innerclass_name;
      char* outerclass_name;
      char* innerclass_type;
      char* innerclass_access;
      
      printf("\nInner classes:");
            
      for(j = 0; j < attrib->no_innerclasses; j++)
      {
            if(attrib->classes[j].type_index)
            {
                  innerclass_access = jclass_access_flag_to_string(attrib->classes[j].access_flags, 1);
                  
                  name_index = attrib->classes[j].name_index;
                  
                  if(name_index)
                  {
                        innerclass_name = jclass_utf8_to_string(constant_pool->entries[name_index].info.utf8->contents,
                                                                                    constant_pool->entries[name_index].info.utf8->length);
                  }
                  else
                        innerclass_name = NULL;
                  
                        innerclass_type = jclass_cp_get_class_name(constant_pool, 
                                                                                    attrib->classes[j].type_index, 0);
                  
                        
                  printf("\n\t%s", innerclass_access);
                  free(innerclass_access);      
                        
                  if(innerclass_type != NULL)
                  {
                        printf(" %s", innerclass_type);
                        free(innerclass_type);  
                  }
                        
                  if (innerclass_name != NULL)
                  {
                        printf(" %s", innerclass_name);
                        free(innerclass_name);
                  }
                        
                  if(attrib->classes[j].outer_class_type_index)
                  {
                        outerclass_name = jclass_cp_get_class_name(constant_pool, 
                                                                  attrib->classes[j].outer_class_type_index, 0);
                        if (outerclass_name != NULL)
                        {
                              printf(" member of %s", outerclass_name);
                              free(outerclass_name);
                        }
                  }
            }
      }
      puts("");
}

void code_attribute_print(const CodeAttribute* code, int do_flag, 
      const ConstantPool* constant_pool)
{
      uint32_t pc;
      uint32_t instruction_pc;
      int is_wide;
      int i;
      
      int32_t s4op;
      uint16_t u2op;
      int32_t count;
      uint16_t exception_counter;
      uint16_t attribute_counter;
      char* class_name;
      LineNumberAttribute* linenumbertable;
      LocalVariableAttribute* localvariabletable;
      TableSwitchOperand* tableswitch;
      LookupSwitchOperand* lookupswitch;
      
      if(do_flag & VERBOSE)
      {
            printf("\n\tMax Stack: %d, Max Locals: %d\n", 
                                                            code->max_stack, code->max_locals);
      }
      
      pc = 0;
      is_wide = 0;
      
      if(do_flag & DISASM)
      {
            puts("{");
            while(pc < code->code_length)
            {
                  /* skip illegal opcodes */
                  do{
                        instruction_pc = pc;
                        pc++;
                  }while(code->code[instruction_pc] > MAX_LEGAL_OPCODE);
                  
                  if(jclass_code_instruction_op_type(code->code[instruction_pc], 0, is_wide) == OP_TYPE_INSTRUCTION)
                  {
                        printf("\t%u wide ", instruction_pc);
                        is_wide = 1;
                        instruction_pc = pc;
                        pc++;
                  }
                  else
                  {
                        is_wide = 0;
                        printf("\t%u ", instruction_pc);
                  }
                  
                  printf("%s", jclass_code_instruction_name(code->code[instruction_pc]));
                  
                  for(i = 0; i < jclass_code_instruction_ops(code->code[instruction_pc]); i++)
                  {
                        switch(jclass_code_instruction_op_type(code->code[instruction_pc], i, is_wide))
                        {
                              case OP_TYPE_INSTRUCTION:
                                    fputs("Wide cannot follow another wide.\n", stderr);
                                    pc++;
                                    break;
                        
                              case OP_TYPE_UNSIGNED_BYTE_USELESS:
                              case OP_TYPE_ERROR:
                                    pc++;
                              case OP_TYPE_NONE:
                                    break;
                              
                              case OP_TYPE_BYTE_ARRAY_TYPE:
                                    printf(" %s", jclass_code_array_name(jclass_code_read_ubyte(code->code, &pc)));
                                    break;
                              
                              case OP_TYPE_BYTE_CONSTANT_INDEX:
                                    class_name = jclass_cp_get_constant_value(constant_pool, code->code[pc], INT_IS_INT);
                                    if(jclass_cp_get_entry_type(constant_pool, code->code[pc]) == CONSTANT_String)
                                          printf(" \"%s\"", class_name);
                                    else
                                          printf(" %s", class_name);
                                    free(class_name);
                                    pc++;
                                    break;
                              
                              case OP_TYPE_BYTE:
                                    printf(" %d", jclass_code_read_byte(code->code, &pc));
                                    break;
                              
                              case OP_TYPE_UNSIGNED_BYTE:
                                    printf(" %u", jclass_code_read_ubyte(code->code, &pc));
                                    break;
                              
                              case OP_TYPE_SHORT:
                                    printf(" %d", jclass_code_read_short(code->code, &pc));
                                    break;
                        
                              case OP_TYPE_UNSIGNED_SHORT:
                                    printf(" %u", jclass_code_read_ushort(code->code, &pc));
                                    break;
                        
                              case OP_TYPE_SHORT_OFFSET:
                                    printf(" %u", (instruction_pc + jclass_code_read_short(code->code, &pc)));
                                    break;                        
                        
                              case OP_TYPE_INT:
                              case OP_TYPE_INT_OFFSET:
                                    s4op = jclass_code_read_int(code->code, &pc);
                                    if(jclass_code_instruction_op_type(code->code[instruction_pc], i, is_wide) == OP_TYPE_INT_OFFSET)
                                          s4op += instruction_pc;
                                                            
                                    printf(" %d", s4op);
                                    break;
                                    
                              case OP_TYPE_SHORT_METHOD_INDEX:
                              case OP_TYPE_SHORT_FIELD_INDEX:
                                    u2op = jclass_code_read_ushort(code->code, &pc);
                                    class_name = jclass_cp_get_method_signature(constant_pool, u2op, 0);
                                    printf(" %s", class_name);
                                    free(class_name);
                                    break;
                        
                              case OP_TYPE_SHORT_CLASS_INDEX:
                                    u2op = jclass_code_read_ushort(code->code, &pc);
                                    class_name = jclass_cp_get_class_name(constant_pool, u2op, 0);
                                    printf(" %s", class_name);
                                    free(class_name);
                                    break;
                        
                              case OP_TYPE_SHORT_CONSTANT_INDEX:
                                    u2op = jclass_code_read_ushort(code->code, &pc);
                                    class_name = jclass_cp_get_constant_value(constant_pool, u2op, INT_IS_SHORT);
                                    if(jclass_cp_get_entry_type(constant_pool, u2op) == CONSTANT_String)
                                          printf(" \"%s\"", class_name);
                                    else
                                          printf(" %s", class_name);
                                    free(class_name);
                                    break;
                        
                              case OP_TYPE_TABLESWITCH:
                                    tableswitch = jclass_code_read_tableswitch(code->code, &pc);
                                    
                                    for(count = 0; count < tableswitch->num_pairs; count++)
                                    {
                                          printf("\n\t    %d: %u", 
                                                count + tableswitch->low_value, tableswitch->target[count]);
                                    }
                                    printf("\n\t    default: %u", tableswitch->default_target);
                                    
                                    jclass_code_tableswitch_operand_free(tableswitch);
                                    break;
                        
                              case OP_TYPE_LOOKUPSWITCH:
                                    lookupswitch= jclass_code_read_lookupswitch(code->code, &pc);

                                    for(count = 0; count < lookupswitch->num_pairs; count ++)
                                    {
                                          printf("\n\t    %d: %u", 
                                                lookupswitch->value[count], lookupswitch->target[count]);
                                    }
                                    
                                    printf("\n\t    default: %u", lookupswitch->default_target);      
                                    jclass_code_lookupswitch_operand_free(lookupswitch);
                                    break;
                        }
                  }
                  puts("");
                  
            }           
            puts("}");
      }
      
      if((code->exception_table != NULL) && (do_flag & VERBOSE))
      {
            puts("\tException table:");
            puts("\tfrom\tto\ttarget\ttype");
            for(exception_counter = 0; exception_counter < code->exception_table_length; exception_counter++)
            {
                  printf("\t%d   ", code->exception_table[exception_counter].start_pc);
                  printf("\t%d", code->exception_table[exception_counter].end_pc);
                  printf("\t%d", code->exception_table[exception_counter].handler_pc);
                  
                  if(code->exception_table[exception_counter].catch_type)
                  {
                        class_name = jclass_cp_get_class_name(constant_pool, 
                              code->exception_table[exception_counter].catch_type, 0);
                        
                        printf("\t%s\n", class_name);
                        free(class_name);
                  }
                  else
                        puts("\tany");
            }
      }
      
      if(code->attributes_count && (do_flag & METHOD_DEBUG_INFO))
      {
            for(attribute_counter = 0; attribute_counter < code->attributes_count; attribute_counter++)
            {
                  if(jclass_attribute_container_has_attribute(&code->attributes[attribute_counter], "LineNumberTable", constant_pool))
                  {
                        linenumbertable = jclass_linenumber_attribute_new(&code->attributes[attribute_counter]);
                        linenumber_attribute_print(linenumbertable);
                        jclass_linenumber_attribute_free(linenumbertable);
                  }
                  else if(jclass_attribute_container_has_attribute(&code->attributes[attribute_counter], "LocalVariableTable", constant_pool ))
                  {
                        localvariabletable = jclass_localvariable_attribute_new(&code->attributes[attribute_counter]);
                        localvariable_attribute_print(localvariabletable, constant_pool);
                        jclass_localvariable_attribute_free(localvariabletable);
                  }
            }
      }
}

void localvariable_attribute_print(const LocalVariableAttribute* localvariabletable, 
      const ConstantPool* constant_pool)
{
      uint16_t counter;
      char* short_name;
      char* type;
      char* type_string;
      
      if(localvariabletable->length)
            puts("\n\tLocal variables:");
      
      for(counter = 0; counter < localvariabletable->length; counter++)
      {
            type_string = jclass_utf8_to_string(
                  constant_pool->entries[localvariabletable->localvariable[counter].descriptor_index].info.utf8->contents,
                  constant_pool->entries[localvariabletable->localvariable[counter].descriptor_index].info.utf8->length);
            
            type = jclass_descriptor_get_type(type_string);
            free(type_string);
            
            short_name = jclass_utf8_to_string(
                  constant_pool->entries[localvariabletable->localvariable[counter].name_index].info.utf8->contents,
                  constant_pool->entries[localvariabletable->localvariable[counter].name_index].info.utf8->length);
            
            printf("\t%d) %s %s (PC=%d, length=%d)\n",
                  localvariabletable->localvariable[counter].index,
                  type,
                  short_name,
                  localvariabletable->localvariable[counter].start_pc, 
                  localvariabletable->localvariable[counter].length);
            
            free(type);
            free(short_name);
      }
}

void linenumber_attribute_print(const LineNumberAttribute* linenumbertable)
{
      uint16_t counter;
      
      if(linenumbertable->length)
            puts("\n\tLine numbers:");
      
      for(counter = 0; counter < linenumbertable->length; counter++)
      {
            printf("\tline %d: %d\n", 
                  linenumbertable->line_number[counter].line_number, 
                  linenumbertable->line_number[counter].start_pc);
      }
}

Generated by  Doxygen 1.6.0   Back to index