ByNameModding / BNM-Android

Modding il2cpp games by classes, methods, fields names on Android.
MIT License
210 stars 41 forks source link

Crash when calling GetMethods on Action (MulticastDelegateBase) #72

Open solomode0001 opened 6 days ago

solomode0001 commented 6 days ago

There is an issue when attempting to retrieve methods using GetMethods on an Action delegate within a MulticastDelegateBase. This consistently leads to a crash.

log:

SpawnManager = 0xb67fea50
OnEnemySpawn = 0xb64be980
*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
Version '2020.3.48f1 (b805b124c6b7)', Build type 'Release', Scripting Backend 'il2cpp', CPU 'armeabi-v7a'
Build fingerprint: 'Asus/Asus/ASUS_I003DD:9/mv-dev103041042:user/release-keys'
Revision: '0'
ABI: 'arm'
Timestamp: 2024-09-22 06:17:00+0700
pid: 20558, tid: 20609, name: UnityMain  >>> com.madfingergames.deadtrigger <<<
uid: 10102
signal -1623598376 (?), code 75596760 (?), fault addr --------
    r0  00000000  r1  00000000  r2  00000000  r3  00000000
    r4  00000000  r5  00000000  r6  00000000  r7  00000000
    r8  00000000  r9  00000000  r10 00000000  r11 00000000
    ip  00000000  sp  00000000  lr  00000000  pc  00000000
--------- beginning of crash
Tombstone written to: /storage/emulated/0/Android/data/com.madfingergames.deadtrigger/files/tombstone_02
FATAL EXCEPTION: UnityMain
Process: com.madfingergames.deadtrigger, PID: 20558
java.lang.Error: *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
Version '2020.3.48f1 (b805b124c6b7)', Build type 'Release', Scripting Backend 'il2cpp', CPU 'armeabi-v7a'
Build fingerprint: 'Asus/Asus/ASUS_I003DD:9/mv-dev103041042:user/release-keys'
Revision: '0'
ABI: 'arm'
Timestamp: 2024-09-22 06:17:00+0700
pid: 20558, tid: 20609, name: UnityMain  >>> com.madfingergames.deadtrigger <<<
uid: 10102
signal -1623598376 (?), code 75596760 (?), fault addr --------
    r0  00000000  r1  00000000  r2  00000000  r3  00000000
    r4  00000000  r5  00000000  r6  00000000  r7  00000000
    r8  00000000  r9  00000000  r10 00000000  r11 00000000
    ip  00000000  sp  00000000  lr  00000000  pc  00000000

code:

void (*_SpawnManager)(void*,float);
void SpawnManager(void* instance, float deltaTime) {
    _SpawnManager(instance, deltaTime);

    BNM_LOG_INFO("SpawnManager = %p", instance);
    auto OnEnemySpawn = *(Action<void*>**)((uint64_t)instance + 0x40);
    if (OnEnemySpawn) {
        BNM_LOG_INFO("OnEnemySpawn = %p", OnEnemySpawn);

        auto methods = OnEnemySpawn->GetMethods();
        for (const auto& method : methods) {
            BNM_LOG_INFO(method.str().c_str());
        }
    }
}

/*
// SpawnManager
// Token: 0x04000FC5 RID: 4037
[Token(Token = "0x4000FC5")]
[FieldOffset(Offset = "0x40")]
[Attribute(Name = "CompilerGeneratedAttribute", RVA = "0x16EAD0", Offset = "0x16EAD0")]
private Action<AgentHuman> OnEnemySpawn;
*/
BNM-Dev commented 5 days ago

In v2.1.1 I added potential crash fix, try.

solomode0001 commented 5 days ago

The crash previously encountered when using GetMethods() has been resolved. However, the intended purpose of the GetMethods() function remains unclear.

Currently, the code utilizes GetMethods() on a delegate instance:

void (*_SpawnManager)(void*,float);
void SpawnManager(void* instance, float deltaTime) {
    _SpawnManager(instance, deltaTime);

    auto OnEnemySpawn = *(Action<void*>**)((uint64_t)instance + 0x40);
    if (OnEnemySpawn) {
        BNM_LOG_INFO("%s::%s", OnEnemySpawn->delegate.method->klass->name, OnEnemySpawn->delegate.method->name);

        auto methods = OnEnemySpawn->GetMethods();
        for (const auto& method : methods) {
            BNM_LOG_INFO(method.str().c_str());
        }
    }
}

logs:

SpawnDirector::OnEnemySpawn
SpawnDirector::OnEnemySpawn
SpawnDirector::OnEnemySpawn
SpawnDirector::OnEnemySpawn
SpawnDirector::OnEnemySpawn
SpawnDirector::OnEnemySpawn
SpawnDirector::OnEnemySpawn
SpawnDirector::OnEnemySpawn
SpawnDirector::OnEnemySpawn
SpawnDirector::OnEnemySpawn
SpawnDirector::OnEnemySpawn
SpawnDirector::OnEnemySpawn
SpawnDirector::OnEnemySpawn
SpawnDirector::OnEnemySpawn
SpawnDirector::OnEnemySpawn

While GetMethods() seems to be functional, its practical application in this context is not evident.

Suggestion: It would be beneficial to introduce a dedicated function for extracting relevant information about the target method associated with the delegate (in this case, OnEnemySpawn). This function could potentially provide access to details such as:

Having such a function would improve clarity and facilitate easier manipulation and inspection of the delegate's target method. This issue serves to both inquire about the intended use of GetMethods() and propose the implementation of a more specific method information retrieval function for delegates.

BNM-Dev commented 2 days ago

In v2.1.2 I fixed issue when only one method exists in Delegate. So your code:

auto methods = OnEnemySpawn->GetMethods();
for (const auto& method : methods) {
    BNM_LOG_INFO(method.str().c_str());
}

Will log method SpawnDirector::OnEnemySpawn.

About suggestion, BNM already has API for getting almost all info that you mentioned using BNM::MethodBase::str() (that you use in your code). Example output: [mscorlib.dll]::[System]::[Int32] [Assembly-CSharp.dll]::[]::[Delegates].(<Start>b__8_2){arguments count: 2}

изображение