Почему-то у меня не работает DLL под Windows 8 x64. regsvr32 выдаёт ошибку: The module test64.dll failed to load. Make sure the binary is stored at the specified path or debug it to check for problems with the binary or dependent .DLL files. Invalid access to memory location. В гугле решения найти не удалось (только вот понятно что это ошибка error 998 - но почему непонятно). В Windows XP 64bit и в Windows 7 64bit - кладу свою test64.dll в C:\Windows\System32, и в CMD-консоле запускаю C:\>regsvr32 test64.dll Всё отлично, контрольные MessageBoxы вылезают, всё работает. Единственное есть багофича с наследованием у консоли - консоль должна быть открыта через Win+R или проводник, если же она запущена из-под 32-битного файлового менеджера - то 64-битную DLL не позволяет регистрировать в windows\system32, только в пользовательских папках с явным указанием пути. Ну а проблема то собственно с Windows 8 x64. Там моя test64.dll не работает вообще никак и ни из каких папок. И в C:\Windows\System32, и просто в несистемных папках, и пути в regsvr32 указывал, и UAC вырублен полностью, я админ, и пробовал написать .cmd и запускать его Run as Adminstrator… В любом случае итог один - Invalid access to memory location. И ни одного моего контрольного MessageBox не вылезает - т.е. DLL тупо не открывается вообще - DllEntryPoint не вызывается. Другие варианты запуска (через реестр) тоже не работают. Собственно, с этого и началось разбирательство. Есть моя программка (COM-сервер расширения оболочки) которая работает во всех 64битных виндах (xp, 7, 2008), но вот в Win8 обнаружил что не работает. В процессе чего набросал такой вот простейший пример test64.dll - и убедился что в Win8 он тоже не работает… Есть идеи в чём у меня тут ошибка то ? Код (Text): ; build in FASM v.1.69.35 ; X:\ASM\FASM\FASM.EXE test64dll.asm test64.dll format PE64 GUI 4.0 DLL entry DllEntryPoint include 'X:\ASM\FASM\INCLUDE\WIN64A.INC' section '.idata' import data readable writeable library user32,'USER32.DLL' import user32,MessageBoxA,'MessageBoxA' section '.text' code readable executable proc DllEntryPoint .hinstDLL,.fdwReason,.lpvReserved invoke MessageBoxA, 0, t_DllEntryPoint, t_test64, MB_OK mov rax, 1 ret endp proc DllCanUnloadNow invoke MessageBoxA, 0, t_DllCanUnloadNow, t_test64, MB_OK mov rax, 0 ret endp proc DllGetClassObject, rclsid,riid,ppv mov [rclsid], rcx mov [riid], rdx mov [ppv], r8 push rdi sub rsp, 8 ; stack align invoke MessageBoxA, 0, t_DllGetClassObject, t_test64, MB_OK mov rdi, [ppv] mov qword [rdi], 0 mov rax, 0x80040111 ; CLASS_E_CLASSNOTAVAILABLE add rsp, 8 pop rdi ret endp proc DllRegisterServer invoke MessageBoxA, 0, t_DllRegisterServer, t_test64, MB_OK mov rax, 0 ret endp proc DllUnregisterServer invoke MessageBoxA, 0, t_DllUnregisterServer, t_test64, MB_OK mov rax, 0 ret endp section '.bss' data readable writeable t_test64 db 'test64.dll',0 t_DllEntryPoint db 'DllEntryPoint',0 t_DllCanUnloadNow db 'DllCanUnloadNow',0 t_DllGetClassObject db 'DllGetClassObject',0 t_DllRegisterServer db 'DllRegisterServer',0 t_DllUnregisterServer db 'DllUnregisterServer',0 section '.edata' export data readable export 'test64.DLL',\ DllEntryPoint,'DllEntryPoint',\ DllCanUnloadNow,'DllCanUnloadNow',\ DllGetClassObject,'DllGetClassObject',\ DllRegisterServer,'DllRegisterServer',\ DllUnregisterServer,'DllUnregisterServer' section '.reloc' fixups data discardable Дизассемблировал DllEntryPoint: Код (Text): Section 2. (virtual address 00002000) Virtual size : 00000155 Section size in file : 00000200 Offset to raw data for section : 00000600 Flags 60000020 : Text Executable Readable Alignment : default Exported entry 1. DllEntryPoint Segment type: Pure code Segment permissions: Read/Execute _text segment para public 'CODE' use64 assume cs:_text org 402000h assume es:nothing, ss:nothing, ds:nothing, fs:nothing, gs:nothing ; Attributes: bp-based frame ; BOOL __stdcall DllEntryPoint(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved) public DllEntryPoint DllEntryPoint proc near push rbp mov rbp, rsp sub rsp, 20h mov rcx, 0 ; hWnd mov rdx, offset Text ; "DllEntryPoint" mov r8, offset Caption ; "test64.dll" mov r9, 0 ; uType call cs:MessageBoxA add rsp, 20h mov rax, 1 leave retn DllEntryPoint endp
Никто что ли под win8 ещё не пишет dll ? Уже ведь несколько месяцев как win8-бета выложена… Вобщем, методом тыка и анализа других немногочисленных примеров - удалил строчку section '.reloc'… И в Win8 заработало! Но зато сломалось в WinXP64 (LoadLibrary failed - Attempt to access invalid address) и Win7x64 (Invalid access to memory location). Далее обнаружил что проблема касается не только win8x64, а вообще обоих Win8 - в 32битной точно такая же ошибка (разумеется там я написал 32битную DLL). Может теперь какие-нибудь идеи будут ? Что надо явным образом написать в '.reloc' чтобы работало и в WinXP/Win7 и в Win8 ? Собрал эту же DLL в MASM x64 v10 - она работает и в xp64, и в win8x64… Проблема у FASM…
Проблема решена. Если кому интересно - у FASM (даже вот в том дистрибутиве что на оф.сайте на сегодня есть) кривые примеры .dll в \examples. Причём это я уже 3 раз сталкиваюсь с проблемами которые как потом обнаруживаю - из-за ошибок в примерах и в инклюдах у FASM… Секции .reloc вообще не должно быть. В конце секции .text (для dll) надо вставить две строчки: data fixups end data и теперь dll работает как в winxp/win7, так и в win8. причём всё это актуально и для 32битной винды и для 64битной.
Это вы методом тыка нашли? А принцип объяснить можете? Почему это секции релоков быть не должно и при этом сами же тычете релоки в секцию кода? О_О
Когда стало ясно что проблема в FASM - в гугле и на оф.форуме нашёл много обсуждений. На оф.форуме по ссылкам можно найти и высказывание самого автора FASM что можно вот сделать так… Ну и - работает! Я уже тщательно проверил на реальной сложной DLL, на всех виндах - XP32, 2003r2-32, XP64, 7-32, 7-64, 2008r2-64, 8-32, 8-64 - всё работает - проблема решена. Неа, я во внутренностях .exe разбираюсь плохо. Но по вышеуказанной ссылке про это много страниц обсуждений…
Для желающих всё-же разобраться с причинами… Сейчас проверил в Windows 8. Вот в том исходнике что в первом сообщении - дописал в конце «dd ?» - не работает… Попробовал также «dq 0» или «dq ?» - тоже не работает. а удаляю строчку «section '.reloc'…» вообще, и пишу перед section '.bss' : Код (Text): … endp data fixups end data section '.bss' data readable writeable … И оно работает в Windows 8… Ну и в других виндах тоже. Вообще на оф.форуме фасма тоже видел такой совет что в секцию писать dd или dd 2000 dup… Но мне не помогло, а к тому же там упомянуто что вот в последних версиях фасма это не работает, а в предыдущих работало. кстати секция .reloc не пустая, там два адреса… смотрел при помощи PEBrowse. Посмотрел на 64-битные dll от winrar и 7zip - у них секции .reloc есть, но в Win8 работают нормально… Вероятно какая-то совокупность других параметров заголовка вместе с .reloc в FASM приводит к тому что в win8 проблема. вот в аттаче test64dll_v2.rar три варианта скомпилировал: c fixup в text (работает везде), и с reloc-секцией (не работает в win8) - один по дефолту другой секция раздута до 0x2000 (но всё это не помогло). Код (Text): ; build in FASM v.1.69.35 ; X:\ASM\FASM\FASM.EXE test64dll.asm test64.dll format PE64 GUI 4.0 DLL entry DllEntryPoint include 'X:\ASM\FASM\INCLUDE\WIN64A.INC' section '.idata' import data readable writeable library user32,'USER32.DLL' import user32,MessageBoxA,'MessageBoxA' section '.text' code readable executable proc DllEntryPoint .hinstDLL,.fdwReason,.lpvReserved lea rax, [t_DllEntryPoint_p_a] cmp rdx, DLL_PROCESS_ATTACH je .m0 lea rax, [t_DllEntryPoint_p_d] cmp rdx, DLL_PROCESS_DETACH je .m0 lea rax, [t_DllEntryPoint_t_a] cmp rdx, DLL_THREAD_ATTACH je .m0 lea rax, [t_DllEntryPoint_t_d] cmp rdx, DLL_THREAD_DETACH je .m0 lea rax, [t_DllEntryPoint_unknow] .m0: mov rdx, rax call msgbox mov rax, 1 ret endp proc DllCanUnloadNow lea rdx, [t_DllCanUnloadNow] call msgbox xor rax, rax ret endp proc DllGetClassObject, rclsid,riid,ppv mov [rclsid], rcx mov [riid], rdx mov [ppv], r8 lea rdx, [t_DllGetClassObject] call msgbox mov rax, [ppv] mov qword [rax], 0 mov rax, 0x80040111 ; CLASS_E_CLASSNOTAVAILABLE ret endp proc DllRegisterServer lea rdx, [t_DllRegisterServer] call msgbox xor rax, rax ret endp proc DllUnregisterServer lea rdx, [t_DllUnregisterServer] call msgbox invoke MessageBoxA, 0, t_DllUnregisterServer, t_test64, MB_OK xor rax, rax ret endp msgbox: sub rsp, 0x28 xor r9, r9 ; MB_OK lea r8, [t_test64] xor rcx, rcx call [MessageBoxA] add rsp, 0x28 retn ;data fixups ;end data section '.bss' data readable writeable include 'build_datetime.inc' t_test64 db 'test64.dll ', build_datetime, 0 t_DllEntryPoint_p_a db 'DllEntryPoint_process_attach',0 t_DllEntryPoint_p_d db 'DllEntryPoint_process_detach',0 t_DllEntryPoint_t_a db 'DllEntryPoint_thread_attach',0 t_DllEntryPoint_t_d db 'DllEntryPoint_thread_detach',0 t_DllEntryPoint_unknow db 'DllEntryPoint_unknow',0 t_DllCanUnloadNow db 'DllCanUnloadNow',0 t_DllGetClassObject db 'DllGetClassObject',0 t_DllRegisterServer db 'DllRegisterServer',0 t_DllUnregisterServer db 'DllUnregisterServer',0 section '.edata' export data readable export 'test64.dll',\ DllEntryPoint,'DllEntryPoint',\ DllCanUnloadNow,'DllCanUnloadNow',\ DllGetClassObject,'DllGetClassObject',\ DllRegisterServer,'DllRegisterServer',\ DllUnregisterServer,'DllUnregisterServer' section '.reloc' fixups data discardable ;dq 0 ;dq 0x2000 dup 0
f2065 Здесь неважно, что именно дописывать. Важно, чтобы хотя бы виртуальный размер секции был ненулевым. В противном случае Windows откажется грузить образ. И это не баг fasm, и ошибок в примерах fasm тоже нет. Все когда-либо предлагаемые решения (от добавления dd ? до переноса директории релоков в общую с чем-нибудь секцию) относятся именно к этой проблеме. Но конкретно в Вашем случае (доселе невиданная) проблема явно в чём-то другом. Вполне вероятно, что здесь как раз таки баг fasm'а. Была бы у меня восьмёрка, я бы обязательно потестировал. Вопрос имеет смысл запостить на форуме fasm с явным указанием на то, что пустых секций в образе нет.