In the past, il2cpp would emit a single call to il2cpp_codegen_initialize_method with a method token. Now there are multiple calls to il2cpp_codegen_initialize_runtime_metadata with potentially multiple tokens.
When using XrefScan on a method before the runtime, values can be left uninitialized, resulting in a segfault/AccessViolation.
Didn't bisect when exactly codegen was altered but I can observe this behavior in 2022.3.5
I couldn't find any conversation on this issue so far. I'll work on a patch myself if you don't have something waiting for it already.
This would probably change the Cache-Attribute parameter "public long MetadataInitTokenRva;" to public long[] MetadataInitTokenRvas;.
I don't expect this to cause any major breakage on any prior version so I don't think I'll actually have to bisect the version and nail this logic down.
Steps for reproduction
- Project on ~2022.3.5
- Have class like
```cs
using UnityEngine;
public class Test : MonoBehaviour
{
void Update()
{
Debug.Log("test");
Debug.Log("This is a test with a long string");
}
}
```
- Compile with il2cpp
- Install mod framework using il2cppinterop
- Invoke xref on Test::Update before the game does
```cs
var method = typeof(Il2Cpp.Test)
.GetMethod("Update", Public | Instance);
foreach (var str in XrefScanner
.XrefScan(method)
.Where(scan => scan.Type == XrefType.Global)
.Select(scan => scan.ReadAsObject().ToString())) {
LoggerInstance.Msg(str);
};
```
- Observe crash
- Observe that it doesn't crash if you add this snippet before the xref
```cs
var test = new Il2Cpp.Test();
test.Update();
```
Ok this is even more annoying than I had anticipated.
I couldn't get Cecil to store the arrays. I'll look into that but for now I'm just testing without caching.
I found a function that has multiple initializer blocks sprinkled in. I couldn't find such code in the generated C++ files but it might be inlined by the compiler... Not entirely sure how I'd want to deal with that just yet. I could just call the metadata init function before dereferencing any of the found globals but that's messy, potentially slow and I'm not sure if those are always immutable or if a game could alter those.
In the past, il2cpp would emit a single call to
il2cpp_codegen_initialize_method
with a method token. Now there are multiple calls toil2cpp_codegen_initialize_runtime_metadata
with potentially multiple tokens. When using XrefScan on a method before the runtime, values can be left uninitialized, resulting in a segfault/AccessViolation.Didn't bisect when exactly codegen was altered but I can observe this behavior in 2022.3.5
I couldn't find any conversation on this issue so far. I'll work on a patch myself if you don't have something waiting for it already. This would probably change the Cache-Attribute parameter "public long MetadataInitTokenRva;" to
public long[] MetadataInitTokenRvas;
. I don't expect this to cause any major breakage on any prior version so I don't think I'll actually have to bisect the version and nail this logic down.Steps for reproduction