struct dump_memory
{
- ULONG base;
+ ULONG64 base;
ULONG size;
ULONG rva;
};
struct dump_module
{
unsigned is_elf;
- ULONG base;
+ ULONG64 base;
ULONG size;
DWORD timestamp;
DWORD checksum;
/* module information */
struct dump_module* modules;
unsigned num_modules;
+ unsigned alloc_modules;
/* exception information */
/* output information */
MINIDUMP_TYPE type;
RVA rva;
struct dump_memory* mem;
unsigned num_mem;
+ unsigned alloc_mem;
/* callback information */
MINIDUMP_CALLBACK_INFORMATION* cb;
};
dc->spi = dc->pcs_buffer;
for (;;)
{
- if (dc->spi->dwProcessID == dc->pid) return TRUE;
- if (!dc->spi->dwOffset) break;
- dc->spi = (SYSTEM_PROCESS_INFORMATION*)
- ((char*)dc->spi + dc->spi->dwOffset);
+ if (HandleToUlong(dc->spi->UniqueProcessId) == dc->pid) return TRUE;
+ if (!dc->spi->NextEntryOffset) break;
+ dc->spi = (SYSTEM_PROCESS_INFORMATION*)((char*)dc->spi + dc->spi->NextEntryOffset);
}
}
HeapFree(GetProcessHeap(), 0, dc->pcs_buffer);
const CONTEXT* ctx, MINIDUMP_MEMORY_DESCRIPTOR* mmd)
{
NT_TIB tib;
+ ADDRESS64 addr;
- if (ReadProcessMemory(dc->hProcess, teb_addr, &tib, sizeof(tib), NULL))
+ if (ReadProcessMemory(dc->hProcess, teb_addr, &tib, sizeof(tib), NULL) &&
+ dbghelp_current_cpu &&
+ dbghelp_current_cpu->get_addr(NULL /* FIXME */, ctx, cpu_addr_stack, &addr) && addr.Mode == AddrModeFlat)
{
-#ifdef __i386__
- /* limiting the stack dumping to the size actually used */
- if (ctx->Esp){
-
- /* make sure ESP is within the established range of the stack. It could have
- been clobbered by whatever caused the original exception. */
- if (ctx->Esp - 4 < (ULONG_PTR)tib.StackLimit || ctx->Esp - 4 > (ULONG_PTR)tib.StackBase)
- mmd->StartOfMemoryRange = (ULONG_PTR)tib.StackLimit;
-
- else
- mmd->StartOfMemoryRange = (ctx->Esp - 4);
- }
-
- else
- mmd->StartOfMemoryRange = (ULONG_PTR)tib.StackLimit;
-
-#elif defined(__powerpc__)
- if (ctx->Iar){
-
- /* make sure IAR is within the established range of the stack. It could have
- been clobbered by whatever caused the original exception. */
- if (ctx->Iar - 4 < (ULONG_PTR)tib.StackLimit || ctx->Iar - 4 > (ULONG_PTR)tib.StackBase)
- mmd->StartOfMemoryRange = (ULONG_PTR)tib.StackLimit;
-
- else
- mmd->StartOfMemoryRange = (ctx->Iar - 4);
- }
-
- else
- mmd->StartOfMemoryRange = (ULONG_PTR)tib.StackLimit;
-
-#elif defined(__x86_64__)
- if (ctx->Rsp){
-
- /* make sure RSP is within the established range of the stack. It could have
+ if (addr.Offset)
+ {
+ addr.Offset -= dbghelp_current_cpu->word_size;
+ /* make sure stack pointer is within the established range of the stack. It could have
been clobbered by whatever caused the original exception. */
- if (ctx->Rsp - 8 < (ULONG_PTR)tib.StackLimit || ctx->Rsp - 8 > (ULONG_PTR)tib.StackBase)
+ if (addr.Offset < (ULONG_PTR)tib.StackLimit || addr.Offset > (ULONG_PTR)tib.StackBase)
mmd->StartOfMemoryRange = (ULONG_PTR)tib.StackLimit;
else
- mmd->StartOfMemoryRange = (ctx->Rsp - 8);
+ mmd->StartOfMemoryRange = addr.Offset;
}
-
else
mmd->StartOfMemoryRange = (ULONG_PTR)tib.StackLimit;
-
-#else
-#error unsupported CPU
-#endif
mmd->Memory.DataSize = (ULONG_PTR)tib.StackBase - mmd->StartOfMemoryRange;
}
}
const MINIDUMP_EXCEPTION_INFORMATION* except,
MINIDUMP_THREAD* mdThd, CONTEXT* ctx)
{
- DWORD tid = dc->spi->ti[thd_idx].dwThreadID;
+ DWORD tid = HandleToUlong(dc->spi->ti[thd_idx].ClientId.UniqueThread);
HANDLE hThread;
THREAD_BASIC_INFORMATION tbi;
memset(ctx, 0, sizeof(*ctx));
- mdThd->ThreadId = dc->spi->ti[thd_idx].dwThreadID;
+ mdThd->ThreadId = tid;
mdThd->SuspendCount = 0;
mdThd->Teb = 0;
mdThd->Stack.StartOfMemoryRange = 0;
if ((hThread = OpenThread(THREAD_ALL_ACCESS, FALSE, tid)) == NULL)
{
- FIXME("Couldn't open thread %u (%u)\n",
- dc->spi->ti[thd_idx].dwThreadID, GetLastError());
+ FIXME("Couldn't open thread %u (%u)\n", tid, GetLastError());
return FALSE;
}
ReadProcessMemory(dc->hProcess, except->ExceptionPointers,
&ep, sizeof(ep), NULL);
ReadProcessMemory(dc->hProcess, ep.ContextRecord,
- &ctx, sizeof(ctx), NULL);
+ &lctx, sizeof(lctx), NULL);
pctx = &lctx;
}
else pctx = except->ExceptionPointers->ContextRecord;
* Add a module to a dump context
*/
static BOOL add_module(struct dump_context* dc, const WCHAR* name,
- DWORD base, DWORD size, DWORD timestamp, DWORD checksum,
+ DWORD64 base, DWORD size, DWORD timestamp, DWORD checksum,
BOOL is_elf)
{
if (!dc->modules)
+ {
+ dc->alloc_modules = 32;
dc->modules = HeapAlloc(GetProcessHeap(), 0,
- ++dc->num_modules * sizeof(*dc->modules));
- else
+ dc->alloc_modules * sizeof(*dc->modules));
+ }
+ else if(dc->num_modules >= dc->alloc_modules)
+ {
+ dc->alloc_modules *= 2;
dc->modules = HeapReAlloc(GetProcessHeap(), 0, dc->modules,
- ++dc->num_modules * sizeof(*dc->modules));
- if (!dc->modules) return FALSE;
+ dc->alloc_modules * sizeof(*dc->modules));
+ }
+ if (!dc->modules)
+ {
+ dc->alloc_modules = dc->num_modules = 0;
+ return FALSE;
+ }
if (is_elf ||
- !GetModuleFileNameExW(dc->hProcess, (HMODULE)base,
- dc->modules[dc->num_modules - 1].name,
- sizeof(dc->modules[dc->num_modules - 1].name) / sizeof(WCHAR)))
- lstrcpynW(dc->modules[dc->num_modules - 1].name, name,
- sizeof(dc->modules[dc->num_modules - 1].name) / sizeof(WCHAR));
- dc->modules[dc->num_modules - 1].base = base;
- dc->modules[dc->num_modules - 1].size = size;
- dc->modules[dc->num_modules - 1].timestamp = timestamp;
- dc->modules[dc->num_modules - 1].checksum = checksum;
- dc->modules[dc->num_modules - 1].is_elf = is_elf;
+ !GetModuleFileNameExW(dc->hProcess, (HMODULE)(DWORD_PTR)base,
+ dc->modules[dc->num_modules].name,
+ sizeof(dc->modules[dc->num_modules].name) / sizeof(WCHAR)))
+ lstrcpynW(dc->modules[dc->num_modules].name, name,
+ sizeof(dc->modules[dc->num_modules].name) / sizeof(WCHAR));
+ dc->modules[dc->num_modules].base = base;
+ dc->modules[dc->num_modules].size = size;
+ dc->modules[dc->num_modules].timestamp = timestamp;
+ dc->modules[dc->num_modules].checksum = checksum;
+ dc->modules[dc->num_modules].is_elf = is_elf;
+ dc->num_modules++;
return TRUE;
}
static BOOL WINAPI fetch_pe_module_info_cb(PCWSTR name, DWORD64 base, ULONG size,
PVOID user)
{
- struct dump_context* dc = (struct dump_context*)user;
+ struct dump_context* dc = user;
IMAGE_NT_HEADERS nth;
if (!validate_addr64(base)) return FALSE;
if (pe_load_nt_header(dc->hProcess, base, &nth))
- add_module((struct dump_context*)user, name, base, size,
+ add_module(user, name, base, size,
nth.FileHeader.TimeDateStamp, nth.OptionalHeader.CheckSum,
FALSE);
return TRUE;
static BOOL fetch_elf_module_info_cb(const WCHAR* name, unsigned long base,
void* user)
{
- struct dump_context* dc = (struct dump_context*)user;
+ struct dump_context* dc = user;
DWORD rbase, size, checksum;
/* FIXME: there's no relevant timestamp on ELF modules */
return TRUE;
}
+/******************************************************************
+ * fetch_macho_module_info_cb
+ *
+ * Callback for accumulating in dump_context a Mach-O modules set
+ */
+static BOOL fetch_macho_module_info_cb(const WCHAR* name, unsigned long base,
+ void* user)
+{
+ struct dump_context* dc = (struct dump_context*)user;
+ DWORD rbase, size, checksum;
+
+ /* FIXME: there's no relevant timestamp on Mach-O modules */
+ /* NB: if we have a non-null base from the live-target use it. If we have
+ * a null base, then grab its base address from Mach-O file.
+ */
+ if (!macho_fetch_file_info(name, &rbase, &size, &checksum))
+ size = checksum = 0;
+ add_module(dc, name, base ? base : rbase, size, 0 /* FIXME */, checksum, TRUE);
+ return TRUE;
+}
+
static void fetch_modules_info(struct dump_context* dc)
{
EnumerateLoadedModulesW64(dc->hProcess, fetch_pe_module_info_cb, dc);
* a given application in a post mortem debugging condition.
*/
elf_enum_modules(dc->hProcess, fetch_elf_module_info_cb, dc);
+ macho_enum_modules(dc->hProcess, fetch_macho_module_info_cb, dc);
}
static void fetch_module_versioninfo(LPCWSTR filename, VS_FIXEDFILEINFO* ffi)
*/
static void add_memory_block(struct dump_context* dc, ULONG64 base, ULONG size, ULONG rva)
{
- if (dc->mem)
- dc->mem = HeapReAlloc(GetProcessHeap(), 0, dc->mem,
- ++dc->num_mem * sizeof(*dc->mem));
- else
- dc->mem = HeapAlloc(GetProcessHeap(), 0, ++dc->num_mem * sizeof(*dc->mem));
+ if (!dc->mem)
+ {
+ dc->alloc_mem = 32;
+ dc->mem = HeapAlloc(GetProcessHeap(), 0, dc->alloc_mem * sizeof(*dc->mem));
+ }
+ else if (dc->num_mem >= dc->alloc_mem)
+ {
+ dc->alloc_mem *= 2;
+ dc->mem = HeapReAlloc(GetProcessHeap(), 0, dc->mem,
+ dc->alloc_mem * sizeof(*dc->mem));
+ }
if (dc->mem)
{
- dc->mem[dc->num_mem - 1].base = base;
- dc->mem[dc->num_mem - 1].size = size;
- dc->mem[dc->num_mem - 1].rva = rva;
+ dc->mem[dc->num_mem].base = base;
+ dc->mem[dc->num_mem].size = size;
+ dc->mem[dc->num_mem].rva = rva;
+ dc->num_mem++;
}
- else dc->num_mem = 0;
+ else dc->num_mem = dc->alloc_mem = 0;
}
/******************************************************************
* writes a new chunk of data to the minidump, increasing the current
* rva in dc
*/
-static void append(struct dump_context* dc, void* data, unsigned size)
+static void append(struct dump_context* dc, const void* data, unsigned size)
{
writeat(dc, dc->rva, data, size);
dc->rva += size;
{
MINIDUMP_THREAD mdThd;
MINIDUMP_THREAD_LIST mdThdList;
- unsigned i;
+ unsigned i, sz;
RVA rva_base;
DWORD flags_out;
CONTEXT ctx;
mdThdList.NumberOfThreads = 0;
rva_base = dc->rva;
- dc->rva += sizeof(mdThdList.NumberOfThreads) +
- dc->spi->dwThreadCount * sizeof(mdThd);
+ dc->rva += sz = sizeof(mdThdList.NumberOfThreads) + dc->spi->dwThreadCount * sizeof(mdThd);
for (i = 0; i < dc->spi->dwThreadCount; i++)
{
cbin.ProcessId = dc->pid;
cbin.ProcessHandle = dc->hProcess;
cbin.CallbackType = ThreadCallback;
- cbin.u.Thread.ThreadId = dc->spi->ti[i].dwThreadID;
+ cbin.u.Thread.ThreadId = HandleToUlong(dc->spi->ti[i].ClientId.UniqueThread);
cbin.u.Thread.ThreadHandle = 0; /* FIXME */
cbin.u.Thread.Context = ctx;
cbin.u.Thread.SizeOfContext = sizeof(CONTEXT);
writeat(dc, rva_base,
&mdThdList.NumberOfThreads, sizeof(mdThdList.NumberOfThreads));
- return dc->rva - rva_base;
+ return sz;
}
/******************************************************************
{
len = min(dc->mem[i].size - pos, sizeof(tmp));
if (ReadProcessMemory(dc->hProcess,
- (void*)(dc->mem[i].base + pos),
+ (void*)(DWORD_PTR)(dc->mem[i].base + pos),
tmp, len, NULL))
WriteFile(dc->hFile, tmp, len, &written, NULL);
}
dc.pid = pid;
dc.modules = NULL;
dc.num_modules = 0;
+ dc.alloc_modules = 0;
dc.cb = CallbackParam;
dc.type = DumpType;
dc.mem = NULL;
dc.num_mem = 0;
+ dc.alloc_mem = 0;
dc.rva = 0;
if (!fetch_processes_info(&dc)) return FALSE;
PMINIDUMP_DIRECTORY* pdir,
PVOID* stream, ULONG* size)
{
- MINIDUMP_HEADER* mdHead = (MINIDUMP_HEADER*)base;
+ MINIDUMP_HEADER* mdHead = base;
if (mdHead->Signature == MINIDUMP_SIGNATURE)
{
{
if (dir->StreamType == str_idx)
{
- *pdir = dir;
- *stream = (char*)base + dir->Location.Rva;
- *size = dir->Location.DataSize;
+ if (pdir) *pdir = dir;
+ if (stream) *stream = (char*)base + dir->Location.Rva;
+ if (size) *size = dir->Location.DataSize;
return TRUE;
}
}