Cygwin: Use MEMORY_WORKING_SET_EX_INFORMATION in dumper
Use the (undocumented) MEMORY_WORKING_SET_EX_INFORMATION in dumper to determine if a MEM_IMAGE region is unsharable, and hence has been modified. After this, we will end up dumping memory regions where: - state is MEM_COMMIT (i.e. is not MEM_RESERVE or MEM_FREE), and -- type is MEM_PRIVATE and protection allows reads (i.e. not a guardpage), or -- type is MEM_IMAGE and attribute is non-sharable (i.e. it was WC, got written to, and is now a RW copy)
This commit is contained in:
parent
574bc4a349
commit
270282e9a4
|
@ -524,11 +524,11 @@ error_start=x:\path\to\dumper.exe
|
|||
<command>dumper</command> exits, the target process is terminated too. </para>
|
||||
|
||||
<para> To save space in the core dump, <command>dumper</command> doesn't
|
||||
write those portions of target process' memory space that are loaded from
|
||||
executable and dll files and are unchangeable, such as program code and
|
||||
debug info. Instead, <command>dumper</command> saves paths to files which
|
||||
write those portions of the target process's memory space that are loaded
|
||||
from executable and dll files and are unchanged (e.g. program code).
|
||||
Instead, <command>dumper</command> saves paths to the files which
|
||||
contain that data. When a core dump is loaded into gdb, it uses these
|
||||
paths to load appropriate files. That means that if you create a core
|
||||
paths to load the appropriate files. That means that if you create a core
|
||||
dump on one machine and try to debug it on another, you'll need to place
|
||||
identical copies of the executable and dlls in the same directories as on
|
||||
the machine where the core dump was created. </para>
|
||||
|
|
|
@ -116,7 +116,7 @@ CYGWIN_BINS += dumper.exe
|
|||
dumper.o module_info.o: CXXFLAGS += -I$(top_srcdir)/include
|
||||
dumper.o: dumper.h
|
||||
dumper.exe: module_info.o
|
||||
dumper.exe: CYGWIN_LDFLAGS += -lpsapi -lbfd -lintl -liconv -liberty ${ZLIB}
|
||||
dumper.exe: CYGWIN_LDFLAGS += -lpsapi -lbfd -lintl -liconv -liberty ${ZLIB} -lntdll
|
||||
else
|
||||
all: warn_dumper
|
||||
endif
|
||||
|
|
|
@ -266,6 +266,46 @@ void protect_dump(DWORD protect, char *buf)
|
|||
strcat (buf, pt[i]);
|
||||
}
|
||||
|
||||
typedef enum _MEMORY_INFORMATION_CLASS
|
||||
{
|
||||
MemoryWorkingSetExInformation = 4, // MEMORY_WORKING_SET_EX_INFORMATION
|
||||
} MEMORY_INFORMATION_CLASS;
|
||||
|
||||
extern "C"
|
||||
NTSTATUS
|
||||
NtQueryVirtualMemory(HANDLE ProcessHandle,
|
||||
LPVOID BaseAddress,
|
||||
MEMORY_INFORMATION_CLASS MemoryInformationClass,
|
||||
LPVOID MemoryInformation,
|
||||
SIZE_T MemoryInformationLength,
|
||||
SIZE_T *ReturnLength);
|
||||
|
||||
typedef struct _MEMORY_WORKING_SET_EX_INFORMATION
|
||||
{
|
||||
LPVOID VirtualAddress;
|
||||
ULONG_PTR Long;
|
||||
} MEMORY_WORKING_SET_EX_INFORMATION;
|
||||
|
||||
#define MWSEI_ATTRIB_SHARED (0x1 << 15)
|
||||
|
||||
static BOOL
|
||||
getRegionAttributes(HANDLE hProcess, LPVOID address, DWORD &attribs)
|
||||
{
|
||||
MEMORY_WORKING_SET_EX_INFORMATION mwsei = { address };
|
||||
NTSTATUS status = NtQueryVirtualMemory(hProcess, 0,
|
||||
MemoryWorkingSetExInformation,
|
||||
&mwsei, sizeof(mwsei), 0);
|
||||
|
||||
if (!status)
|
||||
{
|
||||
attribs = mwsei.Long;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
deb_printf("MemoryWorkingSetExInformation failed status %08x\n", status);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int
|
||||
dumper::collect_memory_sections ()
|
||||
{
|
||||
|
@ -292,10 +332,27 @@ dumper::collect_memory_sections ()
|
|||
int skip_region_p = 0;
|
||||
const char *disposition = "dumped";
|
||||
|
||||
if ((mbi.Type & MEM_IMAGE) && !(mbi.Protect & (PAGE_EXECUTE_READWRITE | PAGE_READWRITE)))
|
||||
if (mbi.Type & MEM_IMAGE)
|
||||
{
|
||||
skip_region_p = 1;
|
||||
disposition = "skipped due to non-writeable MEM_IMAGE";
|
||||
DWORD attribs = 0;
|
||||
if (getRegionAttributes(hProcess, current_page_address, attribs))
|
||||
{
|
||||
if (attribs & MWSEI_ATTRIB_SHARED)
|
||||
{
|
||||
skip_region_p = 1;
|
||||
disposition = "skipped due to shared MEM_IMAGE";
|
||||
}
|
||||
}
|
||||
/*
|
||||
The undocumented MemoryWorkingSetExInformation is allegedly
|
||||
supported since XP, so should always succeed, but if it fails,
|
||||
fallback to looking at region protection.
|
||||
*/
|
||||
else if (!(mbi.Protect & (PAGE_EXECUTE_READWRITE | PAGE_READWRITE)))
|
||||
{
|
||||
skip_region_p = 1;
|
||||
disposition = "skipped due to non-writeable MEM_IMAGE";
|
||||
}
|
||||
}
|
||||
|
||||
if (mbi.Protect & PAGE_NOACCESS)
|
||||
|
|
Loading…
Reference in New Issue