Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-cw
Commits
800773f9
Commit
800773f9
authored
Aug 06, 2001
by
Eric Pouech
Committed by
Alexandre Julliard
Aug 06, 2001
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Extended bt command to display backtrace of another thread.
Enhanced process & thread display with process name.
parent
c457fbdd
Show whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
113 additions
and
40 deletions
+113
-40
dbg.y
debugger/dbg.y
+2
-1
debugger.h
debugger/debugger.h
+4
-1
info.c
debugger/info.c
+21
-5
stack.c
debugger/stack.c
+62
-13
winedbg.c
debugger/winedbg.c
+20
-19
debugger.sgml
documentation/debugger.sgml
+4
-1
No files found.
debugger/dbg.y
View file @
800773f9
...
...
@@ -120,7 +120,8 @@ command:
| tENABLE tNUM tEOL { DEBUG_EnableBreakpoint( $2, TRUE ); }
| tDISABLE tNUM tEOL { DEBUG_EnableBreakpoint( $2, FALSE ); }
| tDELETE tBREAK tNUM tEOL { DEBUG_DelBreakpoint( $3 ); }
| tBACKTRACE tEOL { DEBUG_BackTrace(TRUE); }
| tBACKTRACE tEOL { DEBUG_BackTrace(DEBUG_CurrTid, TRUE); }
| tBACKTRACE tNUM tEOL { DEBUG_BackTrace($2, TRUE); }
| tUP tEOL { DEBUG_SetFrame( curr_frame + 1 ); }
| tUP tNUM tEOL { DEBUG_SetFrame( curr_frame + $2 ); }
| tDOWN tEOL { DEBUG_SetFrame( curr_frame - 1 ); }
...
...
debugger/debugger.h
View file @
800773f9
...
...
@@ -191,6 +191,7 @@ typedef struct tagDBG_DELAYED_BP {
typedef
struct
tagDBG_PROCESS
{
HANDLE
handle
;
DWORD
pid
;
const
char
*
imageName
;
DBG_THREAD
*
threads
;
int
num_threads
;
unsigned
continue_on_first_exception
;
...
...
@@ -434,7 +435,7 @@ extern BOOL DEBUG_DisassembleInstruction(DBG_ADDR *addr);
/* debugger/stack.c */
extern
void
DEBUG_InfoStack
(
void
);
extern
void
DEBUG_BackTrace
(
BOOL
noisy
);
extern
void
DEBUG_BackTrace
(
DWORD
threadID
,
BOOL
noisy
);
extern
int
DEBUG_InfoLocals
(
void
);
extern
int
DEBUG_SetFrame
(
int
newframe
);
extern
int
DEBUG_GetCurrentFrame
(
struct
name_hash
**
name
,
...
...
@@ -493,6 +494,8 @@ extern int DEBUG_Printf(int chn, const char* format, ...);
extern
DBG_INTVAR
*
DEBUG_GetIntVar
(
const
char
*
);
extern
BOOL
DEBUG_Attach
(
DWORD
pid
,
BOOL
cofe
);
extern
void
DEBUG_Run
(
const
char
*
args
);
extern
DBG_PROCESS
*
DEBUG_GetProcess
(
DWORD
pid
);
extern
DBG_THREAD
*
DEBUG_GetThread
(
DBG_PROCESS
*
p
,
DWORD
tid
);
extern
int
curr_frame
;
/* Choose your allocator! */
...
...
debugger/info.c
View file @
800773f9
...
...
@@ -469,20 +469,36 @@ void DEBUG_WalkThreads(void)
THREADENTRY32
entry
;
DWORD
current
=
DEBUG_CurrThread
?
DEBUG_CurrThread
->
tid
:
0
;
BOOL
ok
;
DWORD
lastProcessId
=
0
;
entry
.
dwSize
=
sizeof
(
entry
);
ok
=
Thread32First
(
snap
,
&
entry
);
DEBUG_Printf
(
DBG_CHN_MESG
,
"%-8.8s %-8.8s %s
\n
"
,
"tid"
,
"process"
,
"prio"
);
DEBUG_Printf
(
DBG_CHN_MESG
,
"%-8.8s %-8.8s %s
\n
"
,
"process"
,
"tid"
,
"prio"
);
while
(
ok
)
{
if
(
entry
.
th32OwnerProcessID
!=
GetCurrentProcessId
())
DEBUG_Printf
(
DBG_CHN_MESG
,
"%08lx %08lx %4ld%s
\n
"
,
entry
.
th32ThreadID
,
entry
.
th32OwnerProcessID
,
entry
.
tpBasePri
,
(
entry
.
th32ThreadID
==
current
)
?
" <=="
:
""
);
{
/* FIXME: this assumes that, in the snapshot, all threads of a same process are
* listed sequentially, which is not specified in the doc (Wine's implementation
* does it)
*/
if
(
entry
.
th32OwnerProcessID
!=
lastProcessId
)
{
DBG_PROCESS
*
p
=
DEBUG_GetProcess
(
entry
.
th32OwnerProcessID
);
DEBUG_Printf
(
DBG_CHN_MESG
,
"%08lx%s %s
\n
"
,
entry
.
th32OwnerProcessID
,
p
?
" (D)"
:
""
,
p
?
p
->
imageName
:
""
);
lastProcessId
=
entry
.
th32OwnerProcessID
;
}
DEBUG_Printf
(
DBG_CHN_MESG
,
"
\t
%08lx %4ld%s
\n
"
,
entry
.
th32ThreadID
,
entry
.
tpBasePri
,
(
entry
.
th32ThreadID
==
current
)
?
" <=="
:
""
);
}
ok
=
Thread32Next
(
snap
,
&
entry
);
}
CloseHandle
(
snap
);
}
}
...
...
debugger/stack.c
View file @
800773f9
...
...
@@ -106,7 +106,7 @@ static void DEBUG_ForceFrame(DBG_ADDR *stack, DBG_ADDR *code, int frameno, enum
}
}
static
BOOL
DEBUG_Frame16
(
DBG_ADDR
*
addr
,
unsigned
int
*
cs
,
int
frameno
,
int
noisy
)
static
BOOL
DEBUG_Frame16
(
DBG_
THREAD
*
thread
,
DBG_
ADDR
*
addr
,
unsigned
int
*
cs
,
int
frameno
,
int
noisy
)
{
unsigned
int
possible_cs
=
0
;
FRAME16
frame
;
...
...
@@ -128,7 +128,7 @@ static BOOL DEBUG_Frame16(DBG_ADDR *addr, unsigned int *cs, int frameno, int noi
if
(((
frame
.
cs
&
7
)
==
7
)
&&
(
frame
.
cs
!=
*
cs
))
{
LDT_ENTRY
le
;
if
(
GetThreadSelectorEntry
(
DEBUG_CurrT
hread
->
handle
,
frame
.
cs
,
&
le
)
&&
if
(
GetThreadSelectorEntry
(
t
hread
->
handle
,
frame
.
cs
,
&
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 */
...
...
@@ -174,25 +174,64 @@ static BOOL DEBUG_Frame32(DBG_ADDR *addr, unsigned int *cs, int frameno, int noi
*
* Display a stack back-trace.
*/
void
DEBUG_BackTrace
(
BOOL
noisy
)
void
DEBUG_BackTrace
(
DWORD
tid
,
BOOL
noisy
)
{
#ifdef __i386
DBG_ADDR
addr
,
sw_addr
,
code
,
tmp
;
unsigned
int
ss
=
DEBUG_context
.
SegSs
;
unsigned
int
cs
=
DEBUG_context
.
SegCs
;
unsigned
int
ss
,
cs
;
int
frameno
=
0
,
is16
,
ok
;
DWORD
next_switch
,
cur_switch
,
p
;
STACK16FRAME
frame16
;
STACK32FRAME
frame32
;
char
ch
;
CONTEXT
ctx
;
DBG_THREAD
*
thread
;
int
copy_nframe
=
0
;
int
copy_curr_frame
=
0
;
struct
bt_info
*
copy_frames
=
NULL
;
if
(
noisy
)
DEBUG_Printf
(
DBG_CHN_MESG
,
"Backtrace:
\n
"
);
nframe
=
0
;
if
(
tid
==
DEBUG_CurrTid
)
{
ctx
=
DEBUG_context
;
thread
=
DEBUG_CurrThread
;
if
(
frames
)
DBG_free
(
frames
);
/* frames = (struct bt_info *) DBG_alloc( sizeof(struct bt_info) ); */
}
else
{
thread
=
DEBUG_GetThread
(
DEBUG_CurrProcess
,
tid
);
if
(
!
thread
)
{
DEBUG_Printf
(
DBG_CHN_MESG
,
"Unknown thread id (0x%08lx) in current process
\n
"
,
tid
);
return
;
}
memset
(
&
ctx
,
0
,
sizeof
(
ctx
));
ctx
.
ContextFlags
=
CONTEXT_CONTROL
|
CONTEXT_SEGMENTS
;
if
(
SuspendThread
(
thread
->
handle
)
==
-
1
||
!
GetThreadContext
(
thread
->
handle
,
&
ctx
))
{
DEBUG_Printf
(
DBG_CHN_MESG
,
"Can't get context for thread id (0x%08lx) in current process
\n
"
,
tid
);
return
;
}
/* need to avoid trashing stack frame for current thread */
copy_nframe
=
nframe
;
copy_frames
=
frames
;
copy_curr_frame
=
curr_frame
;
curr_frame
=
0
;
}
nframe
=
0
;
frames
=
NULL
;
cs
=
ctx
.
SegCs
;
ss
=
ctx
.
SegSs
;
if
(
DEBUG_IsSelectorSystem
(
ss
))
ss
=
0
;
if
(
DEBUG_IsSelectorSystem
(
cs
))
cs
=
0
;
...
...
@@ -201,16 +240,16 @@ void DEBUG_BackTrace(BOOL noisy)
{
case
MODE_32
:
code
.
seg
=
cs
;
code
.
off
=
DEBUG_context
.
Eip
;
code
.
off
=
ctx
.
Eip
;
addr
.
seg
=
ss
;
addr
.
off
=
DEBUG_context
.
Ebp
;
addr
.
off
=
ctx
.
Ebp
;
DEBUG_ForceFrame
(
&
addr
,
&
code
,
frameno
,
MODE_32
,
noisy
,
NULL
);
if
(
!
(
code
.
seg
||
code
.
off
))
{
/* trying to execute a null pointer... yuck...
* if it was a call to null, the return EIP should be
* available at SS:ESP, so let's try to retrieve it */
tmp
.
seg
=
ss
;
tmp
.
off
=
DEBUG_context
.
Esp
;
tmp
.
off
=
ctx
.
Esp
;
if
(
DEBUG_READ_MEM
((
void
*
)
DEBUG_ToLinear
(
&
tmp
),
&
code
.
off
,
sizeof
(
code
.
off
)))
{
DEBUG_ForceFrame
(
&
addr
,
&
code
,
++
frameno
,
MODE_32
,
noisy
,
", null call assumed"
);
}
...
...
@@ -220,9 +259,9 @@ void DEBUG_BackTrace(BOOL noisy)
case
MODE_16
:
case
MODE_VM86
:
code
.
seg
=
cs
;
code
.
off
=
LOWORD
(
DEBUG_context
.
Eip
);
code
.
off
=
LOWORD
(
ctx
.
Eip
);
addr
.
seg
=
ss
;
addr
.
off
=
LOWORD
(
DEBUG_context
.
Ebp
);
addr
.
off
=
LOWORD
(
ctx
.
Ebp
);
DEBUG_ForceFrame
(
&
addr
,
&
code
,
frameno
,
MODE_16
,
noisy
,
NULL
);
is16
=
TRUE
;
break
;
...
...
@@ -234,7 +273,7 @@ void DEBUG_BackTrace(BOOL noisy)
/* cur_switch holds address of curr_stack's field in TEB in debuggee
* address space
*/
cur_switch
=
(
DWORD
)
DEBUG_CurrT
hread
->
teb
+
OFFSET_OF
(
TEB
,
cur_stack
);
cur_switch
=
(
DWORD
)
t
hread
->
teb
+
OFFSET_OF
(
TEB
,
cur_stack
);
if
(
!
DEBUG_READ_MEM
((
void
*
)
cur_switch
,
&
next_switch
,
sizeof
(
next_switch
)))
{
if
(
noisy
)
DEBUG_Printf
(
DBG_CHN_MESG
,
"Can't read TEB:cur_stack
\n
"
);
return
;
...
...
@@ -342,11 +381,21 @@ void DEBUG_BackTrace(BOOL noisy)
}
}
else
{
/* ordinary stack frame */
ok
=
is16
?
DEBUG_Frame16
(
&
addr
,
&
cs
,
++
frameno
,
noisy
)
ok
=
is16
?
DEBUG_Frame16
(
thread
,
&
addr
,
&
cs
,
++
frameno
,
noisy
)
:
DEBUG_Frame32
(
&
addr
,
&
cs
,
++
frameno
,
noisy
);
}
}
if
(
noisy
)
DEBUG_Printf
(
DBG_CHN_MESG
,
"
\n
"
);
if
(
tid
!=
DEBUG_CurrTid
)
{
ResumeThread
(
thread
->
handle
);
/* restore stack frame for current thread */
if
(
frames
)
DBG_free
(
frames
);
frames
=
copy_frames
;
nframe
=
copy_nframe
;
curr_frame
=
copy_curr_frame
;
}
#endif
}
...
...
debugger/winedbg.c
View file @
800773f9
...
...
@@ -126,7 +126,7 @@ static WINE_EXCEPTION_FILTER(wine_dbg)
return
EXCEPTION_EXECUTE_HANDLER
;
}
static
DBG_PROCESS
*
DEBUG_GetProcess
(
DWORD
pid
)
DBG_PROCESS
*
DEBUG_GetProcess
(
DWORD
pid
)
{
DBG_PROCESS
*
p
;
...
...
@@ -135,13 +135,14 @@ static DBG_PROCESS* DEBUG_GetProcess(DWORD pid)
return
p
;
}
static
DBG_PROCESS
*
DEBUG_AddProcess
(
DWORD
pid
,
HANDLE
h
)
static
DBG_PROCESS
*
DEBUG_AddProcess
(
DWORD
pid
,
HANDLE
h
,
const
char
*
imageName
)
{
DBG_PROCESS
*
p
=
DBG_alloc
(
sizeof
(
DBG_PROCESS
));
if
(
!
p
)
return
NULL
;
p
->
handle
=
h
;
p
->
pid
=
pid
;
p
->
imageName
=
imageName
?
DBG_strdup
(
imageName
)
:
NULL
;
p
->
threads
=
NULL
;
p
->
num_threads
=
0
;
p
->
continue_on_first_exception
=
FALSE
;
...
...
@@ -177,6 +178,7 @@ static void DEBUG_DelProcess(DBG_PROCESS* p)
if
(
p
->
next
)
p
->
next
->
prev
=
p
->
prev
;
if
(
p
==
DEBUG_ProcessList
)
DEBUG_ProcessList
=
p
->
next
;
if
(
p
==
DEBUG_CurrProcess
)
DEBUG_CurrProcess
=
NULL
;
DBG_free
((
char
*
)
p
->
imageName
);
DBG_free
(
p
);
}
...
...
@@ -206,7 +208,7 @@ static BOOL DEBUG_ProcessGetStringIndirect(char* buffer, int size, HANDLE hp, LP
return
FALSE
;
}
static
DBG_THREAD
*
DEBUG_GetThread
(
DBG_PROCESS
*
p
,
DWORD
tid
)
DBG_THREAD
*
DEBUG_GetThread
(
DBG_PROCESS
*
p
,
DWORD
tid
)
{
DBG_THREAD
*
t
;
...
...
@@ -273,7 +275,7 @@ static void DEBUG_DelThread(DBG_THREAD* t)
BOOL
DEBUG_Attach
(
DWORD
pid
,
BOOL
cofe
)
{
if
(
!
(
DEBUG_CurrProcess
=
DEBUG_AddProcess
(
pid
,
0
)))
return
FALSE
;
if
(
!
(
DEBUG_CurrProcess
=
DEBUG_AddProcess
(
pid
,
0
,
NULL
)))
return
FALSE
;
if
(
!
DebugActiveProcess
(
pid
))
{
DEBUG_Printf
(
DBG_CHN_MESG
,
"Can't attach process %lx: error %ld
\n
"
,
pid
,
GetLastError
());
...
...
@@ -338,7 +340,7 @@ static BOOL DEBUG_ExceptionProlog(BOOL is_debug, BOOL force, DWORD code)
* Do a quiet backtrace so that we have an idea of what the situation
* is WRT the source files.
*/
DEBUG_BackTrace
(
FALSE
);
DEBUG_BackTrace
(
DEBUG_CurrTid
,
FALSE
);
}
else
{
/* This is a real crash, dump some info */
DEBUG_InfoRegisters
();
...
...
@@ -351,7 +353,7 @@ static BOOL DEBUG_ExceptionProlog(BOOL is_debug, BOOL force, DWORD code)
}
DEBUG_InfoSegments
(
DEBUG_context
.
SegFs
>>
3
,
1
);
#endif
DEBUG_BackTrace
(
TRUE
);
DEBUG_BackTrace
(
DEBUG_CurrTid
,
TRUE
);
}
if
(
!
is_debug
||
...
...
@@ -626,9 +628,9 @@ static BOOL DEBUG_HandleDebugEvent(DEBUG_EVENT* de, LPDWORD cont)
de
->
u
.
CreateProcessInfo
.
lpImageName
);
/* FIXME unicode ? de->u.CreateProcessInfo.fUnicode */
DEBUG_Printf
(
DBG_CHN_TRACE
,
"%08lx:%08lx: create process
%s
@%08lx (%ld<%ld>)
\n
"
,
DEBUG_Printf
(
DBG_CHN_TRACE
,
"%08lx:%08lx: create process
'%s'/%p
@%08lx (%ld<%ld>)
\n
"
,
de
->
dwProcessId
,
de
->
dwThreadId
,
buffer
,
buffer
,
de
->
u
.
CreateProcessInfo
.
lpImageName
,
(
unsigned
long
)(
LPVOID
)
de
->
u
.
CreateProcessInfo
.
lpStartAddress
,
de
->
u
.
CreateProcessInfo
.
dwDebugInfoFileOffset
,
de
->
u
.
CreateProcessInfo
.
nDebugInfoSize
);
...
...
@@ -639,9 +641,13 @@ static BOOL DEBUG_HandleDebugEvent(DEBUG_EVENT* de, LPDWORD cont)
break
;
}
DEBUG_CurrProcess
->
handle
=
de
->
u
.
CreateProcessInfo
.
hProcess
;
if
(
DEBUG_CurrProcess
->
imageName
==
NULL
)
DEBUG_CurrProcess
->
imageName
=
DBG_strdup
(
buffer
[
0
]
?
buffer
:
"<Debugged Process>"
);
}
else
{
DEBUG_CurrProcess
=
DEBUG_AddProcess
(
de
->
dwProcessId
,
de
->
u
.
CreateProcessInfo
.
hProcess
);
de
->
u
.
CreateProcessInfo
.
hProcess
,
buffer
[
0
]
?
buffer
:
"<Debugged Process>"
);
if
(
DEBUG_CurrProcess
==
NULL
)
{
DEBUG_Printf
(
DBG_CHN_ERR
,
"Unknown process
\n
"
);
break
;
...
...
@@ -665,11 +671,7 @@ static BOOL DEBUG_HandleDebugEvent(DEBUG_EVENT* de, LPDWORD cont)
DEBUG_InitCurrProcess
();
DEBUG_InitCurrThread
();
DEBUG_ProcessGetStringIndirect
(
buffer
,
sizeof
(
buffer
),
DEBUG_CurrThread
->
process
->
handle
,
de
->
u
.
CreateProcessInfo
.
lpImageName
);
DEBUG_LoadModule32
(
buffer
[
0
]
?
buffer
:
"<Debugged process>"
,
de
->
u
.
CreateProcessInfo
.
hFile
,
DEBUG_LoadModule32
(
DEBUG_CurrProcess
->
imageName
,
de
->
u
.
CreateProcessInfo
.
hFile
,
(
DWORD
)
de
->
u
.
CreateProcessInfo
.
lpBaseOfImage
);
if
(
buffer
[
0
])
/* we got a process name */
...
...
@@ -825,7 +827,7 @@ static BOOL DEBUG_Start(LPSTR cmdLine)
return
FALSE
;
}
DEBUG_CurrPid
=
info
.
dwProcessId
;
if
(
!
(
DEBUG_CurrProcess
=
DEBUG_AddProcess
(
DEBUG_CurrPid
,
0
)))
return
FALSE
;
if
(
!
(
DEBUG_CurrProcess
=
DEBUG_AddProcess
(
DEBUG_CurrPid
,
0
,
NULL
)))
return
FALSE
;
return
TRUE
;
}
...
...
@@ -859,7 +861,7 @@ int DEBUG_main(int argc, char** argv)
DEBUG_InitTypes
();
DEBUG_InitCVDataTypes
();
/* Initialize internal vars (types must
be
initialized before) */
/* Initialize internal vars (types must
have been
initialized before) */
if
(
!
DEBUG_IntVarsRW
(
TRUE
))
return
-
1
;
/* keep it as a guiexe for now, so that Wine won't touch the Unix stdin,
...
...
@@ -881,8 +883,6 @@ int DEBUG_main(int argc, char** argv)
if
((
pid
=
atoi
(
argv
[
1
]))
!=
0
&&
(
hEvent
=
(
HANDLE
)
atoi
(
argv
[
2
]))
!=
0
)
{
if
(
!
DEBUG_Attach
(
pid
,
TRUE
))
{
DEBUG_Printf
(
DBG_CHN_ERR
,
"Can't attach process %ld: %ld
\n
"
,
DEBUG_CurrPid
,
GetLastError
());
/* don't care about result */
SetEvent
(
hEvent
);
goto
leave
;
...
...
@@ -920,10 +920,11 @@ int DEBUG_main(int argc, char** argv)
}
retv
=
DEBUG_MainLoop
();
leave:
/* saves modified variables */
DEBUG_IntVarsRW
(
FALSE
);
leave:
return
retv
;
oom_leave:
...
...
documentation/debugger.sgml
View file @
800773f9
...
...
@@ -1349,11 +1349,14 @@ info break lists all (break|watch)points (with state)
<screen>
bt print calling stack of current thread
bt N print calling stack of thread of ID N (note: this
doesn't change the position of the current frame as
manipulated by the up & dn commands)
up goes up one frame in current thread's stack
up N goes up N frames in current thread's stack
dn goes down one frame in current thread's stack
dn N goes down N frames in current thread's stack
frame N set N as the current frame
frame N set N as the current frame
for current thread's stack
info local prints information on local variables for current
function
</screen>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment