имхо, МАСМ поступает исключительно верно хоть его так ругали на протяжении нескольких страниц одного из топиков на этом форуме
А х.з., я ж и говорю надо в спецификации прочитать, факт что масм в релоках ставит dd 0,8 и больше ничего, это работает, значит такая запись чем-то определена?
O, пока я собирался поделиться соображениями, bogrus уже раскрыл миру "секрет" dd 0,8 Я методом квазинаучного тыка тоже до этого допер - чтобы вылечить фасм можно после объявы section '.reloc' добавить следующее Код (Text): if rva $ and 0FFFh = 0 ;если начало страницы, то с вероятность 99.9(9) релоков нет dd 0,8 ;page RVA = 0 (не важно), block size = 8, т.е. число релоков = 0 end if Суть в том, что если релоков нет, то fasm создает в PE-заголовке запись секции, нормально указывает ее адрес и адрес таблицы релоков, но вот размеры устанавливает в 0 и саму секцию в файл не пишет, что видимо винде и не нравится. Действительно, вроде как инициализированные данные, а в файле их нет - подозрение на "коррупцию". А винде видимо нужно явное подтверждение отсутствия релоков, т.е. таблица должна быть обязательно, но если релоков нет, то должна быть запись одного пустого блока: размер таблицы = 8, page RVA = 0 (или любое значение, т.к. до него дело не доходит), block size = 8 (т.е. дальше ничего нет) Причем интересно, что XP SP2 сама глюкавая, т.к. если задать block size = 0, то при загрузке хрюша выдает Access Violation на начале страницы, следующей за секцией .reloc - возможно тупо сканирует всю секцию в поисках неведомо чего
В w2k точно также! (если ставить dd 0,0), мне кажется в MSPECOFF об этом одном блоке ничего не сказано(потому в фасме этого и нет), хотя кто знает инглиш лучше посмотрит спецификацию, и на форуме фасма надо сообщить если там явно указано
В спецификации вроде как ничего такого нет Поэтому это больше похоже на глюк MS, т.к. с точки зрения здравой логики достаточно указать размеры секции и таблицы релоков = 0, а не выделять 512 байт в файле и 4К драгоценной физпамяти ради магических 8 байт dd 0,8
Кажется я поторопился с выводами По всей видимости причина ошибки в том, что секция инициализированных данных не может иметь размер = 0. По крайней мере в XP, именно это приводит к отказу загрузки. При отсутствии релоков в XP достаточно указать размер таблицы = 0, при этом никакой секции reloc не требуется вообще, а если она есть, то ее размер должен быть > 0, но заполнена она м.б. нулями или вообще любым мусором. Если же размер таблицы > 0, то в ней по кр.мере должен быть один (пустой) валидный блок с blocksize > 0, иначе винда может заглючить Вывод: все таки это ошибка фасма, т.к. если релоков нет, то нужно либо 1) вообще не создавать секцию reloc (если это катит в других win), либо 2) создавать секцию и соответственно отводить под нее место в файле и либо 2.1) указывать размер таблицы = 0 и забивать секцию нулями, либо 2.2) указывать размер таблицы = 8 и писать в секцию пустой блок dd 0,8
Число релокейшенов определяется по след. формуле: (Размер chunk'a - 8(<-- размер заголовка chunk'a) )/2 В случае масма, если релоков нет, то имеем: (8 - 8)/2 = 0 (т.е всё правильно) Для фасма соответственно 0, т.е. получаем (0 - 8)/2 = ...??? Скорее всего, дело именно в этом. P.S. и в этом фасм обоср.лся.
ааа... там даже до этого дело не доходит: Код (Text): ДДДДДKERNEL32!VirtualQueryEx+27A9ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД ДДДДPROT32Д 016F:BFF87A4C JNZ BFF87A75 016F:BFF87A4E PUSH 10 016F:BFF87A50 MOV EAX,[EBP-00F0] ; ImageSize 016F:BFF87A56 ADD EAX,00000FFF 016F:BFF87A5B SHR EAX,0C 016F:BFF87A5E PUSH EAX 016F:BFF87A5F MOV EAX,[EBP-010C] ; ImageBase 016F:BFF87A65 SHR EAX,0C 016F:BFF87A68 PUSH EAX 016F:BFF87A69 PUSH 00010000 ; _PageReserve 016F:BFF87A6E CALL KERNEL32!ORD_0001 016F:BFF87A73 MOV EDI,EAX 016F:BFF87A75 CMP EDI,-01 ; is addr already in use? 016F:BFF87A78 JNZ BFF87AD3 016F:BFF87A7A CMP DWORD PTR [ESI+000000A4],04 ; <-- !!! SizeOfDir for Fixup Directory 016F:BFF87A81 JA BFF87A8F 016F:BFF87A83 PUSH 0B 016F:BFF87A85 PUSH DWORD PTR [EBP+08] 016F:BFF87A88 PUSH 0C 016F:BFF87A8A JMP BFF87B26 016F:BFF87A8F PUSH 10 016F:BFF87A91 MOV EAX,[EBP-00F0] 016F:BFF87A97 ADD EAX,00000FFF 016F:BFF87A9C SHR EAX,0C 016F:BFF87A9F CMP EBX,01 016F:BFF87AA2 PUSH EAX 016F:BFF87AA3 SBB EAX,EAX 016F:BFF87AA5 AND EAX,FFFA0400 016F:BFF87AAA SUB EAX,7FFA0000 016F:BFF87AAF PUSH EAX 016F:BFF87AB0 PUSH 00010000 016F:BFF87AB5 CALL KERNEL32!ORD_0001 016F:BFF87ABA MOV EDI,EAX 016F:BFF87ABC MOV ECX,[EBP-08] 016F:BFF87ABF OR BYTE PTR [ECX],02 016F:BFF87AC2 CMP EDI,-01 016F:BFF87AC5 MOV [ESI+34],EDI 016F:BFF87AC8 JNZ BFF87AD3 ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДKERNEL32!.text+EA4CДДДДДДДДДДДДДДДДДДДДДДДДД
_BC_ > "Скорее всего, дело именно в этом" Наверное ты прав, и именно так винда без всяких проверок определяет число релоков и соответсвенно глупо нарывается на Access Viоlation при TableSize > 0 и BlockSize = 0. И обоср-ся тут не фасм, а гениальные ламеры от микрософта А фасм, как я уже сказал, не прав в том что указывает размер секции инициализированных данных SizeOfRawData = 0, что ес-но недопустимо. Если заменить флаг секции с INITIALIZED на UNINITIALIZED или вообще не создавать секцию reloc, то при TableSize=0 все грузится без проблем. А логика загрузки видимо такая. Сначала просто анализируется PE-хидер и создается сырой образ. Если встречается инициализированная секция с SizeOfRawData = 0, то на выход с песнями и сообщением о неверном формате. Если же сырой образ создается нормально, то на стадии релока первым делом проверяется размер таблицы релоков. Если он = 0, то винда считает, что релоков нет и идет дальше. Если размер таблицы > 0, то тупая винда забывает про этот размер и начинает без всяких проверок обрабатывать блоки таблицы, наивно предполагая что тут ошибок быть не может и все BlockSize >= 8. Скорее всего по жизни так оно и есть, но все таки такой подход выглядит чистейшой шарой и ламерством
Имхо товарищи, это наш глюк Такая dll нормально грузится по любому адресу и работает Код (Text): ;================================= format pe gui dll include '%fasminc%\win32a.inc' ;================================= entry $ xor eax,eax inc eax ret 0x0c ;================================= Т.ч. нам релоки тут не нужны и нефиг их сюда добавлять, Привалов абсолютно прав, все в наших руках, а масму если хочется создавать отдельную секцию, тем более когда это не надо - то его проблемы (попробуйте заставить его это не делать IceStudent собсно сразу это и сказал, нам надо было протестировать без релоков, загрузчик тогда сообщает Message=Debug string: LDR: Fixups won't be re-applied to non-Dll @ 140000, где 140000 - новый imagebase
масм тоже должен! короче раз так: масм - сам создает релоки (даже когда они не нужны) - всегда в отдельной секции (merge не работает) фасм - возможно указать создавать или нет - возможность определить в отдельной секции или нет Масм это HL ассемблер, не дающий право выбора программисту(переход в LL решается патчингом), Фасм это LL ассемблер, требующий явных указаний прораммистом (переход в HL решается макросами)
bogrus, ты не прав Если уж фасм взялся создавать секцию, то должен это делать правильно или по кр.мере выдавать соответсвующий лог или предупреждение, что фиксапов 0, секция пуста, создавать ее в любом сл. или нет и т.п. А то, что "нам тут релоки не нужны" легко сообразить в твоем простейшем примере и не так просто в общем случае и тем более начинающему программеру, который возможно о релоках то ничего не слышал
leo Не смотрел на ХР, но W9x останавливает загрузку на проверке размера директории релоков (должна быть более 4, строка с '!!!' в вышеприведенном фрагменте), section header для секции .reloc вообще не трогается на данном этапе. Если ImageBase dll'ки не занят, то никакие проверки вообще не выполняются.
_BC_ Да ты прав - 98SE отказывается грузить dll при Relocation Table Size = 0 Значит для совместимости с 9x таблица релоков все таки должна быть в любом случае и надо бы ткнуть упрямого Томаша носом в этот фак(т) )) Поэтому добавочка dd 0,8 при отсутсвии релоков все таки нужна. Что-то вроде этого: Код (Text): fixupstart: data fixups if rva $ = rva fixapstart dd 0,8 end if end data Кстати в 98 есть еще одна хитрая фишка, если фиксапы расположить в секции кода. Если релоков нет (т.е. рулит dd 0,8) то dll грузится нормально. При наличии релоков dll грузится без проблем только в случае, если секция кода writeable, иначе происходит капитальный висяк. Если же совать фиксапы в другие секции без атрибута writeble (.data,.export,.import), то все грузится нормально. Вот такие хитрости
leo Так значит мой мини-пример dll без релоков не будет загружен LoadLibrary на 9x? Хм, это же все меняет (очередной раз , значит где-то должно быть четко сказано: любая dll обязана иметь директорию релоков с размером не меньше 8 байт!!! Т.ч. если хотите тыкать кого-то носом, найдите сперва куда тыкать (у меня не получается, bad english) Peering Inside the PE: A Tour of the Win32 Portable Executable File Format PE File Base Relocations When the linker creates an EXE file, it makes an assumption about where the file will be mapped into memory. Based on this, the linker puts the real addresses of code and data items into the executable file. If for whatever reason the executable ends up being loaded somewhere else in the virtual address space, the addresses the linker plugged into the image are wrong. The information stored in the .reloc section allows the PE loader to fix these addresses in the loaded image so that they're correct again. On the other hand, <font color="red]if the loader was able to load the file at the base address assumed by the linker, the .reloc section data isn't needed and is ignored</font><!--color-->. The entries in the .reloc section are called base relocations since their use depends on the base address of the loaded image. Может это был баг 9x, который потом исправили? Такое не редко бывает, мы же все не можем знать
bogrus ИМХО если бы это было где-то четко сказано, то наверное Томаш бы в эту фигню не "вляпался" Скорее всего это просто недокументированная особенность 9х, проверить которую никому не пришло в голову PS: Не понятно, что и зачем ты выделил красным, т.к. если базовый адрес не изменяется, то все нормально работает без всяких релоков и в NT и в 9х. А секция .reloc вообще не обязательна, т.к. таблица (директория) релоков может располагаться в любой другой секции