Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

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)

AltStyle によって変換されたページ (->オリジナル) /