mirror of
https://github.com/reactos/reactos.git
synced 2025-03-30 17:10:22 +00:00
Sync dbghelp and imagehlp to Wine 1.2
Winhttp and Wininet don't like me and so I skip them for now. svn path=/trunk/; revision=48290
This commit is contained in:
parent
e3b6d0cea7
commit
7d17455cc4
25 changed files with 2775 additions and 1953 deletions
|
@ -98,7 +98,7 @@ enum st_mode {stm_start, stm_32bit, stm_16bit, stm_done};
|
|||
#define curr_switch (frame->Reserved[__CurrentSwitch])
|
||||
#define next_switch (frame->Reserved[__NextSwitch])
|
||||
|
||||
static BOOL i386_stack_walk(struct cpu_stack_walk* csw, LPSTACKFRAME64 frame)
|
||||
static BOOL i386_stack_walk(struct cpu_stack_walk* csw, LPSTACKFRAME64 frame, CONTEXT* context)
|
||||
{
|
||||
STACK32FRAME frame32;
|
||||
STACK16FRAME frame16;
|
||||
|
@ -107,6 +107,7 @@ static BOOL i386_stack_walk(struct cpu_stack_walk* csw, LPSTACKFRAME64 frame)
|
|||
DWORD p;
|
||||
WORD val;
|
||||
BOOL do_switch;
|
||||
unsigned deltapc = 1;
|
||||
|
||||
/* sanity check */
|
||||
if (curr_mode >= stm_done) return FALSE;
|
||||
|
@ -132,6 +133,7 @@ static BOOL i386_stack_walk(struct cpu_stack_walk* csw, LPSTACKFRAME64 frame)
|
|||
|
||||
/* Init done */
|
||||
curr_mode = (frame->AddrPC.Mode == AddrModeFlat) ? stm_32bit : stm_16bit;
|
||||
deltapc = 0;
|
||||
|
||||
/* cur_switch holds address of WOW32Reserved field in TEB in debuggee
|
||||
* address space
|
||||
|
@ -191,6 +193,21 @@ static BOOL i386_stack_walk(struct cpu_stack_walk* csw, LPSTACKFRAME64 frame)
|
|||
* we will get it in the next frame
|
||||
*/
|
||||
memset(&frame->AddrBStore, 0, sizeof(frame->AddrBStore));
|
||||
#ifdef __i386__
|
||||
if (curr_mode == stm_32bit)
|
||||
{
|
||||
DWORD_PTR xframe;
|
||||
|
||||
if (dwarf2_virtual_unwind(csw, frame->AddrPC.Offset - deltapc, context, &xframe))
|
||||
{
|
||||
frame->AddrStack.Mode = frame->AddrFrame.Mode = frame->AddrReturn.Mode = AddrModeFlat;
|
||||
frame->AddrStack.Offset = context->Esp = xframe;
|
||||
frame->AddrFrame.Offset = context->Ebp;
|
||||
frame->AddrReturn.Offset = context->Eip;
|
||||
goto done_pep;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -317,6 +334,18 @@ static BOOL i386_stack_walk(struct cpu_stack_walk* csw, LPSTACKFRAME64 frame)
|
|||
}
|
||||
else
|
||||
{
|
||||
#ifdef __i386__
|
||||
DWORD_PTR xframe;
|
||||
|
||||
if (dwarf2_virtual_unwind(csw, frame->AddrPC.Offset - deltapc, context, &xframe))
|
||||
{
|
||||
frame->AddrStack.Mode = frame->AddrFrame.Mode = frame->AddrReturn.Mode = AddrModeFlat;
|
||||
frame->AddrStack.Offset = context->Esp = xframe;
|
||||
frame->AddrFrame.Offset = context->Ebp;
|
||||
frame->AddrReturn.Offset = context->Eip;
|
||||
goto done_pep;
|
||||
}
|
||||
#endif
|
||||
frame->AddrStack.Offset = frame->AddrFrame.Offset + 2 * sizeof(DWORD);
|
||||
/* "pop up" previous EBP value */
|
||||
if (!sw_read_mem(csw, frame->AddrFrame.Offset,
|
||||
|
@ -381,6 +410,23 @@ static BOOL i386_stack_walk(struct cpu_stack_walk* csw, LPSTACKFRAME64 frame)
|
|||
sw_read_mem(csw, frame->AddrFrame.Offset + 2 * sizeof(DWORD),
|
||||
frame->Params, sizeof(frame->Params));
|
||||
}
|
||||
#ifdef __i386__
|
||||
if (context)
|
||||
{
|
||||
#define SET(field, seg, reg) \
|
||||
switch (frame->field.Mode) \
|
||||
{ \
|
||||
case AddrModeFlat: context->reg = frame->field.Offset; break; \
|
||||
case AddrMode1616: context->seg = frame->field.Segment; context->reg = frame->field.Offset; break; \
|
||||
default: assert(0); \
|
||||
}
|
||||
SET(AddrStack, SegSs, Esp);
|
||||
SET(AddrFrame, SegSs, Ebp);
|
||||
SET(AddrReturn, SegCs, Eip);
|
||||
#undef SET
|
||||
}
|
||||
done_pep:
|
||||
#endif
|
||||
|
||||
frame->Far = TRUE;
|
||||
frame->Virtual = TRUE;
|
||||
|
@ -404,9 +450,132 @@ done_err:
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static unsigned i386_map_dwarf_register(unsigned regno)
|
||||
{
|
||||
unsigned reg;
|
||||
|
||||
switch (regno)
|
||||
{
|
||||
case 0: reg = CV_REG_EAX; break;
|
||||
case 1: reg = CV_REG_ECX; break;
|
||||
case 2: reg = CV_REG_EDX; break;
|
||||
case 3: reg = CV_REG_EBX; break;
|
||||
case 4: reg = CV_REG_ESP; break;
|
||||
case 5: reg = CV_REG_EBP; break;
|
||||
case 6: reg = CV_REG_ESI; break;
|
||||
case 7: reg = CV_REG_EDI; break;
|
||||
case 8: reg = CV_REG_EIP; break;
|
||||
case 9: reg = CV_REG_EFLAGS; break;
|
||||
case 10: reg = CV_REG_CS; break;
|
||||
case 11: reg = CV_REG_SS; break;
|
||||
case 12: reg = CV_REG_DS; break;
|
||||
case 13: reg = CV_REG_ES; break;
|
||||
case 14: reg = CV_REG_FS; break;
|
||||
case 15: reg = CV_REG_GS; break;
|
||||
case 16: case 17: case 18: case 19:
|
||||
case 20: case 21: case 22: case 23:
|
||||
reg = CV_REG_ST0 + regno - 16; break;
|
||||
case 24: reg = CV_REG_CTRL; break;
|
||||
case 25: reg = CV_REG_STAT; break;
|
||||
case 26: reg = CV_REG_TAG; break;
|
||||
/*
|
||||
reg: fiseg 27
|
||||
reg: fioff 28
|
||||
reg: foseg 29
|
||||
reg: fooff 30
|
||||
reg: fop 31
|
||||
*/
|
||||
case 32: case 33: case 34: case 35:
|
||||
case 36: case 37: case 38: case 39:
|
||||
reg = CV_REG_XMM0 + regno - 32; break;
|
||||
case 40: reg = CV_REG_MXCSR; break;
|
||||
default:
|
||||
FIXME("Don't know how to map register %d\n", regno);
|
||||
return 0;
|
||||
}
|
||||
return reg;
|
||||
}
|
||||
|
||||
static void* i386_fetch_context_reg(CONTEXT* ctx, unsigned regno, unsigned* size)
|
||||
{
|
||||
#ifdef __i386__
|
||||
switch (regno)
|
||||
{
|
||||
case CV_REG_EAX: *size = sizeof(ctx->Eax); return &ctx->Eax;
|
||||
case CV_REG_EDX: *size = sizeof(ctx->Edx); return &ctx->Edx;
|
||||
case CV_REG_ECX: *size = sizeof(ctx->Ecx); return &ctx->Ecx;
|
||||
case CV_REG_EBX: *size = sizeof(ctx->Ebx); return &ctx->Ebx;
|
||||
case CV_REG_ESI: *size = sizeof(ctx->Esi); return &ctx->Esi;
|
||||
case CV_REG_EDI: *size = sizeof(ctx->Edi); return &ctx->Edi;
|
||||
case CV_REG_EBP: *size = sizeof(ctx->Ebp); return &ctx->Ebp;
|
||||
case CV_REG_ESP: *size = sizeof(ctx->Esp); return &ctx->Esp;
|
||||
case CV_REG_EIP: *size = sizeof(ctx->Eip); return &ctx->Eip;
|
||||
|
||||
case CV_REG_ST0 + 0: *size = sizeof(long double); return &ctx->FloatSave.RegisterArea[0*sizeof(long double)];
|
||||
case CV_REG_ST0 + 1: *size = sizeof(long double); return &ctx->FloatSave.RegisterArea[1*sizeof(long double)];
|
||||
case CV_REG_ST0 + 2: *size = sizeof(long double); return &ctx->FloatSave.RegisterArea[2*sizeof(long double)];
|
||||
case CV_REG_ST0 + 3: *size = sizeof(long double); return &ctx->FloatSave.RegisterArea[3*sizeof(long double)];
|
||||
case CV_REG_ST0 + 4: *size = sizeof(long double); return &ctx->FloatSave.RegisterArea[4*sizeof(long double)];
|
||||
case CV_REG_ST0 + 5: *size = sizeof(long double); return &ctx->FloatSave.RegisterArea[5*sizeof(long double)];
|
||||
case CV_REG_ST0 + 6: *size = sizeof(long double); return &ctx->FloatSave.RegisterArea[6*sizeof(long double)];
|
||||
case CV_REG_ST0 + 7: *size = sizeof(long double); return &ctx->FloatSave.RegisterArea[7*sizeof(long double)];
|
||||
|
||||
case CV_REG_EFLAGS: *size = sizeof(ctx->EFlags); return &ctx->EFlags;
|
||||
case CV_REG_ES: *size = sizeof(ctx->SegEs); return &ctx->SegEs;
|
||||
case CV_REG_CS: *size = sizeof(ctx->SegCs); return &ctx->SegCs;
|
||||
case CV_REG_SS: *size = sizeof(ctx->SegSs); return &ctx->SegSs;
|
||||
case CV_REG_DS: *size = sizeof(ctx->SegDs); return &ctx->SegDs;
|
||||
case CV_REG_FS: *size = sizeof(ctx->SegFs); return &ctx->SegFs;
|
||||
case CV_REG_GS: *size = sizeof(ctx->SegGs); return &ctx->SegGs;
|
||||
|
||||
}
|
||||
#endif
|
||||
FIXME("Unknown register %x\n", regno);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char* i386_fetch_regname(unsigned regno)
|
||||
{
|
||||
switch (regno)
|
||||
{
|
||||
case CV_REG_EAX: return "eax";
|
||||
case CV_REG_EDX: return "edx";
|
||||
case CV_REG_ECX: return "ecx";
|
||||
case CV_REG_EBX: return "ebx";
|
||||
case CV_REG_ESI: return "esi";
|
||||
case CV_REG_EDI: return "edi";
|
||||
case CV_REG_EBP: return "ebp";
|
||||
case CV_REG_ESP: return "esp";
|
||||
case CV_REG_EIP: return "eip";
|
||||
|
||||
case CV_REG_ST0 + 0: return "st0";
|
||||
case CV_REG_ST0 + 1: return "st1";
|
||||
case CV_REG_ST0 + 2: return "st2";
|
||||
case CV_REG_ST0 + 3: return "st3";
|
||||
case CV_REG_ST0 + 4: return "st4";
|
||||
case CV_REG_ST0 + 5: return "st5";
|
||||
case CV_REG_ST0 + 6: return "st6";
|
||||
case CV_REG_ST0 + 7: return "st7";
|
||||
|
||||
case CV_REG_EFLAGS: return "eflags";
|
||||
case CV_REG_ES: return "es";
|
||||
case CV_REG_CS: return "cs";
|
||||
case CV_REG_SS: return "ss";
|
||||
case CV_REG_DS: return "ds";
|
||||
case CV_REG_FS: return "fs";
|
||||
case CV_REG_GS: return "gs";
|
||||
}
|
||||
FIXME("Unknown register %x\n", regno);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct cpu cpu_i386 = {
|
||||
IMAGE_FILE_MACHINE_I386,
|
||||
4,
|
||||
i386_get_addr,
|
||||
i386_stack_walk,
|
||||
NULL,
|
||||
i386_map_dwarf_register,
|
||||
i386_fetch_context_reg,
|
||||
i386_fetch_regname,
|
||||
};
|
||||
|
|
|
@ -48,15 +48,37 @@ static unsigned ppc_get_addr(HANDLE hThread, const CONTEXT* ctx,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static BOOL ppc_stack_walk(struct cpu_stack_walk* csw, LPSTACKFRAME64 frame)
|
||||
static BOOL ppc_stack_walk(struct cpu_stack_walk* csw, LPSTACKFRAME64 frame, CONTEXT* context)
|
||||
{
|
||||
FIXME("not done\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static unsigned ppc_map_dwarf_register(unsigned regno)
|
||||
{
|
||||
FIXME("not done\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void* ppc_fetch_context_reg(CONTEXT* ctx, unsigned regno, unsigned* size)
|
||||
{
|
||||
FIXME("NIY\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char* ppc_fetch_regname(unsigned regno)
|
||||
{
|
||||
FIXME("Unknown register %x\n", regno);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct cpu cpu_ppc = {
|
||||
IMAGE_FILE_MACHINE_POWERPC,
|
||||
4,
|
||||
ppc_get_addr,
|
||||
ppc_stack_walk,
|
||||
NULL,
|
||||
ppc_map_dwarf_register,
|
||||
ppc_fetch_context_reg,
|
||||
ppc_fetch_regname,
|
||||
};
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
/*
|
||||
* File cpu_x86_64.c
|
||||
*
|
||||
* Copyright (C) 2009-2009, Eric Pouech.
|
||||
* Copyright (C) 1999, 2005 Alexandre Julliard
|
||||
* Copyright (C) 2009 Eric Pouech.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -20,6 +21,8 @@
|
|||
|
||||
#include <assert.h>
|
||||
|
||||
#define NONAMELESSUNION
|
||||
#define NONAMELESSSTRUCT
|
||||
#include "ntstatus.h"
|
||||
#define WIN32_NO_STATUS
|
||||
#include "dbghelp_private.h"
|
||||
|
@ -28,6 +31,66 @@
|
|||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
|
||||
|
||||
/* x86-64 unwind information, for PE modules, as described on MSDN */
|
||||
|
||||
typedef enum _UNWIND_OP_CODES
|
||||
{
|
||||
UWOP_PUSH_NONVOL = 0,
|
||||
UWOP_ALLOC_LARGE,
|
||||
UWOP_ALLOC_SMALL,
|
||||
UWOP_SET_FPREG,
|
||||
UWOP_SAVE_NONVOL,
|
||||
UWOP_SAVE_NONVOL_FAR,
|
||||
UWOP_SAVE_XMM128,
|
||||
UWOP_SAVE_XMM128_FAR,
|
||||
UWOP_PUSH_MACHFRAME
|
||||
} UNWIND_CODE_OPS;
|
||||
|
||||
typedef union _UNWIND_CODE
|
||||
{
|
||||
struct
|
||||
{
|
||||
BYTE CodeOffset;
|
||||
BYTE UnwindOp : 4;
|
||||
BYTE OpInfo : 4;
|
||||
};
|
||||
USHORT FrameOffset;
|
||||
} UNWIND_CODE, *PUNWIND_CODE;
|
||||
|
||||
typedef struct _UNWIND_INFO
|
||||
{
|
||||
BYTE Version : 3;
|
||||
BYTE Flags : 5;
|
||||
BYTE SizeOfProlog;
|
||||
BYTE CountOfCodes;
|
||||
BYTE FrameRegister : 4;
|
||||
BYTE FrameOffset : 4;
|
||||
UNWIND_CODE UnwindCode[1]; /* actually CountOfCodes (aligned) */
|
||||
/*
|
||||
* union
|
||||
* {
|
||||
* OPTIONAL ULONG ExceptionHandler;
|
||||
* OPTIONAL ULONG FunctionEntry;
|
||||
* };
|
||||
* OPTIONAL ULONG ExceptionData[];
|
||||
*/
|
||||
} UNWIND_INFO, *PUNWIND_INFO;
|
||||
|
||||
#define GetUnwindCodeEntry(info, index) \
|
||||
((info)->UnwindCode[index])
|
||||
|
||||
#define GetLanguageSpecificDataPtr(info) \
|
||||
((PVOID)&GetUnwindCodeEntry((info),((info)->CountOfCodes + 1) & ~1))
|
||||
|
||||
#define GetExceptionHandler(base, info) \
|
||||
((PEXCEPTION_HANDLER)((base) + *(PULONG)GetLanguageSpecificDataPtr(info)))
|
||||
|
||||
#define GetChainedFunctionEntry(base, info) \
|
||||
((PRUNTIME_FUNCTION)((base) + *(PULONG)GetLanguageSpecificDataPtr(info)))
|
||||
|
||||
#define GetExceptionDataPtr(info) \
|
||||
((PVOID)((PULONG)GetLanguageSpecificData(info) + 1)
|
||||
|
||||
static unsigned x86_64_get_addr(HANDLE hThread, const CONTEXT* ctx,
|
||||
enum cpu_addr ca, ADDRESS64* addr)
|
||||
{
|
||||
|
@ -55,8 +118,368 @@ enum st_mode {stm_start, stm_64bit, stm_done};
|
|||
#define curr_switch (frame->Reserved[__CurrentSwitch])
|
||||
#define next_switch (frame->Reserved[__NextSwitch])
|
||||
|
||||
static BOOL x86_64_stack_walk(struct cpu_stack_walk* csw, LPSTACKFRAME64 frame)
|
||||
#ifdef __x86_64__
|
||||
union handler_data
|
||||
{
|
||||
RUNTIME_FUNCTION chain;
|
||||
ULONG handler;
|
||||
};
|
||||
|
||||
static void dump_unwind_info(HANDLE hProcess, ULONG64 base, RUNTIME_FUNCTION *function)
|
||||
{
|
||||
static const char * const reg_names[16] =
|
||||
{ "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi",
|
||||
"r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15" };
|
||||
|
||||
union handler_data *handler_data;
|
||||
char buffer[sizeof(UNWIND_INFO) + 256 * sizeof(UNWIND_CODE)];
|
||||
UNWIND_INFO* info = (UNWIND_INFO*)buffer;
|
||||
unsigned int i, count;
|
||||
SIZE_T r;
|
||||
|
||||
TRACE("**** func %x-%x\n", function->BeginAddress, function->EndAddress);
|
||||
for (;;)
|
||||
{
|
||||
if (function->UnwindData & 1)
|
||||
{
|
||||
#if 0
|
||||
RUNTIME_FUNCTION *next = (RUNTIME_FUNCTION*)((char*)base + (function->UnwindData & ~1));
|
||||
TRACE("unwind info for function %p-%p chained to function %p-%p\n",
|
||||
(char*)base + function->BeginAddress, (char*)base + function->EndAddress,
|
||||
(char*)base + next->BeginAddress, (char*)base + next->EndAddress);
|
||||
function = next;
|
||||
continue;
|
||||
#else
|
||||
FIXME("NOT SUPPORTED\n");
|
||||
#endif
|
||||
}
|
||||
ReadProcessMemory(hProcess, (char*)base + function->UnwindData, info, sizeof(*info), &r);
|
||||
ReadProcessMemory(hProcess, (char*)base + function->UnwindData + FIELD_OFFSET(UNWIND_INFO, UnwindCode),
|
||||
info->UnwindCode, 256 * sizeof(UNWIND_CODE), &r);
|
||||
TRACE("unwind info at %p flags %x prolog 0x%x bytes function %p-%p\n",
|
||||
info, info->Flags, info->SizeOfProlog,
|
||||
(char*)base + function->BeginAddress, (char*)base + function->EndAddress);
|
||||
|
||||
if (info->FrameRegister)
|
||||
TRACE(" frame register %s offset 0x%x(%%rsp)\n",
|
||||
reg_names[info->FrameRegister], info->FrameOffset * 16);
|
||||
|
||||
for (i = 0; i < info->CountOfCodes; i++)
|
||||
{
|
||||
TRACE(" 0x%x: ", info->UnwindCode[i].CodeOffset);
|
||||
switch (info->UnwindCode[i].UnwindOp)
|
||||
{
|
||||
case UWOP_PUSH_NONVOL:
|
||||
TRACE("pushq %%%s\n", reg_names[info->UnwindCode[i].OpInfo]);
|
||||
break;
|
||||
case UWOP_ALLOC_LARGE:
|
||||
if (info->UnwindCode[i].OpInfo)
|
||||
{
|
||||
count = *(DWORD*)&info->UnwindCode[i+1];
|
||||
i += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
count = *(USHORT*)&info->UnwindCode[i+1] * 8;
|
||||
i++;
|
||||
}
|
||||
TRACE("subq $0x%x,%%rsp\n", count);
|
||||
break;
|
||||
case UWOP_ALLOC_SMALL:
|
||||
count = (info->UnwindCode[i].OpInfo + 1) * 8;
|
||||
TRACE("subq $0x%x,%%rsp\n", count);
|
||||
break;
|
||||
case UWOP_SET_FPREG:
|
||||
TRACE("leaq 0x%x(%%rsp),%s\n",
|
||||
info->FrameOffset * 16, reg_names[info->FrameRegister]);
|
||||
break;
|
||||
case UWOP_SAVE_NONVOL:
|
||||
count = *(USHORT*)&info->UnwindCode[i+1] * 8;
|
||||
TRACE("movq %%%s,0x%x(%%rsp)\n", reg_names[info->UnwindCode[i].OpInfo], count);
|
||||
i++;
|
||||
break;
|
||||
case UWOP_SAVE_NONVOL_FAR:
|
||||
count = *(DWORD*)&info->UnwindCode[i+1];
|
||||
TRACE("movq %%%s,0x%x(%%rsp)\n", reg_names[info->UnwindCode[i].OpInfo], count);
|
||||
i += 2;
|
||||
break;
|
||||
case UWOP_SAVE_XMM128:
|
||||
count = *(USHORT*)&info->UnwindCode[i+1] * 16;
|
||||
TRACE("movaps %%xmm%u,0x%x(%%rsp)\n", info->UnwindCode[i].OpInfo, count);
|
||||
i++;
|
||||
break;
|
||||
case UWOP_SAVE_XMM128_FAR:
|
||||
count = *(DWORD*)&info->UnwindCode[i+1];
|
||||
TRACE("movaps %%xmm%u,0x%x(%%rsp)\n", info->UnwindCode[i].OpInfo, count);
|
||||
i += 2;
|
||||
break;
|
||||
case UWOP_PUSH_MACHFRAME:
|
||||
TRACE("PUSH_MACHFRAME %u\n", info->UnwindCode[i].OpInfo);
|
||||
break;
|
||||
default:
|
||||
FIXME("unknown code %u\n", info->UnwindCode[i].UnwindOp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
handler_data = (union handler_data*)&info->UnwindCode[(info->CountOfCodes + 1) & ~1];
|
||||
if (info->Flags & UNW_FLAG_CHAININFO)
|
||||
{
|
||||
TRACE(" chained to function %p-%p\n",
|
||||
(char*)base + handler_data->chain.BeginAddress,
|
||||
(char*)base + handler_data->chain.EndAddress);
|
||||
function = &handler_data->chain;
|
||||
continue;
|
||||
}
|
||||
if (info->Flags & (UNW_FLAG_EHANDLER | UNW_FLAG_UHANDLER))
|
||||
TRACE(" handler %p data at %p\n",
|
||||
(char*)base + handler_data->handler, &handler_data->handler + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* highly derived from dlls/ntdll/signal_x86_64.c */
|
||||
static ULONG64 get_int_reg(CONTEXT *context, int reg)
|
||||
{
|
||||
return *(&context->Rax + reg);
|
||||
}
|
||||
|
||||
static void set_int_reg(CONTEXT *context, int reg, ULONG64 val)
|
||||
{
|
||||
*(&context->Rax + reg) = val;
|
||||
}
|
||||
|
||||
static void set_float_reg(CONTEXT *context, int reg, M128A val)
|
||||
{
|
||||
*(&context->u.s.Xmm0 + reg) = val;
|
||||
}
|
||||
|
||||
static int get_opcode_size(UNWIND_CODE op)
|
||||
{
|
||||
switch (op.UnwindOp)
|
||||
{
|
||||
case UWOP_ALLOC_LARGE:
|
||||
return 2 + (op.OpInfo != 0);
|
||||
case UWOP_SAVE_NONVOL:
|
||||
case UWOP_SAVE_XMM128:
|
||||
return 2;
|
||||
case UWOP_SAVE_NONVOL_FAR:
|
||||
case UWOP_SAVE_XMM128_FAR:
|
||||
return 3;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL is_inside_epilog(struct cpu_stack_walk* csw, DWORD64 pc)
|
||||
{
|
||||
BYTE op0, op1, op2;
|
||||
|
||||
if (!sw_read_mem(csw, pc, &op0, 1)) return FALSE;
|
||||
|
||||
/* add or lea must be the first instruction, and it must have a rex.W prefix */
|
||||
if ((op0 & 0xf8) == 0x48)
|
||||
{
|
||||
if (!sw_read_mem(csw, pc + 1, &op1, 1)) return FALSE;
|
||||
switch (op1)
|
||||
{
|
||||
case 0x81: /* add $nnnn,%rsp */
|
||||
if (!sw_read_mem(csw, pc + 2, &op2, 1)) return FALSE;
|
||||
if (op0 == 0x48 && op2 == 0xc4)
|
||||
{
|
||||
pc += 7;
|
||||
break;
|
||||
}
|
||||
return FALSE;
|
||||
case 0x83: /* add $n,%rsp */
|
||||
if (op0 == 0x48 && op2 == 0xc4)
|
||||
{
|
||||
pc += 4;
|
||||
break;
|
||||
}
|
||||
return FALSE;
|
||||
case 0x8d: /* lea n(reg),%rsp */
|
||||
if (op0 & 0x06) return FALSE; /* rex.RX must be cleared */
|
||||
if (((op2 >> 3) & 7) != 4) return FALSE; /* dest reg mus be %rsp */
|
||||
if ((op2 & 7) == 4) return FALSE; /* no SIB byte allowed */
|
||||
if ((op2 >> 6) == 1) /* 8-bit offset */
|
||||
{
|
||||
pc += 4;
|
||||
break;
|
||||
}
|
||||
if ((op2 >> 6) == 2) /* 32-bit offset */
|
||||
{
|
||||
pc += 7;
|
||||
break;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
/* now check for various pop instructions */
|
||||
for (;;)
|
||||
{
|
||||
BYTE rex = 0;
|
||||
|
||||
if (!sw_read_mem(csw, pc, &op0, 1)) return FALSE;
|
||||
if ((op0 & 0xf0) == 0x40)
|
||||
{
|
||||
rex = op0 & 0x0f; /* rex prefix */
|
||||
if (!sw_read_mem(csw, ++pc, &op0, 1)) return FALSE;
|
||||
}
|
||||
|
||||
switch (op0)
|
||||
{
|
||||
case 0x58: /* pop %rax/%r8 */
|
||||
case 0x59: /* pop %rcx/%r9 */
|
||||
case 0x5a: /* pop %rdx/%r10 */
|
||||
case 0x5b: /* pop %rbx/%r11 */
|
||||
case 0x5c: /* pop %rsp/%r12 */
|
||||
case 0x5d: /* pop %rbp/%r13 */
|
||||
case 0x5e: /* pop %rsi/%r14 */
|
||||
case 0x5f: /* pop %rdi/%r15 */
|
||||
pc++;
|
||||
continue;
|
||||
case 0xc2: /* ret $nn */
|
||||
case 0xc3: /* ret */
|
||||
return TRUE;
|
||||
/* FIXME: add various jump instructions */
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
static BOOL default_unwind(struct cpu_stack_walk* csw, LPSTACKFRAME64 frame, CONTEXT* context)
|
||||
{
|
||||
if (!sw_read_mem(csw, frame->AddrStack.Offset,
|
||||
&frame->AddrReturn.Offset, sizeof(DWORD64)))
|
||||
{
|
||||
WARN("Cannot read new frame offset %s\n", wine_dbgstr_longlong(frame->AddrStack.Offset));
|
||||
return FALSE;
|
||||
}
|
||||
context->Rip = frame->AddrReturn.Offset;
|
||||
frame->AddrStack.Offset += sizeof(DWORD64);
|
||||
context->Rsp += sizeof(DWORD64);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static BOOL interpret_function_table_entry(struct cpu_stack_walk* csw, LPSTACKFRAME64 frame,
|
||||
CONTEXT* context, RUNTIME_FUNCTION* function, DWORD64 base)
|
||||
{
|
||||
char buffer[sizeof(UNWIND_INFO) + 256 * sizeof(UNWIND_CODE)];
|
||||
UNWIND_INFO* info = (UNWIND_INFO*)buffer;
|
||||
unsigned i;
|
||||
DWORD64 newframe, prolog_offset, off, value;
|
||||
M128A floatvalue;
|
||||
union handler_data handler_data;
|
||||
|
||||
/* FIXME: we have some assumptions here */
|
||||
assert(context);
|
||||
if (context->Rsp != frame->AddrStack.Offset) FIXME("unconsistent Stack Pointer\n");
|
||||
if (context->Rip != frame->AddrPC.Offset) FIXME("unconsistent Instruction Pointer\n");
|
||||
dump_unwind_info(csw->hProcess, sw_module_base(csw, frame->AddrPC.Offset), frame->FuncTableEntry);
|
||||
newframe = context->Rsp;
|
||||
for (;;)
|
||||
{
|
||||
if (!sw_read_mem(csw, base + function->UnwindData, info, sizeof(*info)) ||
|
||||
!sw_read_mem(csw, base + function->UnwindData + FIELD_OFFSET(UNWIND_INFO, UnwindCode),
|
||||
info->UnwindCode, info->CountOfCodes * sizeof(UNWIND_CODE)))
|
||||
{
|
||||
WARN("Couldn't read unwind_code at %lx\n", base + function->UnwindData);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (info->Version != 1)
|
||||
{
|
||||
WARN("unknown unwind info version %u at %lx\n", info->Version, base + function->UnwindData);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (info->FrameRegister)
|
||||
newframe = get_int_reg(context, info->FrameRegister) - info->FrameOffset * 16;
|
||||
|
||||
/* check if in prolog */
|
||||
if (frame->AddrPC.Offset >= base + function->BeginAddress &&
|
||||
frame->AddrPC.Offset < base + function->BeginAddress + info->SizeOfProlog)
|
||||
{
|
||||
prolog_offset = frame->AddrPC.Offset - base - function->BeginAddress;
|
||||
}
|
||||
else
|
||||
{
|
||||
prolog_offset = ~0;
|
||||
if (is_inside_epilog(csw, frame->AddrPC.Offset))
|
||||
{
|
||||
FIXME("epilog management not fully done\n");
|
||||
/* interpret_epilog((const BYTE*)frame->AddrPC.Offset, context); */
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < info->CountOfCodes; i += get_opcode_size(info->UnwindCode[i]))
|
||||
{
|
||||
if (prolog_offset < info->UnwindCode[i].CodeOffset) continue; /* skip it */
|
||||
|
||||
switch (info->UnwindCode[i].UnwindOp)
|
||||
{
|
||||
case UWOP_PUSH_NONVOL: /* pushq %reg */
|
||||
if (!sw_read_mem(csw, context->Rsp, &value, sizeof(DWORD64))) return FALSE;
|
||||
set_int_reg(context, info->UnwindCode[i].OpInfo, value);
|
||||
context->Rsp += sizeof(ULONG64);
|
||||
break;
|
||||
case UWOP_ALLOC_LARGE: /* subq $nn,%rsp */
|
||||
if (info->UnwindCode[i].OpInfo) context->Rsp += *(DWORD*)&info->UnwindCode[i+1];
|
||||
else context->Rsp += *(USHORT*)&info->UnwindCode[i+1] * 8;
|
||||
break;
|
||||
case UWOP_ALLOC_SMALL: /* subq $n,%rsp */
|
||||
context->Rsp += (info->UnwindCode[i].OpInfo + 1) * 8;
|
||||
break;
|
||||
case UWOP_SET_FPREG: /* leaq nn(%rsp),%framereg */
|
||||
context->Rsp = newframe;
|
||||
break;
|
||||
case UWOP_SAVE_NONVOL: /* movq %reg,n(%rsp) */
|
||||
off = newframe + *(USHORT*)&info->UnwindCode[i+1] * 8;
|
||||
if (!sw_read_mem(csw, context->Rsp, &value, sizeof(DWORD64))) return FALSE;
|
||||
set_int_reg(context, info->UnwindCode[i].OpInfo, value);
|
||||
break;
|
||||
case UWOP_SAVE_NONVOL_FAR: /* movq %reg,nn(%rsp) */
|
||||
off = newframe + *(DWORD*)&info->UnwindCode[i+1];
|
||||
if (!sw_read_mem(csw, context->Rsp, &value, sizeof(DWORD64))) return FALSE;
|
||||
set_int_reg(context, info->UnwindCode[i].OpInfo, value);
|
||||
break;
|
||||
case UWOP_SAVE_XMM128: /* movaps %xmmreg,n(%rsp) */
|
||||
off = newframe + *(USHORT*)&info->UnwindCode[i+1] * 16;
|
||||
if (!sw_read_mem(csw, context->Rsp, &floatvalue, sizeof(M128A))) return FALSE;
|
||||
set_float_reg(context, info->UnwindCode[i].OpInfo, floatvalue);
|
||||
break;
|
||||
case UWOP_SAVE_XMM128_FAR: /* movaps %xmmreg,nn(%rsp) */
|
||||
off = newframe + *(DWORD*)&info->UnwindCode[i+1];
|
||||
if (!sw_read_mem(csw, context->Rsp, &floatvalue, sizeof(M128A))) return FALSE;
|
||||
set_float_reg(context, info->UnwindCode[i].OpInfo, floatvalue);
|
||||
break;
|
||||
case UWOP_PUSH_MACHFRAME:
|
||||
FIXME("PUSH_MACHFRAME %u\n", info->UnwindCode[i].OpInfo);
|
||||
break;
|
||||
default:
|
||||
FIXME("unknown code %u\n", info->UnwindCode[i].UnwindOp);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!(info->Flags & UNW_FLAG_CHAININFO)) break;
|
||||
if (!sw_read_mem(csw, base + function->UnwindData + FIELD_OFFSET(UNWIND_INFO, UnwindCode) +
|
||||
((info->CountOfCodes + 1) & ~1) * sizeof(UNWIND_CODE),
|
||||
&handler_data, sizeof(handler_data))) return FALSE;
|
||||
function = &handler_data.chain; /* restart with the chained info */
|
||||
}
|
||||
frame->AddrStack.Offset = context->Rsp;
|
||||
return default_unwind(csw, frame, context);
|
||||
}
|
||||
|
||||
static BOOL x86_64_stack_walk(struct cpu_stack_walk* csw, LPSTACKFRAME64 frame, CONTEXT* context)
|
||||
{
|
||||
DWORD64 base;
|
||||
DWORD_PTR cfa;
|
||||
unsigned deltapc = 0;
|
||||
|
||||
/* sanity check */
|
||||
if (curr_mode >= stm_done) return FALSE;
|
||||
assert(!csw->is32);
|
||||
|
@ -90,25 +513,37 @@ static BOOL x86_64_stack_walk(struct cpu_stack_walk* csw, LPSTACKFRAME64 frame)
|
|||
{
|
||||
if (frame->AddrReturn.Offset == 0) goto done_err;
|
||||
frame->AddrPC = frame->AddrReturn;
|
||||
deltapc = 1;
|
||||
}
|
||||
|
||||
if (!sw_read_mem(csw, frame->AddrStack.Offset,
|
||||
&frame->AddrReturn.Offset, sizeof(DWORD64)))
|
||||
if (!frame->AddrPC.Offset || !(base = sw_module_base(csw, frame->AddrPC.Offset))) goto done_err;
|
||||
frame->FuncTableEntry = sw_table_access(csw, frame->AddrPC.Offset);
|
||||
frame->AddrStack.Mode = frame->AddrFrame.Mode = frame->AddrReturn.Mode = AddrModeFlat;
|
||||
if (frame->FuncTableEntry)
|
||||
{
|
||||
WARN("Cannot read new frame offset %s\n",
|
||||
wine_dbgstr_longlong(frame->AddrFrame.Offset + sizeof(DWORD64)));
|
||||
goto done_err;
|
||||
if (!interpret_function_table_entry(csw, frame, context, frame->FuncTableEntry, base))
|
||||
goto done_err;
|
||||
}
|
||||
/* FIXME: simplistic stuff... need to handle both dwarf & PE stack information */
|
||||
frame->AddrStack.Offset += sizeof(DWORD64);
|
||||
else if (dwarf2_virtual_unwind(csw, frame->AddrPC.Offset - deltapc, context, &cfa))
|
||||
{
|
||||
frame->AddrStack.Offset = context->Rsp = cfa;
|
||||
frame->AddrReturn.Offset = context->Rip;
|
||||
TRACE("next function rip=%016lx\n", context->Rip);
|
||||
TRACE(" rax=%016lx rbx=%016lx rcx=%016lx rdx=%016lx\n",
|
||||
context->Rax, context->Rbx, context->Rcx, context->Rdx);
|
||||
TRACE(" rsi=%016lx rdi=%016lx rbp=%016lx rsp=%016lx\n",
|
||||
context->Rsi, context->Rdi, context->Rbp, context->Rsp);
|
||||
TRACE(" r8=%016lx r9=%016lx r10=%016lx r11=%016lx\n",
|
||||
context->R8, context->R9, context->R10, context->R11);
|
||||
TRACE(" r12=%016lx r13=%016lx r14=%016lx r15=%016lx\n",
|
||||
context->R12, context->R13, context->R14, context->R15);
|
||||
}
|
||||
else if (!default_unwind(csw, frame, context)) goto done_err;
|
||||
|
||||
memset(&frame->Params, 0, sizeof(frame->Params));
|
||||
|
||||
frame->Far = TRUE;
|
||||
frame->Virtual = TRUE;
|
||||
if (frame->AddrPC.Offset && sw_module_base(csw, frame->AddrPC.Offset))
|
||||
frame->FuncTableEntry = sw_table_access(csw, frame->AddrPC.Offset);
|
||||
else
|
||||
frame->FuncTableEntry = NULL;
|
||||
|
||||
TRACE("Leave: PC=%s Frame=%s Return=%s Stack=%s Mode=%s FuncTable=%p\n",
|
||||
wine_dbgstr_addr(&frame->AddrPC),
|
||||
|
@ -123,10 +558,226 @@ done_err:
|
|||
curr_mode = stm_done;
|
||||
return FALSE;
|
||||
}
|
||||
#else
|
||||
static BOOL x86_64_stack_walk(struct cpu_stack_walk* csw, LPSTACKFRAME64 frame, CONTEXT* context)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void* x86_64_find_runtime_function(struct module* module, DWORD64 addr)
|
||||
{
|
||||
#ifdef __x86_64__
|
||||
RUNTIME_FUNCTION* rtf;
|
||||
ULONG size;
|
||||
int min, max;
|
||||
|
||||
rtf = (RUNTIME_FUNCTION*)pe_map_directory(module, IMAGE_DIRECTORY_ENTRY_EXCEPTION, &size);
|
||||
if (rtf) for (min = 0, max = size / sizeof(*rtf); min <= max; )
|
||||
{
|
||||
int pos = (min + max) / 2;
|
||||
if (addr < module->module.BaseOfImage + rtf[pos].BeginAddress) max = pos - 1;
|
||||
else if (addr >= module->module.BaseOfImage + rtf[pos].EndAddress) min = pos + 1;
|
||||
else
|
||||
{
|
||||
rtf += pos;
|
||||
while (rtf->UnwindData & 1) /* follow chained entry */
|
||||
{
|
||||
FIXME("RunTime_Function outside IMAGE_DIRECTORY_ENTRY_EXCEPTION unimplemented yet!\n");
|
||||
/* we need to read into the other process */
|
||||
/* rtf = (RUNTIME_FUNCTION*)(module->module.BaseOfImage + (rtf->UnwindData & ~1)); */
|
||||
}
|
||||
return rtf;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static unsigned x86_64_map_dwarf_register(unsigned regno)
|
||||
{
|
||||
unsigned reg;
|
||||
|
||||
if (regno >= 17 && regno <= 24)
|
||||
reg = CV_AMD64_XMM0 + regno - 17;
|
||||
else if (regno >= 25 && regno <= 32)
|
||||
reg = CV_AMD64_XMM8 + regno - 25;
|
||||
else if (regno >= 33 && regno <= 40)
|
||||
reg = CV_AMD64_ST0 + regno - 33;
|
||||
else switch (regno)
|
||||
{
|
||||
case 0: reg = CV_AMD64_RAX; break;
|
||||
case 1: reg = CV_AMD64_RDX; break;
|
||||
case 2: reg = CV_AMD64_RCX; break;
|
||||
case 3: reg = CV_AMD64_RBX; break;
|
||||
case 4: reg = CV_AMD64_RSI; break;
|
||||
case 5: reg = CV_AMD64_RDI; break;
|
||||
case 6: reg = CV_AMD64_RBP; break;
|
||||
case 7: reg = CV_AMD64_RSP; break;
|
||||
case 8: reg = CV_AMD64_R8; break;
|
||||
case 9: reg = CV_AMD64_R9; break;
|
||||
case 10: reg = CV_AMD64_R10; break;
|
||||
case 11: reg = CV_AMD64_R11; break;
|
||||
case 12: reg = CV_AMD64_R12; break;
|
||||
case 13: reg = CV_AMD64_R13; break;
|
||||
case 14: reg = CV_AMD64_R14; break;
|
||||
case 15: reg = CV_AMD64_R15; break;
|
||||
case 16: reg = CV_AMD64_RIP; break;
|
||||
case 49: reg = CV_AMD64_EFLAGS; break;
|
||||
case 50: reg = CV_AMD64_ES; break;
|
||||
case 51: reg = CV_AMD64_CS; break;
|
||||
case 52: reg = CV_AMD64_SS; break;
|
||||
case 53: reg = CV_AMD64_DS; break;
|
||||
case 54: reg = CV_AMD64_FS; break;
|
||||
case 55: reg = CV_AMD64_GS; break;
|
||||
case 62: reg = CV_AMD64_TR; break;
|
||||
case 63: reg = CV_AMD64_LDTR; break;
|
||||
case 64: reg = CV_AMD64_MXCSR; break;
|
||||
case 65: reg = CV_AMD64_CTRL; break;
|
||||
case 66: reg = CV_AMD64_STAT; break;
|
||||
/*
|
||||
* 56-57 reserved
|
||||
* 58 %fs.base
|
||||
* 59 %gs.base
|
||||
* 60-61 reserved
|
||||
*/
|
||||
default:
|
||||
FIXME("Don't know how to map register %d\n", regno);
|
||||
return 0;
|
||||
}
|
||||
return reg;
|
||||
}
|
||||
|
||||
static void* x86_64_fetch_context_reg(CONTEXT* ctx, unsigned regno, unsigned* size)
|
||||
{
|
||||
#ifdef __x86_64__
|
||||
switch (regno)
|
||||
{
|
||||
case CV_AMD64_RAX: *size = sizeof(ctx->Rax); return &ctx->Rax;
|
||||
case CV_AMD64_RDX: *size = sizeof(ctx->Rdx); return &ctx->Rdx;
|
||||
case CV_AMD64_RCX: *size = sizeof(ctx->Rcx); return &ctx->Rcx;
|
||||
case CV_AMD64_RBX: *size = sizeof(ctx->Rbx); return &ctx->Rbx;
|
||||
case CV_AMD64_RSI: *size = sizeof(ctx->Rsi); return &ctx->Rsi;
|
||||
case CV_AMD64_RDI: *size = sizeof(ctx->Rdi); return &ctx->Rdi;
|
||||
case CV_AMD64_RBP: *size = sizeof(ctx->Rbp); return &ctx->Rbp;
|
||||
case CV_AMD64_RSP: *size = sizeof(ctx->Rsp); return &ctx->Rsp;
|
||||
case CV_AMD64_R8: *size = sizeof(ctx->R8); return &ctx->R8;
|
||||
case CV_AMD64_R9: *size = sizeof(ctx->R9); return &ctx->R9;
|
||||
case CV_AMD64_R10: *size = sizeof(ctx->R10); return &ctx->R10;
|
||||
case CV_AMD64_R11: *size = sizeof(ctx->R11); return &ctx->R11;
|
||||
case CV_AMD64_R12: *size = sizeof(ctx->R12); return &ctx->R12;
|
||||
case CV_AMD64_R13: *size = sizeof(ctx->R13); return &ctx->R13;
|
||||
case CV_AMD64_R14: *size = sizeof(ctx->R14); return &ctx->R14;
|
||||
case CV_AMD64_R15: *size = sizeof(ctx->R15); return &ctx->R15;
|
||||
case CV_AMD64_RIP: *size = sizeof(ctx->Rip); return &ctx->Rip;
|
||||
|
||||
case CV_AMD64_XMM0 + 0: *size = sizeof(ctx->u.s.Xmm0 ); return &ctx->u.s.Xmm0;
|
||||
case CV_AMD64_XMM0 + 1: *size = sizeof(ctx->u.s.Xmm1 ); return &ctx->u.s.Xmm1;
|
||||
case CV_AMD64_XMM0 + 2: *size = sizeof(ctx->u.s.Xmm2 ); return &ctx->u.s.Xmm2;
|
||||
case CV_AMD64_XMM0 + 3: *size = sizeof(ctx->u.s.Xmm3 ); return &ctx->u.s.Xmm3;
|
||||
case CV_AMD64_XMM0 + 4: *size = sizeof(ctx->u.s.Xmm4 ); return &ctx->u.s.Xmm4;
|
||||
case CV_AMD64_XMM0 + 5: *size = sizeof(ctx->u.s.Xmm5 ); return &ctx->u.s.Xmm5;
|
||||
case CV_AMD64_XMM0 + 6: *size = sizeof(ctx->u.s.Xmm6 ); return &ctx->u.s.Xmm6;
|
||||
case CV_AMD64_XMM0 + 7: *size = sizeof(ctx->u.s.Xmm7 ); return &ctx->u.s.Xmm7;
|
||||
case CV_AMD64_XMM8 + 0: *size = sizeof(ctx->u.s.Xmm8 ); return &ctx->u.s.Xmm8;
|
||||
case CV_AMD64_XMM8 + 1: *size = sizeof(ctx->u.s.Xmm9 ); return &ctx->u.s.Xmm9;
|
||||
case CV_AMD64_XMM8 + 2: *size = sizeof(ctx->u.s.Xmm10); return &ctx->u.s.Xmm10;
|
||||
case CV_AMD64_XMM8 + 3: *size = sizeof(ctx->u.s.Xmm11); return &ctx->u.s.Xmm11;
|
||||
case CV_AMD64_XMM8 + 4: *size = sizeof(ctx->u.s.Xmm12); return &ctx->u.s.Xmm12;
|
||||
case CV_AMD64_XMM8 + 5: *size = sizeof(ctx->u.s.Xmm13); return &ctx->u.s.Xmm13;
|
||||
case CV_AMD64_XMM8 + 6: *size = sizeof(ctx->u.s.Xmm14); return &ctx->u.s.Xmm14;
|
||||
case CV_AMD64_XMM8 + 7: *size = sizeof(ctx->u.s.Xmm15); return &ctx->u.s.Xmm15;
|
||||
|
||||
case CV_AMD64_ST0 + 0: *size = sizeof(ctx->u.s.Legacy[0]); return &ctx->u.s.Legacy[0];
|
||||
case CV_AMD64_ST0 + 1: *size = sizeof(ctx->u.s.Legacy[1]); return &ctx->u.s.Legacy[1];
|
||||
case CV_AMD64_ST0 + 2: *size = sizeof(ctx->u.s.Legacy[2]); return &ctx->u.s.Legacy[2];
|
||||
case CV_AMD64_ST0 + 3: *size = sizeof(ctx->u.s.Legacy[3]); return &ctx->u.s.Legacy[3];
|
||||
case CV_AMD64_ST0 + 4: *size = sizeof(ctx->u.s.Legacy[4]); return &ctx->u.s.Legacy[4];
|
||||
case CV_AMD64_ST0 + 5: *size = sizeof(ctx->u.s.Legacy[5]); return &ctx->u.s.Legacy[5];
|
||||
case CV_AMD64_ST0 + 6: *size = sizeof(ctx->u.s.Legacy[6]); return &ctx->u.s.Legacy[6];
|
||||
case CV_AMD64_ST0 + 7: *size = sizeof(ctx->u.s.Legacy[7]); return &ctx->u.s.Legacy[7];
|
||||
|
||||
case CV_AMD64_EFLAGS: *size = sizeof(ctx->EFlags); return &ctx->EFlags;
|
||||
case CV_AMD64_ES: *size = sizeof(ctx->SegEs); return &ctx->SegEs;
|
||||
case CV_AMD64_CS: *size = sizeof(ctx->SegCs); return &ctx->SegCs;
|
||||
case CV_AMD64_SS: *size = sizeof(ctx->SegSs); return &ctx->SegSs;
|
||||
case CV_AMD64_DS: *size = sizeof(ctx->SegDs); return &ctx->SegDs;
|
||||
case CV_AMD64_FS: *size = sizeof(ctx->SegFs); return &ctx->SegFs;
|
||||
case CV_AMD64_GS: *size = sizeof(ctx->SegGs); return &ctx->SegGs;
|
||||
|
||||
}
|
||||
#endif
|
||||
FIXME("Unknown register %x\n", regno);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char* x86_64_fetch_regname(unsigned regno)
|
||||
{
|
||||
switch (regno)
|
||||
{
|
||||
case CV_AMD64_RAX: return "rax";
|
||||
case CV_AMD64_RDX: return "rdx";
|
||||
case CV_AMD64_RCX: return "rcx";
|
||||
case CV_AMD64_RBX: return "rbx";
|
||||
case CV_AMD64_RSI: return "rsi";
|
||||
case CV_AMD64_RDI: return "rdi";
|
||||
case CV_AMD64_RBP: return "rbp";
|
||||
case CV_AMD64_RSP: return "rsp";
|
||||
case CV_AMD64_R8: return "r8";
|
||||
case CV_AMD64_R9: return "r9";
|
||||
case CV_AMD64_R10: return "r10";
|
||||
case CV_AMD64_R11: return "r11";
|
||||
case CV_AMD64_R12: return "r12";
|
||||
case CV_AMD64_R13: return "r13";
|
||||
case CV_AMD64_R14: return "r14";
|
||||
case CV_AMD64_R15: return "r15";
|
||||
case CV_AMD64_RIP: return "rip";
|
||||
|
||||
case CV_AMD64_XMM0 + 0: return "xmm0";
|
||||
case CV_AMD64_XMM0 + 1: return "xmm1";
|
||||
case CV_AMD64_XMM0 + 2: return "xmm2";
|
||||
case CV_AMD64_XMM0 + 3: return "xmm3";
|
||||
case CV_AMD64_XMM0 + 4: return "xmm4";
|
||||
case CV_AMD64_XMM0 + 5: return "xmm5";
|
||||
case CV_AMD64_XMM0 + 6: return "xmm6";
|
||||
case CV_AMD64_XMM0 + 7: return "xmm7";
|
||||
case CV_AMD64_XMM8 + 0: return "xmm8";
|
||||
case CV_AMD64_XMM8 + 1: return "xmm9";
|
||||
case CV_AMD64_XMM8 + 2: return "xmm10";
|
||||
case CV_AMD64_XMM8 + 3: return "xmm11";
|
||||
case CV_AMD64_XMM8 + 4: return "xmm12";
|
||||
case CV_AMD64_XMM8 + 5: return "xmm13";
|
||||
case CV_AMD64_XMM8 + 6: return "xmm14";
|
||||
case CV_AMD64_XMM8 + 7: return "xmm15";
|
||||
|
||||
case CV_AMD64_ST0 + 0: return "st0";
|
||||
case CV_AMD64_ST0 + 1: return "st1";
|
||||
case CV_AMD64_ST0 + 2: return "st2";
|
||||
case CV_AMD64_ST0 + 3: return "st3";
|
||||
case CV_AMD64_ST0 + 4: return "st4";
|
||||
case CV_AMD64_ST0 + 5: return "st5";
|
||||
case CV_AMD64_ST0 + 6: return "st6";
|
||||
case CV_AMD64_ST0 + 7: return "st7";
|
||||
|
||||
case CV_AMD64_EFLAGS: return "eflags";
|
||||
case CV_AMD64_ES: return "es";
|
||||
case CV_AMD64_CS: return "cs";
|
||||
case CV_AMD64_SS: return "ss";
|
||||
case CV_AMD64_DS: return "ds";
|
||||
case CV_AMD64_FS: return "fs";
|
||||
case CV_AMD64_GS: return "gs";
|
||||
}
|
||||
FIXME("Unknown register %x\n", regno);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct cpu cpu_x86_64 = {
|
||||
IMAGE_FILE_MACHINE_AMD64,
|
||||
8,
|
||||
x86_64_get_addr,
|
||||
x86_64_stack_walk,
|
||||
x86_64_find_runtime_function,
|
||||
x86_64_map_dwarf_register,
|
||||
x86_64_fetch_context_reg,
|
||||
x86_64_fetch_regname,
|
||||
};
|
||||
|
|
|
@ -139,8 +139,8 @@ DWORD calc_crc32(int fd)
|
|||
unsigned char buffer[8192];
|
||||
DWORD crc = ~0;
|
||||
|
||||
_lseek(fd, 0, SEEK_SET);
|
||||
while ((r = _read(fd, buffer, sizeof(buffer))) > 0)
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
while ((r = read(fd, buffer, sizeof(buffer))) > 0)
|
||||
{
|
||||
for (i = 0; i < r; i++) crc = UPDC32(buffer[i], crc);
|
||||
}
|
||||
|
|
|
@ -151,14 +151,16 @@ const char* wine_dbgstr_addr(const ADDRESS64* addr)
|
|||
}
|
||||
}
|
||||
|
||||
extern struct cpu cpu_i386, cpu_x86_64;
|
||||
extern struct cpu cpu_i386, cpu_x86_64, cpu_ppc;
|
||||
|
||||
static struct cpu* dbghelp_cpus[] = {&cpu_i386, &cpu_x86_64, NULL};
|
||||
static struct cpu* dbghelp_cpus[] = {&cpu_i386, &cpu_x86_64, &cpu_ppc, NULL};
|
||||
struct cpu* dbghelp_current_cpu =
|
||||
#if defined(__i386__)
|
||||
&cpu_i386
|
||||
#elif defined(__x86_64__)
|
||||
&cpu_x86_64
|
||||
#elif defined(__powerpc__)
|
||||
&cpu_ppc
|
||||
#else
|
||||
#error define support for your CPU
|
||||
#endif
|
||||
|
|
|
@ -8,6 +8,7 @@
|
|||
<define name="__WINESRC__" />
|
||||
<define name="_WINE" />
|
||||
<define name="HAVE_REGEX_H" />
|
||||
<define name="_IMAGEHLP_SOURCE_" />
|
||||
<file>coff.c</file>
|
||||
<file>cpu_i386.c</file>
|
||||
<file>cpu_ppc.c</file>
|
||||
|
@ -18,7 +19,6 @@
|
|||
<file>elf_module.c</file>
|
||||
<file>image.c</file>
|
||||
<file>macho_module.c</file>
|
||||
<file>memory.c</file>
|
||||
<file>minidump.c</file>
|
||||
<file>module.c</file>
|
||||
<file>msc.c</file>
|
||||
|
|
|
@ -90,9 +90,9 @@
|
|||
@ stdcall SymGetLineFromAddr64(long double ptr ptr)
|
||||
@ stdcall SymGetLineFromAddr(long long ptr ptr)
|
||||
@ stdcall SymGetLineFromAddrW64(long double ptr ptr)
|
||||
@ stdcall SymGetLineFromName64(ptr str str long ptr ptr)
|
||||
@ stdcall SymGetLineFromName(ptr str str long ptr ptr)
|
||||
@ stdcall SymGetLineFromNameW64(ptr str str long ptr ptr)
|
||||
@ stdcall SymGetLineFromName64(long str str long ptr ptr)
|
||||
@ stdcall SymGetLineFromName(long str str long ptr ptr)
|
||||
@ stdcall SymGetLineFromNameW64(long wstr wstr long ptr ptr)
|
||||
@ stdcall SymGetLineNext64(long ptr)
|
||||
@ stdcall SymGetLineNext(long ptr)
|
||||
@ stdcall SymGetLineNextW64(ptr ptr)
|
||||
|
@ -105,7 +105,7 @@
|
|||
@ stdcall SymGetModuleInfo(long long ptr)
|
||||
@ stdcall SymGetModuleInfoW64(long double ptr)
|
||||
@ stdcall SymGetModuleInfoW(long long ptr)
|
||||
@ stdcall SymGetOmaps(ptr double ptr ptr ptr ptr)
|
||||
@ stub SymGetOmapBlockBase
|
||||
@ stdcall SymGetOptions()
|
||||
@ stdcall SymGetScope(ptr double long ptr)
|
||||
@ stdcall SymGetScopeW(ptr double long ptr)
|
||||
|
@ -121,11 +121,11 @@
|
|||
@ stdcall SymGetSourceVarFromTokenW(ptr ptr str str str long)
|
||||
@ stdcall SymGetSymFromAddr64(long double ptr ptr)
|
||||
@ stdcall SymGetSymFromAddr(long long ptr ptr)
|
||||
@ stdcall SymGetSymFromName64(ptr str ptr)
|
||||
@ stdcall SymGetSymFromName64(long str ptr)
|
||||
@ stdcall SymGetSymFromName(long str ptr)
|
||||
@ stdcall SymGetSymNext64(ptr ptr)
|
||||
@ stdcall SymGetSymNext64(long ptr)
|
||||
@ stdcall SymGetSymNext(long ptr)
|
||||
@ stdcall SymGetSymPrev64(ptr ptr)
|
||||
@ stdcall SymGetSymPrev64(long ptr)
|
||||
@ stdcall SymGetSymPrev(long ptr)
|
||||
@ stdcall SymGetSymbolFile(ptr str str long str ptr str ptr)
|
||||
@ stdcall SymGetSymbolFileW(ptr str str long str ptr str ptr)
|
||||
|
@ -149,7 +149,7 @@
|
|||
@ stdcall SymNextW(ptr ptr)
|
||||
@ stdcall SymPrev(ptr ptr)
|
||||
@ stdcall SymPrevW(ptr ptr)
|
||||
@ stdcall SymRefreshModuleList(ptr)
|
||||
@ stdcall SymRefreshModuleList(long)
|
||||
@ stdcall SymRegisterCallback64(long ptr double)
|
||||
@ stdcall SymRegisterCallback(long ptr ptr)
|
||||
@ stdcall SymRegisterCallbackW64(long ptr double)
|
||||
|
@ -182,6 +182,7 @@
|
|||
@ stdcall SymSrvStoreFileW(ptr str str long)
|
||||
@ stdcall SymSrvStoreSupplement(ptr str str str long)
|
||||
@ stdcall SymSrvStoreSupplementW(ptr str str str long)
|
||||
@ stub SymSetSymWithAddr64
|
||||
@ stdcall SymUnDName64(ptr str long)
|
||||
@ stdcall SymUnDName(ptr str long)
|
||||
@ stdcall SymUnloadModule64(long double)
|
||||
|
|
|
@ -120,6 +120,7 @@ extern unsigned dbghelp_options;
|
|||
#define SYMOPT_WINE_WITH_NATIVE_MODULES 0x40000000
|
||||
|
||||
enum location_kind {loc_error, /* reg is the error code */
|
||||
loc_unavailable, /* location is not available */
|
||||
loc_absolute, /* offset is the location */
|
||||
loc_register, /* reg is the location */
|
||||
loc_regrel, /* [reg+offset] is the location */
|
||||
|
@ -346,12 +347,14 @@ struct module_format
|
|||
|
||||
struct module
|
||||
{
|
||||
struct process* process;
|
||||
IMAGEHLP_MODULEW64 module;
|
||||
/* ANSI copy of module.ModuleName for efficiency */
|
||||
char module_name[MAX_PATH];
|
||||
struct module* next;
|
||||
enum module_type type : 16;
|
||||
unsigned short is_virtual : 1;
|
||||
DWORD64 reloc_delta;
|
||||
|
||||
/* specific information for debug types */
|
||||
struct module_format* format_info[DFI_LAST];
|
||||
|
@ -474,7 +477,17 @@ struct cpu
|
|||
enum cpu_addr, ADDRESS64* addr);
|
||||
|
||||
/* stack manipulation */
|
||||
BOOL (*stack_walk)(struct cpu_stack_walk* csw, LPSTACKFRAME64 frame);
|
||||
BOOL (*stack_walk)(struct cpu_stack_walk* csw, LPSTACKFRAME64 frame, CONTEXT* context);
|
||||
|
||||
/* module manipulation */
|
||||
void* (*find_runtime_function)(struct module*, DWORD64 addr);
|
||||
|
||||
/* dwarf dedicated information */
|
||||
unsigned (*map_dwarf_register)(unsigned regno);
|
||||
|
||||
/* context related maniputation */
|
||||
void* (*fetch_context_reg)(CONTEXT* context, unsigned regno, unsigned* size);
|
||||
const char* (*fetch_regname)(unsigned regno);
|
||||
};
|
||||
|
||||
extern struct cpu* dbghelp_current_cpu;
|
||||
|
@ -570,6 +583,9 @@ extern struct module*
|
|||
DWORD64 base, DWORD64 size);
|
||||
extern BOOL pe_load_debug_info(const struct process* pcs,
|
||||
struct module* module);
|
||||
extern const char* pe_map_directory(struct module* module, int dirno, DWORD* size);
|
||||
extern void pe_unmap_directoy(struct module* module, int dirno);
|
||||
|
||||
/* source.c */
|
||||
extern unsigned source_new(struct module* module, const char* basedir, const char* source);
|
||||
extern const char* source_get(const struct module* module, unsigned idx);
|
||||
|
@ -588,6 +604,8 @@ extern BOOL stabs_parse(struct module* module, unsigned long load_offset
|
|||
extern BOOL dwarf2_parse(struct module* module, unsigned long load_offset,
|
||||
const struct elf_thunk_area* thunks,
|
||||
struct image_file_map* fmap);
|
||||
extern BOOL dwarf2_virtual_unwind(struct cpu_stack_walk* csw, DWORD_PTR ip,
|
||||
CONTEXT* context, ULONG_PTR* cfa);
|
||||
|
||||
/* stack.c */
|
||||
extern BOOL sw_read_mem(struct cpu_stack_walk* csw, DWORD64 addr, void* ptr, DWORD sz);
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -379,6 +379,9 @@ typedef enum dwarf_operation_e
|
|||
DW_OP_form_tls_address = 0x9b,
|
||||
DW_OP_call_frame_cfa = 0x9c,
|
||||
DW_OP_bit_piece = 0x9d,
|
||||
/** Dwarf4 new values */
|
||||
DW_OP_implicit_value = 0x9e,
|
||||
DW_OP_stack_value = 0x9f,
|
||||
|
||||
/* Implementation defined extensions */
|
||||
DW_OP_lo_user = 0xe0,
|
||||
|
@ -418,3 +421,57 @@ enum dwarf_calling_convention
|
|||
#define DW_LNE_end_sequence 0x01
|
||||
#define DW_LNE_set_address 0x02
|
||||
#define DW_LNE_define_file 0x03
|
||||
/* Dwarf4 new values */
|
||||
#define DW_LNE_set_discriminator 0x04
|
||||
|
||||
#define DW_CIE_ID ~(0x0)
|
||||
|
||||
enum dwarf_call_frame_info
|
||||
{
|
||||
DW_CFA_advance_loc = 0x40,
|
||||
DW_CFA_offset = 0x80,
|
||||
DW_CFA_restore = 0xc0,
|
||||
DW_CFA_nop = 0x00,
|
||||
DW_CFA_set_loc = 0x01,
|
||||
DW_CFA_advance_loc1 = 0x02,
|
||||
DW_CFA_advance_loc2 = 0x03,
|
||||
DW_CFA_advance_loc4 = 0x04,
|
||||
DW_CFA_offset_extended = 0x05,
|
||||
DW_CFA_restore_extended = 0x06,
|
||||
DW_CFA_undefined = 0x07,
|
||||
DW_CFA_same_value = 0x08,
|
||||
DW_CFA_register = 0x09,
|
||||
DW_CFA_remember_state = 0x0a,
|
||||
DW_CFA_restore_state = 0x0b,
|
||||
DW_CFA_def_cfa = 0x0c,
|
||||
DW_CFA_def_cfa_register = 0x0d,
|
||||
DW_CFA_def_cfa_offset = 0x0e,
|
||||
DW_CFA_def_cfa_expression = 0x0f,
|
||||
DW_CFA_expression = 0x10,
|
||||
DW_CFA_offset_extended_sf = 0x11,
|
||||
DW_CFA_def_cfa_sf = 0x12,
|
||||
DW_CFA_def_cfa_offset_sf = 0x13,
|
||||
DW_CFA_val_offset = 0x14,
|
||||
DW_CFA_val_offset_sf = 0x15,
|
||||
DW_CFA_val_expression = 0x16,
|
||||
/* GNU extensions */
|
||||
DW_CFA_GNU_window_save = 0x2d,
|
||||
DW_CFA_GNU_args_size = 0x2e,
|
||||
DW_CFA_GNU_negative_offset_extended = 0x2f,
|
||||
|
||||
};
|
||||
|
||||
#define DW_EH_PE_native 0x00
|
||||
#define DW_EH_PE_leb128 0x01
|
||||
#define DW_EH_PE_data2 0x02
|
||||
#define DW_EH_PE_data4 0x03
|
||||
#define DW_EH_PE_data8 0x04
|
||||
#define DW_EH_PE_signed 0x08
|
||||
#define DW_EH_PE_abs 0x00
|
||||
#define DW_EH_PE_pcrel 0x10
|
||||
#define DW_EH_PE_textrel 0x20
|
||||
#define DW_EH_PE_datarel 0x30
|
||||
#define DW_EH_PE_funcrel 0x40
|
||||
#define DW_EH_PE_aligned 0x50
|
||||
#define DW_EH_PE_indirect 0x80
|
||||
#define DW_EH_PE_omit 0xff
|
||||
|
|
|
@ -272,7 +272,12 @@ static BOOL elf_map_file(const WCHAR* filenameW, struct image_file_map* fmap)
|
|||
lseek(fmap->u.elf.fd, fmap->u.elf.elfhdr.e_shoff, SEEK_SET);
|
||||
for (i = 0; i < fmap->u.elf.elfhdr.e_shnum; i++)
|
||||
{
|
||||
read(fmap->u.elf.fd, &fmap->u.elf.sect[i].shdr, sizeof(fmap->u.elf.sect[i].shdr));
|
||||
if (read(fmap->u.elf.fd, &fmap->u.elf.sect[i].shdr, sizeof(fmap->u.elf.sect[i].shdr)) != sizeof(fmap->u.elf.sect[i].shdr))
|
||||
{
|
||||
HeapFree(GetProcessHeap, 0, fmap->u.elf.sect);
|
||||
fmap->u.elf.sect = NULL;
|
||||
goto done;
|
||||
}
|
||||
fmap->u.elf.sect[i].mapped = IMAGE_NO_MAP;
|
||||
}
|
||||
|
||||
|
@ -1075,6 +1080,7 @@ static BOOL elf_load_file(struct process* pcs, const WCHAR* filename,
|
|||
HeapFree(GetProcessHeap(), 0, modfmt);
|
||||
goto leave;
|
||||
}
|
||||
elf_info->module->reloc_delta = elf_info->module->module.BaseOfImage - fmap.u.elf.elf_start;
|
||||
elf_module_info = (void*)(modfmt + 1);
|
||||
elf_info->module->format_info[DFI_ELF] = modfmt;
|
||||
modfmt->module = elf_info->module;
|
||||
|
|
|
@ -1,61 +0,0 @@
|
|||
/*
|
||||
* File memory.c - managing memory
|
||||
*
|
||||
* Copyright (C) 2004, Eric Pouech
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include "dbghelp_private.h"
|
||||
#include "wine/debug.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
|
||||
|
||||
/******************************************************************
|
||||
* addr_to_linear
|
||||
*
|
||||
* converts an address into its linear value
|
||||
*/
|
||||
DWORD WINAPI addr_to_linear(HANDLE hProcess, HANDLE hThread, ADDRESS* addr)
|
||||
{
|
||||
LDT_ENTRY le;
|
||||
|
||||
switch (addr->Mode)
|
||||
{
|
||||
case AddrMode1616:
|
||||
if (GetThreadSelectorEntry(hThread, addr->Segment, &le))
|
||||
return (le.HighWord.Bits.BaseHi << 24) +
|
||||
(le.HighWord.Bits.BaseMid << 16) + le.BaseLow + LOWORD(addr->Offset);
|
||||
break;
|
||||
case AddrMode1632:
|
||||
if (GetThreadSelectorEntry(hThread, addr->Segment, &le))
|
||||
return (le.HighWord.Bits.BaseHi << 24) +
|
||||
(le.HighWord.Bits.BaseMid << 16) + le.BaseLow + addr->Offset;
|
||||
break;
|
||||
case AddrModeReal:
|
||||
return (DWORD)(LOWORD(addr->Segment) << 4) + addr->Offset;
|
||||
case AddrModeFlat:
|
||||
return addr->Offset;
|
||||
default:
|
||||
FIXME("Unsupported (yet) mode (%x)\n", addr->Mode);
|
||||
return 0;
|
||||
}
|
||||
FIXME("Failed to linearize address %04x:%08x (mode %x)\n",
|
||||
addr->Segment, addr->Offset, addr->Mode);
|
||||
return 0;
|
||||
}
|
|
@ -142,6 +142,7 @@ struct module* module_new(struct process* pcs, const WCHAR* name,
|
|||
|
||||
pool_init(&module->pool, 65536);
|
||||
|
||||
module->process = pcs;
|
||||
module->module.SizeOfStruct = sizeof(module->module);
|
||||
module->module.BaseOfImage = mod_addr;
|
||||
module->module.ImageSize = size;
|
||||
|
@ -167,6 +168,7 @@ struct module* module_new(struct process* pcs, const WCHAR* name,
|
|||
module->module.SourceIndexed = FALSE;
|
||||
module->module.Publics = FALSE;
|
||||
|
||||
module->reloc_delta = 0;
|
||||
module->type = type;
|
||||
module->is_virtual = virtual ? TRUE : FALSE;
|
||||
for (i = 0; i < DFI_LAST; i++) module->format_info[i] = NULL;
|
||||
|
@ -1034,13 +1036,10 @@ BOOL WINAPI SymGetModuleInfoW64(HANDLE hProcess, DWORD64 dwAddr,
|
|||
*/
|
||||
DWORD WINAPI SymGetModuleBase(HANDLE hProcess, DWORD dwAddr)
|
||||
{
|
||||
struct process* pcs = process_find_by_handle(hProcess);
|
||||
struct module* module;
|
||||
DWORD64 ret;
|
||||
|
||||
if (!pcs) return 0;
|
||||
module = module_find_by_addr(pcs, dwAddr, DMT_UNKNOWN);
|
||||
if (!module) return 0;
|
||||
return module->module.BaseOfImage;
|
||||
ret = SymGetModuleBase64(hProcess, dwAddr);
|
||||
return validate_addr64(ret) ? ret : 0;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
@ -1048,8 +1047,13 @@ DWORD WINAPI SymGetModuleBase(HANDLE hProcess, DWORD dwAddr)
|
|||
*/
|
||||
DWORD64 WINAPI SymGetModuleBase64(HANDLE hProcess, DWORD64 dwAddr)
|
||||
{
|
||||
if (!validate_addr64(dwAddr)) return 0;
|
||||
return SymGetModuleBase(hProcess, (DWORD)dwAddr);
|
||||
struct process* pcs = process_find_by_handle(hProcess);
|
||||
struct module* module;
|
||||
|
||||
if (!pcs) return 0;
|
||||
module = module_find_by_addr(pcs, dwAddr, DMT_UNKNOWN);
|
||||
if (!module) return 0;
|
||||
return module->module.BaseOfImage;
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
|
@ -1087,3 +1091,26 @@ BOOL WINAPI SymRefreshModuleList(HANDLE hProcess)
|
|||
|
||||
return refresh_module_list(pcs);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* SymFunctionTableAccess (DBGHELP.@)
|
||||
*/
|
||||
PVOID WINAPI SymFunctionTableAccess(HANDLE hProcess, DWORD AddrBase)
|
||||
{
|
||||
return SymFunctionTableAccess64(hProcess, AddrBase);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* SymFunctionTableAccess64 (DBGHELP.@)
|
||||
*/
|
||||
PVOID WINAPI SymFunctionTableAccess64(HANDLE hProcess, DWORD64 AddrBase)
|
||||
{
|
||||
struct process* pcs = process_find_by_handle(hProcess);
|
||||
struct module* module;
|
||||
|
||||
if (!pcs || !dbghelp_current_cpu->find_runtime_function) return NULL;
|
||||
module = module_find_by_addr(pcs, AddrBase, DMT_UNKNOWN);
|
||||
if (!module) return NULL;
|
||||
|
||||
return dbghelp_current_cpu->find_runtime_function(module, AddrBase);
|
||||
}
|
||||
|
|
|
@ -171,6 +171,25 @@ unsigned pe_get_map_size(const struct image_section_map* ism)
|
|||
return ism->fmap->u.pe.sect[ism->sidx].shdr.SizeOfRawData;
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
* pe_is_valid_pointer_table
|
||||
*
|
||||
* Checks whether the PointerToSymbolTable and NumberOfSymbols in file_header contain
|
||||
* valid information.
|
||||
*/
|
||||
static BOOL pe_is_valid_pointer_table(const IMAGE_NT_HEADERS* nthdr, const void* mapping, DWORD64 sz)
|
||||
{
|
||||
DWORD64 offset;
|
||||
|
||||
/* is the iSym table inside file size ? (including first DWORD of string table, which is its size) */
|
||||
offset = (DWORD64)nthdr->FileHeader.PointerToSymbolTable;
|
||||
offset += (DWORD64)nthdr->FileHeader.NumberOfSymbols * sizeof(IMAGE_SYMBOL);
|
||||
if (offset + sizeof(DWORD) > sz) return FALSE;
|
||||
/* is string table (following iSym table) inside file size ? */
|
||||
offset += *(DWORD*)((const char*)mapping + offset);
|
||||
return offset <= sz;
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
* pe_map_file
|
||||
*
|
||||
|
@ -209,16 +228,29 @@ static BOOL pe_map_file(HANDLE file, struct image_file_map* fmap, enum module_ty
|
|||
}
|
||||
if (nthdr->FileHeader.PointerToSymbolTable && nthdr->FileHeader.NumberOfSymbols)
|
||||
{
|
||||
/* FIXME ugly: should rather map the relevant content instead of copying it */
|
||||
const char* src = (const char*)mapping +
|
||||
nthdr->FileHeader.PointerToSymbolTable +
|
||||
nthdr->FileHeader.NumberOfSymbols * sizeof(IMAGE_SYMBOL);
|
||||
char* dst;
|
||||
DWORD sz = *(DWORD*)src;
|
||||
LARGE_INTEGER li;
|
||||
|
||||
if ((dst = HeapAlloc(GetProcessHeap(), 0, sz)))
|
||||
memcpy(dst, src, sz);
|
||||
fmap->u.pe.strtable = dst;
|
||||
if (GetFileSizeEx(file, &li) && pe_is_valid_pointer_table(nthdr, mapping, li.QuadPart))
|
||||
{
|
||||
/* FIXME ugly: should rather map the relevant content instead of copying it */
|
||||
const char* src = (const char*)mapping +
|
||||
nthdr->FileHeader.PointerToSymbolTable +
|
||||
nthdr->FileHeader.NumberOfSymbols * sizeof(IMAGE_SYMBOL);
|
||||
char* dst;
|
||||
DWORD sz = *(DWORD*)src;
|
||||
|
||||
if ((dst = HeapAlloc(GetProcessHeap(), 0, sz)))
|
||||
memcpy(dst, src, sz);
|
||||
fmap->u.pe.strtable = dst;
|
||||
}
|
||||
else
|
||||
{
|
||||
WARN("Bad coff table... wipping out\n");
|
||||
/* we have bad information here, wipe it out */
|
||||
fmap->u.pe.ntheader.FileHeader.PointerToSymbolTable = 0;
|
||||
fmap->u.pe.ntheader.FileHeader.NumberOfSymbols = 0;
|
||||
fmap->u.pe.strtable = NULL;
|
||||
}
|
||||
}
|
||||
else fmap->u.pe.strtable = NULL;
|
||||
}
|
||||
|
@ -257,6 +289,35 @@ static void pe_unmap_file(struct image_file_map* fmap)
|
|||
}
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
* pe_map_directory
|
||||
*
|
||||
* Maps a directory content out of a PE file
|
||||
*/
|
||||
const char* pe_map_directory(struct module* module, int dirno, DWORD* size)
|
||||
{
|
||||
IMAGE_NT_HEADERS* nth;
|
||||
void* mapping;
|
||||
|
||||
if (module->type != DMT_PE || !module->format_info[DFI_PE]) return NULL;
|
||||
if (dirno >= IMAGE_NUMBEROF_DIRECTORY_ENTRIES ||
|
||||
!(mapping = pe_map_full(&module->format_info[DFI_PE]->u.pe_info->fmap, &nth)))
|
||||
return NULL;
|
||||
if (size) *size = nth->OptionalHeader.DataDirectory[dirno].Size;
|
||||
return RtlImageRvaToVa(nth, mapping,
|
||||
nth->OptionalHeader.DataDirectory[dirno].VirtualAddress, NULL);
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
* pe_unmap_directory
|
||||
*
|
||||
* Unmaps a directory content
|
||||
*/
|
||||
void pe_unmap_directory(struct image_file_map* fmap, int dirno)
|
||||
{
|
||||
pe_unmap_full(fmap);
|
||||
}
|
||||
|
||||
static void pe_module_remove(struct process* pcs, struct module_format* modfmt)
|
||||
{
|
||||
pe_unmap_file(&modfmt->u.pe_info->fmap);
|
||||
|
@ -348,10 +409,10 @@ static BOOL pe_load_coff_symbol_table(struct module* module)
|
|||
if (!fmap->u.pe.ntheader.FileHeader.PointerToSymbolTable || !numsym)
|
||||
return TRUE;
|
||||
if (!(mapping = pe_map_full(fmap, NULL))) return FALSE;
|
||||
isym = (const IMAGE_SYMBOL*)((char*)mapping + fmap->u.pe.ntheader.FileHeader.PointerToSymbolTable);
|
||||
isym = (const IMAGE_SYMBOL*)((const char*)mapping + fmap->u.pe.ntheader.FileHeader.PointerToSymbolTable);
|
||||
/* FIXME: no way to get strtable size */
|
||||
strtable = (const char*)&isym[numsym];
|
||||
sect = IMAGE_FIRST_SECTION(&fmap->u.pe.ntheader);
|
||||
sect = IMAGE_FIRST_SECTION(RtlImageNtHeader((HMODULE)mapping));
|
||||
|
||||
for (i = 0; i < numsym; i+= naux, isym += naux)
|
||||
{
|
||||
|
|
|
@ -95,10 +95,11 @@ static inline void addr_64to32(const ADDRESS64* addr64, ADDRESS* addr32)
|
|||
|
||||
BOOL sw_read_mem(struct cpu_stack_walk* csw, DWORD64 addr, void* ptr, DWORD sz)
|
||||
{
|
||||
DWORD bytes_read = 0;
|
||||
if (csw->is32)
|
||||
return csw->u.s32.f_read_mem(csw->hProcess, addr, ptr, sz, NULL);
|
||||
return csw->u.s32.f_read_mem(csw->hProcess, addr, ptr, sz, &bytes_read);
|
||||
else
|
||||
return csw->u.s64.f_read_mem(csw->hProcess, addr, ptr, sz, NULL);
|
||||
return csw->u.s64.f_read_mem(csw->hProcess, addr, ptr, sz, &bytes_read);
|
||||
}
|
||||
|
||||
DWORD64 sw_xlat_addr(struct cpu_stack_walk* csw, ADDRESS64* addr)
|
||||
|
@ -180,7 +181,7 @@ BOOL WINAPI StackWalk(DWORD MachineType, HANDLE hProcess, HANDLE hThread,
|
|||
csw.u.s32.f_tabl_acs = (FunctionTableAccessRoutine) ? FunctionTableAccessRoutine : SymFunctionTableAccess;
|
||||
csw.u.s32.f_modl_bas = (GetModuleBaseRoutine) ? GetModuleBaseRoutine : SymGetModuleBase;
|
||||
|
||||
if ((ret = cpu->stack_walk(&csw, &frame64)))
|
||||
if ((ret = cpu->stack_walk(&csw, &frame64, ctx)))
|
||||
{
|
||||
addr_64to32(&frame64.AddrPC, &frame32->AddrPC);
|
||||
addr_64to32(&frame64.AddrReturn, &frame32->AddrReturn);
|
||||
|
@ -236,7 +237,7 @@ BOOL WINAPI StackWalk64(DWORD MachineType, HANDLE hProcess, HANDLE hThread,
|
|||
csw.u.s64.f_tabl_acs = (FunctionTableAccessRoutine) ? FunctionTableAccessRoutine : SymFunctionTableAccess64;
|
||||
csw.u.s64.f_modl_bas = (GetModuleBaseRoutine) ? GetModuleBaseRoutine : SymGetModuleBase64;
|
||||
|
||||
if (!cpu->stack_walk(&csw, frame)) return FALSE;
|
||||
if (!cpu->stack_walk(&csw, frame, ctx)) return FALSE;
|
||||
|
||||
/* we don't handle KdHelp */
|
||||
frame->KdHelp.Thread = 0xC000FADE;
|
||||
|
|
|
@ -476,7 +476,7 @@ struct symt_data* symt_add_func_local(struct module* module,
|
|||
locsym->hash_elt.name = pool_strdup(&module->pool, name);
|
||||
locsym->hash_elt.next = NULL;
|
||||
locsym->kind = dt;
|
||||
locsym->container = &block->symt;
|
||||
locsym->container = block ? &block->symt : &func->symt;
|
||||
locsym->type = type;
|
||||
locsym->u.var = *loc;
|
||||
if (block)
|
||||
|
@ -724,6 +724,10 @@ static void symt_fill_sym_info(struct module_pair* pair,
|
|||
sym_info->Register = loc.reg ? loc.reg : CV_REG_EBP;
|
||||
sym_info->Address = loc.offset;
|
||||
break;
|
||||
case loc_absolute:
|
||||
sym_info->Flags |= SYMFLAG_VALUEPRESENT;
|
||||
sym_info->Value = loc.offset;
|
||||
break;
|
||||
default:
|
||||
FIXME("Shouldn't happen (kind=%d), debug reader backend is broken\n", loc.kind);
|
||||
assert(0);
|
||||
|
@ -1016,7 +1020,7 @@ static BOOL symt_enum_locals(struct process* pcs, const char* mask,
|
|||
{
|
||||
struct module_pair pair;
|
||||
struct symt_ht* sym;
|
||||
DWORD pc = pcs->ctx_frame.InstructionOffset;
|
||||
DWORD_PTR pc = pcs->ctx_frame.InstructionOffset;
|
||||
|
||||
se->sym_info->SizeOfStruct = sizeof(*se->sym_info);
|
||||
se->sym_info->MaxNameLen = sizeof(se->buffer) - sizeof(SYMBOL_INFO);
|
||||
|
@ -1037,9 +1041,8 @@ static BOOL symt_enum_locals(struct process* pcs, const char* mask,
|
|||
&((struct symt_function*)sym)->vchildren);
|
||||
regfree(&preg);
|
||||
return ret;
|
||||
|
||||
}
|
||||
return send_symbol(se, &pair, NULL, &sym->symt);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
|
@ -1793,24 +1796,6 @@ BOOL WINAPI SymGetLineNext(HANDLE hProcess, PIMAGEHLP_LINE Line)
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* SymFunctionTableAccess (DBGHELP.@)
|
||||
*/
|
||||
PVOID WINAPI SymFunctionTableAccess(HANDLE hProcess, DWORD AddrBase)
|
||||
{
|
||||
WARN("(%p, 0x%08x): stub\n", hProcess, AddrBase);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* SymFunctionTableAccess64 (DBGHELP.@)
|
||||
*/
|
||||
PVOID WINAPI SymFunctionTableAccess64(HANDLE hProcess, DWORD64 AddrBase)
|
||||
{
|
||||
WARN("(%p, %s): stub\n", hProcess, wine_dbgstr_longlong(AddrBase));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* SymUnDName (DBGHELP.@)
|
||||
*/
|
||||
|
|
|
@ -803,9 +803,35 @@ BOOL symt_get_info(struct module* module, const struct symt* type,
|
|||
break;
|
||||
|
||||
case TI_GET_VALUE:
|
||||
if (type->tag != SymTagData || ((const struct symt_data*)type)->kind != DataIsConstant)
|
||||
return FALSE;
|
||||
X(VARIANT) = ((const struct symt_data*)type)->u.value;
|
||||
if (type->tag != SymTagData) return FALSE;
|
||||
switch (((const struct symt_data*)type)->kind)
|
||||
{
|
||||
case DataIsConstant: X(VARIANT) = ((const struct symt_data*)type)->u.value; break;
|
||||
case DataIsLocal:
|
||||
case DataIsParam:
|
||||
{
|
||||
struct location loc = ((const struct symt_data*)type)->u.var;
|
||||
unsigned i;
|
||||
struct module_format* modfmt;
|
||||
|
||||
if (loc.kind < loc_user) return FALSE;
|
||||
for (i = 0; i < DFI_LAST; i++)
|
||||
{
|
||||
modfmt = module->format_info[i];
|
||||
if (modfmt && modfmt->loc_compute)
|
||||
{
|
||||
modfmt->loc_compute(module->process, modfmt,
|
||||
(const struct symt_function*)((const struct symt_data*)type)->container, &loc);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (loc.kind != loc_absolute) return FALSE;
|
||||
X(VARIANT).n1.n2.vt = VT_UI4; /* FIXME */
|
||||
X(VARIANT).n1.n2.n3.uiVal = loc.offset;
|
||||
}
|
||||
break;
|
||||
default: return FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
case TI_GET_CALLING_CONVENTION:
|
||||
|
|
|
@ -18,10 +18,15 @@
|
|||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include "precomp.h"
|
||||
|
||||
#define _WINNT_H
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "winnt.h"
|
||||
#include "winternl.h"
|
||||
#include "winerror.h"
|
||||
#include "wine/debug.h"
|
||||
#include "imagehlp.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(imagehlp);
|
||||
|
||||
|
@ -29,13 +34,32 @@ WINE_DEFAULT_DEBUG_CHANNEL(imagehlp);
|
|||
* Data
|
||||
*/
|
||||
|
||||
BOOLEAN DllListInitialized;
|
||||
LIST_ENTRY ImageLoadListHead;
|
||||
static PLOADED_IMAGE IMAGEHLP_pFirstLoadedImage=NULL;
|
||||
static PLOADED_IMAGE IMAGEHLP_pLastLoadedImage=NULL;
|
||||
|
||||
static LOADED_IMAGE IMAGEHLP_EmptyLoadedImage = {
|
||||
NULL, /* ModuleName */
|
||||
0, /* hFile */
|
||||
NULL, /* MappedAddress */
|
||||
NULL, /* FileHeader */
|
||||
NULL, /* LastRvaSection */
|
||||
0, /* NumberOfSections */
|
||||
NULL, /* Sections */
|
||||
1, /* Characteristics */
|
||||
FALSE, /* fSystemImage */
|
||||
FALSE, /* fDOSImage */
|
||||
FALSE, /* fReadOnly */
|
||||
0, /* Version */
|
||||
{ &IMAGEHLP_EmptyLoadedImage.Links, &IMAGEHLP_EmptyLoadedImage.Links }, /* Links */
|
||||
148, /* SizeOfImage; */
|
||||
};
|
||||
|
||||
extern HANDLE IMAGEHLP_hHeap;
|
||||
|
||||
/***********************************************************************
|
||||
* GetImageConfigInformation (IMAGEHLP.@)
|
||||
*/
|
||||
BOOL IMAGEAPI GetImageConfigInformation(
|
||||
BOOL WINAPI GetImageConfigInformation(
|
||||
PLOADED_IMAGE LoadedImage,
|
||||
PIMAGE_LOAD_CONFIG_DIRECTORY ImageConfigInformation)
|
||||
{
|
||||
|
@ -49,54 +73,15 @@ BOOL IMAGEAPI GetImageConfigInformation(
|
|||
/***********************************************************************
|
||||
* GetImageUnusedHeaderBytes (IMAGEHLP.@)
|
||||
*/
|
||||
DWORD IMAGEAPI GetImageUnusedHeaderBytes(
|
||||
DWORD WINAPI GetImageUnusedHeaderBytes(
|
||||
PLOADED_IMAGE LoadedImage,
|
||||
LPDWORD SizeUnusedHeaderBytes)
|
||||
{
|
||||
SIZE_T FirstFreeByte;
|
||||
PIMAGE_OPTIONAL_HEADER OptionalHeader = NULL;
|
||||
PIMAGE_NT_HEADERS NtHeaders;
|
||||
ULONG i;
|
||||
|
||||
/* Read the NT Headers */
|
||||
NtHeaders = LoadedImage->FileHeader;
|
||||
|
||||
/* Find the first free byte, which is after all the headers and sections */
|
||||
FirstFreeByte = (ULONG_PTR)NtHeaders -
|
||||
(ULONG_PTR)LoadedImage->MappedAddress +
|
||||
FIELD_OFFSET(IMAGE_NT_HEADERS, OptionalHeader) +
|
||||
NtHeaders->FileHeader.SizeOfOptionalHeader +
|
||||
NtHeaders->FileHeader.NumberOfSections * sizeof(IMAGE_SECTION_HEADER);
|
||||
|
||||
/* Get the Optional Header */
|
||||
OptionalHeader = &LoadedImage->FileHeader->OptionalHeader;
|
||||
|
||||
/*
|
||||
* There is the possibilty that one of the Data Directories is in the PE Header
|
||||
* itself, so we'll need to find such a case and add it to our PE used space
|
||||
*/
|
||||
for (i = 0; i < OptionalHeader->NumberOfRvaAndSizes; i++)
|
||||
{
|
||||
/* If the VA is less then the size of headers, then the data is inside the PE header */
|
||||
if (OptionalHeader->DataDirectory[i].VirtualAddress <
|
||||
OptionalHeader->SizeOfHeaders)
|
||||
{
|
||||
/* However, make sure it's not 0, which means it doesnt actually exist */
|
||||
if (OptionalHeader->DataDirectory[i].VirtualAddress >=
|
||||
FirstFreeByte)
|
||||
{
|
||||
/* Our first empty byte is after this Directory Data then */
|
||||
FirstFreeByte = OptionalHeader->DataDirectory[i].VirtualAddress +
|
||||
OptionalHeader->DataDirectory[i].Size;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the unused Header Bytes */
|
||||
*SizeUnusedHeaderBytes = OptionalHeader->SizeOfHeaders - (DWORD)FirstFreeByte;
|
||||
|
||||
/* And return the first free byte*/
|
||||
return (DWORD)FirstFreeByte;
|
||||
FIXME("(%p, %p): stub\n",
|
||||
LoadedImage, SizeUnusedHeaderBytes
|
||||
);
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
|
@ -104,250 +89,147 @@ DWORD IMAGEAPI GetImageUnusedHeaderBytes(
|
|||
*/
|
||||
PLOADED_IMAGE IMAGEAPI ImageLoad(LPSTR DllName, LPSTR DllPath)
|
||||
{
|
||||
PLIST_ENTRY Head, Next;
|
||||
PLOADED_IMAGE LoadedImage;
|
||||
CHAR Drive[_MAX_DRIVE], Dir[_MAX_DIR], Filename[_MAX_FNAME], Ext[_MAX_EXT];
|
||||
BOOL CompleteName = TRUE;
|
||||
CHAR FullName[MAX_PATH];
|
||||
PLOADED_IMAGE pLoadedImage;
|
||||
|
||||
/* Initialize the List Head */
|
||||
if (!DllListInitialized)
|
||||
{
|
||||
InitializeListHead(&ImageLoadListHead);
|
||||
DllListInitialized = TRUE;
|
||||
}
|
||||
|
||||
/* Move to the Next DLL */
|
||||
Head = &ImageLoadListHead;
|
||||
Next = Head->Flink;
|
||||
TRACE("Trying to find library: %s in current ListHead \n", DllName);
|
||||
|
||||
/* Split the path */
|
||||
_splitpath(DllName, Drive, Dir, Filename, Ext);
|
||||
|
||||
/* Check if we only got a name */
|
||||
if (!strlen(Drive) && !strlen(Dir)) CompleteName = FALSE;
|
||||
|
||||
/* Check if we already Loaded it */
|
||||
while (Next != Head)
|
||||
{
|
||||
/* Get the Loaded Image Structure */
|
||||
LoadedImage = CONTAINING_RECORD(Next, LOADED_IMAGE, Links);
|
||||
TRACE("Found: %s in current ListHead \n", LoadedImage->ModuleName);
|
||||
|
||||
/* Check if we didn't have a complete name */
|
||||
if (!CompleteName)
|
||||
{
|
||||
/* Split this module's name */
|
||||
_splitpath(LoadedImage->ModuleName, NULL, NULL, Filename, Ext);
|
||||
|
||||
/* Use only the name and extension */
|
||||
strcpy(FullName, Filename);
|
||||
strcat(FullName, Ext);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Use the full untouched name */
|
||||
strcpy(FullName, LoadedImage->ModuleName);
|
||||
}
|
||||
|
||||
/* Check if the Names Match */
|
||||
if (!_stricmp(DllName, FullName))
|
||||
{
|
||||
TRACE("Found it, returning it\n");
|
||||
return LoadedImage;
|
||||
}
|
||||
|
||||
/* Move to next Entry */
|
||||
Next = Next->Flink;
|
||||
}
|
||||
|
||||
/* Allocate memory for the Structure, and write the Module Name under */
|
||||
TRACE("Didn't find it...allocating it for you now\n");
|
||||
LoadedImage = HeapAlloc(IMAGEHLP_hHeap,
|
||||
0,
|
||||
sizeof(*LoadedImage) + strlen(DllName) + 1);
|
||||
if (LoadedImage)
|
||||
{
|
||||
/* Module Name will be after structure */
|
||||
LoadedImage->ModuleName = (LPSTR)(LoadedImage + 1);
|
||||
|
||||
/* Copy the Module Name */
|
||||
strcpy(LoadedImage->ModuleName, DllName);
|
||||
|
||||
/* Now Load it */
|
||||
if (MapAndLoad(DllName, DllPath, LoadedImage, TRUE, TRUE))
|
||||
{
|
||||
/* Add it to our list and return it */
|
||||
InsertTailList(&ImageLoadListHead, &LoadedImage->Links);
|
||||
return LoadedImage;
|
||||
}
|
||||
|
||||
/* If we're here...there's been a failure */
|
||||
HeapFree(IMAGEHLP_hHeap, 0, LoadedImage);
|
||||
LoadedImage = NULL;
|
||||
}
|
||||
return LoadedImage;
|
||||
FIXME("(%s, %s): stub\n", DllName, DllPath);
|
||||
|
||||
pLoadedImage = HeapAlloc(IMAGEHLP_hHeap, 0, sizeof(LOADED_IMAGE));
|
||||
if (pLoadedImage)
|
||||
pLoadedImage->FileHeader = HeapAlloc(IMAGEHLP_hHeap, 0, sizeof(IMAGE_NT_HEADERS));
|
||||
|
||||
return pLoadedImage;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* ImageUnload (IMAGEHLP.@)
|
||||
*/
|
||||
BOOL IMAGEAPI ImageUnload(PLOADED_IMAGE pLoadedImage)
|
||||
BOOL WINAPI ImageUnload(PLOADED_IMAGE pLoadedImage)
|
||||
{
|
||||
/* If the image list isn't empty, remove this entry */
|
||||
if (!IsListEmpty(&pLoadedImage->Links)) RemoveEntryList(&pLoadedImage->Links);
|
||||
LIST_ENTRY *pCurrent, *pFind;
|
||||
|
||||
/* Unmap and unload it */
|
||||
UnMapAndLoad(pLoadedImage);
|
||||
TRACE("(%p)\n", pLoadedImage);
|
||||
|
||||
if(!IMAGEHLP_pFirstLoadedImage || !pLoadedImage)
|
||||
{
|
||||
/* No image loaded or null pointer */
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Free the structure */
|
||||
HeapFree(IMAGEHLP_hHeap, 0, pLoadedImage);
|
||||
pFind=&pLoadedImage->Links;
|
||||
pCurrent=&IMAGEHLP_pFirstLoadedImage->Links;
|
||||
while((pCurrent != pFind) &&
|
||||
(pCurrent != NULL))
|
||||
pCurrent = pCurrent->Flink;
|
||||
if(!pCurrent)
|
||||
{
|
||||
/* Not found */
|
||||
SetLastError(ERROR_INVALID_PARAMETER);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Return success */
|
||||
return TRUE;
|
||||
if(pCurrent->Blink)
|
||||
pCurrent->Blink->Flink = pCurrent->Flink;
|
||||
else
|
||||
IMAGEHLP_pFirstLoadedImage = pCurrent->Flink?CONTAINING_RECORD(
|
||||
pCurrent->Flink, LOADED_IMAGE, Links):NULL;
|
||||
|
||||
if(pCurrent->Flink)
|
||||
pCurrent->Flink->Blink = pCurrent->Blink;
|
||||
else
|
||||
IMAGEHLP_pLastLoadedImage = pCurrent->Blink?CONTAINING_RECORD(
|
||||
pCurrent->Blink, LOADED_IMAGE, Links):NULL;
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* MapAndLoad (IMAGEHLP.@)
|
||||
*/
|
||||
BOOL IMAGEAPI MapAndLoad(
|
||||
LPSTR ImageName, LPSTR DllPath, PLOADED_IMAGE pLoadedImage,
|
||||
BOOL DotDll, BOOL ReadOnly)
|
||||
BOOL IMAGEAPI MapAndLoad(LPSTR pszImageName, LPSTR pszDllPath, PLOADED_IMAGE pLoadedImage,
|
||||
BOOL bDotDll, BOOL bReadOnly)
|
||||
{
|
||||
HANDLE hFile;
|
||||
HANDLE hFileMapping;
|
||||
ULONG Tried = 0;
|
||||
UCHAR Buffer[MAX_PATH];
|
||||
LPSTR FilePart;
|
||||
LPSTR FileToOpen;
|
||||
PIMAGE_NT_HEADERS NtHeader;
|
||||
CHAR szFileName[MAX_PATH];
|
||||
HANDLE hFile = INVALID_HANDLE_VALUE;
|
||||
HANDLE hFileMapping = NULL;
|
||||
PVOID mapping = NULL;
|
||||
PIMAGE_NT_HEADERS pNtHeader = NULL;
|
||||
|
||||
/* So we can add the DLL Path later */
|
||||
FileToOpen = ImageName;
|
||||
TRACE("(%s, %s, %p, %d, %d)\n",
|
||||
pszImageName, pszDllPath, pLoadedImage, bDotDll, bReadOnly);
|
||||
|
||||
/* Assume failure */
|
||||
pLoadedImage->hFile = INVALID_HANDLE_VALUE;
|
||||
|
||||
/* Start open loop */
|
||||
while (TRUE)
|
||||
if (!SearchPathA(pszDllPath, pszImageName, bDotDll ? ".DLL" : ".EXE",
|
||||
sizeof(szFileName), szFileName, NULL))
|
||||
{
|
||||
/* Get a handle to the file */
|
||||
hFile = CreateFileA(FileToOpen,
|
||||
ReadOnly ? GENERIC_READ :
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
ReadOnly ? FILE_SHARE_READ :
|
||||
FILE_SHARE_READ | FILE_SHARE_WRITE,
|
||||
NULL,
|
||||
OPEN_EXISTING,
|
||||
0,
|
||||
NULL);
|
||||
|
||||
if (hFile == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
/* Check if we already tried this once */
|
||||
if (!Tried)
|
||||
{
|
||||
/* We didn't do do a path search now */
|
||||
Tried = SearchPath(DllPath,
|
||||
ImageName,
|
||||
DotDll ? ".dll" : ".exe",
|
||||
MAX_PATH,
|
||||
(PSTR)Buffer,
|
||||
&FilePart);
|
||||
|
||||
/* Check if it was successful */
|
||||
if (Tried && (Tried < MAX_PATH))
|
||||
{
|
||||
/* Change the filename to use, and try again */
|
||||
FileToOpen = (PSTR)Buffer;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* Fail */
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Success, break out */
|
||||
break;
|
||||
SetLastError(ERROR_FILE_NOT_FOUND);
|
||||
goto Error;
|
||||
}
|
||||
|
||||
/* Create the File Mapping */
|
||||
hFileMapping = CreateFileMappingA(hFile,
|
||||
NULL,
|
||||
ReadOnly ? PAGE_READONLY :
|
||||
PAGE_READWRITE,
|
||||
0,
|
||||
0,
|
||||
NULL);
|
||||
hFile = CreateFileA(szFileName,
|
||||
GENERIC_READ | (bReadOnly ? 0 : GENERIC_WRITE),
|
||||
FILE_SHARE_READ,
|
||||
NULL, OPEN_EXISTING, 0, NULL);
|
||||
if (hFile == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
WARN("CreateFile: Error = %d\n", GetLastError());
|
||||
goto Error;
|
||||
}
|
||||
|
||||
hFileMapping = CreateFileMappingA(hFile, NULL,
|
||||
(bReadOnly ? PAGE_READONLY : PAGE_READWRITE) | SEC_COMMIT,
|
||||
0, 0, NULL);
|
||||
if (!hFileMapping)
|
||||
{
|
||||
/* Fail */
|
||||
SetLastError(GetLastError());
|
||||
CloseHandle(hFile);
|
||||
return FALSE;
|
||||
WARN("CreateFileMapping: Error = %d\n", GetLastError());
|
||||
goto Error;
|
||||
}
|
||||
|
||||
/* Get a pointer to the file */
|
||||
pLoadedImage->MappedAddress = MapViewOfFile(hFileMapping,
|
||||
ReadOnly ? FILE_MAP_READ :
|
||||
FILE_MAP_WRITE,
|
||||
0,
|
||||
0,
|
||||
0);
|
||||
|
||||
/* Close the handle to the map, we don't need it anymore */
|
||||
mapping = MapViewOfFile(hFileMapping, bReadOnly ? FILE_MAP_READ : FILE_MAP_WRITE, 0, 0, 0);
|
||||
CloseHandle(hFileMapping);
|
||||
|
||||
/* Write the image size */
|
||||
pLoadedImage->SizeOfImage = GetFileSize(hFile, NULL);
|
||||
|
||||
/* Get the Nt Header */
|
||||
NtHeader = ImageNtHeader(pLoadedImage->MappedAddress);
|
||||
|
||||
/* Allocate memory for the name and save it */
|
||||
pLoadedImage->ModuleName = HeapAlloc(IMAGEHLP_hHeap,
|
||||
0,
|
||||
strlen(FileToOpen) + 16);
|
||||
strcpy(pLoadedImage->ModuleName, FileToOpen);
|
||||
|
||||
/* Save the NT Header */
|
||||
pLoadedImage->FileHeader = NtHeader;
|
||||
|
||||
/* Save the section data */
|
||||
pLoadedImage->Sections = IMAGE_FIRST_SECTION(NtHeader);
|
||||
pLoadedImage->NumberOfSections = NtHeader->FileHeader.NumberOfSections;
|
||||
|
||||
/* Setup other data */
|
||||
pLoadedImage->SizeOfImage = NtHeader->OptionalHeader.SizeOfImage;
|
||||
pLoadedImage->Characteristics = NtHeader->FileHeader.Characteristics;
|
||||
pLoadedImage->LastRvaSection = pLoadedImage->Sections;
|
||||
pLoadedImage->fSystemImage = FALSE; /* FIXME */
|
||||
pLoadedImage->fDOSImage = FALSE; /* FIXME */
|
||||
InitializeListHead(&pLoadedImage->Links);
|
||||
|
||||
/* Check if it was read-only */
|
||||
if (ReadOnly)
|
||||
if (!mapping)
|
||||
{
|
||||
/* It was, so close our handle and write it as invalid */
|
||||
CloseHandle(hFile);
|
||||
pLoadedImage->hFile = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Write our file handle */
|
||||
pLoadedImage->hFile = hFile;
|
||||
WARN("MapViewOfFile: Error = %d\n", GetLastError());
|
||||
goto Error;
|
||||
}
|
||||
|
||||
/* Return Success */
|
||||
if (!(pNtHeader = RtlImageNtHeader(mapping)))
|
||||
{
|
||||
WARN("Not an NT header\n");
|
||||
UnmapViewOfFile(mapping);
|
||||
goto Error;
|
||||
}
|
||||
|
||||
pLoadedImage->ModuleName = HeapAlloc(GetProcessHeap(), 0,
|
||||
strlen(szFileName) + 1);
|
||||
if (pLoadedImage->ModuleName) strcpy(pLoadedImage->ModuleName, szFileName);
|
||||
pLoadedImage->hFile = hFile;
|
||||
pLoadedImage->MappedAddress = mapping;
|
||||
pLoadedImage->FileHeader = pNtHeader;
|
||||
pLoadedImage->Sections = (PIMAGE_SECTION_HEADER)
|
||||
((LPBYTE) &pNtHeader->OptionalHeader +
|
||||
pNtHeader->FileHeader.SizeOfOptionalHeader);
|
||||
pLoadedImage->NumberOfSections = pNtHeader->FileHeader.NumberOfSections;
|
||||
pLoadedImage->SizeOfImage = GetFileSize(hFile, NULL);
|
||||
pLoadedImage->Characteristics = pNtHeader->FileHeader.Characteristics;
|
||||
pLoadedImage->LastRvaSection = pLoadedImage->Sections;
|
||||
|
||||
pLoadedImage->fSystemImage = FALSE; /* FIXME */
|
||||
pLoadedImage->fDOSImage = FALSE; /* FIXME */
|
||||
|
||||
pLoadedImage->Links.Flink = &pLoadedImage->Links;
|
||||
pLoadedImage->Links.Blink = &pLoadedImage->Links;
|
||||
|
||||
return TRUE;
|
||||
|
||||
Error:
|
||||
if (hFile != INVALID_HANDLE_VALUE) CloseHandle(hFile);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* SetImageConfigInformation (IMAGEHLP.@)
|
||||
*/
|
||||
BOOL IMAGEAPI SetImageConfigInformation(
|
||||
BOOL WINAPI SetImageConfigInformation(
|
||||
PLOADED_IMAGE LoadedImage,
|
||||
PIMAGE_LOAD_CONFIG_DIRECTORY ImageConfigInformation)
|
||||
{
|
||||
|
@ -361,276 +243,11 @@ BOOL IMAGEAPI SetImageConfigInformation(
|
|||
/***********************************************************************
|
||||
* UnMapAndLoad (IMAGEHLP.@)
|
||||
*/
|
||||
BOOL IMAGEAPI UnMapAndLoad(PLOADED_IMAGE Image)
|
||||
BOOL WINAPI UnMapAndLoad(PLOADED_IMAGE pLoadedImage)
|
||||
{
|
||||
PIMAGE_NT_HEADERS NtHeader;
|
||||
DWORD HeaderCheckSum, CheckSum;
|
||||
|
||||
/* Check if the image was read-only */
|
||||
if (Image->hFile == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
/* We'll only unmap the view */
|
||||
UnmapViewOfFile(Image->MappedAddress);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Calculate the checksum */
|
||||
CheckSumMappedFile(Image->MappedAddress,
|
||||
Image->SizeOfImage,
|
||||
&HeaderCheckSum,
|
||||
&CheckSum);
|
||||
|
||||
/* Get the NT Header */
|
||||
NtHeader = Image->FileHeader;
|
||||
|
||||
/* Write the new checksum to it */
|
||||
NtHeader->OptionalHeader.CheckSum = CheckSum;
|
||||
|
||||
/* Now flush and unmap the image */
|
||||
FlushViewOfFile(Image->MappedAddress, Image->SizeOfImage);
|
||||
UnmapViewOfFile(Image->MappedAddress);
|
||||
|
||||
/* Check if the size changed */
|
||||
if (Image->SizeOfImage != GetFileSize(Image->hFile, NULL))
|
||||
{
|
||||
/* Update the file pointer */
|
||||
SetFilePointer(Image->hFile, Image->SizeOfImage, NULL, FILE_BEGIN);
|
||||
SetEndOfFile(Image->hFile);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if the image had a valid handle, and close it */
|
||||
if (Image->hFile != INVALID_HANDLE_VALUE) CloseHandle(Image->hFile);
|
||||
|
||||
/* Return success */
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
PVOID
|
||||
IMAGEAPI
|
||||
ImageDirectoryEntryToData32(PVOID Base,
|
||||
BOOLEAN MappedAsImage,
|
||||
USHORT DirectoryEntry,
|
||||
PULONG Size,
|
||||
PIMAGE_SECTION_HEADER *FoundHeader OPTIONAL,
|
||||
PIMAGE_FILE_HEADER FileHeader,
|
||||
PIMAGE_OPTIONAL_HEADER OptionalHeader)
|
||||
{
|
||||
ULONG i;
|
||||
PIMAGE_SECTION_HEADER CurrentSection;
|
||||
ULONG DirectoryEntryVA;
|
||||
|
||||
/* Check if this entry is invalid */
|
||||
if (DirectoryEntry >= OptionalHeader->NumberOfRvaAndSizes)
|
||||
{
|
||||
/* Nothing found */
|
||||
*Size = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Get the VA of the Directory Requested */
|
||||
DirectoryEntryVA = OptionalHeader->DataDirectory[DirectoryEntry].VirtualAddress;
|
||||
if (!DirectoryEntryVA)
|
||||
{
|
||||
/* It doesn't exist */
|
||||
*Size = 0;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Get the size of the Directory Requested */
|
||||
*Size = OptionalHeader->DataDirectory[DirectoryEntry].Size;
|
||||
|
||||
/* Check if it was mapped as an image or if the entry is within the headers */
|
||||
if ((MappedAsImage) || (DirectoryEntryVA < OptionalHeader->SizeOfHeaders))
|
||||
{
|
||||
/* No header found */
|
||||
if (FoundHeader) *FoundHeader = NULL;
|
||||
|
||||
/* And simply return the VA */
|
||||
return (PVOID)((ULONG_PTR)Base + DirectoryEntryVA);
|
||||
}
|
||||
|
||||
/* Read the first Section */
|
||||
CurrentSection = (PIMAGE_SECTION_HEADER)((ULONG_PTR)OptionalHeader +
|
||||
FileHeader->SizeOfOptionalHeader);
|
||||
|
||||
/* Loop through every section*/
|
||||
for (i = 0; i < FileHeader->NumberOfSections; i++)
|
||||
{
|
||||
/* If the Directory VA is located inside this section's VA, then this section belongs to this Directory */
|
||||
if ((DirectoryEntryVA >= CurrentSection->VirtualAddress) &&
|
||||
(DirectoryEntryVA < (CurrentSection->VirtualAddress +
|
||||
CurrentSection->SizeOfRawData)))
|
||||
{
|
||||
/* Return the section header */
|
||||
if (FoundHeader) *FoundHeader = CurrentSection;
|
||||
return ((PVOID)((ULONG_PTR)Base +
|
||||
(DirectoryEntryVA - CurrentSection->VirtualAddress) +
|
||||
CurrentSection->PointerToRawData));
|
||||
}
|
||||
|
||||
/* Move to the next section */
|
||||
CurrentSection++;
|
||||
}
|
||||
|
||||
/* If we got here, then we didn't find anything */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
*/
|
||||
DWORD
|
||||
IMAGEAPI
|
||||
GetTimestampForLoadedLibrary(HMODULE Module)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
PVOID
|
||||
IMAGEAPI
|
||||
ImageDirectoryEntryToData(PVOID Base,
|
||||
BOOLEAN MappedAsImage,
|
||||
USHORT DirectoryEntry,
|
||||
PULONG Size)
|
||||
{
|
||||
/* Let the extended function handle it */
|
||||
return ImageDirectoryEntryToDataEx(Base,
|
||||
MappedAsImage,
|
||||
DirectoryEntry,
|
||||
Size,
|
||||
NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
PVOID
|
||||
IMAGEAPI
|
||||
ImageDirectoryEntryToDataEx(IN PVOID Base,
|
||||
IN BOOLEAN MappedAsImage,
|
||||
IN USHORT DirectoryEntry,
|
||||
OUT PULONG Size,
|
||||
OUT PIMAGE_SECTION_HEADER *FoundSection OPTIONAL)
|
||||
{
|
||||
PIMAGE_NT_HEADERS NtHeader;
|
||||
PIMAGE_FILE_HEADER FileHeader;
|
||||
PIMAGE_OPTIONAL_HEADER OptionalHeader;
|
||||
|
||||
/* Get the optional header ourselves */
|
||||
NtHeader = ImageNtHeader(Base);
|
||||
FileHeader = &NtHeader->FileHeader;
|
||||
OptionalHeader = &NtHeader->OptionalHeader;
|
||||
|
||||
/* FIXME: Read image type and call appropriate function (32, 64, ROM) */
|
||||
return ImageDirectoryEntryToData32(Base,
|
||||
MappedAsImage,
|
||||
DirectoryEntry,
|
||||
Size,
|
||||
FoundSection,
|
||||
FileHeader,
|
||||
OptionalHeader);
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
PIMAGE_SECTION_HEADER
|
||||
IMAGEAPI
|
||||
ImageRvaToSection(IN PIMAGE_NT_HEADERS NtHeaders,
|
||||
IN PVOID Base,
|
||||
IN ULONG Rva)
|
||||
{
|
||||
PIMAGE_SECTION_HEADER Section;
|
||||
ULONG i;
|
||||
|
||||
/* Get the First Section */
|
||||
Section = IMAGE_FIRST_SECTION(NtHeaders);
|
||||
|
||||
/* Look through each section */
|
||||
for (i = 0; i < NtHeaders->FileHeader.NumberOfSections; i++)
|
||||
{
|
||||
/* Check if the RVA is in between */
|
||||
if ((Rva >= Section->VirtualAddress) &&
|
||||
(Rva < (Section->VirtualAddress + Section->SizeOfRawData)))
|
||||
{
|
||||
/* Return this section */
|
||||
return Section;
|
||||
}
|
||||
|
||||
/* Move to the next section */
|
||||
Section++;
|
||||
}
|
||||
|
||||
/* Not Found */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
PIMAGE_NT_HEADERS
|
||||
IMAGEAPI
|
||||
ImageNtHeader(PVOID Base)
|
||||
{
|
||||
/* Let RTL do it */
|
||||
return RtlImageNtHeader(Base);
|
||||
}
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
PVOID
|
||||
IMAGEAPI
|
||||
ImageRvaToVa(IN PIMAGE_NT_HEADERS NtHeaders,
|
||||
IN PVOID Base,
|
||||
IN ULONG Rva,
|
||||
IN OUT PIMAGE_SECTION_HEADER *LastRvaSection OPTIONAL)
|
||||
{
|
||||
PIMAGE_SECTION_HEADER Section;
|
||||
|
||||
/* Get the Section Associated */
|
||||
Section = ImageRvaToSection(NtHeaders, Base, Rva);
|
||||
|
||||
/* Return it, if specified */
|
||||
if (LastRvaSection) *LastRvaSection = Section;
|
||||
|
||||
/* Return the VA */
|
||||
return (PVOID)((ULONG_PTR)Base + (Rva - Section->VirtualAddress) +
|
||||
Section->PointerToRawData);
|
||||
}
|
||||
|
||||
BOOL
|
||||
IMAGEAPI
|
||||
UnloadAllImages(VOID)
|
||||
{
|
||||
PLIST_ENTRY Head, Entry;
|
||||
PLOADED_IMAGE CurrentImage;
|
||||
|
||||
/* Make sure we're initialized */
|
||||
if (!DllListInitialized) return TRUE;
|
||||
|
||||
/* Get the list pointers and loop */
|
||||
Head = &ImageLoadListHead;
|
||||
Entry = Head->Flink;
|
||||
while (Entry != Head)
|
||||
{
|
||||
/* Get this image */
|
||||
CurrentImage = CONTAINING_RECORD(Entry, LOADED_IMAGE, Links);
|
||||
|
||||
/* Move to the next entry */
|
||||
Entry = Entry->Flink;
|
||||
|
||||
/* Unload it */
|
||||
ImageUnload(CurrentImage);
|
||||
}
|
||||
|
||||
/* We are not initialized anymore */
|
||||
DllListInitialized = FALSE;
|
||||
HeapFree(GetProcessHeap(), 0, pLoadedImage->ModuleName);
|
||||
/* FIXME: MSDN states that a new checksum is computed and stored into the file */
|
||||
if (pLoadedImage->MappedAddress) UnmapViewOfFile(pLoadedImage->MappedAddress);
|
||||
if (pLoadedImage->hFile != INVALID_HANDLE_VALUE) CloseHandle(pLoadedImage->hFile);
|
||||
return TRUE;
|
||||
}
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
<module name="imagehlp" type="win32dll" baseaddress="${BASEADDRESS_IMAGEHLP}" installbase="system32" installname="imagehlp.dll">
|
||||
<module name="imagehlp" type="win32dll" baseaddress="${BASEADDRESS_IMAGEHLP}" installbase="system32" allowwarnings="true" installname="imagehlp.dll" crt="msvcrt">
|
||||
<importlibrary definition="imagehlp.spec" />
|
||||
<include base="imagehlp">.</include>
|
||||
<define name="_IMAGEHLP_SOURCE_"></define>
|
||||
<library>wine</library>
|
||||
<library>dbghelp</library>
|
||||
<library>ntdll</library>
|
||||
<file>access.c</file>
|
||||
<file>imagehlp_main.c</file>
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
@ stdcall BindImage(str str str)
|
||||
@ stdcall BindImageEx(long str str str ptr)
|
||||
@ stdcall CheckSumMappedFile(ptr long ptr ptr)
|
||||
@ stdcall EnumerateLoadedModules(long ptr ptr) dbghelp.EnumerateLoadedModules
|
||||
@ stdcall EnumerateLoadedModules64(long ptr ptr) dbghelp.EnumerateLoadedModules64
|
||||
@ stdcall EnumerateLoadedModules(long ptr ptr) dbghelp.EnumerateLoadedModules
|
||||
@ stdcall FindDebugInfoFile(str str str) dbghelp.FindDebugInfoFile
|
||||
@ stdcall FindDebugInfoFileEx(str str ptr ptr ptr) dbghelp.FindDebugInfoFileEx
|
||||
@ stdcall FindExecutableImage(str str str) dbghelp.FindExecutableImage
|
||||
|
@ -13,96 +13,97 @@
|
|||
@ stdcall GetImageUnusedHeaderBytes(ptr ptr)
|
||||
@ stdcall GetTimestampForLoadedLibrary(long) dbghelp.GetTimestampForLoadedLibrary
|
||||
@ stdcall ImageAddCertificate(long ptr ptr)
|
||||
@ stdcall ImageDirectoryEntryToData(ptr long long ptr)
|
||||
@ stdcall ImageDirectoryEntryToDataEx(ptr long long ptr ptr)
|
||||
@ stdcall ImageDirectoryEntryToData(ptr long long ptr) dbghelp.ImageDirectoryEntryToData
|
||||
@ stdcall ImageDirectoryEntryToDataEx(ptr long long ptr ptr) dbghelp.ImageDirectoryEntryToDataEx
|
||||
@ stdcall ImageEnumerateCertificates(long long ptr ptr long)
|
||||
@ stdcall ImageGetCertificateData(long long ptr ptr)
|
||||
@ stdcall ImageGetCertificateHeader(long long ptr)
|
||||
@ stdcall ImageGetDigestStream(long long ptr long)
|
||||
@ stdcall ImagehlpApiVersion() dbghelp.ImagehlpApiVersion
|
||||
@ stdcall ImagehlpApiVersionEx(ptr) dbghelp.ImagehlpApiVersionEx
|
||||
@ stdcall ImageLoad(str str)
|
||||
@ stdcall ImageNtHeader(ptr) ntdll.RtlImageNtHeader
|
||||
@ stdcall ImageRemoveCertificate(long long)
|
||||
@ stdcall ImageRvaToSection(ptr ptr long) ntdll.RtlImageRvaToSection
|
||||
@ stdcall ImageRvaToVa(ptr ptr long ptr) ntdll.RtlImageRvaToVa
|
||||
@ stdcall ImageUnload(ptr)
|
||||
@ stdcall ImagehlpApiVersion() dbghelp.ImagehlpApiVersion
|
||||
@ stdcall ImagehlpApiVersionEx(ptr) dbghelp.ImagehlpApiVersionEx
|
||||
@ stdcall MakeSureDirectoryPathExists(str) dbghelp.MakeSureDirectoryPathExists
|
||||
@ stdcall MapAndLoad(str str ptr long long)
|
||||
@ stdcall MapDebugInformation(long str str long) dbghelp.MapDebugInformation
|
||||
@ stdcall MapFileAndCheckSumA(str ptr ptr)
|
||||
@ stdcall MapFileAndCheckSumW(wstr ptr ptr)
|
||||
@ stdcall ReBaseImage(str str long long long long ptr ptr ptr ptr long)
|
||||
@ stub MarkImageAsRunFromSwap
|
||||
@ stub ReBaseImage64
|
||||
@ stdcall ReBaseImage(str str long long long long ptr ptr ptr ptr long)
|
||||
@ stdcall RemovePrivateCvSymbolic(ptr ptr ptr)
|
||||
@ stub RemovePrivateCvSymbolicEx
|
||||
@ stdcall RemoveRelocations(ptr)
|
||||
@ stdcall SearchTreeForFile(str str str) dbghelp.SearchTreeForFile
|
||||
@ stdcall SetImageConfigInformation(ptr ptr)
|
||||
@ stdcall SplitSymbols(str str str long)
|
||||
@ stdcall StackWalk(long long long ptr ptr ptr ptr ptr ptr) dbghelp.StackWalk
|
||||
@ stdcall StackWalk64(long long long ptr ptr ptr ptr ptr ptr) dbghelp.StackWalk64
|
||||
@ stdcall StackWalk(long long long ptr ptr ptr ptr ptr ptr) dbghelp.StackWalk
|
||||
@ stdcall SymCleanup(long) dbghelp.SymCleanup
|
||||
@ stdcall SymEnumerateModules(long ptr ptr) dbghelp.SymEnumerateModules
|
||||
@ stdcall SymEnumerateModules64(long ptr ptr) dbghelp.SymEnumerateModules64
|
||||
@ stdcall SymEnumerateSymbols(long long ptr ptr) dbghelp.SymEnumerateSymbols
|
||||
@ stub SymEnumerateSymbols64
|
||||
@ stdcall SymEnumerateSymbolsW(long long ptr ptr) dbghelp.SymEnumerateSymbolsW
|
||||
@ stub SymEnumerateSymbolsW64
|
||||
@ stdcall SymEnumSourceFiles(long long str ptr ptr) dbghelp.SymEnumSourceFiles
|
||||
@ stub SymEnumSym
|
||||
@ stdcall SymEnumSymbols(long double str ptr ptr) dbghelp.SymEnumSymbols
|
||||
@ stdcall SymEnumSymbols(long long str ptr ptr) dbghelp.SymEnumSymbols
|
||||
@ stdcall SymEnumTypes(long long ptr ptr) dbghelp.SymEnumTypes
|
||||
@ stdcall SymEnumerateModules64(long ptr ptr) dbghelp.SymEnumerateModules64
|
||||
@ stdcall SymEnumerateModules(long ptr ptr) dbghelp.SymEnumerateModules
|
||||
@ stdcall SymEnumerateSymbols64(long double ptr ptr) dbghelp.SymEnumerateSymbols64
|
||||
@ stdcall SymEnumerateSymbols(long long ptr ptr) dbghelp.SymEnumerateSymbols
|
||||
@ stub SymEnumerateSymbolsW64
|
||||
@ stub SymEnumerateSymbolsW
|
||||
@ stdcall SymFindFileInPath(long str str ptr long long long ptr ptr ptr) dbghelp.SymFindFileInPath
|
||||
@ stdcall SymFromAddr(long long ptr ptr) dbghelp.SymFromAddr
|
||||
@ stdcall SymFromName(long str ptr) dbghelp.SymFromName
|
||||
@ stdcall SymFunctionTableAccess(long long) dbghelp.SymFunctionTableAccess
|
||||
@ stdcall SymFunctionTableAccess64(long double) dbghelp.SymFunctionTableAccess64
|
||||
@ stdcall SymGetLineFromAddr(long long ptr ptr) dbghelp.SymGetLineFromAddr
|
||||
@ stdcall SymFunctionTableAccess(long long) dbghelp.SymFunctionTableAccess
|
||||
@ stdcall SymGetLineFromAddr64(long double ptr ptr) dbghelp.SymGetLineFromAddr64
|
||||
@ stdcall SymGetLineFromName(long str str long ptr ptr) dbghelp.SymGetLineFromName
|
||||
@ stdcall SymGetLineFromName64(long str str long ptr ptr) dbghelp.SymGetLineFromName
|
||||
@ stdcall SymGetLineNext(long ptr) dbghelp.SymGetLineNext
|
||||
@ stdcall SymGetLineFromAddr(long long ptr ptr) dbghelp.SymGetLineFromAddr
|
||||
@ stub SymGetLineFromName64
|
||||
@ stub SymGetLineFromName
|
||||
@ stdcall SymGetLineNext64(long ptr) dbghelp.SymGetLineNext64
|
||||
@ stdcall SymGetLinePrev(long ptr) dbghelp.SymGetLinePrev
|
||||
@ stdcall SymGetLineNext(long ptr) dbghelp.SymGetLineNext
|
||||
@ stdcall SymGetLinePrev64(long ptr) dbghelp.SymGetLinePrev64
|
||||
@ stdcall SymGetModuleBase(long long) dbghelp.SymGetModuleBase
|
||||
@ stdcall SymGetLinePrev(long ptr) dbghelp.SymGetLinePrev
|
||||
@ stdcall SymGetModuleBase64(long double) dbghelp.SymGetModuleBase64
|
||||
@ stdcall SymGetModuleInfo(long long ptr) dbghelp.SymGetModuleInfo
|
||||
@ stdcall SymGetModuleBase(long long) dbghelp.SymGetModuleBase
|
||||
@ stdcall SymGetModuleInfo64(long double ptr) dbghelp.SymGetModuleInfo64
|
||||
@ stdcall SymGetModuleInfoW(long long ptr) dbghelp.SymGetModuleInfoW
|
||||
@ stdcall SymGetModuleInfo(long long ptr) dbghelp.SymGetModuleInfo
|
||||
@ stdcall SymGetModuleInfoW64(long double ptr) dbghelp.SymGetModuleInfoW64
|
||||
@ stdcall SymGetModuleInfoW(long long ptr) dbghelp.SymGetModuleInfoW
|
||||
@ stdcall SymGetOptions() dbghelp.SymGetOptions
|
||||
@ stdcall SymGetSearchPath(long str long) dbghelp.SymGetSearchPath
|
||||
@ stdcall SymGetSymFromAddr(long long ptr ptr) dbghelp.SymGetSymFromAddr
|
||||
@ stdcall SymGetSymFromAddr64(long double ptr ptr) dbghelp.SymGetSymFromAddr64
|
||||
@ stdcall SymGetSymFromAddr(long long ptr ptr) dbghelp.SymGetSymFromAddr
|
||||
@ stdcall SymGetSymFromName64(long str ptr) dbghelp.SymGetSymFromName64
|
||||
@ stdcall SymGetSymFromName(long str ptr) dbghelp.SymGetSymFromName
|
||||
@ stub SymGetSymFromName64
|
||||
@ stdcall SymGetSymNext64(long ptr) dbghelp.SymGetSymNext64
|
||||
@ stdcall SymGetSymNext(long ptr) dbghelp.SymGetSymNext
|
||||
@ stub SymGetSymNext64
|
||||
@ stdcall SymGetSymPrev64(long ptr) dbghelp.SymGetSymPrev64
|
||||
@ stdcall SymGetSymPrev(long ptr) dbghelp.SymGetSymPrev
|
||||
@ stub SymGetSymPrev64
|
||||
@ stdcall SymGetTypeFromName(long long str ptr) dbghelp.SymGetTypeFromName
|
||||
@ stdcall SymGetTypeInfo(long long long long ptr) dbghelp.SymGetTypeInfo
|
||||
@ stdcall SymInitialize(long str long) dbghelp.SymInitialize
|
||||
@ stdcall SymLoadModule(long long str str long long) dbghelp.SymLoadModule
|
||||
@ stdcall SymLoadModule64(long long str str double long) dbghelp.SymLoadModule64
|
||||
@ stdcall SymLoadModule(long long str str long long) dbghelp.SymLoadModule
|
||||
@ stdcall SymMatchFileName(str str ptr ptr) dbghelp.SymMatchFileName
|
||||
@ stdcall SymMatchString(str str long) dbghelp.SymMatchString
|
||||
@ stdcall SymRegisterCallback(long ptr ptr) dbghelp.SymRegisterCallback
|
||||
@ stdcall SymRegisterCallback64(long ptr double) dbghelp.SymRegisterCallback64
|
||||
@ stdcall SymRegisterFunctionEntryCallback(ptr ptr ptr) dbghelp.SymRegisterFunctionEntryCallback
|
||||
@ stdcall SymRegisterCallback(long ptr ptr) dbghelp.SymRegisterCallback
|
||||
@ stdcall SymRegisterFunctionEntryCallback64(ptr ptr double) dbghelp.SymRegisterFunctionEntryCallback64
|
||||
@ stdcall SymRegisterFunctionEntryCallback(ptr ptr ptr) dbghelp.SymRegisterFunctionEntryCallback
|
||||
@ stdcall SymSetContext(long ptr ptr) dbghelp.SymSetContext
|
||||
@ stdcall SymSetOptions(long) dbghelp.SymSetOptions
|
||||
@ stdcall SymSetSearchPath(long str) dbghelp.SymSetSearchPath
|
||||
@ stdcall SymUnDName64(ptr str long) dbghelp.SymUnDName64
|
||||
@ stdcall SymUnDName(ptr str long) dbghelp.SymUnDName
|
||||
@ stub SymUnDName64
|
||||
@ stdcall SymUnloadModule(long long) dbghelp.SymUnloadModule
|
||||
@ stdcall SymUnloadModule64(long double) dbghelp.SymUnloadModule64
|
||||
@ stdcall SymUnloadModule(long long) dbghelp.SymUnloadModule
|
||||
@ stdcall TouchFileTimes(long ptr)
|
||||
@ stdcall UnDecorateSymbolName(str str long long) dbghelp.UnDecorateSymbolName
|
||||
@ stdcall UnMapAndLoad(ptr)
|
||||
@ stdcall UnmapDebugInformation(ptr) dbghelp.UnmapDebugInformation
|
||||
@ stdcall UpdateDebugInfoFile(str str str ptr)
|
||||
@ stdcall UpdateDebugInfoFileEx(str str str ptr long)
|
||||
@ stdcall UpdateDebugInfoFileEx(str str str ptr long)
|
||||
|
|
|
@ -18,24 +18,20 @@
|
|||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
|
||||
#include "precomp.h"
|
||||
|
||||
#define _WINNT_H
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "imagehlp.h"
|
||||
#include "wine/debug.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(imagehlp);
|
||||
|
||||
/**********************************************************************/
|
||||
HANDLE IMAGEHLP_hHeap = NULL;
|
||||
|
||||
/***********************************************************************
|
||||
* DllMain (IMAGEHLP.init)
|
||||
*/
|
||||
BOOL IMAGEAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
||||
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
||||
{
|
||||
switch(fdwReason)
|
||||
{
|
||||
|
@ -52,3 +48,27 @@ BOOL IMAGEAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
|||
}
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* MarkImageAsRunFromSwap (IMAGEHLP.@)
|
||||
* FIXME
|
||||
* No documentation available.
|
||||
*/
|
||||
|
||||
/***********************************************************************
|
||||
* TouchFileTimes (IMAGEHLP.@)
|
||||
*/
|
||||
BOOL WINAPI TouchFileTimes(HANDLE FileHandle, LPSYSTEMTIME lpSystemTime)
|
||||
{
|
||||
FILETIME FileTime;
|
||||
SYSTEMTIME SystemTime;
|
||||
|
||||
if(lpSystemTime == NULL)
|
||||
{
|
||||
GetSystemTime(&SystemTime);
|
||||
lpSystemTime = &SystemTime;
|
||||
}
|
||||
|
||||
return (SystemTimeToFileTime(lpSystemTime, &FileTime) &&
|
||||
SetFileTime(FileHandle, NULL, NULL, &FileTime));
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
*
|
||||
* Copyright 1998 Patrik Stridvall
|
||||
* Copyright 2003 Mike McCormack
|
||||
* Copyright 2009 Owen Rudge for CodeWeavers
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -19,72 +20,217 @@
|
|||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "windef.h"
|
||||
#include "winbase.h"
|
||||
#include "winerror.h"
|
||||
#include "winternl.h"
|
||||
#include "winnt.h"
|
||||
#include "imagehlp.h"
|
||||
#include "wine/debug.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(imagehlp);
|
||||
|
||||
/*
|
||||
* These functions are partially documented at:
|
||||
* http://www.cs.auckland.ac.nz/~pgut001/pubs/authenticode.txt
|
||||
*/
|
||||
|
||||
/* INCLUDES ******************************************************************/
|
||||
#define HDR_FAIL -1
|
||||
#define HDR_NT32 0
|
||||
#define HDR_NT64 1
|
||||
|
||||
#include "precomp.h"
|
||||
|
||||
#define _WINNT_H
|
||||
#include "wine/debug.h"
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(imagehlp);
|
||||
|
||||
/* FUNCTIONS *****************************************************************/
|
||||
|
||||
static
|
||||
BOOL
|
||||
IMAGEHLP_GetSecurityDirOffset(HANDLE handle,
|
||||
DWORD *pdwOfs,
|
||||
DWORD *pdwSize)
|
||||
/***********************************************************************
|
||||
* IMAGEHLP_GetNTHeaders (INTERNAL)
|
||||
*
|
||||
* Return the IMAGE_NT_HEADERS for a PE file, after validating magic
|
||||
* numbers and distinguishing between 32-bit and 64-bit files.
|
||||
*/
|
||||
static int IMAGEHLP_GetNTHeaders(HANDLE handle, DWORD *pe_offset, IMAGE_NT_HEADERS32 *nt32, IMAGE_NT_HEADERS64 *nt64)
|
||||
{
|
||||
IMAGE_DOS_HEADER dos_hdr;
|
||||
IMAGE_NT_HEADERS nt_hdr;
|
||||
DWORD count;
|
||||
BOOL r;
|
||||
IMAGE_DATA_DIRECTORY *sd;
|
||||
|
||||
TRACE("handle %p\n", handle );
|
||||
TRACE("handle %p\n", handle);
|
||||
|
||||
if ((!nt32) || (!nt64))
|
||||
return HDR_FAIL;
|
||||
|
||||
/* read the DOS header */
|
||||
count = SetFilePointer( handle, 0, NULL, FILE_BEGIN );
|
||||
if( count == INVALID_SET_FILE_POINTER )
|
||||
return FALSE;
|
||||
count = SetFilePointer(handle, 0, NULL, FILE_BEGIN);
|
||||
|
||||
if (count == INVALID_SET_FILE_POINTER)
|
||||
return HDR_FAIL;
|
||||
|
||||
count = 0;
|
||||
r = ReadFile( handle, &dos_hdr, sizeof dos_hdr, &count, NULL );
|
||||
if( !r )
|
||||
return FALSE;
|
||||
if( count != sizeof dos_hdr )
|
||||
return FALSE;
|
||||
|
||||
r = ReadFile(handle, &dos_hdr, sizeof dos_hdr, &count, NULL);
|
||||
|
||||
if (!r)
|
||||
return HDR_FAIL;
|
||||
|
||||
if (count != sizeof dos_hdr)
|
||||
return HDR_FAIL;
|
||||
|
||||
/* verify magic number of 'MZ' */
|
||||
if (dos_hdr.e_magic != 0x5A4D)
|
||||
return HDR_FAIL;
|
||||
|
||||
if (pe_offset != NULL)
|
||||
*pe_offset = dos_hdr.e_lfanew;
|
||||
|
||||
/* read the PE header */
|
||||
count = SetFilePointer( handle, dos_hdr.e_lfanew, NULL, FILE_BEGIN );
|
||||
if( count == INVALID_SET_FILE_POINTER )
|
||||
return FALSE;
|
||||
count = SetFilePointer(handle, dos_hdr.e_lfanew, NULL, FILE_BEGIN);
|
||||
|
||||
if (count == INVALID_SET_FILE_POINTER)
|
||||
return HDR_FAIL;
|
||||
|
||||
count = 0;
|
||||
r = ReadFile( handle, &nt_hdr, sizeof nt_hdr, &count, NULL );
|
||||
if( !r )
|
||||
return FALSE;
|
||||
if( count != sizeof nt_hdr )
|
||||
|
||||
r = ReadFile(handle, nt32, sizeof(IMAGE_NT_HEADERS32), &count, NULL);
|
||||
|
||||
if (!r)
|
||||
return HDR_FAIL;
|
||||
|
||||
if (count != sizeof(IMAGE_NT_HEADERS32))
|
||||
return HDR_FAIL;
|
||||
|
||||
/* verify NT signature */
|
||||
if (nt32->Signature != IMAGE_NT_SIGNATURE)
|
||||
return HDR_FAIL;
|
||||
|
||||
/* check if we have a 32-bit or 64-bit executable */
|
||||
switch (nt32->OptionalHeader.Magic)
|
||||
{
|
||||
case IMAGE_NT_OPTIONAL_HDR32_MAGIC:
|
||||
return HDR_NT32;
|
||||
|
||||
case IMAGE_NT_OPTIONAL_HDR64_MAGIC:
|
||||
/* Re-read as 64-bit */
|
||||
|
||||
count = SetFilePointer(handle, dos_hdr.e_lfanew, NULL, FILE_BEGIN);
|
||||
|
||||
if (count == INVALID_SET_FILE_POINTER)
|
||||
return HDR_FAIL;
|
||||
|
||||
count = 0;
|
||||
|
||||
r = ReadFile(handle, nt64, sizeof(IMAGE_NT_HEADERS64), &count, NULL);
|
||||
|
||||
if (!r)
|
||||
return HDR_FAIL;
|
||||
|
||||
if (count != sizeof(IMAGE_NT_HEADERS64))
|
||||
return HDR_FAIL;
|
||||
|
||||
/* verify NT signature */
|
||||
if (nt64->Signature != IMAGE_NT_SIGNATURE)
|
||||
return HDR_FAIL;
|
||||
|
||||
return HDR_NT64;
|
||||
}
|
||||
|
||||
return HDR_FAIL;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* IMAGEHLP_GetSecurityDirOffset (INTERNAL)
|
||||
*
|
||||
* Read a file's PE header, and return the offset and size of the
|
||||
* security directory.
|
||||
*/
|
||||
static BOOL IMAGEHLP_GetSecurityDirOffset( HANDLE handle,
|
||||
DWORD *pdwOfs, DWORD *pdwSize )
|
||||
{
|
||||
IMAGE_NT_HEADERS32 nt_hdr32;
|
||||
IMAGE_NT_HEADERS64 nt_hdr64;
|
||||
IMAGE_DATA_DIRECTORY *sd;
|
||||
int ret;
|
||||
|
||||
ret = IMAGEHLP_GetNTHeaders(handle, NULL, &nt_hdr32, &nt_hdr64);
|
||||
|
||||
if (ret == HDR_NT32)
|
||||
sd = &nt_hdr32.OptionalHeader.DataDirectory[IMAGE_FILE_SECURITY_DIRECTORY];
|
||||
else if (ret == HDR_NT64)
|
||||
sd = &nt_hdr64.OptionalHeader.DataDirectory[IMAGE_FILE_SECURITY_DIRECTORY];
|
||||
else
|
||||
return FALSE;
|
||||
|
||||
sd = &nt_hdr.OptionalHeader.
|
||||
DataDirectory[IMAGE_DIRECTORY_ENTRY_SECURITY];
|
||||
TRACE("ret = %d size = %x addr = %x\n", ret, sd->Size, sd->VirtualAddress);
|
||||
|
||||
TRACE("size = %lx addr = %lx\n", sd->Size, sd->VirtualAddress);
|
||||
*pdwSize = sd->Size;
|
||||
*pdwOfs = sd->VirtualAddress;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* IMAGEHLP_SetSecurityDirOffset (INTERNAL)
|
||||
*
|
||||
* Read a file's PE header, and update the offset and size of the
|
||||
* security directory.
|
||||
*/
|
||||
static BOOL IMAGEHLP_SetSecurityDirOffset(HANDLE handle,
|
||||
DWORD dwOfs, DWORD dwSize)
|
||||
{
|
||||
IMAGE_NT_HEADERS32 nt_hdr32;
|
||||
IMAGE_NT_HEADERS64 nt_hdr64;
|
||||
IMAGE_DATA_DIRECTORY *sd;
|
||||
int ret, nt_hdr_size = 0;
|
||||
DWORD pe_offset;
|
||||
void *nt_hdr;
|
||||
DWORD count;
|
||||
BOOL r;
|
||||
|
||||
ret = IMAGEHLP_GetNTHeaders(handle, &pe_offset, &nt_hdr32, &nt_hdr64);
|
||||
|
||||
if (ret == HDR_NT32)
|
||||
{
|
||||
sd = &nt_hdr32.OptionalHeader.DataDirectory[IMAGE_FILE_SECURITY_DIRECTORY];
|
||||
|
||||
nt_hdr = &nt_hdr32;
|
||||
nt_hdr_size = sizeof(IMAGE_NT_HEADERS32);
|
||||
}
|
||||
else if (ret == HDR_NT64)
|
||||
{
|
||||
sd = &nt_hdr64.OptionalHeader.DataDirectory[IMAGE_FILE_SECURITY_DIRECTORY];
|
||||
|
||||
nt_hdr = &nt_hdr64;
|
||||
nt_hdr_size = sizeof(IMAGE_NT_HEADERS64);
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
|
||||
sd->Size = dwSize;
|
||||
sd->VirtualAddress = dwOfs;
|
||||
|
||||
TRACE("size = %x addr = %x\n", sd->Size, sd->VirtualAddress);
|
||||
|
||||
/* write the header back again */
|
||||
count = SetFilePointer(handle, pe_offset, NULL, FILE_BEGIN);
|
||||
|
||||
if (count == INVALID_SET_FILE_POINTER)
|
||||
return FALSE;
|
||||
|
||||
count = 0;
|
||||
|
||||
r = WriteFile(handle, nt_hdr, nt_hdr_size, &count, NULL);
|
||||
|
||||
if (!r)
|
||||
return FALSE;
|
||||
|
||||
if (count != nt_hdr_size)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* IMAGEHLP_GetCertificateOffset (INTERNAL)
|
||||
*
|
||||
* Read a file's PE header, and return the offset and size of the
|
||||
* Read a file's PE header, and return the offset and size of the
|
||||
* security directory.
|
||||
*/
|
||||
static BOOL IMAGEHLP_GetCertificateOffset( HANDLE handle, DWORD num,
|
||||
|
@ -122,6 +268,11 @@ static BOOL IMAGEHLP_GetCertificateOffset( HANDLE handle, DWORD num,
|
|||
|
||||
/* calculate the offset of the next certificate */
|
||||
offset += len;
|
||||
|
||||
/* padded out to the nearest 8-byte boundary */
|
||||
if( len % 8 )
|
||||
offset += 8 - (len % 8);
|
||||
|
||||
if( offset >= size )
|
||||
return FALSE;
|
||||
}
|
||||
|
@ -129,91 +280,242 @@ static BOOL IMAGEHLP_GetCertificateOffset( HANDLE handle, DWORD num,
|
|||
*pdwOfs = sd_VirtualAddr + offset;
|
||||
*pdwSize = len;
|
||||
|
||||
TRACE("len = %lx addr = %lx\n", len, sd_VirtualAddr + offset);
|
||||
TRACE("len = %x addr = %x\n", len, sd_VirtualAddr + offset);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static
|
||||
WORD
|
||||
CalcCheckSum(DWORD StartValue,
|
||||
LPVOID BaseAddress,
|
||||
DWORD WordCount)
|
||||
/***********************************************************************
|
||||
* IMAGEHLP_RecalculateChecksum (INTERNAL)
|
||||
*
|
||||
* Update the NT header checksum for the specified file.
|
||||
*/
|
||||
static BOOL IMAGEHLP_RecalculateChecksum(HANDLE handle)
|
||||
{
|
||||
LPWORD Ptr;
|
||||
DWORD Sum;
|
||||
DWORD i;
|
||||
DWORD FileLength, count, HeaderSum, pe_offset, nt_hdr_size;
|
||||
IMAGE_NT_HEADERS32 nt_hdr32;
|
||||
IMAGE_NT_HEADERS64 nt_hdr64;
|
||||
LPVOID BaseAddress;
|
||||
HANDLE hMapping;
|
||||
DWORD *CheckSum;
|
||||
void *nt_hdr;
|
||||
int ret;
|
||||
BOOL r;
|
||||
|
||||
Sum = StartValue;
|
||||
Ptr = (LPWORD)BaseAddress;
|
||||
for (i = 0; i < WordCount; i++)
|
||||
{
|
||||
Sum += *Ptr;
|
||||
if (HIWORD(Sum) != 0)
|
||||
{
|
||||
Sum = LOWORD(Sum) + HIWORD(Sum);
|
||||
}
|
||||
Ptr++;
|
||||
}
|
||||
TRACE("handle %p\n", handle);
|
||||
|
||||
return (WORD)(LOWORD(Sum) + HIWORD(Sum));
|
||||
ret = IMAGEHLP_GetNTHeaders(handle, &pe_offset, &nt_hdr32, &nt_hdr64);
|
||||
|
||||
if (ret == HDR_NT32)
|
||||
{
|
||||
CheckSum = &nt_hdr32.OptionalHeader.CheckSum;
|
||||
|
||||
nt_hdr = &nt_hdr32;
|
||||
nt_hdr_size = sizeof(IMAGE_NT_HEADERS32);
|
||||
}
|
||||
else if (ret == HDR_NT64)
|
||||
{
|
||||
CheckSum = &nt_hdr64.OptionalHeader.CheckSum;
|
||||
|
||||
nt_hdr = &nt_hdr64;
|
||||
nt_hdr_size = sizeof(IMAGE_NT_HEADERS64);
|
||||
}
|
||||
else
|
||||
return FALSE;
|
||||
|
||||
hMapping = CreateFileMappingW(handle, NULL, PAGE_READONLY, 0, 0, NULL);
|
||||
|
||||
if (!hMapping)
|
||||
return FALSE;
|
||||
|
||||
BaseAddress = MapViewOfFile(hMapping, FILE_MAP_READ, 0, 0, 0);
|
||||
|
||||
if (!BaseAddress)
|
||||
{
|
||||
CloseHandle(hMapping);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
FileLength = GetFileSize(handle, NULL);
|
||||
|
||||
*CheckSum = 0;
|
||||
CheckSumMappedFile(BaseAddress, FileLength, &HeaderSum, CheckSum);
|
||||
|
||||
UnmapViewOfFile(BaseAddress);
|
||||
CloseHandle(hMapping);
|
||||
|
||||
if (*CheckSum)
|
||||
{
|
||||
/* write the header back again */
|
||||
count = SetFilePointer(handle, pe_offset, NULL, FILE_BEGIN);
|
||||
|
||||
if (count == INVALID_SET_FILE_POINTER)
|
||||
return FALSE;
|
||||
|
||||
count = 0;
|
||||
|
||||
r = WriteFile(handle, nt_hdr, nt_hdr_size, &count, NULL);
|
||||
|
||||
if (!r)
|
||||
return FALSE;
|
||||
|
||||
if (count != nt_hdr_size)
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/*
|
||||
* @unimplemented
|
||||
/***********************************************************************
|
||||
* ImageAddCertificate (IMAGEHLP.@)
|
||||
*
|
||||
* Adds the specified certificate to the security directory of
|
||||
* open PE file.
|
||||
*/
|
||||
BOOL
|
||||
IMAGEAPI
|
||||
ImageAddCertificate(HANDLE FileHandle,
|
||||
LPWIN_CERTIFICATE Certificate,
|
||||
PDWORD Index)
|
||||
|
||||
BOOL WINAPI ImageAddCertificate(
|
||||
HANDLE FileHandle, LPWIN_CERTIFICATE Certificate, PDWORD Index)
|
||||
{
|
||||
UNIMPLEMENTED;
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
||||
return FALSE;
|
||||
DWORD size = 0, count = 0, offset = 0, sd_VirtualAddr = 0, index = 0;
|
||||
WIN_CERTIFICATE hdr;
|
||||
const size_t cert_hdr_size = sizeof hdr - sizeof hdr.bCertificate;
|
||||
BOOL r;
|
||||
|
||||
TRACE("(%p, %p, %p)\n", FileHandle, Certificate, Index);
|
||||
|
||||
r = IMAGEHLP_GetSecurityDirOffset(FileHandle, &sd_VirtualAddr, &size);
|
||||
|
||||
/* If we've already got a security directory, find the end of it */
|
||||
if ((r) && (sd_VirtualAddr != 0))
|
||||
{
|
||||
offset = 0;
|
||||
index = 0;
|
||||
count = 0;
|
||||
|
||||
/* Check if the security directory is at the end of the file.
|
||||
If not, we should probably relocate it. */
|
||||
if (GetFileSize(FileHandle, NULL) != sd_VirtualAddr + size)
|
||||
{
|
||||
FIXME("Security directory already present but not located at EOF, not adding certificate\n");
|
||||
|
||||
SetLastError(ERROR_NOT_SUPPORTED);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
while (offset < size)
|
||||
{
|
||||
/* read the length of the current certificate */
|
||||
count = SetFilePointer (FileHandle, sd_VirtualAddr + offset,
|
||||
NULL, FILE_BEGIN);
|
||||
|
||||
if (count == INVALID_SET_FILE_POINTER)
|
||||
return FALSE;
|
||||
|
||||
r = ReadFile(FileHandle, &hdr, cert_hdr_size, &count, NULL);
|
||||
|
||||
if (!r)
|
||||
return FALSE;
|
||||
|
||||
if (count != cert_hdr_size)
|
||||
return FALSE;
|
||||
|
||||
/* check the certificate is not too big or too small */
|
||||
if (hdr.dwLength < cert_hdr_size)
|
||||
return FALSE;
|
||||
|
||||
if (hdr.dwLength > (size-offset))
|
||||
return FALSE;
|
||||
|
||||
/* next certificate */
|
||||
offset += hdr.dwLength;
|
||||
|
||||
/* padded out to the nearest 8-byte boundary */
|
||||
if (hdr.dwLength % 8)
|
||||
offset += 8 - (hdr.dwLength % 8);
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
count = SetFilePointer (FileHandle, sd_VirtualAddr + offset, NULL, FILE_BEGIN);
|
||||
|
||||
if (count == INVALID_SET_FILE_POINTER)
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
sd_VirtualAddr = SetFilePointer(FileHandle, 0, NULL, FILE_END);
|
||||
|
||||
if (sd_VirtualAddr == INVALID_SET_FILE_POINTER)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Write the certificate to the file */
|
||||
r = WriteFile(FileHandle, Certificate, Certificate->dwLength, &count, NULL);
|
||||
|
||||
if (!r)
|
||||
return FALSE;
|
||||
|
||||
/* Pad out if necessary */
|
||||
if (Certificate->dwLength % 8)
|
||||
{
|
||||
char null[8];
|
||||
|
||||
ZeroMemory(null, 8);
|
||||
WriteFile(FileHandle, null, 8 - (Certificate->dwLength % 8), NULL, NULL);
|
||||
|
||||
size += 8 - (Certificate->dwLength % 8);
|
||||
}
|
||||
|
||||
size += Certificate->dwLength;
|
||||
|
||||
/* Update the security directory offset and size */
|
||||
if (!IMAGEHLP_SetSecurityDirOffset(FileHandle, sd_VirtualAddr, size))
|
||||
return FALSE;
|
||||
|
||||
if (!IMAGEHLP_RecalculateChecksum(FileHandle))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* ImageEnumerateCertificates (IMAGEHLP.@)
|
||||
*/
|
||||
BOOL IMAGEAPI ImageEnumerateCertificates(
|
||||
HANDLE FileHandle, WORD TypeFilter, PDWORD CertificateCount,
|
||||
BOOL WINAPI ImageEnumerateCertificates(
|
||||
HANDLE handle, WORD TypeFilter, PDWORD CertificateCount,
|
||||
PDWORD Indices, DWORD IndexCount)
|
||||
{
|
||||
DWORD size, count, offset, sd_VirtualAddr;
|
||||
DWORD size, count, offset, sd_VirtualAddr, index;
|
||||
WIN_CERTIFICATE hdr;
|
||||
const size_t cert_hdr_size = sizeof hdr - sizeof hdr.bCertificate;
|
||||
BOOL r;
|
||||
|
||||
TRACE("%p %hd %p %p %ld\n",
|
||||
FileHandle, TypeFilter, CertificateCount, Indices, IndexCount);
|
||||
TRACE("%p %hd %p %p %d\n",
|
||||
handle, TypeFilter, CertificateCount, Indices, IndexCount);
|
||||
|
||||
if( Indices )
|
||||
{
|
||||
FIXME("Indicies not handled!\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
r = IMAGEHLP_GetSecurityDirOffset( FileHandle, &sd_VirtualAddr, &size );
|
||||
r = IMAGEHLP_GetSecurityDirOffset( handle, &sd_VirtualAddr, &size );
|
||||
if( !r )
|
||||
return FALSE;
|
||||
|
||||
offset = 0;
|
||||
index = 0;
|
||||
*CertificateCount = 0;
|
||||
while( offset < size )
|
||||
{
|
||||
/* read the length of the current certificate */
|
||||
count = SetFilePointer( FileHandle, sd_VirtualAddr + offset,
|
||||
count = SetFilePointer( handle, sd_VirtualAddr + offset,
|
||||
NULL, FILE_BEGIN );
|
||||
if( count == INVALID_SET_FILE_POINTER )
|
||||
return FALSE;
|
||||
r = ReadFile( FileHandle, &hdr, (DWORD)cert_hdr_size, &count, NULL );
|
||||
r = ReadFile( handle, &hdr, cert_hdr_size, &count, NULL );
|
||||
if( !r )
|
||||
return FALSE;
|
||||
if( count != cert_hdr_size )
|
||||
return FALSE;
|
||||
|
||||
TRACE("Size = %08lx id = %08hx\n",
|
||||
TRACE("Size = %08x id = %08hx\n",
|
||||
hdr.dwLength, hdr.wCertificateType );
|
||||
|
||||
/* check the certificate is not too big or too small */
|
||||
|
@ -221,15 +523,23 @@ BOOL IMAGEAPI ImageEnumerateCertificates(
|
|||
return FALSE;
|
||||
if( hdr.dwLength > (size-offset) )
|
||||
return FALSE;
|
||||
|
||||
|
||||
if( (TypeFilter == CERT_SECTION_TYPE_ANY) ||
|
||||
(TypeFilter == hdr.wCertificateType) )
|
||||
{
|
||||
(*CertificateCount)++;
|
||||
if(Indices && *CertificateCount <= IndexCount)
|
||||
*Indices++ = index;
|
||||
}
|
||||
|
||||
/* next certificate */
|
||||
offset += hdr.dwLength;
|
||||
|
||||
/* padded out to the nearest 8-byte boundary */
|
||||
if (hdr.dwLength % 8)
|
||||
offset += 8 - (hdr.dwLength % 8);
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
@ -240,23 +550,23 @@ BOOL IMAGEAPI ImageEnumerateCertificates(
|
|||
*
|
||||
* FIXME: not sure that I'm dealing with the Index the right way
|
||||
*/
|
||||
BOOL IMAGEAPI ImageGetCertificateData(
|
||||
BOOL WINAPI ImageGetCertificateData(
|
||||
HANDLE handle, DWORD Index,
|
||||
LPWIN_CERTIFICATE Certificate, PDWORD RequiredLength)
|
||||
{
|
||||
DWORD r, offset, ofs, size, count;
|
||||
|
||||
TRACE("%p %ld %p %p\n", handle, Index, Certificate, RequiredLength);
|
||||
TRACE("%p %d %p %p\n", handle, Index, Certificate, RequiredLength);
|
||||
|
||||
if( !RequiredLength)
|
||||
{
|
||||
SetLastError( ERROR_INVALID_PARAMETER );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if( !IMAGEHLP_GetCertificateOffset( handle, Index, &ofs, &size ) )
|
||||
return FALSE;
|
||||
|
||||
if( !Certificate )
|
||||
{
|
||||
*RequiredLength = size;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if( *RequiredLength < size )
|
||||
{
|
||||
*RequiredLength = size;
|
||||
|
@ -264,6 +574,12 @@ BOOL IMAGEAPI ImageGetCertificateData(
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
if( !Certificate )
|
||||
{
|
||||
SetLastError( ERROR_INVALID_PARAMETER );
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
*RequiredLength = size;
|
||||
|
||||
offset = SetFilePointer( handle, ofs, NULL, FILE_BEGIN );
|
||||
|
@ -277,6 +593,7 @@ BOOL IMAGEAPI ImageGetCertificateData(
|
|||
return FALSE;
|
||||
|
||||
TRACE("OK\n");
|
||||
SetLastError( NO_ERROR );
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -284,26 +601,25 @@ BOOL IMAGEAPI ImageGetCertificateData(
|
|||
/***********************************************************************
|
||||
* ImageGetCertificateHeader (IMAGEHLP.@)
|
||||
*/
|
||||
BOOL IMAGEAPI ImageGetCertificateHeader(
|
||||
HANDLE FileHandle, DWORD CertificateIndex, LPWIN_CERTIFICATE Certificateheader)
|
||||
BOOL WINAPI ImageGetCertificateHeader(
|
||||
HANDLE handle, DWORD index, LPWIN_CERTIFICATE pCert)
|
||||
{
|
||||
DWORD r, offset, ofs, size, count;
|
||||
const size_t cert_hdr_size = sizeof *Certificateheader -
|
||||
sizeof Certificateheader->bCertificate;
|
||||
const size_t cert_hdr_size = sizeof *pCert - sizeof pCert->bCertificate;
|
||||
|
||||
TRACE("%p %ld %p\n", FileHandle, CertificateIndex, Certificateheader);
|
||||
TRACE("%p %d %p\n", handle, index, pCert);
|
||||
|
||||
if( !IMAGEHLP_GetCertificateOffset( FileHandle, CertificateIndex, &ofs, &size ) )
|
||||
if( !IMAGEHLP_GetCertificateOffset( handle, index, &ofs, &size ) )
|
||||
return FALSE;
|
||||
|
||||
if( size < cert_hdr_size )
|
||||
return FALSE;
|
||||
|
||||
offset = SetFilePointer( FileHandle, ofs, NULL, FILE_BEGIN );
|
||||
offset = SetFilePointer( handle, ofs, NULL, FILE_BEGIN );
|
||||
if( offset == INVALID_SET_FILE_POINTER )
|
||||
return FALSE;
|
||||
|
||||
r = ReadFile( FileHandle, Certificateheader, (DWORD)cert_hdr_size, &count, NULL );
|
||||
r = ReadFile( handle, pCert, cert_hdr_size, &count, NULL );
|
||||
if( !r )
|
||||
return FALSE;
|
||||
if( count != cert_hdr_size )
|
||||
|
@ -317,11 +633,11 @@ BOOL IMAGEAPI ImageGetCertificateHeader(
|
|||
/***********************************************************************
|
||||
* ImageGetDigestStream (IMAGEHLP.@)
|
||||
*/
|
||||
BOOL IMAGEAPI ImageGetDigestStream(
|
||||
BOOL WINAPI ImageGetDigestStream(
|
||||
HANDLE FileHandle, DWORD DigestLevel,
|
||||
DIGEST_FUNCTION DigestFunction, DIGEST_HANDLE DigestHandle)
|
||||
{
|
||||
FIXME("(%p, %ld, %p, %p): stub\n",
|
||||
FIXME("(%p, %d, %p, %p): stub\n",
|
||||
FileHandle, DigestLevel, DigestFunction, DigestHandle
|
||||
);
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
||||
|
@ -331,62 +647,86 @@ BOOL IMAGEAPI ImageGetDigestStream(
|
|||
/***********************************************************************
|
||||
* ImageRemoveCertificate (IMAGEHLP.@)
|
||||
*/
|
||||
BOOL IMAGEAPI ImageRemoveCertificate(HANDLE FileHandle, DWORD Index)
|
||||
BOOL WINAPI ImageRemoveCertificate(HANDLE FileHandle, DWORD Index)
|
||||
{
|
||||
FIXME("(%p, %ld): stub\n", FileHandle, Index);
|
||||
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @implemented
|
||||
*/
|
||||
PIMAGE_NT_HEADERS
|
||||
IMAGEAPI
|
||||
CheckSumMappedFile(LPVOID BaseAddress,
|
||||
DWORD FileLength,
|
||||
LPDWORD HeaderSum,
|
||||
LPDWORD CheckSum)
|
||||
{
|
||||
PIMAGE_NT_HEADERS Header;
|
||||
DWORD CalcSum;
|
||||
DWORD HdrSum;
|
||||
TRACE("stub\n");
|
||||
|
||||
CalcSum = (DWORD)CalcCheckSum(0,
|
||||
BaseAddress,
|
||||
(FileLength + 1) / sizeof(WORD));
|
||||
|
||||
Header = ImageNtHeader(BaseAddress);
|
||||
HdrSum = Header->OptionalHeader.CheckSum;
|
||||
|
||||
/* Subtract image checksum from calculated checksum. */
|
||||
/* fix low word of checksum */
|
||||
if (LOWORD(CalcSum) >= LOWORD(HdrSum))
|
||||
{
|
||||
CalcSum -= LOWORD(HdrSum);
|
||||
}
|
||||
else
|
||||
{
|
||||
CalcSum = ((LOWORD(CalcSum) - LOWORD(HdrSum)) & 0xFFFF) - 1;
|
||||
}
|
||||
|
||||
/* fix high word of checksum */
|
||||
if (LOWORD(CalcSum) >= HIWORD(HdrSum))
|
||||
{
|
||||
CalcSum -= HIWORD(HdrSum);
|
||||
}
|
||||
else
|
||||
{
|
||||
CalcSum = ((LOWORD(CalcSum) - HIWORD(HdrSum)) & 0xFFFF) - 1;
|
||||
}
|
||||
|
||||
/* add file length */
|
||||
CalcSum += FileLength;
|
||||
|
||||
*CheckSum = CalcSum;
|
||||
*HeaderSum = Header->OptionalHeader.CheckSum;
|
||||
|
||||
return Header;
|
||||
DWORD size = 0, count = 0, sd_VirtualAddr = 0, offset = 0;
|
||||
DWORD data_size = 0, cert_size = 0, cert_size_padded = 0, ret = 0;
|
||||
LPVOID cert_data;
|
||||
BOOL r;
|
||||
|
||||
TRACE("(%p, %d)\n", FileHandle, Index);
|
||||
|
||||
r = ImageEnumerateCertificates(FileHandle, CERT_SECTION_TYPE_ANY, &count, NULL, 0);
|
||||
|
||||
if ((!r) || (count == 0))
|
||||
return FALSE;
|
||||
|
||||
if ((!IMAGEHLP_GetSecurityDirOffset(FileHandle, &sd_VirtualAddr, &size)) ||
|
||||
(!IMAGEHLP_GetCertificateOffset(FileHandle, Index, &offset, &cert_size)))
|
||||
return FALSE;
|
||||
|
||||
/* Ignore any padding we have, too */
|
||||
if (cert_size % 8)
|
||||
cert_size_padded = cert_size + (8 - (cert_size % 8));
|
||||
else
|
||||
cert_size_padded = cert_size;
|
||||
|
||||
data_size = size - (offset - sd_VirtualAddr) - cert_size_padded;
|
||||
|
||||
if (data_size == 0)
|
||||
{
|
||||
ret = SetFilePointer(FileHandle, sd_VirtualAddr, NULL, FILE_BEGIN);
|
||||
|
||||
if (ret == INVALID_SET_FILE_POINTER)
|
||||
return FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
cert_data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, data_size);
|
||||
|
||||
if (!cert_data)
|
||||
return FALSE;
|
||||
|
||||
ret = SetFilePointer(FileHandle, offset + cert_size_padded, NULL, FILE_BEGIN);
|
||||
|
||||
if (ret == INVALID_SET_FILE_POINTER)
|
||||
goto error;
|
||||
|
||||
/* Read any subsequent certificates */
|
||||
r = ReadFile(FileHandle, cert_data, data_size, &count, NULL);
|
||||
|
||||
if ((!r) || (count != data_size))
|
||||
goto error;
|
||||
|
||||
SetFilePointer(FileHandle, offset, NULL, FILE_BEGIN);
|
||||
|
||||
/* Write them one index back */
|
||||
r = WriteFile(FileHandle, cert_data, data_size, &count, NULL);
|
||||
|
||||
if ((!r) || (count != data_size))
|
||||
goto error;
|
||||
|
||||
HeapFree(GetProcessHeap(), 0, cert_data);
|
||||
}
|
||||
|
||||
/* If security directory is at end of file, trim the file */
|
||||
if (GetFileSize(FileHandle, NULL) == sd_VirtualAddr + size)
|
||||
SetEndOfFile(FileHandle);
|
||||
|
||||
if (count == 1)
|
||||
r = IMAGEHLP_SetSecurityDirOffset(FileHandle, 0, 0);
|
||||
else
|
||||
r = IMAGEHLP_SetSecurityDirOffset(FileHandle, sd_VirtualAddr, size - cert_size_padded);
|
||||
|
||||
if (!r)
|
||||
return FALSE;
|
||||
|
||||
if (!IMAGEHLP_RecalculateChecksum(FileHandle))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
|
||||
error:
|
||||
HeapFree(GetProcessHeap(), 0, cert_data);
|
||||
return FALSE;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1367,6 +1367,18 @@ typedef enum {
|
|||
#define IMAGE_FILE_MACHINE_TRICORE 0x0520
|
||||
#define IMAGE_FILE_MACHINE_CEF 0x0CEF
|
||||
|
||||
#define IMAGE_FILE_EXPORT_DIRECTORY 0
|
||||
#define IMAGE_FILE_IMPORT_DIRECTORY 1
|
||||
#define IMAGE_FILE_RESOURCE_DIRECTORY 2
|
||||
#define IMAGE_FILE_EXCEPTION_DIRECTORY 3
|
||||
#define IMAGE_FILE_SECURITY_DIRECTORY 4
|
||||
#define IMAGE_FILE_BASE_RELOCATION_TABLE 5
|
||||
#define IMAGE_FILE_DEBUG_DIRECTORY 6
|
||||
#define IMAGE_FILE_DESCRIPTION_STRING 7
|
||||
#define IMAGE_FILE_MACHINE_VALUE 8 /* Mips */
|
||||
#define IMAGE_FILE_THREAD_LOCAL_STORAGE 9
|
||||
#define IMAGE_FILE_CALLBACK_DIRECTORY 10
|
||||
|
||||
#define IMAGE_DOS_SIGNATURE 0x5A4D
|
||||
#define IMAGE_OS2_SIGNATURE 0x454E
|
||||
#define IMAGE_OS2_SIGNATURE_LE 0x454C
|
||||
|
|
|
@ -48,17 +48,17 @@ reactos/dll/win32/browseui # Out of sync
|
|||
reactos/dll/win32/cabinet # Autosync
|
||||
reactos/dll/win32/clusapi # Autosync
|
||||
reactos/dll/win32/comcat # Autosync
|
||||
reactos/dll/win32/comctl32 # Autosync ??
|
||||
reactos/dll/win32/comctl32 # Autosync
|
||||
reactos/dll/win32/comdlg32 # Autosync
|
||||
reactos/dll/win32/compstui # Autosync
|
||||
reactos/dll/win32/credui # Autosync
|
||||
reactos/dll/win32/crypt32 # Synced to Wine-1_1_43
|
||||
reactos/dll/win32/crypt32 # Autosync
|
||||
reactos/dll/win32/cryptdlg # Autosync
|
||||
reactos/dll/win32/cryptdll # Autosync
|
||||
reactos/dll/win32/cryptnet # Autosync
|
||||
reactos/dll/win32/cryptui # Autosync
|
||||
reactos/dll/win32/dbghelp # Synced to Wine-20080802
|
||||
reactos/dll/win32/dciman32 # Synced to Wine-1_1_43
|
||||
reactos/dll/win32/dbghelp # Autosync
|
||||
reactos/dll/win32/dciman32 # Autosync
|
||||
reactos/dll/win32/dwmapi # Autosync
|
||||
reactos/dll/win32/fusion # Autosync
|
||||
reactos/dll/win32/gdiplus # Autosync
|
||||
|
@ -70,7 +70,7 @@ reactos/dll/win32/iccvid # Autosync
|
|||
reactos/dll/win32/icmp # Synced to Wine-0_9_10
|
||||
reactos/dll/win32/imaadp32.acm # Autosync
|
||||
reactos/dll/win32/imm32 # Autosync
|
||||
reactos/dll/win32/imagehlp # Patches for BindImage need review and submission to winehq.
|
||||
reactos/dll/win32/imagehlp # Autosync
|
||||
reactos/dll/win32/inetcomm # Autosync
|
||||
reactos/dll/win32/inetmib1 # Autosync
|
||||
reactos/dll/win32/initpki # Autosync
|
||||
|
@ -90,7 +90,7 @@ reactos/dll/win32/mciseq # Autosync
|
|||
reactos/dll/win32/mciwave # Autosync
|
||||
reactos/dll/win32/mlang # Autosync
|
||||
reactos/dll/win32/mpr # Autosync
|
||||
reactos/dll/win32/msacm32 # Out of sync
|
||||
reactos/dll/win32/msacm32 # Autosync
|
||||
reactos/dll/win32/msadp32.acm # Autosync
|
||||
reactos/dll/win32/mscat32 # Autosync
|
||||
reactos/dll/win32/mscms # Autosync
|
||||
|
@ -113,7 +113,7 @@ reactos/dll/win32/mstask # Autosync
|
|||
reactos/dll/win32/msvcrt20 # Autosync
|
||||
reactos/dll/win32/msvfw32 # Autosync
|
||||
reactos/dll/win32/msvidc32 # Autosync
|
||||
reactos/dll/win32/msxml3 # Synced to Wine-1_1_43
|
||||
reactos/dll/win32/msxml3 # Autosync
|
||||
reactos/dll/win32/nddeapi # Autosync
|
||||
reactos/dll/win32/netapi32 # Autosync
|
||||
reactos/dll/win32/ntdsapi # Autosync
|
||||
|
@ -143,13 +143,13 @@ reactos/dll/win32/rpcrt4 # Synced to Wine-0_9_55
|
|||
reactos/dll/win32/rsabase # Autosync
|
||||
reactos/dll/win32/rsaenh # Autosync
|
||||
reactos/dll/win32/sccbase # Autosync
|
||||
reactos/dll/win32/schannel # Autosync ??
|
||||
reactos/dll/win32/schannel # Autosync
|
||||
reactos/dll/win32/secur32 # Forked
|
||||
reactos/dll/win32/security # Forked (different .spec)
|
||||
reactos/dll/win32/sensapi # Autosync
|
||||
reactos/dll/win32/setupapi # Forked at Wine-20050524
|
||||
reactos/dll/win32/shell32 # Forked at Wine-20071011
|
||||
reactos/dll/win32/shdocvw # Synced to Wine-1_1_40
|
||||
reactos/dll/win32/shdocvw # Autosync
|
||||
reactos/dll/win32/shfolder # Autosync
|
||||
reactos/dll/win32/shlwapi # Autosync
|
||||
reactos/dll/win32/slbcsp # Autosync
|
||||
|
@ -166,11 +166,11 @@ reactos/dll/win32/url # Autosync
|
|||
reactos/dll/win32/urlmon # Autosync
|
||||
reactos/dll/win32/usp10 # Autosync
|
||||
reactos/dll/win32/uxtheme # Autosync
|
||||
reactos/dll/win32/version # Autosync ??
|
||||
reactos/dll/win32/version # Autosync
|
||||
reactos/dll/win32/windowscodecs # Autosync
|
||||
reactos/dll/win32/winemp3.acm # Autosync ??
|
||||
reactos/dll/win32/wininet # Autosync ??
|
||||
reactos/dll/win32/winhttp # Autosync ??
|
||||
reactos/dll/win32/winemp3.acm # Autosync
|
||||
reactos/dll/win32/wininet # Autosync
|
||||
reactos/dll/win32/winhttp # Autosync
|
||||
reactos/dll/win32/winmm # Forked at Wine-20050628
|
||||
reactos/dll/win32/winmm/midimap # Forked at Wine-20050628
|
||||
reactos/dll/win32/winmm/wavemap # Forked at Wine-20050628
|
||||
|
|
Loading…
Reference in a new issue