Bornish
September 4th, 2004, 10:05 AM
Aloha!
I'm in a bit of a jam... any hints will be greatly appreciated.
Description:
There's this multithreaded process which throws an exception. In the exception handler, am trying to dump the stack for all the threads in the process. For the thread generating the exception is a piece of cake, and I figured will be almost as easy for the other threads:
Step 1 - get the context of each thread using GetThreadContext() API
Step 2 - get TIB (Thread Information Block) of the thread in question
Step 3 - dump from stack's top until stack's base
Unexpected result:
I believed that when switching the thread's context for yielding the execution to a different thread, SegFs member of the CONTEXT structure must have a different value from one thread to another, in order to have FS:[18h] pointing to a different TIB structure. It seems I was wrong!
Questions:
- Is the following function retrieving the TIB of the calling thread?
static tagXTIB* GetTIB()
{
tagXTIB* pTib;
__asm
{
MOV EAX , FS:[18h]
MOV pTib , EAX
}
return pTib;
}...where tagXTIB is defined as:
typedef struct tagXTIB
{
PEXCEPTION_REGISTRATION_RECORD pvExcept; //00h Head of exception record list
PVOID pvStackUserTop; //04 Top of user stack
PVOID pvStackUserBase; //08h Base of user stack
union
{
struct //Win95 fields
{
WORD pvTDB; //0Ch
WORD pvThunkSS; //0Eh SS selector used for thunking to 16 bits
DWORD unknown1; //10h
} WIN95;
struct //WinNT fields
{
PVOID SubSystemTib; //0Ch
ULONG FiberData; //10h
} WINNT;
} TIB_UNION1;
PVOID pvArbitrary; //14h Available for application
struct _tib *ptibSelf; //18h Linear address of TIB structure
union
{
struct //Win95 fields
{
WORD TIBFlags; //1Ch
WORD Win16MutexCount; //1Eh
DWORD DebugContext; //20h
DWORD pCurrentPriority; //24h
DWORD pvQueue; //28h Message Queue
} WIN95;
struct //WinNT fields
{
DWORD unknown1; //1Ch
DWORD processID; //20h
DWORD threadID; //24h
DWORD unknown2; //28h
} WINNT;
} TIB_UNION2;
PVOID* pvTLSArray;
union
{
struct //Win95 fields
{
PVOID* pProcess; //30h Pointer to owning process database
} WIN95;
} TIB_UNION3;
} XTIB;
#pragma pack() - Are the pvStackUserTop & pvStackUserBase members of tagXTIB structure the addresses defining the memory interval where the thread's stack is located?
- Do you know any other way of getting these values, besides reading them from the TIB?
- In order to get the address of the TIB for all the other threads of the process (not the calling thread), is it correct to use the SegFs member of the CONTEXT structure filled by a GetThreadContext() call, instead of FS from GetTIB() function?
- Then, why SegFs is equal with FS? Makes no sense to get the TIBs this way, since FS:[18h] will be equal with SegFs:[18h], but TIB should be different for two threads, isn't it?
Conclusions:
My interest is to dump the stack for each thread belonging to the process. Having the stack's top & base addresses, and also the Esp pointer (which seems to be retrieved correctly by the API), I will be able to list the call stack. All registers are looking as valid information, as returned by GetThreadContext() API. I've checked Eip value, too. So, makes me believe that SegFs is also correct. But then, why has the same value with the calling thread's FS? If so, from where to read the TIB of the other threads? Or, at least, how to get the correct location of their stack (because I know for sure that threads are not sharing the stack)?
Many anticipated thanks,
I'm in a bit of a jam... any hints will be greatly appreciated.
Description:
There's this multithreaded process which throws an exception. In the exception handler, am trying to dump the stack for all the threads in the process. For the thread generating the exception is a piece of cake, and I figured will be almost as easy for the other threads:
Step 1 - get the context of each thread using GetThreadContext() API
Step 2 - get TIB (Thread Information Block) of the thread in question
Step 3 - dump from stack's top until stack's base
Unexpected result:
I believed that when switching the thread's context for yielding the execution to a different thread, SegFs member of the CONTEXT structure must have a different value from one thread to another, in order to have FS:[18h] pointing to a different TIB structure. It seems I was wrong!
Questions:
- Is the following function retrieving the TIB of the calling thread?
static tagXTIB* GetTIB()
{
tagXTIB* pTib;
__asm
{
MOV EAX , FS:[18h]
MOV pTib , EAX
}
return pTib;
}...where tagXTIB is defined as:
typedef struct tagXTIB
{
PEXCEPTION_REGISTRATION_RECORD pvExcept; //00h Head of exception record list
PVOID pvStackUserTop; //04 Top of user stack
PVOID pvStackUserBase; //08h Base of user stack
union
{
struct //Win95 fields
{
WORD pvTDB; //0Ch
WORD pvThunkSS; //0Eh SS selector used for thunking to 16 bits
DWORD unknown1; //10h
} WIN95;
struct //WinNT fields
{
PVOID SubSystemTib; //0Ch
ULONG FiberData; //10h
} WINNT;
} TIB_UNION1;
PVOID pvArbitrary; //14h Available for application
struct _tib *ptibSelf; //18h Linear address of TIB structure
union
{
struct //Win95 fields
{
WORD TIBFlags; //1Ch
WORD Win16MutexCount; //1Eh
DWORD DebugContext; //20h
DWORD pCurrentPriority; //24h
DWORD pvQueue; //28h Message Queue
} WIN95;
struct //WinNT fields
{
DWORD unknown1; //1Ch
DWORD processID; //20h
DWORD threadID; //24h
DWORD unknown2; //28h
} WINNT;
} TIB_UNION2;
PVOID* pvTLSArray;
union
{
struct //Win95 fields
{
PVOID* pProcess; //30h Pointer to owning process database
} WIN95;
} TIB_UNION3;
} XTIB;
#pragma pack() - Are the pvStackUserTop & pvStackUserBase members of tagXTIB structure the addresses defining the memory interval where the thread's stack is located?
- Do you know any other way of getting these values, besides reading them from the TIB?
- In order to get the address of the TIB for all the other threads of the process (not the calling thread), is it correct to use the SegFs member of the CONTEXT structure filled by a GetThreadContext() call, instead of FS from GetTIB() function?
- Then, why SegFs is equal with FS? Makes no sense to get the TIBs this way, since FS:[18h] will be equal with SegFs:[18h], but TIB should be different for two threads, isn't it?
Conclusions:
My interest is to dump the stack for each thread belonging to the process. Having the stack's top & base addresses, and also the Esp pointer (which seems to be retrieved correctly by the API), I will be able to list the call stack. All registers are looking as valid information, as returned by GetThreadContext() API. I've checked Eip value, too. So, makes me believe that SegFs is also correct. But then, why has the same value with the calling thread's FS? If so, from where to read the TIB of the other threads? Or, at least, how to get the correct location of their stack (because I know for sure that threads are not sharing the stack)?
Many anticipated thanks,