Skip to content

Commit 3b8a070

Browse files
committed
fix for case 984330, static field bytes being reported without any static fields being reported as present.
* changed class crawling to be recursive and now store non inited classes * metadata type reporting will now also report invalid uninitialized types * metadata type reporting will now account for array types being fields inside a class
1 parent 8ac9f63 commit 3b8a070

File tree

1 file changed

+96
-79
lines changed

1 file changed

+96
-79
lines changed

mono/metadata/unity-memory-info.c

Lines changed: 96 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -24,67 +24,82 @@ typedef struct CollectMetadataContext
2424
MonoMetadataSnapshot* metadata;
2525
} CollectMetadataContext;
2626

27-
static void ContextInsertClass(CollectMetadataContext* context, MonoClass* klass)
27+
static void
28+
ContextRecurseClassData (CollectMetadataContext *context, MonoClass *klass)
2829
{
2930
gpointer orig_key, value;
31+
gpointer iter = NULL;
32+
MonoClassField *field = NULL;
33+
int fieldCount;
34+
3035
/* use g_hash_table_lookup_extended as it returns boolean to indicate if value was found.
3136
* If we use g_hash_table_lookup it returns the value which we were comparing to NULL. The problem is
3237
* that 0 is a valid class index and was confusing our logic.
3338
*/
34-
if (klass->inited && !g_hash_table_lookup_extended(context->allTypes, klass, &orig_key, &value))
35-
g_hash_table_insert(context->allTypes, klass, GINT_TO_POINTER(context->currentIndex++));
39+
if (!g_hash_table_lookup_extended (context->allTypes, klass, &orig_key, &value))
40+
g_hash_table_insert (context->allTypes, klass, GINT_TO_POINTER (context->currentIndex++));
41+
42+
fieldCount = mono_class_num_fields (klass);
43+
if (fieldCount > 0) {
44+
while ((field = mono_class_get_fields (klass, &iter))) {
45+
MonoClass *fieldKlass = mono_class_from_mono_type (field->type);
46+
47+
if (!g_hash_table_lookup_extended (context->allTypes, fieldKlass, &orig_key, &value))
48+
ContextRecurseClassData (context, fieldKlass);
49+
}
50+
}
3651
}
3752

38-
static void CollectHashMapClass(gpointer key, gpointer value, gpointer user_data)
53+
static void
54+
CollectHashMapClass (gpointer key, gpointer value, gpointer user_data)
3955
{
40-
CollectMetadataContext* context = (CollectMetadataContext*)user_data;
41-
MonoClass* klass = (MonoClass*)value;
42-
ContextInsertClass(context, klass);
56+
CollectMetadataContext *context = (CollectMetadataContext *)user_data;
57+
MonoClass *klass = (MonoClass *)value;
58+
ContextRecurseClassData (context, klass);
4359
}
4460

