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 60c2e6f

Browse files
committed
initial commit
0 parents commit 60c2e6f

File tree

10 files changed

+667
-0
lines changed

10 files changed

+667
-0
lines changed

‎Makefile

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
CC=gcc
2+
TARGET=class_parser.a
3+
4+
all:
5+
$(CC) main.c class_reader.c class_reader.h pretty_printer.c pretty_printer.h -o $(TARGET)
6+
7+
clean:
8+
rm $(TARGET)

‎README.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
## Вывод данных пула констант
2+
Программа для парсинга .class файлов и извлечения из них пула констант. Примером работы являлся инструмент `javap`.
3+
4+
Сборка осуществляется посрдством утилиты `make`:
5+
```
6+
$ make
7+
gcc main.c class_reader.c class_reader.h pretty_printer.c pretty_printer.h -o class_parser.a
8+
```
9+
10+
Пример запуска:
11+
```
12+
$ ./class_parser.a examples/MyTcpForwardServer.class
13+
minor version: 0
14+
major version: 55
15+
16+
#1 = MethodRef #39.#77 // java/lang/Object.<init>:()V
17+
#2 = Class #78 // org/apache/commons/cli/Options
18+
#3 = MethodRef #2.#77 // org/apache/commons/cli/Options.<init>:()V
19+
#4 = Class #79 // org/apache/commons/cli/Option
20+
#5 = String #80 // h
21+
#6 = String #81 // destination-host
22+
#7 = String #82 // host to forward
23+
#8 = MethodRef #4.#83 // org/apache/commons/cli/Option.<init>:(Ljava/lang/String;Ljava/lang/String;ZLjava/lang/String;)V
24+
#9 = String #84 // p
25+
#10 = String #59 // port
26+
#11 = String #85 // port to listen
27+
#12 = String #86 // hp
28+
#13 = String #87 // host-port
29+
#14 = String #88 // host port
30+
#15 = MethodRef #4.#89 // org/apache/commons/cli/Option.setRequired:(Z)V
31+
#16 = MethodRef #2.#90 // org/apache/commons/cli/Options.addOption:(Lorg/apache/commons/cli/Option;)Lorg/apache/commons/cli/Options;
32+
#17 = Class #91 // org/apache/commons/cli/DefaultParser
33+
#18 = MethodRef #17.#77 // org/apache/commons/cli/DefaultParser.<init>:()V
34+
...
35+
```
36+
37+
По примеру запуска видно, что мне удалось воссоздать точную копию вывода пула констант как из `javap`.
38+
39+
В папке `examples` можно найти парочку `.class` файлов которые я позаимствовал из лаб 5 семестра.

