[DBGHELP]

sync dbghelp with wine 1.1.40

svn path=/trunk/; revision=46212
This commit is contained in:
Christoph von Wittich 2010-03-15 17:58:48 +00:00
parent 48cc443d59
commit 920b13160c
27 changed files with 4128 additions and 1479 deletions

View file

@ -108,12 +108,18 @@ static int coff_add_file(struct CoffFileSet* coff_files, struct module* module,
if (coff_files->nfiles + 1 >= coff_files->nfiles_alloc)
{
coff_files->nfiles_alloc += 10;
coff_files->files = (coff_files->files) ?
HeapReAlloc(GetProcessHeap(), 0, coff_files->files,
coff_files->nfiles_alloc * sizeof(struct CoffFile)) :
HeapAlloc(GetProcessHeap(), 0,
coff_files->nfiles_alloc * sizeof(struct CoffFile));
if (coff_files->files)
{
coff_files->nfiles_alloc *= 2;
coff_files->files = HeapReAlloc(GetProcessHeap(), 0, coff_files->files,
coff_files->nfiles_alloc * sizeof(struct CoffFile));
}
else
{
coff_files->nfiles_alloc = 16;
coff_files->files = HeapAlloc(GetProcessHeap(), 0,
coff_files->nfiles_alloc * sizeof(struct CoffFile));
}
}
file = coff_files->files + coff_files->nfiles;
file->startaddr = 0xffffffff;
@ -132,7 +138,7 @@ static void coff_add_symbol(struct CoffFile* coff_file, struct symt* sym)
{
if (coff_file->neps + 1 >= coff_file->neps_alloc)
{
coff_file->neps_alloc += 10;
coff_file->neps_alloc *= 2;
coff_file->entries = (coff_file->entries) ?
HeapReAlloc(GetProcessHeap(), 0, coff_file->entries,
coff_file->neps_alloc * sizeof(struct symt*)) :
@ -389,6 +395,7 @@ BOOL coff_process_info(const struct msc_debug_info* msc_dbg)
{
if (coff_files.files[j].entries != NULL)
{
symt_cmp_addr_module = msc_dbg->module;
qsort(coff_files.files[j].entries, coff_files.files[j].neps,
sizeof(struct symt*), symt_cmp_addr);
}
@ -413,7 +420,7 @@ BOOL coff_process_info(const struct msc_debug_info* msc_dbg)
for (;;)
{
if (l+1 >= coff_files.files[j].neps) break;
symt_get_info(coff_files.files[j].entries[l+1], TI_GET_ADDRESS, &addr);
symt_get_info(msc_dbg->module, coff_files.files[j].entries[l+1], TI_GET_ADDRESS, &addr);
if (((msc_dbg->module->module.BaseOfImage + linepnt->Type.VirtualAddress) < addr))
break;
l++;
@ -426,7 +433,7 @@ BOOL coff_process_info(const struct msc_debug_info* msc_dbg)
* start of the function, so we need to subtract that offset
* first.
*/
symt_get_info(coff_files.files[j].entries[l+1], TI_GET_ADDRESS, &addr);
symt_get_info(msc_dbg->module, coff_files.files[j].entries[l+1], TI_GET_ADDRESS, &addr);
symt_add_func_line(msc_dbg->module, (struct symt_function*)coff_files.files[j].entries[l+1],
coff_files.files[j].compiland->source, linepnt->Linenumber,
msc_dbg->module->module.BaseOfImage + linepnt->Type.VirtualAddress - addr);

View file

@ -0,0 +1,412 @@
/*
* File cpu_i386.c
*
* Copyright (C) 2009-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
* 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 <assert.h>
#include "ntstatus.h"
#define WIN32_NO_STATUS
#include "dbghelp_private.h"
#include "wine/winbase16.h"
#include "winternl.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
#define STEP_FLAG 0x00000100 /* single step flag */
#define V86_FLAG 0x00020000
#define IS_VM86_MODE(ctx) (ctx->EFlags & V86_FLAG)
#ifdef __i386__
static ADDRESS_MODE get_selector_type(HANDLE hThread, const CONTEXT* ctx, WORD sel)
{
LDT_ENTRY le;
if (IS_VM86_MODE(ctx)) return AddrModeReal;
/* null or system selector */
if (!(sel & 4) || ((sel >> 3) < 17)) return AddrModeFlat;
if (hThread && GetThreadSelectorEntry(hThread, sel, &le))
return le.HighWord.Bits.Default_Big ? AddrMode1632 : AddrMode1616;
/* selector doesn't exist */
return -1;
}
static unsigned i386_build_addr(HANDLE hThread, const CONTEXT* ctx, ADDRESS64* addr,
unsigned seg, unsigned long offset)
{
addr->Mode = AddrModeFlat;
addr->Segment = seg;
addr->Offset = offset;
if (seg)
{
switch (addr->Mode = get_selector_type(hThread, ctx, seg))
{
case AddrModeReal:
case AddrMode1616:
addr->Offset &= 0xffff;
break;
case AddrModeFlat:
case AddrMode1632:
break;
default:
return FALSE;
}
}
return TRUE;
}
#endif
static unsigned i386_get_addr(HANDLE hThread, const CONTEXT* ctx,
enum cpu_addr ca, ADDRESS64* addr)
{
#ifdef __i386__
switch (ca)
{
case cpu_addr_pc: return i386_build_addr(hThread, ctx, addr, ctx->SegCs, ctx->Eip);
case cpu_addr_stack: return i386_build_addr(hThread, ctx, addr, ctx->SegSs, ctx->Esp);
case cpu_addr_frame: return i386_build_addr(hThread, ctx, addr, ctx->SegSs, ctx->Ebp);
}
#endif
return FALSE;
}
enum st_mode {stm_start, stm_32bit, stm_16bit, stm_done};
/* indexes in Reserved array */
#define __CurrentMode 0
#define __CurrentSwitch 1
#define __NextSwitch 2
#define curr_mode (frame->Reserved[__CurrentMode])
#define curr_switch (frame->Reserved[__CurrentSwitch])
#define next_switch (frame->Reserved[__NextSwitch])
static BOOL i386_stack_walk(struct cpu_stack_walk* csw, LPSTACKFRAME64 frame)
{
STACK32FRAME frame32;
STACK16FRAME frame16;
char ch;
ADDRESS64 tmp;
DWORD p;
WORD val;
BOOL do_switch;
/* sanity check */
if (curr_mode >= stm_done) return FALSE;
TRACE("Enter: PC=%s Frame=%s Return=%s Stack=%s Mode=%s cSwitch=%p nSwitch=%p\n",
wine_dbgstr_addr(&frame->AddrPC),
wine_dbgstr_addr(&frame->AddrFrame),
wine_dbgstr_addr(&frame->AddrReturn),
wine_dbgstr_addr(&frame->AddrStack),
curr_mode == stm_start ? "start" : (curr_mode == stm_16bit ? "16bit" : "32bit"),
(void*)(DWORD_PTR)curr_switch, (void*)(DWORD_PTR)next_switch);
if (curr_mode == stm_start)
{
THREAD_BASIC_INFORMATION info;
if ((frame->AddrPC.Mode == AddrModeFlat) &&
(frame->AddrFrame.Mode != AddrModeFlat))
{
WARN("Bad AddrPC.Mode / AddrFrame.Mode combination\n");
goto done_err;
}
/* Init done */
curr_mode = (frame->AddrPC.Mode == AddrModeFlat) ? stm_32bit : stm_16bit;
/* cur_switch holds address of WOW32Reserved field in TEB in debuggee
* address space
*/
if (NtQueryInformationThread(csw->hThread, ThreadBasicInformation, &info,
sizeof(info), NULL) == STATUS_SUCCESS)
{
curr_switch = (unsigned long)info.TebBaseAddress + FIELD_OFFSET(TEB, WOW32Reserved);
if (!sw_read_mem(csw, curr_switch, &p, sizeof(p)))
{
WARN("Can't read TEB:WOW32Reserved\n");
goto done_err;
}
next_switch = p;
if (!next_switch) /* no 16-bit stack */
{
curr_switch = 0;
}
else if (curr_mode == stm_16bit)
{
if (!sw_read_mem(csw, next_switch, &frame32, sizeof(frame32)))
{
WARN("Bad stack frame %p\n", (void*)(DWORD_PTR)next_switch);
goto done_err;
}
curr_switch = (DWORD)frame32.frame16;
tmp.Mode = AddrMode1616;
tmp.Segment = SELECTOROF(curr_switch);
tmp.Offset = OFFSETOF(curr_switch);
if (!sw_read_mem(csw, sw_xlat_addr(csw, &tmp), &ch, sizeof(ch)))
curr_switch = 0xFFFFFFFF;
}
else
{
tmp.Mode = AddrMode1616;
tmp.Segment = SELECTOROF(next_switch);
tmp.Offset = OFFSETOF(next_switch);
p = sw_xlat_addr(csw, &tmp);
if (!sw_read_mem(csw, p, &frame16, sizeof(frame16)))
{
WARN("Bad stack frame 0x%08x\n", p);
goto done_err;
}
curr_switch = (DWORD_PTR)frame16.frame32;
if (!sw_read_mem(csw, curr_switch, &ch, sizeof(ch)))
curr_switch = 0xFFFFFFFF;
}
}
else
/* FIXME: this will allow to work when we're not attached to a live target,
* but the 16 <=> 32 switch facility won't be available.
*/
curr_switch = 0;
frame->AddrReturn.Mode = frame->AddrStack.Mode = (curr_mode == stm_16bit) ? AddrMode1616 : AddrModeFlat;
/* don't set up AddrStack on first call. Either the caller has set it up, or
* we will get it in the next frame
*/
memset(&frame->AddrBStore, 0, sizeof(frame->AddrBStore));
}
else
{
if (frame->AddrFrame.Offset == 0) goto done_err;
if (frame->AddrFrame.Mode == AddrModeFlat)
{
assert(curr_mode == stm_32bit);
do_switch = curr_switch && frame->AddrFrame.Offset >= curr_switch;
}
else
{
assert(curr_mode == stm_16bit);
do_switch = curr_switch &&
frame->AddrFrame.Segment == SELECTOROF(curr_switch) &&
frame->AddrFrame.Offset >= OFFSETOF(curr_switch);
}
if (do_switch)
{
if (curr_mode == stm_16bit)
{
if (!sw_read_mem(csw, next_switch, &frame32, sizeof(frame32)))
{
WARN("Bad stack frame %p\n", (void*)(DWORD_PTR)next_switch);
goto done_err;
}
frame->AddrPC.Mode = AddrModeFlat;
frame->AddrPC.Segment = 0;
frame->AddrPC.Offset = frame32.retaddr;
frame->AddrFrame.Mode = AddrModeFlat;
frame->AddrFrame.Segment = 0;
frame->AddrFrame.Offset = frame32.ebp;
frame->AddrStack.Mode = AddrModeFlat;
frame->AddrStack.Segment = 0;
frame->AddrReturn.Mode = AddrModeFlat;
frame->AddrReturn.Segment = 0;
next_switch = curr_switch;
tmp.Mode = AddrMode1616;
tmp.Segment = SELECTOROF(next_switch);
tmp.Offset = OFFSETOF(next_switch);
p = sw_xlat_addr(csw, &tmp);
if (!sw_read_mem(csw, p, &frame16, sizeof(frame16)))
{
WARN("Bad stack frame 0x%08x\n", p);
goto done_err;
}
curr_switch = (DWORD_PTR)frame16.frame32;
curr_mode = stm_32bit;
if (!sw_read_mem(csw, curr_switch, &ch, sizeof(ch)))
curr_switch = 0;
}
else
{
tmp.Mode = AddrMode1616;
tmp.Segment = SELECTOROF(next_switch);
tmp.Offset = OFFSETOF(next_switch);
p = sw_xlat_addr(csw, &tmp);
if (!sw_read_mem(csw, p, &frame16, sizeof(frame16)))
{
WARN("Bad stack frame 0x%08x\n", p);
goto done_err;
}
TRACE("Got a 16 bit stack switch:"
"\n\tframe32: %08lx"
"\n\tedx:%08x ecx:%08x ebp:%08x"
"\n\tds:%04x es:%04x fs:%04x gs:%04x"
"\n\tcall_from_ip:%08x module_cs:%04x relay=%08x"
"\n\tentry_ip:%04x entry_point:%08x"
"\n\tbp:%04x ip:%04x cs:%04x\n",
(unsigned long)frame16.frame32,
frame16.edx, frame16.ecx, frame16.ebp,
frame16.ds, frame16.es, frame16.fs, frame16.gs,
frame16.callfrom_ip, frame16.module_cs, frame16.relay,
frame16.entry_ip, frame16.entry_point,
frame16.bp, frame16.ip, frame16.cs);
frame->AddrPC.Mode = AddrMode1616;
frame->AddrPC.Segment = frame16.cs;
frame->AddrPC.Offset = frame16.ip;
frame->AddrFrame.Mode = AddrMode1616;
frame->AddrFrame.Segment = SELECTOROF(next_switch);
frame->AddrFrame.Offset = frame16.bp;
frame->AddrStack.Mode = AddrMode1616;
frame->AddrStack.Segment = SELECTOROF(next_switch);
frame->AddrReturn.Mode = AddrMode1616;
frame->AddrReturn.Segment = frame16.cs;
next_switch = curr_switch;
if (!sw_read_mem(csw, next_switch, &frame32, sizeof(frame32)))
{
WARN("Bad stack frame %p\n", (void*)(DWORD_PTR)next_switch);
goto done_err;
}
curr_switch = (DWORD)frame32.frame16;
tmp.Mode = AddrMode1616;
tmp.Segment = SELECTOROF(curr_switch);
tmp.Offset = OFFSETOF(curr_switch);
if (!sw_read_mem(csw, sw_xlat_addr(csw, &tmp), &ch, sizeof(ch)))
curr_switch = 0;
curr_mode = stm_16bit;
}
}
else
{
frame->AddrPC = frame->AddrReturn;
if (curr_mode == stm_16bit)
{
frame->AddrStack.Offset = frame->AddrFrame.Offset + 2 * sizeof(WORD);
/* "pop up" previous BP value */
if (!sw_read_mem(csw, sw_xlat_addr(csw, &frame->AddrFrame),
&val, sizeof(WORD)))
goto done_err;
frame->AddrFrame.Offset = val;
}
else
{
frame->AddrStack.Offset = frame->AddrFrame.Offset + 2 * sizeof(DWORD);
/* "pop up" previous EBP value */
if (!sw_read_mem(csw, frame->AddrFrame.Offset,
&frame->AddrFrame.Offset, sizeof(DWORD)))
goto done_err;
}
}
}
if (curr_mode == stm_16bit)
{
unsigned int i;
p = sw_xlat_addr(csw, &frame->AddrFrame);
if (!sw_read_mem(csw, p + sizeof(WORD), &val, sizeof(WORD)))
goto done_err;
frame->AddrReturn.Offset = val;
/* get potential cs if a far call was used */
if (!sw_read_mem(csw, p + 2 * sizeof(WORD), &val, sizeof(WORD)))
goto done_err;
if (frame->AddrFrame.Offset & 1)
frame->AddrReturn.Segment = val; /* far call assumed */
else
{
/* not explicitly marked as far call,
* but check whether it could be anyway
*/
if ((val & 7) == 7 && val != frame->AddrReturn.Segment)
{
LDT_ENTRY le;
if (GetThreadSelectorEntry(csw->hThread, val, &le) &&
(le.HighWord.Bits.Type & 0x08)) /* code segment */
{
/* it is very uncommon to push a code segment cs as
* a parameter, so this should work in most cases
*/
frame->AddrReturn.Segment = val;
}
}
}
frame->AddrFrame.Offset &= ~1;
/* we "pop" parameters as 16 bit entities... of course, this won't
* work if the parameter is in fact bigger than 16bit, but
* there's no way to know that here
*/
for (i = 0; i < sizeof(frame->Params) / sizeof(frame->Params[0]); i++)
{
sw_read_mem(csw, p + (2 + i) * sizeof(WORD), &val, sizeof(val));
frame->Params[i] = val;
}
}
else
{
if (!sw_read_mem(csw, frame->AddrFrame.Offset + sizeof(DWORD),
&frame->AddrReturn.Offset, sizeof(DWORD)))
{
WARN("Cannot read new frame offset %p\n",
(void*)(DWORD_PTR)(frame->AddrFrame.Offset + (int)sizeof(DWORD)));
goto done_err;
}
sw_read_mem(csw, frame->AddrFrame.Offset + 2 * sizeof(DWORD),
frame->Params, sizeof(frame->Params));
}
frame->Far = TRUE;
frame->Virtual = TRUE;
p = sw_xlat_addr(csw, &frame->AddrPC);
if (p && sw_module_base(csw, p))
frame->FuncTableEntry = sw_table_access(csw, p);
else
frame->FuncTableEntry = NULL;
TRACE("Leave: PC=%s Frame=%s Return=%s Stack=%s Mode=%s cSwitch=%p nSwitch=%p FuncTable=%p\n",
wine_dbgstr_addr(&frame->AddrPC),
wine_dbgstr_addr(&frame->AddrFrame),
wine_dbgstr_addr(&frame->AddrReturn),
wine_dbgstr_addr(&frame->AddrStack),
curr_mode == stm_start ? "start" : (curr_mode == stm_16bit ? "16bit" : "32bit"),
(void*)(DWORD_PTR)curr_switch, (void*)(DWORD_PTR)next_switch, frame->FuncTableEntry);
return TRUE;
done_err:
curr_mode = stm_done;
return FALSE;
}
struct cpu cpu_i386 = {
IMAGE_FILE_MACHINE_I386,
4,
i386_get_addr,
i386_stack_walk,
};

View file

@ -0,0 +1,62 @@
/*
* File cpu_ppc.c
*
* Copyright (C) 2009-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
* 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 <assert.h>
#include "ntstatus.h"
#define WIN32_NO_STATUS
#include "dbghelp_private.h"
#include "winternl.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
static unsigned ppc_get_addr(HANDLE hThread, const CONTEXT* ctx,
enum cpu_addr ca, ADDRESS64* addr)
{
switch (ca)
{
#if defined(__powerpc__)
case cpu_addr_pc:
addr->Mode = AddrModeFlat;
addr->Segment = 0; /* don't need segment */
addr->Offset = ctx->Iar;
return TRUE;
#endif
default:
case cpu_addr_stack:
case cpu_addr_frame:
FIXME("not done\n");
}
return FALSE;
}
static BOOL ppc_stack_walk(struct cpu_stack_walk* csw, LPSTACKFRAME64 frame)
{
FIXME("not done\n");
return FALSE;
}
struct cpu cpu_ppc = {
IMAGE_FILE_MACHINE_POWERPC,
4,
ppc_get_addr,
ppc_stack_walk,
};

View file

@ -0,0 +1,132 @@
/*
* File cpu_x86_64.c
*
* Copyright (C) 2009-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
* 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 <assert.h>
#include "ntstatus.h"
#define WIN32_NO_STATUS
#include "dbghelp_private.h"
#include "winternl.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
static unsigned x86_64_get_addr(HANDLE hThread, const CONTEXT* ctx,
enum cpu_addr ca, ADDRESS64* addr)
{
addr->Mode = AddrModeFlat;
switch (ca)
{
#ifdef __x86_64__
case cpu_addr_pc: addr->Segment = ctx->SegCs; addr->Offset = ctx->Rip; return TRUE;
case cpu_addr_stack: addr->Segment = ctx->SegSs; addr->Offset = ctx->Rsp; return TRUE;
case cpu_addr_frame: addr->Segment = ctx->SegSs; addr->Offset = ctx->Rbp; return TRUE;
#endif
default: addr->Mode = -1;
return FALSE;
}
}
enum st_mode {stm_start, stm_64bit, stm_done};
/* indexes in Reserved array */
#define __CurrentMode 0
#define __CurrentSwitch 1
#define __NextSwitch 2
#define curr_mode (frame->Reserved[__CurrentMode])
#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)
{
/* sanity check */
if (curr_mode >= stm_done) return FALSE;
assert(!csw->is32);
TRACE("Enter: PC=%s Frame=%s Return=%s Stack=%s Mode=%s\n",
wine_dbgstr_addr(&frame->AddrPC),
wine_dbgstr_addr(&frame->AddrFrame),
wine_dbgstr_addr(&frame->AddrReturn),
wine_dbgstr_addr(&frame->AddrStack),
curr_mode == stm_start ? "start" : "64bit");
if (curr_mode == stm_start)
{
if ((frame->AddrPC.Mode == AddrModeFlat) &&
(frame->AddrFrame.Mode != AddrModeFlat))
{
WARN("Bad AddrPC.Mode / AddrFrame.Mode combination\n");
goto done_err;
}
/* Init done */
curr_mode = stm_64bit;
curr_switch = 0;
frame->AddrReturn.Mode = frame->AddrStack.Mode = AddrModeFlat;
/* don't set up AddrStack on first call. Either the caller has set it up, or
* we will get it in the next frame
*/
memset(&frame->AddrBStore, 0, sizeof(frame->AddrBStore));
}
else
{
if (frame->AddrReturn.Offset == 0) goto done_err;
frame->AddrPC = frame->AddrReturn;
}
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->AddrFrame.Offset + sizeof(DWORD64)));
goto done_err;
}
/* FIXME: simplistic stuff... need to handle both dwarf & PE stack information */
frame->AddrStack.Offset += sizeof(DWORD64);
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),
wine_dbgstr_addr(&frame->AddrFrame),
wine_dbgstr_addr(&frame->AddrReturn),
wine_dbgstr_addr(&frame->AddrStack),
curr_mode == stm_start ? "start" : "64bit",
frame->FuncTableEntry);
return TRUE;
done_err:
curr_mode = stm_done;
return FALSE;
}
struct cpu cpu_x86_64 = {
IMAGE_FILE_MACHINE_AMD64,
8,
x86_64_get_addr,
x86_64_stack_walk,
};

View file

@ -0,0 +1,149 @@
/*
* File crc32.c - calculate CRC32 checksum of a file
*
* Copyright (C) 1996, Eric Youngdale.
* 1999-2007 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 "wine/port.h"
#include <stdio.h>
#include "dbghelp_private.h"
/* Copyright (C) 1986 Gary S. Brown. Modified by Robert Shearman. You may use
the following calc_crc32 code or tables extracted from it, as desired without
restriction. */
/**********************************************************************\
|* Demonstration program to compute the 32-bit CRC used as the frame *|
|* check sequence in ADCCP (ANSI X3.66, also known as FIPS PUB 71 *|
|* and FED-STD-1003, the U.S. versions of CCITT's X.25 link-level *|
|* protocol). The 32-bit FCS was added via the Federal Register, *|
|* 1 June 1982, p.23798. I presume but don't know for certain that *|
|* this polynomial is or will be included in CCITT V.41, which *|
|* defines the 16-bit CRC (often called CRC-CCITT) polynomial. FIPS *|
|* PUB 78 says that the 32-bit FCS reduces otherwise undetected *|
|* errors by a factor of 10^-5 over 16-bit FCS. *|
\**********************************************************************/
/* First, the polynomial itself and its table of feedback terms. The */
/* polynomial is */
/* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */
/* Note that we take it "backwards" and put the highest-order term in */
/* the lowest-order bit. The X^32 term is "implied"; the LSB is the */
/* X^31 term, etc. The X^0 term (usually shown as "+1") results in */
/* the MSB being 1. */
/* Note that the usual hardware shift register implementation, which */
/* is what we're using (we're merely optimizing it by doing eight-bit */
/* chunks at a time) shifts bits into the lowest-order term. In our */
/* implementation, that means shifting towards the right. Why do we */
/* do it this way? Because the calculated CRC must be transmitted in */
/* order from highest-order term to lowest-order term. UARTs transmit */
/* characters in order from LSB to MSB. By storing the CRC this way, */
/* we hand it to the UART in the order low-byte to high-byte; the UART */
/* sends each low-bit to hight-bit; and the result is transmission bit */
/* by bit from highest- to lowest-order term without requiring any bit */
/* shuffling on our part. Reception works similarly. */
/* The feedback terms table consists of 256, 32-bit entries. Notes: */
/* */
/* 1. The table can be generated at runtime if desired; code to do so */
/* is shown later. It might not be obvious, but the feedback */
/* terms simply represent the results of eight shift/xor opera- */
/* tions for all combinations of data and CRC register values. */
/* */
/* 2. The CRC accumulation logic is the same for all CRC polynomials, */
/* be they sixteen or thirty-two bits wide. You simply choose the */
/* appropriate table. Alternatively, because the table can be */
/* generated at runtime, you can start by generating the table for */
/* the polynomial in question and use exactly the same "updcrc", */
/* if your application needn't simultaneously handle two CRC */
/* polynomials. (Note, however, that XMODEM is strange.) */
/* */
/* 3. For 16-bit CRCs, the table entries need be only 16 bits wide; */
/* of course, 32-bit entries work OK if the high 16 bits are zero. */
/* */
/* 4. The values must be right-shifted by eight bits by the "updcrc" */
/* logic; the shift must be unsigned (bring in zeroes). On some */
/* hardware you could probably optimize the shift in assembler by */
/* using byte-swap instructions. */
DWORD calc_crc32(int fd)
{
#define UPDC32(octet,crc) (crc_32_tab[((crc) ^ (octet)) & 0xff] ^ ((crc) >> 8))
static const DWORD crc_32_tab[] =
{ /* CRC polynomial 0xedb88320 */
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
int i, r;
unsigned char buffer[8192];
DWORD crc = ~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);
}
return ~crc;
#undef UPDC32
}

