Skip to content

Commit 0f33e5c

Browse files
Fix "dump" of ManagedReferenceRegistry
Fix bug when doing a UnityDataTool analysis on Megacity project. Two sharedAsset files had this error. "System.Exception: Unsupported ManagedReferenceRegistry version 1001" This is because of complexities in the TypeTress for ManagedReferenceRegistry, The registry always exists at the top level. So we have to ignore any that we find when traversing the contents of the ManagedReferenceRegistry. The fix matches the binary2text implementation, and i did side by side comparison of the previously problematic object data to confirm. Binary2Text output: references (ManagedReferencesRegistry) version 2 (int) rid -2 (class: , ns: , asm: ) rid 1000 (class: VisualElement/UxmlSerializedData, ns: UnityEngine.UIElements, asm: UnityEngine.UIElementsModule) UxmlSerializedData uxmlAssetId -993838062 (int) name "main-menu-container" (string) name_UxmlAttributeFlags 1 (UInt8) ... dataSourceTypeString_UxmlAttributeFlags 0 (UInt8) bindings (UxmlSerializedData) size 0 (int) bindings_UxmlAttributeFlags 0 (UInt8) rid 1001 (class: VisualElement/UxmlSerializedData, ns: UnityEngine.UIElements, asm: UnityEngine.UIElementsModule) UxmlSerializedData uxmlAssetId 76538276 (int) name "menu-panel" (string) name_UxmlAttributeFlags 1 (UInt8) enabledSelf 0 (UInt8) UnityDataTool output after fix: references (ManagedReferencesRegistry) version (int) 2 rid(-2) ReferencedObject type (ReferencedManagedType) class (string) ns (string) asm (string) data ReferencedObjectData null rid(1000) ReferencedObject type (ReferencedManagedType) class (string) VisualElement/UxmlSerializedData ns (string) UnityEngine.UIElements asm (string) UnityEngine.UIElementsModule data ReferencedObjectData uxmlAssetId (int) -993838062 name (string) main-menu-container name_UxmlAttributeFlags (UInt8) 1 ... dataSourceTypeString_UxmlAttributeFlags (UInt8) 0 bindings (UxmlSerializedData) Array<managedRefArrayItem>[0] bindings_UxmlAttributeFlags (UInt8) 0 rid(1001) ReferencedObject type (ReferencedManagedType) class (string) VisualElement/UxmlSerializedData ns (string) UnityEngine.UIElements asm (string) UnityEngine.UIElementsModule data ReferencedObjectData uxmlAssetId (int) 76538276 name (string) menu-panel name_UxmlAttributeFlags (UInt8) 1 enabledSelf (UInt8) 0
1 parent c7f190b commit 0f33e5c

File tree

2 files changed

+55
-48
lines changed

2 files changed

+55
-48
lines changed

Analyzer/PPtrAndCrcProcessor.cs

