Maison >développement back-end >Golang >MiniDumpWriteDump avec rappels dans Go

MiniDumpWriteDump avec rappels dans Go

王林
王林avant
2024-02-05 23:51:03527parcourir

Go 中带有回调的 MiniDumpWriteDump

Contenu de la question

J'essaie d'implémenter MiniDumpWriteDump en utilisant callbacks dans Go.

Appelez MiniDumpWriteDump :

callback := syscall.NewCallback(miniDumpCallback)
    var newCallbackRoutine MINIDUMP_CALLBACK_INFORMATION
    newCallbackRoutine.CallbackParam = 0
    newCallbackRoutine.CallbackRoutine = callback
    ret, _, err := miniDumpWriteDump.Call(
        uintptr(processHandle),
        uintptr(processId),
        uintptr(dumpFile),
        uintptr(options),
        0,
        0,
        uintptr(unsafe.Pointer(&newCallbackRoutine)),
    )

La fonction de rappelelle-même :

func miniDumpCallback(_ uintptr, CallbackInput *MINIDUMP_CALLBACK_INPUT, _ uintptr) uintptr {
    fmt.Println(CallbackInput.ProcessId, CallbackInput.CallbackType)
    return 1
}

TypeDéfinition :

type MINIDUMP_CALLBACK_INPUT struct {
    ProcessId     win32.ULONG
    ProcessHandle win32.HANDLE
    CallbackType  win32.ULONG
    CallbackInfo  uintptr
}

type MINIDUMP_CALLBACK_INFORMATION struct {
    CallbackRoutine uintptr
    CallbackParam   uintptr
}

Le rappel est appelé et certains champs reçoivent des données correctes, mais certains champs obtiennent des valeurs sans signification.

Par exemple, le rappel ci-dessus reçoit correctement le champ ProcessId de CallbackInput, mais reçoit un entier aléatoire comme l'énumération CallbackType MINIDUMP_CALLBACK_TYPE quand il le devrait.

Sortie :

12544 0
12544 1133445120
12544 12548
12544 13028
12544 1114112
12544 1023344640
12544 999620608
12544 990117888
12544 992542720
12544 1005518848
12544 1994850304
12544 1114112
12544 1994915840

Bonne réponse


Comme les commentaires le suggèrent, le problème vient de l'alignement structurel.

Comme @IInspectable l'a expliqué, minidumpapiset.h, qui exporte la fonction MiniDumpWriteDump et la structure MINIDUMP_CALLBACK_INPUT, utilise l'alignement 4 octets strong> pour les architectures 32 bits et 64 bits, tandis que Go utilise 64 bits. par défaut 8 octets alignement, et ne fournit pas de moyen automatique de le modifier.

La solution est de lire la structure manuellement. Voici un exemple fonctionnel :

type MINIDUMP_CALLBACK_INPUT struct {
ProcessId     uint32
ProcessHandle uintptr
CallbackType  uint32
CallbackInfo uintptr}

func ptrToMinidumpCallbackInput(ptrCallbackInput uintptr) MINIDUMP_CALLBACK_INPUT{
    var input MINIDUMP_CALLBACK_INPUT
    input.ProcessId = *(*uint32)(unsafe.Pointer(ptrCallbackInput))
    input.ProcessHandle = *(*uintptr)(unsafe.Pointer(ptrCallbackInput + unsafe.Sizeof(uint32(0))))
    input.CallbackType = *(*uint32)(unsafe.Pointer(ptrCallbackInput + unsafe.Sizeof(uint32(0)) + unsafe.Sizeof(uintptr(0))))
    input.CallbackInfo = *(*uintptr)(unsafe.Pointer(ptrCallbackInput + unsafe.Sizeof(uint32(0)) + unsafe.Sizeof(uintptr(0)) + unsafe.Sizeof(uint32(0))))
    return input}

Le code original devrait fonctionner correctement sur les architectures 32 bits car son remplissage (4 octets) correspond au remplissage utilisé par minidumpapiset.h.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer