Skip to content

Commit 001770a

Browse files
authored
Merge pull request #14 from hankluo6/string
Support java string and concatenation
2 parents 12b7af8 + 32eedd6 commit 001770a

File tree

11 files changed

+350
-8
lines changed

11 files changed

+350
-8
lines changed

Makefile

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,8 @@ TESTS = \
5050
Static \
5151
Invokevirtual \
5252
Inherit \
53-
Initializer
53+
Initializer \
54+
Strings
5455

5556
check: $(addprefix tests/,$(TESTS:=-result.out))
5657

class-heap.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,15 @@ void free_class_heap()
109109
}
110110
free(class_heap.class_info[i]->clazz->methods);
111111

112+
bootmethods_attr_t *bootstrap =
113+
class_heap.class_info[i]->clazz->bootstrap;
114+
if (bootstrap) {
115+
for (u2 j = 0; j < bootstrap->num_bootstrap_methods; j++)
116+
free(bootstrap->bootstrap_methods[j].bootstrap_arguments);
117+
free(bootstrap->bootstrap_methods);
118+
free(bootstrap);
119+
}
120+
112121
free(class_heap.class_info[i]->clazz);
113122
free(class_heap.class_info[i]->name);
114123
free(class_heap.class_info[i]);

classfile.c

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ class_info_t *get_class_info(FILE *class_file)
2222
}
2323

2424
/**
25-
* Get the number of integer parameters that a method takes.
25+
* Get the number of parameters that a method takes.
2626
* Use the descriptor string of the method to determine its signature.
2727
*/
2828
uint16_t get_number_of_parameters(method_t *method)
@@ -175,6 +175,15 @@ char *find_class_name_from_index(uint16_t idx, class_file_t *clazz)
175175
return (char *) name->info;
176176
}
177177

178+
bootmethods_t *find_bootstrap_method(uint16_t idx, class_file_t *clazz)
179+
{
180+
const_pool_info *info = get_constant(&clazz->constant_pool, idx);
181+
assert(info->tag == CONSTANT_InvokeDynamic && "Expected a InvokeDynanmic");
182+
return &clazz->bootstrap
183+
->bootstrap_methods[((CONSTANT_InvokeDynamic_info *) info->info)
184+
->bootstrap_method_attr_index];
185+
}
186+
178187
void read_field_attributes(FILE *class_file, field_info *info)
179188
{
180189
for (u2 i = 0; i < info->attributes_count; i++) {
@@ -223,6 +232,54 @@ void read_method_attributes(FILE *class_file,
223232
assert(found_code && "Missing method code");
224233
}
225234

235+
bootmethods_attr_t *read_bootstrap_attribute(FILE *class_file,
236+
constant_pool_t *cp)
237+
{
238+
u2 attributes_count = read_u2(class_file);
239+
for (u2 i = 0; i < attributes_count; i++) {
240+
attribute_info ainfo = {
241+
.attribute_name_index = read_u2(class_file),
242+
.attribute_length = read_u4(class_file),
243+
};
244+
long attribute_end = ftell(class_file) + ainfo.attribute_length;
245+
const_pool_info *type_constant =
246+
get_constant(cp, ainfo.attribute_name_index);
247+
assert(type_constant->tag == CONSTANT_Utf8 && "Expected a UTF8");
248+
if (!strcmp((char *) type_constant->info, "BootstrapMethods")) {
249+
bootmethods_attr_t *bootstrap = malloc(sizeof(*bootstrap));
250+
251+
bootstrap->num_bootstrap_methods = read_u2(class_file);
252+
bootstrap->bootstrap_methods = malloc(
253+
sizeof(bootmethods_t) * bootstrap->num_bootstrap_methods);
254+
255+
assert(bootstrap->bootstrap_methods &&
256+
"Failed to allocate bootstrap method");
257+
for (int j = 0; j < bootstrap->num_bootstrap_methods; ++j) {
258+
bootstrap->bootstrap_methods[j].bootstrap_method_ref =
259+
read_u2(class_file);
260+
bootstrap->bootstrap_methods[j].num_bootstrap_arguments =
261+
read_u2(class_file);
262+
bootstrap->bootstrap_methods[j].bootstrap_arguments = malloc(
263+
sizeof(u2) *
264+
bootstrap->bootstrap_methods[j].num_bootstrap_arguments);
265+
assert(bootstrap->bootstrap_methods[j].bootstrap_arguments &&
266+
"Failed to allocate bootstrap argument");
267+
for (int k = 0;
268+
k <
269+
bootstrap->bootstrap_methods[j].num_bootstrap_arguments;
270+
++k) {
271+
bootstrap->bootstrap_methods[j].bootstrap_arguments[k] =
272+
read_u2(class_file);
273+
}
274+
}
275+
return bootstrap;
276+
}
277+
/* Skip the rest of the attribute */
278+
fseek(class_file, attribute_end, SEEK_SET);
279+
}
280+
return NULL;
281+
}
282+
226283
#define IS_STATIC 0x0008
227284

228285
field_t *get_fields(FILE *class_file, constant_pool_t *cp, class_file_t *clazz)
@@ -311,6 +368,10 @@ class_file_t get_class(FILE *class_file)
311368
/* Read the list of static methods */
312369
clazz.methods = get_methods(class_file, &clazz.constant_pool);
313370

371+
/* Read the list of attributes */
372+
clazz.bootstrap =
373+
read_bootstrap_attribute(class_file, &clazz.constant_pool);
374+
314375
clazz.initialized = false;
315376

316377
return clazz;

classfile.h

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,12 +54,26 @@ typedef struct {
5454
variable_t *static_var; /* store static fields in the class */
5555
} field_t;
5656

57+
typedef struct {
58+
u2 bootstrap_method_ref;
59+
u2 num_bootstrap_arguments;
60+
u2 *bootstrap_arguments;
61+
} bootmethods_t;
62+
63+
typedef struct {
64+
u2 attribute_name_index;
65+
u4 attribute_length;
66+
u2 num_bootstrap_methods;
67+
bootmethods_t *bootstrap_methods;
68+
} bootmethods_attr_t;
69+
5770
typedef struct class_file {
5871
constant_pool_t constant_pool;
5972
class_info_t *info;
6073
method_t *methods;
6174
field_t *fields;
6275
u2 fields_count;
76+
bootmethods_attr_t *bootstrap;
6377
bool initialized;
6478
struct class_file *next;
6579
struct class_file *prev;
@@ -89,4 +103,7 @@ char *find_field_info_from_index(uint16_t idx,
89103
char **name_info,
90104
char **descriptor_info);
91105
void read_field_attributes(FILE *class_file, field_info *info);
106+
bootmethods_t *find_bootstrap_method(uint16_t idx, class_file_t *clazz);
107+
bootmethods_attr_t *read_bootstrap_attribute(FILE *class_file,
108+
constant_pool_t *cp);
92109
field_t *get_fields(FILE *class_file, constant_pool_t *cp, class_file_t *clazz);

constant-pool.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,23 @@ CONSTANT_Class_info *get_class_name(constant_pool_t *cp, u2 idx)
4848
return (CONSTANT_Class_info *) class->info;
4949
}
5050

51+
CONSTANT_MethodHandle_info *get_method_handle(constant_pool_t *cp, u2 idx)
52+
{
53+
const_pool_info *handle = get_constant(cp, idx);
54+
assert(handle->tag == CONSTANT_MethodHandle && "Expected a MethodHandle");
55+
return (CONSTANT_MethodHandle_info *) handle->info;
56+
}
57+
58+
char *get_string_utf(constant_pool_t *cp, u2 idx)
59+
{
60+
const_pool_info *str = get_constant(cp, idx);
61+
assert(str->tag == CONSTANT_String && "Expected a String");
62+
const_pool_info *utf8 =
63+
get_constant(cp, ((CONSTANT_String_info *) str->info)->string_index);
64+
assert(utf8->tag == CONSTANT_Utf8 && "Expected a UTF8");
65+
return (char *) utf8->info;
66+
}
67+
5168
constant_pool_t get_constant_pool(FILE *class_file)
5269
{
5370
constant_pool_t cp = {
@@ -120,6 +137,32 @@ constant_pool_t get_constant_pool(FILE *class_file)
120137
break;
121138
}
122139

140+
case CONSTANT_String: {
141+
CONSTANT_String_info *value = malloc(sizeof(*value));
142+
assert(value && "Failed to allocate String constant");
143+
value->string_index = read_u2(class_file);
144+
constant->info = (u1 *) value;
145+
break;
146+
}
147+
148+
case CONSTANT_InvokeDynamic: {
149+
CONSTANT_InvokeDynamic_info *value = malloc(sizeof(*value));
150+
assert(value && "Failed to allocate InvokeDynamic constant");
151+
value->bootstrap_method_attr_index = read_u2(class_file);
152+
value->name_and_type_index = read_u2(class_file);
153+
constant->info = (u1 *) value;
154+
break;
155+
}
156+
157+
case CONSTANT_MethodHandle: {
158+
CONSTANT_MethodHandle_info *value = malloc(sizeof(*value));
159+
assert(value && "Failed to allocate MethodHandle constant");
160+
value->reference_kind = read_u1(class_file);
161+
value->reference_index = read_u2(class_file);
162+
constant->info = (u1 *) value;
163+
break;
164+
}
165+
123166
default:
124167
fprintf(stderr, "Unknown constant type %d\n", constant->tag);
125168
exit(1);

constant-pool.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,12 @@ typedef enum {
1313
CONSTANT_Integer = 3,
1414
CONSTANT_Long = 5,
1515
CONSTANT_Class = 7,
16+
CONSTANT_String = 8,
1617
CONSTANT_FieldRef = 9,
1718
CONSTANT_MethodRef = 10,
1819
CONSTANT_NameAndType = 12,
20+
CONSTANT_MethodHandle = 15,
21+
CONSTANT_InvokeDynamic = 18,
1922
} const_pool_tag_t;
2023

2124
typedef struct {
@@ -41,6 +44,20 @@ typedef struct {
4144
u2 descriptor_index;
4245
} CONSTANT_NameAndType_info;
4346

47+
typedef struct {
48+
u2 string_index;
49+
} CONSTANT_String_info;
50+
51+
typedef struct {
52+
u2 bootstrap_method_attr_index;
53+
u2 name_and_type_index;
54+
} CONSTANT_InvokeDynamic_info;
55+
56+
typedef struct {
57+
u1 reference_kind;
58+
u2 reference_index;
59+
} CONSTANT_MethodHandle_info;
60+
4461
typedef struct {
4562
const_pool_tag_t tag;
4663
u1 *info;
@@ -58,3 +75,5 @@ const_pool_info *get_constant(constant_pool_t *constant_pool, u2 index);
5875
constant_pool_t get_constant_pool(FILE *class_file);
5976
CONSTANT_FieldOrMethodRef_info *get_methodref(constant_pool_t *cp, u2 idx);
6077
CONSTANT_Class_info *get_class_name(constant_pool_t *cp, u2 idx);
78+
CONSTANT_MethodHandle_info *get_method_handle(constant_pool_t *cp, u2 idx);
79+
char *get_string_utf(constant_pool_t *cp, u2 idx);

0 commit comments

Comments
 (0)