Disparity between !process <eproc> Flag StackDisplay VS Kb StackDisplay

!process flag documentation Flag 0x10 is documented to
provide user mode stack also

does this user mode stack contains all the user mode stack frames or
just a single frame

i mean

if i create a process in windbg say x and step into it some way and issue a KB

if i get a stack trace say 4 frames deep

will the same 4 frames deep user mode stack will be displayed if i use

say lkd

and issue a !process 0x17

i dont seem to get the complete user mode stack can some one explain
what iam missing ?

example below

a windbg usermode session gone ahead some way into a simple Messagebox
and stacktrace dipalyed below

0:000> ~.;kb
. 0 Id: c5c.c60 Suspend: 1 Teb: 7ffde000 Unfrozen
Start: msgbox!start (00401000)
Priority: 0 Priority class: 32 Affinity: 1
ChildEBP RetAddr Args to Child
0013ff70 7e450877 00000000 00403019 00403000 user32!MessageBoxTimeoutA+0x31
0013ff90 7e45082f 00000000 00403019 00403000 user32!MessageBoxExA+0x1b
0013ffac 00401013 00000000 00403019 00403000 user32!MessageBoxA+0x45
0013fff0 00000000 00401000 00000000 78746341 msgbox!start+0x13 [msgbox.asm @ 18]

now in lkd if do a

!process 17
or
!process PID 17

the user mode stack portion does not contain anything below
user32!MessageBoxTimeoutA+0x31

see below

lkd> !process 85ec6da0 0x17 ; !process c5c 0x17

PROCESS 85ec6da0 SessionId: 0 Cid: 0c5c Peb: 7ffdf000 ParentCid: 05f8
DirBase: 0fbc03a0 ObjectTable: e40bd8c8 HandleCount: 14.
Image: msgbox.exe
VadRoot 85ed1ce0 Vads 36 Clone 0 Private 99. Modified 2. Locked 0.
DeviceMap e2dbb250
Token e4408870
ElapsedTime 00:32:32.625
UserTime 00:00:00.015
KernelTime 00:00:00.000
QuotaPoolUsage[PagedPool] 26708
QuotaPoolUsage[NonPagedPool] 1440
Working Set Sizes (now,min,max) (355, 50, 345) (1420KB, 200KB, 1380KB)
PeakWorkingSetSize 372
VirtualSize 12 Mb
PeakVirtualSize 13 Mb
PageFaultCount 381
MemoryPriority BACKGROUND
BasePriority 8
CommitCharge 123
DebugPort 86537828

THREAD 85ed9030 Cid 0c5c.0c60 Teb: 7ffde000 Win32Thread:
e452baa8 WAIT: (Executive) KernelMode Non-Alertable
SuspendCount 1
a87647d4 SynchronizationEvent
Not impersonating
DeviceMap e2dbb250
Owning Process 0 Image:
Attached Process 85ec6da0 Image: msgbox.exe
Wait Start TickCount 220909 Ticks: 88641 (0:00:23:05.015)
Context Switch Count 350 LargeStack
UserTime 00:00:00.000
KernelTime 00:00:00.000
Win32 Start Address msgbox!start (0x00401000)
Start Address kernel32!BaseProcessStartThunk (0x7c810705)
Stack Init a8765000 Current a8764758 Base a8765000 Limit a8761000 Call 0
Priority 9 BasePriority 8 PriorityDecrement 0 DecrementCount 0
ChildEBP RetAddr Args to Child
a8764770 80500cf0 85ed90a0 85ed9030 804f9d72
nt!KiSwapContext+0x2e (FPO: [Uses EBP] [0,0,4])
a876477c 804f9d72 00000000 85ed9030 a87647cc
nt!KiSwapThread+0x46 (FPO: [0,0,0])
a87647a4 80638fc4 00000000 00000000 00000000
nt!KeWaitForSingleObject+0x1c2 (FPO: [Non-Fpo])
a8764884 8063a099 85ec6da0 00000000 a87648bc
nt!DbgkpQueueMessage+0x17c (FPO: [Non-Fpo])
a87648a8 8063a1cb a87648bc 00000001 a8764d64
nt!DbgkpSendApiMessage+0x45 (FPO: [Non-Fpo])
a8764934 804fcb42 a8764d10 00000001 00000000
nt!DbgkForwardException+0x8f (FPO: [Non-Fpo])
a8764cf4 8053e0a1 a8764d10 00000000 a8764d64
nt!KiDispatchException+0x1f4 (FPO: [Non-Fpo])
a8764d5c 8053e03a 0013ff70 7e466437 badb0d00
nt!CommonDispatchException+0x4d (FPO: [0,20,0])
a8764d64 7e466437 badb0d00 00403019 00000000 nt!KiExceptionExit+0x172
a8764d7c 00000000 00000000 00000000 00000000
user32!MessageBoxTimeoutA+0x31 (FPO: [Non-Fpo])

Searching for Process with Cid == c5c
Cid handle table at e129a000 with 590 entries in use

PROCESS 85ec6da0 SessionId: 0 Cid: 0c5c Peb: 7ffdf000 ParentCid: 05f8
DirBase: 0fbc03a0 ObjectTable: e40bd8c8 HandleCount: 14.
Image: msgbox.exe
VadRoot 85ed1ce0 Vads 36 Clone 0 Private 99. Modified 2. Locked 0.
DeviceMap e2dbb250
Token e4408870
ElapsedTime 00:32:50.531
UserTime 00:00:00.015
KernelTime 00:00:00.000
QuotaPoolUsage[PagedPool] 26708
QuotaPoolUsage[NonPagedPool] 1440
Working Set Sizes (now,min,max) (355, 50, 345) (1420KB, 200KB, 1380KB)
PeakWorkingSetSize 372
VirtualSize 12 Mb
PeakVirtualSize 13 Mb
PageFaultCount 381
MemoryPriority BACKGROUND
BasePriority 8
CommitCharge 123
DebugPort 86537828