‎class_reader.c

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
/**
2+
* A program to output the contents of constant_pool
3+
* by parsing java .class files as that's made in javap tool.
4+
*
5+
* This code is written as an assignment to understand
6+
* the structure of the class files.
7+
*
8+
* Author: Aleksandr Ushaev
9+
* Created: 14.02.2020
10+
*
11+
*/
12+
13+
#include "class_reader.h"
14+
15+
/**
16+
* Attempts to open a file, on success checks
17+
* if the file is a valid .class file.
18+
*
19+
* @param path of the file to open
20+
* @return file if it is valid .class file
21+
*/
22+
FILE *open_class_file(char *path)
23+
{
24+
FILE *file = fopen(path, "rb");
25+
26+
if (!file)
27+
{
28+
perror("Error ");
29+
exit(EXIT_FAILURE);
30+
}
31+
32+
if (!is_class_file(file))
33+
{
34+
fprintf(stderr, "This file is not a .class file!\n");
35+
exit(0);
36+
}
37+
38+
return file;
39+
}
40+
41+
/**
42+
* Checks the file for a magic value 0xcafebabe
43+
*
44+
* @param file to check
45+
* @return true if file contatins magic value
46+
*/
47+
bool is_class_file(FILE *file)
48+
{
49+
uint32_t magic_number;
50+
size_t read_cnt = fread(&magic_number, sizeof(uint32_t), 1, file);
51+
magic_number = be32toh(magic_number);
52+
return read_cnt == 1 && magic_number == MAGIC_NUMBER;
53+
}
54+
55+
/**
56+
* Reads minor, major versions, constant pool size
57+
* and constant pool from a file
58+
*
59+
* @param file to read from
60+
* @return class struct filled with collected data
61+
*/
62+
class *parse_class_file(FILE *class_file)
63+
{
64+
class *cls = (class *)malloc(sizeof(class));
65+
66+
// Read header
67+
parse_u2(class_file, &cls->minor_version);
68+
parse_u2(class_file, &cls->major_version);
69+
parse_u2(class_file, &cls->constant_pool_count);
70+
71+
parse_constant_pool(class_file, cls);
72+
fclose(class_file);
73+
return cls;
74+
}
75+
76+
/**
77+
* Reads an "unsigned two-byte quantity" from a file
78+
*
79+
* @param file to read from
80+
* @param variable to write
81+
*/
82+
void parse_u2(FILE *class_file, uint16_t *cls)
83+
{
84+
fread(cls, sizeof(uint16_t), 1, class_file);
85+
(*cls) = be16toh((*cls));
86+
}
87+
88+
/**
89+
* Parse symbolic information from the "constant_pool" table
90+
* from a file
91+
*
92+
* @param file to read from
93+
* @param class struct to write
94+
*/
95+
void parse_constant_pool(FILE *class_file, class *cls)
96+
{
97+
const uint16_t total_constants_count = cls->constant_pool_count - 1;
98+
cls->constant_pool = malloc(total_constants_count * sizeof(constant_info));
99+
uint8_t tag;
100+
101+
CONSTANT_Class_info class_info;
102+
CONSTANT_Ref_info ref_info;
103+
CONSTANT_String_info string_info;
104+
CONSTANT_IntFloat_info int_float_info;
105+
CONSTANT_LongDouble_info long_double_info;
106+
CONSTANT_Utf8_info utf_info;
107+
CONSTANT_MethodHandle_info method_handle_info;
108+
CONSTANT_MethodType_info method_type_info;
109+
CONSTANT_InvokeDynamic_info invoke_info;
110+
111+
for (int i = 1; i <= total_constants_count; i++)
112+
{
113+
constant_info *cur_constant_info = cls->constant_pool + (i - 1);
114+
fread(&tag, sizeof(uint8_t), 1, class_file);
115+
116+
switch (tag)
117+
{
118+
case CONSTANT_Class:
119+
fread(&class_info.name_index, sizeof(class_info.name_index), 1, class_file);
120+
class_info.tag = tag;
121+
class_info.name_index = be16toh(class_info.name_index);
122+
cur_constant_info->class_i = class_info;
123+
break;
124+
125+
case CONSTANT_Fieldref:
126+
case CONSTANT_InterfaceMethodref:
127+
case CONSTANT_Methodref:
128+
case CONSTANT_NameAndType:
129+
fread(&ref_info.class_index, sizeof(ref_info.class_index), 1, class_file);
130+
fread(&ref_info.name_and_type_index, sizeof(ref_info.name_and_type_index), 1, class_file);
131+
ref_info.tag = tag;
132+
ref_info.class_index = be16toh(ref_info.class_index);
133+
ref_info.name_and_type_index = be16toh(ref_info.name_and_type_index);
134+
cur_constant_info->ref_i = ref_info;
135+
break;
136+
137+
case CONSTANT_String:
138+
fread(&string_info.string_index, sizeof(string_info.string_index), 1, class_file);
139+
string_info.tag = tag;
140+
string_info.string_index = be16toh(string_info.string_index);
141+
cur_constant_info->string_i = string_info;
142+
break;
143+
144+
case CONSTANT_Integer:
145+
case CONSTANT_Float:
146+
fread(&int_float_info.bytes, sizeof(int_float_info.bytes), 1, class_file);
147+
int_float_info.tag = tag;
148+
int_float_info.bytes = be32toh(int_float_info.bytes);
149+
cur_constant_info->int_float_i = int_float_info;
150+
break;
151+
152+
case CONSTANT_Long:
153+
case CONSTANT_Double:
154+
fread(&long_double_info.high_bytes, sizeof(long_double_info.high_bytes), 1, class_file);
155+
fread(&long_double_info.low_bytes, sizeof(long_double_info.low_bytes), 1, class_file);
156+
long_double_info.tag = tag;
157+
long_double_info.high_bytes = be32toh(long_double_info.high_bytes);
158+
long_double_info.low_bytes = be32toh(long_double_info.low_bytes);
159+
cur_constant_info->long_double_i = long_double_info;
160+
i++; // Takes two entries
161+
break;
162+
163+
case CONSTANT_Utf8:
164+
fread(&utf_info.length, sizeof(utf_info.length), 1, class_file);
165+
utf_info.length = be16toh(utf_info.length);
166+
utf_info.bytes = malloc(sizeof(char) * (utf_info.length + 1));
167+
fread(utf_info.bytes, sizeof(char), utf_info.length, class_file);
168+
utf_info.bytes[utf_info.length] = '0円';
169+
utf_info.tag = tag;
170+
cur_constant_info->utf_i = utf_info;
171+
break;
172+
173+
case CONSTANT_MethodHandle:
174+
fread(&method_handle_info.reference_kind, sizeof(method_handle_info.reference_kind), 1, class_file);
175+
fread(&method_handle_info.reference_index, sizeof(method_handle_info.reference_index), 1, class_file);
176+
method_handle_info.reference_index = be16toh(method_handle_info.reference_index);
177+
method_handle_info.tag = tag;
178+
cur_constant_info->method_handle_i = method_handle_info;
179+
break;
180+
181+
case CONSTANT_MethodType:
182+
fread(&method_type_info.descriptor_index, sizeof(method_type_info.descriptor_index), 1, class_file);
183+
method_type_info.descriptor_index = be16toh(method_type_info.descriptor_index);
184+
method_type_info.tag = tag;
185+
cur_constant_info->method_type_i = method_type_info;
186+
break;
187+
188+
case CONSTANT_InvokeDynamic:
189+
fread(&invoke_info.bootstrap_method_attr_index, sizeof(invoke_info.bootstrap_method_attr_index), 1, class_file);
190+
fread(&invoke_info.name_and_type_index, sizeof(invoke_info.name_and_type_index), 1, class_file);
191+
invoke_info.bootstrap_method_attr_index = be16toh(invoke_info.bootstrap_method_attr_index);
192+
invoke_info.name_and_type_index = be16toh(invoke_info.name_and_type_index);
193+
invoke_info.tag = tag;
194+
cur_constant_info->invoke_dynamic_i = invoke_info;
195+
break;
196+
197+
default:
198+
fprintf(stderr, "Don't know what to do with %d tag byte :(\n", tag);
199+
cur_constant_info = NULL;
200+
break;
201+
}
202+
}
203+
}

0 commit comments

Comments
(0)

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