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 <assert.h>
|
||||||
#include <memory.h>
|
#include <memory.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@ -37,6 +38,10 @@ void read_u4(void* ptr, size_t n, FILE* file) {
|
|||||||
memcpy(ptr, &buffer, n * sizeof(u4));
|
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) {
|
stack_frame_type stack_frame_type_enum(u2 frame_type) {
|
||||||
if (0 <= frame_type && frame_type <= 63) {
|
if (0 <= frame_type && frame_type <= 63) {
|
||||||
return SAME;
|
return SAME;
|
||||||
@ -214,10 +219,12 @@ ClassFile* ClassFile_load(const char* path) {
|
|||||||
case CONSTANT_Long:
|
case CONSTANT_Long:
|
||||||
read_u4(&(cp->info.long_info.high_bytes), 1, file);
|
read_u4(&(cp->info.long_info.high_bytes), 1, file);
|
||||||
read_u4(&(cp->info.long_info.low_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;
|
break;
|
||||||
case CONSTANT_Double:
|
case CONSTANT_Double:
|
||||||
read_u4(&(cp->info.double_info.high_bytes), 1, file);
|
read_u4(&(cp->info.double_info.high_bytes), 1, file);
|
||||||
read_u4(&(cp->info.double_info.low_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;
|
break;
|
||||||
case CONSTANT_NameAndType:
|
case CONSTANT_NameAndType:
|
||||||
read_u2(&(cp->info.name_and_type_info.name_index), 1, file);
|
read_u2(&(cp->info.name_and_type_info.name_index), 1, file);
|
||||||
@ -251,7 +258,7 @@ ClassFile* ClassFile_load(const char* path) {
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
printf("unknown constant tag: %hhu\n", cp->tag);
|
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",
|
"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->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);
|
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_Package = 20,
|
||||||
} CONSTANT_TAGS;
|
} 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 {
|
typedef struct {
|
||||||
u2 name_index;
|
u2 name_index;
|
||||||
} CONSTANT_Class_info;
|
} CONSTANT_Class_info;
|
||||||
@ -313,4 +335,7 @@ typedef struct {
|
|||||||
ClassFile* ClassFile_load(const char* path);
|
ClassFile* ClassFile_load(const char* path);
|
||||||
void ClassFile_info(const ClassFile* cf);
|
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()
|
#pragma pack()
|
Loading…
Reference in New Issue
Block a user