THREAD 85ed9030 Cid 0c5c.0c60 Teb: 7ffde000 Win32Thread:
e452baa8 WAIT: (Executive) KernelMode Non-Alertable
SuspendCount 1
a87647d4 SynchronizationEvent
Not impersonating
DeviceMap e2dbb250
Owning Process 0 Image:
Attached Process 85ec6da0 Image: msgbox.exe
Wait Start TickCount 220909 Ticks: 89786 (0:00:23:22.906)
Context Switch Count 350 LargeStack
UserTime 00:00:00.000
KernelTime 00:00:00.000
Win32 Start Address msgbox!start (0x00401000)
Start Address kernel32!BaseProcessStartThunk (0x7c810705)
Stack Init a8765000 Current a8764758 Base a8765000 Limit a8761000 Call 0
Priority 9 BasePriority 8 PriorityDecrement 0 DecrementCount 0
ChildEBP RetAddr Args to Child
a8764770 80500cf0 85ed90a0 85ed9030 804f9d72
nt!KiSwapContext+0x2e (FPO: [Uses EBP] [0,0,4])
a876477c 804f9d72 00000000 85ed9030 a87647cc
nt!KiSwapThread+0x46 (FPO: [0,0,0])
a87647a4 80638fc4 00000000 00000000 00000000
nt!KeWaitForSingleObject+0x1c2 (FPO: [Non-Fpo])
a8764884 8063a099 85ec6da0 00000000 a87648bc
nt!DbgkpQueueMessage+0x17c (FPO: [Non-Fpo])
a87648a8 8063a1cb a87648bc 00000001 a8764d64
nt!DbgkpSendApiMessage+0x45 (FPO: [Non-Fpo])
a8764934 804fcb42 a8764d10 00000001 00000000
nt!DbgkForwardException+0x8f (FPO: [Non-Fpo])
a8764cf4 8053e0a1 a8764d10 00000000 a8764d64
nt!KiDispatchException+0x1f4 (FPO: [Non-Fpo])
a8764d5c 8053e03a 0013ff70 7e466437 badb0d00
nt!CommonDispatchException+0x4d (FPO: [0,20,0])
a8764d64 7e466437 badb0d00 00403019 00000000 nt!KiExceptionExit+0x172
a8764d7c 00000000 00000000 00000000 00000000
user32!MessageBoxTimeoutA+0x31 (FPO: [Non-Fpo])

i observed this behavior when tinkering with some dbgeng functions

i see the same behavior in my code as well as a real windbg and lkd

any pointers on how to get a full stack (kernel mode as well as user
mode ) in lkd would be great

question no 2

is there an easy way to get eprocess from pid in USERMODE (especially
any dbgeng methods like
GetEprocessFromCurrentProcessID(); using either GetCurrentProcessId
viz 0xffffffff or some imagehelp routines ?
GetEprocessFromCurrentProcessHandle(); using the handle retrieved by
say OpenProcess()

did i miss any method that does this

anything that is equivalent in usermode for the
PsGetProcessFromProcessId() in kernel mode

i hate the way i have to parse / grep / sed /awk / to retrieve
given a pid

!process takes pid

but .process /p /r does not take a PID

it needs an Eproc and iam atm doing a horrible parsing and grabbing
from the output of
!process 0 result to get the eproc of my choice

AFAIK !process/!thread have a non-configurable limit on the number of call
frames they will show . So, in order to see more frames you have to switch
to the thread context of the thread you’re interested in and then use the k
command (which is controllable by .kframes):

.thread /r /p [thread]
k

In terms of turning a PID into an EPROCESS, I don’t know of any built in way
(though it’s always possible there is one). You could probably write
something fairly quickly that would walk the active process list and do the
translation.

For example, I made a couple of minor modifications to a script that we use
in labs where we teach WinDBG scripting. It takes two parameters, the PID
you want to translate and the temporary register to store the resulting
EPROCESS address in. An example usage would be:

1: kd> !process 0 0
**** NT ACTIVE PROCESS DUMP ****

PROCESS fffffa8007042980
SessionId: none Cid: 00e0 Peb: 7f7aaf3b000 ParentCid: 0004
DirBase: 06a17000 ObjectTable: fffff8a0010d25c0 HandleCount: Accessible>
Image: smss.exe

PROCESS fffffa8008aa3780
SessionId: 1 Cid: 0a44 Peb: 7f60483f000 ParentCid: 08cc
DirBase: 4af3a000 ObjectTable: fffff8a001958040 HandleCount: Accessible>
Image: wordpad.exe


1: kd> $$>a<f: e0>1: kd> !process @$t0 0
PROCESS fffffa8007042980
SessionId: none Cid: 00e0 Peb: 7f7aaf3b000 ParentCid: 0004
DirBase: 06a17000 ObjectTable: fffff8a0010d25c0 HandleCount: Accessible>
Image: smss.exe

1: kd> $$>a<f: a44>1: kd> !process @$t0 0
PROCESS fffffa8008aa3780
SessionId: 1 Cid: 0a44 Peb: 7f60483f000 ParentCid: 08cc
DirBase: 4af3a000 ObjectTable: fffff8a001958040 HandleCount: Accessible>
Image: wordpad.exe

Full script provided below. Feel free to email me for a copy if the mailer
mangles it too much.

-scott

$$
$$ findpid.wbs
$$
$$ Walk the current list of processes and find the matching PID
$$
$$ OSR Open Systems Resources, inc.
$$
$$ http://www.osr.com
$$ http://www.osronline.com
$$
$$
$$ To run:
$$
$$ $$>a<findpid.wbs>$$
$$ Uses:
$$
$$ $t17-$t19
$$

.echo
.echo * This command brought to you by osronline.com
.echo


$$ Global aliases

$$ Note that we use ${/v:} around all of our alias names. This shuts
$$ alias expansion OFF for these names. Without these, multiple invocations
$$ of the script can cause issues

$$ Cast the active process list head as a LIST_ENTRY pointer

aS ${/v:PsActiveProcessHead} "@@c++((nt!_LIST_ENTRY
)@@masm(nt!PsActiveProcessHead))"

