Отключить LFH в Windows? - PullRequest
       46

Отключить LFH в Windows?

3 голосов
/ 23 марта 2012

Я пытаюсь отключить LFH для приложения, которое пытаюсь отладить.Я могу перестроить и заново развернуть приложение, но не могу подключить отладчик или установить какие-либо флаги.

Какой хороший способ отключить LFH с этими ограничениями?Может ли быть атрибут, который я могу изменить в самом исполняемом файле?Или какой-нибудь код запуска, который я могу добавить в программу?

Ответы [ 4 ]

2 голосов
/ 23 марта 2012

В Vista и Win7, я думаю, вы можете отключить кучу низкой фрагментации для каждого исполняемого файла с помощью Application Compatibility Toolkit.

В XP документация предлагает вы не получите LFH по умолчанию .Так что, вероятно, это ваша библиотека времени выполнения C ++ (которую вы не назвали), которая включает ее.И это не может быть отключено после включения.Так что проверьте документацию для вашей конкретной библиотеки времени выполнения, чтобы увидеть, можете ли вы сказать ей, что она не должна включать LFH, или есть другая версия библиотеки времени выполнения, с которой вы можете связать ее, но она не включается.1009 * эта тема на форумах Microsoft

1 голос
/ 25 марта 2012

На основании приведенного выше комментария Майкла Барра о IMAGE_LOAD_CONFIG_DIRECTORY, содержащем GlobalFlagSet, я написал следующий код, чтобы продемонстрировать, как правильно использовать GlobalFlag для отключения кучи с низкой фрагментацией.Одно предупреждение о написании вашего собственного IMAGE_LOAD_CONFIG_DIRECTORY во время компиляции заключается в том, что он отключает SafeSEH.

// editloadconfig.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <windows.h>

#include <tchar.h>
#include <stdio.h>


/*
typedef struct {
    DWORD   Size;
    DWORD   TimeDateStamp;
    WORD    MajorVersion;
    WORD    MinorVersion;
    DWORD   GlobalFlagsClear;
    DWORD   GlobalFlagsSet;
    DWORD   CriticalSectionDefaultTimeout;
    DWORD   DeCommitFreeBlockThreshold;
    DWORD   DeCommitTotalFreeThreshold;
    DWORD   LockPrefixTable;            // VA
    DWORD   MaximumAllocationSize;
    DWORD   VirtualMemoryThreshold;
    DWORD   ProcessHeapFlags;
    DWORD   ProcessAffinityMask;
    WORD    CSDVersion;
    WORD    Reserved1;
    DWORD   EditList;                   // VA
    DWORD   SecurityCookie;             // VA
    DWORD   SEHandlerTable;             // VA
    DWORD   SEHandlerCount;
} IMAGE_LOAD_CONFIG_DIRECTORY32, *PIMAGE_LOAD_CONFIG_DIRECTORY32;
*/


extern "C" 
IMAGE_LOAD_CONFIG_DIRECTORY _load_config_used = { 0x48, 0, 0, 0,0, 0x00000020/*enable heap free checking*/};
// change the last value to 0 to not enable any globalflags


#define HEAP_STANDARD 0
#define HEAP_LAL 1
#define HEAP_LFH 2
#define SIZE 100

int _tmain(int argc, _TCHAR* argv[])
{
   BOOL bResult;
   HANDLE hHeap;
   ULONG HeapInformation;
   void* allocb[0x12+1];


   // based on "Understanding the LFH" paper at
   // http://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=5&ved=0CE0QFjAE&url=http%3A%2F%2Fillmatics.com%2FUnderstanding_the_LFH.pdf&ei=GlBvT9yrMKHy0gGHpLnaBg&usg=AFQjCNGsvVtl54X7MWGyWYqiSrsdTBrbXQ
   int i = 0;
   for(i = 0; i < 0x12; i++) 
   { 
        printf("Allocation 0x%02x for 0x%02x bytes\n", i, SIZE); 
        allocb[i] = HeapAlloc(GetProcessHeap(), 0x0, SIZE); 
   }

   printf("Allocation 0x%02x for 0x%02x bytes\n", i++, SIZE); 
   printf("\tFirst serviced by the LFH\n"); 
   allocb[i] = HeapAlloc(GetProcessHeap(), 0x0, SIZE);
   // LFH is now activated so the query below will return 0 or 2.

   // sample code from MSDN for querying heap information
   //
   // Get a handle to the default process heap.
   //
   hHeap = GetProcessHeap();
   if (hHeap == NULL) {
       _tprintf(TEXT("Failed to retrieve default process heap with LastError %d.\n"),
                GetLastError());
       return 1;
   }

   //
   // Query heap features that are enabled.
   //
   bResult = HeapQueryInformation(hHeap,
                                  HeapCompatibilityInformation,
                                  &HeapInformation,
                                  sizeof(HeapInformation),
                                  NULL);
   if (bResult == FALSE) {
       _tprintf(TEXT("Failed to retrieve heap features with LastError %d.\n"),
                GetLastError());
       return 1;
   }

   //
   // Print results of the query.
   //
   _tprintf(TEXT("HeapCompatibilityInformation is %d.\n"), HeapInformation);
   switch(HeapInformation)
   {
   case HEAP_STANDARD:
       _tprintf(TEXT("The default process heap is a standard heap.\n"));
       break;
   case HEAP_LAL:
       _tprintf(TEXT("The default process heap supports look-aside lists.\n"));
       break;
   case HEAP_LFH:
       _tprintf(TEXT("The default process heap has the low-fragmentation ") \
                TEXT("heap enabled.\n"));
       break;
   default:
       _tprintf(TEXT("Unrecognized HeapInformation reported for the default ") \
                TEXT("process heap.\n"));
       break;
    }

   return 0; 
}
1 голос
/ 23 марта 2012

Вы можете использовать инструмент gflags.exe, который входит в состав WDK (возможно, также SDK через пакет средств отладки для Windows), чтобы управлять подмножеством gflags в PE-заголовке исполняемого образа. Просто перейдите на вкладку «Файл изображения» в «gflags.exe».

Как указал jcopenha в комментарии, похоже, что gflags.exe не манипулирует заголовком PE-файла (я полагался на информацию из «Внутренних компонентов Windows, пятое издание» в главе 9 «Функции отладки кучи») по-видимому, он манипулирует только разделом реестра «Параметры выполнения файла изображения».

Тем не менее, все еще возможно установить (или очистить) биты gflags для конкретного исполняемого файла в образе - см. документы для IMAGE_LOAD_CONFIG_DIRECTORY структуры ; в частности поля GlobalFlagsClear и GlobalFlagsSet:

  • GlobalFlagsClear - глобальные флаги, управляющие поведением системы. Для получения дополнительной информации см. Gflags.exe.
  • GlobalFlagsSet - глобальные флаги, управляющие поведением системы. Для получения дополнительной информации см. Gflags.exe.

Вы можете вывести эти поля с помощью dumpbin (или link /dump), используя опцию /loadconfig:

C:\temp>dumpbin /loadconfig test.exe
Microsoft (R) COFF/PE Dumper Version 10.00.40219.01
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file test.exe

File Type: EXECUTABLE IMAGE

  Section contains the following load config:

            00000048 size
                   0 time date stamp
                0.00 Version
                   0 GlobalFlags Clear
                   0 GlobalFlags Set             // <=======
                   0 Critical Section Default Timeout

 // remainder of dump snipped...

Вы можете получить RVA «Загрузить каталог конфигурации», используя dumpbin /headers:

C:\temp>dumpbin /headers test.exe
Microsoft (R) COFF/PE Dumper Version 10.00.40219.01
Copyright (C) Microsoft Corporation.  All rights reserved.


Dump of file test.exe

// ...

OPTIONAL HEADER VALUES

// ...

           142B0 [      40] RVA [size] of Load Configuration Directory
//         ^^^^^            ^^^
// ...

Интересно, что опции /loadconfig и /headers не согласуются с размером структуры (для записи, похоже, информация /header неверна)

К сожалению, я не знаю редактора PE, который напрямую поддерживает эти поля - вам, вероятно, придется использовать шестнадцатеричный редактор (или функцию шестнадцатеричного редактирования редактора PE), чтобы изменить эти поля. RVA структуры IMAGE_LOAD_CONFIG_DIRECTORY должна помочь вам найти ее в шестнадцатеричном редакторе.

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

0 голосов
/ 24 марта 2012

Самый простой способ, если вы не можете изменить конфигурацию на машине, это установить информацию о куче.

http://msdn.microsoft.com/en-us/library/windows/desktop/aa366705(v=vs.85).aspx

Я полагаю, что таким способом вы можете отключить кучу LFH, хотя я не пробовал.

...