702 lines
15 KiB
C
702 lines
15 KiB
C
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
|
*
|
|
* The contents of this file are subject to the Netscape Public
|
|
* License Version 1.1 (the "License"); you may not use this file
|
|
* except in compliance with the License. You may obtain a copy of
|
|
* the License at http://www.mozilla.org/NPL/
|
|
*
|
|
* Software distributed under the License is distributed on an "AS
|
|
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
|
|
* implied. See the License for the specific language governing
|
|
* rights and limitations under the License.
|
|
*
|
|
* The Original Code is mozilla.org code.
|
|
*
|
|
* The Initial Developer of the Original Code is Netscape
|
|
* Communications Corporation. Portions created by Netscape are
|
|
* Copyright (C) 1998 Netscape Communications Corporation. All
|
|
* Rights Reserved.
|
|
*
|
|
* Contributor(s):
|
|
*/
|
|
/********************************************************************
|
|
*
|
|
* classdump.h
|
|
*
|
|
* author: Patrick Dionisio
|
|
*
|
|
* purpose: Header file for classdump.c
|
|
*
|
|
********************************************************************/
|
|
|
|
|
|
/*Variables.*/
|
|
|
|
/*linked_list stores the index and the name of a string in
|
|
the constant_pool.*/
|
|
struct linked_list {
|
|
|
|
int index;
|
|
char name[255];
|
|
struct linked_list *next_ptr;
|
|
|
|
};
|
|
|
|
/********************************************************************
|
|
*
|
|
* function: void printTab(int i)
|
|
*
|
|
* purpose: Used for standout format. Prints out tabs
|
|
* in by the number of i.
|
|
*
|
|
*********************************************************************/
|
|
|
|
void printTab(int i)
|
|
{
|
|
int j;
|
|
|
|
for (j=0; j<i; j++ ) printf("\t");
|
|
|
|
}
|
|
|
|
/********************************************************************
|
|
*
|
|
* function: void printByte(int i)
|
|
*
|
|
* purpose: Prints out the byte from the integer passed.
|
|
*
|
|
*
|
|
*********************************************************************/
|
|
|
|
void printByte(int i)
|
|
{
|
|
putc(i,stdout);
|
|
}
|
|
|
|
/********************************************************************
|
|
*
|
|
* function: void printHex1(int i)
|
|
*
|
|
* purpose: Prints out the hexidecimal value of one byte.
|
|
*
|
|
*
|
|
*********************************************************************/
|
|
|
|
void printHex1(int i)
|
|
{
|
|
/*hex[] stores all hex values.*/
|
|
static char hex[] = { '0','1','2','3','4','5','6','7','8','9','a',
|
|
'b','c','d','e','f' };
|
|
|
|
/*Print our the byte.*/
|
|
printByte(hex[(i>>4)&15]);
|
|
printByte(hex[i&15]);
|
|
|
|
}
|
|
|
|
/********************************************************************
|
|
*
|
|
* function: void printHex2(int i)
|
|
*
|
|
* purpose: Prints out the hexidecimal value of two bytes.
|
|
*
|
|
*
|
|
*********************************************************************/
|
|
|
|
void printHex2(int i)
|
|
{
|
|
/*Print high-byte.*/
|
|
printHex1(i>>8);
|
|
|
|
/*Print low-byte.*/
|
|
printHex1(i&0xff);
|
|
}
|
|
|
|
/********************************************************************
|
|
*
|
|
* function: void printHex4(int i)
|
|
*
|
|
* purpose: Prints out the hexidecimal value of four bytes.
|
|
*
|
|
*
|
|
*********************************************************************/
|
|
|
|
void printHex4(int i)
|
|
{
|
|
/*Print out the first two bytes.*/
|
|
printHex2(i>>16);
|
|
|
|
/*Print out the next two bytes.*/
|
|
printHex2(i&0xffff);
|
|
}
|
|
|
|
/********************************************************************
|
|
*
|
|
* function: void printDec4(int i)
|
|
*
|
|
* purpose: Prints out the decimal value of four bytes.
|
|
*
|
|
*
|
|
*********************************************************************/
|
|
|
|
void printDec4(int i)
|
|
{
|
|
int k,j=1;
|
|
|
|
/*Check if i is negative. If it is, then print out a '-' and
|
|
make i positive.*/
|
|
if ( i < 0 )
|
|
{
|
|
putc('-',stdout);
|
|
i = -i;
|
|
}
|
|
|
|
/*Print out the bytes.*/
|
|
k = i;
|
|
while ( k /= 10 ) j *= 10;
|
|
while (j)
|
|
{
|
|
k = i/j;
|
|
printByte(k+'0');
|
|
i -= k*j;
|
|
j /= 10;
|
|
}
|
|
}
|
|
|
|
/********************************************************************
|
|
*
|
|
* function: void printDec2(int i)
|
|
*
|
|
* purpose: Prints out the decimal value of the two bytes.
|
|
*
|
|
*
|
|
*********************************************************************/
|
|
|
|
void printDec2(int i)
|
|
{
|
|
printDec4(i&0xffff);
|
|
}
|
|
|
|
/********************************************************************
|
|
*
|
|
* function: int printDec1(int i)
|
|
*
|
|
* purpose: Prints out the decimal value of the one byte.
|
|
*
|
|
*
|
|
*********************************************************************/
|
|
|
|
void printDec1(int i)
|
|
{
|
|
printDec4(i&0xff);
|
|
}
|
|
|
|
/********************************************************************
|
|
*
|
|
* function: char * getName(struct linked_list *first_ptr,int index)
|
|
*
|
|
* purpose: Returns the name stored in the given index from the
|
|
* constant_pool.
|
|
*
|
|
*********************************************************************/
|
|
|
|
char* getName(struct linked_list *first_ptr,int index)
|
|
{
|
|
/*The pointer to use in going through the linked list.*/
|
|
struct linked_list *current_ptr = NULL;
|
|
current_ptr = first_ptr;
|
|
|
|
/*Find the name in the list.*/
|
|
while ( current_ptr != NULL )
|
|
{
|
|
if ( (*current_ptr).index == index ) return (*current_ptr).name;
|
|
else current_ptr = (*current_ptr).next_ptr;
|
|
}
|
|
|
|
return "Error in getName";
|
|
|
|
}
|
|
|
|
/********************************************************************
|
|
*
|
|
* function: void freeList(struct linked_list *first_ptr)
|
|
*
|
|
* purpose: Frees up the allocated memory.
|
|
*
|
|
*
|
|
*********************************************************************/
|
|
|
|
void freeList(struct linked_list *first_ptr)
|
|
{
|
|
/*The pointer to use in going through the linked list.*/
|
|
struct linked_list *current_ptr = NULL;
|
|
current_ptr = first_ptr;
|
|
|
|
/*Go through and clean the list.*/
|
|
while ( first_ptr != NULL )
|
|
{
|
|
current_ptr = (*current_ptr).next_ptr;
|
|
free(first_ptr);
|
|
first_ptr = current_ptr;
|
|
}
|
|
}
|
|
|
|
/********************************************************************
|
|
*
|
|
* function: char* getBytecode(int i, FILE *input)
|
|
*
|
|
* purpose: Prints the bytecode value.
|
|
*
|
|
*
|
|
*********************************************************************/
|
|
|
|
void getBytecode(int i, FILE *input)
|
|
{
|
|
/*Local variables.*/
|
|
int nested[10];
|
|
int j,k,l,m,n,o;
|
|
int posn = 0; /*Index for nested.*/
|
|
int posf = 0; /*Current length of code.*/
|
|
|
|
/*Reference type table.*/
|
|
static char typ[256] = {
|
|
/* 0 1 2 3 4 5 6 7 8 9 a b c d e f */
|
|
/*0*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
/*1*/ 1, 2, 1, 2, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
|
|
/*2*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
/*3*/ 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,
|
|
/*4*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
/*5*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
/*6*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
/*7*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
/*8*/ 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
/*9*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 6, 6, 6, 6, 6, 6,
|
|
/*a*/ 6, 6, 6, 6, 6, 6, 6, 6, 6, 1, 7, 8, 0, 0, 0, 0,
|
|
/*b*/ 0, 0, 2, 2, 2, 2, 2, 2, 2, 9,10, 2, 0, 2, 0, 0,
|
|
/*c*/ 2, 2, 0, 0,11, 5, 2, 2, 3, 3, 0, 0, 0, 2, 0, 0,
|
|
/*d*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
/*e*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
|
/*f*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
|
|
|
|
|
l=posf;
|
|
j=posf+i;
|
|
posn++;
|
|
|
|
/*Print out bytecodes till the length has been reached.*/
|
|
while (posf<j)
|
|
{
|
|
printf("\n");
|
|
printTab(4);
|
|
nested[posn]=posf-l;
|
|
|
|
/*Get opcode.*/
|
|
k=getu1(input);
|
|
posf++;
|
|
|
|
/*Check if opcode is valid.*/
|
|
if (k>0xd2) k=0xd2;
|
|
|
|
|
|
/*Refer to the type table and print out the correct bytecode along
|
|
with any values.*/
|
|
switch (typ[k])
|
|
{
|
|
|
|
case 0:
|
|
printf(mnem[k]);
|
|
break;
|
|
|
|
case 1:
|
|
m=getu1(input);
|
|
printf(mnem[k]);
|
|
printf(" ");
|
|
printHex1(m);
|
|
posf++;
|
|
break;
|
|
|
|
case 2:
|
|
m=getu2(input);
|
|
printf(mnem[k]);
|
|
printf(" ");
|
|
printHex2(m);
|
|
posf = posf + 2;
|
|
break;
|
|
|
|
case 3:
|
|
m=getu4(input);
|
|
printf(mnem[k]);
|
|
printf(" ");
|
|
printHex4(m);
|
|
posf = posf + 4;
|
|
break;
|
|
|
|
case 4:
|
|
m=getu1(input);
|
|
n=getu1(input);
|
|
printf(mnem[k]);
|
|
printf(" ");
|
|
printHex1(m);
|
|
printf(",");
|
|
printHex1(n);
|
|
posf = posf + 2;
|
|
break;
|
|
|
|
case 5:
|
|
m=getu2(input);
|
|
n=getu1(input);
|
|
printf(mnem[k]);
|
|
printf(" ");
|
|
printHex2(m);
|
|
printf(",");
|
|
printHex1(n);
|
|
posf = posf + 3;
|
|
break;
|
|
|
|
case 6:
|
|
m=getu2(input);
|
|
printf(mnem[k]);
|
|
printf(" ");
|
|
printHex2(m+nested[posn]);
|
|
posf = posf + 2;
|
|
break;
|
|
|
|
case 7: /*Special case for tableswitch*/
|
|
|
|
/*Read and ignore padded bytes.*/
|
|
for (m=(nested[posn]&3)^3; m>0; m--)
|
|
{ getu1(input); posf++; }
|
|
|
|
m=getu4(input);
|
|
n=getu4(input);
|
|
o=getu4(input);
|
|
posf = posf + 12;
|
|
|
|
printf(mnem[k]);
|
|
printTab(1);
|
|
printHex4(m+nested[posn]);
|
|
printf(",");
|
|
printHex4(n);
|
|
printf(",");
|
|
printHex2(o);
|
|
posn++;
|
|
nested[posn]=n;
|
|
|
|
/*Print jump-offsets.*/
|
|
while (nested[posn] <= o)
|
|
{
|
|
m=getu4(input);
|
|
printf("\n");
|
|
printTab(6);
|
|
posf = posf + 4;
|
|
printHex4(m+nested[posn-1]);
|
|
nested[posn]++;
|
|
}
|
|
|
|
posn--;
|
|
printf("\n");
|
|
break;
|
|
|
|
case 8: /*Special case for lookupswitch. */
|
|
|
|
/*Read and ignore padded bytes.*/
|
|
for (m=(nested[posn]&3)^3; m>0; m--)
|
|
{ getu1(input); posf++; }
|
|
|
|
m=getu4(input);
|
|
n=getu4(input);
|
|
posf = posf + 8;
|
|
printf(mnem[k]);
|
|
printTab(1);
|
|
printHex4(m+nested[posn]);
|
|
printf(",");
|
|
printHex4(n);
|
|
printf("\n");
|
|
printTab(6);
|
|
posn++;
|
|
nested[posn]=0;
|
|
|
|
/*Print out offset pairs.*/
|
|
while (nested[posn] < n)
|
|
{
|
|
m=getu4(input);
|
|
o=getu4(input);
|
|
posf = posf + 8;
|
|
printHex4(m);
|
|
printf(" : ");
|
|
printHex4(o+nested[posn-1]);
|
|
nested[posn]++;
|
|
printf("\n");
|
|
printTab(6);
|
|
}
|
|
|
|
posn--;
|
|
printf("\n");
|
|
break;
|
|
|
|
case 9:
|
|
m=getu2(input);
|
|
n=getu1(input);
|
|
o=getu1(input);
|
|
posf = posf + 4;
|
|
printf(mnem[k]);
|
|
printf(" ");
|
|
printHex2(m);
|
|
printf(",");
|
|
printHex1(n);
|
|
printf(",");
|
|
printHex1(o);
|
|
break;
|
|
|
|
case 10:
|
|
m=getu1(input);
|
|
posf++;
|
|
printf(mnem[k]);
|
|
printf(" ");
|
|
|
|
switch (m)
|
|
{
|
|
case 4: printf("T_BOOLEAN"); break;
|
|
case 5: printf("T_CHAR"); break;
|
|
case 6: printf("T_FLOAT"); break;
|
|
case 7: printf("T_DOUBLE"); break;
|
|
case 8: printf("T_BYTE"); break;
|
|
case 9: printf("T_SHORT"); break;
|
|
case 10: printf("T_INT"); break;
|
|
case 11: printf("T_LONG"); break;
|
|
default: printf("\nError");
|
|
}
|
|
break;
|
|
|
|
case 11:
|
|
m=getu1(input);
|
|
n=getu1(input);
|
|
posf = posf + 2;
|
|
if ( n<0x15 || (n>0x19 && n<0x36) || (n>0x3a && n!=0x84)) printf("\nError");
|
|
|
|
m=(m<<8)+getu1(input);
|
|
posf++;
|
|
printf(mnem[n]);
|
|
printf(" ");
|
|
printHex2(m);
|
|
break;
|
|
|
|
default: printf("\nError");
|
|
}
|
|
|
|
}
|
|
|
|
if (posf!=j) printf("\nError");
|
|
posn--;
|
|
printf("\n");
|
|
|
|
}
|
|
|
|
|
|
/********************************************************************
|
|
*
|
|
* function: int whichAttribute(char *constant_pool_name)
|
|
*
|
|
* purpose: Returns the attribute of the passed string.
|
|
*
|
|
*
|
|
*********************************************************************/
|
|
|
|
int whichAttribute(char *constant_pool_name)
|
|
{
|
|
if ( strcmp("SourceFile",constant_pool_name) == 0 ) return SOURCE_FILE;
|
|
if ( strcmp("ConstantValue",constant_pool_name) == 0 ) return CONSTANT_VALUE;
|
|
if ( strcmp("Code",constant_pool_name) == 0 ) return CODE;
|
|
if ( strcmp("Exceptions",constant_pool_name) == 0 ) return EXCEPTIONS;
|
|
if ( strcmp("LineNumberTable",constant_pool_name) == 0 ) return LINENUMBERTABLE;
|
|
if ( strcmp("LocalVariableTable",constant_pool_name) == 0 ) return LOCALVARIABLETABLE;
|
|
|
|
}
|
|
|
|
/********************************************************************
|
|
*
|
|
* function: void getAttributes(int attr, FILE *input, struct linked_list *first_ptr)
|
|
*
|
|
* purpose: Prints out the attribute info.
|
|
*
|
|
*
|
|
*********************************************************************/
|
|
|
|
void getAttributes(int attr, FILE *input, struct linked_list *first_ptr)
|
|
{
|
|
/*Local variables.*/
|
|
int length = 0;
|
|
int k = 0;
|
|
int count = 0;
|
|
int index = 0;
|
|
|
|
/*Print out the appropriate attribute. Refer to the JVM Spec for more info.*/
|
|
switch (attr)
|
|
{
|
|
case SOURCE_FILE:
|
|
printf("SourceFile");
|
|
printf(" length ");
|
|
printDec4(getu4(input));
|
|
printf(" index ");
|
|
printDec2(getu2(input));
|
|
break;
|
|
|
|
case CONSTANT_VALUE:
|
|
printf("ConstantValue");
|
|
printf(" length ");
|
|
printDec4(getu4(input));
|
|
printf(" index ");
|
|
printDec2(getu2(input));
|
|
break;
|
|
|
|
case CODE:
|
|
printf("Code");
|
|
|
|
printf("\n");
|
|
printTab(2);
|
|
printf("length");
|
|
printTab(2);
|
|
printDec4(getu4(input));
|
|
|
|
printf("\n");
|
|
printTab(2);
|
|
printf("max_stack");
|
|
printTab(1);
|
|
printDec2(getu2(input));
|
|
|
|
printf("\n");
|
|
printTab(2);
|
|
printf("max_local");
|
|
printTab(1);
|
|
printDec2(getu2(input));
|
|
|
|
printf("\n");
|
|
printTab(2);
|
|
printf("length");
|
|
printTab(2);
|
|
length = getu4(input);
|
|
printDec4(length);
|
|
|
|
/*Print out the bytecodes.*/
|
|
printf("\n\t\tbytecode");
|
|
getBytecode(length,input);
|
|
|
|
printf("\n");
|
|
printTab(2);
|
|
printf("exceptions");
|
|
length = getu2(input);
|
|
printTab(1);
|
|
printDec2(length);
|
|
for ( k=0; k < length; k++ )
|
|
{
|
|
printf("\n");
|
|
printTab(4);
|
|
printf("exception %i",k);
|
|
printf("\n");
|
|
printTab(4);
|
|
printf("start_pc: ");
|
|
printDec2(getu2(input));
|
|
printf("end_pc: ");
|
|
printDec2(getu2(input));
|
|
printf("handler_pc: ");
|
|
printDec2(getu2(input));
|
|
printf("catch_type: ");
|
|
printDec2(getu2(input));
|
|
}
|
|
|
|
printf("\n");
|
|
printTab(2);
|
|
printf("attributes");
|
|
printTab(1);
|
|
count = getu2(input);
|
|
printDec2(count);
|
|
for ( k=0; k<count; k++ )
|
|
{
|
|
index = getu2(input);
|
|
switch(whichAttribute(getName(first_ptr,index)))
|
|
{
|
|
case LINENUMBERTABLE:
|
|
getAttributes(LINENUMBERTABLE,input,first_ptr);
|
|
printf("\n");
|
|
break;
|
|
|
|
case LOCALVARIABLETABLE:
|
|
getAttributes(LOCALVARIABLETABLE,input,first_ptr);
|
|
printf("\n");
|
|
break;
|
|
|
|
default: /*Ignore.*/
|
|
for ( length=0; length < getu4(input); length++ ) getu1(input);
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
case EXCEPTIONS:
|
|
printf("Exceptions");
|
|
length = getu4(input);
|
|
printDec4(length);
|
|
for ( k=0; k < length; k++ ) getu1(input);
|
|
break;
|
|
|
|
case LINENUMBERTABLE:
|
|
|
|
printf("\n");
|
|
printTab(4);
|
|
printf("LineNumberTable ");
|
|
|
|
printDec4(getu4(input));
|
|
|
|
length = getu2(input);
|
|
for ( k=0; k < length; k++ )
|
|
{
|
|
printf("\n");
|
|
printTab(4);
|
|
printf("%i",k);
|
|
printf(" start ");
|
|
printDec2(getu2(input));
|
|
printf(" line ");
|
|
printDec2(getu2(input));
|
|
}
|
|
break;
|
|
|
|
case LOCALVARIABLETABLE:
|
|
|
|
printf("\n");
|
|
printTab(4);
|
|
printf("LocalVariableTable ");
|
|
|
|
printDec4(getu4(input));
|
|
|
|
length = getu2(input);
|
|
for ( k=0; k < length; k++ )
|
|
{
|
|
printf("\n");
|
|
printTab(4);
|
|
printf("%i",k);
|
|
printf(" start ");
|
|
printDec2(getu2(input));
|
|
printf(" length ");
|
|
printDec2(getu2(input));
|
|
printf(" name ");
|
|
printDec2(getu2(input));
|
|
printf(" descriptor ");
|
|
printDec2(getu2(input));
|
|
printf(" index ");
|
|
printDec2(getu2(input));
|
|
}
|
|
break;
|
|
|
|
default:
|
|
printf("\nError in Attribute");
|
|
exit(0);
|
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|