+26-25
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ namespace UnityDataTools.Analyzer;
1212
public class PPtrAndCrcProcessor : IDisposable
1313
{
1414
public delegate int CallbackDelegate(long objectId, int fileId, long pathId, string propertyPath, string propertyType);
15-
15+
1616
private SerializedFile m_SerializedFile;
1717
private UnityFileReader m_Reader;
1818
private long m_Offset;
@@ -21,7 +21,7 @@ public class PPtrAndCrcProcessor : IDisposable
2121
private string m_Folder;
2222
private StringBuilder m_StringBuilder = new();
2323
private byte[] m_pptrBytes = new byte[4];
24-
24+
2525
private CallbackDelegate m_Callback;
2626

2727
private Dictionary<string, UnityFileReader> m_resourceReaders = new();
@@ -34,14 +34,14 @@ public PPtrAndCrcProcessor(SerializedFile serializedFile, UnityFileReader reader
3434
m_Folder = folder;
3535
m_Callback = callback;
3636
}
37-
37+
3838
public void Dispose()
3939
{
4040
foreach (var r in m_resourceReaders.Values)
4141
{
4242
r?.Dispose();
4343
}
44-
44+
4545
m_resourceReaders.Clear();
4646
}
4747

@@ -52,7 +52,7 @@ private UnityFileReader GetResourceReader(string filename)
5252
{
5353
filename = filename.Remove(0, slashPos + 1);
5454
}
55-
55+
5656
if (!m_resourceReaders.TryGetValue(filename, out var reader))
5757
{
5858
try
@@ -89,13 +89,13 @@ public uint Process(long objectId, long offset, TypeTreeNode node)
8989
{
9090
m_StringBuilder.Clear();
9191
m_StringBuilder.Append(child.Name);
92-
ProcessNode(child);
92+
ProcessNode(child, false);
9393
}
9494

9595
return m_Crc32;
9696
}
9797

98-
private void ProcessNode(TypeTreeNode node)
98+
private void ProcessNode(TypeTreeNode node, bool isInManagedReferenceRegistry)
9999
{
100100
if (node.IsBasicType)
101101
{
@@ -104,18 +104,18 @@ private void ProcessNode(TypeTreeNode node)
104104
}
105105
else if (node.IsArray)
106106
{
107-
ProcessArray(node);
107+
ProcessArray(node, false, isInManagedReferenceRegistry);
108108
}
109109
else if (node.Type == "vector" || node.Type == "map" || node.Type == "staticvector")
110110
{
111-
ProcessArray(node.Children[0]);
111+
ProcessArray(node.Children[0], false, isInManagedReferenceRegistry);
112112
}
113113
else if (node.Type.StartsWith("PPtr<"))
114114
{
115115
var startIndex = node.Type.IndexOf('<') + 1;
116116
var endIndex = node.Type.Length - 1;
117117
var referencedType = node.Type.Substring(startIndex, endIndex - startIndex);
118-
118+
119119
ExtractPPtr(referencedType);
120120
}
121121
else if (node.Type == "StreamingInfo")
@@ -125,10 +125,10 @@ private void ProcessNode(TypeTreeNode node)
125125

126126
var offset = node.Children[0].Size == 4 ? m_Reader.ReadInt32(m_Offset) : m_Reader.ReadInt64(m_Offset);
127127
m_Offset += node.Children[0].Size;
128-
128+
129129
var size = m_Reader.ReadInt32(m_Offset);
130130
m_Offset += 4;
131-
131+
132132
var stringSize = m_Reader.ReadInt32(m_Offset);
133133
var filename = m_Reader.ReadString(m_Offset + 4, stringSize);
134134
m_Offset += stringSize + 4;
@@ -148,15 +148,15 @@ private void ProcessNode(TypeTreeNode node)
148148
{
149149
if (node.Children.Count != 3)
150150
throw new Exception("Invalid StreamedResource");
151-
151+
152152
var stringSize = m_Reader.ReadInt32(m_Offset);
153153
var filename = m_Reader.ReadString(m_Offset + 4, stringSize);
154154
m_Offset += stringSize + 4;
155155
m_Offset = (m_Offset + 3) & ~(3);
156156

157157
var offset = m_Reader.ReadInt64(m_Offset);
158158
m_Offset += 8;
159-
159+
160160
var size = (int)m_Reader.ReadInt64(m_Offset);
161161
m_Offset += 8;
162162

@@ -178,7 +178,9 @@ private void ProcessNode(TypeTreeNode node)
178178
}
179179
else if (node.IsManagedReferenceRegistry)
180180
{
181-
ProcessManagedReferenceRegistry(node);
181+
// ManagedReferenceRegistry are never nested
182+
if (!isInManagedReferenceRegistry)
183+
ProcessManagedReferenceRegistry(node);
182184
}
183185
else
184186
{
@@ -187,11 +189,11 @@ private void ProcessNode(TypeTreeNode node)
187189
var size = m_StringBuilder.Length;
188190
m_StringBuilder.Append('.');
189191
m_StringBuilder.Append(child.Name);
190-
ProcessNode(child);
192+
ProcessNode(child, isInManagedReferenceRegistry);
191193
m_StringBuilder.Remove(size, m_StringBuilder.Length - size);
192194
}
193195
}
194-
196+
195197
if (
196198
((int)node.MetaFlags & (int)TypeTreeMetaFlags.AlignBytes) != 0 ||
197199
((int)node.MetaFlags & (int)TypeTreeMetaFlags.AnyChildUsesAlignBytes) != 0
@@ -201,7 +203,7 @@ private void ProcessNode(TypeTreeNode node)
201203
}
202204
}
203205

