better info printing
This commit is contained in:
parent
0c697627aa
commit
5228c765ef
95
classfile.c
95
classfile.c
@ -2,6 +2,7 @@
|
||||
#include <assert.h>
|
||||
#include <memory.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
@ -37,6 +38,10 @@ void read_u4(void* ptr, size_t n, FILE* file) {
|
||||
memcpy(ptr, &buffer, n * sizeof(u4));
|
||||
}
|
||||
|
||||
uint64_t merge_bytes(uint32_t high, uint32_t low) {
|
||||
return ((uint64_t)high) << 32 | low;
|
||||
}
|
||||
|
||||
stack_frame_type stack_frame_type_enum(u2 frame_type) {
|
||||
if (0 <= frame_type && frame_type <= 63) {
|
||||
return SAME;
|
||||
@ -214,10 +219,12 @@ ClassFile* ClassFile_load(const char* path) {
|
||||
case CONSTANT_Long:
|
||||
read_u4(&(cp->info.long_info.high_bytes), 1, file);
|
||||
read_u4(&(cp->info.long_info.low_bytes), 1, file);
|
||||
i++; // Oracle docs: 4.4.5: 'In retrospect, making 8-byte constants take two constant pool entries was a poor choice.'
|
||||
break;
|
||||
case CONSTANT_Double:
|
||||
read_u4(&(cp->info.double_info.high_bytes), 1, file);
|
||||
read_u4(&(cp->info.double_info.low_bytes), 1, file);
|
||||
i++; // Oracle docs: 4.4.5: 'In retrospect, making 8-byte constants take two constant pool entries was a poor choice.'
|
||||
break;
|
||||
case CONSTANT_NameAndType:
|
||||
read_u2(&(cp->info.name_and_type_info.name_index), 1, file);
|
||||
@ -251,7 +258,7 @@ ClassFile* ClassFile_load(const char* path) {
|
||||
break;
|
||||
default:
|
||||
printf("unknown constant tag: %hhu\n", cp->tag);
|
||||
// assert(0);
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
@ -331,4 +338,90 @@ void ClassFile_info(const ClassFile* cf) {
|
||||
"attributes_count=%hu\n",
|
||||
cf->magic, cf->minor_version, cf->major_version, cf->constant_pool_count, cf->access_flags, cf->this_class, cf->super_class, cf->interfaces_count,
|
||||
cf->fields_count, cf->methods_count, cf->attributes_count);
|
||||
|
||||
// constants
|
||||
printf("Constant pool:\n");
|
||||
for (u2 i = 0; i < cf->constant_pool_count - 1; i++) {
|
||||
char name[6];
|
||||
sprintf(name, "#%d", i + 1);
|
||||
printf("%5s = %s\t", name, CONSTANT_TAGS_STRINGS[cf->constant_pool[i].tag]);
|
||||
|
||||
uint64_t merged;
|
||||
char* buffer;
|
||||
|
||||
switch (cf->constant_pool[i].tag) {
|
||||
case CONSTANT_Utf8:
|
||||
printf("\t%s\n", cf->constant_pool[i].info.utf8_info.bytes);
|
||||
break;
|
||||
case CONSTANT_Integer:
|
||||
printf("%d\n", cf->constant_pool[i].info.integer_info.bytes);
|
||||
break;
|
||||
case CONSTANT_Float:
|
||||
printf("%f\n", (float)cf->constant_pool[i].info.float_info.bytes);
|
||||
break;
|
||||
case CONSTANT_Long:
|
||||
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);
|
||||
break;
|
||||
case CONSTANT_Double:
|
||||
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);
|
||||
break;
|
||||
case CONSTANT_Class:
|
||||
printf("\t#%hu\t\t\t// %s\n", cf->constant_pool[i].info.class_info.name_index,
|
||||
cf->constant_pool[cf->constant_pool[i].info.class_info.name_index - 1].info.utf8_info.bytes);
|
||||
break;
|
||||
case CONSTANT_String:
|
||||
printf("\t#%hu\t\t\t// %s\n", cf->constant_pool[i].info.string_info.string_index,
|
||||
cf->constant_pool[cf->constant_pool[i].info.string_info.string_index - 1].info.utf8_info.bytes);
|
||||
break;
|
||||
case CONSTANT_Fieldref:
|
||||
case CONSTANT_Methodref:
|
||||
case CONSTANT_InterfaceMethodref:
|
||||
buffer = ClassFile_resolve_Fieldref_Methodref_InterfaceMethodref(cf, cf->constant_pool[i].info.fieldref_info);
|
||||
printf("#%hu.#%hu\t\t\t// %s", cf->constant_pool[i].info.fieldref_info.class_index, cf->constant_pool[i].info.fieldref_info.name_and_type_index,
|
||||
buffer);
|
||||
free(buffer);
|
||||
break;
|
||||
case CONSTANT_NameAndType:
|
||||
buffer = ClassFile_resolve_NameAnyType(cf, cf->constant_pool[i].info.name_and_type_info);
|
||||
printf("#%hu:#%hu\t\t\t// %s", cf->constant_pool[i].info.name_and_type_info.name_index, cf->constant_pool[i].info.name_and_type_info.descriptor_index,
|
||||
buffer);
|
||||
free(buffer);
|
||||
default:
|
||||
putchar('\n');
|
||||
}
|
||||
}
|
||||
|
||||
// interfaces
|
||||
|
||||
// fields
|
||||
|
||||
// methods
|
||||
}
|
||||
|
||||
char* ClassFile_resolve_NameAnyType(const ClassFile* cf, CONSTANT_NameAndType_info info) {
|
||||
CONSTANT_Utf8_info name = cf->constant_pool[info.name_index - 1].info.utf8_info;
|
||||
CONSTANT_Utf8_info descriptor = cf->constant_pool[info.descriptor_index - 1].info.utf8_info;
|
||||
|
||||
char* buffer = (char*)malloc(name.length + descriptor.length + 2);
|
||||
|
||||
sprintf(buffer, "%s:%s", name.bytes, descriptor.bytes);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
char* ClassFile_resolve_Fieldref_Methodref_InterfaceMethodref(const ClassFile* cf, CONSTANT_Fieldref_info info) {
|
||||
CONSTANT_Class_info class_info = cf->constant_pool[info.class_index - 1].info.class_info;
|
||||
CONSTANT_NameAndType_info name_and_type_info = cf->constant_pool[info.name_and_type_index - 1].info.name_and_type_info;
|
||||
|
||||
CONSTANT_Utf8_info class_name = cf->constant_pool[class_info.name_index - 1].info.utf8_info;
|
||||
CONSTANT_Utf8_info name = cf->constant_pool[name_and_type_info.name_index - 1].info.utf8_info;
|
||||
CONSTANT_Utf8_info descriptor = cf->constant_pool[name_and_type_info.descriptor_index - 1].info.utf8_info;
|
||||
|
||||
char* buffer = (char*)malloc(class_name.length + name.length + descriptor.length + 3);
|
||||
|
||||
sprintf(buffer, "%s.%s:%s\n", class_name.bytes, name.bytes, descriptor.bytes);
|
||||
|
||||
return buffer;
|
||||
}
|
25
classfile.h
25
classfile.h
@ -51,6 +51,28 @@ typedef enum {
|
||||
CONSTANT_Package = 20,
|
||||
} CONSTANT_TAGS;
|
||||
|
||||
static const char* CONSTANT_TAGS_STRINGS[] = {"",
|
||||
"UTF-8",
|
||||
"",
|
||||
"Interger",
|
||||
"Float",
|
||||
"Long",
|
||||
"Double",
|
||||
"Class",
|
||||
"String",
|
||||
"Fieldref",
|
||||
"Methodref",
|
||||
"InterfaceMethodref",
|
||||
"NameAndType",
|
||||
"",
|
||||
"",
|
||||
"MethodHandle",
|
||||
"MethodType",
|
||||
"Dynamic",
|
||||
"InvokeDynamic",
|
||||
"Module",
|
||||
"Package"};
|
||||
|
||||
typedef struct {
|
||||
u2 name_index;
|
||||
} CONSTANT_Class_info;
|
||||
@ -313,4 +335,7 @@ typedef struct {
|
||||
ClassFile* ClassFile_load(const char* path);
|
||||
void ClassFile_info(const ClassFile* cf);
|
||||
|
||||
char* ClassFile_resolve_Fieldref_Methodref_InterfaceMethodref(const ClassFile* cf, CONSTANT_Fieldref_info info);
|
||||
char* ClassFile_resolve_NameAnyType(const ClassFile* cf, CONSTANT_NameAndType_info info);
|
||||
|
||||
#pragma pack()
|
Loading…
Reference in New Issue
Block a user