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:
Daniel Reimer 2010-07-26 22:33:59 +00:00
parent e3b6d0cea7
commit 7d17455cc4
25 changed files with 2775 additions and 1953 deletions

View file

@ -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,
};

View file

@ -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,
};

View file

@ -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,
};

View file

@ -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);
}

View file

@ -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

View file

@ -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>

View 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)

View file

@ -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

View file

@ -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

View file

@ -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;

View file

@ -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;
}

View file

@ -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);
}

View file

@ -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)
{

View file

@ -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;

View file

@ -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.@)
*/

View file

@ -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:

View file

@ -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;
}

View file

@ -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>

View 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)

View file

@ -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));
}

View file

@ -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

View file

@ -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

View file

@ -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