$$ This is the offset of the list entry that PsActiveProcessHead points to

aS ${/v:ProcessLinksOffset} “@@c++(#FIELD_OFFSET(nt!_EPROCESS,
ActiveProcessLinks))”

$$ And the offset to the PID

aS ${/v:PIDOffset} “@@c++(#FIELD_OFFSET(nt!_EPROCESS, UniqueProcessId))”

$$ Locals

aS ${/v:currProcPid} “@$t17”
aS ${/v:listEntry} “@$t18”
aS ${/v:currProc} “@$t19”

$$ Force the script to evaluate the above aliases with a .block
.block
{

$$ Get the Flink value of the head. Note that r? is required
$$ to use the C++ syntax in the r statement. Also, the type is
$$ assigned to the resulting register

r? ${listEntry} = @@c++(${PsActiveProcessHead}->Flink)

$$ And loop while we have entries…

.while (${listEntry} != ${PsActiveProcessHead})
{

$$ Get the base of the struct from the list pointer.
$$ Note that #CONTAINING_RECORD would also work

r ${currProc} = ${listEntry} - ${ProcessLinksOffset}

$$ Collect the PID from the process

r ${currProcPid} = poi(${currProc} + ${PIDOffset})

$$ Compare it to the first user argumnet
.if (${currProcPid} == ${$arg1})
{
$$ Found it!
r ${$arg2} = ${currProc}
.break
}

$$ Move on to the next entry. Our r? command makes sure
$$ that ${listEntry} is typed appropriately

r? ${listEntry} = @@c++(${listEntry}->Flink)

}
}

$$ /v: suppresses the alias expansion

ad ${/v:currProc}
ad ${/v:listEntry}
ad ${/v:currProcPid}
ad ${/v:ProcessLinksOffset}
ad ${/v:PIDOffset}
ad ${/v:PsActiveProcessHead}</findpid.wbs></f:></f:>

thanks for the reply scott

in local kernel debuging it is a limitation that we cannot use Kb for
viewing stack

so i was snooping around this !process Flag route to view the
call stack (interested in user mode part of it especially )

and i couldnt eek out more than one frame with 0x17 flag

i will check out if i can get more frames with thread commands thanks

as for finding EPROCESS from PID

i used a terribly horrible parsing routine at first now i use a less
than horrible but still horrible way of parsing :slight_smile:

memset(printbuff,0,BUFFLEN);

sprintf_s(printbuff,(BUFFLEN-SAFETYLIMIT),“.foreach /ps 100 /pS 12
(place { !process %x 0 } ) { r $t0 = place; as /x eproc @$t0; .block
{.process /p /r ${$eproc} } }”,Pid);

g_Control->Execute(
DEBUG_OUTCTL_IGNORE,
printbuff,
DEBUG_EXECUTE_DEFAULT
);

the .foreach here is very delicate :frowning: there is no uniformity in windbg
output for many extension COMMAND OUTPUT and this can fail in one such
occasion since it relies on positional count )

and since i had an alias it seems i could use this alias later too

if ( ( status = g_Control->Execute( DEBUG_OUTCTL_IGNORE,“.process /p
/r eproc”,DEBUG_EXECUTE_DEFAULT ) ) != S_OK { \ this works in
later part

thanks a lot for the script i will take a look at it and see if i can adapt it

On 9/14/12, Scott Noone wrote:
> AFAIK !process/!thread have a non-configurable limit on the number of call
> frames they will show . So, in order to see more frames you have to switch
> to the thread context of the thread you’re interested in and then use the k
>
> command (which is controllable by .kframes):
>
> .thread /r /p [thread]
> k
>
> In terms of turning a PID into an EPROCESS, I don’t know of any built in way
>
> (though it’s always possible there is one). You could probably write
> something fairly quickly that would walk the active process list and do the
>
> translation.
>
> For example, I made a couple of minor modifications to a script that we use
>
> in labs where we teach WinDBG scripting. It takes two parameters, the PID
> you want to translate and the temporary register to store the resulting
> EPROCESS address in. An example usage would be:
>
> 1: kd> !process 0 0
> NT ACTIVE PROCESS DUMP
> …
> PROCESS fffffa8007042980
> SessionId: none Cid: 00e0 Peb: 7f7aaf3b000 ParentCid: 0004
> DirBase: 06a17000 ObjectTable: fffff8a0010d25c0 HandleCount: >
> Accessible>
> Image: smss.exe
> …
> PROCESS fffffa8008aa3780
> SessionId: 1 Cid: 0a44 Peb: 7f60483f000 ParentCid: 08cc
> DirBase: 4af3a000 ObjectTable: fffff8a001958040 HandleCount: >
> Accessible>
> Image: wordpad.exe
> …
>
> 1: kd> $$>a<f: e0>> 1: kd> !process @$t0 0
> PROCESS fffffa8007042980
> SessionId: none Cid: 00e0 Peb: 7f7aaf3b000 ParentCid: 0004
> DirBase: 06a17000 ObjectTable: fffff8a0010d25c0 HandleCount: >
> Accessible>
> Image: smss.exe
>
> 1: kd> $$>a<f: a44>> 1: kd> !process @$t0 0
> PROCESS fffffa8008aa3780
> SessionId: 1 Cid: 0a44 Peb: 7f60483f000 ParentCid: 08cc
> DirBase: 4af3a000 ObjectTable: fffff8a001958040 HandleCount: >
> Accessible>
> Image: wordpad.exe
>
> Full script provided below. Feel free to email me for a copy if the mailer
> mangles it too much.
>
> -scott
>
>
> $$
> $$ findpid.wbs
> $$
> $$ Walk the current list of processes and find the matching PID
> $$
> $$ OSR Open Systems Resources, inc.
> $$
> $$ http://www.osr.com
> $$ http://www.osronline.com
> $$
> $$
> $$ To run:
> $$
> $$ $$>a<findpid.wbs>> $$
> $$ Uses:
> $$
> $$ $t17-$t19
> $$
>
> .echo *
> .echo * This command brought to you by osronline.com
> .echo

>
>
> $$ Global aliases
>
> $$ Note that we use ${/v:} around all of our alias names. This shuts
> $$ alias expansion OFF for these names. Without these, multiple invocations
> $$ of the script can cause issues
>
> $$ Cast the active process list head as a LIST_ENTRY pointer
>
> aS ${/v:PsActiveProcessHead} “@@c++((nt!_LIST_ENTRY
> *)@@masm(nt!PsActiveProcessHead))”
>
> $$ This is the offset of the list entry that PsActiveProcessHead points to
>
> aS ${/v:ProcessLinksOffset} “@@c++(#FIELD_OFFSET(nt!_EPROCESS,
> ActiveProcessLinks))”
>
> $$ And the offset to the PID
>
> aS ${/v:PIDOffset} “@@c++(#FIELD_OFFSET(nt!_EPROCESS, UniqueProcessId))”
>
> $$ Locals
>
> aS ${/v:currProcPid} “@$t17”
> aS ${/v:listEntry} “@$t18”
> aS ${/v:currProc} “@$t19”
>
> $$ Force the script to evaluate the above aliases with a .block
> .block
> {
>
> $$ Get the Flink value of the head. Note that r? is required
> $$ to use the C++ syntax in the r statement. Also, the type is
> $$ assigned to the resulting register
>
> r? ${listEntry} = @@c++(${PsActiveProcessHead}->Flink)
>
> $$ And loop while we have entries…
>
> .while (${listEntry} != ${PsActiveProcessHead})
> {
>
> $$ Get the base of the struct from the list pointer.
> $$ Note that #CONTAINING_RECORD would also work
>
> r ${currProc} = ${listEntry} - ${ProcessLinksOffset}
>
> $$ Collect the PID from the process
>
> r ${currProcPid} = poi(${currProc} + ${PIDOffset})
>
> $$ Compare it to the first user argumnet
> .if (${currProcPid} == ${$arg1})
> {
> $$ Found it!
> r ${$arg2} = ${currProc}
> .break
> }
>
> $$ Move on to the next entry. Our r? command makes sure
> $$ that ${listEntry} is typed appropriately
>
> r? ${listEntry} = @@c++(${listEntry}->Flink)
>
> }
> }
>
> $$ /v: suppresses the alias expansion
>
> ad ${/v:currProc}
> ad ${/v:listEntry}
> ad ${/v:currProcPid}
> ad ${/v:ProcessLinksOffset}
> ad ${/v:PIDOffset}
> ad ${/v:PsActiveProcessHead}
>
>
>
>
> —
> WINDBG is sponsored by OSR
>
> For our schedule of WDF, WDM, debugging and other seminars visit:
> http://www.osr.com/seminars
>
> To unsubscribe, visit the List Server section of OSR Online at
> http://www.osronline.com/page.cfm?name=ListServer
></findpid.wbs></f:></f:>

there again is a roadblock :frowning: i cant use k in lkd

(works ok in a kd session )

result of kd session

kd> .foreach /pS 1c /ps 8 ( place { !process 0 4 explorer.exe } )
{.thread /p /r place;k}

Implicit thread is now ffae2460
Implicit process is now ffba0da0
.cache forcedecodeuser done
Loading User Symbols


*** Stack trace for last set context - .thread/.cxr resets it
ChildEBP RetAddr
f8f90c64 804dc0f7 nt!KiSwapContext+0x2e
f8f90c70 804dc143 nt!KiSwapThread+0x46
f8f90c98 8056b640 nt!KeWaitForSingleObject+0x1c2
f8f90d48 804de7ec nt!NtReplyWaitReceivePortEx+0x3dc
f8f90d48 7c90e4f4 nt!KiFastCallEntry+0xf8
00d7fe14 7c90da8c ntdll!KiFastSystemCallRet
00d7fe18 77e765e3 ntdll!ZwReplyWaitReceivePortEx+0xc
00d7ff80 77e76caf RPCRT4!LRPC_ADDRESS::ReceiveLotsaCalls+0x12a
00d7ff88 77e76ad1 RPCRT4!RecvLotsaCallsWrapper+0xd
00d7ffa8 77e76c97 RPCRT4!BaseCachedThreadRoutine+0x79
00d7ffb4 7c80b713 RPCRT4!ThreadStartRoutine+0x1a
00d7ffec 00000000 kernel32!BaseThreadStart+0x37

Implicit thread is now ffae1740
<------------------------------------------ see below for lkd session
output for same thread

Implicit process is now ffba0da0
.cache forcedecodeuser done
Loading User Symbols


*** Stack trace for last set context - .thread/.cxr resets it
ChildEBP RetAddr
fbef8cc8 804dc0f7 nt!KiSwapContext+0x2e
fbef8cd4 804dc143 nt!KiSwapThread+0x46
fbef8cfc bf802f52 nt!KeWaitForSingleObject+0x1c2
fbef8d38 bf803758 win32k!xxxSleepThread+0x192
fbef8d4c bf803775 win32k!xxxRealWaitMessageEx+0x12
fbef8d5c 804de7ec win32k!NtUserWaitMessage+0x14
fbef8d5c 7c90e4f4 nt!KiFastCallEntry+0xf8
00e0ff10 7e419418 ntdll!KiFastSystemCallRet
00e0ff44 0100ffd1 USER32!NtUserWaitMessage+0xc
00e0ff50 77f76f42 Explorer!CTray::MainThreadProc+0x29
00e0ffb4 7c80b713 SHLWAPI!WrapperThreadProc+0x94
00e0ffec 00000000 kernel32!BaseThreadStart+0x37
Implicit thread is now ffae10c0
Implicit process is now ffba0da0
.cache forcedecodeuser done
Loading User Symbols

an lkd session on same app viz explorer.exe

lkd> .foreach /pS 1c /ps 8 ( place { !process 0 4 explorer.exe } )
{.thread /p /r place;}

Can’t retrieve thread context, NTSTATUS 0xC0000001
Implicit thread is now ffae1740
<-------------------------- see 2nd thread in kd session
Implicit process is now ffba0da0 <--------------------
Loading User Symbols
…WARNING: Loader 00191f18 timestamp 8b55ff8b != header timestamp 4802a12c

…Missing image name, possible paged-out or corrupt data.
(awwwh crap)

Can’t retrieve thread context, NTSTATUS 0xC0000001
Implicit thread is now ffae0030
Implicit process is now ffba0da0
Loading User Symbols
…WARNING: Loader 00191f18 timestamp 8b55ff8b != header timestamp 4802a12c

On 9/14/12, raj_r wrote:
> thanks for the reply scott
>
> in local kernel debuging it is a limitation that we cannot use Kb for
> viewing stack
>
> so i was snooping around this !process Flag route to view the
> call stack (interested in user mode part of it especially )
>
> and i couldnt eek out more than one frame with 0x17 flag
>
> i will check out if i can get more frames with thread commands thanks
>
>
> as for finding EPROCESS from PID
>
> i used a terribly horrible parsing routine at first now i use a less
> than horrible but still horrible way of parsing :slight_smile:
>
>
>
> memset(printbuff,0,BUFFLEN);
>
> sprintf_s(printbuff,(BUFFLEN-SAFETYLIMIT),“.foreach /ps 100 /pS 12
> (place { !process %x 0 } ) { r $t0 = place; as /x eproc @$t0; .block
> {.process /p /r ${$eproc} } }”,Pid);
>
> g_Control->Execute(
> DEBUG_OUTCTL_IGNORE,
> printbuff,
> DEBUG_EXECUTE_DEFAULT
> );
>
> the .foreach here is very delicate :frowning: there is no uniformity in windbg
> output for many extension COMMAND OUTPUT and this can fail in one such
> occasion since it relies on positional count )
>
> and since i had an alias it seems i could use this alias later too
>
> if ( ( status = g_Control->Execute( DEBUG_OUTCTL_IGNORE,“.process /p
> /r eproc”,DEBUG_EXECUTE_DEFAULT ) ) != S_OK { \ this works in
> later part
>
> thanks a lot for the script i will take a look at it and see if i can adapt
> it
>
> On 9/14/12, Scott Noone wrote:
>> AFAIK !process/!thread have a non-configurable limit on the number of
>> call
>> frames they will show . So, in order to see more frames you have to
>> switch
>> to the thread context of the thread you’re interested in and then use the
>> k
>>
>> command (which is controllable by .kframes):
>>
>> .thread /r /p [thread]
>> k
>>
>> In terms of turning a PID into an EPROCESS, I don’t know of any built in
>> way
>>
>> (though it’s always possible there is one). You could probably write
>> something fairly quickly that would walk the active process list and do
>> the
>>
>> translation.
>>
>> For example, I made a couple of minor modifications to a script that we
>> use
>>
>> in labs where we teach WinDBG scripting. It takes two parameters, the PID
>> you want to translate and the temporary register to store the resulting
>> EPROCESS address in. An example usage would be:
>>
>> 1: kd> !process 0 0
>> NT ACTIVE PROCESS DUMP
>> …
>> PROCESS fffffa8007042980
>> SessionId: none Cid: 00e0 Peb: 7f7aaf3b000 ParentCid: 0004
>> DirBase: 06a17000 ObjectTable: fffff8a0010d25c0 HandleCount: >> Not
>>
>> Accessible>
>> Image: smss.exe
>> …
>> PROCESS fffffa8008aa3780
>> SessionId: 1 Cid: 0a44 Peb: 7f60483f000 ParentCid: 08cc
>> DirBase: 4af3a000 ObjectTable: fffff8a001958040 HandleCount: >> Not
>>
>> Accessible>
>> Image: wordpad.exe
>> …
>>
>> 1: kd> $$>a<f: e0>>> 1: kd> !process @$t0 0
>> PROCESS fffffa8007042980
>> SessionId: none Cid: 00e0 Peb: 7f7aaf3b000 ParentCid: 0004
>> DirBase: 06a17000 ObjectTable: fffff8a0010d25c0 HandleCount: >> Not
>>
>> Accessible>
>> Image: smss.exe
>>
>> 1: kd> $$>a<f: a44>>> 1: kd> !process @$t0 0
>> PROCESS fffffa8008aa3780
>> SessionId: 1 Cid: 0a44 Peb: 7f60483f000 ParentCid: 08cc
>> DirBase: 4af3a000 ObjectTable: fffff8a001958040 HandleCount: >> Not
>>
>> Accessible>
>> Image: wordpad.exe
>>
>> Full script provided below. Feel free to email me for a copy if the
>> mailer
>> mangles it too much.
>>
>> -scott
>>
>>
>> $$
>> $$ findpid.wbs
>> $$
>> $$ Walk the current list of processes and find the matching PID
>> $$
>> $$ OSR Open Systems Resources, inc.
>> $$
>> $$ http://www.osr.com
>> $$ http://www.osronline.com
>> $$
>> $$
>> $$ To run:
>> $$
>> $$ $$>a<findpid.wbs>>> $$
>> $$ Uses:
>> $$
>> $$ $t17-$t19
>> $$
>>
>> .echo *
>> .echo * This command brought to you by osronline.com
>> .echo

>>
>>
>> $$ Global aliases
>>
>> $$ Note that we use ${/v:} around all of our alias names. This shuts
>> $$ alias expansion OFF for these names. Without these, multiple
>> invocations
>> $$ of the script can cause issues
>>
>> $$ Cast the active process list head as a LIST_ENTRY pointer
>>
>> aS ${/v:PsActiveProcessHead} “@@c++((nt!_LIST_ENTRY
>> *)@@masm(nt!PsActiveProcessHead))”
>>
>> $$ This is the offset of the list entry that PsActiveProcessHead points
>> to
>>
>> aS ${/v:ProcessLinksOffset} “@@c++(#FIELD_OFFSET(nt!_EPROCESS,
>> ActiveProcessLinks))”
>>
>> $$ And the offset to the PID
>>
>> aS ${/v:PIDOffset} “@@c++(#FIELD_OFFSET(nt!_EPROCESS,
>> UniqueProcessId))”
>>
>> $$ Locals
>>
>> aS ${/v:currProcPid} “@$t17”
>> aS ${/v:listEntry} “@$t18”
>> aS ${/v:currProc} “@$t19”
>>
>> $$ Force the script to evaluate the above aliases with a .block
>> .block
>> {
>>
>> $$ Get the Flink value of the head. Note that r? is required
>> $$ to use the C++ syntax in the r statement. Also, the type is
>> $$ assigned to the resulting register
>>
>> r? ${listEntry} = @@c++(${PsActiveProcessHead}->Flink)
>>
>> $$ And loop while we have entries…
>>
>> .while (${listEntry} != ${PsActiveProcessHead})
>> {
>>
>> $$ Get the base of the struct from the list pointer.
>> $$ Note that #CONTAINING_RECORD would also work
>>
>> r ${currProc} = ${listEntry} - ${ProcessLinksOffset}
>>
>> $$ Collect the PID from the process
>>
>> r ${currProcPid} = poi(${currProc} + ${PIDOffset})
>>
>> $$ Compare it to the first user argumnet
>> .if (${currProcPid} == ${$arg1})
>> {
>> $$ Found it!
>> r ${$arg2} = ${currProc}
>> .break
>> }
>>
>> $$ Move on to the next entry. Our r? command makes sure
>> $$ that ${listEntry} is typed appropriately
>>
>> r? ${listEntry} = @@c++(${listEntry}->Flink)
>>
>> }
>> }
>>
>> $$ /v: suppresses the alias expansion
>>
>> ad ${/v:currProc}
>> ad ${/v:listEntry}
>> ad ${/v:currProcPid}
>> ad ${/v:ProcessLinksOffset}
>> ad ${/v:PIDOffset}
>> ad ${/v:PsActiveProcessHead}
>>
>>
>>
>>
>> —
>> WINDBG is sponsored by OSR
>>
>> For our schedule of WDF, WDM, debugging and other seminars visit:
>> http://www.osr.com/seminars
>>
>> To unsubscribe, visit the List Server section of OSR Online at
>> http://www.osronline.com/page.cfm?name=ListServer
>>
></findpid.wbs></f:></f:>

Sorry, missed that (thought you meant LiveKD). I don’t think I’ve used the
Local KD option for anything since the XP timeframe, so I’m not as familiar
with its limitations. If !thread/!process can show you a call stack then it
should be possible to write your own extension to do the same (and
presumably without their limitations). Though I’d imagine that Local KD
makes it difficult to get a good call stack due to the fact that the system
is running.

-scott

“raj_r” wrote in message news:xxxxx@windbg…

there again is a roadblock :frowning: i cant use k in lkd

(works ok in a kd session )

result of kd session

kd> .foreach /pS 1c /ps 8 ( place { !process 0 4 explorer.exe } )
{.thread /p /r place;k}

Implicit thread is now ffae2460
Implicit process is now ffba0da0
.cache forcedecodeuser done
Loading User Symbols


*** Stack trace for last set context - .thread/.cxr resets it
ChildEBP RetAddr
f8f90c64 804dc0f7 nt!KiSwapContext+0x2e
f8f90c70 804dc143 nt!KiSwapThread+0x46
f8f90c98 8056b640 nt!KeWaitForSingleObject+0x1c2
f8f90d48 804de7ec nt!NtReplyWaitReceivePortEx+0x3dc
f8f90d48 7c90e4f4 nt!KiFastCallEntry+0xf8
00d7fe14 7c90da8c ntdll!KiFastSystemCallRet
00d7fe18 77e765e3 ntdll!ZwReplyWaitReceivePortEx+0xc
00d7ff80 77e76caf RPCRT4!LRPC_ADDRESS::ReceiveLotsaCalls+0x12a
00d7ff88 77e76ad1 RPCRT4!RecvLotsaCallsWrapper+0xd
00d7ffa8 77e76c97 RPCRT4!BaseCachedThreadRoutine+0x79
00d7ffb4 7c80b713 RPCRT4!ThreadStartRoutine+0x1a
00d7ffec 00000000 kernel32!BaseThreadStart+0x37

Implicit thread is now ffae1740
<------------------------------------------ see below for lkd session
output for same thread

Implicit process is now ffba0da0
.cache forcedecodeuser done
Loading User Symbols


*** Stack trace for last set context - .thread/.cxr resets it
ChildEBP RetAddr
fbef8cc8 804dc0f7 nt!KiSwapContext+0x2e
fbef8cd4 804dc143 nt!KiSwapThread+0x46
fbef8cfc bf802f52 nt!KeWaitForSingleObject+0x1c2
fbef8d38 bf803758 win32k!xxxSleepThread+0x192
fbef8d4c bf803775 win32k!xxxRealWaitMessageEx+0x12
fbef8d5c 804de7ec win32k!NtUserWaitMessage+0x14
fbef8d5c 7c90e4f4 nt!KiFastCallEntry+0xf8
00e0ff10 7e419418 ntdll!KiFastSystemCallRet
00e0ff44 0100ffd1 USER32!NtUserWaitMessage+0xc
00e0ff50 77f76f42 Explorer!CTray::MainThreadProc+0x29
00e0ffb4 7c80b713 SHLWAPI!WrapperThreadProc+0x94
00e0ffec 00000000 kernel32!BaseThreadStart+0x37
Implicit thread is now ffae10c0
Implicit process is now ffba0da0
.cache forcedecodeuser done
Loading User Symbols

an lkd session on same app viz explorer.exe

lkd> .foreach /pS 1c /ps 8 ( place { !process 0 4 explorer.exe } )
{.thread /p /r place;}

Can’t retrieve thread context, NTSTATUS 0xC0000001
Implicit thread is now ffae1740
<-------------------------- see 2nd thread in kd session
Implicit process is now ffba0da0 <--------------------
Loading User Symbols
…WARNING: Loader 00191f18 timestamp 8b55ff8b != header timestamp 4802a12c

…Missing image name, possible paged-out or corrupt data.
(awwwh crap)

Can’t retrieve thread context, NTSTATUS 0xC0000001
Implicit thread is now ffae0030
Implicit process is now ffba0da0
Loading User Symbols
…WARNING: Loader 00191f18 timestamp 8b55ff8b != header timestamp 4802a12c

On 9/14/12, raj_r wrote:
> thanks for the reply scott
>
> in local kernel debuging it is a limitation that we cannot use Kb for
> viewing stack
>
> so i was snooping around this !process Flag route to view the
> call stack (interested in user mode part of it especially )
>
> and i couldnt eek out more than one frame with 0x17 flag
>
> i will check out if i can get more frames with thread commands thanks
>
>
> as for finding EPROCESS from PID
>
> i used a terribly horrible parsing routine at first now i use a less
> than horrible but still horrible way of parsing :slight_smile:
>
>
>
> memset(printbuff,0,BUFFLEN);
>
> sprintf_s(printbuff,(BUFFLEN-SAFETYLIMIT),“.foreach /ps 100 /pS 12
> (place { !process %x 0 } ) { r $t0 = place; as /x eproc @$t0; .block
> {.process /p /r ${$eproc} } }”,Pid);
>
> g_Control->Execute(
> DEBUG_OUTCTL_IGNORE,
> printbuff,
> DEBUG_EXECUTE_DEFAULT
> );
>
> the .foreach here is very delicate :frowning: there is no uniformity in windbg
> output for many extension COMMAND OUTPUT and this can fail in one such
> occasion since it relies on positional count )
>
> and since i had an alias it seems i could use this alias later too
>
> if ( ( status = g_Control->Execute( DEBUG_OUTCTL_IGNORE,“.process /p
> /r eproc”,DEBUG_EXECUTE_DEFAULT ) ) != S_OK { \ this works in
> later part
>
> thanks a lot for the script i will take a look at it and see if i can
> adapt
> it
>
> On 9/14/12, Scott Noone wrote:
>> AFAIK !process/!thread have a non-configurable limit on the number of
>> call
>> frames they will show . So, in order to see more frames you have to
>> switch
>> to the thread context of the thread you’re interested in and then use the
>> k
>>
>> command (which is controllable by .kframes):
>>
>> .thread /r /p [thread]
>> k
>>
>> In terms of turning a PID into an EPROCESS, I don’t know of any built in
>> way
>>
>> (though it’s always possible there is one). You could probably write
>> something fairly quickly that would walk the active process list and do
>> the
>>
>> translation.
>>
>> For example, I made a couple of minor modifications to a script that we
>> use
>>
>> in labs where we teach WinDBG scripting. It takes two parameters, the PID
>> you want to translate and the temporary register to store the resulting
>> EPROCESS address in. An example usage would be:
>>
>> 1: kd> !process 0 0
>> NT ACTIVE PROCESS DUMP
>> …
>> PROCESS fffffa8007042980
>> SessionId: none Cid: 00e0 Peb: 7f7aaf3b000 ParentCid: 0004
>> DirBase: 06a17000 ObjectTable: fffff8a0010d25c0 HandleCount: >> Not
>>
>> Accessible>
>> Image: smss.exe
>> …
>> PROCESS fffffa8008aa3780
>> SessionId: 1 Cid: 0a44 Peb: 7f60483f000 ParentCid: 08cc
>> DirBase: 4af3a000 ObjectTable: fffff8a001958040 HandleCount: >> Not
>>
>> Accessible>
>> Image: wordpad.exe
>> …
>>
>> 1: kd> $$>a<f: e0>>> 1: kd> !process @$t0 0
>> PROCESS fffffa8007042980
>> SessionId: none Cid: 00e0 Peb: 7f7aaf3b000 ParentCid: 0004
>> DirBase: 06a17000 ObjectTable: fffff8a0010d25c0 HandleCount: >> Not
>>
>> Accessible>
>> Image: smss.exe
>>
>> 1: kd> $$>a<f: a44>>> 1: kd> !process @$t0 0
>> PROCESS fffffa8008aa3780
>> SessionId: 1 Cid: 0a44 Peb: 7f60483f000 ParentCid: 08cc
>> DirBase: 4af3a000 ObjectTable: fffff8a001958040 HandleCount: >> Not
>>
>> Accessible>
>> Image: wordpad.exe
>>
>> Full script provided below. Feel free to email me for a copy if the
>> mailer
>> mangles it too much.
>>
>> -scott
>>
>>
>> $$
>> $$ findpid.wbs
>> $$
>> $$ Walk the current list of processes and find the matching PID
>> $$
>> $$ OSR Open Systems Resources, inc.
>> $$
>> $$ http://www.osr.com
>> $$ http://www.osronline.com
>> $$
>> $$
>> $$ To run:
>> $$
>> $$ $$>a<findpid.wbs>>> $$
>> $$ Uses:
>> $$
>> $$ $t17-$t19
>> $$
>>
>> .echo *
>> .echo * This command brought to you by osronline.com
>> .echo

>>
>>
>> $$ Global aliases
>>
>> $$ Note that we use ${/v:} around all of our alias names. This shuts
>> $$ alias expansion OFF for these names. Without these, multiple
>> invocations
>> $$ of the script can cause issues
>>
>> $$ Cast the active process list head as a LIST_ENTRY pointer
>>
>> aS ${/v:PsActiveProcessHead} “@@c++((nt!_LIST_ENTRY
>> *)@@masm(nt!PsActiveProcessHead))”
>>
>> $$ This is the offset of the list entry that PsActiveProcessHead points
>> to
>>
>> aS ${/v:ProcessLinksOffset} “@@c++(#FIELD_OFFSET(nt!_EPROCESS,
>> ActiveProcessLinks))”
>>
>> $$ And the offset to the PID
>>
>> aS ${/v:PIDOffset} “@@c++(#FIELD_OFFSET(nt!_EPROCESS,
>> UniqueProcessId))”
>>
>> $$ Locals
>>
>> aS ${/v:currProcPid} “@$t17”
>> aS ${/v:listEntry} “@$t18”
>> aS ${/v:currProc} “@$t19”
>>
>> $$ Force the script to evaluate the above aliases with a .block
>> .block
>> {
>>
>> $$ Get the Flink value of the head. Note that r? is required
>> $$ to use the C++ syntax in the r statement. Also, the type is
>> $$ assigned to the resulting register
>>
>> r? ${listEntry} = @@c++(${PsActiveProcessHead}->Flink)
>>
>> $$ And loop while we have entries…
>>
>> .while (${listEntry} != ${PsActiveProcessHead})
>> {
>>
>> $$ Get the base of the struct from the list pointer.
>> $$ Note that #CONTAINING_RECORD would also work
>>
>> r ${currProc} = ${listEntry} - ${ProcessLinksOffset}
>>
>> $$ Collect the PID from the process
>>
>> r ${currProcPid} = poi(${currProc} + ${PIDOffset})
>>
>> $$ Compare it to the first user argumnet
>> .if (${currProcPid} == ${$arg1})
>> {
>> $$ Found it!
>> r ${$arg2} = ${currProc}
>> .break
>> }
>>
>> $$ Move on to the next entry. Our r? command makes sure
>> $$ that ${listEntry} is typed appropriately
>>
>> r? ${listEntry} = @@c++(${listEntry}->Flink)
>>
>> }
>> }
>>
>> $$ /v: suppresses the alias expansion
>>
>> ad ${/v:currProc}
>> ad ${/v:listEntry}
>> ad ${/v:currProcPid}
>> ad ${/v:ProcessLinksOffset}
>> ad ${/v:PIDOffset}
>> ad ${/v:PsActiveProcessHead}
>>
>>
>>
>>
>> —
>> WINDBG is sponsored by OSR
>>
>> For our schedule of WDF, WDM, debugging and other seminars visit:
>> http://www.osr.com/seminars
>>
>> To unsubscribe, visit the List Server section of OSR Online at
>> http://www.osronline.com/page.cfm?name=ListServer
>>
></findpid.wbs></f:></f:>