зеркало из https://github.com/mozilla/pjs.git
278 строки
7.5 KiB
C++
278 строки
7.5 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):
|
|
*/
|
|
/* Test program for ClassFileSummary */
|
|
|
|
#include "prinit.h"
|
|
#include "ClassFileSummary.h"
|
|
#include "ClassCentral.h"
|
|
#include "ErrorHandling.h"
|
|
|
|
char *fileName = 0;
|
|
char *className = 0;
|
|
char *classPath = 0;
|
|
|
|
void printUsage()
|
|
{
|
|
printf("Usage: classinfo [-f filename] [-cpath classpath] classname\n");
|
|
exit(0);
|
|
}
|
|
|
|
void parseOptions(int argc, char **argv)
|
|
{
|
|
int i;
|
|
|
|
for (i = 1; i < argc; i++)
|
|
if (!strcmp(argv[i], "-f"))
|
|
fileName = argv[++i];
|
|
else if (!strcmp(argv[i], "-cpath"))
|
|
classPath = argv[++i];
|
|
else if (!strcmp(argv[i], "-help"))
|
|
printUsage();
|
|
else if (className) {/* must be a classname */
|
|
printf("Syntax error or duplicate filename\n");
|
|
printUsage();
|
|
} else
|
|
className = argv[i];
|
|
|
|
if (!className) {
|
|
printf("Insufficient arguments\n");
|
|
printUsage();
|
|
}
|
|
|
|
}
|
|
|
|
Pool dynamicPool;
|
|
ClassWorld world(dynamicPool);
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
int i;
|
|
|
|
#ifndef NO_NSPR
|
|
PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 1);
|
|
#endif
|
|
|
|
parseOptions(argc, argv);
|
|
|
|
// Pool dynamicPool;
|
|
StringPool sp(dynamicPool);
|
|
// ClassWorld world(dynamicPool);
|
|
|
|
ClassCentral central(dynamicPool, world, sp, classPath);
|
|
|
|
printf("Initializing distinguished objects....\n");
|
|
try {
|
|
initDistinguishedObjects(central);
|
|
} catch (VerifyError err) {
|
|
printf("Error initializing distinguished objects: %d\n", err.cause);
|
|
exit(1);
|
|
}
|
|
printf("Initialized distinguished objects!\n");
|
|
|
|
ClassFileSummary *info;
|
|
const ConstantPool *constantPool;
|
|
int constantPoolCount;
|
|
|
|
printf("Initialized class central\n");
|
|
|
|
try {
|
|
if (fileName) {
|
|
printf("Loading from file %s\n", fileName);
|
|
info = ¢ral.addClass((const char *) className,
|
|
(const char *) fileName);
|
|
} else
|
|
info = ¢ral.addClass((const char *) className);
|
|
|
|
} catch (VerifyError err) {
|
|
printf("Cannot load class %s: error %d\n", className, err.cause);
|
|
exit(1);
|
|
}
|
|
|
|
constantPool = info->getConstantPool();
|
|
constantPoolCount = info->getConstantPoolCount();
|
|
|
|
printf("Total size of object : %d\n", info->getObjSize());
|
|
|
|
/* Resolve fields, methods, constants, interfaceMethods */
|
|
for (i = 0; i < constantPoolCount; i++)
|
|
if (constantPool->get(i)) {
|
|
uint8 type = constantPool->get(i)->getType();
|
|
|
|
if (type == CR_CONSTANT_FIELDREF) {
|
|
ConstantFieldRef *ref = (ConstantFieldRef *) constantPool->get(i);
|
|
ConstantNameAndType *nameAndType = (ConstantNameAndType *) ref->getTypeInfo();
|
|
ConstantClass *cclass = ref->getClassInfo();
|
|
|
|
printf("--> Resolving field %s::%s...\n",
|
|
cclass->getUtf()->getUtfString(),
|
|
nameAndType->getName()->getUtfString());
|
|
|
|
uint32 offset;
|
|
bool isVolatile, isConstant;
|
|
bool isStatic = false;
|
|
TypeKind tk;
|
|
ValueKind vk;
|
|
|
|
try {
|
|
tk = info->lookupInstanceField(i, vk,
|
|
offset, isVolatile, isConstant);
|
|
} catch (VerifyError err) {
|
|
printf("\tlookupInstanceField() failed with error %d.\n",
|
|
err.cause);
|
|
printf("\tOk, so it's not an instance field. Trying static.\n");
|
|
addr a;
|
|
|
|
try {
|
|
tk = info->lookupStaticField(i, vk, a, isVolatile, isConstant);
|
|
isStatic = true;
|
|
} catch (VerifyError err) {
|
|
printf("Cannot resolve field %s: %d\n",
|
|
nameAndType->getName()->getUtfString(), err.cause);
|
|
}
|
|
}
|
|
|
|
if (isStatic)
|
|
printf("Resolved as static field.\n");
|
|
else
|
|
printf("Resolved as instance field with offset %u\n", offset);
|
|
|
|
} else if (type == CR_CONSTANT_METHODREF) {
|
|
ConstantMethodRef *ref = (ConstantMethodRef *) constantPool->get(i);
|
|
ConstantNameAndType *nameAndType = (ConstantNameAndType *) ref->getTypeInfo();
|
|
ConstantClass *cclass = ref->getClassInfo();
|
|
|
|
const char *methodName = nameAndType->getName()->getUtfString();
|
|
|
|
printf("--> Resolving method %s::%s...\n",
|
|
cclass->getUtf()->getUtfString(),
|
|
methodName);
|
|
|
|
uint32 vIndex;
|
|
addr a;
|
|
Signature sig;
|
|
bool dynamicallyResolved = false;
|
|
|
|
if (!strcmp(methodName, "<init>") || !strcmp(methodName, "<clinit>")) {
|
|
try {
|
|
info->lookupSpecialMethod(i, sig, a);
|
|
|
|
printf("\tResolved special method %s.\n", methodName);
|
|
|
|
} catch (VerifyError err) {
|
|
printf("Could not resolve special method %s: error %d\n",
|
|
methodName, err.cause);
|
|
exit(1);
|
|
}
|
|
} else {
|
|
try {
|
|
dynamicallyResolved =
|
|
info->lookupVirtualMethod(i, sig, vIndex, a);
|
|
} catch (VerifyError err) {
|
|
printf("\tlookupVirtualMethod() failed with erorr %d\n",
|
|
err.cause);
|
|
printf("\tOk, so method is not virtual. trying static...\n");
|
|
|
|
try {
|
|
info->lookupStaticMethod(i, sig, a);
|
|
} catch (VerifyError err) {
|
|
printf("Cannot resolve method %s: %d\n",
|
|
nameAndType->getName()->getUtfString(), err.cause);
|
|
exit(1);
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
if (dynamicallyResolved)
|
|
printf("\tResolved method %s as virtual: vindex %u.\n",
|
|
nameAndType->getName()->getUtfString(), vIndex);
|
|
else {
|
|
printf("\tResolved method %s statically\n",
|
|
nameAndType->getName()->getUtfString());
|
|
}
|
|
|
|
} else if (type == CR_CONSTANT_INTERFACEMETHODREF) {
|
|
ConstantMethodRef *ref = (ConstantMethodRef *) constantPool->get(i);
|
|
ConstantNameAndType *nameAndType = (ConstantNameAndType *) ref->getTypeInfo();
|
|
ConstantClass *cclass = ref->getClassInfo();
|
|
|
|
const char *methodName = nameAndType->getName()->getUtfString();
|
|
printf("--> Resolving interface method %s::%s...\n",
|
|
cclass->getUtf()->getUtfString(),
|
|
methodName);
|
|
|
|
Signature sig;
|
|
uint32 interfaceIndex;
|
|
addr a;
|
|
uint32 nArgs;
|
|
|
|
if (!strcmp(methodName, "<init>") || !strcmp(methodName, "<clinit>")) {
|
|
try {
|
|
info->lookupSpecialMethod(i, sig, a);
|
|
|
|
printf("\tResolved special method %s.\n", methodName);
|
|
|
|
} catch (VerifyError err) {
|
|
printf("Could not resolve special method %s: error %d\n",
|
|
methodName, err.cause);
|
|
exit(1);
|
|
}
|
|
} else {
|
|
try {
|
|
bool staticallyResolved = info->lookupInterfaceMethod(i, sig,
|
|
interfaceIndex,
|
|
a,
|
|
nArgs);
|
|
printf("\tResolved interface method %s %s.\n",
|
|
nameAndType->getName()->getUtfString(),
|
|
(staticallyResolved) ? "statically" : "dynamically");
|
|
} catch (VerifyError err) {
|
|
printf("\tCould not resolve interface method %s: error %d\n",
|
|
nameAndType->getName()->getUtfString(), err.cause);
|
|
exit(1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
printf("Successfully loaded class file. \n");
|
|
|
|
printf("Getting class descriptor...\n");
|
|
Class *clazz = static_cast<Class *>(info->getThisClass());
|
|
printf("Obtained class descriptor.\n");
|
|
|
|
/* Now look up all the interfaces this class implements */
|
|
printf("Loading interfaces...\n");
|
|
const Interface **interfaces = info->getInterfaces();
|
|
|
|
printf("Done!\n");
|
|
return 0;
|
|
}
|
|
|
|
|
|
#ifdef DEBUG_LAURENT
|
|
#ifdef __GNUC__
|
|
// for gcc with -fhandle-exceptions
|
|
void terminate() {}
|
|
#endif
|
|
#endif
|