Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New function metadata init cause runtime crash with XrefScan #107

Open
HookedBehemoth opened this issue Sep 15, 2023 · 2 comments
Open

New function metadata init cause runtime crash with XrefScan #107

HookedBehemoth opened this issue Sep 15, 2023 · 2 comments

Comments

@HookedBehemoth
Copy link
Contributor

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
var test = new Il2Cpp.Test();
test.Update();
@HookedBehemoth HookedBehemoth changed the title New RVO generation cause runtime crash with XrefScan New RVA generation cause runtime crash with XrefScan Sep 16, 2023
@HookedBehemoth HookedBehemoth changed the title New RVA generation cause runtime crash with XrefScan New function metadata init cause runtime crash with XrefScan Sep 16, 2023
@HookedBehemoth
Copy link
Contributor Author

Ok I missed that those aren't tokens but object pointers.

@HookedBehemoth
Copy link
Contributor Author

Ok this is even more annoying than I had anticipated.

  1. I couldn't get Cecil to store the arrays. I'll look into that but for now I'm just testing without caching.
  2. 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant