Skip to content
Snippets Groups Projects
Commit 800864a0 authored by Eric Pouech's avatar Eric Pouech Committed by Alexandre Julliard
Browse files

First shot at implementing dbghelp.

parent 7e301d8a
No related branches found
No related tags found
No related merge requests found
Showing
with 8113 additions and 5 deletions
...@@ -3128,9 +3128,12 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $ ...@@ -3128,9 +3128,12 @@ ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $
ac_compiler_gnu=$ac_cv_c_compiler_gnu ac_compiler_gnu=$ac_cv_c_compiler_gnu
   
   
echo "$as_me:$LINENO: checking for X" >&5
if test "x$ac_path_x_has_been_run" != xyes; then
echo "$as_me:$LINENO: checking for X" >&5
echo $ECHO_N "checking for X... $ECHO_C" >&6 echo $ECHO_N "checking for X... $ECHO_C" >&6
   
ac_path_x_has_been_run=yes
   
# Check whether --with-x or --without-x was given. # Check whether --with-x or --without-x was given.
if test "${with_x+set}" = set; then if test "${with_x+set}" = set; then
...@@ -3223,7 +3226,7 @@ ac_x_header_dirs=' ...@@ -3223,7 +3226,7 @@ ac_x_header_dirs='
/usr/openwin/share/include' /usr/openwin/share/include'
   
if test "$ac_x_includes" = no; then if test "$ac_x_includes" = no; then
# Guess where to find include files, by looking for Intrinsic.h. # Guess where to find include files, by looking for a specified header file.
# First, try using that file with no special directory specified. # First, try using that file with no special directory specified.
cat >conftest.$ac_ext <<_ACEOF cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */ /* confdefs.h. */
...@@ -3357,10 +3360,15 @@ else ...@@ -3357,10 +3360,15 @@ else
# Update the cache value to reflect the command line values. # Update the cache value to reflect the command line values.
ac_cv_have_x="have_x=yes \ ac_cv_have_x="have_x=yes \
ac_x_includes=$x_includes ac_x_libraries=$x_libraries" ac_x_includes=$x_includes ac_x_libraries=$x_libraries"
echo "$as_me:$LINENO: result: libraries $x_libraries, headers $x_includes" >&5 # It might be that x_includes is empty (headers are found in the
echo "${ECHO_T}libraries $x_libraries, headers $x_includes" >&6 # standard search path. Then output the corresponding message
ac_out_x_includes=$x_includes
test "x$x_includes" = x && ac_out_x_includes="in standard search path"
echo "$as_me:$LINENO: result: libraries $x_libraries, headers $ac_out_x_includes" >&5
echo "${ECHO_T}libraries $x_libraries, headers $ac_out_x_includes" >&6
fi fi
   
fi
if test "$no_x" = yes; then if test "$no_x" = yes; then
# Not all programs may use this symbol, but it does not hurt to define it. # Not all programs may use this symbol, but it does not hurt to define it.
   
...@@ -19964,7 +19972,7 @@ MAKE_LIB_RULES=libs/Makelib.rules ...@@ -19964,7 +19972,7 @@ MAKE_LIB_RULES=libs/Makelib.rules
MAKE_PROG_RULES=programs/Makeprog.rules MAKE_PROG_RULES=programs/Makeprog.rules
   
   
ac_config_files="$ac_config_files Make.rules dlls/Makedll.rules dlls/Maketest.rules libs/Makelib.rules programs/Makeprog.rules Makefile dlls/Makefile dlls/advapi32/Makefile dlls/advapi32/tests/Makefile dlls/amstream/Makefile dlls/avicap32/Makefile dlls/avifil32/Makefile dlls/cabinet/Makefile dlls/capi2032/Makefile dlls/cards/Makefile dlls/cfgmgr32/Makefile dlls/comcat/Makefile dlls/comctl32/Makefile dlls/comctl32/tests/Makefile dlls/commdlg/Makefile dlls/crtdll/Makefile dlls/crypt32/Makefile dlls/ctl3d/Makefile dlls/d3d8/Makefile dlls/d3d9/Makefile dlls/d3dim/Makefile dlls/d3dx8/Makefile dlls/dciman32/Makefile dlls/ddraw/Makefile dlls/ddraw/tests/Makefile dlls/devenum/Makefile dlls/dinput/Makefile dlls/dinput8/Makefile dlls/dmband/Makefile dlls/dmcompos/Makefile dlls/dmime/Makefile dlls/dmloader/Makefile dlls/dmscript/Makefile dlls/dmstyle/Makefile dlls/dmsynth/Makefile dlls/dmusic/Makefile dlls/dmusic32/Makefile dlls/dplay/Makefile dlls/dplayx/Makefile dlls/dpnhpast/Makefile dlls/dsound/Makefile dlls/dsound/tests/Makefile dlls/dswave/Makefile dlls/dxerr8/Makefile dlls/dxerr9/Makefile dlls/dxguid/Makefile dlls/gdi/Makefile dlls/gdi/tests/Makefile dlls/glu32/Makefile dlls/glut32/Makefile dlls/iccvid/Makefile dlls/icmp/Makefile dlls/ifsmgr.vxd/Makefile dlls/imagehlp/Makefile dlls/imm32/Makefile dlls/iphlpapi/Makefile dlls/iphlpapi/tests/Makefile dlls/kernel/Makefile dlls/kernel/tests/Makefile dlls/lzexpand/Makefile dlls/mapi32/Makefile dlls/mmdevldr.vxd/Makefile dlls/monodebg.vxd/Makefile dlls/mpr/Makefile dlls/msacm/Makefile dlls/msacm/imaadp32/Makefile dlls/msacm/msadp32/Makefile dlls/msacm/msg711/Makefile dlls/msacm/winemp3/Makefile dlls/msdmo/Makefile dlls/mshtml/Makefile dlls/msi/Makefile dlls/msimg32/Makefile dlls/msisys/Makefile dlls/msnet32/Makefile dlls/msrle32/Makefile dlls/msvcrt/Makefile dlls/msvcrt/tests/Makefile dlls/msvcrt20/Makefile dlls/msvcrt40/Makefile dlls/msvcrtd/Makefile dlls/msvidc32/Makefile dlls/msvideo/Makefile dlls/mswsock/Makefile dlls/netapi32/Makefile dlls/netapi32/tests/Makefile dlls/newdev/Makefile dlls/ntdll/Makefile dlls/ntdll/tests/Makefile dlls/odbc32/Makefile dlls/ole32/Makefile dlls/oleacc/Makefile dlls/oleaut32/Makefile dlls/oleaut32/tests/Makefile dlls/olecli/Makefile dlls/oledlg/Makefile dlls/olepro32/Makefile dlls/olesvr/Makefile dlls/opengl32/Makefile dlls/psapi/Makefile dlls/qcap/Makefile dlls/quartz/Makefile dlls/rasapi32/Makefile dlls/richedit/Makefile dlls/rpcrt4/Makefile dlls/rpcrt4/tests/Makefile dlls/rsabase/Makefile dlls/secur32/Makefile dlls/serialui/Makefile dlls/setupapi/Makefile dlls/shdocvw/Makefile dlls/shell32/Makefile dlls/shell32/tests/Makefile dlls/shfolder/Makefile dlls/shlwapi/Makefile dlls/shlwapi/tests/Makefile dlls/snmpapi/Makefile dlls/sti/Makefile dlls/tapi32/Makefile dlls/ttydrv/Makefile dlls/twain/Makefile dlls/unicows/Makefile dlls/url/Makefile dlls/urlmon/Makefile dlls/urlmon/tests/Makefile dlls/user/Makefile dlls/user/tests/Makefile dlls/uuid/Makefile dlls/uxtheme/Makefile dlls/vdhcp.vxd/Makefile dlls/version/Makefile dlls/vmm.vxd/Makefile dlls/vnbt.vxd/Makefile dlls/vnetbios.vxd/Makefile dlls/vtdapi.vxd/Makefile dlls/vwin32.vxd/Makefile dlls/win32s/Makefile dlls/winaspi/Makefile dlls/wined3d/Makefile dlls/winedos/Makefile dlls/wineps/Makefile dlls/wininet/Makefile dlls/wininet/tests/Makefile dlls/winmm/Makefile dlls/winmm/joystick/Makefile dlls/winmm/mcianim/Makefile dlls/winmm/mciavi/Makefile dlls/winmm/mcicda/Makefile dlls/winmm/mciseq/Makefile dlls/winmm/mciwave/Makefile dlls/winmm/midimap/Makefile dlls/winmm/tests/Makefile dlls/winmm/wavemap/Makefile dlls/winmm/winealsa/Makefile dlls/winmm/winearts/Makefile dlls/winmm/wineaudioio/Makefile dlls/winmm/winejack/Makefile dlls/winmm/winenas/Makefile dlls/winmm/wineoss/Makefile dlls/winnls/Makefile dlls/winsock/Makefile dlls/winsock/tests/Makefile dlls/winspool/Makefile dlls/winspool/tests/Makefile dlls/wintab32/Makefile dlls/wintrust/Makefile dlls/wow32/Makefile dlls/wsock32/Makefile dlls/x11drv/Makefile documentation/Makefile include/Makefile libs/Makefile libs/port/Makefile libs/unicode/Makefile libs/wine/Makefile libs/wpp/Makefile loader/Makefile programs/Makefile programs/avitools/Makefile programs/clock/Makefile programs/cmdlgtst/Makefile programs/control/Makefile programs/expand/Makefile programs/notepad/Makefile programs/progman/Makefile programs/regedit/Makefile programs/regsvr32/Makefile programs/rpcss/Makefile programs/rundll32/Makefile programs/start/Makefile programs/taskmgr/Makefile programs/uninstaller/Makefile programs/view/Makefile programs/wcmd/Makefile programs/wineboot/Makefile programs/winebrowser/Makefile programs/winecfg/Makefile programs/wineconsole/Makefile programs/winedbg/Makefile programs/winefile/Makefile programs/winemenubuilder/Makefile programs/winemine/Makefile programs/winepath/Makefile programs/winetest/Makefile programs/winevdm/Makefile programs/winhelp/Makefile programs/winver/Makefile server/Makefile tools/Makefile tools/widl/Makefile tools/winapi/Makefile tools/winebuild/Makefile tools/winedump/Makefile tools/winegcc/Makefile tools/wmc/Makefile tools/wrc/Makefile" ac_config_files="$ac_config_files Make.rules dlls/Makedll.rules dlls/Maketest.rules libs/Makelib.rules programs/Makeprog.rules Makefile dlls/Makefile dlls/advapi32/Makefile dlls/advapi32/tests/Makefile dlls/amstream/Makefile dlls/avicap32/Makefile dlls/avifil32/Makefile dlls/cabinet/Makefile dlls/capi2032/Makefile dlls/cards/Makefile dlls/cfgmgr32/Makefile dlls/comcat/Makefile dlls/comctl32/Makefile dlls/comctl32/tests/Makefile dlls/commdlg/Makefile dlls/crtdll/Makefile dlls/crypt32/Makefile dlls/ctl3d/Makefile dlls/d3d8/Makefile dlls/d3d9/Makefile dlls/d3dim/Makefile dlls/d3dx8/Makefile dlls/dbghelp/Makefile dlls/dciman32/Makefile dlls/ddraw/Makefile dlls/ddraw/tests/Makefile dlls/devenum/Makefile dlls/dinput/Makefile dlls/dinput8/Makefile dlls/dmband/Makefile dlls/dmcompos/Makefile dlls/dmime/Makefile dlls/dmloader/Makefile dlls/dmscript/Makefile dlls/dmstyle/Makefile dlls/dmsynth/Makefile dlls/dmusic/Makefile dlls/dmusic32/Makefile dlls/dplay/Makefile dlls/dplayx/Makefile dlls/dpnhpast/Makefile dlls/dsound/Makefile dlls/dsound/tests/Makefile dlls/dswave/Makefile dlls/dxerr8/Makefile dlls/dxerr9/Makefile dlls/dxguid/Makefile dlls/gdi/Makefile dlls/gdi/tests/Makefile dlls/glu32/Makefile dlls/glut32/Makefile dlls/iccvid/Makefile dlls/icmp/Makefile dlls/ifsmgr.vxd/Makefile dlls/imagehlp/Makefile dlls/imm32/Makefile dlls/iphlpapi/Makefile dlls/iphlpapi/tests/Makefile dlls/kernel/Makefile dlls/kernel/tests/Makefile dlls/lzexpand/Makefile dlls/mapi32/Makefile dlls/mmdevldr.vxd/Makefile dlls/monodebg.vxd/Makefile dlls/mpr/Makefile dlls/msacm/Makefile dlls/msacm/imaadp32/Makefile dlls/msacm/msadp32/Makefile dlls/msacm/msg711/Makefile dlls/msacm/winemp3/Makefile dlls/msdmo/Makefile dlls/mshtml/Makefile dlls/msi/Makefile dlls/msimg32/Makefile dlls/msisys/Makefile dlls/msnet32/Makefile dlls/msrle32/Makefile dlls/msvcrt/Makefile dlls/msvcrt/tests/Makefile dlls/msvcrt20/Makefile dlls/msvcrt40/Makefile dlls/msvcrtd/Makefile dlls/msvidc32/Makefile dlls/msvideo/Makefile dlls/mswsock/Makefile dlls/netapi32/Makefile dlls/netapi32/tests/Makefile dlls/newdev/Makefile dlls/ntdll/Makefile dlls/ntdll/tests/Makefile dlls/odbc32/Makefile dlls/ole32/Makefile dlls/oleacc/Makefile dlls/oleaut32/Makefile dlls/oleaut32/tests/Makefile dlls/olecli/Makefile dlls/oledlg/Makefile dlls/olepro32/Makefile dlls/olesvr/Makefile dlls/opengl32/Makefile dlls/psapi/Makefile dlls/qcap/Makefile dlls/quartz/Makefile dlls/rasapi32/Makefile dlls/richedit/Makefile dlls/rpcrt4/Makefile dlls/rpcrt4/tests/Makefile dlls/rsabase/Makefile dlls/secur32/Makefile dlls/serialui/Makefile dlls/setupapi/Makefile dlls/shdocvw/Makefile dlls/shell32/Makefile dlls/shell32/tests/Makefile dlls/shfolder/Makefile dlls/shlwapi/Makefile dlls/shlwapi/tests/Makefile dlls/snmpapi/Makefile dlls/sti/Makefile dlls/tapi32/Makefile dlls/ttydrv/Makefile dlls/twain/Makefile dlls/unicows/Makefile dlls/url/Makefile dlls/urlmon/Makefile dlls/urlmon/tests/Makefile dlls/user/Makefile dlls/user/tests/Makefile dlls/uuid/Makefile dlls/uxtheme/Makefile dlls/vdhcp.vxd/Makefile dlls/version/Makefile dlls/vmm.vxd/Makefile dlls/vnbt.vxd/Makefile dlls/vnetbios.vxd/Makefile dlls/vtdapi.vxd/Makefile dlls/vwin32.vxd/Makefile dlls/win32s/Makefile dlls/winaspi/Makefile dlls/wined3d/Makefile dlls/winedos/Makefile dlls/wineps/Makefile dlls/wininet/Makefile dlls/wininet/tests/Makefile dlls/winmm/Makefile dlls/winmm/joystick/Makefile dlls/winmm/mcianim/Makefile dlls/winmm/mciavi/Makefile dlls/winmm/mcicda/Makefile dlls/winmm/mciseq/Makefile dlls/winmm/mciwave/Makefile dlls/winmm/midimap/Makefile dlls/winmm/tests/Makefile dlls/winmm/wavemap/Makefile dlls/winmm/winealsa/Makefile dlls/winmm/winearts/Makefile dlls/winmm/wineaudioio/Makefile dlls/winmm/winejack/Makefile dlls/winmm/winenas/Makefile dlls/winmm/wineoss/Makefile dlls/winnls/Makefile dlls/winsock/Makefile dlls/winsock/tests/Makefile dlls/winspool/Makefile dlls/winspool/tests/Makefile dlls/wintab32/Makefile dlls/wintrust/Makefile dlls/wow32/Makefile dlls/wsock32/Makefile dlls/x11drv/Makefile documentation/Makefile include/Makefile libs/Makefile libs/port/Makefile libs/unicode/Makefile libs/wine/Makefile libs/wpp/Makefile loader/Makefile programs/Makefile programs/avitools/Makefile programs/clock/Makefile programs/cmdlgtst/Makefile programs/control/Makefile programs/expand/Makefile programs/notepad/Makefile programs/progman/Makefile programs/regedit/Makefile programs/regsvr32/Makefile programs/rpcss/Makefile programs/rundll32/Makefile programs/start/Makefile programs/taskmgr/Makefile programs/uninstaller/Makefile programs/view/Makefile programs/wcmd/Makefile programs/wineboot/Makefile programs/winebrowser/Makefile programs/winecfg/Makefile programs/wineconsole/Makefile programs/winedbg/Makefile programs/winefile/Makefile programs/winemenubuilder/Makefile programs/winemine/Makefile programs/winepath/Makefile programs/winetest/Makefile programs/winevdm/Makefile programs/winhelp/Makefile programs/winver/Makefile server/Makefile tools/Makefile tools/widl/Makefile tools/winapi/Makefile tools/winebuild/Makefile tools/winedump/Makefile tools/winegcc/Makefile tools/wmc/Makefile tools/wrc/Makefile"
   
   
cat >confcache <<\_ACEOF cat >confcache <<\_ACEOF
...@@ -20522,6 +20530,7 @@ do ...@@ -20522,6 +20530,7 @@ do
"dlls/d3d9/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/d3d9/Makefile" ;; "dlls/d3d9/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/d3d9/Makefile" ;;
"dlls/d3dim/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/d3dim/Makefile" ;; "dlls/d3dim/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/d3dim/Makefile" ;;
"dlls/d3dx8/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/d3dx8/Makefile" ;; "dlls/d3dx8/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/d3dx8/Makefile" ;;
"dlls/dbghelp/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/dbghelp/Makefile" ;;
"dlls/dciman32/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/dciman32/Makefile" ;; "dlls/dciman32/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/dciman32/Makefile" ;;
"dlls/ddraw/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/ddraw/Makefile" ;; "dlls/ddraw/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/ddraw/Makefile" ;;
"dlls/ddraw/tests/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/ddraw/tests/Makefile" ;; "dlls/ddraw/tests/Makefile" ) CONFIG_FILES="$CONFIG_FILES dlls/ddraw/tests/Makefile" ;;
......
...@@ -1510,6 +1510,7 @@ dlls/d3d8/Makefile ...@@ -1510,6 +1510,7 @@ dlls/d3d8/Makefile
dlls/d3d9/Makefile dlls/d3d9/Makefile
dlls/d3dim/Makefile dlls/d3dim/Makefile
dlls/d3dx8/Makefile dlls/d3dx8/Makefile
dlls/dbghelp/Makefile
dlls/dciman32/Makefile dlls/dciman32/Makefile
dlls/ddraw/Makefile dlls/ddraw/Makefile
dlls/ddraw/tests/Makefile dlls/ddraw/tests/Makefile
......
...@@ -31,6 +31,7 @@ BASEDIRS = \ ...@@ -31,6 +31,7 @@ BASEDIRS = \
crypt32 \ crypt32 \
ctl3d \ ctl3d \
d3dim \ d3dim \
dbghelp \
dciman32 \ dciman32 \
devenum \ devenum \
dinput \ dinput \
...@@ -243,6 +244,7 @@ SYMLINKS_SO = \ ...@@ -243,6 +244,7 @@ SYMLINKS_SO = \
crypt32.dll.so \ crypt32.dll.so \
ctl3d32.dll.so \ ctl3d32.dll.so \
d3dim.dll.so \ d3dim.dll.so \
dbghelp.dll.so \
dciman32.dll.so \ dciman32.dll.so \
devenum.dll.so \ devenum.dll.so \
dinput.dll.so \ dinput.dll.so \
...@@ -443,6 +445,9 @@ d3dim.dll.so: d3dim/d3dim.dll.so ...@@ -443,6 +445,9 @@ d3dim.dll.so: d3dim/d3dim.dll.so
d3dx8.dll.so: d3dx8/d3dx8.dll.so d3dx8.dll.so: d3dx8/d3dx8.dll.so
$(RM) $@ && $(LN_S) d3dx8/d3dx8.dll.so $@ $(RM) $@ && $(LN_S) d3dx8/d3dx8.dll.so $@
dbghelp.dll.so: dbghelp/dbghelp.dll.so
$(RM) $@ && $(LN_S) dbghelp/dbghelp.dll.so $@
dciman32.dll.so: dciman32/dciman32.dll.so dciman32.dll.so: dciman32/dciman32.dll.so
$(RM) $@ && $(LN_S) dciman32/dciman32.dll.so $@ $(RM) $@ && $(LN_S) dciman32/dciman32.dll.so $@
...@@ -926,6 +931,7 @@ IMPORT_LIBS = \ ...@@ -926,6 +931,7 @@ IMPORT_LIBS = \
libd3d9 \ libd3d9 \
libd3dim \ libd3dim \
libd3dx8 \ libd3dx8 \
libdbghelp \
libdciman32 \ libdciman32 \
libddraw \ libddraw \
libdevenum \ libdevenum \
...@@ -1123,6 +1129,11 @@ libd3dx8.def: d3dx8/d3dx8.spec.def ...@@ -1123,6 +1129,11 @@ libd3dx8.def: d3dx8/d3dx8.spec.def
libd3dx8.a: d3dx8/d3dx8.spec.def libd3dx8.a: d3dx8/d3dx8.spec.def
$(DLLTOOL) -k -l $@ -d d3dx8/d3dx8.spec.def $(DLLTOOL) -k -l $@ -d d3dx8/d3dx8.spec.def
libdbghelp.def: dbghelp/dbghelp.spec.def
$(RM) $@ && $(LN_S) dbghelp/dbghelp.spec.def $@
libdbghelp.a: dbghelp/dbghelp.spec.def
$(DLLTOOL) -k -l $@ -d dbghelp/dbghelp.spec.def
libdciman32.def: dciman32/dciman32.spec.def libdciman32.def: dciman32/dciman32.spec.def
$(RM) $@ && $(LN_S) dciman32/dciman32.spec.def $@ $(RM) $@ && $(LN_S) dciman32/dciman32.spec.def $@
libdciman32.a: dciman32/dciman32.spec.def libdciman32.a: dciman32/dciman32.spec.def
...@@ -1626,6 +1637,7 @@ d3d8/d3d8.spec.def: $(WINEBUILD) ...@@ -1626,6 +1637,7 @@ d3d8/d3d8.spec.def: $(WINEBUILD)
d3d9/d3d9.spec.def: $(WINEBUILD) d3d9/d3d9.spec.def: $(WINEBUILD)
d3dim/d3dim.spec.def: $(WINEBUILD) d3dim/d3dim.spec.def: $(WINEBUILD)
d3dx8/d3dx8.spec.def: $(WINEBUILD) d3dx8/d3dx8.spec.def: $(WINEBUILD)
dbghelp/dbghelp.spec.def: $(WINEBUILD)
dciman32/dciman32.spec.def: $(WINEBUILD) dciman32/dciman32.spec.def: $(WINEBUILD)
ddraw/ddraw.spec.def: $(WINEBUILD) ddraw/ddraw.spec.def: $(WINEBUILD)
devenum/devenum.spec.def: $(WINEBUILD) devenum/devenum.spec.def: $(WINEBUILD)
...@@ -1747,6 +1759,7 @@ d3d8/d3d8.dll.so: d3d8 ...@@ -1747,6 +1759,7 @@ d3d8/d3d8.dll.so: d3d8
d3d9/d3d9.dll.so: d3d9 d3d9/d3d9.dll.so: d3d9
d3dim/d3dim.dll.so: d3dim d3dim/d3dim.dll.so: d3dim
d3dx8/d3dx8.dll.so: d3dx8 d3dx8/d3dx8.dll.so: d3dx8
dbghelp/dbghelp.dll.so: dbghelp
dciman32/dciman32.dll.so: dciman32 dciman32/dciman32.dll.so: dciman32
ddraw/ddraw.dll.so: ddraw ddraw/ddraw.dll.so: ddraw
devenum/devenum.dll.so: devenum devenum/devenum.dll.so: devenum
......
Makefile
dbghelp.dll.dbg.c
dbghelp.spec.def
TOPSRCDIR = @top_srcdir@
TOPOBJDIR = ../..
SRCDIR = @srcdir@
VPATH = @srcdir@
MODULE = dbghelp.dll
IMPORTS = psapi kernel32 ntdll
C_SRCS = \
dbghelp.c \
elf_module.c \
image.c \
memory.c \
minidump.c \
module.c \
msc.c \
path.c \
pe_module.c \
source.c \
stabs.c \
stack.c \
storage.c \
symbol.c \
type.c
@MAKE_DLL_RULES@
### Dependencies:
/*
* File dbghelp.c - generic routines (process) for dbghelp DLL
*
* Copyright (C) 2004, Eric Pouech
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include "dbghelp_private.h"
#include "winerror.h"
#include "psapi.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
/* TODO
* - support for symbols' types is still partly missing
* + debug start/stop in functions
* + parameters in function prototype...
* + C++ support
* - most options (dbghelp_options) are not used (loading lines, decoration,
* deferring reading of module symbols, public symbols...)
* - (un)decoration is not handled (should make winedump's code a (.a) library
* and link it to winedump, and potentially to msvcrt and dbghelp (check best
* way not to duplicate code in msvcrt & dbghelp)
* - msc:
* + handle the debug_start & debug_end information block
* + get rid of MSC reading FIXME:s (lots of types are not defined)
* + C++ management
* - stabs:
* + we should add parameters' types to the function's signature
* while processing a function's parameters
* + should generate the func debug_{start,end} statements (black magic ?)
* + should identify the relay code in Wine and mark it as thunk type
* + C++ management
* - implement the callback notification mechanism
*/
unsigned dbghelp_options = SYMOPT_UNDNAME;
/***********************************************************************
* DllMain (DEBUGHLP.@)
*/
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
switch (fdwReason)
{
case DLL_PROCESS_ATTACH: break;
case DLL_PROCESS_DETACH: break;
case DLL_THREAD_ATTACH: break;
case DLL_THREAD_DETACH: break;
default: break;
}
return TRUE;
}
static struct process* process_first /* = NULL */;
/******************************************************************
* process_find_by_handle
*
*/
struct process* process_find_by_handle(HANDLE hProcess)
{
struct process* p;
for (p = process_first; p && p->handle != hProcess; p = p->next);
if (!p) SetLastError(ERROR_INVALID_HANDLE);
return p;
}
/******************************************************************
* SymSetSearchPath (DBGHELP.@)
*
*/
BOOL WINAPI SymSetSearchPath(HANDLE hProcess, PSTR searchPath)
{
struct process* pcs = process_find_by_handle(hProcess);
if (!pcs) return FALSE;
if (!searchPath) return FALSE;
HeapFree(GetProcessHeap(), 0, pcs->search_path);
pcs->search_path = strcpy(HeapAlloc(GetProcessHeap(), 0, strlen(searchPath) + 1),
searchPath);
return TRUE;
}
/***********************************************************************
* SymGetSearchPath (DBGHELP.@)
*/
BOOL WINAPI SymGetSearchPath(HANDLE hProcess, LPSTR szSearchPath,
DWORD SearchPathLength)
{
struct process* pcs = process_find_by_handle(hProcess);
if (!pcs) return FALSE;
strncpy(szSearchPath, pcs->search_path, SearchPathLength);
szSearchPath[SearchPathLength - 1] = '\0';
return TRUE;
}
/******************************************************************
* invade_process
*
* SymInitialize helper: loads in dbghelp all known (and loaded modules)
* this assumes that hProcess is a handle on a valid process
*/
static BOOL process_invade(HANDLE hProcess)
{
HMODULE hMods[256];
char img[256], mod[256];
DWORD i, sz;
MODULEINFO mi;
if (!EnumProcessModules(hProcess, hMods, sizeof(hMods), &sz))
return FALSE; /* FIXME should grow hMods */
for (i = 0; i < sz / sizeof(HMODULE); i++)
{
if (!GetModuleInformation(hProcess, hMods[i], &mi, sizeof(mi)) ||
!GetModuleFileNameExA(hProcess, hMods[i], img, sizeof(img)) ||
!GetModuleBaseNameA(hProcess, hMods[i], mod, sizeof(mod)) ||
!SymLoadModule(hProcess, 0, img, mod, (DWORD)mi.lpBaseOfDll, mi.SizeOfImage))
return FALSE;
}
return sz != 0;
}
/******************************************************************
* SymInitialize (DBGHELP.@)
*
* The initialisation of a dbghelp's context.
* Note that hProcess doesn't need to be a valid process handle (except
* when fInvadeProcess is TRUE).
* Since, we're also allow to load ELF (pure) libraries and Wine ELF libraries
* containing PE (and NE) module(s), here's how we handle it:
* - we load every module (ELF, NE, PE) passed in SymLoadModule
* - in fInvadeProcess (in SymInitialize) is TRUE, we set up what is called ELF
* synchronization: hProcess should be a valid process handle, and we hook
* ourselves on hProcess's loaded ELF-modules, and keep this list in sync with
* our internal ELF modules representation (loading / unloading). This way,
* we'll pair every loaded builtin PE module with its ELF counterpart (and
* access its debug information).
* - if fInvadeProcess (in SymInitialize) is FALSE, we won't be able to
* make the peering between a builtin PE module and its ELF counterpart, hence
* we won't be able to provide the requested debug information. We'll
* however be able to load native PE modules (and their debug information)
* without any trouble.
* Note also that this scheme can be intertwined with the deferred loading
* mechanism (ie only load the debug information when we actually need it).
*/
BOOL WINAPI SymInitialize(HANDLE hProcess, PSTR UserSearchPath, BOOL fInvadeProcess)
{
struct process* pcs;
TRACE("(%p %s %u)\n", hProcess, debugstr_a(UserSearchPath), fInvadeProcess);
if (process_find_by_handle(hProcess))
FIXME("what to do ??\n");
pcs = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*pcs));
if (!pcs) return FALSE;
pcs->handle = hProcess;
if (UserSearchPath)
{
pcs->search_path = strcpy(HeapAlloc(GetProcessHeap(), 0, strlen(UserSearchPath) + 1),
UserSearchPath);
}
else
{
unsigned size;
unsigned len;
pcs->search_path = HeapAlloc(GetProcessHeap(), 0, len = MAX_PATH);
while ((size = GetCurrentDirectoryA(len, pcs->search_path)) >= len)
pcs->search_path = HeapReAlloc(GetProcessHeap(), 0, pcs->search_path, len *= 2);
pcs->search_path = HeapReAlloc(GetProcessHeap(), 0, pcs->search_path, size + 1);
len = GetEnvironmentVariableA("_NT_SYMBOL_PATH", NULL, 0);
if (len)
{
pcs->search_path = HeapReAlloc(GetProcessHeap(), 0, pcs->search_path, size + 1 + len + 1);
pcs->search_path[size] = ';';
GetEnvironmentVariableA("_NT_SYMBOL_PATH", pcs->search_path + size + 1, len);
size += 1 + len;
}
len = GetEnvironmentVariableA("_NT_ALTERNATE_SYMBOL_PATH", NULL, 0);
if (len)
{
pcs->search_path = HeapReAlloc(GetProcessHeap(), 0, pcs->search_path, size + 1 + len + 1);
pcs->search_path[size] = ';';
GetEnvironmentVariableA("_NT_ALTERNATE_SYMBOL_PATH", pcs->search_path + size + 1, len);
size += 1 + len;
}
}
pcs->lmodules = NULL;
pcs->dbg_hdr_addr = 0;
pcs->next = process_first;
process_first = pcs;
if (fInvadeProcess)
{
pcs->dbg_hdr_addr = elf_read_wine_loader_dbg_info(pcs);
if (pcs->dbg_hdr_addr == 0)
{
SymCleanup(hProcess);
return FALSE;
}
process_invade(hProcess);
elf_synchronize_module_list(pcs);
}
return TRUE;
}
/******************************************************************
* SymCleanup (DBGHELP.@)
*
*/
BOOL WINAPI SymCleanup(HANDLE hProcess)
{
struct process** ppcs;
struct process* next;
for (ppcs = &process_first; *ppcs; ppcs = &(*ppcs)->next)
{
if ((*ppcs)->handle == hProcess)
{
while ((*ppcs)->lmodules) module_remove(*ppcs, (*ppcs)->lmodules);
HeapFree(GetProcessHeap(), 0, (*ppcs)->search_path);
next = (*ppcs)->next;
HeapFree(GetProcessHeap(), 0, *ppcs);
*ppcs = next;
return TRUE;
}
}
return FALSE;
}
/******************************************************************
* SymSetOptions (DBGHELP.@)
*
*/
DWORD WINAPI SymSetOptions(DWORD opts)
{
return dbghelp_options = opts;
}
/******************************************************************
* SymGetOptions (DBGHELP.@)
*
*/
DWORD WINAPI SymGetOptions(void)
{
return dbghelp_options;
}
/******************************************************************
* SymSetContext (DBGHELP.@)
*
*/
BOOL WINAPI SymSetContext(HANDLE hProcess, PIMAGEHLP_STACK_FRAME StackFrame,
PIMAGEHLP_CONTEXT Context)
{
struct process* pcs = process_find_by_handle(hProcess);
if (!pcs) return FALSE;
pcs->ctx_frame = *StackFrame;
/* MSDN states that Context is not (no longer?) used */
return TRUE;
}
/***********************************************************************
* SymRegisterCallback (DBGHELP.@)
*/
BOOL WINAPI SymRegisterCallback(HANDLE hProcess,
PSYMBOL_REGISTERED_CALLBACK CallbackFunction,
PVOID UserContext)
{
FIXME("(%p, %p, %p): stub\n", hProcess, CallbackFunction, UserContext);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
/* This is imagehlp version not dbghelp !! */
static API_VERSION api_version = { 4, 0, 2, 0 };
/***********************************************************************
* ImagehlpApiVersion (DBGHELP.@)
*/
LPAPI_VERSION WINAPI ImagehlpApiVersion(VOID)
{
return &api_version;
}
/***********************************************************************
* ImagehlpApiVersionEx (DBGHELP.@)
*/
LPAPI_VERSION WINAPI ImagehlpApiVersionEx(LPAPI_VERSION AppVersion)
{
if (!AppVersion) return NULL;
AppVersion->MajorVersion = api_version.MajorVersion;
AppVersion->MinorVersion = api_version.MinorVersion;
AppVersion->Revision = api_version.Revision;
AppVersion->Reserved = api_version.Reserved;
return AppVersion;
}
@ stub DbgHelpCreateUserDump
@ stub DbgHelpCreateUserDumpW
@ stdcall EnumerateLoadedModules(long ptr ptr)
@ stub EnumerateLoadedModules64
@ stub ExtensionApiVersion
@ stdcall FindDebugInfoFile(str str ptr)
@ stdcall FindDebugInfoFileEx(str str ptr ptr ptr)
@ stdcall FindExecutableImage(str str str)
@ stub FindExecutableImageEx
@ stub FindFileInPath
@ stub FindFileInSearchPath
@ stdcall GetTimestampForLoadedLibrary(long)
@ stub ImageDirectoryEntryToData
@ stub ImageDirectoryEntryToDataEx
@ stdcall ImageNtHeader(ptr) ntdll.RtlImageNtHeader
@ stdcall ImageRvaToSection(ptr ptr long) ntdll.RtlImageRvaToSection
@ stdcall ImageRvaToVa(ptr ptr long ptr) ntdll.RtlImageRvaToVa
@ stdcall ImagehlpApiVersion()
@ stdcall ImagehlpApiVersionEx(ptr)
@ stdcall MakeSureDirectoryPathExists(str)
@ stdcall MapDebugInformation(long str str long)
@ stub MiniDumpReadDumpStream
@ stub MiniDumpWriteDump
@ stdcall SearchTreeForFile(str str str)
@ stdcall StackWalk(long long long ptr ptr ptr ptr ptr ptr)
@ stub StackWalk64
@ stdcall SymCleanup(long)
@ stdcall SymEnumSourceFiles(long long str ptr ptr)
@ stub SymEnumSym
@ stdcall SymEnumSymbols(long long str ptr ptr)
@ stdcall SymEnumTypes(long long ptr ptr)
@ stdcall SymEnumerateModules(long ptr ptr)
@ stub SymEnumerateModules64
@ stdcall SymEnumerateSymbols(long long ptr ptr)
@ stub SymEnumerateSymbols64
@ stub SymEnumerateSymbolsW
@ stub SymEnumerateSymbolsW64
@ stub SymFindFileInPath
@ stdcall SymFromAddr(long long ptr ptr)
@ stdcall SymFromName(long str ptr)
@ stdcall SymFunctionTableAccess(long long)
@ stub SymFunctionTableAccess64
@ stub SymGetFileLineOffsets64
@ stdcall SymGetLineFromAddr(long long ptr ptr)
@ stub SymGetLineFromAddr64
@ stub SymGetLineFromName
@ stub SymGetLineFromName64
@ stdcall SymGetLineNext(long ptr)
@ stub SymGetLineNext64
@ stdcall SymGetLinePrev(long ptr)
@ stub SymGetLinePrev64
@ stdcall SymGetModuleBase(long long)
@ stub SymGetModuleBase64
@ stdcall SymGetModuleInfo(long long ptr)
@ stub SymGetModuleInfo64
@ stub SymGetModuleInfoW
@ stub SymGetModuleInfoW64
@ stdcall SymGetOptions()
@ stdcall SymGetSearchPath(long str long)
@ stdcall SymGetSymFromAddr(long long ptr ptr)
@ stub SymGetSymFromAddr64
@ stdcall SymGetSymFromName(long str ptr)
@ stub SymGetSymFromName64
@ stdcall SymGetSymNext(long ptr)
@ stub SymGetSymNext64
@ stdcall SymGetSymPrev(long ptr)
@ stub SymGetSymPrev64
@ stdcall SymGetTypeFromName(long long str ptr)
@ stdcall SymGetTypeInfo(long long long long ptr)
@ stdcall SymInitialize(long str long)
@ stdcall SymLoadModule(long long str str long long)
@ stub SymLoadModule64
@ stub SymLoadModuleEx
@ stub SymMatchFileName
@ stub SymMatchString
@ stdcall SymRegisterCallback(long ptr ptr)
@ stub SymRegisterCallback64
@ stub SymRegisterFunctionEntryCallback
@ stub SymRegisterFunctionEntryCallback64
@ stdcall SymSetContext(long ptr ptr)
@ stdcall SymSetOptions(long)
@ stdcall SymSetSearchPath(long str)
@ stub SymSetSymWithAddr64
@ stdcall SymUnDName(ptr str long)
@ stub SymUnDName64
@ stdcall SymUnloadModule(long long)
@ stub SymUnloadModule64
@ stdcall UnDecorateSymbolName(str str long long)
@ stdcall UnmapDebugInformation(ptr)
@ stub WinDbgExtensionDllInit
#@ stub dbghelp
#@ stub dh
#@ stub lm
#@ stub lmi
#@ stub omap
#@ stub srcfiles
#@ stub sym
#@ stub vc7fpo
/*
* File dbghelp_private.h - dbghelp internal definitions
*
* Copyright (C) 1995, Alexandre Julliard
* Copyright (C) 1996, Eric Youngdale.
* Copyright (C) 1999-2000, Ulrich Weigand.
* Copyright (C) 2004, Eric Pouech.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "winver.h"
#include "dbghelp.h"
#include "cvconst.h"
/* #define USE_STATS */
struct pool /* poor's man */
{
struct pool_arena* first;
unsigned arena_size;
};
void pool_init(struct pool* a, unsigned arena_size);
void pool_destroy(struct pool* a);
void* pool_alloc(struct pool* a, unsigned len);
/* void* pool_realloc(struct pool* a, void* p,
unsigned old_size, unsigned new_size); */
char* pool_strdup(struct pool* a, const char* str);
struct vector
{
void** buckets;
unsigned elt_size : 24, shift : 8;
unsigned num_elts : 20, num_buckets : 12;
};
void vector_init(struct vector* v, unsigned elt_sz, unsigned bucket_sz);
unsigned vector_length(const struct vector* v);
void* vector_at(const struct vector* v, unsigned pos);
void* vector_add(struct vector* v, struct pool* pool);
/*void vector_pool_normalize(struct vector* v, struct pool* pool); */
void* vector_iter_up(const struct vector* v, void* elt);
void* vector_iter_down(const struct vector* v, void* elt);
struct hash_table_elt
{
const char* name;
struct hash_table_elt* next;
};
struct hash_table
{
unsigned num_buckets;
struct hash_table_elt** buckets;
};
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);
void* hash_table_find(const struct hash_table* ht, const char* name);
unsigned hash_table_hash(const char* name, unsigned num_buckets);
struct hash_table_iter
{
const struct hash_table* ht;
struct hash_table_elt* element;
int index;
int last;
};
void hash_table_iter_init(const struct hash_table* ht,
struct hash_table_iter* hti, const char* name);
void* hash_table_iter_up(struct hash_table_iter* hti);
#define GET_ENTRY(__i, __t, __f) \
((__t*)((char*)(__i) - (unsigned int)(&((__t*)0)->__f)))
extern unsigned dbghelp_options;
struct symt
{
enum SymTagEnum tag;
};
struct symt_ht
{
struct symt symt;
struct hash_table_elt hash_elt; /* if global symbol or type */
};
/* lexical tree */
struct symt_block
{
struct symt symt;
unsigned long address;
unsigned long size;
struct symt* container; /* block, or func */
struct vector vchildren; /* sub-blocks & local variables */
};
struct symt_compiland
{
struct symt symt;
unsigned source;
struct vector vchildren; /* global variables & functions */
};
struct symt_data
{
struct symt symt;
struct hash_table_elt hash_elt; /* if global symbol */
enum DataKind kind;
struct symt* container;
struct symt* type;
enum LocationType location;
union /* depends on location */
{
unsigned long address; /* used by Static, Tls, ThisRel */
int offset; /* used by RegRel */
unsigned reg_id; /* used by Enregistered */
struct
{
unsigned position;
unsigned length;
} bitfield; /* used by BitField */
#if 1
unsigned value; /* LocIsConstant */
#else
VARIANT value; /* LocIsConstant */
#endif
} u;
};
struct symt_function
{
struct symt symt;
struct hash_table_elt hash_elt; /* if global symbol */
unsigned long addr;
struct symt* container; /* compiland */
struct symt* type; /* points to function_signature */
unsigned long size;
struct vector vlines;
struct vector vchildren; /* locals, params, blocks */
};
struct symt_public
{
struct symt symt;
struct hash_table_elt hash_elt;
struct symt* container; /* compiland */
unsigned long address;
unsigned long size;
unsigned in_code : 1,
is_function : 1;
};
/* class tree */
struct symt_array
{
struct symt symt;
int start;
int end;
struct symt* basetype;
};
struct symt_basic
{
struct symt symt;
struct hash_table_elt hash_elt;
enum BasicType bt;
unsigned long size;
};
struct symt_enum
{
struct symt symt;
const char* name;
struct vector vchildren;
};
struct symt_function_signature
{
struct symt symt;
struct symt* rettype;
};
struct symt_pointer
{
struct symt symt;
struct symt* pointsto;
};
struct symt_typedef
{
struct symt symt;
struct hash_table_elt hash_elt;
struct symt* type;
};
struct symt_udt
{
struct symt symt;
struct hash_table_elt hash_elt;
enum UdtKind kind;
int size;
struct vector vchildren;
};
enum DbgModuleType {DMT_UNKNOWN, DMT_ELF, DMT_NE, DMT_PE};
struct module
{
IMAGEHLP_MODULE module;
struct module* next;
enum DbgModuleType type;
unsigned short elf_mark : 1;
struct tagELF_DBG_INFO* elf_dbg_info;
/* memory allocation pool */
struct pool pool;
/* symbol tables */
int sortlist_valid;
struct symt_ht** addr_sorttab;
struct hash_table ht_symbols;
/* types */
struct hash_table ht_types;
/* source files */
unsigned sources_used;
unsigned sources_alloc;
char* sources;
};
struct process
{
struct process* next;
HANDLE handle;
char* search_path;
struct module* lmodules;
unsigned long dbg_hdr_addr;
IMAGEHLP_STACK_FRAME ctx_frame;
};
/* dbghelp.c */
extern struct process* process_find_by_handle(HANDLE hProcess);
/* elf_module.c */
extern SYM_TYPE elf_load_debug_info(struct module* module);
extern struct module*
elf_load_module(struct process* pcs, const char* name);
extern unsigned long
elf_read_wine_loader_dbg_info(struct process* pcs);
extern BOOL elf_synchronize_module_list(struct process* pcs);
/* memory.c */
struct memory_access
{
BOOL (*read_mem)(HANDLE hProcess, DWORD addr, void* buf, DWORD len);
BOOL (*write_mem)(HANDLE hProcess, DWORD addr, void* buf, DWORD len);
};
extern struct memory_access mem_access;
#define read_mem(p,a,b,l) (mem_access.read_mem)((p),(a),(b),(l))
#define write_mem(p,a,b,l) (mem_access.write_mem)((p),(a),(b),(l))
extern unsigned long WINAPI addr_to_linear(HANDLE hProcess, HANDLE hThread, ADDRESS* addr);
/* module.c */
extern struct module*
module_find_by_addr(const struct process* pcs, unsigned long addr,
enum DbgModuleType type);
extern struct module*
module_find_by_name(const struct process* pcs,
const char* name, enum DbgModuleType type);
extern struct module*
module_get_debug(const struct process* pcs, struct module*);
extern struct module*
module_new(struct process* pcs, const char* name,
enum DbgModuleType type, unsigned long addr,
unsigned long size, unsigned long stamp,
unsigned long checksum);
extern BOOL module_remove(struct process* pcs,
struct module* module);
/* msc.c */
extern SYM_TYPE pe_load_debug_directory(const struct process* pcs,
struct module* module,
const BYTE* file_map,
PIMAGE_DEBUG_DIRECTORY dbg, int nDbg);
/* pe_module.c */
extern struct module*
pe_load_module(struct process* pcs, char* name,
HANDLE hFile, DWORD base, DWORD size);
extern struct module*
pe_load_module_from_pcs(struct process* pcs, const char* name,
const char* mod_name, DWORD base, DWORD size);
extern SYM_TYPE pe_load_debug_info(const struct process* pcs,
struct module* module);
/* source.c */
extern unsigned source_new(struct module* module, const char* source);
extern const char* source_get(const struct module* module, unsigned idx);
/* stabs.c */
extern SYM_TYPE stabs_parse(struct module* module, const char* addr,
unsigned long load_offset,
unsigned int staboff, int stablen,
unsigned int strtaboff, int strtablen);
/* symbol.c */
extern const char* symt_get_name(const struct symt* sym);
extern int symt_cmp_addr(const void* p1, const void* p2);
extern struct symt_compiland*
symt_new_compiland(struct module* module,
const char* filename);
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);
extern struct symt_data*
symt_new_global_variable(struct module* module,
struct symt_compiland* parent,
const char* name, unsigned is_static,
unsigned long addr, unsigned long size,
struct symt* type);
extern struct symt_function*
symt_new_function(struct module* module,
struct symt_compiland* parent,
const char* name,
unsigned long addr, unsigned long size,
struct symt* type);
extern BOOL symt_normalize_function(struct module* module,
struct symt_function* func);
extern void symt_add_func_line(struct module* module,
struct symt_function* func,
unsigned source_idx, int line_num,
unsigned long offset);
extern struct symt_data*
symt_add_func_local(struct module* module,
struct symt_function* func,
int regno, int offset,
struct symt_block* block,
struct symt* type, const char* name);
extern struct symt_block*
symt_open_func_block(struct module* module,
struct symt_function* func,
struct symt_block* block, unsigned pc);
extern struct symt_block*
symt_close_func_block(struct module* module,
struct symt_function* func,
struct symt_block* block, unsigned pc);
/* type.c */
extern void symt_init_basic(struct module* module);
extern BOOL symt_get_info(const struct symt* type,
IMAGEHLP_SYMBOL_TYPE_INFO req, void* pInfo);
extern struct symt_basic*
symt_new_basic(struct module* module, enum BasicType,
const char* typename, unsigned size);
extern struct symt_udt*
symt_new_udt(struct module* module, const char* typename,
unsigned size, enum UdtKind kind);
extern BOOL symt_set_udt_size(struct module* module,
struct symt_udt* type, unsigned size);
extern BOOL symt_add_udt_element(struct module* module,
struct symt_udt* udt_type,
const char* name,
struct symt* elt_type, unsigned offset,
unsigned size);
extern struct symt_enum*
symt_new_enum(struct module* module, const char* typename);
extern BOOL symt_add_enum_element(struct module* module,
struct symt_enum* enum_type,
const char* name, unsigned value);
extern struct symt_array*
symt_new_array(struct module* module, int min, int max,
struct symt* base);
extern struct symt_function_signature*
symt_new_function_signature(struct module* module,
struct symt* ret_type);
extern struct symt_pointer*
symt_new_pointer(struct module* module,
struct symt* ref_type);
This diff is collapsed.
/*
* File image.c - managing images
*
* Copyright (C) 2004, Eric Pouech
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "dbghelp_private.h"
#include "winreg.h"
#include "winternl.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
/***********************************************************************
* GetTimestampForLoadedLibrary (DBGHELP.@)
*/
DWORD WINAPI GetTimestampForLoadedLibrary(HMODULE Module)
{
IMAGE_NT_HEADERS* nth = RtlImageNtHeader(Module);
return (nth) ? nth->FileHeader.TimeDateStamp : 0;
}
/***********************************************************************
* MapDebugInformation (DBGHELP.@)
*/
PIMAGE_DEBUG_INFORMATION WINAPI MapDebugInformation(HANDLE FileHandle, LPSTR FileName,
LPSTR SymbolPath, DWORD ImageBase)
{
FIXME("(%p, %s, %s, 0x%08lx): stub\n", FileHandle, FileName, SymbolPath, ImageBase);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return NULL;
}
/***********************************************************************
* UnmapDebugInformation (DBGHELP.@)
*/
BOOL WINAPI UnmapDebugInformation(PIMAGE_DEBUG_INFORMATION DebugInfo)
{
FIXME("(%p): stub\n", DebugInfo);
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
/*
* File memory.c - managing memory
*
* Copyright (C) 2004, Eric Pouech
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include <assert.h>
#include "dbghelp_private.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
BOOL win32_read_mem(HANDLE hProcess, DWORD addr, void* buf, DWORD len)
{
return ReadProcessMemory(hProcess, (void*)addr, buf, len, NULL);
}
BOOL win32_write_mem(HANDLE hProcess, DWORD addr, void* buf, DWORD len)
{
return WriteProcessMemory(hProcess, (void*)addr, buf, len, NULL);
}
/* standard routines for reading / writing memory. Can be overriden for some
* minidump usage
*/
struct memory_access mem_access = {win32_read_mem, win32_write_mem};
/******************************************************************
* addr_to_linear
*
* converts an address into its linear value
*/
unsigned long WINAPI addr_to_linear(HANDLE hProcess, HANDLE hThread, ADDRESS* addr)
{
LDT_ENTRY le;
switch (addr->Mode)
{
case AddrMode1616:
if (GetThreadSelectorEntry(hThread, addr->Segment, &le))
return (le.HighWord.Bits.BaseHi << 24) +
(le.HighWord.Bits.BaseMid << 16) + le.BaseLow + LOWORD(addr->Offset);
break;
case AddrMode1632:
if (GetThreadSelectorEntry(hThread, addr->Segment, &le))
return (le.HighWord.Bits.BaseHi << 24) +
(le.HighWord.Bits.BaseMid << 16) + le.BaseLow + addr->Offset;
break;
case AddrModeReal:
return (DWORD)(LOWORD(addr->Segment) << 4) + addr->Offset;
case AddrModeFlat:
return addr->Offset;
default:
FIXME("Unsupported (yet) mode (%x)\n", addr->Mode);
return 0;
}
FIXME("Failed to linearize address %04x:%08lx (mode %x)\n",
addr->Segment, addr->Offset, addr->Mode);
return 0;
}
/*
* File minidump.c - management of dumps (read & write)
*
* Copyright (C) 2004, Eric Pouech
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include <time.h>
#define NONAMELESSUNION
#define NONAMELESSSTRUCT
#include "dbghelp_private.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
#if 0
/* hard to see how we can generate this very easily (how to grab latest exception
* in a process ?)
*/
static void DumpException(struct process* pcs, HANDLE hFile, RVA* rva)
{
MINIDUMP_EXCEPTION_STREAM mdExcpt;
mdExcpt.ThreadId = DEBUG_CurrThread->tid;
mdExcpt.__alignment = 0;
mdExcpt.ExceptionRecord.
ULONG ExceptionCode;
ULONG ExceptionFlags;
ULONGLONG ExceptionRecord;
ULONGLONG ExceptionAddress;
ULONG NumberParameters;
ULONG __unusedAlignment;
ULONGLONG ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
}
#endif
/******************************************************************
* dump_modules
*
* Write in File the modules from pcs
*/
static void dump_modules(struct process* pcs, HANDLE hFile, RVA* rva)
{
MINIDUMP_MODULE mdModule;
MINIDUMP_MODULE_LIST mdModuleList;
DWORD written;
struct module* module = NULL;
mdModuleList.NumberOfModules = 0;
for (module = pcs->lmodules; module; module = module->next)
mdModuleList.NumberOfModules++;
WriteFile(hFile, &mdModuleList.NumberOfModules,
sizeof(mdModuleList.NumberOfModules), &written, NULL);
*rva += sizeof(mdModuleList.NumberOfModules) +
sizeof(mdModule) * mdModuleList.NumberOfModules;
for (module = pcs->lmodules; module; module = module->next)
{
mdModule.BaseOfImage = (DWORD)module->module.BaseOfImage;
mdModule.SizeOfImage = module->module.ImageSize;
mdModule.CheckSum = module->module.CheckSum;
mdModule.TimeDateStamp = module->module.TimeDateStamp;
mdModule.ModuleNameRva = *rva;
*rva += strlen(module->module.ModuleName) + 1;
memset(&mdModule.VersionInfo, 0, sizeof(mdModule.VersionInfo)); /* FIXME */
mdModule.CvRecord.DataSize = 0; /* FIXME */
mdModule.CvRecord.Rva = 0; /* FIXME */
mdModule.MiscRecord.DataSize = 0; /* FIXME */
mdModule.MiscRecord.Rva = 0; /* FIXME */
mdModule.Reserved0 = 0;
mdModule.Reserved1 = 0;
WriteFile(hFile, &mdModule, sizeof(mdModule), &written, NULL);
}
for (module = pcs->lmodules; module; module = module->next)
{
WriteFile(hFile, module->module.ModuleName,
strlen(module->module.ModuleName) + 1, &written, NULL);
FIXME("CV and misc records not written\n");
}
}
/******************************************************************
* dump_system_info
*
* Dumps into File the information about the system
*/
static void dump_system_info(struct process* pcs, HANDLE hFile, RVA* rva)
{
MINIDUMP_SYSTEM_INFO mdSysInfo;
SYSTEM_INFO sysInfo;
OSVERSIONINFOA osInfo;
DWORD written;
GetSystemInfo(&sysInfo);
GetVersionExA(&osInfo);
mdSysInfo.ProcessorArchitecture = sysInfo.u.s.wProcessorArchitecture;
mdSysInfo.ProcessorLevel = sysInfo.wProcessorLevel;
mdSysInfo.ProcessorRevision = sysInfo.wProcessorRevision;
mdSysInfo.Reserved0 = 0;
mdSysInfo.MajorVersion = osInfo.dwMajorVersion;
mdSysInfo.MinorVersion = osInfo.dwMinorVersion;
mdSysInfo.BuildNumber = osInfo.dwBuildNumber;
mdSysInfo.PlatformId = osInfo.dwPlatformId;
mdSysInfo.CSDVersionRva = *rva + sizeof(mdSysInfo);
mdSysInfo.Reserved1 = 0;
WriteFile(hFile, &mdSysInfo, sizeof(mdSysInfo), &written, NULL);
*rva += sizeof(mdSysInfo);
WriteFile(hFile, osInfo.szCSDVersion, strlen(osInfo.szCSDVersion) + 1,
&written, NULL);
*rva += strlen(osInfo.szCSDVersion) + 1;
}
/******************************************************************
* dump_threads
*
* Dumps into File the information about running threads
*/
static void dump_threads(struct process* pcs, HANDLE hFile, RVA* rva)
{
#if 0
MINIDUMP_THREAD mdThd;
MINIDUMP_THREAD_LIST mdThdList;
DWORD written;
DBG_THREAD* thd;
mdThdList.NumberOfThreads = pcs->num_threads;
WriteFile(hFile, &mdThdList.NumberOfThreads, sizeof(mdThdList.NumberOfThreads),
&written, NULL);
*rva += sizeof(mdThdList.NumberOfThreads) +
mdThdList.NumberOfThreads * sizeof(mdThd);
for (thd = pcs->threads; thd; thd = thd->next)
{
mdThd.ThreadId = thd->tid;
mdThd.SuspendCount = 0; /* FIXME */
mdThd.PriorityClass = 0; /* FIXME */
mdThd.Priority = 0; /* FIXME */
mdThd.Teb = 0; /* FIXME */
mdThd.Stack.StartOfMemoryRange = 0; /* FIXME */
mdThd.Stack.Memory.DataSize = 0; /* FIXME */
mdThd.Stack.Memory.Rva = 0; /* FIXME */
mdThd.ThreadContext.DataSize = 0;/* FIXME */
mdThd.ThreadContext.Rva = 0; /* FIXME */
WriteFile(hFile, &mdThd, sizeof(mdThd), &written, NULL);
FIXME("Stack & thread context not written\n");
}
#endif
}
/******************************************************************
* MiniDumpWriteDump (DEBUGHLP.@)
*
*
*/
BOOL WINAPI MiniDumpWriteDump(HANDLE hProcess, DWORD ProcessId, HANDLE hFile,
MINIDUMP_TYPE DumpType,
PMINIDUMP_EXCEPTION_INFORMATION ExceptionParam,
PMINIDUMP_USER_STREAM_INFORMATION UserStreamParam,
PMINIDUMP_CALLBACK_INFORMATION CallbackParam)
{
struct process* pcs;
MINIDUMP_HEADER mdHead;
MINIDUMP_DIRECTORY mdDir;
DWORD currRva, written;
DWORD i, nStream, addStream;
RVA rva;
pcs = process_find_by_handle(hProcess);
if (!pcs) return FALSE; /* FIXME: should try to load it ??? */
/* 1) init */
nStream = UserStreamParam ? UserStreamParam->UserStreamCount : 0;
addStream = 0;
if (DumpType & MiniDumpNormal)
addStream += 3; /* sure ? thread stack back trace */
if (DumpType & MiniDumpWithDataSegs)
FIXME("NIY MiniDumpWithDataSegs\n");
if (DumpType & MiniDumpWithFullMemory)
FIXME("NIY MiniDumpWithFullMemory\n");
if (DumpType & MiniDumpWithHandleData)
FIXME("NIY MiniDumpWithHandleData\n");
if (DumpType & MiniDumpFilterMemory)
FIXME("NIY MiniDumpFilterMemory\n");
if (DumpType & MiniDumpScanMemory)
FIXME("NIY MiniDumpScanMemory\n");
/* 2) write header */
rva = sizeof(mdHead);
mdHead.Signature = MINIDUMP_SIGNATURE;
mdHead.Version = MINIDUMP_VERSION;
mdHead.NumberOfStreams = nStream + addStream;
mdHead.StreamDirectoryRva = rva;
mdHead.u.TimeDateStamp = time(NULL);
mdHead.Flags = DumpType;
WriteFile(hFile, &mdHead, sizeof(mdHead), &written, NULL);
/* 3) write stream directories */
rva += (nStream + addStream) * sizeof(mdDir);
/* 3.1) write data stream directories */
currRva = SetFilePointer(hFile, 0, NULL, FILE_CURRENT);
SetFilePointer(hFile, rva, NULL, FILE_BEGIN);
mdDir.StreamType = ModuleListStream;
mdDir.Location.Rva = rva;
dump_modules(pcs, hFile, &rva);
mdDir.Location.DataSize = SetFilePointer(hFile, 0, NULL, FILE_CURRENT) - mdDir.Location.Rva;
SetFilePointer(hFile, currRva, NULL, FILE_BEGIN);
WriteFile(hFile, &mdDir, sizeof(mdDir), &written, NULL);
currRva = SetFilePointer(hFile, 0, NULL, FILE_CURRENT);
SetFilePointer(hFile, rva, NULL, FILE_BEGIN);
mdDir.StreamType = ThreadListStream;
mdDir.Location.Rva = rva;
dump_threads(pcs, hFile, &rva);
mdDir.Location.DataSize = SetFilePointer(hFile, 0, NULL, FILE_CURRENT) - mdDir.Location.Rva;
SetFilePointer(hFile, currRva, NULL, FILE_BEGIN);
WriteFile(hFile, &mdDir, sizeof(mdDir), &written, NULL);
currRva = SetFilePointer(hFile, 0, NULL, FILE_CURRENT);
SetFilePointer(hFile, rva, NULL, FILE_BEGIN);
mdDir.StreamType = SystemInfoStream;
mdDir.Location.Rva = rva;
dump_system_info(pcs, hFile, &rva);
mdDir.Location.DataSize = SetFilePointer(hFile, 0, NULL, FILE_CURRENT) - mdDir.Location.Rva;
SetFilePointer(hFile, currRva, NULL, FILE_BEGIN);
WriteFile(hFile, &mdDir, sizeof(mdDir), &written, NULL);
/* 3.2) write user define stream */
for (i = 0; i < nStream; i++)
{
mdDir.StreamType = UserStreamParam->UserStreamArray[i].Type;
mdDir.Location.DataSize = UserStreamParam->UserStreamArray[i].BufferSize;
mdDir.Location.Rva = rva;
WriteFile(hFile, &mdDir, sizeof(mdDir), &written, NULL);
currRva = SetFilePointer(hFile, 0, NULL, FILE_CURRENT);
SetFilePointer(hFile, rva, NULL, FILE_BEGIN);
WriteFile(hFile,
UserStreamParam->UserStreamArray[i].Buffer,
UserStreamParam->UserStreamArray[i].BufferSize,
&written, NULL);
rva += UserStreamParam->UserStreamArray[i].BufferSize;
SetFilePointer(hFile, currRva, NULL, FILE_BEGIN);
}
return TRUE;
}
/*
* File module.c - module handling for the wine debugger
*
* Copyright (C) 1993, Eric Youngdale.
* 2000-2004, Eric Pouech
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "dbghelp_private.h"
#include "psapi.h"
#include "winreg.h"
#include "winternl.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
/***********************************************************************
* Creates and links a new module to a process
*/
struct module* module_new(struct process* pcs, const char* name,
enum DbgModuleType type,
unsigned long mod_addr, unsigned long size,
unsigned long stamp, unsigned long checksum)
{
struct module* module;
const char* ptr;
if (!(module = HeapAlloc(GetProcessHeap(), 0, sizeof(*module))))
return NULL;
memset(module, 0, sizeof(*module));
module->next = pcs->lmodules;
pcs->lmodules = module;
TRACE("=> %s %08lx-%08lx %s\n",
type == DMT_ELF ? "ELF" : (type == DMT_PE ? "PE" : "---"),
mod_addr, mod_addr + size, name);
pool_init(&module->pool, 65536);
module->module.SizeOfStruct = sizeof(module->module);
module->module.BaseOfImage = mod_addr;
module->module.ImageSize = size;
for (ptr = name + strlen(name) - 1;
*ptr != '/' && *ptr != '\\' && ptr >= name;
ptr--);
if (ptr < name || *ptr == '/' || *ptr == '\\') ptr++;
strncpy(module->module.ModuleName, ptr, sizeof(module->module.ModuleName));
module->module.ModuleName[sizeof(module->module.ModuleName) - 1] = '\0';
module->module.ImageName[0] = '\0';
strncpy(module->module.LoadedImageName, name,
sizeof(module->module.LoadedImageName));
module->module.LoadedImageName[sizeof(module->module.LoadedImageName) - 1] = '\0';
module->module.SymType = SymNone;
module->module.NumSyms = 0;
module->module.TimeDateStamp = stamp;
module->module.CheckSum = checksum;
module->type = type;
module->sortlist_valid = FALSE;
module->addr_sorttab = NULL;
/* FIXME: this seems a bit too high (on a per module basis)
* need some statistics about this
*/
hash_table_init(&module->pool, &module->ht_symbols, 4096);
hash_table_init(&module->pool, &module->ht_types, 4096);
module->sources_used = 0;
module->sources_alloc = 0;
module->sources = 0;
return module;
}
/***********************************************************************
* module_find_by_name
*
*/
struct module* module_find_by_name(const struct process* pcs,
const char* name, enum DbgModuleType type)
{
struct module* module;
if (type == DMT_UNKNOWN)
{
if ((module = module_find_by_name(pcs, name, DMT_PE)) ||
(module = module_find_by_name(pcs, name, DMT_ELF)))
return module;
}
else
{
for (module = pcs->lmodules; module; module = module->next)
{
if (type == module->type && !strcasecmp(name, module->module.LoadedImageName))
return module;
}
for (module = pcs->lmodules; module; module = module->next)
{
if (type == module->type && !strcasecmp(name, module->module.ModuleName))
return module;
}
}
SetLastError(ERROR_INVALID_NAME);
return NULL;
}
/***********************************************************************
* module_has_container
*
*/
static struct module* module_get_container(const struct process* pcs,
const struct module* inner)
{
struct module* module;
for (module = pcs->lmodules; module; module = module->next)
{
if (module != inner &&
module->module.BaseOfImage <= inner->module.BaseOfImage &&
module->module.BaseOfImage + module->module.ImageSize >=
inner->module.BaseOfImage + inner->module.ImageSize)
return module;
}
return NULL;
}
/******************************************************************
* module_get_debug
*
* get the debug information from a module:
* - if the module's type is deferred, then force loading of debug info (and return
* the module itself)
* - if the module has no debug info and has an ELF container, then return the ELF
* container (and also force the ELF container's debug info loading if deferred)
* - otherwise return the module itself if it has some debug info
*/
struct module* module_get_debug(const struct process* pcs, struct module* module)
{
if (!module) return NULL;
switch (module->module.SymType)
{
case -1: break;
case SymNone:
module = module_get_container(pcs, module);
if (!module || module->module.SymType != SymDeferred) break;
/* fall through */
case SymDeferred:
switch (module->type)
{
case DMT_ELF:
elf_load_debug_info(module);
break;
case DMT_PE:
pe_load_debug_info(pcs, module);
break;
default: break;
}
break;
default: break;
}
return (module && module->module.SymType > SymNone) ? module : NULL;
}
/***********************************************************************
* module_find_by_addr
*
* either the addr where module is loaded, or any address inside the
* module
*/
struct module* module_find_by_addr(const struct process* pcs, unsigned long addr,
enum DbgModuleType type)
{
struct module* module;
if (type == DMT_UNKNOWN)
{
if ((module = module_find_by_addr(pcs, addr, DMT_PE)) ||
(module = module_find_by_addr(pcs, addr, DMT_ELF)))
return module;
}
else
{
for (module = pcs->lmodules; module; module = module->next)
{
if (type == module->type && addr >= module->module.BaseOfImage &&
addr < module->module.BaseOfImage + module->module.ImageSize)
return module;
}
}
SetLastError(ERROR_INVALID_ADDRESS);
return module;
}
/***********************************************************************
* SymLoadModule (DBGHELP.@)
*/
DWORD WINAPI SymLoadModule(HANDLE hProcess, HANDLE hFile, char* ImageName,
char* ModuleName, DWORD BaseOfDll, DWORD SizeOfDll)
{
struct process* pcs;
struct module* module = NULL;
TRACE("(%p %p %s %s %08lx %08lx)\n",
hProcess, hFile, debugstr_a(ImageName), debugstr_a(ModuleName),
BaseOfDll, SizeOfDll);
pcs = process_find_by_handle(hProcess);
if (!pcs) return FALSE;
if (!(module = pe_load_module(pcs, ImageName, hFile, BaseOfDll, SizeOfDll)))
{
unsigned len = strlen(ImageName);
if (!strcmp(ImageName + len - 3, ".so") &&
(module = elf_load_module(pcs, ImageName))) goto done;
if ((module = pe_load_module_from_pcs(pcs, ImageName, ModuleName, BaseOfDll, SizeOfDll)))
goto done;
WARN("Couldn't locate %s\n", ImageName);
return 0;
}
done:
/* by default pe_load_module fills module.ModuleName from a derivation
* of ImageName. Overwrite it, if we have better information
*/
if (ModuleName)
{
strncpy(module->module.ModuleName, ModuleName,
sizeof(module->module.ModuleName));
module->module.ModuleName[sizeof(module->module.ModuleName) - 1] = '\0';
}
strncpy(module->module.ImageName, ImageName, sizeof(module->module.ImageName));
module->module.ImageName[sizeof(module->module.ImageName) - 1] = '\0';
/* force transparent ELF loading / unloading */
if (module->type != DMT_ELF) elf_synchronize_module_list(pcs);
return module->module.BaseOfImage;
}
/******************************************************************
* module_remove
*
*/
BOOL module_remove(struct process* pcs, struct module* module)
{
struct module** p;
TRACE("%s (%p)\n", module->module.ModuleName, module);
hash_table_destroy(&module->ht_symbols);
hash_table_destroy(&module->ht_types);
HeapFree(GetProcessHeap(), 0, (char*)module->sources);
HeapFree(GetProcessHeap(), 0, module->addr_sorttab);
pool_destroy(&module->pool);
for (p = &pcs->lmodules; *p; p = &(*p)->next)
{
if (*p == module)
{
*p = module->next;
HeapFree(GetProcessHeap(), 0, module);
return TRUE;
}
}
FIXME("This shouldn't happen\n");
return FALSE;
}
/******************************************************************
* SymUnloadModule (DBGHELP.@)
*
*/
BOOL WINAPI SymUnloadModule(HANDLE hProcess, DWORD BaseOfDll)
{
struct process* pcs;
struct module* module;
pcs = process_find_by_handle(hProcess);
if (!pcs) return FALSE;
module = module_find_by_addr(pcs, BaseOfDll, DMT_UNKNOWN);
if (!module) return FALSE;
return module_remove(pcs, module);
}
/******************************************************************
* SymEnumerateModules (DBGHELP.@)
*
*/
BOOL WINAPI SymEnumerateModules(HANDLE hProcess,
PSYM_ENUMMODULES_CALLBACK EnumModulesCallback,
PVOID UserContext)
{
struct process* pcs = process_find_by_handle(hProcess);
struct module* module;
if (!pcs) return FALSE;
for (module = pcs->lmodules; module; module = module->next)
{
if (module->type != DMT_PE) continue;
if (!EnumModulesCallback(module->module.ModuleName,
module->module.BaseOfImage, UserContext))
break;
}
return TRUE;
}
/******************************************************************
* EnumerateLoadedModules (DBGHELP.@)
*
*/
BOOL WINAPI EnumerateLoadedModules(HANDLE hProcess,
PENUMLOADED_MODULES_CALLBACK EnumLoadedModulesCallback,
PVOID UserContext)
{
HMODULE* hMods;
char img[256], mod[256];
DWORD i, sz;
MODULEINFO mi;
hMods = HeapAlloc(GetProcessHeap(), 0, sz);
if (!hMods) return FALSE;
if (!EnumProcessModules(hProcess, hMods, 256 * sizeof(hMods[0]), &sz))
{
/* hProcess should also be a valid process handle !! */
FIXME("If this happens, bump the number in mod\n");
HeapFree(GetProcessHeap(), 0, hMods);
return FALSE;
}
sz /= sizeof(HMODULE);
for (i = 0; i < sz; i++)
{
if (!GetModuleInformation(hProcess, hMods[i], &mi, sizeof(mi)) ||
!GetModuleFileNameExA(hProcess, hMods[i], img, sizeof(img)) ||
!GetModuleBaseNameA(hProcess, hMods[i], mod, sizeof(mod)))
break;
EnumLoadedModulesCallback(mod, (DWORD)mi.lpBaseOfDll, mi.SizeOfImage,
UserContext);
}
HeapFree(GetProcessHeap(), 0, hMods);
return sz != 0 && i == sz;
}
/******************************************************************
* SymGetModuleInfo (DBGHELP.@)
*
*/
BOOL WINAPI SymGetModuleInfo(HANDLE hProcess, DWORD dwAddr,
PIMAGEHLP_MODULE ModuleInfo)
{
struct process* pcs = process_find_by_handle(hProcess);
struct module* module;
if (!pcs) return FALSE;
if (ModuleInfo->SizeOfStruct < sizeof(*ModuleInfo)) return FALSE;
module = module_find_by_addr(pcs, dwAddr, DMT_UNKNOWN);
if (!module) return FALSE;
*ModuleInfo = module->module;
if (module->module.SymType <= SymNone)
{
module = module_get_container(pcs, module);
if (module && module->module.SymType > SymNone)
ModuleInfo->SymType = module->module.SymType;
}
return TRUE;
}
/***********************************************************************
* SymGetModuleBase (IMAGEHLP.@)
*/
DWORD WINAPI SymGetModuleBase(HANDLE hProcess, DWORD dwAddr)
{
struct process* pcs = process_find_by_handle(hProcess);
struct module* module;
if (!pcs) return 0;
module = module_find_by_addr(pcs, dwAddr, DMT_UNKNOWN);
if (!module) return 0;
return module->module.BaseOfImage;
}
This diff is collapsed.
/*
* File path.c - managing path in debugging environments
*
* Copyright (C) 2004, Eric Pouech
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "dbghelp_private.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
/******************************************************************
* FindDebugInfoFile (DBGHELP.@)
*
*/
HANDLE WINAPI FindDebugInfoFile(PSTR FileName, PSTR SymbolPath, PSTR DebugFilePath)
{
HANDLE h;
h = CreateFileA(DebugFilePath, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (h == INVALID_HANDLE_VALUE)
{
const char* p = strrchr(FileName, '/');
if (!p) p = FileName;
if (!SearchPathA(SymbolPath, p, NULL, MAX_PATH, DebugFilePath, NULL))
return NULL;
h = CreateFileA(DebugFilePath, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
}
return (h == INVALID_HANDLE_VALUE) ? NULL : h;
}
/******************************************************************
* FindDebugInfoFileEx (DBGHELP.@)
*
*/
HANDLE WINAPI FindDebugInfoFileEx(PSTR FileName, PSTR SymbolPath,
PSTR DebugFilePath,
PFIND_DEBUG_FILE_CALLBACK Callback,
PVOID CallerData)
{
FIXME("(%s %s %p %p %p): stub\n",
FileName, SymbolPath, DebugFilePath, Callback, CallerData);
return NULL;
}
/******************************************************************
* FindExecutableImage (DBGHELP.@)
*
*/
HANDLE WINAPI FindExecutableImage(PSTR FileName, PSTR SymbolPath, PSTR ImageFilePath)
{
HANDLE h;
if (!SearchPathA(SymbolPath, FileName, NULL, MAX_PATH, ImageFilePath, NULL))
return NULL;
h = CreateFileA(ImageFilePath, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
return (h == INVALID_HANDLE_VALUE) ? NULL : h;
}
/***********************************************************************
* MakeSureDirectoryPathExists (DBGHELP.@)
*/
BOOL WINAPI MakeSureDirectoryPathExists(LPCSTR DirPath)
{
if (CreateDirectoryA(DirPath, NULL)) return TRUE;
if (GetLastError() == ERROR_ALREADY_EXISTS)
{
SetLastError(ERROR_SUCCESS);
return TRUE;
}
return FALSE;
}
/***********************************************************************
* SearchTreeForFile (DBGHELP.@)
*/
BOOL WINAPI SearchTreeForFile(LPSTR RootPath, LPSTR InputPathName,
LPSTR OutputPathBuffer)
{
FIXME("(%s, %s, %s): stub\n",
debugstr_a(RootPath), debugstr_a(InputPathName),
debugstr_a(OutputPathBuffer));
SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
return FALSE;
}
/*
* File pe_module.c - handle PE module information
*
* Copyright (C) 1996, Eric Youngdale.
* Copyright (C) 1999-2000, Ulrich Weigand.
* Copyright (C) 2004, Eric Pouech.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "dbghelp_private.h"
#include "winreg.h"
#include "winternl.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
/******************************************************************
* pe_load_stabs
*
* look for stabs information in PE header (it's how the mingw compiler provides
* its debugging information)
*/
static SYM_TYPE pe_load_stabs(const struct process* pcs, struct module* module,
const void* mapping, IMAGE_NT_HEADERS* nth)
{
IMAGE_SECTION_HEADER* section;
int i, stabsize = 0, stabstrsize = 0;
unsigned int stabs = 0, stabstr = 0;
SYM_TYPE sym_type = SymNone;
section = (IMAGE_SECTION_HEADER*)
((char*)&nth->OptionalHeader + nth->FileHeader.SizeOfOptionalHeader);
for (i = 0; i < nth->FileHeader.NumberOfSections; i++, section++)
{
if (!strcasecmp(section->Name, ".stab"))
{
stabs = section->VirtualAddress;
stabsize = section->SizeOfRawData;
}
else if (!strncasecmp(section->Name, ".stabstr", 8))
{
stabstr = section->VirtualAddress;
stabstrsize = section->SizeOfRawData;
}
}
if (stabstrsize && stabsize)
{
sym_type = stabs_parse(module, mapping, module->module.BaseOfImage,
stabs, stabsize, stabstr, stabstrsize);
}
return sym_type;
}
/******************************************************************
* pe_load_dbg_file
*
* loads a .dbg file
*/
static SYM_TYPE pe_load_dbg_file(const struct process* pcs, struct module* module,
char* dbg_name, DWORD timestamp)
{
char tmp[MAX_PATH];
HANDLE hFile, hMap = 0;
const BYTE* dbg_mapping = NULL;
PIMAGE_SEPARATE_DEBUG_HEADER hdr;
PIMAGE_DEBUG_DIRECTORY dbg;
SYM_TYPE sym_type = -1;
WINE_TRACE("Processing DBG file %s\n", dbg_name);
if ((hFile = FindDebugInfoFile(dbg_name, pcs->search_path, tmp)) != NULL &&
((hMap = CreateFileMappingA(hFile, NULL, PAGE_READONLY, 0, 0, NULL)) != 0) &&
((dbg_mapping = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0)) != NULL))
{
hdr = (PIMAGE_SEPARATE_DEBUG_HEADER)dbg_mapping;
if (hdr->TimeDateStamp != timestamp)
{
WINE_ERR("Warning - %s has incorrect internal timestamp\n",
dbg_name);
/*
* Well, sometimes this happens to DBG files which ARE REALLY the
* right .DBG files but nonetheless this check fails. Anyway,
* WINDBG (debugger for Windows by Microsoft) loads debug symbols
* which have incorrect timestamps.
*/
}
dbg = (PIMAGE_DEBUG_DIRECTORY)
(dbg_mapping + sizeof(*hdr) +
hdr->NumberOfSections * sizeof(IMAGE_SECTION_HEADER) +
hdr->ExportedNamesSize);
sym_type = pe_load_debug_directory(pcs, module, dbg_mapping, dbg,
hdr->DebugDirectorySize / sizeof(*dbg));
}
else
{
WINE_ERR("-Unable to peruse .DBG file %s (%s)\n",
dbg_name, debugstr_a(tmp));
}
if (dbg_mapping) UnmapViewOfFile((void*)dbg_mapping);
if (hMap) CloseHandle(hMap);
if (hFile != NULL) CloseHandle(hFile);
return sym_type;
}
/******************************************************************
* pe_load_msc_debug_info
*
* Process MSC debug information in PE file.
*/
static SYM_TYPE pe_load_msc_debug_info(const struct process* pcs,
struct module* module,
const void* mapping, IMAGE_NT_HEADERS* nth)
{
SYM_TYPE sym_type = -1;
PIMAGE_DATA_DIRECTORY dir;
PIMAGE_DEBUG_DIRECTORY dbg = NULL;
int nDbg;
/* Read in debug directory */
dir = nth->OptionalHeader.DataDirectory + IMAGE_DIRECTORY_ENTRY_DEBUG;
nDbg = dir->Size / sizeof(IMAGE_DEBUG_DIRECTORY);
if (!nDbg) return sym_type;
dbg = (PIMAGE_DEBUG_DIRECTORY)((char*)mapping + dir->VirtualAddress);
/* Parse debug directory */
if (nth->FileHeader.Characteristics & IMAGE_FILE_DEBUG_STRIPPED)
{
/* Debug info is stripped to .DBG file */
PIMAGE_DEBUG_MISC misc = (PIMAGE_DEBUG_MISC)
((char*)mapping + dbg->PointerToRawData);
if (nDbg != 1 || dbg->Type != IMAGE_DEBUG_TYPE_MISC ||
misc->DataType != IMAGE_DEBUG_MISC_EXENAME)
{
WINE_ERR("-Debug info stripped, but no .DBG file in module %s\n",
module->module.ModuleName);
}
else
{
sym_type = pe_load_dbg_file(pcs, module, misc->Data, nth->FileHeader.TimeDateStamp);
}
}
else
{
/* Debug info is embedded into PE module */
sym_type = pe_load_debug_directory(pcs, module, mapping, dbg, nDbg);
}
return sym_type;
}
/***********************************************************************
* pe_load_export_debug_info
*/
static SYM_TYPE pe_load_export_debug_info(const struct process* pcs,
struct module* module,
const void* mapping, IMAGE_NT_HEADERS* nth)
{
char buffer[512];
unsigned int i;
IMAGE_DATA_DIRECTORY* dir;
DWORD base = module->module.BaseOfImage;
ADDRESS addr;
addr.Mode = AddrModeFlat;
addr.Segment = 0;
#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, 0,
TRUE /* FIXME */, TRUE /* FIXME */);
#endif
/* Add entry point */
snprintf(buffer, sizeof(buffer), "%s.EntryPoint", module->module.ModuleName);
symt_new_public(module, NULL, buffer,
base + nth->OptionalHeader.AddressOfEntryPoint, 0,
TRUE /* FIXME */, TRUE /* FIXME */);
#if 0
IMAGE_SECTION_HEADER* section;
/* Add start of sections */
section = (IMAGE_SECTION_HEADER*)
((char*)&nth->OptionalHeader + nth->FileHeader.SizeOfOptionalHeader);
for (i = 0; i < nth->FileHeader.NumberOfSections; i++, section++)
{
snprintf(buffer, sizeof(buffer), "%s.%s",
module->module.ModuleName, section->Name);
symt_new_public(module, NULL, buffer, base + section->VirtualAddress, 0,
TRUE /* FIXME */, TRUE /* FIXME */);
}
#endif
/* Add exported functions */
if ((dir = RtlImageDirectoryEntryToData((void*)mapping, TRUE,
IMAGE_DIRECTORY_ENTRY_EXPORT, NULL)))
{
IMAGE_EXPORT_DIRECTORY* exports;
WORD* ordinals = NULL;
void** functions = NULL;
DWORD* names = NULL;
unsigned int j;
exports = (void*)((char*)mapping + dir->VirtualAddress);
functions = (void*)((char*)mapping + exports->AddressOfFunctions);
ordinals = (void*)((char*)mapping + exports->AddressOfNameOrdinals);
names = (void*)((char*)mapping + exports->AddressOfNames);
for (i = 0; i < exports->NumberOfNames; i++)
{
if (!names[i]) continue;
snprintf(buffer, sizeof(buffer), "%s.%s",
module->module.ModuleName, (char*)base + names[i]);
symt_new_public(module, NULL, buffer,
base + (DWORD)functions[ordinals[i]], 0,
TRUE /* FIXME */, TRUE /* FIXME */);
}
for (i = 0; i < exports->NumberOfFunctions; i++)
{
if (!functions[i]) continue;
/* Check if we already added it with a name */
for (j = 0; j < exports->NumberOfNames; j++)
if ((ordinals[j] == i) && names[j]) break;
if (j < exports->NumberOfNames) continue;
snprintf(buffer, sizeof(buffer), "%s.%ld",
module->module.ModuleName, i + exports->Base);
symt_new_public(module, NULL, buffer, base + (DWORD)functions[i], 0,
TRUE /* FIXME */, TRUE /* FIXME */);
}
}
/* no real debug info, only entry points */
return module->module.SymType = SymExport;
}
/******************************************************************
* pe_load_debug_info
*
*/
SYM_TYPE pe_load_debug_info(const struct process* pcs, struct module* module)
{
SYM_TYPE sym_type = -1;
HANDLE hFile;
HANDLE hMap;
void* mapping;
IMAGE_NT_HEADERS* nth;
hFile = CreateFileA(module->module.LoadedImageName, GENERIC_READ, FILE_SHARE_READ,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE) return -1;
if ((hMap = CreateFileMappingA(hFile, NULL, PAGE_READONLY, 0, 0, NULL)) != 0)
{
if ((mapping = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0)) != NULL)
{
nth = RtlImageNtHeader(mapping);
if (!(dbghelp_options & SYMOPT_PUBLICS_ONLY))
{
sym_type = pe_load_stabs(pcs, module, mapping, nth);
if (sym_type <= SymNone)
sym_type = pe_load_msc_debug_info(pcs, module, mapping, nth);
/* 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
*/
}
if (sym_type <= SymNone && !module_get_debug(pcs, module))
sym_type = pe_load_export_debug_info(pcs, module, mapping, nth);
UnmapViewOfFile(mapping);
}
CloseHandle(hMap);
}
CloseHandle(hFile);
module->module.SymType = (sym_type >= SymNone) ? sym_type : SymNone;
return sym_type;
}
/******************************************************************
* pe_load_module
*
*/
struct module* pe_load_module(struct process* pcs, char* name,
HANDLE hFile, DWORD base, DWORD size)
{
struct module* module = NULL;
BOOL opened = FALSE;
HANDLE hMap;
void* mapping;
char loaded_name[MAX_PATH];
loaded_name[0] = '\0';
if (!hFile)
{
if (!name)
{
/* FIXME SetLastError */
return NULL;
}
if ((hFile = FindExecutableImage(name, NULL, loaded_name)) == NULL)
return NULL;
opened = TRUE;
}
else if (name) strcpy(loaded_name, name);
else if (dbghelp_options & SYMOPT_DEFERRED_LOADS)
FIXME("Trouble ahead (no module name passed in deferred mode)\n");
if ((hMap = CreateFileMappingA(hFile, NULL, PAGE_READONLY, 0, 0, NULL)) != 0)
{
if ((mapping = MapViewOfFile(hMap, FILE_MAP_READ, 0, 0, 0)) != NULL)
{
IMAGE_NT_HEADERS* nth = RtlImageNtHeader(mapping);
if (nth)
{
if (!base) base = nth->OptionalHeader.ImageBase;
if (!size) size = nth->OptionalHeader.SizeOfImage;
module = module_new(pcs, loaded_name, DMT_PE, base, size,
nth->FileHeader.TimeDateStamp,
nth->OptionalHeader.CheckSum);
if (module)
{
module->module.SymType = (dbghelp_options & SYMOPT_DEFERRED_LOADS) ?
SymDeferred : pe_load_debug_info(pcs, module);
}
}
UnmapViewOfFile(mapping);
}
CloseHandle(hMap);
}
if (opened) CloseHandle(hFile);
return module;
}
/******************************************************************
* pe_load_module_from_pcs
*
*/
struct module* pe_load_module_from_pcs(struct process* pcs, const char* name,
const char* mod_name, DWORD base, DWORD size)
{
struct module* module;
const char* ptr;
if ((module = module_find_by_name(pcs, name, DMT_PE))) return module;
if (mod_name) ptr = mod_name;
else
{
for (ptr = name + strlen(name) - 1; ptr >= name; ptr--)
{
if (*ptr == '/' || *ptr == '\\')
{
ptr++;
break;
}
}
}
if (ptr && (module = module_find_by_name(pcs, ptr, DMT_PE))) return module;
if (base && pcs->dbg_hdr_addr)
{
IMAGE_DOS_HEADER dos;
IMAGE_NT_HEADERS nth;
if (read_mem(pcs->handle, base, &dos, sizeof(dos)) &&
dos.e_magic == IMAGE_DOS_SIGNATURE &&
read_mem(pcs->handle, base + dos.e_lfanew, &nth, sizeof(nth)) &&
nth.Signature == IMAGE_NT_SIGNATURE)
{
if (!size) size = nth.OptionalHeader.SizeOfImage;
module = module_new(pcs, name, DMT_PE, base, size,
nth.FileHeader.TimeDateStamp, nth.OptionalHeader.CheckSum);
}
}
return module;
}
/*
* File source.c - source files management
*
* Copyright (C) 2004, Eric Pouech.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "dbghelp_private.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(dbghelp);
/******************************************************************
* source_find
*
* check whether a source file has already been stored
*/
static unsigned source_find(const struct module* module, const char* name)
{
char* ptr = module->sources;
while (*ptr)
{
if (strcmp(ptr, name) == 0) return ptr - module->sources;
ptr += strlen(ptr) + 1;
}
return (unsigned)-1;
}
/******************************************************************
* source_new
*
* checks if source exists. if not, add it
*/
unsigned source_new(struct module* module, const char* name)
{
int len;
unsigned ret;
if (!name) return (unsigned)-1;
if (module->sources && (ret = source_find(module, name)) != (unsigned)-1)
return ret;
len = strlen(name) + 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 = HeapAlloc(GetProcessHeap(), 0, module->sources_alloc);
else
module->sources = HeapReAlloc(GetProcessHeap(), 0, module->sources,
module->sources_alloc);
}
ret = module->sources_used;
strcpy(module->sources + module->sources_used, name);
module->sources_used += len;
module->sources[module->sources_used] = '\0';
return ret;
}
/******************************************************************
* source_get
*
* returns a stored source file name
*/
const char* source_get(const struct module* module, unsigned idx)
{
if (idx == -1) return "";
assert(module->sources);
return module->sources + idx;
}
/******************************************************************
* SymEnumSourceFiles (DBGHELP.@)
*
*/
BOOL WINAPI SymEnumSourceFiles(HANDLE hProcess, ULONG ModBase, LPSTR Mask,
PSYM_ENUMSOURCFILES_CALLBACK cbSrcFiles,
void* UserContext)
{
struct process* pcs;
struct module* module;
SOURCEFILE sf;
char* ptr;
if (!cbSrcFiles) return FALSE;
pcs = process_find_by_handle(hProcess);
if (!pcs) return FALSE;
if (ModBase)
{
module = module_find_by_addr(pcs, ModBase, DMT_UNKNOWN);
if (!(module = module_get_debug(pcs, module))) return FALSE;
}
else
{
if (Mask[0] == '!')
{
module = module_find_by_name(pcs, Mask + 1, DMT_UNKNOWN);
if (!(module = module_get_debug(pcs, module))) return FALSE;
}
else
{
FIXME("Unsupported yet (should get info from current context)\n");
return FALSE;
}
}
if (!module->sources) return FALSE;
for (ptr = module->sources; *ptr; ptr += strlen(ptr) + 1)
{
/* FIXME: not using Mask */
sf.ModBase = ModBase;
sf.FileName = ptr;
if (!cbSrcFiles(&sf, UserContext)) break;
}
return TRUE;
}
This diff is collapsed.
/*
* Stack walking
*
* Copyright 1995 Alexandre Julliard
* Copyright 1996 Eric Youngdale
* Copyright 1999 Ove Kven
* Copyright 2004 Eric Pouech
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>
#include "dbghelp_private.h"
#include "winreg.h"
#include "ntstatus.h"
#include "thread.h" /* FIXME: must be included before winternl.h */
#include "winternl.h"
#include "wine/debug.h"
#include "stackframe.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)
{
if (!addr) return "(null)";
switch (addr->Mode)
{
case AddrModeFlat:
return wine_dbg_sprintf("flat<%08lx>", addr->Offset);
case AddrMode1616:
return wine_dbg_sprintf("1616<%04x:%04lx>", addr->Segment, addr->Offset);
case AddrMode1632:
return wine_dbg_sprintf("1632<%04x:%08lx>", addr->Segment, addr->Offset);
case AddrModeReal:
return wine_dbg_sprintf("real<%04x:%04lx>", addr->Segment, addr->Offset);
default:
return "unknown";
}
}
/* 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])
/***********************************************************************
* StackWalk (DBGHELP.@)
*/
BOOL WINAPI StackWalk(DWORD MachineType, HANDLE hProcess, HANDLE hThread,
LPSTACKFRAME frame, LPVOID _ctx,
PREAD_PROCESS_MEMORY_ROUTINE f_read_mem,
PFUNCTION_TABLE_ACCESS_ROUTINE FunctionTableAccessRoutine,
PGET_MODULE_BASE_ROUTINE GetModuleBaseRoutine,
PTRANSLATE_ADDRESS_ROUTINE f_xlat_adr)
{
CONTEXT* ctx = (CONTEXT*)_ctx;
STACK32FRAME frame32;
STACK16FRAME frame16;
char ch;
ADDRESS tmp;
DWORD p;
WORD val;
BOOL do_switch;
TRACE("(%ld, %p, %p, %p, %p, %p, %p, %p, %p)\n",
MachineType, hProcess, hThread, frame, _ctx,
f_read_mem, FunctionTableAccessRoutine,
GetModuleBaseRoutine, f_xlat_adr);
if (MachineType != IMAGE_FILE_MACHINE_I386)
{
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
/* sanity check */
if (curr_mode >= stm_done) return FALSE;
if (!f_read_mem) f_read_mem = ReadProcessMemory;
if (!f_xlat_adr) f_xlat_adr = addr_to_linear;
TRACE("Enter: PC=%s Frame=%s Return=%s Stack=%s Mode=%s cSwitch=%08lx nSwitch=%08lx\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;
/* Init done */
curr_mode = (frame->AddrPC.Mode == AddrModeFlat) ?
stm_32bit : stm_16bit;
/* Get the current ESP (don't know if this is valid) */
if (ctx)
{
frame->AddrStack.Segment = 0;
frame->AddrStack.Offset = ctx->Esp;
frame->AddrStack.Mode = AddrModeFlat;
}
/* cur_switch holds address of curr_stack's field in TEB in debuggee
* address space
*/
if (NtQueryInformationThread(hThread, ThreadBasicInformation, &info,
sizeof(info), NULL) != STATUS_SUCCESS)
goto done_err;
curr_switch = (unsigned long)info.TebBaseAddress + FIELD_OFFSET(TEB, cur_stack);
if (!f_read_mem(hProcess, (void*)curr_switch, &next_switch,
sizeof(next_switch), NULL))
{
WARN("Can't read TEB:cur_stack\n");
goto done_err;
}
if (curr_mode == stm_16bit)
{
if (!f_read_mem(hProcess, (void*)next_switch, &frame32,
sizeof(frame32), NULL))
{
WARN("Bad stack frame 0x%08lx\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 (!f_read_mem(hProcess, (void*)f_xlat_adr(hProcess, hThread, &tmp),
&ch, sizeof(ch), NULL))
curr_switch = 0xFFFFFFFF;
frame->AddrReturn.Mode = frame->AddrStack.Mode = AddrMode1616;
/* "pop up" previous BP value */
if (!f_read_mem(hProcess, (void*)frame->AddrFrame.Offset,
&val, sizeof(WORD), NULL))
goto done_err;
frame->AddrFrame.Offset = val;
}
else
{
tmp.Mode = AddrMode1616;
tmp.Segment = SELECTOROF(next_switch);
tmp.Offset = OFFSETOF(next_switch);
p = f_xlat_adr(hProcess, hThread, &tmp);
if (!f_read_mem(hProcess, (void*)p, &frame16, sizeof(frame16), NULL))
{
WARN("Bad stack frame 0x%08lx\n", p);
goto done_err;
}
curr_switch = (DWORD)frame16.frame32;
if (!f_read_mem(hProcess, (void*)curr_switch, &ch, sizeof(ch), NULL))
curr_switch = 0xFFFFFFFF;
frame->AddrReturn.Mode = frame->AddrStack.Mode = AddrModeFlat;
/* "pop up" previous EBP value */
if (!f_read_mem(hProcess, (void*)frame->AddrFrame.Offset,
&frame->AddrFrame.Offset, sizeof(DWORD), NULL))
goto done_err;
}
}
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 = OFFSETOF(curr_switch) &&
frame->AddrFrame.Segment == SELECTOROF(curr_switch) &&
frame->AddrFrame.Offset >= OFFSETOF(curr_switch);
}
if (do_switch)
{
if (curr_mode == stm_16bit)
{
if (!f_read_mem(hProcess, (void*)next_switch, &frame32,
sizeof(frame32), NULL))
{
WARN("Bad stack frame 0x%08lx\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 = f_xlat_adr(hProcess, hThread, &tmp);
if (!f_read_mem(hProcess, (void*)p, &frame16, sizeof(frame16), NULL))
{
WARN("Bad stack frame 0x%08lx\n", p);
goto done_err;
}
curr_switch = (DWORD)frame16.frame32;
curr_mode = stm_32bit;
if (!f_read_mem(hProcess, (void*)curr_switch, &ch, sizeof(ch), NULL))
curr_switch = 0xFFFFFFFF;
}
else
{
tmp.Mode = AddrMode1616;
tmp.Segment = SELECTOROF(next_switch);
tmp.Offset = OFFSETOF(next_switch);
p = f_xlat_adr(hProcess, hThread, &tmp);
if (!f_read_mem(hProcess, (void*)p, &frame16, sizeof(frame16), NULL))
{
WARN("Bad stack frame 0x%08lx\n", p);
goto done_err;
}
TRACE("Got a 16 bit stack switch:"
"\n\tframe32: %08lx"
"\n\tedx:%08lx ecx:%08lx ebp:%08lx"
"\n\tds:%04x es:%04x fs:%04x gs:%04x"
"\n\tcall_from_ip:%08lx module_cs:%04lx relay=%08lx"
"\n\tentry_ip:%04x entry_point:%08lx"
"\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 (!f_read_mem(hProcess, (void*)next_switch, &frame32, sizeof(frame32),
NULL))
{
WARN("Bad stack frame 0x%08lx\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 (!f_read_mem(hProcess, (void*)f_xlat_adr(hProcess, hThread, &tmp),
&ch, sizeof(ch), NULL))
curr_switch = 0xFFFFFFFF;
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 (!f_read_mem(hProcess,
(void*)f_xlat_adr(hProcess, hThread, &frame->AddrFrame),
&val, sizeof(WORD), NULL))
goto done_err;
frame->AddrFrame.Offset = val;
}
else
{
frame->AddrStack.Offset = frame->AddrFrame.Offset + 2 * sizeof(DWORD);
/* "pop up" previous EBP value */
if (!f_read_mem(hProcess, (void*)frame->AddrFrame.Offset,
&frame->AddrFrame.Offset, sizeof(DWORD), NULL))
goto done_err;
}
}
}
if (curr_mode == stm_16bit)
{
int i;
p = f_xlat_adr(hProcess, hThread, &frame->AddrFrame);
if (!f_read_mem(hProcess, (void*)(p + sizeof(WORD)), &val, sizeof(WORD), NULL))
goto done_err;
frame->AddrReturn.Offset = val;
/* get potential cs if a far call was used */
if (!f_read_mem(hProcess, (void*)(p + 2 * sizeof(WORD)),
&val, sizeof(WORD), NULL))
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(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" paramaters 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++)
{
f_read_mem(hProcess, (void*)(p + (2 + i) * sizeof(WORD)),
&val, sizeof(val), NULL);
frame->Params[i] = val;
}
}
else
{
if (!f_read_mem(hProcess,
(void*)(frame->AddrFrame.Offset + sizeof(DWORD)),
&frame->AddrReturn.Offset, sizeof(DWORD), NULL))
goto done_err;
f_read_mem(hProcess,
(void*)(frame->AddrFrame.Offset + 2 * sizeof(DWORD)),
frame->Params, sizeof(frame->Params), NULL);
}
frame->Far = FALSE;
frame->Virtual = FALSE;
TRACE("Leave: PC=%s Frame=%s Return=%s Stack=%s Mode=%s cSwitch=%08lx nSwitch=%08lx\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);
return TRUE;
done_err:
curr_mode = stm_done;
return FALSE;
}
This diff is collapsed.
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment