BootstrapMethods and printing

This commit is contained in:
BENEDEK 2024-04-13 22:25:38 +02:00
parent 5228c765ef
commit af118981c4
2 changed files with 205 additions and 107 deletions

View File

@ -63,11 +63,28 @@ stack_frame_type stack_frame_type_enum(u2 frame_type) {
} }
} }
ATTRIBUTE_TAGS attribute_tag(char* name) {
for (size_t i = 1; i < ATTRIBUTE_TAGS_END; i++) {
if (strcmp(ATTRIBUTE_TAGS_STRINGS[i - 1], name) == 0)
return (ATTRIBUTE_TAGS)i;
}
return UNKNOWN;
}
char* constant_to_string(ClassFile* cf, cp_info info) {}
void parse_attribute(ClassFile* cf, attribute_info* base, FILE* file) { void parse_attribute(ClassFile* cf, attribute_info* base, FILE* file) {
char* name = (char*)cf->constant_pool[base->attribute_name_index - 1].info.utf8_info.bytes; char* name = (char*)cf->constant_pool[base->attribute_name_index - 1].info.utf8_info.bytes;
if (strcmp("ConstantValue", name) == 0) { base->_tag = attribute_tag(name);
switch (base->_tag) {
case UNKNOWN:
printf("unhandled attribute type: %s\n", name);
fseek(file, base->attribute_length, SEEK_CUR);
break;
case CONSTANT_VALUE:
read_u2(&(base->info.constant_value_attribute.constantvalue_index), 1, file); read_u2(&(base->info.constant_value_attribute.constantvalue_index), 1, file);
} else if (strcmp("Code", name) == 0) { break;
case CODE:
read_u2(&(base->info.code_attribute.max_stack), 2, file); read_u2(&(base->info.code_attribute.max_stack), 2, file);
read_u4(&(base->info.code_attribute.code_length), 1, file); read_u4(&(base->info.code_attribute.code_length), 1, file);
base->info.code_attribute.code = (u1*)malloc(base->info.code_attribute.code_length); base->info.code_attribute.code = (u1*)malloc(base->info.code_attribute.code_length);
@ -85,7 +102,8 @@ void parse_attribute(ClassFile* cf, attribute_info* base, FILE* file) {
read_u4(&(attr->attribute_length), 1, file); read_u4(&(attr->attribute_length), 1, file);
parse_attribute(cf, attr, file); parse_attribute(cf, attr, file);
} }
} else if (strcmp("StackMapTable", name) == 0) { break;
case STACK_MAP_TABLE:
read_u2(&(base->info.stack_map_table_attribute.number_of_entries), 1, file); read_u2(&(base->info.stack_map_table_attribute.number_of_entries), 1, file);
base->info.stack_map_table_attribute.entries = malloc(sizeof(stack_map_frame) * base->info.stack_map_table_attribute.number_of_entries); base->info.stack_map_table_attribute.entries = malloc(sizeof(stack_map_frame) * base->info.stack_map_table_attribute.number_of_entries);
for (u2 i = 0; i < base->info.stack_map_table_attribute.number_of_entries; i++) { for (u2 i = 0; i < base->info.stack_map_table_attribute.number_of_entries; i++) {
@ -156,19 +174,36 @@ void parse_attribute(ClassFile* cf, attribute_info* base, FILE* file) {
break; break;
} }
} }
} else if (strcmp("NestHost", name) == 0) { break;
case BOOTSTRAP_METHODS: {
BootstrapMethods_attribute* attr = &base->info.bootstrap_methods_attribute;
read_u2(&(attr->num_bootstrap_methods), 1, file);
attr->bootstrap_methods = malloc(sizeof(BootstrapMethod) * attr->num_bootstrap_methods);
for (u2 i = 0; i < attr->num_bootstrap_methods; i++) {
BootstrapMethod* method = &attr->bootstrap_methods[i];
read_u2(&(method->bootstrap_method_ref), 2, file);
method->bootstrap_arguments = malloc(sizeof(u2) * method->num_bootstrap_arguments);
read_u2(method->bootstrap_arguments, method->num_bootstrap_arguments, file);
}
break;
}
case NEST_HOST:
read_u2(&(base->info.nest_host_attribute.host_class_index), 1, file); read_u2(&(base->info.nest_host_attribute.host_class_index), 1, file);
} else if (strcmp("NestMembers", name) == 0) { break;
case NEST_MEMBERS:
read_u2(&(base->info.nest_members_attribute.number_of_classes), 1, file); read_u2(&(base->info.nest_members_attribute.number_of_classes), 1, file);
base->info.nest_members_attribute.classes = malloc(sizeof(u2) * base->info.nest_members_attribute.number_of_classes); base->info.nest_members_attribute.classes = malloc(sizeof(u2) * base->info.nest_members_attribute.number_of_classes);
read_u2(base->info.nest_members_attribute.classes, base->info.nest_members_attribute.number_of_classes, file); read_u2(base->info.nest_members_attribute.classes, base->info.nest_members_attribute.number_of_classes, file);
} else if (strcmp("PermittedSubclasses", name) == 0) { break;
case PERMITTED_SUBCLASSES:
read_u2(&(base->info.permitted_subclasses_attribute.number_of_classes), 1, file); read_u2(&(base->info.permitted_subclasses_attribute.number_of_classes), 1, file);
base->info.permitted_subclasses_attribute.classes = malloc(sizeof(u2) * base->info.permitted_subclasses_attribute.number_of_classes); base->info.permitted_subclasses_attribute.classes = malloc(sizeof(u2) * base->info.permitted_subclasses_attribute.number_of_classes);
read_u2(base->info.permitted_subclasses_attribute.classes, base->info.permitted_subclasses_attribute.number_of_classes, file); read_u2(base->info.permitted_subclasses_attribute.classes, base->info.permitted_subclasses_attribute.number_of_classes, file);
} else { break;
printf("unhandled attribute type: %s\n", name); case ATTRIBUTE_TAGS_END:
fseek(file, base->attribute_length, SEEK_CUR); assert(0);
} }
} }
@ -362,10 +397,12 @@ void ClassFile_info(const ClassFile* cf) {
case CONSTANT_Long: case CONSTANT_Long:
merged = merge_bytes(cf->constant_pool[i].info.long_info.high_bytes, cf->constant_pool[i].info.long_info.low_bytes); merged = merge_bytes(cf->constant_pool[i].info.long_info.high_bytes, cf->constant_pool[i].info.long_info.low_bytes);
printf("\t%ld\n", *(long*)&merged); printf("\t%ld\n", *(long*)&merged);
i++;
break; break;
case CONSTANT_Double: case CONSTANT_Double:
merged = merge_bytes(cf->constant_pool[i].info.double_info.high_bytes, cf->constant_pool[i].info.double_info.low_bytes); merged = merge_bytes(cf->constant_pool[i].info.double_info.high_bytes, cf->constant_pool[i].info.double_info.low_bytes);
printf("\t%lf\n", *(double*)&merged); printf("\t%lf\n", *(double*)&merged);
i++;
break; break;
case CONSTANT_Class: case CONSTANT_Class:
printf("\t#%hu\t\t\t// %s\n", cf->constant_pool[i].info.class_info.name_index, printf("\t#%hu\t\t\t// %s\n", cf->constant_pool[i].info.class_info.name_index,
@ -393,9 +430,51 @@ void ClassFile_info(const ClassFile* cf) {
} }
} }
// class
char* this_name = (char*)cf->constant_pool[cf->constant_pool[cf->this_class - 1].info.class_info.name_index - 1].info.utf8_info.bytes;
char* super_name =
cf->super_class != 0 ? (char*)cf->constant_pool[cf->constant_pool[cf->super_class - 1].info.class_info.name_index - 1].info.utf8_info.bytes : NULL;
char* type = (cf->access_flags & ACC_INTERFACE ? "interface" : (cf->access_flags & ACC_ENUM ? "enum" : (cf->access_flags & ACC_MODULE ? "module" : "class")));
printf("%s%s%s%s %s%s%s ", cf->access_flags & ACC_PUBLIC ? "public " : "", cf->access_flags & ACC_FINAL ? "final " : "",
cf->access_flags & ACC_ABSTRACT ? "abstract " : "", type, this_name, super_name ? " extends " : "", super_name ? super_name : "");
// interfaces // interfaces
if (cf->interfaces_count > 0)
printf("implements ");
for (u2 i = 0; i < cf->interfaces_count; i++) {
printf("%s ", cf->constant_pool[cf->interfaces[i] - 1].info.utf8_info.bytes);
}
printf("{\n");
// fields // fields
for (u2 i = 0; i < cf->fields_count; i++) {
u2 flags = cf->fields[i].access_flags;
char* access = flags & ACC_PUBLIC ? "public" : flags & ACC_PRIVATE ? "private" : flags & ACC_PROTECTED ? "protected" : "";
char* descriptor = (char*)cf->constant_pool[cf->fields[i].descriptor_index - 1].info.utf8_info.bytes;
char* name = (char*)cf->constant_pool[cf->fields[i].name_index - 1].info.utf8_info.bytes;
printf("\t%s %s%s%s%s %s", access, flags & ACC_STATIC ? "static " : "", flags & ACC_FINAL ? "final " : "", flags & ACC_VOLATLE ? "volatile " : "",
descriptor, name);
for (u2 j = 0; j < cf->fields[i].attributes_count; j++) {
switch (cf->fields[i].attributes[j]._tag) {
case CONSTANT_VALUE:
break;
case BOOTSTRAP_METHODS:
break;
case NEST_HOST:
break;
case NEST_MEMBERS:
break;
case PERMITTED_SUBCLASSES:
break;
default:
break;
}
}
printf(";\n");
}
// methods // methods
} }