View file

@ -106,7 +106,7 @@ struct process* process_find_by_handle(HANDLE hProcess)
*/
BOOL validate_addr64(DWORD64 addr)
{
if (addr >> 32)
if (sizeof(void*) == sizeof(int) && (addr >> 32))
{
FIXME("Unsupported address %s\n", wine_dbgstr_longlong(addr));
SetLastError(ERROR_INVALID_PARAMETER);
@ -133,6 +133,48 @@ void* fetch_buffer(struct process* pcs, unsigned size)
return pcs->buffer;
}
const char* wine_dbgstr_addr(const ADDRESS64* addr)
{
if (!addr) return "(null)";
switch (addr->Mode)
{
case AddrModeFlat:
return wine_dbg_sprintf("flat<%s>", wine_dbgstr_longlong(addr->Offset));
case AddrMode1616:
return wine_dbg_sprintf("1616<%04x:%04x>", addr->Segment, (DWORD)addr->Offset);
case AddrMode1632:
return wine_dbg_sprintf("1632<%04x:%08x>", addr->Segment, (DWORD)addr->Offset);
case AddrModeReal:
return wine_dbg_sprintf("real<%04x:%04x>", addr->Segment, (DWORD)addr->Offset);
default:
return "unknown";
}
}
extern struct cpu cpu_i386, cpu_x86_64;
static struct cpu* dbghelp_cpus[] = {&cpu_i386, &cpu_x86_64, NULL};
struct cpu* dbghelp_current_cpu =
#if defined(__i386__)
&cpu_i386
#elif defined(__x86_64__)
&cpu_x86_64
#else
#error define support for your CPU
#endif
;
struct cpu* cpu_find(DWORD machine)
{
struct cpu** cpu;
for (cpu = dbghelp_cpus ; *cpu; cpu++)
{
if (cpu[0]->machine == machine) return cpu[0];
}
return NULL;
}
/******************************************************************
* SymSetSearchPathW (DBGHELP.@)
*
@ -211,16 +253,16 @@ BOOL WINAPI SymGetSearchPath(HANDLE hProcess, PSTR szSearchPath,
* SymInitialize helper: loads in dbghelp all known (and loaded modules)
* this assumes that hProcess is a handle on a valid process
*/
static BOOL WINAPI process_invade_cb(PCSTR name, ULONG base, ULONG size, PVOID user)
static BOOL WINAPI process_invade_cb(PCWSTR name, ULONG64 base, ULONG size, PVOID user)
{
char tmp[MAX_PATH];
WCHAR tmp[MAX_PATH];
HANDLE hProcess = user;
if (!GetModuleFileNameExA(hProcess, (HMODULE)base,
tmp, sizeof(tmp)))
lstrcpynA(tmp, name, sizeof(tmp));
if (!GetModuleFileNameExW(hProcess, (HMODULE)(DWORD_PTR)base,
tmp, sizeof(tmp) / sizeof(WCHAR)))
lstrcpynW(tmp, name, sizeof(tmp) / sizeof(WCHAR));
SymLoadModule(hProcess, 0, tmp, name, base, size);
SymLoadModuleExW(hProcess, 0, tmp, name, base, size, NULL, 0);
return TRUE;
}
@ -232,7 +274,8 @@ static BOOL check_live_target(struct process* pcs)
{
if (!GetProcessId(pcs->handle)) return FALSE;
if (GetEnvironmentVariableA("DBGHELP_NOLIVE", NULL, 0)) return FALSE;
elf_read_wine_loader_dbg_info(pcs);
if (!elf_read_wine_loader_dbg_info(pcs))
macho_read_wine_loader_dbg_info(pcs);
return TRUE;
}
@ -325,8 +368,9 @@ BOOL WINAPI SymInitializeW(HANDLE hProcess, PCWSTR UserSearchPath, BOOL fInvadeP
if (check_live_target(pcs))
{
if (fInvadeProcess)
EnumerateLoadedModules(hProcess, process_invade_cb, hProcess);
EnumerateLoadedModulesW64(hProcess, process_invade_cb, hProcess);
elf_synchronize_module_list(pcs);
macho_synchronize_module_list(pcs);
}
else if (fInvadeProcess)
{
@ -459,25 +503,25 @@ BOOL WINAPI SymSetContext(HANDLE hProcess, PIMAGEHLP_STACK_FRAME StackFrame,
*/
static BOOL CALLBACK reg_cb64to32(HANDLE hProcess, ULONG action, ULONG64 data, ULONG64 user)
{
PSYMBOL_REGISTERED_CALLBACK cb32 = (PSYMBOL_REGISTERED_CALLBACK)(DWORD)(user >> 32);
DWORD user32 = (DWORD)user;
struct process* pcs = process_find_by_handle(hProcess);
void* data32;
IMAGEHLP_DEFERRED_SYMBOL_LOAD64* idsl64;
IMAGEHLP_DEFERRED_SYMBOL_LOAD idsl;
if (!pcs) return FALSE;
switch (action)
{
case CBA_DEBUG_INFO:
case CBA_DEFERRED_SYMBOL_LOAD_CANCEL:
case CBA_SET_OPTIONS:
case CBA_SYMBOLS_UNLOADED:
data32 = (void*)(DWORD)data;
data32 = (void*)(DWORD_PTR)data;
break;
case CBA_DEFERRED_SYMBOL_LOAD_COMPLETE:
case CBA_DEFERRED_SYMBOL_LOAD_FAILURE:
case CBA_DEFERRED_SYMBOL_LOAD_PARTIAL:
case CBA_DEFERRED_SYMBOL_LOAD_START:
idsl64 = (IMAGEHLP_DEFERRED_SYMBOL_LOAD64*)(DWORD)data;
idsl64 = (IMAGEHLP_DEFERRED_SYMBOL_LOAD64*)(DWORD_PTR)data;
if (!validate_addr64(idsl64->BaseOfImage))
return FALSE;
idsl.SizeOfStruct = sizeof(idsl);
@ -495,7 +539,7 @@ static BOOL CALLBACK reg_cb64to32(HANDLE hProcess, ULONG action, ULONG64 data, U
FIXME("No mapping for action %u\n", action);
return FALSE;
}
return cb32(hProcess, action, data32, (PVOID)user32);
return pcs->reg_cb32(hProcess, action, data32, (PVOID)(DWORD_PTR)user);
}
/******************************************************************
@ -522,7 +566,7 @@ BOOL pcs_callback(const struct process* pcs, ULONG action, void* data)
case CBA_DEFERRED_SYMBOL_LOAD_FAILURE:
case CBA_DEFERRED_SYMBOL_LOAD_PARTIAL:
case CBA_DEFERRED_SYMBOL_LOAD_START:
idslW = (IMAGEHLP_DEFERRED_SYMBOL_LOADW64*)(DWORD)data;
idslW = data;
idsl.SizeOfStruct = sizeof(idsl);
idsl.BaseOfImage = idslW->BaseOfImage;
idsl.CheckSum = idslW->CheckSum;
@ -548,14 +592,16 @@ BOOL pcs_callback(const struct process* pcs, ULONG action, void* data)
*
* Helper for registering a callback.
*/
static BOOL sym_register_cb(HANDLE hProcess,
static BOOL sym_register_cb(HANDLE hProcess,
PSYMBOL_REGISTERED_CALLBACK64 cb,
PSYMBOL_REGISTERED_CALLBACK cb32,
DWORD64 user, BOOL unicode)
{
struct process* pcs = process_find_by_handle(hProcess);
if (!pcs) return FALSE;
pcs->reg_cb = cb;
pcs->reg_cb32 = cb32;
pcs->reg_is_unicode = unicode;
pcs->reg_user = user;
@ -569,10 +615,9 @@ BOOL WINAPI SymRegisterCallback(HANDLE hProcess,
PSYMBOL_REGISTERED_CALLBACK CallbackFunction,
PVOID UserContext)
{
DWORD64 tmp = ((ULONGLONG)(DWORD)CallbackFunction << 32) | (DWORD)UserContext;
TRACE("(%p, %p, %p)\n",
hProcess, CallbackFunction, UserContext);
return sym_register_cb(hProcess, reg_cb64to32, tmp, FALSE);
return sym_register_cb(hProcess, reg_cb64to32, CallbackFunction, (DWORD_PTR)UserContext, FALSE);
}
/***********************************************************************
@ -584,7 +629,7 @@ BOOL WINAPI SymRegisterCallback64(HANDLE hProcess,
{
TRACE("(%p, %p, %s)\n",
hProcess, CallbackFunction, wine_dbgstr_longlong(UserContext));
return sym_register_cb(hProcess, CallbackFunction, UserContext, FALSE);
return sym_register_cb(hProcess, CallbackFunction, NULL, UserContext, FALSE);
}
/***********************************************************************
@ -596,7 +641,7 @@ BOOL WINAPI SymRegisterCallbackW64(HANDLE hProcess,
{
TRACE("(%p, %p, %s)\n",
hProcess, CallbackFunction, wine_dbgstr_longlong(UserContext));
return sym_register_cb(hProcess, CallbackFunction, UserContext, TRUE);
return sym_register_cb(hProcess, CallbackFunction, NULL, UserContext, TRUE);
}
/* This is imagehlp version not dbghelp !! */

View file

@ -9,10 +9,15 @@
<define name="_WINE" />
<define name="HAVE_REGEX_H" />
<file>coff.c</file>
<file>cpu_i386.c</file>
<file>cpu_ppc.c</file>
<file>cpu_x86_64.c</file>
<file>crc32.c</file>
<file>dbghelp.c</file>
<file>dwarf.c</file>
<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>
@ -27,6 +32,7 @@
<file>storage.c</file>
<file>symbol.c</file>
<file>type.c</file>
<file>version.rc</file>
<library>wine</library>
<library>psapi</library>
<library>version</library>

View file

@ -29,6 +29,7 @@
#include "objbase.h"
#include "oaidl.h"
#include "winnls.h"
#include "wine/list.h"
#include "wine/unicode.h"
#include "cvconst.h"
@ -37,13 +38,14 @@
struct pool /* poor's man */
{
struct pool_arena* first;
unsigned arena_size;
struct list arena_list;
struct list arena_full;
size_t arena_size;
};
void pool_init(struct pool* a, unsigned arena_size);
void pool_init(struct pool* a, size_t arena_size);
void pool_destroy(struct pool* a);
void* pool_alloc(struct pool* a, unsigned len);
void* pool_alloc(struct pool* a, size_t len);
char* pool_strdup(struct pool* a, const char* str);
struct vector
@ -96,7 +98,6 @@ void hash_table_init(struct pool* pool, struct hash_table* ht,
unsigned num_buckets);
void hash_table_destroy(struct hash_table* ht);
void hash_table_add(struct hash_table* ht, struct hash_table_elt* elt);
unsigned hash_table_hash(const char* name, unsigned num_buckets);
struct hash_table_iter
{
@ -116,7 +117,7 @@ void* hash_table_iter_up(struct hash_table_iter* hti);
extern unsigned dbghelp_options;
/* some more Wine extensions */
#define SYMOPT_WINE_WITH_ELF_MODULES 0x40000000
#define SYMOPT_WINE_WITH_NATIVE_MODULES 0x40000000
enum location_kind {loc_error, /* reg is the error code */
loc_absolute, /* offset is the location */
@ -226,8 +227,6 @@ struct symt_public
struct symt* container; /* compiland */
unsigned long address;
unsigned long size;
unsigned in_code : 1,
is_function : 1;
};
struct symt_thunk
@ -245,7 +244,7 @@ struct symt_array
{
struct symt symt;
int start;
int end;
int end; /* end index if > 0, or -array_len (in bytes) if < 0 */
struct symt* base_type;
struct symt* index_type;
};
@ -308,6 +307,7 @@ enum module_type
DMT_UNKNOWN, /* for lookup, not actually used for a module */
DMT_ELF, /* a real ELF shared module */
DMT_PE, /* a native or builtin PE module */
DMT_MACHO, /* a real Mach-O shared module */
DMT_PDB, /* .PDB file */
DMT_DBG, /* .DBG file */
};
@ -327,12 +327,17 @@ struct module
struct elf_module_info* elf_info;
struct dwarf2_module_info_s*dwarf2_info;
struct macho_module_info* macho_info;
/* memory allocation pool */
struct pool pool;
/* symbols & symbol tables */
struct vector vsymt;
int sortlist_valid;
unsigned num_sorttab; /* number of symbols with addresses */
unsigned num_symbols;
unsigned sorttab_size;
struct symt_ht** addr_sorttab;
struct hash_table ht_symbols;
void (*loc_compute)(struct process* pcs,
@ -355,8 +360,9 @@ struct process
struct process* next;
HANDLE handle;
WCHAR* search_path;
PSYMBOL_REGISTERED_CALLBACK64 reg_cb;
PSYMBOL_REGISTERED_CALLBACK reg_cb32;
BOOL reg_is_unicode;
DWORD64 reg_user;
@ -411,17 +417,62 @@ struct pdb_lookup
} u;
};
struct cpu_stack_walk
{
HANDLE hProcess;
HANDLE hThread;
BOOL is32;
union
{
struct
{
PREAD_PROCESS_MEMORY_ROUTINE f_read_mem;
PTRANSLATE_ADDRESS_ROUTINE f_xlat_adr;
PFUNCTION_TABLE_ACCESS_ROUTINE f_tabl_acs;
PGET_MODULE_BASE_ROUTINE f_modl_bas;
} s32;
struct
{
PREAD_PROCESS_MEMORY_ROUTINE64 f_read_mem;
PTRANSLATE_ADDRESS_ROUTINE64 f_xlat_adr;
PFUNCTION_TABLE_ACCESS_ROUTINE64 f_tabl_acs;
PGET_MODULE_BASE_ROUTINE64 f_modl_bas;
} s64;
} u;
};
enum cpu_addr {cpu_addr_pc, cpu_addr_stack, cpu_addr_frame};
struct cpu
{
DWORD machine;
DWORD word_size;
/* address manipulation */
unsigned (*get_addr)(HANDLE hThread, const CONTEXT* ctx,
enum cpu_addr, ADDRESS64* addr);
/* stack manipulation */
BOOL (*stack_walk)(struct cpu_stack_walk* csw, LPSTACKFRAME64 frame);
};
extern struct cpu* dbghelp_current_cpu;
/* dbghelp.c */
extern struct process* process_find_by_handle(HANDLE hProcess);
extern HANDLE hMsvcrt;
extern BOOL validate_addr64(DWORD64 addr);
extern BOOL pcs_callback(const struct process* pcs, ULONG action, void* data);
extern void* fetch_buffer(struct process* pcs, unsigned size);
extern const char* wine_dbgstr_addr(const ADDRESS64* addr);
extern struct cpu* cpu_find(DWORD);
/* crc32.c */
extern DWORD calc_crc32(int fd);
typedef BOOL (*enum_modules_cb)(const WCHAR*, unsigned long addr, void* user);
/* elf_module.c */
#define ELF_NO_MAP ((const void*)0xffffffff)
typedef BOOL (*elf_enum_modules_cb)(const WCHAR*, unsigned long addr, void* user);
extern BOOL elf_enum_modules(HANDLE hProc, elf_enum_modules_cb, void*);
#define ELF_NO_MAP ((const void*)-1)
extern BOOL elf_enum_modules(HANDLE hProc, enum_modules_cb, void*);
extern BOOL elf_fetch_file_info(const WCHAR* name, DWORD* base, DWORD* size, DWORD* checksum);
struct elf_file_map;
extern BOOL elf_load_debug_info(struct module* module, struct elf_file_map* fmap);
@ -431,21 +482,27 @@ extern BOOL elf_read_wine_loader_dbg_info(struct process* pcs);
extern BOOL elf_synchronize_module_list(struct process* pcs);
struct elf_thunk_area;
extern int elf_is_in_thunk_area(unsigned long addr, const struct elf_thunk_area* thunks);
extern DWORD WINAPI addr_to_linear(HANDLE hProcess, HANDLE hThread, ADDRESS* addr);
/* macho_module.c */
#define MACHO_NO_MAP ((const void*)-1)
extern BOOL macho_enum_modules(HANDLE hProc, enum_modules_cb, void*);
extern BOOL macho_fetch_file_info(const WCHAR* name, DWORD* base, DWORD* size, DWORD* checksum);
struct macho_file_map;
extern BOOL macho_load_debug_info(struct module* module, struct macho_file_map* fmap);
extern struct module*
macho_load_module(struct process* pcs, const WCHAR* name, unsigned long);
extern BOOL macho_read_wine_loader_dbg_info(struct process* pcs);
extern BOOL macho_synchronize_module_list(struct process* pcs);
/* module.c */
extern const WCHAR S_ElfW[];
extern const WCHAR S_WineLoaderW[];
extern const WCHAR S_WinePThreadW[];
extern const WCHAR S_WineKThreadW[];
extern const WCHAR S_WineW[];
extern const WCHAR S_SlashW[];
extern struct module*
module_find_by_addr(const struct process* pcs, unsigned long addr,
enum module_type type);
extern struct module*
module_find_by_name(const struct process* pcs,
const WCHAR* name);
extern struct module*
module_find_by_nameA(const struct process* pcs,
const char* name);
@ -456,11 +513,8 @@ extern BOOL module_get_debug(struct module_pair*);
extern struct module*
module_new(struct process* pcs, const WCHAR* name,
enum module_type type, BOOL virtual,
unsigned long addr, unsigned long size,
DWORD64 addr, DWORD64 size,
unsigned long stamp, unsigned long checksum);
extern struct module*
module_get_container(const struct process* pcs,
const struct module* inner);
extern struct module*
module_get_containee(const struct process* pcs,
const struct module* inner);
@ -485,13 +539,13 @@ extern BOOL path_find_symbol_file(const struct process* pcs, PCSTR full_
BOOL* is_unmatched);
/* pe_module.c */
extern BOOL pe_load_nt_header(HANDLE hProc, DWORD base, IMAGE_NT_HEADERS* nth);
extern BOOL pe_load_nt_header(HANDLE hProc, DWORD64 base, IMAGE_NT_HEADERS* nth);
extern struct module*
pe_load_native_module(struct process* pcs, const WCHAR* name,
HANDLE hFile, DWORD base, DWORD size);
extern struct module*
pe_load_builtin_module(struct process* pcs, const WCHAR* name,
DWORD base, DWORD size);
DWORD64 base, DWORD64 size);
extern BOOL pe_load_debug_info(const struct process* pcs,
struct module* module);
/* source.c */
@ -499,9 +553,14 @@ extern unsigned source_new(struct module* module, const char* basedir, const
extern const char* source_get(const struct module* module, unsigned idx);
/* stabs.c */
typedef void (*stabs_def_cb)(struct module* module, unsigned long load_offset,
const char* name, unsigned long offset,
BOOL is_public, BOOL is_global, unsigned char other,
struct symt_compiland* compiland, void* user);
extern BOOL stabs_parse(struct module* module, unsigned long load_offset,
const void* stabs, int stablen,
const char* strs, int strtablen);
const char* strs, int strtablen,
stabs_def_cb callback, void* user);
/* dwarf.c */
extern BOOL dwarf2_parse(struct module* module, unsigned long load_offset,
@ -512,12 +571,19 @@ extern BOOL dwarf2_parse(struct module* module, unsigned long load_offse
const unsigned char* line, unsigned int line_size,
const unsigned char* loclist, unsigned int loclist_size);
/* stack.c */
extern BOOL sw_read_mem(struct cpu_stack_walk* csw, DWORD64 addr, void* ptr, DWORD sz);
extern DWORD64 sw_xlat_addr(struct cpu_stack_walk* csw, ADDRESS64* addr);
extern void* sw_table_access(struct cpu_stack_walk* csw, DWORD64 addr);
extern DWORD64 sw_module_base(struct cpu_stack_walk* csw, DWORD64 addr);
/* symbol.c */
extern const char* symt_get_name(const struct symt* sym);
extern struct module* symt_cmp_addr_module;
extern int symt_cmp_addr(const void* p1, const void* p2);
extern void copy_symbolW(SYMBOL_INFOW* siw, const SYMBOL_INFO* si);
extern struct symt_ht*
symt_find_nearest(struct module* module, DWORD addr);
symt_find_nearest(struct module* module, DWORD_PTR addr);
extern struct symt_compiland*
symt_new_compiland(struct module* module, unsigned long address,
unsigned src_idx);
@ -525,8 +591,7 @@ extern struct symt_public*
symt_new_public(struct module* module,
struct symt_compiland* parent,
const char* typename,
unsigned long address, unsigned size,
BOOL in_code, BOOL is_func);
unsigned long address, unsigned size);
extern struct symt_data*
symt_new_global_variable(struct module* module,
struct symt_compiland* parent,
@ -540,7 +605,7 @@ extern struct symt_function*
unsigned long addr, unsigned long size,
struct symt* type);
extern BOOL symt_normalize_function(struct module* module,
struct symt_function* func);
const struct symt_function* func);
extern void symt_add_func_line(struct module* module,
struct symt_function* func,
unsigned source_idx, int line_num,
@ -558,7 +623,7 @@ extern struct symt_block*
unsigned pc, unsigned len);
extern struct symt_block*
symt_close_func_block(struct module* module,
struct symt_function* func,
const struct symt_function* func,
struct symt_block* block, unsigned pc);
extern struct symt_hierarchy_point*
symt_add_function_point(struct module* module,
@ -568,8 +633,8 @@ extern struct symt_hierarchy_point*
const char* name);
extern BOOL symt_fill_func_line_info(const struct module* module,
const struct symt_function* func,
DWORD addr, IMAGEHLP_LINE* line);
extern BOOL symt_get_func_line_next(const struct module* module, PIMAGEHLP_LINE line);
DWORD64 addr, IMAGEHLP_LINE64* line);
extern BOOL symt_get_func_line_next(const struct module* module, PIMAGEHLP_LINE64 line);
extern struct symt_thunk*
symt_new_thunk(struct module* module,
struct symt_compiland* parent,
@ -584,10 +649,12 @@ extern struct symt_hierarchy_point*
symt_new_label(struct module* module,
struct symt_compiland* compiland,
const char* name, unsigned long address);
extern struct symt* symt_index2ptr(struct module* module, DWORD id);
extern DWORD symt_ptr2index(struct module* module, const struct symt* sym);
/* type.c */
extern void symt_init_basic(struct module* module);
extern BOOL symt_get_info(const struct symt* type,
extern BOOL symt_get_info(struct module* module, const struct symt* type,
IMAGEHLP_SYMBOL_TYPE_INFO req, void* pInfo);
extern struct symt_basic*
symt_new_basic(struct module* module, enum BasicType,

View file

@ -72,7 +72,7 @@ static void dump(const void* ptr, unsigned len)
int i, j;
BYTE msg[128];
static const char hexof[] = "0123456789abcdef";
const BYTE* x = (const BYTE*)ptr;
const BYTE* x = ptr;
for (i = 0; i < len; i += 16)
{
@ -217,7 +217,7 @@ static unsigned char dwarf2_parse_byte(dwarf2_traverse_context_t* ctx)
static unsigned short dwarf2_get_u2(const unsigned char* ptr)
{
return *(const unsigned short*)ptr;
return *(const UINT16*)ptr;
}
static unsigned short dwarf2_parse_u2(dwarf2_traverse_context_t* ctx)
@ -229,7 +229,7 @@ static unsigned short dwarf2_parse_u2(dwarf2_traverse_context_t* ctx)
static unsigned long dwarf2_get_u4(const unsigned char* ptr)
{
return *(const unsigned long*)ptr;
return *(const UINT32*)ptr;
}
static unsigned long dwarf2_parse_u4(dwarf2_traverse_context_t* ctx)
@ -239,6 +239,18 @@ static unsigned long dwarf2_parse_u4(dwarf2_traverse_context_t* ctx)
return uvalue;
}
static DWORD64 dwarf2_get_u8(const unsigned char* ptr)
{
return *(const UINT64*)ptr;
}
static DWORD64 dwarf2_parse_u8(dwarf2_traverse_context_t* ctx)
{
DWORD64 uvalue = dwarf2_get_u8(ctx->data);
ctx->data += 8;
return uvalue;
}
static unsigned long dwarf2_get_leb128_as_unsigned(const unsigned char* ptr, const unsigned char** end)
{
unsigned long ret = 0;
@ -309,6 +321,13 @@ static unsigned dwarf2_leb128_length(const dwarf2_traverse_context_t* ctx)
return ret + 1;
}
/******************************************************************
* dwarf2_get_addr
*
* Returns an address.
* We assume that in all cases word size from Dwarf matches the size of
* addresses in platform where the exec is compiled.
*/
static unsigned long dwarf2_get_addr(const unsigned char* ptr, unsigned word_size)
{
unsigned long ret;
@ -318,6 +337,9 @@ static unsigned long dwarf2_get_addr(const unsigned char* ptr, unsigned word_siz
case 4:
ret = dwarf2_get_u4(ptr);
break;
case 8:
ret = dwarf2_get_u8(ptr);
break;
default:
FIXME("Unsupported Word Size %u\n", word_size);
ret = 0;
@ -490,7 +512,9 @@ static void dwarf2_fill_attr(const dwarf2_parse_context_t* ctx,
break;
case DW_FORM_data8:
FIXME("Unhandled 64bits support\n");
attr->u.block.size = 8;
attr->u.block.ptr = data;
data += 8;
break;
case DW_FORM_ref1:
@ -652,7 +676,7 @@ static enum location_error
compute_location(dwarf2_traverse_context_t* ctx, struct location* loc,
HANDLE hproc, const struct location* frame)
{
unsigned long stack[64];
DWORD_PTR tmp, stack[64];
unsigned stk;
unsigned char op;
BOOL piece_found = FALSE;
@ -665,27 +689,11 @@ compute_location(dwarf2_traverse_context_t* ctx, struct location* loc,
while (ctx->data < ctx->end_data)
{
op = dwarf2_parse_byte(ctx);
switch (op)
if (op >= DW_OP_lit0 && op <= DW_OP_lit31)
stack[++stk] = op - DW_OP_lit0;
else if (op >= DW_OP_reg0 && op <= DW_OP_reg31)
{
case DW_OP_addr: stack[++stk] = dwarf2_parse_addr(ctx); break;
case DW_OP_const1u: stack[++stk] = dwarf2_parse_byte(ctx); break;
case DW_OP_const1s: stack[++stk] = (long)(signed char)dwarf2_parse_byte(ctx); break;
case DW_OP_const2u: stack[++stk] = dwarf2_parse_u2(ctx); break;
case DW_OP_const2s: stack[++stk] = (long)(short)dwarf2_parse_u2(ctx); break;
case DW_OP_const4u: stack[++stk] = dwarf2_parse_u4(ctx); break;
case DW_OP_const4s: stack[++stk] = dwarf2_parse_u4(ctx); break;
case DW_OP_constu: stack[++stk] = dwarf2_leb128_as_unsigned(ctx); break;
case DW_OP_consts: stack[++stk] = dwarf2_leb128_as_signed(ctx); break;
case DW_OP_plus_uconst:
stack[stk] += dwarf2_leb128_as_unsigned(ctx); break;
case DW_OP_reg0: case DW_OP_reg1: case DW_OP_reg2: case DW_OP_reg3:
case DW_OP_reg4: case DW_OP_reg5: case DW_OP_reg6: case DW_OP_reg7:
case DW_OP_reg8: case DW_OP_reg9: case DW_OP_reg10: case DW_OP_reg11:
case DW_OP_reg12: case DW_OP_reg13: case DW_OP_reg14: case DW_OP_reg15:
case DW_OP_reg16: case DW_OP_reg17: case DW_OP_reg18: case DW_OP_reg19:
case DW_OP_reg20: case DW_OP_reg21: case DW_OP_reg22: case DW_OP_reg23:
case DW_OP_reg24: case DW_OP_reg25: case DW_OP_reg26: case DW_OP_reg27:
case DW_OP_reg28: case DW_OP_reg29: case DW_OP_reg30: case DW_OP_reg31:
/* dbghelp APIs don't know how to cope with this anyway
* (for example 'long long' stored in two registers)
* FIXME: We should tell winedbg how to deal with it (sigh)
@ -698,15 +706,9 @@ compute_location(dwarf2_traverse_context_t* ctx, struct location* loc,
loc->reg = dwarf2_map_register(op - DW_OP_reg0);
}
loc->kind = loc_register;
break;
case DW_OP_breg0: case DW_OP_breg1: case DW_OP_breg2: case DW_OP_breg3:
case DW_OP_breg4: case DW_OP_breg5: case DW_OP_breg6: case DW_OP_breg7:
case DW_OP_breg8: case DW_OP_breg9: case DW_OP_breg10: case DW_OP_breg11:
case DW_OP_breg12: case DW_OP_breg13: case DW_OP_breg14: case DW_OP_breg15:
case DW_OP_breg16: case DW_OP_breg17: case DW_OP_breg18: case DW_OP_breg19:
case DW_OP_breg20: case DW_OP_breg21: case DW_OP_breg22: case DW_OP_breg23:
case DW_OP_breg24: case DW_OP_breg25: case DW_OP_breg26: case DW_OP_breg27:
case DW_OP_breg28: case DW_OP_breg29: case DW_OP_breg30: case DW_OP_breg31:
}
else if (op >= DW_OP_breg0 && op <= DW_OP_breg31)
{
/* dbghelp APIs don't know how to cope with this anyway
* (for example 'long long' stored in two registers)
* FIXME: We should tell winedbg how to deal with it (sigh)
@ -714,13 +716,71 @@ compute_location(dwarf2_traverse_context_t* ctx, struct location* loc,
if (!piece_found)
{
if (loc->reg != Wine_DW_no_register)
FIXME("Only supporting one reg (%d -> %d)\n",
FIXME("Only supporting one breg (%d -> %d)\n",
loc->reg, dwarf2_map_register(op - DW_OP_breg0));
loc->reg = dwarf2_map_register(op - DW_OP_breg0);
}
stack[++stk] = dwarf2_leb128_as_signed(ctx);
loc->kind = loc_regrel;
break;
}
else switch (op)
{
case DW_OP_nop: break;
case DW_OP_addr: stack[++stk] = dwarf2_parse_addr(ctx); break;
case DW_OP_const1u: stack[++stk] = dwarf2_parse_byte(ctx); break;
case DW_OP_const1s: stack[++stk] = dwarf2_parse_byte(ctx); break;
case DW_OP_const2u: stack[++stk] = dwarf2_parse_u2(ctx); break;
case DW_OP_const2s: stack[++stk] = dwarf2_parse_u2(ctx); break;
case DW_OP_const4u: stack[++stk] = dwarf2_parse_u4(ctx); break;
case DW_OP_const4s: stack[++stk] = dwarf2_parse_u4(ctx); break;
case DW_OP_const8u: stack[++stk] = dwarf2_parse_u8(ctx); break;
case DW_OP_const8s: stack[++stk] = dwarf2_parse_u8(ctx); break;
case DW_OP_constu: stack[++stk] = dwarf2_leb128_as_unsigned(ctx); break;
case DW_OP_consts: stack[++stk] = dwarf2_leb128_as_signed(ctx); break;
case DW_OP_dup: stack[stk + 1] = stack[stk]; stk++; break;
case DW_OP_drop: stk--; break;
case DW_OP_over: stack[stk + 1] = stack[stk - 1]; stk++; break;
case DW_OP_pick: stack[stk + 1] = stack[stk - dwarf2_parse_byte(ctx)]; stk++; break;
case DW_OP_swap: tmp = stack[stk]; stack[stk] = stack[stk-1]; stack[stk-1] = tmp; break;
case DW_OP_rot: tmp = stack[stk]; stack[stk] = stack[stk-1]; stack[stk-1] = stack[stk-2]; stack[stk-2] = tmp; break;
case DW_OP_abs: stack[stk] = labs(stack[stk]); break;
case DW_OP_neg: stack[stk] = -stack[stk]; break;
case DW_OP_not: stack[stk] = ~stack[stk]; break;
case DW_OP_and: stack[stk-1] &= stack[stk]; stk--; break;
case DW_OP_or: stack[stk-1] |= stack[stk]; stk--; break;
case DW_OP_minus: stack[stk-1] -= stack[stk]; stk--; break;
case DW_OP_mul: stack[stk-1] *= stack[stk]; stk--; break;
case DW_OP_plus: stack[stk-1] += stack[stk]; stk--; break;
case DW_OP_xor: stack[stk-1] ^= stack[stk]; stk--; break;
case DW_OP_shl: stack[stk-1] <<= stack[stk]; stk--; break;
case DW_OP_shr: stack[stk-1] >>= stack[stk]; stk--; break;
case DW_OP_plus_uconst: stack[stk] += dwarf2_leb128_as_unsigned(ctx); break;
case DW_OP_shra: stack[stk-1] = stack[stk-1] / (1 << stack[stk]); stk--; break;
case DW_OP_div: stack[stk-1] = stack[stk-1] / stack[stk]; stk--; break;
case DW_OP_mod: stack[stk-1] = stack[stk-1] % stack[stk]; stk--; break;
case DW_OP_ge: stack[stk-1] = (stack[stk-1] >= stack[stk]); stk--; break;
case DW_OP_gt: stack[stk-1] = (stack[stk-1] > stack[stk]); stk--; break;
case DW_OP_le: stack[stk-1] = (stack[stk-1] <= stack[stk]); stk--; break;
case DW_OP_lt: stack[stk-1] = (stack[stk-1] < stack[stk]); stk--; break;
case DW_OP_eq: stack[stk-1] = (stack[stk-1] == stack[stk]); stk--; break;
case DW_OP_ne: stack[stk-1] = (stack[stk-1] != stack[stk]); stk--; break;
case DW_OP_skip: tmp = dwarf2_parse_u2(ctx); ctx->data += tmp; break;
case DW_OP_bra: tmp = dwarf2_parse_u2(ctx); if (!stack[stk--]) ctx->data += tmp; break;
case DW_OP_regx:
if (loc->reg != Wine_DW_no_register)
FIXME("Only supporting one regx\n");
loc->reg = dwarf2_map_register(dwarf2_leb128_as_unsigned(ctx));
loc->kind = loc_register;
break;
case DW_OP_bregx:
tmp = dwarf2_leb128_as_unsigned(ctx);
ctx->data++;
if (loc->reg != Wine_DW_no_register)
FIXME("Only supporting one regx\n");
loc->reg = dwarf2_map_register(tmp) + dwarf2_leb128_as_signed(ctx);
loc->kind = loc_register;
break;
case DW_OP_fbreg:
if (loc->reg != Wine_DW_no_register)
FIXME("Only supporting one reg (%d -> -2)\n", loc->reg);
@ -765,12 +825,12 @@ compute_location(dwarf2_traverse_context_t* ctx, struct location* loc,
}
if (hproc)
{
DWORD addr = stack[stk--];
DWORD deref;
DWORD_PTR addr = stack[stk--];
DWORD_PTR deref;
if (!ReadProcessMemory(hproc, (void*)addr, &deref, sizeof(deref), NULL))
{
WARN("Couldn't read memory at %x\n", addr);
WARN("Couldn't read memory at %lx\n", addr);
return loc_err_cant_read;
}
stack[++stk] = deref;
@ -780,8 +840,46 @@ compute_location(dwarf2_traverse_context_t* ctx, struct location* loc,
loc->kind = loc_dwarf2_block;
}
break;
case DW_OP_deref_size:
if (!stk)
{
FIXME("Unexpected empty stack\n");
return loc_err_internal;
}
if (loc->reg != Wine_DW_no_register)
{
WARN("Too complex expression for deref\n");
return loc_err_too_complex;
}
if (hproc)
{
DWORD_PTR addr = stack[stk--];
BYTE derefsize = dwarf2_parse_byte(ctx);
DWORD64 deref;
if (!ReadProcessMemory(hproc, (void*)addr, &deref, derefsize, NULL))
{
WARN("Couldn't read memory at %lx\n", addr);
return loc_err_cant_read;
}
switch (derefsize)
{
case 1: stack[++stk] = *(unsigned char*)&deref; break;
case 2: stack[++stk] = *(unsigned short*)&deref; break;
case 4: stack[++stk] = *(DWORD*)&deref; break;
case 8: if (ctx->word_size >= derefsize) stack[++stk] = deref; break;
}
}
else
{
loc->kind = loc_dwarf2_block;
}
break;
default:
FIXME("Unhandled attr op: %x\n", op);
if (op < DW_OP_lo_user) /* as DW_OP_hi_user is 0xFF, we don't need to test against it */
FIXME("Unhandled attr op: %x\n", op);
/* FIXME else unhandled extension */
return loc_err_internal;
}
}
@ -1163,7 +1261,8 @@ static void dwarf2_parse_udt_member(dwarf2_parse_context_t* ctx,
if (!dwarf2_find_attribute(ctx, di, DW_AT_byte_size, &nbytes))
{
DWORD64 size;
nbytes.u.uvalue = symt_get_info(elt_type, TI_GET_LENGTH, &size) ? (unsigned long)size : 0;
nbytes.u.uvalue = symt_get_info(ctx->module, elt_type, TI_GET_LENGTH, &size) ?
(unsigned long)size : 0;
}
bit_offset.u.uvalue = nbytes.u.uvalue * 8 - bit_offset.u.uvalue - bit_size.u.uvalue;
}
@ -1214,6 +1313,10 @@ static struct symt* dwarf2_parse_udt_type(dwarf2_parse_context_t* ctx,
case DW_TAG_union_type:
case DW_TAG_typedef:
/* FIXME: we need to handle nested udt definitions */
case DW_TAG_inheritance:
case DW_TAG_subprogram:
case DW_TAG_variable:
/* FIXME: some C++ related stuff */
break;
default:
FIXME("Unhandled Tag type 0x%lx at %s, for %s\n",
@ -1334,6 +1437,8 @@ static void dwarf2_parse_variable(dwarf2_subprogram_t* subpgm,
switch (loc.kind)
{
case loc_error:
break;
case loc_absolute:
/* it's a global variable */
/* FIXME: we don't handle its scope yet */
@ -1389,11 +1494,28 @@ static void dwarf2_parse_variable(dwarf2_subprogram_t* subpgm,
v.n1.n2.n3.byref = pool_strdup(&subpgm->ctx->module->pool, value.u.string);
break;
case DW_FORM_data8:
case DW_FORM_block:
case DW_FORM_block1:
case DW_FORM_block2:
case DW_FORM_block4:
v.n1.n2.vt = VT_I4;
switch (value.u.block.size)
{
case 1: v.n1.n2.n3.lVal = *(BYTE*)value.u.block.ptr; break;
case 2: v.n1.n2.n3.lVal = *(USHORT*)value.u.block.ptr; break;
case 4: v.n1.n2.n3.lVal = *(DWORD*)value.u.block.ptr; break;
default:
v.n1.n2.vt = VT_I1 | VT_BYREF;
v.n1.n2.n3.byref = pool_alloc(&subpgm->ctx->module->pool, value.u.block.size);
memcpy(v.n1.n2.n3.byref, value.u.block.ptr, value.u.block.size);
}
break;
case DW_FORM_data8:
v.n1.n2.vt = VT_I1 | VT_BYREF;
v.n1.n2.n3.byref = pool_alloc(&subpgm->ctx->module->pool, value.u.block.size);
memcpy(v.n1.n2.n3.byref, value.u.block.ptr, value.u.block.size);
break;
default:
FIXME("Unsupported form for const value %s (%lx)\n",
@ -1786,6 +1908,11 @@ static void dwarf2_load_one_entry(dwarf2_parse_context_t* ctx,
dwarf2_parse_variable(&subpgm, NULL, di);
}
break;
/* silence a couple of C++ defines */
case DW_TAG_namespace:
case DW_TAG_imported_module:
case DW_TAG_imported_declaration:
break;
default:
FIXME("Unhandled Tag type 0x%lx at %s, for %lu\n",
di->abbrev->tag, dwarf2_debug_ctx(ctx), di->abbrev->entry_code);
@ -2010,7 +2137,7 @@ static BOOL dwarf2_parse_compilation_unit(const dwarf2_section_t* sections,
cu_ctx.word_size = dwarf2_parse_byte(&cu_ctx);
TRACE("Compilation Unit Header found at 0x%x:\n",
comp_unit_start - sections[section_debug].address);
(int)(comp_unit_start - sections[section_debug].address));
TRACE("- length: %lu\n", cu_length);
TRACE("- version: %u\n", cu_version);
TRACE("- abbrev_offset: %lu\n", cu_abbrev_offset);

View file

@ -376,6 +376,18 @@ typedef enum dwarf_operation_e
DW_OP_call2 = 0x98,
DW_OP_call4 = 0x99,
DW_OP_call_ref = 0x9a,
DW_OP_form_tls_address = 0x9b,
DW_OP_call_frame_cfa = 0x9c,
DW_OP_bit_piece = 0x9d,
/* Implementation defined extensions */
DW_OP_lo_user = 0xe0,
DW_OP_hi_user = 0xff,
/* GNU extensions */
DW_OP_GNU_push_tls_address = 0xe0,
DW_OP_GNU_uninit = 0xf0,
DW_OP_GNU_encoded_addr = 0xf1,
} dwarf_operation_t;
enum dwarf_calling_convention

View file

@ -77,7 +77,7 @@
struct elf_module_info
{
unsigned long elf_addr;
DWORD_PTR elf_addr;
unsigned short elf_mark : 1,
elf_loader : 1;
};
@ -93,22 +93,36 @@ WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
struct elf_info
{
unsigned flags; /* IN one (or several) of the ELF_INFO constants */
unsigned long dbg_hdr_addr; /* OUT address of debug header (if ELF_INFO_DEBUG_HEADER is set) */
DWORD_PTR dbg_hdr_addr; /* OUT address of debug header (if ELF_INFO_DEBUG_HEADER is set) */
struct module* module; /* OUT loaded module (if ELF_INFO_MODULE is set) */
const WCHAR* module_name; /* OUT found module name (if ELF_INFO_NAME is set) */
};
#ifdef _WIN64
#define Elf_Ehdr Elf64_Ehdr
#define Elf_Shdr Elf64_Shdr
#define Elf_Phdr Elf64_Phdr
#define Elf_Dyn Elf64_Dyn
#define Elf_Sym Elf64_Sym
#else
#define Elf_Ehdr Elf32_Ehdr
#define Elf_Shdr Elf32_Shdr
#define Elf_Phdr Elf32_Phdr
#define Elf_Dyn Elf32_Dyn
#define Elf_Sym Elf32_Sym
#endif
/* structure holding information while handling an ELF image
* allows one by one section mapping for memory savings
*/
struct elf_file_map
{
Elf32_Ehdr elfhdr;
Elf_Ehdr elfhdr;
size_t elf_size;
size_t elf_start;
struct
{
Elf32_Shdr shdr;
Elf_Shdr shdr;
const char* mapped;
}* sect;
int fd;
@ -125,7 +139,7 @@ struct elf_section_map
struct symtab_elt
{
struct hash_table_elt ht_elt;
const Elf32_Sym* symp;
const Elf_Sym* symp;
struct symt_compiland* compiland;
unsigned used;
};
@ -237,7 +251,7 @@ static void elf_end_find(struct elf_file_map* fmap)
*
* Get the size of an ELF section
*/
static inline unsigned elf_get_map_size(struct elf_section_map* esm)
static inline unsigned elf_get_map_size(const struct elf_section_map* esm)
{
if (esm->sidx < 0 || esm->sidx >= esm->fmap->elfhdr.e_shnum)
return 0;
@ -254,7 +268,7 @@ static BOOL elf_map_file(const WCHAR* filenameW, struct elf_file_map* fmap)
static const BYTE elf_signature[4] = { ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3 };
struct stat statbuf;
int i;
Elf32_Phdr phdr;
Elf_Phdr phdr;
unsigned tmp, page_mask = getpagesize() - 1;
char* filename;
unsigned len;
@ -279,7 +293,12 @@ static BOOL elf_map_file(const WCHAR* filenameW, struct elf_file_map* fmap)
/* and check for an ELF header */
if (memcmp(fmap->elfhdr.e_ident,
elf_signature, sizeof(elf_signature))) goto done;
/* and check 32 vs 64 size according to current machine */
#ifdef _WIN64
if (fmap->elfhdr.e_ident[EI_CLASS] != ELFCLASS64) goto done;
#else
if (fmap->elfhdr.e_ident[EI_CLASS] != ELFCLASS32) goto done;
#endif
fmap->sect = HeapAlloc(GetProcessHeap(), 0,
fmap->elfhdr.e_shnum * sizeof(fmap->sect[0]));
if (!fmap->sect) goto done;
@ -350,7 +369,7 @@ int elf_is_in_thunk_area(unsigned long addr,
{
unsigned i;
for (i = 0; thunks[i].symname; i++)
if (thunks) for (i = 0; thunks[i].symname; i++)
{
if (addr >= thunks[i].rva_start && addr < thunks[i].rva_end)
return i;
@ -372,13 +391,13 @@ static void elf_hash_symtab(struct module* module, struct pool* pool,
const char* symname;
struct symt_compiland* compiland = NULL;
const char* ptr;
const Elf32_Sym* symp;
const Elf_Sym* symp;
struct symtab_elt* ste;
struct elf_section_map esm, esm_str;
if (!elf_find_section(fmap, ".symtab", SHT_SYMTAB, &esm) &&
!elf_find_section(fmap, ".dynsym", SHT_DYNSYM, &esm)) return;
if ((symp = (const Elf32_Sym*)elf_map_section(&esm)) == ELF_NO_MAP) return;
if ((symp = (const Elf_Sym*)elf_map_section(&esm)) == ELF_NO_MAP) return;
esm_str.fmap = fmap;
esm_str.sidx = fmap->sect[esm.sidx].shdr.sh_link;
if ((strp = elf_map_section(&esm_str)) == ELF_NO_MAP) return;
@ -471,9 +490,9 @@ static void elf_hash_symtab(struct module* module, struct pool* pool,
*
* lookup a symbol by name in our internal hash table for the symtab
*/
static const Elf32_Sym* elf_lookup_symtab(const struct module* module,
static const Elf_Sym* elf_lookup_symtab(const struct module* module,
const struct hash_table* ht_symtab,
const char* name, struct symt* compiland)
const char* name, const struct symt* compiland)
{
struct symtab_elt* weak_result = NULL; /* without compiland name */
struct symtab_elt* result = NULL;
@ -490,7 +509,7 @@ static const Elf32_Sym* elf_lookup_symtab(const struct module* module,
if (compiland)
{
compiland_name = source_get(module,
((struct symt_compiland*)compiland)->source);
((const struct symt_compiland*)compiland)->source);
compiland_basename = strrchr(compiland_name, '/');
if (!compiland_basename++) compiland_basename = compiland_name;
}
@ -542,12 +561,12 @@ static const Elf32_Sym* elf_lookup_symtab(const struct module* module,
* - get any relevant information (address & size) from the bits we got from the
* stabs debugging information
*/
static void elf_finish_stabs_info(struct module* module, struct hash_table* symtab)
static void elf_finish_stabs_info(struct module* module, const struct hash_table* symtab)
{
struct hash_table_iter hti;
void* ptr;
struct symt_ht* sym;
const Elf32_Sym* symp;
const Elf_Sym* symp;
hash_table_iter_init(&module->ht_symbols, &hti, NULL);
while ((ptr = hash_table_iter_up(&hti)))
@ -623,13 +642,13 @@ static void elf_finish_stabs_info(struct module* module, struct hash_table* symt
*
* creating the thunk objects for a wine native DLL
*/
static int elf_new_wine_thunks(struct module* module, struct hash_table* ht_symtab,
static int elf_new_wine_thunks(struct module* module, const struct hash_table* ht_symtab,
const struct elf_thunk_area* thunks)
{
int j;
struct hash_table_iter hti;
struct symtab_elt* ste;
DWORD addr;
DWORD_PTR addr;
struct symt_ht* symt;
hash_table_iter_init(ht_symtab, &hti, NULL);
@ -650,8 +669,8 @@ static int elf_new_wine_thunks(struct module* module, struct hash_table* ht_symt
ULONG64 ref_addr;
symt = symt_find_nearest(module, addr);
if (symt)
symt_get_info(&symt->symt, TI_GET_ADDRESS, &ref_addr);
if (symt && !symt_get_info(module, &symt->symt, TI_GET_ADDRESS, &ref_addr))
ref_addr = addr;
if (!symt || addr != ref_addr)
{
/* creating public symbols for all the ELF symbols which haven't been
@ -687,9 +706,9 @@ static int elf_new_wine_thunks(struct module* module, struct hash_table* ht_symt
ULONG64 xaddr = 0, xsize = 0;
DWORD kind = -1;
symt_get_info(&symt->symt, TI_GET_ADDRESS, &xaddr);
symt_get_info(&symt->symt, TI_GET_LENGTH, &xsize);
symt_get_info(&symt->symt, TI_GET_DATAKIND, &kind);
symt_get_info(module, &symt->symt, TI_GET_ADDRESS, &xaddr);
symt_get_info(module, &symt->symt, TI_GET_LENGTH, &xsize);
symt_get_info(module, &symt->symt, TI_GET_DATAKIND, &kind);
/* If none of symbols has a correct size, we consider they are both markers
* Hence, we can silence this warning
@ -698,7 +717,7 @@ static int elf_new_wine_thunks(struct module* module, struct hash_table* ht_symt
*/
if ((xsize || ste->symp->st_size) &&
(kind == (ELF32_ST_BIND(ste->symp->st_info) == STB_LOCAL) ? DataIsFileStatic : DataIsGlobal))
FIXME("Duplicate in %s: %s<%08x-%08x> %s<%s-%s>\n",
FIXME("Duplicate in %s: %s<%08lx-%08x> %s<%s-%s>\n",
debugstr_w(module->module.ModuleName),
ste->ht_elt.name, addr, (unsigned int)ste->symp->st_size,
symt->hash_elt.name,
@ -716,7 +735,7 @@ static int elf_new_wine_thunks(struct module* module, struct hash_table* ht_symt
*
* Creates a set of public symbols from an ELF symtab
*/
static int elf_new_public_symbols(struct module* module, struct hash_table* symtab)
static int elf_new_public_symbols(struct module* module, const struct hash_table* symtab)
{
struct hash_table_iter hti;
struct symtab_elt* ste;
@ -730,142 +749,19 @@ static int elf_new_public_symbols(struct module* module, struct hash_table* symt
{
symt_new_public(module, ste->compiland, ste->ht_elt.name,
module->elf_info->elf_addr + ste->symp->st_value,
ste->symp->st_size, TRUE /* FIXME */,
ELF32_ST_TYPE(ste->symp->st_info) == STT_FUNC);
ste->symp->st_size);
}
return TRUE;
}
/* Copyright (C) 1986 Gary S. Brown. Modified by Robert Shearman. You may use
the following calc_crc32 code or tables extracted from it, as desired without
restriction. */
/**********************************************************************\
|* Demonstration program to compute the 32-bit CRC used as the frame *|
|* check sequence in ADCCP (ANSI X3.66, also known as FIPS PUB 71 *|
|* and FED-STD-1003, the U.S. versions of CCITT's X.25 link-level *|
|* protocol). The 32-bit FCS was added via the Federal Register, *|
|* 1 June 1982, p.23798. I presume but don't know for certain that *|
|* this polynomial is or will be included in CCITT V.41, which *|
|* defines the 16-bit CRC (often called CRC-CCITT) polynomial. FIPS *|
|* PUB 78 says that the 32-bit FCS reduces otherwise undetected *|
|* errors by a factor of 10^-5 over 16-bit FCS. *|
\**********************************************************************/
/* First, the polynomial itself and its table of feedback terms. The */
/* polynomial is */
/* X^32+X^26+X^23+X^22+X^16+X^12+X^11+X^10+X^8+X^7+X^5+X^4+X^2+X^1+X^0 */
/* Note that we take it "backwards" and put the highest-order term in */
/* the lowest-order bit. The X^32 term is "implied"; the LSB is the */
/* X^31 term, etc. The X^0 term (usually shown as "+1") results in */
/* the MSB being 1. */
/* Note that the usual hardware shift register implementation, which */
/* is what we're using (we're merely optimizing it by doing eight-bit */
/* chunks at a time) shifts bits into the lowest-order term. In our */
/* implementation, that means shifting towards the right. Why do we */
/* do it this way? Because the calculated CRC must be transmitted in */
/* order from highest-order term to lowest-order term. UARTs transmit */
/* characters in order from LSB to MSB. By storing the CRC this way, */
/* we hand it to the UART in the order low-byte to high-byte; the UART */
/* sends each low-bit to hight-bit; and the result is transmission bit */
/* by bit from highest- to lowest-order term without requiring any bit */
/* shuffling on our part. Reception works similarly. */
/* The feedback terms table consists of 256, 32-bit entries. Notes: */
/* */
/* 1. The table can be generated at runtime if desired; code to do so */
/* is shown later. It might not be obvious, but the feedback */
/* terms simply represent the results of eight shift/xor opera- */
/* tions for all combinations of data and CRC register values. */
/* */
/* 2. The CRC accumulation logic is the same for all CRC polynomials, */
/* be they sixteen or thirty-two bits wide. You simply choose the */
/* appropriate table. Alternatively, because the table can be */
/* generated at runtime, you can start by generating the table for */
/* the polynomial in question and use exactly the same "updcrc", */
/* if your application needn't simultaneously handle two CRC */
/* polynomials. (Note, however, that XMODEM is strange.) */
/* */
/* 3. For 16-bit CRCs, the table entries need be only 16 bits wide; */
/* of course, 32-bit entries work OK if the high 16 bits are zero. */
/* */
/* 4. The values must be right-shifted by eight bits by the "updcrc" */
/* logic; the shift must be unsigned (bring in zeroes). On some */
/* hardware you could probably optimize the shift in assembler by */
/* using byte-swap instructions. */
static DWORD calc_crc32(struct elf_file_map* fmap)
{
#define UPDC32(octet,crc) (crc_32_tab[((crc) ^ (octet)) & 0xff] ^ ((crc) >> 8))
static const DWORD crc_32_tab[] =
{ /* CRC polynomial 0xedb88320 */
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
};
int i, r;
unsigned char buffer[256];
DWORD crc = ~0;
lseek(fmap->fd, 0, SEEK_SET);
while ((r = read(fmap->fd, buffer, sizeof(buffer))) > 0)
{
for (i = 0; i < r; i++) crc = UPDC32(buffer[i], crc);
}
return ~crc;
#undef UPDC32
}
static BOOL elf_check_debug_link(const WCHAR* file, struct elf_file_map* fmap, DWORD crc)
{
BOOL ret;
if (!elf_map_file(file, fmap)) return FALSE;
if (!(ret = crc == calc_crc32(fmap)))
if (!(ret = crc == calc_crc32(fmap->fd)))
{
WARN("Bad CRC for file %s (got %08x while expecting %08x)\n",
debugstr_w(file), calc_crc32(fmap), crc);
debugstr_w(file), calc_crc32(fmap->fd), crc);
elf_unmap_file(fmap);
}
return ret;
@ -952,7 +848,7 @@ found:
* Parses a .gnu_debuglink section and loads the debug info from
* the external file specified there.
*/
static BOOL elf_debuglink_parse(struct elf_file_map* fmap, struct module* module,
static BOOL elf_debuglink_parse(struct elf_file_map* fmap, const struct module* module,
const BYTE* debuglink)
{
/* The content of a debug link section is:
@ -1039,7 +935,8 @@ static BOOL elf_load_debug_info_from_map(struct module* module,
/* OK, now just parse all of the stabs. */
lret = stabs_parse(module, module->elf_info->elf_addr,
stab, elf_get_map_size(&stab_sect),
stabstr, elf_get_map_size(&stabstr_sect));
stabstr, elf_get_map_size(&stabstr_sect),
NULL, NULL);
if (lret)
/* and fill in the missing information for stabs */
elf_finish_stabs_info(module, ht_symtab);
@ -1160,7 +1057,7 @@ BOOL elf_fetch_file_info(const WCHAR* name, DWORD* base,
if (!elf_map_file(name, &fmap)) return FALSE;
if (base) *base = fmap.elf_start;
*size = fmap.elf_size;
*checksum = calc_crc32(&fmap);
*checksum = calc_crc32(fmap.fd);
elf_unmap_file(&fmap);
return TRUE;
}
@ -1184,7 +1081,7 @@ static BOOL elf_load_file(struct process* pcs, const WCHAR* filename,
TRACE("Processing elf file '%s' at %08lx\n", debugstr_w(filename), load_offset);
if (!elf_map_file(filename, &fmap)) goto leave;
if (!elf_map_file(filename, &fmap)) return ret;
/* Next, we need to find a few of the internal ELF headers within
* this thing. We need the main executable header, and the section
@ -1206,7 +1103,7 @@ static BOOL elf_load_file(struct process* pcs, const WCHAR* filename,
if (elf_find_section(&fmap, ".dynamic", SHT_DYNAMIC, &esm))
{
Elf32_Dyn dyn;
Elf_Dyn dyn;
char* ptr = (char*)fmap.sect[esm.sidx].shdr.sh_addr;
unsigned long len;
@ -1234,7 +1131,7 @@ static BOOL elf_load_file(struct process* pcs, const WCHAR* filename,
if (!elf_module_info) goto leave;
elf_info->module = module_new(pcs, filename, DMT_ELF, FALSE,
(load_offset) ? load_offset : fmap.elf_start,
fmap.elf_size, 0, calc_crc32(&fmap));
fmap.elf_size, 0, calc_crc32(fmap.fd));
if (!elf_info->module)
{
HeapFree(GetProcessHeap(), 0, elf_module_info);
@ -1389,7 +1286,7 @@ static BOOL elf_search_and_load_file(struct process* pcs, const WCHAR* filename,
*/
static BOOL elf_enum_modules_internal(const struct process* pcs,
const WCHAR* main_name,
elf_enum_modules_cb cb, void* user)
enum_modules_cb cb, void* user)
{
struct r_debug dbg_hdr;
void* lm_addr;
@ -1492,9 +1389,7 @@ static BOOL elf_search_loader(struct process* pcs, struct elf_info* elf_info)
const char* ptr;
/* All binaries are loaded with WINELOADER (if run from tree) or by the
* main executable (either wine-kthread or wine-pthread)
* FIXME: the heuristic used to know whether we need to load wine-pthread
* or wine-kthread is not 100% safe
* main executable
*/
if ((ptr = getenv("WINELOADER")))
{
@ -1504,8 +1399,7 @@ static BOOL elf_search_loader(struct process* pcs, struct elf_info* elf_info)
}
else
{
ret = elf_search_and_load_file(pcs, S_WineKThreadW, 0, elf_info) ||
elf_search_and_load_file(pcs, S_WinePThreadW, 0, elf_info);
ret = elf_search_and_load_file(pcs, S_WineW, 0, elf_info);
}
return ret;
}
@ -1533,7 +1427,7 @@ BOOL elf_read_wine_loader_dbg_info(struct process* pcs)
* This function doesn't require that someone has called SymInitialize
* on this very process.
*/
BOOL elf_enum_modules(HANDLE hProc, elf_enum_modules_cb cb, void* user)
BOOL elf_enum_modules(HANDLE hProc, enum_modules_cb cb, void* user)
{
struct process pcs;
struct elf_info elf_info;
@ -1638,7 +1532,7 @@ BOOL elf_read_wine_loader_dbg_info(struct process* pcs)
return FALSE;
}
BOOL elf_enum_modules(HANDLE hProc, elf_enum_modules_cb cb, void* user)
BOOL elf_enum_modules(HANDLE hProc, enum_modules_cb cb, void* user)
{
return FALSE;
}

File diff suppressed because it is too large Load diff

View file

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

View file

@ -35,10 +35,10 @@ WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
const WCHAR S_ElfW[] = {'<','e','l','f','>','\0'};
const WCHAR S_WineLoaderW[] = {'<','w','i','n','e','-','l','o','a','d','e','r','>','\0'};
static const WCHAR S_DotSoW[] = {'.','s','o','\0'};
static const WCHAR S_DotDylibW[] = {'.','d','y','l','i','b','\0'};
static const WCHAR S_DotPdbW[] = {'.','p','d','b','\0'};
static const WCHAR S_DotDbgW[] = {'.','d','b','g','\0'};
const WCHAR S_WinePThreadW[] = {'w','i','n','e','-','p','t','h','r','e','a','d','\0'};
const WCHAR S_WineKThreadW[] = {'w','i','n','e','-','k','t','h','r','e','a','d','\0'};
const WCHAR S_WineW[] = {'w','i','n','e',0};
const WCHAR S_SlashW[] = {'/','\0'};
static const WCHAR S_AcmW[] = {'.','a','c','m','\0'};
@ -87,9 +87,7 @@ static void module_fill_module(const WCHAR* in, WCHAR* out, size_t size)
out[len] = '\0';
if (len > 4 && (l = match_ext(out, len)))
out[len - l] = '\0';
else if (len > 12 &&
(!strcmpiW(out + len - 12, S_WinePThreadW) ||
!strcmpiW(out + len - 12, S_WineKThreadW)))
else if (len > 4 && !strcmpiW(out + len - 4, S_WineW))
lstrcpynW(out, S_WineLoaderW, size);
else
{
@ -114,6 +112,7 @@ static const char* get_module_type(enum module_type type, BOOL virtual)
{
case DMT_ELF: return virtual ? "Virtual ELF" : "ELF";
case DMT_PE: return virtual ? "Virtual PE" : "PE";
case DMT_MACHO: return virtual ? "Virtual Mach-O" : "Mach-O";
default: return "---";
}
}
@ -123,20 +122,21 @@ static const char* get_module_type(enum module_type type, BOOL virtual)
*/
struct module* module_new(struct process* pcs, const WCHAR* name,
enum module_type type, BOOL virtual,
unsigned long mod_addr, unsigned long size,
DWORD64 mod_addr, DWORD64 size,
unsigned long stamp, unsigned long checksum)
{
struct module* module;
assert(type == DMT_ELF || type == DMT_PE);
assert(type == DMT_ELF || type == DMT_PE || type == DMT_MACHO);
if (!(module = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*module))))
return NULL;
module->next = pcs->lmodules;
pcs->lmodules = module;
TRACE("=> %s %08lx-%08lx %s\n",
get_module_type(type, virtual), mod_addr, mod_addr + size,
TRACE("=> %s %s-%s %s\n",
get_module_type(type, virtual),
wine_dbgstr_longlong(mod_addr), wine_dbgstr_longlong(mod_addr + size),
debugstr_w(name));
pool_init(&module->pool, 65536);
@ -169,7 +169,12 @@ struct module* module_new(struct process* pcs, const WCHAR* name,
module->type = type;
module->is_virtual = virtual ? TRUE : FALSE;
module->sortlist_valid = FALSE;
module->sorttab_size = 0;
module->addr_sorttab = NULL;
module->num_sorttab = 0;
module->num_symbols = 0;
vector_init(&module->vsymt, sizeof(struct symt*), 128);
/* FIXME: this seems a bit too high (on a per module basis)
* need some statistics about this
*/
@ -188,7 +193,7 @@ struct module* module_new(struct process* pcs, const WCHAR* name,
* module_find_by_name
*
*/
struct module* module_find_by_name(const struct process* pcs, const WCHAR* name)
static struct module* module_find_by_name(const struct process* pcs, const WCHAR* name)
{
struct module* module;
@ -238,7 +243,7 @@ struct module* module_is_already_loaded(const struct process* pcs, const WCHAR*
* module_get_container
*
*/
struct module* module_get_container(const struct process* pcs,
static struct module* module_get_container(const struct process* pcs,
const struct module* inner)
{
struct module* module;
@ -319,6 +324,9 @@ BOOL module_get_debug(struct module_pair* pair)
ret ? CBA_DEFERRED_SYMBOL_LOAD_COMPLETE : CBA_DEFERRED_SYMBOL_LOAD_FAILURE,
&idslW64);
break;
case DMT_MACHO:
ret = macho_load_debug_info(pair->effective, NULL);
break;
default:
ret = FALSE;
break;
@ -344,7 +352,8 @@ struct module* module_find_by_addr(const struct process* pcs, unsigned long addr
if (type == DMT_UNKNOWN)
{
if ((module = module_find_by_addr(pcs, addr, DMT_PE)) ||
(module = module_find_by_addr(pcs, addr, DMT_ELF)))
(module = module_find_by_addr(pcs, addr, DMT_ELF)) ||
(module = module_find_by_addr(pcs, addr, DMT_MACHO)))
return module;
}
else
@ -361,13 +370,13 @@ struct module* module_find_by_addr(const struct process* pcs, unsigned long addr
}
/******************************************************************
* module_is_elf_container_loaded
* module_is_container_loaded
*
* checks whether the ELF container, for a (supposed) PE builtin is
* checks whether the native container, for a (supposed) PE builtin is
* already loaded
*/
static BOOL module_is_elf_container_loaded(const struct process* pcs,
const WCHAR* ImageName, DWORD base)
static BOOL module_is_container_loaded(const struct process* pcs,
const WCHAR* ImageName, DWORD64 base)
{
size_t len;
struct module* module;
@ -379,7 +388,7 @@ static BOOL module_is_elf_container_loaded(const struct process* pcs,
for (module = pcs->lmodules; module; module = module->next)
{
if (module->type == DMT_ELF &&
if ((module->type == DMT_ELF || module->type == DMT_MACHO) &&
base >= module->module.BaseOfImage &&
base < module->module.BaseOfImage + module->module.ImageSize)
{
@ -419,8 +428,17 @@ enum module_type module_get_type_by_name(const WCHAR* name)
} while (len);
/* check for terminating .so or .so.[digit] */
/* FIXME: Can't rely solely on extension; have to check magic or
* stop using .so on Mac OS X. For now, base on platform. */
if (len > 3 && !memcmp(name + len - 3, S_DotSoW, 3))
#ifdef __APPLE__
return DMT_MACHO;
#else
return DMT_ELF;
#endif
if (len > 6 && !strncmpiW(name + len - 6, S_DotDylibW, 6))
return DMT_MACHO;
if (len > 4 && !strncmpiW(name + len - 4, S_DotPdbW, 4))
return DMT_PDB;
@ -428,16 +446,27 @@ enum module_type module_get_type_by_name(const WCHAR* name)
if (len > 4 && !strncmpiW(name + len - 4, S_DotDbgW, 4))
return DMT_DBG;
/* wine-[kp]thread is also an ELF module */
if (((len > 12 && name[len - 13] == '/') || len == 12) &&
(!strncmpiW(name + len - 12, S_WinePThreadW, 12) ||
!strncmpiW(name + len - 12, S_WineKThreadW, 12)))
/* wine is also a native module (Mach-O on Mac OS X, ELF elsewhere) */
if (((len > 4 && name[len - 5] == '/') || len == 4) && !strcmpiW(name + len - 4, S_WineW))
{
#ifdef __APPLE__
return DMT_MACHO;
#else
return DMT_ELF;
#endif
}
return DMT_PE;
}
/******************************************************************
* refresh_module_list
*/
static BOOL refresh_module_list(struct process* pcs)
{
/* force transparent ELF and Mach-O loading / unloading */
return elf_synchronize_module_list(pcs) || macho_synchronize_module_list(pcs);
}
/***********************************************************************
* SymLoadModule (DBGHELP.@)
*/
@ -508,8 +537,9 @@ DWORD64 WINAPI SymLoadModuleExW(HANDLE hProcess, HANDLE hFile, PCWSTR wImageNam
if (Flags & SLMFLAG_VIRTUAL)
{
if (!wImageName) return FALSE;
module = module_new(pcs, wImageName, module_get_type_by_name(wImageName),
TRUE, (DWORD)BaseOfDll, SizeOfDll, 0, 0);
TRUE, BaseOfDll, SizeOfDll, 0, 0);
if (!module) return FALSE;
if (wModuleName) module_set_module(module, wModuleName);
module->module.SymType = SymVirtual;
@ -519,8 +549,7 @@ DWORD64 WINAPI SymLoadModuleExW(HANDLE hProcess, HANDLE hFile, PCWSTR wImageNam
if (Flags & ~(SLMFLAG_VIRTUAL))
FIXME("Unsupported Flags %08x for %s\n", Flags, debugstr_w(wImageName));
/* force transparent ELF loading / unloading */
elf_synchronize_module_list(pcs);
refresh_module_list(pcs);
/* this is a Wine extension to the API just to redo the synchronisation */
if (!wImageName && !hFile) return 0;
@ -531,7 +560,7 @@ DWORD64 WINAPI SymLoadModuleExW(HANDLE hProcess, HANDLE hFile, PCWSTR wImageNam
if (wImageName)
{
module = module_is_already_loaded(pcs, wImageName);
if (!module && module_is_elf_container_loaded(pcs, wImageName, BaseOfDll))
if (!module && module_is_container_loaded(pcs, wImageName, BaseOfDll))
{
/* force the loading of DLL as builtin */
module = pe_load_builtin_module(pcs, wImageName, BaseOfDll, SizeOfDll);
@ -540,11 +569,22 @@ DWORD64 WINAPI SymLoadModuleExW(HANDLE hProcess, HANDLE hFile, PCWSTR wImageNam
if (!module)
{
/* otherwise, try a regular PE module */
if (!(module = pe_load_native_module(pcs, wImageName, hFile, BaseOfDll, SizeOfDll)))
if (!(module = pe_load_native_module(pcs, wImageName, hFile, BaseOfDll, SizeOfDll)) &&
wImageName)
{
/* and finally and ELF module */
if (module_get_type_by_name(wImageName) == DMT_ELF)
module = elf_load_module(pcs, wImageName, BaseOfDll);
/* and finally an ELF or Mach-O module */
switch (module_get_type_by_name(wImageName))
{
case DMT_ELF:
module = elf_load_module(pcs, wImageName, BaseOfDll);
break;
case DMT_MACHO:
module = macho_load_module(pcs, wImageName, BaseOfDll);
break;
default:
/* Ignored */
break;
}
}
}
if (!module)
@ -558,7 +598,8 @@ DWORD64 WINAPI SymLoadModuleExW(HANDLE hProcess, HANDLE hFile, PCWSTR wImageNam
*/
if (wModuleName)
module_set_module(module, wModuleName);
lstrcpynW(module->module.ImageName, wImageName,
if (wImageName)
lstrcpynW(module->module.ImageName, wImageName,
sizeof(module->module.ImageName) / sizeof(WCHAR));
return module->module.BaseOfImage;
@ -715,7 +756,8 @@ BOOL WINAPI SymEnumerateModulesW64(HANDLE hProcess,
for (module = pcs->lmodules; module; module = module->next)
{
if (!(dbghelp_options & SYMOPT_WINE_WITH_ELF_MODULES) && module->type == DMT_ELF)
if (!(dbghelp_options & SYMOPT_WINE_WITH_NATIVE_MODULES) &&
(module->type == DMT_ELF || module->type == DMT_MACHO))
continue;
if (!EnumModulesCallback(module->module.ModuleName,
module->module.BaseOfImage, UserContext))
@ -1008,7 +1050,9 @@ DWORD64 WINAPI SymGetModuleBase64(HANDLE hProcess, DWORD64 dwAddr)
void module_reset_debug_info(struct module* module)
{
module->sortlist_valid = TRUE;
module->sorttab_size = 0;
module->addr_sorttab = NULL;
module->num_sorttab = module->num_symbols = 0;
hash_table_destroy(&module->ht_symbols);
module->ht_symbols.num_buckets = 0;
module->ht_symbols.buckets = NULL;
@ -1020,3 +1064,17 @@ void module_reset_debug_info(struct module* module)
module->sources_used = module->sources_alloc = 0;
module->sources = NULL;
}
/******************************************************************
* SymRefreshModuleList (DBGHELP.@)
*/
BOOL WINAPI SymRefreshModuleList(HANDLE hProcess)
{
struct process* pcs;
TRACE("(%p)\n", hProcess);
if (!(pcs = process_find_by_handle(hProcess))) return FALSE;
return refresh_module_list(pcs);
}

View file

@ -71,7 +71,7 @@ static void dump(const void* ptr, unsigned len)
unsigned int i, j;
char msg[128];
const char* hexof = "0123456789abcdef";
const BYTE* x = (const BYTE*)ptr;
const BYTE* x = ptr;
for (i = 0; i < len; i += 16)
{
@ -95,7 +95,7 @@ static void dump(const void* ptr, unsigned len)
* Process CodeView type information.
*/
#define MAX_BUILTIN_TYPES 0x0480
#define MAX_BUILTIN_TYPES 0x0604
#define FIRST_DEFINABLE_TYPE 0x1000
static struct symt* cv_basic_types[MAX_BUILTIN_TYPES];
@ -113,6 +113,7 @@ static struct cv_defined_module*cv_current_module;
static void codeview_init_basic_types(struct module* module)
{
struct symt_udt* udt;
/*
* These are the common builtin types that are used by VC++.
*/
@ -169,6 +170,12 @@ static void codeview_init_basic_types(struct module* module)
cv_basic_types[T_32PINT8] = &symt_new_pointer(module, cv_basic_types[T_INT8])->symt;
cv_basic_types[T_32PUINT8] = &symt_new_pointer(module, cv_basic_types[T_UINT8])->symt;
cv_basic_types[T_32PHRESULT]= &symt_new_pointer(module, cv_basic_types[T_HRESULT])->symt;
/* The .pdb file can refer to 64 bit pointers values even on 32 bits applications. */
udt = symt_new_udt(module, "PVOID64", 8, UdtStruct);
symt_add_udt_element(module, udt, "ptr64_low", cv_basic_types[T_LONG], 0, 32);
symt_add_udt_element(module, udt, "ptr64_high", cv_basic_types[T_LONG], 32, 32);
cv_basic_types[0x603]= &udt->symt;
}
static int leaf_as_variant(VARIANT* v, const unsigned short int* leaf)
@ -486,18 +493,23 @@ static int codeview_add_type(unsigned int typeno, struct symt* dt)
if ((typeno >> 24) != 0)
FIXME("No module index while inserting type-id assumption is wrong %x\n",
typeno);
while (typeno - FIRST_DEFINABLE_TYPE >= cv_current_module->num_defined_types)
if (typeno - FIRST_DEFINABLE_TYPE >= cv_current_module->num_defined_types)
{
cv_current_module->num_defined_types += 0x100;
if (cv_current_module->defined_types)
{
cv_current_module->num_defined_types = max( cv_current_module->num_defined_types * 2,
typeno - FIRST_DEFINABLE_TYPE + 1 );
cv_current_module->defined_types = HeapReAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY, cv_current_module->defined_types,
cv_current_module->num_defined_types * sizeof(struct symt*));
}
else
{
cv_current_module->num_defined_types = max( 256, typeno - FIRST_DEFINABLE_TYPE + 1 );
cv_current_module->defined_types = HeapAlloc(GetProcessHeap(),
HEAP_ZERO_MEMORY,
cv_current_module->num_defined_types * sizeof(struct symt*));
}
if (cv_current_module->defined_types == NULL) return FALSE;
}
if (cv_current_module->defined_types[typeno - FIRST_DEFINABLE_TYPE])
@ -581,15 +593,8 @@ static struct symt* codeview_add_type_array(struct codeview_type_parse* ctp,
{
struct symt* elem = codeview_fetch_type(ctp, elemtype, FALSE);
struct symt* index = codeview_fetch_type(ctp, indextype, FALSE);
DWORD arr_max = 0;
if (elem)
{
DWORD64 elem_size;
symt_get_info(elem, TI_GET_LENGTH, &elem_size);
if (elem_size) arr_max = arr_len / (DWORD)elem_size;
}
return &symt_new_array(ctp->module, 0, arr_max, elem, index)->symt;
return &symt_new_array(ctp->module, 0, -arr_len, elem, index)->symt;
}
static int codeview_add_type_enum_field_list(struct module* module,
@ -669,7 +674,7 @@ static void codeview_add_udt_element(struct codeview_type_parse* ctp,
if (subtype)
{
DWORD64 elem_size = 0;
symt_get_info(subtype, TI_GET_LENGTH, &elem_size);
symt_get_info(ctp->module, subtype, TI_GET_LENGTH, &elem_size);
symt_add_udt_element(ctp->module, symt, name, subtype,
value << 3, (DWORD)elem_size << 3);
}
@ -1357,48 +1362,72 @@ static void codeview_snarf_linetab(const struct msc_debug_info* msc_dbg, const B
}
static void codeview_snarf_linetab2(const struct msc_debug_info* msc_dbg, const BYTE* linetab, DWORD size,
const char* strimage, DWORD strsize)
const char* strimage, DWORD strsize)
{
DWORD offset;
unsigned i;
DWORD addr;
const struct codeview_linetab2_block* lbh;
const struct codeview_linetab2_file* fd;
const struct codeview_linetab2* lt2;
const struct codeview_linetab2* lt2_files = NULL;
const struct codeview_lt2blk_lines* lines_blk;
const struct codeview_linetab2_file*fd;
unsigned source;
struct symt_function* func;
if (*(const DWORD*)linetab != 0x000000f4) return;
offset = *((const DWORD*)linetab + 1);
for (lbh = (const struct codeview_linetab2_block*)(linetab + 8 + offset);
(const BYTE*)lbh < linetab + size;
lbh = (const struct codeview_linetab2_block*)((const char*)lbh + 8 + lbh->size_of_block))
/* locate LT2_FILES_BLOCK (if any) */
lt2 = (const struct codeview_linetab2*)linetab;
while ((const BYTE*)(lt2 + 1) < linetab + size)
{
if (lbh->header != 0x000000f2)
/* FIXME: should also check that whole lbh fits in linetab + size */
if (lt2->header == LT2_FILES_BLOCK)
{
TRACE("block end %x\n", lbh->header);
lt2_files = lt2;
break;
}
addr = codeview_get_address(msc_dbg, lbh->seg, lbh->start);
TRACE("block from %04x:%08x #%x (%x lines)\n",
lbh->seg, lbh->start, lbh->size, lbh->nlines);
fd = (const struct codeview_linetab2_file*)(linetab + 8 + lbh->file_offset);
/* FIXME: should check that string is within strimage + strsize */
source = source_new(msc_dbg->module, NULL, strimage + fd->offset);
func = (struct symt_function*)symt_find_nearest(msc_dbg->module, addr);
/* FIXME: at least labels support line numbers */
if (!func || func->symt.tag != SymTagFunction)
lt2 = codeview_linetab2_next_block(lt2);
}
if (!lt2_files)
{
TRACE("No LT2_FILES_BLOCK found\n");
return;
}
lt2 = (const struct codeview_linetab2*)linetab;
while ((const BYTE*)(lt2 + 1) < linetab + size)
{
/* FIXME: should also check that whole lines_blk fits in linetab + size */
switch (lt2->header)
{
WARN("--not a func at %04x:%08x %x tag=%d\n",
lbh->seg, lbh->start, addr, func ? func->symt.tag : -1);
case LT2_LINES_BLOCK:
lines_blk = (const struct codeview_lt2blk_lines*)lt2;
/* FIXME: should check that file_offset is within the LT2_FILES_BLOCK we've seen */
addr = codeview_get_address(msc_dbg, lines_blk->seg, lines_blk->start);
TRACE("block from %04x:%08x #%x (%x lines)\n",
lines_blk->seg, lines_blk->start, lines_blk->size, lines_blk->nlines);
fd = (const struct codeview_linetab2_file*)((const char*)lt2_files + 8 + lines_blk->file_offset);
/* FIXME: should check that string is within strimage + strsize */
source = source_new(msc_dbg->module, NULL, strimage + fd->offset);
func = (struct symt_function*)symt_find_nearest(msc_dbg->module, addr);
/* FIXME: at least labels support line numbers */
if (!func || func->symt.tag != SymTagFunction)
{
WARN("--not a func at %04x:%08x %x tag=%d\n",
lines_blk->seg, lines_blk->start, addr, func ? func->symt.tag : -1);
break;
}
for (i = 0; i < lines_blk->nlines; i++)
{
symt_add_func_line(msc_dbg->module, func, source,
lines_blk->l[i].lineno ^ 0x80000000,
lines_blk->l[i].offset);
}
break;
case LT2_FILES_BLOCK: /* skip */
break;
default:
TRACE("Block end %x\n", lt2->header);
lt2 = (const struct codeview_linetab2*)((const char*)linetab + size);
continue;
}
for (i = 0; i < lbh->nlines; i++)
{
symt_add_func_line(msc_dbg->module, func, source,
lbh->l[i].lineno ^ 0x80000000, lbh->l[i].offset - lbh->start);
}
lt2 = codeview_linetab2_next_block(lt2);
}
}
@ -1897,8 +1926,7 @@ static int codeview_snarf_public(const struct msc_debug_info* msc_dbg, const BYT
{
symt_new_public(msc_dbg->module, compiland,
terminate_string(&sym->data_v1.p_name),
codeview_get_address(msc_dbg, sym->data_v1.segment, sym->data_v1.offset),
1, TRUE /* FIXME */, TRUE /* FIXME */);
codeview_get_address(msc_dbg, sym->data_v1.segment, sym->data_v1.offset), 1);
}
break;
case S_PUB_V2: /* FIXME is this really a 'data_v2' structure ?? */
@ -1906,8 +1934,7 @@ static int codeview_snarf_public(const struct msc_debug_info* msc_dbg, const BYT
{
symt_new_public(msc_dbg->module, compiland,
terminate_string(&sym->data_v2.p_name),
codeview_get_address(msc_dbg, sym->data_v2.segment, sym->data_v2.offset),
1, TRUE /* FIXME */, TRUE /* FIXME */);
codeview_get_address(msc_dbg, sym->data_v2.segment, sym->data_v2.offset), 1);
}
break;
@ -1916,8 +1943,7 @@ static int codeview_snarf_public(const struct msc_debug_info* msc_dbg, const BYT
{
symt_new_public(msc_dbg->module, compiland,
sym->data_v3.name,
codeview_get_address(msc_dbg, sym->data_v3.segment, sym->data_v3.offset),
1, FALSE /* FIXME */, FALSE);
codeview_get_address(msc_dbg, sym->data_v3.segment, sym->data_v3.offset), 1);
}
break;
case S_PUB_FUNC1_V3:
@ -1928,8 +1954,7 @@ static int codeview_snarf_public(const struct msc_debug_info* msc_dbg, const BYT
{
symt_new_public(msc_dbg->module, compiland,
sym->data_v3.name,
codeview_get_address(msc_dbg, sym->data_v3.segment, sym->data_v3.offset),
1, TRUE /* FIXME */, TRUE);
codeview_get_address(msc_dbg, sym->data_v3.segment, sym->data_v3.offset), 1);
}
#endif
break;
@ -2150,7 +2175,7 @@ static void pdb_convert_symbol_file(const PDB_SYMBOLS* symbols,
{
if (symbols->version < 19970000)
{
const PDB_SYMBOL_FILE *sym_file = (const PDB_SYMBOL_FILE*)image;
const PDB_SYMBOL_FILE *sym_file = image;
memset(sfile, 0, sizeof(*sfile));
sfile->file = sym_file->file;
sfile->range.index = sym_file->range.index;
@ -2217,7 +2242,8 @@ static void pdb_process_types(const struct msc_debug_info* msc_dbg,
case 19950410: /* VC 4.0 */
case 19951122:
case 19961031: /* VC 5.0 / 6.0 */
case 19990903:
case 19990903: /* VC 7.0 */
case 20040203: /* VC 8.0 */
break;
default:
ERR("-Unknown type info version %d\n", types.version);
@ -2385,7 +2411,7 @@ static void pdb_process_symbol_imports(const struct process* pcs,
imp = (const PDB_SYMBOL_IMPORT*)((const char*)symbols_image + sizeof(PDB_SYMBOLS) +
symbols->module_size + symbols->offset_size +
symbols->hash_size + symbols->srcmodule_size);
first = (const char*)imp;
first = imp;
last = (const char*)imp + symbols->pdbimport_size;
while (imp < (const PDB_SYMBOL_IMPORT*)last)
{
@ -2524,7 +2550,7 @@ static BOOL pdb_process_internal(const struct process* pcs,
}
file_name = (const char*)file + size;
file_name += strlen(file_name) + 1;
file = (BYTE*)((DWORD)(file_name + strlen(file_name) + 1 + 3) & ~3);
file = (BYTE*)((DWORD_PTR)(file_name + strlen(file_name) + 1 + 3) & ~3);
}
/* finish the remaining public and global information */
if (globalimage)

View file

@ -234,7 +234,7 @@ static BOOL do_searchW(PCWSTR file, PWSTR buffer, BOOL recurse,
strcpyW(buffer + pos, fd.cFileName);
if (recurse && (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
found = do_searchW(file, buffer, TRUE, cb, user);
else if (SymMatchFileNameW(buffer, (WCHAR*)file, NULL, NULL))
else if (SymMatchFileNameW(buffer, file, NULL, NULL))
{
if (!cb || cb(buffer, user)) found = TRUE;
}
@ -340,13 +340,13 @@ struct sffip
*/
static BOOL CALLBACK sffip_cb(PCWSTR buffer, PVOID user)
{
struct sffip* s = (struct sffip*)user;
struct sffip* s = user;
if (!s->cb) return TRUE;
/* yes, EnumDirTree/do_search and SymFindFileInPath callbacks use the opposite
* convention to stop/continue enumeration. sigh.
*/
return !(s->cb)((WCHAR*)buffer, s->user);
return !(s->cb)(buffer, s->user);
}
/******************************************************************
@ -461,7 +461,7 @@ struct module_find
*/
static BOOL CALLBACK module_find_cb(PCWSTR buffer, PVOID user)
{
struct module_find* mf = (struct module_find*)user;
struct module_find* mf = user;
DWORD size, checksum, timestamp;
unsigned matched = 0;
@ -522,6 +522,21 @@ static BOOL CALLBACK module_find_cb(PCWSTR buffer, PVOID user)
return FALSE;
}
break;
case DMT_MACHO:
if (macho_fetch_file_info(buffer, 0, &size, &checksum))
{
matched++;
if (checksum == mf->dw1) matched++;
else
WARN("Found %s, but wrong checksums: %08x %08x\n",
debugstr_w(buffer), checksum, mf->dw1);
}
else
{
WARN("Couldn't read %s\n", debugstr_w(buffer));
return FALSE;
}
break;
case DMT_PDB:
{
struct pdb_lookup pdb_lookup;
@ -580,7 +595,7 @@ static BOOL CALLBACK module_find_cb(PCWSTR buffer, PVOID user)
if ((mapping = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0)) != NULL)
{
const IMAGE_SEPARATE_DEBUG_HEADER* hdr;
hdr = (const IMAGE_SEPARATE_DEBUG_HEADER*)mapping;
hdr = mapping;
if (hdr->Signature == IMAGE_SEPARATE_DEBUG_SIGNATURE)
{

View file

@ -35,6 +35,141 @@
WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
/******************************************************************
* pe_locate_with_coff_symbol_table
*
* Use the COFF symbol table (if any) from the IMAGE_FILE_HEADER to set the absolute address
* of global symbols.
* Mingw32 requires this for stabs debug information as address for global variables isn't filled in
* (this is similar to what is done in elf_module.c when using the .symtab ELF section)
*/
static BOOL pe_locate_with_coff_symbol_table(struct module* module, IMAGE_NT_HEADERS* nth, void* mapping)
{
const IMAGE_SYMBOL* isym;
int i, numsym, naux;
const char* strtable;
char tmp[9];
const char* name;
struct hash_table_iter hti;
void* ptr;
struct symt_data* sym;
const IMAGE_SECTION_HEADER* sect;
numsym = nth->FileHeader.NumberOfSymbols;
if (!nth->FileHeader.PointerToSymbolTable || !numsym)
return TRUE;
isym = (const IMAGE_SYMBOL*)((char*)mapping + nth->FileHeader.PointerToSymbolTable);
/* FIXME: no way to get strtable size */
strtable = (const char*)&isym[numsym];
sect = IMAGE_FIRST_SECTION(nth);
for (i = 0; i < numsym; i+= naux, isym += naux)
{
if (isym->StorageClass == IMAGE_SYM_CLASS_EXTERNAL &&
isym->SectionNumber > 0 && isym->SectionNumber <= nth->FileHeader.NumberOfSections)
{
if (isym->N.Name.Short)
{
name = memcpy(tmp, isym->N.ShortName, 8);
tmp[8] = '\0';
}
else name = strtable + isym->N.Name.Long;
if (name[0] == '_') name++;
hash_table_iter_init(&module->ht_symbols, &hti, name);
while ((ptr = hash_table_iter_up(&hti)))
{
sym = GET_ENTRY(ptr, struct symt_data, hash_elt);
if (sym->symt.tag == SymTagData &&
(sym->kind == DataIsGlobal || sym->kind == DataIsFileStatic) &&
!strcmp(sym->hash_elt.name, name))
{
TRACE("Changing absolute address for %d.%s: %lx -> %s\n",
isym->SectionNumber, name, sym->u.var.offset,
wine_dbgstr_longlong(module->module.BaseOfImage +
sect[isym->SectionNumber - 1].VirtualAddress + isym->Value));
sym->u.var.offset = module->module.BaseOfImage +
sect[isym->SectionNumber - 1].VirtualAddress + isym->Value;
break;
}
}
}
naux = isym->NumberOfAuxSymbols + 1;
}
return TRUE;
}
/******************************************************************
* pe_load_coff_symbol_table
*
* Load public symbols out of the COFF symbol table (if any).
*/
static BOOL pe_load_coff_symbol_table(struct module* module, IMAGE_NT_HEADERS* nth, void* mapping)
{
const IMAGE_SYMBOL* isym;
int i, numsym, naux;
const char* strtable;
char tmp[9];
const char* name;
const char* lastfilename = NULL;
struct symt_compiland* compiland = NULL;
const IMAGE_SECTION_HEADER* sect;
numsym = nth->FileHeader.NumberOfSymbols;
if (!nth->FileHeader.PointerToSymbolTable || !numsym)
return TRUE;
isym = (const IMAGE_SYMBOL*)((char*)mapping + nth->FileHeader.PointerToSymbolTable);
/* FIXME: no way to get strtable size */
strtable = (const char*)&isym[numsym];
sect = IMAGE_FIRST_SECTION(nth);
for (i = 0; i < numsym; i+= naux, isym += naux)
{
if (isym->StorageClass == IMAGE_SYM_CLASS_FILE)
{
lastfilename = (const char*)(isym + 1);
compiland = NULL;
}
if (isym->StorageClass == IMAGE_SYM_CLASS_EXTERNAL &&
isym->SectionNumber > 0 && isym->SectionNumber <= nth->FileHeader.NumberOfSections)
{
if (isym->N.Name.Short)
{
name = memcpy(tmp, isym->N.ShortName, 8);
tmp[8] = '\0';
}
else name = strtable + isym->N.Name.Long;
if (name[0] == '_') name++;
if (!compiland && lastfilename)
compiland = symt_new_compiland(module, 0,
source_new(module, NULL, lastfilename));
symt_new_public(module, compiland, name,
module->module.BaseOfImage + sect[isym->SectionNumber - 1].VirtualAddress + isym->Value,
1);
}
naux = isym->NumberOfAuxSymbols + 1;
}
module->module.SymType = SymCoff;
module->module.LineNumbers = FALSE;
module->module.GlobalSymbols = FALSE;
module->module.TypeInfo = FALSE;
module->module.SourceIndexed = FALSE;
module->module.Publics = TRUE;
return TRUE;
}
static inline void* pe_get_sect(IMAGE_NT_HEADERS* nth, void* mapping,
IMAGE_SECTION_HEADER* sect)
{
return (sect) ? RtlImageRvaToVa(nth, mapping, sect->VirtualAddress, NULL) : NULL;
}
static inline DWORD pe_get_sect_size(IMAGE_SECTION_HEADER* sect)
{
return (sect) ? sect->SizeOfRawData : 0;
}
/******************************************************************
* pe_load_stabs
*
@ -45,37 +180,85 @@ static BOOL pe_load_stabs(const struct process* pcs, struct module* module,
void* mapping, IMAGE_NT_HEADERS* nth)
{
IMAGE_SECTION_HEADER* section;
int i, stabsize = 0, stabstrsize = 0;
unsigned int stabs = 0, stabstr = 0;
IMAGE_SECTION_HEADER* sect_stabs = NULL;
IMAGE_SECTION_HEADER* sect_stabstr = NULL;
int i;
BOOL ret = FALSE;
section = (IMAGE_SECTION_HEADER*)
((char*)&nth->OptionalHeader + nth->FileHeader.SizeOfOptionalHeader);
for (i = 0; i < nth->FileHeader.NumberOfSections; i++, section++)
{
if (!strcasecmp((const char*)section->Name, ".stab"))
{
stabs = section->VirtualAddress;
stabsize = section->SizeOfRawData;
}
else if (!strncasecmp((const char*)section->Name, ".stabstr", 8))
{
stabstr = section->VirtualAddress;
stabstrsize = section->SizeOfRawData;
}
if (!strcasecmp((const char*)section->Name, ".stab")) sect_stabs = section;
else if (!strncasecmp((const char*)section->Name, ".stabstr", 8)) sect_stabstr = section;
}
if (stabstrsize && stabsize)
if (sect_stabs && sect_stabstr)
{
ret = stabs_parse(module,
module->module.BaseOfImage - nth->OptionalHeader.ImageBase,
RtlImageRvaToVa(nth, mapping, stabs, NULL),
stabsize,
RtlImageRvaToVa(nth, mapping, stabstr, NULL),
stabstrsize);
ret = stabs_parse(module,
module->module.BaseOfImage - nth->OptionalHeader.ImageBase,
pe_get_sect(nth, mapping, sect_stabs), pe_get_sect_size(sect_stabs),
pe_get_sect(nth, mapping, sect_stabstr), pe_get_sect_size(sect_stabstr),
NULL, NULL);
if (ret) pe_locate_with_coff_symbol_table(module, nth, mapping);
}
TRACE("%s the STABS debug info\n", ret ? "successfully loaded" : "failed to load");
return ret;
}
/******************************************************************
* pe_load_dwarf
*
* look for dwarf information in PE header (it's also a way for the mingw compiler
* to provide its debugging information)
*/
static BOOL pe_load_dwarf(const struct process* pcs, struct module* module,
void* mapping, IMAGE_NT_HEADERS* nth)
{
IMAGE_SECTION_HEADER* section;
IMAGE_SECTION_HEADER* sect_debuginfo = NULL;
IMAGE_SECTION_HEADER* sect_debugstr = NULL;
IMAGE_SECTION_HEADER* sect_debugabbrev = NULL;
IMAGE_SECTION_HEADER* sect_debugline = NULL;
IMAGE_SECTION_HEADER* sect_debugloc = NULL;
int i;
const char* strtable;
const char* sectname;
BOOL ret = FALSE;
if (nth->FileHeader.PointerToSymbolTable && nth->FileHeader.NumberOfSymbols)
/* FIXME: no way to get strtable size */
strtable = (const char*)mapping + nth->FileHeader.PointerToSymbolTable +
nth->FileHeader.NumberOfSymbols * sizeof(IMAGE_SYMBOL);
else strtable = NULL;
section = (IMAGE_SECTION_HEADER*)
((char*)&nth->OptionalHeader + nth->FileHeader.SizeOfOptionalHeader);
for (i = 0; i < nth->FileHeader.NumberOfSections; i++, section++)
{
sectname = (const char*)section->Name;
/* long section names start with a '/' (at least on MinGW32) */
if (*sectname == '/' && strtable)
sectname = strtable + atoi(sectname + 1);
if (!strcasecmp(sectname, ".debug_info")) sect_debuginfo = section;
else if (!strcasecmp(sectname, ".debug_str")) sect_debugstr = section;
else if (!strcasecmp(sectname, ".debug_abbrev")) sect_debugabbrev = section;
else if (!strcasecmp(sectname, ".debug_line")) sect_debugline = section;
else if (!strcasecmp(sectname, ".debug_loc")) sect_debugloc = section;
}
if (sect_debuginfo)
{
ret = dwarf2_parse(module,
module->module.BaseOfImage - nth->OptionalHeader.ImageBase,
NULL, /* FIXME: some thunks to deal with ? */
pe_get_sect(nth, mapping, sect_debuginfo), pe_get_sect_size(sect_debuginfo),
pe_get_sect(nth, mapping, sect_debugabbrev), pe_get_sect_size(sect_debugabbrev),
pe_get_sect(nth, mapping, sect_debugstr), pe_get_sect_size(sect_debugstr),
pe_get_sect(nth, mapping, sect_debugline), pe_get_sect_size(sect_debugline),
pe_get_sect(nth, mapping, sect_debugloc), pe_get_sect_size(sect_debugloc));
}
TRACE("%s the DWARF debug info\n", ret ? "successfully loaded" : "failed to load");
return ret;
}
@ -133,7 +316,7 @@ static BOOL pe_load_dbg_file(const struct process* pcs, struct module* module,
*/
static BOOL pe_load_msc_debug_info(const struct process* pcs,
struct module* module,
void* mapping, IMAGE_NT_HEADERS* nth)
void* mapping, const IMAGE_NT_HEADERS* nth)
{
BOOL ret = FALSE;
const IMAGE_DATA_DIRECTORY* dir;
@ -181,7 +364,7 @@ static BOOL pe_load_msc_debug_info(const struct process* pcs,
*/
static BOOL pe_load_export_debug_info(const struct process* pcs,
struct module* module,
void* mapping, IMAGE_NT_HEADERS* nth)
void* mapping, const IMAGE_NT_HEADERS* nth)
{
unsigned int i;
const IMAGE_EXPORT_DIRECTORY* exports;
@ -193,14 +376,12 @@ static BOOL pe_load_export_debug_info(const struct process* pcs,
#if 0
/* Add start of DLL (better use the (yet unimplemented) Exe SymTag for this) */
/* FIXME: module.ModuleName isn't correctly set yet if it's passed in SymLoadModule */
symt_new_public(module, NULL, module->module.ModuleName, base, 1,
TRUE /* FIXME */, TRUE /* FIXME */);
symt_new_public(module, NULL, module->module.ModuleName, base, 1);
#endif
/* Add entry point */
symt_new_public(module, NULL, "EntryPoint",
base + nth->OptionalHeader.AddressOfEntryPoint, 1,
TRUE, TRUE);
base + nth->OptionalHeader.AddressOfEntryPoint, 1);
#if 0
/* FIXME: we'd better store addresses linked to sections rather than
absolute values */
@ -211,8 +392,7 @@ static BOOL pe_load_export_debug_info(const struct process* pcs,
for (i = 0; i < nth->FileHeader.NumberOfSections; i++, section++)
{
symt_new_public(module, NULL, section->Name,
RtlImageRvaToVa(nth, mapping, section->VirtualAddress, NULL),
1, TRUE /* FIXME */, TRUE /* FIXME */);
RtlImageRvaToVa(nth, mapping, section->VirtualAddress, NULL), 1);
}
#endif
@ -237,8 +417,7 @@ static BOOL pe_load_export_debug_info(const struct process* pcs,
if (!names[i]) continue;
symt_new_public(module, NULL,
RtlImageRvaToVa(nth, mapping, names[i], NULL),
base + functions[ordinals[i]],
1, TRUE /* FIXME */, TRUE /* FIXME */);
base + functions[ordinals[i]], 1);
}
for (i = 0; i < exports->NumberOfFunctions; i++)
@ -249,8 +428,7 @@ static BOOL pe_load_export_debug_info(const struct process* pcs,
if ((ordinals[j] == i) && names[j]) break;
if (j < exports->NumberOfNames) continue;
snprintf(buffer, sizeof(buffer), "%d", i + exports->Base);
symt_new_public(module, NULL, buffer, base + (DWORD)functions[i], 1,
TRUE /* FIXME */, TRUE /* FIXME */);
symt_new_public(module, NULL, buffer, base + (DWORD)functions[i], 1);
}
}
}
@ -284,7 +462,9 @@ BOOL pe_load_debug_info(const struct process* pcs, struct module* module)
if (!(dbghelp_options & SYMOPT_PUBLICS_ONLY))
{
ret = pe_load_stabs(pcs, module, mapping, nth) ||
pe_load_msc_debug_info(pcs, module, mapping, nth);
pe_load_dwarf(pcs, module, mapping, nth) ||
pe_load_msc_debug_info(pcs, module, mapping, nth) ||
pe_load_coff_symbol_table(module, nth, mapping);
/* if we still have no debug info (we could only get SymExport at this
* point), then do the SymExport except if we have an ELF container,
* in which case we'll rely on the export's on the ELF side
@ -367,13 +547,13 @@ struct module* pe_load_native_module(struct process* pcs, const WCHAR* name,
* pe_load_nt_header
*
*/
BOOL pe_load_nt_header(HANDLE hProc, DWORD base, IMAGE_NT_HEADERS* nth)
BOOL pe_load_nt_header(HANDLE hProc, DWORD64 base, IMAGE_NT_HEADERS* nth)
{
IMAGE_DOS_HEADER dos;
return ReadProcessMemory(hProc, (char*)base, &dos, sizeof(dos), NULL) &&
return ReadProcessMemory(hProc, (char*)(DWORD_PTR)base, &dos, sizeof(dos), NULL) &&
dos.e_magic == IMAGE_DOS_SIGNATURE &&
ReadProcessMemory(hProc, (char*)(base + dos.e_lfanew),
ReadProcessMemory(hProc, (char*)(DWORD_PTR)(base + dos.e_lfanew),
nth, sizeof(*nth), NULL) &&
nth->Signature == IMAGE_NT_SIGNATURE;
}
@ -383,7 +563,7 @@ BOOL pe_load_nt_header(HANDLE hProc, DWORD base, IMAGE_NT_HEADERS* nth)
*
*/
struct module* pe_load_builtin_module(struct process* pcs, const WCHAR* name,
DWORD base, DWORD size)
DWORD64 base, DWORD64 size)
{
struct module* module = NULL;
@ -435,7 +615,7 @@ PVOID WINAPI ImageDirectoryEntryToDataEx( PVOID base, BOOLEAN image, USHORT dir,
*size = nt->OptionalHeader.DataDirectory[dir].Size;
if (image || addr < nt->OptionalHeader.SizeOfHeaders) return (char *)base + addr;
return RtlImageRvaToVa( nt, (HMODULE)base, addr, section );
return RtlImageRvaToVa( nt, base, addr, section );
}
/***********************************************************************

View file

@ -309,42 +309,6 @@ SymGetHomeDirectoryW(DWORD dwType,
return NULL;
}
BOOL WINAPI
SymGetLineFromName64(HANDLE hProcess,
PCSTR pszModuleName,
PCSTR pszFileName,
DWORD dwLineNumber,
PLONG plDisplacement,
PIMAGEHLP_LINE64 Line)
{
UNIMPLEMENTED;
return FALSE;
}
BOOL WINAPI
SymGetLineFromName(HANDLE hProcess,
PCSTR pszModuleName,
PCSTR pszFileName,
DWORD dwLineNumber,
PLONG plDisplacement,
PIMAGEHLP_LINE Line)
{
UNIMPLEMENTED;
return FALSE;
}
BOOL WINAPI
SymGetLineFromNameW64(HANDLE hProcess,
PCWSTR pszModuleName,
PCWSTR pszFileName,
DWORD dwLineNumber,
PLONG lpDisplacement,
PIMAGEHLP_LINEW64 Line)
{
UNIMPLEMENTED;
return FALSE;
}
BOOL WINAPI
SymGetLineNextW64(HANDLE hProcess,
PIMAGEHLP_LINEW64 Line)
@ -459,31 +423,6 @@ SymGetSourceVarFromTokenW(
return FALSE;
}
BOOL WINAPI
SymGetSymFromName64(HANDLE hProcess,
PCSTR pszName,
PIMAGEHLP_SYMBOL64 Symbol)
{
UNIMPLEMENTED;
return FALSE;
}
BOOL WINAPI
SymGetSymNext64(HANDLE hProcess,
PIMAGEHLP_SYMBOL64 Symbol)
{
UNIMPLEMENTED;
return FALSE;
}
BOOL WINAPI
SymGetSymPrev64(HANDLE hProcess,
PIMAGEHLP_SYMBOL64 Symbol)
{
UNIMPLEMENTED;
return FALSE;
}
BOOL WINAPI
SymGetSymbolFile(HANDLE hProcess,
PCSTR pszSymPath,
@ -581,16 +520,6 @@ SymPrevW(HANDLE hProcess,
return FALSE;
}
BOOL
WINAPI
SymRefreshModuleList(
HANDLE hProcess)
{
UNIMPLEMENTED;
return FALSE;
}
PCHAR WINAPI
SymSetHomeDirectory(HANDLE hProcess,
PCSTR pszDir)
@ -766,15 +695,6 @@ SymSrvStoreSupplementW(HANDLE hProcess,
return NULL;
}
BOOL WINAPI
SymUnDName64(PIMAGEHLP_SYMBOL64 Symbol,
PSTR pszUndecoratedName,
DWORD dwUndecoratedNameLength)
{
UNIMPLEMENTED;
return FALSE;
}
DWORD WINAPI
UnDecorateSymbolNameW(PCWSTR DecoratedName,
PWSTR pszUnDecoratedName,

View file

@ -26,9 +26,6 @@
#include "dbghelp_private.h"
#include "wine/debug.h"
#ifdef HAVE_REGEX_H
# include <regex.h>
#endif
WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
@ -79,13 +76,18 @@ unsigned source_new(struct module* module, const char* base, const char* name)
int len = strlen(full) + 1;
if (module->sources_used + len + 1 > module->sources_alloc)
{
/* Alloc by block of 256 bytes */
module->sources_alloc = (module->sources_used + len + 1 + 255) & ~255;
if (!module->sources)
{
module->sources_alloc = (module->sources_used + len + 1 + 255) & ~255;
module->sources = HeapAlloc(GetProcessHeap(), 0, module->sources_alloc);
}
else
{
module->sources_alloc = max( module->sources_alloc * 2,
(module->sources_used + len + 1 + 255) & ~255 );
module->sources = HeapReAlloc(GetProcessHeap(), 0, module->sources,
module->sources_alloc);
}
}
ret = module->sources_used;
memcpy(module->sources + module->sources_used, full, len);
@ -154,116 +156,6 @@ BOOL WINAPI SymEnumSourceFiles(HANDLE hProcess, ULONG64 ModBase, PCSTR Mask,
return TRUE;
}
static inline void re_append(char** mask, unsigned* len, char ch)
{
*mask = HeapReAlloc(GetProcessHeap(), 0, *mask, ++(*len));
(*mask)[*len - 2] = ch;
}
static BOOL compile_regex(regex_t* re, const char* srcfile)
{
char* mask;
unsigned len = 1;
mask = HeapAlloc(GetProcessHeap(), 0, 1);
re_append(&mask, &len, '^');
if (!srcfile || !*srcfile) re_append(&mask, &len, '*');
else while (*srcfile)
{
switch (*srcfile)
{
case '\\':
case '/':
re_append(&mask, &len, '[');
re_append(&mask, &len, '\\');
re_append(&mask, &len, '\\');
re_append(&mask, &len, '/');
re_append(&mask, &len, ']');
break;
case '.':
re_append(&mask, &len, '\\');
re_append(&mask, &len, '.');
break;
default:
re_append(&mask, &len, *srcfile);
break;
}
srcfile++;
}
re_append(&mask, &len, '$');
mask[len - 1] = '\0';
len = regcomp(re, mask, REG_NOSUB);
HeapFree(GetProcessHeap(), 0, mask);
if (len)
{
FIXME("Couldn't compile %s\n", mask);
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
return TRUE;
}
/******************************************************************
* SymEnumLines (DBGHELP.@)
*
*/
BOOL WINAPI SymEnumLines(HANDLE hProcess, ULONG64 base, PCSTR compiland,
PCSTR srcfile, PSYM_ENUMLINES_CALLBACK cb, PVOID user)
{
struct module_pair pair;
struct hash_table_iter hti;
struct symt_ht* sym;
regex_t re;
struct line_info* dli;
void* ptr;
SRCCODEINFO sci;
const char* file;
if (!cb) return FALSE;
if (!(dbghelp_options & SYMOPT_LOAD_LINES)) return TRUE;
pair.pcs = process_find_by_handle(hProcess);
if (!pair.pcs) return FALSE;
if (compiland) FIXME("Unsupported yet (filtering on compiland %s)\n", compiland);
pair.requested = module_find_by_addr(pair.pcs, base, DMT_UNKNOWN);
if (!module_get_debug(&pair)) return FALSE;
if (!compile_regex(&re, srcfile)) return FALSE;
sci.SizeOfStruct = sizeof(sci);
sci.ModBase = base;
hash_table_iter_init(&pair.effective->ht_symbols, &hti, NULL);
while ((ptr = hash_table_iter_up(&hti)))
{
unsigned int i;
sym = GET_ENTRY(ptr, struct symt_ht, hash_elt);
if (sym->symt.tag != SymTagFunction) continue;
sci.FileName[0] = '\0';
for (i=0; i<vector_length(&((struct symt_function*)sym)->vlines); i++)
{
dli = vector_at(&((struct symt_function*)sym)->vlines, i);
if (dli->is_source_file)
{
file = source_get(pair.effective, dli->u.source_file);
if (regexec(&re, file, 0, NULL, 0) != 0) file = "";
strcpy(sci.FileName, file);
}
else if (sci.FileName[0])
{
sci.Key = dli;
sci.Obj[0] = '\0'; /* FIXME */
sci.LineNumber = dli->line_number;
sci.Address = dli->u.pc_offset;
if (!cb(&sci, user)) break;
}
}
}
regfree(&re);
return TRUE;
}
/******************************************************************
* SymGetSourceFileToken (DBGHELP.@)
*

View file

@ -26,7 +26,7 @@
* The "stabs" debug format
* by Julia Menapace, Jim Kingdon, David Mackenzie
* of Cygnus Support
* available (hopefully) from http:\\sources.redhat.com\gdb\onlinedocs
* available (hopefully) from http://sources.redhat.com/gdb/onlinedocs
*/
#include "config.h"
@ -53,6 +53,10 @@
#include <assert.h>
#include <stdarg.h>
#ifdef HAVE_MACH_O_NLIST_H
# include <mach-o/nlist.h>
#endif
#include "windef.h"
#include "winbase.h"
#include "winnls.h"
@ -65,9 +69,24 @@ WINE_DEFAULT_DEBUG_CHANNEL(dbghelp_stabs);
#define strtoull _strtoui64
/* Masks for n_type field */
#ifndef N_STAB
#define N_STAB 0xe0
#endif
#ifndef N_TYPE
#define N_TYPE 0x1e
#endif
#ifndef N_EXT
#define N_EXT 0x01
#endif
/* Values for (n_type & N_TYPE) */
#ifndef N_UNDF
#define N_UNDF 0x00
#endif
#ifndef N_ABS
#define N_ABS 0x02
#endif
#define N_GSYM 0x20
#define N_FUN 0x24
@ -81,6 +100,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(dbghelp_stabs);
#define N_SLINE 0x44
#define N_ENSYM 0x4e
#define N_SO 0x64
#define N_OSO 0x66
#define N_LSYM 0x80
#define N_BINCL 0x82
#define N_SOL 0x84
@ -162,14 +182,18 @@ static int stabs_new_include(const char* file, unsigned long val)
{
if (num_include_def == num_alloc_include_def)
{
num_alloc_include_def += 256;
if (!include_defs)
include_defs = HeapAlloc(GetProcessHeap(), 0,
{
num_alloc_include_def = 256;
include_defs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof(include_defs[0]) * num_alloc_include_def);
}
else
include_defs = HeapReAlloc(GetProcessHeap(), 0, include_defs,
{
num_alloc_include_def *= 2;
include_defs = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, include_defs,
sizeof(include_defs[0]) * num_alloc_include_def);
memset(include_defs + num_include_def, 0, sizeof(include_defs[0]) * 256);
}
}
include_defs[num_include_def].name = strcpy(HeapAlloc(GetProcessHeap(), 0, strlen(file) + 1), file);
include_defs[num_include_def].value = val;
@ -244,13 +268,13 @@ static struct symt** stabs_find_ref(long filenr, long subnr)
{
if (cu_nrofentries <= subnr)
{
cu_nrofentries = max( cu_nrofentries * 2, subnr + 1 );
if (!cu_vector)
cu_vector = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof(cu_vector[0]) * (subnr+1));
cu_vector = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof(cu_vector[0]) * cu_nrofentries);
else
cu_vector = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
cu_vector, sizeof(cu_vector[0]) * (subnr+1));
cu_nrofentries = subnr + 1;
cu_vector = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
cu_vector, sizeof(cu_vector[0]) * cu_nrofentries);
}
ret = &cu_vector[subnr];
}
@ -263,13 +287,13 @@ static struct symt** stabs_find_ref(long filenr, long subnr)
if (idef->nrofentries <= subnr)
{
idef->nrofentries = max( idef->nrofentries * 2, subnr + 1 );
if (!idef->vector)
idef->vector = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof(idef->vector[0]) * (subnr+1));
idef->vector = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
sizeof(idef->vector[0]) * idef->nrofentries);
else
idef->vector = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
idef->vector, sizeof(idef->vector[0]) * (subnr+1));
idef->nrofentries = subnr + 1;
idef->vector = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
idef->vector, sizeof(idef->vector[0]) * idef->nrofentries);
}
ret = &idef->vector[subnr];
}
@ -630,25 +654,21 @@ static inline int stabs_pts_read_aggregate(struct ParseTypedefData* ptd,
PTS_ABORTIF(ptd, stabs_pts_read_type_def(ptd, NULL, &adt) == -1);
if (doadd)
if (doadd && adt)
{
char tmp[256];
WCHAR* name;
DWORD64 size;
symt_get_info(adt, TI_GET_SYMNAME, &name);
strcpy(tmp, "__inherited_class_");
WideCharToMultiByte(CP_ACP, 0, name, -1,
tmp + strlen(tmp), sizeof(tmp) - strlen(tmp),
NULL, NULL);
HeapFree(GetProcessHeap(), 0, name);
strcat(tmp, symt_get_name(adt));
/* FIXME: TI_GET_LENGTH will not always work, especially when adt
* has just been seen as a forward definition and not the real stuff
* yet.
* As we don't use much the size of members in structs, this may not
* be much of a problem
*/
symt_get_info(adt, TI_GET_LENGTH, &size);
symt_get_info(ptd->module, adt, TI_GET_LENGTH, &size);
symt_add_udt_element(ptd->module, sdt, tmp, adt, ofs, (DWORD)size * 8);
}
PTS_ABORTIF(ptd, *ptd->ptr++ != ';');
@ -1094,6 +1114,12 @@ static struct symt* stabs_parse_type(const char* stab)
return *stabs_read_type_enum(&c);
}
enum pending_obj_kind
{
PENDING_VAR,
PENDING_LINE,
};
struct pending_loc_var
{
char name[256];
@ -1102,44 +1128,99 @@ struct pending_loc_var
struct location loc;
};
struct pending_block
struct pending_line
{
struct pending_loc_var* vars;
int source_idx;
int line_num;
unsigned long offset;
unsigned long load_offset;
};
struct pending_object
{
enum pending_obj_kind tag;
union {
struct pending_loc_var var;
struct pending_line line;
} u;
};
struct pending_list
{
struct pending_object* objs;
unsigned num;
unsigned allocated;
};
static inline void pending_add(struct pending_block* pending, const char* name,
enum DataKind dt, const struct location* loc)
static inline void pending_make_room(struct pending_list* pending)
{
if (pending->num == pending->allocated)
{
pending->allocated += 8;
if (!pending->vars)
pending->vars = HeapAlloc(GetProcessHeap(), 0,
pending->allocated * sizeof(pending->vars[0]));
else
pending->vars = HeapReAlloc(GetProcessHeap(), 0, pending->vars,
pending->allocated * sizeof(pending->vars[0]));
if (!pending->objs)
{
pending->allocated = 8;
pending->objs = HeapAlloc(GetProcessHeap(), 0,
pending->allocated * sizeof(pending->objs[0]));
}
else
{
pending->allocated *= 2;
pending->objs = HeapReAlloc(GetProcessHeap(), 0, pending->objs,
pending->allocated * sizeof(pending->objs[0]));
}
}
stab_strcpy(pending->vars[pending->num].name,
sizeof(pending->vars[pending->num].name), name);
pending->vars[pending->num].type = stabs_parse_type(name);
pending->vars[pending->num].kind = dt;
pending->vars[pending->num].loc = *loc;
}
static inline void pending_add_var(struct pending_list* pending, const char* name,
enum DataKind dt, const struct location* loc)
{
pending_make_room(pending);
pending->objs[pending->num].tag = PENDING_VAR;
stab_strcpy(pending->objs[pending->num].u.var.name,
sizeof(pending->objs[pending->num].u.var.name), name);
pending->objs[pending->num].u.var.type = stabs_parse_type(name);
pending->objs[pending->num].u.var.kind = dt;
pending->objs[pending->num].u.var.loc = *loc;
pending->num++;
}
static void pending_flush(struct pending_block* pending, struct module* module,
static inline void pending_add_line(struct pending_list* pending, int source_idx,
int line_num, unsigned long offset,
unsigned long load_offset)
{
pending_make_room(pending);
pending->objs[pending->num].tag = PENDING_LINE;
pending->objs[pending->num].u.line.source_idx = source_idx;
pending->objs[pending->num].u.line.line_num = line_num;
pending->objs[pending->num].u.line.offset = offset;
pending->objs[pending->num].u.line.load_offset = load_offset;
pending->num++;
}
static void pending_flush(struct pending_list* pending, struct module* module,
struct symt_function* func, struct symt_block* block)
{
unsigned int i;
for (i = 0; i < pending->num; i++)
{
symt_add_func_local(module, func,
pending->vars[i].kind, &pending->vars[i].loc,
block, pending->vars[i].type, pending->vars[i].name);
switch (pending->objs[i].tag)
{
case PENDING_VAR:
symt_add_func_local(module, func,
pending->objs[i].u.var.kind, &pending->objs[i].u.var.loc,
block, pending->objs[i].u.var.type, pending->objs[i].u.var.name);
break;
case PENDING_LINE:
if (module->type == DMT_MACHO)
pending->objs[i].u.line.offset -= func->address - pending->objs[i].u.line.load_offset;
symt_add_func_line(module, func, pending->objs[i].u.line.source_idx,
pending->objs[i].u.line.line_num, pending->objs[i].u.line.offset);
break;
default:
ERR("Unknown pending object tag %u\n", (unsigned)pending->objs[i].tag);
break;
}
}
pending->num = 0;
}
@ -1156,7 +1237,7 @@ static void pending_flush(struct pending_block* pending, struct module* module,
static void stabs_finalize_function(struct module* module, struct symt_function* func,
unsigned long size)
{
IMAGEHLP_LINE il;
IMAGEHLP_LINE64 il;
struct location loc;
if (!func) return;
@ -1175,9 +1256,25 @@ static void stabs_finalize_function(struct module* module, struct symt_function*
if (size) func->size = size;
}
static inline void stabbuf_append(char **buf, unsigned *buf_size, const char *str)
{
unsigned str_len, buf_len;
str_len = strlen(str);
buf_len = strlen(*buf);
if(str_len+buf_len >= *buf_size) {
*buf_size += buf_len + str_len;
*buf = HeapReAlloc(GetProcessHeap(), 0, *buf, *buf_size);
}
strcpy(*buf+buf_len, str);
}
BOOL stabs_parse(struct module* module, unsigned long load_offset,
const void* pv_stab_ptr, int stablen,
const char* strs, int strtablen)
const char* strs, int strtablen,
stabs_def_cb callback, void* user)
{
struct symt_function* curr_func = NULL;
struct symt_block* block = NULL;
@ -1195,16 +1292,19 @@ BOOL stabs_parse(struct module* module, unsigned long load_offset,
unsigned incl[32];
int incl_stk = -1;
int source_idx = -1;
struct pending_block pending;
struct pending_list pending_block;
struct pending_list pending_func;
BOOL ret = TRUE;
struct location loc;
unsigned char type;
nstab = stablen / sizeof(struct stab_nlist);
strs_end = strs + strtablen;
memset(srcpath, 0, sizeof(srcpath));
memset(stabs_basic, 0, sizeof(stabs_basic));
memset(&pending, 0, sizeof(pending));
memset(&pending_block, 0, sizeof(pending_block));
memset(&pending_func, 0, sizeof(pending_func));
/*
* Allocate a buffer into which we can build stab strings for cases
@ -1230,23 +1330,22 @@ BOOL stabs_parse(struct module* module, unsigned long load_offset,
* next record. Repeat the process until we find a stab without the
* '/' character, as this indicates we have the whole thing.
*/
unsigned len = strlen(ptr);
if (strlen(stabbuff) + len > stabbufflen)
{
stabbufflen += 65536;
stabbuff = HeapReAlloc(GetProcessHeap(), 0, stabbuff, stabbufflen);
}
strncat(stabbuff, ptr, len - 1);
stabbuf_append(&stabbuff, &stabbufflen, ptr);
continue;
}
else if (stabbuff[0] != '\0')
{
strcat(stabbuff, ptr);
stabbuf_append(&stabbuff, &stabbufflen, ptr);
ptr = stabbuff;
}
if (stab_ptr->n_type & N_STAB)
type = stab_ptr->n_type;
else
type = (stab_ptr->n_type & N_TYPE);
/* only symbol entries contain a typedef */
switch (stab_ptr->n_type)
switch (type)
{
case N_GSYM:
case N_LCSYM:
@ -1263,7 +1362,8 @@ BOOL stabs_parse(struct module* module, unsigned long load_offset,
*/
if (ptr != stabbuff)
{
strcpy(stabbuff, ptr);
stabbuff[0] = 0;
stabbuf_append(&stabbuff, &stabbufflen, ptr);
ptr = stabbuff;
}
stab_strcpy(symname, sizeof(symname), ptr);
@ -1276,7 +1376,7 @@ BOOL stabs_parse(struct module* module, unsigned long load_offset,
}
}
switch (stab_ptr->n_type)
switch (type)
{
case N_GSYM:
/*
@ -1305,7 +1405,7 @@ BOOL stabs_parse(struct module* module, unsigned long load_offset,
{
block = symt_open_func_block(module, curr_func, block,
stab_ptr->n_value, 0);
pending_flush(&pending, module, curr_func, block);
pending_flush(&pending_block, module, curr_func, block);
}
break;
case N_RBRAC:
@ -1356,6 +1456,22 @@ BOOL stabs_parse(struct module* module, unsigned long load_offset,
case 17:
case 18:
case 19: loc.reg = CV_REG_ST0 + stab_ptr->n_value - 12; break;
case 21:
case 22:
case 23:
case 24:
case 25:
case 26:
case 27:
case 28: loc.reg = CV_REG_XMM0 + stab_ptr->n_value - 21; break;
case 29:
case 30:
case 31:
case 32:
case 33:
case 34:
case 35:
case 36: loc.reg = CV_REG_MM0 + stab_ptr->n_value - 29; break;
default:
FIXME("Unknown register value (%lu)\n", stab_ptr->n_value);
loc.reg = CV_REG_NONE;
@ -1373,7 +1489,7 @@ BOOL stabs_parse(struct module* module, unsigned long load_offset,
param_type);
}
else
pending_add(&pending, ptr, DataIsLocal, &loc);
pending_add_var(&pending_block, ptr, DataIsLocal, &loc);
}
break;
case N_LSYM:
@ -1381,19 +1497,24 @@ BOOL stabs_parse(struct module* module, unsigned long load_offset,
loc.kind = loc_regrel;
loc.reg = 0; /* FIXME */
loc.offset = stab_ptr->n_value;
if (curr_func != NULL) pending_add(&pending, ptr, DataIsLocal, &loc);
if (curr_func != NULL) pending_add_var(&pending_block, ptr, DataIsLocal, &loc);
break;
case N_SLINE:
/*
* This is a line number. These are always relative to the start
* of the function (N_FUN), and this makes the lookup easier.
*/
assert(source_idx >= 0);
if (curr_func != NULL)
{
assert(source_idx >= 0);
unsigned long offset = stab_ptr->n_value;
if (module->type == DMT_MACHO)
offset -= curr_func->address - load_offset;
symt_add_func_line(module, curr_func, source_idx,
stab_ptr->n_desc, stab_ptr->n_value);
stab_ptr->n_desc, offset);
}
else pending_add_line(&pending_func, source_idx, stab_ptr->n_desc,
stab_ptr->n_value, load_offset);
break;
case N_FUN:
/*
@ -1428,6 +1549,7 @@ BOOL stabs_parse(struct module* module, unsigned long load_offset,
curr_func = symt_new_function(module, compiland, symname,
load_offset + stab_ptr->n_value, 0,
&func_type->symt);
pending_flush(&pending_func, module, curr_func, NULL);
}
else
{
@ -1508,10 +1630,38 @@ BOOL stabs_parse(struct module* module, unsigned long load_offset,
break;
case N_BNSYM:
case N_ENSYM:
case N_OSO:
/* Always ignore these, they seem to be used only on Darwin. */
break;
case N_ABS:
#ifdef N_SECT
case N_SECT:
#endif
/* FIXME: Other definition types (N_TEXT, N_DATA, N_BSS, ...)? */
if (callback)
{
BOOL is_public = (stab_ptr->n_type & N_EXT);
BOOL is_global = is_public;
#ifdef N_PEXT
/* "private extern"; shared among compilation units in a shared
* library, but not accessible from outside the library. */
if (stab_ptr->n_type & N_PEXT)
{
is_public = FALSE;
is_global = TRUE;
}
#endif
if (*ptr == '_') ptr++;
stab_strcpy(symname, sizeof(symname), ptr);
callback(module, load_offset, symname, stab_ptr->n_value,
is_public, is_global, stab_ptr->n_other, compiland, user);
}
break;
default:
ERR("Unknown stab type 0x%02x\n", stab_ptr->n_type);
ERR("Unknown stab type 0x%02x\n", type);
break;
}
stabbuff[0] = '\0';
@ -1529,7 +1679,8 @@ BOOL stabs_parse(struct module* module, unsigned long load_offset,
done:
HeapFree(GetProcessHeap(), 0, stabbuff);
stabs_free_includes();
HeapFree(GetProcessHeap(), 0, pending.vars);
HeapFree(GetProcessHeap(), 0, pending_block.objs);
HeapFree(GetProcessHeap(), 0, pending_func.objs);
return ret;
}

View file

@ -27,40 +27,45 @@
#include <string.h>
#include <assert.h>
#include "ntstatus.h"
#define WIN32_NO_STATUS
#include "dbghelp_private.h"
#include "winternl.h"
#include "wine/winbase16.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
enum st_mode {stm_start, stm_32bit, stm_16bit, stm_done};
static const char* wine_dbgstr_addr(const ADDRESS* addr)
static DWORD64 WINAPI addr_to_linear(HANDLE hProcess, HANDLE hThread, ADDRESS64* addr)
{
if (!addr) return "(null)";
LDT_ENTRY le;
switch (addr->Mode)
{
case AddrModeFlat:
return wine_dbg_sprintf("flat<%08x>", addr->Offset);
case AddrMode1616:
return wine_dbg_sprintf("1616<%04x:%04x>", addr->Segment, addr->Offset);
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:
return wine_dbg_sprintf("1632<%04x:%08x>", addr->Segment, addr->Offset);
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 wine_dbg_sprintf("real<%04x:%04x>", addr->Segment, addr->Offset);
return (DWORD)(LOWORD(addr->Segment) << 4) + addr->Offset;
case AddrModeFlat:
return addr->Offset;
default:
return "unknown";
FIXME("Unsupported (yet) mode (%x)\n", addr->Mode);
return 0;
}
FIXME("Failed to linearize address %04x:%s (mode %x)\n",
addr->Segment, wine_dbgstr_longlong(addr->Offset), addr->Mode);
return 0;
}
static BOOL CALLBACK read_mem(HANDLE hProcess, DWORD addr, void* buffer,
DWORD size, LPDWORD nread)
{
SIZE_T r;
if (!ReadProcessMemory(hProcess, (void*)addr, buffer, size, &r)) return FALSE;
if (!ReadProcessMemory(hProcess, (void*)(DWORD_PTR)addr, buffer, size, &r)) return FALSE;
if (nread) *nread = r;
return TRUE;
}
@ -74,39 +79,6 @@ static BOOL CALLBACK read_mem64(HANDLE hProcess, DWORD64 addr, void* buffer,
return TRUE;
}
/* indexes in Reserved array */
#define __CurrentMode 0
#define __CurrentSwitch 1
#define __NextSwitch 2
#define curr_mode (frame->Reserved[__CurrentMode])
#define curr_switch (frame->Reserved[__CurrentSwitch])
#define next_switch (frame->Reserved[__NextSwitch])
struct stack_walk_callback
{
HANDLE hProcess;
HANDLE hThread;
BOOL is32;
union
{
struct
{
PREAD_PROCESS_MEMORY_ROUTINE f_read_mem;
PTRANSLATE_ADDRESS_ROUTINE f_xlat_adr;
PFUNCTION_TABLE_ACCESS_ROUTINE f_tabl_acs;
PGET_MODULE_BASE_ROUTINE f_modl_bas;
} s32;
struct
{
PREAD_PROCESS_MEMORY_ROUTINE64 f_read_mem;
PTRANSLATE_ADDRESS_ROUTINE64 f_xlat_adr;
PFUNCTION_TABLE_ACCESS_ROUTINE64 f_tabl_acs;
PGET_MODULE_BASE_ROUTINE64 f_modl_bas;
} s64;
} u;
};
static inline void addr_32to64(const ADDRESS* addr32, ADDRESS64* addr64)
{
addr64->Offset = (ULONG64)addr32->Offset;
@ -121,379 +93,113 @@ static inline void addr_64to32(const ADDRESS64* addr64, ADDRESS* addr32)
addr32->Mode = addr64->Mode;
}
static inline BOOL sw_read_mem(struct stack_walk_callback* cb, DWORD addr, void* ptr, DWORD sz)
BOOL sw_read_mem(struct cpu_stack_walk* csw, DWORD64 addr, void* ptr, DWORD sz)
{
if (cb->is32)
return cb->u.s32.f_read_mem(cb->hProcess, addr, ptr, sz, NULL);
if (csw->is32)
return csw->u.s32.f_read_mem(csw->hProcess, addr, ptr, sz, NULL);
else
return cb->u.s64.f_read_mem(cb->hProcess, addr, ptr, sz, NULL);
return csw->u.s64.f_read_mem(csw->hProcess, addr, ptr, sz, NULL);
}
static inline DWORD sw_xlat_addr(struct stack_walk_callback* cb, ADDRESS* addr)
DWORD64 sw_xlat_addr(struct cpu_stack_walk* csw, ADDRESS64* addr)
{
if (addr->Mode == AddrModeFlat) return addr->Offset;
if (cb->is32) return cb->u.s32.f_xlat_adr(cb->hProcess, cb->hThread, addr);
if (cb->u.s64.f_xlat_adr)
if (csw->is32)
{
ADDRESS64 addr64;
ADDRESS addr32;
addr_32to64(addr, &addr64);
return cb->u.s64.f_xlat_adr(cb->hProcess, cb->hThread, &addr64);
addr_64to32(addr, &addr32);
return csw->u.s32.f_xlat_adr(csw->hProcess, csw->hThread, &addr32);
}
return addr_to_linear(cb->hProcess, cb->hThread, addr);
else if (csw->u.s64.f_xlat_adr)
return csw->u.s64.f_xlat_adr(csw->hProcess, csw->hThread, addr);
return addr_to_linear(csw->hProcess, csw->hThread, addr);
}
static inline void* sw_tabl_acs(struct stack_walk_callback* cb, DWORD addr)
void* sw_table_access(struct cpu_stack_walk* csw, DWORD64 addr)
{
if (cb->is32)
return cb->u.s32.f_tabl_acs(cb->hProcess, addr);
if (csw->is32)
return csw->u.s32.f_tabl_acs(csw->hProcess, addr);
else
return cb->u.s64.f_tabl_acs(cb->hProcess, addr);
return csw->u.s64.f_tabl_acs(csw->hProcess, addr);
}
static inline DWORD sw_modl_bas(struct stack_walk_callback* cb, DWORD addr)
DWORD64 sw_module_base(struct cpu_stack_walk* csw, DWORD64 addr)
{
if (cb->is32)
return cb->u.s32.f_modl_bas(cb->hProcess, addr);
if (csw->is32)
return csw->u.s32.f_modl_bas(csw->hProcess, addr);
else
return cb->u.s64.f_modl_bas(cb->hProcess, addr);
}
static BOOL stack_walk(struct stack_walk_callback* cb, LPSTACKFRAME frame)
{
STACK32FRAME frame32;
STACK16FRAME frame16;
char ch;
ADDRESS tmp;
DWORD p;
WORD val;
BOOL do_switch;
/* sanity check */
if (curr_mode >= stm_done) return FALSE;
TRACE("Enter: PC=%s Frame=%s Return=%s Stack=%s Mode=%s cSwitch=%08x nSwitch=%08x\n",
wine_dbgstr_addr(&frame->AddrPC),
wine_dbgstr_addr(&frame->AddrFrame),
wine_dbgstr_addr(&frame->AddrReturn),
wine_dbgstr_addr(&frame->AddrStack),
curr_mode == stm_start ? "start" : (curr_mode == stm_16bit ? "16bit" : "32bit"),
curr_switch, next_switch);
if (curr_mode == stm_start)
{
THREAD_BASIC_INFORMATION info;
if ((frame->AddrPC.Mode == AddrModeFlat) &&
(frame->AddrFrame.Mode != AddrModeFlat))
{
WARN("Bad AddrPC.Mode / AddrFrame.Mode combination\n");
goto done_err;
}
/* Init done */
curr_mode = (frame->AddrPC.Mode == AddrModeFlat) ?
stm_32bit : stm_16bit;
/* cur_switch holds address of WOW32Reserved field in TEB in debuggee
* address space
*/
if (NtQueryInformationThread(cb->hThread, ThreadBasicInformation, &info,
sizeof(info), NULL) == STATUS_SUCCESS)
{
curr_switch = (unsigned long)info.TebBaseAddress + FIELD_OFFSET(TEB, WOW32Reserved);
if (!sw_read_mem(cb, curr_switch, &next_switch, sizeof(next_switch)))
{
WARN("Can't read TEB:WOW32Reserved\n");
goto done_err;
}
if (curr_mode == stm_16bit)
{
if (!sw_read_mem(cb, next_switch, &frame32, sizeof(frame32)))
{
WARN("Bad stack frame 0x%08x\n", next_switch);
goto done_err;
}
curr_switch = (DWORD)frame32.frame16;
tmp.Mode = AddrMode1616;
tmp.Segment = SELECTOROF(curr_switch);
tmp.Offset = OFFSETOF(curr_switch);
if (!sw_read_mem(cb, sw_xlat_addr(cb, &tmp), &ch, sizeof(ch)))
curr_switch = 0xFFFFFFFF;
}
else
{
tmp.Mode = AddrMode1616;
tmp.Segment = SELECTOROF(next_switch);
tmp.Offset = OFFSETOF(next_switch);
p = sw_xlat_addr(cb, &tmp);
if (!sw_read_mem(cb, p, &frame16, sizeof(frame16)))
{
WARN("Bad stack frame 0x%08x\n", p);
goto done_err;
}
curr_switch = (DWORD)frame16.frame32;
if (!sw_read_mem(cb, curr_switch, &ch, sizeof(ch)))
curr_switch = 0xFFFFFFFF;
}
}
else
/* FIXME: this will allow to work when we're not attached to a live target,
* but the 16 <=> 32 switch facility won't be available.
*/
curr_switch = 0;
frame->AddrReturn.Mode = frame->AddrStack.Mode = (curr_mode == stm_16bit) ? AddrMode1616 : AddrModeFlat;
/* don't set up AddrStack on first call. Either the caller has set it up, or
* we will get it in the next frame
*/
memset(&frame->AddrBStore, 0, sizeof(frame->AddrBStore));
}
else
{
if (frame->AddrFrame.Offset == 0) goto done_err;
if (frame->AddrFrame.Mode == AddrModeFlat)
{
assert(curr_mode == stm_32bit);
do_switch = curr_switch && frame->AddrFrame.Offset >= curr_switch;
}
else
{
assert(curr_mode == stm_16bit);
do_switch = curr_switch &&
frame->AddrFrame.Segment == SELECTOROF(curr_switch) &&
frame->AddrFrame.Offset >= OFFSETOF(curr_switch);
}
if (do_switch)
{
if (curr_mode == stm_16bit)
{
if (!sw_read_mem(cb, next_switch, &frame32, sizeof(frame32)))
{
WARN("Bad stack frame 0x%08x\n", next_switch);
goto done_err;
}
frame->AddrPC.Mode = AddrModeFlat;
frame->AddrPC.Segment = 0;
frame->AddrPC.Offset = frame32.retaddr;
frame->AddrFrame.Mode = AddrModeFlat;
frame->AddrFrame.Segment = 0;
frame->AddrFrame.Offset = frame32.ebp;
frame->AddrStack.Mode = AddrModeFlat;
frame->AddrStack.Segment = 0;
frame->AddrReturn.Mode = AddrModeFlat;
frame->AddrReturn.Segment = 0;
next_switch = curr_switch;
tmp.Mode = AddrMode1616;
tmp.Segment = SELECTOROF(next_switch);
tmp.Offset = OFFSETOF(next_switch);
p = sw_xlat_addr(cb, &tmp);
if (!sw_read_mem(cb, p, &frame16, sizeof(frame16)))
{
WARN("Bad stack frame 0x%08x\n", p);
goto done_err;
}
curr_switch = (DWORD)frame16.frame32;
curr_mode = stm_32bit;
if (!sw_read_mem(cb, curr_switch, &ch, sizeof(ch)))
curr_switch = 0;
}
else
{
tmp.Mode = AddrMode1616;
tmp.Segment = SELECTOROF(next_switch);
tmp.Offset = OFFSETOF(next_switch);
p = sw_xlat_addr(cb, &tmp);
if (!sw_read_mem(cb, p, &frame16, sizeof(frame16)))
{
WARN("Bad stack frame 0x%08x\n", p);
goto done_err;
}
TRACE("Got a 16 bit stack switch:"
"\n\tframe32: %08lx"
"\n\tedx:%08x ecx:%08x ebp:%08x"
"\n\tds:%04x es:%04x fs:%04x gs:%04x"
"\n\tcall_from_ip:%08x module_cs:%04x relay=%08x"
"\n\tentry_ip:%04x entry_point:%08x"
"\n\tbp:%04x ip:%04x cs:%04x\n",
(unsigned long)frame16.frame32,
frame16.edx, frame16.ecx, frame16.ebp,
frame16.ds, frame16.es, frame16.fs, frame16.gs,
frame16.callfrom_ip, frame16.module_cs, frame16.relay,
frame16.entry_ip, frame16.entry_point,
frame16.bp, frame16.ip, frame16.cs);
frame->AddrPC.Mode = AddrMode1616;
frame->AddrPC.Segment = frame16.cs;
frame->AddrPC.Offset = frame16.ip;
frame->AddrFrame.Mode = AddrMode1616;
frame->AddrFrame.Segment = SELECTOROF(next_switch);
frame->AddrFrame.Offset = frame16.bp;
frame->AddrStack.Mode = AddrMode1616;
frame->AddrStack.Segment = SELECTOROF(next_switch);
frame->AddrReturn.Mode = AddrMode1616;
frame->AddrReturn.Segment = frame16.cs;
next_switch = curr_switch;
if (!sw_read_mem(cb, next_switch, &frame32, sizeof(frame32)))
{
WARN("Bad stack frame 0x%08x\n", next_switch);
goto done_err;
}
curr_switch = (DWORD)frame32.frame16;
tmp.Mode = AddrMode1616;
tmp.Segment = SELECTOROF(curr_switch);
tmp.Offset = OFFSETOF(curr_switch);
if (!sw_read_mem(cb, sw_xlat_addr(cb, &tmp), &ch, sizeof(ch)))
curr_switch = 0;
curr_mode = stm_16bit;
}
}
else
{
frame->AddrPC = frame->AddrReturn;
if (curr_mode == stm_16bit)
{
frame->AddrStack.Offset = frame->AddrFrame.Offset + 2 * sizeof(WORD);
/* "pop up" previous BP value */
if (!sw_read_mem(cb, sw_xlat_addr(cb, &frame->AddrFrame),
&val, sizeof(WORD)))
goto done_err;
frame->AddrFrame.Offset = val;
}
else
{
frame->AddrStack.Offset = frame->AddrFrame.Offset + 2 * sizeof(DWORD);
/* "pop up" previous EBP value */
if (!sw_read_mem(cb, frame->AddrFrame.Offset,
&frame->AddrFrame.Offset, sizeof(DWORD)))
goto done_err;
}
}
}
if (curr_mode == stm_16bit)
{
unsigned int i;
p = sw_xlat_addr(cb, &frame->AddrFrame);
if (!sw_read_mem(cb, p + sizeof(WORD), &val, sizeof(WORD)))
goto done_err;
frame->AddrReturn.Offset = val;
/* get potential cs if a far call was used */
if (!sw_read_mem(cb, p + 2 * sizeof(WORD), &val, sizeof(WORD)))
goto done_err;
if (frame->AddrFrame.Offset & 1)
frame->AddrReturn.Segment = val; /* far call assumed */
else
{
/* not explicitly marked as far call,
* but check whether it could be anyway
*/
if ((val & 7) == 7 && val != frame->AddrReturn.Segment)
{
LDT_ENTRY le;
if (GetThreadSelectorEntry(cb->hThread, val, &le) &&
(le.HighWord.Bits.Type & 0x08)) /* code segment */
{
/* it is very uncommon to push a code segment cs as
* a parameter, so this should work in most cases
*/
frame->AddrReturn.Segment = val;
}
}
}
frame->AddrFrame.Offset &= ~1;
/* we "pop" parameters as 16 bit entities... of course, this won't
* work if the parameter is in fact bigger than 16bit, but
* there's no way to know that here
*/
for (i = 0; i < sizeof(frame->Params) / sizeof(frame->Params[0]); i++)
{
sw_read_mem(cb, p + (2 + i) * sizeof(WORD), &val, sizeof(val));
frame->Params[i] = val;
}
}
else
{
if (!sw_read_mem(cb, frame->AddrFrame.Offset + sizeof(DWORD),
&frame->AddrReturn.Offset, sizeof(DWORD)))
{
WARN("Cannot read new frame offset %08x\n", frame->AddrFrame.Offset + (int)sizeof(DWORD));
goto done_err;
}
sw_read_mem(cb, frame->AddrFrame.Offset + 2 * sizeof(DWORD),
frame->Params, sizeof(frame->Params));
}
frame->Far = TRUE;
frame->Virtual = TRUE;
p = sw_xlat_addr(cb, &frame->AddrPC);
if (p && sw_modl_bas(cb, p))
frame->FuncTableEntry = sw_tabl_acs(cb, p);
else
frame->FuncTableEntry = NULL;
TRACE("Leave: PC=%s Frame=%s Return=%s Stack=%s Mode=%s cSwitch=%08x nSwitch=%08x FuncTable=%p\n",
wine_dbgstr_addr(&frame->AddrPC),
wine_dbgstr_addr(&frame->AddrFrame),
wine_dbgstr_addr(&frame->AddrReturn),
wine_dbgstr_addr(&frame->AddrStack),
curr_mode == stm_start ? "start" : (curr_mode == stm_16bit ? "16bit" : "32bit"),
curr_switch, next_switch, frame->FuncTableEntry);
return TRUE;
done_err:
curr_mode = stm_done;
return FALSE;
return csw->u.s64.f_modl_bas(csw->hProcess, addr);
}
/***********************************************************************
* StackWalk (DBGHELP.@)
*/
BOOL WINAPI StackWalk(DWORD MachineType, HANDLE hProcess, HANDLE hThread,
LPSTACKFRAME frame, PVOID ctx,
LPSTACKFRAME frame32, PVOID ctx,
PREAD_PROCESS_MEMORY_ROUTINE f_read_mem,
PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine,
PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine,
PTRANSLATE_ADDRESS_ROUTINE f_xlat_adr)
{
struct stack_walk_callback swcb;
struct cpu_stack_walk csw;
STACKFRAME64 frame64;
BOOL ret;
struct cpu* cpu;
TRACE("(%d, %p, %p, %p, %p, %p, %p, %p, %p)\n",
MachineType, hProcess, hThread, frame, ctx,
MachineType, hProcess, hThread, frame32, ctx,
f_read_mem, FunctionTableAccessRoutine,
GetModuleBaseRoutine, f_xlat_adr);
if (MachineType != IMAGE_FILE_MACHINE_I386)
if (!(cpu = cpu_find(MachineType)))
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
swcb.hProcess = hProcess;
swcb.hThread = hThread;
swcb.is32 = TRUE;
/* sigh... MS isn't even consistent in the func prototypes */
swcb.u.s32.f_read_mem = (f_read_mem) ? f_read_mem : read_mem;
swcb.u.s32.f_xlat_adr = (f_xlat_adr) ? f_xlat_adr : addr_to_linear;
swcb.u.s32.f_tabl_acs = (FunctionTableAccessRoutine) ? FunctionTableAccessRoutine : SymFunctionTableAccess;
swcb.u.s32.f_modl_bas = (GetModuleBaseRoutine) ? GetModuleBaseRoutine : SymGetModuleBase;
addr_32to64(&frame32->AddrPC, &frame64.AddrPC);
addr_32to64(&frame32->AddrReturn, &frame64.AddrReturn);
addr_32to64(&frame32->AddrFrame, &frame64.AddrFrame);
addr_32to64(&frame32->AddrStack, &frame64.AddrStack);
addr_32to64(&frame32->AddrBStore, &frame64.AddrBStore);
frame64.FuncTableEntry = frame32->FuncTableEntry; /* FIXME */
frame64.Far = frame32->Far;
frame64.Virtual = frame32->Virtual;
frame64.Reserved[0] = frame32->Reserved[0];
frame64.Reserved[1] = frame32->Reserved[1];
frame64.Reserved[2] = frame32->Reserved[2];
/* we don't handle KdHelp */
return stack_walk(&swcb, frame);
csw.hProcess = hProcess;
csw.hThread = hThread;
csw.is32 = TRUE;
/* sigh... MS isn't even consistent in the func prototypes */
csw.u.s32.f_read_mem = (f_read_mem) ? f_read_mem : read_mem;
csw.u.s32.f_xlat_adr = f_xlat_adr;
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)))
{
addr_64to32(&frame64.AddrPC, &frame32->AddrPC);
addr_64to32(&frame64.AddrReturn, &frame32->AddrReturn);
addr_64to32(&frame64.AddrFrame, &frame32->AddrFrame);
addr_64to32(&frame64.AddrStack, &frame32->AddrStack);
addr_64to32(&frame64.AddrBStore, &frame32->AddrBStore);
frame32->FuncTableEntry = frame64.FuncTableEntry; /* FIXME */
frame32->Params[0] = frame64.Params[0];
frame32->Params[1] = frame64.Params[1];
frame32->Params[2] = frame64.Params[2];
frame32->Params[3] = frame64.Params[3];
frame32->Far = frame64.Far;
frame32->Virtual = frame64.Virtual;
frame32->Reserved[0] = frame64.Reserved[0];
frame32->Reserved[1] = frame64.Reserved[1];
frame32->Reserved[2] = frame64.Reserved[2];
}
return ret;
}
@ -501,78 +207,49 @@ BOOL WINAPI StackWalk(DWORD MachineType, HANDLE hProcess, HANDLE hThread,
* StackWalk64 (DBGHELP.@)
*/
BOOL WINAPI StackWalk64(DWORD MachineType, HANDLE hProcess, HANDLE hThread,
LPSTACKFRAME64 frame64, PVOID ctx,
LPSTACKFRAME64 frame, PVOID ctx,
PREAD_PROCESS_MEMORY_ROUTINE64 f_read_mem,
PFUNCTION_TABLE_ACCESS_ROUTINE64 FunctionTableAccessRoutine,
PGET_MODULE_BASE_ROUTINE64 GetModuleBaseRoutine,
PTRANSLATE_ADDRESS_ROUTINE64 f_xlat_adr)
{
struct stack_walk_callback swcb;
STACKFRAME frame32;
BOOL ret;
struct cpu_stack_walk csw;
struct cpu* cpu;
TRACE("(%d, %p, %p, %p, %p, %p, %p, %p, %p)\n",
MachineType, hProcess, hThread, frame64, ctx,
MachineType, hProcess, hThread, frame, ctx,
f_read_mem, FunctionTableAccessRoutine,
GetModuleBaseRoutine, f_xlat_adr);
if (MachineType != IMAGE_FILE_MACHINE_I386)
if (!(cpu = cpu_find(MachineType)))
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
addr_64to32(&frame64->AddrPC, &frame32.AddrPC);
addr_64to32(&frame64->AddrReturn, &frame32.AddrReturn);
addr_64to32(&frame64->AddrFrame, &frame32.AddrFrame);
addr_64to32(&frame64->AddrStack, &frame32.AddrStack);
addr_64to32(&frame64->AddrBStore, &frame32.AddrBStore);
frame32.FuncTableEntry = frame64->FuncTableEntry; /* FIXME */
frame32.Far = frame64->Far;
frame32.Virtual = frame64->Virtual;
frame32.Reserved[0] = (ULONG)frame64->Reserved[0];
frame32.Reserved[1] = (ULONG)frame64->Reserved[1];
frame32.Reserved[2] = (ULONG)frame64->Reserved[2];
/* we don't handle KdHelp */
swcb.hProcess = hProcess;
swcb.hThread = hThread;
swcb.is32 = FALSE;
csw.hProcess = hProcess;
csw.hThread = hThread;
csw.is32 = FALSE;
/* sigh... MS isn't even consistent in the func prototypes */
swcb.u.s64.f_read_mem = (f_read_mem) ? f_read_mem : read_mem64;
swcb.u.s64.f_xlat_adr = f_xlat_adr;
swcb.u.s64.f_tabl_acs = (FunctionTableAccessRoutine) ? FunctionTableAccessRoutine : SymFunctionTableAccess64;
swcb.u.s64.f_modl_bas = (GetModuleBaseRoutine) ? GetModuleBaseRoutine : SymGetModuleBase64;
csw.u.s64.f_read_mem = (f_read_mem) ? f_read_mem : read_mem64;
csw.u.s64.f_xlat_adr = (f_xlat_adr) ? f_xlat_adr : addr_to_linear;
csw.u.s64.f_tabl_acs = (FunctionTableAccessRoutine) ? FunctionTableAccessRoutine : SymFunctionTableAccess64;
csw.u.s64.f_modl_bas = (GetModuleBaseRoutine) ? GetModuleBaseRoutine : SymGetModuleBase64;
ret = stack_walk(&swcb, &frame32);
if (!cpu->stack_walk(&csw, frame)) return FALSE;
addr_32to64(&frame32.AddrPC, &frame64->AddrPC);
addr_32to64(&frame32.AddrReturn, &frame64->AddrReturn);
addr_32to64(&frame32.AddrFrame, &frame64->AddrFrame);
addr_32to64(&frame32.AddrStack, &frame64->AddrStack);
addr_32to64(&frame32.AddrBStore, &frame64->AddrBStore);
frame64->FuncTableEntry = frame32.FuncTableEntry; /* FIXME */
frame64->Params[0] = frame32.Params[0];
frame64->Params[1] = frame32.Params[1];
frame64->Params[2] = frame32.Params[2];
frame64->Params[3] = frame32.Params[3];
frame64->Far = frame32.Far;
frame64->Virtual = frame32.Virtual;
frame64->Reserved[0] = frame32.Reserved[0];
frame64->Reserved[1] = frame32.Reserved[1];
frame64->Reserved[2] = frame32.Reserved[2];
/* we don't handle KdHelp */
frame64->KdHelp.Thread = 0xC000FADE;
frame64->KdHelp.ThCallbackStack = 0x10;
frame64->KdHelp.ThCallbackBStore = 0;
frame64->KdHelp.NextCallback = 0;
frame64->KdHelp.FramePointer = 0;
frame64->KdHelp.KiCallUserMode = 0xD000DAFE;
frame64->KdHelp.KeUserCallbackDispatcher = 0xE000F000;
frame64->KdHelp.SystemRangeStart = 0xC0000000;
frame64->KdHelp.Reserved[0] /* KiUserExceptionDispatcher */ = 0xE0005000;
frame->KdHelp.Thread = 0xC000FADE;
frame->KdHelp.ThCallbackStack = 0x10;
frame->KdHelp.ThCallbackBStore = 0;
frame->KdHelp.NextCallback = 0;
frame->KdHelp.FramePointer = 0;
frame->KdHelp.KiCallUserMode = 0xD000DAFE;
frame->KdHelp.KeUserCallbackDispatcher = 0xE000F000;
frame->KdHelp.SystemRangeStart = 0xC0000000;
frame->KdHelp.Reserved[0] /* KiUserExceptionDispatcher */ = 0xE0005000;
return ret;
return TRUE;
}
/******************************************************************

View file

@ -34,14 +34,16 @@ WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
struct pool_arena
{
struct pool_arena* next;
char* current;
struct list entry;
char *current;
char *end;
};
void pool_init(struct pool* a, unsigned arena_size)
void pool_init(struct pool* a, size_t arena_size)
{
list_init( &a->arena_list );
list_init( &a->arena_full );
a->arena_size = arena_size;
a->first = NULL;
}
void pool_destroy(struct pool* pool)
@ -50,58 +52,73 @@ void pool_destroy(struct pool* pool)
struct pool_arena* next;
#ifdef USE_STATS
unsigned alloc, used, num;
size_t alloc, used, num;
alloc = used = num = 0;
arena = pool->first;
while (arena)
LIST_FOR_EACH_ENTRY( arena, &pool->arena_list, struct pool_arena, entry )
{
alloc += pool->arena_size;
alloc += arena->end - (char *)arena;
used += arena->current - (char*)arena;
num++;
}
LIST_FOR_EACH_ENTRY( arena, &pool->arena_full, struct pool_arena, entry )
{
alloc += arena->end - (char *)arena;
used += arena->current - (char*)arena;
num++;
arena = arena->next;
}
if (alloc == 0) alloc = 1; /* avoid division by zero */
FIXME("STATS: pool %p has allocated %u kbytes, used %u kbytes in %u arenas,\n"
"\t\t\t\tnon-allocation ratio: %.2f%%\n",
pool, alloc >> 10, used >> 10, num, 100.0 - (float)used / (float)alloc * 100.0);
FIXME("STATS: pool %p has allocated %u kbytes, used %u kbytes in %u arenas, non-allocation ratio: %.2f%%\n",
pool, (unsigned)(alloc >> 10), (unsigned)(used >> 10), (unsigned)num,
100.0 - (float)used / (float)alloc * 100.0);
#endif
arena = pool->first;
while (arena)
LIST_FOR_EACH_ENTRY_SAFE( arena, next, &pool->arena_list, struct pool_arena, entry )
{
next = arena->next;
list_remove( &arena->entry );
HeapFree(GetProcessHeap(), 0, arena);
}
LIST_FOR_EACH_ENTRY_SAFE( arena, next, &pool->arena_full, struct pool_arena, entry )
{
list_remove( &arena->entry );
HeapFree(GetProcessHeap(), 0, arena);
arena = next;
}
pool_init(pool, 0);
}
void* pool_alloc(struct pool* pool, unsigned len)
void* pool_alloc(struct pool* pool, size_t len)
{
struct pool_arena* arena;
void* ret;
size_t size;
len = (len + 3) & ~3; /* round up size on DWORD boundary */
assert(sizeof(struct pool_arena) + len <= pool->arena_size && len);
for (arena = pool->first; arena; arena = arena->next)
LIST_FOR_EACH_ENTRY( arena, &pool->arena_list, struct pool_arena, entry )
{
if ((char*)arena + pool->arena_size - arena->current >= len)
if (arena->end - arena->current >= len)
{
ret = arena->current;
arena->current += len;
if (arena->current + 16 >= arena->end)
{
list_remove( &arena->entry );
list_add_tail( &pool->arena_full, &arena->entry );
}
return ret;
}
}
arena = HeapAlloc(GetProcessHeap(), 0, pool->arena_size);
if (!arena) {ERR("OOM\n");return NULL;}
size = max( pool->arena_size, len );
arena = HeapAlloc(GetProcessHeap(), 0, size + sizeof(struct pool_arena));
if (!arena) return NULL;
ret = (char*)arena + sizeof(*arena);
arena->next = pool->first;
pool->first = arena;
ret = arena + 1;
arena->current = (char*)ret + len;
arena->end = (char*)ret + size;
if (arena->current + 16 >= arena->end)
list_add_tail( &pool->arena_full, &arena->entry );
else
list_add_head( &pool->arena_list, &arena->entry );
return ret;
}
@ -298,7 +315,7 @@ unsigned sparse_array_length(const struct sparse_array* sa)
return sa->elements.num_elts;
}
unsigned hash_table_hash(const char* name, unsigned num_buckets)
static unsigned hash_table_hash(const char* name, unsigned num_buckets)
{
unsigned hash = 0;
while (*name)

File diff suppressed because it is too large Load diff

View file

@ -304,6 +304,21 @@ struct symt_array* symt_new_array(struct module* module, int min, int max,
return sym;
}
static inline DWORD symt_array_count(struct module* module, const struct symt_array* array)
{
if (array->end < 0)
{
DWORD64 elem_size;
/* One could want to also set the array->end field in array, but we won't do it
* as long as all the get_type() helpers use const objects
*/
if (symt_get_info(module, array->base_type, TI_GET_LENGTH, &elem_size) && elem_size)
return -array->end / (DWORD)elem_size;
return 0;
}
return array->end - array->start + 1;
}
struct symt_function_signature* symt_new_function_signature(struct module* module,
struct symt* ret_type,
enum CV_call_e call_conv)
@ -400,9 +415,9 @@ BOOL WINAPI SymEnumTypes(HANDLE hProcess, ULONG64 BaseOfDll,
for (i=0; i<vector_length(&pair.effective->vtypes); i++)
{
type = *(struct symt**)vector_at(&pair.effective->vtypes, i);
sym_info->TypeIndex = (DWORD)type;
sym_info->TypeIndex = symt_ptr2index(pair.effective, type);
sym_info->info = 0; /* FIXME */
symt_get_info(type, TI_GET_LENGTH, &size);
symt_get_info(pair.effective, type, TI_GET_LENGTH, &size);
sym_info->Size = size;
sym_info->ModBase = pair.requested->module.BaseOfImage;
sym_info->Flags = 0; /* FIXME */
@ -462,8 +477,8 @@ BOOL WINAPI SymEnumTypesW(HANDLE hProcess, ULONG64 BaseOfDll,
*
* Retrieves information about a symt (either symbol or type)
*/
BOOL symt_get_info(const struct symt* type, IMAGEHLP_SYMBOL_TYPE_INFO req,
void* pInfo)
BOOL symt_get_info(struct module* module, const struct symt* type,
IMAGEHLP_SYMBOL_TYPE_INFO req, void* pInfo)
{
unsigned len;
@ -495,7 +510,7 @@ BOOL symt_get_info(const struct symt* type, IMAGEHLP_SYMBOL_TYPE_INFO req,
for (i = 0; i < tifp->Count; i++)
{
if (!(pt = vector_at(v, tifp->Start + i))) return FALSE;
tifp->ChildId[i] = (DWORD)*pt;
tifp->ChildId[i] = symt_ptr2index(module, *pt);
}
}
break;
@ -522,7 +537,7 @@ BOOL symt_get_info(const struct symt* type, IMAGEHLP_SYMBOL_TYPE_INFO req,
case SymTagFuncDebugStart:
case SymTagFuncDebugEnd:
case SymTagLabel:
if (!symt_get_info(((const struct symt_hierarchy_point*)type)->parent,
if (!symt_get_info(module, ((const struct symt_hierarchy_point*)type)->parent,
req, pInfo))
return FALSE;
X(ULONG64) += ((const struct symt_hierarchy_point*)type)->loc.offset;
@ -597,8 +612,7 @@ BOOL symt_get_info(const struct symt* type, IMAGEHLP_SYMBOL_TYPE_INFO req,
switch (type->tag)
{
case SymTagArrayType:
X(DWORD) = ((const struct symt_array*)type)->end -
((const struct symt_array*)type)->start + 1;
X(DWORD) = symt_array_count(module, (const struct symt_array*)type);
break;
case SymTagFunctionType:
/* this seems to be wrong for (future) C++ methods, where 'this' parameter
@ -639,18 +653,17 @@ BOOL symt_get_info(const struct symt* type, IMAGEHLP_SYMBOL_TYPE_INFO req,
return FALSE;
X(DWORD64) = ((const struct symt_data*)type)->u.member.length;
break;
case SymTagArrayType:
if (!symt_get_info(((const struct symt_array*)type)->base_type,
case SymTagArrayType:
if (!symt_get_info(module, ((const struct symt_array*)type)->base_type,
TI_GET_LENGTH, pInfo))
return FALSE;
X(DWORD64) *= ((const struct symt_array*)type)->end -
((const struct symt_array*)type)->start + 1;
X(DWORD64) *= symt_array_count(module, (const struct symt_array*)type);
break;
case SymTagPublicSymbol:
X(DWORD64) = ((const struct symt_public*)type)->size;
break;
case SymTagTypedef:
return symt_get_info(((const struct symt_typedef*)type)->type, TI_GET_LENGTH, pInfo);
return symt_get_info(module, ((const struct symt_typedef*)type)->type, TI_GET_LENGTH, pInfo);
case SymTagThunk:
X(DWORD64) = ((const struct symt_thunk*)type)->size;
break;
@ -670,19 +683,19 @@ BOOL symt_get_info(const struct symt* type, IMAGEHLP_SYMBOL_TYPE_INFO req,
switch (type->tag)
{
case SymTagBlock:
X(DWORD) = (DWORD)((const struct symt_block*)type)->container;
X(DWORD) = symt_ptr2index(module, ((const struct symt_block*)type)->container);
break;
case SymTagData:
X(DWORD) = (DWORD)((const struct symt_data*)type)->container;
X(DWORD) = symt_ptr2index(module, ((const struct symt_data*)type)->container);
break;
case SymTagFunction:
X(DWORD) = (DWORD)((const struct symt_function*)type)->container;
X(DWORD) = symt_ptr2index(module, ((const struct symt_function*)type)->container);
break;
case SymTagThunk:
X(DWORD) = (DWORD)((const struct symt_thunk*)type)->container;
X(DWORD) = symt_ptr2index(module, ((const struct symt_thunk*)type)->container);
break;
case SymTagFunctionArgType:
X(DWORD) = (DWORD)((const struct symt_function_arg_type*)type)->container;
X(DWORD) = symt_ptr2index(module, ((const struct symt_function_arg_type*)type)->container);
break;
default:
FIXME("Unsupported sym-tag %s for get-lexical-parent\n",
@ -750,29 +763,29 @@ BOOL symt_get_info(const struct symt* type, IMAGEHLP_SYMBOL_TYPE_INFO req,
{
/* hierarchical => hierarchical */
case SymTagArrayType:
X(DWORD) = (DWORD)((const struct symt_array*)type)->base_type;
X(DWORD) = symt_ptr2index(module, ((const struct symt_array*)type)->base_type);
break;
case SymTagPointerType:
X(DWORD) = (DWORD)((const struct symt_pointer*)type)->pointsto;
X(DWORD) = symt_ptr2index(module, ((const struct symt_pointer*)type)->pointsto);
break;
case SymTagFunctionType:
X(DWORD) = (DWORD)((const struct symt_function_signature*)type)->rettype;
X(DWORD) = symt_ptr2index(module, ((const struct symt_function_signature*)type)->rettype);
break;
case SymTagTypedef:
X(DWORD) = (DWORD)((const struct symt_typedef*)type)->type;
X(DWORD) = symt_ptr2index(module, ((const struct symt_typedef*)type)->type);
break;
/* lexical => hierarchical */
case SymTagData:
X(DWORD) = (DWORD)((const struct symt_data*)type)->type;
X(DWORD) = symt_ptr2index(module, ((const struct symt_data*)type)->type);
break;
case SymTagFunction:
X(DWORD) = (DWORD)((const struct symt_function*)type)->type;
X(DWORD) = symt_ptr2index(module, ((const struct symt_function*)type)->type);
break;
case SymTagEnum:
X(DWORD) = (DWORD)((const struct symt_enum*)type)->base_type;
X(DWORD) = symt_ptr2index(module, ((const struct symt_enum*)type)->base_type);
break;
case SymTagFunctionArgType:
X(DWORD) = (DWORD)((const struct symt_function_arg_type*)type)->arg_type;
X(DWORD) = symt_ptr2index(module, ((const struct symt_function_arg_type*)type)->arg_type);
break;
default:
FIXME("Unsupported sym-tag %s for get-type\n",
@ -806,7 +819,7 @@ BOOL symt_get_info(const struct symt* type, IMAGEHLP_SYMBOL_TYPE_INFO req,
break;
case TI_GET_ARRAYINDEXTYPEID:
if (type->tag != SymTagArrayType) return FALSE;
X(DWORD) = (DWORD)((const struct symt_array*)type)->index_type;
X(DWORD) = symt_ptr2index(module, ((const struct symt_array*)type)->index_type);
break;
case TI_GET_CLASSPARENTID:
@ -854,7 +867,7 @@ BOOL WINAPI SymGetTypeInfo(HANDLE hProcess, DWORD64 ModBase,
return FALSE;
}
return symt_get_info((struct symt*)TypeId, GetType, pInfo);
return symt_get_info(pair.effective, symt_index2ptr(pair.effective, TypeId), GetType, pInfo);
}
/******************************************************************
@ -865,15 +878,15 @@ BOOL WINAPI SymGetTypeFromName(HANDLE hProcess, ULONG64 BaseOfDll,
PCSTR Name, PSYMBOL_INFO Symbol)
{
struct process* pcs = process_find_by_handle(hProcess);
struct module* module;
struct module_pair pair;
struct symt* type;
if (!pcs) return FALSE;
module = module_find_by_addr(pcs, BaseOfDll, DMT_UNKNOWN);
if (!module) return FALSE;
type = symt_find_type_by_name(module, SymTagNull, Name);
pair.requested = module_find_by_addr(pcs, BaseOfDll, DMT_UNKNOWN);
if (!module_get_debug(&pair)) return FALSE;
type = symt_find_type_by_name(pair.effective, SymTagNull, Name);
if (!type) return FALSE;
Symbol->TypeIndex = (DWORD)type;
Symbol->TypeIndex = symt_ptr2index(pair.effective, type);
return TRUE;
}

View file

@ -0,0 +1,26 @@
/*
* Copyright 2009 Louis Lenders
*
* 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
*/
#define WINE_FILEDESCRIPTION_STR "Wine Image Helper"
#define WINE_FILENAME_STR "dbghelp.dll"
#define WINE_FILEVERSION 5,1,2600,3264
#define WINE_FILEVERSION_STR "5.1.2600.3264"
#define WINE_PRODUCTVERSION 5,1,2600,3264
#define WINE_PRODUCTVERSION_STR "5.1.2600.3264"
#include "wine/wine_common_ver.rc"

View file

@ -871,20 +871,20 @@ typedef struct _UNWIND_HISTORY_TABLE {
*/
/* This is used by NtQuerySystemInformation */
typedef struct _SYSTEM_THREAD_INFORMATION{
FILETIME ftKernelTime;
FILETIME ftUserTime;
FILETIME ftCreateTime;
DWORD dwTickCount;
DWORD dwStartAddress;
DWORD dwOwningPID;
DWORD dwThreadID;
DWORD dwCurrentPriority;
DWORD dwBasePriority;
DWORD dwContextSwitches;
DWORD dwThreadState;
DWORD dwWaitReason;
DWORD dwUnknown;
typedef struct _SYSTEM_THREAD_INFORMATION
{ /* win32/win64 */
LARGE_INTEGER KernelTime; /* 00/00 */
LARGE_INTEGER UserTime; /* 08/08 */
LARGE_INTEGER CreateTime; /* 10/10 */
DWORD dwTickCount; /* 18/18 */
LPVOID StartAddress; /* 1c/20 */
CLIENT_ID ClientId; /* 20/28 */
DWORD dwCurrentPriority; /* 28/38 */
DWORD dwBasePriority; /* 2c/3c */
DWORD dwContextSwitches; /* 30/40 */
DWORD dwThreadState; /* 34/44 */
DWORD dwWaitReason; /* 38/48 */
DWORD dwUnknown; /* 3c/4c */
} SYSTEM_THREAD_INFORMATION, *PSYSTEM_THREAD_INFORMATION;
typedef struct _IO_STATUS_BLOCK {
@ -1195,38 +1195,39 @@ typedef struct _VM_COUNTERS_ {
SIZE_T QuotaNonPagedPoolUsage;
SIZE_T PagefileUsage;
SIZE_T PeakPagefileUsage;
SIZE_T PrivatePageCount;
} VM_COUNTERS, *PVM_COUNTERS;
typedef struct _SYSTEM_PROCESS_INFORMATION {
#ifdef __WINESRC__
DWORD dwOffset;
DWORD dwThreadCount;
DWORD dwUnknown1[6];
FILETIME ftCreationTime;
FILETIME ftUserTime;
FILETIME ftKernelTime;
UNICODE_STRING ProcessName;
DWORD dwBasePriority;
DWORD dwProcessID;
DWORD dwParentProcessID;
DWORD dwHandleCount;
DWORD dwUnknown3;
DWORD dwUnknown4;
VM_COUNTERS vmCounters;
IO_COUNTERS ioCounters;
SYSTEM_THREAD_INFORMATION ti[1];
#ifdef __WINESRC__ /* win32/win64 */
ULONG NextEntryOffset; /* 00/00 */
DWORD dwThreadCount; /* 04/04 */
DWORD dwUnknown1[6]; /* 08/08 */
LARGE_INTEGER CreationTime; /* 20/20 */
LARGE_INTEGER UserTime; /* 28/28 */
LARGE_INTEGER KernelTime; /* 30/30 */
UNICODE_STRING ProcessName; /* 38/38 */
DWORD dwBasePriority; /* 40/48 */
HANDLE UniqueProcessId; /* 44/50 */
HANDLE ParentProcessId; /* 48/58 */
ULONG HandleCount; /* 4c/60 */
DWORD dwUnknown3; /* 50/64 */
DWORD dwUnknown4; /* 54/68 */
VM_COUNTERS vmCounters; /* 58/70 */
IO_COUNTERS ioCounters; /* 88/d0 */
SYSTEM_THREAD_INFORMATION ti[1]; /* b8/100 */
#else
ULONG NextEntryOffset;
BYTE Reserved1[52];
PVOID Reserved2[3];
HANDLE UniqueProcessId;
PVOID Reserved3;
ULONG HandleCount;
BYTE Reserved4[4];
PVOID Reserved5[11];
SIZE_T PeakPagefileUsage;
SIZE_T PrivatePageCount;
LARGE_INTEGER Reserved6[6];
ULONG NextEntryOffset; /* 00/00 */
BYTE Reserved1[52]; /* 04/04 */
PVOID Reserved2[3]; /* 38/38 */
HANDLE UniqueProcessId; /* 44/50 */
PVOID Reserved3; /* 48/58 */
ULONG HandleCount; /* 4c/60 */
BYTE Reserved4[4]; /* 50/64 */
PVOID Reserved5[11]; /* 54/68 */
SIZE_T PeakPagefileUsage; /* 80/c0 */
SIZE_T PrivatePageCount; /* 84/c8 */
LARGE_INTEGER Reserved6[6]; /* 88/d0 */
#endif
} SYSTEM_PROCESS_INFORMATION, *PSYSTEM_PROCESS_INFORMATION;

View file

@ -1642,14 +1642,28 @@ struct startend
unsigned int end;
};
#define LT2_LINES_BLOCK 0x000000f2
#define LT2_FILES_BLOCK 0x000000f4
/* there's a new line tab structure from MS Studio 2005 and after
* it's made of:
* DWORD 000000f4
* DWORD lineblk_offset (counting bytes after this field)
* an array of codeview_linetab2_file structures
* an array (starting at <lineblk_offset>) of codeview_linetab2_block structures
* it's made of a list of codeview_linetab2 blocks.
* We've only seen (so far) list with a single LT2_FILES_BLOCK and several
* LT2_LINES_BLOCK. The LT2_FILES block has been encountered either as first
* or last block of the list.
* A LT2_FILES contains one or several codeview_linetab2_file:s
*/
struct codeview_linetab2
{
DWORD header;
DWORD size_of_block;
};
static inline const struct codeview_linetab2* codeview_linetab2_next_block(const struct codeview_linetab2* lt2)
{
return (const struct codeview_linetab2*)((const char*)(lt2 + 1) + lt2->size_of_block);
}
struct codeview_linetab2_file
{
DWORD offset; /* offset in string table for filename */
@ -1658,16 +1672,21 @@ struct codeview_linetab2_file
WORD pad0; /* always 0 */
};
struct codeview_linetab2_block
struct codeview_lt2blk_files
{
DWORD header; /* 0x000000f2 */
DWORD size_of_block; /* next block is at # bytes after this field */
DWORD start; /* start address of function with line numbers */
DWORD seg; /* segment of function with line numbers */
DWORD size; /* size of function with line numbers */
DWORD file_offset; /* offset for accessing corresponding codeview_linetab2_file */
DWORD nlines; /* number of lines in this block */
DWORD size_lines; /* number of bytes following for line number information */
struct codeview_linetab2 lt2; /* LT2_FILES */
struct codeview_linetab2_file file[1];
};
struct codeview_lt2blk_lines
{
struct codeview_linetab2 lt2; /* LT2_LINE_BLOCK */
DWORD start; /* start address of function with line numbers */
DWORD seg; /* segment of function with line numbers */
DWORD size; /* size of function with line numbers */
DWORD file_offset; /* offset for accessing corresponding codeview_linetab2_file */
DWORD nlines; /* number of lines in this block */
DWORD size_lines; /* number of bytes following for line number information */
struct {
DWORD offset; /* offset (from <seg>:<start>) for line number */
DWORD lineno; /* the line number (OR:ed with 0x80000000 why ???) */