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
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
|
#pragma once
#include "classfile.h"
#include <map>
#include <vector>
namespace java
{
enum element_value_type : uint8_t
{
INVALID = 0,
STRING = 's',
ENUM_CONSTANT = 'e',
CLASS = 'c',
ANNOTATION = '@',
ARRAY = '[', // one array dimension
PRIMITIVE_INT = 'I', // integer
PRIMITIVE_BYTE = 'B', // signed byte
PRIMITIVE_CHAR = 'C', // Unicode character code point in the Basic Multilingual Plane, encoded with UTF-16
PRIMITIVE_DOUBLE = 'D', // double-precision floating-point value
PRIMITIVE_FLOAT = 'F', // single-precision floating-point value
PRIMITIVE_LONG = 'J', // long integer
PRIMITIVE_SHORT = 'S', // signed short
PRIMITIVE_BOOLEAN = 'Z' // true or false
};
/**
* The element_value structure is a discriminated union representing the value of an element-value pair.
* It is used to represent element values in all attributes that describe annotations
* - RuntimeVisibleAnnotations
* - RuntimeInvisibleAnnotations
* - RuntimeVisibleParameterAnnotations
* - RuntimeInvisibleParameterAnnotations).
*
* The element_value structure has the following format:
*/
class element_value
{
protected:
element_value_type type;
constant_pool & pool;
public:
element_value(element_value_type type, constant_pool & pool): type(type), pool(pool) {};
element_value_type getElementValueType()
{
return type;
}
virtual std::string toString() = 0;
static element_value * readElementValue(util::membuffer & input, constant_pool & pool);
};
/**
* Each value of the annotations table represents a single runtime-visible annotation on a program element.
* The annotation structure has the following format:
*/
class annotation
{
public:
typedef std::vector< std::pair<uint16_t, element_value * > > value_list;
protected:
/**
* The value of the type_index item must be a valid index into the constant_pool table.
* The constant_pool entry at that index must be a CONSTANT_Utf8_info (§4.4.7) structure
* representing a field descriptor representing the annotation type corresponding
* to the annotation represented by this annotation structure.
*/
uint16_t type_index;
/**
* map between element_name_index and value.
*
* The value of the element_name_index item must be a valid index into the constant_pool table.
* The constant_pool entry at that index must be a CONSTANT_Utf8_info (§4.4.7) structure representing
* a valid field descriptor (§4.3.2) that denotes the name of the annotation type element represented
* by this element_value_pairs entry.
*/
value_list name_val_pairs;
/**
* Reference to the parent constant pool
*/
constant_pool & pool;
public:
annotation(uint16_t type_index, constant_pool& pool):type_index(type_index), pool(pool) {};
~annotation()
{
for(unsigned i = 0 ; i < name_val_pairs.size(); i++)
{
delete name_val_pairs[i].second;
}
}
void add_pair(uint16_t key, element_value * value)
{
name_val_pairs.push_back(std::make_pair(key, value));
};
value_list::const_iterator begin()
{
return name_val_pairs.cbegin();
}
value_list::const_iterator end()
{
return name_val_pairs.cend();
}
std::string toString();
static annotation * read(util::membuffer & input, constant_pool & pool);
};
typedef std::vector<annotation *> annotation_table;
/// type for simple value annotation elements
class element_value_simple : public element_value
{
protected:
/// index of the constant in the constant pool
uint16_t index;
public:
element_value_simple(element_value_type type, uint16_t index , constant_pool& pool):
element_value(type, pool), index(index)
{
// TODO: verify consistency
};
uint16_t getIndex()
{
return index;
}
virtual std::string toString()
{
return pool[index].toString();
};
};
/// The enum_const_value item is used if the tag item is 'e'.
class element_value_enum : public element_value
{
protected:
/**
* The value of the type_name_index item must be a valid index into the constant_pool table.
* The constant_pool entry at that index must be a CONSTANT_Utf8_info (§4.4.7) structure
* representing a valid field descriptor (§4.3.2) that denotes the internal form of the binary
* name (§4.2.1) of the type of the enum constant represented by this element_value structure.
*/
uint16_t typeIndex;
/**
* The value of the const_name_index item must be a valid index into the constant_pool table.
* The constant_pool entry at that index must be a CONSTANT_Utf8_info (§4.4.7) structure
* representing the simple name of the enum constant represented by this element_value structure.
*/
uint16_t valueIndex;
public:
element_value_enum(element_value_type type, uint16_t typeIndex, uint16_t valueIndex, constant_pool& pool):
element_value(type, pool), typeIndex(typeIndex), valueIndex(valueIndex)
{
// TODO: verify consistency
}
uint16_t getValueIndex()
{
return valueIndex;
}
uint16_t getTypeIndex()
{
return typeIndex;
}
virtual std::string toString()
{
return "enum value";
};
};
class element_value_class : public element_value
{
protected:
/**
* The class_info_index item must be a valid index into the constant_pool table.
* The constant_pool entry at that index must be a CONSTANT_Utf8_info (§4.4.7) structure
* representing the return descriptor (§4.3.3) of the type that is reified by the class
* represented by this element_value structure.
*
* For example, 'V' for Void.class, 'Ljava/lang/Object;' for Object, etc.
*
* Or in plain english, you can store type information in annotations. Yay.
*/
uint16_t classIndex;
public:
element_value_class(element_value_type type, uint16_t classIndex, constant_pool& pool):
element_value(type, pool), classIndex(classIndex)
{
// TODO: verify consistency
}
uint16_t getIndex()
{
return classIndex;
}
virtual std::string toString()
{
return "class";
};
};
/// nested annotations... yay
class element_value_annotation : public element_value
{
private:
annotation * nestedAnnotation;
public:
element_value_annotation(element_value_type type, annotation * nestedAnnotation, constant_pool& pool):
element_value(type, pool), nestedAnnotation(nestedAnnotation)
{};
~element_value_annotation()
{
if(nestedAnnotation)
{
delete nestedAnnotation;
nestedAnnotation = nullptr;
}
}
virtual std::string toString()
{
return "nested annotation";
};
};
/// and arrays!
class element_value_array : public element_value
{
public:
typedef std::vector <element_value *> elem_vec;
protected:
elem_vec values;
public:
element_value_array ( element_value_type type, std::vector <element_value *>& values, constant_pool& pool ):
element_value(type, pool), values(values)
{};
~element_value_array ()
{
for(unsigned i = 0; i < values.size();i++)
{
delete values[i];
}
};
elem_vec::const_iterator begin()
{
return values.cbegin();
}
elem_vec::const_iterator end()
{
return values.cend();
}
virtual std::string toString()
{
return "array";
};
};
}
|