summaryrefslogtreecommitdiffstats
path: root/depends/classparser/src/classfile.h
blob: a5e7ee50d85338c4ae5c8ed6c7933f1fe3ebba5f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#pragma once
#include "membuffer.h"
#include "constants.h"
#include "annotations.h"
#include <map>
namespace java
{
/**
 * Class representing a Java .class file
 */
class classfile : public util::membuffer
{
public:
	classfile(char *data, std::size_t size) : membuffer(data, size)
	{
		valid = false;
		is_synthetic = false;
		read_be(magic);
		if (magic != 0xCAFEBABE)
			throw new classfile_exception();
		read_be(minor_version);
		read_be(major_version);
		constants.load(*this);
		read_be(access_flags);
		read_be(this_class);
		read_be(super_class);

		// Interfaces
		uint16_t iface_count = 0;
		read_be(iface_count);
		while (iface_count)
		{
			uint16_t iface;
			read_be(iface);
			interfaces.push_back(iface);
			iface_count--;
		}

		// Fields
		// read fields (and attributes from inside fields) (and possible inner classes. yay for
		// recursion!)
		// for now though, we will ignore all attributes
		/*
		 * field_info
		 * {
		 * 	u2 access_flags;
		 * 	u2 name_index;
		 * 	u2 descriptor_index;
		 * 	u2 attributes_count;
		 * 	attribute_info attributes[attributes_count];
		 * }
		 */
		uint16_t field_count = 0;
		read_be(field_count);
		while (field_count)
		{
			// skip field stuff
			skip(6);
			// and skip field attributes
			uint16_t attr_count = 0;
			read_be(attr_count);
			while (attr_count)
			{
				skip(2);
				uint32_t attr_length = 0;
				read_be(attr_length);
				skip(attr_length);
				attr_count--;
			}
			field_count--;
		}

		// class methods
		/*
		 * method_info
		 * {
		 * 	u2 access_flags;
		 * 	u2 name_index;
		 * 	u2 descriptor_index;
		 * 	u2 attributes_count;
		 * 	attribute_info attributes[attributes_count];
		 * }
		 */
		uint16_t method_count = 0;
		read_be(method_count);
		while (method_count)
		{
			skip(6);
			// and skip method attributes
			uint16_t attr_count = 0;
			read_be(attr_count);
			while (attr_count)
			{
				skip(2);
				uint32_t attr_length = 0;
				read_be(attr_length);
				skip(attr_length);
				attr_count--;
			}
			method_count--;
		}

		// class attributes
		// there are many kinds of attributes. this is just the generic wrapper structure.
		// type is decided by attribute name. extensions to the standard are *possible*
		// class annotations are one kind of a attribute (one per class)
		/*
		 * attribute_info
		 * {
		 * 	u2 attribute_name_index;
		 * 	u4 attribute_length;
		 * 	u1 info[attribute_length];
		 * }
		 */
		uint16_t class_attr_count = 0;
		read_be(class_attr_count);
		while (class_attr_count)
		{
			uint16_t name_idx = 0;
			read_be(name_idx);
			uint32_t attr_length = 0;
			read_be(attr_length);

			auto name = constants[name_idx];
			if (name.str_data == "RuntimeVisibleAnnotations")
			{
				uint16_t num_annotations = 0;
				read_be(num_annotations);
				while (num_annotations)
				{
					visible_class_annotations.push_back(annotation::read(*this, constants));
					num_annotations--;
				}
			}
			else
				skip(attr_length);
			class_attr_count--;
		}
		valid = true;
	}
	;
	bool valid;
	bool is_synthetic;
	uint32_t magic;
	uint16_t minor_version;
	uint16_t major_version;
	constant_pool constants;
	uint16_t access_flags;
	uint16_t this_class;
	uint16_t super_class;
	// interfaces this class implements ? must be. investigate.
	std::vector<uint16_t> interfaces;
	// FIXME: doesn't free up memory on delete
	java::annotation_table visible_class_annotations;
};
}