204-
private void ProcessArray(TypeTreeNode node, bool isManagedReferenceRegistry = false)
206+
private void ProcessArray(TypeTreeNode node, bool isManagedReferenceRegistry, bool isInManagedReferenceRegistry)
205207
{
206208
var dataNode = node.Children[1];
207209

@@ -221,14 +223,13 @@ private void ProcessArray(TypeTreeNode node, bool isManagedReferenceRegistry = f
221223
{
222224
if (!isManagedReferenceRegistry)
223225
{
224-
225226
var size = m_StringBuilder.Length;
226227
m_StringBuilder.Append('[');
227228
m_StringBuilder.Append(i);
228229
m_StringBuilder.Append(']');
229-
230-
ProcessNode(dataNode);
231-
230+
231+
ProcessNode(dataNode, isInManagedReferenceRegistry);
232+
232233
m_StringBuilder.Remove(size, m_StringBuilder.Length - size);
233234
}
234235
else
@@ -285,7 +286,7 @@ private void ProcessManagedReferenceRegistry(TypeTreeNode node)
285286
var size = m_StringBuilder.Length;
286287
m_StringBuilder.Append('.');
287288
m_StringBuilder.Append("RefIds");
288-
ProcessArray(refIdsArrayNode, true);
289+
ProcessArray(refIdsArrayNode, true, true);
289290
m_StringBuilder.Remove(size, m_StringBuilder.Length - size);
290291
}
291292
else
@@ -330,9 +331,9 @@ bool ProcessManagedReferenceData(TypeTreeNode refTypeNode, TypeTreeNode referenc
330331
m_StringBuilder.Append("rid(");
331332
m_StringBuilder.Append(rid);
332333
m_StringBuilder.Append(").data");
333-
ProcessNode(refTypeTypeTree);
334+
ProcessNode(refTypeTypeTree, true);
334335
m_StringBuilder.Remove(size, m_StringBuilder.Length - size);
335-
336+
336337
return true;
337338
}
338339

TextDumper/TextDumperTool.cs

+29-23
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,20 @@ void RecursiveDump(TypeTreeNode node, ref long offset, int level, int arrayIndex
6060
{
6161
bool skipChildren = false;
6262

63-
if (!node.IsArray)
63+
if (level > 1 && node.IsManagedReferenceRegistry)
64+
{
65+
// If we are already inside a ManagedReferenceRegistry, then we ignore the ManagedReferenceRegistry node
66+
// they can appear in the TypeTrees of Managed objects, but only the root object actually has a registry
67+
skipChildren = true;
68+
}
69+
else if (node.IsArray)
70+
{
71+
DumpArray(node, ref offset, level);
72+
73+
// Skip child nodes as they were already processed here.
74+
skipChildren = true;
75+
}
76+
else
6477
{
6578
m_StringBuilder.Append(' ', level * 2);
6679

@@ -106,7 +119,7 @@ void RecursiveDump(TypeTreeNode node, ref long offset, int level, int arrayIndex
106119

107120
m_Writer.WriteLine(m_StringBuilder);
108121
m_StringBuilder.Clear();
109-
122+
110123
if (node.IsManagedReferenceRegistry)
111124
{
112125
DumpManagedReferenceRegistry(node, ref offset, level + 1);
@@ -115,13 +128,6 @@ void RecursiveDump(TypeTreeNode node, ref long offset, int level, int arrayIndex
115128
skipChildren = true;
116129
}
117130
}
118-
else
119-
{
120-
DumpArray(node, ref offset, level);
121-
122-
// Skip child nodes as they were already processed here.
123-
skipChildren = true;
124-
}
125131

126132
if (!skipChildren)
127133
{
@@ -194,7 +200,7 @@ void DumpArray(TypeTreeNode node, ref long offset, int level)
194200
else
195201
{
196202
++level;
197-
203+
198204
for (int i = 0; i < arraySize; ++i)
199205
{
200206
RecursiveDump(dataNode, ref offset, level, i);
@@ -207,22 +213,22 @@ void DumpManagedReferenceRegistry(TypeTreeNode node, ref long offset, int level)
207213
{
208214
if (node.Children.Count < 2)
209215
throw new Exception("Invalid ManagedReferenceRegistry");
210-
216+
211217
// First child is version number.
212218
var version = m_Reader.ReadInt32(offset);
213219
RecursiveDump(node.Children[0], ref offset, level);
214220

215221
TypeTreeNode refTypeNode;
216222
TypeTreeNode refObjData;
217-
223+
218224
if (version == 1)
219225
{
220226
// Second child is the ReferencedObject.
221227
var refObjNode = node.Children[1];
222228
// And its children are the referenced type and data nodes.
223229
refTypeNode = refObjNode.Children[0];
224230
refObjData = refObjNode.Children[1];
225-
231+
226232
int i = 0;
227233

228234
while (DumpManagedReferenceData(refTypeNode, refObjData, ref offset, level, i++))
@@ -244,7 +250,7 @@ void DumpManagedReferenceRegistry(TypeTreeNode node, ref long offset, int level)
244250
// First child is the array size.
245251
int arraySize = m_Reader.ReadInt32(offset);
246252
offset += 4;
247-
253+
248254
// Second child is the ReferencedObject.
249255
var refObjNode = refIdsArrayNode.Children[1];
250256

@@ -253,7 +259,7 @@ void DumpManagedReferenceRegistry(TypeTreeNode node, ref long offset, int level)
253259
// First child is the rid.
254260
long rid = m_Reader.ReadInt64(offset);
255261
offset += 8;
256-
262+
257263
// And the next children are the referenced type and data nodes.
258264
refTypeNode = refObjNode.Children[1];
259265
refObjData = refObjNode.Children[2];
@@ -270,28 +276,28 @@ bool DumpManagedReferenceData(TypeTreeNode refTypeNode, TypeTreeNode referencedT
270276
{
271277
if (refTypeNode.Children.Count < 3)
272278
throw new Exception("Invalid ReferencedManagedType");
273-
279+
274280
m_StringBuilder.Append(' ', level * 2);
275281
m_StringBuilder.Append($"rid(");
276282
m_StringBuilder.Append(id);
277283
m_StringBuilder.Append(") ReferencedObject");
278-
284+
279285
m_Writer.WriteLine(m_StringBuilder);
280286
m_StringBuilder.Clear();
281-
287+
282288
++level;
283289

284290
var refTypeOffset = offset;
285291
var stringSize = m_Reader.ReadInt32(offset);
286292
var className = m_Reader.ReadString(offset + 4, stringSize);
287293
offset += stringSize + 4;
288294
offset = (offset + 3) & ~(3);
289-
295+
290296
stringSize = m_Reader.ReadInt32(offset);
291297
var namespaceName = m_Reader.ReadString(offset + 4, stringSize);
292298
offset += stringSize + 4;
293299
offset = (offset + 3) & ~(3);
294-
300+
295301
stringSize = m_Reader.ReadInt32(offset);
296302
var assemblyName = m_Reader.ReadString(offset + 4, stringSize);
297303
offset += stringSize + 4;
@@ -308,23 +314,23 @@ bool DumpManagedReferenceData(TypeTreeNode refTypeNode, TypeTreeNode referencedT
308314
m_StringBuilder.Append(' ');
309315
m_StringBuilder.Append(referencedTypeDataNode.Type);
310316
m_StringBuilder.Append(' ');
311-
317+
312318
m_Writer.WriteLine(m_StringBuilder);
313319
m_StringBuilder.Clear();
314320

315321
if (id == -1 || id == -2)
316322
{
317323
m_StringBuilder.Append(' ', level * 2);
318324
m_StringBuilder.Append(id == -1 ? " unknown" : " null");
319-
325+
320326
m_Writer.WriteLine(m_StringBuilder);
321327
m_StringBuilder.Clear();
322328

323329
return true;
324330
}
325331

326332
var refTypeRoot = m_SerializedFile.GetRefTypeTypeTreeRoot(className, namespaceName, assemblyName);
327-
333+
328334
// Dump the ReferencedObject using its own TypeTree, but skip the root.
329335
foreach (var child in refTypeRoot.Children)
330336
{

0 commit comments

Comments
 (0)