2014-07-06 12:29:36 +04:00
|
|
|
/* -*- Mode: Java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
|
|
|
|
/* vim: set shiftwidth=4 tabstop=4 autoindent cindent expandtab: */
|
|
|
|
|
|
|
|
'use strict';
|
|
|
|
|
2014-07-13 20:52:01 +04:00
|
|
|
var getClassImage = function(classBytes) {
|
2014-07-06 12:29:36 +04:00
|
|
|
var classImage = {};
|
2014-07-12 08:26:05 +04:00
|
|
|
|
2014-07-13 21:04:17 +04:00
|
|
|
var getAttributes = function(attribute_name_index, bytes) {
|
2014-07-06 12:29:36 +04:00
|
|
|
var reader = new Reader(bytes);
|
|
|
|
var attribute = { attribute_name_index: attribute_name_index };
|
2014-07-12 08:26:05 +04:00
|
|
|
|
2014-07-06 12:29:36 +04:00
|
|
|
var item = classImage.constant_pool[attribute_name_index];
|
2014-07-12 08:26:05 +04:00
|
|
|
|
2014-07-06 12:29:36 +04:00
|
|
|
switch(item.tag) {
|
|
|
|
case TAGS.CONSTANT_Long:
|
|
|
|
case TAGS.CONSTANT_Float:
|
|
|
|
case TAGS.CONSTANT_Double:
|
|
|
|
case TAGS.CONSTANT_Integer:
|
|
|
|
case TAGS.CONSTANT_String:
|
|
|
|
attribute.type = ATTRIBUTE_TYPES.ConstantValue;
|
2014-07-13 09:19:03 +04:00
|
|
|
attribute.info = reader.read16();
|
2014-07-12 08:26:05 +04:00
|
|
|
return attribute;
|
|
|
|
|
2014-07-06 12:29:36 +04:00
|
|
|
case TAGS.CONSTANT_Utf8:
|
|
|
|
switch(item.bytes) {
|
|
|
|
case ATTRIBUTE_TYPES.Code:
|
|
|
|
attribute.type = ATTRIBUTE_TYPES.Code;
|
|
|
|
attribute.max_stack = reader.read16();
|
|
|
|
attribute.max_locals = reader.read16();
|
|
|
|
var code_length = reader.read32();
|
|
|
|
attribute.code = reader.readBytes(code_length);
|
2014-07-12 20:48:24 +04:00
|
|
|
|
|
|
|
var exception_table_length = reader.read16();
|
2014-07-06 12:29:36 +04:00
|
|
|
attribute.exception_table = [];
|
2014-07-13 20:52:01 +04:00
|
|
|
for (var i=0; i<exception_table_length; i++) {
|
|
|
|
attribute.exception_table.push({
|
|
|
|
start_pc: reader.read16(),
|
|
|
|
end_pc: reader.read16(),
|
|
|
|
handler_pc: reader.read16(),
|
|
|
|
catch_type: reader.read16()
|
|
|
|
});
|
2014-07-06 12:29:36 +04:00
|
|
|
}
|
|
|
|
|
2014-07-12 20:48:24 +04:00
|
|
|
var attributes_count = reader.read16();
|
2014-07-06 12:29:36 +04:00
|
|
|
attribute.attributes = [];
|
|
|
|
for(var i=0; i<attributes_count; i++) {
|
|
|
|
var attribute_name_index = reader.read16();
|
|
|
|
var attribute_length = reader.read32();
|
|
|
|
var info = reader.readBytes(attribute_length);
|
2014-07-13 21:04:17 +04:00
|
|
|
attribute.attributes.push({ attribute_name_index: attribute_name_index, info: info });
|
2014-07-06 12:29:36 +04:00
|
|
|
}
|
|
|
|
return attribute;
|
2014-07-12 08:26:05 +04:00
|
|
|
|
2014-07-06 12:29:36 +04:00
|
|
|
case ATTRIBUTE_TYPES.SourceFile:
|
|
|
|
attribute.type = ATTRIBUTE_TYPES.SourceFile;
|
|
|
|
attribute.sourcefile_index = reader.read16();
|
|
|
|
return attribute;
|
2014-07-12 08:26:05 +04:00
|
|
|
|
2014-07-06 12:29:36 +04:00
|
|
|
case ATTRIBUTE_TYPES.Exceptions:
|
|
|
|
attribute.type = ATTRIBUTE_TYPES.Exceptions;
|
|
|
|
var number_of_exceptions = reader.read16();
|
|
|
|
attribute.exception_index_table = [];
|
|
|
|
for(var i=0; i<number_of_exceptions; i++) {
|
|
|
|
attribute.exception_index_table.push(reader.read16());
|
|
|
|
}
|
|
|
|
return attribute;
|
2014-07-12 20:48:24 +04:00
|
|
|
|
2014-07-06 12:29:36 +04:00
|
|
|
case ATTRIBUTE_TYPES.InnerClasses:
|
|
|
|
attribute.type = ATTRIBUTE_TYPES.InnerClasses;
|
|
|
|
var number_of_classes = reader.read16();
|
|
|
|
attribute.classes = [];
|
|
|
|
for(var i=0; i<number_of_classes; i++) {
|
|
|
|
var inner = {};
|
|
|
|
inner.inner_class_info_index = reader.read16();
|
|
|
|
inner.outer_class_info_index = reader.read16();
|
|
|
|
inner.inner_name_index = reader.read16();
|
|
|
|
inner.inner_class_access_flags = reader.read16();
|
|
|
|
attribute.classes.push(inner);
|
|
|
|
}
|
|
|
|
return attribute;
|
2014-07-12 08:26:05 +04:00
|
|
|
|
2014-07-30 04:34:46 +04:00
|
|
|
case ATTRIBUTE_TYPES.Synthetic:
|
|
|
|
attribute.type = ATTRIBUTE_TYPES.Synthetic;
|
|
|
|
return attribute;
|
|
|
|
|
2014-07-31 04:25:07 +04:00
|
|
|
case ATTRIBUTE_TYPES.Deprecated:
|
|
|
|
attribute.type = ATTRIBUTE_TYPES.Deprecated;
|
|
|
|
return attribute;
|
|
|
|
|
2014-07-06 12:29:36 +04:00
|
|
|
default:
|
2014-07-12 20:48:24 +04:00
|
|
|
throw new Error("This attribute type is not supported yet. [" + JSON.stringify(item) + "]");
|
2014-07-06 12:29:36 +04:00
|
|
|
}
|
2014-07-12 08:26:05 +04:00
|
|
|
|
2014-07-06 12:29:36 +04:00
|
|
|
default:
|
2014-07-12 20:48:24 +04:00
|
|
|
throw new Error("This attribute type is not supported yet. [" + JSON.stringify(item) + "]");
|
2014-07-06 12:29:36 +04:00
|
|
|
}
|
|
|
|
};
|
2014-07-12 08:26:05 +04:00
|
|
|
|
2014-07-06 12:29:36 +04:00
|
|
|
var reader = Reader(classBytes);
|
|
|
|
classImage.magic = reader.read32().toString(16);
|
|
|
|
|
|
|
|
classImage.version = {
|
|
|
|
minor_version: reader.read16(),
|
|
|
|
major_version: reader.read16()
|
|
|
|
};
|
2014-07-12 08:26:05 +04:00
|
|
|
|
2014-07-06 12:29:36 +04:00
|
|
|
classImage.constant_pool = [ null ];
|
|
|
|
var constant_pool_count = reader.read16();
|
2014-07-12 20:48:24 +04:00
|
|
|
for(var i=1; i<constant_pool_count; i++) {
|
2014-07-17 09:45:10 +04:00
|
|
|
var tag = reader.read8();
|
2014-07-06 12:29:36 +04:00
|
|
|
switch(tag) {
|
|
|
|
case TAGS.CONSTANT_Class:
|
|
|
|
var name_index = reader.read16();
|
2014-07-17 07:56:04 +04:00
|
|
|
classImage.constant_pool.push({ tag: tag, name_index: name_index });
|
2014-07-06 12:29:36 +04:00
|
|
|
break;
|
|
|
|
case TAGS.CONSTANT_Utf8:
|
|
|
|
var length = reader.read16();
|
|
|
|
var bytes = reader.readString(length);
|
2014-07-17 07:56:04 +04:00
|
|
|
classImage.constant_pool.push({ tag: tag, bytes: bytes });
|
2014-07-06 12:29:36 +04:00
|
|
|
break;
|
|
|
|
case TAGS.CONSTANT_Methodref:
|
|
|
|
var class_index = reader.read16();
|
|
|
|
var name_and_type_index = reader.read16();
|
2014-07-17 07:57:12 +04:00
|
|
|
classImage.constant_pool.push({ tag: tag, class_index: class_index, name_and_type_index: name_and_type_index });
|
2014-07-06 12:29:36 +04:00
|
|
|
break;
|
|
|
|
case TAGS.CONSTANT_NameAndType:
|
|
|
|
var name_index = reader.read16();
|
|
|
|
var signature_index = reader.read16();
|
2014-07-17 07:56:04 +04:00
|
|
|
classImage.constant_pool.push({ tag: tag, name_index: name_index, signature_index: signature_index });
|
2014-07-06 12:29:36 +04:00
|
|
|
break;
|
|
|
|
case TAGS.CONSTANT_Fieldref:
|
|
|
|
var class_index = reader.read16();
|
|
|
|
var name_and_type_index = reader.read16();
|
2014-07-17 07:56:04 +04:00
|
|
|
classImage.constant_pool.push({ tag: tag, class_index: class_index, name_and_type_index: name_and_type_index });
|
2014-07-06 12:29:36 +04:00
|
|
|
break;
|
|
|
|
case TAGS.CONSTANT_String:
|
|
|
|
var string_index = reader.read16();
|
2014-07-17 07:56:04 +04:00
|
|
|
classImage.constant_pool.push({ tag: tag, string_index: string_index });
|
2014-07-06 12:29:36 +04:00
|
|
|
break;
|
|
|
|
case TAGS.CONSTANT_Integer:
|
2014-07-17 07:56:04 +04:00
|
|
|
classImage.constant_pool.push({ tag: tag, integer: reader.readInteger() });
|
2014-07-17 07:53:54 +04:00
|
|
|
break;
|
|
|
|
case TAGS.CONSTANT_Float:
|
2014-07-17 07:56:04 +04:00
|
|
|
classImage.constant_pool.push({ tag: tag, float: reader.readFloat() });
|
2014-07-06 12:29:36 +04:00
|
|
|
break;
|
|
|
|
case TAGS.CONSTANT_Double:
|
2014-07-17 09:45:10 +04:00
|
|
|
classImage.constant_pool.push({ tag: tag, double: reader.readDouble() });
|
|
|
|
classImage.constant_pool.push(null);
|
|
|
|
++i;
|
|
|
|
break;
|
2014-07-06 12:29:36 +04:00
|
|
|
case TAGS.CONSTANT_Long:
|
2014-07-17 11:42:20 +04:00
|
|
|
classImage.constant_pool.push({ tag: tag, highBits: reader.readInteger(), lowBits: reader.readInteger() });
|
2014-07-17 09:45:10 +04:00
|
|
|
classImage.constant_pool.push(null);
|
|
|
|
++i;
|
2014-07-06 12:29:36 +04:00
|
|
|
break;
|
|
|
|
case TAGS.CONSTANT_Fieldref:
|
|
|
|
case TAGS.CONSTANT_Methodref:
|
|
|
|
case TAGS.CONSTANT_InterfaceMethodref:
|
|
|
|
var class_index = reader.read16();
|
|
|
|
var name_and_type_index = reader.read16();
|
2014-07-17 07:56:04 +04:00
|
|
|
classImage.constant_pool.push({ tag: tag, class_index: class_index, name_and_type_index:name_and_type_index });
|
2014-07-06 12:29:36 +04:00
|
|
|
break;
|
2014-07-12 20:48:24 +04:00
|
|
|
default:
|
2014-07-14 02:27:25 +04:00
|
|
|
throw new Error("tag " + tag + " not supported.");
|
2014-07-06 12:29:36 +04:00
|
|
|
}
|
|
|
|
}
|
2014-07-12 20:48:24 +04:00
|
|
|
|
2014-07-06 12:29:36 +04:00
|
|
|
classImage.access_flags = reader.read16();
|
2014-07-12 20:48:24 +04:00
|
|
|
|
2014-07-06 12:29:36 +04:00
|
|
|
classImage.this_class = reader.read16();
|
2014-07-12 20:48:24 +04:00
|
|
|
|
2014-07-06 12:29:36 +04:00
|
|
|
classImage.super_class = reader.read16();
|
|
|
|
|
|
|
|
classImage.interfaces = [];
|
|
|
|
var interfaces_count = reader.read16();
|
|
|
|
for(var i=0; i<interfaces_count; i++) {
|
|
|
|
var index = reader.read16();
|
2014-07-18 10:26:34 +04:00
|
|
|
if (index != 0) {
|
2014-07-06 12:29:36 +04:00
|
|
|
classImage.interfaces.push(index);
|
|
|
|
}
|
|
|
|
}
|
2014-07-12 08:26:05 +04:00
|
|
|
|
2014-07-06 12:29:36 +04:00
|
|
|
classImage.fields = [];
|
|
|
|
var fields_count = reader.read16();
|
|
|
|
for(var i=0; i<fields_count; i++) {
|
2014-07-13 21:04:17 +04:00
|
|
|
var field_info = { access_flags: reader.read16(), name_index: reader.read16(), descriptor_index: reader.read16(), attributes: [] };
|
2014-07-06 12:29:36 +04:00
|
|
|
var attributes_count = reader.read16();
|
|
|
|
for(var j=0; j <attributes_count; j++) {
|
|
|
|
var attribute_name_index = reader.read16();
|
|
|
|
var attribute_length = reader.read32();
|
2014-07-13 21:04:17 +04:00
|
|
|
var info = reader.readBytes(attribute_length);
|
|
|
|
field_info.attributes.push({ attribute_name_index: attribute_name_index, info: info });
|
2014-07-06 12:29:36 +04:00
|
|
|
}
|
|
|
|
classImage.fields.push(field_info);
|
2014-07-12 20:48:24 +04:00
|
|
|
}
|
2014-07-12 08:26:05 +04:00
|
|
|
|
2014-07-06 12:29:36 +04:00
|
|
|
classImage.methods = [];
|
|
|
|
var methods_count = reader.read16();
|
|
|
|
for(var i=0; i<methods_count; i++) {
|
2014-07-13 21:04:17 +04:00
|
|
|
var method_info = { access_flags: reader.read16(), name_index: reader.read16(), signature_index: reader.read16(), attributes: [] };
|
2014-07-06 12:29:36 +04:00
|
|
|
var attributes_count = reader.read16();
|
|
|
|
for(var j=0; j <attributes_count; j++) {
|
|
|
|
var attribute_name_index = reader.read16();
|
|
|
|
var attribute_length = reader.read32();
|
2014-07-13 21:04:17 +04:00
|
|
|
var info = getAttributes(attribute_name_index, reader.readBytes(attribute_length));
|
2014-07-13 21:37:28 +04:00
|
|
|
method_info.attributes.push({ attribute_name_index: attribute_name_index, info: info });
|
2014-07-06 12:29:36 +04:00
|
|
|
}
|
|
|
|
classImage.methods.push(method_info);
|
|
|
|
}
|
2014-07-12 08:26:05 +04:00
|
|
|
|
2014-07-06 12:29:36 +04:00
|
|
|
classImage.attributes = [];
|
|
|
|
var attributes_count = reader.read16();
|
|
|
|
for(var i=0; i<attributes_count; i++) {
|
|
|
|
var attribute_name_index = reader.read16();
|
|
|
|
var attribute_length = reader.read32();
|
2014-07-13 21:04:17 +04:00
|
|
|
var info = getAttributes(attribute_name_index, reader.readBytes(attribute_length));
|
2014-07-13 21:37:28 +04:00
|
|
|
classImage.attributes.push({ attribute_name_index: attribute_name_index, info: info });
|
2014-07-06 12:29:36 +04:00
|
|
|
}
|
2014-07-12 08:26:05 +04:00
|
|
|
|
2014-07-06 12:29:36 +04:00
|
|
|
return classImage;
|
|
|
|
};
|