45-
static void CollectHashMapListClasses(gpointer key, gpointer value, gpointer user_data)
61+
static void
62+
CollectHashMapListClasses (gpointer key, gpointer value, gpointer user_data)
4663
{
47-
CollectMetadataContext* context = (CollectMetadataContext*)user_data;
48-
GSList* list = (GSList*)value;
64+
CollectMetadataContext *context = (CollectMetadataContext *)user_data;
65+
GSList *list = (GSList *)value;
4966

50-
while (list != NULL)
51-
{
52-
MonoClass* klass = (MonoClass*)list->data;
53-
ContextInsertClass(context, klass);
67+
while (list != NULL) {
68+
MonoClass *klass = (MonoClass *)list->data;
69+
ContextRecurseClassData (context, klass);
5470

55-
list = g_slist_next(list);
71+
list = g_slist_next (list);
5672
}
5773
}
5874

59-
static void CollectGenericClass(MonoGenericClass* genericClass, gpointer user_data)
75+
static void
76+
CollectGenericClass (MonoGenericClass *genericClass, gpointer user_data)
6077
{
61-
CollectMetadataContext* context = (CollectMetadataContext*)user_data;
78+
CollectMetadataContext *context = (CollectMetadataContext *)user_data;
6279

6380
if (genericClass->cached_class != NULL)
64-
ContextInsertClass(context, genericClass->cached_class);
81+
ContextRecurseClassData (context, genericClass->cached_class);
6582
}
6683

67-
static void CollectImageMetaData(MonoImage* image, gpointer value, CollectMetadataContext* context)
84+
static void
85+
CollectImageMetaData (MonoImage *image, gpointer value, CollectMetadataContext *context)
6886
{
6987
int i;
7088
MonoTableInfo *tdef = &image->tables[MONO_TABLE_TYPEDEF];
7189
GSList *list;
7290

73-
if (image->dynamic)
74-
{
91+
if (image->dynamic) {
7592
GHashTableIter iter;
7693
gpointer key;
77-
MonoDynamicImage* dynamicImage = (MonoDynamicImage*)image;
94+
MonoDynamicImage *dynamicImage = (MonoDynamicImage *)image;
95+
g_hash_table_iter_init (&iter, dynamicImage->typeref);
7896

79-
g_hash_table_iter_init(&iter, dynamicImage->typeref);
80-
81-
while (g_hash_table_iter_next(&iter, &key, NULL))
82-
{
83-
MonoType* monoType = (MonoType*)key;
84-
MonoClass* klass = mono_type_get_class(monoType);
97+
while (g_hash_table_iter_next (&iter, &key, NULL)) {
98+
MonoType *monoType = (MonoType *)key;
99+
MonoClass *klass = mono_type_get_class (monoType);
85100

86101
if (klass)
87-
ContextInsertClass(context, klass);
102+
ContextRecurseClassData (context, klass);
88103
}
89104
}
90105

@@ -93,119 +108,121 @@ static void CollectImageMetaData(MonoImage* image, gpointer value, CollectMetada
93108
*/
94109
list = image->reflection_info_unregister_classes;
95110

96-
while (list)
97-
{
111+
while (list) {
98112
MonoClass *klass = (MonoClass *)list->data;
99113

100114
if (klass)
101-
ContextInsertClass(context, klass);
115+
ContextRecurseClassData (context, klass);
102116

103117
list = list->next;
104118
}
105119

106-
for (i = 1; i < tdef->rows; ++i)
107-
{
120+
for (i = 1; i < tdef->rows; ++i) {
108121
MonoClass *klass;
109122
MonoError error;
110123

111124
guint32 token = (i + 1) | MONO_TOKEN_TYPE_DEF;
112125

113-
klass = mono_class_get_checked(image, token, &error);
126+
klass = mono_class_get_checked (image, token, &error);
114127

115128
if (klass)
116-
ContextInsertClass(context, klass);
129+
ContextRecurseClassData (context, klass);
117130
}
118131

119132
if (image->array_cache)
120-
g_hash_table_foreach(image->array_cache, CollectHashMapListClasses, context);
133+
g_hash_table_foreach (image->array_cache, CollectHashMapListClasses, context);
121134

122135
if (image->szarray_cache)
123-
g_hash_table_foreach(image->szarray_cache, CollectHashMapClass, context);
136+
g_hash_table_foreach (image->szarray_cache, CollectHashMapClass, context);
124137

125138
if (image->ptr_cache)
126-
g_hash_table_foreach(image->ptr_cache, CollectHashMapClass, context);
139+
g_hash_table_foreach (image->ptr_cache, CollectHashMapClass, context);
127140
}
128141

129-
static int FindClassIndex(GHashTable* hashTable, MonoClass* klass)
142+
static int
143+
FindClassIndex (GHashTable *hashTable, MonoClass *klass)
130144
{
131145
gpointer orig_key, value;
132146

133-
if (!g_hash_table_lookup_extended(hashTable, klass, &orig_key, &value))
147+
if (!g_hash_table_lookup_extended (hashTable, klass, &orig_key, &value))
134148
return -1;
135149

136-
return GPOINTER_TO_INT(value);
150+
return GPOINTER_TO_INT (value);
137151
}
138152

139-
static void AddMetadataType(gpointer key, gpointer value, gpointer user_data)
153+
static void
154+
AddMetadataType (gpointer key, gpointer value, gpointer user_data)
140155
{
141-
MonoClass* klass = (MonoClass*)key;
142-
int index = GPOINTER_TO_INT(value);
143-
CollectMetadataContext* context = (CollectMetadataContext*)user_data;
144-
MonoMetadataSnapshot* metadata = context->metadata;
145-
MonoMetadataType* type = &metadata->types[index];
156+
MonoClass *klass = (MonoClass *)key;
146157

147-
if (klass->rank > 0)
148-
{
149-
type->flags = (MonoMetadataTypeFlags)(kArray | (kArrayRankMask & (klass->rank << 16)));
150-
type->baseOrElementTypeIndex = FindClassIndex(context->allTypes, mono_class_get_element_class(klass));
151-
}
152-
else
153-
{
158+
int index = GPOINTER_TO_INT (value);
159+
CollectMetadataContext *context = (CollectMetadataContext *)user_data;
160+
MonoMetadataSnapshot *metadata = context->metadata;
161+
MonoMetadataType *type = &metadata->types[index];
162+
163+
if (klass->rank > 0) {
164+
type->flags = (MonoMetadataTypeFlags) (kArray | (kArrayRankMask & (klass->rank << 16)));
165+
type->baseOrElementTypeIndex = FindClassIndex (context->allTypes, mono_class_get_element_class (klass));
166+
} else {
154167
gpointer iter = NULL;
155168
int fieldCount = 0;
156-
MonoClassField* field;
157-
MonoClass* baseClass;
158-
MonoVTable* vtable;
159-
void* statics_data;
169+
MonoClassField *field;
170+
MonoClass *baseClass;
171+
MonoVTable *vtable;
172+
void *statics_data;
160173

161174
type->flags = (klass->valuetype || klass->byval_arg.type == MONO_TYPE_PTR) ? kValueType : kNone;
162175
type->fieldCount = 0;
176+
fieldCount = mono_class_num_fields (klass);
177+
if (fieldCount > 0) {
178+
type->fields = g_new (MonoMetadataField, fieldCount);
163179

164-
if (mono_class_num_fields(klass) > 0)
165-
{
166-
type->fields = g_new(MonoMetadataField, mono_class_num_fields(klass));
180+
while ((field = mono_class_get_fields (klass, &iter))) {
181+
MonoMetadataField *metaField = &type->fields[type->fieldCount];
182+
MonoClass *typeKlass = mono_class_from_mono_type (field->type);
167183

168-
while ((field = mono_class_get_fields(klass, &iter)))
169-
{
170-
MonoMetadataField* metaField = &type->fields[type->fieldCount];
171-
metaField->typeIndex = FindClassIndex(context->allTypes, mono_class_from_mono_type(field->type));
184+
if (typeKlass->rank > 0)
185+
metaField->typeIndex = FindClassIndex (context->allTypes, mono_class_get_element_class (typeKlass));
186+
else
187+
metaField->typeIndex = FindClassIndex (context->allTypes, typeKlass);
172188

173189
// This will happen if fields type is not initialized
174190
// It's OK to skip it, because it means the field is guaranteed to be null on any object
175-
if (metaField->typeIndex == -1)
191+
if (metaField->typeIndex == -1) {
176192
continue;
193+
}
177194

178195
// literals have no actual storage, and are not relevant in this context.
179196
if ((field->type->attrs & FIELD_ATTRIBUTE_LITERAL) != 0)
180197
continue;
181198

182199
metaField->isStatic = (field->type->attrs & FIELD_ATTRIBUTE_STATIC) != 0;
200+
183201
metaField->offset = field->offset;
184202
metaField->name = field->name;
185203
type->fieldCount++;
186204
}
187205
}
188206

189-
vtable = mono_class_try_get_vtable(mono_domain_get(), klass);
190-
statics_data = vtable ? mono_vtable_get_static_field_data(vtable) : NULL;
207+
vtable = mono_class_try_get_vtable (mono_domain_get (), klass);
208+
statics_data = vtable ? mono_vtable_get_static_field_data (vtable) : NULL;
191209

192-
type->staticsSize = statics_data ? mono_class_data_size(klass) : 0;
210+
type->staticsSize = statics_data ? mono_class_data_size (klass) : 0;
193211
type->statics = NULL;
194212

195-
if (type->staticsSize > 0)
196-
{
197-
type->statics = g_new0(uint8_t, type->staticsSize);
198-
memcpy(type->statics, statics_data, type->staticsSize);
213+
if (type->staticsSize > 0) {
214+
type->statics = g_new0 (uint8_t, type->staticsSize);
215+
memcpy (type->statics, statics_data, type->staticsSize);
199216
}
200217

201-
baseClass = mono_class_get_parent(klass);
202-
type->baseOrElementTypeIndex = baseClass ? FindClassIndex(context->allTypes, baseClass) : -1;
218+
baseClass = mono_class_get_parent (klass);
219+
type->baseOrElementTypeIndex = baseClass ? FindClassIndex (context->allTypes, baseClass) : -1;
203220
}
204221

205-
type->assemblyName = mono_class_get_image(klass)->assembly->aname.name;
206-
type->name = mono_type_get_name_full(&klass->byval_arg, MONO_TYPE_NAME_FORMAT_IL);
222+
type->assemblyName = mono_class_get_image (klass)->assembly->aname.name;
223+
type->name = mono_type_get_name_full (&klass->byval_arg, MONO_TYPE_NAME_FORMAT_IL);
207224
type->typeInfoAddress = (uint64_t)klass;
208-
type->size = (klass->valuetype) != 0 ? (mono_class_instance_size(klass) - sizeof(MonoObject)) : mono_class_instance_size(klass);
225+
type->size = (klass->valuetype) != 0 ? (mono_class_instance_size (klass) - sizeof (MonoObject)) : mono_class_instance_size (klass);
209226
}
210227

211228
static void CollectMetadata(MonoMetadataSnapshot* metadata, GHashTable* monoImages)

0 commit comments

Comments
 (0)