better info printing

This commit is contained in:
Benedek László 2024-04-13 11:56:14 +02:00
parent 0c697627aa
commit 5228c765ef
2 changed files with 119 additions and 1 deletions

View File

@ -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;
}

View File

@ -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()