View File

@ -261,12 +261,14 @@ typedef struct {
} StackMapTable_attribute; } StackMapTable_attribute;
typedef struct { typedef struct {
u2 num_bootstrap_methods;
struct {
u2 bootstrap_method_ref; u2 bootstrap_method_ref;
u2 num_bootstrap_arguments; u2 num_bootstrap_arguments;
u2* bootstrap_arguments; u2* bootstrap_arguments;
} * bootstrap_methods; } BootstrapMethod;
typedef struct {
u2 num_bootstrap_methods;
BootstrapMethod* bootstrap_methods;
} BootstrapMethods_attribute; } BootstrapMethods_attribute;
typedef struct { typedef struct {
@ -283,9 +285,26 @@ typedef struct {
u2* classes; u2* classes;
} PermittedSubclasses_attribute; } PermittedSubclasses_attribute;
typedef enum {
UNKNOWN,
CONSTANT_VALUE,
CODE,
STACK_MAP_TABLE,
BOOTSTRAP_METHODS,
NEST_HOST,
NEST_MEMBERS,
PERMITTED_SUBCLASSES,
ATTRIBUTE_TAGS_END
} ATTRIBUTE_TAGS;
static const char* ATTRIBUTE_TAGS_STRINGS[] = {
"ConstantValue", "Code", "StackMapTable", "BootstrapMethods", "NestHost", "NestMembers", "PermittedSubclasses",
};
typedef struct { typedef struct {
u2 attribute_name_index; u2 attribute_name_index;
u4 attribute_length; u4 attribute_length;
ATTRIBUTE_TAGS _tag;
union { union {
ConstantValue_attribute constant_value_attribute; ConstantValue_attribute constant_value_attribute;
Code_attribute code_attribute; Code_attribute code_attribute;