Собственный обратный вызов Windows возвращает только 32-битный результат на 64-битной платформе - PullRequest
0 голосов
/ 19 декабря 2018

Я вызываю функцию DLL, которая принимает функцию обратного вызова, где функция обратного вызова возвращает указатель на некоторую структуру данных, а DLL выполняет некоторые действия с этой структурой данных.

package main

import (
    "golang.org/x/sys/windows"
    "unsafe"
)

type A struct {}
var a = &A{}

func Callback() uintptr {
    ptr := uintptr(unsafe.Pointer(a))
    fmt.Printf("Address: 0x%X\n", ptr)
    return ptr
}

func main() {
    dll := windows.MustLoadDLL("some.dll")
    init := dll.MustFindProc("init")
    init.Call(windows.NewCallback(Callback))
    fmt.Printf("This never get prints\n")
}

Я бегу на Windows 64-разрядной машине, DLL также 64-разрядная.

$ go version
go version go1.11.4 windows/amd64

Приведенный выше код будет печатать адрес указателя, который 0xC000080018, но вызовDLL потерпит молчание.У меня нет исходного кода для DLL, поэтому я не могу заставить его напечатать полученное значение.Поэтому я использовал IDA pro для динамической отладки программы и обнаружил, что функция обратного вызова Go фактически возвращает 32-разрядное значение вместо 64-разрядного.Это последний код подпрограммы обратного вызова Go, прежде чем она вернется обратно в DLL:

main.exe:00000000004537E7     mov     eax, [rcx+rdx-8]
main.exe:00000000004537EB     pop     qword ptr [rcx+rdx-8]
main.exe:00000000004537EF     retn

Как вы можете видеть, Go записывает возвращаемое значение в eax вместо rax, что отбрасываетболее высокий адрес, поэтому DLL получит только 0x80018 и вызвало ошибки.

Хотя я знаю, что с ним не так, я не могу понять, как это исправить.

Обновление:

Я немного покопался в реализации обратного вызова Go и нашел код сборки в src/runtime/sys_windows_amd64.s.Я заметил, что в runtime·callbackasm1 возвращаемое значение устанавливается с помощью MOVL вместо MOVQ.Поэтому я изменил его на MOVQ и все заработало.

Я не уверен, является ли это ошибкой или на самом деле предназначено, поэтому я открою проблему на GitHub .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...